# 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.py` 建 `SspControlImplExportItem` 時沒有填 `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` | `SspAoExportItem` 加 `ao_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.py` — `catalog_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）：
   ```bash
   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 觀察：
[貼上問題描述]
```
