SSP 匯入與專案啟動完整流程

白話參考文件 — 涵蓋「新增資源庫 → 匯入 Word / Excel → 啟動專案」全 BE 寫入路徑|文件日期:2026-05-25

適用版本
Excel template v3.0.0 / Docx adapter v2.x
分支
feature/ssp-oscal-alignment
最近 fix
Bug A/B/C/D/E/F 已 close
DB Schema
oscal / compliance / public
目錄
  1. 一、核心概念與名詞對照
  2. 二、Step A:新增合規資源庫 (Module Frame)
  3. 三、Step B:匯入 Word / Excel(兩階段:解析 → 確認)
  4. 四、Step C:啟動專案(建立 AP / AR / Workflow)
  5. 五、所有寫入 Table 總覽表
  6. 六、流程資料問題檢查(潛在風險)
  7. 七、相關檔案 / 設計文件索引

一、核心概念與名詞對照

系統把 OSCAL 規範對應到三個層次,每個層次有自己的「樣板 (template)」跟「實例 (instance)」。 搞懂這三層,整個匯入流程就好理解。
層次OSCAL 對應系統名稱白話說明
控制項層Catalog合規框架 (oscal_frameworks)NIST 800-171 / CMMC L1 / ISO 27001 等控制項全集
樣板層Profile合規資源庫 (module_frame)從 Catalog 挑選一組 controls + 預設「責任單位」「外部利用服務」等「樣板資料」
實作層SSP樣板 SSP (template SSP) + 專案 SSP樣板 SSP 跟 module_frame 1:1,內容是「樣板資料」實體儲存所在;專案啟動時 clone 出新 SSP 給專案用
評估層AP / AR評估計畫 (assessment_plan) / 評估結果 (assessment_result)專案啟動後產生,driving 整個稽核工作流

三段流程的關係(資料流方向)

【Step A】 新增合規資源庫 (module_frame) │ │ 建立空 profile + 空樣板 SSP shell ▼ 【Step B】 匯入 Word / Excel │ │ 把文件解析後的內容(責任單位 / 人員 / 利用授權 / │ 元件 / 資產 / 控制項)寫進樣板 SSP(同個 module_frame) ▼ 【Step C】 啟動專案 │ │ 以 profile 為基準 clone 新 SSP / 建 AP / 建 AR / │ per task clone workflow_template / 建 workflow_execution ▼ 專案進入 PENDING 狀態,user 可開始稽核任務

二、Step A:新增合規資源庫 (Module Frame)

入口 1:手動建立(FE「合規資源庫 → 新增 → 從合規框架挑選」)
入口 2:從 docx/Excel 自動建立(會走 Step B 內的 superset flow,內部呼叫此方法)
入口 3:YAML import (歷史功能)

核心 serviceModuleFrameService.add_module_frame()app/module_frame/service/module_frame_service.py:121

執行步驟(單一 @transaction)

1檢查名稱不重複 READ
public.module_frames WHERE name=?,已存在則 raise ConflictError。
2取得 OSCAL Framework Version READ
payload.oscal_framework_version_uidoscal.oscal_framework_versions,順帶取得對應的 catalog.uid。 這就是「CMMC Level 1」「CMMC Level 2」這類版本選擇實際對應的紀錄。
3建立 OSCAL Profile INSERT
呼叫 OscalProfileService.add_profile(),寫入兩張表:
  • oscal.profiles:含 title (= module_frame.name) / catalog_uid / status='draft'
  • oscal.profile_controls:依 include_controls 從 catalog 挑控制項(空 list = 全納入)— 每筆 control 一 row
4建立 ModuleFrame 主檔 INSERT
寫入 public.module_frames:name / group / version / description / frequency / provider / oscal_framework_version_uid / oscal_profile_uid(指向 Step 3 建的 profile)。
5為每個 Assessment 建 Workflow Template INSERT
遍歷 profile 的所有控制項 (profile_controls),對每個控制項的所有 catalog assessment object 建一個 BPMN workflow template:
  • workflow_templates(jedi_flow_engine):每個 assessment 一筆 template,含「上傳證據」「Reviewer 審核」等預設 BPMN nodes
  • oscal.profile_assessment_workflow_mapping:建立「profile_control × catalog_control_assessment × workflow_template」三方關聯
注意:若控制項沒任何 assessment object(很少見),系統會塞一個預設「Evidence upload」task 進去;確保每個 control 至少有 1 個 workflow。

Step A 完成後 DB 狀態

#TableSchema寫入動作每次呼叫筆數
1oscal.profilesoscalINSERT1
2oscal.profile_controlsoscalINSERTN (控制項數)
3public.module_framespublicINSERT1
4public.workflow_templatespublicINSERTM (assessment 數)
5oscal.profile_assessment_workflow_mappingoscalINSERTM (1:1 對應 workflow_template)
白話總結:建好 module_frame 後,這個資源庫已經有「控制項清單」+「每控制項對應的 BPMN 流程模板」,但還沒有任何樣板資料(單位/人員/外部服務/元件/資產)。樣板資料要靠 Step B 匯入 Word/Excel 填,或 user 在 template-edit 頁手動填。

三、Step B:匯入 Word / Excel(兩階段:解析 → 確認)

系統匯入流程拆兩階段:
  1. 解析 (parse):上傳檔案 → BE 抽取內容 → 存 JSONB 暫存 → 跳預覽頁
  2. 確認 (confirm):user 在預覽頁微調 → BE 寫入正式表
Word (docx) 跟 Excel (xlsx) 的「解析」邏輯不同(parser 各一套),但「確認」階段對「外部利用服務 / 元件 / 資產」三類資料共用同一條 path (SspImportConfirmService) — Bug A/D 修完後完全對齊。

3.1 解析階段(共用:建 parse_job + 寫 parsed_result JSONB)

P1建 parse_job INSERT
Excel → oscal.ssp_excel_parse_jobs
Docx → oscal.ssp_docx_parse_jobs

兩張表 schema 類似:id / status / source_type / source_uid / framework / template_version / file_path / parsed_result (JSONB) / created_at
Status 從 parsingawaiting_reviewcompleted / failed / expired(24h TTL)。
P2檔案存到 MinIO / 本地 INSERT
透過 jedi-file-upload 套件,原始檔上傳到 storage,parse_job.file_path 存 file_uid (對應 uploaded_files 表)。
P3Parser 抽取內容 UPDATE
  • Excel:依 v3.0.0 樣板 8 個 sheet(基本資料 / 受評標的 / 單位 / 參與人員 / 利用授權 / 元件清冊 / 資產清冊 / 控制項與AO / 程序書)抽 row dict → 組 ParsedExcel
  • Docx:依 CMMC SSP 樣板 section anchor 抽 metadata / parties / Table #6 (FedRAMP 外部服務) / Table #7 (Category 外部服務) / 控制項 narrative
抽完寫進 parsed_result JSONB(schema_version=v2-bundle);status 改 awaiting_review,FE 跳預覽頁。

3.2 確認階段(依 source_type 分三條 flow)

source_type 是 FE 在「上傳」前選的,決定 confirm 階段寫到「誰」:

Flow B-1:framework_version(從框架建新資源庫,superset flow)

B1a套 user 在預覽頁的編輯 UPDATE
四個 helper 依序套用:_apply_content_overrides(user 改字串)→ _apply_inline_creates(user 新建 device/user/...)→ _apply_decisions(user 選下拉框)→ _apply_removed_rows(user 標記不匯入的 row)。全在同個 @transaction 內,失敗整段 rollback。
B1b呼叫 Step A 建立 MF + Profile + Workflow templates INSERT
內部呼叫 ModuleFrameService.add_module_frame()(就是 Step A 那套),所以 Step A 的 5 張表都會建。include_controlscontrols_with_aos_target_in_profile=true 那批,限縮 profile 範圍。
B1c確保 Template SSP shell 存在 INSERT
對 module_frame 來源的匯入,須有一個「樣板 SSP」承載責任單位 / 利用授權 / 元件 / 資產等資料:
  • oscal.oscal_metadatas:SSP metadata
  • oscal.system_security_plans:template-level SSP shell(連 profile_id / status=draft)
(Bug A fix 後新增的 path,見 SspShellService.ensure_shell()
B1d寫責任單位 / 人員(Parties)INSERT
透過 ModuleFrameWriteStrategy.write_parties
  • oscal.oscal_parties:每筆 party 一 row(含 name / email / address / telephone / party_type / role)
  • oscal.oscal_responsible_parties:建立 mf ↔ party 的「責任角色」link(含 role_id / party_uuid / context_type='module_frame' / context_id=mf_id)
Bug B fix:docx 解出來的 person 沒 role 欄位時 fallback default role(org → responsible-organization, person → system-user);否則 _upsert_responsible_party 在空 role 會 silent return,link 表完全沒寫。
B1e寫利用授權 / 元件 / 資產(v2-bundle dispatch)INSERT
透過 SspImportConfirmService.confirm() 內三 strategy 按序:
  • LeveragedWriteStrategy.writeoscal.ssp_leveraged_authorizations(overwrite 模式 — 先 delete 既有,再 insert)
  • ComponentWriteStrategy.writeoscal.ssp_components(含 leveraged_authorization_uid FK resolve)
  • InventoryItemWriteStrategy.writeoscal.ssp_inventory_items + M2M oscal.ssp_inventory_item_components
順序固定(FK 依賴:inventory → component → LA)。
Bug D fix:docx Table #7 (Category) 行除了 emit Component 之外也 emit LA(用 props JSONB 帶 category / protocol / port_ranges / security_auth 等 non-OSCAL fields),與 Table #6 (CSP/CSO) 對稱。修前 4 筆只寫 1 LA。
B1f寫控制項 narrative / 受評標的 (SC) INSERT
  • oscal.system_security_plan_control_implementations:每控制項 narrative
  • oscal.system_security_plan_control_implementation_objectives:每 AO 的 narrative / impl_status
  • oscal.system_security_plan_system_characteristic:受評標的(system_name / security_sensitivity_level / status)
B1g寫 import_summary + parse_job 收尾 UPDATE
parse_job status → completed,summary 寫進 import_summary JSONB;回傳 mf_uid / profile_uid 給 FE。

Flow B-2:module_frame(更新既有資源庫)

跟 B-1 差異:

Flow B-3:ssp(per-AP SSP 編輯)

跟 B-1 差異:

3.3 Word 跟 Excel 的差異一覽

項目Word (docx)Excel (xlsx)
解析方式section anchor + 內表抽取固定 sheet 名 / column index
外部利用服務拆 tableTable #6 FedRAMP + Table #7 Category(兩 table)
Bug D fix 後兩 table 都 emit LA
單一 利用授權 sheet,每行 1 LA
Parties role 預設值抽不到 role 時 fallback (Bug B fix 後)SHEET_PERSONS 有 role enum 欄位,user 直接選
樣板版本檢查有 GRC_DOCX_FRAMEWORK_MISMATCH 守門有 GRC_EXCEL_TEMPLATE_VERSION_UNSUPPORTED (v2.x 拒絕)
props 欄位T7 自動帶 category / protocol / security_auth 等目前 sheet 沒帶 category 欄位 → LA.props 多半 NULL(cross-source 不一致,列 follow-up)

四、Step C:啟動專案(建立 AP / AR / Workflow)

入口:POST /api/1.0/oscal/projects/startOscalProjectService.start_oscal_project()
整個方法單一 @transaction;除 Step 7 有 try/except 外,任何失敗整段 rollback。
寫入 21 張表(含某些表多次寫入)。

Request Payload

{
  "profile_uid":   "required — OSCAL Profile UID (對應 module_frame.oscal_profile_uid)",
  "ssp_uid":       "optional — 既有 SSP UID;不傳則自動建新 SSP",
  "name":          "required — 專案名稱",
  "description":   "optional",
  "start_date":    "optional — YYYY-MM-DD",
  "end_date":      "optional — YYYY-MM-DD"
}

執行步驟

1檢查專案名稱不重複 READ
compliance.projects WHERE name=?
2取得 Profile READ
oscal.profiles WHERE uid=?,找不到 raise NotFound。
3取得或建立 SSP INSERT (optional)
若無 ssp_uid → 呼叫 SspService.add_empty_ssp(profile_id)
  • oscal.oscal_metadatas:SSP metadata(每 OSCAL 模型必有 metadata)
  • oscal.system_security_plans:SSP 主檔(連 profile_id)
4建立 Assessment Plan (AP) INSERT
  • oscal.oscal_metadatas:AP metadata
  • oscal.assessment_plans:AP 主檔(status=ACTIVE,連 profile + ssp)
4.5建立空白 Assessment Result (AR) INSERT
  • oscal.oscal_metadatas:AR metadata
  • oscal.assessment_results:AR 主檔(連 AP)
  • oscal.assessment_result_datas:初始 run_no=1
5建立 Project 主檔 INSERT
compliance.projects(status=PENDING)— 走 jedi-project 套件。
6建立 Project ↔ AP 關聯 INSERT
compliance.project_assessment_plan_mapping
7初始化 AP Controls / Groups / Tasks INSERT try/except
從 Profile→Catalog 把控制項清單 clone 到 AP:
  • oscal.assessment_plan_groups:每 catalog group 一 row
  • oscal.assessment_plan_controls:每 control snapshot 一 row(凍結 title / control_id)
  • oscal.assessment_plan_tasks:每 control assessment 一 row(task_code / title / assessment_methods)
  • oscal.assessment_task_controls:task ↔ control 關聯
⚠️ 風險點:此 step 被 try/except 包,失敗只 log 不 raise → AP tasks 為空 → Step 8 的 for loop 不執行 → 整個專案沒任何 workflow。但因為其他 step 已 commit,user 看 project 是 PENDING 但無法做任何任務。詳見「六、流程資料問題檢查」。
8為每個 AP Task 建立 Workflow(per task loop) INSERT silent continue
每個 task 依序執行:
  1. 查 workflow_template mappingoscal.profile_assessment_workflow_mapping。找不到 → silently continue(該 task 永遠沒 workflow)⚠️
  2. Clone workflow_template(避免之後改 template 影響已啟動的專案):workflow_templates (parent_template_id 指向原始)
  3. 建 Workflow Executionworkflow_executions(type=SUB_PROCESS, status=TODO)+ 遞迴處理巢狀 → 為每個 BPMN User Task 建 job_executions + element_variables(PROCESS / TASK 兩種)
  4. 建 AP task ↔ Workflow Template 關聯oscal.assessment_plan_task_workflow_mapping
  5. 建 AP task ↔ Workflow Execution 關聯oscal.assessment_plan_task_workflow_execution_mapping
9創建者加入專案管理員 INSERT UPDATE
  • compliance.project_participants INSERT(is_admin=True)
  • oscal.oscal_metadatas UPDATE — 把 user 當 Person party 加進 SSP metadata 的 parties 列表

呼叫鏈視覺化

POST /oscal/projects/start │ └─ OscalProjectService.start_oscal_project() [@transaction] │ ├─ Step 1: 名稱檢查 → READ compliance.projects ├─ Step 2: Profile 取得 → READ oscal.profiles ├─ Step 3: SSP get/add → INSERT oscal_metadatas, system_security_plans ├─ Step 4: AP add → INSERT oscal_metadatas, assessment_plans ├─ Step 4.5: AR add → INSERT oscal_metadatas, assessment_results, │ assessment_result_datas ├─ Step 5: Project add → INSERT compliance.projects ├─ Step 6: Project↔AP → INSERT project_assessment_plan_mapping │ ├─ Step 7: init AP controls [try/except] │ → INSERT ap_groups, ap_controls, ap_tasks, assessment_task_controls │ └─ Step 8: for task in ap.tasks (若 Step 7 失敗則 0 iter) ├─ READ profile_assessment_workflow_mapping (找不到 → continue) ├─ INSERT workflow_templates (clone 定版) ├─ INSERT workflow_executions + element_variables + job_executions └─ INSERT assessment_plan_task_workflow_mapping assessment_plan_task_workflow_execution_mapping └─ Step 9: add participant → INSERT project_participants UPDATE oscal_metadatas (SSP parties)

五、所有寫入 Table 總覽表

5.1 Step A:新增合規資源庫

#TableSchema套件動作說明
1profilesoscaljedi_oscalINSERT樣板 profile 主檔
2profile_controlsoscaljedi_oscalINSERT × N每控制項一 row
3module_framespublicmainINSERT資源庫主檔
4workflow_templatespublicjedi_flow_engineINSERT × M每 assessment 一筆 BPMN template
5profile_assessment_workflow_mappingoscalmainINSERT × Mprofile_control × assessment × template 三方關聯

5.2 Step B:匯入 Word / Excel(完整 superset / module_frame flow)

#TableSchema動作說明
解析階段
P1ssp_excel_parse_jobs / ssp_docx_parse_jobsoscalINSERTparse_job 主檔
P2uploaded_files(jedi)INSERT原始檔 storage record
P3同上 (parse_job)oscalUPDATEparsed_result JSONB + status=awaiting_review
確認階段 — superset (建新 mf)
C1~C5同 Step A 的 5 張表INSERT內部呼叫 add_module_frame
C6oscal_metadatasoscalINSERT樣板 SSP metadata
C7system_security_plansoscalINSERT樣板 SSP shell(Bug A fix 後新增)
確認階段 — entity 樣板資料寫入
C8oscal_partiesoscalINSERT/UPSERT每筆 party 一 row
C9oscal_responsible_partiesoscalINSERTmf ↔ party 角色 link(context_type=module_frame)
C10ssp_leveraged_authorizationsoscalDELETE + INSERToverwrite 模式
C11ssp_componentsoscalDELETE + INSERT每元件一 row,含 leveraged_authorization_uid FK
C12ssp_inventory_itemsoscalDELETE + INSERT每資產一 row
C13ssp_inventory_item_componentsoscalINSERT資產 ↔ 元件 M2M
C14system_security_plan_control_implementationsoscalINSERT控制項 narrative
C15system_security_plan_control_implementation_objectivesoscalINSERTAO narrative + impl_status
C16system_security_plan_system_characteristicoscalINSERT受評標的
C17module_frame_reference_documentsoscalINSERT程序書 (若 Excel 有填)
收尾
C18parse_job (same as P1)oscalUPDATEstatus=completed + import_summary JSONB

5.3 Step C:啟動專案

#TableSchema套件動作說明
1oscal_metadatasoscaljedi_oscalINSERTSSP metadata
2system_security_plansoscaljedi_oscalINSERTSSP 主檔
3oscal_metadatasoscaljedi_oscalINSERTAP metadata
4assessment_plansoscaljedi_oscalINSERTAP 主檔
5oscal_metadatasoscaljedi_oscalINSERTAR metadata
6assessment_resultsoscaljedi_oscalINSERTAR 主檔
7assessment_result_datasoscaljedi_oscalINSERTAR 初始 run
8assessment_plan_groupsoscaljedi_oscalINSERT × NAP 群組 (clone)
9assessment_plan_controlsoscaljedi_oscalINSERT × NAP 控制項 snapshot
10assessment_plan_tasksoscaljedi_oscalINSERT × MAP 任務
11assessment_task_controlsoscaljedi_oscalINSERTtask ↔ control
12projectscompliancejedi_projectINSERT專案主檔 (status=PENDING)
13project_assessment_plan_mappingcompliancemainINSERTProject ↔ AP
14workflow_templatespublicjedi_flow_engineINSERT × M複製定版 template
15workflow_executionspublicjedi_flow_engineINSERT (含巢狀)子流程 instance
16element_variablespublicjedi_flow_engineINSERTWorkflow / Job 變數
17job_executionspublicjedi_flow_engineINSERTBPMN User Task instance
18assessment_plan_task_workflow_mappingoscalmainINSERTAP task ↔ template
19assessment_plan_task_workflow_execution_mappingoscalmainINSERTAP task ↔ execution
20project_participantscompliancemainINSERT創建者 = 管理員
21oscal_metadatasoscaljedi_oscalUPDATESSP parties 加 user

六、流程資料問題檢查(潛在風險)

以下列出目前流程已知的「設計潛在風險」+「歷史 bug 教訓」,做為日後 review / 維護重點。

6.1 啟動專案:Step 7 silent failure 可能造成 zombie project 高風險

問題init_ap_controls_from_profile 用 try/except 包,失敗只 log 不 raise。
後果
  1. AP tasks 完全沒建
  2. Step 8 的 for loop 0 iter(沒 workflow_templates / workflow_executions / job_executions)
  3. 但 Step 5/6 已寫 Project + Mapping → commit
  4. User 看到專案是 PENDING 但點進去發現完全沒任務 — 完全 stuck
建議:拿掉 try/except,讓失敗整段 rollback;或加 post-condition assertion「AP tasks 數 > 0」+ raise。

6.2 啟動專案:Step 8 找不到 workflow_template silently continue 中風險

問題profile_assessment_workflow_mapping 查不到對應 → continue,該 AP task 永遠沒 workflow。
後果:部分 task 無法執行;user 不知道是「該 task 無流程」還是「流程跑爛」。
發生條件:Step A 建 mf 時某些 assessment 漏建 template(很少見但可能);或 mf 建好後手動刪了 mapping。
建議:log.warning + 寫入 AP 的 import_warnings;或在啟動前 pre-flight check(缺幾個 task 沒 workflow 立刻 raise)。

6.3 匯入:「parties_written 計數」會騙人 中風險(已部分 fix)

問題(Bug B 教訓)write_parties return 的計數只算 oscal_parties 寫成功的 row,不驗 oscal_responsible_parties link 是否真的建。Caller 看到 parties_written=5 以為 OK,實際 link 表 0 筆。
已 fix:Bug B 第二段 fix 補 default role;但底層 silent skip pattern (if not X: return) 還在 jedi-oscal 套件內。
建議:jedi-oscal 進版時改 log.warning 或 raise;strategy.write 加 post-write verification(兩張表 row count 一致才 return)。

6.4 匯入:跨 source 不一致(Word vs Excel)中風險(已部分 fix)

問題(Bug D 教訓):Word docx Table #7 加 LA props (category / protocol / security_auth),Excel 利用授權 sheet 沒對應欄位 → Excel 匯入的 LA 全部沒 category。
後果:跨 source 行為差異;UI 顯示 Excel 來源「印表機」category 是 — (空白),docx 來源是「互連」(interconnection)。
建議
  1. 短期 — Excel 利用授權 sheet 加 category 欄位(enum: external-service / interconnection / api / fedramp)
  2. 長期 — 共用 ParsedLA adapter helper,Excel + docx + 未來 OSCAL JSON 都從同個地方 build ParsedLA

6.5 匯入:source_type 三分支(framework_version / module_frame / ssp)有歷史漏洞 已 fix

問題(Bug A 教訓):早期 docx confirm path 只處理 project_sspmodule_frame 分支整段缺失 → 樣板 SSP shell 從沒建 → entity 寫入全失敗。
已 fixSspShellService.ensure_shell() 自動 resolve-or-build;docx + Excel 兩 service 都接通。

6.6 匯入:content_overrides 應用順序 vs v2-bundle dispatch 已 fix

問題(Bug C 教訓):早期 user 在預覽頁編輯後,_apply_content_overrides 改 v1 keys (devices / leveraged) 但 _run_v2_bundle_confirm 讀 v2-bundle keys → user 編輯 silent loss。
已 fix:confirm 內加 derive_v2_bundle_keys(parsed_result) 在 dispatch 前 re-derive。

6.7 設計級風險:Overwrite vs Append 語意混合 設計面

觀察LeveragedWriteStrategyComponentWriteStrategy 都採 overwrite(先 delete 既有 → re-insert)。但 oscal_partiesoscal_responsible_partiesupsert(不刪舊)。
後果:重複匯入同一份文件,parties 會累積(雖然 idempotent,但留下舊孤立 parties record);leveraged / components / inventory 每次重整。
建議:明確標註各 strategy 的 overwrite vs upsert 語意;考慮統一行為(user 可選「重整」vs「增補」)。

6.8 設計級風險:跨 schema FK 沒 constraint 設計面

觀察compliance.project_assessment_plan_mapping(compliance schema)參考 oscal.assessment_plans(oscal schema),但這條跨 schema FK 沒在 DB 層建 constraint(per CLAUDE.md DDD 規範 — soft Integer reference)。
後果:刪 AP 不會 cascade 刪 mapping;orphan row 累積。
緩解:app service 層做手動 cascade;長期可考慮加 trigger 或 cleanup job。

6.9 設計級風險:project_extensions 不在 Step C 內 設計面

觀察compliance.project_extensions(含 module_frame_id / owner_id 等 GRC 專屬欄位)由另一個路由維護,不在 Step C 啟動流程內。
後果:啟動專案後立刻查 project_extensions 會是空 row;GRC 模組需要 project_extensions 才能顯示完整資訊。
緩解:FE 在「啟動專案」之後立刻 call POST /grc/projects/{uid}/extensions 補;但沒程式碼保證 user 一定點得到。

6.10 設計級風險:parse_job TTL 24h 已設計

機制:parse_job 預設 24h 後 expire(status → expired),confirm 會被擋。
清理:背景 scheduler「framework_parse_job_cleanup」每日 01:00 UTC 跑。
建議:UI 顯示 TTL 倒數計時(目前 schema 有 ttl_expires_at 欄位但 FE 沒 surface)。

七、相關檔案 / 設計文件索引

類別路徑用途
Specdocs/features/FR-028-2605-ssp-oscal-alignment/design.mdSSP OSCAL alignment 完整設計(含 §11 reconciliation)
Phase 4 SUMMARYdocs/features/FR-028-2605-ssp-oscal-alignment/handoff/2026-05-25-phase4-COMPLETE-SUMMARY.mdPhase 4 收尾 (Excel preview / inline CRUD / 移舊 tab)
Bug D SUMMARYdocs/features/FR-028-2605-ssp-oscal-alignment/handoff/2026-05-25-bug-d-FIXED-SUMMARY.mdBug D / E / F 完整 fix
啟動專案邏輯prompt/oscal_project_start_flow.mdOscalProjectStartRoute 21 表寫入順序
Excel parserapp/oscal/service/excel_parser/parser.py / sheet_handlers.py / v2_bundle.py / types.py
Excel sheet schemaapp/module_frame/excel_template/sheet_definitions.py8 個 sheet 的欄位定義(含 v3.0.0 OSCAL-aligned 重組)
Excel confirmapp/oscal/service/ssp_excel_import_app_service.py3 條 flow (superset / update / ssp_update)
Docx parserdomain/oscal/parser/docx_section_extractors.pySection anchor 抽取(Table #6 / #7 / parties)
Docx adapterdomain/oscal/adapter/cmmc_ssp_adapter.pyParsedDocx → ParsedSsp + adapt_to_bundle (Bug D fix)
Docx confirmapp/oscal/service/ssp_docx_import_app_service.pyconfirm_import + _run_v2_bundle_confirm
共用 confirm servicedomain/oscal/import_pipeline/confirm_service.pyExcel + Docx 共用 LA / Component / Inventory 寫入
Write strategiesdomain/oscal/service/write_strategy/leveraged / component / inventory write strategy
jedi-oscal 套件~/Projects/Jedicogy/module/jedi-python-package/jedi-oscal/OSCAL entity / service / repo(jedi 系列)
OSCAL knowledge skill~/.claude/skills/oscal-knowledge/OSCAL 8 model 完整 reference