# ADR-093: Telegram 告警全面遷移至 SRE 戰情室群組

> **狀態**: ✅ 已全面切換
> **日期**: 2026-04-24
> **決策者**: 統帥 + 12-Agent 全景分析團隊（onboarder / debugger / db-expert / tool-expert / web-researcher / planner / critic / frontend-designer / fullstack-engineer / refactor-specialist / migration-engineer / vuln-verifier）

## 背景

原 Telegram 告警雙軌路由設計：
- 所有告警類（TYPE-3/4/4D/8M）預設發私人 DM `OPENCLAW_TG_CHAT_ID`
- 僅心跳報告、週月報、AI 三頭分析發群組 `SRE_GROUP_CHAT_ID=-1003711974679`
- `_interactive_types` 黑名單曾把互動式告警擋在群組外

使用者需求：把**所有**告警（含需人工簽核的 TYPE-3/4/4D/8M）遷到 AwoooI SRE 戰情室群組（4 名成員），以便團隊共同監察。

## 決策

採取**群組優先、個人只作缺設定 fallback**：

1. **所有告警卡片**（TYPE-1/2/3/4/4D/5S/6B/7E/8M）→ `SRE_GROUP_CHAT_ID`
2. **所有告警旁路通知**（自動修復結果、rollback 提案、provider failover、成本、容量、規則品質、合規、coverage、Gitea/Code Review）→ `SRE_GROUP_CHAT_ID`
3. `OPENCLAW_TG_CHAT_ID` 只保留為 `SRE_GROUP_CHAT_ID` 缺失時的 fail-soft fallback，不再是正式告警收件人

正式入口由 `TelegramGateway.alert_chat_id` 維護；直接呼叫 Bot API 的告警旁路必須使用 `settings.SRE_GROUP_CHAT_ID or settings.OPENCLAW_TG_CHAT_ID`。

所有告警生命週期操作都屬於群組遷移範圍：initial send、analyzing placeholder、deleteMessage、editMessageText、editMessageReplyMarkup、CI progress、action-result update。只把新卡片送進 SRE 群組，但後續 edit/delete 還打 `self.chat_id` / 個人 DM，會造成 ghost button 與狀態分裂，視為遷移未完成。

## 理由

### 為什麼是群組（而非純 DM）
- SRE 戰情室 4 名成員需**即時共同監察**，避免單一收件人漏讀
- 系統日報已在群組，告警分散到 DM 造成資訊割裂
- 符合 SRE best practice（PagerDuty / Opsgenie 都是群組導向）

### 為什麼需要新 nonce 模型（P0-1 修）
- 現有 callback_data 格式 `approve:{approval_id}:{timestamp}:{random}` 不含 user_id 簽章
- 進群組 = CSRF 簽核漏洞：任何 member 可按批准按鈕
- **新格式** `apr:{short_id}:{action}:{user_id_hash}` + Redis `cb:{short_id}` 後端映射
- Handler 強制 `callback_query.from.id == bound_user_id`，違反 → 回 `answer_callback_query(text="⛔ 你未被指派")`

### 為什麼要 Approvers Allowlist
- Telegram group admin 可在未通知下新增成員
- `chat_member` webhook 事件同步維護 Approvers 白名單
- 按鈕先顯示給所有人，**按下後檢查** `from.id ∈ APPROVERS_WHITELIST`

## 後果

### 優點
- SRE 團隊共同可見所有告警，降低漏讀率
- 清理 24 處硬編 chat_id 技術債
- 統一路由矩陣便於未來擴充

### 缺點
- 遷移期間 pending ApprovalRecord 卡片需重發（48h editMessage 限制，見 ADR-094 §F1）
- 需新建 Approvers 白名單 + `chat_member` 同步機制
- 破壞 ADR-075 斷點 C 的「DM only」假設 → 修訂 ADR-075 D4

### 風險
- **CSRF 簽核**：若 user_id binding 實作有缺陷，非授權者可簽核 → 必須有 Round 3 vuln-verifier 的 PoC 測試把關
- **Telegram group 20 msg/min rate limit**：12 agent 回覆 + 告警齊發可能觸 429 → 必須走 `TelegramRouter` token bucket
- **群組成員動態變動**：admin 隨時可拉人進群 → `chat_member` webhook 必須即時同步 Approvers

## Rollback

Feature flag `TG_GROUP_CUTOVER ∈ {off, 10%, 50%, 100%}`，以 `alert.labels.env` hash 分桶切流。失敗回 `off` 恢復 DM 模式。

## 參考

- 上位：[ADR-075](ADR-075-telegram-notification-standard.md)（需修訂 D4 加 allowlist 子條款）
- 平行：[ADR-094](ADR-094-hermes-nl-interface.md) / [ADR-095](ADR-095-12agent-sdk-integration.md)
- Memory: `feedback_no_ghost_buttons.md` / `feedback_telegram_alert_format.md`
- 實施：Round 3 planner 的 WS0-WS5（`/Users/ogt/awoooi/docs/design/hermes-telegram-flows/hermes-flows.html`）

## 變更紀錄

| 版本 | 日期 | 執行者 | 變更內容 |
|------|------|--------|---------|
| v1.0 | 2026-04-24 | 12-Agent 全景分析 | 初版 Proposed |
| v1.1 | 2026-04-25 | Claude Sonnet 4.6 | WS2-WS5 實作完成：NotificationMatrix + BIGINT + approval_records prod 建立 + Approvers 白名單 |
| v2.0 | 2026-04-30 | Codex | 告警訊息全面切到 AwoooI SRE 戰情室群組；個人 DM 僅保留缺群組設定 fallback |
| v2.1 | 2026-05-01 | Codex | 補齊 placeholder/delete/edit/CI progress/action update 的 `alert_chat_id` 路由，封住 group card + DM edit 的 ghost-button 路徑 |
