---
title: "CRA 第二期 — 底層機制與內容補強討論稿 (FR-135)"
brand: "Guidant AI · **FR-135** CRA 合規框架"
eyebrow: "FR-135 · 第二期討論稿 · 2026-10-11"
h1: "讓 CRA 專案開得出工作、填得齊資料"
subtitle: "平台層兩項先修（影響所有框架），CRA 層補表單設定、證據指到節、評估目標拆分、Annex II 欄位"
lede: "第〇步拿自家材料在 DEV 走完 CRA 31 條，露出兩個**所有框架都會踩到**的底層缺口：規劃頁看不到條文與建議證據、沒有評估目標（AO）時準備期一個工作都開不出來。這兩件先拆小卡修。其餘是 **CRA 本身要補的內容**：資源庫第四件「表單設定」、證據指到檔內某一節、把一條包多件事的控制項拆成多個 AO、Annex II 的產品資訊存成結構化欄位，外加資訊系統版本、風險評估雛形、文件範本。本稿盤點現況、畫出資料落點、拆成四個階段，列出 14 項待裁。"
chips: [
  {text: "已裁 5 項（本期前提）", kind: ok},
  {text: "待裁 14 項（D1～D14）", kind: warn},
  {text: "平台層 2 項先拆小卡", kind: accent},
  {text: "design.md 拆兩份：platform／cra", kind: accent},
  {text: "沒有「複製資源庫」功能", kind: crit}
]
footer: "FR-135 · CRA 第二期討論稿 · 2026-10-11 · 輸入：[第〇步掛不上去的清單](step-zero-gap-list.md) 第四節、[CRA 導入規劃](cra-implementation-plan.md) · 現況依據：四份探脈（規劃頁顯示、無 AO 開工、表單設定與 SSP 擴充、CRA 內容層）實查程式碼與 DEV DB，座標以 `檔案:行號` 標於各段"
---

**狀態**：討論稿（待裁 14 項）　｜　**日期**：2026-10-11　｜　**輸入**：[`step-zero-gap-list.md`](step-zero-gap-list.md) 第四節、[`cra-implementation-plan.md`](cra-implementation-plan.md)「第二期」

## 分工概述（30 秒版） {#overview nav="概述"}

整案一句話：**先讓任何沒有評估目標的框架也能在規劃頁看到條文、開得出收證據的工作；再讓 CRA 專案有地方填產品版本、支援期、通報窗口這些法規要的資料，而 CMMC 專案的畫面一點都不變。**

給非工程讀者的背景：每本框架（CMMC、CRA）在系統裡是一棵「控制項樹」；控制項底下可以再分「評估目標」（AO，一條控制項要查的幾件具體事情）。CMMC 每條都有 AO，CRA 第一期刻意不建，結果暴露出系統有兩處只在「有 AO」時才會動。

::: {.callout .decided}
**本期前提（決策者 2026-10-11 已裁，不再討論）**

① 第二期範圍＝規劃稿「第二期」四件 ＋ gap list 第四節六項，合併做；平台層兩項先拆小卡獨立修。② design.md 拆兩份：`design-platform.md`（平台層，影響所有框架）與 `design-cra.md`（CRA 層）。③ 表單設定最小版：固定結構設定、四種欄位型別（文字／日期／下拉／布林）、CRA 公版由 seed（隨程式出貨的初始資料）建好、CMMC 畫面不變；畫面上的表單編輯器、條件顯示、驗證規則留 GRC。④ 瀏覽對話框第三態（CM-2687）與 DEV CMMC PDF 遺失不進本稿。⑤ 沿用既有裁示：通報與跨框架對應另開 FR；稽核階段當「檢查」用、系統不改；風險評估第一版手填登錄表。
:::

| 項目 | 做什麼 | 產出 | 完成怎麼判定（決策者檢查法） |
|---|---|---|---|
| **平台層 A** 規劃頁顯示條文 | 控制項樹多帶「條文原文」與「建議證據」兩欄，規劃頁控制項面板顯示 | 後端樹多兩欄、前端面板兩塊 | 開 CRA 專案規劃頁點任一條，看得到「條文」「建議證據」且段落換行正常；開 CMMC 專案同一頁，AO 面板與現在一樣 |
| **平台層 B** 無 AO 也開得出工作 | 系統內建一份「收證據」流程範本給所有租戶用；沒 AO 的控制項每條各開一筆工作 | 範本改系統層級、出貨基線帶上、開工邏輯修正 | 用 CRA 公版新建專案，準備期出現 31 筆工作；隨便改一條的流程，另一條不受影響；換一個新租戶建專案結果一樣 |
| **CRA 1** 表單設定 | 資源庫第四件：決定這本框架的專案多顯示哪些欄位、要不要風險評估頁籤 | 設定欄位、CRA 公版設定內容、受評標的頁動態欄位 | CRA 專案受評標的頁多一段 CRA 欄位、出現風險評估頁籤；CMMC 專案畫面與現在一模一樣 |
| **CRA 2** 證據指到節 | 掛文件到控制項時可寫「§4.2；SR 1.1, 2.3」 | 對應表加一個文字欄、掛載對話框加輸入框 | 掛 FR-126 矩陣時填章節，規劃頁清單看得到；用此資源庫再建一個專案，章節還在 |
| **CRA 3** 拆評估目標 | 7 條一條包多件事的控制項拆成 2～3 個 AO，隨框架出貨 | 套件 seed、重建 CRA 公版 | 新建 CRA 專案，那 7 條底下出現 AO，準備期按 AO 數開工作 |
| **CRA 4** Annex II 欄位 | 支援期結束日、通報窗口網址等 6 項存成結構化欄位，預設說明文字預填 | 受評標的擴充鍵、控制項預設值 | 受評標的填支援期結束日，存檔重整還在；新專案 A2.x 實作說明已預填文字 |
| 附：資訊系統版本 | 資訊系統盤點加「版本」子清單 | 新子表＋畫面 | 系統盤點某一筆底下能新增 v1.0／v1.1，各有上市日與支援期結束日 |
| 附：風險評估雛形 | 專案多一個手填的風險登錄表 | 頁籤＋存放處 | CRA 專案新增兩筆風險、重整後還在；CMMC 專案看不到這個頁籤 |
| 附：文件範本 | CVD 政策等 4～5 份 docx 範本放進 CRA 公版程序書池並預掛 13 條 | 純資料上傳 | 新建 CRA 專案，程序書池已有範本，13 條控制項都掛著 |

依賴：平台層 A、B 互不相依，最先做。CRA 1 是 CRA 4 與風險評估頁籤的前提。CRA 3 與 CRA 4 的預設文字都要「重建 CRA 公版」才生效（D5），所以 CRA 層內容一次灌完再重建一次。**決策者功課**：請顧問確認 ① 7 條 AO 怎麼拆（D6）② 4～5 份文件範本內容（D10）③ Annex II 預設說明文字。

---

## 第二期要解的六件事 {#problems nav="問題"}

來源是 [`step-zero-gap-list.md`](step-zero-gap-list.md) 第四節，括號內是第〇步實測時受影響的條數。第 8 項「定期執行的證明」（1 條，II.3）四份探脈都沒查，本期不處理，列入範圍外。

### 平台層（任何沒有 AO 的框架都會踩到）

**① 規劃頁看不到條文原文與建議證據（31 條）**

- 白話問題：顧問在規劃頁只看得到「資料最小化」這種標題，法條原文與建議證據只在框架管理頁看得到。CMMC 有 AO 文字補上「要查什麼」，CRA 沒有就整個空掉。
- 現況：後端其實已把每條控制項的全部段落撈出來（`app/oscal/service/ssp_control_implementation_service.py:224-227`），卻只留下 AO、把條文（statement）與建議證據（guidance）丟掉（`:226`）。回傳的控制項物件沒有這兩欄（`:820-832`）；前端組樹時說明欄寫死空字串（FE `ProjectPlanningView.vue:647`）。沒 AO 時後端塞一個與控制項同名的假 AO（`:792-803`），畫面上是控制項底下一個同名節點、面板沒有任何「要查什麼」。

**② 沒有 AO 時準備期一個工作都開不出來（31 條）**

- 白話問題：建專案回 `job_count: 0`，準備期空轉，沒有工作能派給客戶收證據。
- 現況：程式其實已寫好「沒 AO 就在控制項層開一筆」（`app/flow_control/service/prep_job_generation_service.py:165-166`），但要找收證據的流程範本，來源只有兩個：AO 上掛的範本，或資源庫的 `template_uid` 退路（`:168-169`）。兩個都空時**靜默略過**（`:170-172`），只在 info log 記一筆 skipped（`:220-225`）。新建資源庫的寫入不寫 `template_uid`（`app/oscal/service/resource_library_app_service.py:545-553`），DEV 上 CRA 兩個資源庫 AO 數都是 0。

### CRA 層（只影響 CRA）

**③ 流程與文件類證據沒有材料（13 條）**：CVD 政策、通報窗口、安全通告、支援期聲明，產品本身沒有、系統也沒幫客戶產出的地方。現況：SSP 匯出用寫死的 CMMC 範本（`app/oscal/service/ssp_docx_generator.py:1-29`），程序書池只能上傳掛載、不能渲染，**系統沒有通用的「範本→產出」機制**。

**④ 證據只能掛整份檔（11 條）**：FR-126 矩陣一份要掛 12 條，每條依據的 SR 只能寫在說明欄。現況：掛載對應表 `oscal.ssp_reference_document_mappings` 只有文件 id 與掛載對象，沒有章節欄（`scripts/sql/2026-06-15-fr038-b3-ssp-reference-documents.sql:26-34`）；說明欄在池本體，整份共用。另有一套舊掛法並存（見 §4「CRA 2」）。

**⑤ 一條包多件事要拆 AO（7 條）**：I.1、I.2.b、I.2.d、I.2.h、I.2.l、II.2、A2.8 的證據混在一起。現況：系統沒有手動新增 AO 的路徑——框架編輯端點只有改與刪（`framework_version_edit_route.py:112-133`），且只有草稿版可改，CRA 已發布。

**⑥ Annex II 的「資訊本身」要結構化（6 條）**：支援期結束日、通報窗口網址現在只能截圖或寫說明。現況：受評標的表已有擴充屬性（props，OSCAL 標準的自訂鍵值欄）`oscal.ssp_system_characteristics.props`（jedi-oscal-v2 `oscal_ssp_system_characteristics.py:104`），已存 `target-type`／`owner-uid` 兩鍵（`app/module_frame/service/module_frame_system_characteristic_service.py:34-36`），加鍵即可。

---

## 現況盤點：可複用 vs 要新做 {#inventory nav="盤點"}

| 項目 | 可複用（已存在） | 要新做 |
|---|---|---|
| 規劃頁條文 | 後端已撈全部段落（`ssp_control_implementation_service.py:224-227`）；條文／建議證據挑法 `framework_version_edit_service.py:266,272`；同頁換行樣式先例 FE `ProjectPlanningView.vue:2226` | `_resolve_inscope_catalog`（`:165`）多帶兩欄；`_build_control`（`:820`）加兩欄；FE 面板兩塊；無 AO 退回分支（`:792`）改顯示控制項建議證據 |
| 無 AO 開工 | 控制項層退回邏輯（`prep_job_generation_service.py:165-166`）；下游工作紀錄、指派、覆核沿用、證據範圍、稽核判定全部對得上（探脈逐一查過，見 §4「平台層 B」） | 系統層級「收證據」範本；資源庫範本來源補值或讀時退回；每條各 clone 一份；規劃頁控制項層那筆補範本 uid |
| 表單設定 | 受評標的 props 非破壞合併工具（`module_frame_system_characteristic_service.py:94-115,163-182`）；建專案深拷貝帶 props（`ssp_clone_service.py:147-153`）；動態頁籤 v-if 先例（雲端頁籤 FE `ProjectPlanningView.vue:416-429`）；公版 seed 入口 `public_library_seed_cli.py:_seed_one` | 設定落點＋migration＋ORM＋DTO；專案端拿設定的管道；動態欄位渲染元件（四型別）；CRA 公版設定內容 |
| 複製資源庫 | **不存在**。唯一 clone `module_frame_service.py:130-222` 只複製 BPMN 範本與資源庫列，FE 無呼叫端（`api.js:152`） | 若要「隨資源庫複製」得新做（D1） |
| 證據指到節 | 新套掛法：池（`ssp_document_pool_service.py:63-78`）＋多對多對應（`:148-201`）；建專案複製（`project_start_app_service.py:255-295`） | 對應表加 `locator` 文字欄；新增／列出 API、FE 掛載對話框、建專案複製（`:270,292`）、快照還原（`ssp_document_pool_service.py:216,249`） |
| AO 拆分 | AO 存法（`catalog_control_parts` name=`assessment-objective`，key `{control_id}_obj.N`）；003 seed 的冪等寫法 | 套件 `004` seed；重建 CRA 公版 |
| Annex II | 受評標的 props；控制項預設值（`module_frame_control_default_service.py:36-41,187-201`）建專案隨範本 SSP 複製 | 6 個鍵＋FE 表單；A2.x 預設說明文字 |
| 資訊系統版本 | `compliance.information_systems` 表與端點（jedi-asset `routing.py:48-51`）；SSP 軟關聯（`module_frame_inventory_service.py:43-46`） | jedi-asset 新子表 `information_system_versions`＋CRUD＋畫面 |
| 風險評估 | AR／POA&M 層有風險表與畫面（`oscal.assessment_risks`、FE `RiskBadge.vue`）可參考欄位 | SSP 層**完全沒有**風險表與頁籤（D9） |
| 文件範本 | 資源庫層程序書池（`api/module_frame/__init__.py:167-177`），建專案整池複製 | 4～5 份 docx 內容（顧問功課）＋上傳預掛 |
| 自家 SBOM | build 產 CycloneDX（`scripts/build/sbom.sh:60,70`）；源碼掃描可匯入（`api/source_scan/routes/target_route.py:130-145`） | 掃描結果→控制項證據的連結（D14） |

---

## 方案與資料落點 {#design nav="方案"}

### 整體架構

```{.mermaid cap="圖 1 — 資源庫四件如何流到專案與準備期工作（虛線＝本期要新增或補值）"}
%%{init: {'theme':'base','themeVariables':{'primaryColor':'#E2F0F1','primaryTextColor':'#14201F','primaryBorderColor':'#0E7C86','secondaryColor':'#EEF2F3','secondaryTextColor':'#14201F','tertiaryColor':'#FBFCFC','tertiaryTextColor':'#14201F','lineColor':'#4A5A5C','textColor':'#14201F','mainBkg':'#E2F0F1','nodeBorder':'#0E7C86','nodeTextColor':'#14201F','edgeLabelBackground':'#FBFCFC','titleColor':'#14201F','clusterBkg':'#FBFCFC','clusterBorder':'#E4EAEB','actorBkg':'#E2F0F1','actorTextColor':'#14201F','actorBorder':'#0E7C86','actorLineColor':'#C7D1D2','signalColor':'#4A5A5C','signalTextColor':'#14201F','labelBoxBkgColor':'#EEF2F3','labelBoxBorderColor':'#C7D1D2','labelTextColor':'#14201F','loopTextColor':'#14201F','noteBkgColor':'#F6EBD5','noteTextColor':'#14201F','noteBorderColor':'#9C6B12','activationBkgColor':'#EEF2F3','activationBorderColor':'#C7D1D2','sequenceNumberColor':'#FFFFFF'}}}%%
flowchart LR
  subgraph RL["資源庫（module_frames）"]
    P["① 控制項選集<br/>oscal_profile_uid"]
    S["② SSP 範本<br/>template_ssp_id"]
    F["③ 稽核流程範本<br/>audit_flow_template_uid"]
    T["收證據退路<br/>template_uid"]
    FS["④ 表單設定<br/>（新）"]
  end
  SYS["系統「收證據」範本<br/>（改 SYSTEM 層級）"]
  subgraph PJ["專案"]
    SSP["專案 SSP<br/>受評標的 props"]
    TREE["控制項樹<br/>＋條文／建議證據"]
    JOB["準備期工作"]
  end
  P -->|建專案複製| TREE
  S -->|深拷貝帶 props| SSP
  F -->|建首輪預設| JOB
  FS -.->|決定顯示哪些欄位| SSP
  SYS -.->|補值或讀時退回| T
  T -->|無 AO 時| JOB
  TREE -->|每 AO 或每控制項| JOB
```

### 平台層 A：控制項樹加條文與建議證據兩欄 {#design-a}

- **做法**：`_resolve_inscope_catalog`（`ssp_control_implementation_service.py:165`）本來就對每條控制項撈全部段落（`:224-227`），改成順手留下 statement 與 guidance；`_build_control`（`:820`）加 `statement`、`guidance` 兩欄。挑段落的邏輯沿用 `framework_version_edit_service.py:266`（`_statement_prose`）與 `:272`（`_guidance_prose`）。
- **不增 SQL**：段落原本就全撈。CMMC L2 110 條合計約 50KB、CRA 31 條約 25KB，直接併進樹，不做延遲載入。每控制項各查一次的既有問題不是本案造成，不在本期處理。
- **順手收掉的重複查詢**：分類器用的 `build_classifier_catalog_by_ssp_id`（`:266-272`）為了拿 statement 重打一次，改形狀後兩邊共用。
- **前端**：`ProjectPlanningView.vue:647` 改接新欄位；控制項面板加「條文」「建議證據」兩塊，換行樣式照同頁 `:2226`；沒 AO 的退回分支（後端 `:792`）顯示控制項的建議證據。
- **命名**：新欄位直接叫 `statement`／`guidance`，**不沿用 `description`**——框架管理頁的 description 是條文、規劃頁的 description 是空佔位，同字兩義。
- **影響面**：control-tree 另有 6 頁在用（RoundAuditReview、RoundApAuthoring、ProjectAuditorOverview、EvidenceClassificationReview、AutoClassifyBatch 等），只加欄位不動既有欄位就不會壞。稽核執行頁 `AuditControlRef.vue:65-66` 已有欄位但 `RoundAuditReviewView.vue:337-338` 寫死空字串，要不要一併接起來在 design-platform.md 定。

### 平台層 B：沒有 AO 也開得出準備期工作 {#design-b}

```{.mermaid cap="圖 2 — 建專案時開準備期工作的判斷順序（紅字＝現在會靜默略過的地方）"}
%%{init: {'theme':'base','themeVariables':{'primaryColor':'#E2F0F1','primaryTextColor':'#14201F','primaryBorderColor':'#0E7C86','secondaryColor':'#EEF2F3','secondaryTextColor':'#14201F','tertiaryColor':'#FBFCFC','tertiaryTextColor':'#14201F','lineColor':'#4A5A5C','textColor':'#14201F','mainBkg':'#E2F0F1','nodeBorder':'#0E7C86','nodeTextColor':'#14201F','edgeLabelBackground':'#FBFCFC','titleColor':'#14201F','clusterBkg':'#FBFCFC','clusterBorder':'#E4EAEB','actorBkg':'#E2F0F1','actorTextColor':'#14201F','actorBorder':'#0E7C86','actorLineColor':'#C7D1D2','signalColor':'#4A5A5C','signalTextColor':'#14201F','labelBoxBkgColor':'#EEF2F3','labelBoxBorderColor':'#C7D1D2','labelTextColor':'#14201F','loopTextColor':'#14201F','noteBkgColor':'#F6EBD5','noteTextColor':'#14201F','noteBorderColor':'#9C6B12','activationBkgColor':'#EEF2F3','activationBorderColor':'#C7D1D2','sequenceNumberColor':'#FFFFFF'}}}%%
sequenceDiagram
  participant API as 建專案 API
  participant ST as 啟動服務
  participant GEN as 準備期產生器
  participant WT as 流程範本表
  API->>ST: start_project
  ST->>ST: 讀資源庫 template_uid（可能是空）
  ST->>GEN: generate（fallback_template_uid）
  loop 每條在範圍內的控制項
    alt 控制項有 AO
      GEN->>GEN: 每個 AO 取 props 上的範本 uid
    else 沒有 AO
      GEN->>GEN: 控制項層一筆，取 fallback
    end
    alt 範本 uid 是空
      Note over GEN: 靜默略過 skipped+1（:170-172）
    else 有 uid
      GEN->>WT: 依 uid 取範本
      alt 本租戶讀不到（TENANT 範本跨租戶）
        Note over GEN: 一樣靜默略過（:173-175）
      else 讀得到
        GEN->>WT: clone 專案副本（同來源只 clone 一次）
        GEN->>GEN: 寫一筆準備期工作
      end
    end
  end
```

四處要改，缺一個都還是 0 工作或工作打架：

1. **系統「收證據」範本改成所有租戶讀得到**：系統只有一份 `compliance.workflow_templates` uid `f4038001-…0001`「收證據」，DEV 上是租戶 102 的 TENANT 層級，其他租戶因 RLS（資料庫依租戶隔離）讀不到，`get_workflow_template_by_uid` 回空照樣略過。要改 SYSTEM 層級，並帶進出貨基線——但基線 `scripts/init/04-seed-core.sql:824,868` 目前**強制** workflow_templates 必須為空（D4）。
2. **範本來源補上**：兩條路擇一或併用（D12）——建資源庫的 INSERT 帶上系統範本 uid（`resource_library_app_service.py:545-553`），或啟動時讀到空值退回系統預設（`project_start_app_service.py:146`）。前者要回頭補 DEV 既有資源庫；後者既有資源庫自動生效。
3. **每條控制項各 clone 一份**：現在 `_clone_for` 快取同來源只 clone 一次（`prep_job_generation_service.py:142-156`），31 筆工作共用一份副本，`inject_job_execution_uid` 覆蓋寫入只留最後一筆，流程編輯器存檔還會重複建工作（`:139-141,194-203`）。控制項層退回時改成每條各 clone。
4. **規劃頁控制項層那筆補範本 uid**：`ssp_control_implementation_service.py:796-803` 有輪次時帶得到工作，但沒帶 `workflow_template_uid`／`workflow_execution_uid`，FE `ProjectPlanningView.vue:1407` 會提示「沒有流程」；無輪次的舊路徑（`:488-494`）依 AO props 找工作，控制項層工作看不到。

**下游不用改**（探脈逐一查過）：工作紀錄寫 `(control_id=cid, ao_part_id=cid)`（`prep_job_generation_service.py:214-216`）；指派綁工作 id（`flow_control_job_repo_impl.py:548-552`）；覆核輪沿用指派用 `ao_part_id IS NOT DISTINCT FROM` 配得上（`reverify_clone_query.py:48`）；稽核判定 `ao_derivation.py:38-41` 無 AO 同樣退回 `(cid,cid)`。

**唯一例外在套件**：覆核輪 jedi-compliance-audit `audit_round_app_service.py:774-779` 傳 `fallback=None`，控制項層一定略過（D8）。

### CRA 1：資源庫第四件「表單設定」 {#design-form}

- **落點取捨**（D2）：

| | 資源庫表加 JSONB 欄 `module_frames.form_settings` | 新表 `module_frame_form_settings` |
|---|---|---|
| 改動量 | 一個 INSERT＋mapper，seed／DTO 帶得順 | 多 repo、mapper、RLS 政策，複製多一段，載入多一次查詢 |
| 約束 | 資料庫不擋結構錯誤，靠程式驗 | 每欄一列，可加約束與排序 |
| 未來 GRC 表單編輯器 | 結構變大後較難維護 | 擴充好接 |
| 先例 | `detection_tools.config_field_schema`（`scripts/sql/2026-07-31-fr058-9-...sql:22-36`） | — |

- **值存哪**：使用者填的值存專案 SSP 受評標的 props，鍵加 `ext:` 前綴（例 `ext:cra-support-end-date`），避免撞到既有 `target-type`／`owner-uid`。寫入用既有非破壞合併工具（`module_frame_system_characteristic_service.py:94-115`），建專案深拷貝自然帶過去（`ssp_clone_service.py:147-153`）。
- **專案怎麼拿到設定**（D3）：專案已記得資源庫（`projects.module_frame_id`，建專案寫於 `project_start_app_service.py:374`），但規劃頁拿的 `GET /grc/project/<uid>` 回應裡資源庫只有 id／name／group／version／frequency（jedi-compliance-audit `api/serializers/project.py:203-212`、`project_dto.py:72-76`）。兩條路：改套件 DTO 加欄，或主專案另開端點。
- **畫面**：受評標的固定 8 欄（`SspTabPanel.vue:339-342` → `SspBasicSection.vue`，`useSspSystemCharacteristic.js:34`），設定有值時在下方多渲染一段動態欄位；風險評估頁籤照雲端頁籤 v-if 先例（`ProjectPlanningView.vue:416-429`）。
- **CMMC 不受影響的條件**：設定為空就照現在固定頁籤與 8 欄；CMMC 公版不寫設定。
- **CRA 公版怎麼帶設定**：`public_library_seed_cli.py` 的 `PublicLibrary` dataclass（`:18-23`）加 `form_settings`，在 `_seed_one` 建庫之後（`:79`）、改名升 SYSTEM 之前（`:80-83`）同一個交易寫入。
- **建議結構**（草案，design-cra.md 定稿）：`{ "sections": {"risk_assessment": true}, "fields": [{"key": "ext:cra-support-end-date", "label": "...", "type": "date", "required": true, "options": null}] }`，`type` 限 text／date／select／boolean。

### CRA 2：證據指到檔內某一節（locator） {#design-locator}

- 對應表 `oscal.ssp_reference_document_mappings` 加一個文字欄 `locator`，內容自由寫（「§4.2；SR 1.1, 2.3」），**不做結構化**——各家文件的章節格式不一。
- 連動五處：新增對應的請求、列出對應的回傳（jedi_compliance_audit `SspDocumentPoolQuery`）、FE 掛載對話框（`ProjectPlanningView.vue:2509` DocumentLinkDialog）加輸入框、建專案複製（`project_start_app_service.py:270,292`）、快照還原（`ssp_document_pool_service.py:216,249`）。
- **舊套掛法**：`context_type=control_implementation|objective` 直接寫在 `ssp_reference_documents`（寫 `ssp_control_implementation_service.py:887,974-992`、讀 `:1010-1012`），FE 上傳函式 `handleUploadRefDoc`（`ProjectPlanningView.vue:1511-1533`）沒有模板呼叫＝沒有入口，這就是「控制項詳情回空陣列」的原因；建專案也只複製新套。只在新套加 locator，舊套 API 繼續回空（D7）。

### CRA 3：拆評估目標（AO seed 004）與重建公版 {#design-ao}

- 仿套件 003 的冪等寫法（以 part_id 判斷不存在才寫），新增 `jedi_oscal_v2/migrations/004`，7 條各寫 2～3 個 AO，key 用 `{control_id}_obj.N`。CMMC 的 AO 來自 PDF 解析器（`cmmc2_lv2_parser_adapter.py:610-620`），CRA 002 明寫不建 AO（`:9`），所以只能走 seed。
- **只對之後新建的資源庫與專案有效**：建資源庫時整份複製 catalog（`resource_library_app_service.py:500-501`），AO 的流程範本也只在那時建（`_init_ao_workflows`，`:236-278`）。既有 CRA 公版與第〇步測資吃不到（D5）；本期稍早灌的 guidance 同理。
- 生效後：拆了 AO 的 7 條準備期自動變每 AO 一筆（`prep_job_generation_service.py:160-172`），稽核計畫的查核項（`assessment_plan_app_service.py:401`）跟著 AO 走。**其餘 24 條仍靠平台層 B 的退路開工**——拆 AO 不能取代平台層 B。

### CRA 4：Annex II 結構化欄位與預設文字 {#design-annex2}

- **結構化值**：受評標的 props 加 6 個鍵（例 `ext:cra-support-end-date`、`ext:cra-vuln-contact-url`），由 CRA 1 的表單設定宣告、受評標的頁渲染。不開新表、不加新欄。
- **預設說明文字**：放「適用控制項預設值」——資源庫範本 SSP 的實作需求 props（`implementation-description` 等，`module_frame_control_default_service.py:1-16,36-41,187-201`），建專案隨範本 SSP 複製。A2.x 的預設說明文字是純資料，寫進 CRA 公版 seed。
- **與規劃稿的落點差異**：規劃稿把「漏洞揭露政策、通報窗口、通報人員」放組織層資訊系統盤點，探脈建議放受評標的 props（D13）。

### 資訊系統版本子表 {#design-version}

- `compliance.information_systems`（`scripts/sql/packages/jedi_asset/001-asset-tables.sql:97-118`）沒有版本欄。建議 jedi-asset 新子表 `information_system_versions`（資訊系統 FK、版號、上市日、支援期結束日、理由）＋CRUD 端點＋FE `InformationSystemManage.vue` 子清單。
- SSP 端軟關聯不動：受評標的 inventory_items.props 存 `ref-type=information_system`＋`ref-id`（`module_frame_inventory_service.py:43-46`）。**專案要不要「選到某個版本」**（規劃稿樹狀圖寫「專案（選系統與版本）」）探脈未查、待驗，design-cra.md 定。

### 風險評估頁籤（最小雛形） {#design-risk}

- 現況：專案頂層頁籤固定六個（`ProjectPlanningView.vue:405-413`），SSP 子頁籤固定四個（`SspTabPanel.vue:336-386`），**SSP 層完全沒有風險表**；風險只存在稽核結果層 `oscal.assessment_risks`（`oscal_ar_risk.py:25`，characterizations JSONB `:59`）與 POA&M 畫面（`RoundPoamView.vue:533-633`）。
- 已裁第一版是手填登錄表，預留「威脅來源」「元件連結」兩欄。存放處 D9。頁籤顯示由表單設定的 `sections.risk_assessment` 控制。
- 規劃稿寫「風險資料掛在系統主檔、由專案頁籤寫入」，若照此做就要掛到資訊系統而非 SSP；D9 一併裁。

### 文件範本進程序書池 {#design-docs}

- 系統沒有通用的範本產出機制（SSP 匯出寫死 CMMC docx，摘要報告是 Jinja HTML→PDF，`common/util/html_pdf.py:26`）。
- 最小做法：CVD 政策、通報窗口、安全通告、支援期聲明等 4～5 份 docx 放 CRA 公版的資源庫程序書池（`/module-frame/<uid>/reference-documents`），預掛到 13 條控制項；建專案整池複製（`project_start_app_service.py:229-297`）。客戶下載填寫、再上傳成證據。屬純資料（S），範本內容是顧問功課（D10）。
- 「填欄位自動產出」（docxtpl＋Annex II props）是 M～L，屬第三期「三份文件範本」範圍，本期不做。

### 自家 SBOM：可匯，但不會變成證據 {#design-sbom}

- build 產 CycloneDX JSON（`scripts/build/sbom.sh:60,70`），安裝包收進 `sbom/`（`build_bundle.sh:30,359-361`）；源碼掃描對象端點收 CycloneDX 1.2–1.6、SPDX 2.1–2.3（`target_route.py:130-145`）——**現在就能匯**。
- 但掃描模組與控制項證據沒有連結，要當 I.2.a／II.1 證據只能下載報告再手動上傳（D14）。

---

## 階段拆分（草案） {#phases nav="階段"}

| 階段 | 卡（粗切） | 規模 | 依賴 |
|---|---|---|---|
| **P2-A 平台層先行** | A1 控制項樹加 statement／guidance＋規劃頁兩塊（BE＋FE 同卡） | S | 無 |
| | B1 「收證據」範本 SYSTEM 化＋出貨基線放行＋範本來源補值或退回 | M | D4、D12 |
| | B2 控制項層每條各 clone＋規劃頁控制項層那筆補 uid | M | B1 |
| | B3 覆核輪改從上一輪取範本（改 jedi-compliance-audit，發版） | S | D8，B1 |
| **P2-B 表單設定與受評標的擴充** | F1 表單設定落點＋migration＋ORM＋mapper | S～M | D2 |
| | F2 專案取得設定（套件 DTO 或新端點） | S～M | D3、F1 |
| | F3 FE 動態欄位元件（四型別）＋受評標的頁接上＋頁籤開關 | M | F2 |
| | F4 CRA 公版設定內容＋Annex II 六鍵＋A2.x 預設文字（seed） | S | F1、顧問確認預設文字 |
| **P2-C 產品版本與風險** | V1 jedi-asset 版本子表＋CRUD＋FE 子清單 | M | 無（可與 P2-B 平行） |
| | R1 風險評估頁籤雛形（存放處＋頁籤＋表格） | M | D9、F3 |
| **P2-D CRA 內容補強** | C1 套件 AO seed 004（7 條） | S | D6、顧問確認 |
| | C2 證據 locator（對應表欄＋API＋FE＋複製＋快照；視 D7 收舊套） | M | D7 |
| | C3 文件範本 4～5 份上傳 CRA 公版程序書池並預掛 13 條 | S | D10 |
| | C4 重建 CRA 公版與測資（或回灌補丁） | S | D5，C1、F4、C3 全部完成 |

- P2-A 四張卡互不碰 CRA 內容，可立刻派；A1 與 B1 平行。
- P2-D 的 C4 是收口卡：所有要進 catalog 或公版的資料灌完後只重建一次。
- 合計約 14 張卡；design-platform.md 管 P2-A，design-cra.md 管 P2-B～D。

---

## 待決策 {#decisions nav="待裁"}

::: {.callout .pending}
**⏸ D1 — 沒有「複製資源庫」功能：第二期做，還是明列範圍外**

已裁「表單設定隨資源庫複製」，但系統沒有複製資源庫的功能：唯一的 clone（`module_frame_service.py:130-222`）只複製 BPMN 範本與資源庫列，FE 沒有呼叫端。真正「資源庫→副本」只發生在建專案（`oscal_snapshot_service.py:105` 複製 catalog／profile／SSP，`project_start_app_service.py:390` 複製程序書池）。表單設定若放資源庫 JSONB，專案可以直接讀資源庫的設定，不必複製。

[**建議**：明列範圍外，專案直接讀資源庫設定。理由：「之後 SEMI E187 複製 CRA 資源庫微調」是 GRC 期才出現的需求，現在做複製服務要連 profile、SSP 範本、流程範本、程序書池一起處理，是 L 級工程；建專案時已會帶走 SC.props 與程序書池，CRA 第二期用不到複製。風險：資源庫設定事後被改，舊專案畫面會跟著變——表單設定最小版只有 seed 建、沒有畫面編輯器，這個風險現在不存在。]{.rec}
:::

::: {.callout .pending}
**⏸ D2 — 表單設定落點：資源庫 JSONB 欄 vs 新表**

利弊見 §4「CRA 1：資源庫第四件」的對照表。

[**建議**：JSONB（`module_frames.form_settings`）。最小版只有 seed 寫入、沒有畫面編輯器，用不到每欄一列的約束；只動一個 INSERT 與 mapper。結構驗證放程式（讀取時檢查四種型別）。GRC 做表單編輯器時再評估拆表。]{.rec}
:::

::: {.callout .pending}
**⏸ D3 — 專案怎麼拿到表單設定：改套件 DTO 加欄 vs 主專案新端點**

規劃頁現在讀 `GET /grc/project/<uid>`，資源庫資訊只有五欄（jedi-compliance-audit `project_dto.py:72-76`）。

[**建議**：主專案新端點（例 `GET /module-frame/<uid>/form-settings`，用專案已有的 `module_frame_id` 查）。理由：不用為一個欄位發 jedi-compliance-audit 版本、不碰其他 consumer；表單設定是 CRA 期才有的概念，放主專案。代價是規劃頁多一次請求，可接受。]{.rec}
:::

::: {.callout .pending}
**⏸ D4 — 「收證據」範本改 SYSTEM 層級，要動出貨基線的「必須為空」檢查**

出貨基線 `scripts/init/04-seed-core.sql:824,868` 強制 workflow_templates 為空，新裝客戶目前沒有這份範本。要讓所有租戶讀得到，得把這一份放進基線並把檢查改成「只允許這一份 SYSTEM 範本」。重產基線屬決策者裁示。

[**建議**：同意。只放一份、uid 固定、檢查改成白名單。不放的話平台層 B 對新客戶等於沒修。]{.rec}
:::

::: {.callout .pending}
**⏸ D5 — 既有 CRA 公版（SYSTEM 451）與第〇步測資：重建 vs 回灌補丁**

catalog 是建資源庫當下整份複製，之後灌的 AO、guidance、Annex II 預設文字都吃不到。

現況（DEV，2026-10-11 查）：`compliance.module_frames` 451＝SYSTEM 公版（tenant 1），掛專案 1398「CM-2682 公版建專案測試（驗完刪）」；449＝租戶版第〇步測資（tenant 102），掛專案 1397「CRA 第〇步測試（Guidant AI 自評）」。STG／POC 兩台都沒有任何 CRA 資源庫與 CRA 專案（唯讀查證）。

[**建議**：公版重建（seed 遇同名 SYSTEM 庫會跳過，`public_library_seed_cli.py:62-66`，所以要先刪再重跑 `RUN_MODE=seed-public-libraries`），重建 451 時專案 1398 一起刪；449 與專案 1397 保留當第〇步測資，另建一個新測試專案驗收。理由：公版是程式建的、本來就可重跑；回灌補丁要同時處理 catalog、AO 流程範本、控制項預設值三處，等於重寫一次建庫邏輯。STG／POC 都沒有 CRA 資源庫與專案，直接重建沒有外部影響。]{.rec}
:::

::: {.callout .pending}
**⏸ D6 — 7 條 AO 各拆幾個、怎麼拆，由誰定**

[**建議**：runner 以第一期 ENISA 對照底稿（`enisa-mapping-worksheet.md`）的子要求為依據直接擬稿，顧問審稿後才灌。理由：底稿已逐條對到 ENISA 拆出的子要求，起稿成本低；AO 會影響稽核判定單位，不比建議證據可以先上再修，所以要審。]{.rec}
:::

::: {.callout .pending}
**⏸ D7 — 兩套程序書掛法並存，加 locator 時順手收掉舊套嗎**

[**建議**：收。舊套沒有 FE 入口、建專案不複製，只剩控制項詳情 API 回空陣列造成誤導。同卡把詳情 API 改讀新套的對應，舊套寫入路徑標棄用；DEV 查證 `oscal.ssp_reference_documents` 5,222 筆全是 `context_type='ssp'`（池本體），舊套 control_implementation／objective 零筆，`ssp_reference_document_mappings` 45 筆——收舊套不需要搬資料。]{.rec}
:::

::: {.callout .pending}
**⏸ D8 — 覆核輪對控制項層工作傳 None，本期修嗎（改 jedi-compliance-audit）**

`audit_round_app_service.py:774-779` 傳 `fallback=None`，沒 AO 的控制項在覆核輪一定開不出工作。

[**建議**：本期修。平台層 B 修好後首輪會有工作、覆核輪卻沒有，使用者會以為是新 bug；改法小（從上一輪對應紀錄取範本 uid），跟 B 系列卡一起發套件版本。]{.rec}
:::

::: {.callout .pending}
**⏸ D9 — 風險評估雛形存哪：新表 vs 先用受評標的 props 存 JSON 陣列**

SSP 層沒有風險表；規劃稿又寫「資料掛在系統主檔」。

[**建議**：新表，掛專案 SSP（不掛資訊系統主檔）。理由：風險會一筆一筆增刪改，塞 props 的 JSON 陣列會有並發覆寫問題，也難接下一階段的「依元件類型建議威脅」；掛 SSP 符合「專案的風險評估」語意，組織層風險登錄等 GRC 再從各專案彙整。欄位參考 `oscal.assessment_risks`。]{.rec}
:::

::: {.callout .pending}
**⏸ D10 — 4～5 份文件範本 docx 由誰寫**

[**建議**：顧問主筆、runner 只做格式與上傳預掛。理由：CVD 政策、支援期聲明是對外法律文件，AI 起稿可以，但出貨前要有人負責內容；這是決策者功課，不卡 P2-A～C。]{.rec}
:::

::: {.callout .pending}
**⏸ D11 — 舊 `clone_module_frame` 端點保留還是刪**

FE 無呼叫（`api.js:152`），`template_uid` 為空時推斷會在 .xml 步驟壞（未實跑）；平台層 B 補值後它會深複製子流程，語意與新模型可能不一致。

[**建議**：刪（含 FE 常數）。沒人用、補值後行為不可預期，留著反而讓人以為已有「複製資源庫」。D1 若裁要做複製，也是新寫，不在這支上改。]{.rec}
:::

::: {.callout .pending}
**⏸ D12 — 收證據範本來源：建資源庫時寫入 vs 啟動時讀到空值退回系統預設**

[**建議**：啟動時退回系統預設（`project_start_app_service.py:146`）。理由：既有資源庫不必回頭補值，所有租戶自動生效；資源庫有填 template_uid 的照舊優先。建資源庫的 INSERT 不必改。]{.rec}
:::

::: {.callout .pending}
**⏸ D13 — 漏洞揭露政策、通報窗口放哪：資訊系統主檔 vs 受評標的 props**

規劃稿放組織層資訊系統盤點；探脈建議受評標的 props。

[**建議**：值存受評標的 props（跟著專案與表單設定走，CMMC 不受影響），資訊系統主檔本期只加版本子表。理由：放主檔要改 jedi-asset 主表與畫面且所有框架都看得到；第三期通報模組需要時再把窗口提升到主檔。]{.rec}
:::

::: {.callout .pending}
**⏸ D14 — 自家 SBOM「掃描結果→控制項證據」連結、定期執行證明，本期做嗎**

[**建議**：範圍外。只影響 3 條（I.2.a、II.1、II.3），現有做法（下載報告再上傳）可用；連結是 M 級且屬掃描模組與證據模組的整合，放 FR-134 後續或 GRC。]{.rec}
:::

---

## 風險與陷阱 {#risks nav="風險"}

::: {.callout .crit}
**🔴 catalog 是建庫當下整份複製，seed 對既有資源庫與專案無效**

AO、guidance、Annex II 預設文字灌進套件後，既有 CRA 公版與專案都吃不到，必須重建或回灌（D5）。驗收一律用新建的資源庫與專案，不要拿第〇步測資驗。
:::

::: {.callout .crit}
**🔴 拆 AO 不能取代平台層 B**

AO seed 只解 7 條，另 24 條仍靠 template_uid 退路開工，而 DEV 全部是空的。P2-D 不能早於 P2-A 的 B 系列宣告「CRA 準備期能開工」。
:::

::: {.callout .crit}
**🔴 範本跨租戶讀不到也是靜默略過**

「收證據」範本現在是租戶 102 的 TENANT 層級，其他租戶 `get_workflow_template_by_uid` 回空，結果一樣是 0 工作且只有 info log。驗收必須換一個非 102 的租戶建專案。
:::

::: {.callout .crit}
**🔴 同來源範本只 clone 一次，31 筆工作會共用一份副本**

`_clone_for` 快取讓控制項層退回時全部工作共用一份流程副本，`inject_job_execution_uid` 只留最後一筆、編輯器存檔會重複建工作（`prep_job_generation_service.py:139-141,194-203`）。只補範本 uid 不改 clone 粒度，會從「0 工作」變成「31 筆工作互相覆蓋」。
:::

::: {.callout .crit}
**🔴 `_resolve_inscope_catalog` 有兩個使用者，control-tree 有 7 頁在用**

控制項樹與分類器（`ssp_control_implementation_service.py:242`）共用，改回傳形狀兩邊一起改；control-tree 只加欄位、不改 `description` 語意，否則其他 6 頁會壞。
:::

::: {.callout .crit}
**🔴 兩套程序書掛法，只改一套會繼續誤導**

locator 只加在新套對應表，舊套的控制項詳情 API 仍回空陣列；建專案、快照還原各有一份複製邏輯，漏一處 locator 就在新專案消失（D7）。
:::

::: {.callout .crit}
**🔴 擴充屬性鍵要加前綴**

受評標的 props 已存 `target-type`／`owner-uid`，新鍵不加 `ext:` 前綴可能撞名；寫入必須走既有非破壞合併，整包覆寫會把這兩鍵清掉。
:::

::: {.callout .crit}
**🔴 資源庫「第三件」稽核流程範本的欄位也沒人寫**

`module_frames.audit_flow_template_uid` 只有 migration 加欄，app 與 api 全無寫入者，只在建首輪時當預設值讀（`audit_round_app_service.py:302`）。規劃稿說「四件並列」，實際上第三件與收證據退路（template_uid）兩欄建庫時都是空的。設計表單設定時別假設前三件都已完整落地。
:::

---

沿革見 [`handoff/FR-135-LOG.md`](handoff/FR-135-LOG.md) 與 git log。
