FR-037 · 2026-06-10 · 只盤點不實作

OSCAL 模型 × DB Schema 必填欄位盤點

以 NIST OSCAL 5 份官方 JSON schema 的 required 為權威,逐欄位比對我們 oscal.* ORM,找出缺漏的必填物件 / 欄位,並回答 import 類型欄位的解法。供下一輪 table 調整一次到位。

比對基準 Catalog · Profile · SSP · AP · AR + POA&M 來源 docs/reference/oscal_model_schemas/ + NIST 概念頁 對象 jedi-oscal ORM + compliance.poams arc relates to FR-028 / FR-036

總覽一句話結論

Catalog / Profile 的必填欄位幾乎全到位;缺口集中在 SSP(實作層)與 AR(評估層),外加跨模型的 back-matter 大洞。「一定必填且完全缺」其實很少——只有 3 條,加上 6 條「欄位在但約束錯」。其餘多屬「不啟用該功能就不違規」的條件式必填。

3
Tier A · 一定必填、完全沒有
6
Tier B · 必填但約束 / 詞彙錯
7
Tier C · 條件式必填結構缺
有解
import 欄位 · 多數零動表
嚴重度圖例:🔴 阻擋有效匯入/匯出 🟠 必填但可延後/mapper 補 🟡 fidelity 損失 ✅ 已到位

§0必填欄位缺失速查(required-only)

必填要分「一定必填」與「條件式必填」——差別決定要不要補。

TIER A一定必填、完全沒有(沒表沒欄位)← 真正的硬缺口
模型缺的必填必填理由
SSPinformation-type 子樹
title / description;categorization.system;C/I/A impact.base
system-characteristics 必填 system-information → 必填 information-types[],一路必填(FIPS 199 分類)
SSPcontrol-implementation.descriptioncontrol-implementation 是 root 必填,其 description 必填;我們無 header 列描述
ARresult.descriptionresult 必填,description 必填;我們只有 remarks
TIER B一定必填、欄位在但約束錯(nullable / 詞彙)← 改 DDL 或值域就好
模型欄位問題
SSPssp_system_characteristics.status值 active/archived ≠ OSCAL state(operational / under-development / under-major-modification / disposition / other)
SSPssp_components.status / .descriptionnullable,OSCAL component 兩者必填
ARassessment_result_datas.title / .started_atnullable,OSCAL result.title / start 必填
ARassessment_result_findings.titlenullable,OSCAL finding.title 必填
APassessment_plan_tasks.task_type被 manual/automated/hybrid 占用,OSCAL task.type(milestone/action) 等於沒存
Catalogcatalog_control_parts.prose反向:我們 NOT NULL 比 OSCAL 嚴(part.prose 其實選填),會擋匯入
TIER C條件式必填(assembly 選填,一旦用就必填子欄位)← 看 conformance 目標
模型結構一旦使用即必填
SSPby-componentcomponent-uuid / uuid / description / implementation-status.state
SSPsystem-user + authorized-privilegeuser.uuid;title + functions-performed
SSPleveraged-authorizationparty_uuid / date_authorized (欄位在但 nullable)
SSPset-parameter / diagramparam-id + values;diagram.uuid
ARfinding.targettype / target-id / status / implementation-status.state
ARobservation / riskobservation: uuid/description/methods/collected;risk: uuid/title/description/statement/status
POA&Mpoam-itemtitle / description
重點:「一定必填且完全缺」只有 Tier A 3 條 + Tier B 6 條約束。Tier C 不啟用該功能就不算違規,做不做取決於產品 conformance 目標(見 §待決策)。

§6.3import 類型欄位 — 有解

三個必填 import 都是 OSCAL 跨文件參照(href = URI 指向另一份 OSCAL 文件)。

OSCAL 必填我們存的型別
SSP import-profile.hrefssps.profile_idint FK → profiles
AP import-ssp.hrefassessment_plans.ssp_idString(36) 存 stringified int,無 FK
AR import-ap.hrefassessment_results.assessment_plan_idint FK → assessment_plans
關鍵事實:每張目標表都有 uid(UUID v4),所以 內部 id → 目標.uid 永遠可解析
profile_id / ssp_id / ap_id→ 查 →目標.uid→ 合成 →href="#<uuid>"

情境 1內部文件互參(我們自己產的 OSCAL)

匯出時 id → 查目標 uid → 合成 href="#<uuid>"

  • 零動表,純 mapper 工作
  • 內部 round-trip 完全可行

情境 2匯入外部 OSCAL(target 不在我們 DB)

int FK 存不了「我們沒有的文件」的 href(外部 URL / 對方 uuid)。

  • 三個 root 表加 import_href(String) + optional import_remarks
  • 否則來源在匯入即丟失
順帶技術債:assessment_plans.ssp_id 現存 stringified int(memory feedback_ap_ssp_id_varchar_stringified_int)。VARCHAR(36) = UUID 長度,正好可改存 ssp.uid,語意直接貼 OSCAL href、匯出免查表——但屬 breaking 資料遷移,單獨評估。
結論:import 欄位有解、不一定要動表。只求內部 round-trip 走 mapper id→uid(0 動表);要支援匯入外部文件 / 完整保真才加 import_href(+remarks),並建議 ssp_id 改存 uuid。

§3SSP 實作層 — 缺口最深

FR-036 正要動這批 ssp_* 表 → 結構缺口最划算一次補。

SSP 必填缺口明細

OSCAL 結構必填欄位 / 問題嚴重度我們的現況
information-type + C/I/A impact
FIPS 199 分類
title / description / categorization.system / impact.base🔴完全沒表沒欄位
control-implementation.descriptionroot 必填的 description🔴無 header 列描述
system-characteristics.statusstate 詞彙🔴status 值 active/archived 不對
component.status / .description必填卻 nullable🔴ssp_components.* nullable
security-impact-levelC/I/A 三軸 objective🟠只有單一 security_sensitivity_level
by-component(+ provided/inherited/satisfied)component-uuid/uuid/description🟠只到 requirement+objective,無元件層
system-user + authorized-privilegeuser.uuid;title+functions-performed🟠只有單一 owner_uid 純量
set-parameter(三層)param-id + values🟠參數值無法 round-trip
leveraged-authorizationparty_uuid / date_authorized🟠欄位在但 nullable
diagrams(auth-boundary / network / data-flow)diagram.uuid + description🟡沒 diagram 表
system-id 陣列 + identifier-typesystem-id.id🟡system_identifier 單值
⚠️ 遷移風險:ssp_inventory_item_components 仍 FK 到 legacy 表 oscal.ssp_system_implementation_items,與新 ssp_inventory_implemented_components 並存(mid-migration)。動 inventory↔component join 前先確認哪張是 live。

§4評估層 — AP / AR / POA&M

Assessment Plan

OSCAL 必填狀態
uuid / metadata / task.uuid / task.title
task.type(milestone/action)
欄位被 manual/hybrid 占用
🔴
import-ssp.href
存 stringified int
🟠
reviewed-controls
攤平有損
🟠

Assessment Results

OSCAL 必填狀態
uuid / metadata / finding.uuid / .description
result.description🔴
result.title / .start(nullable)🔴
finding.title(nullable)🔴
finding.target + implementation-status🔴
observation(整段)🔴
risk(status/characterization/response/log)🔴
import-ap.href(存內部 FK)🟠

POA&M(compliance.poams 扁平單表 vs OSCAL 獨立模型)

OSCAL POA&M必填compliance.poams
root uuid + metadataR 無文件根 / metadata,只有扁平列
poam-item.uuidR uid
poam-item.titleR 無 title 欄
poam-item.descriptionR~ remediation_plan(語意是 remediation 非 description)
related-findingsopt~ ar_finding_id 單一,OSCAL 允許多筆

§2控制層 — Catalog / Profile 基本健康

Catalog 所有必填到位

catalog / group / control / part 的必填欄位都有對應。

  • 唯一要修:catalog_control_parts.prose NOT NULL 比 OSCAL 嚴(part.prose 選填)→ 放寬 nullable
  • 非必填缺口:props/links、子控制項巢狀、parameter 的 constraints/guidelines(皆 OSCAL optional)

Profile imports 需注意

是「已解析的選取控制項清單」,存結果不存規則。

  • profile.imports 是 root 必填,現壓成單一 catalog_id + 扁平 profile_controls → 匯出保證 imports[] 非空
  • merge / modify / set-parameters 皆 OSCAL optional,未建模

§5跨模型共用層

Metadata 的 4 個 root 必填(title / last-modified / version / oscal-version)全到位;缺口是幾個結構性大洞。

OSCAL 構件必填嚴重度狀態
back-matter → resourceresource.uuid;rlink.href;base64.value;citation.text🔴完全未建模。document_id 是原始檔 blob FK,與 OSCAL resource 無關 — 整體最大結構洞,附件/citation/嵌入證據無法 round-trip
hash(rlink 內)value, algorithm🟠未建模(依附 back-matter)
document-ididentifier🟠metadata / resource 的 document-ids[] 未建模
revisionversion(逐筆)🟡oscal_metadatas.revision 是單一純量,存不了歷史清單

§7待決策(留 implementation-plan)

1目標 conformance 等級:完整 OSCAL round-trip(含 risk/observation/back-matter)還是內部資料完整 + 主要必填?決定 Tier C 那批大結構做不做
2分期:Tier B 約束/詞彙可獨立先發低風險 migration;SSP 群建議與 FR-036 動表同期;AR 群 + back-matter 規模大宜獨立 phase
3與 FR-036 界線:FR-036 管「MF defaults 折進樣板 SSP」;本 FR 管「SSP 等表 OSCAL 欄位補齊」。兩者都動 ssp_*,FR-036 結構先定、本 FR 補在其上
4jedi-oscal 發版:OSCAL ORM 全在套件,補欄位=改套件 → path-dependency dev、user 明示才發版
5三環境零丟失 migration:新增 NOT NULL 給 default 或先 nullable 回填再收緊;詞彙改值要資料轉換;dev→stg→poc 漸進