fix(approval): create_approval_with_fingerprint 補注 48h expires_at 預設值
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled

根因(盤點後確認):
  所有 webhook 建立 approval 的路徑(webhooks.py:908/1426/1566)均未傳
  expires_at,DB 欄位為 NULL。get_pending_approvals() 的自動過期邏輯
  WHERE expires_at < now 對 NULL 永遠為 False → 殭屍 PENDING 永不清理。

修正策略:
  在 create_approval_with_fingerprint()(告警 approval 唯一共用入口)
  注入預設 48h TTL,一次覆蓋全部 3 個 webhook 呼叫點。
  手動 API 建立(approvals.py)自行傳 expires_at,不受影響。

與 2026-04-15 24h PENDING_TTL_HOURS 補丁協同工作:
  - 24h: find_by_fingerprint 不再收斂過期 PENDING → 新告警重新觸發通知
  - 48h: get_pending_approvals auto-expire → UI 殭屍記錄自動清除

2026-04-15 ogt + Claude Sonnet 4.6(亞太):完整盤點後補完

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
OG T
2026-04-15 19:08:08 +08:00
parent 1d22376b86
commit f31b4e31ba

View File

@@ -237,8 +237,22 @@ class ApprovalDBService:
"""
建立帶指紋的授權請求 (戰略 B)
用於告警收斂:相同指紋的告警會被聚合
用於告警收斂:相同指紋的告警會被聚合
ADR-073 補丁 2026-04-15 ogt + Claude Sonnet 4.6:
所有 webhook 路徑都未傳 expires_at導致 DB 欄位為 NULL
get_pending_approvals() 的自動過期邏輯 (WHERE expires_at < now)
永遠不觸發,殭屍 PENDING 記錄無限堆積。
修正:凡未傳 expires_at自動注入 48h 預設值。
"""
DEFAULT_APPROVAL_TTL_HOURS = 48 # 給人類 48h 決定視窗
if not request.expires_at:
now = datetime.now(UTC)
request = request.model_copy(
update={"expires_at": now + timedelta(hours=DEFAULT_APPROVAL_TTL_HOURS)}
)
risk_level = classify_risk(
action=request.action,
blast_radius=request.blast_radius,