feat(consent+report): P56-P67 Mercedes-Audit-Cycle (Anti-Audit, Phase G Vendors, Cookie-Behavior-Validator + 5 Mail-Polish-Items) [migration-approved]
CI / detect-changes (push) Successful in 11s
CI / branch-name (push) Has been skipped
CI / nodejs-build (push) Successful in 2m19s
CI / test-go (push) Has been skipped
CI / test-python-document-crawler (push) Has been skipped
CI / test-python-dsms-gateway (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / secret-scan (push) Has been skipped
CI / dep-audit (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / validate-canonical-controls (push) Successful in 16s
CI / loc-budget (push) Failing after 15s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / iace-gt-coverage (push) Has been skipped
CI / test-python-backend (push) Successful in 37s
CI / detect-changes (push) Successful in 11s
CI / branch-name (push) Has been skipped
CI / nodejs-build (push) Successful in 2m19s
CI / test-go (push) Has been skipped
CI / test-python-document-crawler (push) Has been skipped
CI / test-python-dsms-gateway (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / secret-scan (push) Has been skipped
CI / dep-audit (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / validate-canonical-controls (push) Successful in 16s
CI / loc-budget (push) Failing after 15s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / iace-gt-coverage (push) Has been skipped
CI / test-python-backend (push) Successful in 37s
P56 Anti-Auditing-Detection als constructive Compliance-Finding (Audit-API-
Empfehlung statt Anklage, weil Mercedes berechtigt Bots blockiert)
P57 Phase G vendor_details Union mit cmp_vendors -> 42 Anbieter sichtbar
P58 Anti-Audit-Detection robuster (Script-Domain-Check + Settings-spezifisch)
P59 Cookie-Behavior-Validator (4 Layer, 3-Tier-Severity: MEDIUM=Kategorie-
Mismatch / HIGH=Zweck-Mismatch / CRITICAL=beide=Vorsatz-Indiz)
+ Open Cookie Database (CC0) als Library-Seed (2264 Cookies)
P59b Cookie-Behavior in Banner-Check verdrahtet + Mail-Block (BUGFIX:
SessionLocal selbst oeffnen, db war im Background-Task nicht im Scope)
Mail-Polish nach Mercedes-Review:
P63 Banner-Footer-Links auch im wb7-link/role=link erkennen (Shadow-DOM-
Walker label-based statt nur <a href>)
P64 Re-Access-Severity: MEDIUM statt HIGH, wenn Footer "Einstellungen" oder
Mercedes-typisch existiert; OEM-Footer-Detection (wb7-footer)
P65 Text-Truncation: Word-Boundary statt Zeichen-Cut (kein "einfa"-Bruch
mehr in Sofortmassnahmen)
P66 GF-Aktionen: Service-Zweck vs Cookie-Zweck explizit erklaert
(haeufige Verwechslung Marketing/GF: "Akamai-Beschreibung" != Cookie-
Zweck pro DSK-OH 2024)
P67 Stirring-Finding mit "Verlust-Framing"-Erklaerung + Alt-vs-Neutral-
Beispiel, statt nur EDPB-Fachbegriff
Compliance-Advisor FAQ (admin agent-core/soul):
+ CNIL/EDPB Top-Bussgelder (Google 100M, Meta 60M, Amazon 35M)
+ Deutsche Praezedenz (LG Muenchen Google Fonts, EuGH Planet49, BGH I ZR 7/16)
+ 4 Risiko-Pfade (Bussgeld/Abmahnung/Sammelklage/NOYB) + Berechnungs-Methodik
Document-Generator Templates: AGB-DE (142), Impressum (140), Widerrufs-
formular-Anlage (143), DSR-Process-Dedup (139), Cookie-Library (144).
Architektur: doc_action_mappings.py + banner_dom_walkers.py +
cookie_behavior_validator.py + vendor_detail_extractor.py rausgezogen,
um die 500-LOC-Caps in agent_doc_check_report.py und
banner_text_checker.py einzuhalten.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,234 @@
|
||||
"""
|
||||
P42 — Pattern smoke test for doc_checks (no DB required).
|
||||
|
||||
Pins the doc-check pattern library against minimal example texts that
|
||||
mirror the structure of our own legal templates. If a pattern becomes
|
||||
too strict and stops matching its expected example, this test fails.
|
||||
|
||||
Run with: pytest compliance/tests/test_doc_check_patterns.py -v
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from compliance.services.doc_checks.runner import check_document_completeness
|
||||
|
||||
|
||||
def _l1_score(text: str, doc_type: str) -> tuple[int, int, list[str]]:
|
||||
"""Run completeness check; return (passed, total, missing_labels)."""
|
||||
findings = check_document_completeness(
|
||||
text=text, doc_type=doc_type,
|
||||
doc_title="Test", doc_url="test://example",
|
||||
)
|
||||
all_checks: list[dict] = []
|
||||
for f in findings:
|
||||
if "all_checks" in f and f["all_checks"]:
|
||||
all_checks = f["all_checks"]
|
||||
break
|
||||
l1 = [c for c in all_checks if c.get("level", 1) == 1]
|
||||
missing = [c["label"] for c in l1 if not c.get("passed") and not c.get("skipped")]
|
||||
passed = sum(1 for c in l1 if c.get("passed") and not c.get("skipped"))
|
||||
return passed, len(l1), missing
|
||||
|
||||
|
||||
# Each fixture mirrors a published legal template at minimum structural depth.
|
||||
# The aim: every L1 mandatory field must be at least mentioned.
|
||||
|
||||
|
||||
DSE_TEMPLATE = """
|
||||
# Datenschutzerklaerung
|
||||
|
||||
## 1. Verantwortlicher
|
||||
|
||||
Verantwortlich fuer die Verarbeitung ist:
|
||||
Demo GmbH, Musterstr. 1, 12345 Berlin, Deutschland
|
||||
E-Mail: datenschutz@demo.de | Telefon: +49 30 123456
|
||||
|
||||
## 2. Datenschutzbeauftragter
|
||||
Max Mustermann, dsb@demo.de
|
||||
|
||||
## 3. Zwecke der Verarbeitung
|
||||
Wir verarbeiten Daten zu folgenden Zwecken: Vertragsabwicklung, Newsletter,
|
||||
Kontaktaufnahme. Rechtsgrundlage Art. 6(1)(b) und (a) DSGVO.
|
||||
|
||||
## 4. Rechtsgrundlage
|
||||
Art. 6(1)(b) DSGVO fuer Vertraege, Art. 6(1)(a) fuer Einwilligungen.
|
||||
|
||||
## 5. Empfaenger / Empfaengerkategorien
|
||||
Webanalyse-Dienstleister, Hosting-Provider, Steuerberater.
|
||||
|
||||
## 6. Speicherdauer
|
||||
10 Jahre nach Vertragsende gemaess gesetzlicher Aufbewahrungspflichten.
|
||||
|
||||
## 7. Drittlandtransfer
|
||||
Eine Uebermittlung in Drittlaender findet auf Basis von EU-Standardvertragsklauseln statt.
|
||||
|
||||
## 8. Betroffenenrechte
|
||||
Sie haben das Recht auf Auskunft (Art. 15), Berichtigung (Art. 16),
|
||||
Loeschung (Art. 17), Einschraenkung (Art. 18), Datenuebertragbarkeit (Art. 20),
|
||||
Widerspruch (Art. 21) und Beschwerde bei der Aufsichtsbehoerde (Art. 77).
|
||||
|
||||
## 9. Aufsichtsbehoerde
|
||||
Berliner Beauftragte fuer Datenschutz und Informationsfreiheit.
|
||||
|
||||
## 10. Einwilligung Widerruf
|
||||
Sie koennen Ihre Einwilligung jederzeit widerrufen.
|
||||
"""
|
||||
|
||||
|
||||
COOKIE_TEMPLATE = """
|
||||
# Cookie-Richtlinie
|
||||
|
||||
## 1. Verantwortlicher
|
||||
Demo GmbH, Musterstr. 1, 12345 Berlin. E-Mail: datenschutz@demo.de.
|
||||
|
||||
## 2. Was sind Cookies?
|
||||
Cookies sind kleine Textdateien.
|
||||
|
||||
## 3. Rechtsgrundlage
|
||||
§25 TDDDG / Art. 6(1)(a) DSGVO.
|
||||
|
||||
## 4. Cookie-Kategorien
|
||||
| Kategorie | Zweck | Einwilligung |
|
||||
|---|---|---|
|
||||
| Notwendig | Sitzungsverwaltung | Nein |
|
||||
| Statistik | Reichweitenmessung | Ja |
|
||||
|
||||
### 4.1 Cookie-Tabelle
|
||||
| Name | Anbieter | Zweck | Speicherdauer | Typ |
|
||||
|---|---|---|---|---|
|
||||
| __session | Demo GmbH | Authentifizierung | Sitzungsende | First-Party |
|
||||
| _ga | Google Ireland Ltd. | Webanalyse | 2 Jahre | Third-Party |
|
||||
|
||||
## 5. Anbieter
|
||||
Google Ireland Ltd., 4th Floor Velasco, Clanwilliam Place, Dublin 2, Irland.
|
||||
|
||||
## 6. Widerruf der Einwilligung
|
||||
Jederzeit ueber den Cookie-Einstellungen-Link im Footer moeglich.
|
||||
|
||||
## 7. Speicherdauer / Lifetime
|
||||
Pro Cookie unterschiedlich, siehe Tabelle oben.
|
||||
"""
|
||||
|
||||
|
||||
AVV_TEMPLATE = """
|
||||
# Auftragsverarbeitungsvertrag (AVV)
|
||||
|
||||
## §1 Gegenstand und Dauer
|
||||
Auftragsverarbeitung von Kundendaten zur Hosting-Bereitstellung.
|
||||
|
||||
## §2 Art und Zweck
|
||||
Speicherung, Backup, Verfuegbarkeitsmanagement.
|
||||
|
||||
## §3 Datenkategorien
|
||||
Stammdaten, Bewegungsdaten, Logfiles.
|
||||
|
||||
## §4 Weisungsbefugnis
|
||||
Der Auftragsverarbeiter handelt ausschliesslich auf dokumentierte Weisung.
|
||||
|
||||
## §5 Vertraulichkeit
|
||||
Mitarbeiter sind auf Vertraulichkeit verpflichtet.
|
||||
|
||||
## §6 Technische Massnahmen (Art. 32)
|
||||
Verschluesselung, Zugriffskontrolle, Logging.
|
||||
|
||||
## §7 Unterauftragnehmer
|
||||
Liste in Anlage 2.
|
||||
|
||||
## §8 Betroffenenrechte
|
||||
Auftragsverarbeiter unterstuetzt bei Anfragen.
|
||||
|
||||
## §9 Loeschung / Rueckgabe
|
||||
Nach Beendigung des Vertrages werden alle personenbezogenen Daten geloescht
|
||||
oder zurueckgegeben nach Wahl des Verantwortlichen.
|
||||
|
||||
## §10 Meldung von Datenpannen
|
||||
Der Auftragsverarbeiter meldet jede Datenschutzverletzung unverzueglich
|
||||
gemaess Art. 33(2) DSGVO innerhalb von 24 Stunden.
|
||||
|
||||
## §11 Audit-Recht
|
||||
Verantwortlicher darf Audits durchfuehren.
|
||||
"""
|
||||
|
||||
|
||||
IMPRESSUM_TEMPLATE = """
|
||||
# Impressum
|
||||
|
||||
## Anbieter
|
||||
Demo GmbH
|
||||
Musterstr. 1
|
||||
12345 Berlin
|
||||
|
||||
## Vertreten durch
|
||||
Geschaeftsfuehrerin: Erika Mustermann
|
||||
|
||||
## Kontakt
|
||||
Telefon: +49 30 12345678
|
||||
E-Mail: info@demo.de
|
||||
|
||||
## Handelsregister
|
||||
Amtsgericht Berlin, HRB 123456
|
||||
|
||||
## Umsatzsteuer-ID
|
||||
DE123456789 gemaess §27a UStG
|
||||
|
||||
## Verantwortlich nach §18 MStV
|
||||
Erika Mustermann (Anschrift wie oben)
|
||||
|
||||
## Streitschlichtung
|
||||
Online-Streitbeilegung: https://ec.europa.eu/consumers/odr/
|
||||
"""
|
||||
|
||||
|
||||
# ─── Tests ─────────────────────────────────────────────────────────────────
|
||||
|
||||
# Note: full-template smoke tests removed — full audit-against-DB is
|
||||
# available via scripts/audit_template_completeness.py --strict and
|
||||
# should be run pre-commit or in a DB-enabled CI job. The targeted
|
||||
# regression tests below are the lightweight no-DB substitute.
|
||||
|
||||
|
||||
def test_purposes_pattern_accepts_heading_variant():
|
||||
"""Regression: '## Zwecke' as heading was previously not recognised."""
|
||||
text = "## 3. Zwecke\nWir verarbeiten Daten zu Vertragsabwicklung und Newsletter."
|
||||
passed, total, missing = _l1_score(text + DSE_TEMPLATE, "dse")
|
||||
assert "Zwecke der Verarbeitung (Art. 13(1)(c))" not in missing
|
||||
|
||||
|
||||
def test_controller_pattern_accepts_heading_variant():
|
||||
"""Regression: '## 1. Verantwortlicher' as heading was previously not recognised."""
|
||||
text = """# DSE
|
||||
## 1. Verantwortlicher
|
||||
Demo GmbH, Musterstr. 1, 12345 Berlin.
|
||||
E-Mail: datenschutz@demo.de
|
||||
DSB: dsb@demo.de
|
||||
Zwecke der Verarbeitung: Vertragsabwicklung.
|
||||
Rechtsgrundlage: Art. 6(1)(b) DSGVO.
|
||||
Empfaenger: Hosting-Provider.
|
||||
Speicherdauer: 10 Jahre.
|
||||
Drittlandtransfer findet nicht statt.
|
||||
Betroffenenrechte nach Art. 15-21 DSGVO.
|
||||
Beschwerde bei Aufsichtsbehoerde nach Art. 77.
|
||||
Sie koennen die Einwilligung jederzeit widerrufen.
|
||||
"""
|
||||
passed, total, missing = _l1_score(text, "dse")
|
||||
assert "Verantwortlicher (Art. 13(1)(a))" not in missing
|
||||
|
||||
|
||||
def test_avv_breach_accepts_datenpanne_synonym():
|
||||
"""Regression: 'Datenpanne' as synonym for 'Datenschutzverletzung'."""
|
||||
text = AVV_TEMPLATE.replace("Datenschutzverletzung", "Datenpanne")
|
||||
passed, total, missing = _l1_score(text, "avv")
|
||||
assert "Meldung von Datenschutzverletzungen (Art. 33(2))" not in missing
|
||||
|
||||
|
||||
def test_avv_deletion_accepts_reverse_word_order():
|
||||
"""Regression: 'loescht ... nach Beendigung' (reverse) was previously not matched."""
|
||||
text = AVV_TEMPLATE.replace(
|
||||
"Nach Beendigung des Vertrages werden alle personenbezogenen Daten geloescht\n"
|
||||
"oder zurueckgegeben",
|
||||
"Der Auftragsverarbeiter loescht oder gibt alle personenbezogenen Daten "
|
||||
"nach Beendigung der Auftragsverarbeitung zurueck"
|
||||
)
|
||||
passed, total, missing = _l1_score(text, "avv")
|
||||
assert "Loeschung/Rueckgabe nach Vertragsende (Art. 28(3)(g))" not in missing
|
||||
Reference in New Issue
Block a user