# 專案流程與流程引擎整合 — FINAL SPEC v1.0

> **狀態**：v1.0 shipped
> **發版日期**：2026-05-15
> **取代**：sub-spec design.md（spec 1 / 2 / 3 / 4）— 仍保留作 detail reference，但對外溝通以本檔為主
>
> 本檔是 v1.0 single source of truth。需要看「為什麼這樣做」見各 sub-spec design.md 的 `Reconciliation` 段；需要看「實作步驟」見對應 implementation-plan.md。

---

## 一、目標

把 AP（稽核計畫，Assessment Plan）的生命週期從寫死的 6 階段流程，改成 **BPMN 流程引擎驅動**。使用者可建立 / 複製 / 自訂流程範本，AP 套用範本後依範本定義的階段順序推進（含「審核」階段、退回機制與方向性驗證）。

### 解決的稽核情境

| 情境 | 範本 | 階段組合 |
|---|---|---|
| A：正式稽核導入 | `builtin-full-audit` | Start → planning → task_execution → audit → (Gateway) → poam → audit /（無缺失）End |
| A+：含審核 | `builtin-full-audit-with-review` | Start → planning → task_execution → **review** → audit → (Gateway) → poam → audit /（無缺失）End |
| B：內部自查 | `builtin-internal-check` | Start → planning → task_execution → End |
| C：自我評估 | `builtin-self-assessment` | Start → planning → task_execution → audit → End |

---

## 二、v1.0 範圍

### In scope

- **階段物件（stage_objects）** schema + seed 5 個基礎階段（planning / task_execution / **review** / audit / poam）
- **流程範本（flow_templates）** schema（含 BPMN XML 儲存）+ CRUD API + draft/published 狀態機
- **內建範本** seed 4 套（上表）
- **BPMN 編輯器 UI**（範本編輯頁、預覽頁、拓撲驗證 inline 警告）
- **AP 套用範本**：建 AP 時挑範本 + snapshot clone 到 workflow_execution（每輪獨立）
- **Stage 推進機制**：Banner UI + 推進按鈕 + 角色驗證 + precondition 檢查 + handler dispatch
- **Review stage 退回機制**：reviewer 可選 approve / reject；reject 必填 comment 並透過 BPMN reverse flow 回到上一個 stage
- **拓撲方向性驗證**：BPMN UserTask 的 stage 順序需符合 `allowed_predecessors` / `allowed_successors` 規則；發布前 / 草稿編輯時 inline 警告
- **左側選單**「流程管理」項，RBAC `flow_template_manage` capability 控制可見
- **完整 audit log**：階段推進 / 退回事件寫進 `public.system_logs`（event_code 6050-6054），方便追溯誰在何時做了什麼

### Out of scope（v1.x 後續）

- 階段物件的 CRUD UI（v1 全部 builtin，FE 無 admin UI 可改）
- 參與角色（participants role）細部權限（v1 沿用既有 4 種：manager / reviewer / auditor / viewer）
- 跨 AP 的 workflow merge / split
- 範本 import / export（v1 只能複製內建或新建空白）
- 自訂 stage handler / precondition plugin 機制（架構保留，code 未開放擴充）

---

## 三、資料模型

### 3.1 階段物件 `compliance.stage_objects`

| 欄位 | 型別 | 說明 |
|---|---|---|
| `id` | serial PK | |
| `uid` | uuid | external identifier |
| `code` | text unique | 例：`planning` / `task_execution` / `review` / `audit` / `poam` |
| `name_i18n` | jsonb | `{"zh_Hant_TW": "規劃", "en": "Planning"}` |
| `kind` | text | `routed`（綁頁面）/ `stateful`（無專屬頁面）|
| `route_pattern` | text | 僅 routed 有（如 `/project/projects/:projectUID/settings`）|
| `complete_button_label_i18n` | jsonb | Banner「完成此階段」按鈕文字 |
| `entry_button_label_i18n` | jsonb | Banner「進入下一階段」按鈕文字（v1 衍生新增） |
| `complete_handler_key` | text | BE registry key（如 `activate_project`） |
| `precondition_key` | text | BE registry key（如 `all_tasks_closed`） |
| `default_main_roles` | jsonb | 預設能 complete 此 stage 的角色（`["manager"]`）|
| `can_start` | bool | 此 stage 是否可作為 BPMN start 後的第一個 UserTask |
| `can_end` | bool | 此 stage 是否可直接連 EndEvent |
| `allowed_predecessors` | jsonb | 允許作為前驅的 stage code list（空陣列=不限制）|
| `allowed_successors` | jsonb | 允許作為後繼的 stage code list（空陣列=不限制）|
| `is_builtin` | bool | v1 全部 true |
| `sort` | int | 列表排序 |

#### v1 seed 5 個 stage

| code | sort | can_start | can_end | allowed_predecessors | allowed_successors |
|---|---|---|---|---|---|
| `planning` | 10 | ✅ | ❌ | `[]` | `["task_execution"]` |
| `task_execution` | 20 | ❌ | ✅ | `["planning", "review"]` | `["review", "audit"]` |
| `review` | 25 | ❌ | ❌ | `["task_execution", "review"]` | `["task_execution", "review", "audit"]` |
| `audit` | 30 | ❌ | ✅ | `["task_execution", "review", "poam"]` | `["poam"]` |
| `poam` | 40 | ❌ | ✅ | `["audit"]` | `["audit"]` |

### 3.2 流程範本 `compliance.flow_templates`

| 欄位 | 型別 | 說明 |
|---|---|---|
| `id` | serial PK | |
| `uid` | uuid | |
| `tenant_id` | int | RLS（NULL = system-wide builtin） |
| `name` | text | |
| `description` | text | |
| `bpmn_xml` | text | BPMN 2.0 XML（含 stage_object_code / main_role extension properties） |
| `is_builtin` | bool | 內建範本（不可編輯，只能複製） |
| `status` | text | `draft` / `published`（v1 衍生狀態機） |
| `is_active` | bool | 軟刪除 flag |
| `created_user` / `created_at` / `updated_user` / `updated_at` | | 審計欄位 |

#### v1 seed 4 個 builtin（`status='published'`）

| name | 用途 |
|---|---|
| `builtin-full-audit` | 完整稽核流程（無 review） |
| `builtin-full-audit-with-review` | 完整稽核流程 + reviewer 審核 |
| `builtin-internal-check` | 內部自查 |
| `builtin-self-assessment` | 自我評估稽核 |

### 3.3 AP extension `compliance.assessment_plan_extensions`

每個 AP 一筆，存 main workflow 的 snapshot 引用 + flow_template 來源 uid。

| 欄位 | 說明 |
|---|---|
| `assessment_plan_id` | FK → `oscal.assessment_plans` |
| `flow_template_uid` | snapshot 來源 |
| `workflow_execution_uid` | snapshot 後的 main workflow execution 引用 |

### 3.4 Snapshot 三層獨立性

```
flow_template (master, 系統層)
    ↓ clone (建 AP 時)
workflow_template_snapshot (per-AP 凍結)
    ↓ instantiate
workflow_execution (runtime instance)
```

- master 改不影響已啟動 AP
- snapshot 凍結後 immutable
- runtime instance 由 BPMN engine 推進

---

## 四、API 清單

### 4.1 流程範本管理（admin / flow-template-manage 權限）

| Method | Path | 說明 |
|---|---|---|
| GET | `/flow-engine/flow-templates` | 列表（分頁、search、tenant filter） |
| GET | `/flow-engine/flow-templates/<uid>` | 取單筆（含 BPMN XML） |
| POST | `/flow-engine/flow-templates` | 建立（status=draft） |
| PUT | `/flow-engine/flow-templates/<uid>` | 更新（含 BPMN XML 重寫） |
| DELETE | `/flow-engine/flow-templates/<uid>` | 軟刪除 |
| POST | `/flow-engine/flow-templates/<uid>/duplicate` | 複製（builtin → 自訂） |
| POST | `/flow-engine/flow-templates/<uid>/publish` | draft → published |
| PUT | `/flow-engine/flow-templates/<uid>/unpublish` | published → draft |
| POST | `/flow-engine/flow-templates/validate` | 純驗證（不存檔），回 violations 陣列 |

### 4.2 AP 階段推進（project participant 權限）

| Method | Path | 說明 |
|---|---|---|
| GET | `/project/<uid>/ap/<ap_uid>/stage/info` | Banner 顯示用（當前 stage / progress / 按鈕 label / precondition） |
| POST | `/project/<uid>/ap/<ap_uid>/stage/advance` | 推進 / 退回（含 decision / comment） |

### 4.3 AP 套用範本

建 AP（`POST /oscal/projects/start`）時 `flow_template_uid` 必填。launch_new_round 自動沿用前一輪的 flow_template_uid。

---

## 五、Stage 推進 / 退回流程

### 5.1 advance_stage 7 步檢查（按順序）

1. **解 workflow context**（找當前 user_task）→ 沒有 → 422 `GRC_STAGE_NO_NEXT_NODE`
2. **取 stage_object_code**（從 BPMN UserTask extension） → 沒綁 → 422 `GRC_STAGE_OBJECT_NOT_BOUND`
3. **查 stage_object** → 不存在 → 404 `GRC_STAGE_OBJECT_NOT_FOUND`
4. **review stage 業務驗證**：
   - decision 必填 → 否則 400 `GRC_STAGE_REVIEW_DECISION_INVALID`
   - decision='reject' 必填 comment → 否則 400 `GRC_STAGE_REVIEW_REJECT_REQUIRES_COMMENT`
   - 非 review stage 送 decision → 忽略 + log warning
5. **角色驗證**：user 在 project_participants 的 role 是否在 stage `main_roles` → 否則 403 `GRC_STAGE_ROLE_FORBIDDEN`
6. **Precondition**（force=true 跳過）→ 失敗 412 `GRC_STAGE_PRECONDITION_FAILED`
7. **Handler dispatch**：
   - terminal user_task → `terminal_close` handler
   - 其他 → `stage_object.complete_handler_key`
   - handler 未註冊 → 412 `GRC_STAGE_HANDLER_NOT_REGISTERED`

完成後 BPMN engine 推進到下一個 UserTask（reject 走 reverse flow 回上一階段）。

### 5.2 Audit log

13 處 logger 統一前綴 `[AUDIT:STAGE_ADVANCE]`，含 event_code 寫進 `public.system_logs`：

| Event | Code | Level | 觸發 |
|---|---|---|---|
| requested | 6050 | INFO | 進入 API |
| success (forward) | 6051 | INFO | 推進成功 |
| success (rejected) | 6052 | INFO | 退回成功 |
| halted | 6053 | INFO | handler warning 中止 |
| denied | 6054 | WARN/ERROR | 各種拒絕（reason 看 message）|

#### 除錯 SQL

```sql
-- 某 user 今天所有推進事件
SELECT act_time, event_code, level, LEFT(message, 120)
  FROM public.system_logs
 WHERE user_uid = '<uid>'
   AND act_time >= CURRENT_DATE
   AND event_code LIKE '605%'
 ORDER BY act_time;

-- 某 AP 推進歷程
SELECT act_time, user_name, event_code, message
  FROM public.system_logs
 WHERE message LIKE '%ap_uid=<uid>%'
   AND event_code LIKE '605%'
 ORDER BY act_time;
```

---

## 六、Banner UI（FE）

### 6.1 顯示元素

- **當前階段名稱**（從 stage_object.name_i18n 取）
- **進度條**（純預覽不可點）— per UserTask dot，依完成度填色（v1 衍生 dynamic）
- **提示文字**（precondition 未達時顯示 `reason_i18n_key`）
- **推進按鈕**（dynamic label 從 BPMN flow @name 讀，fallback stage_object.complete_button_label_i18n）
- **退回按鈕**（僅 review stage 顯示，跟 BPMN reverse flow @name 同步）
- **流程結構警告區**（拓撲驗證 violations 列表 + 對應節點視覺紅框）

### 6.2 推進按鈕邏輯

按下後依 stage 不同行為：

| stage | 行為 |
|---|---|
| `planning` | 呼叫既有 `POST /grc/.../activate`（搬到 ActivateProjectHandler）|
| `task_execution` | 呼叫既有 `POST /grc/.../launch-audit`（搬到 LaunchAuditHandler，未強制完成有 warning）|
| `review` | dispatch ReviewDecisionHandler（approve / reject）|
| `audit` | 呼叫既有 `POST /grc/.../confirm-audit` |
| `poam` | 呼叫既有 `POST /grc/.../close-round` |
| terminal | dispatch `terminal_close` handler |

---

## 七、RBAC

### 7.1 capability：`flow_template_manage`

控制左側選單「流程管理」可見 + 範本 CRUD route 存取（resource_type='ui_route', url='/flow-template-manage'）。

### 7.2 AP 推進權限

stage_object.default_main_roles 決定哪些 role 能完成此 stage；FE Banner 推進按鈕的可見性 = user role 是否在 main_roles 內。

`role_capabilities` v1 沿用既有 4 role（manager / reviewer / auditor / viewer）。

---

## 八、內建範本詳解

### 8.1 builtin-full-audit-with-review（推薦）

```
StartEvent → planning → task_execution → review →  audit  →  Gateway
                                  ↑              (default)    ├── (default, 無缺失) → EndEvent
                                  └── (reject)                └── (has_findings) → poam → audit
```

- review stage 的 reject 透過 BPMN reverse flow 回 task_execution（condition=`${decision == 'reject'}`）
- review stage 可串接多個（review1 → review2 → audit）
- review approve 不會提前 launch_audit；只有 next stage 是 audit 時才 launch

### 8.2 builtin-full-audit（無 review）

```
StartEvent → planning → task_execution → audit → Gateway
                                                    ├── EndEvent
                                                    └── poam → audit
```

### 8.3 builtin-internal-check / builtin-self-assessment

簡單線性流程，無 review、無 POAM 迴圈。

---

## 九、拓撲驗證

### 9.1 7 條 rule（design §7）

1. StartEvent 後第一個 UserTask 必須 `can_start=true`
2. 每個 UserTask 必須綁合法 `stage_object_code`
3. 每條 forward sequenceFlow 的 source/target stage 需符合 `allowed_predecessors` / `allowed_successors`
4. 連到 EndEvent 的 UserTask 必須 `can_end=true`
5. 每個 ExclusiveGateway 至少一條 outgoing 有 condition
6. 所有 UserTask 從 StartEvent 走 forward edge 必可達
7. Reverse flow 偵測：`${var == 'reject'}` 嚴格 regex 或 extension property `reverse=true`

### 9.2 違規處理

- `POST /flow-engine/flow-templates/validate` 純驗證回 200 + `{valid, violations}`
- `PUT .../<uid>/publish` 違規 → 400 `GRC_FLOW_TOPOLOGY_INVALID` data 帶 violations
- FE editor inline 警告 + 對應節點 addMarker（v1 衍生：含 `start_stage_not_allowed` 用節點 BPMN @name 顯示 + user_task_id 紅框）

---

## 十、Error Code（GrcErrorCode）

| Code | 中文 | 場景 |
|---|---|---|
| GRC_403040 | 內建範本不可編輯或刪除 | builtin guard |
| GRC_403041 | 無流程範本管理權限 | flow-template-manage cap 缺 |
| GRC_403050 | 使用者不具備此階段推進權限 | role_forbidden |
| GRC_409xxx | 範本名稱重複 / 範本未發布 | publish flow |
| GRC_412xxx | precondition / handler / stage 相關 | 推進 7 步檢查 |

完整列表見 `common/code/grc_error_code.py`。

---

## 十一、v1.0 milestones（已完成）

| Spec | Phase | 完成日 |
|---|---|---|
| 1 — 流程管理 | Phase A–E | 2026-05-12 |
| 2 — 階段抽象整合 | Phase A–E | 2026-05-13 |
| 3 — AP 套用流程 | M0–M12 + follow-up | 2026-05-13 |
| 4 — review stage + topology validator | M0–M11 | 2026-05-14 |
| flow-template draft/published 狀態機 | — | 2026-05-15 |
| banner 動態化（progress dots / button label） | — | 2026-05-15 |
| audit log + event_code | — | 2026-05-15 |
| `start_stage_not_allowed` 訊息修補 + 紅框 | — | 2026-05-15 |
| `OSCAL project` PUT/DELETE 加 Owner/Manager 權限 | — | 2026-05-15 |

---

## 十二、部署

### 12.1 SQL upgrade

執行：

```bash
psql -h <host> -p <port> -U cmmgr -d <db_name> \
     -v ON_ERROR_STOP=1 \
     -f scripts/sql/2026-05-15-bpmn-integration-v1.0-upgrade.sql
```

入口 SQL 是 `2026-05-15-bpmn-integration-v1.0-upgrade.sql`，內含全套 7 個 migration（idempotent，重跑安全）：

1. spec 1+2+3 整合 DDL + seed
2. spec 4 M1 — stage_objects 4 欄方向性驗證 + review seed
3. spec 4 M4 — builtin-full-audit-with-review BPMN + reverse patch
4. spec 4 衍生 — topology 規則放寬
5. spec 4 衍生 — entry_button_label_i18n
6. flow-template 衍生 — flow_templates.status 狀態機
7. v1.0 patch — poam.allowed_successors 加 audit（支援 POAM→audit 回測）

跑完會自動 print verify SELECT。

### 12.2 部署順序

1. 跑 SQL upgrade（cmmgr 執行）
2. BE 重啟（service signature / DI 變動需重啟才生效）
3. FE 重新部署（含 banner 動態化 / button alignment 變更）
4. Smoke：
   - 流程管理頁面（admin user）→ 看到 4 個 builtin 範本（全 published 狀態）
   - 建新 AP 選 `builtin-full-audit-with-review` → Banner 顯示 planning 階段
   - 推進 planning → 進 task_execution（log/app.log 有 `[AUDIT:STAGE_ADVANCE]` + `public.system_logs.event_code='6051'`）
   - 走到 review → 試 reject（必填 comment）→ 退回 task_execution（event_code='6052'）
   - 走完整輪 → terminal_close → AP closed

---

## 十三、未來規劃（v1.1+ 候選）

| 議題 | 優先級 |
|---|---|
| 階段物件 CRUD UI（admin 可加 stage） | high |
| 範本 import / export | medium |
| 範本 version history（每次 publish snapshot）| medium |
| Stage handler / precondition plugin 機制 | low（架構保留，code 未開放）|
| 跨 AP workflow merge / split | low |
| Audit log retention policy（system_logs 累積大）| ops |

---

## 十四、Reference

### 14.1 Sub-spec detail（detail 仍有效，但對外溝通優先看本檔）

- `01-flow-template-management/design.md` — Spec 1 流程管理（含 reconciliation §9）
- `02-stage-integration/design.md` — Spec 2 階段抽象整合（含 reconciliation §10）
- `03-ap-binding/design.md` — Spec 3 AP 套用流程（含 reconciliation §16）
- `04-review-stage-and-flow-validation/design.md` — Spec 4 review + topology（含 reconciliation §16）

### 14.2 Handoff 紀錄（純歷史，task arc 收尾用）

- `03-ap-binding/handoff-v1.md` ~ `handoff-v3.md`
- `04-review-stage-and-flow-validation/handoff-v1.md` ~ `handoff-v3.md`

### 14.3 後續修補 changelog

- `2026-05-15-tweak-multi-review-stage-support.md`
- `2026-05-15-fix-reviewer-role-blocked-from-launch-audit.md`
- `2026-05-15-fix-stage-object-topology-rules-too-restrictive.md`
- `2026-05-15-tweak-flow-engine-banner-dynamic-button-label.md`
- `2026-05-15-fix-flow-template-validator-start-stage-msg-and-marker.md`
- `2026-05-15-tweak-stage-advance-audit-log.md`
- `2026-05-15-tweak-stage-advance-audit-event-code.md`

### 14.4 核心 code 索引

| 位置 | 用途 |
|---|---|
| `app/flow_engine/service/flow_template_app_service.py` | 範本 CRUD + publish/unpublish + validate |
| `app/flow_engine/service/stage_advance_service.py` | Stage 推進 / 退回 service（含 audit log） |
| `app/flow_engine/util/bpmn_topology_validator.py` | 拓撲驗證器（7 條 rule，pure function） |
| `app/flow_engine/handler/` | 各 stage 的 on_complete handler |
| `domain/flow_engine/entity/stage_object_entity.py` | stage_object domain entity |
| `infra/flow_engine/model/` | flow_templates / stage_objects ORM model |
| `api/flow_engine/routes/` | flow-template / stage-advance routes |
| `compliance-manager-fe/src/views/flow-template/FlowTemplateEditorView.vue` | BPMN editor + 拓撲警告 |
| `compliance-manager-fe/src/components/grc/ProjectFlowBanner.vue` | Banner UI |
