feat: Add actionable hints to all 138 compliance checks
Build + Deploy / build-admin-compliance (push) Successful in 1m40s
Build + Deploy / build-backend-compliance (push) Successful in 7s
Build + Deploy / build-ai-sdk (push) Successful in 35s
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 8s
Build + Deploy / build-dsms-gateway (push) Successful in 7s
Build + Deploy / build-dsms-node (push) Successful in 8s
CI / branch-name (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / loc-budget (push) Failing after 16s
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
CI / nodejs-build (push) Successful in 2m50s
CI / dep-audit (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / test-go (push) Failing after 40s
CI / test-python-backend (push) Successful in 37s
CI / test-python-document-crawler (push) Successful in 25s
CI / test-python-dsms-gateway (push) Successful in 23s
CI / validate-canonical-controls (push) Successful in 15s
Build + Deploy / trigger-orca (push) Successful in 2m28s

Each check now has a "hint" field explaining what is missing and
what the customer should do to fix it. Hints are shown in the
frontend below failed checks in red text.

Examples:
- "Bei Verarbeitung auf Basis von Art. 6(1)(f) muss dokumentiert
  werden, warum Ihr berechtigtes Interesse die Rechte der
  Betroffenen ueberwiegt."
- "Die ladungsfaehige Anschrift fehlt. Erforderlich: Strasse,
  Hausnummer, PLZ und Ort."

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-05-07 14:05:01 +02:00
parent 912684644e
commit 293c58d0dd
10 changed files with 151 additions and 0 deletions
@@ -19,6 +19,7 @@ ART13_CHECKLIST = [
r"responsible\s+(?:party|for)",
],
"severity": "HIGH",
"hint": "Der Name und die Kontaktdaten des Verantwortlichen muessen gemaess Art. 13(1)(a) DSGVO angegeben werden. Ergaenzen Sie: Firmenname, Rechtsform, Anschrift, E-Mail und Telefon.",
},
{
"id": "controller_address",
@@ -29,6 +30,7 @@ ART13_CHECKLIST = [
r"[a-z\u00c0-\u017e]\w+(?:str|stra(?:ss|ß)e|weg|platz|allee|gasse|ring|damm)\s*\.?\s*\d",
],
"severity": "MEDIUM",
"hint": "Die ladungsfaehige Anschrift des Verantwortlichen fehlt oder ist unvollstaendig. Erforderlich: Strasse, Hausnummer, PLZ und Ort. Ein Postfach allein genuegt nicht.",
},
{
"id": "controller_email",
@@ -38,6 +40,7 @@ ART13_CHECKLIST = [
r"[a-z0-9._%+\-]+@[a-z0-9.\-]+\.[a-z]{2,}",
],
"severity": "MEDIUM",
"hint": "Eine E-Mail-Adresse des Verantwortlichen muss angegeben werden, damit Betroffene ihre Rechte ausueben koennen.",
},
{
"id": "controller_phone",
@@ -48,6 +51,7 @@ ART13_CHECKLIST = [
r"\+49\s*[\d\s/\-]{8,}",
],
"severity": "MEDIUM",
"hint": "Eine Telefonnummer sollte angegeben werden, um eine niedrigschwellige Kontaktaufnahme zu ermoeglichen.",
},
# ── L1: Datenschutzbeauftragter ───────────────────────────────────
@@ -61,6 +65,7 @@ ART13_CHECKLIST = [
r"dsb", r"dpo",
],
"severity": "MEDIUM",
"hint": "Falls ein Datenschutzbeauftragter bestellt ist (Pflicht ab 20 Personen regelmaessig mit Datenverarbeitung), muessen dessen Kontaktdaten angegeben werden (Art. 13(1)(b) DSGVO).",
},
{
"id": "dpo_contact",
@@ -72,6 +77,7 @@ ART13_CHECKLIST = [
r"datenschutz@",
],
"severity": "MEDIUM",
"hint": "Fuer den DSB muss mindestens eine direkte Kontaktmoeglichkeit angegeben sein (E-Mail-Adresse oder Telefon). Empfehlung: datenschutz@ihredomain.de",
},
# ── L1: Zwecke der Verarbeitung ───────────────────────────────────
@@ -87,6 +93,7 @@ ART13_CHECKLIST = [
r"daten\s+werden\s+(?:zu|fuer|für)\s+(?:folgende|diese)",
],
"severity": "HIGH",
"hint": "Art. 13(1)(c) verlangt eine Angabe der Zwecke, fuer die personenbezogene Daten verarbeitet werden. Listen Sie alle Verarbeitungszwecke konkret auf (z.B. Vertragserfuellung, Newsletter, Webanalyse).",
},
{
"id": "purposes_specific",
@@ -97,6 +104,7 @@ ART13_CHECKLIST = [
r"(?:bereitstellung|betrieb|sicherheit|optimierung)\s+(?:der|des|unserer|unseres)",
],
"severity": "LOW",
"hint": "Allgemeine Formulierungen wie 'Wir verarbeiten Daten' genuegen nicht. Nennen Sie konkrete Zwecke: z.B. Vertragsabwicklung, Kontaktanfragen, Website-Analyse, Newsletter-Versand.",
},
# ── L1: Rechtsgrundlage ───────────────────────────────────────────
@@ -114,6 +122,7 @@ ART13_CHECKLIST = [
r"einwilligung\s+gem",
],
"severity": "HIGH",
"hint": "Fuer jeden Verarbeitungszweck muss die Rechtsgrundlage nach Art. 6(1) DSGVO genannt werden: Einwilligung (a), Vertrag (b), rechtliche Pflicht (c), lebenswichtige Interessen (d), oeffentliches Interesse (e) oder berechtigtes Interesse (f).",
},
{
"id": "legal_basis_consent_6a",
@@ -124,6 +133,7 @@ ART13_CHECKLIST = [
r"einwilligung\s+(?:gem|nach|i\.?\s*s\.?\s*d\.?)",
],
"severity": "LOW",
"hint": "Wenn Daten auf Basis einer Einwilligung verarbeitet werden (z.B. Newsletter, Cookies), sollte Art. 6(1)(a) DSGVO als Rechtsgrundlage genannt und auf das Widerrufsrecht hingewiesen werden.",
},
{
"id": "legal_basis_contract_6b",
@@ -135,6 +145,7 @@ ART13_CHECKLIST = [
r"durchf(?:ue|ü)hrung\s+(?:eines|des|vorvertragliche)",
],
"severity": "LOW",
"hint": "Daten, die zur Vertragserfuellung oder vorvertraglichen Massnahmen verarbeitet werden, sollten auf Art. 6(1)(b) DSGVO gestuetzt werden.",
},
{
"id": "legal_basis_interest_6f",
@@ -145,6 +156,7 @@ ART13_CHECKLIST = [
r"berechtigte[sn]?\s+interesse",
],
"severity": "LOW",
"hint": "Wenn Sie sich auf ein berechtigtes Interesse (Art. 6(1)(f)) stuetzen, muss dieses Interesse konkret benannt werden (z.B. Betrugspraevention, IT-Sicherheit, Direktwerbung).",
},
{
"id": "legal_basis_balancing",
@@ -156,6 +168,7 @@ ART13_CHECKLIST = [
r"abw(?:ae|ä)gung.*(?:recht|interesse|freiheit)",
],
"severity": "LOW",
"hint": "Bei Verarbeitung auf Basis von Art. 6(1)(f) muss dokumentiert werden, warum Ihr berechtigtes Interesse die Rechte der Betroffenen ueberwiegt. Ergaenzen Sie eine Interessenabwaegung oder verweisen Sie auf eine solche.",
},
# ── L1: Empfaenger ────────────────────────────────────────────────
@@ -170,6 +183,7 @@ ART13_CHECKLIST = [
r"auftragsverarbeit",
],
"severity": "MEDIUM",
"hint": "Empfaenger oder Kategorien von Empfaengern der Daten muessen benannt werden (Art. 13(1)(e) DSGVO). Beispiele: Hosting-Anbieter, Zahlungsdienstleister, Steuerberater.",
},
{
"id": "recipients_categories",
@@ -180,6 +194,7 @@ ART13_CHECKLIST = [
r"(?:dienstleister|auftragnehmer|subunternehmer).*(?:fuer|für|im bereich)",
],
"severity": "LOW",
"hint": "Listen Sie konkrete Empfaenger-Kategorien auf: z.B. IT-Dienstleister, Hosting-Anbieter, Zahlungsabwickler, Versandunternehmen, Steuerberater. 'Dritte' allein genuegt nicht.",
},
{
"id": "recipients_processor",
@@ -191,6 +206,7 @@ ART13_CHECKLIST = [
r"avv|av-vertrag|auftragsverarbeitungsvertrag",
],
"severity": "LOW",
"hint": "Falls Auftragsverarbeiter eingesetzt werden (z.B. Cloud-Hosting, E-Mail-Service), sollte dies erwaehnt und auf bestehende AVVs nach Art. 28 DSGVO hingewiesen werden.",
},
# ── L1: Drittlandtransfer ─────────────────────────────────────────
@@ -207,6 +223,7 @@ ART13_CHECKLIST = [
r"privacy\s+shield", r"data\s+privacy\s+framework",
],
"severity": "MEDIUM",
"hint": "Falls Daten ausserhalb des EWR uebermittelt werden (z.B. USA-basierte Dienste wie Google, Microsoft, AWS), muss dies angegeben werden — inkl. des Empfaengerlandes und der Schutzgarantien.",
},
{
"id": "third_country_mechanism",
@@ -219,6 +236,7 @@ ART13_CHECKLIST = [
r"art\.\s*4[5-9]",
],
"severity": "MEDIUM",
"hint": "Bei Drittlandtransfers muss der konkrete Schutzmechanismus benannt werden: Angemessenheitsbeschluss (Art. 45), Standardvertragsklauseln/SCC (Art. 46(2)(c)) oder EU-US Data Privacy Framework. Ohne Angabe ist der Transfer nicht DSGVO-konform dokumentiert.",
},
# ── L1: Speicherdauer ─────────────────────────────────────────────
@@ -237,6 +255,7 @@ ART13_CHECKLIST = [
r"gesetzliche.*aufbewahrung",
],
"severity": "HIGH",
"hint": "Die Speicherdauer oder die Kriterien zur Festlegung der Dauer muessen angegeben werden (Art. 13(2)(a) DSGVO). Nennen Sie konkrete Fristen (z.B. '10 Jahre steuerrechtliche Aufbewahrung') oder Loeschkriterien.",
},
{
"id": "retention_periods",
@@ -248,6 +267,7 @@ ART13_CHECKLIST = [
r"(?:nach|innerhalb)\s+(?:von\s+)?\d+\s+(?:tag|monat|jahr)",
],
"severity": "MEDIUM",
"hint": "Statt allgemeiner Aussagen ('so lange wie noetig') sollten konkrete Fristen stehen: z.B. 'Logfiles: 7 Tage', 'Vertragsdaten: 10 Jahre (§257 HGB)', 'Bewerbungen: 6 Monate nach Absage'.",
},
{
"id": "retention_deletion",
@@ -259,6 +279,7 @@ ART13_CHECKLIST = [
r"nach\s+(?:ablauf|wegfall).*(?:gel(?:oe|ö)scht|l(?:oe|ö)sch)",
],
"severity": "LOW",
"hint": "Beschreiben Sie, wie und wann Daten geloescht werden: z.B. 'Nach Ablauf der Aufbewahrungsfrist werden die Daten routinemaessig geloescht.' oder Verweis auf ein internes Loeschkonzept.",
},
# ── L1: Betroffenenrechte ─────────────────────────────────────────
@@ -275,6 +296,7 @@ ART13_CHECKLIST = [
r"ihnen\s+(?:stehen|steht)\s+(?:ein|folgende)\s+recht",
],
"severity": "HIGH",
"hint": "Die Betroffenenrechte (Art. 15-22 DSGVO) muessen vollstaendig aufgezaehlt werden: Auskunft, Berichtigung, Loeschung, Einschraenkung, Datenportabilitaet, Widerspruch und ggf. automatisierte Entscheidungen.",
},
{
"id": "rights_art15",
@@ -282,6 +304,7 @@ ART13_CHECKLIST = [
"level": 2, "parent": "rights",
"patterns": [r"art\.\s*15", r"recht\s+auf\s+auskunft", r"right\s+(?:of|to)\s+access"],
"severity": "LOW",
"hint": "Ergaenzen Sie den Hinweis auf das Auskunftsrecht nach Art. 15 DSGVO: Betroffene koennen eine Kopie aller ueber sie gespeicherten Daten anfordern.",
},
{
"id": "rights_art16",
@@ -289,6 +312,7 @@ ART13_CHECKLIST = [
"level": 2, "parent": "rights",
"patterns": [r"art\.\s*16", r"recht\s+auf\s+berichtigung", r"right\s+to\s+rectification"],
"severity": "LOW",
"hint": "Ergaenzen Sie das Recht auf Berichtigung nach Art. 16 DSGVO: Betroffene koennen die Korrektur unrichtiger Daten verlangen.",
},
{
"id": "rights_art17",
@@ -296,6 +320,7 @@ ART13_CHECKLIST = [
"level": 2, "parent": "rights",
"patterns": [r"art\.\s*17", r"recht\s+auf\s+l(?:oe|ö)schung", r"right\s+to\s+erasure"],
"severity": "LOW",
"hint": "Ergaenzen Sie das Recht auf Loeschung ('Recht auf Vergessenwerden') nach Art. 17 DSGVO.",
},
{
"id": "rights_art18",
@@ -303,6 +328,7 @@ ART13_CHECKLIST = [
"level": 2, "parent": "rights",
"patterns": [r"art\.\s*18", r"einschr(?:ae|ä)nkung\s+der\s+verarbeitung", r"right\s+to\s+restriction"],
"severity": "LOW",
"hint": "Ergaenzen Sie das Recht auf Einschraenkung der Verarbeitung nach Art. 18 DSGVO.",
},
{
"id": "rights_art20",
@@ -310,6 +336,7 @@ ART13_CHECKLIST = [
"level": 2, "parent": "rights",
"patterns": [r"art\.\s*20", r"daten(?:ue|ü)bertragbarkeit|datenportabilit", r"right\s+to\s+data\s+portability"],
"severity": "LOW",
"hint": "Ergaenzen Sie das Recht auf Datenuebertragbarkeit nach Art. 20 DSGVO: Betroffene koennen ihre Daten in einem maschinenlesbaren Format erhalten.",
},
{
"id": "rights_art21",
@@ -317,6 +344,7 @@ ART13_CHECKLIST = [
"level": 2, "parent": "rights",
"patterns": [r"art\.\s*21", r"widerspruchsrecht", r"right\s+to\s+object"],
"severity": "LOW",
"hint": "Ergaenzen Sie das Widerspruchsrecht nach Art. 21 DSGVO, insbesondere bei Verarbeitung auf Basis von Art. 6(1)(e) oder (f). Der Hinweis muss gesondert und in klarer Sprache erfolgen.",
},
{
"id": "rights_art22_profiling",
@@ -327,6 +355,7 @@ ART13_CHECKLIST = [
r"profiling", r"automated\s+(?:decision|individual)",
],
"severity": "LOW",
"hint": "Falls automatisierte Entscheidungen oder Profiling stattfinden, muss dies offengelegt werden (Art. 22 DSGVO). Falls nicht: Ergaenzen Sie 'Es findet keine automatisierte Entscheidungsfindung einschliesslich Profiling statt.'",
},
# ── L1: Beschwerderecht ───────────────────────────────────────────
@@ -343,6 +372,7 @@ ART13_CHECKLIST = [
r"(?:zust(?:ae|ä)ndige|competent)\s+(?:beh(?:oe|ö)rde|authority)",
],
"severity": "MEDIUM",
"hint": "Betroffene muessen auf ihr Recht hingewiesen werden, sich bei einer Aufsichtsbehoerde zu beschweren (Art. 77 DSGVO). Nennen Sie idealerweise die zustaendige Landesbehoerde.",
},
{
"id": "complaint_authority_named",
@@ -355,5 +385,6 @@ ART13_CHECKLIST = [
r"(?:bayerische|hessische|s(?:ae|ä)chsische|berliner)\s+(?:datenschutz|aufsicht)",
],
"severity": "LOW",
"hint": "Nennen Sie die zustaendige Aufsichtsbehoerde mit Name und Kontakt. Z.B.: 'Der Landesbeauftragte fuer den Datenschutz und die Informationsfreiheit Baden-Wuerttemberg' mit Adresse und Website.",
},
]