Files
awoooi/apps/api/tests/test_controlled_alert_target_router.py
ogt 6cf8429d17
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
fix(automation): enforce durable alert closure
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.
2026-07-14 09:40:53 +08:00

243 lines
8.6 KiB
Python

from __future__ import annotations
from types import SimpleNamespace
from unittest.mock import AsyncMock
import pytest
from src.api.v1 import webhooks
from src.services.awooop_ansible_audit_service import (
_catalog_hints,
build_ansible_decision_audit_payload,
build_ansible_truth,
)
from src.services.controlled_alert_target_router import (
build_controlled_recovery_handoff,
build_controlled_recovery_promotion_contract,
resolve_controlled_alert_target,
)
def _cold_start_incident() -> dict:
return {
"incident_id": "INC-20260711-11C751",
"project_id": "awoooi",
"alertname": "ColdStartGateBlocked",
"alert_category": "general",
"affected_services": ["cold-start-gate"],
"signals": [
{
"alert_name": "ColdStartGateBlocked",
"labels": {
"component": "cold-start-gate",
"namespace": "default",
"host": "110",
},
"annotations": {
"summary": (
"full-stack cold-start recovery blocked; backup and "
"Docker evidence must be checked"
)
},
}
],
}
def test_normalizer_separates_source_namespace_from_execution_domain() -> None:
route = resolve_controlled_alert_target(
alertname="ColdStartGateBlocked",
target_resource="cold-start-gate",
namespace="default",
)
assert route is not None
assert route["source_namespace"] == "default"
assert route["normalized_execution_namespace"] == "host_recovery"
assert route["kubernetes_namespace_applicable"] is False
assert route["executor"] == "Agent99"
assert route["runtime_execution_authorized"] is False
assert resolve_controlled_alert_target(
alertname="SentryRpsZero",
target_resource="sentry",
namespace="awoooi-prod",
) is None
def test_cold_start_contract_requires_same_run_receipts_before_closure() -> None:
contract = build_controlled_recovery_promotion_contract(
alertname="ColdStartGateBlocked",
target_resource="cold-start-gate",
namespace="default",
incident_id="INC-20260711-11C751",
)
assert contract is not None
fields = {row["field"]: row for row in contract["fields"]}
assert fields["target_selector"]["status"] == "ready"
assert fields["controlled_apply_route"]["status"] == "ready"
for required in (
"source_sensor_receipt",
"check_mode_receipt",
"dispatch_receipt",
"post_apply_verifier",
"incident_closure_receipt",
"telegram_receipt",
"km_writeback",
"playbook_trust_writeback",
):
assert fields[required]["status"] == "pending"
assert contract["runtime_execution_authorized"] is False
assert contract["owner_review_required"] is False
assert contract["needs_human"] is False
assert contract["completion_status"] == "partial"
def test_cold_start_is_excluded_from_generic_ansible_keyword_catalog() -> None:
hints = _catalog_hints(_cold_start_incident(), None)
assert hints["match_mode"] == "domain_controlled_executor_route_v1"
assert hints["decision_effect"] == "delegate_to_domain_executor"
assert hints["candidates"] == []
assert hints["controlled_executor"]["executor"] == "Agent99"
assert "ansible:110-devops" in hints["unmatched_catalog_ids"]
assert "ansible:188-momo-backup-user" in hints["unmatched_catalog_ids"]
truth = build_ansible_truth([], incident=_cold_start_incident(), drift=None)
assert truth["not_used_reason"] == "non_kubernetes_control_plane_route"
assert truth["candidate_catalog"]["controlled_executor"]["route_id"] == (
"agent99_recover_after_owner_review"
)
def test_cold_start_does_not_emit_ansible_candidate_audit() -> None:
incident = SimpleNamespace(
incident_id="INC-20260711-11C751",
project_id="awoooi",
alertname="ColdStartGateBlocked",
alert_category="general",
notification_type="TYPE-3",
severity=SimpleNamespace(value="P3"),
affected_services=["cold-start-gate"],
signals=[
SimpleNamespace(
alert_name="ColdStartGateBlocked",
labels={"component": "cold-start-gate", "namespace": "default"},
annotations={"summary": "full-stack cold-start blocked"},
)
],
)
payload = build_ansible_decision_audit_payload(
incident=incident,
proposal_data={"source": "test", "risk_level": "low"},
decision_path="alert_webhook_controlled_router",
not_used_reason="test",
)
assert payload is None
def test_handoff_stays_partial_until_dispatch_verifier_and_learning() -> None:
handoff = build_controlled_recovery_handoff(
alertname="custom",
target_resource="cold-start-gate",
namespace="default",
incident_id="INC-20260711-11C751",
)
assert handoff is not None
assert handoff["single_writer_executor"] == "Agent99"
assert handoff["queued"] is False
assert handoff["side_effect_performed"] is False
assert handoff["runtime_execution_authorized"] is False
assert handoff["owner_review_required"] is False
assert handoff["needs_human"] is False
assert handoff["active_blockers"] == [
"agent99_dispatch_receipt_readback_pending",
"post_apply_verifier_missing",
"km_playbook_writeback_missing",
]
@pytest.mark.asyncio
async def test_webhook_router_never_queues_generic_ansible_for_cold_start(
monkeypatch: pytest.MonkeyPatch,
) -> None:
queue = AsyncMock(side_effect=AssertionError("generic Ansible must not be queued"))
append = AsyncMock()
incident_lookup = AsyncMock(side_effect=AssertionError("incident lookup not needed"))
bridge = AsyncMock(
return_value={
"status": "dispatched",
"dispatchPerformed": True,
"identity": {
"run_id": "7cf8fdf7-0966-5ac6-95b2-09e32808b248",
"trace_id": "00-11111111111111111111111111111111-2222222222222222-01",
"work_item_id": "agent99-dispatch:awoooi:INC-20260711-11C751:recovery",
"idempotency_key": "agent99-controlled:stable-key",
},
"dispatchReceipt": {
"status": "accepted_inbox_triggered",
"accepted": True,
"inbox_triggered": True,
},
"correlatedReceipt": {
"status": "dispatch_accepted_verifier_pending",
"receipt_persisted": True,
"runtime_execution_authorized": False,
"runtime_closure_verified": False,
"verifier": {"status": "pending"},
"learning_writeback": {"status": "pending_verifier"},
},
}
)
monkeypatch.setattr(
"src.jobs.awooop_ansible_candidate_backfill_job.enqueue_ai_decision_ansible_candidate",
queue,
)
monkeypatch.setattr(
"src.repositories.alert_operation_log_repository.get_alert_operation_log_repository",
lambda: SimpleNamespace(append=append),
)
monkeypatch.setattr(
webhooks,
"get_incident_service",
lambda: SimpleNamespace(get_from_working_memory=incident_lookup),
)
monkeypatch.setattr(webhooks, "bridge_alertmanager_to_agent99", bridge)
handoff = await webhooks._try_auto_repair_background(
incident_id="INC-20260711-11C751",
approval_id="00000000-0000-0000-0000-000000000751",
alert_type="custom",
target_resource="cold-start-gate",
namespace="default",
risk_level="low",
source_alert_id="alert-11c751",
source_alertname="ColdStartGateBlocked",
source_fingerprint="source-fingerprint",
)
queue.assert_not_awaited()
incident_lookup.assert_not_awaited()
bridge.assert_awaited_once()
assert handoff["single_writer_executor"] == "Agent99"
assert handoff["execution_priority"] == 30
assert handoff["queued"] is True
assert handoff["runtime_execution_authorized"] is False
assert handoff["runtime_closure_verified"] is False
assert handoff["automation_run_id"] == (
"7cf8fdf7-0966-5ac6-95b2-09e32808b248"
)
append.assert_awaited_once()
receipt = append.await_args.kwargs
assert receipt["action_detail"] == "controlled_check_mode_queued"
assert receipt["success"] is True
assert receipt["context"]["safe_next_action"] == (
"run_independent_cold_start_verifier_then_km_playbook_writeback"
)
assert receipt["context"]["runtime_closure_verified"] is False