給下一個 FE session 用。複製整段「〇、起手語」往下到 session 開頭。 Phase B(BE 全做完,5 commits 待 push)的細節在最後段 §六「Phase B 已交付摘要」可查。
我要在新 FE session 接 Spec 2「階段抽象整合」Phase C — FE Banner 元件 + composable + service。 保持 BE 主導模式(與 Spec 1 / Phase B 同 pattern;BE 已先做完,FE 只接 API)。
Phase B 5 commits 已上 BE branch feature/project-flow-engine-integrate(領先 origin 5 個 commit,user 視 smoke test 結果決定 push 時機):
| Commit | 內容 |
|---|---|
180be60 |
B.1+B.2:OSCAL Stage Handlers + Preconditions(4+3 個 Singleton 註冊到 stage_registry) |
6a3eea5 |
B.3:StageAdvanceService + complete_main_workflow_job |
a7fd578 |
B.4:Stage Advance Route + Schemas |
186828e |
B.5:start_oscal_project Step 22(建 AP 同步啟動 main workflow + 寫 AP ext) |
4646b4c |
B.6:刪除暫態 ExtAssessmentPlanRepo + EndEvent reconciliation |
Base URL prefix:/api/1.0
| Method | URL | Body / Query | Response data shape |
|---|---|---|---|
| GET | /project/<project_uid>/ap/<ap_uid>/stage/info |
– | StageInfoResponseSchema |
| POST | /project/<project_uid>/ap/<ap_uid>/stage/advance |
{ "force": bool, "ctx": {} } |
StageAdvanceResponseSchema |
{
"status": true,
"data": {
"current_stage": {
"code": "planning",
"name_i18n": {"zh_Hant_TW": "規劃", "en": "Planning"},
"kind": "routed",
"complete_button_label_i18n": {"zh_Hant_TW": "啟動專案", "en": "Activate"},
"complete_handler_key": "activate_project",
"precondition_key": null,
"main_roles": ["manager"]
},
"user_can_advance": true,
"user_role": "manager",
"precondition": {
"passed": true,
"reason_i18n_key": null,
"context": {}
},
"progress": [
{"code": "planning", "name_i18n": {"zh_Hant_TW": "規劃"}, "status": "current"},
{"code": "task_execution", "name_i18n": {"zh_Hant_TW": "執行任務"}, "status": "pending"},
{"code": "audit", "name_i18n": {"zh_Hant_TW": "稽核"}, "status": "pending"},
{"code": "poam", "name_i18n": {"zh_Hant_TW": "缺失改善"}, "status": "pending"}
],
"workflow_execution_uid": "...",
"workflow_status": "PROCESSING",
"job_id": "UserTask_planning"
}
}{
"status": true,
"data": {
"advanced": true,
"handler_result": {"ap_uid": "...", "status": "active", "notified_count": 3},
"current_stage_info": { ... 同上 stage/info 結構 ... }
}
}如果 handler 返回 warning(如 launch_audit 在有未完成 task 時且 force=false):
{
"status": true,
"data": {
"advanced": false,
"handler_result": {
"warning": true,
"incomplete_tasks": 12,
"message": "尚有 12 個未完成的任務,確認要啟動稽核?"
},
"current_stage_info": { ... }
}
}FE 收到 advanced=false + handler_result.warning=true → 開 ConfirmDialog 讓 user 二次確認;確認 → 再次 POST 同 endpoint 帶 {"force": true}。
| Status | error code | 情境 | response data 額外欄位 |
|---|---|---|---|
| 412 | GRC_412021 (GRC_STAGE_PRECONDITION_FAILED) |
precondition fail 且 force=false |
data.context 含 reason_i18n_key + context |
| 403 | GRC_403050 (GRC_STAGE_ROLE_FORBIDDEN) |
user 角色不符 stage main_roles | – |
| 404 | GRC_404029 (GRC_AP_NO_WORKFLOW_BINDING) |
AP 沒綁 workflow_execution(既有 AP 未跑 Step 22 backfill 才會發生) | – |
| 400 | GRC_400052 (GRC_STAGE_OBJECT_NOT_BOUND) |
BPMN UserTask 沒 stage_object_code extension property |
– |
| 400 | GRC_400051 (GRC_STAGE_HANDLER_NOT_REGISTERED) |
stage_object.complete_handler_key 對應 handler 沒註冊 | – |
Phase C 範圍(implementation-plan.md §五):
| Sub | 內容 | Plan §參照 |
|---|---|---|
| C.1 | API service:src/service/StageService.js(繼承 BaseService) |
§C.1 |
| C.2 | Composable:src/composables/useStageInfo.js |
§C.2 |
| C.3 | 元件:src/components/grc/FlowPhaseBanner.vue + StageProgressBar.vue + i18n 補齊 |
§C.3 |
Plan 建議 C.1+C.2+C.3 包成 一個大 commit(內聚性高,難拆);可視實際進度視情況拆 2 個 commit(service+composable / 元件)。
| Sub | 內容 |
|---|---|
| D.1 | ProjectSettingsView.vue 頂部加 Banner,拆「啟動專案」按鈕 |
| D.2 | ProjectAuditorOverview.vue 頂部加 Banner,拆「啟動稽核」按鈕(4 個導航按鈕不動) |
| D.3 | AuditReviewView.vue 頂部加 Banner,拆「提交稽核」按鈕 |
| D.4 | PoamView.vue 頂部加 Banner,拆「完成改善」按鈕 |
| D.5 | MyTasksView.vue 不掛 Banner(spec 明確) |
| D.6 | i18n 補齊 + docs/claude/frontend-overview.md 加 Banner 元件條目 |
BE 接口完整 spec(最重要):
~/Projects/Billows/Audit-Manager/compliance-manager-be/docs/changelog/
2026-05-12-feat-spec2-phase-b4-stage-advance-route.md
含 2 endpoint 完整 request / response / error 範例。
整體脈絡 + 6 條決議:
~/Projects/Billows/Audit-Manager/compliance-manager-be/docs/features/
project-flow-engine-integrate/02-stage-integration/design.md
特別看 §四 Banner 元件設計、§五 互動規格、§9 決議。
Phase C 詳細計畫:
~/Projects/Billows/Audit-Manager/compliance-manager-be/docs/features/
project-flow-engine-integrate/02-stage-integration/implementation-plan.md
§五(Phase C)全段。
FE 既有規範速查:
~/Projects/Billows/Audit-Manager/compliance-manager-be/docs/claude/frontend-overview.md
API 慣例、design tokens、可重用元件、composables、stores。
FE 工作目錄:
~/Projects/Billows/Audit-Manager/compliance-manager-fe/
含獨立 CLAUDE.md(FE 規範以該 file 為準)。
FE 既有 API service 範例(C.1 mirror pattern):
src/service/ 下任一 GRC service(例:ProjectService.js、AuditService.js)— 確認 BaseService 用法、URL placeholder 替換、return 值結構src/config/api/api.js — API endpoint 常數定義FE 既有 i18n files:
src/i18n/zh-tw.js / src/i18n/en.js — 需新增 stage_object name + button label + 4 個 precondition reason key新增 src/service/StageService.js:
getStageInfo(projectUid, apUid) → GET /project/:projectUid/ap/:apUid/stage/infoadvanceStage(projectUid, apUid, payload) → POST /project/:projectUid/ap/:apUid/stage/advance更新 src/config/api/api.js 加 2 個常數:
STAGE_INFO: '/project/:projectUid/ap/:apUid/stage/info',
STAGE_ADVANCE: '/project/:projectUid/ap/:apUid/stage/advance',⚠ FE BaseService 的 return 慣例請參考既有 service(有些 service 解開 envelope .data,有些直接傳整個 response)— 沿用同模組已有 pattern,不要新發明。
新增 src/composables/useStageInfo.js:
export function useStageInfo(projectUid, apUid) {
const stageInfo = ref(null)
const loading = ref(false)
const error = ref(null)
async function fetchStageInfo() { ... }
async function advance({ force = false, ctx = {} } = {}) {
// POST → 若 response.advanced=false 且 handler_result.warning=true →
// emit 'needs-confirmation' event 給呼叫端開 ConfirmDialog;
// 確認後 caller 再次呼叫 advance({ force: true })
}
return { stageInfo, loading, error, fetchStageInfo, advance }
}新增 src/components/grc/FlowPhaseBanner.vue:
project-uid: String + ap-uid: StringuseStageInfo(projectUid, apUid)t(reason_i18n_key, context)advance({ force: true })fetchStageInfo refresh banner + emit stage-advanced 給父 view(讓父 view refresh 自己的資料)StageProgressBar.vue(純展示 4 dot + label,CSS only)// src/i18n/zh-tw.js / en.js 新增
flow_engine: {
precondition: {
tasks_not_complete: '尚有 {incomplete} / {total} 個任務未完成',
verdict_incomplete: '尚有 {missing} / {total} 個控制項未填判定',
poam_not_all_closed: '尚有 {not_closed} / {total} 個缺失未結案',
ap_not_found: '找不到稽核計畫',
ar_not_found: '找不到稽核結果',
ar_data_not_found: '找不到稽核資料',
},
}⚠ stage_object 的 name_i18n / complete_button_label_i18n 由 BE 直接回 dict(多語),FE 依當前 locale 取對應字串即可,不需另設 i18n key。Locale key 是 zh_Hant_TW / en(不是 zh-tw,這是 Reconciliation #2)。
activate_project / launch_audit / confirm_audit / close_round(無前綴);DB seed 已對齊;FE 不直接用 handler key 做判斷邏輯(FE 看 stage_code + i18n label 就好)。zh_Hant_TW,不是 zh-tw — BE 回的 name_i18n dict key 是 zh_Hant_TW。FE 取值前若要 normalize:const label = info.current_stage.name_i18n[currentLocale.replace('-','_')] || info.current_stage.name_i18n['zh_Hant_TW']。complete_job 不適合 main workflow — BE 已加 complete_main_workflow_job 平行 method(B.3)。FE 無感,沿用 /stage/advance endpoint 即可。flow_templates 沒 stable code 欄位 — BE Step 22 用 hardcode "完整稽核流程" 找預設範本。FE 無感;未來 Spec 3 範本 wizard 才會需要 code 欄位。~/Projects/Billows/Audit-Manager/compliance-manager-be/log/app.log — FE 任何 BE call 異常都先 grep 這個192.168.50.188:25432 / guidant_ai_dev,cmmgr 帳號(密碼 jedi@123!)~/Projects/Billows/Audit-Manager/compliance-manager-fe/...cd ~/Projects/Billows/Audit-Manager/compliance-manager-fe && npm run dev(如未已起 dev server)依 ~/Projects/Billows/Audit-Manager/compliance-manager-fe/CLAUDE.md 規範。重點摘要(FE CLAUDE.md 為準):
Phase C 完成(service + composable + 元件 + i18n)後,在本目錄 02-stage-integration/ 內產出 handoff-prompt-phase-d.md(mirror 本檔格式),交給下一個 FE session 做 Phase D(4 個 view 掛 Banner + 拆按鈕)。
或本 session 直接接 Phase D(D.1~D.6,5 commits)— 視 context budget 而定。
zh_Hant_TW(非 zh-tw)— Phase C 上下傳遞時注意 normalizecomplete_job AP-task 假設 → 新增平行 complete_main_workflow_job — Phase B.3 已落地flow_templates 無 code 欄位 → 單點 hardcode "完整稽核流程" — Phase B.5 已落地Phase C / D 完成後若有新 reconciliation,補進 design.md §十 段(mirror Spec 1 §九 pattern)。
| 範圍 | 檔案位置 |
|---|---|
| 4 個 stage handler | app/grc/service/oscal_stage_handlers.py |
| 3 個 precondition check | app/grc/service/oscal_stage_preconditions.py |
| StageAdvanceService | app/flow_engine/service/stage_advance_service.py |
| Route + Schema | api/flow_engine/routes/stage_advance_route.py / api/flow_engine/serializers/stage_advance.py |
| Step 22 (build AP → start workflow → write ext) | app/project/service/oscal_project_service.py:_bind_main_workflow_to_ap |
| DI registration | di_containers/grc/grc_containers.py:register_stage_hooks_to_registry (called from core/app_factory.py after wire) |
| 6 個 error code | common/code/grc_error_code.py (GRC_412021 ~ GRC_400052) |
| DB schema | compliance.assessment_plan_extensions (1:1 of oscal.assessment_plans),已 backfill 149 列 |
| Stage object seed | compliance.stage_objects 4 列含 handler_key + precondition_key + default_main_roles |
| Builtin BPMN | compliance.flow_templates 含「完整稽核流程」(Process_builtin_full_audit) 4 個 UserTask 帶 stage_object_code + main_role extension property |
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be
git log --oneline origin/feature/project-flow-engine-integrate..HEAD
# 預期:5 commitsgit push origin feature/project-flow-engine-integrate 由 user 決定時機,FE session 不主動 push BE。
依 2026-05-12-feat-spec2-phase-b1-b2-handlers-preconditions.md ~ 2026-05-12-tweak-spec2-phase-b6-delete-legacy-ext-ap-repo.md 6 個 changelog 內提到的 test 項目:
lsof -ti :8000 | xargs -r kill -9 && python main_socketio.py/api/oscal/projects/startSELECT workflow_execution_uid, flow_template_snapshot_uid FROM compliance.assessment_plan_extensions WHERE assessment_plan_id = <new_ap_id>; 預期非 NULL/api/1.0/project/<uid>/ap/<apUid>/stage/info:預期 current_stage.code='planning' + user_can_advance=true(manager 帳號){"force": true} → 200FE session 不需親跑這些,但若 Banner 元件行為怪異請先確認 user 已跑過上述基本 smoke。