Files
awoooi/docs/superpowers/plans/2026-04-14-PHASE-5-category-buttons-completion.md
OG T 50edeaa9ea docs(Phase 5): 分類按鈕完整化 — 完整解決方案與實施步驟
統帥要求「提出完整的解決方案和詳細的實施步驟」→ 本 plan 回覆。

內容涵蓋:
- 28 按鈕完整 action → MCP tool 對應表(3 類:查/寫/secops)
- 6 個 Sprint 工作分解(5.0 規格 → 5.1 dispatch → 5.2 查類 → 5.3 寫類 → 5.4 secops → 5.5 E2E)
- 架構設計決策(callback_dispatcher registry pattern)
- 依賴與風險矩陣
- 5 個 E2E 驗收案例
- Rollout 策略(查類先上線,觀察 24h 再上寫類)

估時: 3-5 天(總計 5.5 工作日)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-04-14 20:22:03 +08:00

11 KiB
Raw Blame History

Phase 5 實施計畫Telegram 分類按鈕完整化

建立: 2026-04-14 台北深夜 Claude Sonnet 4.6(首席架構師) 狀態: 🟡 待統帥批准啟動 相關: ADR-079下架 + 計畫), feedback_no_ghost_buttons.md鐵律 估時: 3-5 天6 個 Sprint


0. 戰略目標

把已下架的 28 個分類按鈕完整實作為可用功能,讓 Telegram 卡片從「資訊展示板」升級為「一鍵 SRE 動作平台」。

成功條件

  • 統帥在 Telegram 點任何分類按鈕 → 在原卡片下方 reply 執行結果(成功/失敗/log摘要
  • 寫類按鈕(有副作用)有 nonce + audit log
  • 查類按鈕(無副作用)秒回
  • E2E 測試覆蓋 click → action → MCP → result reply 完整鏈

1. Action → MCP 對應表(完整規格)

1.1 查類按鈕(無副作用,優先實作)

# 分類 Action callback_data 格式 MCP Tool 參數 回覆
1 host_resource check_process check_process:{incident_id} ssh_get_top_processes host=from labels.instance Top 10 by CPU
2 host_resource check_log check_log:{incident_id} ssh_get_nginx_error_log / ssh_get_container_logs service=from signals 最後 50 行
3 network check_port check_port:{incident_id} ssh_check_port host, port Port 狀態
4 devops_tool check_log check_log:{incident_id} ssh_get_container_logs container_name 最後 50 行
5 storage check_minio_log check_minio_log:{incident_id} ssh_get_container_logs container=minio Log
6 external_site check_health check_health:{incident_id} prometheus_query probe_success{instance=...} Probe 結果
7 external_site check_log check_log:{incident_id} ssh_get_nginx_error_log host=188 Log
8 business open_signoz open_signoz:{incident_id} URL 返回) SignOz link 返回 deeplink URL
9 flywheel_health open_flywheel open_flywheel:{incident_id} URL 返回) Flywheel dashboard 返回 URL
10 database check_slow_query check_slow_query:{incident_id} database_list_slow_queries (需新增) namespace Slow query 列表

查類總計 10 個按鈕 | 估時 1 天

1.2 寫類按鈕(有副作用,需 nonce + audit

# 分類 Action callback_data4-part nonce MCP Tool 風險
11 kubernetes restart restart:{id}:{ts}:{rand} kubectl_restart MEDIUM
12 kubernetes scale_up scale_up:{id}:{ts}:{rand} kubectl_scale replicas+1 MEDIUM
13 kubernetes scale_down scale_down:{id}:{ts}:{rand} kubectl_scale replicas-1禁 0 MEDIUM
14 kubernetes rollback rollback:{id}:{ts}:{rand} kubectl_rollout_undo(需新增) HIGH
15 host_resource restart_service restart_service:{id}:{ts}:{rand} ssh_systemctl_restart HIGH
16 host_resource clear_log clear_log:{id}:{ts}:{rand} ssh_clear_docker_logs LOW
17 devops_tool restart_service restart_service:{id}:{ts}:{rand} ssh_docker_restart HIGH
18 storage restart_minio restart_service:{id}:{ts}:{rand} ssh_docker_restart container=minio HIGH
19 network reload_nginx reload_nginx:{id}:{ts}:{rand} ssh_reload_nginx LOW
20 ssl_cert renew_cert renew_cert:{id}:{ts}:{rand} ssh_renew_ssl MEDIUM
21 database kill_slow_query kill_slow_query:{id}:{ts}:{rand} kubectl_exec psql terminate HIGH
22 database clear_conn_pool clear_conn_pool:{id}:{ts}:{rand} kubectl_restart (間接) HIGH
23 business pause_1h pause_1h:{id}:{ts}:{rand} Alertmanager silence API LOW
24 flywheel_health trigger_diagnose flywheel_diagnose:{id}:{ts}:{rand} 內部 API call LOW

寫類總計 14 個按鈕 | 估時 2 天

1.3 資安按鈕(最高風險,需 Multi-Sig

# 分類 Action callback_data MCP Tool 風險
25 secops isolate secops_isolate:{id}:{ts}:{rand} kubectl_exec NetworkPolicy apply CRITICAL
26 secops block_ip secops_block_ip:{id}:{ts}:{rand} ssh_systemctl_restart iptables add CRITICAL
27 secops evict secops_evict:{id}:{ts}:{rand} kubectl_delete pod CRITICAL
28 secops authorize secops_authorize:{id}:{ts}:{rand} 內部授權 API HIGH

資安總計 4 個按鈕 | 估時 0.5 天


2. Sprint 工作分解

Sprint 5.0規格與設計0.5 天)

  • 建立 callback_action_spec.yaml — 每 action 的規格alert_category / MCP tool / 參數模板 / 風險 / 所需 label
  • 更新 _security.parse_callback_data() — 支援 action namespaced format
  • telegram_gateway.py_CATEGORY_ACTIONS registryaction → spec

Sprint 5.1Dispatch 框架0.5 天)

  • 新增 apps/api/src/services/callback_dispatcher.py
    • async def dispatch_action(action: str, incident_id: str, user: User) -> ActionResult
    • 從 registry 查 spec → 建 MCP call → 執行 → format reply
  • telegram_gateway._handle_callback_query 加 fallback 分支 → callback_dispatcher.dispatch_action()
  • Reply 格式:✅ {action_label}\n<code>{mcp_output[:500]}</code> reply_to 原卡片

Sprint 5.2查類按鈕實作1 天)

按 1.1 表格實作 10 個查類按鈕。每按鈕:

  • callback_data 用 2-part info 格式(無副作用無需 nonce
  • dispatcher 呼叫對應 MCP tool
  • reply_to 原卡片顯示結果摘要
  • 單元測試action spec 註冊 + dispatch 呼叫正確 MCP
  • E2E 測試:發告警 → 點按鈕 → reply 正確

Sprint 5.3寫類按鈕實作2 天)

按 1.2 表格實作 14 個寫類按鈕。每按鈕:

  • callback_data 用 4-part nonce 格式
  • nonce 驗證通過
  • dispatcher 執行前 log audit_action_start
  • MCP 執行
  • 執行後 log audit_action_complete + reply 原卡片
  • 失敗 reply 「 執行失敗: {error}」
  • rollback 動作需 Multi-Sig見 Sprint 5.4

Sprint 5.4資安按鈕Multi-Sig0.5 天)

4 個 secops 按鈕都標為 CRITICAL

  • 啟用 Guardrail BLOCK 層(已有 sprint5r_guardrail
  • 2 人簽核才執行current_signatures >= 2
  • audit log 需記錄兩個簽核者
  • 失敗通知發 SRE 群組 + 統帥 DM

Sprint 5.5E2E 測試與上線1 天)

  • 每按鈕至少 1 個 E2E 測試click simulation → dispatcher → MCP mock OR real → reply
  • 端到端驗證:真實告警觸發 → 統帥 Telegram 點按鈕 → 看到 reply
  • Rollout 策略先上查類Sprint 5.2)觀察 24h確認零 bug 再上寫類5.3
  • 更新 ADR-079 狀態為 Completed

3. 架構設計決策

3.1 為何用 callback_dispatcher 而非每按鈕寫 elif

原因

  • 28 個按鈕寫 28 個 elif → 900 行代碼,違反 leWOOOgo 積木化
  • Registry pattern + spec 分離 → 新增按鈕只需 yaml 一行

檔案結構

apps/api/src/services/
├── callback_dispatcher.py      # dispatcher 主邏輯
├── callback_action_spec.yaml   # action → MCP spec 註冊
└── callback_action_registry.py # spec loader (lru_cache)

3.2 為何不直接重新啟用 _CATEGORY_BUTTONS

原因

  • 當前下架狀態 = 零風險 baseline
  • Phase 5 完成才重新啟用(按 category 逐批)
  • 避免「啟用→爆炸→再下架」振盪

步驟

  1. Phase 5.2 完成 → 啟用查類按鈕(只 check_*
  2. 觀察 24h
  3. Phase 5.3 完成 → 啟用寫類按鈕
  4. Phase 5.4 完成 → 啟用 secops 按鈕

3.3 reply_to 訊息策略

所有 action reply 必須 reply_to_message_id=原告警卡 msg_id

  • 用戶可以點 reply 看到對應的告警上下文
  • Redis tg_msg:{incident_id} 已有此資料approval_execution 用同一套)

4. 依賴與風險

4.1 必須先修的技術債

  • _security.parse_callback_data() 目前只認 4-part nonce 和 2-part info需擴充為「註冊表驗證」
  • Redis tg_msg:{incident_id} 寫入時機確認approval_execution 寫,其他路徑也要寫)
  • callback_dispatcher 要整合 Langfuse trace每 action 可追蹤)

4.2 新增 MCP 能力

  • kubectl_rollout_undoSprint 5.3 rollback 按鈕需要)
  • database_list_slow_queriesSprint 5.2 database check 需要)
  • Alertmanager /api/v2/silences integrationSprint 5.3 pause_1h 需要)

4.3 風險

風險 機率 影響 緩解
寫類按鈕被誤點 非預期修復 nonce 4-part + 寫明「確認執行」 UI
Multi-Sig 未達 2 人 secops 動作卡住 超時 15 min 降級 TYPE-4 人工
MCP 呼叫超時 用戶看不到 reply 每 dispatcher call 包 30s timeout
大量同時點按鈕 Ollama/K8s 負載 Redis lock dispatch:{incident_id}:{action} 60s

5. 驗收標準

5.1 單元測試覆蓋率

  • callback_action_spec loader 100%
  • callback_dispatcher 主路徑 + 錯誤路徑 > 80%
  • 每按鈕 action → MCP mapping 正確性測試

5.2 E2E 驗收

  • E2E-1 (查類):發 HostHighCpuLoad 告警 → 點「🔍 查程序」→ 1 秒內 reply「Top 10 processes」
  • E2E-2 (寫類):發 KubePodCrashLooping → 點「🔄 重啟」→ nonce 驗證 → 執行 kubectl rollout restart → reply「 執行成功」
  • E2E-3 (secops):發 UnauthorizedSSH → 點「🚫 隔離」→ 等第二簽核 → apply NetworkPolicy → reply「 已隔離」
  • E2E-4 (failure):寫類按鈕執行失敗 → reply「 執行失敗: {error}」+ fallback TYPE-4 人工審核
  • E2E-5 (nonce replay):舊 callback_data 重複使用 → parser reject → reply「⚠️ Callback 已過期」

5.3 效能指標

  • 查類按鈕 P95 < 2s
  • 寫類按鈕 P95 < 10s含 MCP call + reply
  • 所有 dispatcher call 100% 記錄 audit log

6. 文件更新

Phase 5 完成後需更新:

  • ADR-079 狀態改為 Completed
  • ADR-075 更新:分類按鈕從 _CATEGORY_BUTTONS dict 改引用 registry
  • LOGBOOK.md 記錄 Sprint 5.0-5.5 完成
  • docs/operations/ON-CALL-HANDBOOK.md 新增「如何用 Telegram 按鈕自助排障」章節
  • docs/reference/ALERT-TAXONOMY-CATALOG.md 每分類加「可用按鈕」欄位

7. 起始點(等批准後第 1 步)

Kick-off 檢查0.5 小時):

# 1. 確認 MCP provider 全綠
kubectl exec -n awoooi-prod deploy/awoooi-api -- python -c "
from src.plugins.mcp.registry import list_providers
for p in list_providers():
    print(f'{p.name}: {len(p.tools)} tools')
"
# 預期: k8s=10, ssh=15, prometheus=3, signoz=5, database=4, sentry=3

# 2. 確認 Redis tg_msg:* 有資料
ssh 192.168.0.188 'redis-cli -p 6380 -n 10 KEYS "tg_msg:*" | head'

# 3. 確認 Guardrail BLOCK 層啟用Sprint 5.4 依賴)
grep "GUARDRAIL_MODE" apps/api/src/core/config.py

批准後第 1 個 commit 範圍:callback_action_spec.yaml + callback_dispatcher.py 骨架 + 單元測試。


Awaiting 統帥批准 → 啟動 Sprint 5.0