手冊首頁 / 專案與任務 / 稽核判定工作區

稽核判定工作區(Audit Verdict)

功能群:稽核執行|階段轉換、AP→AR→POA&M 資料模型、AO 判定粒度先讀 功能群總覽|上層導航頁見 稽核執行頁

事實基準:2026-07-05 從 FE src/views/project/RoundAuditReviewView.vue + AuditTreeNav.vue / AuditControlRef.vue / EvidencePreviewDialog.vue + BE assessment_result_app_service.py / serializer api/project/serializers/audit_round.py 掃出(FR-038 v2 B5 AR + FR-041 稽核指引)

變更紀錄

日期 FR 變更
2026-07-06 FR-047 audit-review.md 拆出:Tab0 三欄判定工作區(控制項樹 / 參考面板 / 判定 + 內嵌風險 + 觀察)獨立成子頁

1. 功能描述

稽核判定工作區是 稽核執行頁Tab0「控制項稽核判定」:三欄版面——左欄控制項樹導覽(AuditTreeNav)、中欄控制項參考面板(AuditControlRef:稽核指引 / SSP 現況 / AO 與各 AO 證據頁籤)、右欄判定面板(verdict SelectButton + 說明、not_met 時內嵌風險、觀察區)。稽核員選中控制項後在右欄逐 AO 做判定(met / not_met / not_applicable / pending),記錄觀察(看到什麼),判定為 not_met 時可就地帶出風險。判定的控制項母體來自凍結 SSP 快照(見 _overview §4)。

主要使用者:稽核員(auditor)、專案經理(manager,可代行)。

角色速覽(完整定義見 _overview §3;本群主角是 auditor):

角色 一句話
auditor 稽核員 — 判定 / 觀察 / 內嵌風險的執行者
manager 專案經理 — 可代行 auditor
viewer 一般參與者 — 只能檢視

1.1 功能總覽(本頁全部功能)

# 功能 說明 位置 詳述
1 控制項樹導覽 / 搜尋 / 篩選 群組→控制項樹;判定色點、繼承圖示、findings 數徽章;搜尋 + 展開/收合 左欄 AuditTreeNav §5
2 控制項參考面板 選中控制項的指引 / SSP 現況 / AO 與各 AO 的證據頁籤 中欄 AuditControlRef §5
3 判定(verdict) 對控制項選 met / not_met / not_applicable / pending,填判定說明 右欄 SelectButton + 說明 UC-AR-01
4 判定內嵌風險(not_met 時) 判定為 not_met 時就地填風險等級 / 影響 / 矯正建議,存判定同時建/更新風險 右欄(editState==='not_met' 顯示) UC-AR-01
5 觀察(observation)新增 / 編輯 / 刪除 記錄「看到什麼」:方法(EXAMINE…)+ 描述 + 受評對象 + 引用證據 右欄觀察區 UC-AR-01
6 證據瀏覽 觀察卡的證據以按鈕收合,點開 dialog 列出檔案 / 問卷 / 連結,可預覽 觀察卡 → 證據 dialog + EvidencePreviewDialog §5

展開成 UC:UC-AR-01(判定控制項並記錄觀察,含 not_met 內嵌風險)。系統風險本體管理與跨風險關聯見 稽核風險管理;頁級 finalize / 統計徽章 / 唯讀模式見 稽核執行頁 hub。純顯示 / 導覽類(1 樹導覽、2 參考面板、6 證據瀏覽)於 §5 描述,不另開 UC。

2. Use Case

角色速覽(完整定義見 _overview §3;本群主角是 auditor):

角色 一句話
auditor 稽核員 — 判定 / 觀察 / 內嵌風險的執行者
manager 專案經理 — 可代行 auditor
viewer 一般參與者 — 只能檢視

流程圖視覺慣例:菱形 = 判斷、橘底 = 例外/擋下、紅框 = 錯誤(標 error code)、綠框 = 成功終點、虛線 = 可選路徑。

UC-AR-01 判定控制項並記錄觀察

項目 內容
角色 auditor(manager 可代行)
前置條件 已登入、為專案參與者;輪次狀態 = auditing
產出 / 後置條件 oscal.assessment_findings.target_status_state 更新(met→satisfied / not_met→not-satisfied);觀察寫 assessment_observations;統計徽章刷新
ar_uc_01 start gate 輪次 = auditing?(canEdit) start->gate ro 唯讀 banner 判定/觀察禁用 gate->ro pick 左樹選控制項 中欄看指引/SSP 現況/證據 gate->pick vd 右欄選 verdict (met/not_met/not_applicable/pending)+說明 pick->vd obs (可選)新增觀察 POST /ar/observations 方法+描述+對象+引用證據 vd->obs risk (not_met 可選)內嵌風險 等級/影響/矯正建議 vd->risk save 儲存判定 PUT /ar/finding/{finding_uid} vd->save obs->save risk->save perm BE 檢查:auditor/manager +phase = auditing? save->perm deny 403 GRC_NOT_AUDITOR /412 GRC_ROUND_PHASE_READONLY perm->deny ok target_status_state 更新 (met→satisfied / not_met→not-satisfied) refreshStats 刷新徽章 perm->ok
UC-AR-01 流程:auditing 才可判定;選 verdict + 描述 → BE 檢查 auditor + phase guard → upsert finding;not_met 可就地帶風險

3. 權限矩陣

專案層角色基調見 _overview §3。本頁(Tab0 判定 / 觀察)檢查點(FE / BE 對齊,phase guard BE 硬擋):

操作 FE 判定 BE 強制 BE 檢查位置
讀 findings / 樹 / 證據 參與者即可(JWT) 讀走 writable=False(finalize 後仍可讀) assessment_result_app_service.py::get_findings
判定 / 觀察 寫入 canEdit = roundStatus==='auditing'(RoundAuditReviewView.vue:49) _check_auditor + assert_round_phase({auditing}) assessment_result_app_service.py:111-118round_guard.py:31

內嵌風險(not_met 時)走風險寫入路徑,權限見 稽核風險管理 §3;finalize / 匯入等頁級操作見 稽核執行頁 §3

本頁 FE / BE 權限對齊良好:兩端都以 auditing 階段 + auditor/manager 判定;BE assert_round_phase 硬擋——過階段直接打 API 仍回 412(見 _overview §5 坑 2)。

4. 狀態機與前置條件

輪次狀態機見 專案管理群 _overview §2;本群階段轉換見 _overview §2。本頁相關 gate:

條件 效果 出處
roundStatus === 'auditing' canEdit=true:判定 / 觀察 可寫 RoundAuditReviewView.vue:49
其餘狀態 canEdit=false:唯讀 banner + 全表單禁用 同上 + Message(:686-688)
BE 寫入 phase guard AR 寫入一律 assert_round_phase({auditing}),過階段回 412 round_guard.py:31
範圍過濾 inScopeTreeGroups 只顯示有 finding 的控制項(AP 可能縮小 scope) RoundAuditReviewView.vue:327-332
SelectButton unselectable=false 防止取消選取造成 null 判定(一律有 verdict 值) RoundAuditReviewView.vue(verdict SelectButton)

finalize 前置(無 pending / 風險皆關聯)等頁級 gate 見 稽核執行頁 §4

5. UI 設計

Tab [0] 控制項稽核判定 — 三欄工作區(選中控制項驅動右欄) 開啟:§4 狀態機與前置條件(範圍過濾 / 樹) 左欄 · 控制項樹 搜尋 / 展開收合 群組(進度徽章) 控制項:判定色點 繼承圖示 / findings 數 inScopeTreeGroups 範圍過濾 GET …/ar/findings → §4(點我) 開啟:§6.2 載入類(ar/findings:planning / observations) 中欄 · 控制項參考面板 稽核指引(FR-041 planning) SSP 現況 AO + 各 AO 證據頁籤 證據 dialog(EvidencePreviewDialog) 檔案 / 問卷 / 連結,lazy 快取 GET …/ar/findings(controls[].planning) → §6.2(點我) 開啟:UC-AR-01 判定控制項並記錄觀察 右欄 · 判定 + 觀察 verdict SelectButton + 說明 (met/not_met/not_applicable/pending) not_met 時內嵌風險(等級/影響/矯正) 存判定同時建/更新風險 → audit-risk.md 觀察區:方法 + 描述 + 對象 + 證據 PUT …/ar/finding/{uid} POST …/ar/observations → UC-AR-01(點我) 彩色=可點跳本頁小節錨點(purple=§4 樹範圍/teal=§6.2 findings/coral=UC-AR-01 判定觀察)|灰=結構描述|虛線框=dialog/條件層 內嵌風險本體管理見 audit-risk.md;API 僅列代表性,完整規格見 §6
稽核判定工作區版面 wireframe:左欄控制項樹(搜尋/色點/findings 數)、中欄控制項參考(指引/SSP 現況/AO 證據頁籤)、右欄判定 SelectButton+not_met 內嵌風險+觀察區;標代表性 API PUT finding / POST observations

實機截圖(STG,亮色模式,2026-07-05,帳號 blsadmin,專案「亞○ CMMC L1 合規」/ auditing 輪次):

判定面板:選取控制項後顯示規劃查核指引 + 受評對象 + 現況說明 + 右側 verdict SelectButton(符合/不符合/不適用/待判定)+ 觀察記錄區

觀察新增表單:蒐證方法 / 看到什麼(觀察內容)/ 證據 / 查核對象

證據瀏覽 dialog:點擊評估物件底下的證據檔案開啟全螢幕預覽

狀態呈現:樹節點帶判定色點與 findings 數;判定 per-按鈕 spinner(savingVerdict / savingObs);證據 lazy 載入並 per-控制項快取。SelectButton 設 unselectable=false 防 null 判定。無 socket,判定後 refreshStats(重取統計,驅動頂部徽章與樹範圍),觀察增改刪後重取對應清單。

6. API 規格

Envelope:成功 {"code": 1, "data": …}、失敗 {"code": 0, "msg": "…"}

6.1 總清單(本頁呼叫的 endpoint)

分類 Method + Path 說明 完整規格
載入 GET /ssp/{ssp_uid}/control-tree 凍結 SSP 控制樹(中欄參考) 見 project-planning §6.2
載入 GET /audit-round/{round_uid}/ar/findings AO 全量判定矩陣(控制項分組 + 觀察 + 統計 + 稽核指引) §6.2
證據 GET /job-evidences?job_execution_uid={jobId}、GET /grc/project/{uid}/job/{jobId} 選中控制項的 AO 證據 / 問卷(lazy) GAI-SD-02
判定 PUT /audit-round/{round_uid}/ar/finding/{finding_uid} 存單一 AO 判定(met/not_met/pending + 說明 + 關聯觀察) §6.3
觀察 POST /ar/observations、PUT/DELETE /ar/observation/{obs_uid} 觀察增 / 改 / 刪 §6.3

風險 / 風險關聯端點見 稽核風險管理 §6;finalize / 匯入 / 專案載入端點見 稽核執行頁 §6

以下 §6.2~6.3 為本頁核心 endpoint 完整規格(欄位逐條對照 serializer / service 組裝碼,出處標在各段末);標 GAI-SD-02 者屬常規 CRUD,細節見 API 規格書或 Swagger /swagger-ui/

6.2 載入類

[GET] /audit-round/{round_uid}/ar/findings

AO 全量判定矩陣(控制項分組)。無 query 參數。Response data

欄位 型別 說明
ar_result_uid / round_uid string AR / 輪次識別
stats object {total_ao, met, not_met, pending, controls_total, controls_with_not_met}(皆 int)——徽章來源
controls[] array 控制項節點(下表)
assessment_subjects[] array OSCAL result.assessment-subjects[]

Control 節點controls[] 每項):

子欄位 型別 說明
control_id string 控制項識別
ao_findings[] array AO 判定(下表)
observations[] array 觀察(下表)
planning object FR-041 稽核指引(下表;源自 AP 行程)

ao_findings[](每項):

欄位 型別 說明
finding_uid string finding 識別
ao_id string AO 識別(無 AO 時 fallback control_id)
state string met / not_met / pending
description string 判定說明
observation_uid string 關聯觀察 uid(選填)
updated_user string 更新者

observations[](每項):

欄位 型別 說明
uid string 觀察識別
title string 標題
description string 觀察內容
methods string[] 蒐證方法
subjects array 受評對象
relevant_evidence array 引用證據
collected date 蒐集時間

planning(FR-041 稽核指引):

欄位 型別 說明
methods string[] 蒐證方法
guidance array 每項 {method, description}
subjects string[] 受評對象

出處:app/grc/service/assessment_result_app_service.py:385-446get_findings)。

6.3 判定 / 觀察類

[PUT] /audit-round/{round_uid}/ar/finding/{finding_uid}

存單一 AO 判定(upsert)。Request:

欄位 型別 必填 說明
state string OneOf met / not_met / pendingJudgeFindingRequest 寫入僅接受這 3 值;第 4 值 not_applicable 不可由手動判定寫入——會被 OneOf 擋成 400,僅在唯讀路徑如 AR 匯入 / matrix 服務可能出現,見 §12 坑 2)
description string 判定說明 / 缺失描述
observation_uid string 關聯觀察 uid(軟連結)

Response data

欄位 型別 說明
finding_uid string finding 識別
ao_id string AO 識別
state string met / not_met / pending
description string 判定說明
related_observations array 關聯觀察
updated_user string 更新者

verdict 值 API↔︎DB 映射assessment_findings.target_status_state 直接存 4 種 product token——met→satisfied、not_met→not-satisfied、not_applicable→not-applicable、pending→pendingnot-applicable/pending 是 OSCAL 規格外的 product token,直存於同一欄,非落 JSONB)。target_status JSONB 是全狀態鏡射(含 reason)非 pending 專屬。出處:serializer JudgeFindingRequestapi/project/serializers/audit_round.py:114-122)、service judge_findingassessment_result_app_service.py:509-543)、jedi-oscal-v2 .../domain/service/ar/ar_finding_matrix_service.py

[POST] /audit-round/{round_uid}/ar/observations

建立觀察(證據引用不複製)。Request:

欄位 型別 必填 說明
description string 觀察內容(看到什麼)
title string 標題
methods string[] 蒐證方法(EXAMINE / INTERVIEW / TEST)
relevant_evidence raw 引用證據(自包含 file 中繼資料,不複製)
subjects raw OSCAL observation.subjects[](軟引用)

Response data

欄位 型別 說明
uid string 觀察識別
title string 標題
description string 觀察內容
methods string[] 蒐證方法
subjects array 受評對象
relevant_evidence array 引用證據
collected date 蒐集時間

出處:serializer CreateObservationRequestaudit_round.py:125-133)、service create_observationassessment_result_app_service.py:545-574)。

PUT /ar/observation/{obs_uid}UpdateObservationRequest,全欄選填 partial update)/ DELETE(解除所有 finding 連結)同檔。

7. 前端檔案地圖(compliance-manager-fe/)

檔案 角色
src/views/project/RoundAuditReviewView.vue 主檢視(判定 / 觀察 CRUD、證據瀏覽、樹狀態管理皆在此檔;TabView 容器見 hub §7
src/components/grc/AuditTreeNav.vue 左欄控制項樹(搜尋 / 篩選 / 展開;判定色點、繼承圖示)
src/components/grc/AuditControlRef.vue 中欄控制項參考(指引 / SSP 現況 / AO 證據頁籤)
src/components/grc/EvidencePreviewDialog.vue 證據預覽(檔案 / 連結 / 問卷)
src/service/BaseService.js axios 封裝(AR findings / verdict / obs 直接呼叫)
src/config/api/api.js 端點常數(AUDIT_ROUND / SSP_CONTROL_TREE …)

Tab1 風險元件見 稽核風險管理 §7

8. 後端檔案地圖

鏈路 Route App Service 底層
判定矩陣 api/project/routes/audit_round_route.py::AuditRoundFindingsRoute(GET /ar/findings assessment_result_app_service.py::get_findings(AO 衍生 + finding/observation 組裝 + FR-041 planning) ao_derivation.py::derive_ao_pairs + AR finding/observation repo(jedi_oscal_v2)
判定寫入 同檔 AuditRoundFindingRoute judge_finding_check_auditor + assert_round_phase({auditing}) + upsert finding) AssessmentResultService.upsert_finding(v2)→ assessment_findings
觀察 同檔 AuditRoundObservationsRoute / AuditRoundObservationRoute create_observation / update_observation / delete_observation ArObservationRepoImplassessment_observations

風險鏈路見 稽核風險管理 §8;finalize / 階段推進鏈路見 稽核執行頁 §8

DDD 提醒:判定 / 觀察 寫入 API 都照層級走(route 不碰 DB、app service @transaction_check_auditor + assert_round_phase 雙檢查)——與 AP 頁一致的 phase-guard 樣板。

9. DB

9.1 資料表總清單(本頁讀寫的表)

讀/寫 說明 欄位詳述
oscal.system_security_plans 凍結 SSP 快照(判定母體) GAI-SD-03
oscal.assessment_plans AP(import_ap_id 溯源;FR-041 稽核指引來源) 見 ap-authoring §9.3
oscal.assessment_results / ar_results 讀/ AR root / 每輪 result §9.3
oscal.assessment_findings 逐 AO 判定(target_status_state) §9.3
oscal.assessment_observations 觀察 §9.3
compliance.job_executions / evidence 相關 AO 證據(lazy 載入) GAI-SD-03

風險相關表(assessment_risks / assessment_finding_risks)欄位卡見 稽核風險管理 §9.3

9.2 ER 圖(本頁讀寫範圍)

ar_er cluster_ar AR(本頁寫入) cluster_poam POA&M(finalize 生成) ap oscal.assessment_plans AP(import_ap_id 溯源) arroot oscal.assessment_results AR root(import_ap_id) arroot->ap import_ap_id arres oscal.ar_results 每輪一筆 result arroot->arres 1:N(每輪) find oscal.assessment_findings 逐 AO 判定(target_status_state) arres->find 1:N obs oscal.assessment_observations 觀察(methods / evidence) arres->obs 1:N risk oscal.assessment_risks 系統風險(severity 在 characterizations) arres->risk 1:N find->obs related_observations fr oscal.assessment_finding_risks finding ↔ risk 多對多 find->fr finding_id poam oscal.poams / poam_items not_met → 一控制項一 item find->poam not_met → generate risk->fr risk_id
AR 寫入鏈:AR root(綠)承接 AP;每輪 ar_results 掛 findings / observations / risks;finding↔risk 多對多;not_met → poam_items(橘)

9.3 核心表欄位(取自 DEV DB dump,含 DB comment)

oscal.assessment_results / ar_results — AR root / 每輪結果

assessment_results 是 AR 文件 root(import_ap_id → AP,NOT NULL);ar_resultsresults[](一份 AR 多輪,每輪一筆 result)。

表.欄位 型別 說明
assessment_results.import_ap_id bigint → oscal.assessment_plans(AR 必由本地 AP 建立)
ar_results.assessment_result_id bigint containment → assessment_results
ar_results.reviewed_controls jsonb 本結果涵蓋的控制項選取
ar_results.start / end timestamptz 評估起 / 迄

oscal.assessment_findings — 逐 AO 判定

assessment-common finding(AR / POA&M 共用)。owner = ar_result_idpoam_id(擇一,應用層保證)。

欄位 型別 說明
ar_result_id bigint|null owner(AR result)
uuid uuid finding 身分(= FE 的 finding_uid)
target_type varchar(60) statement-id(AO 層)/ objective-id
target_id varchar(255) AO 識別(_obj.N)或 fallback control_id
target_status_state varchar(40) 判定值,直存 4 種 product tokensatisfied(met)/ not-satisfied(not_met)/ not-applicable(na)/ pending(未判定)
target_status jsonb 全狀態的冗餘鏡射(reason / product state); pending 專屬
implementation_statement_uuid uuid|null 對應 SSP ssp_statements.uuid(跨文件軟參照)
related_observations / related_risks jsonb 關聯觀察 / 風險(雙寫保真)

oscal.assessment_observations — 觀察

assessment-common observation。owner = ar_result_id / poam_id。required=[collected, description, methods, uuid]。

欄位 型別 說明
uuid uuid 觀察身分(= obs_uid)
description text [必填] 觀察內容
methods jsonb [必填] EXAMINE / INTERVIEW / TEST / UNKNOWN
subjects jsonb 受評對象(軟引用)
relevant_evidence jsonb 佐證(href/description,自包含 file 中繼資料)
collected timestamptz [必填] 蒐集時間

10. 頁面邏輯與資料對應

關鍵欄位對應(畫面 ↔︎ API):

畫面元素 FE state API 欄位
樹判定色點 findingByControl[cid].state(AO roll-up) ao_findings[].state(控制項層聚合)
verdict SelectButton editState PUT finding state
判定說明 editDesc PUT finding description
內嵌風險(not_met) inlineRiskSeverity / inlineRiskImpact / inlineRemediation POST/PUT risk + link findings(見 稽核風險管理 §6
觀察卡 selectedObservations control.observations[]

儲存流程:判定 = PUT findingrefreshStats(重取統計);not_met 內嵌風險同存(新建走 POST risk + PUT risk/findings,既有走 PUT,端點見 稽核風險管理);觀察增改刪後重取對應清單。findingByControl 用淺拷貝觸發 notMetControls / inScopeTreeGroups 重算。

錯誤對應:BE error envelope → toast;本頁常見碼 GRC_NOT_AUDITOR(403)、GRC_ROUND_PHASE_READONLY(412,過階段)。412 由 axios interceptor → event bus → App.vue toast 統一處理。finalize 相關錯誤碼見 稽核執行頁 §10

11. 背景行為與外部依賴

類型 內容
通知 本頁判定 / 觀察站內通知
Socket 本頁 socket / 輪詢;各動作後手動重取
jedi-* 套件 jedi-oscal-v2(AR finding/observation repo + AssessmentResultService)、jedi-auth(JWT)
系統參數 蒐證方法來自 AP planning(FR-041)或 fallback OSCAL 三法;無 feature flag

12. 邊界情況與已知坑

  1. phase guard BE 硬擋:判定 / 觀察 寫入只在 auditing,過階段直接打 API 也回 412(見 _overview §5 坑 2
  2. verdict 值 API↔︎DB 映射:API FindingStatemet/not_met/pending+第 4 值 not_applicable);DB target_status_state 直存 4 種 product token satisfied/not-satisfied/not-applicable/pendingtarget_status JSONB 是全狀態鏡射非 pending 專屬,比對以 target_status_state 為準(_overview §5 坑 4
  3. 判定 AO 層 / 顯示與 POA&M 控制項層statsmet/not_met/pending(AO 計數)與 controls_with_not_met(控制項計數)兩套;控制項 verdict 由 AO roll-up(任一 AO not_met → 控制項 not_met)
  4. 證據自包含 + lazy 快取:觀察 relevant_evidence 內含 file 中繼資料(供 POA&M 免 N+1);證據 per-控制項 lazy 載入並快取,切控制項可能短暫顯示前一個的快取
  5. 範圍過濾inScopeTreeGroups 只顯示有 finding 的控制項(AP reviewed-controls 可能縮小 scope),樹上看不到的控制項不代表不存在、是不在本輪範圍
  6. 內嵌風險走風險寫入路徑:not_met 就地帶的風險與 Tab1 是同一批資料,notMetControls 依賴 refreshStats 重算——改完 verdict 未刷新前,風險來源清單可能過時(見 稽核風險管理 §12

13. 開發與驗證

  • 跑起來:BE python main_socketio.py(port 8000,log 在 log/app.log);FE 在 compliance-manager-fe/ 起 Vite dev server。BE 改 service code 後必須重啟(無 hot reload)
  • 測試帳號:dev 環境稽核員角色帳號(密碼見 .env / 部署文件)
  • 導航路徑:登入 → 專案 → 進入 auditing 狀態的輪次 → 稽核執行 → Tab「控制項稽核判定」
  • 前置資料:輪次需已 start-auditing(AR 矩陣已初始化);控制項要有證據才判得動
  • E2Ecompliance-manager-test/ repo(Cucumber + Playwright);以 稽核執行 / audit-review / 判定 搜尋
  • 相關文件:上層導航 稽核執行頁稽核風險管理(Tab1 系統風險與關聯);FR-038(v2 遷移 B5 AR)、FR-041(稽核指引);DB / API 全量見 GAI-SD-02/03