881e9c28de
- _scanner_run reicht browser_profile an run_consent_test durch (statt Single-Chromium-Shim) - neue scan_matrix_summary.matrix_scan_dict: ConsentTestResult -> schlanke Matrix-dict-Form (phases fuer _extract_dimensions + kompakter `summary`: cookies_before_consent/after_reject, reject_respected-Heuristik [keine Verstoesse UND kein neuer Tracker], surface, screenshot) - multi_browser_scanner._run_one hebt summary + engine + is_mobile an die Zeile, verwirft die vollen Cookie-Listen (JSONB-Persistenz schlank) - consent_scanner: _ctx_base mit Mobile-Device-Emulation (iPhone-Profil -> echtes Mobile-Viewport/Touch), alle 5 new_context auf **_ctx_base - Tests: test_scan_matrix_summary (6) inkl. _extract_dimensions-Vertrag Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
67 lines
2.4 KiB
Python
67 lines
2.4 KiB
Python
"""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
|