Files
awoooi/docs/awooop/TELEGRAM-INCIDENT-NOTIFICATION-MODEL.md
Your Name b191f8e9fe
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Failing after 2m6s
CD Pipeline / build-and-deploy (push) Has been skipped
CD Pipeline / post-deploy-checks (push) Has been skipped
fix(telegram): close ops direct sender gaps
2026-07-02 19:32:36 +08:00

180 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Telegram 事故通知模型
> 目的:讓 SRE 戰情室一眼分辨「AI 已修復」、「AI 可建議但需批准」、「AI 無法安全修復需人工」與「僅通知」,避免告警、執行 log、Code Review、Drift 與審批結果互相洗版。
## 核心判斷
Telegram 不應是完整執行日誌,也不應承載所有 AI 推理細節。Telegram 的職責是把需要人類注意力的決策摘要送到 SRE 戰情室完整時間線、工具輸出、重試原因、provider fallback 與 audit 交給 AwoooP Run Monitor / Incident Timeline。
## 四種通知狀態
| 狀態 | 意義 | Telegram 行為 | 操作者動作 |
| --- | --- | --- | --- |
| AI 已自動修復 | 自動化已完成且驗證通過 | 更新原 incident 卡或回覆一次結果 | 檢查即可,不需批准 |
| AI 建議待審批 | AI / 規則已提出可執行建議,但被 Trust / Risk gate 擋下 | 發一張 ACTION REQUIRED 主卡 | 批准、拒絕、靜默或看詳情 |
| AI 無法安全修復 | NO_ACTION、INVALID_TARGET、LLM timeout、MCP 失敗或缺少安全動作 | 發人工接手摘要,不重複刷同一狀態 | 人工排查,或要求重診 |
| 僅通知 | 心跳、報表、Code Review 完成、低風險治理資訊 | 彙總卡或摘要頻道 | 通常不需即時動作 |
## 專業化訊息規則
1. 同一個 `incident_id` 只應有一張主卡。後續狀態使用原卡回覆、編輯按鈕或 AwoooP timeline不再每一步都新發卡。
2. 主卡第一屏必須顯示「處置狀態」先回答AI 是否能修、是否已修、是否需要人工。
3. 同一個 `incident_id` 的相同狀態更新,短時間內要去重。詳細重試與錯誤放到 timeline不洗 Telegram。
4. P0 / P1 escalation 可以另發升級卡,但內容必須是「目前影響、已嘗試、卡住原因、需要誰做什麼」,不可重貼所有底層 log。
5. Code Review、Config Drift、報表、心跳不應和 incident 執行回覆混在同一種語義;它們可以在同一 SRE 群組,但必須以摘要卡與固定前綴區分。
6. 主機、容器、runner、Nginx、Wazuh、Kali、CI/CD 這類資安 / 維運告警不得直接外送 `ps aux``docker stats`、stdout/stderr 或完整路徑;必須先轉成 AI 自動化事件包,再只保留可判讀摘要與 top evidence。
## AI 自動化告警事件包
IwoooS / AwoooP 是 AI 自動化產品Telegram 告警不是終點,而是自動化飛輪的入口。任何可觸發值班判斷的告警,至少要能被轉成 `ai_automation_alert_card_v1` 等級的事件包。
合格告警的定義不是「有送出訊息」,而是能讓 operator 直接看出 AI 已把訊號送進哪一條自動化 lane、產生哪一個候選、目前被哪一道 Gate 擋住、誰要審、驗證要看哪裡,以及後續如何回寫 Timeline / KM / PlayBook。未做到這件事的訊息只能算 raw observability不能算 AWOOOI 產品層告警。
事件包必填欄位:
| 欄位 | 說明 |
| --- | --- |
| 事件類型 | 例如 `host_resource_pressure``runner_build_resource_pressure``wazuh_intrusion_signal``kali_assessment_signal``nginx_config_drift`。 |
| 影響判讀 | 用一到三行說明現在影響的是服務可用性、入侵風險、部署風險、資料完整性或觀測盲點。 |
| 視覺化摘要 | 使用條狀圖、狀態列、矩陣或後續圖卡;不得只丟 raw log。Telegram 純文字階段可用 `■■□□` 類視覺 bar前端 / 報表可再升級圖卡。 |
| AI lane | 指定 AI 後續分流 lane例如 runner 資源壓力、主機入侵、設定漂移、供應鏈風險。 |
| Gate | 明確顯示 `candidate_only``approval_required``runtime_write_gate=0` 或已取得的授權;不得把告警當成 runtime 寫入批准。 |
| Top evidence | 最多保留前三個可判讀證據;只放 PID、CPU、服務類型、告警規則、redacted evidence ref不放完整主機路徑、secret、個人 namespace 或內部對話內容。 |
| 建議下一步 | 指向 AI 要沉澱的候選、owner 欄位、AwoooP Run / Work Item / IwoooS gate而不是只叫人看 log。 |
| 禁止事項 | 當下不允許的動作要明確列出,例如不 kill process、不 restart Docker / Gitea、不 reload Nginx、不改 firewall、不觸發 Kali active scan。 |
事件包必須能接到下列產品閉環:
| 閉環節點 | 必須可回讀的狀態 |
| --- | --- |
| AI lane | `security_intrusion_triage``runner_build_resource_pressure``nginx_config_drift``supply_chain_drift` 等明確 lane。 |
| Candidate | 對應候選動作、owner request、dry-run、Work Item 或 Run不得只有「請人工判斷」。 |
| Gate | `candidate_only``approval_required``runtime_write_gate=0/1`、批准者與批准理由。 |
| Verifier | post-check、route smoke、receipt readback、Wazuh / SIEM readback、production health 或 no-write 驗證結果。 |
| Learning | Timeline event、KM / PlayBook writeback、trust score / rule learning 或報表沉澱狀態。 |
不合格告警範例:
- 只貼 CPU、`ps aux``docker stats`、stdout/stderr、完整路徑或完整 log。
- 只說「AI 選擇不執行」但沒有候選、Gate、owner、verifier 或 learning。
- 把工作視窗、內部對話、個人 namespace、內網位址、secret 片段或未脫敏 raw payload 放進 Telegram 或前端。
- 把 Telegram 送達、UI 可見、CD success 或 smoke success 誤當成 runtime 寫入批准。
Host / runner 資源告警的第一版落地:
- `TelegramGateway.send_alert_notification()``send_text()` 會在最後出口自動套用 host resource formatter即使呼叫端傳入 Markdown也必須強制改成脫敏 HTML 卡片。
- `TelegramGateway._send_request("sendMessage", ...)` 也必須套用同一個 formatter避免 approval execution、legacy helper 或未來 direct gateway 呼叫繞過 `send_alert_notification()` / `send_text()`
- `CPU 警告``容器內 root Node.js 進程`、含 `ps aux` 且指向 build / package install / Prisma generate 程序的文字,會被轉成 `ai_automation_alert_card_v1`
- raw process dump 會被壓成 `PID + CPU + 精簡命令`,不保留 `/workspace/...``/opt/hostedtoolcache/...`、完整 `node_modules` 路徑、外部檢查 URL、JSON payload 或整段 `ps aux`
- build 壓力會分流到 `runner_build_resource_pressure`Prisma / package install 壓力會分流到 `runner_prisma_generate_resource_pressure`;預設都是 `candidate_only / runtime_write_gate=0`
- 這只建立 AI 候選與判讀入口,不代表允許 kill process、restart 服務、改 Nginx、改 firewall 或執行 Kali active scan。
非 host 維運 / 資安訊號的第一版落地:
- `TelegramGateway.send_alert_notification()``send_text()` 現在也會把 Wazuh、Kali、Nginx drift、Backup / Restore / Escrow、Provider freshness、Supply-chain drift 類訊號轉成同一版 `ai_automation_alert_card_v1`
- 事件類型固定映射:
- `wazuh_dashboard_api_readback_degraded``siem_observability_readback_degraded`
- `wazuh_intrusion_signal``security_intrusion_triage`
- `kali_assessment_signal``security_assessment_review`
- `nginx_config_drift``public_gateway_config_drift`
- `backup_restore_escrow_signal``backup_restore_escrow_triage`
- `provider_freshness_signal``source_provider_freshness_triage`
- `supply_chain_drift``supply_chain_drift_review`
- 所有上述卡片都必須顯示 `candidate_only / runtime_write_gate=0`,並把下一步導向 owner evidence、reviewer acceptance、rendered diff / freshness / restore / SIEM readback、KM / PlayBook / Verifier 沉澱。
- Wazuh Dashboard 顯示 agent 消失但 agent transport 或 manager service 仍有只讀證據時,必須優先分類為 `wazuh_dashboard_api_readback_degraded`;在 manager registry counts 未驗收前,不得把它寫成「所有 agent 已消失」或「agent 已恢復」。
- formatter 會在 Telegram 最後出口脫敏 URL、內網 IP、絕對路徑、Bearer token、token / password / secret / api key 類 assignmentTop evidence 最多保留三行摘要。
- 這只把 raw signal 變成 AI 自動化候選,不代表允許 Wazuh 封鎖、Kali active scan、`nginx -t` / reload、backup / restore / remote delete、provider switch、package upgrade、workflow dispatch 或 production write。
通知出口旁路清冊:
- `docs/security/telegram-notification-egress-inventory.snapshot.json` 目前固定 repo 內 `0` 個 direct Bot API `sendMessage`,分布為 Gitea workflow `0`、ops script `0`、API direct path `0`
- `apps/api/src/services/channel_hub.py` 的 interim feedback sender 已改走 `TelegramGateway.send_text()`,讓 non-shadow interim 訊息進入既有 final-exit formatter、thread reply、錯誤 sanitizer 與 AwoooP outbound mirror path不再直接讀 `TELEGRAM_BOT_TOKEN` 或拼 Bot API URL。
- `scripts/ops/backup-from-110.sh``scripts/ops/docker-health-monitor.sh``scripts/ops/dr-drill.sh``scripts/ops/pg-backup.sh` 的 legacy direct Bot API fallback 已移除API 不可達時只留下本地 log不再繞過 DB/log receipt 與 AI automation。
- `docs/security/telegram-notification-egress-owner-request-draft.snapshot.json` 已讀回 `0` 份 metadata-only candidateowner response 欄位只能作為 evidence不得阻擋低爆炸半徑 controlled apply。
- `docs/security/telegram-notification-egress-migration-plan-draft.snapshot.json` 已讀回 `0` 份 migration candidatemigration runtime send / Bot API call / secret read 仍維持 `0`
- `GET /api/v1/agents/telegram-alert-ai-automation-matrix` 會把上述清冊與 readability guard、AI digest policy、AwoooP outbound mirror source contract 合併,讀回 DB/log receipt、AI route、controlled queue、work item、post verifier、learning writeback、manual/default gap 與 direct send gap。
- direct egress 已不再是目前 repo 內已知缺口;後續若新增 direct Bot API 會被 no-new-bypass guard 阻擋,並必須先回到 TelegramGateway / AwoooP receipt path。
- 清冊階段只允許保存 path、line、redacted excerpt、owner 欄位與 reviewer gate不送 Telegram、不讀 Bot token、不保存 chat secret、不改 workflow / script、不開 runtime gate。
- 後續每個 direct egress 要收斂前,都必須補 owner route、message shape、redaction contract、formatter convergence plan、delivery receipt、fallback mode、rollback owner 與 post-check evidence。
Host / runner 告警卡片必須採用下列第一屏版型:
```text
P1 主機資源壓力h110-gitea
ai_automation_alert_card_v1
一眼摘要
├ CPU 使用率29.8%
├ Load8.62 ■■■■■■■■
├ 容器 root 進程3
└ 影響Prisma generate / package build 程序正在吃 CPU先確認 CI/CD、runner job 與供應鏈來源,不可直接 kill
AI 自動化判讀
├ Lanerunner_prisma_generate_resource_pressure
├ Gatecandidate_only / runtime_write_gate=0
└ 下一步:建立 Prisma / package install 資源壓力候選,交由 AI 彙整 CI/CD run、套件來源、runner queue 與供應鏈 evidence
Top evidence
├ PID 365 CPU 27.5%Prisma generate root
├ PID 376 CPU 15.5%Prisma generate root
└ PID 392 CPU 0%Prisma generate root
建議下一步
├ 確認是否為 CI/CD / Actions / runner 正常建置或 package install 窗口
├ 若持續超過門檻,先查 runner queue、build job、套件來源、容器資源限制與服務 SLO
└ 同一 host/service 5 分鐘聚合一次,避免洗版
禁止事項
└ 不 kill process、不 restart Docker / Gitea、不 reload Nginx、不改 firewall除非已有維護窗口與 owner 批准。
```
## 與 AwoooP 的分工
| 介面 | 承載內容 |
| --- | --- |
| Telegram | 決策摘要、升級、人工批准入口 |
| AwoooP Run Monitor | 非同步 Run、provider fallback、tool call、retry、latency |
| Approval Queue | 所有等待批准的高風險動作 |
| Incident Timeline | 事件完整歷程、AI 嘗試、失敗原因、KM / Playbook 回寫 |
| MCP Audit | 工具執行、redaction、permission gate、credential 注入 |
## 2026-05-12 live gate
> Canonical diagnosis and repair waves live in `docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md` §2.5. This section is only the Telegram-facing contract.
Telegram 卡片目前不能再只顯示「AI 研判 / 建議動作」。每張卡都必須能回查到一筆 truth-chain 狀態,最少包含:
- `source_event_id` / `fingerprint` / `repeat_count` / `first_seen` / `last_seen`
- current stagereceived、deduped、evidence、MCP、decision、approval、execution、verification、learning、resolved / manual_required
- evidence qualitysensors attempted / succeeded、failed sensors、Sentry / SignOz / Prometheus refs
- MCP usageAwoooP Gateway audit、legacy direct MCP、not-used reason
- executor choiceAnsible / MCP / K8s / SSH / no_action以及 dry-run / diff / rollback evidence
- approval / execution / verificationapproval_id、operation op_id、verification_result、KM / Playbook writeback
Live 2026-05-12 evidence shows this gate is not yet green:
- AwoooP Run State 24h is still `legacy_outbound` shadow with `step_total=0`.
- `awooop_mcp_gateway_audit` has 0 rows; legacy `mcp_audit_log` has activity but is not the AwoooP choke point.
- `INC-20260512-B6C589` has incident / approval status mismatch and `8/8` failed SSH sensors.
- Config Drift repeats hourly with the same counts and pending status, but Telegram does not show repeat/update state.
- Outbound mirror visibility must be revalidated after RLS; the app role currently cannot rely on it as a complete truth source.
## 本輪落地
- `TelegramMessage` 主卡新增「處置狀態」。
- `append_incident_update()` 對同一 incident 的相同狀態做 5 分鐘 Redis 去重。
- `append_incident_update()` 對相同的「AI 自動修復失敗 / AI 診斷工具失敗」摘要增加 10 分鐘跨 incident 去重;每個 incident 仍會移除原卡危險按鈕,但 Telegram 不再重複 reply 同一個失敗摘要。
- `TelegramGateway._send_request()` 對成功送出的 legacy `sendMessage` 增加 AwoooP `awooop_outbound_message` 鏡像。鏡像失敗只記錄 `telegram_outbound_mirror_failed`,不能影響 Telegram 正常送達。
- `ai_automation_alert_card_v1` 送出後AwoooP mirror envelope 需帶 `ai_automation_alert_card_mirror_v1` metadata至少包含 `event_type``lane``target``gates``runtime_write_gate_count=0``delivery_receipt_readback_required=true`;不得把 raw alert、完整 Telegram text、token、內網 URL、主機路徑或 raw Wazuh payload 放進 envelope。
- `GET /api/v1/platform/runs/ai-alert-cards` 只讀查詢 `ai_automation_alert_card_v1` delivery readback可用 `project_id``event_type``lane` 篩選;此路徑只回 metadata、source refs 與 send status不回完整 Telegram text也不代表 Telegram 已實發或 Wazuh registry 已驗收。
- 成本告警、審批執行結果、自愈 rollback 提案已由 direct Bot API 改走 `TelegramGateway._send_request()`,避免繞過 outbound mirror。
- `telegram_gateway.py` 內部歷史直打 `sendMessage` 路徑已收斂;多 Bot `_send_as_bot()` 因需指定 token 保留 direct HTTP但成功後同樣鏡像到 `awooop_outbound_message`
- 既有 `詳情 / 重診 / 歷史` 按鈕保留,讓 Telegram 保持輕量,細節回到控制台。
## 後續建議
1. 將 Telegram 群組升級為 Forum topics 或固定 topic lane`P0/P1 事故``人工審批``治理/報表``CI/Code Review`
2. AwoooP Approval Queue 顯示與 Telegram 相同的「處置狀態」欄位,避免前後端語義分裂。
3. 將 auto-repair failure 的完整 stdout/stderr 改寫入 Run Timeline只在 Telegram 顯示最短摘要與詳情連結。
4. 對 firing 告警做 fingerprint 聚合:同一 alertname + target + namespace 在窗口內只更新卡片,不新增卡片。