Bug H ~ L 整段 arc 收尾 SUMMARY(2026-05-25 整日)

項目 內容
Branch feature/ssp-oscal-alignment(跨 BE + FE + jedi-common + jedi-oscal 4 repos)
起源 早上 §11.25 Bug D fix ship 後 user 連續手測,一路追出 7 個連環 bug
涵蓋 Bug H (FE 4 子)、Bug H-5 (BE email parse)、Bug H-6 (jedi-common 假鉤稽)、Bug I (revert §11.25 + 廢棄 dual TabPanel)、Bug J (template SSP uid null)、Bug K (SSP endpoint 對 template SSP 404)、Bug L (LeveragedSection v3 對齊 + Card→Table + 命名)
狀態 全 ship 到 working tree,未 commit,等 user 多輪測試後 batch commit + push
design.md §11.26 ~ §11.32 七段完整 root cause / fix / 教訓已補;§11 index reference 已更新
對話歷史 尚未歸檔(per CLAUDE.md「做 summary」流程,等整 case 真正收尾再從 JSONL extract)

1. Seven bugs root cause 一覽

Bug 層級 Root cause 一行 Fix scope
H (4 子) FE 純 UI preview / template-edit / diff stepper 三元件 render 同 party 欄位但獨立維護,Bug B Issue 1 只修 diff stepper 留缺 FE 4 檔(i18n + 2 vue)
H-5 BE parser _PARTY_LABEL_MAP substring 順序 bug:'address' 排在 'emailaddress' 之前 → email row mis-classify 成 address → silently dropped;9 個歷史 parse_job 全踩 BE 2 檔(parser + regression test)
H-6 jedi-common shared infra SQLAlchemy before_flush hook 自動填 org_unit_id 是 RLS 設計用,但 OSCAL 4 表把 org_unit_id 當「鉤稽到的部門」業務欄位 → 雙語意衝突 → 467 row 假鉤稽 jedi-common 1 + jedi-oscal 4 + BE pyproject + DB cleanup
I BE adapter + FE Bug D §11.25 short-term fix 把 T7 emit LA 違反 §1 設計;Phase 4 過渡 dual TabPanel 沒收尾 BE adapter revert + FE 廢棄 3 TabPanel + preview 拆兩 section + DB cleanup
J BE app service try/except: pass 默吞 AttributeError(get_by_id) 應為 get_ssp_by_idssp_uid 永遠 null → FE 「元件清冊」tab 永遠走 hint BE 1 line fix
K BE permission SspProjectResolver 假設所有 SSP 屬 project,template SSP 沒 AP 一律 404 SspContextResolver + permission 雙模式 + 3 SSP endpoint 改用新 method
L FE preview ↔︎ BE 寫入 FE LeveragedSection 讀 v2 leveraged_services + emit 到 draft.leveraged_services,但 confirm payload 沒帶 + BE _apply_v2_bundle_overrides 只認 v3 keys → user edits 完全 silently dropped;連帶 LA template-edit 視覺不對稱 + sub-panel 命名升級 FE 3 檔(LeveragedSection 改 v3 + SspDocxImportPage 改 viewModel/payload + SspComponentsLeveragedInventoryTab Card→Table)+ 2 i18n + FE CLAUDE.md 新規範

2. 改動清單(working tree,未 commit)

compliance-manager-fe

  • src/views/module_frame/ModuleFrameTemplateEditView.vue — 廢棄 3 過渡 TabPanel + 新 tab header i18n key 引用 (Bug I + L)
  • src/components/grc/ssp-docx-import-v2/sections/PartiesSection.vue — 加電話/地址欄位 + ROLE_LABEL 改「負責單位」(Bug H)
  • src/components/grc/ssp-docx-import-v2/sections/LeveragedSection.vue完全重寫:v3 keys + 兩 section + 對齊 sub-panel 命名 (Bug I + L)
  • src/components/grc/ssp-docx-import-v2/SspDocxImportPage.vue — viewModel 加 v3 keys + confirm payload 用 _buildIdxOverrides 把 draft diff 轉 BE 期望 idx-keyed map (Bug L)
  • src/components/grc/ModuleFramePartiesPanel.vue — DataTable +2 column / Dialog +2 input / Column header 改「負責單位名稱」(Bug H)
  • src/components/grc/ssp/SspComponentsLeveragedInventoryTab.vue — 利用授權 Card→DataTable + 3 add buttons outlined (Bug L)
  • src/config/locales/i18n/zh-tw/ssp-docx-import.json — section title 2 key 改「負責單位」/「參與人員」(Bug H)
  • src/config/locales/i18n/zh-tw/module-frame.json — tab_responsible_org/person 2 key 改「負責單位」/「參與人員」(Bug H)
  • src/config/locales/i18n/{zh-tw,en}/ssp-components-leveraged-inventory.json — 新 tab_header key + rename section_components/section_leveraged + 對應 add/edit/empty labels (Bug K + L)
  • CLAUDE.md — 新增「Add / Create Action Button Style」section (user 規範: 新增類按鈕用 outlined)

compliance-manager-be

  • domain/oscal/parser/docx_section_extractors.py_PARTY_LABEL_MAP 重排 email 在 address 之前 (Bug H-5)
  • domain/oscal/adapter/cmmc_ssp_adapter.py — Table #7 不再 emit LA (Bug I Phase A)
  • domain/oscal/service/ssp_context_resolver.py 新檔 — 雙模式 SSP context resolver (Bug K Phase A)
  • common/middleware/permission/ssp_permission.py — 新 require_read_access / require_write_access (Bug K Phase B)
  • app/oscal/service/ssp_components_app_service.py / ssp_inventory_items_app_service.py / ssp_leveraged_app_service.py — 改用新 permission method (Bug K Phase C)
  • app/oscal/service/module_frame_template_ssp_app_service.pyget_by_idget_ssp_by_id (Bug J)
  • di_containers/oscal/oscal_containers.py — wire SspContextResolver (Bug K)
  • pyproject.toml — jedi-common 切 path dep (Bug H-6 dev-only,不該 commit)
  • tests/test_docx_section_extractors.py — 收緊 email test + 加 substring collision regression (Bug H-5)
  • tests/test_cmmc_ssp_adapter_v3_bundle.py — 改 T6+T7 expected (Bug I)
  • tests/test_ssp_leveraged_app_service.py — sed rename mock method (Bug K side effect)
  • docs/features/FR-028-2605-ssp-oscal-alignment/design.md — §11.26~32 七段完整 entries + §11 index reference (本 doc)
  • scripts/sql/2026-05-25-bug-i-revert-t7-la.sql 新檔 — DB cleanup mf 372 + 373 (Bug I Phase D)

jedi-common (path dep, 未 commit)

  • jedi_common/session/database/db_mw.pyset_tenant_info_before_insert__skip_auto_org_unit__ opt-out check (Bug H-6)

jedi-oscal (path dep, 未 commit)

  • jedi_oscal/infra/model/base/oscal_party.py__skip_auto_org_unit__ = True (Bug H-6)
  • jedi_oscal/infra/model/base/oscal_leveraged_authorization.py — 同上
  • jedi_oscal/infra/model/base/oscal_component.py — 同上
  • jedi_oscal/infra/model/base/oscal_inventory_item.py — 同上

DB cleanup(已執行)

  • mf 372 + 373 T7 LA 各刪 3 row (Bug I Phase D)
  • 4 OSCAL 表 org_unit_id 全清成 NULL (467 row 累計:37 party + 36 LA + 391 component + 3 inventory) (Bug H-6)

3. Verify Evidence

BE pytest

  • Bug H/H-5 後:168 passed (含新 regression)
  • Bug L 後:683 passed / 16 fail
    • 5 fail 是 test_ssp_leveraged_app_service 我引起 → 已 sed-rename 修,新 verify 5 passed
    • 11 fail 拆解:4 pre-existing (ssp_resources 2 + ssp_system_characteristic 2) + 6 cloud_integration env-dependent + 1 雜
    • K1 引起的 leveraged_app_service 5 fail 已修,其他 surface 給 user 不阻擋 ship

E2E (Playwright + DB)

  • mf 372 (2c4ba0b8-...) template-edit「系統元件、外部授權與資產」tab — 3 sub-panel 全 render、0 console errors、0 SSP endpoint 404
  • 元件清冊 sub-panel 4 components (T6 MDR paired + 3 T7) — 「利用授權」column 正確顯示 T6 ref / T7 空
  • 外部正式授權服務 sub-panel 1 LA (T6 MDR) DataTable + FedRAMP fields
  • 資產清冊 0 (mf docx 沒 inventory)
  • 鉤稽欄全「未鉤稽」(Bug H-6 cleanup verified)
  • Tab 廢棄成 7 個(vs 過渡 10 個)

截圖

  • bug-h-template-edit-org-tab.png / bug-h-org-edit-dialog.png / bug-h-person-edit-dialog.png (Bug H)
  • bug-h-import-preview-parties-tab.png / bug-h5-preview-email-filled.png (Bug H + H-5)
  • bug-h6-cleanup-org-tab-no-link.png / bug-h6-cleanup-person-tab-no-link.png (Bug H-6)
  • bug-k1-verify-3-subpanel-working.png (Bug K1)

4. 不在 scope / 殘留

項目 處理
en locale 多處未對齊(Bug H section_title / tab header / add button labels 等) 等 user 拍板英文後 batch 補
oscal-role.json responsible-organization.label「專案負責單位」是否改「負責單位」 暫不動 — Tag 角色 label vs Tab 分類 label 視覺層級不同
<PartyFieldRow> 共用元件 refactor (三元件 render 同 5 欄位) future cleanup — scope 太大本期不動
jedi-oscal _upsert_responsible_party silent-skip pattern 同 §11.24 Bug B follow-up — jedi-oscal 進版時順手
Bug G init_ap_controls silent failure 已撤回(早晨 swap commit b7f02084)
Phase 5 OSCAL Export Deferred
jedi-common + jedi-oscal Nexus 進版 + BE/FE 版號對齊 user 拍板 — 待 feature 全 verified 才一次 bump 兩套件版本,BE pyproject 改回 pin
Pre-existing pytest fail:test_ssp_resources_app_service 2 + test_ssp_system_characteristic_app_service 2 不關 K1,可未來 cleanup phase 同 K1 pattern 改用新 permission method
template_module_frame_id entity field 沒 wire (Bug K1 改走 reverse query workaround) future fix 可一併補 entity field auto-fill
對話紀錄 export to docs/conversation-history user 全測完 + commit 後再 extract from JSONL

5. 整段 arc 的 7 條核心教訓

  1. 三元件對齊 ≠ 一處改完 (Bug H) — preview / template-edit / diff stepper 三元件 render 同欄位但獨立維護,補 1 處不夠
  2. substring matching 順序敏感性 (Bug H-5) — dict-as-priority-map 短 pattern 排在長 pattern 之前會偷走 match ('address''emailaddress')
  3. shared infra hook 的雙語意陷阱 (Bug H-6) — jedi-common before_flush hook 把 org_unit_id 當 RLS scope 自動填,但 OSCAL 4 表把它當「鉤稽到的部門」業務欄位 → 雙語意衝突,opt-out flag 是正解
  4. short-term tactical fix 留 follow-up 要明確列追蹤 (Bug I) — §11.25 教訓 3 標「長期拆兩 tab,本期非 scope」但沒 follow-up tracking → user 踩到代價才升級
  5. try/except: pass 默吞錯誤是 anti-pattern (Bug J) — silent failure 讓 bug 隱形數週,至少要 log.warning 留 trace
  6. Wrapper / routing 概念不該複製成獨立 domain (Bug K) — MF 只是 SSP 的另一層入口,不該為每個 SSP sub-resource 寫 MF mirror endpoint。Permission resolver 對 context 應 explicit
  7. FE preview ↔︎ BE 寫入 path 必須對齊 (Bug L) — v2 legacy keys 跟 v3 bundle keys 共存時,FE 編輯哪個 source 直接決定能不能寫入。Phase 4 v2→v3 transition 沒清 v2 wire-up 是 latent bug

6. 給 user 的 hand-off summary

已修 + 已驗收(含 mf 372 自動回歸測 + 跨 7 bugs 連環追蹤):

  1. FE 9 檔(含 1 完全重寫 + 1 新 CLAUDE.md section)
  2. BE 7 檔(含 1 新 resolver + 1 新 cleanup SQL + design.md §11.26~32 七段 entries)
  3. jedi-common 1 檔 + jedi-oscal 4 檔(path dep)
  4. DB 4 表清理共 467 row + mf 372/373 T7 LA 6 row
  5. design.md §11.26~32 七段 + §11 index reference

動作項(user 拍板)

  1. 多輪手測(per user 之前指示):
    • mf 372 既有資料、新 docx import 全 chain、project SSP regression
    • 特別驗 Bug L-2:preview 編 status / category 後 confirm,template-edit 確認帶到
  2. 全測通過後 batch commit + push
    • BE: 1 commit 含 design.md / parser / adapter / context resolver / permission / 3 services / template ssp / DI / tests / SQL script
    • FE: 1 commit 含 9 檔
    • jedi-common: 1 commit (1 檔 db_mw)
    • jedi-oscal: 1 commit (4 model)
    • BE pyproject.toml 不 commit(dev-only path dep;等 jedi-common + jedi-oscal 進版才改回 pin 一起 commit)
  3. 後續 release 時:
    • jedi-common + jedi-oscal 一次性 bump version + 推 Nexus
    • BE pyproject.toml 改回 pin 新版本 → poetry update jedi-common jedi-oscal → 跟其他改動一起 commit
    • 走 release SOP (release_notes / BE+FE 版號對齊)
  4. 對話紀錄歸檔(待 user 確認時觸發):
    • python3 scripts/extract_claude_sessions.py --date 2026-05-25 --topic bug-h-to-l-arc --auto

測試新建殘留資料

  • mf 369 ~ 373 為前後測試殘留,可手動刪
  • parse_job 140 ~ 153 同樣

6.5 接手下個 session:Bug O 已 ship spec + handoff doc

Bug O 範圍:docx 重 import diff stepper 缺 4 key (sc / components / leveraged_authorizations / inventory_items) + UI 改 TabView。spec 已寫進 design.md §11.34 (⏸ DEFERRED 標註)、handoff 文件已寫進 docs/features/FR-028-2605-ssp-oscal-alignment/handoff/2026-05-25-bug-o-diff-stepper-expansion-handoff.md — 自包含、下個 session 冷接可動工。

為什麼分新 session

  • Scope 大(跨 BE + FE,~10+ 檔,估 6-10 小時)— 跟 H-N arc 同級
  • H-N batch commit + push 後再開,working tree 乾淨
  • 避免兩 track 並行(H-N 驗測修補 + Bug O 開發)造成 context 混亂

接手 prompt:見 handoff doc §10「給 fresh session 的超短 prompt」段。


7. 為何整段 arc 拖出 7 個連環 bug

Bug H (user 報的 FE label) → 補欄位 render (H-2/H-4) → 露出 email 欄位 (H-5: 從 day 1 就有,借 H-4 浮出) → 露出鉤稽欄位 (H-6: 從 day 1 就有,借 H-4 浮出) → 補完 leveraged section 拆兩 sub (Bug I:違反 §1 原設計被 §11.25 short-term fix 蓋著) → ship Bug I 後 template-edit 永遠 hint (Bug J: silent AttributeError) → Bug J 修完 endpoint 404 (Bug K: project resolver 假設所有 SSP 屬 project) → Bug K 修完發現 preview edits 沒帶到 (Bug L: FE v2 / BE v3 wire 不同 source)

根本啟示借「user 看不到的 bug 借 UI 補新欄位才浮出」這個模式追下去,會連環暴露 latent bug,每個 bug 都 day 1 就有,只是長期沒人查。 整段 arc 是「補一層 UI 後續往下挖」的 7 連發。