Files
awoooi/apps/api/src/services/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

282 lines
10 KiB
Python

"""Domain-aware routing for non-Kubernetes controlled alert targets.
The Alertmanager namespace label is a source attribute, not proof that every
alert is a Kubernetes workload. Cold-start/reboot recovery is a host control
plane lane. It must never fall through to a guessed ``kubectl`` action or the
generic Ansible keyword catalog merely because the source payload mentions a
host, backup, or container.
This module is deliberately pure. It only builds machine-readable routing
and receipt contracts; it does not dispatch Agent99, run a command, or write
runtime state.
"""
from __future__ import annotations
import re
from typing import Any
_RECOVERY_MARKERS = (
"cold-start",
"cold_start",
"cold start",
"full-stack-cold-start",
"full_stack_cold_start",
"full stack cold start",
"reboot-auto-recovery",
"reboot_auto_recovery",
"reboot auto recovery",
)
def _text_token(value: str | None) -> str:
return " ".join(str(value or "").strip().lower().split())
def _asset_token(value: str) -> str:
normalized = re.sub(r"[^a-z0-9_.-]+", "-", value.lower()).strip("-.")
return normalized[:96] or "unbound"
def resolve_controlled_alert_target(
*,
alertname: str,
target_resource: str,
namespace: str,
) -> dict[str, Any] | None:
"""Return the dedicated executor route for a known non-K8s target."""
text = " ".join(
(
_text_token(alertname),
_text_token(target_resource),
)
)
if not any(marker in text for marker in _RECOVERY_MARKERS):
return None
return {
"schema_version": "controlled_alert_target_route_v1",
"target_kind": "control_plane_recovery",
"target_resource": target_resource or "cold-start-gate",
"source_namespace": namespace or None,
"normalized_execution_namespace": "host_recovery",
"kubernetes_namespace_applicable": False,
"executor": "Agent99",
"route_id": "agent99_recover_after_owner_review",
"check_route": "agent99-mode Status controlledApply=false",
"controlled_apply_route": "agent99-mode Recover controlledApply=true",
"rollback_route": "agent99-mode Status controlledApply=false",
"runtime_execution_authorized": False,
"runtime_write_allowed": False,
}
def build_controlled_recovery_promotion_contract(
*,
alertname: str,
target_resource: str,
namespace: str,
incident_id: str = "",
) -> dict[str, Any] | None:
"""Build the no-false-green check/apply/verifier/learning contract."""
route = resolve_controlled_alert_target(
alertname=alertname,
target_resource=target_resource,
namespace=namespace,
)
if route is None:
return None
source_id = _asset_token(incident_id or f"{alertname}:{target_resource}")
fields = [
{
"field": "target_selector",
"status": "ready",
"source": "domain_target_normalizer",
"value": {
"target_kind": route["target_kind"],
"target_resource": route["target_resource"],
"normalized_execution_namespace": route[
"normalized_execution_namespace"
],
},
},
{
"field": "source_sensor_receipt",
"status": "pending",
"source": "alertmanager+cold_start_scorecard",
"value": "require_current_firing_or_recurrence_and_scorecard_ref",
},
{
"field": "check_mode_receipt",
"status": "pending",
"source": "Agent99 Status + read-only cold-start sensor",
"value": route["check_route"],
},
{
"field": "controlled_apply_route",
"status": "ready",
"source": "domain_target_normalizer",
"value": route["controlled_apply_route"],
},
{
"field": "dispatch_receipt",
"status": "pending",
"source": "agent99_sre_dispatch_receipt_v1",
"value": "accepted_and_inbox_triggered_required",
},
{
"field": "rollback_route",
"status": "ready",
"source": "domain_target_normalizer",
"value": route["rollback_route"],
},
{
"field": "post_apply_verifier",
"status": "pending",
"source": "Agent99 outcome + cold-start scorecard",
"value": [
"agent99_recover_outcome_terminal_readback",
"full_stack_cold_start_scorecard_rerun",
"required_hosts_harbor_k3s_routes_green",
"original_fingerprint_resolved_or_recurrence_decreased",
],
},
{
"field": "incident_closure_receipt",
"status": "pending",
"source": "incident_timeline",
"value": "terminal_only_after_independent_verifier",
},
{
"field": "telegram_receipt",
"status": "pending",
"source": "telegram_outbound_mirror",
"value": "lifecycle_result_delivery_ack_required",
},
{
"field": "km_writeback",
"status": "pending",
"source": "Hermes",
"value": f"km:cold-start-recovery:{source_id}",
},
{
"field": "playbook_trust_writeback",
"status": "pending",
"source": "OpenClaw/NemoTron",
"value": f"playbook-trust:cold-start-recovery:{source_id}",
},
]
ready_fields = [row["field"] for row in fields if row["status"] == "ready"]
blocked_fields = [row["field"] for row in fields if row["status"] != "ready"]
return {
"schema_version": "repair_candidate_promotion_contract_v1",
"status": "controlled_route_candidate_pending_receipts",
"route_id": route["route_id"],
"executor": route["executor"],
"incident_id": incident_id or None,
"target_route": route,
"ready_count": len(ready_fields),
"total_count": len(fields),
"blocked_count": len(blocked_fields),
"ready_fields": ready_fields,
"blocked_fields": blocked_fields,
"fields": fields,
"runtime_execution_authorized": False,
"runtime_write_allowed": False,
"controlled_playbook_queue": True,
"owner_review_required": False,
"owner_review_gate": "auto_waived_for_low_medium_high",
"needs_human": False,
"completion_status": "partial",
"completion_blocker": "dispatch_verifier_and_learning_receipts_missing",
"forbidden_operations": [
"kubectl_for_host_control_plane_target",
"generic_ansible_keyword_fallback",
"host_reboot",
"node_drain",
"backup_restore",
"secret_read",
"mark_resolved_without_post_verifier",
],
"controlled_automation_closure": {
"schema_version": "controlled_recovery_closure_contract_v1",
"trace_id_required": True,
"status": "pending_source_check_dispatch_verify_writeback",
"stages": [
{"stage": "sensor", "status": "pending", "writes_runtime_state": False},
{"stage": "normalize", "status": "passed", "writes_runtime_state": False},
{"stage": "check", "status": "pending", "writes_runtime_state": False},
{"stage": "controlled_apply", "status": "pending", "writes_runtime_state": False},
{"stage": "verify", "status": "pending", "writes_runtime_state": False},
{"stage": "learn_writeback", "status": "pending", "writes_runtime_state": False},
],
"required_receipts": [row["field"] for row in fields],
"automation_asset_ledger": [
{
"asset_type": "Sensor",
"asset_id": "scripts/reboot-recovery/full-stack-cold-start-check.sh",
"owner": "ColdStartMonitor",
"status": "read_only_receipt_pending",
},
{
"asset_type": "PlayBook",
"asset_id": "agent99:Recover",
"owner": "Agent99",
"status": "dispatch_receipt_pending",
},
{
"asset_type": "Verifier",
"asset_id": f"verifier:cold-start-recovery:{source_id}",
"owner": "PostExecutionVerifier",
"status": "pending",
},
{
"asset_type": "KM",
"asset_id": f"km:cold-start-recovery:{source_id}",
"owner": "Hermes",
"status": "pending_after_verifier",
},
],
},
}
def build_controlled_recovery_handoff(
*,
alertname: str,
target_resource: str,
namespace: str,
incident_id: str = "",
) -> dict[str, Any] | None:
contract = build_controlled_recovery_promotion_contract(
alertname=alertname,
target_resource=target_resource,
namespace=namespace,
incident_id=incident_id,
)
if contract is None:
return None
return {
"schema_version": "ai_decision_controlled_executor_handoff_v1",
"status": "agent99_dispatch_receipt_readback_pending",
"queued": False,
"side_effect_performed": False,
"single_writer_executor": "Agent99",
"route_id": contract["route_id"],
"active_blockers": [
"agent99_dispatch_receipt_readback_pending",
"post_apply_verifier_missing",
"km_playbook_writeback_missing",
],
"safe_next_action": "read_agent99_dispatch_then_run_independent_cold_start_verifier",
"repair_candidate_promotion_contract": contract,
"runtime_execution_authorized": False,
"runtime_write_allowed": False,
"owner_review_required": False,
"owner_review_gate": "auto_waived_for_low_medium_high",
"needs_human": False,
}