""" 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