fix(agent99): persist canonical verifier run identity
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 1s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m25s
CD Pipeline / build-and-deploy (push) Successful in 15m19s
CD Pipeline / post-deploy-checks (push) Successful in 2m12s
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 1s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m25s
CD Pipeline / build-and-deploy (push) Successful in 15m19s
CD Pipeline / post-deploy-checks (push) Successful in 2m12s
This commit is contained in:
@@ -5760,6 +5760,7 @@ async def _record_post_apply_verifier_and_learning(
|
||||
result,
|
||||
verifier_receipt,
|
||||
)
|
||||
automation_run_id = _automation_run_id_for_claim(claim)
|
||||
post_state = {
|
||||
**verifier_receipt,
|
||||
"automation_run_id": automation_run_id,
|
||||
|
||||
@@ -41,6 +41,14 @@ class _RowsResult:
|
||||
return self._rows
|
||||
|
||||
|
||||
class _ScalarResult:
|
||||
def __init__(self, value) -> None:
|
||||
self._value = value
|
||||
|
||||
def scalar(self):
|
||||
return self._value
|
||||
|
||||
|
||||
class _SequenceDB:
|
||||
def __init__(self, *results) -> None:
|
||||
self._results = list(results)
|
||||
@@ -208,6 +216,64 @@ def test_backfill_accepts_only_same_run_successful_durable_verifier() -> None:
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_post_apply_verifier_persists_canonical_same_run_identity(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
claim = _wazuh_claim()
|
||||
apply_op_id = "00000000-0000-0000-0000-000000000203"
|
||||
receipt = _durable_verifier_receipt(claim, apply_op_id=apply_op_id)
|
||||
verifier_db = _SequenceDB(_ScalarResult("evidence-id"))
|
||||
context_calls = 0
|
||||
|
||||
@asynccontextmanager
|
||||
async def fake_db_context(_project_id: str):
|
||||
nonlocal context_calls
|
||||
context_calls += 1
|
||||
if context_calls == 1:
|
||||
yield verifier_db
|
||||
return
|
||||
raise RuntimeError("KM persistence is outside this focused receipt test")
|
||||
|
||||
monkeypatch.setattr(service, "get_db_context", fake_db_context)
|
||||
monkeypatch.setattr(
|
||||
service,
|
||||
"_resolve_ansible_post_verifier_receipt",
|
||||
AsyncMock(return_value=(receipt, True)),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
service,
|
||||
"_record_apply_post_verifier_terminal",
|
||||
AsyncMock(return_value=True),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
service,
|
||||
"_record_learning_writeback_receipt",
|
||||
AsyncMock(return_value=None),
|
||||
)
|
||||
|
||||
result = await service._record_post_apply_verifier_and_learning(
|
||||
claim,
|
||||
service.AnsibleRunResult(
|
||||
returncode=0,
|
||||
stdout="",
|
||||
stderr="",
|
||||
duration_ms=5,
|
||||
),
|
||||
apply_op_id=apply_op_id,
|
||||
project_id="default",
|
||||
durable_verifier_receipt=receipt,
|
||||
)
|
||||
|
||||
post_state = json.loads(verifier_db.parameters[0]["post_execution_state"])
|
||||
assert post_state["automation_run_id"] == claim.input_payload["automation_run_id"]
|
||||
assert post_state["trace_id"] == claim.input_payload["trace_id"]
|
||||
assert post_state["run_id"] == claim.input_payload["run_id"]
|
||||
assert result["verification"] is True
|
||||
assert result["verification_passed"] is True
|
||||
assert result["durable_verifier_receipt_reused"] is True
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_backfill_repairs_orphan_incident_and_reuses_verifier(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
|
||||
Reference in New Issue
Block a user