fix(adr100): hash approval fingerprint for postgres
All checks were successful
CD Pipeline / tests (push) Successful in 1m28s
Code Review / ai-code-review (push) Successful in 28s
CD Pipeline / build-and-deploy (push) Successful in 4m31s
CD Pipeline / post-deploy-checks (push) Successful in 2m9s

This commit is contained in:
Your Name
2026-06-01 21:08:07 +08:00
parent 6125fb6923
commit 3ab48d70c5
3 changed files with 7 additions and 5 deletions

View File

@@ -11,6 +11,7 @@ T25: remediation queue items are now actionable without mutating incident state:
from __future__ import annotations
import asyncio
import hashlib
from datetime import datetime, timedelta, timezone
from typing import Any, Literal, Protocol
@@ -770,7 +771,7 @@ def _approval_fingerprint(item: dict[str, Any]) -> str:
playbook_id = str(item.get("playbook_id") or "")
incident_id = str(item.get("incident_id") or "")
basis = work_item_id or f"{incident_id}:{playbook_id}:{item.get('remediation_action') or ''}"
return f"adr100_playbook_authoring:{basis}"[:240]
return hashlib.sha256(f"adr100_playbook_authoring:{basis}".encode("utf-8")).hexdigest()
def _approval_result_payload(

View File

@@ -320,7 +320,7 @@ async def test_create_approval_request_is_record_only_and_does_not_authorize_rep
assert result["mode"] == "approval"
assert result["writes_approval_record"] is True
assert result["deduplicated"] is False
assert result["fingerprint"].startswith("adr100_playbook_authoring:")
assert len(result["fingerprint"]) == 64
assert result["writes_incident_state"] is False
assert result["writes_auto_repair_result"] is False
assert result["approval_id"] == "00000000-0000-0000-0000-00000000a100"
@@ -332,8 +332,9 @@ async def test_create_approval_request_is_record_only_and_does_not_authorize_rep
assert approval_service.requests[0].metadata["approval_kind"] == "adr100_playbook_authoring"
assert approval_service.requests[0].metadata["execution_authorized"] is False
assert approval_service.requests[0].metadata["repair_executed"] is False
assert approval_service.fingerprints[0].startswith("lookup:adr100_playbook_authoring:")
assert approval_service.fingerprints[1].startswith("adr100_playbook_authoring:")
assert approval_service.fingerprints[0].startswith("lookup:")
assert len(approval_service.fingerprints[0].removeprefix("lookup:")) == 64
assert len(approval_service.fingerprints[1]) == 64
assert alert_repo.calls[0]["event_type"] == "APPROVAL_ESCALATED"
assert alert_repo.calls[0]["approval_id"] == "00000000-0000-0000-0000-00000000a100"
assert alert_repo.calls[0]["context"]["writes_approval_record"] is True

View File

@@ -69,7 +69,7 @@
- `apps/api/src/services/adr100_remediation_service.py`
- 新增 `create_approval_request()`,可從 remediation work item 建立 `adr100_playbook_authoring` approval。
- approval scope 明確為 `playbook_authoring_record_only``execution_authorized=false``repair_attempted=false``repair_executed=false`
- 以 `adr100_playbook_authoring:{work_item}` fingerprint 收斂重複送審,避免同一個告警項目一直產生重複 approval
- 以 `adr100_playbook_authoring:{work_item}` 的 SHA-256 fingerprint 收斂重複送審,符合 production `approval_records.fingerprint VARCHAR(64)` 限制
- 寫入 `approval_records``alert_operation_log(APPROVAL_ESCALATED)` 與 timeline不寫 incident state、不寫 auto-repair result、不建立外部 ticket。
- `apps/api/src/services/approval_execution.py`
- 新增 `playbook_authoring_record_only` 執行分支。