# C8 — Implementation Plan

> 對應 design：[design-C8.md](design-C8.md)
> 級別：小
> 預估工時：BE 0.5 天（含 test fix）

---

## Pre-flight 驗證

```bash
# 1. 確認 _ROLE_LABEL_MAP 仍在預期位置
grep -n "_ROLE_LABEL_MAP" app/oscal/service/export/ssp_docx_generator.py
# 預期：line 32

# 2. 確認 _ROLE_LABEL_PATTERNS 仍在預期位置
grep -n "_ROLE_LABEL_PATTERNS\|_ORGANIZATION_ROLES" domain/oscal/adapter/cmmc_ssp_adapter.py
# 預期：line 49 / 56

# 3. data audit — 既有 SSP 用 'security-officer' 的數量
psql -h 192.168.50.188 -p 25432 -U cmmgr -d guidant_ai_dev -c \
  "SELECT role_id, COUNT(*) FROM oscal.oscal_responsible_parties
   WHERE role_id IN ('security-officer','manager','auditor','viewer','reviewer')
   GROUP BY role_id ORDER BY role_id;"
# 預期：希望全 0（若有需 data fix migration）

# 4. 找出測試會 break 的位置
grep -rn "security-officer\|_ROLE_LABEL_MAP\|_ROLE_LABEL_PATTERNS" tests/ --include="*.py" | head -10
```

---

## 任務清單

### T1 — 修 `ssp_docx_generator.py` _ROLE_LABEL_MAP（BE）

**檔案**：`app/oscal/service/export/ssp_docx_generator.py:32`

**改動**：對齊 design-C8.md §3.1（9 條 OSCAL 標準角色，移除 manager/auditor/viewer + 修 system-security-officer）

**測試**：
- 跑既有 SSP docx 匯出單元測試確認不 break
- 必要時 update test fixture（map 內容已改）

**Commit message**：`fix(ssp-export): C8 _ROLE_LABEL_MAP 對齊 OSCAL 9 個標準角色，移除誤入專案角色`

---

### T2 — 修 `cmmc_ssp_adapter.py` _ROLE_LABEL_PATTERNS（BE）

**檔案**：`domain/oscal/adapter/cmmc_ssp_adapter.py:49`

**改動**：對齊 design-C8.md §3.2（9 條 pattern + 補 `prepared-for` 到 `_ORGANIZATION_ROLES`）

**測試**：
- `tests/test_cmmc_ssp_adapter.py` — 加新測試 case：
  - docx 含「授權機關」/「Authorizing Official」字樣 → 解析出 role='authorizing-official'
  - docx 含「文件撰寫者」 → 解析出 role='prepared-by'
- 既有 5 角色測試 case 維持

**Commit message**：`feat(ssp-docx-parser): C8 CMMC adapter 角色 pattern 擴增到 9 個 OSCAL 標準角色`

---

### T3 — Data fix migration（依 pre-flight 結果決定是否需要）

**前提**：pre-flight Step 3 audit 發現有 broken role_id（`security-officer` 等）

**檔案**：`scripts/sql/2026-MM-DD-fix-broken-ssp-role-ids.sql`

```sql
-- Date: 2026-MM-DD
-- Purpose: C8 — 修 oscal_responsible_parties 內 broken role_id
-- 帳號：cmmgr

BEGIN;

-- 1. security-officer → system-security-officer (2026-MM-DD)
UPDATE oscal.oscal_responsible_parties
   SET role_id = 'system-security-officer'
 WHERE role_id = 'security-officer';

-- 2. 清除誤入的專案角色（這些根本不該在 SSP context）
-- 注意：執行前先 audit 是否真的全為 SSP context 殘留
SELECT role_id, context_type, COUNT(*)
  FROM oscal.oscal_responsible_parties
 WHERE role_id IN ('manager','reviewer','auditor','viewer')
 GROUP BY role_id, context_type;

-- 確認後 (uncomment 才執行)
-- DELETE FROM oscal.oscal_responsible_parties
--  WHERE role_id IN ('manager','reviewer','auditor','viewer');

COMMIT;

-- 驗證
-- SELECT role_id, COUNT(*) FROM oscal.oscal_responsible_parties
-- WHERE role_id IN ('security-officer','manager','reviewer','auditor','viewer')
-- GROUP BY role_id;
-- 預期：0
```

**Commit message**：`chore(sql): C8 修 oscal_responsible_parties broken role_id (security-officer 等)`

**注意**：DELETE 那段預設註解，pre-flight 後 user 確認再開。

---

### T4 — Test fixtures 更新（BE）

**可能受影響的測試**：
- `tests/test_cmmc_ssp_adapter.py`
- `tests/test_ssp_docx_import_diff_response.py`
- `tests/test_ssp_write_strategy_v2_parties.py`
- `tests/test_ssp_export*.py`（B 階段相關）

**動作**：
- 跑 `pytest tests/ -k "role"` 看哪些 break
- 逐一 update assertion 對齊新 map / patterns
- 加新測試 case for 新角色 (authorizing-official / prepared-by / prepared-for / information-owner)

**Commit message**：`test(ssp): C8 更新 test fixtures 對齊 9 個 OSCAL 角色`

---

### T5 — Changelog

**檔案**：`docs/changelog/YYYY-MM-DD-tweak-ssp-role-label-cleanup.md`

```markdown
---
type: tweak
breaking: false
modules: [oscal_export, oscal_docx_import]
---

## 需求說明
C8：清理 _ROLE_LABEL_MAP 內誤入的專案角色 (manager/auditor/viewer)，
修 security-officer → system-security-officer 對應，
擴增 CMMC docx adapter pattern 到 9 個 OSCAL 標準角色。

## 變更範圍
### BE
- `app/oscal/service/export/ssp_docx_generator.py`：_ROLE_LABEL_MAP 重寫
- `domain/oscal/adapter/cmmc_ssp_adapter.py`：_ROLE_LABEL_PATTERNS 擴增 + _ORGANIZATION_ROLES 補 prepared-for
- `tests/`：更新 fixture + 新 role 測試 case
- (optional) `scripts/sql/2026-MM-DD-fix-broken-ssp-role-ids.sql`

## 行為差異
- SSP 匯出時不再出現 manager/auditor/viewer 文字（誤入專案角色）
- CMMC docx 匯入可辨識 authorizing-official / prepared-by 等 4 個新角色
```

---

## 測試規格

| 測試 | 內容 |
|------|------|
| Unit | docx_generator 對 9 個 role_id 都能輸出對應 label |
| Unit | cmmc_adapter 對 9 個中英文 pattern 都能 match |
| Unit | unknown role_id fallback 行為（顯示 raw key）|
| Integration | 跑一份 CMMC SSP docx import → 確認新角色被正確解析 |
| Manual | 跑一份 SSP docx 匯出 → 確認 role 顯示正常 |

---

## 完成標準（DoD）

- [ ] `_ROLE_LABEL_MAP` 對齊 9 個 OSCAL 角色
- [ ] `_ROLE_LABEL_PATTERNS` 擴增到 9 個
- [ ] 既有測試全綠
- [ ] 新角色測試 case 加入
- [ ] （optional）broken role_id data fix SQL 跑完
- [ ] Changelog 完成
- [ ] README tracker (C8) 狀態更新

---

## 風險 / Rollback

| 風險 | 緩解 |
|------|------|
| 既有 SSP 有 `security-officer` 資料，改 map 後匯出顯示 raw key | 跑 T3 data fix SQL |
| Test fixtures 漏改造成 CI red | 開工前 `grep -rn "_ROLE_LABEL" tests/` 確認全找到 |

**Rollback**：純程式碼改動，`git revert` 即可
