# Risk Engine Spezifikation -- BreakPilot Compliance ## Ueberblick Die Risk Engine berechnet auf Basis von **Impact** und **Likelihood** einen Risiko-Score (0--100), ordnet diesem Score ein **Risk-Tier** zu und leitet daraus die erforderlichen technisch-organisatorischen Massnahmen (TOM) ab. Sie ergaenzt die bestehende vereinfachte I*L-Bewertung (1--5-Skala) um eine feinere Granularitaet (0--10-Skala). --- ## 1. Impact-Heuristik (0--10 Skala) Der Impact-Wert beschreibt die Schwere des potenziellen Schadens fuer betroffene Personen. | Faktor | Punkte | DSGVO-Bezug | |--------|--------|-------------| | Basis-Impact (jede Verarbeitung) | +2 | -- | | Besondere Datenkategorien (Art. 9) oder Straftaten (Art. 10) | +2 | Art. 9, Art. 10 DSGVO | | Kinder oder schutzbeduerftige Personen betroffen | +2 | ErwGr. 75, Art. 8 DSGVO | | Mehr als 10.000 Betroffene | +1 | ErwGr. 91 | | Automatisierte Einzelentscheidungen / Profiling | +1 | Art. 22 DSGVO | | Gesundheits- oder Finanzdaten | +1 | Art. 9 Abs. 2 lit. h | | Systematische Ueberwachung / oeffentlich zugaenglicher Bereich | +1 | Art. 35 Abs. 3 lit. c | **Cap:** `I = min(Summe, 10)` ### Beispiel-Berechnung ``` Szenario: Schul-App mit Schueler-Gesundheitsdaten Basis = 2 + Besondere Kategorien (Gesundheit) = +2 + Kinder betroffen = +2 + Gesundheitsdaten = +1 ----------------------------------------- Impact (roh) = 7 Impact (nach Cap) = min(7, 10) = 7 ``` ### Implementierung ```typescript interface ImpactContext { special_categories: boolean; // Art. 9/10 Daten vulnerable_persons: boolean; // Kinder, Schutzbeduerftige data_subject_count: number; // Anzahl Betroffene automated_decisions: boolean; // Art. 22 Profiling health_or_finance: boolean; // Gesundheits-/Finanzdaten systematic_monitoring: boolean; // Systematische Ueberwachung } function calculateImpact(ctx: ImpactContext): number { let impact = 2; // Basis if (ctx.special_categories) impact += 2; if (ctx.vulnerable_persons) impact += 2; if (ctx.data_subject_count > 10_000) impact += 1; if (ctx.automated_decisions) impact += 1; if (ctx.health_or_finance) impact += 1; if (ctx.systematic_monitoring) impact += 1; return Math.min(impact, 10); } ``` --- ## 2. Likelihood-Heuristik (0--10 Skala) Der Likelihood-Wert beschreibt die Eintrittswahrscheinlichkeit einer Datenschutzverletzung. | Faktor | Punkte | Begruendung | |--------|--------|-------------| | Basis-Likelihood (jede Verarbeitung) | +2 | -- | | Internet-Exponierung (oeffentlich zugaengliche Systeme) | +2 | Groessere Angriffsflaeche | | Viele Subprozessoren / kein zentrales IAM | +2 | Kontrollverlust, Zugriffschaos | | Fehlendes Logging / SIEM | +2 | Keine Erkennung von Vorfaellen | | Cloud ohne Verschluesselung at rest | +1 | Daten bei Breach lesbar | | Fehlendes Patch-Management / veralteter Software-Stand | +1 | Bekannte Schwachstellen | | Fehlende Mitarbeiterschulung | +1 | Social Engineering, Fehlbedienung | **Cap:** `L = min(Summe, 10)` ### Beispiel-Berechnung ``` Szenario: Cloud-SaaS ohne zentrale Zugriffsverwaltung Basis = 2 + Internet-Exponierung = +2 + Kein zentrales IAM = +2 + Cloud ohne Verschluesselung at rest = +1 ----------------------------------------- Likelihood (roh) = 7 Likelihood (nach Cap) = min(7, 10) = 7 ``` ### Implementierung ```typescript interface LikelihoodContext { internet_exposed: boolean; // Oeffentlich erreichbar many_subprocessors: boolean; // Viele AVV-Partner / kein IAM no_logging: boolean; // Kein SIEM / Audit-Log cloud_unencrypted: boolean; // Cloud ohne Verschluesselung at rest no_patch_management: boolean; // Veralteter Software-Stand no_employee_training: boolean; // Keine DS-Schulung } function calculateLikelihood(ctx: LikelihoodContext): number { let likelihood = 2; // Basis if (ctx.internet_exposed) likelihood += 2; if (ctx.many_subprocessors) likelihood += 2; if (ctx.no_logging) likelihood += 2; if (ctx.cloud_unencrypted) likelihood += 1; if (ctx.no_patch_management) likelihood += 1; if (ctx.no_employee_training) likelihood += 1; return Math.min(likelihood, 10); } ``` --- ## 3. Score-Berechnung Der Risiko-Score ergibt sich aus dem Produkt von Impact und Likelihood: ``` Score = round(I * L) ``` | Parameter | Bereich | |-----------|---------| | Impact (I) | 0--10 | | Likelihood (L) | 0--10 | | **Score** | **0--100** | ### Implementierung ```typescript function calculateRiskScore(impact: number, likelihood: number): number { return Math.round( Math.min(impact, 10) * Math.min(likelihood, 10) ); } ``` ### Risiko-Matrix (Impact x Likelihood) ``` L\I │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 ────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼───── 2 │ 4 │ 6 │ 8 │ 10 │ 12 │ 14 │ 16 │ 18 │ 20 3 │ 6 │ 9 │ 12 │ 15 │ 18 │ 21 │ 24 │ 27 │ 30 4 │ 8 │ 12 │ 16 │ 20 │ 24 │ 28 │ 32 │ 36 │ 40 5 │ 10 │ 15 │ 20 │ 25 │ 30 │ 35 │ 40 │ 45 │ 50 6 │ 12 │ 18 │ 24 │ 30 │ 36 │ 42 │ 48 │ 54 │ 60 7 │ 14 │ 21 │ 28 │ 35 │ 42 │ 49 │ 56 │ 63 │ 70 8 │ 16 │ 24 │ 32 │ 40 │ 48 │ 56 │ 64 │ 72 │ 80 9 │ 18 │ 27 │ 36 │ 45 │ 54 │ 63 │ 72 │ 81 │ 90 10 │ 20 │ 30 │ 40 │ 50 │ 60 │ 70 │ 80 │ 90 │ 100 ``` --- ## 4. Risk-Tier Zuordnung | Score-Range | Tier | Anzahl Controls | Farbe | Beschreibung | |-------------|------|-----------------|-------|--------------| | 0--24 | `BASELINE` | ~60 Mindestanforderungen | Gruen | Standard-Schutzniveau | | 25--49 | `ENHANCED` | +40 erweiterte Massnahmen | Gelb | Erhoehtes Schutzniveau | | 50--74 | `HIGH_RISK` | +50 Hochrisiko-Pack | Orange | Hohes Risiko, DSFA empfohlen | | 75--100 | `CRITICAL` | +30 Kritisches Pack | Rot | Kritisch, DSFA verpflichtend | **Controls sind kumulativ:** - `BASELINE` = 60 Controls - `ENHANCED` = BASELINE + 40 = 100 Controls - `HIGH_RISK` = BASELINE + ENHANCED + 50 = 150 Controls - `CRITICAL` = BASELINE + ENHANCED + HIGH_RISK + 30 = 180 Controls ### Implementierung ```typescript enum RiskTier { BASELINE = "BASELINE", ENHANCED = "ENHANCED", HIGH_RISK = "HIGH_RISK", CRITICAL = "CRITICAL", } const TIER_ORDER: Record = { [RiskTier.BASELINE]: 0, [RiskTier.ENHANCED]: 1, [RiskTier.HIGH_RISK]: 2, [RiskTier.CRITICAL]: 3, }; function scoreTier(score: number): RiskTier { if (score >= 75) return RiskTier.CRITICAL; if (score >= 50) return RiskTier.HIGH_RISK; if (score >= 25) return RiskTier.ENHANCED; return RiskTier.BASELINE; } ``` --- ## 5. Control-Selection Algorithmus Der Algorithmus waehlt Controls basierend auf dem Risk-Tier und kontextspezifischen Trigger-Regeln. ### Pseudocode ``` function selectControls(score, context): tier = scoreTier(score) controls = allControls.filter(c => c.risk_tier <= tier) # Trigger-Rules: zusaetzliche Controls je nach Kontext if context.special_categories: controls += allControls.filter(c => c.applies_if.field == "special_categories") if context.third_country_transfer: controls += allControls.filter(c => c.applies_if.field == "third_country_transfer") if context.large_scale: controls += allControls.filter(c => c.applies_if.field == "large_scale") if context.vulnerable_persons: controls += allControls.filter(c => c.applies_if.field == "vulnerable_persons") return deduplicate(controls) ``` ### Implementierung ```typescript interface Control { id: string; title: string; description: string; risk_tier: RiskTier; domain: TOMDomain; applies_if?: { field: string; value: boolean; }; } interface SelectionContext { score: number; special_categories: boolean; third_country_transfer: boolean; large_scale: boolean; vulnerable_persons: boolean; } function selectControls( allControls: Control[], ctx: SelectionContext ): Control[] { const tier = scoreTier(ctx.score); const tierLevel = TIER_ORDER[tier]; // 1. Tier-basierte Auswahl (kumulativ) const tierControls = allControls.filter( (c) => TIER_ORDER[c.risk_tier] <= tierLevel ); // 2. Trigger-basierte Zusatz-Controls const triggerFields: (keyof SelectionContext)[] = [ "special_categories", "third_country_transfer", "large_scale", "vulnerable_persons", ]; const triggerControls = allControls.filter((c) => { if (!c.applies_if) return false; const field = c.applies_if.field as keyof SelectionContext; return triggerFields.includes(field) && ctx[field] === true; }); // 3. Deduplizieren const controlMap = new Map(); [...tierControls, ...triggerControls].forEach((c) => { controlMap.set(c.id, c); }); return Array.from(controlMap.values()); } ``` ### Trigger-Rules im Detail | Trigger | Zusaetzliche Controls | Beispiel | |---------|----------------------|----------| | `special_categories` | Erweiterte Zugriffskontrolle, Verschluesselung, DSFA-Pflicht | Gesundheitsdaten in HR-System | | `third_country_transfer` | SCCs, TIA, Binding Corporate Rules | US-Cloud-Anbieter | | `large_scale` | DPO-Pflicht, erweitertes Monitoring, Kapazitaetsplanung | >100.000 Betroffene | | `vulnerable_persons` | Altersverifikation, elterliche Einwilligung, kindgerechte UI | Schul-App | --- ## 6. Loeschfristen-Engine Die Loeschfristen-Engine bestimmt automatisch Aufbewahrungsfristen und Loeschzeitpunkte. ### Berechnung der Aufbewahrungsfrist ``` RetentionPeriod = max(legal_minimum, operational_need) ``` ### Loeschausloeser (DeletionTrigger) | Trigger | Beschreibung | Beispiel | |---------|--------------|----------| | `Vertragsende` | Ende der Vertragsbeziehung | Schueler verlaesst Schule | | `Zweckwegfall` | Verarbeitungszweck entfaellt | Projekt abgeschlossen | | `Widerruf` | Betroffener widerruft Einwilligung | Einwilligung zurueckgezogen | ### Ausnahmeregeln (ExceptionRules) | Rechtsgrundlage | Frist | Datenkategorie | |-----------------|-------|----------------| | HGB Par. 257 (Handelsbuecher) | 10 Jahre | Buchungsbelege, Jahresabschluesse | | AO Par. 147 (Abgabenordnung) | 10 Jahre | Steuerrelevante Unterlagen | | AO Par. 147 (sonstige Unterlagen) | 6 Jahre | Geschaeftsbriefe | | BetrVG (Betriebsrat) | 3 Jahre | Betriebsratsprotokolle | | BDSG Par. 35 | Unverzueglich | Nicht mehr benoetigte personenbezogene Daten | | **Rechtsstreit-Hold** | Bis Abschluss | Alle prozessrelevanten Daten | ### Default-Retention je Datenkategorie | Datenkategorie | Default-Frist | Gesetzliche Grundlage | |----------------|---------------|----------------------| | Stammdaten (Name, Adresse) | 3 Jahre nach Vertragsende | DSGVO Art. 17, Verjaehrung Par. 195 BGB | | Vertragsdaten | 10 Jahre | HGB Par. 257 | | Rechnungsdaten | 10 Jahre | AO Par. 147 | | Kommunikationsdaten (E-Mails) | 6 Jahre | AO Par. 147 | | Bewerberdaten | 6 Monate | AGG Par. 15 Abs. 4 | | Log-Daten (Server, Zugriff) | 90 Tage | DSGVO Art. 5 Abs. 1 lit. e | | Gesundheitsdaten | 10 Jahre | Aerztliche Aufbewahrungspflicht | | Schulnoten / Zeugnisse | 10 Jahre nach Abgang | Landesschulgesetze | | Einwilligungen (Nachweis) | 3 Jahre nach Widerruf | DSGVO Art. 7 Abs. 1, Beweislast | | Video-Ueberwachung | 72 Stunden | BDSG Par. 4 Abs. 5 | ### Implementierung ```typescript interface RetentionRule { category: string; default_days: number; legal_basis: string; deletion_trigger: "Vertragsende" | "Zweckwegfall" | "Widerruf"; exception_rules: ExceptionRule[]; } interface ExceptionRule { condition: string; // z.B. "Rechtsstreit-Hold" override_days: number; // -1 = unbegrenzt bis Bedingung entfaellt legal_basis: string; } function calculateDeletionDate( rule: RetentionRule, triggerDate: Date, activeExceptions: ExceptionRule[] ): Date | null { // Aktive Ausnahmen pruefen const holdException = activeExceptions.find( (e) => e.override_days === -1 ); if (holdException) return null; // Loeschung ausgesetzt // Maximale Frist berechnen const retentionDays = Math.max( rule.default_days, ...activeExceptions.map((e) => e.override_days) ); const deletionDate = new Date(triggerDate); deletionDate.setDate(deletionDate.getDate() + retentionDays); return deletionDate; } ``` --- ## 7. Mapping: Score → TOM-Domaenen → Textbausteine ### TOM-Domaenen nach SDM (Standard-Datenschutzmodell) | Domaene | Beschreibung | SDM-Gewaehrleistungsziel | |---------|--------------|--------------------------| | `ZUGANG` | Zugangskontrolle | Vertraulichkeit | | `ZUGRIFF` | Zugriffskontrolle | Vertraulichkeit | | `UEBERTRAGUNG` | Weitergabekontrolle | Integritaet | | `EINGABE` | Eingabekontrolle | Integritaet | | `AUFTRAG` | Auftragskontrolle | Integritaet | | `VERFUEGBARKEIT` | Verfuegbarkeitskontrolle | Verfuegbarkeit | | `TRENNUNG` | Trennungskontrolle | Nichtverkettung | | `TRANSPARENZ` | Transparenzkontrolle | Transparenz | | `INTERVENIERBARKEIT` | Betroffenenrechte | Intervenierbarkeit | | `DATENMINIMIERUNG` | Datenminimierung | Datenminimierung | ### Tier → Domaenen-Zuordnung | Domaene | BASELINE | ENHANCED | HIGH_RISK | CRITICAL | |---------|----------|----------|-----------|----------| | ZUGANG | Pflicht | Pflicht | Pflicht | Pflicht | | ZUGRIFF | Pflicht | Pflicht | Pflicht | Pflicht | | UEBERTRAGUNG | Pflicht | Pflicht | Pflicht | Pflicht | | EINGABE | Empfohlen | Pflicht | Pflicht | Pflicht | | AUFTRAG | Empfohlen | Pflicht | Pflicht | Pflicht | | VERFUEGBARKEIT | Pflicht | Pflicht | Pflicht | Pflicht | | TRENNUNG | Empfohlen | Empfohlen | Pflicht | Pflicht | | TRANSPARENZ | Pflicht | Pflicht | Pflicht | Pflicht | | INTERVENIERBARKEIT | Pflicht | Pflicht | Pflicht | Pflicht | | DATENMINIMIERUNG | Empfohlen | Pflicht | Pflicht | Pflicht | ### Textbausteine je Tier und Domaene (Auszug) ```typescript const TOM_TEXTBAUSTEINE: Record> = { BASELINE: { ZUGANG: [ "Passwortrichtlinie mit Mindestlaenge 12 Zeichen", "Automatische Bildschirmsperre nach 5 Minuten", "Besuchermanagement mit Protokollierung", ], ZUGRIFF: [ "Rollenbasierte Zugriffskontrolle (RBAC)", "Need-to-know-Prinzip", "Regelmaessige Ueberpruefung der Berechtigungen (jaehrlich)", ], VERFUEGBARKEIT: [ "Taegliche Backups mit Integritaetspruefung", "USV-Anlage fuer kritische Systeme", "Dokumentierter Notfallplan", ], }, ENHANCED: { ZUGANG: [ "Multi-Faktor-Authentifizierung (MFA) fuer alle Nutzer", "Zentrales Identity Management (IdP)", "Hardware-Token oder FIDO2 fuer Admin-Zugaenge", ], ZUGRIFF: [ "Attributbasierte Zugriffskontrolle (ABAC)", "Privileged Access Management (PAM)", "Quartalsweise Zugriffs-Reviews", ], VERFUEGBARKEIT: [ "Geo-redundante Backups", "Recovery Time Objective (RTO) < 4 Stunden", "Jaehrlicher Disaster-Recovery-Test", ], }, HIGH_RISK: { ZUGANG: [ "Zero-Trust-Architektur", "Biometrische Zugangskontrolle fuer Serverraeume", "Netzwerksegmentierung mit Mikrosegmenten", ], ZUGRIFF: [ "Just-in-Time Access (zeitlich begrenzte Berechtigungen)", "Vier-Augen-Prinzip fuer kritische Operationen", "Echtzeit-Anomalieerkennung bei Zugriffen", ], TRENNUNG: [ "Mandantentrennung auf Datenbankebene (Schemata)", "Getrennte Verschluesselungsschluessel je Mandant", "Isolierte Verarbeitungsumgebungen", ], }, CRITICAL: { ZUGANG: [ "Air-Gapped Systeme fuer kritischste Daten", "24/7 SOC-Ueberwachung", "Penetrationstests (quartalsweise, extern)", ], ZUGRIFF: [ "Hardware Security Modules (HSM) fuer Schluessel", "Break-Glass-Verfahren mit Audit-Trail", "Kontinuierliche Authentifizierung", ], VERFUEGBARKEIT: [ "Active-Active Cluster mit automatischem Failover", "RTO < 15 Minuten, RPO < 5 Minuten", "Monatliche Disaster-Recovery-Tests", ], }, }; ``` --- ## 8. Kompatibilitaet mit bestehendem Modell ### Bestehendes Modell (backend-compliance) Das bestehende Modell in `backend-compliance/compliance/db/models.py` nutzt eine vereinfachte Skala: | Parameter | Bestehend | Neu (diese Spec) | |-----------|-----------|-------------------| | Impact-Skala | 1--5 | 0--10 | | Likelihood-Skala | 1--5 | 0--10 | | Score-Bereich | 1--25 | 0--100 | | Schwellenwerte | 6 / 12 / 20 | 25 / 50 / 75 | ### Konvertierung: Alte Skala → Neue Skala ```typescript // Alt (1-5) → Neu (0-10) function oldToNewScale(oldValue: number): number { return Math.round((oldValue / 5) * 10); } // Neu (0-10) → Alt (1-5) function newToOldScale(newValue: number): number { return Math.max(1, Math.round((newValue / 10) * 5)); } ``` ### Konvertierung: Alter Score → Neuer Score ```typescript // Alt (1-25) → Neu (0-100) function oldScoreToNew(oldScore: number): number { return Math.round((oldScore / 25) * 100); } // Neu (0-100) → Alt (1-25) function newScoreToOld(newScore: number): number { return Math.max(1, Math.round((newScore / 100) * 25)); } ``` ### Schwellenwert-Mapping | Altes Tier (1--25) | Neues Tier (0--100) | Risk-Tier | |---------------------|---------------------|-----------| | 1--5 | 0--24 | BASELINE | | 6--11 | 25--49 | ENHANCED | | 12--19 | 50--74 | HIGH_RISK | | 20--25 | 75--100 | CRITICAL | ### Migrations-Strategie Bei der Migration bestehender Risikobewertungen: ```sql -- Bestehende Scores konvertieren (1-25 → 0-100) UPDATE compliance_risks SET score_v2 = ROUND((score::numeric / 25.0) * 100) WHERE score_v2 IS NULL; -- Impact/Likelihood konvertieren (1-5 → 0-10) UPDATE compliance_risks SET impact_v2 = ROUND((impact::numeric / 5.0) * 10), likelihood_v2 = ROUND((likelihood::numeric / 5.0) * 10) WHERE impact_v2 IS NULL; ``` --- ## Anhang A: Vollstaendiges Berechnungsbeispiel ### Szenario: Lernplattform mit KI-Korrekturvorschlaegen **Kontext:** - Schueler-Plattform (Kinder betroffen) - KI bewertet Klausuren (automatisierte Entscheidung) - Gesundheitsdaten bei Attestverwaltung - Cloud-Hosting (AWS Frankfurt) - MFA vorhanden, aber kein SIEM **Impact-Berechnung:** ``` Basis = 2 + Kinder / Schutzbeduerftige = +2 + Automatisierte Entscheidungen = +1 + Gesundheitsdaten = +1 + Besondere Kategorien (Art. 9) = +2 ───────────────────────────────────── Impact = min(8, 10) = 8 ``` **Likelihood-Berechnung:** ``` Basis = 2 + Internet-Exponierung = +2 + Fehlendes Logging / SIEM = +2 ───────────────────────────────────── Likelihood = min(6, 10) = 6 ``` **Score und Tier:** ``` Score = round(8 * 6) = 48 → Tier: ENHANCED ``` **Ausgewaehlte Controls:** 100 (60 BASELINE + 40 ENHANCED) plus Trigger-Controls fuer `special_categories` und `vulnerable_persons`. **Empfohlene Massnahmen (Auszug):** - MFA fuer alle Nutzer (bereits vorhanden) - SIEM-System einfuehren (fehlend -- Prioritaet hoch) - Altersverifikation und elterliche Einwilligung - DSFA durchfuehren (Art. 35 -- Kinder + automatisierte Entscheidung) - Erklaerbarkeit der KI-Entscheidungen sicherstellen (AI Act) --- ## Anhang B: Glossar | Begriff | Erklaerung | |---------|-----------| | **TOM** | Technisch-organisatorische Massnahmen (Art. 32 DSGVO) | | **DSFA** | Datenschutz-Folgenabschaetzung (Art. 35 DSGVO) | | **SDM** | Standard-Datenschutzmodell der Datenschutzkonferenz | | **IAM** | Identity and Access Management | | **SIEM** | Security Information and Event Management | | **SCCs** | Standard Contractual Clauses (Standardvertragsklauseln) | | **TIA** | Transfer Impact Assessment | | **AVV** | Auftragsverarbeitungsvertrag (Art. 28 DSGVO) | | **RBAC** | Role-Based Access Control | | **ABAC** | Attribute-Based Access Control | | **PAM** | Privileged Access Management | | **HSM** | Hardware Security Module | | **SOC** | Security Operations Center | | **RTO** | Recovery Time Objective | | **RPO** | Recovery Point Objective |