feat(browser-matrix): Cross-Browser-Befunde + Browser-Default-Einordnung (Phase 4)
- browser_cross_finding: deterministische Sicht ueber die Matrix (keine 2. Engine, kein LLM). Findet Inkonsistenzen ZWISCHEN Browsern (Cookies vor Consent / Ablehnen nicht universell respektiert / Banner-Links fehlend) und ordnet ein: Safari-ITP / Brave-Shields / Firefox-ETP maskieren Verstoesse clientseitig → strenge Engine "sauber" ist KEIN Compliance-Beleg, massgeblich sind die nachgiebigen (Chrome/Edge). Coverage-Hinweis fuer nicht verfuegbare Browser. Je Befund Titel/Detail/Severity/affected/Massnahme. - snapshot_check_routes: cross_findings frisch in run + GET (nicht persistiert). - BrowserBehaviorView: "Cross-Browser-Befunde"-Block ueber der Tabelle. - Tests: test_browser_cross_finding (6). Offen (Folge-Task): Borlabs-Consent-Historie-Live-Erkennung (braucht consent-tester-Storage-Scan). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
"""Cross-Browser-Befunde (deterministische Matrix-Sicht, Phase 4).
|
||||
|
||||
Sichert die Inkonsistenz-Erkennung ZWISCHEN Engines + die Einordnung, dass
|
||||
Browser-Tracking-Schutz (Safari/ITP, Brave/Shields, Firefox/ETP) Verstöße
|
||||
clientseitig maskiert (kein Compliance-Beleg)."""
|
||||
|
||||
from compliance.services.browser_cross_finding import build_cross_findings
|
||||
|
||||
|
||||
def _row(pid, label, engine, *, before=0, reject_ok=True,
|
||||
impressum=True, dse=True, with_summary=True):
|
||||
if not with_summary:
|
||||
return {"profile_id": pid, "label": label, "engine": engine,
|
||||
"summary": None, "error": "launch failed"}
|
||||
return {
|
||||
"profile_id": pid, "label": label, "engine": engine,
|
||||
"summary": {
|
||||
"cookies_before_consent": before,
|
||||
"cookies_after_reject": 0 if reject_ok else 2,
|
||||
"reject_respected": reject_ok,
|
||||
"surface": {"has_impressum_link": impressum, "has_dse_link": dse},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def _titles(findings):
|
||||
return " | ".join(f["title"] for f in findings)
|
||||
|
||||
|
||||
def test_empty_matrix():
|
||||
assert build_cross_findings(None) == []
|
||||
assert build_cross_findings({"browser_matrix": []}) == []
|
||||
|
||||
|
||||
def test_pre_consent_in_all_engines_high():
|
||||
m = {"browser_matrix": [
|
||||
_row("chromium-headed-de", "Chromium", "blink", before=5),
|
||||
_row("firefox-headed-de", "Firefox", "gecko", before=3),
|
||||
]}
|
||||
f = build_cross_findings(m)
|
||||
hit = [x for x in f if "in allen Browsern" in x["title"]]
|
||||
assert hit and hit[0]["severity"] == "HIGH"
|
||||
assert "TDDDG" in hit[0]["measure"]
|
||||
|
||||
|
||||
def test_pre_consent_inconsistent_flags_browser_protection():
|
||||
# Chrome (nachgiebig) setzt vor Consent, Safari/WebKit (ITP) nicht.
|
||||
m = {"browser_matrix": [
|
||||
_row("chrome-channel-desktop-de", "Chrome", "blink", before=4),
|
||||
_row("webkit-headed-de", "Safari/WebKit", "webkit", before=0),
|
||||
]}
|
||||
f = build_cross_findings(m)
|
||||
hit = [x for x in f if "nur in manchen" in x["title"]]
|
||||
assert hit and hit[0]["severity"] == "HIGH"
|
||||
# Einordnung: ITP maskiert clientseitig → kein Compliance-Beleg.
|
||||
assert "ITP" in hit[0]["detail"]
|
||||
assert "Chrome" in hit[0]["affected"]
|
||||
|
||||
|
||||
def test_reject_inconsistent_high():
|
||||
m = {"browser_matrix": [
|
||||
_row("chrome-channel-desktop-de", "Chrome", "blink", reject_ok=False),
|
||||
_row("brave-default-de", "Brave", "blink", reject_ok=True),
|
||||
]}
|
||||
f = build_cross_findings(m)
|
||||
hit = [x for x in f if "nicht in allen Browsern respektiert" in x["title"]]
|
||||
assert hit and hit[0]["severity"] == "HIGH"
|
||||
assert "Chrome" in hit[0]["affected"]
|
||||
|
||||
|
||||
def test_missing_engines_coverage_hint():
|
||||
m = {"browser_matrix": [
|
||||
_row("chromium-headed-de", "Chromium", "blink"),
|
||||
_row("brave-default-de", "Brave", "blink", with_summary=False),
|
||||
]}
|
||||
f = build_cross_findings(m)
|
||||
hit = [x for x in f if "Nicht alle Browser getestet" in x["title"]]
|
||||
assert hit and hit[0]["severity"] == "LOW"
|
||||
assert "Brave" in hit[0]["affected"]
|
||||
|
||||
|
||||
def test_clean_matrix_no_violations():
|
||||
m = {"browser_matrix": [
|
||||
_row("chromium-headed-de", "Chromium", "blink"),
|
||||
_row("firefox-headed-de", "Firefox", "gecko"),
|
||||
]}
|
||||
# Alles sauber → keine Verstoß-Befunde (Impressum/DSE vorhanden).
|
||||
assert build_cross_findings(m) == []
|
||||
Reference in New Issue
Block a user