# Station Flow 總覽

Station Flow 是工作站流程管理系統。一件要做的事開成一張**任務**（task），任務依照**流程**（process）在一個個**工作站**（station）之間流轉，每一站由綁定的角色負責處理，處理完再選一個出口送往下一站，直到結束。每次換站都會留下一筆流轉紀錄。

工作站像一份合約：規定這一站要做什麼、做完能往哪走。執行的可以是人，也可以是 agent（就是你）。

## 名詞

| 名詞 | 一句話解釋 |
|---|---|
| process（流程） | 一條業務流程的藍圖，由多個工作站與它們之間的連線組成。 |
| station（工作站） | 流程裡的一個步驟。每站有說明（`execution_instructions`）告訴執行者要做什麼。特殊站：開始站（start）、結束站（end）、存查站、異常站（exception）。 |
| transition（轉移、出口） | 從某站往下一站的連線。一站可以有多個出口（例如「核准」「退件」），推進任務時要指定走哪一個。 |
| routine（例行事務） | 把流程套用到實際業務的單位，在這裡決定每一站由哪個角色（role）、哪些人負責；事務負責人（`owner`）是需求方的窗口。任務一定屬於某個 routine。 |
| task（任務、票） | 實際在流程上跑的一件事，任何時刻都停在某一站（`current_station_id`）。 |

## 認證

1. 向你所屬組織的管理者（admin）申請一把 API key。key 以 `sfk_` 開頭，只會顯示一次，請立刻存好，不要寫進程式碼或公開的地方。
2. 每個請求都帶這兩個 header：

```
Authorization: Bearer <你的 API key>
Accept: application/json
```

注意：是 `Authorization: Bearer`，不是 `X-API-Key`。

3. 先確認 key 可用：

```bash
curl -s -X GET "https://station-flow.staging.quanhox.com.tw/api/v1/auth/me" \
  -H "Authorization: Bearer $SF_KEY" -H "Accept: application/json"
```

成功回 200，內容是你的身份與 key 所屬的組織：

```json
{"data": {"id": 12, "name": "報價助理", "account": "quote-bot", "email": "...", "role": "staff",
          "organization": {"id": 3, "role": "staff"}}}
```

- 一把 key 綁定一個組織，所有操作都只看得到該組織的資料。要操作另一個組織，需要那個組織的 admin 另外發 key。
- `organization.role` 是你在這個組織的身份：`admin` 或一般成員（`staff`）。很多權限看這個值。另有 `requester`（需求方）：只能用 `/r` 前台留言提需求，API 不開放。

### 一定要帶 `Accept: application/json`

沒帶時，伺服器會把你當成瀏覽器：

- 認證失敗不會回 401 JSON，而是回 **302 轉址到網頁登入頁**，body 是 HTML。
- 欄位驗證失敗也可能被轉址，而不是回 422 JSON。

看到 302 或 HTML 回應，第一步先檢查這個 header。送 JSON body 時再加 `Content-Type: application/json`。

## 回傳格式

| 情況 | 格式 |
|---|---|
| 讀取、更新成功 | HTTP 200，`{"data": ...}` |
| 建立成功 | HTTP 201，`{"data": ...}` |
| 刪除成功 | HTTP 200 `{"message": "..."}`，或 HTTP 204 沒有 body（依端點） |
| 流轉類動作（推進、退回、異常、跳回） | HTTP 200，**扁平物件，沒有 `data` 包裹**：`{"task_id", "from_station", "to_station", "transition_type", "created_at"}` |
| 錯誤 | `{"message": "中文說明"}`；欄位驗證錯誤另帶 `{"errors": {"欄位": ["說明"]}}` |

時間欄位是 ISO 8601 字串，**一律是 UTC**：結尾可能是 `Z` 或 `+00:00`，秒以下的位數也不固定（例如 `2026-10-30T02:00:00.000000Z`、`2026-10-30T02:00:00+00:00`）。請用 ISO 8601 解析器讀，不要用字串比對；要給人看時再自行換算成當地時區。

## 授權原則

**權限由伺服器依你的身份判斷，不看你在 query 帶了什麼。**

- 一般成員（非 admin）查任務清單時，帶 `for_user_id=別人` 會被忽略，伺服器一律只回你自己的。只有 admin 可以查別人。
- 一般成員列 routine 時只看得到自己有角色的 routine。
- 推進、退回、送異常、跳回任務：你必須屬於**任務目前所在站**綁定的角色，否則 403。這條連 admin 也不例外。
- 建立、修改、刪除流程、刪除任務、管理別人的 key 等管理動作只有 admin 能做，其他人回 403 `權限不足`。
- 別的組織的資料一律當成不存在，回 404。

所以寫程式時，不要假設「帶了參數就會生效」。收到 403，代表你的身份沒有這個權限，換參數也沒用，請找組織管理者調整角色。

## 錯誤碼

| HTTP | 意思 | 常見原因與處理 |
|---|---|---|
| 302 | 被轉址到登入頁 | 沒帶 `Accept: application/json`。 |
| 401 | 未認證 | key 錯誤、已撤銷，或 header 不是 `Authorization: Bearer`。message 為 `Unauthenticated.`。 |
| 403 | 已認證但沒權限 | 你不屬於任務目前站的角色（`權限不足：你不屬於『某某』站綁定的角色`）、非 admin 做管理動作、key 綁定的組織已停用。 |
| 404 | 不存在 | id 打錯，或資料屬於別的組織。message 如 `任務不存在`、`屬性不存在`。 |
| 405 | 方法不允許 | 路徑存在但 method 不對，例如想用 POST 寫流轉紀錄（留言請用留言端點）。 |
| 409 | 狀態衝突 | 任務已被別人認領（claim）；或標已讀時帶的版本已過期。重新讀取後再決定。 |
| 410 | 功能已移除 | 打到已下線的舊端點，例如任務層附件的列表／上傳／刪除。照 message 指示改用新做法。 |
| 422 | 驗證失敗或違反業務規則 | 缺必填欄位、`transition_id` 不屬於目前站、開始站不能退回、出口要求的資料沒補齊等。看 `message` 與 `errors`。 |
| 429 | 請求太頻繁 | 有限流的端點超過次數（例如每分鐘 60 次）。等一分鐘再試，並降低輪詢頻率。 |
| 500 | 伺服器錯誤 | 不是你的問題。稍後重試；持續發生請回報組織管理者，附上請求內容與時間。 |

失敗的流轉不會留下紀錄，也不會留下上傳的檔案，修正後直接重送即可。

## 完整範例：從開票到流轉

先設定環境變數：

```bash
export SF_KEY="<你的 API key>"
H=(-H "Authorization: Bearer $SF_KEY" -H "Accept: application/json")
```

**0. 找到你能開票的 routine**

`GET /routines` 只列出你有角色的 routine，但有角色不代表能開票——開票要屬於**開始站**綁定的角色。對每個候選 routine 查各站負責角色，找 `station_type` 是 `start` 的那一列，確認 `role` 是你所屬的角色（`users` 裡有你）：

```bash
curl -s -X GET "https://station-flow.staging.quanhox.com.tw/api/v1/routines" "${H[@]}"
curl -s -X GET "https://station-flow.staging.quanhox.com.tw/api/v1/routines/1/station-assignees" "${H[@]}"
```

```json
{"data": [{"station_id": 10, "station_name": "開始", "station_type": "start",
           "role": {"id": 24, "name": "業務", "is_auto": false},
           "users": [{"id": 12, "name": "報價助理"}]}]}
```

**不要在正式業務的 routine 開測試票。** 票一開出來，負責下一站的人或 agent 就會被通知並開始處理。要試 API，請組織管理者給你一個測試用的 routine。

**1. 建立任務。** 任務一律落在流程的開始站；你必須屬於開始站綁定的角色，否則 403。

```bash
curl -s -X POST "https://station-flow.staging.quanhox.com.tw/api/v1/tasks" "${H[@]}" -H "Content-Type: application/json" \
  -d '{"routine_id": 1, "name": "A 客戶報價單", "priority": "high"}'
```

回 201：

```json
{"data": {"id": 57, "name": "A 客戶報價單", "routine_id": 1, "current_station_id": 10,
          "current_station_role_id": 24, "process_version": 3,
          "priority": "high", "task_deadline_at": null, "station_deadline_at": null, "project": null}}
```

**2. 讀任務與這一站的說明。** `current_station.execution_instructions`（站說明）和 `current_station.process_common_instructions`（流程每站共通說明）兩段都要讀，站說明比較具體時以站說明為準。

```bash
curl -s -X GET "https://station-flow.staging.quanhox.com.tw/api/v1/tasks/57" "${H[@]}"
```

**3. 查目前站可以走哪些出口**

```bash
curl -s -X GET "https://station-flow.staging.quanhox.com.tw/api/v1/tasks/57/transitions" "${H[@]}"
```

```json
{"data": [{"id": 21, "name": "送審", "transition_type": "normal", "to_station_id": 11,
           "to_station_name": "主管審核", "tone": "positive", "comment_required": false, "required_data": []}]}
```

`comment_required` 為 true 時一定要寫 `comment`；`required_data` 不是空的，代表送出前任務上必須先有那些屬性或附件。

**4. 推進任務**

```bash
curl -s -X POST "https://station-flow.staging.quanhox.com.tw/api/v1/tasks/57/transition" "${H[@]}" -H "Content-Type: application/json" \
  -d '{"transition_id": 21, "comment": "報價已試算完成，請主管審核"}'
```

```json
{"task_id": 57, "from_station": "開始", "to_station": "主管審核", "transition_type": "normal",
 "created_at": "2026-10-30T02:00:00.000000Z"}
```

推進後任務到了新站，通常已經不歸你的角色管，之後對它的推進操作會回 403，這是正常的。

**5. 查流轉紀錄**

```bash
curl -s -X GET "https://station-flow.staging.quanhox.com.tw/api/v1/tasks/57/logs" "${H[@]}"
```

每筆紀錄有 `from_station_name`、`to_station_name`、`transition_type`（`normal`／`rollback`／`exception`／`jumpback`／`comment`）、`transition_name`、`transition_tone`、`is_return`、`comment`、`actor`、`attachments` 與 `created_at`。各欄位說明見[任務操作](https://station-flow.staging.quanhox.com.tw/agent/tasks.md)。

## 其他主題

- [任務操作](https://station-flow.staging.quanhox.com.tw/agent/tasks.md)：查詢、我的任務、退回、異常、跳回、留言、認領、已讀、屬性
- [附件](https://station-flow.staging.quanhox.com.tw/agent/attachments.md)：流轉時附檔、下載、跨票複製
- [專案](https://station-flow.staging.quanhox.com.tw/agent/projects.md)：跨任務共享的檔案目錄
- [需求方窗口](https://station-flow.staging.quanhox.com.tw/agent/requester-window.md)：誰是窗口、事件游標、回覆、開票、問卷與確認卡
- [流程設計](https://station-flow.staging.quanhox.com.tw/agent/process-design.md)：建流程、工作站、出口、角色
- [報表](https://station-flow.staging.quanhox.com.tw/agent/reports.md)
- [把這份說明存成你的 skill](https://station-flow.staging.quanhox.com.tw/agent/save-as-skill.md)
- [版本異動紀錄](https://station-flow.staging.quanhox.com.tw/agent/changelog.md)
