✅ DONE — 2026-06-04 收尾。E-a 全部完成並驗證(系統資產匯入回灌 + 名稱比對 master、 範本下載填值修復、資產→設備資產改名、設備 + 系統資產 picker round-trip + 雙向回填)。 BE 5 commits(
1359ce48/743fc2a3/e51bd809/9116e5df/22929d6e)+ FE 2 commits(8c888e2/f983e38),皆未 push。收尾報告見同目錄2026-06-04-ea-SUMMARY.md;偏差紀錄見 design.md §11.11~11.19。
| 項目 | 內容 |
|---|---|
| 緣由 | FR-032 A/B/C/D/F 已完成(系統資產 + 設備鉤稽 CRUD + clone + docx 匯出);本份交接 E-a:Excel 匯入回灌系統資產 + 依名稱比對 information_systems master |
| BE branch | feature/FR-032(compliance-manager-be) |
| FE branch | feature/FR-032(compliance-manager-fe) |
| 套件 repo | ~/Projects/Jedicogy/module/jedi-python-package/(單一 monorepo,含 jedi-oscal / jedi-device),branch feature/FR-032 |
| 接手前必讀 | 本檔 → design.md(全) → §5 列的匯入管線檔 |
| 預估時間 | BE 4 層 ~0.5–1 天 + FE preview ~0.5 天 |
| 性質 | 完整縱切,碰專案最敏感的 Excel 匯入管線 — 慢工出細活,每層加測試 |
docs/features/FR-032-2606-system-asset-inventory/design.md(重點 §2 設計原則 / §3 資料模型 / §6 匯出 / §10 驗證結果)common/util/system_asset_snapshot.py(核心共用邏輯,E-a 寫入要重用 snapshot_information_system)app/module_frame/excel_template/sheet_definitions.py(樣板 sheet spec,看 SHEET_INVENTORY_ITEMS + ALL_SHEETS)app/oscal/service/excel_parser/sheet_handlers.py(parser,看 parse_inventory_items_sheet)domain/oscal/parser/ssp_intermediate.py(ParsedInventoryItem)domain/oscal/service/write_strategy/inventory_item_write_strategy.py(SSP 寫入)app/oscal/service/ssp_excel_import_app_service.py(MF defaults 寫入,搜 _write_mf_defaults)src/components/grc/ssp-excel-import/SheetPreviewInfoSystems.vue(廢棄但可當 preview 範本)| 塊 | 內容 | 狀態 |
|---|---|---|
| A | 範本層(module_frame)系統資產表 + picker(hybrid soft-ref) | ✅ |
| B | 啟動專案 clone 帶 asset_type/ref(module_frame_template_copy_service.py Step 6) |
✅ |
| C | 專案 SSP view 系統資產表 + 編輯(SspInventoryItemsAppService) |
✅ |
| D1-A | docx 匯出獨立「System Assets」表 + 設備表 repoint live 表 | ✅ |
| F | 設備 inventory 鉤稽 jedi-device(device picker,帶 hostname/ip/os) | ✅ |
資料模型(已落地):compliance.module_frame_inventory_item_defaults + oscal.ssp_inventory_items 各有 asset_type('hardware'/'information_system') / ref_type('information_system'/'device') / ref_id(master uid)。DEV 已套 migration scripts/sql/2026-06-04-fr032-inventory-asset-type.sql。
E-a 要做什麼:目前 Excel 匯入(資產 sheet)解析的 inventory 列寫死 asset_type='hardware',沒有「系統資產」的匯入路徑。E-a 要讓使用者能從 Excel 匯入系統資產,並依系統名稱比對 compliance.information_systems master 自動鉤稽(設 ref_id),配不到則自由輸入。docx 匯出已有獨立 System Assets 表,Excel 端要對稱補上。
common/util/system_asset_snapshot.py 有 snapshot_information_system(info_ds, ref_id)(回 (description, props, ref_id_str))+ snapshot_device。E-a 寫入時重用,不要重寫。GRC_INFORMATION_SYSTEM_NOT_FOUND 已存在(GRC_404020),差點加重複碼。新 code 先 grep 名稱。pyproject.toml 為 path(已改、未 commit)+ user 跑 poetry update jedi-device。E-a 若不動套件就無此問題。SheetPreview*.vue,否則匯入預覽該 sheet 不顯示。建議:系統資產走獨立「系統資產」sheet(對稱 UI 兩表 + docx System Assets 表),不要塞進「資產」sheet 加 asset_type 欄(欄位不同:系統是 name/abbreviation/owner/deployment/status,設備是 IP/MAC/FQDN)。
app/module_frame/excel_template/)sheet_definitions.py:新增 SHEET_SYSTEM_ASSETS(sheet_name="系統資產"),columns 對齊 docx System Assets:name(required) / abbreviation / description / owner_name / deployment_model(enum) / system_status(enum)。加進 ALL_SHEETS(放在「資產」sheet 後)。header_i18n.py:加新欄位 header i18n key。generator.py:確認新 sheet 會被產生;若匯出樣板需填入現有系統資產(round-trip),找匯出填值邏輯補上(檢查 downloadSspExcelTemplate 'filled' 模式怎麼填其他 sheet)。jedi_information_system/common/enum/information_system_enum.py(on-premise/cloud/hybrid/co-location;operational/under-development/under-major-modification/disposition/other)。python -c "from app.module_frame.excel_template.sheet_definitions import ALL_SHEETS; print([s.sheet_name for s in ALL_SHEETS])" 應含「系統資產」。app/oscal/service/excel_parser/sheet_handlers.py)parse_inventory_items_sheet(~line 191)寫 parse_system_assets_sheet,回 list[dict]。domain/oscal/parser/ssp_intermediate.py + app/oscal/service/excel_parser/v2_bundle.py)ParsedSystemAsset dataclass(name/abbreviation/description/owner_name/deployment_model/system_status)。parsed_system_assets list。app/oscal/service/ssp_excel_import_app_service.py 搜 _write_mf_defaults(~1714),寫 ModuleFrameInventoryItemDefaultEntity 時設 asset_type='information_system' + ref。domain/oscal/service/write_strategy/inventory_item_write_strategy.py(~124),寫 InventoryItemEntity 時設 asset_type + ref。information_system_domain_service.get_information_systems(InformationSystemQueryEntity(name=<sheet name>)) 比對:
ref_type='information_system', ref_id=<master uid>,並用 snapshot_information_system(info_ds, ref_id) 回填 props(master 為準)。snapshot_information_system 風格),MF + SSP 兩路徑共用。test_ssp_excel_import_app_service.py:46)。compliance-manager-fe)src/components/grc/ssp-excel-import/SheetPreviewSystemAssets.vue(仿 SheetPreviewInfoSystems.vue 廢棄檔,但欄位對齊新 sheet + 顯示「比對到的 master / 自由輸入」狀態)。ImportExcelPreviewPage.vue 或 store sspExcelImportStore.js)。BE
app/module_frame/excel_template/sheet_definitions.py(加 SHEET_SYSTEM_ASSETS + ALL_SHEETS)app/module_frame/excel_template/header_i18n.py(header keys)app/module_frame/excel_template/generator.py(產生 + 可能填值)app/oscal/service/excel_parser/sheet_handlers.py(parse_system_assets_sheet + dispatch)app/oscal/service/excel_parser/v2_bundle.py(bundle 加 list)domain/oscal/parser/ssp_intermediate.py(ParsedSystemAsset)app/oscal/service/ssp_excel_import_app_service.py(MF defaults 寫入路徑 ~1714)domain/oscal/service/write_strategy/inventory_item_write_strategy.py(SSP 寫入 ~124)common/util/system_asset_snapshot.py(重用 snapshot_information_system;可加 import 比對 helper)di_containers/oscal/oscal_containers.py 補)FE
src/components/grc/ssp-excel-import/SheetPreviewSystemAssets.vue(新)cd ~/Projects/Billows/Audit-Manager/compliance-manager-be
git branch --show-current # 應為 feature/FR-032
git status --short # pyproject.toml M 是 dev-only(jedi-device path),勿 commit
# pytest smoke(FR-032 既有測試應全綠)
python -m pytest test/test_fr032_mf_inventory_asset_type.py test/test_fr032_ssp_inventory_asset_type.py \
test/test_fr032_inventory_export_mapping.py test/test_fr032_device_picker.py -q | tail -5
# jedi monorepo branch
cd ~/Projects/Jedicogy/module/jedi-python-package && git branch --show-current # feature/FR-032cd ~/Projects/Billows/Audit-Manager/compliance-manager-be
# DB 三欄存在(密碼查 .env DB_SECRET,psql 必帶 -p 25432)
PW=$(python3 -c "import json;print([json.loads(l[len('DB_SECRET='):])['rds_master_password'] for l in open('.env') if l.startswith('DB_SECRET=')][0])")
PGPASSWORD="$PW" psql -h 192.168.50.188 -p 25432 -U cmmgr -d guidant_ai_dev -tA -c "
SELECT table_name||'.'||column_name FROM information_schema.columns
WHERE column_name IN ('asset_type','ref_type','ref_id')
AND table_name IN ('module_frame_inventory_item_defaults','ssp_inventory_items') ORDER BY 1;"
# 應印出 6 列(兩表 × 三欄)-am。poetry update)。E-a 若不動套件就不碰這塊。pyproject.toml 的 jedi-device path 改動是 dev-only,不 commit。test_ssp_excel_import_app_service.py:46)。docs/changelog/YYYY-MM-DD-feat-fr032-excel-roundtrip.md> ✓ DONE 標頭system_implementations,是跟本功能無關的既有深層缺陷(design §6.3 follow-up)BE(feature/FR-032)
2f167300 feat(FR-032 F): DeviceMenuResponse 加 hostname / os
02ac0662 feat(FR-032 F): 設備 inventory 支援鉤稽 jedi-device(BE)
a49f6b41 fix(FR-032): docx 匯出系統資產獨立成 System Assets 表
fe30ce52 fix(FR-032): ssp_version 匯出 system_implementations 改 getattr
ce71c84a feat(FR-032): docx 匯出 repoint 到 live inventory 表(D1-A)
0afb037e feat(FR-032): SSP 層系統資產 hybrid soft-ref(C)
58100d31 feat(FR-032): 範本層系統資產 hybrid soft-ref(A + clone)
cfcd0345 feat(FR-032): migration 加 inventory asset_type/ref_type/ref_id
0bfa1c0f / f10b8dcc / 420f5e19 docs(FR-032): design + spec sharpen + 對齊 live
(FR-032 BE 測試檔:test/test_fr032_*.py 共 4 檔 23 測試綠)
jedi monorepo(feature/FR-032,~/Projects/Jedicogy/module/jedi-python-package)
9277d5b feat(device): device menu 加 hostname / os
d3af930 feat(inventory): OscalInventoryItem 加 asset_type/ref_type/ref_id
FE(feature/FR-032)
c8bf554 fix(FR-032 F): 設備 dialog「描述」label + 驗證提示改「名稱」
1a97a98 feat(FR-032 F): device picker 帶入 hostname/os + 設備資產文案
68a5de2 feat(FR-032 F): 設備資產 dialog 加 device picker
841c2a9 Revert SspTabPanel 跑版 fix(user 覺得醜,還原原樣式待議)
91b55b4 feat(FR-032): 專案 SSP view 分「資產清冊 + 系統資產」兩表
7338cd9 / 941fb59 fix: 來源欄 Tag 統一 / enum label 顯示
c39138d feat(FR-032): 範本層系統元件 tab 新增「系統資產」表 + picker
已知未決(非 E-a):FE SspTabPanel.vue Excel 按鈕 layout(user 嫌新版醜,已 revert 回原樣式,待議調整);.env.production 是 FE 本機既有改動勿碰。
請閱讀 docs/features/FR-032-2606-system-asset-inventory/handoff/2026-06-04-ea-excel-roundtrip-handoff.md,
按 §0 讀序了解現況,接手做 FR-032 Phase E-a(Excel 匯入回灌系統資產 + 依名稱比對
information_systems master 設 ref_id)。先跑 §6 pre-flight + §7 verify,再依 §4 順位
五層縱切實作(每層加測試)。BE/FE/jedi 在 feature/FR-032。不切 branch、不自動 push、
收尾等我明示。