# FR-037 補強欄位逐條驗證表（OSCAL 出處 + 必填等級 + 資料來源）

> 供逐條核對。`required` 全部由 5 份官方 schema 程式化抽出（`docs/reference/oscal_model_schemas/*.json` 的 `required` 陣列，含 anyOf 分支），非憑記憶。

**必填等級**
- **Req**：在必填路徑上的必填欄 → OSCAL 一定要有
- **Opt\***：父層 assembly 選填，但一旦使用就必填此欄
- **Opt**：完全選填

**資料來源**：**A** 衍生/回填（資料已在或可推導）· **B** 轉換（值/約束改，資料多半已在）· **C** 全新捕捉（今天無來源，需新 UI/parser）

**出處標記**：`<schema>: <assembly>.<field>`，schema ∈ ssp / ap(assessment-plan) / ar(assessment-results) / catalog / profile / common(metadata 共用)

---

## A. import 跨文件參照（補強表 Part 1.1）

| 欄位 | OSCAL 出處 | 必填 | 來源 | 依據（schema required） |
|---|---|---|---|---|
| `ssps.import_profile` | ssp: `system-security-plan.import-profile.href` | **Req** | A | system-security-plan.required 含 `import-profile`；import-profile.required=`[href]` |
| `assessment_plans.import_ssp` | ap: `assessment-plan.import-ssp.href` | **Req** | A | assessment-plan.required 含 `import-ssp`；import-ssp.required=`[href]` |
| `assessment_results.import_ap` | ar: `assessment-results.import-ap.href` | **Req** | A | assessment-results.required 含 `import-ap`；import-ap.required=`[href]` |
| `compliance.poams.import_ssp` | POA&M: `plan-of-action-and-milestones.import-ssp.href` | **Opt** | A | POA&M root required=`[uuid, metadata, poam-items]`；import-ssp 選填（POA&M 模型不在本 5 份 schema，依 OSCAL 官方 POA&M model）|

---

## B. OSCAL 同名小欄（補強表 Part 1.2，全部 additive）

| 欄位 | OSCAL 出處 | 必填 | 來源 | 依據 |
|---|---|---|---|---|
| `oscal_props.uuid` | common: `property.uuid` | Opt | C | property.required=`[name, value]` |
| `oscal_props.group` | `property.group` | Opt | C | 同上 |
| `oscal_props.remarks` | `property.remarks` | Opt | C | 同上 |
| `oscal_links.resource_fragment` | common: `link.resource-fragment` | Opt | C | link.required=`[href]` |
| `oscal_links.text` | `link.text` | Opt | C | 同上 |
| `oscal_roles.short_name` | common: `role.short-name` | Opt | C | role.required=`[id, title]` |
| `oscal_roles.remarks` | `role.remarks` | Opt | C | 同上 |
| `oscal_responsible_parties.remarks` | common: `responsible-party.remarks` | Opt | C | responsible-party.required=`[party-uuids, role-id]` |
| `catalog_groups.group_id` | catalog: `group.id` | Opt | C | group.required=`[title]`；id=TokenDatatype「Group Identifier」 |
| `catalog_groups.group_class` | catalog: `group.class` | Opt | C | 同上；class=TokenDatatype「Group Class」 |
| `catalog_controls.control_class` | catalog: `control.class` | Opt | C | control.required=`[id, title]` |
| `catalog_control_parts.part_id` | catalog: `part.id` | Opt | C | part.required=`[name]` |
| `catalog_control_parts.ns` | `part.ns` | Opt | C | 同上 |
| `catalog_control_parts.part_class` | `part.class` | Opt | C | 同上 |
| `catalog_control_parts.title` | `part.title` | Opt | C | 同上 |
| `catalog_control_parameters.param_class` | catalog: `parameter.class` | Opt | C | parameter.required=`[]`（無必填）|
| `catalog_control_parameters.depends_on` | `parameter.depends-on` | Opt | C | 同上 |
| `catalog_control_parameters.usage` | `parameter.usage` | Opt | C | 同上 |
| `catalog_control_parameters.remarks` | `parameter.remarks` | Opt | C | 同上 |
| `ssp_system_characteristics.system_name_short` | ssp: `system-characteristics.system-name-short` | Opt | C | system-characteristics.required 不含此欄 |
| `…date_authorized` | `system-characteristics.date-authorized` | Opt | C | 同上 |
| `…network_architecture_description` | ssp: `network-architecture.description` | Opt\* | C | network-architecture 在 sys-char 為選填；network-architecture.required=`[description]` |
| `…data_flow_description` | ssp: `data-flow.description` | Opt\* | C | data-flow 選填；data-flow.required=`[description]` |
| `…security_objective_confidentiality` | ssp: `security-impact-level.security-objective-confidentiality` | Opt\* | C | security-impact-level 在 sys-char 為選填；其 required=三個 objective 全要 |
| `…security_objective_integrity` | `…security-objective-integrity` | Opt\* | C | 同上 |
| `…security_objective_availability` | `…security-objective-availability` | Opt\* | C | 同上 |
| `ssp_control_implementations.description` | ssp: `control-implementation.description` | **Req** | C | control-implementation.required=`[description, implemented-requirements]`（目前無 block-level 列，可給 default/衍生）|
| `ssp_control_implementations.control_id` | ssp: `implemented-requirement.control-id` | **Req** | A | implemented-requirement.required=`[control-id, uuid]`；＝既有 control_identifier |
| `ssp_control_implementation_objectives.statement_id` | ssp: `statement.statement-id` | **Req** | A | statement.required=`[statement-id, uuid]`；＝既有 statement_identifier |
| `assessment_result_datas.description` | ar: `result.description` | **Req** | C | result.required=`[description, reviewed-controls, start, title, uuid]`（launch_audit 沒填，可衍生）|

---

## C. 約束 / 詞彙修正（補強表 Part 2，既有欄位）

| 欄位 | OSCAL 出處 | 必填 | 來源 | 依據 / 備註 |
|---|---|---|---|---|
| `catalog_control_parts.prose` | catalog: `part.prose` | **Opt** | B | part.required=`[name]`，prose 選填 → 我們 NOT NULL **反而過嚴**，放寬 |
| `ssp_components.status` | ssp: `system-component.status` | **Req** | B | system-component.required=`[description, status, title, type, uuid]` |
| `ssp_components.description` | `system-component.description` | **Req** | B | 同上 |
| `ssp_leveraged_authorizations.party_uuid` | ssp: `leveraged-authorization.party-uuid` | **Req** | B | leveraged-authorization.required=`[uuid, title, party-uuid, date-authorized]` |
| `ssp_leveraged_authorizations.date_authorized` | `leveraged-authorization.date-authorized` | **Req** | B | 同上 |
| `ssp_system_characteristics.status`（詞彙）| ssp: `status.state` | **Req** | B | sys-char.required 含 `status`；status.required=`[state]`；值域 operational/under-development/… |
| `ssp_system_characteristics.description` | ssp: `system-characteristics.description` | **Req** | B | sys-char.required 含 `description` |
| `ssp_system_characteristics.scope_description`→NN | ssp: `authorization-boundary.description` | **Req** | B | sys-char.required 含 `authorization-boundary`；authorization-boundary.required=`[description]` |
| `assessment_result_datas.title`→NN | ar: `result.title` | **Req** | B | result.required 含 `title`（launch_audit 已寫 '稽核執行'，有值）|
| `assessment_result_datas.started_at`→NN | ar: `result.start` | **Req** | B | result.required 含 `start`（launch 寫 now，有值）|
| `assessment_result_findings.title`→NN | ar: `finding.title` | **Req** | A | finding.required=`[description, target, title, uuid]`；稽核員已填，直接設 NN |
| `assessment_result_evidences.description`→NN | ar: `relevant-evidence.description` | **Req** | B | relevant-evidence.required=`[description]` |
| `assessment_plan_tasks.task_type`（詞彙）| ap: `task.type` | **Req** | C | task.required=`[title, type, uuid]`；OSCAL type=milestone/action **今天沒存**（被 manual/hybrid 佔用）→ 需給值 |
| `assessment_result_controls.verdict`（詞彙）| ar: `finding-target.status.state` | **Req**(在 finding-target 內) | A→B | 稽核員已填 verdict(pass/fail/partial/na)；匯出需 map 到 satisfied/not-satisfied |

---

## D. 全新表 / 結構（補強表 Part 3，全部 🆕）

### SSP 層

| 欄位 | OSCAL 出處 | 必填 | 來源 | 依據 |
|---|---|---|---|---|
| `ssp_system_information_types.title` | ssp: `information-type.title` | **Req** | C | sys-char.required 含 `system-information`；system-information.required=`[information-types]` → 一路必填 |
| `…description` | `information-type.description` | **Req** | C | 同上（information-type 必填 title/description）|
| `…categorization_system` | ssp: `categorization.system` | Opt\* | C | categorizations 選填，有則 `system` 必填 |
| `…confidentiality_impact_base` / `…integrity_…` / `…availability_…` | ssp: `impact.base` | Opt\* | C | C/I/A impact 選填，有則 impact.required=`[base]` |
| `ssp_system_users.uid` | ssp: `system-user.uuid` | Opt\* | C | system-implementation.users 選填；system-user.required=`[uuid]` |
| `ssp_authorized_privileges.title` | ssp: `authorized-privilege.title` | Opt\* | C | authorized-privilege.required=`[functions-performed, title]` |
| `…functions_performed` | `authorized-privilege.functions-performed` | Opt\* | C | 同上 |
| `ssp_by_components.component_uuid` | ssp: `by-component.component-uuid` | Opt\* | C | by-components 選填；by-component.required=`[component-uuid, description, uuid]` |
| `…uuid` / `…description` | `by-component.uuid` / `.description` | Opt\* | C | 同上 |
| `…implementation_status` | ssp: `implementation-status.state` | Opt\* | C | implementation-status.required=`[state]` |
| `ssp_set_parameters.param_id` / `…values` | ssp: `set-parameter.param-id` / `.values` | Opt\* | C | set-parameters 選填；set-parameter.required=`[param-id, values]` |
| `ssp_diagrams.uid` | ssp: `diagram.uuid` | Opt\* | C | diagrams 選填；diagram.required=`[uuid]` |
| `ssp_component_responsible_roles.role_id` | ssp: `responsible-role.role-id` | Opt\* | C | responsible-roles 選填；responsible-role.required=`[role-id]` |

### AR 層

| 欄位 | OSCAL 出處 | 必填 | 來源 | 依據 |
|---|---|---|---|---|
| `assessment_result_finding_targets.target_type` | ar: `finding-target.type` | **Req** | C | **finding.required 含 `target`**；finding-target.required=`[status, target-id, type]` → finding 一定要 target |
| `…target_id` / `…status_state` | `finding-target.target-id` / `.status` | **Req** | C | 同上（status→state 必填）|
| `…implementation_status` | ar: `implementation-status.state` | Opt | C | finding-target 內 implementation-status 選填 |
| `assessment_result_observations.uuid/description/methods/collected` | ar: `observation.*` | Opt\* | C | result.observations 選填；observation.required=`[collected, description, methods, uuid]` |
| `assessment_result_risks.uuid/title/description/statement/status` | ar: `risk.*` | Opt\* | C | result.risks 選填；risk.required=`[description, statement, status, title, uuid]` |

### 共用層 / 控制層

| 欄位 | OSCAL 出處 | 必填 | 來源 | 依據 |
|---|---|---|---|---|
| `oscal_resources.uid` | common: back-matter `resource.uuid` | Opt\* | C | back-matter 選填；resource.uuid 必填（依 OSCAL metadata schema）|
| `oscal_resources.rlink_href` | `resource.rlinks[].href` | Opt\* | C | 有 rlink 才必填 href |
| `oscal_resources.base64_value` | `resource.base64.value` | Opt\* | C | 有嵌入檔才必填 |
| `oscal_resources.citation_text` | `resource.citation.text` | Opt\* | C | 有 citation 才必填 |
| `oscal_hashes.value` / `.algorithm` | common: `hash.value` / `.algorithm` | Opt\* | C | 用到 hash 才必填二者 |
| `oscal_document_ids.identifier` | common: `document-id.identifier` | Opt\* | C | 用到 document-id 才必填 |
| `oscal_revisions.version` | common: `revision.version` | Opt\* | C | revisions 選填，每筆必填 version |
| `profile_imports.*`（import_catalog / include_all / …）| profile: `import` | **Req**(結構) | C | profile.required 含 `imports`；import.required=`[include-all, include-controls]`（擇一）|
| catalog props/links/子控制項/param constraints | catalog: `control.props/links/controls` 等 | Opt | C | 皆 OSCAL optional；parser 目前丟棄 |

---

## E. FR-036 已套用欄位（非 OSCAL，產品欄）

| 欄位 | OSCAL 出處 | 必填 | 來源 | 依據 |
|---|---|---|---|---|
| `oscal.ssps.is_template` | 非 OSCAL（產品 discriminator）| — | A（已套用）| FR-036 migration；OSCAL 無此概念 |
| `compliance.module_frames.template_ssp_id` | 非 OSCAL（compliance 產品欄）| — | A（已套用）| FR-036 M3 migration 回填 |

---

## 驗證提示（哪些可砍/緩做）

逐條看下來，**真正「Req 根必填且今天無資料來源(C)」** 的只有少數，值得優先：
- `ssp_control_implementations.description`（control-implementation 必填，無 block-level 列）
- `assessment_result_datas.description`（result 必填，launch 沒填）
- `assessment_result_finding_targets.*`（finding 必填 target，但今天只有 control 層 verdict）
- `assessment_plan_tasks.task_type`（task 必填 type，被 manual/hybrid 佔用）

**Req 但資料已在(A/B)** → 低風險照做：import_*、control_id/statement_id、finding.title NN、result.title/start NN、component/leveraged 約束收緊、status/verdict 詞彙。

**Opt 或 Opt\*（用到才必填）+ 來源 C** → 全是「OSCAL 完整 round-trip 才需要」的捕捉點，**可依 conformance 目標砍或緩做**：group_id/class、part_id/ns/class、param 細節、information-type、security-impact-level、system-user、by-component、set-parameter、diagrams、observation、risk、back-matter/hash/document-id/revision、profile imports/merge/modify。
