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

@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 解析錯

.envDB_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:

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):

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:

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 工作流程」段