Spec 2 Phase C 交接 Prompt — FE Banner + composable + service

給下一個 FE session 用。複製整段「〇、起手語」往下到 session 開頭。 Phase B(BE 全做完,5 commits 待 push)的細節在最後段 §六「Phase B 已交付摘要」可查。


§1

〇、起手語(直接複製這段給新 session)

我要在新 FE session 接 Spec 2「階段抽象整合」Phase C — FE Banner 元件 + composable + service。 保持 BE 主導模式(與 Spec 1 / Phase B 同 pattern;BE 已先做完,FE 只接 API)。

前置狀態:Spec 2 Phase B 已完成(BE)

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

⚠ BE → FE 接口已 freeze 的 2 個 endpoint(Phase B.4 產出)

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

StageInfoResponseSchema 完整範例(GET stage/info)

{
  "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"
  }
}

StageAdvanceResponseSchema(POST stage/advance)

{
  "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}

Error 範例

Status error code 情境 response data 額外欄位
412 GRC_412021 (GRC_STAGE_PRECONDITION_FAILED) precondition fail 且 force=false data.contextreason_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 沒註冊

主任務:Spec 2 Phase C — FE Banner 元件 + composable + service

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 / 元件)。

Phase D 預告(Phase C 完成後接 D,本 session 可不做)

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 元件條目

開工前必讀(依優先序)

  1. 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 範例。

  2. 整體脈絡 + 6 條決議

    ~/Projects/Billows/Audit-Manager/compliance-manager-be/docs/features/
    project-flow-engine-integrate/02-stage-integration/design.md

    特別看 §四 Banner 元件設計、§五 互動規格、§9 決議。

  3. Phase C 詳細計畫

    ~/Projects/Billows/Audit-Manager/compliance-manager-be/docs/features/
    project-flow-engine-integrate/02-stage-integration/implementation-plan.md

    §五(Phase C)全段。

  4. FE 既有規範速查

    ~/Projects/Billows/Audit-Manager/compliance-manager-be/docs/claude/frontend-overview.md

    API 慣例、design tokens、可重用元件、composables、stores。

  5. FE 工作目錄

    ~/Projects/Billows/Audit-Manager/compliance-manager-fe/

    含獨立 CLAUDE.md(FE 規範以該 file 為準)。

  6. FE 既有 API service 範例(C.1 mirror pattern):

    • src/service/ 下任一 GRC service(例:ProjectService.jsAuditService.js)— 確認 BaseService 用法、URL placeholder 替換、return 值結構
    • src/config/api/api.js — API endpoint 常數定義
  7. FE 既有 i18n files

    • src/i18n/zh-tw.js / src/i18n/en.js — 需新增 stage_object name + button label + 4 個 precondition reason key

Phase C 建議實作順序

C.1 — API service(先做)

新增 src/service/StageService.js

  • getStageInfo(projectUid, apUid) → GET /project/:projectUid/ap/:apUid/stage/info
  • advanceStage(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,不要新發明

C.2 — composable

新增 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 }
}

C.3 — Banner 元件

新增 src/components/grc/FlowPhaseBanner.vue

  • Props:project-uid: String + ap-uid: String
  • 內部呼叫 useStageInfo(projectUid, apUid)
  • 顯示元素:當前 stage name(i18n)/ progress bar(4 dot + label) / 提示文字 / 推進按鈕 + tooltip
  • 互動:
    • precondition.passed=false → 按鈕 disable + tooltip 顯示 t(reason_i18n_key, context)
    • precondition.passed=false + user_role='manager' → 按鈕 disable,點下開 ConfirmDialog → 確認 → advance({ force: true })
    • 推進成功 → fetchStageInfo refresh banner + emit stage-advanced 給父 view(讓父 view refresh 自己的資料)
    • 推進失敗 → toast 顯示後端 error msg
  • 子元件:StageProgressBar.vue(純展示 4 dot + label,CSS only)

C.3 i18n key 設計

// 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)。

Phase C 完成定義(不掛 view)

Phase C → Phase D 之間 manual smoke test(必跑)

⚠ 4 條累積 reconciliation findings(Phase B 期間發現)— Phase C 必須對齊

  1. Handler key 命名跳了 namespace 前綴 — BE handler.key 回 activate_project / launch_audit / confirm_audit / close_round前綴);DB seed 已對齊;FE 不直接用 handler key 做判斷邏輯(FE 看 stage_code + i18n label 就好)。
  2. i18n locale key 是 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']
  3. complete_job 不適合 main workflow — BE 已加 complete_main_workflow_job 平行 method(B.3)。FE 無感,沿用 /stage/advance endpoint 即可。
  4. flow_templates 沒 stable code 欄位 — BE Step 22 用 hardcode "完整稽核流程" 找預設範本。FE 無感;未來 Spec 3 範本 wizard 才會需要 code 欄位。

工作流程約定(與 BE Phase B 相同)

  • BE log 位置~/Projects/Billows/Audit-Manager/compliance-manager-be/log/app.log — FE 任何 BE call 異常都先 grep 這個
  • 改 FE code 後不需要重啟 — Vite HMR 自動 reload
  • DB 連線:192.168.50.188:25432 / guidant_ai_dev,cmmgr 帳號(密碼 jedi@123!
  • 階段性 commit 不用問 — 子 task / milestone 完成直接 commit;user_memory feedback 已說明
  • subagent dispatch 必加「git add 顯式檔名,禁用 -am」(user_memory feedback)
  • 編輯檔用絕對路徑開頭:~/Projects/Billows/Audit-Manager/compliance-manager-fe/...
  • FE 改完用 cd ~/Projects/Billows/Audit-Manager/compliance-manager-fe && npm run dev(如未已起 dev server)

FE CLAUDE.md 規範必檢(Phase C 各 commit)

~/Projects/Billows/Audit-Manager/compliance-manager-fe/CLAUDE.md 規範。重點摘要(FE CLAUDE.md 為準):

完成本 session 後的下一步

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 而定。


§2

一、Reconciliation 紀錄(給未來讀者,目前累積 4 條)

  1. ✅ Handler key 命名(DB 用無前綴)— Phase B.1+B.2 已對齊
  2. ✅ locale key = zh_Hant_TW(非 zh-tw)— Phase C 上下傳遞時注意 normalize
  3. complete_job AP-task 假設 → 新增平行 complete_main_workflow_job — Phase B.3 已落地
  4. flow_templatescode 欄位 → 單點 hardcode "完整稽核流程" — Phase B.5 已落地

Phase C / D 完成後若有新 reconciliation,補進 design.md §十 段(mirror Spec 1 §九 pattern)。


§3

二、Phase B 已交付摘要(給 FE session 參考)

範圍 檔案位置
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

已知 Phase B 待 push(user 視 smoke test 結果決定時機)

cd ~/Projects/Billows/Audit-Manager/compliance-manager-be
git log --oneline origin/feature/project-flow-engine-integrate..HEAD
# 預期:5 commits

git push origin feature/project-flow-engine-integrate 由 user 決定時機,FE session 不主動 push BE。

已知 Phase B 待 manual smoke test 項目

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 項目:

  1. 重啟 BE:lsof -ti :8000 | xargs -r kill -9 && python main_socketio.py
  2. 建新專案 + AP:POST /api/oscal/projects/start
  3. 查 DB:SELECT workflow_execution_uid, flow_template_snapshot_uid FROM compliance.assessment_plan_extensions WHERE assessment_plan_id = <new_ap_id>; 預期非 NULL
  4. GET /api/1.0/project/<uid>/ap/<apUid>/stage/info:預期 current_stage.code='planning' + user_can_advance=true(manager 帳號)
  5. precondition fail:在 task_execution stage 推進(有未完成 task)→ 412
  6. force=true bypass:同上加 {"force": true} → 200
  7. 角色擋:auditor 帳號在 planning 推進 → 403
  8. 完整推進 4 stage 到 EndEvent → AP.status='closed'

FE session 不需親跑這些,但若 Banner 元件行為怪異請先確認 user 已跑過上述基本 smoke。