Files
awoooi/apps/api/tests/test_telegram_gateway_error_sanitizer.py
ogt 34e32f6ed6
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 2m27s
CD Pipeline / build-and-deploy (push) Successful in 6m39s
CD Pipeline / post-deploy-checks (push) Successful in 1m55s
fix(agent99): dispatch actionable alerts with receipts
2026-07-11 10:30:29 +08:00

307 lines
12 KiB
Python
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from __future__ import annotations
from src.services.telegram_gateway import (
_agent99_actionable_outbound_metadata,
_agent99_alert_from_actionable_outbound,
_agent99_alert_from_ai_automation_card,
_merge_outbound_source_envelope_extra,
_outbound_source_envelope,
_sanitize_telegram_error,
format_aiops_signal_alert_card,
)
def test_telegram_gateway_sanitizes_bot_token_url() -> None:
raw = "Client error for https://api.telegram.org/bot123456:SECRET/sendMessage"
sanitized = _sanitize_telegram_error(raw)
assert "SECRET" not in sanitized
assert "bot<redacted>" in sanitized
def test_outbound_source_envelope_keeps_replay_context_without_raw_payload() -> None:
payload = {
"chat_id": "-100123",
"text": (
"ACTION REQUIRED INC-20260513-9B082D "
"<code>7f858956</code> token "
"1234567890:abcdefghijklmnopqrstuvwxyzABCDEFGH"
),
"parse_mode": "HTML",
"reply_markup": {
"inline_keyboard": [
[
{"text": "批准", "callback_data": "approve:approval-id-secret"},
{"text": "詳情", "callback_data": "details:approval-id-secret"},
]
]
},
}
envelope = _outbound_source_envelope("sendMessage", payload)
assert envelope["adapter"] == "legacy_telegram_gateway"
assert envelope["method"] == "sendMessage"
assert envelope["payload_sha256"]
assert envelope["payload_keys"] == ["chat_id", "parse_mode", "reply_markup", "text"]
assert envelope["parse_mode"] == "HTML"
assert envelope["reply_markup"]["button_count"] == 2
assert envelope["reply_markup"]["buttons"][0]["callback_prefix"] == "approve"
assert envelope["reply_markup"]["buttons"][1]["callback_prefix"] == "details"
assert envelope["source_refs"]["incident_ids"] == ["INC-20260513-9B082D"]
assert envelope["source_refs"]["code_refs"] == ["7f858956"]
assert "approval-id-secret" not in str(envelope)
assert "1234567890:" not in str(envelope)
assert "ACTION REQUIRED" not in str(envelope)
def test_outbound_source_envelope_reads_incident_refs_from_buttons() -> None:
payload = {
"chat_id": "-100123",
"text": "ACTION REQUIRED without incident id in visible text",
"reply_markup": {
"inline_keyboard": [
[
{"text": "詳情", "callback_data": "detail:INC-20260525-ABC123"},
{"text": "歷史", "callback_data": "history:INC-20260525-ABC123"},
],
[
{"text": "重診", "callback_data": "reanalyze:INC-20260525-DEF456"},
],
],
},
}
envelope = _outbound_source_envelope("sendMessage", payload)
assert envelope["source_refs"]["incident_ids"] == [
"INC-20260525-ABC123",
"INC-20260525-DEF456",
]
assert envelope["reply_markup"]["buttons"][0]["callback_prefix"] == "detail"
assert "detail:INC-20260525-ABC123" not in str(envelope)
def test_outbound_source_envelope_reads_meta_event_ref_from_text() -> None:
payload = {
"chat_id": "-100123",
"text": (
"⚙️ META SYSTEM\n"
"📋 <code>META-20260525201300</code>\n"
"異常元件AI 自健診異常"
),
"parse_mode": "HTML",
"reply_markup": {
"inline_keyboard": [
[{"text": "靜默", "callback_data": "silence:opaque-secret"}]
],
},
}
envelope = _outbound_source_envelope("sendMessage", payload)
assert envelope["source_refs"]["event_ids"] == ["META-20260525201300"]
assert envelope["source_refs"]["incident_ids"] == []
assert envelope["reply_markup"]["buttons"][0]["callback_prefix"] == "silence"
assert "opaque-secret" not in str(envelope)
def test_outbound_source_envelope_reads_ai_advisory_refs_without_raw_callback() -> None:
payload = {
"chat_id": "-100123",
"text": "Coverage 缺口分析",
"reply_markup": {
"inline_keyboard": [
[
{
"text": "已處理",
"callback_data": (
"ai_advisory_handled:coverage_gap:auto_rule_creation"
),
},
{
"text": "忽略",
"callback_data": (
"ai_advisory_snooze:coverage_gap:auto_rule_creation"
),
},
]
],
},
}
envelope = _outbound_source_envelope("sendMessage", payload)
assert envelope["source_refs"]["event_ids"] == [
"ai_advisory:coverage_gap:auto_rule_creation"
]
assert envelope["source_refs"]["advisory_ids"] == [
"coverage_gap:auto_rule_creation"
]
assert envelope["source_refs"]["alert_ids"] == ["coverage_gap"]
assert envelope["source_refs"]["fingerprints"] == [
"ai_advisory:coverage_gap:auto_rule_creation"
]
assert "ai_advisory_handled:coverage_gap:auto_rule_creation" not in str(envelope)
def test_outbound_source_envelope_marks_wazuh_ai_alert_card_for_awooop_readback() -> None:
raw_alert = """
wazuh_dashboard_api_readback_degraded dashboard agent list disappeared
POST /api/check-stored-api status=429 POST /api/check-api status=500
https://127.0.0.1:55000 is unreachable manager registry readback blocked
full_log=/var/ossec/logs/alerts/alerts.json Authorization: Bearer abcdefghijklmnopqrstuvwxyz
"""
card = format_aiops_signal_alert_card(raw_alert)
payload = {
"chat_id": "-100123",
"text": card,
"parse_mode": "HTML",
}
envelope = _outbound_source_envelope("sendMessage", payload)
card_metadata = envelope["ai_automation_alert_card"]
assert card_metadata["schema_version"] == "ai_automation_alert_card_mirror_v1"
assert card_metadata["card_schema"] == "ai_automation_alert_card_v1"
assert card_metadata["event_type"] == "wazuh_dashboard_api_readback_degraded"
assert card_metadata["lane"] == "siem_observability_readback_degraded"
assert card_metadata["target"] == "wazuh_dashboard_api"
assert card_metadata["gates"] == [
"controlled_playbook_queue",
"runtime_write_gate=controlled",
]
assert card_metadata["controlled_playbook_queue"] is True
assert card_metadata["runtime_write_gate_state"] == "controlled"
assert card_metadata["runtime_write_gate_count"] == 1
assert card_metadata["delivery_receipt_readback_required"] is True
assert envelope["source_refs"]["alert_ids"] == [
"wazuh_dashboard_api_readback_degraded"
]
assert envelope["source_refs"]["fingerprints"] == [
"ai_automation_alert_card:wazuh_dashboard_api_readback_degraded:siem_observability_readback_degraded"
]
assert "127.0.0.1:55000" not in str(envelope)
assert "/var/ossec" not in str(envelope)
assert "abcdefghijkl" not in str(envelope)
def test_ai_alert_card_builds_agent99_provider_freshness_signal() -> None:
raw_alert = """
SourceProviderIngestionStale provider_freshness_signal freshness window timeout
Sentry / SigNoz provider freshness last seen missing direct ref verifier readback
Authorization: Bearer abcdefghijklmnopqrstuvwxyz
"""
card = format_aiops_signal_alert_card(raw_alert)
payload = _agent99_alert_from_ai_automation_card(
card,
source="unit-test",
)
assert payload is not None
assert payload["source"] == "awoooi-api-telegram-gateway"
assert str(payload["id"]).startswith(
"awoooi-telegram-alert-card-provider_freshness_signal-"
)
assert payload["kind"] == "provider_freshness_signal"
assert payload["suggestedMode"] == "ProviderFreshness"
assert payload["controlledApply"] is False
assert payload["routing"]["routeSource"] == "structured_kind"
assert payload["awoooi"]["alertCategory"] == "source_provider_freshness_triage"
assert payload["awoooi"]["notificationType"] == "ai_automation_alert_card_v1"
assert "component=telegram_gateway" in payload["labels"]
assert "source=unit-test" in payload["labels"]
assert "provider-freshness" in payload["labels"]
assert "no-false-green" in payload["labels"]
assert "abcdefghijklmnopqrstuvwxyz" not in str(payload)
def test_action_required_cold_start_card_routes_to_agent99_recover() -> None:
card = (
" ACTION REQUIRED | <b>低風險</b>\n"
"──────────────────────\n"
"📋 <code>INC-20260710-5700F7</code>\n"
"🎯 資源:<code>cold-start-gate</code>\n"
"🏷️ 分類:<b>general</b>\n"
"🧭 處置狀態:<b>AI 選擇不執行修復</b>\n"
"🤖 <b>AI 自動化鏈路</b>"
)
metadata = _agent99_actionable_outbound_metadata(card)
payload = _agent99_alert_from_actionable_outbound(card, source="unit-test")
assert metadata is not None
assert metadata["card_schema"] == "awooop_action_required_v1"
assert metadata["incident_id"] == "INC-20260710-5700F7"
assert metadata["target"] == "cold-start-gate"
assert payload is not None
assert payload["kind"] == "host_recovery"
assert payload["suggestedMode"] == "Recover"
assert payload["controlledApply"] is True
assert payload["resolution"]["policy"] == "mode_verifier_can_resolve"
assert payload["awoooi"]["incidentId"] == "INC-20260710-5700F7"
def test_failed_cicd_card_routes_to_agent99_status_with_commit_receipt() -> None:
card = (
"❌ <b>[AWOOOI CI/CD]</b> | build-and-deploy\n"
"📦 AWOOOI 部署失敗\n"
"📋 <code>85159f25</code>\n"
"📝 fix(security): restrict executor SSH egress\n"
"🔗 <a href='https://gitea.example.invalid/run'>Workflow</a>"
)
metadata = _agent99_actionable_outbound_metadata(card)
payload = _agent99_alert_from_actionable_outbound(card, source="unit-test")
assert metadata is not None
assert metadata["card_schema"] == "awoooi_cicd_failure_v1"
assert metadata["commit_sha"] == "85159f25"
assert payload is not None
assert payload["kind"] == "cicd_failure"
assert payload["suggestedMode"] == "Status"
assert payload["controlledApply"] is False
assert payload["resolution"]["policy"] == "external_source_receipt_required"
assert payload["awoooi"]["commitSha"] == "85159f25"
assert "gitea.example.invalid" not in str(payload)
def test_agent99_dispatch_receipt_is_persisted_without_raw_transport_body() -> None:
envelope = _outbound_source_envelope(
"sendMessage",
{
"chat_id": "chat",
"text": (
" ACTION REQUIRED | 低風險\n"
"📋 INC-20260710-5700F7\n"
"🎯 資源cold-start-gate\n"
"🤖 AI 自動化鏈路"
),
},
)
receipt = {
"schema_version": "telegram_agent99_dispatch_receipt_v1",
"status": "accepted_inbox_triggered",
"transport": "relay",
"alert_id": "awoooi-telegram-actionable-awooop_action_required-safehash",
"kind": "host_recovery",
"suggested_mode": "Recover",
"accepted": True,
"inbox_triggered": True,
"stores_raw_response": False,
}
merged = _merge_outbound_source_envelope_extra(
envelope,
{"agent99_dispatch_receipt": receipt},
)
assert merged["agent99_dispatch_receipt"] == receipt
assert merged["agent99_actionable_outbound"]["incident_id"] == (
"INC-20260710-5700F7"
)
assert "incomingFile" not in str(merged)
assert "private-path" not in str(merged)