狀態:需求分析(Phase 0/1)· 待 user review 後進入設計/計畫 來源:
draft-requirement.md+ PM 教材OSCAL_稽核生命週期_PM教材.html+ 現況盤點(jedi-oscal / BE / FE / v2 schema) 撰寫日:2026-06-14
把現在「只套用 OSCAL 概念、底層大量自定義欄位、用 AP 兼當稽核輪次」的實作, 重寫成「正式 OSCAL v1.2.2 物件模型落地、三層 clone/snapshot 邊界清楚、稽核輪次獨立成 project_audit_rounds」的專業 OSCAL GRC 系統。 範圍橫跨三個 repo:jedi-oscal-v2(全新套件)+ 主專案 BE + 主專案 FE。
盤點現有 jedi-oscal 0.0.22 + 主專案後,確認以下結構性問題(這些是「重練」而非「重構」的理由):
| # | 問題 | 現況 | 影響 |
|---|---|---|---|
| P1 | 大量自定義欄位偏離 OSCAL | SSP 有 template_module_frame_id/is_template/group_id/version_no;AP task 把 assessment-methods 壓成 JSON;ResponsibleParty 是無 uid 的 link record |
無法無損匯出標準 OSCAL、跟外部工具不互通、欄位語意混亂 |
| P2 | 用 AP 兼當「稽核輪次」 | 1 AP = 整個稽核 arc,多輪靠 assessment_result_datas.run_no 疊加 |
輪次語意藏在 AR 子表,狀態機綁在 AP 上,二次稽核/改善覆核難建模(user 明指「這設計是不對的」) |
| P3 | catalog 階層與 AO 落地不標準 | 舊 catalog_control_assessments 用自定義 assessment_method 欄;AO 不是用 OSCAL part 表達 |
跟 NIST SP 800-53A 的 part/assessment-objective 結構對不上 |
| P4 | Profile 只存 include 旗標、靠 runtime join 回母表 | profile_controls.include |
PM 教材明列地雷:「不能只存 id 即時 join 回會變動的母表」→ 母版改動會抽換進行中的工作 |
| P5 | 三層 clone 邊界不乾淨 | MF defaults 與 template SSP 兩套並存(FR-036 才剛退役 *_defaults);snapshot 概念散落 | 「單一真相來源」不成立,改一處對不齊其他 |
| P6 | AR 缺總結層、AP 幾乎不存在 | AR 只有逐條 verdict;AP 前端只有列表沒有編輯畫面;無系統風險總結 | 稽核生命週期的 Phase 3(稽核員寫 AR/findings/risks)斷掉 |
PM 教材 §市場定位:Phase 3(外部稽核員寫 AR/findings)是市場空白區,多數產品到此斷掉 —— 這正是本次重設計要補的核心價值。
依 PM 教材 §09「三層架構與 clone 邊界」,目標是把控制集分三層存放,每層邊界都做一次「複製並固定」,讓上游改動不波及下游進行中的工作:
第 1 層 · 合規框架(母版,很少改)
catalog 母版 ── group→control→part(AO) 樹 · 永不硬刪 · 改版=新增 framework_version
profile ── 從 catalog 挑控制 + 指向特定 framework_version
│ 解析 + clone(建立資源庫時)
▼
第 2 層 · 合規資源庫(公版範本,稽核顧問維護,共用)
catalog 副本(已挑選、已固定)+ 公版 profile + 公版 SSP 範本
│ 專案成立 → clone(脫鉤公版)
▼
第 3 層 · 專案(這個專案自己的,可編輯)
專案 catalog 副本 ★單一真相來源
SSP / AP / AR / POA&M ── 全部 import 指向同一份控制副本,不互相複製
│ 啟動稽核 → snapshot(再凍結一份)
▼
凍結的 SSP 快照 + 控制定義 ── 稽核判定的不變依據
四個 clone/snapshot 邊界(每個都是「複製並固定」):
鐵則(PM 教材明列地雷):副本要存「內容」或指向「永不原地改的版本化控制」,不能只存 id 即時 join 回會變動的母表。這直接否定現有 P4 的 profile 做法。
~/Projects/Jedicogy/module/jedi-python-package/jedi-oscal-v2/,不在舊 jedi-oscal 下改,進入 v2.0。feedback_hybrid_soft_ref_asset_pattern / feedback_jedi_package_extraction_pattern)。feedback_jedi_package_dev_path_first),feature 完成才正式 bump + 推 Nexus(feedback_jedi_package_publish_flow)。docs/features/FR-037-2606-oscal-schema-gap-audit/oscal-catalog-and-roots-schema-v2.sql(42 表、~650 欄、逐欄中文 COMMENT)已是 OSCAL v1.2.2 七大 model 的高保真關聯式落地,AP/AR/POA&M 都已在內。對齊度極高。但落地前必須補三塊:
| 缺口 | 說明 | 處置 |
|---|---|---|
| G1 framework / framework_versions 完全沒有 | v2 SQL 不含這兩表(grep 零命中);FR-038 §23-24 要 oscal_frameworks→frameworks、oscal_framework_versions→framework_versions;§26 要 catalogs 對應一個 framework_versions |
新增 frameworks / framework_versions 兩表 + catalogs.framework_version_id FK |
| G2 schema name | v2 SQL 直接 CREATE SCHEMA oscal |
已定(D1):直接 drop 現有 oscal 重建,schema name 維持 oscal,不走 oscalv2 過渡。dev DB 已備份;正式環境遷移走 D7 |
G3 缺 project_audit_rounds |
user 提出的新輪次表(取代「AP 當輪次」),v2 SQL 沒有(它只管純 OSCAL 物件) | 在主專案 compliance schema 新增(見 3.3) |
v2 schema 已知刻意取捨(非缺陷):mapping model 裁剪不實作;AP 的 terms-and-conditions/assessment-subjects/assessment-assets/local-definitions 暫 deferred;深層宣告式 leaf 留 JSONB。這些可在後續迭代補。
project_audit_rounds(輪次主檔,取代「AP 當輪次」)這是本次最大的流程架構變更。輪次從「藏在 AP/AR 子表的 run_no」升級成獨立 first-class 物件:
id BIGSERIAL PK
project_id int NN FK→compliance.projects
name varchar(255) NN -- 輪次名稱
round_no int NN -- 輪次編號(1,2,3…)
round_type enum NN -- initial / close-out(覆核) / surveillance(年度抽樣) ← PM 教材 §08 round_type 分流
status enum NN -- 7 態(見下方狀態機)
parent_round_id int NULL FK→project_audit_rounds.id -- 複驗的母輪;NOT NULL ⟺ round_type=close-out(initial/surveillance 為 NULL)
ssp_id int NULL FK→oscal.system_security_plans -- 凍結快照,啟動稽核 SSP 鎖定時才填
ar_result_id int NULL FK→oscal.ar_results -- 該輪對應的 AR result(D2:1 round ↔ 1 ar_results)
start_at / end_at datetime
created_at / updated_at / created_user / updated_user
狀態機(Q4 定案 = 7 態 + 覆核開新 round):
尚未開始
─[PM 建立輪次]──────────────▶ 專案規劃中 (受評方持續編 living SSP)
─[PM 啟動稽核, snapshot SSP]─▶ 稽核規劃中 (稽核員補 AP 草稿:subjects/行程/方法)
─[稽核員 開始稽核]──────────▶ 稽核進行中 (稽核員填 AO 全量判定 + finding + risk)
─[稽核員 AR 定版]──┬─ 無 not_met ─────────▶ 結案(直接過,無需整改)
└─ 有 not_met ─────────▶ 改善計劃中(系統自動生 POA&M)
改善計劃中 ─[執行人員整改完 + 更新 living SSP]─▶ 待複驗
待複驗 ─[稽核員 發起覆核]──▶ 自動開新 close-out round(稽核規劃中, parent_round_id=本輪)
parent_round_id 回頭關閉母輪 POA&M → 母輪轉「結案」。輪次 ↔︎ OSCAL 物件關係(決策 D2 已定 = OSCAL 官方做法):
parent_round_id 串:initial → close-out → close-out…;surveillance 另起)ssp_id)ar_results,往後追加、舊的不改(PM 教材「在原 AR 後追加、第一次不改」)ar_results 自帶 narrowed reviewed-controls(OSCAL-faithful,範圍從 parent_round_id 母輪的 not_met findings 推導),UI 呈現成「該輪的計畫」| 面向 | 舊 | 新 |
|---|---|---|
| 主檔 | oscal.oscal_frameworks |
oscal.frameworks(新 schema 重建) |
| 版本 | oscal.oscal_framework_versions |
oscal.framework_versions(新 schema 重建) |
| catalog 關聯 | catalog 自由存在 | catalogs.framework_version_id 綁定(一版本一 catalog) |
| 匯入 | PDF/Excel → 自定義 catalog 結構 | PDF/Excel → 標準 catalog/group/control/part(AO) 結構 |
新定位:公版稽核範本,由稽核顧問針對各框架設計維護;客戶有需求時拿來成立專案。 由三個 OSCAL 物件組成:catalog(控制集副本)+ profile(baseline 定義)+ ssp(公用範本)。
新建資源庫流程:
framework_versions → 把對應 catalog snapshot 一份給該資源庫(邊界①)| 面向 | 舊 | 新 |
|---|---|---|
| 起點 | MF defaults + template SSP(兩套並存) | 最新發布的資源庫三件組,clone 一份脫鉤(邊界②) |
| 寫入 | POST /oscal/projects/start 單一 @transaction 寫 21 表,AP/AR 當場建好 |
專案成立只 clone catalog/profile/ssp + 建 project 主檔;AP/AR 延到輪次啟動才建 |
| 控制集 | AP controls snapshot | 專案 catalog 副本 = ★單一真相來源,SSP/AP/AR/POA&M 全 import 指它 |
「任務執行 / My Jobs」= 受評公司「準備 SSP / 收證據」的工作(Phase 1-2,稽核前)。
project-start 為每個 AP task 建 workflow 的邏輯要改成「為 SSP 控制項建 workflow」,且移到專案成立階段。project_audit_rounds.ssp_id,此後該快照不可改;living SSP 仍可繼續往前改(PM 教材「考試交卷」比喻)。現況:FE 只有 AP 列表、無編輯畫面;概念幾乎不存在。需全新設計。
依 PM 教材 §04,AP 回答四件事(只有①必填,②③④是稽核員臨場專業判斷可省略):
| # | 內容 | OSCAL | 必填 | 系統可自動帶 |
|---|---|---|---|---|
| 1 | 查哪些控制 | reviewed-controls |
✅ | 由 SSP 快照的適用性(SoA)表自動生草稿 |
| 2 | 會碰哪些東西(人/設備/服務/地點抽查) | assessment-subjects |
✗ | 從 SSP 快照資產清單勾選 |
| 3 | 什麼時候查 | tasks.timing |
✗ | 稽核員補行程 |
| 4 | 怎麼查(看文件/訪談/實測 + 步驟) | assessment-methods | ✗ | 稽核員補 |
關鍵設計:按「開始稽核」系統自動產一份 AP 草稿(標題+對著哪份 SSP 快照+查哪些控制都有現成資料),稽核員再補日期與抽查名單。PM 不用從白紙開始。
D3 已定:本期補
assessment-subjects(抽查名單,AP 核心 UX)相關表;assets(工具/團隊)後續。v2 schema 的ap_reviewed_controls/ap_local_objectives/ap_assessment_activities/ap_tasks已備,subjects 需補表。
現況:逐「控制項」填 verdict。需補 PM 教材 §05 的三層鏈 + 總結,並把判定粒度下沉到 AO 層(Q3 定案 = OSCAL 官方做法):
observation(看到什麼,好壞都記)→ finding(每個 in-scope AO 一筆 met/not_met/pending)→ risk(稽核員手動組,沒過的進整改)
| 調整項 | 說明 | 對應 |
|---|---|---|
| A1 AO 層全量判定矩陣(Q3 定案) | 判定下沉到 AO/objective 層:每個 in-scope AO 一筆 finding(met/not_met/pending),不是只記沒過的,也不是只到控制項層。OSCAL finding.target.type="objective-id"、NIST 800-53A determination statements。UI 以控制項為導覽單位、展開填各 AO(控制項摺疊緩解資料量) |
PM 教材 §08 全量判定矩陣;finding 掛 catalog_control_parts(AO) |
| A2 系統風險總結(Q2 定案 / 新) | 稽核員手動建 risk,勾選哪幾條 finding 組成這個風險(多對多),風險等級(low/medium/high/critical)在 risk 層由稽核員判定 | v2 assessment_risks + assessment_findings + finding↔︎risk 多對多關聯表;目前完全沒有,需新畫面 + 後端 |
| A3 observation 引用證據不複製 | ar_evidences → job_evidence_id 引用 |
PM 教材標「教科書級」,沿用 |
| A4 AR 定版 | 稽核員寫完即定版,不再改,每輪往後追加一筆 ar_results |
狀態機 |
現況已完整(列表/詳情/狀態轉換/remediation)。依 PM 教材調整:
| 調整項 | 說明 |
|---|---|
| PM1 FK 指回不複製 | poam-item 是「封面」(哪個缺失/為何改),執行細節在連著的 risk;DB 用 FK 指回 AR,只在匯出 OSCAL 時才填實內容 |
| PM2 整改計畫 + milestone + assignee | OSCAL risk → remediations[](response) → tasks[] 三層忠實落地(B 方案):assessment_remediations(整改計畫)+ poam_milestones(里程碑,每個各別負責人,跨部門 M1 歸 IT、M2 歸採購可拆)。milestone 掛在 response 下而非直接掛 risk,匯出 OSCAL 1:1 免合成 wrapper |
| PM3 deviation / risk_accepted | ISO 風險接受(Clause 6.1.3)需 risk_accepted 分支 → D5 已定屬 ISO,本期 follow-up,先做穩 CMMC 五態 |
| PM4 180 天期限 | CMMC 限 180 天,UI 提醒 |
依 PM 教材 §07 完整流程:
round_type=close-out):重新 snapshot 當下 SSP(PM 教材標:沿用舊快照是 bug)→ 範圍縮小只查那幾條 → 在原 AR 後追加第二次 results結案判斷:所有該輪 POA&M closed → round 可結案。年度查核 = 再走一輪(round_type=surveillance)。
| UI 資料 | OSCAL 落點 |
|---|---|
| 受評標的 | system-characteristics |
| 人員 / 單位 | parties + roles |
| 證據 | by-component.links → back-matter |
| 實施計劃 | props(planned 日期) |
| 實作狀態 | props(implementation-status) |
| 控制實作描述, SoA | implemented-requirement(一條控制一筆):├ props.applicability ← SoA 適用性 ├ props.inclusion-justification ← SoA 理由 ├ props.implementation-status ← 實作狀態 └ statements[].by-components[]:description ← 實作描述 / links ← 證據綁定 |
SoA 釐清(PM 教材 §02):SoA 不是 SSP 之前的獨立步驟,而是 SSP 的一部分(每條控制旁標「適不適用+理由」)。要分清兩件事:「適不適用」(標不適用→不準備證據、跳過查驗、但不跳過審查理由、永遠不會變缺失)vs 「做了沒」(已完成/部分/規劃中/還沒做→標還沒做=缺口=會開不符合)。
| 區塊 | 現況完整度 | 本期變動 |
|---|---|---|
| 合規框架 | ✅ 100% | 不大改(底層 schema rename,API 對齊) |
| 合規資源庫 | ✅ 100% | 不大改(語意調整成三件組,匯入落地改 v2 schema) |
| 專案列表/建立 | ✅ 100% | 不大改 |
| 專案總覽 | ✅ 100% | 不大改 |
| 專案規劃(SSP) | ✅ 100%(7 tabs) | 不大改(OSCAL 落點對齊;新增「啟動稽核→snapshot」動作) |
| 任務執行 | ✅ 100% | 不大改(綁定點後端從 AP task 改為 SSP 控制項,FE 畫面不動,Q1) |
| AP 稽核計畫 | ⚠️ 20%(只列表) | 全新畫面:AP 草稿生成 + reviewed-controls + 抽查名單(subjects) + 行程 + 方法 |
| AR 稽核結果 | ⚠️ 50%(只逐控制項 verdict) | 中改:控制項導覽 + AO 層全量判定矩陣 + 系統風險總結(稽核員手動組 risk、多對多關聯 finding、等級在 risk 層) |
| POA&M | ✅ 100% | 小改:milestone+assignee、180 天告警、從這裡發起覆核 round(deviation/risk_accepted 屬 ISO,本期 follow-up) |
| 輪次切換 | 現用 run_no | 改對應 project_audit_rounds(1 round ↔︎ 1 ar_results) |
與 user 判斷大致一致:合規框架→任務執行不大改;AP 全新、POA&M 小改。唯一修正:AR 從「小改」上修為「中改」——因 Q3 定案判定下沉到 AO 層(OSCAL 官方全量矩陣),畫面要從控制項展開到 AO。
| ID | 決策 | 結論 / 選項 | 備註 |
|---|---|---|---|
| D1 ✅ | schema 過渡策略 | 已定:直接 drop oscal 重建(dev DB 會備份) |
v2 schema 直接用 oscal(不必過渡 oscalv2);不可回頭,正式環境遷移走 D7 |
| D2 ✅ | 輪次 ↔︎ AP/AR 基數 | 已定:採 OSCAL 官方做法 = 每 round 1 筆 ar_results + 全專案 1 AP + 1 AR |
OSCAL 硬規則:AR.import-ap 單一、results[] 是官方多輪機制、每筆 result 可自帶 narrowed reviewed-controls。project_audit_rounds 一列 ↔︎ ar_results 一筆(1:1)。覆核輪「縮小計畫」折進 result 的 narrowed scope(資料 OSCAL-faithful),UI 呈現成「該輪計畫」 |
| D3 ✅ | AP assessment-subjects/assets | 已定:本期做 assessment-subjects(抽查名單),assets 後續 | 需在 v2 schema 補 assessment-subjects 相關表(目前 deferred) |
| D4 | 系統風險總結資料模型 | 用 v2 既有 assessment_risks/assessment_findings/assessment_observations,補 finding↔︎risk 關聯表 |
待 design 階段定 schema 細節 |
| D5 ✅ | 框架範圍 | 已定:本期先做穩 CMMC 流程 | ISO 專屬(risk_accepted deviation、L1⊂L2、SoA 自選排除)標 follow-up |
| D6 | source_identifier / L1⊂L2 | catalog_controls 加 source_identifier 支撐跨框架 crosswalk |
CMMC 本期可先加欄位佔位;L1/L2 合併屬 ISO 整合,follow-up |
| D7 | 舊資料遷移 | dev 直接重建(D1);正式環境(stg/poc/prod)遷移策略需另議 | 重大,上正式前必須有遷移計畫 |
依賴關係決定哪些能平行。第一波必須先收斂「契約」(schema + 套件介面 + API spec),契約定了之後三 repo 才能真正平行。
Wave 0 三項彼此相依(schema→套件→API),建議我序列做但快速,或 schema 先行、套件骨架與 API spec 平行。
契約定稿後,jedi-oscal-v2 各 model 模組可完全平行(彼此無共享狀態):
套件 path-dep 可用後:
平行策略總結:Wave 0 是序列瓶頸(契約),務必先做完;Wave 1 套件模組可開 ~5 個 agent 平行;Wave 2/3 BE/FE 可交疊。我會用 subagent dispatch(顯式 git add、各 repo 分開 commit、不切 branch)。
這份是需求分析。請 user 針對 §7 決策清單(尤其 D1 schema 策略 / D2 輪次基數 / D3 AP 範圍 / D5 是否本期含 ISO)拍板後,我再進 Phase 1 brainstorm → Phase 3 寫 design.md + implementation-plan.md(含詳細 schema、API spec、平行任務拆解到可執行顆粒)。