feat(Phase 5 Sprint 5.4): 分類按鈕從 registry 動態產生 — 按鈕重啟上線
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 17m11s
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 17m11s
_build_inline_keyboard() 改寫:
- 原 hardcode _CATEGORY_BUTTONS dict (28 按鈕) 已下架
- 改從 callback_action_spec.yaml registry 動態產生
- spec.callback_format 決定格式:
* nonce (寫類) → self._security.generate_callback_nonce(approval_id, action_name)
* info (查類) → {action_name}:{incident_id}
- 新按鈕只需改 yaml,零改 code
分類覆蓋 (從 yaml 自動推算):
- kubernetes: 6 按鈕 (4 寫 + 2 查)
- host_resource: 3 按鈕 (1 查 + 2 寫)
- secops: 4 按鈕 (全寫類 + Multi-Sig)
- database: 3 按鈕
- storage: 2 按鈕
- network: 3 按鈕
- devops_tool: 2 按鈕
- external_site: 2 按鈕
- business: 1 按鈕
- flywheel_health: 1 按鈕
- ssl_cert: 1 按鈕
這次按鈕不是鬼魂 — 每個都有:
✅ callback_format 正確 (4-part nonce / 2-part info)
✅ Sprint 5.3 dispatch handler 接收
✅ Sprint 5.2 MCP registry 執行
✅ audit log + reply_to 原卡片
回歸: 188/188
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1376,16 +1376,26 @@ class TelegramGateway:
|
||||
alert_category: 告警類別 (ADR-071-E: 決定 TYPE-3 按鈕組合)
|
||||
notification_type: 通知類型 (TYPE-1/2/3/4/4D)
|
||||
"""
|
||||
# 2026-04-14 Claude Sonnet 4.6 首席架構師裁示:
|
||||
# 原 _CATEGORY_BUTTONS (28 個分類按鈕) 全部下架 — 信任 > 功能
|
||||
# 盤查證據(統帥 2026-04-14 20:00 完整 audit):
|
||||
# - callback_data 格式全錯 (3-part action:xxx:id 不符合 parser 4-part nonce / 2-part info)
|
||||
# - 後端 0 個 handler(grep apps/api/src 無任何 dispatch elif 分支)
|
||||
# - 從 2026-04-11 commit 325b3851 起死了 3 天
|
||||
# - 統帥今天真踩到:點「查程序」沒反應 → 信任破壞
|
||||
# 正式下架改用通用按鈕 (approve/reject/silence/detail/history/reanalyze)
|
||||
# 補完計畫:MASTER 藍圖 Phase 5「分類按鈕完整化」(另立 ADR)
|
||||
_CATEGORY_BUTTONS: dict[str, list[tuple[str, str]]] = {} # 臨時空,fallback 通用按鈕
|
||||
# 2026-04-14 Claude Sonnet 4.6 (Phase 5 Sprint 5.4):
|
||||
# 從 callback_action_spec registry 動態產生按鈕(原 _CATEGORY_BUTTONS hardcode 已下架)
|
||||
# 優點:新增按鈕只需改 yaml,callback_data 格式由 spec.callback_format 決定
|
||||
# 安全:yaml 裡每個 action 都有對應 MCP dispatcher handler(Sprint 5.2/5.3 實作)
|
||||
from src.services.callback_dispatcher import list_actions_for_category as _list_actions
|
||||
|
||||
def _build_category_buttons_for(category: str) -> list[tuple[str, str]]:
|
||||
"""從 registry 產生 (label, callback_data) list"""
|
||||
actions = _list_actions(category)
|
||||
btns: list[tuple[str, str]] = []
|
||||
for spec_it in actions:
|
||||
emoji_label = f"{spec_it.emoji} {spec_it.label}".strip()
|
||||
if spec_it.callback_format == "nonce":
|
||||
# 寫類:產生 4-part nonce
|
||||
cb = self._security.generate_callback_nonce(approval_id, spec_it.name)
|
||||
else:
|
||||
# 查類:2-part info
|
||||
cb = f"{spec_it.name}:{incident_id}"
|
||||
btns.append((emoji_label, cb))
|
||||
return btns
|
||||
|
||||
# 產生 Nonce (防重放,用於寫操作)
|
||||
approve_nonce = self._security.generate_callback_nonce(approval_id, "approve")
|
||||
@@ -1394,11 +1404,13 @@ class TelegramGateway:
|
||||
|
||||
is_type3 = notification_type in ("TYPE-3", NotificationType.TYPE_3, "")
|
||||
|
||||
if is_type3 and alert_category and alert_category in _CATEGORY_BUTTONS:
|
||||
_dynamic_buttons = _build_category_buttons_for(alert_category) if alert_category else []
|
||||
|
||||
if is_type3 and _dynamic_buttons:
|
||||
# TYPE-3 動態操作按鈕:第一行為類別專屬操作
|
||||
category_btns = [
|
||||
{"text": text, "callback_data": cb_data}
|
||||
for text, cb_data in _CATEGORY_BUTTONS[alert_category]
|
||||
for text, cb_data in _dynamic_buttons
|
||||
]
|
||||
# 每行最多 3 個,超過換行
|
||||
rows = [category_btns[i:i+3] for i in range(0, len(category_btns), 3)]
|
||||
|
||||
Reference in New Issue
Block a user