# Spec 1：流程管理

> **狀態**：v1 大方向版，待 review
> **整體脈絡**：`../README.md`

---

## 一、目標

讓使用者管理「專案流程範本」 — 用 BPMN 編輯器組合「階段物件」與分支，存成可重用範本；公司可有自己的流程，也可參考 / 複製系統內建範本。

---

## 二、需求摘要

來源：requirement.md §「想法（粗略）」§1「新增專案流程管理功能」

1. 範本列表（系統內建 + 自訂）並列顯示
2. 內建範本只能複製不可直接編輯
3. 自訂範本可建立 / 編輯 / 軟刪除
4. 編輯器是 BPMN 風格（沿用 jedi-flow-engine 既有 BPMN editor 模式）
5. 每個 BPMN UserTask 引用「階段物件」+ 配置主要角色 / 參與角色
6. 範本入口：左側選單新增「流程管理」項，可見性由 RBAC 控制

---

## 三、階段物件清單（seed v1）

本輪 spec seed **4 個基礎階段物件**，覆蓋 requirement.md §現況的 phase 2~5。

| requirement.md 原 phase | 對應 |
|---|---|
| Phase 1「新增稽核計畫」 | BPMN StartEvent + 系統建立 AP（不是 UserTask，不需 seed） |
| Phase 2~5 | 4 個 seed 階段物件（下表） |
| Phase 6「結案」 | BPMN EndEvent + 系統自動關閉 AP（不是 UserTask，不需 seed） |
| Phase 7「再開新一輪」 | launch_new_round 動作，不在本案範圍 |

### 3.1 4 個 seed 階段物件

| code | 顯示名稱 | 類型 | AP.status | 對應頁面 | 預設主要角色 |
|---|---|---|---|---|---|
| `planning` | 規劃 | routed | `preparing` | `/project/projects/:projectUID/settings` | `manager` |
| `task_execution` | 執行任務 | stateful | `active` | （無專屬頁面，靠 overview + 待辦任務頁的資料過濾） | `manager` |
| `audit` | 稽核 | routed | `auditing` | `/project/projects/:projectUID/ap/:apUID/audit` | `auditor` |
| `poam` | 缺失改善 | routed | `remediation` | `/project/projects/:projectUID/ap/:apUID/poam` | `manager` |

> 「預設主要角色」= 預設「能 complete 此 stage」者；使用者在 BPMN 編輯器拖 UserTask 後可逐個覆蓋。
> 角色 code 沿用系統現有 `project_participants.role`：`manager` / `reviewer` / `auditor` / `viewer`。
> **導航按鈕（routed view 入口）不在此控制** — 沿用既有 FE `v-if` 邏輯（狀態 + 角色），新 spec 不動。

### 3.2 階段 ↔ 既有推進 API 對映

每個 stage 的「完成此階段」推進，本質上是呼叫既有 OSCAL 流程的 4 個 API。Spec 2 的「副作用搬家」= 把這些 API 包進對應 stage 的 `on_complete` handler；**不重做這些 API**。

| code | 推進按鈕文字 | 推進對應既有 API | 推進後 AP.status |
|---|---|---|---|
| `planning` | 啟動專案 | `POST /grc/project/<uid>/ap/<apUid>/activate` | `preparing` → `active` |
| `task_execution` | 啟動稽核 | `POST /grc/project/<uid>/ap/<apUid>/launch-audit` | `active` → `auditing` |
| `audit` | 提交稽核 | `POST /grc/project/<uid>/ap/<apUid>/confirm-audit` | `auditing` → `remediation`（有缺失）/ `closed`（無缺失） |
| `poam` | 完成改善 | `POST /grc/project/<uid>/ap/<apUid>/close-round` | `remediation` → `closed` |

> 對應 `docs/api/grc/design.md §2.1` 既有狀態機。

### 3.3 階段物件 schema 概念欄位

| 欄位 | 說明 |
|---|---|
| `code` | 唯一識別字串，BPMN UserTask 用這個 reference |
| `name_i18n` | 顯示名稱（多語言） |
| `kind` | `routed`（綁定特定頁面） / `stateful`（無專屬頁面，行為由資料層過濾） |
| `route_pattern` | 僅 routed 有，含 placeholder（如 `:projectUID` / `:apUID`） |
| `complete_button_label_i18n` | Banner 上「完成此階段」的按鈕文字 |
| `complete_handler_key` | BE 註冊的 on_complete handler 識別（對應 §3.2 的既有 API） |
| `precondition_key` | BE 註冊的 precondition function 識別（檢查前置條件，例如「全部 task 已 closed」） |
| `default_main_roles` | 預設「能 complete 此 stage」角色清單 |
| `is_builtin` | 內建 / 自訂（v1 全部 builtin） |

> `complete_handler_key` / `precondition_key` 對應的具體 handler / function **實作屬於 Spec 2 範圍**，本 spec 只負責 schema 與 key 命名規範。
> v1 **不含** `default_view_roles` — 導航按鈕沿用既有 FE 邏輯，stage object 不控制可見角色。

---

## 四、內建範本清單（seed v1）

對應 README 提的 A / B / C 三種專案情境：

| 範本 code | 顯示名稱 | 用途 | 階段組合 |
|---|---|---|---|
| `builtin-full-audit` | 完整稽核流程 | A 專案（正式稽核導入） | Start → planning → task_execution → audit → Gateway →（有缺失）poam → audit /（無缺失）End |
| `builtin-internal-check` | 內部自查流程 | B 專案（內部自我檢查） | Start → planning → task_execution → End |
| `builtin-self-assessment` | 自我評估稽核 | C 專案（內部稽核無改善） | Start → planning → task_execution → audit → End |

每個 UserTask 預設套用該階段物件的 default 角色設定；使用者複製成自訂範本後可逐個 UserTask 修改主要 / 參與角色。

---

## 五、範圍

### In scope
- 階段物件 schema 設計（DB 資源）
- 階段物件 seed 4 個基礎物件
- 流程範本 schema 設計（含 BPMN XML 儲存）
- 範本 CRUD API（list / detail / create / update / soft delete / duplicate）
- 內建範本 seed（3 套，對應 A / B / C 三類專案情境）
- BPMN 編輯器 UI（範本編輯頁、預覽頁）
- 左側選單接入 RBAC

### Out of scope（留待後續 spec）
- AP 套用範本（→ Spec 3）
- Stage 實際推進 runtime（→ Spec 2）
- 既有 5 個 view 改動（→ Spec 2）
- 階段物件的 CRUD UI（→ 後續 spec，本輪只 seed）

---

## 六、高階任務拆解

### 後端
- [ ] 設計階段物件 schema（含 §3.3 列的概念欄位）
- [ ] 設計流程範本 schema（uid / tenant_id / name / description / is_builtin / is_active / bpmn_xml / 審計欄位）
- [ ] 範本 CRUD API
- [ ] 內建範本 seed migration（3 套，對應 A / B / C 三類專案情境）
- [ ] 階段物件 seed migration（4 個基礎：planning / task_execution / audit / poam）
- [ ] RBAC migration：ui_route + capability + route_capability

### 前端
- [ ] 左側選單新增「流程管理」項
- [ ] 範本列表頁（DataTable + 內建/自訂篩選 + 搜尋）
- [ ] 範本編輯頁（BPMN 編輯器 + UserTask 屬性面板：**階段物件下拉 + 主要角色**）
- [ ] 範本預覽 Dialog（唯讀 BPMN + 階段清單摘要）

> v1 BPMN UserTask 屬性面板**不含「參與角色」** — 導航按鈕沿用既有 v-if 邏輯（狀態 + 角色），stage 不控制可見角色。

---

## 七、對外介面（給後續 spec 用）

- `GET /flow-engine/stage-objects` — 列出所有可用階段物件（Spec 2 / 3 都要用）
- `GET /flow-engine/flow-templates` — 範本列表（Spec 3 wizard 用）
- `GET /flow-engine/flow-templates/<uid>` — 範本詳情含 BPMN XML（Spec 3 snapshot 用）

---

## 八、開放問題

- [x] BPMN 編輯器要不要支援 Gateway 編輯 — **決議：v1 完整 Gateway 編輯**（含 ExclusiveGateway palette + 屬性面板 name / outgoing flow condition / default flag）
- [ ] 範本是否需要「分類 / tag」（如「稽核類」「自查類」），影響列表頁設計
- [ ] 自訂範本是否能跨 tenant 分享 — 預設 tenant 隔離，但客戶集團內可能想共用
- [ ] 範本「儲存草稿 vs 發佈」是否需要 — 編輯中的範本是否可被 Spec 3 的 wizard 看到

---

## 九、Reconciliation：FE 落地時 spec 偏差紀錄（2026-05-12）

紀錄 FE 實作期間發現的偏差跟取捨理由。**不是補救，是給未來讀者保留決策軌跡** — 看 spec 跟看 code 行為對不上時，有這份就不會繞遠路。

### 9.1 「新增空白範本」流程改成「dialog → 進編輯頁 → 編完才 POST」

| 項目 | 內容 |
|---|---|
| 原 spec | 列表頁「新增範本」dialog 提交 → POST blank XML → 取回 uid → push 編輯頁 |
| 實際落地 | dialog 提交 **不 POST**，純 router push 到 `/flow/template-manage/new?name=...&description=...`；使用者編完 BPMN（加 UserTask + EndEvent + 設階段物件）後在編輯頁點儲存才真的 POST |
| 為什麼偏差 | BE `_validate_bpmn` 嚴格要求 `>=1 UserTask + EndEvent`（line 142），blank XML 只含 StartEvent 直接 reject 回 GRC_400040。FE side commit `40f6f52` 修這個 |
| 考慮過但排除的方案 | **A. BE 放寬 create validation**：讓 blank 入庫，update 時才嚴格驗。排除原因：DB 會留 ghost 範本，Spec 2/3 套用範本到 AP 時要再加防呆 |
| 未來可能反悔的條件 | 若 Spec 2 引入「範本草稿 / 發佈」狀態（§八 開放問題之一），blank 草稿可入庫就合理，屆時 BE 放寬 + FE 改回 |

### 9.2 列表頁 segmented filter 不用 SelectButton，改 v-for Button + pill wrapper

| 項目 | 內容 |
|---|---|
| 原 spec | 「全部 / 內建 / 自訂」filter（沒指定元件）|
| 實際落地 | v-for `<Button text>` + 外層 wrapper 加 border + 內 padding；active 狀態 inline style `rgba(99,102,241,0.2)` 紫底 + 主色字 |
| 為什麼偏差 | PrimeVue 3.53 `SelectButton` 預設 `unselectable=true` quirk 會「點當前 active 變 null」；對齊 `project-dashboard` 我的代辦任務 segmented pill 既有 pattern |
| 沉澱規範 | FE `CLAUDE.md` 新增「Segmented Filter Bar Pattern」段，未來互斥分類 filter 一律用此 pattern |

### 9.3 列表操作欄統一「編輯」icon，移除 builtin「檢視」分支

| 項目 | 內容 |
|---|---|
| 原 spec / 初版 | builtin 顯示 `pi-search`「檢視」、自訂顯示 `pi-pencil`「編輯」 |
| 實際落地 | 統一 `pi-pencil`「編輯」；builtin 進去仍是 readonly Viewer，但 label 一致 UX 更直觀（可走「另存為新範本」修改）|
| 為什麼偏差 | User feedback：兩種 icon 反而困惑，本質都是進編輯頁 |

### 9.4 列表 name cell 包成 `.name-link` 可點

| 項目 | 內容 |
|---|---|
| 原 spec | 沒明說 |
| 實際落地 | name cell 加 cursor pointer + hover 變色加底線 + tooltip「編輯」+ click 進編輯頁（與操作欄編輯按鈕等效） |
| 為什麼偏差 | User feedback：DataTable 名稱應該直觀可點 |

### 9.5 zh-tw「User Task」→「任務」一致中文化

| 項目 | 內容 |
|---|---|
| 原 spec | 沒規範文案，使用「User Task」術語 |
| 實際落地 | zh-tw 5 處字串全改成「任務」；en 維持「User Task」（BPMN 正式術語不翻譯） |
| 為什麼偏差 | User feedback：「User Task 屬性」中英夾雜怪 |

### 9.6 BE 端 — builtin 範本 name 從英文 slug 改中文

| 項目 | 內容 |
|---|---|
| 原 seed | name = `builtin-full-audit` / `builtin-internal-check` / `builtin-self-assessment`（英文 slug）|
| 實際落地 | name = 「完整稽核流程」 / 「內部自查流程」 / 「自我評估稽核」（中文）|
| 為什麼偏差 | User feedback：列表顯示應對齊其他中文 UI |
| 部署備註 | dev DB 已跑 `2026-05-12-rename-builtin-flow-templates-to-zh.sql` 修補；prod 部署前必須先跑 fix-up（直接重跑 seed 會造成 6 列「中英並存」） |

### 9.7 FE 編輯器 — bpmn-js shape 必須 `markRaw` 不能進 Vue reactivity

| 項目 | 內容 |
|---|---|
| 原 spec | 沒明說 |
| 實際落地 | `selectedElement` 用 `shallowRef + markRaw(el)` 包裝 bpmn-js shape；不可用 `ref(el)` |
| 為什麼偏差 | bpmn-js shape 內部用 `Object.defineProperty(labels, writable:false, configurable:false)` 定義 read-only 屬性；Vue 3 reactive Proxy 攔截 get 會違反 invariant 直接 TypeError 炸（commit `d16c504` 修） |
| 沉澱規範 | 若未來 FE 還有其他第三方 lib instance（Cytoscape / Three.js 等）需要 ref，**一律走 `shallowRef + markRaw` 雙保險** |

### 9.8 BPMN canvas 需 `bpmn-auto-layout` 補 DI

| 項目 | 內容 |
|---|---|
| 原 spec | builtin BPMN XML 在 `scripts/sql/seeds/bpmn/builtin-*.bpmn` 只含 process 定義（StartEvent / UserTask / SequenceFlow / EndEvent），**沒帶 `<bpmndi:BPMNDiagram>` DI 資訊** |
| 實際落地 | FE Editor / Preview 在 initModeler / renderBpmn 偵測 `!xml.includes('BPMNDiagram')`，先過 `bpmn-auto-layout` 的 `layoutProcess(xml)` 補 DI 再 import |
| 為什麼偏差 | 直接餵 bpmn-js Viewer 會炸 `Error: no diagram to display`。原 spec 沒考慮 DI 缺失 case |
| 未來改進 | 若 FE 拖拉編輯後存檔的 XML 已含 DI，新建自訂範本後續就不需要再 auto-layout（只有 builtin / 純後端 seed 缺 DI） |

