b363c28539
Split dsi_document_checker.py (466 LOC) into doc_checks/ package (9 files). Two-pass L1→L2 logic: L1 checks "Is it mentioned?", L2 checks "Is it correct?" (e.g. controller has full address, specific Art. 6 lit., concrete time periods). 138 total checks (62 L1 + 76 L2) across 7 doc types: - DSE Art. 13: 31, Impressum §5 TMG: 16, Cookie §25 TDDDG: 15 - Widerruf §355: 15, AGB §305ff: 21, Social Media Art. 26: 20, DSFA Art. 35: 18 Frontend: hierarchical L1→L2 display with dual progress bars (green=completeness, blue=correctness). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
231 lines
9.1 KiB
Python
231 lines
9.1 KiB
Python
"""
|
|
DSFA checks — Art. 35 DSGVO (Datenschutz-Folgenabschaetzung).
|
|
|
|
Level 1: Pflichtangabe erwaehnt?
|
|
Level 2: Pflichtangabe korrekt/vollstaendig?
|
|
"""
|
|
|
|
DSFA_CHECKLIST = [
|
|
# ── L1: Schwellwertanalyse ────────────────────────────────────────
|
|
{
|
|
"id": "trigger",
|
|
"label": "Schwellwertanalyse / Ausloesepruefung (Art. 35(1))",
|
|
"level": 1, "parent": None,
|
|
"patterns": [
|
|
r"art\.\s*35\s*(?:abs|absatz)?\s*\.?\s*1",
|
|
r"hohes\s+risiko",
|
|
r"voraussichtlich.*risiko",
|
|
r"schwellwert",
|
|
r"folgen.*(?:verarbeitung|schutz).*personenbezogen",
|
|
],
|
|
"severity": "HIGH",
|
|
},
|
|
|
|
# ── L1: Beschreibung der Verarbeitungsvorgaenge ───────────────────
|
|
{
|
|
"id": "description",
|
|
"label": "Beschreibung der Verarbeitungsvorgaenge (Art. 35(7)(a))",
|
|
"level": 1, "parent": None,
|
|
"patterns": [
|
|
r"beschreibung.*verarbeitung", r"verarbeitungsvorg(?:ae|ä)ng",
|
|
r"systematische\s+beschreibung", r"gegenstand.*verarbeitung",
|
|
r"social\s*media.*(?:angebot|nutzung|besteht\s+aus)",
|
|
r"(?:kan(?:ae|ä)le|plattform).*(?:facebook|twitter|instagram|youtube|linkedin|xing)",
|
|
],
|
|
"severity": "HIGH",
|
|
},
|
|
{
|
|
"id": "processing_named",
|
|
"label": "Konkreter Verarbeitungsvorgang benannt",
|
|
"level": 2, "parent": "description",
|
|
"patterns": [
|
|
r"(?:betrieb|nutzung|verwaltung|pflege)\s+(?:der|von|unserer|eines)\s+(?:seite|profil|kanal|account|fanpage|pr(?:ae|ä)senz)",
|
|
r"(?:verarbeitung|erhebung|speicherung)\s+(?:von|der)\s+(?:nutzerdaten|personenbezogen|besucher|mitglieder)",
|
|
],
|
|
"severity": "LOW",
|
|
},
|
|
|
|
# ── L1: Notwendigkeit / Verhaeltnismaessigkeit ────────────────────
|
|
{
|
|
"id": "necessity",
|
|
"label": "Notwendigkeit und Verhaeltnismaessigkeit (Art. 35(7)(b))",
|
|
"level": 1, "parent": None,
|
|
"patterns": [
|
|
r"notwendigkeit", r"verh(?:ae|ä)ltnism(?:ae|ä)(?:ss|ß)igkeit",
|
|
r"erforderlichkeit", r"zweckbindung",
|
|
r"geringen?\s+umfang",
|
|
r"nur\s+(?:die|sehr).*daten.*(?:verarbeitet|erhoben)",
|
|
r"freiwillig\s+angegeben",
|
|
],
|
|
"severity": "HIGH",
|
|
},
|
|
{
|
|
"id": "legal_basis_dsfa",
|
|
"label": "Rechtsgrundlage fuer die Verarbeitung",
|
|
"level": 2, "parent": "necessity",
|
|
"patterns": [
|
|
r"rechtsgrundlage.*(?:art\.\s*6|berechtigte|einwilligung)",
|
|
r"art\.\s*6\s*(?:abs\.\s*)?1\s*(?:lit\.\s*)?[a-f]",
|
|
r"(?:einwilligung|vertrag|berechtigt).*(?:rechtsgrundlage|grundlage)",
|
|
],
|
|
"severity": "LOW",
|
|
},
|
|
|
|
# ── L1: Risikobewertung ───────────────────────────────────────────
|
|
{
|
|
"id": "risks",
|
|
"label": "Risikobewertung fuer Betroffene (Art. 35(7)(c))",
|
|
"level": 1, "parent": None,
|
|
"patterns": [
|
|
r"risiko.*(?:bewertung|analyse|einsch(?:ae|ä)tzung|abw(?:ae|ä)gung)",
|
|
r"risiken.*(?:rechte|freiheit)",
|
|
r"eintrittswahrscheinlichkeit",
|
|
r"schwere.*(?:risiko|auswirkung)",
|
|
r"hohes\s+risiko.*(?:rechte|freiheit)",
|
|
r"systematische\s+beobachtung",
|
|
],
|
|
"severity": "HIGH",
|
|
},
|
|
{
|
|
"id": "risk_probability",
|
|
"label": "Eintrittswahrscheinlichkeit bewertet",
|
|
"level": 2, "parent": "risks",
|
|
"patterns": [
|
|
r"eintrittswahrscheinlichkeit",
|
|
r"(?:wahrscheinlichkeit|likelihood)\s*[:\|]",
|
|
r"(?:gering|mittel|hoch)\w*\s+(?:wahrscheinlichkeit|eintritt)",
|
|
],
|
|
"severity": "MEDIUM",
|
|
},
|
|
{
|
|
"id": "risk_severity",
|
|
"label": "Schwere/Auswirkung bewertet",
|
|
"level": 2, "parent": "risks",
|
|
"patterns": [
|
|
r"(?:schwere|auswirkung|schadensh(?:oe|ö)he|schadenpotential|schadenpotenzial)\s*[:\|]",
|
|
r"(?:gering|mittel|hoch|kritisch)\w*\s+(?:schwere|auswirkung|schaden)",
|
|
r"(?:physisch|materiell|immateriell)\w*\s+(?:schaden|nachteil|beeintr(?:ae|ä)chtigung)",
|
|
],
|
|
"severity": "MEDIUM",
|
|
},
|
|
|
|
# ── L1: Abhilfemassnahmen ─────────────────────────────────────────
|
|
{
|
|
"id": "measures",
|
|
"label": "Abhilfemassnahmen (Art. 35(7)(d))",
|
|
"level": 1, "parent": None,
|
|
"patterns": [
|
|
r"abhilfe", r"(?:ma(?:ss|ß)nahm).*(?:risiko|schutz|minderung)",
|
|
r"schutzma(?:ss|ß)nahm",
|
|
r"(?:technisch|organisatorisch).*ma(?:ss|ß)nahm",
|
|
r"tom",
|
|
r"risiko.*(?:minim|reduz|begrenzen)",
|
|
],
|
|
"severity": "HIGH",
|
|
},
|
|
{
|
|
"id": "tom_encryption",
|
|
"label": "Verschluesselung als Massnahme",
|
|
"level": 2, "parent": "measures",
|
|
"patterns": [
|
|
r"verschl(?:ue|ü)sselung|encryption|ssl|tls|https",
|
|
r"(?:transport|ende[\-\s]zu[\-\s]ende)[\-\s]?verschl(?:ue|ü)sselung",
|
|
],
|
|
"severity": "LOW",
|
|
},
|
|
{
|
|
"id": "tom_pseudonymization",
|
|
"label": "Pseudonymisierung als Massnahme",
|
|
"level": 2, "parent": "measures",
|
|
"patterns": [
|
|
r"pseudonymisierung|anonymisierung",
|
|
r"(?:pseudonymisiert|anonymisiert).*(?:daten|verarbeit)",
|
|
],
|
|
"severity": "LOW",
|
|
},
|
|
{
|
|
"id": "tom_access_control",
|
|
"label": "Zugriffskontrolle als Massnahme",
|
|
"level": 2, "parent": "measures",
|
|
"patterns": [
|
|
r"zugriffskontrolle|zugangskontrolle|zutrittskontrolle",
|
|
r"(?:berechtigungs|rollen).*(?:konzept|management|vergabe)",
|
|
r"(?:need[\-\s]to[\-\s]know|least\s+privilege|minimalprinzip)",
|
|
],
|
|
"severity": "LOW",
|
|
},
|
|
{
|
|
"id": "tom_logging",
|
|
"label": "Protokollierung/Logging als Massnahme",
|
|
"level": 2, "parent": "measures",
|
|
"patterns": [
|
|
r"(?:protokollierung|logging|audit[\-\s]?trail|nachvollziehbarkeit)",
|
|
r"(?:zugriff|(?:ae|ä)nderung).*(?:protokoll|logging|nachvollzieh)",
|
|
],
|
|
"severity": "LOW",
|
|
},
|
|
|
|
# ── L1: Landesbehoerden ───────────────────────────────────────────
|
|
{
|
|
"id": "lfdi",
|
|
"label": "Beruecksichtigung Landesbehoerden-Richtlinie",
|
|
"level": 1, "parent": None,
|
|
"patterns": [
|
|
r"l(?:an)?fdi", r"landesbeauftragt.*datenschutz",
|
|
r"landes.?datenschutz",
|
|
r"richtlinie.*(?:land|lfdi|landes)",
|
|
r"(?:aufsichtsbeh(?:oe|ö)rde|beh(?:oe|ö)rde).*(?:richtlinie|empfehlung|vorgabe)",
|
|
],
|
|
"severity": "MEDIUM",
|
|
},
|
|
|
|
# ── L1: Einbeziehung DSB ──────────────────────────────────────────
|
|
{
|
|
"id": "stakeholders",
|
|
"label": "Einbeziehung des DSB (Art. 35(2))",
|
|
"level": 1, "parent": None,
|
|
"patterns": [
|
|
r"datenschutzbeauftragt.*(?:einbez|konsult|beteilig|rat)",
|
|
r"dsb.*(?:konsult|einbez|rat)",
|
|
r"stellungnahme.*dsb",
|
|
r"(?:rat|empfehlung).*datenschutzbeauftragt",
|
|
],
|
|
"severity": "MEDIUM",
|
|
},
|
|
{
|
|
"id": "dsb_opinion_documented",
|
|
"label": "DSB-Stellungnahme dokumentiert",
|
|
"level": 2, "parent": "stakeholders",
|
|
"patterns": [
|
|
r"stellungnahme.*(?:dsb|datenschutzbeauftragt)",
|
|
r"(?:dsb|datenschutzbeauftragt).*(?:stellungnahme|empfiehlt|bewertet|best(?:ae|ä)tigt)",
|
|
r"(?:empfehlung|beurteilung|einsch(?:ae|ä)tzung)\s+(?:des|der)\s+(?:dsb|datenschutzbeauftragt)",
|
|
],
|
|
"severity": "LOW",
|
|
},
|
|
|
|
# ── L1: Dokumentation ─────────────────────────────────────────────
|
|
{
|
|
"id": "documentation",
|
|
"label": "Dokumentation der Ergebnisse",
|
|
"level": 1, "parent": None,
|
|
"patterns": [
|
|
r"(?:dokument|ergebnis|bericht).*(?:dsfa|folgenabsch(?:ae|ä)tzung)",
|
|
r"(?:ergebnis|schlussfolgerung|bewertung).*(?:risiko|verarbeitung)",
|
|
r"vorliegend.*(?:dsfa|analyse|bewertung|absch(?:ae|ä)tzung)",
|
|
],
|
|
"severity": "MEDIUM",
|
|
},
|
|
{
|
|
"id": "review_cycle",
|
|
"label": "Ueberpruefungszyklus/Review-Termin",
|
|
"level": 2, "parent": "documentation",
|
|
"patterns": [
|
|
r"(?:ueberpr(?:ue|ü)f|überpr(?:ue|ü)f|review|aktualisierung).*(?:zyklus|turnus|j(?:ae|ä)hrlich|regelm(?:ae|ä)(?:ss|ß)ig|termin)",
|
|
r"(?:regelm(?:ae|ä)(?:ss|ß)ig|j(?:ae|ä)hrlich|quartal|halbjahr).*(?:ueberpr(?:ue|ü)f|überpr(?:ue|ü)f|review|aktualisier)",
|
|
r"n(?:ae|ä)chste\s+(?:ueberpr(?:ue|ü)fung|überprüfung|review)",
|
|
],
|
|
"severity": "LOW",
|
|
},
|
|
]
|