A previous `git pull --rebase origin main` dropped 177 local commits,
losing 3400+ files across admin-v2, backend, studio-v2, website,
klausur-service, and many other services. The partial restore attempt
(660295e2) only recovered some files.
This commit restores all missing files from pre-rebase ref 98933f5e
while preserving post-rebase additions (night-scheduler, night-mode UI,
NightModeWidget dashboard integration).
Restored features include:
- AI Module Sidebar (FAB), OCR Labeling, OCR Compare
- GPU Dashboard, RAG Pipeline, Magic Help
- Klausur-Korrektur (8 files), Abitur-Archiv (5+ files)
- Companion, Zeugnisse-Crawler, Screen Flow
- Full backend, studio-v2, website, klausur-service
- All compliance SDKs, agent-core, voice-service
- CI/CD configs, documentation, scripts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
720 lines
27 KiB
Go
720 lines
27 KiB
Go
package ucca
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
// ============================================================================
|
|
// DSGVO Module
|
|
// ============================================================================
|
|
//
|
|
// This module implements the GDPR (DSGVO - Datenschutz-Grundverordnung) obligations.
|
|
//
|
|
// DSGVO applies to:
|
|
// - All organizations processing personal data of EU residents
|
|
// - Both controllers and processors
|
|
//
|
|
// Key obligations covered:
|
|
// - Processing records (Art. 30)
|
|
// - Technical and organizational measures (Art. 32)
|
|
// - Data Protection Impact Assessment (Art. 35)
|
|
// - Data subject rights (Art. 15-21)
|
|
// - Breach notification (Art. 33/34)
|
|
// - DPO appointment (Art. 37)
|
|
// - Data Processing Agreements (Art. 28)
|
|
//
|
|
// ============================================================================
|
|
|
|
// DSGVOModule implements the RegulationModule interface for DSGVO
|
|
type DSGVOModule struct {
|
|
obligations []Obligation
|
|
controls []ObligationControl
|
|
incidentDeadlines []IncidentDeadline
|
|
decisionTree *DecisionTree
|
|
loaded bool
|
|
}
|
|
|
|
// DSGVO special categories that require additional measures
|
|
var (
|
|
// Article 9 - Special categories of personal data
|
|
DSGVOSpecialCategories = map[string]bool{
|
|
"racial_ethnic_origin": true,
|
|
"political_opinions": true,
|
|
"religious_beliefs": true,
|
|
"trade_union_membership": true,
|
|
"genetic_data": true,
|
|
"biometric_data": true,
|
|
"health_data": true,
|
|
"sexual_orientation": true,
|
|
}
|
|
|
|
// High risk processing activities (Art. 35)
|
|
DSGVOHighRiskProcessing = map[string]bool{
|
|
"systematic_monitoring": true, // Large-scale systematic monitoring
|
|
"automated_decisions": true, // Automated decision-making with legal effects
|
|
"large_scale_special": true, // Large-scale processing of special categories
|
|
"public_area_monitoring": true, // Systematic monitoring of public areas
|
|
"profiling": true, // Evaluation/scoring of individuals
|
|
"vulnerable_persons": true, // Processing data of vulnerable persons
|
|
}
|
|
)
|
|
|
|
// NewDSGVOModule creates a new DSGVO module, loading obligations from YAML
|
|
func NewDSGVOModule() (*DSGVOModule, error) {
|
|
m := &DSGVOModule{
|
|
obligations: []Obligation{},
|
|
controls: []ObligationControl{},
|
|
incidentDeadlines: []IncidentDeadline{},
|
|
}
|
|
|
|
// Try to load from YAML, fall back to hardcoded if not found
|
|
if err := m.loadFromYAML(); err != nil {
|
|
// Use hardcoded defaults
|
|
m.loadHardcodedObligations()
|
|
}
|
|
|
|
m.buildDecisionTree()
|
|
m.loaded = true
|
|
|
|
return m, nil
|
|
}
|
|
|
|
// ID returns the module identifier
|
|
func (m *DSGVOModule) ID() string {
|
|
return "dsgvo"
|
|
}
|
|
|
|
// Name returns the human-readable name
|
|
func (m *DSGVOModule) Name() string {
|
|
return "DSGVO (Datenschutz-Grundverordnung)"
|
|
}
|
|
|
|
// Description returns a brief description
|
|
func (m *DSGVOModule) Description() string {
|
|
return "EU-Datenschutz-Grundverordnung (Verordnung (EU) 2016/679) - Schutz personenbezogener Daten"
|
|
}
|
|
|
|
// IsApplicable checks if DSGVO applies to the organization
|
|
func (m *DSGVOModule) IsApplicable(facts *UnifiedFacts) bool {
|
|
// DSGVO applies if:
|
|
// 1. Organization processes personal data
|
|
// 2. Organization is in EU, or
|
|
// 3. Organization offers goods/services to EU, or
|
|
// 4. Organization monitors behavior of EU individuals
|
|
|
|
if !facts.DataProtection.ProcessesPersonalData {
|
|
return false
|
|
}
|
|
|
|
// Check if organization is in EU
|
|
if facts.Organization.EUMember {
|
|
return true
|
|
}
|
|
|
|
// Check if offering to EU
|
|
if facts.DataProtection.OffersToEU {
|
|
return true
|
|
}
|
|
|
|
// Check if monitoring EU individuals
|
|
if facts.DataProtection.MonitorsEUIndividuals {
|
|
return true
|
|
}
|
|
|
|
// Default: if processes personal data and no explicit EU connection info,
|
|
// assume applicable for safety
|
|
return facts.DataProtection.ProcessesPersonalData
|
|
}
|
|
|
|
// GetClassification returns the DSGVO classification as string
|
|
func (m *DSGVOModule) GetClassification(facts *UnifiedFacts) string {
|
|
if !m.IsApplicable(facts) {
|
|
return "nicht_anwendbar"
|
|
}
|
|
|
|
// Determine role and risk level
|
|
if m.hasHighRiskProcessing(facts) {
|
|
if facts.DataProtection.IsController {
|
|
return "verantwortlicher_hohes_risiko"
|
|
}
|
|
return "auftragsverarbeiter_hohes_risiko"
|
|
}
|
|
|
|
if facts.DataProtection.IsController {
|
|
return "verantwortlicher"
|
|
}
|
|
return "auftragsverarbeiter"
|
|
}
|
|
|
|
// hasHighRiskProcessing checks if organization performs high-risk processing
|
|
func (m *DSGVOModule) hasHighRiskProcessing(facts *UnifiedFacts) bool {
|
|
// Check for special categories (Art. 9)
|
|
for _, cat := range facts.DataProtection.SpecialCategories {
|
|
if DSGVOSpecialCategories[cat] {
|
|
return true
|
|
}
|
|
}
|
|
|
|
// Check for high-risk activities (Art. 35)
|
|
for _, activity := range facts.DataProtection.HighRiskActivities {
|
|
if DSGVOHighRiskProcessing[activity] {
|
|
return true
|
|
}
|
|
}
|
|
|
|
// Large-scale processing
|
|
if facts.DataProtection.DataSubjectCount > 10000 {
|
|
return true
|
|
}
|
|
|
|
// Systematic monitoring
|
|
if facts.DataProtection.SystematicMonitoring {
|
|
return true
|
|
}
|
|
|
|
// Automated decision-making with legal effects
|
|
if facts.DataProtection.AutomatedDecisions && facts.DataProtection.LegalEffects {
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// requiresDPO checks if a DPO is mandatory
|
|
func (m *DSGVOModule) requiresDPO(facts *UnifiedFacts) bool {
|
|
// Art. 37 - DPO mandatory if:
|
|
// 1. Public authority or body
|
|
if facts.Organization.IsPublicAuthority {
|
|
return true
|
|
}
|
|
|
|
// 2. Core activities require regular and systematic monitoring at large scale
|
|
if facts.DataProtection.SystematicMonitoring && facts.DataProtection.DataSubjectCount > 10000 {
|
|
return true
|
|
}
|
|
|
|
// 3. Core activities consist of processing special categories at large scale
|
|
if len(facts.DataProtection.SpecialCategories) > 0 && facts.DataProtection.DataSubjectCount > 10000 {
|
|
return true
|
|
}
|
|
|
|
// German BDSG: >= 20 employees regularly processing personal data
|
|
if facts.Organization.Country == "DE" && facts.Organization.EmployeeCount >= 20 {
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// DeriveObligations derives all applicable DSGVO obligations
|
|
func (m *DSGVOModule) DeriveObligations(facts *UnifiedFacts) []Obligation {
|
|
if !m.IsApplicable(facts) {
|
|
return []Obligation{}
|
|
}
|
|
|
|
var result []Obligation
|
|
isHighRisk := m.hasHighRiskProcessing(facts)
|
|
needsDPO := m.requiresDPO(facts)
|
|
isController := facts.DataProtection.IsController
|
|
usesProcessors := facts.DataProtection.UsesExternalProcessor
|
|
|
|
for _, obl := range m.obligations {
|
|
if m.obligationApplies(obl, isController, isHighRisk, needsDPO, usesProcessors, facts) {
|
|
customized := obl
|
|
customized.RegulationID = m.ID()
|
|
result = append(result, customized)
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// obligationApplies checks if a specific obligation applies
|
|
func (m *DSGVOModule) obligationApplies(obl Obligation, isController, isHighRisk, needsDPO, usesProcessors bool, facts *UnifiedFacts) bool {
|
|
switch obl.AppliesWhen {
|
|
case "always":
|
|
return true
|
|
case "controller":
|
|
return isController
|
|
case "processor":
|
|
return !isController
|
|
case "high_risk":
|
|
return isHighRisk
|
|
case "needs_dpo":
|
|
return needsDPO
|
|
case "uses_processors":
|
|
return usesProcessors
|
|
case "controller_or_processor":
|
|
return true
|
|
case "special_categories":
|
|
return len(facts.DataProtection.SpecialCategories) > 0
|
|
case "cross_border":
|
|
return facts.DataProtection.CrossBorderProcessing
|
|
case "":
|
|
return true
|
|
default:
|
|
return true
|
|
}
|
|
}
|
|
|
|
// DeriveControls derives all applicable DSGVO controls
|
|
func (m *DSGVOModule) DeriveControls(facts *UnifiedFacts) []ObligationControl {
|
|
if !m.IsApplicable(facts) {
|
|
return []ObligationControl{}
|
|
}
|
|
|
|
var result []ObligationControl
|
|
for _, ctrl := range m.controls {
|
|
ctrl.RegulationID = m.ID()
|
|
result = append(result, ctrl)
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// GetDecisionTree returns the DSGVO applicability decision tree
|
|
func (m *DSGVOModule) GetDecisionTree() *DecisionTree {
|
|
return m.decisionTree
|
|
}
|
|
|
|
// GetIncidentDeadlines returns DSGVO breach notification deadlines
|
|
func (m *DSGVOModule) GetIncidentDeadlines(facts *UnifiedFacts) []IncidentDeadline {
|
|
if !m.IsApplicable(facts) {
|
|
return []IncidentDeadline{}
|
|
}
|
|
|
|
return m.incidentDeadlines
|
|
}
|
|
|
|
// ============================================================================
|
|
// YAML Loading
|
|
// ============================================================================
|
|
|
|
// DSGVOObligationsConfig is the YAML structure for DSGVO obligations
|
|
type DSGVOObligationsConfig struct {
|
|
Regulation string `yaml:"regulation"`
|
|
Name string `yaml:"name"`
|
|
Obligations []ObligationYAML `yaml:"obligations"`
|
|
Controls []ControlYAML `yaml:"controls"`
|
|
IncidentDeadlines []IncidentDeadlineYAML `yaml:"incident_deadlines"`
|
|
}
|
|
|
|
func (m *DSGVOModule) loadFromYAML() error {
|
|
searchPaths := []string{
|
|
"policies/obligations/dsgvo_obligations.yaml",
|
|
filepath.Join(".", "policies", "obligations", "dsgvo_obligations.yaml"),
|
|
filepath.Join("..", "policies", "obligations", "dsgvo_obligations.yaml"),
|
|
filepath.Join("..", "..", "policies", "obligations", "dsgvo_obligations.yaml"),
|
|
"/app/policies/obligations/dsgvo_obligations.yaml",
|
|
}
|
|
|
|
var data []byte
|
|
var err error
|
|
for _, path := range searchPaths {
|
|
data, err = os.ReadFile(path)
|
|
if err == nil {
|
|
break
|
|
}
|
|
}
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("DSGVO obligations YAML not found: %w", err)
|
|
}
|
|
|
|
var config DSGVOObligationsConfig
|
|
if err := yaml.Unmarshal(data, &config); err != nil {
|
|
return fmt.Errorf("failed to parse DSGVO YAML: %w", err)
|
|
}
|
|
|
|
m.convertObligations(config.Obligations)
|
|
m.convertControls(config.Controls)
|
|
m.convertIncidentDeadlines(config.IncidentDeadlines)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (m *DSGVOModule) convertObligations(yamlObls []ObligationYAML) {
|
|
for _, y := range yamlObls {
|
|
obl := Obligation{
|
|
ID: y.ID,
|
|
RegulationID: "dsgvo",
|
|
Title: y.Title,
|
|
Description: y.Description,
|
|
AppliesWhen: y.AppliesWhen,
|
|
Category: ObligationCategory(y.Category),
|
|
Responsible: ResponsibleRole(y.Responsible),
|
|
Priority: ObligationPriority(y.Priority),
|
|
ISO27001Mapping: y.ISO27001,
|
|
HowToImplement: y.HowTo,
|
|
}
|
|
|
|
for _, lb := range y.LegalBasis {
|
|
obl.LegalBasis = append(obl.LegalBasis, LegalReference{
|
|
Norm: lb.Norm,
|
|
Article: lb.Article,
|
|
})
|
|
}
|
|
|
|
if y.Deadline != nil {
|
|
obl.Deadline = &Deadline{
|
|
Type: DeadlineType(y.Deadline.Type),
|
|
Duration: y.Deadline.Duration,
|
|
}
|
|
if y.Deadline.Date != "" {
|
|
if t, err := time.Parse("2006-01-02", y.Deadline.Date); err == nil {
|
|
obl.Deadline.Date = &t
|
|
}
|
|
}
|
|
}
|
|
|
|
if y.Sanctions != nil {
|
|
obl.Sanctions = &SanctionInfo{
|
|
MaxFine: y.Sanctions.MaxFine,
|
|
PersonalLiability: y.Sanctions.PersonalLiability,
|
|
}
|
|
}
|
|
|
|
for _, e := range y.Evidence {
|
|
obl.Evidence = append(obl.Evidence, EvidenceItem{Name: e, Required: true})
|
|
}
|
|
|
|
m.obligations = append(m.obligations, obl)
|
|
}
|
|
}
|
|
|
|
func (m *DSGVOModule) convertControls(yamlCtrls []ControlYAML) {
|
|
for _, y := range yamlCtrls {
|
|
ctrl := ObligationControl{
|
|
ID: y.ID,
|
|
RegulationID: "dsgvo",
|
|
Name: y.Name,
|
|
Description: y.Description,
|
|
Category: y.Category,
|
|
WhatToDo: y.WhatToDo,
|
|
ISO27001Mapping: y.ISO27001,
|
|
Priority: ObligationPriority(y.Priority),
|
|
}
|
|
m.controls = append(m.controls, ctrl)
|
|
}
|
|
}
|
|
|
|
func (m *DSGVOModule) convertIncidentDeadlines(yamlDeadlines []IncidentDeadlineYAML) {
|
|
for _, y := range yamlDeadlines {
|
|
deadline := IncidentDeadline{
|
|
RegulationID: "dsgvo",
|
|
Phase: y.Phase,
|
|
Deadline: y.Deadline,
|
|
Content: y.Content,
|
|
Recipient: y.Recipient,
|
|
}
|
|
for _, lb := range y.LegalBasis {
|
|
deadline.LegalBasis = append(deadline.LegalBasis, LegalReference{
|
|
Norm: lb.Norm,
|
|
Article: lb.Article,
|
|
})
|
|
}
|
|
m.incidentDeadlines = append(m.incidentDeadlines, deadline)
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// Hardcoded Fallback
|
|
// ============================================================================
|
|
|
|
func (m *DSGVOModule) loadHardcodedObligations() {
|
|
m.obligations = []Obligation{
|
|
{
|
|
ID: "DSGVO-OBL-001",
|
|
RegulationID: "dsgvo",
|
|
Title: "Verarbeitungsverzeichnis führen",
|
|
Description: "Führung eines Verzeichnisses aller Verarbeitungstätigkeiten mit Angabe der Zwecke, Kategorien betroffener Personen, Empfänger, Übermittlungen in Drittländer und Löschfristen.",
|
|
LegalBasis: []LegalReference{{Norm: "Art. 30 DSGVO", Article: "Verzeichnis von Verarbeitungstätigkeiten"}},
|
|
Category: CategoryGovernance,
|
|
Responsible: RoleDSB,
|
|
Sanctions: &SanctionInfo{MaxFine: "10 Mio. EUR oder 2% Jahresumsatz"},
|
|
Evidence: []EvidenceItem{{Name: "Verarbeitungsverzeichnis", Required: true}, {Name: "Regelmäßige Aktualisierung", Required: true}},
|
|
Priority: PriorityHigh,
|
|
AppliesWhen: "always",
|
|
ISO27001Mapping: []string{"A.5.1.1"},
|
|
},
|
|
{
|
|
ID: "DSGVO-OBL-002",
|
|
RegulationID: "dsgvo",
|
|
Title: "Technische und organisatorische Maßnahmen (TOMs)",
|
|
Description: "Implementierung geeigneter technischer und organisatorischer Maßnahmen zum Schutz personenbezogener Daten unter Berücksichtigung des Stands der Technik und der Implementierungskosten.",
|
|
LegalBasis: []LegalReference{{Norm: "Art. 32 DSGVO", Article: "Sicherheit der Verarbeitung"}},
|
|
Category: CategoryTechnical,
|
|
Responsible: RoleITLeitung,
|
|
Sanctions: &SanctionInfo{MaxFine: "10 Mio. EUR oder 2% Jahresumsatz"},
|
|
Evidence: []EvidenceItem{{Name: "TOM-Dokumentation", Required: true}, {Name: "Risikoanalyse", Required: true}, {Name: "Verschlüsselungskonzept", Required: true}},
|
|
Priority: PriorityHigh,
|
|
AppliesWhen: "always",
|
|
ISO27001Mapping: []string{"A.8", "A.10", "A.12", "A.13"},
|
|
},
|
|
{
|
|
ID: "DSGVO-OBL-003",
|
|
RegulationID: "dsgvo",
|
|
Title: "Datenschutz-Folgenabschätzung (DSFA)",
|
|
Description: "Durchführung einer Datenschutz-Folgenabschätzung bei Verarbeitungsvorgängen, die voraussichtlich ein hohes Risiko für die Rechte und Freiheiten natürlicher Personen zur Folge haben.",
|
|
LegalBasis: []LegalReference{{Norm: "Art. 35 DSGVO", Article: "Datenschutz-Folgenabschätzung"}},
|
|
Category: CategoryGovernance,
|
|
Responsible: RoleDSB,
|
|
Sanctions: &SanctionInfo{MaxFine: "10 Mio. EUR oder 2% Jahresumsatz"},
|
|
Evidence: []EvidenceItem{{Name: "DSFA-Dokumentation", Required: true}, {Name: "Risikobewertung", Required: true}, {Name: "Abhilfemaßnahmen", Required: true}},
|
|
Priority: PriorityCritical,
|
|
AppliesWhen: "high_risk",
|
|
ISO27001Mapping: []string{"A.5.1.1", "A.18.1"},
|
|
},
|
|
{
|
|
ID: "DSGVO-OBL-004",
|
|
RegulationID: "dsgvo",
|
|
Title: "Datenschutzbeauftragten benennen",
|
|
Description: "Benennung eines Datenschutzbeauftragten bei öffentlichen Stellen, systematischer Überwachung im großen Umfang oder Verarbeitung besonderer Kategorien im großen Umfang.",
|
|
LegalBasis: []LegalReference{{Norm: "Art. 37 DSGVO", Article: "Benennung eines Datenschutzbeauftragten"}, {Norm: "§ 38 BDSG"}},
|
|
Category: CategoryGovernance,
|
|
Responsible: RoleManagement,
|
|
Sanctions: &SanctionInfo{MaxFine: "10 Mio. EUR oder 2% Jahresumsatz"},
|
|
Evidence: []EvidenceItem{{Name: "DSB-Bestellung", Required: true}, {Name: "Meldung an Aufsichtsbehörde", Required: true}, {Name: "Veröffentlichung Kontaktdaten", Required: true}},
|
|
Priority: PriorityHigh,
|
|
AppliesWhen: "needs_dpo",
|
|
},
|
|
{
|
|
ID: "DSGVO-OBL-005",
|
|
RegulationID: "dsgvo",
|
|
Title: "Auftragsverarbeitungsvertrag (AVV)",
|
|
Description: "Abschluss eines Auftragsverarbeitungsvertrags mit allen Auftragsverarbeitern, der die Pflichten gemäß Art. 28 Abs. 3 DSGVO enthält.",
|
|
LegalBasis: []LegalReference{{Norm: "Art. 28 DSGVO", Article: "Auftragsverarbeiter"}},
|
|
Category: CategoryOrganizational,
|
|
Responsible: RoleDSB,
|
|
Sanctions: &SanctionInfo{MaxFine: "10 Mio. EUR oder 2% Jahresumsatz"},
|
|
Evidence: []EvidenceItem{{Name: "AVV-Vertrag", Required: true}, {Name: "TOM-Nachweis des Auftragsverarbeiters", Required: true}, {Name: "Verzeichnis der Auftragsverarbeiter", Required: true}},
|
|
Priority: PriorityHigh,
|
|
AppliesWhen: "uses_processors",
|
|
},
|
|
{
|
|
ID: "DSGVO-OBL-006",
|
|
RegulationID: "dsgvo",
|
|
Title: "Informationspflichten erfüllen",
|
|
Description: "Information der betroffenen Personen über die Verarbeitung ihrer Daten bei Erhebung (Art. 13) oder nachträglich (Art. 14).",
|
|
LegalBasis: []LegalReference{{Norm: "Art. 13 DSGVO", Article: "Informationspflicht bei Erhebung"}, {Norm: "Art. 14 DSGVO", Article: "Informationspflicht bei Dritterhebung"}},
|
|
Category: CategoryOrganizational,
|
|
Responsible: RoleDSB,
|
|
Sanctions: &SanctionInfo{MaxFine: "20 Mio. EUR oder 4% Jahresumsatz"},
|
|
Evidence: []EvidenceItem{{Name: "Datenschutzerklärung", Required: true}, {Name: "Cookie-Banner", Required: true}, {Name: "Informationsblätter", Required: true}},
|
|
Priority: PriorityHigh,
|
|
AppliesWhen: "controller",
|
|
},
|
|
{
|
|
ID: "DSGVO-OBL-007",
|
|
RegulationID: "dsgvo",
|
|
Title: "Betroffenenrechte umsetzen",
|
|
Description: "Einrichtung von Prozessen zur Bearbeitung von Betroffenenanfragen: Auskunft (Art. 15), Berichtigung (Art. 16), Löschung (Art. 17), Einschränkung (Art. 18), Datenübertragbarkeit (Art. 20), Widerspruch (Art. 21).",
|
|
LegalBasis: []LegalReference{{Norm: "Art. 15-21 DSGVO", Article: "Betroffenenrechte"}},
|
|
Category: CategoryOrganizational,
|
|
Responsible: RoleDSB,
|
|
Deadline: &Deadline{Type: DeadlineRelative, Duration: "1 Monat nach Anfrage"},
|
|
Sanctions: &SanctionInfo{MaxFine: "20 Mio. EUR oder 4% Jahresumsatz"},
|
|
Evidence: []EvidenceItem{{Name: "DSR-Prozess dokumentiert", Required: true}, {Name: "Anfrageformulare", Required: true}, {Name: "Bearbeitungsprotokolle", Required: true}},
|
|
Priority: PriorityCritical,
|
|
AppliesWhen: "controller",
|
|
},
|
|
{
|
|
ID: "DSGVO-OBL-008",
|
|
RegulationID: "dsgvo",
|
|
Title: "Einwilligungen dokumentieren",
|
|
Description: "Nachweis gültiger Einwilligungen: freiwillig, informiert, spezifisch, unmissverständlich, widerrufbar. Bei besonderen Kategorien: ausdrücklich.",
|
|
LegalBasis: []LegalReference{{Norm: "Art. 7 DSGVO", Article: "Bedingungen für die Einwilligung"}, {Norm: "Art. 9 Abs. 2 lit. a DSGVO"}},
|
|
Category: CategoryGovernance,
|
|
Responsible: RoleDSB,
|
|
Sanctions: &SanctionInfo{MaxFine: "20 Mio. EUR oder 4% Jahresumsatz"},
|
|
Evidence: []EvidenceItem{{Name: "Consent-Management-System", Required: true}, {Name: "Einwilligungsprotokolle", Required: true}, {Name: "Widerrufsprozess", Required: true}},
|
|
Priority: PriorityHigh,
|
|
AppliesWhen: "controller",
|
|
},
|
|
{
|
|
ID: "DSGVO-OBL-009",
|
|
RegulationID: "dsgvo",
|
|
Title: "Datenschutz durch Technikgestaltung",
|
|
Description: "Umsetzung von Datenschutz durch Technikgestaltung (Privacy by Design) und datenschutzfreundliche Voreinstellungen (Privacy by Default).",
|
|
LegalBasis: []LegalReference{{Norm: "Art. 25 DSGVO", Article: "Datenschutz durch Technikgestaltung"}},
|
|
Category: CategoryTechnical,
|
|
Responsible: RoleITLeitung,
|
|
Sanctions: &SanctionInfo{MaxFine: "10 Mio. EUR oder 2% Jahresumsatz"},
|
|
Evidence: []EvidenceItem{{Name: "Privacy-by-Design-Konzept", Required: true}, {Name: "Default-Einstellungen dokumentiert", Required: true}},
|
|
Priority: PriorityMedium,
|
|
AppliesWhen: "controller",
|
|
ISO27001Mapping: []string{"A.14.1.1"},
|
|
},
|
|
{
|
|
ID: "DSGVO-OBL-010",
|
|
RegulationID: "dsgvo",
|
|
Title: "Löschkonzept umsetzen",
|
|
Description: "Implementierung eines Löschkonzepts mit definierten Aufbewahrungsfristen und automatisierten Löschroutinen.",
|
|
LegalBasis: []LegalReference{{Norm: "Art. 17 DSGVO", Article: "Recht auf Löschung"}, {Norm: "Art. 5 Abs. 1 lit. e DSGVO", Article: "Speicherbegrenzung"}},
|
|
Category: CategoryTechnical,
|
|
Responsible: RoleITLeitung,
|
|
Sanctions: &SanctionInfo{MaxFine: "20 Mio. EUR oder 4% Jahresumsatz"},
|
|
Evidence: []EvidenceItem{{Name: "Löschkonzept", Required: true}, {Name: "Aufbewahrungsfristen", Required: true}, {Name: "Löschprotokolle", Required: true}},
|
|
Priority: PriorityHigh,
|
|
AppliesWhen: "always",
|
|
},
|
|
{
|
|
ID: "DSGVO-OBL-011",
|
|
RegulationID: "dsgvo",
|
|
Title: "Drittlandtransfer absichern",
|
|
Description: "Bei Übermittlung in Drittländer: Angemessenheitsbeschluss, Standardvertragsklauseln (SCCs), BCRs oder andere Garantien nach Kapitel V DSGVO.",
|
|
LegalBasis: []LegalReference{{Norm: "Art. 44-49 DSGVO", Article: "Übermittlung in Drittländer"}},
|
|
Category: CategoryOrganizational,
|
|
Responsible: RoleDSB,
|
|
Sanctions: &SanctionInfo{MaxFine: "20 Mio. EUR oder 4% Jahresumsatz"},
|
|
Evidence: []EvidenceItem{{Name: "SCCs abgeschlossen", Required: true}, {Name: "Transfer Impact Assessment", Required: true}, {Name: "Dokumentation der Garantien", Required: true}},
|
|
Priority: PriorityCritical,
|
|
AppliesWhen: "cross_border",
|
|
},
|
|
{
|
|
ID: "DSGVO-OBL-012",
|
|
RegulationID: "dsgvo",
|
|
Title: "Meldeprozess für Datenschutzverletzungen",
|
|
Description: "Etablierung eines Prozesses zur Erkennung, Bewertung und Meldung von Datenschutzverletzungen an die Aufsichtsbehörde und ggf. an betroffene Personen.",
|
|
LegalBasis: []LegalReference{{Norm: "Art. 33 DSGVO", Article: "Meldung an Aufsichtsbehörde"}, {Norm: "Art. 34 DSGVO", Article: "Benachrichtigung Betroffener"}},
|
|
Category: CategoryMeldepflicht,
|
|
Responsible: RoleDSB,
|
|
Sanctions: &SanctionInfo{MaxFine: "10 Mio. EUR oder 2% Jahresumsatz"},
|
|
Evidence: []EvidenceItem{{Name: "Breach-Notification-Prozess", Required: true}, {Name: "Meldevorlage", Required: true}, {Name: "Vorfallprotokoll", Required: true}},
|
|
Priority: PriorityCritical,
|
|
AppliesWhen: "always",
|
|
},
|
|
}
|
|
|
|
// Hardcoded controls
|
|
m.controls = []ObligationControl{
|
|
{
|
|
ID: "DSGVO-CTRL-001",
|
|
RegulationID: "dsgvo",
|
|
Name: "Consent-Management-System",
|
|
Description: "Implementierung eines Systems zur Verwaltung von Einwilligungen",
|
|
Category: "Technisch",
|
|
WhatToDo: "Implementierung einer Consent-Management-Plattform mit Protokollierung, Widerrufsmöglichkeit und Nachweis",
|
|
ISO27001Mapping: []string{"A.18.1"},
|
|
Priority: PriorityHigh,
|
|
},
|
|
{
|
|
ID: "DSGVO-CTRL-002",
|
|
RegulationID: "dsgvo",
|
|
Name: "Verschlüsselung personenbezogener Daten",
|
|
Description: "Verschlüsselung ruhender und übertragener Daten",
|
|
Category: "Technisch",
|
|
WhatToDo: "Implementierung von TLS 1.3 für Übertragung, AES-256 für Speicherung, Key-Management",
|
|
ISO27001Mapping: []string{"A.10.1"},
|
|
Priority: PriorityHigh,
|
|
},
|
|
{
|
|
ID: "DSGVO-CTRL-003",
|
|
RegulationID: "dsgvo",
|
|
Name: "Zugriffskontrolle",
|
|
Description: "Need-to-know-Prinzip für Zugriff auf personenbezogene Daten",
|
|
Category: "Organisatorisch",
|
|
WhatToDo: "Rollenbasierte Zugriffssteuerung (RBAC), regelmäßige Überprüfung der Berechtigungen, Protokollierung",
|
|
ISO27001Mapping: []string{"A.9.1", "A.9.2", "A.9.4"},
|
|
Priority: PriorityHigh,
|
|
},
|
|
{
|
|
ID: "DSGVO-CTRL-004",
|
|
RegulationID: "dsgvo",
|
|
Name: "Pseudonymisierung/Anonymisierung",
|
|
Description: "Anwendung von Pseudonymisierung wo möglich, Anonymisierung für Analysen",
|
|
Category: "Technisch",
|
|
WhatToDo: "Implementierung von Pseudonymisierungsverfahren, getrennte Speicherung von Zuordnungstabellen",
|
|
ISO27001Mapping: []string{"A.8.2"},
|
|
Priority: PriorityMedium,
|
|
},
|
|
{
|
|
ID: "DSGVO-CTRL-005",
|
|
RegulationID: "dsgvo",
|
|
Name: "Datenschutz-Schulungen",
|
|
Description: "Regelmäßige Schulung aller Mitarbeiter zu Datenschutzthemen",
|
|
Category: "Organisatorisch",
|
|
WhatToDo: "Jährliche Pflichtschulungen, Awareness-Kampagnen, dokumentierte Nachweise",
|
|
ISO27001Mapping: []string{"A.7.2.2"},
|
|
Priority: PriorityMedium,
|
|
},
|
|
}
|
|
|
|
// Hardcoded incident deadlines
|
|
m.incidentDeadlines = []IncidentDeadline{
|
|
{
|
|
RegulationID: "dsgvo",
|
|
Phase: "Meldung an Aufsichtsbehörde",
|
|
Deadline: "72 Stunden",
|
|
Content: "Meldung bei Verletzung des Schutzes personenbezogener Daten, es sei denn, die Verletzung führt voraussichtlich nicht zu einem Risiko für die Rechte und Freiheiten natürlicher Personen.",
|
|
Recipient: "Zuständige Datenschutz-Aufsichtsbehörde",
|
|
LegalBasis: []LegalReference{{Norm: "Art. 33 DSGVO"}},
|
|
},
|
|
{
|
|
RegulationID: "dsgvo",
|
|
Phase: "Benachrichtigung Betroffener",
|
|
Deadline: "unverzüglich",
|
|
Content: "Wenn die Verletzung voraussichtlich ein hohes Risiko für die Rechte und Freiheiten natürlicher Personen zur Folge hat, müssen die betroffenen Personen unverzüglich benachrichtigt werden.",
|
|
Recipient: "Betroffene Personen",
|
|
LegalBasis: []LegalReference{{Norm: "Art. 34 DSGVO"}},
|
|
},
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// Decision Tree
|
|
// ============================================================================
|
|
|
|
func (m *DSGVOModule) buildDecisionTree() {
|
|
m.decisionTree = &DecisionTree{
|
|
ID: "dsgvo_applicability",
|
|
Name: "DSGVO Anwendbarkeits-Entscheidungsbaum",
|
|
RootNode: &DecisionNode{
|
|
ID: "root",
|
|
Question: "Verarbeitet Ihre Organisation personenbezogene Daten?",
|
|
YesNode: &DecisionNode{
|
|
ID: "eu_check",
|
|
Question: "Ist Ihre Organisation in der EU/EWR ansässig?",
|
|
YesNode: &DecisionNode{
|
|
ID: "eu_established",
|
|
Result: "DSGVO anwendbar",
|
|
Explanation: "Die DSGVO gilt für alle in der EU ansässigen Organisationen, die personenbezogene Daten verarbeiten.",
|
|
},
|
|
NoNode: &DecisionNode{
|
|
ID: "offering_check",
|
|
Question: "Bieten Sie Waren oder Dienstleistungen an Personen in der EU an?",
|
|
YesNode: &DecisionNode{
|
|
ID: "offering_to_eu",
|
|
Result: "DSGVO anwendbar",
|
|
Explanation: "Die DSGVO gilt für Organisationen außerhalb der EU, die Waren/Dienstleistungen an EU-Bürger anbieten.",
|
|
},
|
|
NoNode: &DecisionNode{
|
|
ID: "monitoring_check",
|
|
Question: "Beobachten Sie das Verhalten von Personen in der EU?",
|
|
YesNode: &DecisionNode{
|
|
ID: "monitoring_eu",
|
|
Result: "DSGVO anwendbar",
|
|
Explanation: "Die DSGVO gilt für Organisationen, die das Verhalten von Personen in der EU beobachten (z.B. Tracking, Profiling).",
|
|
},
|
|
NoNode: &DecisionNode{
|
|
ID: "not_applicable",
|
|
Result: "DSGVO nicht anwendbar",
|
|
Explanation: "Die DSGVO ist nicht anwendbar, da keine der Anknüpfungskriterien erfüllt ist.",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
NoNode: &DecisionNode{
|
|
ID: "no_personal_data",
|
|
Result: "DSGVO nicht anwendbar",
|
|
Explanation: "Die DSGVO gilt nur für die Verarbeitung personenbezogener Daten.",
|
|
},
|
|
},
|
|
}
|
|
}
|