fix(sre): fail closed typed Agent99 dispatch

This commit is contained in:
Your Name
2026-07-19 03:21:22 +08:00
parent 3223f9c913
commit ba4e5c41a7
7 changed files with 329 additions and 42 deletions

View File

@@ -15,12 +15,17 @@ from src.services import agent99_controlled_dispatch_ledger as ledger_module
from src.services import agent99_outcome_ingestion as ingestion_module
from src.services.agent99_controlled_dispatch_ledger import (
PostgresAgent99DispatchLedger,
attach_agent99_dispatch_identity,
build_agent99_dispatch_identity,
build_agent99_dispatch_receipt_envelope,
parse_agent99_dispatch_identity,
record_agent99_learning_writeback,
)
from src.services.agent99_sre_bridge import bridge_alertmanager_to_agent99
from src.services.agent99_sre_bridge import (
_agent99_dispatch_scope_from_payload,
bridge_alertmanager_to_agent99,
build_agent99_sre_alert,
)
def _identity():
@@ -491,6 +496,115 @@ async def test_verifier_requires_transport_and_all_evidence(monkeypatch) -> None
assert passed["runtime_closure_verified"] is False
@pytest.mark.asyncio
async def test_backupcheck_read_only_scope_passes_real_ledger_verifier(
monkeypatch,
) -> None:
identity = build_agent99_dispatch_identity(
project_id="awoooi",
incident_id="INC-20260711-BACKUP",
source_fingerprint="backup-fingerprint",
route_id="agent99:backup_health:BackupCheck",
execution_generation="1",
work_item_id=(
"agent99-dispatch:awoooi:INC-20260711-BACKUP:BackupCheck"
),
)
payload = build_agent99_sre_alert(
alert_id="backup-readback",
alertname="BackupCredentialEscrowEvidenceMissing",
severity="warning",
namespace="awoooi-prod",
target_resource="backup_restore",
message="freshness escrow restore evidence required",
labels={"event_type": "backup_restore_escrow_signal"},
fingerprint="backup-fingerprint",
)
payload = attach_agent99_dispatch_identity(payload, identity)
scope = _agent99_dispatch_scope_from_payload(payload)
assert scope["executor"] == "Agent99"
assert scope["break_glass_executor"] == "backup_restore_break_glass"
assert scope["controlled_apply_requested"] is False
promoted = build_agent99_dispatch_receipt_envelope(
identity=identity,
dispatch_receipt={
"kind": "backup_health",
"suggested_mode": "BackupCheck",
"target_resource": "backup_restore",
"controlled_apply_requested": False,
"accepted": True,
"inbox_triggered": True,
"queue_accepted": True,
"dispatch_identity_matched": True,
"delivery_certainty": "delivered",
"dispatch_scope": scope,
},
controlled_apply_authorized=False,
)
outcome = {
"identity": identity.public_dict(),
"controlledApply": False,
"mode": "BackupCheck",
"outcome": {
"identity": identity.public_dict(),
"schemaVersion": "agent99_outcome_contract_v1",
"state": "resolved",
"transportOk": True,
"verifierName": "backup_restore_readback_verifier",
"verifierPassed": True,
"sourceEventResolved": True,
"verifiedAt": "2026-07-11T20:00:00+08:00",
},
}
class BackupVerifierDB:
def __init__(self) -> None:
self.call = 0
async def execute(self, _statement):
self.call += 1
if self.call == 1:
return _ScalarResult(
row=SimpleNamespace(
state="waiting_tool",
error_detail=json.dumps(promoted),
)
)
if self.call == 2:
return _ScalarResult(identity.run_id)
if self.call == 4:
return _ScalarResult(identity.incident_id)
if self.call in {5, 6}:
return _ScalarResult(identity.run_id)
return _ScalarResult()
monkeypatch.setattr(
ledger_module,
"get_db_context",
lambda _project_id: _Context(BackupVerifierDB()),
)
result = await PostgresAgent99DispatchLedger().record_verifier(
identity=identity,
outcome_receipt=outcome,
evidence_refs={
**_evidence_refs(),
"backup_status_evidence_ref": "backup-status:1",
"freshness_evidence_ref": "backup-freshness:1",
"offsite_verify_evidence_ref": "offsite-verify:1",
"escrow_evidence_ref": "escrow-readback:1",
"restore_drill_evidence_ref": "restore-drill:1",
"source_resolution_receipt_ref": "alert-resolved:1",
},
)
assert result["status"] == "verifier_passed_learning_writeback_pending"
assert result["post_verifier_passed"] is True
assert result["controlled_apply_authorized"] is False
assert result["runtime_closure_verified"] is False
@pytest.mark.asyncio
@pytest.mark.parametrize("mismatch", ["verifier", "mode", "controlled_apply"])
async def test_verifier_rejects_dispatch_scope_mismatch(