{
    "schema": "https://saferpage.de/schemas/operator-delivery-credential-preflight.v1",
    "generated_at": "2026-08-03T08:02:57+00:00",
    "available": true,
    "status": "blocked",
    "health": "blocked",
    "summary": "Delivery-Credential-Preflight: 1 von 7 Zielsystemtypen voll konfiguriert, 0 teilweise, native Runner-Ziele 1, Versandfreigabe nicht aktiv.",
    "metrics": {
        "channel_count": 7,
        "ready_channel_count": 1,
        "partial_channel_count": 0,
        "native_ready_channel_count": 1,
        "configured_target_ref_count": 0,
        "gate_count": 9,
        "passed_gate_count": 6,
        "warning_gate_count": 2,
        "blocked_gate_count": 1,
        "latest_smoke_available": 1,
        "latest_smoke_ok": 1,
        "latest_smoke_target_count": 7,
        "latest_smoke_failed_check_count": 0,
        "latest_smoke_blocked_expected_count": 1,
        "latest_smoke_dry_run_sent_count": 0,
        "latest_smoke_runner_sent_count": 0,
        "dispatch_approved": false,
        "runner_state_available": true,
        "runner_sent_count": 0,
        "runner_deliverable_count": 0,
        "runner_error_count": 50,
        "runner_outbox_count": 0,
        "runner_channel_count": 4,
        "external_send_attempt_count": 0,
        "local_file_sink_attempt_count": 0,
        "dry_run_queued_count": 0,
        "credential_reference_count": 6,
        "configured_credential_reference_count": 0,
        "runtime_control_count": 8,
        "consolidation_status_count": 5,
        "claim_boundary_count": 5,
        "delivery_owner_handoff_step_count": 6,
        "delivery_owner_handoff_private_input_count": 6,
        "delivery_owner_handoff_public_output_count": 7,
        "delivery_owner_handoff_forbidden_output_count": 8,
        "delivery_owner_handoff_acceptance_count": 7,
        "delivery_owner_handoff_evidence_url_count": 7,
        "delivery_owner_handoff_validation_check_count": 5,
        "delivery_owner_handoff_safe_command_count": 5,
        "delivery_signoff_receipt_private_input_count": 7,
        "delivery_signoff_receipt_public_field_count": 8,
        "delivery_signoff_receipt_evidence_url_count": 7,
        "delivery_signoff_receipt_verification_check_count": 6,
        "delivery_signoff_receipt_no_secret_attestation_count": 6,
        "delivery_signoff_receipt_activation_condition_count": 5,
        "delivery_signoff_receipt_stop_condition_count": 5
    },
    "run_policy": {
        "base_url": "http://127.0.0.1",
        "recent_limit": 300,
        "max_hosts": 50,
        "timeout_seconds": 20,
        "execute_ready": true,
        "dispatch_approved": false,
        "external_delivery_only_if": "--execute-ready was passed, SAFERPAGE_ALERT_DISPATCH_APPROVED=yes and the channel target is configured",
        "external_send_attempt_count": 0,
        "local_file_sink_attempt_count": 0,
        "dry_run_queued_count": 0,
        "local_file_sink_policy": "Writes sanitized JSONL summary rows only when dispatch is approved and --execute-ready is passed.",
        "no_secret_export": true
    },
    "credential_manifest": {
        "reference_count": 6,
        "present_reference_count": 0,
        "external_native_target_ready": false,
        "dispatch_approved": false,
        "secret_policy": "Only env_ref and present flags are exported; never secret values, webhook URLs, recipients, target URLs or raw payloads.",
        "references": [
            {
                "id": "dispatch_approval",
                "env_ref": "SAFERPAGE_ALERT_DISPATCH_APPROVED",
                "present": false,
                "required_for_external_delivery": true,
                "purpose": "Explicit approval gate for productive alert delivery."
            },
            {
                "id": "generic_webhook_url",
                "env_ref": "SAFERPAGE_WEBHOOK_URL",
                "present": false,
                "required_for_external_delivery": false,
                "purpose": "Generic operator webhook target."
            },
            {
                "id": "generic_webhook_secret",
                "env_ref": "SAFERPAGE_WEBHOOK_SECRET",
                "present": false,
                "required_for_signed_webhook": true,
                "purpose": "HMAC-SHA256 signing secret for generic webhook deliveries."
            },
            {
                "id": "slack_webhook_url",
                "env_ref": "SAFERPAGE_SLACK_WEBHOOK_URL",
                "present": false,
                "required_for_external_delivery": false,
                "purpose": "Slack incoming webhook target."
            },
            {
                "id": "teams_webhook_url",
                "env_ref": "SAFERPAGE_TEAMS_WEBHOOK_URL",
                "present": false,
                "required_for_external_delivery": false,
                "purpose": "Microsoft Teams incoming webhook target."
            },
            {
                "id": "local_file_sink_path",
                "env_ref": "SAFERPAGE_LOCAL_FILE_SINK_PATH",
                "present": false,
                "required_for_external_delivery": false,
                "purpose": "Optional override for sanitized local JSONL audit sink; default path is used when absent."
            }
        ]
    },
    "receiver_contract": {
        "event": "monitoring.alert",
        "method": "POST",
        "content_type": "application/json; charset=utf-8",
        "required_headers": [
            "X-SaferPage-Event",
            "X-SaferPage-Domain",
            "X-SaferPage-Idempotency-Key"
        ],
        "optional_headers": [
            "X-SaferPage-Signature"
        ],
        "signature_algorithm": "HMAC-SHA256 over the compact JSON request body, formatted as sha256=<hex>.",
        "signature_header": "X-SaferPage-Signature",
        "idempotency_policy": "Receivers must deduplicate on X-SaferPage-Idempotency-Key and may compare body_sha256 for replay diagnostics.",
        "secret_policy": "Secrets, target URLs, recipients and raw payloads are never included in public runner state."
    },
    "runtime_controls": {
        "schema": "https://saferpage.de/schemas/delivery-runtime-controls.v1",
        "generated_at": "2026-06-13T12:00:08Z",
        "control_count": 8,
        "controls": {
            "credential_manifest_no_secret": true,
            "dispatch_approval_gate": true,
            "execute_ready_required": true,
            "hmac_signature_contract": true,
            "idempotency_contract": true,
            "local_file_sink_sanitized": true,
            "public_runner_state_sanitized": true,
            "dry_run_smoke_isolated_state": true
        },
        "url": "https://saferpage.de/evidence/delivery-runtime-controls.json"
    },
    "approval_contract": {
        "environment_file": "/etc/saferpage/alert-dispatch.env",
        "approval_env": "SAFERPAGE_ALERT_DISPATCH_APPROVED=yes",
        "execute_gate": "Der systemd-Service startet run-alert-dispatch.py mit --execute-ready; Versand erfolgt trotzdem nur bei SAFERPAGE_ALERT_DISPATCH_APPROVED=yes und konfiguriertem Ziel.",
        "native_runner_channels": [
            "local_file_sink",
            "generic_webhook",
            "slack",
            "teams"
        ],
        "payload_only_channels": [
            "jira",
            "email_smtp",
            "sendgrid"
        ],
        "does_not_send_from_preflight": true
    },
    "activation_package": {
        "schema": "https://saferpage.de/schemas/operator-delivery-activation-package.v1",
        "available": true,
        "environment_file": "/etc/saferpage/alert-dispatch.env",
        "template_url": "https://saferpage.de/integrationen/delivery-approval-template.env",
        "does_not_send": true,
        "does_not_include_secret_values": true,
        "env_template": [
            {
                "env_ref": "SAFERPAGE_ALERT_DISPATCH_APPROVED",
                "example_value": "no",
                "required_for_external_delivery": true,
                "public_export_allowed": false,
                "purpose": "Finales Betreiber-Go-live-Gate; erst nach Dry-run, Empfänger- und Datenschutzfreigabe auf yes setzen."
            },
            {
                "env_ref": "SAFERPAGE_WEBHOOK_URL",
                "example_value": "__SET_IN_SECRET_MANAGER_OR_SECURE_SERVER_ENV__",
                "required_for_external_delivery": false,
                "public_export_allowed": false,
                "purpose": "Generisches Betreiber-Webhook-Ziel."
            },
            {
                "env_ref": "SAFERPAGE_WEBHOOK_SECRET",
                "example_value": "__SET_IN_SECRET_MANAGER_OR_SECURE_SERVER_ENV__",
                "required_for_external_delivery": false,
                "public_export_allowed": false,
                "purpose": "HMAC-SHA256-Secret für generische Webhook-Payloads."
            },
            {
                "env_ref": "SAFERPAGE_SLACK_WEBHOOK_URL",
                "example_value": "__SET_IN_SECRET_MANAGER_OR_SECURE_SERVER_ENV__",
                "required_for_external_delivery": false,
                "public_export_allowed": false,
                "purpose": "Slack Incoming Webhook für PrivacyOps-/Security-Alerts."
            },
            {
                "env_ref": "SAFERPAGE_TEAMS_WEBHOOK_URL",
                "example_value": "__SET_IN_SECRET_MANAGER_OR_SECURE_SERVER_ENV__",
                "required_for_external_delivery": false,
                "public_export_allowed": false,
                "purpose": "Microsoft Teams Incoming Webhook für Betreiber-Alerts."
            },
            {
                "env_ref": "SAFERPAGE_LOCAL_FILE_SINK_PATH",
                "example_value": "/var/www/saferpage.de/runtime/alert_delivery_sink.jsonl",
                "required_for_external_delivery": false,
                "public_export_allowed": false,
                "purpose": "Optionaler lokaler Audit-Sink für sanitisierte Zustellnachweise."
            }
        ],
        "approval_record_template": [
            "approver_role",
            "approved_at",
            "scope",
            "target_systems",
            "test_recipient_or_test_channel_ref",
            "preflight_urls",
            "dry_run_result_refs",
            "receiver_signature_verified",
            "idempotency_verified",
            "rollback_owner",
            "expires_or_review_at"
        ],
        "smoke_matrix": [
            {
                "id": "dry_run_no_send",
                "command": "scripts/run-alert-dispatch-dry-run-smoke.sh",
                "expected": "sent_count=0, external_send_attempt_count=0, local_file_sink_attempt_count=0."
            },
            {
                "id": "execute_ready_without_approval",
                "command": "python3 scripts/run-alert-dispatch.py anrufer.info --base-url http://127.0.0.1 --max 1 --timeout 15 --execute-ready",
                "expected": "Ohne SAFERPAGE_ALERT_DISPATCH_APPROVED=yes bleibt sent_count=0."
            },
            {
                "id": "receiver_payload_fixture",
                "command": "curl -fsS https://saferpage.de/alarme/anrufer.info/delivery-json",
                "expected": "Payload enthält Idempotency-Key, body_sha256 und HMAC-Receiver-Vertrag ohne Ziel-URL."
            },
            {
                "id": "public_runner_state",
                "command": "curl -fsS https://saferpage.de/alarme/dispatch-runner-json",
                "expected": "Public State enthält nur Env-Refs, Hashes und Status; keine Secrets, Ziel-URLs oder Empfänger."
            }
        ],
        "acceptance_criteria": [
            "Mindestens ein externes natives Zielsystem ist serverseitig konfiguriert oder der lokale File-Sink ist für Audit-Dry-run bewusst als einziges Ziel zugelassen.",
            "SAFERPAGE_ALERT_DISPATCH_APPROVED=yes ist erst nach dokumentierter Betreiberfreigabe gesetzt.",
            "Receiver prüft X-SaferPage-Idempotency-Key und optional X-SaferPage-Signature.",
            "Dry-run-Smoke zeigt keine externen Sendungen und keine Secret-Leaks.",
            "Nach erstem produktiven Lauf sind sent_count, error_count und Zielsystem-Dedupe dokumentiert."
        ],
        "stop_conditions": [
            "Webhook-URL, Token, API-Key, E-Mail-Empfänger oder private Payloads erscheinen in Public-State, Logs oder Exporten.",
            "sent_count steigt ohne Approval-Record oder ohne SAFERPAGE_ALERT_DISPATCH_APPROVED=yes.",
            "Zielsystem erzeugt Duplikate trotz Idempotency-Key.",
            "error_count größer 0 oder wiederholte HTTP-/TLS-/Rate-Limit-Fehler."
        ],
        "no_secret_policy": "Dieses Paket exportiert nur Env-Referenzen, Placeholder, Smoke-Kommandos und Abnahmekriterien; keine echten URLs, Tokens, Empfänger oder Payload-Rohdaten."
    },
    "latest_smoke_result": {
        "schema": "https://saferpage.de/schemas/alert-delivery-readiness-smoke.v1",
        "generated_at": "2026-06-15T01:11:38+00:00",
        "ok": true,
        "summary": "No-Secret-Smoke für Alert-Delivery-Preflight, Dispatch-Runner, Runtime-Kontrollen, Delivery-Fixture, Operator-Go-live und isolierten Dry-run.",
        "host": "anrufer.info",
        "source_preflight_schema": "https://saferpage.de/schemas/operator-delivery-credential-preflight.v1",
        "source_preflight_url": "https://saferpage.de/integrationen/delivery-credential-preflight-json",
        "metrics": {
            "target_count": 7,
            "http_passed_count": 7,
            "http_failed_count": 0,
            "check_count": 20,
            "failed_check_count": 0,
            "blocked_expected_count": 1,
            "dispatch_approved": 0,
            "native_ready_channel_count": 1,
            "preflight_blocked_gate_count": 1,
            "preflight_consolidation_status_count": 5,
            "preflight_claim_boundary_count": 5,
            "preflight_delivery_owner_handoff_step_count": 6,
            "preflight_delivery_owner_handoff_private_input_count": 6,
            "preflight_delivery_owner_handoff_public_output_count": 7,
            "preflight_delivery_owner_handoff_forbidden_output_count": 8,
            "preflight_delivery_owner_handoff_acceptance_count": 7,
            "preflight_delivery_owner_handoff_evidence_url_count": 7,
            "preflight_delivery_owner_handoff_validation_check_count": 5,
            "preflight_delivery_owner_handoff_safe_command_count": 5,
            "preflight_delivery_signoff_receipt_private_input_count": 7,
            "preflight_delivery_signoff_receipt_public_field_count": 8,
            "preflight_delivery_signoff_receipt_evidence_url_count": 7,
            "preflight_delivery_signoff_receipt_verification_check_count": 6,
            "preflight_delivery_signoff_receipt_no_secret_attestation_count": 6,
            "preflight_delivery_signoff_receipt_activation_condition_count": 5,
            "preflight_delivery_signoff_receipt_stop_condition_count": 5,
            "runner_sent_count": 0,
            "runner_external_send_attempt_count": 0,
            "runner_local_file_sink_attempt_count": 0,
            "delivery_runtime_controls_ok": 1,
            "delivery_runtime_controls_control_count": 8,
            "delivery_runtime_controls_enabled_control_count": 8,
            "delivery_runtime_controls_missing_control_count": 0,
            "delivery_runtime_controls_secret_value_count": 0,
            "delivery_runtime_controls_no_secret_policy_ok": 1,
            "dry_run_sent_count": 0,
            "dry_run_queued_count": 1,
            "alerting_digest_severity_policy_count": 4,
            "alerting_digest_escalation_step_count": 5,
            "alerting_digest_dry_run_drill_count": 5,
            "alerting_digest_impact_triage_count": 4,
            "alerting_digest_communication_template_count": 4,
            "alerting_digest_communication_ticket_html_link_count": 1,
            "alerting_digest_receiver_contract_count": 5,
            "alerting_digest_blocked_gate_count": 3,
            "alerting_digest_scheduled_scan_plan_count": 4,
            "alerting_digest_alert_routing_matrix_count": 4,
            "alerting_digest_scheduled_scan_acceptance_count": 5,
            "alerting_digest_canary_activation_step_count": 6,
            "alerting_digest_retention_review_count": 5,
            "alerting_digest_kill_switch_rollback_count": 5,
            "alerting_digest_delivery_signoff_receipt_count": 6,
            "alerting_digest_receiver_approval_matrix_count": 5,
            "alerting_digest_delivery_pause_policy_count": 5,
            "alerting_digest_delivery_incident_drill_step_count": 5,
            "alerting_digest_parity_acceptance_count": 6,
            "alerting_digest_parity_acceptance_ready_count": 3,
            "alerting_digest_parity_acceptance_blocked_count": 3,
            "alerting_digest_claim_lane_count": 5,
            "alerting_digest_claim_public_ready_count": 2,
            "alerting_digest_claim_gated_readiness_count": 1,
            "alerting_digest_claim_blocked_live_count": 2,
            "alerting_digest_claim_operator_input_count": 5,
            "alerting_digest_claim_do_not_claim_count": 5,
            "alerting_digest_claim_acceptance_criterion_count": 15,
            "alerting_digest_claim_evidence_url_count": 16,
            "alerting_digest_drill_evidence_pack_row_count": 6,
            "alerting_digest_drill_evidence_pack_passed_count": 4,
            "alerting_digest_drill_evidence_pack_blocked_expected_count": 2,
            "alerting_digest_drill_evidence_pack_evidence_url_count": 6,
            "alerting_digest_drill_evidence_pack_no_secret_boundary_count": 6,
            "alerting_digest_drill_evidence_pack_operator_input_count": 6,
            "alerting_digest_drill_evidence_pack_acceptance_criterion_count": 18,
            "alerting_digest_drill_evidence_pack_stop_condition_count": 18,
            "operator_go_live_activation_packet_count": 3,
            "operator_go_live_delivery_activation_step_count": 6,
            "operator_go_live_delivery_rollback_action_count": 4,
            "operator_go_live_delivery_watch_signal_count": 5,
            "operator_go_live_signoff_dossier_count": 3,
            "operator_go_live_signoff_evidence_url_count": 16,
            "operator_go_live_signoff_acceptance_criterion_count": 15,
            "operator_go_live_signoff_stop_condition_count": 12,
            "operator_go_live_signoff_no_secret_check_count": 15
        },
        "checks": [
            {
                "id": "public_routes_http_200",
                "label": "Öffentliche Alert-Delivery-Readiness-Routen erreichbar",
                "status": "passed",
                "evidence": "7/7 Route(s) liefern HTTP 200.",
                "operator_action": "Weiter mit Delivery-Go-live-Gates."
            },
            {
                "id": "dry_run_blocks_external_delivery",
                "label": "Dry-run sendet keine externe Zustellung",
                "status": "passed",
                "evidence": "dry_run_ok=yes, sent_count=0, dry_run_queued_count=1.",
                "operator_action": "Dry-run isoliert halten; externe Zustellung nur mit Execute-Gate, Approval und konfiguriertem Ziel."
            },
            {
                "id": "runner_no_unapproved_delivery",
                "label": "Runner-State zeigt keine ungeprüften Sendungen",
                "status": "passed",
                "evidence": "sent_count=0, external_send_attempt_count=0, local_file_sink_attempt_count=0.",
                "operator_action": "Ungeplante Zustellung stoppen und Public-State/Journal prüfen."
            },
            {
                "id": "runtime_controls_documented",
                "label": "Delivery-Runtime-Kontrollen dokumentiert",
                "status": "passed",
                "evidence": "manifest_ok=yes, controls=8/8, missing=0, secrets=0, Approval-/Execute-/HMAC-/Dry-run-Gates geprüft.",
                "operator_action": "Runtime-Controls bei Runner- oder Zielsystem-Änderungen erneut reviewen."
            },
            {
                "id": "delivery_payload_fixture_contract",
                "label": "Delivery-Payload-Fixture ist abnahmefähig",
                "status": "passed",
                "evidence": "receiver_signature=HMAC-SHA256 over the compact JSON request body, formatted as sha256=<hex>..",
                "operator_action": "Receiver muss Idempotency-Key und optional HMAC-Signatur prüfen."
            },
            {
                "id": "dispatch_approval_blocker_explicit",
                "label": "Produktivblocker Dispatch-Freigabe explizit",
                "status": "blocked_expected",
                "evidence": "dispatch_approved=no.",
                "operator_action": "SAFERPAGE_ALERT_DISPATCH_APPROVED erst nach Zielsystem-, Empfänger- und Datenschutzfreigabe setzen."
            },
            {
                "id": "target_channel_blocker_explicit",
                "label": "Produktivblocker Zielsystem explizit",
                "status": "passed",
                "evidence": "native_ready_channel_count=1, blocked_gate_count=1.",
                "operator_action": "Signatur und Dedupe im Zielsystem testen."
            },
            {
                "id": "delivery_preflight_consolidation_boundaries_ready",
                "label": "Delivery-Preflight trennt Konsolidierungsstand und Claim-Grenzen",
                "status": "passed",
                "evidence": "consolidation_status=5, claim_boundaries=5.",
                "operator_action": "Delivery-Preflight muss für Betreiber klar zeigen: vorbereitet, blockiert, Grenze, nächster sicherer Schritt und nicht erlaubter Alert-Claim."
            },
            {
                "id": "delivery_owner_handoff_packet_ready",
                "label": "Delivery-Handoff trennt private Zielsysteme, Empfänger, Approval, Receiver-Abnahme und Public Evidence",
                "status": "passed",
                "evidence": "status=waiting_for_receiver_target_and_operator_approval, steps=6, private_inputs=6, public_outputs=7, forbidden_outputs=8, acceptance=7, evidence_urls=7, validation_checks=5, safe_commands=5, unsafe_evidence_urls=0.",
                "operator_action": "Delivery-Handoff muss öffentlich nur Env-Refs, Status, Hashes, Zähler, sichere Commands und saferpage.de-Evidence zeigen; Ziel-URLs, Tokens, Empfänger, Header, Rohpayloads und interne Nachweispositionen bleiben verboten."
            },
            {
                "id": "delivery_signoff_receipt_template_ready",
                "label": "Delivery-Signoff-Receipt trennt private Betreiberfreigabe von öffentlicher Evidence",
                "status": "passed",
                "evidence": "private_inputs=7, public_fields=8, evidence_urls=7, checks=6, no_secret=6, activation=5, stop=5, unsafe_evidence_urls=0.",
                "operator_action": "Signoff-Receipt vor Approval privat ausfüllen; öffentlich dürfen nur Status, Evidence-URLs, Hash-/Dedupe-Referenzen und aggregierte Zähler erscheinen."
            },
            {
                "id": "operator_go_live_links_delivery_blocker",
                "label": "Operator-Go-live verlinkt Delivery-Blocker",
                "status": "passed",
                "evidence": "Go-live Delivery-Phase=yes, alert_runner_available=1, alert_sent_count=0.",
                "operator_action": "Go-live-Center nach Zielsystem-/Approval-Freigaben erneut prüfen."
            },
            {
                "id": "operator_go_live_delivery_activation_packet",
                "label": "Operator-Go-live liefert Delivery-Aktivierungspaket mit Rollback und Nachlauf",
                "status": "passed",
                "evidence": "packets=1, steps=6, rollback_actions=4, watch_signals=5.",
                "operator_action": "Delivery-Aktivierungspaket im Go-live-Center pflegen; Signoff darf ohne Rollback- und Nachlaufregeln nicht produktiv werden."
            },
            {
                "id": "operator_go_live_signoff_dossiers_ready",
                "label": "Operator-Go-live liefert Signoff-Dossiers mit No-Secret-Checklisten",
                "status": "passed",
                "evidence": "dossiers=3, evidence_urls=16, acceptance=15, stop=12, no_secret=15.",
                "operator_action": "Signoff-Dossiers im Go-live-Center pflegen; Live-Claims erst nach Betreiberfreigabe und erneuten Smokes zulassen."
            },
            {
                "id": "alerting_digest_sla_escalation_contract",
                "label": "Alerting-Digest dokumentiert Support-Ziel, Eskalation und Dry-run-Drills",
                "status": "passed",
                "evidence": "severity_policy_count=4, escalation_step_count=5, dry_run_drill_count=5, impact_triage_count=4, templates=4, ticket_html_links=1, receiver_contracts=5, blocked_gate_count=3.",
                "operator_action": "Support-/Eskalationsgrenze im Alerting-Digest pflegen; produktive Blocker dürfen erst nach echten Secrets, Zielsystemen und Freigaben verschwinden."
            },
            {
                "id": "alerting_digest_scheduled_scan_routing_contract",
                "label": "Alerting-Digest dokumentiert tägliche Scanplanung und rollenbasiertes Routing",
                "status": "passed",
                "evidence": "scan_plan=4, routing=4, acceptance=5, canary=6, retention=5, rollback=5.",
                "operator_action": "Scan-Kadenz, Rollenrouting und Schedule-Abnahme im Alerting-Digest pflegen; echte Empfänger und Ziel-URLs nicht veröffentlichen."
            },
            {
                "id": "alerting_digest_delivery_signoff_ready",
                "label": "Alerting-Digest dokumentiert Delivery-Signoff, Receiver-Approval, Pause Policy und Incident-Drill",
                "status": "passed",
                "evidence": "signoff=6, receiver_approval=5, pause_policy=5, incident_drill=5.",
                "operator_action": "Delivery-Signoff, Receiver-Approval, Pause Policy und Incident-Drill im Alerting-Digest pflegen; echte Empfänger und Ziel-URLs bleiben privat."
            },
            {
                "id": "alerting_digest_parity_acceptance_visible",
                "label": "Alerting-Digest macht Wettbewerbs-Parity-Abnahme sichtbar",
                "status": "passed",
                "evidence": "parity_acceptance=3/6, blocked=3.",
                "operator_action": "Parity-Abnahme im Alerting-Digest pflegen; tägliche Scans und automatische Alerts erst nach Betreiberfreigabe als live behaupten."
            },
            {
                "id": "alerting_digest_claim_lane_ready",
                "label": "Alerting-Digest trennt Security-Monitoring-Claims in public-ready, gated und blocked-live",
                "status": "passed",
                "evidence": "claims=5, public_ready=2, gated=1, blocked_live=2, operator_inputs=5, do_not=5, acceptance=15, evidence_urls=16.",
                "operator_action": "Security-Claim-Lane mit erlaubten Aussagen, Betreiberinput, Nicht-behaupten-Grenzen, Evidence-Links und Abnahmekriterien pflegen."
            },
            {
                "id": "alerting_digest_drill_evidence_pack_ready",
                "label": "Alerting-Digest liefert No-Secret-Drill-Evidence für Feed und Alert-Zustellung",
                "status": "passed",
                "evidence": "rows=6, passed=4, blocked=2, evidence_urls=6, no_secret=6, operator_input=6, acceptance=18, stops=18.",
                "operator_action": "Drill-Evidence muss Feed-Smoke, Delivery-Smoke, Runtime-Kontrollen, Produktivblocker, Betreiberinput und Nicht-Claims getrennt ausweisen."
            },
            {
                "id": "public_exports_no_secret_scan",
                "label": "Öffentliche Delivery-Exports enthalten keine offensichtlichen Secret-Werte",
                "status": "passed",
                "evidence": "Keine Forbidden-Pattern-Treffer.",
                "operator_action": "Exports können in die Abnahmeakte."
            }
        ],
        "failed_checks": [],
        "failed_targets": [],
        "targets": [
            {
                "id": "delivery_credential_preflight_json",
                "label": "Delivery Credential Preflight JSON",
                "url": "https://saferpage.de/integrationen/delivery-credential-preflight-json",
                "path": "/integrationen/delivery-credential-preflight-json",
                "expected_http_status": 200,
                "actual_http_status": 200,
                "ok": true,
                "started_at": "2026-06-15T01:11:36Z",
                "finished_at": "2026-06-15T01:11:36Z"
            },
            {
                "id": "alert_dispatch_runner_json",
                "label": "Alert Dispatch Runner JSON",
                "url": "https://saferpage.de/alarme/dispatch-runner-json",
                "path": "/alarme/dispatch-runner-json",
                "expected_http_status": 200,
                "actual_http_status": 200,
                "ok": true,
                "started_at": "2026-06-15T01:11:36Z",
                "finished_at": "2026-06-15T01:11:36Z"
            },
            {
                "id": "delivery_runtime_controls",
                "label": "Delivery Runtime Controls",
                "url": "https://saferpage.de/evidence/delivery-runtime-controls.json",
                "path": "/evidence/delivery-runtime-controls.json",
                "expected_http_status": 200,
                "actual_http_status": 200,
                "ok": true,
                "started_at": "2026-06-15T01:11:36Z",
                "finished_at": "2026-06-15T01:11:36Z"
            },
            {
                "id": "delivery_approval_template_env",
                "label": "Delivery Approval Env Template",
                "url": "https://saferpage.de/integrationen/delivery-approval-template.env",
                "path": "/integrationen/delivery-approval-template.env",
                "expected_http_status": 200,
                "actual_http_status": 200,
                "ok": true,
                "started_at": "2026-06-15T01:11:36Z",
                "finished_at": "2026-06-15T01:11:36Z"
            },
            {
                "id": "alert_delivery_package_json",
                "label": "Alert Delivery Package JSON",
                "url": "https://saferpage.de/alarme/anrufer.info/delivery-json",
                "path": "/alarme/anrufer.info/delivery-json",
                "expected_http_status": 200,
                "actual_http_status": 200,
                "ok": true,
                "started_at": "2026-06-15T01:11:36Z",
                "finished_at": "2026-06-15T01:11:36Z"
            },
            {
                "id": "operator_go_live_json",
                "label": "Operator Go-live JSON",
                "url": "https://saferpage.de/betreiber/go-live-json",
                "path": "/betreiber/go-live-json",
                "expected_http_status": 200,
                "actual_http_status": 200,
                "ok": true,
                "started_at": "2026-06-15T01:11:36Z",
                "finished_at": "2026-06-15T01:11:36Z"
            },
            {
                "id": "security_alerting_digest_json",
                "label": "Security Alerting Digest JSON",
                "url": "https://saferpage.de/sicherheit/alerting-digest-json?host=anrufer.info",
                "path": "/sicherheit/alerting-digest-json",
                "expected_http_status": 200,
                "actual_http_status": 200,
                "ok": true,
                "started_at": "2026-06-15T01:11:36Z",
                "finished_at": "2026-06-15T01:11:38Z"
            }
        ],
        "dry_run_smoke": {
            "ok": true,
            "exit_code": 0,
            "evaluated_count": 1,
            "sent_count": 0,
            "dry_run_queued_count": 1,
            "external_delivery_only_if": "--execute-ready was passed, SAFERPAGE_ALERT_DISPATCH_APPROVED=yes and the channel target is configured"
        },
        "no_secret_policy": {
            "contains_secrets": false,
            "contains_target_urls": false,
            "contains_recipients": false,
            "contains_raw_payloads": false,
            "contains_private_documents": false,
            "contains_visitor_logs": false,
            "public_export_secret_pattern_hits": []
        },
        "claim_boundary": "Dieser Smoke setzt keine Delivery-Secrets, konfiguriert keine Zielsysteme, versendet keine Alerts, schreibt keinen produktiven Sink und veröffentlicht keine Webhook-URLs, Tokens, Empfänger oder Rohpayloads.",
        "available": true,
        "status": "passed",
        "url": "https://saferpage.de/evidence/alert-delivery-readiness-smoke.json"
    },
    "consolidation_status": [
        {
            "id": "delivery_contracts",
            "label": "Delivery-Verträge vorbereitet",
            "state": "erreicht",
            "evidence": "8 Runtime-Controls, Receiver-Vertrag, Idempotency-Key und Body-SHA-256 sind öffentlich belegbar.",
            "boundary": "Das ist ein Integrationsvertrag, keine echte Zustellung an Betreiberzielsysteme.",
            "next_action": "Receiver mit Testziel prüfen: HMAC, Idempotency, Dedupe, Retry und Fehlerantworten dokumentieren."
        },
        {
            "id": "dispatch_go_live",
            "label": "Produktive Alert-Zustellung",
            "state": "blockiert",
            "evidence": "dispatch_approved=no, runner_sent_count=0, native_ready_channel_count=1.",
            "boundary": "Nicht behaupten: Betreiber erhalten produktive Alerts, solange SAFERPAGE_ALERT_DISPATCH_APPROVED nicht aktiv ist.",
            "next_action": "Betreiberfreigabe, Zielsystem, Empfänger, Datenschutz-/Security-Abnahme und Monitoring signieren; erst danach Approval setzen."
        },
        {
            "id": "target_systems",
            "label": "Zielsysteme und Empfänger",
            "state": "teilweise_erreicht",
            "evidence": "1/7 Zielsystemtypen sind voll konfiguriert; 1 sind nativ durch den Runner sendbar.",
            "boundary": "Öffentliche Evidence zeigt nur Env-Referenzen und Status; echte Webhook-URLs, Tokens, Channels und Empfänger bleiben privat.",
            "next_action": "Mindestens ein natives Ziel mit Testempfänger einrichten und Zielsystem-Dedupe gegen Idempotency-Key prüfen."
        },
        {
            "id": "dry_run_guardrails",
            "label": "Dry-run und No-Send-Grenzen",
            "state": "erreicht",
            "evidence": "Letzter Smoke: dry_run_sent=0, runner_sent=0, failed_checks=0.",
            "boundary": "Smokes und Preflight senden nicht, setzen keine Secrets und prüfen keine privaten Zielsysteme.",
            "next_action": "Nach jeder Zielsystem- oder Runner-Änderung zuerst Dry-run-Smoke, dann Go-live-Center und Alerting-Digest prüfen."
        },
        {
            "id": "operator_claims",
            "label": "Wettbewerbs- und Betreiber-Claims",
            "state": "begrenzt",
            "evidence": "6/9 Delivery-Gates passed; 1 Blocker und 2 Warnungen bleiben sichtbar.",
            "boundary": "Nicht behaupten: automatische Alerts, Support-Ziel-Eskalation oder Nachweispositions-Zustellung sind live, solange Zielsystem- und Approval-Gates offen sind.",
            "next_action": "Vergleichs- und Betreibertexte nur mit Claim-Grenzen ausgeben; blockierte Gates im Go-live-Board offen lassen."
        }
    ],
    "claim_boundaries": [
        {
            "id": "no_live_alert_claim",
            "label": "Keine produktiven Alerts behaupten",
            "claim_allowed": "Alert-Delivery ist vorbereitet, no-secret dokumentiert und als Dry-run prüfbar.",
            "claim_forbidden": "Betreiber erhalten produktive Alerts.",
            "reason": "Produktiver Versand braucht Zielsystem, Empfängerfreigabe, SAFERPAGE_ALERT_DISPATCH_APPROVED=yes, Receiver-Abnahme und Nachlaufkontrolle.",
            "evidence_url": "https://saferpage.de/integrationen/delivery-credential-preflight-json"
        },
        {
            "id": "no_recipient_or_webhook_publication",
            "label": "Keine Empfänger oder Webhook-URLs veröffentlichen",
            "claim_allowed": "Public Exports zeigen Env-Referenzen, Status, Hashes und Idempotency-Keys.",
            "claim_forbidden": "Webhook-URLs, Slack-/Teams-Ziele, E-Mail-Empfänger, Tokens oder API-Keys sind öffentliche Evidence.",
            "reason": "Zielsystemdaten sind Secrets bzw. personenbezogene oder sicherheitsrelevante Betriebsdaten.",
            "evidence_url": "https://saferpage.de/evidence/alert-delivery-readiness-smoke.json"
        },
        {
            "id": "dry_run_is_not_delivery",
            "label": "Dry-run ist kein Versand",
            "claim_allowed": "Dry-run belegt Payload, Routing, No-Secret-Regeln und Stop-Bedingungen.",
            "claim_forbidden": "Dry-run beweist erfolgreiche Zustellung im Betreiberkanal.",
            "reason": "Dry-run darf keine externen Sends, keine produktiven Sinks und keine privaten Zielsysteme auslösen.",
            "evidence_url": "https://saferpage.de/alarme/dispatch-runner-json"
        },
        {
            "id": "receiver_must_validate",
            "label": "Receiver-Abnahme vor Go-live",
            "claim_allowed": "Receiver-Vertrag nennt HMAC, Idempotency, Body-Hash, Retry und Stop-Bedingungen.",
            "claim_forbidden": "Jedes Zielsystem ist automatisch kompatibel.",
            "reason": "Zielsysteme müssen Signatur, Dedupe, Fehlercodes und Rate-Limits selbst validieren.",
            "evidence_url": "https://saferpage.de/alarme/anrufer.info/delivery-json"
        },
        {
            "id": "no_sla_claim_without_watch",
            "label": "Keine Support-Ziel-/Eskalationsclaims ohne Nachlauf",
            "claim_allowed": "Alerting-Digest beschreibt Support-Ziele, Eskalations- und Incident-Drill-Blueprints.",
            "claim_forbidden": "Support-Ziel-Eskalation ist produktiv garantiert.",
            "reason": "Support-Ziel-Claims brauchen echten Versand, Monitoring, Fehlerbudget, Pausenpolicy und Betreiber-Nachlauf.",
            "evidence_url": "https://saferpage.de/sicherheit/alerting-digest-json"
        }
    ],
    "delivery_owner_handoff_packet": {
        "status": "waiting_for_receiver_target_and_operator_approval",
        "summary": "Delivery-Handoff für Betreiber, Receiver-Verantwortung und Security: Zielsysteme, Empfänger, Approval, HMAC, Dry-run und Claims werden no-secret getrennt.",
        "handoff_steps": [
            {
                "id": "select_receiver_scope",
                "label": "Receiver-Scope festlegen",
                "owner": "Betreiber/IT",
                "action": "Kanal, Eventtypen, Testempfänger, Zweck und Eskalationsfenster privat festlegen.",
                "acceptance": "Scope nennt Zielsystemtyp, Rollenempfänger, Eventtypen, Testfenster und Rollback-Verantwortlichkeit.",
                "evidence_url": "https://saferpage.de/integrationen/delivery-credential-preflight-json",
                "boundary": "Öffentlich erscheinen Rollen und Status, keine echten Empfänger oder Ziel-URLs."
            },
            {
                "id": "set_target_refs_privately",
                "label": "Zielsystem-Referenzen privat setzen",
                "owner": "Platform/Security",
                "action": "Webhook-, Slack-, Teams-, Jira-, SMTP- oder SendGrid-Refs nur in sicherer Server-Env oder Secret Manager setzen.",
                "acceptance": "Preflight zeigt present/missing-Status; Public Exports enthalten keine Zielwerte.",
                "evidence_url": "https://saferpage.de/integrationen/delivery-approval-template.env",
                "boundary": "Env-Template bleibt Placeholder; echte Werte dürfen nie committed oder publiziert werden."
            },
            {
                "id": "verify_receiver_contract",
                "label": "Receiver-Vertrag abnehmen",
                "owner": "Receiver-Verantwortung",
                "action": "HMAC, Idempotency-Key, Body-SHA-256, Retry, Fehlercodes und Dedupe im Testreceiver prüfen.",
                "acceptance": "Receiver akzeptiert signierte Testpayloads, dedupliziert Wiederholungen und liefert definierte Fehlerantworten.",
                "evidence_url": "https://saferpage.de/alarme/anrufer.info/delivery-json",
                "boundary": "Payload-Fixture beweist Vertrag, aber keine erfolgreiche Produktivzustellung."
            },
            {
                "id": "run_no_send_dry_run",
                "label": "No-Send-Dry-run ausführen",
                "owner": "Security/Platform",
                "action": "Alert-Dispatch-Dry-run und Readiness-Smoke ausführen, bevor Approval gesetzt wird.",
                "acceptance": "sent_count=0, external_send_attempt_count=0, failed_check_count=0; erwartete Blocker bleiben sichtbar.",
                "evidence_url": "https://saferpage.de/evidence/alert-delivery-readiness-smoke.json",
                "boundary": "Dry-run ist keine Zustellung an Betreiberkanal."
            },
            {
                "id": "approve_dispatch_gate",
                "label": "Dispatch-Gate signieren",
                "owner": "Betreiber/Security",
                "action": "SAFERPAGE_ALERT_DISPATCH_APPROVED erst nach Receiver-, Empfänger-, Datenschutz- und Stop-Bedingungsfreigabe aktivieren.",
                "acceptance": "Approval-Record nennt Scope, Testrefs, Smoke-Refs, Rollback-Verantwortlichkeit und Review-Ablauf.",
                "evidence_url": "https://saferpage.de/betreiber/go-live-json",
                "boundary": "Freigabestatus darf öffentlich sein; Personen, Empfänger und interne Nachweis-URLs bleiben privat."
            },
            {
                "id": "run_receiver_canary",
                "label": "Receiver-Canary kontrolliert starten",
                "owner": "Platform/Receiver-Verantwortung",
                "action": "Ersten produktionsnahen Test mit begrenztem Scope ausführen und Runner-State, Zielsystem-Dedupe und Fehlerquote prüfen.",
                "acceptance": "sent_count steigt nur für freigegebenen Scope; error_count=0; Dedupe und Pausepfad sind belegt.",
                "evidence_url": "https://saferpage.de/alarme/dispatch-runner-json",
                "boundary": "Canary ist begrenzter Test, kein pauschales Support-Ziel- oder Alert-Versprechen."
            }
        ],
        "private_inputs_required": [
            {
                "id": "receiver_target_url",
                "label": "Webhook-/Slack-/Teams-/Jira-Ziel-URL",
                "reason": "Produktive Zustellung braucht ein konkretes Betreiberziel.",
                "public_handling": "Nie öffentlich ausgeben; nur Zielsystemtyp und present/missing zeigen."
            },
            {
                "id": "receiver_hmac_secret",
                "label": "HMAC-/Webhook-Secret",
                "reason": "Receiver muss Payloads authentifizieren können.",
                "public_handling": "Nur Signaturalgorithmus und Headernamen zeigen."
            },
            {
                "id": "recipient_or_channel_approval",
                "label": "Empfänger-/Channel-Freigabe",
                "reason": "Alerts können personenbezogene oder betriebsinterne Informationen betreffen.",
                "public_handling": "Nur Rollen, Zweck und Freigabestatus zeigen."
            },
            {
                "id": "dispatch_approval_record",
                "label": "Dispatch-Approval-Record",
                "reason": "Produktiver Versand braucht dokumentierten Go-live-Entscheid.",
                "public_handling": "Nur Status, Scope-Klasse, Evidence-Refs und Reviewdatum öffentlich."
            },
            {
                "id": "receiver_test_log",
                "label": "Privates Receiver-Testlog",
                "reason": "Zielsystem muss Dedupe, Fehlercodes und Retry belegen.",
                "public_handling": "Nur aggregierte Abnahme und Hash-/Request-ID-Referenzen zeigen."
            },
            {
                "id": "rollback_pause_responsibility",
                "label": "Rollback-/Pause-Verantwortlichkeit",
                "reason": "Falsche oder doppelte Zustellungen müssen sofort pausierbar sein.",
                "public_handling": "Nur Rolle und Stop-Bedingungen öffentlich zeigen."
            }
        ],
        "public_outputs_allowed": [
            {
                "id": "env_ref_status",
                "label": "Env-Referenzstatus",
                "reason": "Preflight kann ready/missing zeigen, ohne Werte offenzulegen."
            },
            {
                "id": "receiver_contract",
                "label": "Receiver-Vertrag",
                "reason": "HMAC, Idempotency und Body-SHA-256 sind prüfbare Integrationsanforderungen."
            },
            {
                "id": "dry_run_counts",
                "label": "Dry-run-Zähler",
                "reason": "No-Send-Guardrails sind messbar."
            },
            {
                "id": "runner_status_counts",
                "label": "Runner-Statuszähler",
                "reason": "sent/error/outbox zeigen Betriebszustand ohne Zielsystemdetails."
            },
            {
                "id": "stop_conditions",
                "label": "Stop-Bedingungen",
                "reason": "Betreiber sehen, wann Versand pausiert werden muss."
            },
            {
                "id": "approval_status",
                "label": "Approval-Status",
                "reason": "Go-live-Gate ist nachvollziehbar, ohne Empfänger zu nennen."
            },
            {
                "id": "saferpage_evidence_urls",
                "label": "SaferPage-Evidence-URLs",
                "reason": "Abnahme bleibt verlinkbar und maschinenlesbar."
            }
        ],
        "forbidden_outputs": [
            "Webhook-, Slack-, Teams-, Jira-, SMTP- oder SendGrid-Ziel-URLs",
            "API-Keys, Tokens, HMAC-Secrets, SMTP-Passwörter oder Authorization-Header",
            "E-Mail-Adressen, Slack-Channels, Teams-Channel-IDs oder echte Empfängerlisten",
            "Private Alert-Payloads, Rohpayloads, Kundendokumente oder interne Nachweispositionstexte",
            "Zielsystem-Testlogs mit Personen, Hostnamen, internen URLs oder Request-Body",
            "Secret-Manager-Pfade, Environment-Dateien mit echten Werten oder Shell-History",
            "Betreiberentscheidung mit Personennamen, privaten Nachweis-URLs oder internen Kommentaren",
            "Behauptung erfolgreicher Produktivzustellung ohne Approval, Receiver-Abnahme und Runner-Evidence"
        ],
        "validation_checks": [
            "Delivery-Preflight zeigt blocked_gate_count > 0, solange Zielsystem oder Approval fehlt.",
            "Alert-Delivery-Smoke zeigt dry_run_sent_count=0 und runner_sent_count=0 vor Approval.",
            "Public Exports enthalten keine Webhook-/Slack-/Teams-URLs, Tokens, API-Keys oder Empfänger.",
            "Receiver-Fixture enthält Idempotency-Key, Body-SHA-256 und HMAC-Vertrag.",
            "Go-live-Center verlinkt Delivery-Phase, Rollback und Nachlaufbeobachtung."
        ],
        "safe_commands": [
            "scripts/run-alert-dispatch-dry-run-smoke.sh",
            "scripts/run-alert-delivery-readiness-smoke.sh",
            "curl -fsS https://saferpage.de/integrationen/delivery-credential-preflight-json",
            "curl -fsS https://saferpage.de/alarme/anrufer.info/delivery-json",
            "curl -fsS https://saferpage.de/alarme/dispatch-runner-json"
        ],
        "acceptance_criteria": [
            "Mindestens ein natives Zielsystem ist privat konfiguriert oder bewusst blockiert dokumentiert.",
            "Receiver prüft Idempotency-Key und optional HMAC-Signatur.",
            "Dry-run-Smoke bleibt ohne externe Sendung grün.",
            "Dispatch-Approval ist erst nach Zielsystem-, Empfänger-, Datenschutz- und Security-Freigabe aktiv.",
            "Public Evidence enthält keine Ziel-URLs, Tokens, Empfänger, Secrets oder Rohpayloads.",
            "Runner-State nach Canary zeigt begrenzten Scope, keine Fehler und nachvollziehbare Dedupe-Referenz.",
            "Produktclaims bleiben auf vorbereitet/no-secret belegbar begrenzt, bis echte Zustellung belegt ist."
        ],
        "evidence_urls": [
            {
                "id": "preflight",
                "label": "Delivery-Preflight",
                "url": "https://saferpage.de/integrationen/delivery-credential-preflight-json"
            },
            {
                "id": "runner",
                "label": "Dispatch-Runner",
                "url": "https://saferpage.de/alarme/dispatch-runner-json"
            },
            {
                "id": "runtime_controls",
                "label": "Delivery-Runtime-Controls",
                "url": "https://saferpage.de/evidence/delivery-runtime-controls.json"
            },
            {
                "id": "payload_fixture",
                "label": "Payload-Fixture",
                "url": "https://saferpage.de/alarme/anrufer.info/delivery-json"
            },
            {
                "id": "readiness_smoke",
                "label": "Delivery-Smoke",
                "url": "https://saferpage.de/evidence/alert-delivery-readiness-smoke.json"
            },
            {
                "id": "go_live",
                "label": "Operator-Go-live",
                "url": "https://saferpage.de/betreiber/go-live-json"
            },
            {
                "id": "alerting_digest",
                "label": "Alerting-Digest",
                "url": "https://saferpage.de/sicherheit/alerting-digest-json"
            }
        ],
        "signoff_receipt_template": {
            "schema": "https://saferpage.de/schemas/delivery-signoff-receipt.v1",
            "status": "blocked_until_target_and_approval",
            "summary": "Maschinenlesbares Betreiber-Receipt für Delivery-Go-live: private Zielsystemdaten bleiben privat; öffentlich werden nur Status, Evidence-Refs, Hash-/Dedupe-Referenzen und Stop-Bedingungen.",
            "private_inputs_required": [
                "approver_role_or_team",
                "receiver_target_ref",
                "test_recipient_or_channel_ref",
                "hmac_secret_ref",
                "receiver_test_log_ref",
                "rollback_responsibility_ref",
                "review_or_expiry_date"
            ],
            "public_receipt_fields": [
                "receipt_id",
                "scope_class",
                "approved_at",
                "event_types",
                "receiver_contract_status",
                "dry_run_smoke_url",
                "runner_state_url",
                "go_live_board_url"
            ],
            "required_evidence_urls": [
                "https://saferpage.de/integrationen/delivery-credential-preflight-json",
                "https://saferpage.de/alarme/anrufer.info/delivery-json",
                "https://saferpage.de/alarme/dispatch-runner-json",
                "https://saferpage.de/evidence/delivery-runtime-controls.json",
                "https://saferpage.de/evidence/alert-delivery-readiness-smoke.json",
                "https://saferpage.de/betreiber/go-live-json",
                "https://saferpage.de/sicherheit/alerting-digest-json"
            ],
            "verification_checks": [
                "Receiver akzeptiert Testpayload mit Idempotency-Key.",
                "Receiver prüft HMAC oder dokumentiert bewusstes Nicht-Signing für nicht-generische Zielsysteme.",
                "Dry-run-Smoke ist grün und sent_count bleibt 0.",
                "Public Runner-State enthält keine Ziel-URL, Empfänger, Tokens oder Rohpayloads.",
                "Rollback-/Pause-Verantwortlichkeit und Reviewdatum sind privat dokumentiert.",
                "Go-live-Board zeigt Delivery-Gate erst nach Approval als ready."
            ],
            "no_secret_attestation": [
                "Keine Webhook-, Slack-, Teams-, Jira-, SMTP- oder SendGrid-Ziel-URL öffentlich.",
                "Keine Tokens, API-Keys, HMAC-Secrets oder Authorization-Header öffentlich.",
                "Keine E-Mail-Adressen, Channel-IDs oder Empfängerlisten öffentlich.",
                "Keine privaten Payloads, Receiver-Testlogs oder internen Nachweispositionstexte öffentlich.",
                "Keine Secret-Manager-Pfade oder Environment-Dateien mit echten Werten öffentlich.",
                "Keine Behauptung erfolgreicher Produktivzustellung ohne Runner-Evidence."
            ],
            "activation_conditions": [
                "Mindestens ein natives Zielsystem ist privat konfiguriert.",
                "SAFERPAGE_ALERT_DISPATCH_APPROVED=yes wurde nach Betreiberfreigabe gesetzt.",
                "Receiver-Vertrag ist mit Testpayload abgenommen.",
                "Dry-run- und Readiness-Smoke sind ohne Fehler.",
                "Rollback, Pause Policy und Nachlaufbeobachtung sind dokumentiert."
            ],
            "stop_conditions": [
                "Secret, Ziel-URL oder Empfänger erscheint in einem Public Export.",
                "sent_count steigt ohne Approval-Record.",
                "Receiver erzeugt Duplikate trotz Idempotency-Key.",
                "error_count steigt nach Canary oder produktivem Lauf.",
                "Reviewdatum läuft ab oder Scope wird ohne neues Receipt erweitert."
            ],
            "public_export_policy": "Nur Receipt-ID, Scope-Klasse, Status, Evidence-URLs, Hash-/Dedupe-Referenzen und aggregierte Zähler sind öffentlich; private Inputs bleiben im Betreiber-System."
        }
    },
    "channels": [
        {
            "id": "local_file_sink",
            "label": "Lokaler Audit-File-Sink",
            "purpose": "Interne, secretfreie Zustell-Evidence als JSONL schreiben, ohne externe Ziel-URL, Empfänger oder Payload-Rohdaten zu veröffentlichen.",
            "owner": "IT/Compliance",
            "events": [
                "monitoring.alert"
            ],
            "status": "ready_for_approval",
            "required_env_refs": [],
            "present_required_refs": [],
            "missing_required_refs": [],
            "optional_env_refs": [
                "SAFERPAGE_LOCAL_FILE_SINK_PATH"
            ],
            "present_optional_refs": [],
            "missing_optional_refs": [
                "SAFERPAGE_LOCAL_FILE_SINK_PATH"
            ],
            "runner_support": "native_alert_dispatch_runner",
            "secret_policy": "Nur Env-Referenzen und present/missing werden gezeigt; Werte, Ziel-URLs, Tokens und Empfänger bleiben serverseitig."
        },
        {
            "id": "generic_webhook",
            "label": "Generischer Webhook",
            "purpose": "Alerts, Nachweispositionen, Portfolio-Digests und Scan-Dispatches an eine eigene Orchestrierung senden.",
            "owner": "IT/Platform",
            "events": [
                "monitoring.alert",
                "operator.remediation.ticket_ready",
                "saferpage.portfolio.digest",
                "saferpage.portfolio.scan_dispatch"
            ],
            "status": "missing_configuration",
            "required_env_refs": [
                "SAFERPAGE_WEBHOOK_URL",
                "SAFERPAGE_WEBHOOK_SECRET"
            ],
            "present_required_refs": [],
            "missing_required_refs": [
                "SAFERPAGE_WEBHOOK_URL",
                "SAFERPAGE_WEBHOOK_SECRET"
            ],
            "optional_env_refs": [
                "SAFERPAGE_OPERATOR_WEBHOOK_SECRET"
            ],
            "present_optional_refs": [],
            "missing_optional_refs": [
                "SAFERPAGE_OPERATOR_WEBHOOK_SECRET"
            ],
            "runner_support": "native_alert_dispatch_runner",
            "secret_policy": "Nur Env-Referenzen und present/missing werden gezeigt; Werte, Ziel-URLs, Tokens und Empfänger bleiben serverseitig."
        },
        {
            "id": "slack",
            "label": "Slack",
            "purpose": "PrivacyOps- und Security-Kanaele mit priorisierten Alerts, Verantwortlichkeiten und Support-Ziel-Kontext informieren.",
            "owner": "PrivacyOps",
            "events": [
                "monitoring.alert",
                "operator.remediation.ticket_ready",
                "saferpage.portfolio.scan_dispatch"
            ],
            "status": "missing_configuration",
            "required_env_refs": [
                "SAFERPAGE_SLACK_WEBHOOK_URL"
            ],
            "present_required_refs": [],
            "missing_required_refs": [
                "SAFERPAGE_SLACK_WEBHOOK_URL"
            ],
            "optional_env_refs": [
                "SAFERPAGE_SLACK_CHANNEL"
            ],
            "present_optional_refs": [],
            "missing_optional_refs": [
                "SAFERPAGE_SLACK_CHANNEL"
            ],
            "runner_support": "native_alert_dispatch_runner",
            "secret_policy": "Nur Env-Referenzen und present/missing werden gezeigt; Werte, Ziel-URLs, Tokens und Empfänger bleiben serverseitig."
        },
        {
            "id": "teams",
            "label": "Microsoft Teams",
            "purpose": "Adaptive Cards für Betreiber-, Datenschutz- oder Security-Teams vorbereiten.",
            "owner": "Website-Betrieb",
            "events": [
                "monitoring.alert",
                "operator.remediation.ticket_ready",
                "saferpage.portfolio.scan_dispatch"
            ],
            "status": "missing_configuration",
            "required_env_refs": [
                "SAFERPAGE_TEAMS_WEBHOOK_URL"
            ],
            "present_required_refs": [],
            "missing_required_refs": [
                "SAFERPAGE_TEAMS_WEBHOOK_URL"
            ],
            "optional_env_refs": [],
            "present_optional_refs": [],
            "missing_optional_refs": [],
            "runner_support": "native_alert_dispatch_runner",
            "secret_policy": "Nur Env-Referenzen und present/missing werden gezeigt; Werte, Ziel-URLs, Tokens und Empfänger bleiben serverseitig."
        },
        {
            "id": "jira",
            "label": "Jira",
            "purpose": "Nachweis- und Alert-Aufgaben mit External-ID, Labels, Prioritaet und Akzeptanzkriterien anlegen.",
            "owner": "Projekt-/Nachweis-Verantwortung",
            "events": [
                "operator.remediation.ticket_ready",
                "monitoring.alert"
            ],
            "status": "missing_configuration",
            "required_env_refs": [
                "SAFERPAGE_JIRA_BASE_URL",
                "SAFERPAGE_JIRA_EMAIL",
                "SAFERPAGE_JIRA_API_TOKEN"
            ],
            "present_required_refs": [],
            "missing_required_refs": [
                "SAFERPAGE_JIRA_BASE_URL",
                "SAFERPAGE_JIRA_EMAIL",
                "SAFERPAGE_JIRA_API_TOKEN"
            ],
            "optional_env_refs": [],
            "present_optional_refs": [],
            "missing_optional_refs": [],
            "runner_support": "delivery_payload_ready_in_exports",
            "secret_policy": "Nur Env-Referenzen und present/missing werden gezeigt; Werte, Ziel-URLs, Tokens und Empfänger bleiben serverseitig."
        },
        {
            "id": "email_smtp",
            "label": "E-Mail/SMTP",
            "purpose": "Portfolio-Digests und Eskalationen an Management, Datenschutz und Webbetrieb zustellen.",
            "owner": "Programm-Verantwortung",
            "events": [
                "saferpage.portfolio.digest",
                "monitoring.alert"
            ],
            "status": "missing_configuration",
            "required_env_refs": [
                "SAFERPAGE_MAIL_FROM",
                "SAFERPAGE_MAIL_TO"
            ],
            "present_required_refs": [],
            "missing_required_refs": [
                "SAFERPAGE_MAIL_FROM",
                "SAFERPAGE_MAIL_TO"
            ],
            "optional_env_refs": [
                "SAFERPAGE_SMTP_HOST",
                "SAFERPAGE_SMTP_USER",
                "SAFERPAGE_SMTP_PASSWORD"
            ],
            "present_optional_refs": [],
            "missing_optional_refs": [
                "SAFERPAGE_SMTP_HOST",
                "SAFERPAGE_SMTP_USER",
                "SAFERPAGE_SMTP_PASSWORD"
            ],
            "runner_support": "delivery_payload_ready_in_exports",
            "secret_policy": "Nur Env-Referenzen und present/missing werden gezeigt; Werte, Ziel-URLs, Tokens und Empfänger bleiben serverseitig."
        },
        {
            "id": "sendgrid",
            "label": "SendGrid",
            "purpose": "Wiederkehrende Portfolio-Digests über einen Mail-Provider ausliefern.",
            "owner": "IT/Platform",
            "events": [
                "saferpage.portfolio.digest"
            ],
            "status": "missing_configuration",
            "required_env_refs": [
                "SENDGRID_API_KEY",
                "SAFERPAGE_MAIL_FROM",
                "SAFERPAGE_MAIL_TO"
            ],
            "present_required_refs": [],
            "missing_required_refs": [
                "SENDGRID_API_KEY",
                "SAFERPAGE_MAIL_FROM",
                "SAFERPAGE_MAIL_TO"
            ],
            "optional_env_refs": [],
            "present_optional_refs": [],
            "missing_optional_refs": [],
            "runner_support": "delivery_payload_ready_in_exports",
            "secret_policy": "Nur Env-Referenzen und present/missing werden gezeigt; Werte, Ziel-URLs, Tokens und Empfänger bleiben serverseitig."
        }
    ],
    "readiness_gates": [
        {
            "id": "dispatch_approval",
            "label": "Produktive Alert-Zustellung freigegeben",
            "status": "blocked",
            "evidence": "SAFERPAGE_ALERT_DISPATCH_APPROVED ist nicht aktiv; Runner bleibt Dry-run/Outbox.",
            "action": "Freigabe erst nach Zielsystem-Dry-run, Empfängerfreigabe, Datenschutz-/Security-Abnahme und Monitoring setzen."
        },
        {
            "id": "native_target_available",
            "label": "Mindestens ein nativ sendbares Zielsystem konfiguriert",
            "status": "passed",
            "evidence": "1 native(s) Zielsystem(e) sind voll konfiguriert: Webhook, Slack oder Teams.",
            "action": "Mindestens SAFERPAGE_WEBHOOK_URL plus Secret oder SAFERPAGE_SLACK_WEBHOOK_URL/SAFERPAGE_TEAMS_WEBHOOK_URL serverseitig setzen."
        },
        {
            "id": "signed_delivery",
            "label": "HMAC-Signatur für Betreiber-Webhook verfügbar",
            "status": "warning",
            "evidence": "Kein HMAC-Secret gesetzt; generische Webhooks können nicht signiert werden.",
            "action": "HMAC-Secret im Secret Manager oder in /etc/saferpage/alert-dispatch.env setzen."
        },
        {
            "id": "dispatch_runner_state",
            "label": "Alert-Dispatch-Runner-State erreichbar",
            "status": "passed",
            "evidence": "State alert_dispatch_runner_state.json ist lesbar; sent=0, deliverable=0, errors=50.",
            "action": "Timer und Runner-State unter /alarme/dispatch-runner-json prüfen."
        },
        {
            "id": "dry_run_outbox",
            "label": "Dry-run/Outbox als Testnachweis vorhanden",
            "status": "warning",
            "evidence": "0 Outbox-Einträge im letzten Runner-State.",
            "action": "Mit Beispiel-Domain einen Dry-run ausführen und Body-SHA-256, Idempotency-Key und Zielsystemstatus prüfen."
        },
        {
            "id": "no_secret_export",
            "label": "No-Secret-Export",
            "status": "passed",
            "evidence": "Dieser Preflight zeigt nur Env-Referenzen und present/missing-Status, keine Werte, Ziel-URLs, Empfänger, Tokens oder API-Keys.",
            "action": "Neue Felder vor Veröffentlichung auf Secrets, URLs, Empfänger und Rohpayloads prüfen."
        },
        {
            "id": "runtime_controls_manifest",
            "label": "Runtime-Control-Manifest vorhanden",
            "status": "passed",
            "evidence": "8 Delivery-Runtime-Kontrolle(n) im Evidence-Manifest dokumentiert.",
            "action": "Manifest und Smoke nach Runner-Änderungen erneut prüfen."
        },
        {
            "id": "idempotency_contract",
            "label": "Idempotency- und Retry-Vertrag vorhanden",
            "status": "passed",
            "evidence": "Delivery-Payloads und Runner-State nutzen Idempotency-Key, Body-SHA-256, Status und Stop-Bedingungen.",
            "action": "Zielsysteme müssen Idempotency-Key als externe ID oder Dedupe-Key verwenden."
        },
        {
            "id": "provider_matrix_complete",
            "label": "Zielsystem-Matrix abgedeckt",
            "status": "passed",
            "evidence": "1 ready, 0 teilweise, 7 Zielsystemtypen im Preflight.",
            "action": "Jira/E-Mail/SendGrid produktiv erst mit Connector-Code oder externem Orchestrator aktivieren."
        }
    ],
    "dispatch_runner_snapshot": {
        "available": true,
        "state_path": "alert_dispatch_runner_state.json",
        "started_at": "2026-08-03T02:16:37+00:00",
        "finished_at": "2026-08-03T02:16:38+00:00",
        "execute_ready": true,
        "dispatch_approved": false,
        "sent_count": 0,
        "deliverable_count": 0,
        "blocked_count": 0,
        "error_count": 50,
        "run_policy": {
            "external_send_attempt_count": 0,
            "local_file_sink_attempt_count": 0,
            "dry_run_queued_count": 0,
            "no_secret_export": true
        },
        "outbox_preview": []
    },
    "operations_runbook": {
        "purpose": "Produktive Betreiber-Zielsysteme kontrolliert aktivieren, ohne Secret-Werte oder Empfänger im öffentlichen Nachweis offenzulegen.",
        "preflight_sequence": [
            "Zielsystem-Verantwortlichkeit, Empfänger, Kanaele und Zwecke festlegen.",
            "Secrets und Ziel-URLs in /etc/saferpage/alert-dispatch.env oder Secret Manager setzen.",
            "Ohne SAFERPAGE_ALERT_DISPATCH_APPROVED einen Dry-run ausführen und /alarme/dispatch-runner-json prüfen.",
            "HMAC-Signatur, Idempotency-Key, Body-SHA-256 und Zielsystem-Dedupe im Testempfänger verifizieren.",
            "SAFERPAGE_ALERT_DISPATCH_APPROVED=yes erst nach dokumentierter Betreiberfreigabe setzen.",
            "Nach erstem produktiven Lauf sent_count, error_count und Zielsystem-Logs prüfen."
        ],
        "systemd_checks": [
            {
                "label": "Environment-Datei",
                "command": "systemctl cat saferpage-alert-dispatch.service --no-pager",
                "expected": "EnvironmentFile=-/etc/saferpage/alert-dispatch.env ist gesetzt; Secrets stehen nicht in der Unit."
            },
            {
                "label": "Timer",
                "command": "systemctl list-timers saferpage-alert-dispatch.timer --no-pager",
                "expected": "Täglicher Timer ist sichtbar und Persistent=true."
            },
            {
                "label": "Runner-State",
                "command": "curl -fsS https://saferpage.de/alarme/dispatch-runner-json",
                "expected": "channels/outbox zeigen nur Env-Refs, Hashes und Status."
            },
            {
                "label": "Preflight",
                "command": "curl -fsS https://saferpage.de/integrationen/delivery-credential-preflight-json",
                "expected": "readiness_gates zeigen approval, target availability, signing und no-secret export."
            },
            {
                "label": "Isolierter Dry-run-Smoke",
                "command": "scripts/run-alert-dispatch-dry-run-smoke.sh",
                "expected": "Schreibt nur temporaere State-Dateien, sent_count=0 und external_send_attempt_count=0."
            }
        ],
        "stop_conditions": [
            "sent_count größer 0 ohne SAFERPAGE_ALERT_DISPATCH_APPROVED=yes und dokumentierte Betreiberfreigabe.",
            "Öffentliche Exports enthalten Ziel-URLs, API-Keys, Tokens, E-Mail-Empfänger, Slack-/Teams-Webhook-URLs oder private Payloads.",
            "Zielsystem meldet Duplikate trotz Idempotency-Key.",
            "error_count größer 0 oder wiederholte HTTP-/TLS-/Rate-Limit-Fehler.",
            "Empfänger oder Kanalzweck wurden ohne Datenschutz-/Security-Abnahme geändert."
        ],
        "public_contract": [
            "Preflight sendet nichts und testet keine externen Zielsysteme.",
            "Produktiver Versand braucht --execute-ready, SAFERPAGE_ALERT_DISPATCH_APPROVED=yes und mindestens ein konfiguriertes natives Ziel.",
            "Jira, E-Mail und SendGrid sind als Zielsystem-Gates sichtbar; produktive Zustellung braucht Connector oder externen Orchestrator.",
            "Alle öffentlichen Nachweise zeigen nur Referenznamen, Status, Hashes und Idempotency-Keys."
        ]
    },
    "links": {
        "html": "https://saferpage.de/integrationen/delivery-credential-preflight",
        "json": "https://saferpage.de/integrationen/delivery-credential-preflight-json",
        "csv": "https://saferpage.de/integrationen/delivery-credential-preflight-csv",
        "markdown": "https://saferpage.de/integrationen/delivery-credential-preflight-md",
        "integration_setup": "https://saferpage.de/integrationen/setup-json",
        "dispatch_runner": "https://saferpage.de/alarme/dispatch-runner-json",
        "alert_delivery_example": "https://saferpage.de/alarme/anrufer.info/delivery-json",
        "comparison": "https://saferpage.de/vergleich/features-json",
        "security_feed_preflight": "https://saferpage.de/sicherheit/feed-credential-preflight-json",
        "runtime_controls": "https://saferpage.de/evidence/delivery-runtime-controls.json",
        "readiness_smoke": "https://saferpage.de/evidence/alert-delivery-readiness-smoke.json",
        "approval_template_env": "https://saferpage.de/integrationen/delivery-approval-template.env"
    },
    "disclaimer": "Dieser Preflight zeigt nur Credential-Referenzen, Gate-Status und Betriebsnachweise. Er veröffentlicht keine Webhook-URLs, API-Keys, Tokens, E-Mail-Empfänger, Slack-/Teams-Ziel-URLs oder privaten Rohpayloads."
}
