狀態:Phase 0+ — 需求理解 v5(A0.1 結構校正後) 建立日期:2026-05-18 最後更新:2026-05-19(v5:A0 後 review 發現 main 表缺、命名不一致、鉤稽雙路徑 → A0.1 結構重整補丁) 版本歷程:
- v1:草稿整理 + 11 個待釐清項
- v2:Raymond 第一輪回覆 → Q1~Q11 resolved + 補充 OSCAL 匯出 + Excel 樣板設計
- v3:誤判 — 主張建三張新 OSCAL mirror 表 + 廢既有通用表
- v4:校正 — 既有表本就是 OSCAL system-implementation 多型鏡像,改走「擴充既有表」方案(→ A0 shipped)
- v5:A0.1 結構重整 — main 表 / items rename / join 表 / 鉤稽路徑統一(詳見
design-A0.1.md+docs/analysis/2026-05-19-ssp-system-impl-restructure-rationale.md) 撰寫人:Claude(依requirement.md草稿整理) 下一步:A0.1 開工 → A1 / B1 平行
A0 shipped 後 review 發現幾個結構問題:
system_security_plan_system_implementations 表 = items 不是 main,缺 1:1 main 層information_system_id 跟既有 system_characteristics 中介路徑重疊system-implementation 是 block(無 UUID),DB 仍應有 main 表(為 PG 規範 + block-level metadata anchor)ssp_* 前綴慣例不一致v5 補丁(A0.1):
| 項目 | v4(A0 shipped) | v5(A0.1 校正後) |
|---|---|---|
| Items 表名 | system_security_plan_system_implementations |
ssp_system_implementation_items |
| Main 表 | ❌ 無 | ssp_system_implementations(1:1 per scope) |
| Join 表 | ❌ 無 | ssp_inventory_item_components(M:N) |
| Items 鉤稽 information_system | information_system_id 直連 tenant |
system_characteristic_id 走 SSP 中介 |
system-implementation.users[] |
列「視需求才做」 | 不做(既有 oscal_parties cover 人員需求) |
詳細 A0.1 規格見:
docs/features/FR-011.2-2605-ssp-import-export-phase2/design-A0.1.mddocs/features/FR-011.2-2605-ssp-import-export-phase2/implementation-plan-A0.1.mddocs/analysis/2026-05-19-ssp-system-impl-restructure-rationale.md這份不是正式 spec,是 Claude 把 requirement.md 草稿讀完之後,把「我理解你想做的事情」用比較結構化的方式寫回來,方便:
確認過後再進入 brainstorm + design.md + implementation-plan.md + test-plan.md。
module_frame 是專案的範本層 — 顧問先把客戶現有的安全控制現況、政策程序書、組織單位、參與人員、設備、系統等資訊整理進「合規資源庫」,之後客戶建專案時,這些資訊會被當成預設值帶入該專案的 SSP,省去重複輸入,也作為 OSCAL 匯出的資料來源。
| 路徑 | 能匯什麼 | 限制 |
|---|---|---|
| Docx 匯入(已上線 v2) | metadata / parties / leveraged services / 控制項實作 / AOs | 來源是顧問訪談後手寫的 SSP 草稿 docx,客戶不一定有這份文件 |
| Excel 匯入(舊版) | 只匯「控制項現況說明」+「AO 現況說明」+「參考程序書」 | 涵蓋面很窄,缺基本資料、設備、單位、人員、系統 |
| Excel 匯出 | 現況說明 Excel 樣板下載 | 同上,只覆蓋現況說明 |
| SSP 文件匯出 | (目前沒有;OSCAL JSON 匯出有) | 客戶想要的是可讀的 docx/pdf,不是 OSCAL JSON |
讓**「合規資源庫」的所有主要資料領域**都能透過 Excel 雙向同步(匯入 / 匯出),並讓「合規資源庫」與「專案 SSP 版本」都能匯出成可讀的 SSP 文件(docx / pdf / odt)+ OSCAL 結構化格式(JSON / XML / YAML)。
除了 docx / pdf / odt 三種可讀格式,匯出也要提供 OSCAL 結構化格式(JSON / XML / YAML)。這部分技術上:
infra/mapper/ssp/ssp_yaml_mapper.py),可作為 base樣板必須:
data validation 規格做下拉選項,使用者選的時候有 dropdown,例如:
system_owner → 下拉選 tenant 內既有 user(顯示 nickname)org_unit → 下拉選既有組織單位device → 下拉選既有 public.devicesinformation_system → 下拉選既有 compliance.information_systemsimpl_status / sensitivity_level / deployment_model 等 enum → 下拉選 enum 值💡 設計考量:Excel 下拉選單在資料量多時會卡(如 user 上千人),需要評估是用「name list 直接列舉」還是「named range + 工作表隱藏」處理。實作階段再決定。
| 術語 | Tenant 層實體 | OSCAL Mirror 表 | OSCAL 規格對應 |
|---|---|---|---|
| 合規資源庫 | module_frame |
system_security_plans |
system-security-plan |
| 基本資料 | module_frame.metadata + 引用的 information_systems |
system_security_plans_system_characteristics |
system-characteristics |
| 單位 | org_units |
oscal_parties (type=organization)【既有,不動】 |
metadata.parties |
| 參與人員 | users |
oscal_parties (type=person)【既有,不動】 |
metadata.parties |
| 設備(資產) | public.devices |
system_security_plan_system_implementations (implementation_type=inventory-item)【既有,擴充】 |
system-implementation.inventory-items |
| 系統(資訊系統) | compliance.information_systems |
system_security_plan_system_implementations (implementation_type=component / subsystem)【既有,擴充】 |
system-implementation.components |
| Leveraged Services | (無 tenant 層表,純文字) | system_security_plan_system_implementations (implementation_type=leveraged-authorization)【既有,擴充】 |
system-implementation.leveraged-authorizations |
| 控制項現況說明 | module_frame_control_default.implementation_statement |
system_security_plan_control_implementations |
control-implementation.implemented-requirements |
| AO 現況說明 | module_frame_control_objective_default.statement |
ssp_control_implementation_objectives |
implemented-requirements.statements |
| 參考程序書 | module_frame_reference_document + mapping |
ssp_reference_documents + ssp_reference_document_mappings【既有】 |
back-matter.resources + links |
✅ 架構決策(v4 校正):擴充既有
system_security_plan_system_implementations表,不新建三張表。既有表已是「OSCAL system-implementation 多型鏡像」的設計用意,implementation_type已用於區分 system / subsystem / service / component / hardware / software(用 enumSystemImplementationType),且 140 筆 hardware 資料 + jedi-oscal 完整 stack 已在運作。擴充比新建更務實。
Schema(既有):
| 欄位 | 型別 | 用途 |
|---|---|---|
| id | integer PK | 主鍵 |
| uid | uuid UNIQUE | OSCAL UUID(已 uuid4 default) |
| system_security_plan_id | integer NOT NULL FK | 只服 SSP,CASCADE FK |
| name | varchar(255) NOT NULL | 名稱 |
| description | text | 說明 |
| implementation_type | varchar(50) NOT NULL | system / subsystem / service / component / hardware / software(既有 enum) |
| responsible_party | varchar(100) | 負責角色或單位(純字串,沒鉤 oscal_parties.uid) |
| created_at / updated_at / created_user / updated_user | — | 完整稽核欄位 |
程式碼 stack(既有,jedi-oscal):
jedi_oscal/infra/model/ssp/ssp_system_implementation.pyjedi_oscal/domain/entity/ssp/jedi_oscal/domain/repository/ssp/system_implementation_repo.py + jedi_oscal/infra/repository/ssp/jedi_oscal/infra/mapper/ssp/system_implementation_mapper.pyjedi_oscal/app/dto/ssp/ssp_system_implementation_dto.pyjedi_oscal/common/enum/code_enum.py 內的 SystemImplementationTypejedi_oscal/infra/mapper/ssp/ssp_yaml_mapper.py(OSCAL 序列化已部分接通)Caller(主專案):
app/associations/service/project_device_mapping_service.py(專案 device mapping)app/oscal/service/ssp_versioning_service.py(SSP 版本服務)資料量:140 筆 hardware(= 已用作 devices 的 OSCAL 鏡像)。
| 新增欄位 | 型別 | 用途 | nullable |
|---|---|---|---|
| scope_type | varchar(20) | 'ssp' 或 'module_frame' — 標示這筆隸屬哪邊 |
NOT NULL(既有 140 筆 migration 設 'ssp') |
| scope_id | integer | 對應 scope_type 指向的 id(soft FK,無 DB FK constraint) | NOT NULL |
| device_id | integer | soft FK → public.devices.id;鉤稽既有 device 時填 |
nullable |
| information_system_id | integer | soft FK → compliance.information_systems.id;鉤稽既有 system 時填 |
nullable |
| title | varchar(255) | OSCAL component.title(OSCAL 規格的人類可讀標題;與 name 區分) | nullable |
| purpose | text | OSCAL component.purpose(用途說明) | nullable |
| status | varchar(50) | OSCAL component.status(under-development / operational / disposition / other) | nullable |
| party_uuid | varchar(36) | OSCAL leveraged-authorization.party-uuid(授權方);對齊既有 oscal_responsible_parties.party_uuid 型別 | nullable |
| date_authorized | date | OSCAL leveraged-authorization.date-authorized | nullable |
| 欄位 | 變更 | 理由 |
|---|---|---|
system_security_plan_id |
NOT NULL → nullable;CASCADE FK 保留 | scope_type='module_frame' 時不指向 SSP,必須 nullable |
responsible_party |
維持,不動 | 既有資料用,標 deprecated(後續優化由 oscal_responsible_parties 取代) |
SystemImplementationType (jedi-oscal common/enum/code_enum.py) 只加一個新值:
LEVERAGED_AUTHORIZATION = "leveraged-authorization"(OSCAL leveraged services 用)既有 enum 值的延用:
| 既有 enum 值 | 新功能用途 |
|---|---|
hardware |
devices 的鏡像(沿用既有,跟 project_device_mapping_service 一致;不另外造 inventory-item 重複概念) |
component |
information_systems 的鏡像(沿用既有;可選用 system / subsystem 對應 OSCAL system-implementation.this-system / subsystem) |
software / service / system / subsystem |
維持不動 |
為什麼不加 inventory-item:
OSCAL 字面術語上 hardware 是 component.type 子分類,inventory-item 才是「具體 deployed asset」。但既有 code 已用 hardware 涵蓋同一概念、140 筆都是這樣,加 inventory-item 會讓兩個 enum 值意義重疊(dev 心智負擔 + caller 寫入分流)。OSCAL 匯出時若需要 inventory-item 結構,由 mapper 層把 hardware 翻譯成 OSCAL inventory-item JSON 即可,不必動 DB。
既有 140 筆 hardware 資料:
hardware)| 新增 index | 用途 |
|---|---|
ix_ssp_sys_impl_scope (scope_type, scope_id) |
依 scope 查詢 |
ix_ssp_sys_impl_device_id |
依 device 反查 |
ix_ssp_sys_impl_info_system_id |
依 information_system 反查 |
| 不做的事 | 理由 |
|---|---|
新建 oscal_inventory_items |
既有表已有多型 implementation_type,加 column 即可 |
新建 oscal_components |
同上 |
新建 oscal_leveraged_authorizations |
同上 |
廢棄既有 system_security_plan_system_implementations |
既有表正在用,廢棄成本遠高於擴充 |
| Migration 搬資料到新表 | 不新建表,沒地方搬 |
問題:表名是 system_security_plan_system_implementations(含 system_security_plan 前綴),但新增 scope_type='module_frame' 後也會裝 module_frame 資料,名稱語意稍偏。
處理方向(A0 brainstorm 待決):
oscal_system_implementations(更通用),既有 ORM / repo 同步改名oscal.system_implementations 對齊新名稱供新功能讀此項列入剩餘 brainstorm 題目。
下面是「Excel 匯入」要新增的範圍,依資料領域逐項展開:
內容(依 docx parser v2 已建立的欄位推估):
匯入挑戰:
這四類有共同特性:Excel 內填的是「字串名稱」,匯入時要對到系統內既有的實體。
| 狀況 | 系統行為 |
|---|---|
| Excel 填的名稱完全相符系統內既有實體 | 自動鉤上(跟 docx parser 的 party email-match / org-unit name-match 一致) |
| 找不到完全相符的 | 需要進入「預覽 / 編輯」介面,由 user 手動 (a) 從下拉選現有的 (b) 新建一筆 (c) 暫時當純文字保留 |
| 領域 | Tenant 層比對對象 | 建議比對 key | OSCAL Mirror 寫入目標 | 鉤不到時 |
|---|---|---|---|---|
| 單位 | org_units |
organization name 完全相符 | oscal_parties (type=organization) |
標 unmatched → user 可選現有 / 預覽頁新建 / 純文字 OSCAL 紀錄(party_uuid 有,soft FK null) |
| 參與人員 | users |
email 完全相符(同 tenant) | oscal_parties (type=person) |
同上 |
| 設備 | public.devices |
name 或 ip 完全相符 | system_security_plan_system_implementations (implementation_type='inventory-item')【既有表擴充】 |
同上:(a) 鉤已有 device (b) 預覽頁新建到 public.devices (c) 純文字 OSCAL 紀錄(device_id null) |
| 資訊系統 | compliance.information_systems |
name 或 abbreviation 完全相符 | system_security_plan_system_implementations (implementation_type='component')【既有表擴充】 |
同上:(a) 鉤已有 (b) 預覽頁新建 (c) 純文字 OSCAL 紀錄 |
| Leveraged Services | (無 tenant 層表) | service name + authorizing party | system_security_plan_system_implementations (implementation_type='leveraged-authorization')【既有表擴充】 |
直接建一筆,authorizing party 可選既有 oscal_parties 或同步新建 |
寫入路徑(confirm 階段 BE 行為):
user 在預覽頁 confirm
│
▼
┌────────────────────────┐
│ 鉤稽結果分流 │
└────────────────────────┘
│ │ │
matched inline 新建 純文字保留
│ │ │
▼ ▼ ▼
只寫鏡像表 先寫 tenant 只寫鏡像表
(含 soft FK) 層表 → 再寫 (soft FK
鏡像表 = null)
註:「鏡像表」=
system_security_plan_system_implementations,依 implementation_type 區分 inventory-item / component / leveraged-authorization。
✅ Q3 已 resolved:docx parser 本期不擴充到 devices / information_systems,列入「最後統整優化清單」 — 等 Phase 2 完工後再一起處理 docx parser 對齊。同樣的 OSCAL mirror 表新建後,docx parser 之後要對齊寫入這幾張表。
✅ Q8 已 resolved:鉤不到時除了「選現有 / 純文字保留」,也支援直接在預覽頁面新建 — 例如 user 在預覽頁看到 unmatched device,可直接 inline 輸入 ip/os 等欄位,confirm 時先寫
public.devices再寫oscal_inventory_items(soft FK 串起來)。
已有功能,但要對齊 docx 匯入體驗:
意涵:這代表新 Excel 不再綁定某個 module_frame,使用者可以拿任意 Excel(甚至從別的 framework 來的)匯進來,由系統幫忙比對。這跟既有「先匯出某 module_frame 的樣板 → 填 → 匯回同一個」的 round-trip 模式有差異,要釐清是否兩種模式並存。
草稿沒明說,但既有 Excel template 有 參考程序書 欄位,docx parser v2 也有 SSP document pool 模式。新版要:
草稿明確說「匯入模式可以參考 docx 匯入模式」。把 docx 匯入流程(v2 已上線)抓出來,對應到 Excel:
| 階段 | docx 流程(既有) | Excel 流程(本期目標) |
|---|---|---|
| 1. 選 parser | 從 framework 選 docx parser | 從 framework 選 Excel parser(或統一同一個入口) |
| 2. 上傳檔案 | 上傳 docx | 上傳 xlsx |
| 3. BE 解析 | 解析回傳 parse_uid + parsed_result(JSONB,7 天 TTL) | 同 docx 模式 |
| 4. 預覽 | iframe PDF + 右側 Section 編輯 panel | 左右比對(左:Excel 原貌或欄位對照、右:解析後可編輯 Section) |
| 5. 鉤稽 | parties / org-unit / leveraged auto-match + 標出未匹配 | 同 docx 模式 + 涵蓋設備 / 系統 / 控制項 / AO |
| 6. user 編輯 | localStorage 暫存 + BE TTL | 同 docx 模式 |
| 7. 確認 | POST confirm → 寫入 module_frame | 同 docx 模式 |
| 8. 重新上傳 | 棄置 parse_uid,從頭來 | 同 docx 模式 |
✅ Q6 已 resolved:本期不做左右比對。Excel 不像 docx 容易渲染成 PDF,純單欄式預覽 + 編輯介面即可(方案 C)。
按資料領域分多 sheet,欄位顏色 + 下拉選單規格:
| Sheet | 內容 | 必填欄位(黃底) | 下拉選單欄位 |
|---|---|---|---|
00_說明 |
樣板版本、framework、填寫指引、必填顏色圖例 | — | — |
01_基本資料 |
系統 metadata(name / abbreviation / desc / sensitivity / boundary / objectives / deployment) | name / sensitivity / objectives | sensitivity (enum) / objectives (enum) / deployment_model (enum) / system_owner (既有 user list) / org_unit (既有 list) |
02_單位 |
parties type=organization | name | parent_org (既有 org list, optional) |
03_參與人員 |
parties type=person + 鉤稽 user | email / name | role / org_unit (既有 list) |
04_設備 |
devices(鉤稽 public.devices) |
name / ip | os (建議候選 list) / device_type (建議候選 list) / status (enum) |
05_資訊系統 |
information_systems(鉤稽 compliance.information_systems) |
name | sensitivity / objectives / deployment_model / system_owner |
06_外部利用服務 |
leveraged authorizations | service_name / provider | — |
07_控制項與AO |
控制項實作 + AO 現況(保留既有 module_frame_import_template.xlsx 的結構 + 擴充) | statement_id / control_id | impl_status (enum) |
08_程序書 |
reference document pool | doc_name / doc_no | doc_type (enum, 若有) |
💡 已有資料下拉如果量大(如 user 上千人),實作階段用「named range + 隱藏 lookup sheet」處理。
✅ Q5 已 resolved:「合規資源庫」與「專案 SSP 版本」兩邊都要提供匯出。
匯出來源 × 匯出格式組合矩陣:
| 來源 \ 格式 | docx | odt | OSCAL JSON | OSCAL XML | OSCAL YAML | |
|---|---|---|---|---|---|---|
| 合規資源庫(module_frame) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 專案 SSP 版本(project + ssp_version) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
兩個來源的差異:合規資源庫匯出的是「範本層」資料(顧問建好的 default);專案 SSP 版本匯出的是「實際填寫的現況」(含每個 AP round 的差異)。
✅ Q4 已 resolved:odt 本期要做。
| 格式 | 實作成本 | 技術做法 |
|---|---|---|
| docx | 中 | python-docx 手寫,跟既有 system-design DOCX 規範一致(封面 / 版本紀錄 / 目錄 / Graphviz 圖) |
| 低 | docx 完成後用既有 /upload-file/<uid>/preview-as-pdf endpoint 或 LibreOffice headless convert |
|
| odt | 中 | 用 LibreOffice headless --convert-to odt 從 docx 轉,或用 odfpy 直接產(評估後再定) |
| OSCAL JSON | 中 | jedi-oscal 已有 yaml mapper(ssp_yaml_mapper.py)作 base,serialize 改 JSON |
| OSCAL XML | 中 | 同 JSON,OSCAL 標準 XML schema 已定 |
| OSCAL YAML | 低 | jedi-oscal 既有 yaml mapper 已可用 |
✅ Q10 已 resolved:先用 CMMC 通用樣板,後續如果有法規資料不同的需求再抽象化。
ASIA-CMMC-SSP-DRAFT-with-user-info-202604.docx 拆出章節結構、版面樣式、placeholderPOST /module-frame/<uid>/export?format=docx|pdf|odt|json|xml|yamlPOST /projects/<project_id>/ssp/<version_id>/export?format=...草稿說「不要全照我的切,要的話再分更細」。下面是我的版本,跟草稿的差異會標出。
system_security_plan_system_implementations 表(前置必做 ✅ shipped (BE c4804d7 + jedi-oscal afe7035→dbb3d7c, 2026-05-18))| Phase | 主題 | 範圍 | 依賴 |
|---|---|---|---|
| A0 | 既有表 schema 擴充 + ORM / Entity / Repository / Mapper 同步擴充 | 在既有 system_security_plan_system_implementations 上加 scope_type / scope_id / device_id / information_system_id / title / purpose / status / party_uuid / date_authorized 欄位;既有 system_security_plan_id 改 nullable;enum 擴充 inventory-item / leveraged-authorization;jedi-oscal 全 stack 同步擴充 |
無 |
A0 包含項目:
ssp_system_implementation.pyjedi_oscal/domain/entity/ssp/system_implementation_mapper.py + ssp_yaml_mapper.py(OSCAL 序列化)ssp_system_implementation_dto.pySystemImplementationType 加新值project_device_mapping_service + ssp_versioning_service 確保不破壞A0 是 Track A 與 Track B OSCAL 線(B5)共同前置 — 任何 Excel 匯入 / OSCAL 匯出邏輯都要等這層基礎建好才能接。
| Phase | 主題 | 範圍 | 依賴 |
|---|---|---|---|
| A1 | Excel 樣板設計 + 匯出下載 | 設計 multi-sheet xlsx(§4.2 9 個 sheet),含必填欄位顏色標示、enum 與既有資料下拉選單;提供「下載空白樣板」+「從現有 module_frame 下載已填樣板」兩種模式 | A0(樣板下拉要選 OSCAL mirror 既有資料) |
| A2 | Excel Parser + BE 解析 API | 寫 ExcelParser(對應 docx 的 DocxParser),輸出 ParsedResult JSONB;提供 upload + parse endpoint,回傳 parse_uid(沿用 docx parser 的 7 天 TTL 機制) | A1 |
| A3 | 鉤稽邏輯 — parties / org-units(抽共用層) | 把 docx parser 既有的 party / org-unit match 邏輯抽出共用 service,Excel / docx 兩條路徑都用同一份 matcher;寫入路徑寫到 oscal_parties |
A2 |
| A4 | 鉤稽邏輯 — devices / information_systems / leveraged + 控制項/AO 模糊比對 | 新增 devices / information_systems / leveraged / control / AO 的 match 邏輯;寫入路徑寫到 A0 建好的三張 OSCAL mirror 表 | A0, A3 |
| A5 | 預覽 UI + Confirm 寫入(含 inline 新建) | 前端單欄預覽 + 編輯介面、localStorage 暫存、unmatched 項目支援「選現有 / 純文字 OSCAL 紀錄 / inline 新建 tenant 資料」三種處理;confirm 時依路徑寫入 module_frame + OSCAL mirror 表 | A2~A4 |
跟草稿的差異:草稿把「Excel 匯入功能」當一個階段,我拆成 4 階段(A2~A5)+ A0 基礎建設,因為鉤稽邏輯是高風險區域、需要分批驗證;A3 把 docx 既有 matcher 抽出共用,避免兩套 parser 行為不一致。
| Phase | 主題 | 範圍 | 依賴 |
|---|---|---|---|
| B1 | Docx 樣板拆解 + python-docx generator 骨架 | 從 ASIA-CMMC-SSP-DRAFT-with-user-info-202604.docx 拆出章節結構,建立 generator 骨架(章節 helper、樣式、封面、版本紀錄表、目錄) |
無 |
| B2 | 內容組裝服務 — 兩種來源 → 共用 SSP data model | App service 把 module_frame 或 專案 SSP 版本資料組成 generator 用的 SSP data model(metadata / parties / inventory_items / components / leveraged / controls / AOs / references),共用同一個 generator | A0, B1 |
| B3 | Docx Export API + 下載 | POST /module-frame/<uid>/export?format=docx 與 POST /projects/<pid>/ssp/<ver>/export?format=docx 兩支 endpoint;回傳 docx file stream |
B2 |
| B4 | PDF + ODT 補上 | docx 完成後接 LibreOffice headless convert(或 odfpy)補 pdf / odt 兩種格式,同一個 export endpoint 用 format 參數切換 |
B3 |
| B5 | OSCAL 結構化匯出(JSON / XML / YAML) | 基於 jedi-oscal 既有 yaml mapper 擴充,序列化 OSCAL mirror 表(含 A0 三張新表)→ JSON / XML / YAML;同一個 export endpoint format=json|xml|yaml |
A0, B2(與 B3/B4 平行可進行) |
| B6 | 前端 UI + 格式選擇 | 合規資源庫頁 + 專案規劃頁加「匯出 SSP」按鈕 + 格式下拉(docx / pdf / odt / oscal-json / oscal-xml / oscal-yaml) | B3, B4, B5 |
跟草稿的差異:草稿是 3 階段(樣板 / API / UI),我拆成 6 階段:
- 樣板拆成 B1(generator 骨架)+ B2(data model 組裝),技術重點不同
- 多了 B5 OSCAL 結構化匯出線(raymond 第一輪回覆補充)
- ODT 不能等 docx 順手就拿到,獨立做 B4
- UI 集中在最後 B6(含格式 dropdown)
┌── A1 ── A2 ── A3 ── A4 ── A5 (Excel 匯入完成)
│
A0 ───────────┤
(OSCAL mirror │
表基礎) │
│ B1 ── B2 ──┬── B3 ── B4 ──┐
└──────────────┤ ├── B6 (SSP 匯出完成)
└── B5 ────────┘
關鍵 dependency:
project_device_mapping_service + ssp_versioning_service) regression 測試通過、140 筆既有資料 scope_type='ssp' migration 完成| # | 問題 | 決策 |
|---|---|---|
| Q1 | 「設備」對應 OSCAL 哪一項? | ✅ public.devices(jedi-device 套件)→ OSCAL inventory-items(資產概念),匯入時與此表鉤稽 |
| Q2 | 「系統」對應實體? | ✅ compliance.information_systems(既有資訊系統表),匯入時與此表鉤稽 |
| Q3 | docx parser 是否同步擴充 devices / information_systems? | ✅ 本期不擴充,列入「最後統整優化清單」,Phase 2 完工後再處理 |
| Q4 | odt 格式本期是否要做? | ✅ 要做 — docx / pdf / odt 三種可讀格式 + OSCAL JSON / XML / YAML 三種結構化格式 |
| Q5 | SSP 匯出來源? | ✅ 「合規資源庫」與「專案 SSP 版本」兩邊都要 — 矩陣詳見 §5.1 |
| # | 問題 | 決策 |
|---|---|---|
| Q6 | Excel 預覽是否左右比對? | ✅ 不做左右比對 — 單欄式預覽 + 編輯介面即可 |
| Q7 | Excel 匯入流程? | ✅ 對齊 docx parser — create 模式(新建 MF)+ update 模式(補資料到既有 MF)雙模式,編輯 / TTL / 確認流程一致 |
| Q8 | 控制項 / AO 等 unmatched 行為? | ✅ 對齊 docx + 加 inline 新建 — 標 unmatched 後 user 可選 (a) 選現有 (b) 純文字保留 (c) 預覽頁面直接 inline 輸入新建 三種 |
| # | 問題 | 決策 |
|---|---|---|
| Q9 | Excel 樣板要 framework 一份還是通用? | ✅ 通用結構 — 一份 multi-sheet 樣板,控制項 sheet 動態依據 module_frame 的 framework 預填 |
| Q10 | SSP 匯出 docx 樣板? | ✅ 通用,先用 CMMC 當樣板 — 後續若法規資料差異大再抽象化 |
| Q11 | 既有 Excel 匯入(只匯現況)是否保留? | ✅ 保留,移到批次維護「現況說明」功能下;新版定位是「匯入完整資料」,跟舊版定位不同 |
| # | 議題 | 處理方向 |
|---|---|---|
| N1 | OSCAL JSON / XML / YAML 序列化的完整度 | jedi-oscal 既有 yaml mapper 是否覆蓋 SSP 全部欄位?實作前要先盤點缺哪些 mapper |
| N2 | Excel 下拉選單在資料量大時的效能 | named range + 隱藏 lookup sheet 處理;上千筆以下可直接列舉 |
| N3 | inline 新建 device / information_system 的權限檢查 | 需確認匯入者是否有建立這些實體的權限(manager / auditor 角色檢查) |
| N4 | 專案 SSP 版本匯出時,要不要跨多 AP round 合併 | 預設匯出當前最新版本;若要跨 round 比較,列為 follow-up |
| N5 | 既有表擴充欄位細節(v4 校正) | 9 個新欄位的 nullable / index / OSCAL 屬性對應 — 進 SDD 階段定(部分已在 §2.2 草擬) |
| v4 已 obsolete:v3 主張廢棄既有表是誤判,v4 改成擴充既有表 | ||
| N7 | A0 在 OSCAL 寫入 race(v3) | confirm 時:先寫 tenant 表(device)→ 寫鏡像表(含 soft FK)— 要在同一個 @transaction scope 內,避免半寫狀態 |
✅ 已 resolved:只補 scope_type='ssp' + scope_id,不轉 implementation_type;沿用 hardware 不引入 inventory-item 重複概念 |
||
| N9 | 表名語意爭議(v4) | 表名 system_security_plan_system_implementations 含 ssp 前綴但要服 module_frame — rename / 不動 / view alias 三方案 brainstorm 待決 |
| N10 | 既有 responsible_party 欄位後續(v4) |
既有純字串欄位有資料、不鉤 oscal_parties.uid;新功能改用 oscal_responsible_parties(polymorphic);既有 column 暫保留標 deprecated |
| 風險 | 影響 | 緩解 |
|---|---|---|
| 鉤稽邏輯複雜度高(5 種實體、多 key match + 寫入兩層 tenant + OSCAL mirror) | 開發時間翻倍、UX 設計痛苦 | 先把 docx parser 既有 party / org-unit match 抽成共用服務(A3),新領域複用;A0 把 mirror 表基礎打穩再做寫入 |
| A0 既有表擴充欄位定錯(v4 校正) | 後續 A4 / A5 / B5 全部要回改 | A0 SDD 階段先把 OSCAL 規格欄位列清楚再下手;既有 jedi-oscal stack 都要同步擴充 |
| A0 破壞既有 caller(v4 新增) | project_device_mapping_service / ssp_versioning_service regression |
A0 完成後跑既有 caller 的 integration 測試;ALTER TABLE 用 ADD COLUMN 不改既有欄位語意;nullable 化既有 system_security_plan_id 要驗證所有 caller 都接受 null |
| 140 筆既有資料 migration 出錯(v4 新增) | 既有 hardware 紀錄遺失或錯標 | Migration 加 transaction + 先 SELECT count 對帳;migration 完成後 SELECT COUNT(*) WHERE scope_type='ssp' 驗證仍 140 筆 |
| Excel 結構變動成本高(樣板改一次,parser + UI 都要動) | 後續維護負擔 | A1 樣板定版前先跟使用者(顧問)確認 sheet 結構,避免反覆改 |
| docx 樣板渲染品質(中英文混排、表格樣式) | 客戶交付品質直接影響業務 | B1 階段先做 PoC,跟既有 system-design DOCX 模式對齊 |
| docx parser 與 Excel parser 雙系統不一致(同樣資料兩種匯入路徑可能行為不同) | 維運痛苦、bug 散落 | 鉤稽 / 寫入邏輯抽 common 層,parser 只負責格式解析;A3 抽 matcher 共用 |
| OSCAL UUID 引用一致性(v3 新增) | implemented-requirements 引用 inventory-item UUID 對不上 | 既有表 uid 已有 unique constraint;寫入時用 transaction scope 確保鏡像 UUID 與 control_impl 引用同步 |
| 既有 Excel 匯入(舊版)使用者習慣 | 切換成本 | A 系列完成前舊版繼續可用,A5 上線時提供 migration 提示 |
| v4 已 obsolete — 不建新表,沒雙軌問題 | — |
| 項目 | 來源 |
|---|---|
| docx parser 擴充到 devices 鉤稽(寫入鏡像表 implementation_type='hardware') | Q3 |
| docx parser 擴充到 information_systems 鉤稽(寫入鏡像表 implementation_type='component') | Q3 |
| Excel / docx parser 共用 matcher 反向同步(如果 A3 抽得不夠乾淨) | A3 衍生 |
| 跨 AP round 的 SSP 匯出差異比對 | N4 |
| Framework-specific docx 樣板抽象化(如果出現 ISO 27001 / NIST 800-53 客戶) | Q10 |
既有 responsible_party (varchar) 欄位資料遷移到 oscal_responsible_parties |
N10 |
raymond 確認這份理解版本後,按 docs/claude/feature-development-workflow.md 進入:
docs/features/FR-011.2-2605-ssp-import-export-phase2/raw-requirement.md| 既有 feature | 路徑 | 關聯 |
|---|---|---|
| SSP Doc Parser v2 | docs/features/FR-022-2604-ssp-doc-parser/ |
鉤稽邏輯、UI flow、parse_job model 全部可複用 |
| SSP Update Diff | docs/features/FR-025-2605-ssp-update-diff/ |
匯入後若要 diff 與 module_frame 既有資料差異,可對齊 update diff 的 side-by-side UI |
| Module Frame Template Defaults | docs/features/FR-018-2604-module-frame-template-defaults/ |
控制項 / AO defaults 的寫入 model 已存在,匯入直接寫這層 |
| SSP Document Pool | docs/features/FR-010-2603-ssp-document-pool/ |
參考程序書 pool + mapping 機制已存在,Excel 匯入要對齊 |
| Compliance Framework PDF Import v2 | docs/features/FR-024-2605-compliance-framework-pdf-import-v2/ |
框架匯入跟 SSP 匯入是不同層次(前者建框架 / 後者填內容),但 UI 模式可參考 |