{
    "schema": "https://saferpage.de/schemas/dach-crawler-readiness-smoke.v1",
    "generated_at": "2026-06-14T00:15:40+00:00",
    "ok": true,
    "summary": "No-Secret-Smoke fuer DACH-Crawler-Operations, Timer-Runner, User-Agent, Seedquelle, Performance-Grenzen, Recent-Reportlinks, Public-Test-Index-Qualitaetskontrollen und Screenshot-Preview-Coverage.",
    "source_ops_schema": "https://saferpage.de/schemas/dach-crawler-operations.v1",
    "source_timer_schema": "https://saferpage.de/schemas/dach-crawler-timer-runner.v1",
    "source_ops_url": "https://saferpage.de/crawler/ops-json",
    "source_timer_url": "https://saferpage.de/crawler/timer-runner-json",
    "metrics": {
        "target_count": 11,
        "http_passed_count": 11,
        "http_failed_count": 0,
        "target_duration_measured_count": 11,
        "target_duration_max_ms": 2416,
        "target_duration_p95_ms": 2416,
        "target_duration_budget_ms": 8000,
        "target_duration_slow_count": 0,
        "check_count": 19,
        "passed_check_count": 19,
        "warning_check_count": 0,
        "failed_check_count": 0,
        "crawler_available": 1,
        "timer_available": 1,
        "dach_check_count": 1249,
        "queue_count": 1078,
        "seed_file_host_count": 86,
        "recent_report_count": 36,
        "test_index_visible_count": 200,
        "test_index_total_public_checks": 1433,
        "test_index_preview_coverage_percent": 99.9,
        "test_index_preview_missing_count": 2,
        "test_index_preview_actionable_missing_count": 0,
        "test_index_preview_unreachable_missing_count": 2,
        "test_index_preview_renderer_failed_missing_count": 2,
        "test_index_preview_legacy_size_count": 0,
        "test_index_preview_contract_width": 160,
        "test_index_preview_contract_height": 150,
        "test_index_preview_contract_fit": "contain",
        "test_index_preview_contract_source_capture": "full_page",
        "test_index_preview_contract_capture_version": "contain-v4-viewport-transparency-160x150",
        "test_index_canonical_short_url_count": 200,
        "test_index_direct_report_link_count": 200,
        "test_index_preview_ready_item_count": 199,
        "test_index_preview_contract_item_count": 200,
        "test_index_hash_report_link_count": 0,
        "test_index_php_report_link_count": 0,
        "test_index_crawler_german_count": 1249,
        "test_index_quality_control_count": 11,
        "test_index_quality_control_failed_count": 0,
        "test_index_quality_control_warning_count": 0,
        "test_index_quality_boundary_count": 11,
        "test_index_quality_direct_link_count": 200,
        "test_index_quality_preview_contract_count": 200,
        "test_index_quality_operator_link_count": 200,
        "test_index_quality_discovery_link_count": 25,
        "test_index_discovery_manifest_available": 1,
        "test_index_discovery_manifest_linked_check_count": 1433,
        "test_index_discovery_manifest_letter_url_count": 25,
        "test_index_discovery_manifest_letter_page_url_count": 26,
        "test_index_discovery_manifest_test_sitemap_url_count": 26,
        "test_index_discovery_manifest_latest_page_count": 8,
        "test_index_discovery_manifest_latest_page_url_count": 8,
        "test_index_discovery_manifest_export_format_count": 4,
        "test_index_public_summary_raw_hard_warning_count": 199,
        "test_index_public_summary_hard_warning_count": 0,
        "test_index_public_summary_reframed_count": 200,
        "test_index_public_summary_signal_wording_count": 200,
        "preview_coverage_percent": 99.9,
        "preview_missing_count": 2,
        "preview_actionable_missing_count": 0,
        "preview_unreachable_missing_count": 2,
        "preview_renderer_failed_missing_count": 2,
        "error_rate_percent": 2.05,
        "max_hosts_per_run": 8,
        "concurrency": 2,
        "timeout_seconds": 90,
        "timer_gate_count": 11,
        "timer_passed_gate_count": 11,
        "timer_warning_gate_count": 0,
        "timer_blocked_gate_count": 0,
        "preview_backfill_target_count": 0,
        "preview_backfill_processed_count": 0,
        "preview_backfill_ok_count": 0,
        "preview_backfill_skipped_count": 0,
        "preview_backfill_failed_count": 0,
        "preview_backfill_remaining_estimate": 0,
        "preview_backfill_max_per_run": 24,
        "preview_backfill_concurrency": 2
    },
    "checks": [
        {
            "id": "public_routes_http_200",
            "label": "Crawler-Routen öffentlich erreichbar",
            "status": "passed",
            "evidence": "11/11 Route(s) liefern HTTP 200.",
            "operator_action": "Crawler-Evidence bleibt öffentlich verlinkt."
        },
        {
            "id": "public_routes_response_time_budget",
            "label": "Crawler-Routen bleiben unter Betreiber-tauglichem Response-Time-Budget",
            "status": "passed",
            "evidence": "targets=11, timed=11, max_ms=2416, p95_ms=2416, budget_ms=8000, slow=0, slow_ids=.",
            "operator_action": "Langsame Crawler-/Testindex-Routen vor hoeherer Crawl-Frequenz optimieren; Budget nicht durch groessere Batches umgehen."
        },
        {
            "id": "crawler_ops_available",
            "label": "Crawler-Ops-State verfügbar",
            "status": "passed",
            "evidence": "available=yes, health=operational, dach_checks=1249.",
            "operator_action": "API-Service, Port 8092 und Runner-State prüfen, wenn unavailable."
        },
        {
            "id": "timer_runner_gates_green",
            "label": "Timer-Runner-Gates ohne Blocker",
            "status": "passed",
            "evidence": "11/11 Gate(s) passed, warnings=0, blocked=0.",
            "operator_action": "Warnungen vor Skalierung prüfen."
        },
        {
            "id": "versioned_seed_visible",
            "label": "Versionierte DACH-Seedquelle sichtbar",
            "status": "passed",
            "evidence": "seed_file=config/dach-seed-domains.txt, seed_file_host_count=86.",
            "operator_action": "Timer mit config/dach-seed-domains.txt ausführen und Runner-State erneut prüfen."
        },
        {
            "id": "public_user_agent_policy",
            "label": "User-Agent mit Betreiberlink und Beispielreports",
            "status": "passed",
            "evidence": "SaferPageCrawler/0.3 (+https://saferpage.de/bot; schedules passive DACH website checks; report examples: https://saferpage.de/tests)",
            "operator_action": "User-Agent muss /bot und /tests nennen und in Crawler-Exports sichtbar bleiben."
        },
        {
            "id": "bounded_performance_limits",
            "label": "Batch, Parallelität und Timeout begrenzt",
            "status": "passed",
            "evidence": "max_hosts_per_run=8, concurrency=2, timeout_seconds=90.",
            "operator_action": "Grenzen nur nach Last-, Fehler-, robots.txt- und Screenshot-Worker-Prüfung erhöhen."
        },
        {
            "id": "recent_reports_linked",
            "label": "Zuletzt geprüfte Reports direkt verlinkt",
            "status": "passed",
            "evidence": "36 Reportlink(s) im Timer-Runner-Export.",
            "operator_action": "Recent-Checks, /tests und kanonische Kurz-URLs prüfen, wenn keine Reports erscheinen."
        },
        {
            "id": "public_test_index_metrics_ready",
            "label": "Public-Test-Index liefert Recent-, Preview- und Crawler-Metriken",
            "status": "passed",
            "evidence": "visible_count=200, total_public_checks=1433, preview_coverage_percent=99.9, preview_missing_count=2, preview_actionable_missing_count=0, preview_unreachable_missing_count=2, preview_renderer_failed_missing_count=2, preview_legacy_size_count=0, crawler_german_count=1249.",
            "operator_action": "tests-json muss einen metrics-Block mit sichtbaren Reports, Gesamtzahl, Preview-Coverage, Backfill-Missing, Unreachable-Missing und Crawler-Zählern liefern."
        },
        {
            "id": "public_test_index_preview_contract",
            "label": "Public-Test-Index erzwingt 160x150-Full-Page-Preview-Vertrag",
            "status": "passed",
            "evidence": "contract=160x150, fit=contain, source_capture=full_page, capture_version=contain-v4-viewport-transparency-160x150, legacy_size_count=0.",
            "operator_action": "Alte 100x100- oder Crop-Artefakte per Backfill ersetzen; Worker/Scanner/Index müssen denselben 160x150-contain-Vertrag melden."
        },
        {
            "id": "public_test_index_short_url_contract",
            "label": "Public-Test-Index liefert direkte kanonische Kurzlinks",
            "status": "passed",
            "evidence": "visible_count=200, canonical_short_url_count=200, direct_report_link_count=200, hash_report_link_count=0, php_report_link_count=0, first_report_url=https://saferpage.de/aphasie-tage.de.",
            "operator_action": "Alle Index-Items müssen direkt auf https://saferpage.de/{domain} zeigen; keine Platzhalter, keine SaferPage-.php-Links und kein abweichender Canonical-Link."
        },
        {
            "id": "public_test_index_quality_controls",
            "label": "Public-Test-Index erklärt Link-, Preview-, Betreiber- und Bewertungsgrenzen",
            "status": "passed",
            "evidence": "quality_controls=11, failed=0, warnings=0, boundaries=11, direct_links=200, preview_contracts=200, operator_links=200, discovery_links=25, missing_ids=.",
            "operator_action": "tests-json muss index_quality_controls fuer Kurzlinks, Preview, A-Z/Sitemap, Crawler-Identitaet, Betreiber-Fixpfad, Summary-Wording, No-Secret-Grenze und automatische Bewertungsgrenzen liefern."
        },
        {
            "id": "public_test_index_discovery_manifest",
            "label": "Public-Test-Index exportiert ein vollstaendiges A-Z-/Sitemap-Discovery-Manifest",
            "status": "passed",
            "evidence": "available=1, total_public_checks=1433, linked_check_count=1433, latest_pages=8/8, letter_urls=25, letter_page_urls=26, sitemap_urls=26, export_formats=4.",
            "operator_action": "tests-json muss Neueste-Pagination, A-Z-HTML/JSON/CSV/Markdown, Seiten-Pagination und sitemap-tests-*.xml als Discovery-Manifest exportieren."
        },
        {
            "id": "public_test_index_summary_wording",
            "label": "Public-Test-Index formuliert Kurztexte als Datenschutz-Signale",
            "status": "passed",
            "evidence": "visible_count=200, raw_hard_warning_count=199, public_hard_warning_count=0, reframed_count=200, signal_wording_count=200.",
            "operator_action": "Index-Summaries duerfen keine harten Nutzungswarnungen ausgeben; sie muessen Datenschutz-Signale und Bewertungsgrenzen ausdruecken."
        },
        {
            "id": "public_test_index_item_preview_fields",
            "label": "Public-Test-Index exportiert Preview-Felder direkt am Item",
            "status": "passed",
            "evidence": "preview_ready_item_count=199, preview_contract_item_count=200, first_preview_image=https://saferpage.de/cache/screenshots/aphasie-tage.de-160x150-65839a61b7715defc5.png, first_preview_contract=160x150/contain/full_page/contain-v4-viewport-transparency-160x150.",
            "operator_action": "tests-json muss preview_width, preview_height, preview_fit, preview_source_capture und preview_capture_version direkt am Item liefern; fehlende preview_image-Werte muessen als actionable oder unreachable ausgewiesen sein."
        },
        {
            "id": "preview_coverage_ready",
            "label": "Screenshot-Preview-Coverage produktreif",
            "status": "passed",
            "evidence": "preview_coverage_percent=99.9, preview_missing_count=2, preview_actionable_missing_count=0, preview_unreachable_missing_count=2, preview_renderer_failed_missing_count=2, test_index_actionable_missing_count=0, test_index_unreachable_missing_count=2, test_index_renderer_failed_missing_count=2, test_index_legacy_size_count=0.",
            "operator_action": "Fehlende erreichbare 160x150-Seitenvorschauen per Screenshot-Backfill nachziehen; nicht erreichbare Zielserver getrennt beobachten."
        },
        {
            "id": "legacy_preview_backfill_operationalized",
            "label": "Legacy-Preview-Backfill ist begrenzt operationalisiert",
            "status": "passed",
            "evidence": "target_count=0, processed_count=0, ok_count=0, skipped_count=0, failed_count=0, remaining_estimate=0, actionable_missing_count=0, legacy_size_count=0, max_per_run=24, concurrency=2.",
            "operator_action": "Timer laufen lassen oder kleinen manuellen Backfill ausführen, bis erreichbare Missing- und Legacy-Zähler 0 erreichen; nicht erreichbare Zielserver getrennt ausweisen."
        },
        {
            "id": "error_and_queue_stop_guards",
            "label": "Fehlerquote und Queue-Druck unter Stop-Schwellen",
            "status": "passed",
            "evidence": "error_rate_percent=2.05, queue_count=1078.",
            "operator_action": "Bei Fehlerquote >20% oder Queue >5000 nicht skalieren; Ursachen prüfen."
        },
        {
            "id": "no_secret_publication",
            "label": "Crawler-Smoke ohne Secrets und Besucherlogs",
            "status": "passed",
            "evidence": "Keine Forbidden-Pattern-Treffer in Ops/Timer-JSON.",
            "operator_action": "Neue Felder weiter auf Rohpayloads, IPs, Tokens und Besucherlogs prüfen."
        }
    ],
    "failed_checks": [],
    "warning_checks": [],
    "targets": [
        {
            "id": "crawler_html",
            "label": "Crawler Operations HTML",
            "url": "https://saferpage.de/crawler",
            "path": "/crawler",
            "expected_http_status": 200,
            "actual_http_status": 200,
            "ok": true,
            "duration_ms": 1279,
            "started_at": "2026-06-14T00:15:31Z",
            "finished_at": "2026-06-14T00:15:32Z"
        },
        {
            "id": "crawler_ops_json",
            "label": "Crawler Operations JSON",
            "url": "https://saferpage.de/crawler/ops-json",
            "path": "/crawler/ops-json",
            "expected_http_status": 200,
            "actual_http_status": 200,
            "ok": true,
            "duration_ms": 1355,
            "started_at": "2026-06-14T00:15:32Z",
            "finished_at": "2026-06-14T00:15:33Z"
        },
        {
            "id": "crawler_ops_csv",
            "label": "Crawler Operations CSV",
            "url": "https://saferpage.de/crawler/ops-csv",
            "path": "/crawler/ops-csv",
            "expected_http_status": 200,
            "actual_http_status": 200,
            "ok": true,
            "duration_ms": 1304,
            "started_at": "2026-06-14T00:15:33Z",
            "finished_at": "2026-06-14T00:15:35Z"
        },
        {
            "id": "crawler_ops_markdown",
            "label": "Crawler Operations Markdown",
            "url": "https://saferpage.de/crawler/ops-md",
            "path": "/crawler/ops-md",
            "expected_http_status": 200,
            "actual_http_status": 200,
            "ok": true,
            "duration_ms": 1287,
            "started_at": "2026-06-14T00:15:35Z",
            "finished_at": "2026-06-14T00:15:36Z"
        },
        {
            "id": "crawler_timer_html",
            "label": "Crawler Timer Runner HTML",
            "url": "https://saferpage.de/crawler/timer-runner",
            "path": "/crawler/timer-runner",
            "expected_http_status": 200,
            "actual_http_status": 200,
            "ok": true,
            "duration_ms": 380,
            "started_at": "2026-06-14T00:15:36Z",
            "finished_at": "2026-06-14T00:15:37Z"
        },
        {
            "id": "crawler_timer_json",
            "label": "Crawler Timer Runner JSON",
            "url": "https://saferpage.de/crawler/timer-runner-json",
            "path": "/crawler/timer-runner-json",
            "expected_http_status": 200,
            "actual_http_status": 200,
            "ok": true,
            "duration_ms": 379,
            "started_at": "2026-06-14T00:15:37Z",
            "finished_at": "2026-06-14T00:15:37Z"
        },
        {
            "id": "crawler_timer_csv",
            "label": "Crawler Timer Runner CSV",
            "url": "https://saferpage.de/crawler/timer-runner-csv",
            "path": "/crawler/timer-runner-csv",
            "expected_http_status": 200,
            "actual_http_status": 200,
            "ok": true,
            "duration_ms": 365,
            "started_at": "2026-06-14T00:15:37Z",
            "finished_at": "2026-06-14T00:15:37Z"
        },
        {
            "id": "crawler_timer_markdown",
            "label": "Crawler Timer Runner Markdown",
            "url": "https://saferpage.de/crawler/timer-runner-md",
            "path": "/crawler/timer-runner-md",
            "expected_http_status": 200,
            "actual_http_status": 200,
            "ok": true,
            "duration_ms": 358,
            "started_at": "2026-06-14T00:15:37Z",
            "finished_at": "2026-06-14T00:15:38Z"
        },
        {
            "id": "bot_policy",
            "label": "Bot Transparency",
            "url": "https://saferpage.de/bot",
            "path": "/bot",
            "expected_http_status": 200,
            "actual_http_status": 200,
            "ok": true,
            "duration_ms": 33,
            "started_at": "2026-06-14T00:15:38Z",
            "finished_at": "2026-06-14T00:15:38Z"
        },
        {
            "id": "tests_json",
            "label": "Public Test Index JSON",
            "url": "https://saferpage.de/tests-json",
            "path": "/tests-json",
            "expected_http_status": 200,
            "actual_http_status": 200,
            "ok": true,
            "duration_ms": 2416,
            "started_at": "2026-06-14T00:15:38Z",
            "finished_at": "2026-06-14T00:15:40Z"
        },
        {
            "id": "preview_backfill_evidence",
            "label": "Preview Backfill Evidence",
            "url": "https://saferpage.de/evidence/preview-backfill-run.json",
            "path": "/evidence/preview-backfill-run.json",
            "expected_http_status": 200,
            "actual_http_status": 200,
            "ok": true,
            "duration_ms": 20,
            "started_at": "2026-06-14T00:15:40Z",
            "finished_at": "2026-06-14T00:15:40Z"
        }
    ],
    "failed_targets": [],
    "recent_report_links": [
        {
            "host": "aphasie-tage.de",
            "score": 0,
            "checked_at": "2026-06-14 02:11:37.910768+02",
            "report_url": "https://saferpage.de/aphasie-tage.de",
            "summary": "Nur mit Vorsicht nutzen"
        },
        {
            "host": "autopreisservice.de",
            "score": 0,
            "checked_at": "2026-06-14 02:05:14.970364+02",
            "report_url": "https://saferpage.de/autopreisservice.de",
            "summary": "Nur mit Vorsicht nutzen"
        },
        {
            "host": "enit.at",
            "score": 0,
            "checked_at": "2026-06-14 01:45:19.003928+02",
            "report_url": "https://saferpage.de/enit.at",
            "summary": "Nur mit Vorsicht nutzen"
        },
        {
            "host": "aphasie-unterfranken.de",
            "score": 0,
            "checked_at": "2026-06-14 01:40:40.25886+02",
            "report_url": "https://saferpage.de/aphasie-unterfranken.de",
            "summary": "Nur mit Vorsicht nutzen"
        },
        {
            "host": "alexanderfillbrandt.de",
            "score": 0,
            "checked_at": "2026-06-14 01:40:24.751836+02",
            "report_url": "https://saferpage.de/alexanderfillbrandt.de",
            "summary": "Nur mit Vorsicht nutzen"
        },
        {
            "host": "blog.birte-oldenburg.de",
            "score": 0,
            "checked_at": "2026-06-14 01:40:11.567597+02",
            "report_url": "https://saferpage.de/blog.birte-oldenburg.de",
            "summary": "Nur mit Vorsicht nutzen"
        },
        {
            "host": "blumenhaus-eder.de",
            "score": 0,
            "checked_at": "2026-06-14 01:40:06.287043+02",
            "report_url": "https://saferpage.de/blumenhaus-eder.de",
            "summary": "Nur mit Vorsicht nutzen"
        },
        {
            "host": "blog.zuckerhunde.de",
            "score": 0,
            "checked_at": "2026-06-14 01:39:55.164087+02",
            "report_url": "https://saferpage.de/blog.zuckerhunde.de",
            "summary": "Nur mit Vorsicht nutzen"
        },
        {
            "host": "datatime.de",
            "score": 0,
            "checked_at": "2026-06-14 01:38:57.277329+02",
            "report_url": "https://saferpage.de/datatime.de",
            "summary": "Nur mit Vorsicht nutzen"
        },
        {
            "host": "biotop-birsfelden.ch",
            "score": 0,
            "checked_at": "2026-06-14 01:28:31.694211+02",
            "report_url": "https://saferpage.de/biotop-birsfelden.ch",
            "summary": "Nur mit Vorsicht nutzen"
        },
        {
            "host": "blog.knarf.de",
            "score": 0,
            "checked_at": "2026-06-14 01:09:34.273648+02",
            "report_url": "https://saferpage.de/blog.knarf.de",
            "summary": "Nur mit Vorsicht nutzen"
        },
        {
            "host": "crochet-with-love.blogspot.com",
            "score": 0,
            "checked_at": "2026-06-14 01:03:24.783282+02",
            "report_url": "https://saferpage.de/crochet-with-love.blogspot.com",
            "summary": "Nur mit Vorsicht nutzen"
        }
    ],
    "no_secret_policy": {
        "contains_secrets": false,
        "contains_private_target_urls": false,
        "contains_recipients": false,
        "contains_private_documents": false,
        "contains_visitor_logs": false,
        "forbidden_pattern_hits": []
    },
    "preview_backfill_evidence": {
        "schema": "https://saferpage.de/schemas/preview-backfill-run.v1",
        "generated_at": "2026-06-13T23:48:53+00:00",
        "dry_run": false,
        "metrics": {
            "total_public_checks": 1431,
            "reported_legacy_size_count": 0,
            "discovered_legacy_host_count": 0,
            "letter_pages_checked": 25,
            "target_count": 0,
            "processed_count": 0,
            "ok_count": 0,
            "skipped_count": 0,
            "failed_count": 0,
            "remaining_after_selected_batch_estimate": 0,
            "max_per_run": 24,
            "concurrency": 2
        },
        "skipped": [],
        "failures": []
    },
    "claim_boundary": "Dieser Smoke startet keinen Crawl, erhöht keine Parallelität, ruft keine privaten Zielsysteme ab und veröffentlicht keine Besucherlogs. Er belegt nur öffentliche Betriebs- und Readiness-Signale."
}
