Benjamin Admin
cb4b352846
feat(b17): Playwright Audit-Walk-Video (Stufe 1, #7 )
...
Nimmt einen kompletten Site-Walk als WebKit-Browser-Session
inkl. Video auf. Reviewer kann nachträglich exakt nachvollziehen,
wie die Engine zum Befund kam.
consent-tester:
- services/audit_walk_recorder.py: Playwright record_video_dir,
iPhone-Viewport-free 1280×800. Goto homepage → Banner-Accept
(Best-Effort: 12 Text-Phrasen + 5 CMP-Fallback-Selektoren) →
Footer-Links sammeln (compliance-relevant gefiltert) →
pro Link navigate + Dwell-Time → JSON-Action-Index mit
UTC-Timestamps + SHA-256 vom Video als Manipulation-Schutz.
- routes_audit_walk.py: POST /scan-audit-walk; statische
Serves für /audit-walks/{walk_id}/video.webm + walk.json.
- main.py: Router registriert.
backend:
- _b17_wiring.py: Triggert /scan-audit-walk, speichert
Walk-Metadata in state["audit_walk"]. Render-Block mit
HTML-Tabelle aller Actions (HH:MM:SS + Aktion + Detail) +
Links zu Video und walk.json.
- _orchestrator.py: run_b17 nach run_b16, async-aufgerufen.
- mail_render_v2/_compose.py: audit_walk_html im V2-Layout.
- test_b17_audit_walk.py: 8 Tests (Render-Pfade + Wiring).
Stufe-2 (Akkordeon-Expansion) und Stufe-3 (DSMS-CID-Anchor)
folgen separat.
Real-World-Smoke gegen Elli:
- 581 KB Video, SHA-256 verifizierbar
- 3 Footer-Links besucht (Impressum, Datenschutzerkl., Nutzungs-)
- 6 Actions im JSON-Index
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-06-07 17:20:13 +02:00
Benjamin Admin
65e8bb9d42
feat(b16): Footer-Label-vs-URL-Slug-Drift-Check (GT URL-STRUCTURE-001)
...
Erkennt: gängige Footer-Labels / Bookmark- + SEO-Erwartungs-Slugs
(z.B. "Cookie-Richtlinie", "AGB", "Datenschutzerklärung") liefern
404, während das Doc tatsächlich unter einem abweichenden Slug
ausgeliefert wird.
GT-Anker (Elli URL-STRUCTURE-001):
Footer-Label "Cookie-Richtlinie" → /cookie-richtlinie 404
Real: /de/cookies
→ externe Bookmarks und Google-Treffer brechen.
Heuristik:
- Aus auto-discovered URLs Origin + Sprach-Prefix extrahieren
(z.B. /de, /de-de)
- Pro doc_type 2-4 kanonische Standard-Slugs probieren (parallel
via ThreadPoolExecutor, 2s Timeout, HEAD → GET fallback bei 405)
- Wenn alternative Slug 404/410 → LOW Finding pro doc_type
- Probe-Cap auf 18 Requests gesamt (Network-Noise-Schutz)
- Abschaltbar via URL_SLUG_PROBE_DISABLED=1
Severity: LOW (Best-Practice, kein juristisches Hardfail).
Tests: 13/13 grün (Strip-Helper 4 + Origin-Helper 3 + Check-Pfade 6
inkl. mocked _head_status).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-06-07 00:23:25 +02:00
Benjamin Admin
b0b7f80914
feat(b15): AI-Act Rechtsgrundlage-Check (GT AI-ACT-RISK-001)
...
Erkennt: LLM/GPAI-System (Vertex AI, OpenAI/GPT, Claude) wird in
DSE oder Cookie-Doc auf Art. 6 Abs. 1 lit. f (berechtigtes Interesse)
gestützt — statt auf lit. a (Einwilligung).
GT-Anker (Elli AI-ACT-RISK-001): Vertex-AI-Chatbot mit lit. f
deklariert. Bei LLM-Prompt/Output-Logging + US-Transfer +
Profiling-Ähnlichkeit ist Interessenabwägung fragwürdig.
Heuristik:
- KB-basiert (chat_providers.json filter: ai_capable + LLM-Type-Hint)
- LLM-Vendor-Aliases inkl. Marken-Familien (PaLM, Gemini, GPT-4,
ChatGPT, Claude 3, Azure OpenAI)
- Absatz-Boundary-Scope: Provider + lit. f im selben Absatz
- Negativ-Filter: wenn lit. a / Einwilligung ebenfalls im Absatz →
kein Finding (Side-Purpose-Erwähnung)
- Dedup pro (doc_type, provider_id)
Severity: MEDIUM.
Norm: DSGVO Art. 6 Abs. 1 lit. a vs lit. f + AI Act Art. 50 + 51.
Tests: 17/17 grün.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-06-07 00:15:08 +02:00
Benjamin Admin
6aad774fc1
feat(b14): widersprüchliche Speicherdauer im selben Doc (GT TH-RETENTION-001)
...
Erkennt: in derselben DSE / Cookie-Richtlinie nennt der Anbieter für
DIESELBE Datenkategorie mehrere unterschiedliche Speicherdauern.
GT-Anker (Elli): Logfiles "7 Tage" + "30 Tage" im selben DSE → eine
Angabe ist falsch oder veraltet.
Heuristik:
- Satz-Boundary-Scope (kein ±N-Zeichen-Fenster) verhindert
Cross-Category-Leakage
- Pro Satz: Kategorie-Anchor + Retention-Werte beide drin
- Tag-Cluster mit ±20 %-Toleranz: "30 Tage" und "1 Monat" =
1 Cluster; "7 Tage" und "30 Tage" = 2 Cluster → Finding
Kategorien (Phase 1):
- logfile, contact_form, application, newsletter, invoice,
session_cookie
Severity: MEDIUM (DSGVO Art. 5 Abs. 1 lit. a + Art. 13 Abs. 2 lit. a).
Tests: 11/11 grün (Cluster-Logik 5, Check-Pfade 6, inkl. Cross-
Category-Leakage-Regression).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-06-07 00:12:00 +02:00
Benjamin Admin
b9baa8c603
feat(b13): Widerrufsbelehrung-Reachability-Check (GT WIDERRUFSBELEHRUNG-001)
...
Erkennt B2C-Shop ohne öffentlich erreichbare Widerrufsbelehrung.
Schließt eine der offenen GT-Lücken aus dem Elli-Audit.
Signale:
- doc_entries[widerruf]: discovery_attempted=True + Text leer
- kein Footer-Link auf Widerruf/cancellation/rückgabe
- B2C-Scope: Warenkorb/Kasse/Bestellung/MwSt/Wallbox/Tarif (strong)
vs Shop/Produkt/Rechnung (weak, ≥2 = likely)
- B2B-only-Override: "ausschließlich an Unternehmer" etc.
Severity:
- HIGH bei b2c_strong
- MEDIUM bei b2c_likely
- kein Finding bei b2b_only / unknown (False-Positive-Schutz)
Norm: Art. 246a § 1 Abs. 2 Nr. 1 EGBGB i.V.m. § 312d BGB.
Wiring:
- widerrufsbelehrung_reachability_check.py — Check + Scope-Detection
- _b13_wiring.py — Render + state-Anschluss
- _orchestrator.py — run_b13 nach run_b12
- mail_render_v2/_compose.py — widerruf_reach_html-Block
Tests: 13/13 grün (Scope-Detection 5 + Check-Logik 8).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-06-07 00:04:41 +02:00
Benjamin Admin
ff796fb480
feat: B12 Chatbot-Cookie-Klassifikation ( #19 ) + Cookie-Matrix scan + safetykon test
...
#19 Chatbot-Cookie-Klassifikation:
- chat_providers.json KB mit 11 Providern (iAdvize, Intercom, Tidio,
Drift, Userlike, Zendesk, LivePerson, HubSpot, Vertex AI, OpenAI,
Anthropic Claude). Pro Provider: Cookie-Pattern-Regex,
typical_retention_days, tn_functions vs cp_functions, ai_capable.
- chatbot_cookie_classification_check.py mit 4 KORRIGIERTEN Checks:
CHAT-COOKIE-CLASS-001 (MED) — TN deklariert + Vendor-Purpose
erwähnt Targeting/Analytics/A-B-Tests
CHAT-COOKIE-CLASS-002 (MED) — Provider hat tn+cp Funktionen,
Tabelle nennt nur eine Seite → keine Einwilligungs-Differenzierung
CHAT-COOKIE-PURPOSE-001 (LOW) — Zweck zu generisch (Art. 13
DSGVO konkret)
CHAT-COOKIE-RETENTION-001 (HIGH) — deklariert <90d, KB-typisch
>365d → vermutlich unterdeklariert
NEU vs vorigem Plan: kein "eigene Banner-Kategorie Chat/AI"-Check —
gesetzlich nicht vorgeschrieben (Vermischung Zweck-Transparenz vs
Kategorie-Name). Anwender-Frage berechtigt, Konzept geschärft.
- _b12_wiring.py + Orchestrator-Wire + V2-Compose-Slot
- Cookie-Inventar mit [Chat]/[Chat+AI]-Tag pro Cookie-Name (KB-Lookup)
- Smoke (3 Vendors / 5 Cookies): 9 findings korrekt (3 HIGH RETENTION,
3 MEDIUM CLASS-001, 4 LOW PURPOSE)
Cookie-Matrix Scan (Browser-Vergleich gegen safetykon.de):
- consent-tester/services/cookie_behavior_per_browser.py: eigener
fokussierter Scanner. Pro Browser-Profile: cookies before / after
reject / after accept in separaten Kontexten. Sequenzielle Runs
statt parallel (Race-Conditions).
- routes_cookie_matrix.py POST /scan-cookie-matrix
- Live-Test safetykon.de: chromium=1, firefox=0, webkit=1, mobile-
safari=1 nach reject — Firefox setzt KEIN Cookie nach Reject!
(consent-tester Rebuild brachte playwright install-deps für system-libs)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-06-06 23:25:20 +02:00
Benjamin Admin
37093ff9e3
feat: Browser-Matrix C2 + B11 AI-Retention + Impressum-Specialist-Agent + B1 Mobile Playwright
...
Task #15 Stage 1.c-e — Browser-Matrix Backend-Integration:
- _phase_c2_browser_matrix.py: ruft consent-tester /scan-matrix wenn
env BROWSER_MATRIX=true, fuellt state["browser_matrix"] +
state["browser_aggregate"] + state["browser_matrix_html"]
- V2-Mail-Block: 🌐 Browser-Matrix Tabelle (Profile · Score ·
Sub-Scores PC/RR/BD · Bewertung) mit Worst-of-Header
- Orchestrator ruft run_phase_c2 nach run_phase_c
KNOWN: Stage 1.b (consent_scanner browser_profile-Param) bleibt
zurueckgestellt (Datei in loc-exception, Hook-Patch verweigert).
Stage 1.a-Shim laeuft im consent-tester — alle Profile aktuell
auf Chromium, echte Engine-Diversitaet kommt mit 1.b.
Task #17 TH-RETENTION-002 als B11 ai_retention_granularity_check:
- Erkennt AI-Provider-Kontext (vertex/openai/anthropic/etc)
- In +-800-char-Window: prueft ≥2 Datenkategorien aus Standard-Liste
(Texteingaben/IP/Geraet/Session/Fehlerprotokoll/Zeitstempel)
- Wenn 1 pauschale Speicherdauer + ≥2 Kategorien aber kein
per-Kategorie-Differential → LOW
- Smoke: Elli-Mock-DSE trifft LOW "AI-Speicherdauer pauschal"
Task #18 Specialist-Agents Phase-1-Prototyp:
- compliance/services/specialist_agents/__init__.py mit Architektur-Doku
- impressum_agent.py: 9 Pflichtangaben § 5 TMG + § 1 DL-InfoV
als Pattern-Registry (Name, Email, Telefon, HR, USt-IdNr,
Vertretungsberechtigt, Aufsichtsbehoerde, Berufsangaben, OS-Link)
- business_scope-aware (OS-Link nur fuer ecommerce, Aufsichtsbehoerde
nur fuer regulated_profession/financial/insurance)
- Phase-1 ist Pattern-Match-only (kein LLM), demonstriert die
Schnittstelle. Phase 2 ersetzt Pattern durch System-Prompt + KB.
- Smoke: minimal-Impressum triggert 4 Findings korrekt
Task #7 B1 Playwright Mobile-Verifikation:
- consent-tester/services/mobile_reachability_scanner.py: echte
WebKit-launch + p.devices['iPhone 15'] preset + de-DE locale +
Europe/Berlin timezone
- Footer-Anchor-Suche via locator("footer >> text=/.../i") fuer
13 Reopen-Phrasen
- Tap-Target-Boundingbox-Messung (Apple HIG / WCAG ≥44x44)
- Click-Behavior: DOM-Modal-Snapshot vor/nach, erkennt CMP-Open
- Output: has_anchor, anchor_text, tap_target_px, click_opens_cmp,
engine_meta, screenshot_b64 (Footer-Crop wenn kein Anchor)
- consent-tester/routes_mobile.py POST /scan-mobile-reachability
- Backend _b1_wiring erweitert: ruft Mobile-Endpoint zuerst,
Fallback auf statischen HTTP-Fetch. Mobile-Daten enrichen
finding.mobile_playwright + Severity-Bump bei
tap-target<44 / click-doesnt-open-CMP.
KNOWN: WebKit-System-Libs sind im Dockerfile ergaenzt (Stage 1.a-
Commit), greifen aber erst nach CI/CD-Rebuild des consent-tester.
Bis dahin faellt B1 sauber auf statischen Fetch zurueck.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-06-06 22:20:25 +02:00
Benjamin Admin
d0e3621192
feat(audit): V2 mail render + 5 new findings (B4/B5/B6/B7/B8) + LLM-Plausibility-Phase
...
Mail Render V2 (compliance/services/mail_render_v2/) — 11-Modul-Subpackage
das einen einheitlichen Audit-Mail-Output erzeugt mit:
- Header + KPI-Kacheln (Score / Findings / Docs / Vendors)
- TOC + Sprung-Links
- 3-Bucket-Trennung: Kritische Befunde / Manuelle Prüfung / Interne Reminder
- Cookie-Inventar (Name·Vendor·Kategorie·Speicherdauer·Löschfrist·Sitzland·Quelle·Status)
- Sofortmaßnahmen-Aggregator ("Sitzland ergänzen für 11 Cookies")
- 24 Legacy-Wrappers — alle alten build_*_html in V2-Sections
- Scope-Filter: FIN/GOV/MED/INS/EDU/LEG aus Berichten wenn nicht relevant
- Hint/Action-Dedup: keine doppelten Sätze pro Card mehr
Aktiviert via env MAIL_RENDER_V2=true (Default: legacy renderer).
5 neue deterministische Findings als Phase D-2b/B4/B5/B6/B7/B8:
B4 vendor_consistency_check — Cross-Doc-Provider-Widerspruch
(Elli: DSE nennt Vertex AI für Chatbot, /de/cookies nennt Iadvize → HIGH).
6 Service-Types: chatbot/analytics/tag_manager/pixel/cdn/cmp.
B5 ai_act_transparency_check — AI Act Art. 50 Transparenzpflicht
(Elli: Vertex AI vorhanden ohne Pre-Chat-Disclosure → HIGH).
Plus B5-Erweiterung: Rechtsgrundlage Art-6-Abs-1-lit-f bei AI → MED
(Einwilligung empfehlen).
B6 cross_doc_dpo_check — DPO in DSE genannt, nicht im Impressum (LOW).
B7 doc_staleness_check — Datum-Extraktion aus DSE/AGB/Nutzungsbedingungen.
Cap: AGB/NB 3y, DSE 2y. Älter → MEDIUM (Elli NB Stand 2018 → HIGH).
B8 cmp_fingerprint_check — Banner detected, aber CMP-Provider generic
(kein Usercentrics/OneTrust/Cookiebot/etc → MED).
B3-Erweiterung detect_intra_doc_contradictions — Widersprüchliche
Speicherdauer im SELBEN Doc (Elli: Logfile 7d vs 30d → HIGH).
LLM-Plausibility-Phase (Phase D-2b, finding_plausibility_check.py):
- Läuft AFTER MC pipeline, BEFORE D3 render
- Prompt mit Beispiel-IDs + 3-Phase-Mapping: exact-ID / position-fallback /
fuzzy-tail-match
- Stempelt llm_title / llm_severity / llm_recommendation / llm_drop auf
jeden FAIL CheckItem
- V2-Render zeigt "🤖 LLM-Plausibility:" Box pro Finding wenn gestempelt
- KNOWN ISSUE: qwen3:30b-a3b liefert oft empty content auf format='json' +
8000-char-excerpt prompts. Pipeline läuft mit stamped=0 weiter. Task #16 .
Coverage gegen Elli Ground Truth (zeroclaw/docs/ground-truth/elli_eco_2026-06-06.json,
13 expected findings via WebFetch-Agent-Crawl):
- 4/4 HIGH-Findings ✓ (COOKIE-CONSENT-UX-001 + WIDERRUFSBELEHRUNG-001 +
VENDOR-CONSISTENCY-001 + AI-ACT-TRANSPARENCY-001)
- 4/6 MEDIUM ✓
- 2/3 LOW ✓
- Total: 10/13 = 77% (Sprung von 4/13 = 31%)
Restliche 3 Gaps als Task #17 : IMPRESSUM-001 (multi-entity USt-IdNr),
TRANSFER-001 (Vendor-Mechanismus DPF/SCC), TH-RETENTION-002 (AI-Retention
pro Datenkategorie).
V2-Mail-Preview in Mailpit: 'v2all@local.test ' Subject '[V2 ALL] ELLI'.
Backend healthy, B1+B3+B4+B5+B6+B7+B8 alle live im Orchestrator.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-06-06 21:19:49 +02:00