package ucca import ( "fmt" "strings" ) // ============================================================================ // Rule Engine - Deterministic rule evaluation // ============================================================================ // Rule represents a single evaluation rule type Rule struct { Code string Category string Title string TitleDE string Description string DescriptionDE string Severity Severity ScoreDelta int // Points added to risk score GDPRRef string // GDPR article reference Controls []string // Required control IDs Patterns []string // Recommended pattern IDs Condition func(intake *UseCaseIntake) bool Rationale func(intake *UseCaseIntake) string } // RuleEngine holds all rules and performs evaluation type RuleEngine struct { rules []Rule } // NewRuleEngine creates a new rule engine with all rules func NewRuleEngine() *RuleEngine { return &RuleEngine{ rules: AllRules, } } // Evaluate runs all rules against the intake and returns the assessment result func (e *RuleEngine) Evaluate(intake *UseCaseIntake) *AssessmentResult { result := &AssessmentResult{ Feasibility: FeasibilityYES, RiskLevel: RiskLevelMINIMAL, Complexity: ComplexityLOW, RiskScore: 0, TriggeredRules: []TriggeredRule{}, RequiredControls: []RequiredControl{}, RecommendedArchitecture: []PatternRecommendation{}, ForbiddenPatterns: []ForbiddenPattern{}, ExampleMatches: []ExampleMatch{}, DSFARecommended: false, Art22Risk: false, TrainingAllowed: TrainingYES, } // Track triggered severities hasBlock := false hasWarn := false controlMap := make(map[string]bool) patternMap := make(map[string]int) // pattern -> priority // Evaluate each rule for _, rule := range e.rules { if rule.Condition(intake) { // Add triggered rule triggered := TriggeredRule{ Code: rule.Code, Category: rule.Category, Title: rule.TitleDE, Description: rule.DescriptionDE, Severity: rule.Severity, ScoreDelta: rule.ScoreDelta, GDPRRef: rule.GDPRRef, Rationale: rule.Rationale(intake), } result.TriggeredRules = append(result.TriggeredRules, triggered) // Update risk score result.RiskScore += rule.ScoreDelta // Track severity switch rule.Severity { case SeverityBLOCK: hasBlock = true case SeverityWARN: hasWarn = true } // Collect required controls for _, controlID := range rule.Controls { if !controlMap[controlID] { controlMap[controlID] = true if ctrl := GetControlByID(controlID); ctrl != nil { result.RequiredControls = append(result.RequiredControls, *ctrl) } } } // Collect recommended patterns for i, patternID := range rule.Patterns { if _, exists := patternMap[patternID]; !exists { patternMap[patternID] = i + 1 // priority } } } } // Determine feasibility based on aggregation rules (R-090 to R-092) if hasBlock { result.Feasibility = FeasibilityNO } else if hasWarn { result.Feasibility = FeasibilityCONDITIONAL } else { result.Feasibility = FeasibilityYES } // Determine risk level based on score if result.RiskScore >= 80 { result.RiskLevel = RiskLevelUNACCEPTABLE } else if result.RiskScore >= 60 { result.RiskLevel = RiskLevelHIGH } else if result.RiskScore >= 40 { result.RiskLevel = RiskLevelMEDIUM } else if result.RiskScore >= 20 { result.RiskLevel = RiskLevelLOW } else { result.RiskLevel = RiskLevelMINIMAL } // Determine complexity if len(result.RequiredControls) >= 5 || result.RiskScore >= 50 { result.Complexity = ComplexityHIGH } else if len(result.RequiredControls) >= 3 || result.RiskScore >= 25 { result.Complexity = ComplexityMEDIUM } else { result.Complexity = ComplexityLOW } // Check DSFA recommendation if result.RiskLevel == RiskLevelHIGH || result.RiskLevel == RiskLevelUNACCEPTABLE || intake.DataTypes.Article9Data || intake.DataTypes.BiometricData || (intake.Purpose.Profiling && intake.DataTypes.PersonalData) { result.DSFARecommended = true } // Check Art. 22 risk if intake.Automation == AutomationFullyAutomated && (intake.Outputs.LegalEffects || intake.Outputs.RankingsOrScores || intake.Purpose.EvaluationScoring) { result.Art22Risk = true } // Determine training allowed if intake.ModelUsage.Training && intake.DataTypes.PersonalData { result.TrainingAllowed = TrainingNO } else if intake.ModelUsage.Finetune && intake.DataTypes.PersonalData { result.TrainingAllowed = TrainingCONDITIONAL } // Add recommended architecture patterns for patternID, priority := range patternMap { if p := GetPatternByID(patternID); p != nil { result.RecommendedArchitecture = append(result.RecommendedArchitecture, PatternToRecommendation(*p, "Empfohlen basierend auf ausgelösten Regeln", priority)) } } // Add applicable patterns not yet recommended applicable := GetApplicablePatterns(intake) for _, p := range applicable { found := false for _, rec := range result.RecommendedArchitecture { if rec.PatternID == p.ID { found = true break } } if !found { result.RecommendedArchitecture = append(result.RecommendedArchitecture, PatternToRecommendation(p, "Anwendbar für Ihren Use Case", len(result.RecommendedArchitecture)+1)) } } // Add forbidden patterns result.ForbiddenPatterns = GetForbiddenPatterns(intake) // Add matching examples result.ExampleMatches = MatchExamples(intake) // Generate summary result.Summary = generateSummary(result, intake) result.Recommendation = generateRecommendation(result, intake) if result.Feasibility == FeasibilityNO { result.AlternativeApproach = generateAlternative(result, intake) } return result } // generateSummary creates a human-readable summary func generateSummary(result *AssessmentResult, intake *UseCaseIntake) string { var parts []string switch result.Feasibility { case FeasibilityYES: parts = append(parts, "Der Use Case ist aus DSGVO-Sicht grundsätzlich umsetzbar.") case FeasibilityCONDITIONAL: parts = append(parts, "Der Use Case ist unter Auflagen umsetzbar.") case FeasibilityNO: parts = append(parts, "Der Use Case ist in der aktuellen Form nicht DSGVO-konform umsetzbar.") } if len(result.TriggeredRules) > 0 { blockCount := 0 warnCount := 0 for _, r := range result.TriggeredRules { if r.Severity == SeverityBLOCK { blockCount++ } else if r.Severity == SeverityWARN { warnCount++ } } if blockCount > 0 { parts = append(parts, fmt.Sprintf("%d kritische Regelverletzung(en) identifiziert.", blockCount)) } if warnCount > 0 { parts = append(parts, fmt.Sprintf("%d Warnungen erfordern Aufmerksamkeit.", warnCount)) } } if result.DSFARecommended { parts = append(parts, "Eine Datenschutz-Folgenabschätzung (DSFA) wird empfohlen.") } return strings.Join(parts, " ") } // generateRecommendation creates actionable recommendations func generateRecommendation(result *AssessmentResult, intake *UseCaseIntake) string { if result.Feasibility == FeasibilityYES { return "Fahren Sie mit der Implementierung fort. Beachten Sie die empfohlenen Architektur-Patterns für optimale DSGVO-Konformität." } if result.Feasibility == FeasibilityCONDITIONAL { if len(result.RequiredControls) > 0 { return fmt.Sprintf("Implementieren Sie die %d erforderlichen Kontrollen vor dem Go-Live. Dokumentieren Sie alle Maßnahmen für den Nachweis der Rechenschaftspflicht (Art. 5 DSGVO).", len(result.RequiredControls)) } return "Prüfen Sie die ausgelösten Warnungen und implementieren Sie entsprechende Schutzmaßnahmen." } // FeasibilityNO return "Der Use Case erfordert grundlegende Änderungen. Prüfen Sie die Alternative-Ansatz-Empfehlung." } // generateAlternative creates alternative approach suggestions func generateAlternative(result *AssessmentResult, intake *UseCaseIntake) string { var suggestions []string // Check specific blocking reasons if intake.ModelUsage.Training && intake.DataTypes.PersonalData { suggestions = append(suggestions, "Nutzen Sie nur RAG statt Training mit personenbezogenen Daten") } if intake.Automation == AutomationFullyAutomated && intake.Outputs.LegalEffects { suggestions = append(suggestions, "Implementieren Sie Human-in-the-Loop für Entscheidungen mit rechtlichen Auswirkungen") } if intake.DataTypes.MinorData && intake.Purpose.EvaluationScoring { suggestions = append(suggestions, "Verzichten Sie auf automatisches Scoring von Minderjährigen - nutzen Sie KI nur zur Unterstützung menschlicher Entscheidungsträger") } if intake.Hosting.Region == "third_country" && intake.DataTypes.PersonalData { suggestions = append(suggestions, "Hosten Sie innerhalb der EU oder implementieren Sie Standardvertragsklauseln (SCCs)") } if len(suggestions) == 0 { return "Überarbeiten Sie den Use Case unter Berücksichtigung der ausgelösten Regeln." } return strings.Join(suggestions, ". ") + "." } // GetRules returns all rules func (e *RuleEngine) GetRules() []Rule { return e.rules } // ============================================================================ // Control Definitions // ============================================================================ var ControlLibrary = map[string]RequiredControl{ "C-CONSENT": { ID: "C-CONSENT", Title: "Einwilligungsmanagement", Description: "Implementieren Sie ein System zur Einholung und Verwaltung von Einwilligungen.", Severity: SeverityWARN, Category: "organizational", GDPRRef: "Art. 7 DSGVO", }, "C-PII-DETECT": { ID: "C-PII-DETECT", Title: "PII-Erkennung", Description: "Implementieren Sie automatische Erkennung personenbezogener Daten.", Severity: SeverityWARN, Category: "technical", GDPRRef: "Art. 32 DSGVO", }, "C-ANONYMIZE": { ID: "C-ANONYMIZE", Title: "Anonymisierung/Pseudonymisierung", Description: "Implementieren Sie Anonymisierung oder Pseudonymisierung vor der Verarbeitung.", Severity: SeverityWARN, Category: "technical", GDPRRef: "Art. 32 DSGVO", }, "C-ACCESS-CONTROL": { ID: "C-ACCESS-CONTROL", Title: "Zugriffskontrollen", Description: "Implementieren Sie rollenbasierte Zugriffskontrollen.", Severity: SeverityWARN, Category: "technical", GDPRRef: "Art. 32 DSGVO", }, "C-AUDIT-LOG": { ID: "C-AUDIT-LOG", Title: "Audit-Logging", Description: "Protokollieren Sie alle Zugriffe und Verarbeitungen.", Severity: SeverityINFO, Category: "technical", GDPRRef: "Art. 5(2) DSGVO", }, "C-RETENTION": { ID: "C-RETENTION", Title: "Aufbewahrungsfristen", Description: "Definieren und implementieren Sie automatische Löschfristen.", Severity: SeverityWARN, Category: "organizational", GDPRRef: "Art. 5(1)(e) DSGVO", }, "C-HITL": { ID: "C-HITL", Title: "Human-in-the-Loop", Description: "Implementieren Sie menschliche Überprüfung für KI-Entscheidungen.", Severity: SeverityBLOCK, Category: "organizational", GDPRRef: "Art. 22 DSGVO", }, "C-TRANSPARENCY": { ID: "C-TRANSPARENCY", Title: "Transparenz", Description: "Informieren Sie Betroffene über KI-Verarbeitung.", Severity: SeverityWARN, Category: "organizational", GDPRRef: "Art. 13/14 DSGVO", }, "C-DSR-PROCESS": { ID: "C-DSR-PROCESS", Title: "Betroffenenrechte-Prozess", Description: "Implementieren Sie Prozesse für Auskunft, Löschung, Berichtigung.", Severity: SeverityWARN, Category: "organizational", GDPRRef: "Art. 15-22 DSGVO", }, "C-DSFA": { ID: "C-DSFA", Title: "DSFA durchführen", Description: "Führen Sie eine Datenschutz-Folgenabschätzung durch.", Severity: SeverityWARN, Category: "organizational", GDPRRef: "Art. 35 DSGVO", }, "C-SCC": { ID: "C-SCC", Title: "Standardvertragsklauseln", Description: "Schließen Sie EU-Standardvertragsklauseln für Drittlandtransfers ab.", Severity: SeverityBLOCK, Category: "legal", GDPRRef: "Art. 46 DSGVO", }, "C-ENCRYPTION": { ID: "C-ENCRYPTION", Title: "Verschlüsselung", Description: "Verschlüsseln Sie Daten in Übertragung und Speicherung.", Severity: SeverityWARN, Category: "technical", GDPRRef: "Art. 32 DSGVO", }, "C-MINOR-CONSENT": { ID: "C-MINOR-CONSENT", Title: "Elterneinwilligung", Description: "Holen Sie Einwilligung der Erziehungsberechtigten ein.", Severity: SeverityBLOCK, Category: "organizational", GDPRRef: "Art. 8 DSGVO", }, "C-ART9-BASIS": { ID: "C-ART9-BASIS", Title: "Art. 9 Rechtsgrundlage", Description: "Dokumentieren Sie die Rechtsgrundlage für besondere Datenkategorien.", Severity: SeverityBLOCK, Category: "legal", GDPRRef: "Art. 9 DSGVO", }, } // GetControlByID returns a control by its ID func GetControlByID(id string) *RequiredControl { if ctrl, exists := ControlLibrary[id]; exists { return &ctrl } return nil } // ============================================================================ // All Rules (~45 rules in 10 categories) // ============================================================================ var AllRules = []Rule{ // ========================================================================= // A. Datenklassifikation (R-001 bis R-006) // ========================================================================= { Code: "R-001", Category: "A. Datenklassifikation", Title: "Personal Data Processing", TitleDE: "Verarbeitung personenbezogener Daten", Description: "Personal data is being processed", DescriptionDE: "Personenbezogene Daten werden verarbeitet", Severity: SeverityINFO, ScoreDelta: 5, GDPRRef: "Art. 4(1) DSGVO", Controls: []string{"C-PII-DETECT", "C-ACCESS-CONTROL"}, Patterns: []string{"P-PRE-ANON"}, Condition: func(intake *UseCaseIntake) bool { return intake.DataTypes.PersonalData }, Rationale: func(intake *UseCaseIntake) string { return "Der Use Case verarbeitet personenbezogene Daten. Dies erfordert eine Rechtsgrundlage und entsprechende Schutzmaßnahmen." }, }, { Code: "R-002", Category: "A. Datenklassifikation", Title: "Special Category Data (Art. 9)", TitleDE: "Besondere Kategorien personenbezogener Daten (Art. 9)", Description: "Processing of special category data requires explicit consent or legal basis", DescriptionDE: "Verarbeitung besonderer Datenkategorien erfordert ausdrückliche Einwilligung oder Rechtsgrundlage", Severity: SeverityWARN, ScoreDelta: 20, GDPRRef: "Art. 9 DSGVO", Controls: []string{"C-ART9-BASIS", "C-DSFA", "C-ENCRYPTION"}, Patterns: []string{"P-PRE-ANON", "P-HITL-ENFORCED"}, Condition: func(intake *UseCaseIntake) bool { return intake.DataTypes.Article9Data }, Rationale: func(intake *UseCaseIntake) string { return "Besondere Kategorien personenbezogener Daten (Gesundheit, Religion, etc.) erfordern besondere Schutzmaßnahmen und eine spezifische Rechtsgrundlage nach Art. 9 DSGVO." }, }, { Code: "R-003", Category: "A. Datenklassifikation", Title: "Minor Data Processing", TitleDE: "Verarbeitung von Daten Minderjähriger", Description: "Processing data of children requires special protections", DescriptionDE: "Verarbeitung von Daten Minderjähriger erfordert besonderen Schutz", Severity: SeverityWARN, ScoreDelta: 15, GDPRRef: "Art. 8 DSGVO", Controls: []string{"C-MINOR-CONSENT", "C-DSFA"}, Patterns: []string{"P-HITL-ENFORCED"}, Condition: func(intake *UseCaseIntake) bool { return intake.DataTypes.MinorData }, Rationale: func(intake *UseCaseIntake) string { return "Daten von Minderjährigen erfordern besonderen Schutz. Die Einwilligung muss von Erziehungsberechtigten eingeholt werden." }, }, { Code: "R-004", Category: "A. Datenklassifikation", Title: "Biometric Data", TitleDE: "Biometrische Daten", Description: "Biometric data processing is high risk", DescriptionDE: "Verarbeitung biometrischer Daten ist hochriskant", Severity: SeverityWARN, ScoreDelta: 20, GDPRRef: "Art. 9 DSGVO", Controls: []string{"C-ART9-BASIS", "C-DSFA", "C-ENCRYPTION"}, Patterns: []string{"P-PRE-ANON"}, Condition: func(intake *UseCaseIntake) bool { return intake.DataTypes.BiometricData }, Rationale: func(intake *UseCaseIntake) string { return "Biometrische Daten zur eindeutigen Identifizierung fallen unter Art. 9 DSGVO und erfordern eine DSFA." }, }, { Code: "R-005", Category: "A. Datenklassifikation", Title: "Location Data", TitleDE: "Standortdaten", Description: "Location tracking requires transparency and consent", DescriptionDE: "Standortverfolgung erfordert Transparenz und Einwilligung", Severity: SeverityINFO, ScoreDelta: 10, GDPRRef: "Art. 5, Art. 7 DSGVO", Controls: []string{"C-CONSENT", "C-TRANSPARENCY"}, Patterns: []string{"P-LOG-MINIMIZATION"}, Condition: func(intake *UseCaseIntake) bool { return intake.DataTypes.LocationData }, Rationale: func(intake *UseCaseIntake) string { return "Standortdaten ermöglichen Bewegungsprofile und erfordern klare Einwilligung und Aufbewahrungslimits." }, }, { Code: "R-006", Category: "A. Datenklassifikation", Title: "Employee Data", TitleDE: "Mitarbeiterdaten", Description: "Employee data processing has special considerations", DescriptionDE: "Mitarbeiterdatenverarbeitung hat besondere Anforderungen", Severity: SeverityINFO, ScoreDelta: 10, GDPRRef: "§ 26 BDSG", Controls: []string{"C-ACCESS-CONTROL", "C-TRANSPARENCY"}, Patterns: []string{"P-NAMESPACE-ISOLATION"}, Condition: func(intake *UseCaseIntake) bool { return intake.DataTypes.EmployeeData }, Rationale: func(intake *UseCaseIntake) string { return "Mitarbeiterdaten unterliegen zusätzlich dem BDSG § 26 und erfordern klare Zweckbindung." }, }, // ========================================================================= // B. Zweck & Kontext (R-010 bis R-013) // ========================================================================= { Code: "R-010", Category: "B. Zweck & Kontext", Title: "Marketing with Personal Data", TitleDE: "Marketing mit personenbezogenen Daten", Description: "Marketing purposes with PII require explicit consent", DescriptionDE: "Marketing mit PII erfordert ausdrückliche Einwilligung", Severity: SeverityWARN, ScoreDelta: 15, GDPRRef: "Art. 6(1)(a) DSGVO", Controls: []string{"C-CONSENT", "C-DSR-PROCESS"}, Patterns: []string{"P-PRE-ANON"}, Condition: func(intake *UseCaseIntake) bool { return intake.Purpose.Marketing && intake.DataTypes.PersonalData }, Rationale: func(intake *UseCaseIntake) string { return "Marketing mit personenbezogenen Daten erfordert ausdrückliche, freiwillige Einwilligung." }, }, { Code: "R-011", Category: "B. Zweck & Kontext", Title: "Profiling Purpose", TitleDE: "Profiling-Zweck", Description: "Profiling requires DSFA and transparency", DescriptionDE: "Profiling erfordert DSFA und Transparenz", Severity: SeverityWARN, ScoreDelta: 15, GDPRRef: "Art. 22 DSGVO", Controls: []string{"C-DSFA", "C-TRANSPARENCY", "C-DSR-PROCESS"}, Patterns: []string{"P-HITL-ENFORCED"}, Condition: func(intake *UseCaseIntake) bool { return intake.Purpose.Profiling }, Rationale: func(intake *UseCaseIntake) string { return "Profiling erfordert eine DSFA und transparente Information der Betroffenen über die Logik und Auswirkungen." }, }, { Code: "R-012", Category: "B. Zweck & Kontext", Title: "Evaluation/Scoring Purpose", TitleDE: "Bewertungs-/Scoring-Zweck", Description: "Scoring of individuals requires safeguards", DescriptionDE: "Scoring von Personen erfordert Schutzmaßnahmen", Severity: SeverityWARN, ScoreDelta: 15, GDPRRef: "Art. 22 DSGVO", Controls: []string{"C-HITL", "C-TRANSPARENCY"}, Patterns: []string{"P-HITL-ENFORCED"}, Condition: func(intake *UseCaseIntake) bool { return intake.Purpose.EvaluationScoring }, Rationale: func(intake *UseCaseIntake) string { return "Bewertung/Scoring von Personen erfordert menschliche Überprüfung und Transparenz über die verwendete Logik." }, }, { Code: "R-013", Category: "B. Zweck & Kontext", Title: "Customer Support - Low Risk", TitleDE: "Kundenservice - Niedriges Risiko", Description: "Customer support without PII storage is low risk", DescriptionDE: "Kundenservice ohne PII-Speicherung ist risikoarm", Severity: SeverityINFO, ScoreDelta: 0, GDPRRef: "", Controls: []string{}, Patterns: []string{"P-RAG-ONLY"}, Condition: func(intake *UseCaseIntake) bool { return intake.Purpose.CustomerSupport && !intake.DataTypes.PersonalData }, Rationale: func(intake *UseCaseIntake) string { return "Kundenservice mit öffentlichen FAQ-Daten ohne Speicherung personenbezogener Daten ist risikoarm." }, }, // ========================================================================= // C. Automatisierung (R-020 bis R-025) // ========================================================================= { Code: "R-020", Category: "C. Automatisierung", Title: "Fully Automated with Legal Effects", TitleDE: "Vollautomatisiert mit rechtlichen Auswirkungen", Description: "Fully automated decisions with legal effects violate Art. 22", DescriptionDE: "Vollautomatisierte Entscheidungen mit rechtlichen Auswirkungen verletzen Art. 22", Severity: SeverityBLOCK, ScoreDelta: 40, GDPRRef: "Art. 22 DSGVO", Controls: []string{"C-HITL"}, Patterns: []string{"P-HITL-ENFORCED"}, Condition: func(intake *UseCaseIntake) bool { return intake.Automation == AutomationFullyAutomated && intake.Outputs.LegalEffects }, Rationale: func(intake *UseCaseIntake) string { return "Vollautomatisierte Entscheidungen mit rechtlichen Auswirkungen ohne menschliche Beteiligung sind nach Art. 22 DSGVO unzulässig." }, }, { Code: "R-021", Category: "C. Automatisierung", Title: "Fully Automated Rankings/Scores", TitleDE: "Vollautomatisierte Rankings/Scores", Description: "Automated scoring requires human review", DescriptionDE: "Automatisches Scoring erfordert menschliche Überprüfung", Severity: SeverityWARN, ScoreDelta: 20, GDPRRef: "Art. 22 DSGVO", Controls: []string{"C-HITL", "C-TRANSPARENCY"}, Patterns: []string{"P-HITL-ENFORCED"}, Condition: func(intake *UseCaseIntake) bool { return intake.Automation == AutomationFullyAutomated && intake.Outputs.RankingsOrScores }, Rationale: func(intake *UseCaseIntake) string { return "Vollautomatisierte Erstellung von Rankings oder Scores erfordert menschliche Überprüfung vor Verwendung." }, }, { Code: "R-022", Category: "C. Automatisierung", Title: "Fully Automated Access Decisions", TitleDE: "Vollautomatisierte Zugriffsentscheidungen", Description: "Automated access decisions need safeguards", DescriptionDE: "Automatisierte Zugriffsentscheidungen benötigen Schutzmaßnahmen", Severity: SeverityWARN, ScoreDelta: 15, GDPRRef: "Art. 22 DSGVO", Controls: []string{"C-HITL", "C-TRANSPARENCY", "C-DSR-PROCESS"}, Patterns: []string{"P-HITL-ENFORCED"}, Condition: func(intake *UseCaseIntake) bool { return intake.Automation == AutomationFullyAutomated && intake.Outputs.AccessDecisions }, Rationale: func(intake *UseCaseIntake) string { return "Automatisierte Entscheidungen über Zugang erfordern Widerspruchsmöglichkeit und menschliche Überprüfung." }, }, { Code: "R-023", Category: "C. Automatisierung", Title: "Semi-Automated - Medium Risk", TitleDE: "Teilautomatisiert - Mittleres Risiko", Description: "Semi-automated processing with human review", DescriptionDE: "Teilautomatisierte Verarbeitung mit menschlicher Überprüfung", Severity: SeverityINFO, ScoreDelta: 5, GDPRRef: "", Controls: []string{"C-AUDIT-LOG"}, Patterns: []string{"P-HITL-ENFORCED"}, Condition: func(intake *UseCaseIntake) bool { return intake.Automation == AutomationSemiAutomated && intake.DataTypes.PersonalData }, Rationale: func(intake *UseCaseIntake) string { return "Teilautomatisierte Verarbeitung mit menschlicher Überprüfung ist grundsätzlich konform, erfordert aber Dokumentation." }, }, { Code: "R-024", Category: "C. Automatisierung", Title: "Assistive Only - Low Risk", TitleDE: "Nur assistierend - Niedriges Risiko", Description: "Assistive AI without automated decisions is low risk", DescriptionDE: "Assistive KI ohne automatisierte Entscheidungen ist risikoarm", Severity: SeverityINFO, ScoreDelta: 0, GDPRRef: "", Controls: []string{}, Patterns: []string{"P-RAG-ONLY"}, Condition: func(intake *UseCaseIntake) bool { return intake.Automation == AutomationAssistive }, Rationale: func(intake *UseCaseIntake) string { return "Rein assistive KI, die nur Vorschläge macht und keine Entscheidungen trifft, ist risikoarm." }, }, { Code: "R-025", Category: "C. Automatisierung", Title: "HR Scoring - Blocked", TitleDE: "HR-Scoring - Blockiert", Description: "Automated HR scoring/evaluation is prohibited", DescriptionDE: "Automatisiertes HR-Scoring/Bewertung ist verboten", Severity: SeverityBLOCK, ScoreDelta: 50, GDPRRef: "Art. 22, § 26 BDSG", Controls: []string{"C-HITL"}, Patterns: []string{}, Condition: func(intake *UseCaseIntake) bool { return intake.Domain == DomainHR && intake.Purpose.EvaluationScoring && intake.Automation == AutomationFullyAutomated }, Rationale: func(intake *UseCaseIntake) string { return "Vollautomatisierte Bewertung/Scoring von Mitarbeitern ist unzulässig. Arbeitsrechtliche Entscheidungen müssen von Menschen getroffen werden." }, }, // ========================================================================= // D. Training vs Nutzung (R-030 bis R-035) // ========================================================================= { Code: "R-030", Category: "D. Training vs Nutzung", Title: "Training with Personal Data", TitleDE: "Training mit personenbezogenen Daten", Description: "Training AI with personal data is high risk", DescriptionDE: "Training von KI mit personenbezogenen Daten ist hochriskant", Severity: SeverityBLOCK, ScoreDelta: 40, GDPRRef: "Art. 5(1)(b)(c) DSGVO", Controls: []string{"C-ART9-BASIS", "C-DSFA"}, Patterns: []string{"P-RAG-ONLY"}, Condition: func(intake *UseCaseIntake) bool { return intake.ModelUsage.Training && intake.DataTypes.PersonalData }, Rationale: func(intake *UseCaseIntake) string { return "Training von KI-Modellen mit personenbezogenen Daten verstößt gegen Zweckbindung und Datenminimierung. Nutzen Sie stattdessen RAG." }, }, { Code: "R-031", Category: "D. Training vs Nutzung", Title: "Fine-tuning with Personal Data", TitleDE: "Fine-Tuning mit personenbezogenen Daten", Description: "Fine-tuning with PII requires safeguards", DescriptionDE: "Fine-Tuning mit PII erfordert Schutzmaßnahmen", Severity: SeverityWARN, ScoreDelta: 25, GDPRRef: "Art. 5(1)(b)(c) DSGVO", Controls: []string{"C-ANONYMIZE", "C-DSFA"}, Patterns: []string{"P-PRE-ANON"}, Condition: func(intake *UseCaseIntake) bool { return intake.ModelUsage.Finetune && intake.DataTypes.PersonalData }, Rationale: func(intake *UseCaseIntake) string { return "Fine-Tuning mit personenbezogenen Daten ist nur nach Anonymisierung/Pseudonymisierung zulässig." }, }, { Code: "R-032", Category: "D. Training vs Nutzung", Title: "RAG Only - Recommended", TitleDE: "Nur RAG - Empfohlen", Description: "RAG without training is the safest approach", DescriptionDE: "RAG ohne Training ist der sicherste Ansatz", Severity: SeverityINFO, ScoreDelta: 0, GDPRRef: "", Controls: []string{}, Patterns: []string{"P-RAG-ONLY"}, Condition: func(intake *UseCaseIntake) bool { return intake.ModelUsage.RAG && !intake.ModelUsage.Training && !intake.ModelUsage.Finetune }, Rationale: func(intake *UseCaseIntake) string { return "Nur-RAG ohne Training oder Fine-Tuning ist die empfohlene Architektur für DSGVO-Konformität." }, }, { Code: "R-033", Category: "D. Training vs Nutzung", Title: "Training with Article 9 Data", TitleDE: "Training mit Art. 9 Daten", Description: "Training with special category data is prohibited", DescriptionDE: "Training mit besonderen Datenkategorien ist verboten", Severity: SeverityBLOCK, ScoreDelta: 50, GDPRRef: "Art. 9 DSGVO", Controls: []string{}, Patterns: []string{}, Condition: func(intake *UseCaseIntake) bool { return (intake.ModelUsage.Training || intake.ModelUsage.Finetune) && intake.DataTypes.Article9Data }, Rationale: func(intake *UseCaseIntake) string { return "Training oder Fine-Tuning mit besonderen Kategorien personenbezogener Daten (Gesundheit, Religion, etc.) ist grundsätzlich unzulässig." }, }, { Code: "R-034", Category: "D. Training vs Nutzung", Title: "Inference with Public Data", TitleDE: "Inferenz mit öffentlichen Daten", Description: "Using only public data is low risk", DescriptionDE: "Nutzung nur öffentlicher Daten ist risikoarm", Severity: SeverityINFO, ScoreDelta: 0, GDPRRef: "", Controls: []string{}, Patterns: []string{}, Condition: func(intake *UseCaseIntake) bool { return intake.DataTypes.PublicData && !intake.DataTypes.PersonalData }, Rationale: func(intake *UseCaseIntake) string { return "Die ausschließliche Nutzung öffentlich zugänglicher Daten ohne Personenbezug ist unproblematisch." }, }, { Code: "R-035", Category: "D. Training vs Nutzung", Title: "Training with Minor Data", TitleDE: "Training mit Daten Minderjähriger", Description: "Training with children's data is prohibited", DescriptionDE: "Training mit Kinderdaten ist verboten", Severity: SeverityBLOCK, ScoreDelta: 50, GDPRRef: "Art. 8 DSGVO, ErwG 38", Controls: []string{}, Patterns: []string{}, Condition: func(intake *UseCaseIntake) bool { return (intake.ModelUsage.Training || intake.ModelUsage.Finetune) && intake.DataTypes.MinorData }, Rationale: func(intake *UseCaseIntake) string { return "Training von KI-Modellen mit Daten von Minderjährigen ist aufgrund des besonderen Schutzes unzulässig." }, }, // ========================================================================= // E. Speicherung (R-040 bis R-042) // ========================================================================= { Code: "R-040", Category: "E. Speicherung", Title: "Storing Prompts with PII", TitleDE: "Speicherung von Prompts mit PII", Description: "Storing prompts containing PII requires controls", DescriptionDE: "Speicherung von Prompts mit PII erfordert Kontrollen", Severity: SeverityWARN, ScoreDelta: 15, GDPRRef: "Art. 5(1)(e) DSGVO", Controls: []string{"C-RETENTION", "C-ANONYMIZE", "C-DSR-PROCESS"}, Patterns: []string{"P-LOG-MINIMIZATION", "P-PRE-ANON"}, Condition: func(intake *UseCaseIntake) bool { return intake.Retention.StorePrompts && intake.DataTypes.PersonalData }, Rationale: func(intake *UseCaseIntake) string { return "Speicherung von Prompts mit personenbezogenen Daten erfordert Löschfristen und Anonymisierungsoptionen." }, }, { Code: "R-041", Category: "E. Speicherung", Title: "Storing Responses with PII", TitleDE: "Speicherung von Antworten mit PII", Description: "Storing AI responses containing PII requires controls", DescriptionDE: "Speicherung von KI-Antworten mit PII erfordert Kontrollen", Severity: SeverityWARN, ScoreDelta: 10, GDPRRef: "Art. 5(1)(e) DSGVO", Controls: []string{"C-RETENTION", "C-DSR-PROCESS"}, Patterns: []string{"P-LOG-MINIMIZATION"}, Condition: func(intake *UseCaseIntake) bool { return intake.Retention.StoreResponses && intake.DataTypes.PersonalData }, Rationale: func(intake *UseCaseIntake) string { return "Speicherung von KI-Antworten mit personenbezogenen Daten erfordert definierte Aufbewahrungsfristen." }, }, { Code: "R-042", Category: "E. Speicherung", Title: "No Retention Policy", TitleDE: "Keine Aufbewahrungsrichtlinie", Description: "PII storage without retention limits is problematic", DescriptionDE: "PII-Speicherung ohne Aufbewahrungslimits ist problematisch", Severity: SeverityWARN, ScoreDelta: 10, GDPRRef: "Art. 5(1)(e) DSGVO", Controls: []string{"C-RETENTION"}, Patterns: []string{"P-LOG-MINIMIZATION"}, Condition: func(intake *UseCaseIntake) bool { return (intake.Retention.StorePrompts || intake.Retention.StoreResponses) && intake.DataTypes.PersonalData && intake.Retention.RetentionDays == 0 }, Rationale: func(intake *UseCaseIntake) string { return "Speicherung personenbezogener Daten ohne definierte Aufbewahrungsfrist verstößt gegen den Grundsatz der Speicherbegrenzung." }, }, // ========================================================================= // F. Hosting (R-050 bis R-052) // ========================================================================= { Code: "R-050", Category: "F. Hosting", Title: "Third Country Transfer with PII", TitleDE: "Drittlandtransfer mit PII", Description: "Transferring PII to third countries requires safeguards", DescriptionDE: "Übermittlung von PII in Drittländer erfordert Schutzmaßnahmen", Severity: SeverityWARN, ScoreDelta: 20, GDPRRef: "Art. 44-49 DSGVO", Controls: []string{"C-SCC", "C-ENCRYPTION"}, Patterns: []string{}, Condition: func(intake *UseCaseIntake) bool { return intake.Hosting.Region == "third_country" && intake.DataTypes.PersonalData }, Rationale: func(intake *UseCaseIntake) string { return "Übermittlung personenbezogener Daten in Drittländer erfordert Standardvertragsklauseln oder andere geeignete Garantien." }, }, { Code: "R-051", Category: "F. Hosting", Title: "EU Hosting - Compliant", TitleDE: "EU-Hosting - Konform", Description: "Hosting within EU is compliant with GDPR", DescriptionDE: "Hosting innerhalb der EU ist DSGVO-konform", Severity: SeverityINFO, ScoreDelta: 0, GDPRRef: "", Controls: []string{}, Patterns: []string{}, Condition: func(intake *UseCaseIntake) bool { return intake.Hosting.Region == "eu" }, Rationale: func(intake *UseCaseIntake) string { return "Hosting innerhalb der EU/EWR erfüllt grundsätzlich die DSGVO-Anforderungen an den Datenstandort." }, }, { Code: "R-052", Category: "F. Hosting", Title: "On-Premise Hosting", TitleDE: "On-Premise-Hosting", Description: "On-premise hosting gives most control", DescriptionDE: "On-Premise-Hosting gibt die meiste Kontrolle", Severity: SeverityINFO, ScoreDelta: 0, GDPRRef: "", Controls: []string{"C-ENCRYPTION"}, Patterns: []string{}, Condition: func(intake *UseCaseIntake) bool { return intake.Hosting.Region == "on_prem" }, Rationale: func(intake *UseCaseIntake) string { return "On-Premise-Hosting bietet maximale Kontrolle über Daten, erfordert aber eigene Sicherheitsmaßnahmen." }, }, // ========================================================================= // G. Transparenz (R-060 bis R-062) // ========================================================================= { Code: "R-060", Category: "G. Transparenz", Title: "No Human Review for Decisions", TitleDE: "Keine menschliche Überprüfung bei Entscheidungen", Description: "Decisions affecting individuals need human review option", DescriptionDE: "Entscheidungen, die Personen betreffen, benötigen menschliche Überprüfungsoption", Severity: SeverityWARN, ScoreDelta: 15, GDPRRef: "Art. 22(3) DSGVO", Controls: []string{"C-HITL", "C-DSR-PROCESS"}, Patterns: []string{"P-HITL-ENFORCED"}, Condition: func(intake *UseCaseIntake) bool { return (intake.Outputs.LegalEffects || intake.Outputs.AccessDecisions || intake.Purpose.DecisionMaking) && intake.Automation != AutomationAssistive }, Rationale: func(intake *UseCaseIntake) string { return "Betroffene haben das Recht auf menschliche Überprüfung bei automatisierten Entscheidungen." }, }, { Code: "R-061", Category: "G. Transparenz", Title: "External Recommendations", TitleDE: "Externe Empfehlungen", Description: "Recommendations to users need transparency", DescriptionDE: "Empfehlungen an Nutzer erfordern Transparenz", Severity: SeverityINFO, ScoreDelta: 5, GDPRRef: "Art. 13/14 DSGVO", Controls: []string{"C-TRANSPARENCY"}, Patterns: []string{}, Condition: func(intake *UseCaseIntake) bool { return intake.Outputs.RecommendationsToUsers && intake.DataTypes.PersonalData }, Rationale: func(intake *UseCaseIntake) string { return "Personalisierte Empfehlungen erfordern Information der Nutzer über die KI-Verarbeitung." }, }, { Code: "R-062", Category: "G. Transparenz", Title: "Content Generation without Disclosure", TitleDE: "Inhaltsgenerierung ohne Offenlegung", Description: "AI-generated content should be disclosed", DescriptionDE: "KI-generierte Inhalte sollten offengelegt werden", Severity: SeverityINFO, ScoreDelta: 5, GDPRRef: "EU-AI-Act Art. 52", Controls: []string{"C-TRANSPARENCY"}, Patterns: []string{}, Condition: func(intake *UseCaseIntake) bool { return intake.Outputs.ContentGeneration }, Rationale: func(intake *UseCaseIntake) string { return "KI-generierte Inhalte sollten als solche gekennzeichnet werden (EU-AI-Act Transparenzpflicht)." }, }, // ========================================================================= // H. Domain-spezifisch (R-070 bis R-074) // ========================================================================= { Code: "R-070", Category: "H. Domain-spezifisch", Title: "Education + Scoring = Blocked", TitleDE: "Bildung + Scoring = Blockiert", Description: "Automated scoring of students is prohibited", DescriptionDE: "Automatisches Scoring von Schülern ist verboten", Severity: SeverityBLOCK, ScoreDelta: 50, GDPRRef: "Art. 8, Art. 22 DSGVO", Controls: []string{}, Patterns: []string{}, Condition: func(intake *UseCaseIntake) bool { return intake.Domain == DomainEducation && intake.DataTypes.MinorData && (intake.Purpose.EvaluationScoring || intake.Outputs.RankingsOrScores) }, Rationale: func(intake *UseCaseIntake) string { return "Automatisches Scoring oder Ranking von Schülern/Minderjährigen ist aufgrund des besonderen Schutzes unzulässig." }, }, { Code: "R-071", Category: "H. Domain-spezifisch", Title: "Healthcare + Automated Diagnosis", TitleDE: "Gesundheit + Automatische Diagnose", Description: "Automated medical decisions require strict controls", DescriptionDE: "Automatische medizinische Entscheidungen erfordern strenge Kontrollen", Severity: SeverityBLOCK, ScoreDelta: 45, GDPRRef: "Art. 9, Art. 22 DSGVO", Controls: []string{"C-HITL", "C-DSFA", "C-ART9-BASIS"}, Patterns: []string{"P-HITL-ENFORCED"}, Condition: func(intake *UseCaseIntake) bool { return intake.Domain == DomainHealthcare && intake.Automation == AutomationFullyAutomated && intake.Purpose.DecisionMaking }, Rationale: func(intake *UseCaseIntake) string { return "Vollautomatisierte medizinische Diagnosen oder Behandlungsentscheidungen sind ohne ärztliche Überprüfung unzulässig." }, }, { Code: "R-072", Category: "H. Domain-spezifisch", Title: "Finance + Automated Credit Scoring", TitleDE: "Finanzen + Automatisches Credit-Scoring", Description: "Automated credit decisions require transparency", DescriptionDE: "Automatische Kreditentscheidungen erfordern Transparenz", Severity: SeverityWARN, ScoreDelta: 20, GDPRRef: "Art. 22 DSGVO", Controls: []string{"C-HITL", "C-TRANSPARENCY", "C-DSR-PROCESS"}, Patterns: []string{"P-HITL-ENFORCED"}, Condition: func(intake *UseCaseIntake) bool { return intake.Domain == DomainFinance && (intake.Purpose.EvaluationScoring || intake.Outputs.RankingsOrScores) && intake.DataTypes.FinancialData }, Rationale: func(intake *UseCaseIntake) string { return "Automatische Kreditwürdigkeitsprüfung erfordert Erklärbarkeit und Widerspruchsmöglichkeit." }, }, { Code: "R-073", Category: "H. Domain-spezifisch", Title: "Utilities + RAG Chatbot = Low Risk", TitleDE: "Versorgungsunternehmen + RAG-Chatbot = Niedriges Risiko", Description: "RAG-based customer service chatbot is low risk", DescriptionDE: "RAG-basierter Kundenservice-Chatbot ist risikoarm", Severity: SeverityINFO, ScoreDelta: 0, GDPRRef: "", Controls: []string{}, Patterns: []string{"P-RAG-ONLY"}, Condition: func(intake *UseCaseIntake) bool { return intake.Domain == DomainUtilities && intake.ModelUsage.RAG && intake.Purpose.CustomerSupport && !intake.DataTypes.PersonalData }, Rationale: func(intake *UseCaseIntake) string { return "Ein RAG-basierter Kundenservice-Chatbot ohne Speicherung personenbezogener Daten ist ein Best-Practice-Beispiel." }, }, { Code: "R-074", Category: "H. Domain-spezifisch", Title: "Public Sector + Automated Decisions", TitleDE: "Öffentlicher Sektor + Automatische Entscheidungen", Description: "Public sector automated decisions need special care", DescriptionDE: "Automatische Entscheidungen im öffentlichen Sektor erfordern besondere Sorgfalt", Severity: SeverityWARN, ScoreDelta: 20, GDPRRef: "Art. 22 DSGVO", Controls: []string{"C-HITL", "C-TRANSPARENCY", "C-DSFA"}, Patterns: []string{"P-HITL-ENFORCED"}, Condition: func(intake *UseCaseIntake) bool { return intake.Domain == DomainPublic && intake.Purpose.DecisionMaking && intake.Automation != AutomationAssistive }, Rationale: func(intake *UseCaseIntake) string { return "Verwaltungsentscheidungen, die Bürger betreffen, erfordern besondere Transparenz und Überprüfungsmöglichkeiten." }, }, // ========================================================================= // I. Aggregation (R-090 bis R-092) - Implicit in Evaluate() // ========================================================================= { Code: "R-090", Category: "I. Aggregation", Title: "Block Rules Triggered", TitleDE: "Blockierungsregeln ausgelöst", Description: "Any BLOCK severity results in NO feasibility", DescriptionDE: "Jede BLOCK-Schwere führt zu NEIN-Machbarkeit", Severity: SeverityBLOCK, ScoreDelta: 0, GDPRRef: "", Controls: []string{}, Patterns: []string{}, Condition: func(intake *UseCaseIntake) bool { // This is handled in aggregation logic return false }, Rationale: func(intake *UseCaseIntake) string { return "Eine oder mehrere kritische Regelverletzungen führen zur Einstufung als nicht umsetzbar." }, }, { Code: "R-091", Category: "I. Aggregation", Title: "Warning Rules Only", TitleDE: "Nur Warnungsregeln", Description: "Only WARN severity results in CONDITIONAL", DescriptionDE: "Nur WARN-Schwere führt zu BEDINGT", Severity: SeverityWARN, ScoreDelta: 0, GDPRRef: "", Controls: []string{}, Patterns: []string{}, Condition: func(intake *UseCaseIntake) bool { // This is handled in aggregation logic return false }, Rationale: func(intake *UseCaseIntake) string { return "Warnungen erfordern Maßnahmen, blockieren aber nicht die Umsetzung." }, }, { Code: "R-092", Category: "I. Aggregation", Title: "Info Only - Clear Path", TitleDE: "Nur Info - Freier Weg", Description: "Only INFO severity results in YES", DescriptionDE: "Nur INFO-Schwere führt zu JA", Severity: SeverityINFO, ScoreDelta: 0, GDPRRef: "", Controls: []string{}, Patterns: []string{}, Condition: func(intake *UseCaseIntake) bool { // This is handled in aggregation logic return false }, Rationale: func(intake *UseCaseIntake) string { return "Keine kritischen oder warnenden Regeln ausgelöst - Umsetzung empfohlen." }, }, // ========================================================================= // J. Erklärung (R-100) // ========================================================================= { Code: "R-100", Category: "J. Erklärung", Title: "Rejection Must Include Reason and Alternative", TitleDE: "Ablehnung muss Begründung und Alternative enthalten", Description: "When feasibility is NO, provide reason and alternative", DescriptionDE: "Bei Machbarkeit NEIN, Begründung und Alternative angeben", Severity: SeverityINFO, ScoreDelta: 0, GDPRRef: "", Controls: []string{}, Patterns: []string{}, Condition: func(intake *UseCaseIntake) bool { // This is handled in summary generation return false }, Rationale: func(intake *UseCaseIntake) string { return "Jede Ablehnung enthält eine klare Begründung und einen alternativen Ansatz." }, }, }