| 項目 | 內容 |
|---|---|
| 緣由 | User 手測亞航 docx 匯入後實際觀察 4 個 FE 缺漏:① label「責任單位」/「單位」/「人員」/「責任人員」雜亂未統一、② 預覽 + template-edit 兩畫面 org party 缺地址 / 電話、③ 同上 person party 缺地址 / 電話。BE 端已有完整資料(parsed_result.parties JSONB 含 address / telephone_number / title),純 FE label 對齊 + 欄位 render 補齊。 |
| Branch | feature/ssp-oscal-alignment(兩 repo 一致;BE local 領先 origin 4 commits + FE 1 commit 待 push) |
| 主要 file | FE 兩 vue(PartiesSection.vue + ModuleFramePartiesPanel.vue)+ 2 個 i18n locale(zh-tw + en) |
| 接手前必讀 | 本文件自包含 — 按 §0 順序讀本檔 + reference 文件即可 |
| 預估時間 | 1.5-2 小時(FE 改 2 元件 + 4 個 i18n key 更新 + 跨 repo Read FE CLAUDE.md + Playwright 驗證 + 文件) |
docs/features/FR-028-2605-ssp-oscal-alignment/handoff/2026-05-25-bug-d-FIXED-SUMMARY.md — Bug D + E + F 完整 fix(前一輪歷史;本 Bug H 是 user 手測過程發現的後續 FE 缺漏,跟 Bug D 同個 user-facing 區塊 (party tab))~/Projects/Billows/Audit-Manager/compliance-manager-fe/CLAUDE.md — 跨 repo 改 FE 必讀(per memory feedback_cross_repo_read_claude_md_first)docs/features/FR-028-2605-ssp-oscal-alignment/ssp-import-flow-reference.html §3.2 (確認階段) + §6.4 (cross-source 不一致教訓) — 整體 import flow + party fields 在 BE 寫入位置compliance-manager-fe/src/components/grc/ssp-docx-import-v2/sections/PartiesSection.vue — 預覽 (/module-frame/import-docx) 元件,行 100~270compliance-manager-fe/src/components/grc/ModuleFramePartiesPanel.vue — 編輯 (/module-frame/<uid>/template-edit) 元件,DataTable + Dialog 全段compliance-manager-fe/src/views/module_frame/ModuleFrameTemplateEditView.vue 行 1985~2011 — template-edit 兩 party tab 注入點compliance-manager-fe/src/config/locales/i18n/{zh-tw,en}/{ssp-docx-import.json,module-frame.json} — i18n label 字典讀完後跑 §6 Pre-flight + §7 Verify Bug D close → §3 Verify 各 bug 對應檔案行號 → §4 開工順位。
| 畫面 | 目前 label | i18n key | 來源 file:line |
|---|---|---|---|
| Word 文件內欄位(user 提到) | 責任單位 | (純 docx 內文) | (對應 BE party_type='organization') |
| Preview Section title | 單位 | lang.ssp_docx_import.parties_organization_section_title |
ssp-docx-import.json:165 |
| Preview Role label | 責任單位 | (硬寫在 vue 內 ROLE_LABEL map) |
PartiesSection.vue:36 |
| Template-edit Tab header | 責任單位 ({count}) | lang.module_frame.tab_responsible_org |
module-frame.json:5 |
| Template-edit DataTable Column header | 單位名稱 | (硬寫) | ModuleFramePartiesPanel.vue:356 |
期望:上述 5 處 user-facing label 全部改成「負責單位」(DataTable 該欄改「負責單位名稱」)。
現況 — 預覽 (/module-frame/import-docx,元件 PartiesSection.vue org card line 154-163):
<div class="grid">
<div class="col-12 md:col-6 mb-2">
<label>{{ t('lang.ssp_docx_import.field_name') }}</label>
<InputText :model-value="p.name || ''" .../>
</div>
<div class="col-12 md:col-6 mb-2">
<label>{{ t('lang.ssp_docx_import.field_email') }}</label>
<InputText :model-value="p.email_address || ''" .../>
</div>
</div>
→ 只有 name + email,缺 address / telephone_number。
現況 — Template-edit (/module-frame/<uid>/template-edit,元件 ModuleFramePartiesPanel.vue):
BE 證據(parse_job 148 確認 BE 已有完整資料,user docx 也有抓到):
PGPASSWORD='jedi@123!' psql -h 192.168.50.188 -p 25432 -U cmmgr -d guidant_ai_dev -A -t -c "
SET app.is_super_admin='t';
SELECT jsonb_pretty(parsed_result->'parties'->0) FROM oscal.ssp_docx_parse_jobs WHERE id=148;
"
# 預期 output 含完整欄位:
# {"name": "屏東飛機維修廠", "address": "No. 330, Shengli Rd., ...",
# "telephone_number": "08-7656111", "party_type": "organization", ...}期望:兩畫面都加 address + telephone_number 欄位 render(InputText with placeholder + label)。
| 畫面 | 目前 label | i18n key | 來源 file:line |
|---|---|---|---|
| Word 文件內欄位 | 參與人員 | (純 docx 內文) | (對應 BE party_type='person') |
| Preview Section title | 人員 | lang.ssp_docx_import.parties_person_section_title |
ssp-docx-import.json:167 |
| Template-edit Tab header | 責任人員 ({count}) | lang.module_frame.tab_responsible_person |
module-frame.json:6 |
| Template-edit DataTable Column header | 姓名 | (硬寫) | ModuleFramePartiesPanel.vue:356 |
期望:Section title + Tab header 改成「參與人員」(DataTable column「姓名」可保留,是 person 內部欄位本來就叫姓名不是 person 整體 label)。
現況 — 預覽 (PartiesSection.vue person card line 210-222):
<div class="grid">
<div class="col-12 md:col-6 mb-2"> <!-- 已有 -->
<label>{{ t('lang.ssp_docx_import.field_name') }}</label>
<InputText :model-value="p.name || ''" .../>
</div>
<div class="col-12 md:col-6 mb-2"> <!-- 已有 -->
<label>{{ t('lang.ssp_docx_import.field_title') }}</label>
<InputText :model-value="p.title || ''" .../>
</div>
<div class="col-12 md:col-6 mb-2"> <!-- 已有 -->
<label>{{ t('lang.ssp_docx_import.field_email') }}</label>
<InputText :model-value="p.email_address || ''" .../>
</div>
</div>
→ 有 name + title + email,缺 address + telephone_number。
現況 — Template-edit:同 Bug H-2 — DataTable + Dialog 都缺。
期望:兩畫面都加 address + telephone_number 欄位 render。
PartyDiffCard.vue(diff stepper,update mode 用)已修過缺電話/職稱/地址欄位(commit FE f31d0cf),但 create mode preview 元件 (PartiesSection.vue) 跟 template-edit 元件 (ModuleFramePartiesPanel.vue) 是不同 vue 檔,當時沒一起改。本 Bug H 補完三個元件的對齊。feedback_cross_repo_read_claude_md_first)— 直接動 vue 沒 read FE CLAUDE.md 容易踩 PrimeVue quirks(如 SelectButton unselectable)。本 Bug H 不是 root cause 候選題,是「FE render + label 沒對齊 BE 已有資料」純 UI bug。Verify 點只有:
# A1: 確認 docx parse_job parsed_result 有完整 party 欄位
PGPASSWORD='jedi@123!' psql -h 192.168.50.188 -p 25432 -U cmmgr -d guidant_ai_dev -A -t -c "
SET app.is_super_admin='t';
SELECT
jsonb_array_elements(parsed_result->'parties') ->> 'name' AS name,
jsonb_array_elements(parsed_result->'parties') ->> 'party_type' AS ptype,
jsonb_array_elements(parsed_result->'parties') ->> 'address' AS address,
jsonb_array_elements(parsed_result->'parties') ->> 'telephone_number' AS tel,
jsonb_array_elements(parsed_result->'parties') ->> 'title' AS title
FROM oscal.ssp_docx_parse_jobs WHERE id=148;
"
# 預期 5 row 都填好 address / tel(org 也有),person 多 title
# A2: 確認 module-frame parties API response 含完整欄位
#(用前一輪 E2E mf 369 確認;BE 須在跑)
curl -s "http://localhost:8000/api/1.0/module-frame/f489a145-47da-4506-8675-5cf45a6f218b/parties" \
-H "Authorization: Bearer <token>" \
| jq '.data[] | {name, party_type, address, telephone_number, title}'
# 預期 row 含 address / telephone_number / title
# 若 API response 缺 → 表 BE entity → dict 轉換漏(需追 _to_dict)若 A2 發現 API response 缺,須追:
grep -nE "def list_parties\|def _to_dict\|address\|telephone" \
/Users/chouraymond/Projects/Billows/Audit-Manager/compliance-manager-be/app/oscal/service/party_context_service.py 2>&1 | head -20
# 對應的 PartyEntity (jedi-oscal)
ls ~/Projects/Jedicogy/module/jedi-python-package/jedi-oscal/jedi_oscal/domain/entity/base/oscal_party*推測:BE list_parties API 應該已含完整欄位(前一輪 Bug B/D fix 時 BE entity 已 OK,preview 路徑用同個 PartyEntity)— 純 FE 沒 render。Verify A1 + A2 通過即直接動 FE。
_to_dict(少數情境,可能 +30 min)<div>)<div>)<Column>;考慮 responsive — 可能要折疊或 truncate)field_telephone key(已有 field_address/field_title,要查 field_telephone 是否已存).playwright-mcp/uploads/asia-airlines-cmmc-ssp.docx 跑完整 docx import flow(CMMC L1 / module_frame create mode)2026-05-25-bug-d-FIXED-SUMMARY.md)| 檔案 | 為何 read / 改 |
|---|---|
compliance-manager-fe/src/components/grc/ssp-docx-import-v2/sections/PartiesSection.vue (line 100-270) |
預覽元件;org card line 154-163 加 2 input + person card line 210-222 加 2 input |
compliance-manager-fe/src/components/grc/ModuleFramePartiesPanel.vue (line 340-450) |
編輯元件;DataTable 加 2 column + Dialog 加 2 input + Column header 改「負責單位名稱」 |
compliance-manager-fe/src/views/module_frame/ModuleFrameTemplateEditView.vue (line 1985-2011) |
template-edit 兩 party tab 注入點 — 不用改(i18n key 改了 tab header 自動跟) |
compliance-manager-fe/src/config/locales/i18n/zh-tw/ssp-docx-import.json |
改 line 165 parties_organization_section_title「單位」→「負責單位」+ line 167 parties_person_section_title「人員」→「參與人員」;確認 field_telephone key 是否存在 |
compliance-manager-fe/src/config/locales/i18n/en/ssp-docx-import.json |
對應 en:Organizations → Responsible Organizations? People → Participating Persons? 等 user 拍板 en label,或先改 zh-tw 不動 en |
compliance-manager-fe/src/config/locales/i18n/zh-tw/module-frame.json |
改 line 5 tab_responsible_org「責任單位 ({count})」→「負責單位 ({count})」+ line 6 tab_responsible_person「責任人員 ({count})」→「參與人員 ({count})」 |
compliance-manager-fe/src/config/locales/i18n/en/module-frame.json |
對應 en(同上等拍板) |
| 檔案 | 為何 read |
|---|---|
app/oscal/service/party_context_service.py (list_parties / _to_dict) |
確認 API response 含 address / telephone_number / title — 若缺則補 |
app/oscal/service/ssp_docx_import_app_service.py:_load_current_parties |
預覽用同個 service 取 current parties,確認 list dict 完整 |
~/Projects/Jedicogy/module/jedi-python-package/jedi-oscal/jedi_oscal/domain/entity/base/oscal_party_entity.py |
套件 PartyEntity 欄位定義(不該動,純 verify) |
~/Projects/Billows/Audit-Manager/compliance-manager-fe/CLAUDE.md(per memory feedback_cross_repo_read_claude_md_first)# 1. 兩 repo branch
git -C ~/Projects/Billows/Audit-Manager/compliance-manager-be branch --show-current
git -C ~/Projects/Billows/Audit-Manager/compliance-manager-fe branch --show-current
# 預期:兩個都 feature/ssp-oscal-alignment
# 2. 兩 repo working tree
git -C ~/Projects/Billows/Audit-Manager/compliance-manager-be status --short
# 預期:M pyproject.toml only + 3 .png 在根目錄(artifact,不 commit)
git -C ~/Projects/Billows/Audit-Manager/compliance-manager-fe status --short
# 預期:clean
# 3. local vs origin(user 還沒 push 上一輪)
git -C ~/Projects/Billows/Audit-Manager/compliance-manager-be log origin/feature/ssp-oscal-alignment..HEAD --oneline
# 預期 4-5 commits(取決於 Bug G handoff swap 後狀態)
git -C ~/Projects/Billows/Audit-Manager/compliance-manager-fe log origin/feature/ssp-oscal-alignment..HEAD --oneline
# 預期 1 commit(Bug E + F)
# 4. BE listener
lsof -t -i:8000 # 若無 listener,重啟一次
# 重啟方式(避雷:zsh 對 .env 內 { } 會踩 parse error,per 前次教訓用 inline python):
# nohup python -c "
# import os, runpy, sys
# from pathlib import Path
# for line in Path('.env').read_text().splitlines():
# line = line.strip()
# if not line or line.startswith('#') or '=' not in line: continue
# k, _, v = line.partition('=')
# os.environ[k.strip()] = v.strip()
# sys.argv = ['main_app.py', 'run']
# runpy.run_path('main_app.py', run_name='__main__')
# " > /tmp/be_restart.log 2>&1 &
# 5. FE dev server
lsof -t -i:5180 # 預期已在跑(user dev server)
# 6. BE test smoke
poetry run pytest tests/test_ssp_docx_import_app_service.py tests/test_ssp_write_strategy.py \
tests/test_cmmc_ssp_adapter_v3_bundle.py tests/test_ssp_excel_import_app_service.py -q
# 預期:~140 passed# 7.1 — Bug D DB 驗證:mf 369 (docx E2E) + mf 370 (Excel E2E) 都應有 4 LA
PGPASSWORD='jedi@123!' psql -h 192.168.50.188 -p 25432 -U cmmgr -d guidant_ai_dev -c "
SET app.is_super_admin='t';
SELECT mf.uid, mf.name, COUNT(la.id) AS la_count
FROM public.module_frames mf
JOIN oscal.profiles p ON p.uid::text = mf.oscal_profile_uid
JOIN oscal.system_security_plans s ON s.profile_id = p.id
LEFT JOIN oscal.ssp_leveraged_authorizations la ON la.ssp_id = s.id
WHERE mf.uid IN ('f489a145-47da-4506-8675-5cf45a6f218b', 'bf6aed86-3b12-4df4-8c62-cc3bacae983f')
GROUP BY mf.uid, mf.name;
"
# 預期 2 row 都 la_count=4
# 7.2 — Bug B link verify(mf 368 應 5 link)
PGPASSWORD='jedi@123!' psql -h 192.168.50.188 -p 25432 -U cmmgr -d guidant_ai_dev -c "
SET app.is_super_admin='t';
SELECT count(*) FROM oscal.oscal_responsible_parties
WHERE context_type='module_frame' AND context_id=368;
"
# 預期 5feedback_no_branch_switch)feedback_stage_commit_no_ask)feedback_cross_repo_read_claude_md_first)— 本 Bug H 主要動 FE,必做feedback_be_restart_after_service_change)— 若 §3.2 觸發改 BE party_context_service 才需重啟;純 FE 不用feedback_no_chinglish — 動詞 / 連接詞用中文)feedback_plan_vs_reality_verify_first)— 本 handoff §3 候選都已附 verify 命令feedback_subagent_explicit_git_add)docs/features/FR-028-2605-ssp-oscal-alignment/ssp-import-flow-reference.html — 如有相關內容更新handoff/2026-05-25-bug-h-FIXED-SUMMARY.md 寫短收尾報告(mirror 2026-05-25-bug-d-FIXED-SUMMARY.md 樣式)<PartyFieldRow> 元件抽出 refactor(3 元件 render 同樣 5 欄位很適合抽,但 scope 太大,列 future cleanup)origin/feature/ssp-oscal-alignment 已包含(user 之前 push 過):
BE 已 push (4441d3f4 ~):
4441d3f4 docs(ssp-oscal-alignment): Bug B 收尾 SUMMARY + Bug D handoff
fef5eecf fix(ssp-oscal-alignment): Bug B 第二段 — docx _dict_to_parsed_parties 補 default role
ba7885d4 docs(ssp-oscal-alignment): design §11.22 + §11.23 — Bug B + Issue 1 reconciliation
...
FE 已 push (f31d0cf):
f31d0cf fix(ssp-oscal-alignment): Bug B parties default decision + Issue 1 缺欄位 render
本期(2026-05-25 晚)BE local 領先(含本 handoff swap):
[本 commit] docs(ssp-oscal-alignment): swap Bug G handoff → Bug H (Word parties labels + fields)
38336bae docs(ssp-oscal-alignment): Bug G handoff + HTML 參考 + CLAUDE.md 加交接模式 + design §11 索引更新
1406047b chore(ssp-oscal-alignment): 加 E2E Excel fixture generator script
a2989c6e docs(ssp-oscal-alignment): Bug D FIXED SUMMARY 補 §6.1 Bug E + F cascade fixes
20496b65 fix(ssp-oscal-alignment): Bug D — docx adapter T7 (Category) 也 emit LeveragedAuthorization
190254ba docs(ssp-oscal-alignment): Bug D handoff 補完整 context (上一輪已 push 但 origin 未到)
本期 FE local 領先 1 commit:
c7d5791 fix(ssp-oscal-alignment): Bug E + F — DocumentPoolPanel TDZ + Bug B 引發的 i18n missing keys
狀態:BE 5 + FE 1 待 push(user 接手後拍板)。本期 swap commit 也算進去。
請閱讀交接文件,了解現況,並接手繼續修正 bug。
交接文件路徑:
docs/features/FR-028-2605-ssp-oscal-alignment/handoff/2026-05-25-bug-h-word-parties-labels-fields-handoff.md
按本檔 §0 接手讀序執行 — 必跑 §6 Pre-flight + §7 Verify Bug D close →
§3 Verify BE 資料完整 → §4 開工順位。注意 §2 前次教訓 + §8 行為規範。
前次 (Bug B / D / E / F) 已全 close;Bug G (init_ap_controls silent failure)
已撤回 (是靜態分析非實證 bug,user 拍板才修)。本期純 FE label 對齊 + 欄位
render 補齊,BE 端資料已完整不需動。