fix(ai-loop): validate durable Wazuh closure receipts
This commit is contained in:
@@ -3720,9 +3720,7 @@ def _autonomous_execution_loop_ledger(
|
||||
for row in telegram_rows
|
||||
if _durable_controlled_apply_telegram_receipt(
|
||||
row,
|
||||
require_provider_receipt=(
|
||||
catalog_id == _WAZUH_POSTURE_CATALOG_ID
|
||||
),
|
||||
catalog_id=catalog_id,
|
||||
)
|
||||
and (
|
||||
not incident_id
|
||||
@@ -3943,29 +3941,122 @@ def _autonomous_execution_loop_ledger(
|
||||
def _durable_controlled_apply_telegram_receipt(
|
||||
row: Mapping[str, Any],
|
||||
*,
|
||||
require_provider_receipt: bool = False,
|
||||
catalog_id: str = "",
|
||||
retry_terminal_receipt: bool = False,
|
||||
) -> bool:
|
||||
"""Accept provider sends or policy-complete no-send suppression receipts."""
|
||||
|
||||
if str(row.get("action") or "") != "controlled_apply_result":
|
||||
return False
|
||||
wazuh_posture = catalog_id == _WAZUH_POSTURE_CATALOG_ID
|
||||
send_status = str(row.get("send_status") or "")
|
||||
if send_status == "sent":
|
||||
return (
|
||||
bool(row.get("provider_message_id"))
|
||||
if require_provider_receipt
|
||||
else True
|
||||
if not wazuh_posture:
|
||||
return True
|
||||
if not row.get("provider_message_id"):
|
||||
return False
|
||||
policy_version = str(row.get("notification_policy_version") or "")
|
||||
provider_delivery = str(
|
||||
row.get("notification_provider_delivery") or ""
|
||||
)
|
||||
if require_provider_receipt:
|
||||
lifecycle_state = str(row.get("notification_lifecycle_state") or "")
|
||||
if retry_terminal_receipt:
|
||||
execution_kind = str(
|
||||
row.get("notification_execution_kind") or ""
|
||||
)
|
||||
return bool(
|
||||
str(row.get("notification_disposition") or "") == "sent"
|
||||
and lifecycle_state == "failed"
|
||||
and (
|
||||
(
|
||||
execution_kind == "no_write_posture_readback"
|
||||
and (
|
||||
(
|
||||
policy_version
|
||||
== "telegram_posture_lifecycle_transition_v1"
|
||||
and provider_delivery == "state_transition"
|
||||
)
|
||||
or (
|
||||
policy_version
|
||||
== "telegram_posture_state_digest_v1"
|
||||
and provider_delivery == "digest"
|
||||
)
|
||||
)
|
||||
)
|
||||
or (
|
||||
execution_kind == "no_write_replay"
|
||||
and policy_version == "telegram_failure_digest_v2"
|
||||
and provider_delivery == "digest"
|
||||
)
|
||||
)
|
||||
)
|
||||
return bool(
|
||||
policy_version == "telegram_posture_lifecycle_transition_v1"
|
||||
and str(row.get("notification_disposition") or "") == "sent"
|
||||
and provider_delivery == "state_transition"
|
||||
and lifecycle_state == "recovered"
|
||||
)
|
||||
if send_status != "shadow" or row.get("provider_message_id"):
|
||||
return False
|
||||
policy_version = str(row.get("notification_policy_version") or "")
|
||||
provider_delivery = str(row.get("notification_provider_delivery") or "")
|
||||
suppression_reason = str(row.get("notification_suppression_reason") or "")
|
||||
generic_shadow = bool(
|
||||
policy_version
|
||||
and str(row.get("notification_disposition") or "") == "suppressed"
|
||||
and provider_delivery in {"shadow_only", "state_transition", "digest"}
|
||||
and row.get("notification_provider_send_suppressed") is True
|
||||
)
|
||||
if not wazuh_posture:
|
||||
return generic_shadow
|
||||
lifecycle_state = str(row.get("notification_lifecycle_state") or "")
|
||||
if retry_terminal_receipt:
|
||||
if not generic_shadow or lifecycle_state != "failed":
|
||||
return False
|
||||
execution_kind = str(row.get("notification_execution_kind") or "")
|
||||
return bool(
|
||||
(
|
||||
execution_kind == "no_write_posture_readback"
|
||||
and policy_version
|
||||
== "telegram_posture_lifecycle_transition_v1"
|
||||
and provider_delivery == "state_transition"
|
||||
and suppression_reason == "duplicate_lifecycle_state"
|
||||
)
|
||||
or (
|
||||
execution_kind == "no_write_posture_readback"
|
||||
and policy_version == "telegram_posture_state_digest_v1"
|
||||
and provider_delivery == "shadow_only"
|
||||
and suppression_reason == "historical_projection_backfill"
|
||||
)
|
||||
or (
|
||||
execution_kind == "no_write_replay"
|
||||
and policy_version == "telegram_failure_digest_v2"
|
||||
and (
|
||||
(
|
||||
provider_delivery == "digest"
|
||||
and suppression_reason
|
||||
== "duplicate_failure_fingerprint_window"
|
||||
)
|
||||
or (
|
||||
provider_delivery == "shadow_only"
|
||||
and suppression_reason == "historical_projection_backfill"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
if not generic_shadow or lifecycle_state != "recovered":
|
||||
return False
|
||||
return bool(
|
||||
send_status == "shadow"
|
||||
and not row.get("provider_message_id")
|
||||
and str(row.get("notification_policy_version") or "")
|
||||
and str(row.get("notification_disposition") or "") == "suppressed"
|
||||
and str(row.get("notification_provider_delivery") or "")
|
||||
in {"shadow_only", "state_transition", "digest"}
|
||||
and row.get("notification_provider_send_suppressed") is True
|
||||
(
|
||||
policy_version == "telegram_posture_lifecycle_transition_v1"
|
||||
and provider_delivery == "state_transition"
|
||||
and suppression_reason == "duplicate_lifecycle_state"
|
||||
)
|
||||
or (
|
||||
policy_version == "telegram_posture_state_digest_v1"
|
||||
and provider_delivery == "shadow_only"
|
||||
and suppression_reason == "historical_projection_backfill"
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -4038,9 +4129,7 @@ def _latest_flow_closure(
|
||||
for row in telegram_rows
|
||||
if _durable_controlled_apply_telegram_receipt(
|
||||
row,
|
||||
require_provider_receipt=(
|
||||
catalog_id == _WAZUH_POSTURE_CATALOG_ID
|
||||
),
|
||||
catalog_id=catalog_id,
|
||||
)
|
||||
and (
|
||||
not incident_id
|
||||
@@ -5041,6 +5130,15 @@ def _build_autonomous_retry_rollback_terminal_readback(
|
||||
"notification_provider_delivery": row.get(
|
||||
"telegram_notification_provider_delivery"
|
||||
),
|
||||
"notification_execution_kind": row.get(
|
||||
"telegram_notification_execution_kind"
|
||||
),
|
||||
"notification_lifecycle_state": row.get(
|
||||
"telegram_notification_lifecycle_state"
|
||||
),
|
||||
"notification_suppression_reason": row.get(
|
||||
"telegram_notification_suppression_reason"
|
||||
),
|
||||
"notification_provider_send_suppressed": row.get(
|
||||
"telegram_provider_send_suppressed"
|
||||
),
|
||||
@@ -5109,7 +5207,11 @@ def _build_autonomous_retry_rollback_terminal_readback(
|
||||
),
|
||||
"telegram_receipt_same_run": bool(
|
||||
row.get("telegram_message_id")
|
||||
and _durable_controlled_apply_telegram_receipt(telegram_receipt)
|
||||
and _durable_controlled_apply_telegram_receipt(
|
||||
telegram_receipt,
|
||||
catalog_id=str(row.get("catalog_id") or ""),
|
||||
retry_terminal_receipt=True,
|
||||
)
|
||||
and row.get("telegram_automation_run_id") == automation_run_id
|
||||
),
|
||||
"public_safe_receipt": bool(
|
||||
@@ -8146,6 +8248,12 @@ _RUNTIME_RETRY_TERMINAL_LATEST_SQL = """
|
||||
AS telegram_notification_disposition,
|
||||
telegram.notification_provider_delivery
|
||||
AS telegram_notification_provider_delivery,
|
||||
telegram.notification_execution_kind
|
||||
AS telegram_notification_execution_kind,
|
||||
telegram.notification_lifecycle_state
|
||||
AS telegram_notification_lifecycle_state,
|
||||
telegram.notification_suppression_reason
|
||||
AS telegram_notification_suppression_reason,
|
||||
telegram.provider_send_suppressed
|
||||
AS telegram_provider_send_suppressed,
|
||||
replay.created_at AS retry_created_at
|
||||
@@ -8263,6 +8371,17 @@ _RUNTIME_RETRY_TERMINAL_LATEST_SQL = """
|
||||
outbound.source_envelope #>>
|
||||
'{notification_policy,provider_delivery}'
|
||||
AS notification_provider_delivery,
|
||||
coalesce(
|
||||
outbound.source_envelope #>>
|
||||
'{callback_reply,execution_kind}',
|
||||
outbound.source_envelope ->> 'execution_kind'
|
||||
) AS notification_execution_kind,
|
||||
outbound.source_envelope #>>
|
||||
'{notification_policy,lifecycle_state}'
|
||||
AS notification_lifecycle_state,
|
||||
outbound.source_envelope #>>
|
||||
'{notification_policy,suppression_reason}'
|
||||
AS notification_suppression_reason,
|
||||
outbound.source_envelope #>>
|
||||
'{notification_policy,provider_send_performed}'
|
||||
= 'false' AS provider_send_suppressed
|
||||
@@ -8270,7 +8389,10 @@ _RUNTIME_RETRY_TERMINAL_LATEST_SQL = """
|
||||
WHERE outbound.project_id = :project_id
|
||||
AND outbound.channel_type = 'telegram'
|
||||
AND (
|
||||
outbound.send_status = 'sent'
|
||||
(
|
||||
outbound.send_status = 'sent'
|
||||
AND outbound.provider_message_id IS NOT NULL
|
||||
)
|
||||
OR (
|
||||
outbound.send_status = 'shadow'
|
||||
AND outbound.provider_message_id IS NULL
|
||||
@@ -8302,6 +8424,17 @@ _RUNTIME_RETRY_TERMINAL_LATEST_SQL = """
|
||||
replay.input ->> 'automation_run_id',
|
||||
apply.input ->> 'automation_run_id'
|
||||
)
|
||||
AND coalesce(
|
||||
outbound.source_envelope #>>
|
||||
'{callback_reply,incident_id}',
|
||||
outbound.source_envelope #>>
|
||||
'{source_refs,incident_ids,0}'
|
||||
) = coalesce(
|
||||
apply.incident_id::text,
|
||||
apply.input ->> 'incident_id'
|
||||
)
|
||||
AND outbound.source_envelope #>>
|
||||
'{callback_reply,apply_op_id}' = apply.op_id::text
|
||||
ORDER BY outbound.sent_at DESC NULLS LAST, outbound.queued_at DESC
|
||||
LIMIT 1
|
||||
) telegram ON TRUE
|
||||
@@ -8789,6 +8922,10 @@ _RUNTIME_TELEGRAM_LATEST_SQL = """
|
||||
AS notification_disposition,
|
||||
source_envelope #>> '{notification_policy,provider_delivery}'
|
||||
AS notification_provider_delivery,
|
||||
source_envelope #>> '{notification_policy,lifecycle_state}'
|
||||
AS notification_lifecycle_state,
|
||||
source_envelope #>> '{notification_policy,suppression_reason}'
|
||||
AS notification_suppression_reason,
|
||||
source_envelope #>> '{notification_policy,provider_send_performed}'
|
||||
= 'false' AS notification_provider_send_suppressed,
|
||||
queued_at,
|
||||
@@ -8844,6 +8981,10 @@ _RUNTIME_TELEGRAM_LATEST_DIRECT_SQL = """
|
||||
AS notification_disposition,
|
||||
source_envelope #>> '{notification_policy,provider_delivery}'
|
||||
AS notification_provider_delivery,
|
||||
source_envelope #>> '{notification_policy,lifecycle_state}'
|
||||
AS notification_lifecycle_state,
|
||||
source_envelope #>> '{notification_policy,suppression_reason}'
|
||||
AS notification_suppression_reason,
|
||||
source_envelope #>> '{notification_policy,provider_send_performed}'
|
||||
= 'false' AS notification_provider_send_suppressed,
|
||||
queued_at,
|
||||
|
||||
Reference in New Issue
Block a user