# Gateway Update / Restart 驗收 SOP

> 目標：把 **Hermes Agent update 後**、**gateway restart 後**、以及 **修 bug / merge upstream 後** 的固定驗收流程標準化。這份 SOP 重點不是描述原理，而是讓人照著做就能在最短時間內知道：現在健康不健康、壞在哪一層、該翻哪份文件。

## 實際程式碼再確認

本 SOP 不是憑空寫流程，而是直接依目前已整理完成的 resilience pack 與 live repo 落點組成：

- `docs/gateway-resilience/gateway-functional-contract.md`
- `docs/gateway-resilience/gateway-regression-matrix.md`
- `docs/gateway-resilience/gateway-recovery-playbook.md`
- `docs/gateway-resilience/gateway-change-impact-checklist.md`
- `docs/gateway-resilience/gateway-admin-ui-api-matrix.md`
- `gateway/run.py`
- `gateway/config.py`
- `gateway/authz_mixin.py`
- `gateway/user_verification.py`
- `gateway/principal_profiles.py`
- `gateway/platforms/base.py`
- `plugins/platforms/line/adapter.py`
- `plugins/platforms/email/adapter.py`
- `hermes_cli/managed_downloads.py`
- `hermes_cli/web_server.py`

---

## 0. 這份 SOP 什麼時候要跑

以下任一情境，直接跑這份，不要用感覺判斷：

- `hermes update`
- Hermes Agent merge upstream / cherry-pick / refactor
- gateway restart / watchdog 自動重啟後
- messaging adapter / handoff / email delivery 相關 code 改動後
- shared drive 查找 / 展開 / 選檔 / 打包 workflow 相關 code 改動後
- principal / verification / quota / admin 後台相關 code 改動後
- 有人回報「又忘了綁定 / 又沒附件 / 又改寄錯 email / 又 replay 不對」時

---

## 1. 執行角色與輸出格式

### 1.1 執行角色
- **操作者**：執行 update / restart / merge / hotfix 的人
- **驗收者**：可與操作者同一人，但回報時必須分成「已確認」與「未確認」

### 1.2 最終回報格式
驗收完成後，統一用這種格式回報，不要散著講：

```md
更新/重啟驗收結果：
- 狀態：PASS / FAIL / PARTIAL
- 版本/變更：<這次做了什麼>
- Tier 1 測試：PASS/FAIL
- Tier 2 測試：PASS/FAIL
- 綁定 smoke：PASS/FAIL
- LINE 長任務 smoke：PASS/FAIL
- quota fallback smoke：PASS/FAIL
- email 附件 / 下載連結 smoke：PASS/FAIL
- shared drive workflow smoke：PASS/FAIL
- governance/admin smoke：PASS/FAIL
- blocker：<若有>
- 需追修：<若有>
```

---

## 2. 先分辨這次是哪種驗收

### A. 純 restart 驗收
適用：
- watchdog 自動重啟
- 手動 restart gateway/dashboard
- 沒改 code，只確認服務恢復

最少要做：
- 第 4 節「快速健康檢查」
- 第 6 節「核心 smoke」

### B. update / merge / code change 驗收
適用：
- Hermes update
- upstream merge
- 本地修 bug / refactor / patch

最少要做：
- 第 3 節「變更前標記」
- 第 5 節「測試分層執行」
- 第 6 節「核心 smoke」
- 第 7 節「治理後台特別檢查（若有碰 governance）」

---

## 3. 變更前標記（有改 code 時必做）

### Step 3.1
先打開：
- `gateway-change-impact-checklist.md`

### Step 3.2
勾出這次改到哪些模組：
- [ ] `gateway/config.py`
- [ ] `gateway/run.py`
- [ ] `gateway/authz_mixin.py`
- [ ] `gateway/user_verification.py`
- [ ] `gateway/principal_profiles.py`
- [ ] `gateway/platforms/base.py`
- [ ] `plugins/platforms/line/adapter.py`
- [ ] `plugins/platforms/email/adapter.py`
- [ ] `hermes_cli/managed_downloads.py`
- [ ] `hermes_cli/web_server.py`
- [ ] `web/src/...`

### Step 3.3
把「這次該跑的測試」先定出來，不要改完才想。

---

## 4. 快速健康檢查（2～5 分鐘）

這一段是 **最先跑** 的，不要一開始就陷入細節。

### 4.1 process / restart 狀態
- [ ] gateway 有起來
- [ ] 沒有重啟 loop
- [ ] dashboard / web server 能回應

### 4.2 基本功能面有沒有整片死掉
- [ ] 至少一個平台狀態可讀
- [ ] 管理平台頁面能開
- [ ] 沒有整片 401 / 403 / 500

### 4.3 若這裡就失敗
直接跳：
- `gateway-recovery-playbook.md`

不要先猜是 LINE 壞、email 壞，很多時候其實是 gateway 根本沒活穩。

---

## 5. 測試分層執行

## 5.1 Tier 1：所有 delivery 相關更新都先跑
```bash
venv/bin/pytest -q \
  tests/gateway/test_line_plugin.py \
  tests/gateway/test_email.py \
  tests/gateway/test_approval_prompt_redaction.py \
  tests/gateway/test_display_config.py \
  tests/hermes_cli/test_managed_downloads.py
```

### 判讀
- `test_line_plugin.py` 爆：先查 LINE state machine / fallback / file reroute
- `test_email.py` 爆：先查附件 / MIME / link-only fallback
- `test_managed_downloads.py` 爆：先查正式網址 / token / route

## 5.2 Tier 2：有碰綁定 / principal / governance 時再跑
```bash
venv/bin/pytest -q \
  tests/hermes_cli/test_web_verification_admin.py \
  tests/gateway/test_principal_profile_routing_phase1.py \
  tests/gateway/test_verified_email_handoff_guard_helpers.py
```

### 判讀
- `test_principal_profile_routing_phase1.py` 爆：先查 `config.py` / `run.py` / `authz_mixin.py` / `principal_profiles.py`
- `test_web_verification_admin.py` 爆：先查 `web_server.py` / `user_verification.py`
- `test_verified_email_handoff_guard_helpers.py` 爆：先查 live bound email guard

## 5.3 Tier 3：語法與基本匯入檢查
```bash
python -m py_compile \
  gateway/run.py \
  gateway/config.py \
  gateway/authz_mixin.py \
  gateway/user_verification.py \
  gateway/platforms/base.py \
  plugins/platforms/line/adapter.py \
  plugins/platforms/email/adapter.py \
  hermes_cli/managed_downloads.py \
  hermes_cli/web_server.py
```

---

## 6. 核心 smoke（一定按順序做）

這一段是整份 SOP 的重點，因為很多 bug 單元測試綠燈但 live 路徑還是會翻車。

### 6.1 綁定 smoke
依序確認：
- [ ] LINE 綁定 email 正確
- [ ] Telegram 綁定 email 正確
- [ ] OpenWebUI / api_server 綁定 email 正確
- [ ] system-initiated handoff 只會寄到 live bound email

若失敗先看：
- `gateway-functional-contract.md` 第 1 節
- `gateway-recovery-playbook.md` 3.1

### 6.2 principal profile routing smoke
- [ ] verified source 吃到正確 principal profile
- [ ] quick key / session namespace 正確
- [ ] restart 後 mapping 未漂移

若失敗先看：
- `gateway-regression-matrix.md`
- `gateway-recovery-playbook.md` 3.7

### 6.3 LINE 長任務 smoke
- [ ] 觸發一個會超過 pending threshold 的任務
- [ ] 有 pending 流程
- [ ] `查看答案` 在 `PENDING / READY / DELIVERED` 各狀態回應正確
- [ ] heartbeat / busy ack 文案不是 raw tool progress 噪音

若失敗先看：
- `gateway-functional-contract.md` 第 2 節
- `gateway-recovery-playbook.md` 3.2

### 6.4 LINE quota fallback → email smoke
- [ ] 模擬 LINE push 失敗
- [ ] pending 只寄一次
- [ ] final answer 真正寄到 verified email
- [ ] replay / postback 仍保留「已改寄 email」事實

若失敗先看：
- `gateway-functional-contract.md` 第 3 節
- `gateway-recovery-playbook.md` 3.3

### 6.5 email 附件 / 下載連結 smoke
- [ ] 小檔案：附件 + 下載連結
- [ ] 大檔案：只提供下載連結
- [ ] 附件檔名保留副檔名
- [ ] 下載連結網域正確
- [ ] 下載連結實際可下載

若失敗先看：
- `gateway-functional-contract.md` 第 4 節
- `gateway-recovery-playbook.md` 3.4 / 3.5

### 6.6 shared drive workflow smoke
- [ ] `shared_drive_chat_workflow.py search <query>` 可列候選且含 `file_id`
- [ ] `shared_drive_chat_workflow.py children <folder_file_id>` 可展開資料夾
- [ ] `shared_drive_chat_workflow.py bundle --file-ids ... --requester <email>` 可產 24h link
- [ ] 敏感檔會自動轉加密 zip
- [ ] 驗證以真實 GET 為準，`verification.ok = true`

若失敗先看：
- `docs/shared-drive-file-access/shared-drive-file-access-validation-matrix.md`
- `gateway-recovery-playbook.md` 3.7

---

## 7. 治理後台特別檢查（有碰 governance 時才做）

### 7.1 先分清楚你在驗什麼
先打開：
- `gateway-admin-ui-api-matrix.md`

先確認你驗的是：
- **後端-only API**
- 還是 **已存在的前端 UI**

不要把：
- Pairing
- Channels
- System

誤當成完整 governance console。

### 7.2 governance 後端 smoke
- [ ] `/api/admin/verification/role` 正常
- [ ] principals / identities 查得到
- [ ] quota policy / model policy 查得到
- [ ] principal usage 有資料
- [ ] audit log 查得到最近治理操作

### 7.3 若之後補了治理前端 UI
要額外驗：
- [ ] api.ts wrapper 存在
- [ ] App route / nav 存在
- [ ] viewer/operator/admin 權限文案正常
- [ ] 401 / 403 / 404 fallback 合理

---

## 8. FAIL 時不要亂修的規則

### 不要這樣做
- [ ] 還沒定位就直接 patch 一堆地方
- [ ] 只因為某條 smoke 壞，就把整個 feature 關掉當修復
- [ ] 只看一條 log 就武斷判定根因
- [ ] 沒先查 principal / binding，就把 delivery bug 當成純 email bug

### 要這樣做
1. 先看是 **哪一層** 壞：
   - process / restart
   - config / authz
   - session namespace / principal routing
   - delivery path
   - admin/governance API
2. 再回對應文件
3. 最後才 patch

---

## 9. 建議的固定執行時間線

### 情境：update / merge 後
1. 跑第 4 節快速健康檢查
2. 跑第 5 節 Tier 1 / Tier 2 / Tier 3
3. 跑第 6 節核心 smoke
4. 若有碰 governance，再跑第 7 節
5. 用第 1.2 節格式回報

### 情境：restart 後
1. 跑第 4 節快速健康檢查
2. 直接跑第 6 節核心 smoke
3. 若有 governance 影響，再跑第 7 節
4. 用第 1.2 節格式回報

---

## 10. 一句話版

> **先確認服務活著，再跑固定測試，再做固定 smoke，最後才修 bug；不要每次更新後都從聊天記憶和直覺重新發明驗收流程。**
