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:
323
ai-compliance-sdk/internal/ucca/rules_data_fj.go
Normal file
323
ai-compliance-sdk/internal/ucca/rules_data_fj.go
Normal file
@@ -0,0 +1,323 @@
|
||||
package ucca
|
||||
|
||||
func init() {
|
||||
AllRules = append(AllRules, rulesFJ()...)
|
||||
}
|
||||
|
||||
// rulesFJ returns rules for categories F–J (R-050 to R-100)
|
||||
func rulesFJ() []Rule {
|
||||
return []Rule{
|
||||
// =========================================================================
|
||||
// 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 {
|
||||
return false // handled in aggregation logic
|
||||
},
|
||||
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 {
|
||||
return false // handled in aggregation logic
|
||||
},
|
||||
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 {
|
||||
return false // handled in aggregation logic
|
||||
},
|
||||
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 {
|
||||
return false // handled in summary generation
|
||||
},
|
||||
Rationale: func(intake *UseCaseIntake) string {
|
||||
return "Jede Ablehnung enthält eine klare Begründung und einen alternativen Ansatz."
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user