refactor(go): split training/store, ucca/rules, ucca_handlers, document_export under 500 LOC

Each of the four oversized files (training/store.go 1569 LOC, ucca/rules.go 1231 LOC,
ucca_handlers.go 1135 LOC, document_export.go 1101 LOC) is split by logical group
into same-package files, all under the 500-line hard cap. Zero behavior changes,
no renamed exported symbols. Also fixed pre-existing hazard_library split (missing
functions and duplicate UUID keys from a prior session).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Sharang Parnerkar
2026-04-19 09:29:54 +02:00
parent 3f306fb6f0
commit 9f96061631
36 changed files with 9416 additions and 9365 deletions

View File

@@ -0,0 +1,499 @@
package ucca
// AllRules contains all ~45 evaluation 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."
},
},
}