## 新增
- ADR-093: Telegram 告警全面遷移至 SRE 戰情室群組
- 混合策略 allowlist 模式(TYPE-3/4/4D/8M → 群組 + user_id binding)
- nonce 新格式 apr:{short_id}:{action}:{user_id_hash} + Redis 後端映射
- Feature flag TG_GROUP_CUTOVER 灰階切流
- ADR-094: Hermes 自然語言介面(@mention 對話)
- Option C:單 bot + Claude Agent SDK 虛擬分派
- Webhook secret_token + allowed_updates = [message, callback_query, chat_member]
- Prompt Injection 防護:query/describe/summarize only,mutate 走 ApprovalRecord
- Redis session TTL=300s + turn>=5 壓縮
- ADR-095: 12-Agent Claude SDK 整合 × Telegram 視覺分派
- 12 位 agent 完整 emoji/hashtag/handle 表格
- ConsensusEngine weights 擴充(security=0.4 鎖定)
- display_names.py 命名隔離(.claude/agents/ vs src/agents/)
## 更新
- ADR-009: 加 v0.3 變更紀錄指向 ADR-095
- ADR-075: 加更新引用表(ADR-093 D4 allowlist 子條款、ADR-094/095)
- docs/design/hermes-telegram-flows/hermes-flows.html: F1-F7 完整流程圖
## Pre-Flight 確認
- approval_records 表尚不存在 → 將用 BIGINT 全新建立
- docker-compose.yml:78 明碼 token 🔴 P0 待 WS1 修復
- awoooi_migrator 角色尚未建立 → WS2 建立
- claude-agent-sdk 升至 0.1.66(最新)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
7.2 KiB
7.2 KiB
ADR-075:Telegram 告警通知格式標準化與完整流程修復
狀態: 🟡 批准實作中 建立日期: 2026-04-12(台北時間) 決策者: 統帥 ogt + Claude Sonnet 4.6 相關 ADR: ADR-071(四種通知類型)、ADR-073(飛輪修復)、ADR-074(監控補全)
背景
ADR-071(2026-04-11)設計了 TYPE-1/2/3/4/4D 五種通知類型,並實作了 classify_alert_early()、_build_inline_keyboard() 等函數。但在 2026-04-12 的全面盤點中,發現整條資料流存在 4 個斷點,導致動態分類按鈕從未真正生效,所有 TYPE-3 告警一律 fallback 到通用的 [批准][拒絕][靜默] 三鍵。
同時,在與 Gemini 的架構討論中,確認了 8 種通知類型矩陣(TYPE-1 到 TYPE-8M)以及雙頻道發送策略。
問題診斷:4 個斷點
斷點 A:decision_manager._push_decision_to_telegram()
呼叫 send_approval_card() 時沒有傳入 alert_category
斷點 B:telegram_gateway.send_approval_card()
呼叫 _build_inline_keyboard() 時沒有傳入 alert_category/notification_type
斷點 C:telegram_gateway._send_approval_card_to_group()
含 Callback Button 的 TYPE-3 卡片也發到 SRE 群組 → nonce 洩漏安全漏洞
斷點 D:classify_alert_early() 輸出 "kubernetes"
但 _build_inline_keyboard 期待 "k8s_workload" → 永遠不命中
另有 10 個告警分類錯誤(host_resource/devops_tool/ssl_cert 等全落入 general)
決策
D1:統一 Category 命名
k8s_workload→ 改為kubernetes(語義更廣,涵蓋 Node/Service/Ingress)Host*告警從infrastructure分離為host_resourceDocker*告警保留infrastructure
D2:新增 7 個 Category
| Category | 告警 | 說明 |
|---|---|---|
alertchain_health |
AlertChainBroken_* / NoAlertsReceived2Hours / AlertChainUnhealthy | meta-monitoring,優先度最高 |
flywheel_health |
AutoRepairLowSuccessRate / PermanentFixRequired / Flywheel* | 飛輪自身健康 |
storage |
MinIODown | 物件儲存 |
devops_tool |
GiteaDown / HarborDown / SignOzDown / OpenClawDown / SentryDown / AlertmanagerDown | DevOps 工具鏈 |
external_site |
MoWoooWorkDown / TsenyangWebsiteDown / StockWoooWorkDown / BitanWoooWorkDown | 外部業務網站 |
ssl_cert |
ExternalSiteSSL* / TLSCert* | SSL 憑證 |
security_tool |
KaliScannerDown | 資安掃描工具 |
D3:8 種通知類型矩陣(完整版)
| 類型 | 適用場景 | 按鈕 | 發送目標 |
|---|---|---|---|
| TYPE-1 | 純資訊、備份成功、心跳 | 無 | SRE 群組 |
| TYPE-2 | AI 自動修復完成 | 無(結果通知) | 個人 DM + 群組唯讀 |
| TYPE-3 | 需人工審核(預設) | 依 category 動態 ≤4 個 | 個人 DM 只 |
| TYPE-4 | AI 無法判斷 | [手動記錄][查面板][忽略] | 個人 DM 只 |
| TYPE-4D | Config Drift | [查Diff][採納][回滾][忽略] | 個人 DM 只 |
| TYPE-5S | 資安防禦(未來) | [隔離][封鎖IP][驅逐Pod][確認授權] | 個人 DM 只 |
| TYPE-6B | 業務/FinOps(未來) | [暫停][查SignOz][忽略] | SRE 群組 |
| TYPE-7E | 重大事故升級(未來) | [建立戰情室][Postmortem][DR手冊][確認接手] | 個人 DM + 群組 |
| TYPE-8M | 飛輪/告警鏈路健康 | [觸發診斷][查看面板][靜默] | 個人 DM 只 |
D4:雙頻道路由規則
含 Callback Button → 只發個人 DM(@tsenyangbot)
TYPE-3 / TYPE-4 / TYPE-4D / TYPE-5S / TYPE-7E / TYPE-8M
純資訊展示 → 只發 SRE 群組(-1003711974679)
TYPE-1 / TYPE-6B
執行結果 → 兩個都發(群組版唯讀無按鈕)
TYPE-2
(TYPE-7E 升級 → 兩個都發,群組版加 @mention)
D5:Telegram 卡片格式防腐規則
# telegram_gateway.py 頂部常數(ADR-075 鎖定)
NOTIFICATION_TYPE_RULES = {
"TYPE-1": "無按鈕,可有 URL Button,嚴禁 Callback Button",
"TYPE-2": "無按鈕,可有 URL Button,嚴禁 Callback Button",
"TYPE-3": "最多 4 個 Callback Button,依 alert_category 動態選擇",
"TYPE-4": "固定 3 個按鈕:[手動記錄][查看面板][忽略]",
"TYPE-4D": "固定 4 個按鈕:[查看Diff][採納][回滾][忽略]",
"TYPE-5S": "固定 4 個按鈕:[隔離][封鎖IP][驅逐Pod][確認授權]",
"TYPE-6B": "最多 3 個按鈕:[暫停][查看SignOz][忽略]",
"TYPE-7E": "固定 4 個按鈕:[建立戰情室][Postmortem草稿][DR手冊][確認接手]",
"TYPE-8M": "固定 3 個按鈕:[觸發診斷][飛輪面板][靜默]",
}
實施計畫
完整計畫書:docs/superpowers/plans/2026-04-12-adr075-telegram-alert-notification.md
Phase 1(斷點修復,同一 PR):
- Task 1-2:重寫
classify_alert_early()(斷點 D) - Task 3:
_build_inline_keyboard字典對齊(斷點 D) - Task 4:
send_approval_card()接收並傳遞alert_category(斷點 B) - Task 5:雙頻道路由修正(斷點 C)
- Task 6:
decision_manager傳入alert_category(斷點 A)
Phase 2(TYPE-8M 擴充):
- Task 7-8:新增
send_meta_alert()+ decision_manager 路由
Phase 3(Prometheus 規則,獨立):
- Task 9:新增 6 個欠缺告警規則
驗收標準
| 驗收項目 | 驗收方式 |
|---|---|
| HostHighCpuLoad 出現 [查程序][重啟服務][清Log] | 送測試告警驗收 |
| KubePodCrashLooping 出現 [重啟][擴容][縮容][回滾] | 送測試告警驗收 |
| AlertChainBroken_* 出現 [啟動緊急診斷] | 送測試告警驗收 |
| TYPE-3 卡片不發 SRE 群組 | 確認群組無帶按鈕訊息 |
| TYPE-1 卡片只發 SRE 群組 | 確認個人 DM 無純資訊通知 |
| 全部單元測試通過 | pytest >620 passed |
範疇外(本 ADR 不包含)
- TYPE-5S SecOps 卡片(待 SecOps Prometheus 規則完備後)
- TYPE-6B Business 卡片(待 MomoScraper metrics 接入後)
- TYPE-7E Escalation Monitor Service
- FlywheelPlaybookZero 告警(依賴 ADR-074 Exporter)
實作記錄(2026-04-12)
| Phase | Commit | 內容 |
|---|---|---|
| Phase 1 | 2cef209 |
4 斷點修復 + classify_alert_early 13 規則 + _CATEGORY_BUTTONS 更新 |
| Phase 2 | 561c1d8 |
send_meta_alert() + decision_manager TYPE-8M elif |
| CR 修補 | 1cb654c |
TYPE_8M 加入 enum + 死碼清理 + docstring 更新 |
測試覆蓋:52 classify_alert_early tests + 664 total passed
CR 評分:7/10(首席架構師審查通過,P0/P1 全修補)
Phase 3(Prometheus 規則):尚未實作,不阻擋 Phase 1/2 上線
更新引用(2026-04-24)
| ADR | 影響 | 說明 |
|---|---|---|
| ADR-093 | 🔄 更新 D4 雙頻道路由 | 加「群組 Callback Button 授權模式」子條款:TYPE-3/4/4D/8M 解除 _interactive_types 黑名單,改以 callback_data + user_id binding + Approvers 白名單保護(P0-1 修) |
| ADR-094 | ➕ 新增 NL 對話入口 | Hermes 透過 @mention 在群組處理自然語言對話,輸出仍遵守 ADR-075 D5 格式規則 |
| ADR-095 | ➕ 12-Agent 視覺分派 | TG 訊息加 @hermes-* 前綴 + emoji + hashtag 三件套,符合 ADR-086 UI 清洗後的視覺規範 |