refactor(go/ucca): split policy_engine, legal_rag, ai_act, nis2, financial_policy, dsgvo_module

Split 6 oversized files (719–882 LOC each) into focused files under 500 LOC:
- policy_engine.go → types, loader, eval, gen (4 files)
- legal_rag.go     → types, client, http, context, scroll (5 files)
- ai_act_module.go → module, yaml, obligations (3 files)
- nis2_module.go   → module, yaml, obligations + shared obligation_yaml_types.go (3+1 files)
- financial_policy.go → types, engine (2 files)
- dsgvo_module.go  → module, yaml, obligations (3 files)

All in package ucca, zero exported symbol renames, go test ./internal/ucca/... passes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Sharang Parnerkar
2026-04-19 09:48:41 +02:00
parent e0b3c54212
commit c293d76e6b
23 changed files with 3089 additions and 3415 deletions

View File

@@ -0,0 +1,134 @@
package ucca
import (
"context"
"fmt"
"strings"
"time"
)
// GetLegalContextForAssessment retrieves relevant legal context for an assessment.
func (c *LegalRAGClient) GetLegalContextForAssessment(ctx context.Context, assessment *Assessment) (*LegalContext, error) {
queryParts := []string{}
if assessment.Domain != "" {
queryParts = append(queryParts, fmt.Sprintf("KI-Anwendung im Bereich %s", assessment.Domain))
}
if assessment.Intake.DataTypes.Article9Data {
queryParts = append(queryParts, "besondere Kategorien personenbezogener Daten Art. 9 DSGVO")
}
if assessment.Intake.DataTypes.PersonalData {
queryParts = append(queryParts, "personenbezogene Daten")
}
if assessment.Intake.DataTypes.MinorData {
queryParts = append(queryParts, "Daten von Minderjährigen")
}
if assessment.Intake.Purpose.EvaluationScoring {
queryParts = append(queryParts, "automatisierte Bewertung Scoring")
}
if assessment.Intake.Purpose.DecisionMaking {
queryParts = append(queryParts, "automatisierte Entscheidung Art. 22 DSGVO")
}
if assessment.Intake.Purpose.Profiling {
queryParts = append(queryParts, "Profiling")
}
if assessment.DSFARecommended {
queryParts = append(queryParts, "Datenschutz-Folgenabschätzung Art. 35 DSGVO")
}
if assessment.Art22Risk {
queryParts = append(queryParts, "automatisierte Einzelentscheidung rechtliche Wirkung")
}
query := strings.Join(queryParts, " ")
if query == "" {
query = "DSGVO Anforderungen KI-System Datenschutz"
}
regulationIDs := c.determineRelevantRegulations(assessment)
results, err := c.Search(ctx, query, regulationIDs, 5)
if err != nil {
return nil, err
}
regSet := make(map[string]bool)
for _, r := range results {
regSet[r.RegulationCode] = true
}
regulations := make([]string, 0, len(regSet))
for r := range regSet {
regulations = append(regulations, r)
}
articles := make([]string, 0)
for _, r := range results {
if len(r.Pages) > 0 {
key := fmt.Sprintf("%s S. %v", r.RegulationShort, r.Pages)
articles = append(articles, key)
}
}
return &LegalContext{
Query: query,
Results: results,
RelevantArticles: articles,
Regulations: regulations,
GeneratedAt: time.Now().UTC(),
}, nil
}
// determineRelevantRegulations determines which regulations to search based on the assessment.
func (c *LegalRAGClient) determineRelevantRegulations(assessment *Assessment) []string {
ids := []string{"eu_2016_679"}
for _, rule := range assessment.TriggeredRules {
gdprRef := rule.GDPRRef
if strings.Contains(gdprRef, "AI Act") || strings.Contains(gdprRef, "KI-VO") {
if !contains(ids, "eu_2024_1689") {
ids = append(ids, "eu_2024_1689")
}
}
if strings.Contains(gdprRef, "NIS2") || strings.Contains(gdprRef, "NIS-2") {
if !contains(ids, "eu_2022_2555") {
ids = append(ids, "eu_2022_2555")
}
}
if strings.Contains(gdprRef, "CRA") || strings.Contains(gdprRef, "Cyber Resilience") {
if !contains(ids, "eu_2024_2847") {
ids = append(ids, "eu_2024_2847")
}
}
if strings.Contains(gdprRef, "Maschinenverordnung") || strings.Contains(gdprRef, "Machinery") {
if !contains(ids, "eu_2023_1230") {
ids = append(ids, "eu_2023_1230")
}
}
}
for _, ctrl := range assessment.RequiredControls {
if strings.HasPrefix(ctrl.ID, "AI-") {
if !contains(ids, "eu_2024_1689") {
ids = append(ids, "eu_2024_1689")
}
break
}
}
for _, ctrl := range assessment.RequiredControls {
if strings.HasPrefix(ctrl.ID, "CRYPTO-") || strings.HasPrefix(ctrl.ID, "IAM-") || strings.HasPrefix(ctrl.ID, "SEC-") {
if !contains(ids, "eu_2022_2555") {
ids = append(ids, "eu_2022_2555")
}
if !contains(ids, "eu_2024_2847") {
ids = append(ids, "eu_2024_2847")
}
break
}
}
return ids
}