feat: 4 remaining tasks — EU institutions, banner integration, JS-sites, Caritas fixes
Build + Deploy / build-ai-sdk (push) Failing after 36s
Build + Deploy / build-developer-portal (push) Successful in 8s
Build + Deploy / build-tts (push) Successful in 7s
Build + Deploy / build-document-crawler (push) Successful in 7s
Build + Deploy / build-admin-compliance (push) Successful in 8s
Build + Deploy / build-backend-compliance (push) Successful in 8s
CI / nodejs-build (push) Successful in 3m14s
CI / dep-audit (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / test-go (push) Failing after 46s
CI / test-python-backend (push) Successful in 43s
CI / test-python-document-crawler (push) Successful in 29s
CI / test-python-dsms-gateway (push) Successful in 30s
CI / validate-canonical-controls (push) Successful in 16s
Build + Deploy / build-dsms-gateway (push) Successful in 8s
Build + Deploy / build-dsms-node (push) Successful in 8s
CI / branch-name (push) Has been skipped
Build + Deploy / trigger-orca (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / loc-budget (push) Failing after 17s
CI / secret-scan (push) Has been skipped
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
Build + Deploy / build-ai-sdk (push) Failing after 36s
Build + Deploy / build-developer-portal (push) Successful in 8s
Build + Deploy / build-tts (push) Successful in 7s
Build + Deploy / build-document-crawler (push) Successful in 7s
Build + Deploy / build-admin-compliance (push) Successful in 8s
Build + Deploy / build-backend-compliance (push) Successful in 8s
CI / nodejs-build (push) Successful in 3m14s
CI / dep-audit (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / test-go (push) Failing after 46s
CI / test-python-backend (push) Successful in 43s
CI / test-python-document-crawler (push) Successful in 29s
CI / test-python-dsms-gateway (push) Successful in 30s
CI / validate-canonical-controls (push) Successful in 16s
Build + Deploy / build-dsms-gateway (push) Successful in 8s
Build + Deploy / build-dsms-node (push) Successful in 8s
CI / branch-name (push) Has been skipped
Build + Deploy / trigger-orca (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / loc-budget (push) Failing after 17s
CI / secret-scan (push) Has been skipped
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
1. EU Institution Checks (Verordnung 2018/1725): - New doc_type "eu_institution" with 9 L1 + 15 L2 checks - Both German + English patterns (EU institutions are multilingual) - Auto-detection via "2018/1725", "EDSB", "EDPS" keywords - Correct article references (Art. 15 instead of 13, Art. 5 instead of 6) 2. Banner Check Integration: - banner_runner.py maps scan results to 36 L1/L2 structured checks - BannerCheckTab shows hierarchical ChecklistView with hints - 3-phase summary (cookies/scripts before/after consent) - /scan endpoint now includes structured_checks in response 3. JS-heavy Website Fixes (dm, Zalando, HWK): - dsi_helpers.py: goto_resilient (networkidle→domcontentloaded fallback) - try_dismiss_consent_banner before text extraction - PDF redirect detection (dm.de redirects to GCS PDF) 4. Caritas False Positive Fixes: - Phone regex allows parentheses: +49 (0)761 → now matches - "Recht auf Widerspruch" (3 words) + §23 KDG → matches Art. 21 - Church authorities: "Katholisches Datenschutzzentrum" recognized Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -329,6 +329,7 @@ SECTION_TYPE_MAP = [
|
||||
(r"datenschutzfolge|dsfa|risikoanalyse", "dsfa"),
|
||||
(r"^social\s*media$|^soziale\s+(?:medien|netzwerke)$", "social_media"),
|
||||
(r"datenschutzerkl(?:ae|ä)rung.*social|datenschutz\s+f(?:ue|ü)r\s+social", "social_media"),
|
||||
(r"(?:verordnung|regulation)\s*\(?eu\)?\s*2018\s*/?\s*1725", "eu_institution"),
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
doc_checks — Legal document compliance checkers.
|
||||
|
||||
Provides checklists and functions for verifying legal documents
|
||||
(DSI, AGB, Impressum, Cookie, Widerruf, Social Media, DSFA)
|
||||
(DSI, AGB, Impressum, Cookie, Widerruf, Social Media, DSFA, EU Institution)
|
||||
against their mandatory content requirements.
|
||||
|
||||
Two check levels:
|
||||
@@ -18,6 +18,7 @@ from .impressum_checks import IMPRESSUM_CHECKLIST
|
||||
from .cookie_checks import COOKIE_CHECKLIST
|
||||
from .social_media_checks import JOINT_CONTROLLER_CHECKLIST
|
||||
from .dsfa_checks import DSFA_CHECKLIST
|
||||
from .eu_institution_checks import EU_INSTITUTION_CHECKLIST
|
||||
|
||||
__all__ = [
|
||||
"check_document_completeness",
|
||||
@@ -29,4 +30,5 @@ __all__ = [
|
||||
"COOKIE_CHECKLIST",
|
||||
"JOINT_CONTROLLER_CHECKLIST",
|
||||
"DSFA_CHECKLIST",
|
||||
"EU_INSTITUTION_CHECKLIST",
|
||||
]
|
||||
|
||||
@@ -47,8 +47,9 @@ ART13_CHECKLIST = [
|
||||
"label": "Telefonnummer des Verantwortlichen",
|
||||
"level": 2, "parent": "controller",
|
||||
"patterns": [
|
||||
r"(?:tel(?:efon)?|phone|fon)\s*[.:]\s*[\+\d][\d\s/\-]{6,}",
|
||||
r"\+49\s*[\d\s/\-]{8,}",
|
||||
r"(?:tel(?:efon)?|phone|fon)\s*[.:]\s*[\+\d][\d\s/\-\(\)]{6,}",
|
||||
r"\+49\s*[\d\s/\-\(\)]{8,}",
|
||||
r"0\d{2,4}\s*[\(/\-\s]\s*\d{3,}",
|
||||
],
|
||||
"severity": "MEDIUM",
|
||||
"hint": "EuGH (C-298/17, 'Verein fuer Konsumenteninformation') verlangt effektive Kontaktmoeglichkeit. Telefon ist nicht zwingend, aber empfohlen — fehlt sie, muss ein gleichwertiger Kanal (z.B. Chat, Rueckruf) angeboten werden.",
|
||||
@@ -345,7 +346,7 @@ ART13_CHECKLIST = [
|
||||
"id": "rights_art21",
|
||||
"label": "Widerspruchsrecht (Art. 21)",
|
||||
"level": 2, "parent": "rights",
|
||||
"patterns": [r"art\.\s*21", r"widerspruchsrecht", r"right\s+to\s+object"],
|
||||
"patterns": [r"art\.\s*21", r"widerspruchsrecht", r"recht\s+auf\s+widerspruch", r"§\s*23\s+kdg", r"right\s+to\s+object"],
|
||||
"severity": "LOW",
|
||||
"hint": "Art. 21(4) DSGVO: Der Widerspruchshinweis muss spaetestens zum Zeitpunkt der ersten Kommunikation GESONDERT und in klarer Sprache erfolgen. Haeufiger Fehler: Widerspruchsrecht nur im Fliesstext versteckt — eigener Abschnitt/Hervorhebung noetig.",
|
||||
},
|
||||
@@ -386,6 +387,9 @@ ART13_CHECKLIST = [
|
||||
r"l(?:an)?fdi\s+\w+",
|
||||
r"bfdi",
|
||||
r"(?:bayerische|hessische|s(?:ae|ä)chsische|berliner)\s+(?:datenschutz|aufsicht)",
|
||||
r"(?:katholisch|evangelisch|kirchlich)\w*\s+datenschutz",
|
||||
r"datenschutzzentrum",
|
||||
r"kd(?:oe|ö)r",
|
||||
],
|
||||
"severity": "LOW",
|
||||
"hint": "Vollstaendigen Namen, Adresse und Website der Aufsichtsbehoerde angeben. Haeufiger Fehler: 'die zustaendige Aufsichtsbehoerde' ohne Konkretisierung. Korrekt z.B.: 'LfDI BW, Koenigstrasse 10a, 70173 Stuttgart, www.baden-wuerttemberg.datenschutz.de'.",
|
||||
|
||||
@@ -0,0 +1,500 @@
|
||||
"""
|
||||
EU Institution checks — Verordnung (EU) 2018/1725.
|
||||
Applies to EU institutions, bodies, offices and agencies instead of DSGVO.
|
||||
Key differences: Art. 15 (not 13), Art. 5 (not 6), EDSB (not national DPAs).
|
||||
L1: Pflichtangabe erwaehnt? L2: Pflichtangabe korrekt/vollstaendig?
|
||||
"""
|
||||
|
||||
EU_INSTITUTION_CHECKLIST = [
|
||||
# == L1: Verantwortlicher (Controller) =================================
|
||||
{
|
||||
"id": "eu_controller",
|
||||
"label": "Verantwortlicher (Art. 15(1)(a) VO 2018/1725)",
|
||||
"level": 1, "parent": None,
|
||||
"patterns": [
|
||||
r"verantwortlich\w*\s+(?:ist|im sinne|fuer|f(?:ue|ü)r)",
|
||||
r"kontaktdaten\s+des\s+verantwortlichen",
|
||||
r"name\s+(?:und|&)\s+kontaktdaten\s+des",
|
||||
r"controller", r"verantwortliche\s+stelle",
|
||||
r"responsible\s+(?:party|for)",
|
||||
r"data\s+controller",
|
||||
r"identity\s+(?:of\s+)?(?:the\s+)?controller",
|
||||
],
|
||||
"severity": "HIGH",
|
||||
"hint": (
|
||||
"Art. 15(1)(a) VO 2018/1725 verlangt die Identitaet des Verantwortlichen. "
|
||||
"Bei EU-Organen: Vollstaendiger Name der Institution (z.B. 'Europaeische Kommission, "
|
||||
"GD DIGIT'), Dienstadresse und funktionale E-Mail-Adresse. "
|
||||
"Haeufiger Fehler: Nur Abkuerzung ohne vollstaendigen Institutionsnamen."
|
||||
),
|
||||
},
|
||||
{
|
||||
"id": "eu_controller_address",
|
||||
"label": "Dienstadresse des Verantwortlichen",
|
||||
"level": 2, "parent": "eu_controller",
|
||||
"patterns": [
|
||||
r"(?:rue|avenue|boulevard|strasse|stra(?:ss|ß)e)\s+\w+",
|
||||
r"\d{4,5}\s+(?:bruxelles|brussels|br(?:ue|ü)ssel|luxembourg|luxemburg|strasbourg|stra(?:ss|ß)burg)",
|
||||
r"b[\-\s]?\d{4}\s+\w+",
|
||||
r"l[\-\s]?\d{4}\s+\w+",
|
||||
],
|
||||
"severity": "MEDIUM",
|
||||
"hint": (
|
||||
"Angabe der Dienstadresse der EU-Institution (typisch: Bruessel, Luxemburg "
|
||||
"oder Strassburg). Format z.B. 'Rue de la Loi 200, B-1049 Bruxelles'. "
|
||||
"Haeufiger Fehler: Nur Postfach ohne physische Adresse."
|
||||
),
|
||||
},
|
||||
{
|
||||
"id": "eu_controller_email",
|
||||
"label": "E-Mail-Adresse des Verantwortlichen",
|
||||
"level": 2, "parent": "eu_controller",
|
||||
"patterns": [
|
||||
r"[a-z0-9._%+\-]+@[a-z0-9.\-]+\.europa\.eu",
|
||||
r"[a-z0-9._%+\-]+@[a-z0-9.\-]+\.[a-z]{2,}",
|
||||
],
|
||||
"severity": "MEDIUM",
|
||||
"hint": (
|
||||
"Eine funktionale E-Mail-Adresse ist Pflicht (Art. 15(1)(a) VO 2018/1725). "
|
||||
"Bei EU-Organen typischerweise @ec.europa.eu, @europarl.europa.eu o.ae. "
|
||||
"Ein reines Kontaktformular genuegt nicht als unmittelbarer Kommunikationskanal."
|
||||
),
|
||||
},
|
||||
# == L1: Datenschutzbeauftragter (DPO) =================================
|
||||
{
|
||||
"id": "eu_dpo",
|
||||
"label": "Datenschutzbeauftragter (Art. 15(1)(b) / Art. 43 VO 2018/1725)",
|
||||
"level": 1, "parent": None,
|
||||
"patterns": [
|
||||
r"datenschutzbeauftragt",
|
||||
r"data\s+protection\s+officer",
|
||||
r"kontaktdaten\s+de[rs]\s+datenschutz",
|
||||
r"dpo",
|
||||
r"d(?:ae|ä)legu(?:e|é)\s+(?:a|à)\s+la\s+protection\s+des\s+donn(?:e|é)es",
|
||||
],
|
||||
"severity": "HIGH",
|
||||
"hint": (
|
||||
"Art. 43-44 VO 2018/1725: Jedes EU-Organ MUSS einen DSB (DPO) benennen. "
|
||||
"Dies ist — anders als unter der DSGVO — keine Frage der Mitarbeiterzahl, "
|
||||
"sondern absolute Pflicht fuer alle EU-Organe. Die Kontaktdaten muessen in "
|
||||
"jeder Datenschutzerklaerung angegeben werden (Art. 15(1)(b))."
|
||||
),
|
||||
},
|
||||
{
|
||||
"id": "eu_dpo_contact",
|
||||
"label": "DPO-Kontaktdaten (E-Mail oder Adresse)",
|
||||
"level": 2, "parent": "eu_dpo",
|
||||
"patterns": [
|
||||
r"(?:data\s+protection\s+officer|dpo|datenschutzbeauftragt)[\s\S]{0,300}[a-z0-9._%+\-]+@",
|
||||
r"dpo[\s\S]{0,100}@",
|
||||
r"data[\-\.]?protection@",
|
||||
r"dpo@\w+\.europa\.eu",
|
||||
],
|
||||
"severity": "MEDIUM",
|
||||
"hint": (
|
||||
"Art. 44(7) VO 2018/1725: Die Kontaktdaten des DPO muessen veroeffentlicht werden. "
|
||||
"Mindestens eine funktionale E-Mail-Adresse angeben (z.B. DATA-PROTECTION-OFFICER@ec.europa.eu). "
|
||||
"Den Namen des DPO muessen Sie nicht nennen."
|
||||
),
|
||||
},
|
||||
|
||||
{
|
||||
"id": "eu_dpo_function",
|
||||
"label": "DPO-Funktion / -Rolle beschrieben",
|
||||
"level": 2, "parent": "eu_dpo",
|
||||
"patterns": [
|
||||
r"(?:aufgaben|role|function|zustaendig).*(?:dpo|datenschutzbeauftragt|data\s+protection\s+officer)",
|
||||
r"(?:dpo|datenschutzbeauftragt|data\s+protection\s+officer).*(?:aufgaben|role|function|zustaendig)",
|
||||
r"art(?:icle)?\s*44\s+(?:vo|regulation|verordnung)",
|
||||
],
|
||||
"severity": "LOW",
|
||||
"hint": (
|
||||
"Art. 44 VO 2018/1725 beschreibt die Aufgaben des DPO bei EU-Organen: "
|
||||
"Beratung, Ueberwachung, Zusammenarbeit mit dem EDSB. "
|
||||
"Es empfiehlt sich, kurz die Rolle des DPO zu erlaeutern, damit "
|
||||
"Betroffene wissen, wofuer der DPO zustaendig ist."
|
||||
),
|
||||
},
|
||||
|
||||
# == L1: Zwecke und Rechtsgrundlage ====================================
|
||||
{
|
||||
"id": "eu_purposes",
|
||||
"label": "Zwecke der Verarbeitung (Art. 15(1)(c) VO 2018/1725)",
|
||||
"level": 1, "parent": None,
|
||||
"patterns": [
|
||||
r"zweck\w*\s+(?:der|und|die)\s+(?:verarbeitung|datenerhebung|datenverarbeitung)",
|
||||
r"purpose\w*\s+(?:of|for)\s+(?:the\s+)?(?:processing|data)",
|
||||
r"zu\s+welch\w+\s+zweck",
|
||||
r"(?:data|personal\s+data)\s+(?:is|are)\s+(?:collected|processed)\s+(?:for|to)",
|
||||
],
|
||||
"severity": "HIGH",
|
||||
"hint": (
|
||||
"Art. 15(1)(c) VO 2018/1725 verlangt konkrete Zweckangaben. "
|
||||
"EU-Organe muessen jeden Verarbeitungszweck einzeln auffuehren: z.B. "
|
||||
"'Verwaltung von Bewerbungen', 'Zugangsmanagement zum Gebaeude', "
|
||||
"'Webanalyse der Internetseite'. Pauschalformulierungen sind unzulaessig."
|
||||
),
|
||||
},
|
||||
{
|
||||
"id": "eu_purposes_specific",
|
||||
"label": "Konkrete Verarbeitungszwecke benannt",
|
||||
"level": 2, "parent": "eu_purposes",
|
||||
"patterns": [
|
||||
r"(?:recruitment|selection|verwaltung|management|administration|monitoring|evaluation)",
|
||||
r"(?:human\s+resources|hr|personal|bewerbung|grant|procurement|vergabe)",
|
||||
r"(?:access|zugang|building|gebaeude|website|webseite|intranet)",
|
||||
],
|
||||
"severity": "LOW",
|
||||
"hint": (
|
||||
"Mindestens 2 konkrete Zwecke benennen, jeweils mit zugehoeriger "
|
||||
"Rechtsgrundlage. Typische EU-Organ-Zwecke: Personalverwaltung, "
|
||||
"Gebaeudezugang, IT-Sicherheitsmonitoring, Vergabeverfahren, "
|
||||
"Evaluierung von Foerderprogrammen. Pauschalformulierungen genuegen "
|
||||
"nicht dem Bestimmtheitsgrundsatz."
|
||||
),
|
||||
},
|
||||
# == L1: Rechtsgrundlage (Art. 5 statt Art. 6 DSGVO) ==================
|
||||
{
|
||||
"id": "eu_legal_basis",
|
||||
"label": "Rechtsgrundlage (Art. 5 VO 2018/1725)",
|
||||
"level": 1, "parent": None,
|
||||
"patterns": [
|
||||
r"rechtsgrundlage",
|
||||
r"art\.\s*5\s*(?:abs|absatz)?\s*\.?\s*1",
|
||||
r"legal\s+basis",
|
||||
r"lawfulness\s+of\s+processing",
|
||||
r"art(?:icle)?\s*5\s*(?:\(1\))?\s*(?:\([a-d]\))?",
|
||||
r"auf\s+grundlage\s+(?:von|des|der)\s+art",
|
||||
r"regulation\s*\(eu\)\s*2018\s*/?\s*1725",
|
||||
r"verordnung\s*\(eu\)\s*2018\s*/?\s*1725",
|
||||
],
|
||||
"severity": "HIGH",
|
||||
"hint": (
|
||||
"Art. 5(1) VO 2018/1725 enthaelt die Rechtsgrundlagen fuer EU-Organe: "
|
||||
"(a) Einwilligung, (b) Vertrag, (c) rechtliche Verpflichtung, "
|
||||
"(d) im oeffentlichen Interesse/Ausuebung oeffentlicher Gewalt. "
|
||||
"WICHTIG: Art. 5(1)(d) ist der haeufigste Tatbestand bei EU-Organen — "
|
||||
"er entspricht etwa Art. 6(1)(e) DSGVO. Art. 6(1)(f) DSGVO "
|
||||
"(berechtigtes Interesse) existiert in der VO 2018/1725 NICHT."
|
||||
),
|
||||
},
|
||||
{
|
||||
"id": "eu_legal_basis_public_interest",
|
||||
"label": "Art. 5(1)(a) — Oeffentliches Interesse / oeffentliche Gewalt",
|
||||
"level": 2, "parent": "eu_legal_basis",
|
||||
"patterns": [
|
||||
r"art\.\s*5\s*(?:\(1\))?\s*\(?(?:1\s*)?(?:let(?:ter)?\.?\s*)?a\)?",
|
||||
r"(?:oeffentlich|öffentlich).*(?:interesse|gewalt|aufgabe)",
|
||||
r"public\s+interest",
|
||||
r"(?:exercise|performance)\s+of\s+(?:official|public)\s+(?:authority|task)",
|
||||
],
|
||||
"severity": "LOW",
|
||||
"hint": (
|
||||
"Art. 5(1)(a) VO 2018/1725 ist die Hauptrechtsgrundlage fuer EU-Organe. "
|
||||
"Verlangt einen konkreten Rechtsakt als Grundlage (z.B. Verordnung, "
|
||||
"Beschluss, Basisrechtsakt der Institution). Benennen Sie den spezifischen "
|
||||
"Rechtsakt, nicht nur pauschal 'oeffentliches Interesse'."
|
||||
),
|
||||
},
|
||||
{
|
||||
"id": "eu_legal_basis_consent",
|
||||
"label": "Art. 5(1)(d) — Einwilligung",
|
||||
"level": 2, "parent": "eu_legal_basis",
|
||||
"patterns": [
|
||||
r"art\.\s*5\s*(?:\(1\))?\s*\(?(?:1\s*)?(?:let(?:ter)?\.?\s*)?d\)?",
|
||||
r"einwilligung\s+(?:gem|nach|i\.?\s*s\.?\s*d\.?)",
|
||||
r"consent\s+(?:of|given\s+by)\s+the\s+data\s+subject",
|
||||
],
|
||||
"severity": "LOW",
|
||||
"hint": (
|
||||
"Bei Einwilligung (Art. 5(1)(d) VO 2018/1725) muss auf das jederzeitige "
|
||||
"Widerrufsrecht hingewiesen werden (Art. 7(3) VO 2018/1725). "
|
||||
"Achtung: EU-Organe sollten Einwilligung nur als Rechtsgrundlage waehlen, "
|
||||
"wenn keine andere Grundlage greift — wegen des Machtungleichgewichts "
|
||||
"zwischen Institution und Einzelperson (EDSB-Leitlinien)."
|
||||
),
|
||||
},
|
||||
|
||||
# == L1: Empfaenger ====================================================
|
||||
{
|
||||
"id": "eu_recipients",
|
||||
"label": "Empfaenger (Art. 15(1)(e) VO 2018/1725)",
|
||||
"level": 1, "parent": None,
|
||||
"patterns": [
|
||||
r"empf(?:ae|ä)nger",
|
||||
r"(?:ueber|über|weiter)mitt(?:el|l)ung",
|
||||
r"recipient",
|
||||
r"weitergabe\s+(?:an|von)\s+daten",
|
||||
r"data\s+(?:will\s+be|are|is)\s+(?:shared|disclosed|transferred|transmitted)\s+to",
|
||||
r"auftragsverarbeit",
|
||||
r"processor",
|
||||
],
|
||||
"severity": "MEDIUM",
|
||||
"hint": (
|
||||
"Art. 15(1)(e) VO 2018/1725: Empfaenger oder Empfaengerkategorien benennen. "
|
||||
"Typisch bei EU-Organen: andere EU-Institutionen (z.B. OLAF, Rechnungshof), "
|
||||
"Mitgliedstaaten-Behoerden, IT-Dienstleister. Auftragsverarbeiter muessen "
|
||||
"nach Art. 29 VO 2018/1725 vertraglich gebunden sein."
|
||||
),
|
||||
},
|
||||
{
|
||||
"id": "eu_recipients_processor",
|
||||
"label": "Auftragsverarbeiter / Processor (Art. 29 VO 2018/1725)",
|
||||
"level": 2, "parent": "eu_recipients",
|
||||
"patterns": [
|
||||
r"auftragsverarbeit(?:er|ung)",
|
||||
r"art\.\s*29\s+(?:vo|verordnung|regulation)",
|
||||
r"art(?:icle)?\s*29",
|
||||
r"processor",
|
||||
r"sub[\-\s]?processor",
|
||||
],
|
||||
"severity": "LOW",
|
||||
"hint": (
|
||||
"Art. 29 VO 2018/1725 (entspricht Art. 28 DSGVO): "
|
||||
"Auftragsverarbeiter muessen vertraglich gebunden werden. "
|
||||
"Erwaehnen Sie, dass ein Auftragsverarbeitungsvertrag besteht. "
|
||||
"Bei Cloud-Diensten (z.B. Microsoft 365, AWS): Vertrag muss "
|
||||
"die Vorgaben von Art. 29(3) VO 2018/1725 einhalten."
|
||||
),
|
||||
},
|
||||
|
||||
# == L1: Drittlandtransfer =============================================
|
||||
{
|
||||
"id": "eu_third_country",
|
||||
"label": "Drittlandtransfer (Art. 46-50 VO 2018/1725)",
|
||||
"level": 1, "parent": None,
|
||||
"patterns": [
|
||||
r"drittland",
|
||||
r"dritt\s*staat",
|
||||
r"third\s+countr",
|
||||
r"angemessenheitsbeschluss",
|
||||
r"adequacy\s+decision",
|
||||
r"standard\s*(?:vertragsklausel|contractual\s+clause)",
|
||||
r"(?:transfer|uebermittlung|übermittlung).*(?:ausserhalb|außerhalb|outside)",
|
||||
r"(?:europ(?:ae|ä)ischen\s+wirtschaftsraum|ewr|eea)",
|
||||
r"art(?:icle)?\s*4[6-9]",
|
||||
r"art\.\s*50",
|
||||
],
|
||||
"severity": "MEDIUM",
|
||||
"hint": (
|
||||
"Art. 46-50 VO 2018/1725 (entspricht Art. 44-49 DSGVO): "
|
||||
"Drittlandtransfers erfordern Angemessenheitsbeschluss (Art. 47), "
|
||||
"geeignete Garantien (Art. 48) oder Ausnahmen (Art. 50). "
|
||||
"EDSB-Empfehlung: EU-Organe muessen besonders streng pruefen, "
|
||||
"da sie eine Vorbildfunktion fuer die Mitgliedstaaten haben."
|
||||
),
|
||||
},
|
||||
{
|
||||
"id": "eu_third_country_mechanism",
|
||||
"label": "Transfermechanismus benannt (Art. 47-48 VO 2018/1725)",
|
||||
"level": 2, "parent": "eu_third_country",
|
||||
"patterns": [
|
||||
r"standard\s*vertragsklausel|scc|standard\s+contractual",
|
||||
r"angemessenheitsbeschluss|adequacy\s+decision",
|
||||
r"art(?:icle)?\s*4[7-8]",
|
||||
r"data\s+privacy\s+framework|dpf",
|
||||
r"appropriate\s+safeguards",
|
||||
r"geeignete\s+garantien",
|
||||
],
|
||||
"severity": "MEDIUM",
|
||||
"hint": (
|
||||
"Art. 48 VO 2018/1725: Bei fehlender Angemessenheit koennen "
|
||||
"geeignete Garantien (z.B. SCC, verbindliche Verwaltungsvereinbarungen) "
|
||||
"den Transfer absichern. Der EDSB hat 2020 eigene Leitlinien zu "
|
||||
"Drittlandtransfers fuer EU-Organe veroeffentlicht."
|
||||
),
|
||||
},
|
||||
|
||||
# == L1: Speicherdauer =================================================
|
||||
{
|
||||
"id": "eu_retention",
|
||||
"label": "Speicherdauer (Art. 15(1)(g) VO 2018/1725)",
|
||||
"level": 1, "parent": None,
|
||||
"patterns": [
|
||||
r"speicherdauer",
|
||||
r"aufbewahrungsfrist",
|
||||
r"retention\s+period",
|
||||
r"(?:how\s+long|storage\s+period|data\s+retention)",
|
||||
r"l(?:oe|ö)sch(?:ung|frist)",
|
||||
r"daten\s+werden\s+gel(?:oe|ö)scht",
|
||||
r"(?:\d+\s+(?:tage|monate|jahre|days|months|years))",
|
||||
r"dauer\s+der\s+speicherung",
|
||||
r"data\s+will\s+be\s+(?:kept|stored|retained)\s+(?:for|until|during)",
|
||||
],
|
||||
"severity": "HIGH",
|
||||
"hint": (
|
||||
"Art. 15(1)(g) VO 2018/1725 verlangt die Speicherdauer oder "
|
||||
"Kriterien zu deren Festlegung. EU-Organe haben oft interne "
|
||||
"Aufbewahrungsrichtlinien (retention schedules). Nennen Sie die "
|
||||
"konkreten Fristen oder verweisen Sie auf die interne Richtlinie "
|
||||
"mit Dokumentenreferenz."
|
||||
),
|
||||
},
|
||||
{
|
||||
"id": "eu_retention_periods",
|
||||
"label": "Konkrete Zeitangaben",
|
||||
"level": 2, "parent": "eu_retention",
|
||||
"patterns": [
|
||||
r"\d+\s+(?:tage?|monate?|jahre?|days?|months?|years?)",
|
||||
r"(?:after|nach)\s+(?:the\s+)?(?:end|closure|completion|ablauf|beendigung)",
|
||||
r"retention\s+(?:schedule|policy|period)\s+(?:of|for)\s+\d+",
|
||||
],
|
||||
"severity": "MEDIUM",
|
||||
"hint": (
|
||||
"Konkrete Fristen pro Datenkategorie nennen. EU-Organe folgen "
|
||||
"typischerweise der Common Retention List (CRL) der Kommission. "
|
||||
"Beispiel: Bewerbungsdaten 2 Jahre, Finanzunterlagen 7 Jahre, "
|
||||
"Gebaeudezugangslogs 6 Monate."
|
||||
),
|
||||
},
|
||||
|
||||
# == L1: Betroffenenrechte (Art. 17-24 statt Art. 15-22 DSGVO) =========
|
||||
{
|
||||
"id": "eu_rights",
|
||||
"label": "Betroffenenrechte (Art. 17-24 VO 2018/1725)",
|
||||
"level": 1, "parent": None,
|
||||
"patterns": [
|
||||
r"recht\s+auf\s+auskunft",
|
||||
r"recht\s+auf\s+l(?:oe|ö)schung",
|
||||
r"recht\s+auf\s+berichtigung",
|
||||
r"widerspruchsrecht",
|
||||
r"right\s+to\s+(?:access|erasure|rectification|object|restrict)",
|
||||
r"betroffenenrecht",
|
||||
r"rechte\s+(?:des|der)\s+betroffenen",
|
||||
r"(?:your|data\s+subject)\s+rights",
|
||||
r"art(?:icle)?\s*(?:17|18|19|20|21|22|23|24)\s+(?:vo|regulation|verordnung)",
|
||||
],
|
||||
"severity": "HIGH",
|
||||
"hint": (
|
||||
"Art. 15(1)(h) VO 2018/1725 verlangt Nennung der Betroffenenrechte: "
|
||||
"Auskunft (Art. 17), Berichtigung (Art. 18), Loeschung (Art. 19), "
|
||||
"Einschraenkung (Art. 20), Datenportabilitaet (Art. 22), "
|
||||
"Widerspruch (Art. 23). Achtung: Die Artikelnummern unterscheiden sich "
|
||||
"von der DSGVO (Art. 15-22)! Haeufiger Fehler: DSGVO-Artikel "
|
||||
"statt VO 2018/1725 Artikel zitieren."
|
||||
),
|
||||
},
|
||||
{
|
||||
"id": "eu_rights_access",
|
||||
"label": "Recht auf Auskunft (Art. 17 VO 2018/1725)",
|
||||
"level": 2, "parent": "eu_rights",
|
||||
"patterns": [
|
||||
r"art(?:icle)?\s*17\s+(?:vo|regulation|verordnung)",
|
||||
r"art\.\s*17",
|
||||
r"recht\s+auf\s+(?:\w+\s+)?auskunft",
|
||||
r"right\s+(?:of|to)\s+access",
|
||||
],
|
||||
"severity": "LOW",
|
||||
"hint": (
|
||||
"Art. 17 VO 2018/1725 (entspricht Art. 15 DSGVO): Betroffene koennen "
|
||||
"Auskunft und eine Kopie ihrer Daten verlangen. Antwortfrist: 1 Monat "
|
||||
"(Art. 14(3) VO 2018/1725). Anfragen gehen typischerweise an den DPO "
|
||||
"der Institution."
|
||||
),
|
||||
},
|
||||
{
|
||||
"id": "eu_rights_erasure",
|
||||
"label": "Recht auf Loeschung (Art. 19 VO 2018/1725)",
|
||||
"level": 2, "parent": "eu_rights",
|
||||
"patterns": [
|
||||
r"art(?:icle)?\s*19\s+(?:vo|regulation|verordnung)",
|
||||
r"art\.\s*19",
|
||||
r"recht\s+auf\s+(?:\w+\s+)?l(?:oe|ö)schung",
|
||||
r"right\s+to\s+erasure",
|
||||
r"right\s+to\s+be\s+forgotten",
|
||||
],
|
||||
"severity": "LOW",
|
||||
"hint": (
|
||||
"Art. 19 VO 2018/1725 (entspricht Art. 17 DSGVO): "
|
||||
"Recht auf Loeschung bei Zweckentfall, Widerruf der Einwilligung "
|
||||
"oder unrechtmaessiger Verarbeitung. Erwaehnen Sie auch die "
|
||||
"Ausnahmen fuer EU-Organe: Archivzwecke im oeffentlichen Interesse, "
|
||||
"gesetzliche Aufbewahrungspflichten."
|
||||
),
|
||||
},
|
||||
|
||||
{
|
||||
"id": "eu_rights_restriction",
|
||||
"label": "Recht auf Einschraenkung (Art. 20 VO 2018/1725)",
|
||||
"level": 2, "parent": "eu_rights",
|
||||
"patterns": [
|
||||
r"art(?:icle)?\s*20\s+(?:vo|regulation|verordnung)",
|
||||
r"art\.\s*20",
|
||||
r"einschr(?:ae|ä)nkung\s+der\s+verarbeitung",
|
||||
r"right\s+to\s+restrict(?:ion)?",
|
||||
],
|
||||
"severity": "LOW",
|
||||
"hint": (
|
||||
"Art. 20 VO 2018/1725 (entspricht Art. 18 DSGVO): "
|
||||
"Recht auf Einschraenkung der Verarbeitung bei bestrittener "
|
||||
"Richtigkeit, unrechtmaessiger Verarbeitung oder laufendem "
|
||||
"Widerspruch. Wird am haeufigsten vergessen."
|
||||
),
|
||||
},
|
||||
{
|
||||
"id": "eu_rights_automated",
|
||||
"label": "Automatisierte Entscheidungen (Art. 24 VO 2018/1725)",
|
||||
"level": 2, "parent": "eu_rights",
|
||||
"patterns": [
|
||||
r"art(?:icle)?\s*24\s+(?:vo|regulation|verordnung)",
|
||||
r"art\.\s*24",
|
||||
r"automatisierte\s+entscheidung",
|
||||
r"automated\s+(?:decision|individual)",
|
||||
r"profiling",
|
||||
],
|
||||
"severity": "LOW",
|
||||
"hint": (
|
||||
"Art. 24 VO 2018/1725 (entspricht Art. 22 DSGVO): "
|
||||
"Bei automatisierten Einzelentscheidungen muessen Logik, "
|
||||
"Tragweite und Auswirkungen erklaert werden. Falls kein "
|
||||
"Profiling stattfindet, explizit verneinen."
|
||||
),
|
||||
},
|
||||
|
||||
# == L1: Beschwerderecht beim EDSB =====================================
|
||||
{
|
||||
"id": "eu_complaint",
|
||||
"label": "Beschwerderecht beim EDSB (Art. 15(1)(i) VO 2018/1725)",
|
||||
"level": 1, "parent": None,
|
||||
"patterns": [
|
||||
r"beschwerderecht",
|
||||
r"right\s+to\s+lodge\s+a\s+complaint",
|
||||
r"beschwerde.*(?:edsb|edps)",
|
||||
r"edsb",
|
||||
r"edps",
|
||||
r"europ(?:ae|ä)isch\w*\s+datenschutzbeauftragt",
|
||||
r"european\s+data\s+protection\s+supervisor",
|
||||
r"contr(?:o|ô)leur\s+europ(?:e|é)en",
|
||||
r"art(?:icle)?\s*63",
|
||||
],
|
||||
"severity": "HIGH",
|
||||
"hint": (
|
||||
"Art. 15(1)(i) VO 2018/1725: Bei EU-Organen ist der EDSB "
|
||||
"(Europaeischer Datenschutzbeauftragter / European Data Protection "
|
||||
"Supervisor) die zustaendige Aufsichtsbehoerde — NICHT die nationalen "
|
||||
"Datenschutzbehoerden. Kontakt: edps@edps.europa.eu, "
|
||||
"Rue Wiertz 60, B-1047 Bruxelles. Haeufiger Fehler: Verweis auf "
|
||||
"nationale Aufsichtsbehoerde statt EDSB."
|
||||
),
|
||||
},
|
||||
{
|
||||
"id": "eu_complaint_edps_contact",
|
||||
"label": "EDSB-Kontaktdaten angegeben",
|
||||
"level": 2, "parent": "eu_complaint",
|
||||
"patterns": [
|
||||
r"edps@edps\.europa\.eu",
|
||||
r"edps\.europa\.eu",
|
||||
r"edsb.*(?:kontakt|anschrift|adresse|e[\-\s]?mail|wiertz)",
|
||||
r"edps.*(?:contact|address|e[\-\s]?mail|wiertz)",
|
||||
r"rue\s+wiertz",
|
||||
],
|
||||
"severity": "MEDIUM",
|
||||
"hint": (
|
||||
"Vollstaendige EDSB-Kontaktdaten angeben: "
|
||||
"Europaeischer Datenschutzbeauftragter (EDSB), "
|
||||
"Rue Wiertz 60, B-1047 Bruxelles/Bruessel, "
|
||||
"edps@edps.europa.eu, https://edps.europa.eu. "
|
||||
"Haeufiger Fehler: Nur 'EDSB' erwaehnt ohne Kontaktdaten."
|
||||
),
|
||||
},
|
||||
]
|
||||
@@ -15,6 +15,7 @@ from .impressum_checks import IMPRESSUM_CHECKLIST
|
||||
from .cookie_checks import COOKIE_CHECKLIST
|
||||
from .social_media_checks import JOINT_CONTROLLER_CHECKLIST
|
||||
from .dsfa_checks import DSFA_CHECKLIST
|
||||
from .eu_institution_checks import EU_INSTITUTION_CHECKLIST
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -35,6 +36,7 @@ _CHECKLIST_MAP = {
|
||||
"social_media": (JOINT_CONTROLLER_CHECKLIST, "Art. 26 DSGVO"),
|
||||
"joint_controller": (JOINT_CONTROLLER_CHECKLIST, "Art. 26 DSGVO"),
|
||||
"dsfa": (DSFA_CHECKLIST, "Art. 35 DSGVO"),
|
||||
"eu_institution": (EU_INSTITUTION_CHECKLIST, "VO (EU) 2018/1725"),
|
||||
}
|
||||
|
||||
|
||||
@@ -218,6 +220,11 @@ def classify_document_type(title: str, url: str) -> str:
|
||||
if any(kw in combined for kw in ["social media", "facebook", "instagram", "linkedin", "fanpage"]):
|
||||
if any(kw in combined for kw in ["datenschutzerkl", "datenschutz für", "datenschutzinformation"]):
|
||||
return "social_media"
|
||||
# EU institution check BEFORE generic privacy — 2018/1725 is more specific
|
||||
if any(kw in combined for kw in ["2018/1725", "2018 1725", "regulation (eu)",
|
||||
"verordnung (eu)", "edsb", "edps",
|
||||
"european data protection supervisor"]):
|
||||
return "eu_institution"
|
||||
if any(kw in combined for kw in ["datenschutz", "privacy", "dsgvo", "data protection", "données"]):
|
||||
return "dse"
|
||||
if any(kw in combined for kw in ["widerruf", "withdrawal", "rétractation", "desistimiento"]):
|
||||
|
||||
Reference in New Issue
Block a user