fix(automation): enforce durable alert closure
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m32s
CD Pipeline / build-and-deploy (push) Successful in 8m2s
CD Pipeline / post-deploy-checks (push) Successful in 2m22s

Restore D037 durable incident readback without weakening database failure semantics.

Fence Agent99 dispatch and terminal learning to canonical identities, durable leases, verifier receipts, and reconciler-owned checkpoints.

Drain backup and restore legacy receipts in bounded cohorts with strict transport, claim, projection, and no-false-green controls.

Keep SSH service refusal visible while separating it from broker network-policy reachability.
This commit is contained in:
ogt
2026-07-14 09:40:53 +08:00
parent 72a167a322
commit 6cf8429d17
56 changed files with 15100 additions and 227 deletions

View File

@@ -0,0 +1,119 @@
from __future__ import annotations
import pytest
from src.services.agent99_controlled_dispatch_ledger import (
PostgresAgent99DispatchLedger,
build_agent99_dispatch_identity,
build_agent99_dispatch_receipt_envelope,
parse_agent99_dispatch_identity,
)
def test_dispatch_identity_parser_rejects_cross_run_projection() -> None:
identity = build_agent99_dispatch_identity(
project_id="awoooi",
incident_id="INC-20260711-11C751",
source_fingerprint="fp-cold-start",
route_id="agent99:host_recovery:Recover",
)
public = identity.public_dict()
assert parse_agent99_dispatch_identity(public) == identity
public["trace_id"] = "00-00000000000000000000000000000000-0000000000000000-01"
with pytest.raises(ValueError, match="identity_mismatch:trace_id"):
parse_agent99_dispatch_identity(public)
def test_accepted_without_inbox_trigger_is_delivery_unknown_not_authorized() -> None:
identity = build_agent99_dispatch_identity(
project_id="awoooi",
incident_id="INC-20260711-11C751",
source_fingerprint="fp-cold-start",
route_id="agent99:host_recovery:Recover",
)
envelope = build_agent99_dispatch_receipt_envelope(
identity=identity,
dispatch_receipt={
"status": "accepted_inbox_pending",
"accepted": True,
"inbox_triggered": False,
"delivery_certainty": "unknown",
},
controlled_apply_authorized=True,
)
assert envelope["status"] == "dispatch_delivery_unknown_reconcile_only"
assert envelope["dispatch_promoted"] is False
assert envelope["controlled_apply_authorized"] is False
assert envelope["retry_policy"]["reconcile_only"] is True
@pytest.mark.asyncio
async def test_backup_verifier_requires_all_six_dr_evidence_refs() -> None:
identity = build_agent99_dispatch_identity(
project_id="awoooi",
incident_id="INC-20260711-BACKUP",
source_fingerprint="fp-backup",
route_id="agent99:backup_health:BackupCheck",
)
ledger = PostgresAgent99DispatchLedger()
result = await ledger.record_verifier(
identity=identity,
outcome_receipt={
"identity": identity.public_dict(),
"automationRunId": str(identity.run_id),
"traceId": identity.trace_id,
"workItemId": identity.work_item_id,
"mode": "BackupCheck",
"outcome": {
"identity": identity.public_dict(),
"schemaVersion": "agent99_outcome_contract_v1",
"state": "resolved",
"transportOk": True,
"verifierPassed": True,
"sourceEventResolved": True,
},
},
evidence_refs={
"agent99_outcome_receipt_id": "agent99:outcome:1",
"post_verifier_evidence_ref": "agent99:BackupCheck:verified",
"source_event_evidence_ref": "incident:source-resolved",
},
)
assert result["status"] == "verifier_evidence_missing_fail_closed"
assert set(result["missing_evidence_refs"]) == {
"backup_status_evidence_ref",
"freshness_evidence_ref",
"offsite_verify_evidence_ref",
"escrow_evidence_ref",
"restore_drill_evidence_ref",
"source_resolution_receipt_ref",
}
@pytest.mark.asyncio
async def test_backup_learning_requires_dr_scorecard_ack() -> None:
identity = build_agent99_dispatch_identity(
project_id="awoooi",
incident_id="INC-20260711-BACKUP",
source_fingerprint="fp-backup",
route_id="agent99:backup_health:BackupCheck",
)
ledger = PostgresAgent99DispatchLedger()
result = await ledger.record_learning_writeback(
identity=identity,
receipt_refs={
"incident_closure_receipt_id": "incident:1",
"telegram_lifecycle_receipt_id": "telegram:1",
"km_writeback_ack_id": "km:1",
"playbook_trust_writeback_ack_id": "playbook:1",
},
)
assert result["status"] == "learning_writeback_incomplete_fail_closed"
assert result["missing_receipts"] == ["dr_scorecard_writeback_ack_id"]