SSP 匯入匯出 Phase 2 — B 階段完成 + Debug 交接

日期:2026-05-22
狀態:B1~B6 全部 shipped;進入 debug 階段


1. 本 session 完成事項

Bug 修正:DOCX 匯出控制項名稱與 AO 說明空白

症狀:匯出的 DOCX 中,控制項名稱(Control Name)欄位空白;AO 列只顯示識別碼「(a)」,缺少 catalog AO 說明文字。

根本原因

  • ControlImplementationMapper.to_entity() 在 jedi-oscal 中從未映射 catalog_control 關聯,所以 SSP 版本來源的控制項實作 entity 的 catalog_control 永遠是 None
  • ssp_mf_content_loader.pySspControlImplExportItem 時沒有填 control_name;AO 只傳了 user 的 implementation_description,catalog 說明從未被使用

修正範圍(5 個檔案 + jedi-oscal 1 個): | 檔案 | 改了什麼 | |------|----------| | jedi-oscal: infra/mapper/ssp/control_implementation_mapper.py | to_entity()catalog_control 映射(lazy-load,session 內有效) | | app/oscal/service/export/ssp_export_model.py | SspAoExportItemao_name: str 欄位 | | app/oscal/service/export/ssp_mf_content_loader.py | 新增 _build_catalog_maps(mf) 從 profile controls 建 lookup;_build_control_implementations() 填入 control_name + ao_name | | app/oscal/service/export/ssp_version_content_loader.py | 用 ctrl.catalog_control.control_title + assessments 填入 control_name + ao_name | | app/oscal/service/export/ssp_docx_generator.py | all_objectives context 加入 ao_name | | scripts/generate_ssp_docx_template.py + .docx | AO 表格加入「AO Catalog Description AO 說明」欄位並重新生成 |

Changelog:docs/changelog/2026-05-22-fix-ssp-docx-export-missing-control-ao-names.md


2. B 階段全部完成情況

Phase 主題 狀態
B1 Docx 樣板 + generator 骨架 ✅ shipped
B2 內容組裝(MF + SSP version 兩來源) ✅ shipped
B3 Docx Export API ✅ shipped
B4 PDF + ODT ✅ shipped
B5 OSCAL JSON / XML / YAML 匯出 ✅ shipped
B6 前端 UI + 格式選擇 ✅ shipped

B 階段無後續 phase。已進入人工測試 / debug 階段。


3. 目前程式碼狀態

jedi-oscal(本地 path dependency)

  • Branch:feature/ssp-import-export-phase2(或同名 branch 在 jedi-oscal 端)
  • pyproject.toml:dev 期間走 path dependency(jedi-oscal = { path = "...", develop = true} 已取消註解),尚未 commit
  • 最新修改(尚未 commit):control_implementation_mapper.pycatalog_control 映射

BE(compliance-manager-be)

  • Branch:feature/ssp-import-export-phase2
  • 上次 commit:abf7d60(docs)
  • 目前 uncommitted 修改:
    • app/oscal/service/export/ssp_export_model.py
    • app/oscal/service/export/ssp_mf_content_loader.py
    • app/oscal/service/export/ssp_version_content_loader.py
    • app/oscal/service/export/ssp_docx_generator.py
    • scripts/generate_ssp_docx_template.py
    • app/oscal/templates/ssp/ssp_cmmc_template.docx
    • docs/changelog/2026-05-22-fix-ssp-docx-export-missing-control-ao-names.md

FE(compliance-manager-fe)

  • B6 已 committed;無 uncommitted 修改

4. 測試接力點

煙霧測試建議步驟

  1. 重啟 BE(修了 service 層 code,必須 kill+restart):

    lsof -ti:8000 | xargs kill -9
    python main_socketio.py &
  2. 測試 MF 來源 docx 匯出

    GET /api/1.0/module-frame/<mf_uid>/ssp-export?format=docx

    預期:下載的 DOCX 控制項表格有 Control Name;AO 表格有「AO Catalog Description」欄位顯示 catalog 說明

  3. 測試 SSP 版本來源 docx 匯出

    GET /api/1.0/ssp/<ssp_uid>/export?format=docx

    預期:同上,控制項名稱和 AO 說明有值

  4. 測試 OSCAL 格式仍正常

    GET /api/1.0/ssp/<ssp_uid>/export?format=json
    GET /api/1.0/ssp/<ssp_uid>/export?format=yaml
    GET /api/1.0/ssp/<ssp_uid>/export?format=xml
  5. 測試 FE 按鈕

    • 合規資源庫 → 批次維護 → SSP 文件匯出(docx/pdf/odt)
    • 專案規劃頁 → 批次選單 → SSP 文件匯出(docx/pdf/odt/json/yaml/xml)

5. 已知潛在問題 / Debug 觀察點

問題 描述 排查方向
catalog_control lazy-load 可能產生 N+1 每個 control implementation 會觸發一次 SELECT catalog_controls 先 profile 觀察,如有效能問題再加 joinedload
MF 來源:AO 沒有 catalog 說明時顯示空白 statement_identifier 格式不是 UUID 也不是 (a)/(b) pattern,ao_desc_map 查不到 觀察實際資料中 statement_identifier 格式;可能需要補充更多配對邏輯
PDF / ODT 轉換依賴 LibreOffice 未安裝 LibreOffice 時 pdf/odt 請求會回 500 確保 LibreOffice 已安裝;錯誤訊息見 BE log
jedi-oscal path dep 未 commit dev 環境可用;CI / staging 需要正式 bump 版號後才能跑 測試全程用本地 path dep;待 feature arc 收口再 bump

6. Debug Session 接手 Prompt

貼上此段開始新 session:

你好,我在 compliance-manager-be 專案的 feature/ssp-import-export-phase2 branch,
目前正在 debug SSP Export 功能(B 階段已全部 shipped)。

本地 jedi-oscal 用 path dependency(~/Projects/Jedicogy/module/jedi-python-package/jedi-oscal/)。

最近的修改(未 commit):
- 修了 DOCX 匯出控制項名稱與 AO 說明空白的 bug
  - jedi-oscal: control_implementation_mapper.py 加了 catalog_control 映射
  - BE: ssp_export_model.py 加了 SspAoExportItem.ao_name 欄位
  - BE: ssp_mf_content_loader.py + ssp_version_content_loader.py 填入 control_name + ao_name
  - BE: ssp_docx_generator.py + template 更新

BE log 在 log/app.log。
Dev DB:192.168.50.188:25432 / guidant_ai_dev / 帳號 cmmgr(密碼見 .env)。

以下是我的 debug 觀察:
[貼上問題描述]