# Gateway Change Impact Checklist

> 目標：把「你改了哪裡，就一定要驗哪些功能 / 跑哪些測試 / 做哪些 smoke」固定成一張 **更新前、改動中、合併前、重啟後** 都能直接打勾的清單，避免每次靠回憶或翻舊對話排查。

## 實際程式碼再確認

本清單依下列 live 落點整理：

- `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`
- `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/gateway/test_principal_profile_routing_phase1.py`
- `tests/gateway/test_verified_email_handoff_guard_helpers.py`
- `tests/hermes_cli/test_managed_downloads.py`
- `tests/hermes_cli/test_web_verification_admin.py`

這份 checklist 的用途不是取代設計文件，而是把 **變更衝擊 → 驗收責任** 直接綁死。

---

## 0. 使用規則

### 0.1 什麼時候一定要用這份
只要你碰到以下任一類改動，就不能跳過：
- Hermes Agent update / merge upstream
- gateway restart / restart watchdog 調整
- messaging adapter 改動
- 綁定 / principal / verification 改動
- LINE 長任務 / email fallback / 檔案交付改動
- shared drive 查找 / 展開 / 選檔 / 打包 workflow 改動
- quota / role / admin API / dashboard 管理功能改動

### 0.2 勾選規則
- **改到哪個模組，就勾對應區塊，不要只挑自己喜歡的測試跑。**
- 若一個改動同時跨 `run.py` + `line/adapter.py` + `web_server.py`，三塊都要驗。
- 若不確定算不算有影響，**寧可多勾，不要少勾**。

### 0.3 驗收原則
- 單元測試綠燈 ≠ 真正完成。
- 至少要包含：
  1. 對應 pytest
  2. 最少 smoke
  3. 有 side effect 的路徑要實際驗一次

---

## 1. 更新前預檢

### 1.1 先標記這次改到哪些檔案
- [ ] `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/...` dashboard / governance 前端
- [ ] 其他：____________

### 1.2 先判斷功能衝擊面
- [ ] principal / verified email 綁定
- [ ] principal profile routing
- [ ] Telegram / OpenWebUI / LINE / email handoff
- [ ] LINE 長任務 pending / replay / heartbeat
- [ ] LINE 額度不足 fallback 到 email
- [ ] email MIME attachment / link-only fallback
- [ ] managed download 正式網址與下載 route
- [ ] shared drive search / children / bundle workflow
- [ ] approval / 對客文案 / redaction
- [ ] quota policy / model policy / principal usage
- [ ] dashboard role / admin audit / management console

---

## 2. 模組 → 必跑測試 對照

### 2.1 `gateway/config.py`
**高風險原因：** 很容易一改 config schema，就把 runtime 接線弄掉。

- [ ] 跑：
```bash
venv/bin/pytest -q \
  tests/gateway/test_principal_profile_routing_phase1.py \
  tests/hermes_cli/test_web_verification_admin.py
```
- [ ] 確認 nested `gateway.*` 與 top-level 設定都仍被吃到
- [ ] 確認沒有把既有 fallback / display / admin 設定吃壞

### 2.2 `gateway/run.py`
**高風險原因：** 這裡牽動授權、session key、長任務、approval、usage 記帳。

- [ ] 跑：
```bash
venv/bin/pytest -q \
  tests/gateway/test_approval_prompt_redaction.py \
  tests/gateway/test_display_config.py \
  tests/gateway/test_principal_profile_routing_phase1.py \
  tests/hermes_cli/test_web_verification_admin.py
```
- [ ] 確認 verified source 不會被打進 unauthorized
- [ ] 確認 principal profile routing 發生在 session lookup 前
- [ ] 確認長任務文案仍是 generic / 安靜模式
- [ ] 確認 usage 記帳沒斷

### 2.3 `gateway/authz_mixin.py`
- [ ] 跑：
```bash
venv/bin/pytest -q \
  tests/gateway/test_principal_profile_routing_phase1.py \
  tests/gateway/test_verified_email_handoff_guard_helpers.py
```
- [ ] 確認 verified source 被視為合法來源
- [ ] 確認不是誤開成 fail-open 授權

### 2.4 `gateway/user_verification.py`
- [ ] 跑：
```bash
venv/bin/pytest -q \
  tests/hermes_cli/test_web_verification_admin.py \
  tests/gateway/test_verified_email_handoff_guard_helpers.py \
  tests/gateway/test_principal_profile_routing_phase1.py
```
- [ ] 確認 get/bind principal context 正常
- [ ] 確認 bound email live confirm 正常
- [ ] 確認 quota / model / role / audit / usage schema 與 API 沒壞

### 2.5 `gateway/principal_profiles.py`
- [ ] 跑：
```bash
venv/bin/pytest -q tests/gateway/test_principal_profile_routing_phase1.py
```
- [ ] 確認同一 principal 仍映射到同一 profile
- [ ] 確認 `principal_profile_map.json` 不會被莫名覆寫

### 2.6 `plugins/platforms/line/adapter.py`
- [ ] 跑：
```bash
venv/bin/pytest -q \
  tests/gateway/test_line_plugin.py \
  tests/gateway/test_display_config.py
```
- [ ] 確認 `PENDING -> READY -> DELIVERED / ERROR` 狀態機正常
- [ ] 確認 `查看答案` replay 不失真
- [ ] 確認 quota fallback 轉 email 後，replay 仍保留 fallback 事實
- [ ] 確認 pending 通知不會狂寄
- [ ] 確認 **已寄 pending email 後，最終答案完成會自動走 final email fallback，不會只卡在 `READY` 等使用者再按 `查看答案`**
- [ ] 確認 **final email fallback 成功後，RequestCache 會收斂成 `DELIVERED`，且 `_pending_buttons` 會清掉**
- [ ] 確認 **若 LINE 使用者回 `?` / `？` / `妳還好嗎` / `沒收到` 這類低訊號追問，會優先走 recovery probe：重播最近一次可見交付內容或 pending/email fallback 通知，且使用 fresh push 路徑，不要再把這類訊號丟回模型當全新任務**
- [ ] 確認 **搜尋/找檔任務若範圍過廣或處理過久，LINE 端會直接提示使用者回到原 LINE 對話補充位置/大類/關鍵字，不要把需求收斂工作丟到其他平台除錯**
- [ ] 確認 **LINE quota/email fallback 的使用者文案仍保留既有繁中語氣，並明確說明可在同一條 LINE 對話接著補充，不要出現跨平台 debug 指引**

### 2.7 `gateway/platforms/base.py`
- [ ] 跑：
```bash
venv/bin/pytest -q tests/gateway/test_line_plugin.py
```
- [ ] 確認 final 已轉 email 時，post-stream files 不會又回頭走 LINE
- [ ] 確認 `skip_platform_media_delivery` 類邏輯仍正確

### 2.8 `plugins/platforms/email/adapter.py`
- [ ] 跑：
```bash
venv/bin/pytest -q tests/gateway/test_email.py
```
- [ ] 確認附件存在、檔名有副檔名、MIME 正確
- [ ] 確認 HTML / text 內下載網址可點擊，且優先使用短碼型網址（例如 `/downloads/s-<short_id>`）
- [ ] 確認大附件會退成 link-only，不是直接寄失敗
- [ ] 確認 generic documents（`pptx/pdf/docx/xlsx/zip`）預設走 **24h 短下載連結**，不是只靠附件
- [ ] 確認 LINE / quota fallback 走到 standalone email 時，寄件人名稱仍是 **`不來梅的艾瑪 <bremen.hermes@gmail.com>`**
- [ ] 確認 LINE / quota fallback email 主旨是**自然中文**，不可退回 `Hermes Agent` 這類通用機器主旨
- [ ] 確認 LINE / quota fallback email 內文符合既有對客文案規範：簡潔、可交付、說明原因，但不寫成系統廣播

### 2.9 `hermes_cli/managed_downloads.py`
- [ ] 跑：
```bash
venv/bin/pytest -q tests/hermes_cli/test_managed_downloads.py
```
- [ ] 確認 token 可 resolve
- [ ] 確認 URL shape 與正式網域沒跑掉
- [ ] 確認短碼 `/downloads/s-<short_id>` 可 resolve，且仍保留舊長 token 相容

### 2.9b `~/.hermes/scripts/shared_drive_index_query.py` / `shared_drive_lookup.py` / `shared_drive_delivery_bundle.py` / `shared_drive_chat_workflow.py`
- [ ] 跑：
```bash
python3 -m py_compile \
  ~/.hermes/scripts/shared_drive_index_query.py \
  ~/.hermes/scripts/shared_drive_lookup.py \
  ~/.hermes/scripts/shared_drive_delivery_bundle.py \
  ~/.hermes/scripts/shared_drive_chat_workflow.py \
  ~/.hermes/scripts/shared_drive_cleanup.py
```
- [ ] `shared_drive_chat_workflow.py search <query>` 可產出候選清單
- [ ] `shared_drive_chat_workflow.py children <folder_file_id>` 可展開資料夾
- [ ] `shared_drive_chat_workflow.py bundle --file-ids ... --requester <email>` 可產出 24h link
- [ ] 敏感檔會改走加密 zip，並保留第二通道密碼通知資訊
- [ ] `verification.ok = true`，不得只看 HEAD；以真實 GET 驗證為準
- [ ] 若回覆提供下載網址，必須是**完整網址**；不得出現 `...` / `…` 導致 token 被截斷
- [ ] shared drive 在 Telegram / email 對 generic documents 預設提供 **24h 短下載連結**；可直送圖片（jpg/png）才優先附件
- [ ] shared drive 候選/展開/下一步建議需支援**數字序號回覆**（例如 `1`、`1 3 5`）

### 2.10 `hermes_cli/web_server.py`
- [ ] 跑：
```bash
venv/bin/pytest -q \
  tests/hermes_cli/test_web_verification_admin.py \
  tests/hermes_cli/test_managed_downloads.py
```
- [ ] 確認 downloads route 可用
- [ ] 確認 verification/admin/quota/model/usage/audit API 可用
- [ ] 確認 role gate 沒被洗掉

### 2.11 `web/src/...` dashboard / governance 前端
- [ ] 至少做一次 UI/API 對照盤點
- [ ] 確認前端呼叫的 API 路徑仍存在
- [ ] 確認治理後台文案沒出現錯誤 fallback

---

## 3. 功能主線 → 必驗 smoke

### 3.1 綁定 / principal / handoff
- [ ] 從 LINE 確認目前綁定 email 正確
- [ ] 從 Telegram 確認目前綁定 email 正確
- [ ] 從 OpenWebUI / api_server 確認目前綁定 email 正確
- [ ] system-initiated handoff 只會寄到 live bound email
- [ ] 使用者若明確指定其他 email，例外路徑仍正常

### 3.2 principal profile routing
- [ ] verified source 會穩定吃到 principal profile
- [ ] quick key / session namespace 有切到對應 profile
- [ ] restart 後 mapping 未漂移

### 3.3 LINE 長任務
- [ ] 任務超過 pending threshold 時會出現 pending 流程
- [ ] `查看答案` 在 `PENDING/READY/DELIVERED` 各狀態回應正確
- [ ] heartbeat / busy ack 文案仍是對客版，不是 raw tool progress

### 3.4 LINE quota fallback → email
- [ ] 模擬 LINE push 失敗後，會改寄 verified email
- [ ] pending 通知只寄一次
- [ ] final answer 真正有寄到 email
- [ ] replay / postback 仍說明「已改寄 email」
- [ ] 若 slow-response button 已存在，**final answer 仍要直接寄 final email**，不能只塞 cache 然後停在 `READY`
- [ ] final email 成功後，`查看答案` / bare `?` 不得再像未交付一樣等待領取；應反映 **已改寄 email / 已交付**
- [ ] 進入 quota fallback 後，後續 heartbeat / pending 提示不得每分鐘持續重撞 LINE push 產生 429 噪音
- [ ] 至少保留一個**真實驗收案例**可回看；目前可參照：`~/.hermes/skills/devops/line-gateway-delivery-debugging/references/line-welcome-kit-scope-and-email-smoke-2026-07-19.md`

### 3.5 email 附件 / 下載連結
- [ ] 小檔案：有 MIME attachment + 有下載連結
- [ ] 大檔案：不硬塞附件，只提供下載連結
- [ ] 附件檔名保留副檔名
- [ ] 下載連結使用正式網域
- [ ] 下載連結優先用短碼型網址（例如 `/downloads/s-<short_id>`）
- [ ] 下載連結實際可點開下載

### 3.5b Telegram 檔案交付
- [ ] `jpg/png` 可走原生附件時，仍可正常送出
- [ ] generic documents（`pptx/pdf/docx/xlsx/zip`）預設優先提供 **24h 短下載連結**，不要只丟原生文件附件
- [ ] 若同時提供文字說明與下載網址，訊息中不得出現 `...` / `…` 截斷 token
- [ ] 下載連結實際可點開下載

### 3.6 shared drive workflow
- [ ] search 會列出候選，且含 `file_id`
- [ ] children 會列出資料夾內可選檔案，且提示最多 10 檔
- [ ] bundle 對單檔可直接交付，對敏感/多檔可自動轉 zip
- [ ] bundle manifest 有 `verification.ok = true`
- [ ] 不以 urllib/HEAD 403 或 405 誤判為下載路徑壞掉
- [ ] Telegram / email 的 shared drive 完成訊息，generic documents 預設給 **24h 短下載連結**
- [ ] 只有 `jpg/png` 等可安全直送媒體才優先原生附件

### 3.7 governance / admin / quota
- [ ] principals / identities 列表查得到
- [ ] dashboard role 還在
- [ ] quota policy / model policy 查得到
- [ ] principal usage 有累積
- [ ] audit log 查得到最近治理操作

---

## 4. 合併前最小命令清單

### 4.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
```

- [ ] 上述命令通過

### 4.2 binding / 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
```

- [ ] 上述命令通過

### 4.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
```

- [ ] 上述命令通過

---

## 5. restart / update 後固定檢查

### 5.1 不要只看 process 有起來
- [ ] gateway process 有起來
- [ ] 不是重啟 loop
- [ ] 不只看健康頁，也看功能 smoke

### 5.2 restart 後至少做這些
- [ ] 綁定查詢正常
- [ ] principal profile mapping 未漂移
- [ ] LINE 慢任務正常
- [ ] email fallback 正常
- [ ] managed download 正常
- [ ] shared drive workflow 正常
- [ ] governance/admin API 正常

### 5.3 restart / update 後必跑實際 smoke case（最小版）
- [ ] **Telegram generic document**：實際交付一個 `pptx/pdf/docx/xlsx/zip`，確認完成訊息內含 **24h 短下載連結**（`/downloads/s-<short_id>`），且不是只有原生附件
- [ ] **Telegram image**：實際交付一個 `jpg/png`，確認可直送原生附件時仍正常
- [ ] **email generic document**：實際寄送一個 `pptx/pdf/docx/xlsx/zip`，確認信內有 **24h 短下載連結**、正式網域、可點開
- [ ] **email oversize / link-only**：模擬附件過大情境，確認不硬塞附件、而是只提供短下載連結
- [ ] **LINE quota fallback → email**：模擬 LINE 無法交付時，確認最後 email 內仍保留原始檔案的短下載連結
- [ ] **LINE quota fallback state收斂**：模擬 `sent slow-LLM postback button -> pending email -> final answer ready`，確認最終狀態為 `DELIVERED`，不是 `READY`
- [ ] **LINE 模糊找檔收斂 + email fallback**：至少跑一次 `welcome kit / 新人報到資料` 類案例，確認會先在 LINE 原對話要求補大類/位置/關鍵字，不會跨平台除錯；若改寄 Email，寄件人名稱與中文主旨需符合既有規範
- [ ] **shared drive bundle**：實際跑一次 `shared_drive_chat_workflow.py bundle ...`，確認輸出的 `download_url` 為短碼型網址、`verification.ok = true`

### 5.4 smoke 判定規則
- [ ] 不能只看 HTTP `200`；要確認使用者可見文案符合交付規則
- [ ] 不能只看附件成功；generic documents 還要確認**短下載連結**存在，否則 24h 時效規則不算落地
- [ ] 不能只用截圖或預覽判定；至少要做一次真實點開 / GET 驗證

---

## 6. 明確禁止的錯誤驗收方式

- [ ] 不能只說「程式有改好」但沒跑測試
- [ ] 不能只跑 unit test，沒做任何實際交付 smoke
- [ ] 不能只驗 LINE 文字回覆，不驗 email / 附件 / 下載連結
- [ ] 不能只看 admin API 有 200，就當 governance 完整正常
- [ ] 不能因為某條路徑現在沒報錯，就假設 restart 後也沒問題

---

## 7. 維護建議

### 7.1 每次新增回歸點時同步更新
- [ ] `gateway-functional-contract.md`
- [ ] `gateway-regression-matrix.md`
- [ ] `gateway-recovery-playbook.md`
- [ ] `docs/shared-drive-file-access/*`
- [ ] 本 checklist

### 7.2 最重要的一句
> **未來不是「修好 bug 就好」，而是「修好後要把影響面與驗收責任寫進清單」，不然同一類 bug 還是會 cosplay 成不同型態再回來。**
