稽核計畫填寫頁(AP Authoring)
功能群:稽核執行|階段轉換、AP→AR→POA&M 資料模型、角色基調先讀 功能群總覽
事實基準:2026-07-05 從 FE / BE code 掃出(FR-038 v2 round-based + FR-040 行程鉤稽架構);API schema 逐條對照
api/project/serializers/audit_round.py與app/grc/service/assessment_plan_app_service.py
1. 功能描述
稽核計畫填寫頁是稽核輪次 audit_planning
階段的主工作區:稽核員(auditor)在此定義本輪的
AP(Assessment
Plan,評估計畫)——要查哪些控制項、用什麼行程與查核方法進行、實地會碰到哪些受評對象、由哪些稽核人員執行。編輯對象是輪次的
AP 文件(oscal.assessment_plans),其
import_ssp_id 指向 launch-audit 當下凍結的 SSP 快照(見 _overview §4);start-auditing
推進後 AP 凍結、本頁轉唯讀。
主要使用者:稽核員(auditor)、專案經理(manager,可代行)。
角色速覽(完整定義與 manager 全域代行慣例見 _overview §3;本群主角是 auditor):
| 角色 | 一句話 |
|---|---|
| auditor | 稽核員 — AP 的擁有者與填寫者 |
| manager | 專案經理 — 可代行 auditor 的 AP 編輯 |
| viewer | 一般參與者 — 只能檢視 |
1.1 功能總覽(本頁全部功能)
| # | 功能 | 說明 | 位置 | 詳述 |
|---|---|---|---|---|
| 1 | 行程(task)新增 / 刪除 | 逐條規劃稽核行程,每條有標題 / 類型(action / milestone)/ 時間 | Tab0「行程與方法」面板頭 + 卡片 | UC-AP-01 |
| 2 | 查核方法多選 + per-方法查核指引 | 每條行程勾查核方法(EXAMINE / INTERVIEW / TEST,來自 system_menu AUDIT_METHOD),每個方法可填「看什麼 / 怎麼看」指引 | 行程卡 Methods MultiSelect + 指引列 | UC-AP-01 |
| 3 | 行程鉤稽控制項 | 每條行程勾這次查哪些控制項(母體 = 完整凍結控制樹) | 行程卡 Controls MultiSelect | UC-AP-01 |
| 4 | 行程鉤稽受評對象 | 每條行程勾實地會碰到的資產 / 人員(component / inventory-item / party / user,源自 SSP 快照) | 行程卡 Subjects MultiSelect | UC-AP-01 |
| 5 | 行程鉤稽參與稽核人員 | 每條行程指派執行的稽核人員(AP parties) | 行程卡 Participants MultiSelect | UC-AP-01 |
| 6 | 就地新增稽核人員 | 在參與人員下拉底部「+新增稽核人員」開 dialog,填姓名 / email / 電話後即建立並帶回當前行程 | 行程卡 → 新增稽核人員 dialog | UC-AP-02 |
| 7 | 儲存行程 | 「儲存行程」把全部行程全量覆寫寫入(含方法 / 控制項 / 對象 / 人員 / 指引) | Tab0 面板頭 | UC-AP-01 |
| 8 | 受評控制項總覽(唯讀) | 由行程勾選的控制項自動彙整去重,唯讀顯示 | Tab1 | §6.1 |
| 9 | 受評對象總覽(唯讀) | 由行程勾選的對象自動彙整,按類型分組唯讀顯示 | Tab2 | §6.1 |
| 10 | 稽核紀錄 DOCX 匯入 | 上傳既有稽核計畫 docx → 解析預覽 → 確認匯入成行程 | Header「匯入」按鈕 → dialog | UC-AP-03 |
| 11 | 階段推進(FlowPhaseBanner) | 顯示 audit_planning 階段點與前置(受評控制項非空),符合條件可推「啟動稽核」 | 頁面頂部橫幅 | UC-AP-04 |
| 12 | 唯讀模式 | 非 audit_planning 階段(或非 auditor/manager)整頁轉唯讀,表單換成唯讀顯示 | 全頁 | §4 |
UC(§2)展開本頁所有具實質後端邏輯的功能:行程規劃(1,含 2~5 / 7 的鉤稽與儲存)、就地新增稽核人員(6)、DOCX 匯入(10)、階段推進 / 啟動稽核(11)。受評控制項 / 受評對象兩 tab(8 / 9)是行程選取的唯讀投影(BE
_backfill_scope_from_tasks回填),非獨立編輯;唯讀模式(12)是頁面狀態切換——兩者屬純顯示,見 §4 / §6.1。生成草稿(generate-draft)是啟動稽核時的內部產物、非本頁常態操作(規格見 §6.3)。
2. Use Case
角色速覽(完整定義與 manager 全域代行慣例見 _overview §3;本群主角是 auditor):
| 角色 | 一句話 |
|---|---|
| auditor | 稽核員 — AP 的擁有者與填寫者 |
| manager | 專案經理 — 可代行 auditor 的 AP 編輯 |
| viewer | 一般參與者 — 只能檢視 |
流程圖視覺慣例:菱形 = 判斷、橘底 = 例外/擋下、紅框 = 錯誤(標 error code)、綠框 = 成功終點、虛線 = 可選路徑。
UC-AP-01 規劃稽核行程並儲存
| 項目 | 內容 |
|---|---|
| 角色 | auditor(manager 可代行) |
| 前置條件 | 已登入、為專案參與者;輪次狀態 = audit_planning |
| 產出 / 後置條件 | oscal.ap_tasks + ap_assessment_activities
+ ap_task_subjects + ap_task_participants
全量覆寫;受評控制項 / 對象由 _backfill_scope_from_tasks
回填 ap_reviewed_controls /
ap_assessment_subjects |
UC-AP-02 就地新增稽核人員
| 項目 | 內容 |
|---|---|
| 角色 | auditor(manager 可代行) |
| 前置條件 | 輪次 = audit_planning;在某行程的參與人員下拉觸發 |
| 產出 / 後置條件 | AP metadata 下新增一筆
oscal.parties(type=person,role=assessor);建立後自動帶回觸發的行程;同名擋下(GRC_AP_PARTY_NAME_EXISTED) |
UC-AP-03 稽核紀錄 DOCX 匯入
| 項目 | 內容 |
|---|---|
| 角色 | auditor(manager 可代行) |
| 前置條件 | 輪次 = audit_planning 且 AP
已存在(canImportDocx = !readonly && !!apUid) |
| 產出 / 後置條件 | docx 解析成暫存 parse job → 預覽 → confirm 後轉成行程;解析失敗 → 400 |
UC-AP-04 推進階段(啟動稽核)
| 項目 | 內容 |
|---|---|
| 角色 | auditor(manager 可代行) |
| 前置條件 | 輪次 =
audit_planning;受評控制項(reviewed-controls)非空——為空則「啟動稽核」按鈕禁用帶原因 |
| 產出 / 後置條件 | 前置 ApReviewedControlsSetCheck 通過 → handler
SubmitApOnCompleteHandler 呼
start_auditing(AP 凍結)→ BPMN 前進、輪次狀態同步;handler
副作用先於 BPMN 推進,同 transaction 失敗全 rollback |
3. 權限矩陣
專案層角色基調見 _overview §3。本頁的實際檢查點(FE 與 BE 對齊,phase guard BE 硬擋):
| 操作 | FE 判定 | BE 強制 | BE 檢查位置 |
|---|---|---|---|
| 讀 AP / 樹 / 候選對象 | 參與者即可(JWT) | 無額外角色檢查 | AssessmentPlanAppService.get_ap_for_round |
| 寫行程 / 受評控制項 / 對象 | readonly = !(roundStatus==='audit_planning' && (isAuditor||isProjectManager))(RoundApAuthoringView.vue:78-79) |
resolve_ap_and_check_auditor +
assert_round_phase({audit_planning}) |
app/grc/service/assessment_plan_app_service.py:190-208 |
| 新增稽核人員 | 同上 readonly | 同上 + 同名檢查 | 同檔 add_ap_party |
| DOCX 匯入 | canImportDocx(612:!readonly && !!apUid) |
同 phase guard | AP docx import service |
| 啟動稽核(推進) | banner user_can_advance |
_check_auditor + 前置 reviewed-controls
非空 |
oscal_stage_preconditions.py:40-62 |
本頁 FE / BE 權限對齊良好(與專案規劃頁的三層遞進不一致不同):兩端都用「audit_planning 階段 + auditor/manager」判定,且 BE
assert_round_phase硬擋——過階段直接打 API 也會被 412 擋,不像專案規劃頁 SSP 寫入可繞過(見 _overview §5 坑 2)。
4. 狀態機與前置條件
輪次狀態機見 專案管理群 _overview §2;本群階段轉換見 _overview §2。本頁相關 gate:
| 條件 | 效果 | 出處 |
|---|---|---|
roundStatus === 'audit_planning' 且使用者是
auditor/manager |
readonly=false:三 tab 可編、匯入可用、banner 顯示 |
RoundApAuthoringView.vue:78-79 |
| 其餘狀態或非 auditor/manager | readonly=true:表單換唯讀顯示、banner 隱藏 |
同上(v-if="readonly" 切換) |
| BE 寫入 phase guard | AP 寫入 API 一律
assert_round_phase({audit_planning}),過階段回 412 |
assessment_plan_app_service.py:206 |
推進前置:reviewed-controls 非空 |
為空 → 「啟動稽核」按鈕禁用帶原因 | oscal_stage_preconditions.py:40-62 |
| 受評控制項 / 對象兩 tab | 恆唯讀(行程選取的投影,無獨立儲存) | RoundApAuthoringView.vue(derived computed) |
5. UI 設計
版面骨架與區塊職責(TabView 三 tab;Tab0 行程卡在 editable / readonly
兩態 v-if 切換;彩色區塊可點跳對應小節錨點,API
僅標代表性):
實機截圖(STG,亮色模式,2026-07-05,帳號 blsadmin,專案「亞○ CMMC L1 合規」/ auditing 輪次):



稽核紀錄 DOCX 匯入 dialog 截圖從缺:該匯入動作僅在 audit_planning(規劃中)階段開放,2026-07-05 盤點 STG 全庫無任何存活專案處於此狀態,暫無真實資料可拍。
狀態呈現:每個儲存動作 per-按鈕 spinner(savingTasks /
savingParty);無 socket,儲存後靠前端 state
更新(saveTasks 會依日期重排行程並刷新畫面)。DOCX
匯入成功後整頁重載。方法標籤 i18n key
lang.ap_authoring.method_<value>,缺翻譯時顯示原始碼。
6. API 規格
Envelope:成功 {"code": 1, "data": …}、失敗
{"code": 0, "msg": "…"}(見專案根 CLAUDE.md Response
Format)。
6.1 總清單(本頁呼叫的全部 endpoint)
| 分類 | Method + Path | 說明 | 完整規格 |
|---|---|---|---|
| 載入 | GET /grc/project/{project_uid} |
專案基本資料 + 參與人員(角色判定) | GAI-SD-02 |
| 載入 | GET /audit-round/{round_uid}/ap |
本輪 AP 明細(reviewed_controls / tasks / subjects / round_status / import_ssp_uid) | §6.2 |
| 載入 | GET /ssp/{ssp_uid}/control-tree |
凍結 SSP 控制樹(行程鉤稽控制項的母體) | 見 project-planning §6.2 |
| 載入 | GET
/ssp/{ssp_uid}/parties・/components・/inventory-items |
受評對象候選(人員 / 元件 / 盤點項) | GAI-SD-02 |
| 載入 | GET /system/menu/AUDIT_METHOD |
查核方法下拉(EXAMINE / INTERVIEW / TEST…) | GAI-SD-02 |
| 載入 | GET /ap/{ap_uid}/parties |
本 AP 稽核人員清單 | §6.4 |
| 行程 | PUT /ap/{ap_uid}/tasks |
行程 + 方法 + 鉤稽(全量覆寫;連帶回填受評範圍) | §6.3 |
| 受評範圍 | PUT /ap/{ap_uid}/reviewed-controls |
查核控制項(全量覆寫,不可為空) | §6.3 |
| 受評範圍 | PUT /ap/{ap_uid}/assessment-subjects |
抽查對象(全量覆寫) | §6.3 |
| 稽核人員 | POST /ap/{ap_uid}/parties |
就地新增稽核人員(party) | §6.4 |
| 匯入 | POST /ap/{ap_uid}/docx-imports/parse、GET/POST
/ap-docx-import/{parse_uid}(/confirm)、DELETE |
稽核紀錄 docx 解析 → 預覽 → 確認 | GAI-SD-02 |
| 生成 | POST /audit-round/{round_uid}/ap/generate-draft |
從凍結 SSP 重生 AP 草稿(內部 / 重置用) | §6.3 |
| 階段 | GET
/project/{project_uid}/audit-round/{round_uid}/stage/info、POST
.../stage/advance |
FlowPhaseBanner 階段資訊 / 推進 | 見 project-planning §6.5 |
以下 §6.2~6.4 為核心 endpoint 完整規格(欄位逐條對照 serializer /
service 組裝碼,出處標在各段末);標 GAI-SD-02 者屬常規 CRUD,細節見 API
規格書或 Swagger /swagger-ui/。
6.2 載入類
[GET] /audit-round/{round_uid}/ap
本輪 AP 明細,頁面據此填三 tab。無 query 參數。Response
data:
| 欄位 | 型別 | 說明 |
|---|---|---|
| uid / status | string | AP 識別 / 生命週期(draft…) |
| import_ssp_uid | string | 本 AP 依據的凍結 SSP uid |
| round_status | string | 輪次狀態(FE 據此決定 readonly) |
| reviewed_controls[] | array | {control_id, included}——查核範圍投影 |
| reviewed_control_count | int | 查核控制項數 |
| assessment_subjects[] | array | {uid, subject_type, subject_uuid, title, include, sort_order} |
| tasks[] | array | 行程(下表) |
| created_user / created_at | string / datetime | 審計欄 |
Task 節點(tasks[] 每項):
| 欄位 | 型別 | 說明 |
|---|---|---|
| uid | string | 行程識別 |
| title | string | 行程標題 |
| type | string | OSCAL task type(action / milestone) |
| sort_order | int | 排序 |
| description | string | 行程整體備註 |
| timing | raw | 執行時點(date 字串或 OSCAL timing 物件) |
| methods[] | string[] | 查核方法 value |
| controls[] | string[] | 這條行程查的 control_id |
| steps[] | array | per-方法查核指引,每項 {method, description} |
| subjects[] | array | 行程受評對象,每項
{subject_type, subject_uuid, include, title} |
| participants[] | array | 行程參與人員,每項 {party_uuid, role_id} |
出處:app/grc/service/assessment_plan_app_service.py:268-281(AP
detail 組裝)
6.3 AP 寫入類(全量覆寫)
[PUT] /ap/{ap_uid}/tasks
行程 + 方法(全量覆寫:送出的陣列即最終狀態,未列入即刪除)。Request:
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
| tasks[].title | string | 是 | 行程標題 |
| tasks[].type | string | 否 | OSCAL task type(action(預設)/
milestone) |
| tasks[].timing | raw | 否 | date 字串或 OSCAL timing 物件({on-date:{date}} /
{within-date-range} / {at-frequency}) |
| tasks[].methods | string[] | 否 | 查核方法 value(system_menu AUDIT_METHOD)→ 落 activity.props |
| tasks[].controls | string[] | 否 | 這條行程查的 control_id → activity.related-controls |
| tasks[].subjects | array | 否 | {subject_type(OneOf: component/inventory-item/location/party/user), subject_uuid, include(預設 true), title}
→ ap_task_subjects |
| tasks[].participants | array | 否 | {party_uuid(必填), role_id(預設 assessor)} →
ap_task_participants |
| tasks[].steps | array | 否 | {method(必填), description}——每方法的查核指引 →
activity.steps |
| tasks[].description | string | 否 | 行程整體備註 |
副作用:_backfill_scope_from_tasks(assessment_plan_app_service.py:564-589)把所有行程的
controls / subjects 聯集回填 ap_reviewed_controls /
ap_assessment_subjects——故受評控制項 / 對象兩 tab
是行程的投影,不需另存。Response:完整 AP detail(同
§6.2)。出處:serializer
SetTasksRequest(api/project/serializers/audit_round.py:91-96,其行項
schema _TaskItem 在 :65-88)、service
set_tasks(assessment_plan_app_service.py:501-562)
[PUT] /ap/{ap_uid}/reviewed-controls
查核控制項全量覆寫。Request(control_ids
required、不可為空,為空回
GRC_AP_REVIEWED_CONTROLS_REQUIRED):
{ "control_ids": ["string"] }Response:
{ "ap_uid": "string", "reviewed_control_count": 0 }出處:serializer
SetReviewedControlsRequest(audit_round.py:19-24)、service
set_reviewed_controls(assessment_plan_app_service.py:464-474)
[PUT] /ap/{ap_uid}/assessment-subjects
抽查對象全量覆寫。Request:
{
"subjects": [
{
"subject_type": "string", // OneOf: component / inventory-item / location / party / user
"subject_uuid": "string",
"include": true,
"title": "string"
}
]
}Response:
{ "ap_uid": "string", "subjects": [] }出處:serializer
SetAssessmentSubjectsRequest(audit_round.py:27-46)、service
set_assessment_subjects(assessment_plan_app_service.py:476-499)
[POST] /audit-round/{round_uid}/ap/generate-draft
從輪次凍結 SSP 重生 AP 草稿(clone Profile 控制項成 AP tasks/AO)。無
body。前置:輪次有凍結 ssp_id、非 close-out
輪。Response:完整 AP
detail。出處:assessment_plan_app_service.py:591-613
6.4 稽核人員類
[GET] /ap/{ap_uid}/parties
Response data(陣列,每項):
| 欄位 | 型別 | 說明 |
|---|---|---|
| uid | string | party 識別 |
| name | string | 姓名 |
| type | string | person / organization |
| role | string | OSCAL responsible-role |
| email_address | string | |
| telephone_number | string | 聯絡電話 |
出處:assessment_plan_app_service.py:633-641
[POST] /ap/{ap_uid}/parties
就地新增稽核人員。Request:
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
| name | string | 是 | 姓名(同名擋下 GRC_AP_PARTY_NAME_EXISTED) |
| party_type | string | 否 | person(預設)/ organization |
| role | string | 否 | OSCAL responsible-role(預設 assessor) |
| email_address | string | 否 | |
| telephone_number | string | 否 | 聯絡電話 |
Response:
| 欄位 | 型別 | 說明 |
|---|---|---|
| uid | string | party 識別 |
| name | string | 姓名 |
| type | string | person / organization |
| role | string | OSCAL responsible-role |
| email_address | string | |
| telephone_number | string | 聯絡電話 |
出處:serializer
ApPartyAddRequest(audit_round.py:99-110)、service
add_ap_party(assessment_plan_app_service.py:643-672)
7. 前端檔案地圖(compliance-manager-fe/)
| 檔案 | 角色 |
|---|---|
src/views/project/RoundApAuthoringView.vue |
主檢視(約 1,000 行;三 tab、行程卡、鉤稽多選、稽核人員 dialog、匯入觸發) |
src/config/router/index.js:818-823 |
route project-ap-authoring-round(path
/round/:roundUid/ap-authoring) |
src/components/grc/FlowPhaseBanner.vue |
audit_planning 階段推進橫幅(stage info / advance) |
src/components/grc/ap-docx-import/ApDocxImportDialog.vue |
稽核紀錄 docx 匯入三步精靈 |
src/service/SspService.js |
SSP 候選對象(parties / components / inventory-items) |
src/service/BaseService.js |
axios 封裝(AP tasks / reviewed-controls / subjects / parties 直接呼叫) |
src/config/api/api.js |
端點常數(AUDIT_ROUND / AP_AUTHORING /
SSP_CONTROL_TREE / SYSTEM_MENU …) |
src/composables/useStageInfo.js |
FlowPhaseBanner 的階段資訊 / 前置查詢 |
src/config/locales/i18n/{zh-tw,en}/ap-authoring.json・ap-docx-import.json |
頁面 i18n(含 AUDIT_METHOD 標籤 method_*) |
8. 後端檔案地圖(本頁核心鏈路)
| 鏈路 | Route | App Service | 底層 |
|---|---|---|---|
| AP 明細 | api/project/routes/audit_round_route.py::AuditRoundApRoute(GET
/audit-round/{uid}/ap) |
assessment_plan_app_service.py::get_ap_for_round →
_ap_detail |
AP / reviewed-controls / tasks / activities / task-subjects / task-participants 各 repo(jedi_oscal_v2)組裝 |
| 行程寫入 | 同檔 ApTasksRoute |
set_tasks(建 activity + task + link
表,_backfill_scope_from_tasks 回填範圍) |
AssessmentPlanService.set_tasks(v2)+
ap_task_subjects / ap_task_participants
repo |
| 受評範圍 | 同檔 ApReviewedControlsRoute /
ApAssessmentSubjectsRoute |
set_reviewed_controls /
set_assessment_subjects(皆
resolve_ap_and_check_auditor +
assert_round_phase) |
v2 AP repo |
| 稽核人員 | 同檔 ApPartiesRoute |
list_ap_parties / add_ap_party(掛 AP
metadata_id,同名檢查) |
PartyRepoImpl(oscal.parties,scope=metadata_id) |
| 生成草稿 | 同檔 AuditRoundApGenerateDraftRoute |
generate_draft_for_round →
create_draft_for_snapshot(v2) |
凍結 SSP → AP clone |
| 階段推進 | api/flow_engine/routes/stage_advance_route.py |
app/flow_engine/service/stage_advance_service.py +
oscal_stage_handlers.py::SubmitApOnCompleteHandler |
前置
ApReviewedControlsSetCheck(oscal_stage_preconditions.py:40-62)→
start_auditing |
DDD 提醒:AP 寫入 API 都照層級走(route 不碰 DB、app
service
@transaction、resolve_ap_and_check_auditor +
assert_round_phase 雙檢查)——這是本群 phase-guard
的正確樣板,新增本群寫入 API 照抄。
9. DB
9.1 資料表總清單(本頁讀寫的全部表)
| 表 | 讀/寫 | 說明 | 欄位詳述 |
|---|---|---|---|
| compliance.project_audit_rounds | 讀 | 稽核輪次主檔(狀態 / assessment_plan_id / 凍結
ssp_id) |
見 project-planning §9.3 |
| compliance.projects / project_participants | 讀 | 專案主檔 / 參與者角色(權限判定) | GAI-SD-03 |
| oscal.system_security_plans | 讀 | 凍結 SSP 快照(控制項 / 資產母體) | GAI-SD-03 |
| oscal.assessment_plans | 讀 | AP 文件 root(import_ssp_id → 凍結 SSP) |
§9.3 |
| oscal.ap_reviewed_controls | 寫 | 查核範圍(1:1,行程回填) | §9.3 |
| oscal.ap_tasks | 寫 | 行程(timing / type,全量覆寫) | §9.3 |
| oscal.ap_assessment_activities | 寫 | 查核方法(activity:props method / steps / related-controls) | §9.3 |
| oscal.ap_assessment_subjects | 寫 | 抽查對象(AP 層彙整) | §9.3 |
| oscal.ap_task_subjects | 寫 | 行程層受評對象 link(FR-040) | §9.3 |
| oscal.ap_task_participants | 寫 | 行程層參與人員 link(FR-040) | §9.3 |
| oscal.metadata | 讀/寫 | AP 文件 metadata(parties 掛此下) | GAI-SD-03 |
| oscal.parties | 寫 | 稽核人員(就地新增;掛 AP metadata_id) | §9.3 |
9.2 ER 圖(本頁讀寫範圍)
9.3 核心表欄位(取自 DEV DB dump,含 DB comment)
oscal.assessment_plans — AP 文件 root
一份 AP = 「要評估哪份 SSP、評估哪些控制項、用什麼活動與排程」。GRC 專案啟動時即建立並從 Profile clone 控制項。required=[uuid, metadata, import-ssp, reviewed-controls]。
| 欄位 | 型別 | 說明 |
|---|---|---|
| uuid | uuid | OSCAL AP 文件識別碼 |
| metadata_id | bigint | → oscal.metadata(title / version;parties 掛此下) |
| status | varchar(20) | 產品生命週期(draft/published/deprecated) |
| import_ssp_id | bigint | → oscal.system_security_plans(凍結 SSP,NOT NULL;ERD 實線 anchor) |
| local_definitions_remarks | text | local-definitions 補充;objectives → ap_local_objectives、activities → ap_assessment_activities |
oscal.ap_reviewed_controls — 查核範圍(1:1)
assessment-plan.reviewed-controls(AP root
required):本次評估涵蓋哪些控制項。對 AP root 是 required
[1]——建 AP 時必同 transaction 建一筆(應用層保證)。
| 欄位 | 型別 | 說明 |
|---|---|---|
| assessment_plan_id | bigint | 1:1 → assessment_plans |
| control_selections | jsonb | [必填] select-control-by-id[](include/exclude/matching) |
| control_objective_selections | jsonb | 評估目標選取 |
oscal.ap_tasks — 行程(task)
assessment-plan.tasks[]:評估工作項。required=[title,
type, uuid]。
| 欄位 | 型別 | 說明 |
|---|---|---|
| uuid | uuid | 自身身分 |
| parent_id | bigint|null | self-FK;NULL=頂層 task |
| type | varchar(40) | milestone / action(開放 token) |
| title / description | text | 標題 / 備註 |
| timing | jsonb | 執行時點({on-date{date}} /
{within-date-range} / {at-frequency}
三選一) |
| associated_activities | jsonb | 關聯 activity(method 的載體,{activity-uuid}) |
| subjects | jsonb | OSCAL 兜底;真相在 ap_task_subjects link 表 |
oscal.ap_assessment_activities — 查核方法(activity)
local-definitions.activities:可重用評估活動。查核方法存
props({name:method, value:EXAMINE…})、per-方法指引存
steps、鉤稽控制項存
related_controls。required=[description, uuid]。
| 欄位 | 型別 | 說明 |
|---|---|---|
| uuid | uuid | 自身身分(task.associated_activities 指向) |
| description | text | [必填] |
| steps | jsonb | 評估步驟(per-方法查核指引) |
| related_controls | jsonb | reviewed-controls 子集 |
| props | jsonb | 查核方法(method name/value) |
oscal.ap_assessment_subjects / ap_task_subjects — 抽查對象
ap_assessment_subjects(AP 層彙整)與
ap_task_subjects(FR-040 行程層
link,task.subjects[] 的 SoT)欄位對稱:
| 欄位 | 型別 | 說明 |
|---|---|---|
| subject_type | varchar(40) | component / inventory-item / location / party / user |
| subject_uuid | uuid | 指向 SSP 快照物件的 uuid(軟參照不建 FK) |
| include | boolean | 是否納入查核(抽查 = 只勾其中幾筆) |
| title | text | 顯示用快照名(建立時帶入) |
oscal.ap_task_participants — 行程參與人員(FR-040)
task.responsible-roles[] 的 SoT。
| 欄位 | 型別 | 說明 |
|---|---|---|
| task_id | bigint | → ap_tasks |
| party_uuid | uuid | 參與人員 party uuid(軟參照 oscal.parties) |
| role_id | varchar(40) | OSCAL role-id(assessor…) |
oscal.parties — 稽核人員
metadata.parties[]:以 metadata_id 掛在 AP
文件下。就地新增的稽核人員即寫此表。
| 欄位 | 型別 | 說明 |
|---|---|---|
| metadata_id | bigint | → oscal.metadata(AP 的 metadata) |
| uuid | uuid | party 全域識別碼(task participants 軟參照) |
| type | varchar(20) | person / organization |
| name | text | 正式全名 |
| email_addresses | text[] | email 清單(純量陣列,非 JSONB) |
| telephone_numbers | jsonb | 電話清單 |
10. 頁面邏輯與資料對應
載入時序:
關鍵欄位對應(畫面 ↔︎ API):
| 畫面元素 | FE state | API 欄位 |
|---|---|---|
| 行程卡陣列 | tasks[]({title, type, date, methods, controls, subjects, participants, stepGuidance, description}) |
AP tasks[];date ↔︎
timing.on-date.date(帶時區) |
| per-方法查核指引 | tk.stepGuidance[method] |
task.steps [{method, description}] |
| 受評控制項彙整(Tab1) | derivedControlIds(computed,行程 controls
聯集去重) |
回填後 = reviewed_controls |
| 受評對象彙整(Tab2) | derivedSubjectGroups(computed,按類型分組) |
回填後 = assessment_subjects |
| 稽核人員下拉 | apParties[] |
GET /ap/{apUid}/parties |
| Banner | stage/info 回傳 |
precondition.passed(reviewed-controls 非空) |
儲存流程:「儲存行程」= 單一
PUT /ap/{apUid}/tasks 全量覆寫,BE
連帶回填受評範圍;saveTasks 後前端依日期重排行程並更新
state(不重拉)。受評控制項 / 對象兩 tab 是 computed
投影,切過去才看到最新彙整(無自動刷新)。就地新增稽核人員:POST 後
fetchApParties() 重載並自動選入觸發行程。
錯誤對應:BE error envelope → toast;常見碼
GRC_NOT_AUDITOR(403,非稽核員)、GRC_ROUND_PHASE_READONLY(412,過階段)、GRC_AP_REVIEWED_CONTROLS_REQUIRED(412,查核控制項空)、GRC_AP_PARTY_NAME_EXISTED(409,稽核人員同名)。
11. 背景行為與外部依賴
| 類型 | 內容 |
|---|---|
| 通知 | 本頁 AP 編輯無站內通知(通知在啟動任務執行與階段推進時) |
| BPMN | audit_planning 階段推進(「啟動稽核」)= BPMN 引擎前進;前置 handler
SubmitApOnCompleteHandler 呼
start_auditing;handler 副作用先於 BPMN 推進、同
transaction 失敗全 rollback |
| Socket | 本頁無 socket / 輪詢;儲存後靠 state 更新與手動重載 |
| jedi-* 套件 | jedi-oscal-v2(AP repo /
AssessmentPlanService)、jedi-flow-engine(stage
advance)、jedi-auth(JWT) |
| 系統參數 | 查核方法下拉來自 system_menu 的
AUDIT_METHOD;無 feature flag |
12. 邊界情況與已知坑
- phase guard BE 硬擋:AP 寫入只在 audit_planning,過階段直接打 API 也回 412(與專案規劃頁 SSP 寫入可繞過不同,見 _overview §5 坑 2)
- 行程是唯一編輯面,受評範圍是投影:受評控制項 /
對象兩 tab 唯讀,由
_backfill_scope_from_tasks從行程聯集回填;想加控制項要去行程勾,不是在 Tab1 加 - 全量覆寫語意:
PUT /ap/{apUid}/tasks送出的陣列即最終狀態——漏帶某行程 = 刪除該行程;reviewed-controls 送[]會被 412 擋(不可為空) - timing 正規化:FE 單一 Calendar → 一律送
{on-date:{date: ISO 帶時區}};BE 可能回within-date-range,FE 讀取時取第一個可用字串(RoundApAuthoringView.vue:490-509) - subject registry 是記憶體 map:行程對象標籤靠
subjectRegistry快取,候選未預載時可能顯示 UUID 而非名稱 - 就地新增稽核人員 vs SSP parties:AP parties(稽核人員,可就地新增)與 SSP parties(受評方人員,唯讀)是兩組;FE 無交叉使用防呆,BE 靠 metadata_id scope 分離
- 方法 i18n 缺翻譯顯示原始碼:system_menu 新增方法時
FE 直接顯示,但
lang.ap_authoring.method_<value>缺 key 前顯示原始 value(如EXAMINE) - engagement 共用 AP:覆核輪(close-out)不另開
AP,
launch-reverify走clone_ap_for_round(party uuid 依 name remap);generate-draft 對 close-out 輪擋下 - date-only 顯示 08:00 陷阱:行程時間欄位若吐
YYYY-MM-DDTHH:MM:00無 tz,前端顯示留意(見 專案管理群 _overview 慣例)
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/ 部署文件) - 導航路徑:登入 → 專案 → 進入 audit_planning 狀態的輪次 → 稽核計畫填寫
- 前置資料:輪次需已
launch-audit(有凍結 SSP + AP);沒有 AP 先generate-draft或走 launch-audit 自動生成 - E2E:
compliance-manager-test/repo(Cucumber + Playwright);以稽核計畫/ap-authoring搜尋 - 相關文件:FR-038(v2
遷移,
docs/features/FR-038-2606-oscal-redesign/)、FR-040(行程鉤稽模型);稽核執行頁見 稽核執行頁 / AR 判定;DB / API 全量見 GAI-SD-02/03