# Session Handoff — 2026-05-24

| 項目 | 內容 |
|---|---|
| Date | 2026-05-24 |
| Branch | `feature/real_doc_import` |
| Latest commit | `daf2475` |
| BE | Running on :8000 (PID 43568, user 自己起的；非 Claude 起的 — kill 前先確認) |
| Pushed? | **NO** — 所有 commits 仍 local-only |
| 下個 session 預設工作 | `ssp-oscal-alignment` Phase 1 brainstorm + 評估 |

---

## TL;DR — 接手前必讀（3 分鐘）

1. **今天主軸**：docx import 補完 → 驗證可用 → 浮出 OSCAL 結構性對齊議題 → 規劃 5 phases / 25d 的 `ssp-oscal-alignment` feature
2. **目前狀態**：
   - Stage 1 (docx-import-parity) 已上線運作、BE 能完整解客戶 docx
   - Excel template v2.6.0 — leveraged 14 cols + parties 補 address/phone/title
   - FE LeveragedSection 對齊 13 欄 + row expander 顯示完整資料
   - ssp-oscal-alignment design.md 完整規劃寫好（766 行）
3. **明天起重點**：開始走 `ssp-oscal-alignment` — 最大風險在 Phase 1 jedi-oscal 套件異動（要新增 3 entity / 3 service / 3 repo / 4 ORM model）
4. **未 push**：CLAUDE.md「push 永遠要 user 明確指示」— Claude 整段在 local commit；user 自行決定何時 push

---

## 1. 本 session 已完成的 16 個 commits

```
=== ssp-oscal-alignment 規劃 ===
daf2475  docs(ssp-oscal-alignment): design.md — 5 phases foundation→export 完整規劃

=== Excel template 擴張（leveraged + parties）===
d388476  feat(ssp-excel-template): SHEET_ORGS/PERSONS 加 OSCAL Party 完整欄位 + bump v2.6.0
c280982  chore(ssp-excel-template): regenerate reference 樣板 to v2.5.0
ebfcce3  chore(ssp-excel-template): bump TEMPLATE_VERSION v2.4.0 → v2.5.0
078f227  feat(ssp-excel-template): SHEET_LEVERAGED 加 7 個 CMMC 結構化欄位 + docx adapter 對齊

=== Stage 1 (docx-import-parity) ===
57019d3  docs(docx-import-parity): stage1 changelog + overnight handoff SUMMARY (S10)
6d758e7  tweak(docx-import-parity): 加 dev BE 啟動 wrapper script (S8)
530c328  feat(docx-import-parity): app service 上傳後自動 accept track changes (S7+)
4a04e83  test(docx-import-parity): smoke test script for end-to-end parse (S7)
e2bab11  feat(docx-import-parity): app service 補 logger.error + 傳 doc 給 adapter (S6)
2b4fb1a  feat(docx-import-parity): adapter 接 extractor 補欄位 (S5)
3c87b03  test(docx-import-parity): 加 customer fixture integration test (S4)
4ccfff4  tweak(docx-import-parity): scrub 客戶檔產 test fixture (S3)
8262b9e  test(docx-import-parity): 加 extractor unit tests 用 reference docx (S2)
3f2d51d  feat(docx-import-parity): 加 docx section anchor extractors (S1)
f605920  docs(docx-import-parity): stage1 design + plan + gitignore 客戶檔
```

FE repo (`compliance-manager-fe`) 對應 commits（路徑 `~/Projects/Billows/Audit-Manager/compliance-manager-fe/`）：
```
e873fae  feat(ssp-docx-import): LeveragedSection 對齊 Excel 13 欄 schema + row expander
38c9e25  feat(ssp-docx-import): mount MetadataSection + LeveragedSection 到 preview tabs
```

## 2. 第一步該讀的文件（按順序）

| # | 文件 | 用途 |
|---|---|---|
| 1 | `docs/features/FR-028-2605-ssp-oscal-alignment/design.md` | **主要設計**。5 phases + DB schema + dataclass + OSCAL JSON 範例。766 行，重點 §1 背景 / §3 階段切割 / §4 schema migration |
| 2 | `docs/features/FR-027-2605-docx-import-parity/handoff/2026-05-24-stage1-overnight-SUMMARY.md` | Stage 1 收尾 — 已完成的部分、明早 user 驗證指引、Stage 2 預告（被 ssp-oscal-alignment 取代） |
| 3 | `docs/features/FR-027-2605-docx-import-parity/design.md` | Stage 1 設計細節 — 怎麼解客戶 docx、anchor extractor 邏輯、track changes 處理 |
| 4 | `.claude/skills/oscal-knowledge/references/implementation-layer.md` | OSCAL Implementation Layer 領域知識 — SSP 結構、component / inventory-item / leveraged-authorization 對應 |
| 5 | `~/Projects/Jedicogy/module/jedi-python-package/jedi-oscal/jedi_oscal/domain/entity/base/oscal_party_entity.py` | 參考：jedi-oscal 現有 Party entity 形狀（Phase 1 要照此 pattern 加 Component / LeveragedAuthorization / InventoryItem 三類） |
| 6 | `~/Projects/Jedicogy/module/jedi-python-package/jedi-oscal/jedi_oscal/infra/model/base/oscal_party.py` | 參考：對應的 SQLAlchemy ORM model（含 RLS / Mapped / index pattern） |

## 3. 重要決策（不在 code 內、不可丟）

### 3.1 OSCAL 對應勘誤（驗證過 OSCAL official metaschema）

之前的對應有錯，**已修正在 design.md §1**：

| 項目 | 之前錯的 | 正確 |
|---|---|---|
| Component type 列表 | 含 `api` / `cli` / `this-system` 為 first-class | OSCAL 14 個 enum 不含 api/cli；api/cli 走 `<prop ns="cmmc:ssp" name="category">` |
| 2.6.1 vs 2.6.2 關係 | 看作「兩群不同東西」 | **同一筆服務可能同時出現**：FedRAMP-authorized 服務 = `<component>` + `<leveraged-authorization>` 雙寫，靠 `prop[name="leveraged-authorization-uuid"]` 互連 |
| 設備 vs 資訊系統 | 都歸 component | 設備=`<inventory-item>`（instance），資訊系統=`<component>`（type），兩者透過 `<implemented-component component-uuid=...>` 連 |

**官方驗證來源**：
- OSCAL repo `src/metaschema/oscal_implementation-common_metaschema.xml`
- shared-constraints `allowed-values-component-type.ent`：14 個 type enum + `allow-other="yes"`

### 3.2 客戶 docx 重要發現（亞航 SSP）

- 客戶檔（`docs/reference/亞航-CMMC-SSP-20260520-1會議討論版.docx`）**有 Word track changes 未 accept**，造成 BE python-docx 解出 0 parties
- BE 已加 `_normalize_docx_revisions()` 在 parse 前自動 accept 所有 revisions（in-memory only，原檔 bytes 保留在 MinIO 不變）
- **客戶檔在 .gitignore**，scrubbed 版本在 `tests/data/oscal/customer_sample_scrubbed.docx`
- Customer real data 浮出後 scrub 規則加了 30+ rules（屏東飛機維修廠 / Sierra Nevada / 真實姓名電話地址 / Crowdstrike / Fortinet 等）— **下次拿到別份客戶 docx 要重跑 scrub script 並補 SCRUB_RULES**

### 3.3 FedRAMP Package ID 是什麼

- FedRAMP = Federal Risk and Authorization Management Program（美國政府雲服務資安授權標準）
- 每個取得授權的 CSO 在 https://marketplace.fedramp.gov/ 有唯一識別碼（如 `FR18078583629`）
- 客戶 Crowdstrike 那筆是 FedRAMP authorized → 在 OSCAL 同時是 `<component>` 跟 `<leveraged-authorization>` 兩個元素
- 在我們系統內：**不是 first-class column on component table**，而是 `ssp_leveraged_authorizations.props.fedramp_package_id`（design.md §1.2）

### 3.4 Excel template version 軌跡

```
v2.3.x — 既有
v2.4.0 — 之前: leveraged 加 date_authorized + description
v2.5.0 — 本日: leveraged 加 7 個 CMMC props (nature_of_agreement / impact_level /
              data_types / authorized_users / protocol / security_auth / fedramp_package_id)
v2.6.0 — 本日: parties 加 OSCAL Party 完整欄位 (org: address/telephone;
              person: title/telephone/address)
v3.0.0 — 未來 ssp-oscal-alignment Phase 3：major bump
              拆 06_外部利用服務 → 06a/06b
              05_資訊系統 合併進 06a
              04_設備 → 04_資產清冊
              breaking change，v2.x 樣板強制不支援
```

### 3.5 jedi-oscal 套件異動策略

Phase 1 是這 feature 最大風險點：
- 套件側要新增 3 entity (Component / LeveragedAuthorization / InventoryItem) + 3 service + 3 repo + 4 ORM model (含 M2M join)
- **照 CLAUDE.md 規範**：
  - 開發期間用 **poetry path dependency**（pyproject.toml path =本地），不每改必 bump version
  - 主專案 pyproject.toml path 改動 **不該 commit**（dev-only）
  - feature 完成、smoke 通過後 **才一次性 bump + 推 Nexus**
  - `poetry update`（不用 `poetry lock`，會卡）

### 3.6 confirm path 雙路徑相容策略

design.md §2.4 詳述：
- `parse_jobs.parsed_result` JSONB 加頂層 `schema_version` key
- 舊路徑（v1-ssp）跑既有 `_legacy_confirm()`，新路徑（v2-bundle）跑新 orchestrator
- in-flight 舊 parse_job 走舊路徑、新 parse 寫新 schema
- 不強制 user 重 parse、不刪資料

## 4. 已知陷阱 / 注意事項

### 4.1 測試 logger patch（CLAUDE.md feedback 已記）

寫 app service test 必加 `@pytest.fixture(autouse=True)` patch logger 為 MagicMock，否則 jedi DBLogHandler 對 SessionLocal=None 路徑炸 `'NoneType' object is not callable`。

```python
@pytest.fixture(autouse=True)
def patch_logger():
    with patch("app.<module>.service.<svc>.logger", MagicMock()):
        yield
```

Pattern: `tests/test_ssp_docx_import_app_service.py` 已有範例。

### 4.2 既有 pre-existing test failures（不是本 session 造成的）

跑 regression 時這兩個會紅，**不要花時間 debug**：

```
tests/test_ssp_docx_import_create_no_diff.py::TestCreateModeRegression::test_create_mode_get_parse_result_all_controls_added
tests/test_ssp_excel_import_app_service.py::TestConfirmGuards::test_400_when_blocking_validation_error_present
```

兩個都已驗證在 S0 commit (f605920) 之前就 fail，跟本期改動無關。

### 4.3 docs/reference/亞航*.docx 已 gitignore

- 客戶實際檔含敏感資訊（屏東 / Sierra Nevada / 真實人名電話等）
- `.gitignore` 已加 `docs/reference/亞航*.docx + *.xlsx`
- 檔案本身仍在 disk（user 本機 only），但 git 不追蹤
- 下次拿到別份客戶 docx 要重跑 `scripts/scrub_customer_docx.py` 產 test fixture

### 4.4 BE 啟動 `.env` 含 JSON 值 shell 解析錯

`.env` 內 `DB_SECRET={"key": "value"}` 形式 shell `source` 會炸 brace expansion。對策：
- Claude 用 `scripts/start_be_overnight.sh`（用 python-dotenv load）
- User 自己起 BE 走慣用流程（沒問題）

### 4.5 Customer file 解出 `name` 在 preview 顯示成 null

DB 內 `parsed_result.parties[].name` 完整，但經 `diff_service.annotate_parse_result()` 後 preview API response 把 name 蓋成 null。這是**既有 diff service 行為**，跟 docx import 本身無關。

**對應的 issue**：應該由 Stage 4 (FE 重設計) 一併修，或單獨開 bug ticket。design.md §5 風險表沒涵蓋這個（補一條）。

### 4.6 schema_version 命名衝突

`parse_jobs` 表已有 `version` column（但不是 schema 版本概念）。新加 `parsed_result.schema_version` 在 JSONB 內，**不要**改 column 名避免 migration 風險。

## 5. 待解問題 / 決策點（給下個 session）

| # | 問題 | 影響 |
|---|---|---|
| Q1 | Stage 1 commits 要不要 push？ | 影響其他人 review / staging deploy 時機。建議 ssp-oscal-alignment Phase 1 開始前先 push（給 staging 觀察 Stage 1 行為）|
| Q2 | Phase 3 docx 樣板，Table 2 (2.6.2) 是否移除？ | 跟新增的 System Components 表重複度高。**建議**：保留 Table 2 作 fallback、Phase 4 觀察後決定 |
| Q3 | Phase 1 jedi-oscal 套件 PR 要對 main 還是 feature/ssp-oscal-alignment branch？ | 套件側目前主 branch 是？需確認 |
| Q4 | Component type enum 是否要包 `'other'`？ | OSCAL 規範 `allow-other="yes"`，第一公民值不含 `other`。但實務常見「無法分類」狀況 — 建議**Excel sheet 接受 `other` 但 export 時走 prop 標 namespace**，不是 OSCAL `type='other'` |
| Q5 | 既有 `SspSystemImplementationItemEntity` 何時 drop？ | design.md §4.1 寫「6 個月後評估」— 但要訂明確 cutoff 條件（譬如「所有 SSP 已 migrate 且 0 row 在 ssp_system_implementation_items」） |

## 6. Phase 1 開工前的 checklist

按順序執行，第一個 Yes 不通過就停下問 user：

- [ ] **branch 確認** — 仍在 `feature/real_doc_import`？或要新開 `feature/ssp-oscal-alignment` branch？（建議新開、Phase 1 完成 merge 回主線）
- [ ] **Stage 1 commits push 與否決定** — 見 Q1
- [ ] **jedi-oscal 套件本機路徑確認** — `~/Projects/Jedicogy/module/jedi-python-package/jedi-oscal/` 是否乾淨 working tree
- [ ] **跟 user 確認套件 PR 對哪個 branch** — 見 Q3
- [ ] **brainstorming SOP 跑一遍** — design.md 已寫但仍要走 brainstorm 確認沒漏 edge case（特別是 inventory_implemented_components M2M write order）
- [ ] **writing-plans SOP 產 implementation-plan-phase1.md** — 切細 step 並標 commit point
- [ ] **path dependency 設定** — 主專案 `pyproject.toml` 把 jedi-oscal 改 path =本地，**不 commit**

## 7. 不要做的事（避雷）

- ❌ **不要直接 push Stage 1 改動到 main** — feature branch 上 working
- ❌ **不要在 Phase 1 前先動 Excel/Docx 樣板** — 樣板加表 (Phase 3) 依賴 dataclass shape (Phase 1)，反過來會二次工
- ❌ **不要省略 schema_version 雙路徑** — 既有 in-flight parse_job 直接走新 path 會炸（adapter 形狀不對）
- ❌ **不要在套件 PR 帶主專案 path dependency 改動** — 那是 dev-only，會污染套件 commit history
- ❌ **不要把 Component type 直接寫 `'api'` / `'cli'`** — OSCAL enum 沒這兩個，會被 schema validator 拒。要 fallback 到 `'service'` + framework prop

## 8. 對話歸檔建議

本 session 跨多個關鍵設計決策（leveraged 雙寫 / docx import 補欄位 / Excel template 擴張 / OSCAL 對齊規劃），**強烈建議歸檔**到 `docs/conversation-history/2026-05-24/ssp-oscal-alignment-planning/`。

歸檔流程（per CLAUDE.md）：
```bash
poetry run python scripts/extract_claude_sessions.py \
    --date 2026-05-24 \
    --topic ssp-oscal-alignment-planning \
    --auto
```

如果 JSONL 跨多個 phase（譬如「docx import 補欄位」跟「ssp-oscal-alignment 規劃」是兩個 task arc），可以分兩個 sub-topic：
```bash
docs/conversation-history/2026-05-24/
├── docx-import-parity-fields-supplement/  # Excel leveraged + parties 擴欄
└── ssp-oscal-alignment-planning/           # OSCAL 對齊規劃
```

## 9. 環境狀態（接手前確認）

| 項目 | 狀態 |
|---|---|
| Branch | `feature/real_doc_import` |
| Working tree | clean |
| BE | PID 43568, listening :8000（user 自己起的） |
| Stage 1 verified parse_uid | `b338939b-13d0-4145-bf8c-ce074a25a432`（DB 內有完整 5 parties + 4 leveraged + 15 controls） |
| Test fixture | `tests/data/oscal/customer_sample_scrubbed.docx`（207KB, scrubbed） |
| 客戶原檔 | `docs/reference/亞航-CMMC-SSP-20260520-1會議討論版.docx`（local-only, gitignored） |

## 10. 給接手 Claude 的話

1. **不要重做今天已決定的**：design.md 的 OSCAL 對應已經跟官方 metaschema cross-check 過，不要再去 web fetch 一次浪費 token
2. **brainstorm SOP 要跑** — design.md 是 single approach，brainstorm 確認沒第二條更好路徑
3. **plan SOP 要跑** — design.md 是 design layer，plan layer 切細到「每個 commit 對應什麼 step」
4. **Phase 1 不會一個 session 跑完**，預估 5d work，分多 session ship
5. **跟 user 確認 risk tolerance**：套件異動方向若 user 不同意，要 fallback 「主專案內定義」（不動套件）— 這條退路設計上可行但長期維護差
6. **不要 push、不要切 branch** — CLAUDE.md 規範

---

## 附：本 session 路徑速查

| 用途 | 路徑 |
|---|---|
| 主設計 | `docs/features/FR-028-2605-ssp-oscal-alignment/design.md` |
| Stage 1 handoff | `docs/features/FR-027-2605-docx-import-parity/handoff/2026-05-24-stage1-overnight-SUMMARY.md` |
| Stage 1 設計 | `docs/features/FR-027-2605-docx-import-parity/design.md` |
| 客戶 docx scrubbed fixture | `tests/data/oscal/customer_sample_scrubbed.docx` |
| 標準 CMMC SSP 樣板 (reference) | `docs/features/FR-011.2-2605-ssp-import-export-phase2/reference/ASIA-CMMC-SSP-DRAFT-with-user-info-202604.docx` |
| Excel template generator | `app/module_frame/excel_template/{generator.py, sheet_definitions.py, header_i18n.py}` |
| Docx parser | `domain/oscal/parser/{docx_parser_core.py, docx_section_extractors.py, ssp_intermediate.py}` |
| Docx adapter | `domain/oscal/adapter/cmmc_ssp_adapter.py` |
| jedi-oscal Party entity 參考 | `~/Projects/Jedicogy/module/jedi-python-package/jedi-oscal/jedi_oscal/domain/entity/base/oscal_party_entity.py` |
| jedi-oscal Party ORM 參考 | `~/Projects/Jedicogy/module/jedi-python-package/jedi-oscal/jedi_oscal/infra/model/base/oscal_party.py` |
| OSCAL official metaschema | https://github.com/usnistgov/OSCAL/blob/main/src/metaschema/oscal_implementation-common_metaschema.xml |
| Component type enum | https://github.com/usnistgov/OSCAL/blob/main/src/metaschema/shared-constraints/allowed-values-component-type.ent |
| 套件異動規範 | CLAUDE.md「External jedi-* Packages 異動規範」段 |
| changelog SOP | CLAUDE.md「Changelog 分類規範」段 |
| issue SOP | CLAUDE.md「Issue 工作流程」段 |
