"""POST /scan-matrix — browser-matrix stage-1 endpoint. Runs the existing consent_scanner once per browser profile and returns the aggregated robustness-score per browser plus a worst-of/best-of summary. Kept in its own module so main.py stays under the 500-LOC cap. Stage 1.b (erledigt): `run_consent_test` nimmt jetzt einen `browser_profile` kwarg → echte Engine-Diversität (Firefox/Gecko, WebKit/Safari, Blink inkl. Chrome-/Edge-Channel + Brave). `_scanner_run` reicht das Profil durch. """ from __future__ import annotations import logging from datetime import datetime, timezone from fastapi import APIRouter from pydantic import BaseModel from services.consent_scanner import run_consent_test from services.multi_browser_scanner import run_matrix from services.scan_matrix_summary import matrix_scan_dict logger = logging.getLogger(__name__) router = APIRouter() class MatrixScanRequest(BaseModel): url: str timeout_per_phase: int = 10 categories: list[str] = [] # Resolved against browser_profiles.resolve_profiles. None or # empty list → default 4 profiles (chromium/firefox/webkit/iphone). browser_profiles: list[str] | None = None async def _scanner_run(url: str, browser_profile: dict | None = None, timeout_per_phase: int = 10, categories: list[str] | None = None): """Adapter: reicht das aufgelöste `browser_profile` (Engine/Channel/Device) an `run_consent_test` durch, damit jede Matrix-Zeile auf der echten Engine läuft (Firefox/WebKit/Blink + Chrome-/Edge-Channel + Brave). Projiziert das ConsentTestResult auf die schlanke Matrix-dict-Form (phases + kompakter `summary`).""" result = await run_consent_test(url, timeout_per_phase, categories or [], browser_profile=browser_profile) return matrix_scan_dict(result) @router.post("/scan-matrix") async def scan_matrix(req: MatrixScanRequest): """Run consent-scan across the resolved browser-profile matrix.""" logger.info("Matrix scan for %s profiles=%s", req.url, req.browser_profiles or "default") matrix = await run_matrix( _scanner_run, req.url, requested_profiles=req.browser_profiles, timeout_per_phase=req.timeout_per_phase, categories=req.categories, ) matrix["url"] = req.url matrix["scanned_at"] = datetime.now(timezone.utc).isoformat() return matrix