手冊首頁 / 共用元件 / 階段推進橫幅

階段推進橫幅(FlowPhaseBanner)

共用元件|出現在多個稽核輪次生命週期頁的頂部(規劃 / 總覽 / 稽核計畫填寫 / 覆核 / 缺失改善)

事實基準:2026-07-19 從 FE / BE code 掃出(FR-050 階段回退補充);endpoint 對 routes.json、欄位對 marshmallow serializer 逐條核

變更紀錄

日期 FR 變更
2026-07-06 FR-047 從 project-planning.md 抽出成共用元件 spec
2026-07-19 FR-050 新增「返回上一階段」回退功能:manager only + reason 必填 Dialog(白名單 ap_authoring/audit/poam 三階段可退,planning 為鏈頭無上一步不開放);新增階段歷程時間軸展開區(advance/rollback 雙色列表);新增 stage/rollbackstage/transitions 兩 endpoint

1. 功能描述

FlowPhaseBanner 是稽核輪次階段推進的共用 UI 元件(FlowPhaseBanner.vue),固定在生命週期頁頂部。它把當前輪次的 BPMN 流程狀態呈現成一條階段軸(規劃 → 稽核計畫填寫 → 稽核 → 缺失改善),標出目前階段、各階段完成狀態、以及「推進到下一階段」的前置條件與可否推進。推進時呼叫後端 stage/advance,由 handler 執行副作用(如凍結 SSP、開新輪)後再驅動 BPMN 前進——副作用與 BPMN 前進在同一 transaction,失敗全 rollback

因為同一條輪次狀態機貫穿多個頁面,此橫幅在各頁重複出現、行為一致,故抽成單一元件 spec;各頁只引用本頁、不重複描述機制(見 §1.2)。輪次 7 態狀態機(含轉換圖)見 _overview §2

FR-050(2026-07-19)新增「返回上一階段」回退能力:manager 可在 ap_authoring / audit / poam 三個階段將輪次退回相鄰上一步(planning 是鏈頭無上一步,不開放)。回退會觸發副作用復原(frozen SSP / AP 草稿 / POA&M 標記 superseded,不物理刪)+ BPMN job 復原(revert_job)+ round.status 回寫,同一 transaction 失敗全 rollback;每次 advance 或 rollback 都落一筆到「階段歷程時間軸」供稽核追溯。

主要使用者:該 stage 的 main_roles(BPMN 範本定義,多為 auditor / manager);專案 manager 可全域代行推進、亦是回退唯一允許角色。

角色速覽(完整定義見 專案管理 _overview §3):

角色 一句話
manager 專案經理 — 可全域代行推進任一 stage(含 force);回退唯一允許角色
main_roles 該 stage BPMN 定義的負責角色 — 前置通過才可推進
參與者 其餘 — 只看得到進度,不能推進、不能回退

1.2 嵌入此元件的頁面(各頁只引用、不重複描述)

頁面 用途
專案規劃頁 planning 階段主工作區頂部
專案總覽頁 輪次總覽頁頂部
稽核計畫填寫 AP 撰寫階段推進
稽核覆核 稽核 / 覆核階段(含 review 型 decision)
POA&M 缺失改善 缺失改善階段推進 / finalize

各頁的「階段推進」描述一律指回本頁;頁內只保留「本頁對應哪個 stage、推進後去哪」的一句話上下文。

2. Use Case

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

UC-FB-01 推進階段

項目 內容
角色 該 stage 的 main_roles;manager 可全域代行
前置條件 stage 的 precondition handler 通過(如任務執行完成度);banner 顯示 user_can_advance
產出 / 後置條件 handler 副作用先行(同 transaction),成功則 BPMN 前進一個 UserTask、project_audit_rounds.status 同步;失敗全 rollback
uc_pp_04 start info Banner 載入 GET .../stage/info (當前階段+進度點+前置條件) start->info pre precondition 通過? info->pre blocked 按鈕禁用+顯示原因 (reason_i18n_key,如 GRC_412035) pre->blocked click 點推進按鈕 POST .../stage/advance pre->click role 使用者角色 ∈ 該階段 main_roles? (專案 manager 可全域代行) click->role deny 403 GRC_403009 role->deny review review 型 stage? role->review decide 帶 decision(approve/reject) reject 需 comment → 寫 job_comments review->decide handler Step1:complete handler 副作用 (寫 OSCAL 狀態,@transaction) review->handler decide->handler fail handler 失敗 → 全部 rollback BPMN 不推進 handler->fail 例外 bpmn Step2:BPMN 引擎前進 完成當前 UserTask → 下一個 handler->bpmn 成功 sync Step3:round.status 同步升級 planning → audit_planning 本頁轉唯讀 bpmn->sync
UC-FB-01 流程:前置條件→角色→(review 型帶 decision)→handler 副作用先行、失敗全 rollback→BPMN 前進→輪次狀態同步

UC-FB-02 返回上一階段(回退,FR-050)

項目 內容
角色 manager only(無 main_roles 代行概念,不同於推進)
前置條件 reason 非空白字串;round.statusclosedround.status 落在回退邊界白名單(audit_planning/auditing/remediation);registry 查得到對應 handler
產出 / 後置條件 handler 副作用復原(SSP/AP/POA&M 標 superseded,不物理刪)→ 落 round_stage_transitions(direction=rollback)→ BPMN revert_job 復原 → round.status 回寫上一階段 → _sync_project_status;同一 transaction,任何一步失敗全 rollback
uc_fb_02 start click 點「返回上一階段」 (僅 ap_authoring/audit/poam 顯示) start->click dialog Dialog:填寫回退原因(reason,必填) click->dialog submit 送出 POST .../stage/rollback {reason, ctx} dialog->submit isMgr BE 檢查:使用者是專案 manager? submit->isMgr denyMgr 403 GRC_NOT_MANAGER isMgr->denyMgr hasReason reason 非空白字串? isMgr->hasReason denyReason 400 GRC_400096 (GRC_ROUND_ROLLBACK_REASON_REQUIRED) hasReason->denyReason isClosed round.status == closed? hasReason->isClosed denyClosed 412 GRC_412047 (GRC_ROUND_ROLLBACK_NOT_ALLOWED) isClosed->denyClosed boundary round.status ∈ 回退邊界白名單? (audit_planning/auditing/remediation) isClosed->boundary denyBoundary 412 GRC_412047 (GRC_ROUND_ROLLBACK_NOT_ALLOWED) boundary->denyBoundary hasHandler registry 查得到對應 rollback handler? boundary->hasHandler denyHandler 400 GRC_400097 (GRC_ROUND_ROLLBACK_HANDLER_NOT_REGISTERED) hasHandler->denyHandler handler Step1:handler 副作用復原 (AuditRoundAppService.rollback_to_*: SSP/AP/POA&M 標 superseded、round.status 回寫) hasHandler->handler transition Step2:落 round_stage_transitions (direction=rollback,reason 落表) handler->transition bpmn Step3:BPMN 復原 WorkflowExecutionService.revert_job (bypass_round_frozen_gate=True) transition->bpmn sync Step4:_sync_project_status 輪次狀態同步、Banner 重載新 stage info bpmn->sync
UC-FB-02 流程:manager 檢查→reason 必填→closed 擋→邊界白名單→handler 查無擋→副作用復原→落時間軸→BPMN revert_job→輪次狀態同步

3. 權限矩陣

操作 FE 判定 BE 強制 BE 檢查位置
讀階段資訊 參與者即可 隨頁面權限 stage_advance_service.get_current_stage_info
推進階段 banner user_can_advance stage main_roles(manager 代行)→ 不符 GRC_403050GRC_STAGE_ROLE_FORBIDDEN);force 非 manager → GRC_403002 app/flow_engine/service/stage_advance_service.py:286-304
前置不過 按鈕禁用帶原因 precondition handler → 不過 GRC_412021GRC_STAGE_PRECONDITION_FAILED 同上(_run_precondition,約 :307-314
讀階段歷程時間軸 參與者即可(同讀階段資訊) 隨頁面權限 audit_round_app_service.list_stage_transitions
回退階段(FR-050) banner isManager && canRollback(FE 白名單鏡像 BE,見 §12 坑1) manager only → 非 manager GRC_NOT_MANAGER(403);reason 空 → GRC_400096;closed 輪次或狀態不在白名單 → GRC_412047;handler 未註冊 → GRC_400097 app/flow_engine/service/stage_rollback_service.py:90-133

4. 狀態機與前置條件

輪次 7 態狀態機見 _overview §2。本元件相關 gate:

條件 效果 出處
stage precondition handler 通過 banner 顯示可推進、按鈕啟用 stage_advance_serviceprecondition_key → handler)
precondition 不過 按鈕禁用 + precondition.reason_i18n_key 顯示原因;強推(force)→ GRC_412021 同上
review 型 stage 推進必帶 decision(approve/reject);reject 需 comment stage/advance request
使用者非 main_roles 且非 manager 無推進按鈕 user_can_advance=false
round.status{audit_planning, auditing, remediation} 該 stage 顯示「返回上一階段」按鈕(manager 可見);planning 為鏈頭無按鈕 stage_rollback_service.py _ROLLBACK_BOUNDARIES(FE 鏡像白名單見 FlowPhaseBanner.vue ROLLBACK_ELIGIBLE_STAGE_CODES
round.status == closed 回退入口不顯示;API 直打也擋 FE:無 banner(isFlowClosed);BE:GRC_412047
回退 reason 空白 送出鈕 disabled(FE);BE 再擋一次 FE !rollbackReason.trim();BE GRC_400096

5. UI 設計

版面骨架(元件解剖 + 代表性 API + 嵌入頁面,區塊可點):

FlowPhaseBanner 元件(頁面頂部橫幅,跨生命週期頁共用) 規劃(done) 稽核計畫填寫(current) 稽核(pending) 缺失改善(pending) 前置條件 precondition(passed / reason_i18n_key) 不過 → 按鈕禁用並顯示原因(如「任務執行未完成」) 返回上一階段 推進到下一階段 review 型 stage 必帶 decision=approve/reject;reject 需 comment 回退 Dialog(reason 必填,manager only) 未填原因送出鈕 disabled;確認鈕 danger 樣式 開啟:邊界情況與已知坑(時間軸相關坑) 階段歷程時間軸(展開區,StageTransitionTimeline.vue) 垂直清單:advance(藍)/rollback(橘,含 reason + operator_nickname),依 created_at 升冪 GET .../stage/transitions 代表性 API(完整見 §6): GET /project/{uid}/audit-round/{round_uid}/stage/info → 當前階段 + 前置 + 進度點 POST /project/{uid}/audit-round/{round_uid}/stage/advance → handler 副作用 + BPMN 前進(atomic) POST /project/{uid}/audit-round/{round_uid}/stage/rollback → 返回上一階段(FR-050,manager only) GET /project/{uid}/audit-round/{round_uid}/stage/transitions → 階段歷程時間軸(FR-050) 嵌入此元件的生命週期頁(各頁只引用、不重複描述機制): 開啟:專案規劃頁專案規劃頁 開啟:專案總覽頁專案總覽頁 開啟:稽核計畫填寫稽核計畫填寫 開啟:稽核覆核稽核覆核 開啟:POA&M 缺失改善POA&M 缺失改善 灰/紫=元件自身結構|虛線框=條件顯示層(前置不過禁用、review decision、回退 Dialog)|白框可點=嵌入本元件的頁面 API 僅列代表性,完整規格見 §6;階段狀態機(7 態轉換)見 _overview §2;橘字=FR-050 新增
FlowPhaseBanner 版面骨架:階段軸(progress 進度點)+前置條件層+推進/退回鈕(review 型)+回退鈕與 Dialog+階段歷程時間軸展開區+代表性 API+嵌入此元件的生命週期頁

📸 實機截圖(亮色模式):橫幅特寫見 專案規劃頁 §5planning-banner.png(規劃→稽核計畫填寫→稽核→缺失改善 階段軸)。

狀態呈現:階段軸的每個點依 progress[].status(done / current / pending)上色;current_stage 為 null 時(流程未開始或已結束)不顯示推進區、整個 Banner 不渲染(isFlowClosed);無 socket,推進 / 回退後由呼叫端重載頁面資料。

FR-050 回退 UI(2026-07-19)isManager && canRollback 為真時,動作區顯示「返回上一階段」按鈕(canRollback 依 FE 白名單 ap_authoring/audit/poam 判斷,鏡像 BE _ROLLBACK_BOUNDARIES,見 §12 坑1);點擊開 Dialog 要求填 reason(未填送出鈕 disabled),確認鈕 severity="danger"。時間軸展開鈕(pi-history icon-only)永遠顯示,點擊切換 StageTransitionTimeline.vue 展開區——垂直清單依 direction 上色(advance 藍 pi-arrow-right / rollback 橘 pi-replay),rollback 項額外顯示 reasonoperator_nickname

6. API 規格

Envelope:成功 {"status": true, "data": …}、失敗 {"error_code": "…", "msg": "…"}

6.1 總清單

分類 Method + Path 說明 完整規格
階段 GET /project/{uid}/audit-round/{round_uid}/stage/info 當前階段資訊 + 前置條件 + 進度點 §6.2
階段 POST /project/{uid}/audit-round/{round_uid}/stage/advance 推進階段(handler 副作用 + BPMN 前進,atomic) §6.2
回退(FR-050) POST /project/{uid}/audit-round/{round_uid}/stage/rollback 返回上一階段(manager only、reason 必填、handler 副作用復原 + BPMN 復原,atomic) §6.3
回退(FR-050) GET /project/{uid}/audit-round/{round_uid}/stage/transitions 階段歷程時間軸(advance+rollback,依 created_at 升冪) §6.3

6.2 核心 endpoint

[GET] /project/{project_uid}/audit-round/{round_uid}/stage/info

Response data

欄位 型別 說明
current_stage object|null {code, name_i18n, kind, complete_button_label_i18n, reject_button_label_i18n, complete_handler_key, precondition_key, main_roles[]};null = 流程未開始或已結束
user_can_advance / user_role bool / string 當前使用者可否推進、其角色
precondition object|null {passed: bool, reason_i18n_key, context} — 不通過時按鈕禁用並顯示原因
progress[] array 進度點:{code, name_i18n, status: done/current/pending}
workflow_execution_uid / workflow_status / job_id string|null BPMN 狀態

出處:api/flow_engine/serializers/stage_advance.py:56-66

[POST] /project/{project_uid}/audit-round/{round_uid}/stage/advance

Request:

欄位 型別 必填 說明
force bool 強制推進(限 manager)
decision string approve / reject——review 型 stage 必填
comment string reject 時必填,寫入 job_execution_comments
ctx dict handler 上下文

Response data

欄位 型別 說明
advanced bool 是否成功推進
handler_result handler 執行結果
current_stage_info object 推進後的新 stage info

出處:同檔 :8-27

6.3 回退 endpoint(FR-050)

[POST] /project/{project_uid}/audit-round/{round_uid}/stage/rollback

Request:

欄位 型別 必填 說明
reason string 回退原因(min length 1,前後端雙重必填檢查)
ctx dict 額外 context(如 user_nickname,route 層自動塞入)

Response data

欄位 型別 說明
rolled_back bool 是否成功回退
handler_result dict|null rollback handler 執行結果(AuditRoundAppService.rollback_to_* 回傳的輪次 DTO)

錯誤:

Error Code HTTP 情境
(沿用 GRC_NOT_MANAGER 403 非 manager
GRC_400096GRC_ROUND_ROLLBACK_REASON_REQUIRED 400 reason 空白
GRC_412047GRC_ROUND_ROLLBACK_NOT_ALLOWED 412 round.status == closed狀態不在回退邊界白名單(audit_planning/auditing/remediation)——route 進來的請求兩者皆走此碼(stage_rollback_service.py 兩個獨立 if)
GRC_412046GRC_ROUND_ROLLBACK_INVALID_STATE 412 app service 層 rollback_to_* 的狀態複驗分支(防併發競態雙保險)——單線程請求在 route 層即被 GRC_412047 擋下,正常流程打不到此碼
GRC_400097GRC_ROUND_ROLLBACK_HANDLER_NOT_REGISTERED 400 registry 查無對應 handler(理論上不應發生,防呆)

出處:app/flow_engine/service/stage_rollback_service.py:72-168;error code 定義 common/code/grc_error_code.py:338-341

[GET] /project/{project_uid}/audit-round/{round_uid}/stage/transitions

Response data:陣列,依 created_at 升冪排序

欄位 型別 說明
uid string 該筆歷程 uid
from_stage / to_stage string stage_objects.code(非 i18n dict,FE 自行對照顯示名稱)
direction string advance(推進)|rollback(退回)
operator string login_name
operator_nickname string|null 顯示用暱稱快照
reason string|null rollback 必有;advance 恆 null
created_at datetime

出處:app/grc/service/audit_round_app_service.py:696-717list_stage_transitions);serializer api/flow_engine/serializers/stage_rollback.py

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

檔案 角色
src/components/grc/FlowPhaseBanner.vue 本元件(階段軸 + 前置顯示 + 推進 / 退回鈕 + 回退按鈕與 Dialog + 時間軸展開切換;各生命週期頁 import)
src/components/grc/StageTransitionTimeline.vue 階段歷程時間軸子元件(FR-050,純展示,caller-driven:entries 由 Banner 透過 StageService.getStageTransitions 取得後傳入)
src/composables/useStageInfo.js stageInfo 狀態管理 + advance / rollback 方法封裝
src/service/StageService.js 呼叫 stage/info / stage/advance / stage/rollback(FR-050)/ stage/transitions(FR-050)

8. 後端檔案地圖(本元件核心鏈路)

鏈路 Route App Service 底層
階段資訊 / 推進 api/flow_engine/routes/stage_advance_route.py app/flow_engine/service/stage_advance_service.pyget_current_stage_info / advance_stage BPMN 當前 UserTask + compliance.stage_objects + handler registry(app/grc/service/oscal_stage_handlers.py
回退(FR-050) api/flow_engine/routes/stage_rollback_route.pyStageRollbackResource / RoundStageTransitionsResource app/flow_engine/service/stage_rollback_service.pyStageRollbackService.rollback_stage)+ app/grc/service/audit_round_app_service.pyrollback_to_planning / rollback_to_audit_planning / rollback_to_auditing / list_stage_transitions rollback handler registry(app/grc/service/oscal_stage_rollback_handlers.py)+ BPMN WorkflowExecutionService.revert_job(jedi-flow-engine,bypass_round_frozen_gate=True)+ compliance.round_stage_transitions / compliance.round_rollback_supersessions

DDD 提醒:推進 / 回退的 handler 副作用(凍結 SSP、開輪、標記 superseded 等)與 BPMN 前進/復原在同一 transaction,任何一步失敗整筆 rollback——維護 handler 時不可把副作用抽到 transaction 外。

9. DB

9.1 資料表總清單

讀寫 說明 詳述
compliance.stage_objects 階段行為定義(precondition / handler / main_roles / label i18n key) §9.3
compliance.project_audit_rounds 讀 / (status) 推進 / 回退後同步輪次狀態 規劃頁 §9.3
compliance.job_execution_comments (review reject) reject 時寫入 comment GAI-SD-03
compliance.round_stage_transitions / 讀 階段歷程時間軸(FR-050,advance+rollback 皆落表) §9.3
compliance.round_rollback_supersessions 回退時 SSP/AP/POA&M 作廢標記(FR-050,不物理刪) §9.3

9.3 核心表欄位

compliance.stage_objects — 階段行為定義

每個 BPMN stage 對應一列,定義該階段的前置條件 handler、完成 handler、負責角色與按鈕文案 i18n key。stage/infocurrent_stage 大部分欄位即取自此表。

欄位 型別 說明
code varchar stage 代碼(對應 BPMN UserTask)
name_i18n / *_button_label_i18n varchar 顯示文案 i18n key
kind varchar stage 導頁型別(routed=依 route_pattern 導頁 / stateful=站內完成);「review 型 stage」是另一軸,判斷依 code == 'review',非 kind
precondition_key / complete_handler_key varchar 前置條件 / 完成 handler 的 registry key
default_main_roles jsonb 該階段的 fallback 主要角色清單;實際生效的 main_roles(API 回傳)= BPMN UserTask 的 main_role property override 優先,無 override 才 fallback 此欄位(stage_advance_service.py:_resolve_main_roles

欄位以 db_schema.json 為準;stage_objects 為行為配置表,實際 handler 實作在 app/grc/service/oscal_stage_handlers.py 的 registry。

compliance.round_stage_transitions — 階段歷程時間軸(FR-050)

advance / rollback 皆落表;round_id soft-ref project_audit_rounds.id(不建 FK constraint,比照母表軟隔離慣例,見 migration scripts/sql/2026-07-19-fr050-round-stage-transitions.sql)。

欄位 型別 說明
uid varchar(36) 唯一識別
round_id bigint project_audit_rounds.id(soft ref)
from_stage / to_stage varchar(50) stage_objects.code
direction varchar(10) advance | rollback(DB CHECK 限定)
operator / operator_nickname varchar(255) login_name / 顯示暱稱快照
reason text rollback 必填(DB CHECK 強制非空白);advance 恆 NULL
created_at timestamptz

compliance.round_rollback_supersessions — 回退作廢標記(FR-050)

design §4.4 裁決選 B:本專案側標記表,不動 jedi-oscal-v2 PublishStatus 列舉;SSP/AP/POA&M 三種 entity 統一走本表,不物理刪、不改動套件層狀態欄。讀取封裝在 RoundRollbackSupersessionDomainService

欄位 型別 說明
uid varchar(36) 唯一識別
entity_type varchar(20) ssp | ap | poam(DB CHECK 限定)
entity_id bigint 依 entity_type 指向對應表 id(soft ref)
round_id bigint project_audit_rounds.id(哪一輪回退觸發的標記)
reason text 回退原因快照(與 round_stage_transitions.reason 同值,去正規化)
operator varchar(255) login_name
superseded_at timestamptz

10. 頁面邏輯與資料對應

畫面元素 FE state API 欄位
階段軸各點 stage.progress progress[].{code, name_i18n, status}
目前階段標題 stage.current_stage current_stage.name_i18n
推進按鈕啟用 canAdvance user_can_advance && precondition.passed
禁用原因 preconditionReason precondition.reason_i18n_key
退回按鈕(review 型) current_stage.kind reject_button_label_i18n
返回上一階段按鈕(FR-050) isManager && canRollback user_role === 'manager' && current_stage.code ∈ FE 白名單
時間軸展開內容(FR-050) transitionsStageTransitionTimeline entries) GET stage/transitions 回傳陣列

推進流程:按推進 → (review 型帶 decision/comment)→ POST stage/advance → handler 副作用 + BPMN 前進(atomic)→ 回新 current_stage_info,呼叫端重載頁面。

回退流程(FR-050):按「返回上一階段」→ Dialog 填 reason → POST stage/rollback → handler 副作用復原 + 落 round_stage_transitions + BPMN revert_job 復原(atomic)→ 重載 stage/infotransitionsStale 旗標由推進 / 回退共同標記,時間軸展開中即時重抓。

11. 背景行為與外部依賴

類型 內容
交易性 handler 副作用先於 BPMN 推進 / 復原,同一 transaction,失敗全 rollback
BPMN 推進 = jedi-flow-engine 驅動 BPMN 引擎前進一個 UserTask;回退(FR-050)= BE 層 WorkflowExecutionService.revert_job 驅動 BPMN 復原(含 task_survey EDITING 復原副作用),呼叫時傳 bypass_round_frozen_gate=True 繞過「規劃期才可退回」凍結 gate
socket (推進 / 回退後呼叫端重載)
依賴 jedi-flow-engine(BPMN)、compliance.stage_objects(行為配置)、handler registry(含 FR-050 rollback handler 分支)、compliance.round_stage_transitions / compliance.round_rollback_supersessions

12. 邊界情況與已知坑

  1. 副作用與 BPMN 前進同 transaction:handler(凍結 SSP / 開輪)失敗會連 BPMN 前進一起 rollback——不可把副作用移出交易,否則會出現「BPMN 前進了但副作用沒做」的不一致。
  2. review 型 stage 必帶 decisionkind=review 的 stage 推進若沒帶 decision(approve/reject)會被擋;reject 另需 comment(寫 job_execution_comments)。
  3. manager 全域代行 + force:manager 可對非自己 main_roles 的 stage 推進(force);審計上留意「誰推進了不屬於自己角色的階段」。
  4. current_stage 為 null 的兩種情境:流程未開始 vs 已結束都回 null,UI 需靠 progress[] 或輪次 status 區分,別只看 current_stage。
  5. FE 回退白名單是鏡像判斷,非 API 回傳旗標(FR-050)stage/info 沒有回傳「這個 stage 可否回退」的欄位,FE ROLLBACK_ELIGIBLE_STAGE_CODES = ['ap_authoring', 'audit', 'poam'] 是手動鏡像 BE _ROLLBACK_BOUNDARIES(key 是 round.status)——兩者維護時必須同步改,BE 白名單加減邊界時別漏改 FE 常數,否則會出現「按鈕顯示但一按就 412」或「符合條件卻不顯示」的落差。
  6. 只允許退回相鄰上一步,跨階段靠連按:v1 三條回退邊界(audit_planning→planning / auditing→audit_planning / remediation→auditing)都只退一步,不支援一次跳兩級;要退更早的階段須連續操作,每次各留一筆 round_stage_transitions
  7. 回退鐵則:不物理刪,一律作廢標記:SSP/AP/POA&M 回退時標記 superseded(round_rollback_supersessions)而非刪除,重推進會產生新的 snapshot/草稿;已填的 AR 矩陣在 auditing→audit_planning 回退時保留可見(非作廢,因內容仍要可編輯續填),與 SSP/AP/POA&M 的作廢語意不同,勿混淆。
  8. 回退繞過凍結 gaterevert_job 呼叫傳 bypass_round_frozen_gate=True,僅限本回退路徑;既有其他呼叫點保持 False 不受影響(維護時不可把這個 flag 誤用到非回退情境)。

13. 開發與驗證

  • 跑起來:起 BE + FE;登入見 .env / 部署文件測試帳號
  • 導航:任一嵌入頁(規劃 / 總覽 / 稽核計畫 / 覆核 / 缺失改善)頂部即見橫幅
  • 前置資料:需一個有 BPMN 流程綁定的輪次;測不同 stage 的前置 handler(如任務完成度未達 → 按鈕禁用帶原因)、測 review 型的 approve/reject
  • 回退測試(FR-050):manager 帳號在 ap_authoring/audit/poam 三階段各測一次回退(reason 必填、成功後時間軸多一筆 rollback 條目);非 manager 帳號確認按鈕不顯示;closed 輪次確認整個 Banner 不顯示;推進/回退交替操作確認時間軸即時刷新
  • 相關:輪次狀態機見 _overview §2;各嵌入頁見 §1.2;stage handler registry app/grc/service/oscal_stage_handlers.py;rollback handler registry app/grc/service/oscal_stage_rollback_handlers.py;FR-050 implementation-plan.md / design.md