57c0f940a2
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>
235 lines
7.3 KiB
Python
235 lines
7.3 KiB
Python
"""
|
|
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
|