emma-hermes/docs/gateway-resilience/gateway-recovery-playbook.md

9.3 KiB
Raw Blame History

Gateway Recovery Playbook

目標:當 gateway 更新後再次出現綁定錯亂、長任務異常、LINE quota fallback 失效、email 附件壞掉時,可以不用重翻歷史對話試錯,而是按固定順序定位。

0. 先判斷是哪一類故障

A. 綁定 / 寄錯信

症狀:

  • 寄到錯 principal 的 email
  • Telegram / LINE / OpenWebUI 對應到錯綁定
  • fallback email 被 block 或誤放行

先看:

  • gateway/user_verification.py
  • plugins/platforms/line/adapter.py

B. LINE 長任務 / 查看答案異常

症狀:

  • 查看答案 取不到結果
  • 一直顯示還在處理中
  • DELIVERED 後 replay 不符合實際交付 surface

先看:

  • plugins/platforms/line/adapter.py
  • RequestCache
  • _handle_postback_event(...)

C. LINE quota fallback / email fallback 異常

症狀:

  • LINE 429 後沒寄 email
  • 有寄 email 但 replay 還假裝 LINE 已成功
  • final 已寄 email附件卻又跑回 LINE 失敗

先看:

  • plugins/platforms/line/adapter.py
  • gateway/platforms/base.py

D. Email 附件 / 下載連結異常

症狀:

  • 沒附件
  • 附件沒副檔名
  • 下載連結打不開
  • 附件過大直接寄失敗

先看:

  • plugins/platforms/email/adapter.py
  • hermes_cli/managed_downloads.py
  • hermes_cli/web_server.py

E. Shared drive workflow 異常

症狀:

  • 搜尋找不到明明存在的檔案/資料夾
  • 資料夾展開後沒有列出可選檔案
  • bundle 沒產生連結或敏感檔沒加密
  • 24h 連結被誤判壞掉,其實只是 HEAD / bot-like client 驗證失真

先看:

  • ~/.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
  • docs/shared-drive-file-access/shared-drive-file-access-validation-matrix.md

F. 額度 / 權限 / 管理後台異常

症狀:

  • dashboard role 消失或全部變 viewer
  • principal / identity list 不見
  • quota policy / model policy 查不到
  • principal usage 不再累積

先看:

  • gateway/user_verification.py
  • hermes_cli/web_server.py
  • gateway/principal_profiles.py

1. 第一層:不要先猜,先跑最小測試

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 \
  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_line_plugin.py 爆:先看 LINE state machine / fallback ownership / file reroute
  • test_email.py 爆:先看 MIME / HTML / attachment handling
  • test_managed_downloads.py 爆:先看正式網域 URL / token / route
  • test_approval_prompt_redaction.py 爆:先看 approval text fallback / redaction seam
  • test_display_config.py 爆:先看 LINE 是否又被改回 noisy 模式

2. 第二層live log 定位

主要看:

  • ~/.hermes/logs/gateway.log

綁定問題關鍵字

  • verified-email mismatch
  • blocked email handoff
  • get_verified_email_for_source

LINE quota fallback 關鍵字

  • LINE: push send failed
  • LINE Push 額度已滿
  • email_fallback
  • email_fallback_pending
  • Routed LINE attachment delivery to verified email fallback
  • Skipping LINE media attachment send because quota fallback email already carried

Email 附件問題關鍵字

  • Sent multi-attachment email
  • standalone attachment failed
  • size limit
  • Email send failed

Managed downloads 關鍵字

  • /downloads/
  • invalid_download_signature
  • expired_download_token
  • not found

Shared drive workflow 關鍵字

  • verification
  • shared-drive
  • expired_download_token
  • invalid_download_signature
  • find_by_file_ids

governance / admin 關鍵字

  • forbidden
  • unauthenticated
  • dashboard_role_not_persisted
  • principal_usage_not_persisted
  • identity_not_found_after_unbind

3. 第三層:依故障類型對照修復順序

3.1 若是寄錯信 / 綁定錯亂

  1. 確認 active source 是哪個平台、哪個 external user id
  2. GatewayUserStore.get_verified_email_for_source(...)
  3. bound_email_matches_source(...)
  4. 確認呼叫端是否用了 explicit_user_requested=True
  5. 若沒有使用者明確指定其他 email卻仍能寄到不同信箱視為重大回歸

3.2 若是 LINE pending / show_response 異常

  1. _pending_buttons 是否有建立
  2. RequestCache 狀態是否真的進到 READY
  3. _handle_postback_event(...) 是否把 payload 當成一般文字,而不是 email_fallback*
  4. 若 final surface 已是 emailreplay 仍顯示 generic delivered copy代表 fallback payload 被覆蓋或遺失

3.3 若是 final 已寄 email但附件又誤走 LINE

  1. gateway/platforms/base.py
  2. 確認 result.raw_response.kind == email_fallback
  3. 確認 should_route_poststream_files_to_email(chat_id) 為真
  4. 確認 send_email_file_batch_fallback(...) 成功後 skip_platform_media_delivery = True

3.4 若是附件寄失敗 / 沒副檔名

  1. _standalone_send(...)
  2. 確認 MIMEMultipart 是否建立
  3. 確認 attachment 的 Content-Disposition filename=
  4. 確認 mimetypes.guess_type(...) 結果與 fallback content-type

3.5 若是下載連結壞掉

  1. build_public_download_url(...)
  2. 查 token 是否可 resolve_signed_download_token(...)
  3. 實際 GET /downloads/{token}
  4. 若 route 404先確認
    • URL 是否正式網域
    • token 是否重啟後仍可驗證
    • staged file 是否存在

3.6 若是 dashboard role / quota / usage 異常

  1. 先打 /api/admin/verification/role
  2. 再查 /api/admin/verification/roles
  3. 再查 /api/admin/verification/principals
  4. 再查 /api/admin/quota-policies/api/admin/model-policies
  5. 再查 /api/admin/principal-usage
  6. 若 usage 為空,但聊天明明有跑:
    • gateway/run.pyrecord_usage_for_source(...)
    • 確認 source 仍能解析 principal context

3.7 若是 shared drive workflow 壞掉

  1. 先跑:
python3 ~/.hermes/scripts/shared_drive_chat_workflow.py search <query>
python3 ~/.hermes/scripts/shared_drive_chat_workflow.py children <folder_file_id>
python3 ~/.hermes/scripts/shared_drive_chat_workflow.py bundle --file-ids <file_id> --requester dk96@bremen.com.tw
  1. 若 search 沒結果:先查 index 是否重建、shared_drive_index_query.py status 是否有資料
  2. 若 children 空掉:先查該 file_id 是否仍是資料夾、parent_dir 是否對得上
  3. 若 bundle 失敗:先查 find_by_file_ids(...)、staging 目錄、manifest 是否落地
  4. 若外部連結被判失敗:
    • 以真實 GET 驗證,不以 HEAD 為準
    • 不把 urllib / Cloudflare 1010 當成最終失敗判準
    • 確認 verification.ok = true
  5. 若敏感檔沒加密:查 detect_sensitivity(...) 與 bundle payload 的 encrypted / password_channel

3.8 若是 principal profile 漂移

  1. GatewayUserStore.get_principal_context(source) 是否還拿得到 principal_id
  2. gateway/principal_profiles.py::resolve_principal_profile(...)
  3. principal_profile_map.json 是否被重建或覆蓋
  4. 若 mapping 漂移,先修 principal context不要先誤判成單純 delivery bug

4. 更新後固定 smoke checklist

綁定

  • LINE 綁定 email 正確
  • Telegram 綁定 email 正確
  • OpenWebUI / api_server 綁定 email 正確
  • system-initiated handoff 不會寄到非 live bound email

LINE 長任務

  • pending button / wait notice 正常
  • 查看答案PENDING/READY/DELIVERED 各自回應正確
  • heartbeat 文案不是 raw tool progress 噪音

quota fallback

  • LINE 429 後有 email fallback
  • pending 只寄一次等待通知
  • final 真正寄到 verified email
  • replay 說明仍保留 email fallback 事實

權限 / 額度 / 管理後台

  • /api/admin/verification/role 回應符合預期角色
  • principals / identities 列表查得到
  • quota policy / model policy 還在
  • principal usage 持續累積
  • audit log 查得到最近治理操作

email 附件 / 下載連結

  • 小檔案:附件 + 連結
  • 大檔案:只有連結
  • 附件有副檔名
  • 下載連結可點、可下載、網域正確

shared drive workflow

  • search 可列出候選與 file_id
  • children 可展開資料夾並列出最多 10 檔可選項
  • bundle 可產出 24h 連結
  • 敏感檔自動轉加密 zip
  • verification.ok = true

approval

  • approval 信 / 訊息為繁中對客版
  • raw command / token 未外露

5. 維護建議

必做

  • 任何改到上述模組的 PR都在描述中附上
    • 改了哪條契約
    • 跑了哪些 regression tests
    • 做了哪些 live smoke

建議

  • 之後可再補一份 gateway-change-impact-checklist.md
  • 讓每次 update / refactor 前先做 preflight 勾選:
    • 有無碰 principal binding
    • 有無碰 LINE pending/postback
    • 有無碰 email MIME / managed downloads

一句話原則

先用契約定位,再用測試驗證,最後才 patch。

不要再回到「翻對話、猜哪裡壞、邊改邊試」那種高 token、低穩定度修法。