FR-142 稽核結果逐 AO 判定重做 — 白話需求

FR-142 稽核結果逐 AO 判定重做(白話需求)

母卡 CM-2818;第 0 棒(討論稿+雛形)CM-2819。

§1

這系列在做什麼

現在稽核階段的判定頁是「一個控制項一個判定」:畫面擠、填寫框小,要先到別頁建風險再回來勾,很難用。稽核人員到現場拿的是 FR-141 那份逐評估目標(AO,控制項底下一條一條要查的檢查點)的稽核計畫,照表逐條查,結果也應該逐條記。亞航顧問交回的附件 Excel 正是這樣:稽核計畫的欄位原封不動,後面多「佐證資料」「稽核結果」兩欄。

本案做四件事:

  1. 判定頁整個重做,沿用 FR-141 的頁面骨架。左側是控制族群→控制項導航(完成狀態點、「未判定/不符合」篩選),中間一次一條控制項、每條 AO 一張卡,填:判定、發現(現場看到的事實)、佐證資料、風險嚴重度、風險說明、建議。稽核計畫填好的查核方法、受評對象、稽核人員以唯讀方式帶在旁邊參考。控制項結論自動推:任一條 AO 不符合或有風險就是不符合,稽核人員不用自己填。
  2. 第三個頁籤「稽核結果(文字版)」,對應亞航內部稽核報告第 7 章「稽核結果」。上方唯讀帶出第 1~6 章(依據、目的、稽核單位、稽核日期、範圍、方法,全部從稽核計畫來),下方一個大編輯器讓稽核人員直接寫,想分幾點就分幾點。旁邊一顆「帶入不符合項目」按鈕,把這次判為不符合的 AO 連同發現文字塞進編輯器當草稿;全部符合就自己寫。
  3. Excel 匯入匯出:就是 FR-141 那份四頁 Excel(填寫說明/計畫概要/評估目標/可選清單)。評估目標頁在稽核計畫欄(灰底唯讀)後面加「稽核結果、佐證資料、發現、風險嚴重度、風險說明、建議」六欄,可選清單加判定與嚴重度的值域。匯出的檔案就是匯入範本,隱藏的 part_id 欄當比對鍵。不另開工作表。
  4. 報告匯出:Word/PDF,第 1~6 章從稽核計畫帶、第 7 章用文字版內容、附件是逐 AO 結果表;另可匯出 Excel 或打包 zip,三選一比照 FR-141 匯出。
§2

為什麼要做

  • 現行判定頁難用:FE RoundAuditReviewView.vue 1,083 行(超過 800 行上限),判定做在控制項層,風險要跨頁建。
  • 稽核人員的真實工作方式是拿稽核計畫表逐條 AO 查,系統粒度對不上。
  • 目前匯出的 OSCAL 稽核結果(AR)不合規,這次一併修(見下方「套件既有錯誤」)。
§3

決策(決策者 2026-10-16 已裁)

  • D1 判定值域:畫面與 Excel 四個選項——符合/不符合/不適用/未判定。「未判定」是初始狀態、不算判定;Excel 空白=未判定;結案時還有未判定要擋。OSCAL 存法:符合/不符合 → finding 的 target.status.state 存 satisfied/not-satisfied;不適用 → target.implementation-status=not-applicable,state 存 satisfied、reason 存 other,匯出才合規;未判定=不建 finding,不落假值。套件自創的 pending/product_state 一併清掉。
  • D2 風險粒度:一條 AO 就地填一筆風險(嚴重度/說明/建議三格)。每條填了風險的 AO 背後自動生一筆獨立 risk,用連結表綁該 finding;建議存 risk 的 remediation(lifecycle=recommendation)。保留「風險」頁籤當總覽,可在那裡把多條 AO 的風險合併成一筆(進階功能,不是主路徑)。
  • D3 第 7 章文字:一個大編輯器直接寫,不固定子節;「帶入不符合項目」是加分的草稿功能。整段存 AR result 的一個 attestation part,匯出時原樣排進第 7 章。
  • D4 舊資料不遷移:新開的稽核次一律用 AO 層 finding;既有控制項層 finding 的稽核次維持舊讀法。
  • D5 控制項結論不存欄位:由 AO 即時推導。目前 FE、BE 匯入聚合、FR-140 縮範圍規則三處各寫一套,要收斂成套件裡一支。
  • Excel 帶稽核計畫欄:同一份 Excel,稽核計畫欄灰底唯讀、匯入時忽略,讓人看表就知道這一列要查什麼。
§4

OSCAL 落點

畫面 OSCAL AR
每條 AO 判定 finding(每 AO 一筆)target.type=objective-id、target-id=AO part_id、status.state/reason、implementation-status
發現 finding.description(判定理由)+ observation.description(事實),finding 用 related-observations 連
佐證資料 observation.relevant-evidence;observation.methods 從稽核計畫的查核方法帶
風險嚴重度 risk.characterizations[].facets[{name=severity, system, value}](陣列形狀)
風險說明 risk.title/description/statement,status=open
建議 risk.remediations[](型別 response)lifecycle=recommendation
第 7 章文字 result.attestations[].parts
第 1~6 章 從 AP 讀(FR-141 的 ap_terms_and_conditions/parties/task timing),AR 不重存
§5

套件既有錯誤(這次要修)

  1. finding 判定存成自創的 target_status={"product_state":…},匯出直接吐進 target.status,少了必填 state、多了不允許的欄(jedi-oscal-v2 app/service/io/oscal_io_service.py 約 1603 行;domain/service/ar/ar_finding_matrix_service.py 43-48 行)。
  2. 風險嚴重度寫成 characterizations={"severity":…},官方是陣列+origin+facets(app/service/ar/assessment_risk_service.py 99-100 行)。
  3. finding↔︎risk 連結只寫 assessment_finding_risks 表,匯出讀的是 finding.related_risks JSONB,兩邊沒同步,service 建的關聯在匯出時會消失。
  4. assessment_remediations.lifecycle 允許空值且註解寫 recommendation/required;官方必填、值域是 recommendation/planned/completed。
  5. observation、attestation、assessment-log 完全沒有 service。
  6. jedi-compliance-audit assessment_result_app_service.py 約 204 行的 init_ar_matrix_for_round 是控制項層一筆 finding,target_type 寫 objective-id、target_id 卻存 control_id;要改回 AO 層。
§6

前提與限制

  • 頁面骨架、四頁 Excel 格式、docx 報告範本全部沿用 FR-141,不另做。FR-141 的實作碼目前在 feature/FR-141 分支、尚未合回 feature/FR-139;實作階段在哪個 branch 接由決策者裁。
  • 判定與嚴重度的下拉值域進 system_menus,不寫死。
  • 參考資料:亞航內部稽核報告第 7 章沒有表格,只有三段文字結論;附件 59 條全是 MET,沒有不符合樣本,發現/風險/建議的內容要自己擬;附件索引號被藏、沒有 part_id。