日期:2026-05-19 本檔角色:A1 task arc 第三份 summary,承接 SUMMARY-be-partial-ship.md(T4+T5+partial T7 BE),涵蓋 T6 BE+FE+3 輪 UX polish = A1 整體 BE+FE shipped 狀態:A1 BE+FE shipped ✅(T0-T6 完成;T7 cucumber E2E pending follow-up) 剩下:T7 完整 E2E(cucumber + 完整 BE smoke 需 user 端配齊 GitLab env)
承接 BE partial ship (T0-T5),T6 收口本 session 完成 7 個 commits(BE 7 + FE 2,扣除 1 個 tracker doc commit):BE framework-version-scoped 新 endpoint + FE 兩個下載點 + 3 輪 UX polish(hidden cols / VLOOKUP autofill / required body fill / 黃底 border + 範圍限縮 / role enum 對齊 ParticipantRole + cross-domain finding 紀錄)。BE 106 unit test 全綠。A1 整體 shipped,剩 T7 cucumber E2E。
3171116)新 endpoint:
GET /api/1.0/ssp-import-template?framework_version_uid=<uid>&mode=blank&locale=
S1 場景:顧問訪談前下載「framework_version 全 catalog controls 樣板」(superset)。跟既有 MF-scoped endpoint(profile-scoped subset)互補。
範圍:
TemplateDataBundle.mf_uid / mf_name 改 Optionalgenerate_by_framework_version() + 3 helperSspImportTemplateByFrameworkVersionResourceGRC_FRAMEWORK_VERSION_NOT_FOUND + GRC_TEMPLATE_FRAMEWORK_VERSION_REQUIREDe0ff8f1 + 00b6662)| 場景 | UI 入口 | 對應 BE endpoint |
|---|---|---|
| S1 訪談前 | 列表頁右上「新增合規資源庫」menu → 新「下載 SSP 匯入樣板」項 → Dialog 選 framework + version | FW-version-scoped |
| S3 MF 已存在後 | MF template-edit 頁批次維護 menu 加 2 項(空白 / 已填) | MF-scoped |
範圍:
DownloadSspBlankTemplateDialog.vue(兩層 picker,後續 fix-1 改 vertical stack)ModuleFrameTemplateService 加 2 個 methodapi.js 加 2 個 constantModuleFrame.vue createMenuItems 加項ModuleFrameTemplateEditView.vue batchMenuItems 加 2 項66d0d13)A1 status BE partial shipped → BE+FE shipped,commit chain 完整紀錄。
fbcf9f2)— 5 個問題使用者下載樣板實際驗證後反饋:
| # | 問題 | 修補機制 |
|---|---|---|
| 1 | FE Dialog 框架名跑版 | 兩 dropdown 改 vertical stack (00b6662) |
| 2 | UID 欄位 user 看到困惑 | ColumnDef.hidden=True + openpyxl column_dimensions[X].hidden(01 framework_version_uid/profile_uid + 07 statement_id) |
| 3 | 訪談時要手 key email/name | ColumnDef.autofill_from + lookups_helpers + INDEX/MATCH 公式 — 03/04/05 sheet user 選 matched_* 後對應欄位自動帶入 |
| 4 | 07 控制項看不出哪要填 | impl_status + statement 改 required(header 自動黃底) |
| 5 | 08 程序書 doc_no/doc_type/version | 系統 schema 無 → 移除欄位 |
690f25c)— 3 個追加| # | 問題 | 修補 |
|---|---|---|
| 1 | 黃底只 header(user 期待整欄 body 也黃) | _apply_required_body_fill 對 required column body 套黃底 |
| 2 | VLOOKUP 不自動算 | Workbook.calculation.fullCalcOnLoad = True 強制 Excel 開檔重算 |
| 3 | 03 role 應 required + 對齊系統四角色 | enum 改 manager/reviewer/auditor/viewer + required=True |
faade8d + 2b1e93c)— 黃底細節faade8d:黃底蓋掉 Excel gridlines → CELL_THIN_BORDER 加深灰 thin border 到 header + required body2b1e93c:空 sheet 黃底延伸 200 row 視覺糟 → 範圍限縮到 min(1 + len(filled_rows), MAX_DATA_ROW),blank mode 不套 body(只 header)b6b4870)T6 fix2-C 把 SHEET_PERSONS role 改 ParticipantRole 後 audit 既有 docx 匯入流程發現:
oscal_responsible_parties.role_id 跟 GRC project_participants.role (ParticipantRole) 兩條獨立資料流,沒 mappingrole_id=parsed.role or "" 無 validation處理:
design-A1.md §15.3 紀錄完整 finding + A2 parser contractdocs/issues/pending/2026-05-19-person-role-cross-domain-inconsistency.md 含 4 個修補計劃(A2 必做 / docx normalize / DB audit / 雙寫設計)2b1e93c tweak(ssp-import-template): T6 fix4-A 黃底範圍限縮到實際 filled rows
b6b4870 docs(ssp-import-template): T6 fix2-C 跨域 role 不一致 — design.md §15.3 + issue
faade8d tweak(ssp-import-template): T6 fix3-A — 黃底 cell 加 thin border 補回視覺分隔
690f25c feat(ssp-import-template): T6 fix2 round 2 — required body fill + recalc + role enum
fbcf9f2 feat(ssp-import-template): T6 fix UX polish — hidden cols + VLOOKUP + ref_docs schema
66d0d13 docs(ssp-import-export-phase2): A1 T6 FE shipped — update tracker README
3171116 feat(ssp-import-template): A1 T6 BE — framework-version-scoped endpoint (superset)
c653f05 docs(ssp-import-export-phase2): A1 BE partial ship task arc 收口 — SUMMARY + handoff prompt
46b8999 docs(ssp-import-export-phase2): A1 partial T7 — BE smoke + changelog + tracker
419907d feat(ssp-import-template): A1 T5 07_控制項與AO sheet — profile-scoped 父子 row + MF defaults
c3de9fa feat(ssp-import-template): A1 T4 filled mode 非控制項 sheet — 6 領域預填 + DI
f14a942 docs(ssp-import-export-phase2): A1 partial summary — T0-T3 收口 + 換 session 交接
ffd5d63 feat(ssp-import-template): A1 T3 blank mode — generator 主邏輯 + lookup wiring
f68525f feat(ssp-import-template): A1 T2 generator base — sheet defs + styles + lookup + DV helpers
d9d54c2 feat(ssp-import-template): A1 T1 skeleton — route + app service + DI 接通
f59c4ff docs(ssp-import-export-phase2): A1 T0 verify 結果回填 design.md (4 處)
b18db55 docs(ssp-import-export-phase2): A1 phase docs — design + implementation plan
外加最終收尾 commit(含 round 3 changelog + 本 SUMMARY)尚未 commit。
00b6662 tweak(ssp-import-template): T6 fix-1 Dialog 框架名跑版 — 兩 dropdown 改 vertical stack
e0ff8f1 feat(ssp-import-template): A1 T6 FE — Excel 匯入樣板兩個下載點
| 檔案 | 主題 | Commit |
|---|---|---|
2026-05-19-feat-mf-ssp-import-template-download.md |
A1 T0-T5 + partial T7 BE base | b18db55 → 419907d |
2026-05-19-feat-mf-ssp-import-template-by-framework-version.md |
T6 BE FW-version-scoped endpoint | 3171116 |
2026-05-19-feat-mf-ssp-import-template-download-fe.md (FE) |
T6 FE 兩個下載點 + dialog | e0ff8f1 |
2026-05-19-feat-ssp-import-template-ux-polish.md |
UX round 1 (5 fix) | fbcf9f2 |
2026-05-19-feat-ssp-import-template-ux-polish-round2.md |
UX round 2 (3 fix) | 690f25c |
2026-05-19-tweak-ssp-import-template-yellow-fill-polish.md |
UX round 3 (border + range) | faade8d + 2b1e93c |
docs/issues/pending/2026-05-19-person-role-cross-domain-inconsistency.md — Person role 跨 OSCAL/GRC domain 不一致,4 個修補計劃(A2 phase 開工必看)
docs/features/FR-011.2-2605-ssp-import-export-phase2/design-A1.md v1.2,含:
docs/features/FR-011.2-2605-ssp-import-export-phase2/README.md A1 row 標 BE+FE shipped ✅
$ pytest tests/test_excel_template_*.py tests/test_ssp_import_template_app_service.py
106 passed (Unit test 全綠)
範圍:
test_excel_template_base.py — 26(含 ColumnDef invariant + lookup_builder + DV builder + helpers)test_excel_template_generator_blank.py — 25(含 structure / styling / DV / hidden cols / autofill / border / required body fill / role enum)test_excel_template_generator_filled.py — 20(filled mode 各 sheet)test_ssp_import_template_app_service.py — 35(app service helpers + T6 framework_version + helpers)累計:106 全綠(A1 partial ship 時 71 + T6 改動 +35 = 106)
| # | 項目 | 嚴重度 | 處理時機 |
|---|---|---|---|
| 1 | T7 cucumber E2E + 完整 BE smoke | 預期未完 | 後續 session — 跨 compliance-manager-test repo |
| 2 | VLOOKUP autofill Excel 開檔可能不自動算 | UX | user 暫 skip;可按 Ctrl+Alt+F9 強制重算;或後續改用其他機制(INDIRECT / Data Validation macro) |
| 3 | Person role 跨 OSCAL/GRC domain 不一致 | Medium | issue 已開;A2 phase 開工時實作修補 A(Excel parser enum validation 必做) |
| 4 | 既有 docx parser role normalize / dev DB 髒資料 audit | Medium | A2 phase 後考慮(issue 內含修補計劃) |
| 5 | OSCAL party ↔︎ project_participant 雙寫設計 | 大議題 | 不在 A1/A2 範圍,未來 OSCAL 匯出規劃時考慮 |
| 6 | 02_單位 OSCAL role 欄位(系統未 expose UI) | 預期 | 保留 optional 不動;未來 OSCAL 匯出時用 |
| 7 | BE boot 撞 jedi-issue GitLab env | 環境 | A0.1 既有 follow-up;user 端配齊後可跑完整 smoke |
| 8 | test_write_parties_refreshes_existing_party_in_place pre-existing fail |
low | 非 A1/T6 引入 |
| 9 | jedi-oscal 仍 path-dep | 例行 | Phase 2 整體完工再一次性 bump Nexus |
| 10 | pyproject.toml path-dep 改動還原 pin Nexus |
例行 | Phase 2 收口時做 |
無需 migration — A1 純粹是新 endpoint + 新 generator,不動 schema。
lsof -ti:8000 | xargs kill -9
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be
set -a; source .env; set +a
nohup poetry run python main_app.py > /dev/null 2>&1 &TOKEN="..." # from dev login
MF_UID="..." # dev DB existing MF uid
FW_VERSION_UID="..." # dev DB existing framework_version uid
# MF-scoped blank
curl -H "Authorization: Bearer $TOKEN" -H "X-Tenant-ID: 102" \
"http://localhost:8000/api/1.0/module-frame/$MF_UID/ssp-import-template?mode=blank" \
-o /tmp/template_mf_blank.xlsx
# MF-scoped filled
curl -H "Authorization: Bearer $TOKEN" \
"http://localhost:8000/api/1.0/module-frame/$MF_UID/ssp-import-template?mode=filled" \
-o /tmp/template_mf_filled.xlsx
# FW-version-scoped blank (T6 新增)
curl -H "Authorization: Bearer $TOKEN" \
"http://localhost:8000/api/1.0/ssp-import-template?framework_version_uid=$FW_VERSION_UID&mode=blank" \
-o /tmp/template_fw_blank.xlsx
# Verify via openpyxl
poetry run python3 -c "
from openpyxl import load_workbook
for fn in ['/tmp/template_mf_blank.xlsx', '/tmp/template_mf_filled.xlsx', '/tmp/template_fw_blank.xlsx']:
wb = load_workbook(fn)
visible = [s for s in wb.sheetnames if not s.startswith('_lookup_')]
print(f'{fn}: total={len(wb.sheetnames)}, visible={len(visible)}')"FE 有 hot reload,dev server 自動更新;但建議 hard refresh 瀏覽器(避免 cache)。Dialog 元件 + i18n 改動需重新 build production 才會生效。
| 場景 | 驗證步驟 | 預期 |
|---|---|---|
| S1 訪談前 | 列表頁右上「新增合規資源庫」→ 點「下載 SSP 匯入樣板」→ 選 framework + version → 下載 | 下載 xlsx,filename ssp_template_<fw>_<version>_blank_<date>.xlsx |
| S3 MF 已存在 | 進 MF template-edit 頁 → 批次維護 → 選「下載 SSP 匯入樣板(空白)/(已填)」 | 下載對應 xlsx |
| 黃底 + border | 開 xlsx 看 03_參與人員 sheet | A 欄 / B 欄 / F 欄 header 黃底 + thin border |
| 黃底範圍 | 同上看 row 2-50 | blank:body 無黃底;filled:實際 row 黃底 |
| UID 隱藏 | 開 xlsx 看 01_基本資料 | E/F 欄 (framework_version_uid / profile_uid) 應隱藏 |
| Role enum | F 欄下拉 | manager / reviewer / auditor / viewer |
| 程序書欄位 | 08_程序書 sheet | 只有 doc_name + description 兩欄 |
| VLOOKUP(嘗試) | D 欄選 matched_user → 看 A/B/C 欄 | 預期自動帶入;若沒動按 Ctrl+Alt+F9 強制重算 |
A1 已 BE+FE shipped。Phase 2 next stop:
依賴 A1 已 ship。涵蓋:
可平行 A2;依賴 A0.1。涵蓋:
跨 compliance-manager-test repo:
A1 task arc 跨 3 session 完工:
feature/ssp-import-export-phase2 branch 累計 17 commits(含本份 SUMMARY 收尾 commit)。BE 106 unit test 全綠。
A1 整體 BE+FE shipped。剩 T7 E2E 跨 test repo 留 follow-up。