[split-required] Split 58 monoliths across Python, Go, TypeScript (Phases 1-3)

Phase 1 — Python (klausur-service): 5 monoliths → 36 files
- dsfa_corpus_ingestion.py (1,828 LOC → 5 files)
- cv_ocr_engines.py (2,102 LOC → 7 files)
- cv_layout.py (3,653 LOC → 10 files)
- vocab_worksheet_api.py (2,783 LOC → 8 files)
- grid_build_core.py (1,958 LOC → 6 files)

Phase 2 — Go (edu-search-service, school-service): 8 monoliths → 19 files
- staff_crawler.go (1,402 → 4), policy/store.go (1,168 → 3)
- policy_handlers.go (700 → 2), repository.go (684 → 2)
- search.go (592 → 2), ai_extraction_handlers.go (554 → 2)
- seed_data.go (591 → 2), grade_service.go (646 → 2)

Phase 3 — TypeScript (admin-lehrer): 45 monoliths → 220+ files
- sdk/types.ts (2,108 → 16 domain files)
- ai/rag/page.tsx (2,686 → 14 files)
- 22 page.tsx files split into _components/ + _hooks/
- 11 component files split into sub-components
- 10 SDK data catalogs added to loc-exceptions
- Deleted dead backup index_original.ts (4,899 LOC)

All original public APIs preserved via re-export facades.
Zero new errors: Python imports verified, Go builds clean,
TypeScript tsc --noEmit shows only pre-existing errors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-04-24 17:28:57 +02:00
parent 9ba420fa91
commit b681ddb131
251 changed files with 30016 additions and 25037 deletions

View File

@@ -0,0 +1,104 @@
/**
* DSFA API Types - Request/response types and UCCA integration
*
* All types used for API communication with the DSFA backend.
*/
import type { DSFAStatus, DSFARiskLevel } from './types-core'
import type { DSFA } from './types-assessment'
// =============================================================================
// API REQUEST/RESPONSE TYPES
// =============================================================================
export interface DSFAListResponse {
dsfas: DSFA[]
}
export interface DSFAStatsResponse {
status_stats: Record<DSFAStatus | 'total', number>
risk_stats: Record<DSFARiskLevel, number>
total: number
}
export interface CreateDSFARequest {
name: string
description?: string
processing_description?: string
processing_purpose?: string
data_categories?: string[]
legal_basis?: string
}
export interface CreateDSFAFromAssessmentRequest {
name?: string
description?: string
}
export interface CreateDSFAFromAssessmentResponse {
dsfa: DSFA
prefilled: boolean
assessment: unknown // UCCA Assessment
message: string
}
export interface UpdateDSFASectionRequest {
// Section 1
processing_description?: string
processing_purpose?: string
data_categories?: string[]
data_subjects?: string[]
recipients?: string[]
legal_basis?: string
legal_basis_details?: string
// Section 2
necessity_assessment?: string
proportionality_assessment?: string
data_minimization?: string
alternatives_considered?: string
retention_justification?: string
// Section 3
overall_risk_level?: DSFARiskLevel
risk_score?: number
affected_rights?: string[]
// Section 5
dpo_consulted?: boolean
dpo_name?: string
dpo_opinion?: string
authority_consulted?: boolean
authority_reference?: string
authority_decision?: string
}
export interface SubmitForReviewResponse {
message: string
dsfa: DSFA
}
export interface ApproveDSFARequest {
dpo_opinion: string
approved: boolean
}
// =============================================================================
// UCCA INTEGRATION TYPES
// =============================================================================
export interface DSFATriggerInfo {
required: boolean
reason: string
triggered_rules: string[]
assessment_id?: string
existing_dsfa_id?: string
}
export interface UCCATriggeredRule {
code: string
title: string
description: string
severity: 'INFO' | 'WARN' | 'BLOCK'
gdpr_ref?: string
}

View File

@@ -0,0 +1,246 @@
/**
* DSFA Assessment Types - Sub-types and main DSFA interface
*
* Risk, mitigation, review, threshold analysis, stakeholder consultation,
* and the main DSFA data model.
*/
import type {
DSFAStatus,
DSFARiskLevel,
DSFARiskCategory,
DSFAMitigationType,
DSFAMitigationStatus,
} from './types-core'
// =============================================================================
// SUB-TYPES
// =============================================================================
export interface DSFARisk {
id: string
category: DSFARiskCategory
description: string
likelihood: 'low' | 'medium' | 'high'
impact: 'low' | 'medium' | 'high'
risk_level: string
affected_data: string[]
}
export interface DSFAMitigation {
id: string
risk_id: string
description: string
type: DSFAMitigationType
status: DSFAMitigationStatus
implemented_at?: string
verified_at?: string
residual_risk: 'low' | 'medium' | 'high'
tom_reference?: string
responsible_party: string
}
export interface DSFAReviewComment {
id: string
section: number
comment: string
created_by: string
created_at: string
resolved: boolean
}
export interface DSFASectionProgress {
section_0_complete: boolean // Schwellwertanalyse
section_1_complete: boolean // Systematische Beschreibung
section_2_complete: boolean // Notwendigkeit & Verhältnismäßigkeit
section_3_complete: boolean // Risikobewertung
section_4_complete: boolean // Abhilfemaßnahmen
section_5_complete: boolean // Betroffenenperspektive (optional)
section_6_complete: boolean // DSB & Behördenkonsultation
section_7_complete: boolean // Fortschreibung & Review
}
// =============================================================================
// SCHWELLWERTANALYSE / VORABPRÜFUNG (Art. 35 Abs. 1 DSGVO)
// =============================================================================
export interface DSFAThresholdAnalysis {
id: string
dsfa_id?: string
performed_at: string
performed_by: string
// WP248 Kriterien-Bewertung
criteria_assessment: Array<{
criterion_id: string // K1-K9
applies: boolean
justification: string
}>
// Art. 35 Abs. 3 Prüfung
art35_abs3_assessment: Array<{
case_id: string // a, b, c
applies: boolean
justification: string
}>
// Ergebnis
dsfa_required: boolean
decision_justification: string
// Dokumentation der Entscheidung (gem. DSK Kurzpapier Nr. 5)
documented: boolean
documentation_reference?: string
}
// =============================================================================
// BETROFFENENPERSPEKTIVE (Art. 35 Abs. 9 DSGVO)
// =============================================================================
export interface DSFAStakeholderConsultation {
id: string
stakeholder_type: 'data_subjects' | 'representatives' | 'works_council' | 'other'
stakeholder_description: string
consultation_date?: string
consultation_method: 'survey' | 'interview' | 'workshop' | 'written' | 'other'
summary: string
concerns_raised: string[]
addressed_in_dsfa: boolean
response_documentation?: string
}
// =============================================================================
// ART. 36 KONSULTATIONSPFLICHT
// =============================================================================
export interface DSFAConsultationRequirement {
high_residual_risk: boolean
consultation_required: boolean // Art. 36 Abs. 1 DSGVO
consultation_reason?: string
authority_notified: boolean
notification_date?: string
authority_response?: string
authority_recommendations?: string[]
waiting_period_observed: boolean // 8 Wochen gem. Art. 36 Abs. 2
}
// =============================================================================
// FORTSCHREIBUNG / REVIEW (Art. 35 Abs. 11 DSGVO)
// =============================================================================
export interface DSFAReviewTrigger {
id: string
trigger_type: 'scheduled' | 'risk_change' | 'new_technology' | 'new_purpose' | 'incident' | 'regulatory' | 'other'
description: string
detected_at: string
detected_by: string
review_required: boolean
review_completed: boolean
review_date?: string
changes_made: string[]
}
export interface DSFAReviewSchedule {
next_review_date: string
review_frequency_months: number
last_review_date?: string
review_responsible: string
}
// =============================================================================
// MAIN DSFA TYPE
// =============================================================================
export interface DSFA {
id: string
tenant_id: string
namespace_id?: string
processing_activity_id?: string
assessment_id?: string
name: string
description: string
// Section 0: Schwellwertanalyse / Vorabprüfung (NEU - Art. 35 Abs. 1)
threshold_analysis?: DSFAThresholdAnalysis
wp248_criteria_met?: string[] // IDs der erfüllten WP248-Kriterien (K1-K9)
art35_abs3_triggered?: string[] // IDs der ausgelösten Art. 35 Abs. 3 Fälle
// Section 1: Systematische Beschreibung (Art. 35 Abs. 7 lit. a)
processing_description: string
processing_purpose: string
data_categories: string[]
data_subjects: string[]
recipients: string[]
legal_basis: string
legal_basis_details?: string
// Section 2: Notwendigkeit & Verhältnismäßigkeit (Art. 35 Abs. 7 lit. b)
necessity_assessment: string
proportionality_assessment: string
data_minimization?: string
alternatives_considered?: string
retention_justification?: string
// Section 3: Risikobewertung (Art. 35 Abs. 7 lit. c)
risks: DSFARisk[]
overall_risk_level: DSFARiskLevel
risk_score: number
affected_rights?: string[]
triggered_rule_codes?: string[]
// KI-spezifische Trigger (NEU)
involves_ai?: boolean
ai_trigger_ids?: string[] // IDs der ausgelösten KI-Trigger
// Section 4: Abhilfemaßnahmen (Art. 35 Abs. 7 lit. d)
mitigations: DSFAMitigation[]
tom_references?: string[]
residual_risk_level?: DSFARiskLevel // Restrisiko nach Maßnahmen
// Section 5: Stellungnahme DSB (Art. 35 Abs. 2 + Art. 36)
dpo_consulted: boolean
dpo_consulted_at?: string
dpo_name?: string
dpo_opinion?: string
dpo_approved?: boolean
authority_consulted: boolean
authority_consulted_at?: string
authority_reference?: string
authority_decision?: string
// Art. 36 Konsultationspflicht (NEU)
consultation_requirement?: DSFAConsultationRequirement
// Betroffenenperspektive (NEU - Art. 35 Abs. 9)
stakeholder_consultations?: DSFAStakeholderConsultation[]
stakeholder_consultation_not_appropriate?: boolean
stakeholder_consultation_not_appropriate_reason?: string
// Workflow & Approval
status: DSFAStatus
submitted_for_review_at?: string
submitted_by?: string
conclusion: string
review_comments?: DSFAReviewComment[]
// Section Progress Tracking
section_progress: DSFASectionProgress
// Fortschreibung / Review (NEU - Art. 35 Abs. 11)
review_schedule?: DSFAReviewSchedule
review_triggers?: DSFAReviewTrigger[]
version: number // DSFA-Version für Fortschreibung
previous_version_id?: string
// Referenzen zu behördlichen Ressourcen
federal_state?: string // Bundesland für zuständige Aufsichtsbehörde
authority_resource_id?: string // ID aus DSFA_AUTHORITY_RESOURCES
// Metadata & Audit
metadata?: Record<string, unknown>
created_at: string
updated_at: string
created_by: string
approved_by?: string
approved_at?: string
}

View File

@@ -0,0 +1,177 @@
/**
* DSFA Authority Types - German data protection authority resources
*
* DSFA must-lists and resources for all 16 Bundeslaender + BfDI.
*/
// =============================================================================
// DSFA MUSS-LISTEN NACH BUNDESLÄNDERN
// Quellen: Jeweilige Landesdatenschutzbeauftragte
// =============================================================================
export interface DSFAAuthorityResource {
id: string
name: string
shortName: string
state: string // Bundesland oder 'Bund'
overviewUrl: string
publicSectorListUrl?: string
privateSectorListUrl?: string
templateUrl?: string
additionalResources?: Array<{ title: string; url: string }>
}
export const DSFA_AUTHORITY_RESOURCES: DSFAAuthorityResource[] = [
{
id: 'bund',
name: 'Bundesbeauftragter für den Datenschutz und die Informationsfreiheit',
shortName: 'BfDI',
state: 'Bund',
overviewUrl: 'https://www.bfdi.bund.de/DE/Fachthemen/Inhalte/Technik/Datenschutz-Folgenabschaetzungen.html',
publicSectorListUrl: 'https://www.bfdi.bund.de/SharedDocs/Downloads/DE/Muster/Liste_VerarbeitungsvorgaengeArt35.pdf',
templateUrl: 'https://www.bfdi.bund.de/SharedDocs/Downloads/DE/Muster/Muster_Hinweise_DSFA.html',
},
{
id: 'bw',
name: 'Landesbeauftragter für den Datenschutz und die Informationsfreiheit Baden-Württemberg',
shortName: 'LfDI BW',
state: 'Baden-Württemberg',
overviewUrl: 'https://www.baden-wuerttemberg.datenschutz.de/datenschutz-folgenabschaetzung/',
privateSectorListUrl: 'https://www.baden-wuerttemberg.datenschutz.de/wp-content/uploads/2018/05/Liste-von-Verarbeitungsvorg%C3%A4ngen-nach-Art.-35-Abs.-4-DS-GVO-LfDI-BW.pdf',
},
{
id: 'by',
name: 'Bayerischer Landesbeauftragter für den Datenschutz',
shortName: 'BayLfD',
state: 'Bayern',
overviewUrl: 'https://www.datenschutz-bayern.de/dsfa/',
additionalResources: [
{ title: 'DSFA-Module und Formulare', url: 'https://www.datenschutz-bayern.de/dsfa/' },
],
},
{
id: 'be',
name: 'Berliner Beauftragte für Datenschutz und Informationsfreiheit',
shortName: 'BlnBDI',
state: 'Berlin',
overviewUrl: 'https://www.datenschutz-berlin.de/themen/unternehmen/datenschutz-folgenabschaetzung/',
publicSectorListUrl: 'https://www.datenschutz-berlin.de/fileadmin/user_upload/pdf/dokumente/2018-BlnBDI_DSFA-oeffentlich.pdf',
privateSectorListUrl: 'https://www.datenschutz-berlin.de/fileadmin/user_upload/pdf/dokumente/2018-BlnBDI_DSFA-nicht-oeffentlich.pdf',
},
{
id: 'bb',
name: 'Landesbeauftragte für den Datenschutz und für das Recht auf Akteneinsicht Brandenburg',
shortName: 'LDA BB',
state: 'Brandenburg',
overviewUrl: 'https://www.lda.brandenburg.de/lda/de/datenschutz/datenschutz-folgenabschaetzung/',
publicSectorListUrl: 'https://www.lda.brandenburg.de/sixcms/media.php/9/DSFA-Liste_%C3%B6ffentlicher_Bereich.pdf',
privateSectorListUrl: 'https://www.lda.brandenburg.de/sixcms/media.php/9/DSFA-Liste_nicht_%C3%B6ffentlicher_Bereich.pdf',
},
{
id: 'hb',
name: 'Landesbeauftragte für Datenschutz und Informationsfreiheit Bremen',
shortName: 'LfDI HB',
state: 'Bremen',
overviewUrl: 'https://www.datenschutz.bremen.de/datenschutz/datenschutz-folgenabschaetzung-3884',
publicSectorListUrl: 'https://www.datenschutz.bremen.de/sixcms/media.php/13/Liste%20von%20Verarbeitungsvorg%C3%A4ngen%20nach%20Artikel%2035.pdf',
privateSectorListUrl: 'https://www.datenschutz.bremen.de/sixcms/media.php/13/DSFA%20Muss-Liste%20LfDI%20HB.pdf',
},
{
id: 'hh',
name: 'Hamburgischer Beauftragter für Datenschutz und Informationsfreiheit',
shortName: 'HmbBfDI',
state: 'Hamburg',
overviewUrl: 'https://datenschutz-hamburg.de/datenschutz-folgenabschaetzung',
publicSectorListUrl: 'https://datenschutz-hamburg.de/fileadmin/user_upload/HmbBfDI/Datenschutz/Informationen/Liste_Art_35-4_DSGVO_HmbBfDI-oeffentlicher_Bereich_v2.0a.pdf',
privateSectorListUrl: 'https://datenschutz-hamburg.de/fileadmin/user_upload/HmbBfDI/Datenschutz/Informationen/DSFA_Muss-Liste_fuer_den_nicht-oeffentlicher_Bereich_-_Stand_17.10.2018.pdf',
},
{
id: 'he',
name: 'Hessischer Beauftragter für Datenschutz und Informationsfreiheit',
shortName: 'HBDI',
state: 'Hessen',
overviewUrl: 'https://datenschutz.hessen.de/datenschutz/it-und-datenschutz/datenschutz-folgenabschaetzung',
},
{
id: 'mv',
name: 'Landesbeauftragter für Datenschutz und Informationsfreiheit Mecklenburg-Vorpommern',
shortName: 'LfDI MV',
state: 'Mecklenburg-Vorpommern',
overviewUrl: 'https://www.datenschutz-mv.de/datenschutz/DSGVO/Hilfsmittel-zur-Umsetzung/',
publicSectorListUrl: 'https://www.datenschutz-mv.de/static/DS/Dateien/DS-GVO/HilfsmittelzurUmsetzung/MV-DSFA-Muss-Liste-Oeffentlicher-Bereich.pdf',
},
{
id: 'ni',
name: 'Die Landesbeauftragte für den Datenschutz Niedersachsen',
shortName: 'LfD NI',
state: 'Niedersachsen',
overviewUrl: 'https://www.lfd.niedersachsen.de/dsgvo/liste_von_verarbeitungsvorgangen_nach_art_35_abs_4_ds_gvo/muss-listen-zur-datenschutz-folgenabschatzung-179663.html',
publicSectorListUrl: 'https://www.lfd.niedersachsen.de/download/134414/DSFA_Muss-Liste_fuer_den_oeffentlichen_Bereich.pdf',
privateSectorListUrl: 'https://www.lfd.niedersachsen.de/download/131098/Liste_von_Verarbeitungsvorgaengen_nach_Art._35_Abs._4_DS-GVO.pdf',
},
{
id: 'nw',
name: 'Landesbeauftragte für Datenschutz und Informationsfreiheit Nordrhein-Westfalen',
shortName: 'LDI NRW',
state: 'Nordrhein-Westfalen',
overviewUrl: 'https://www.ldi.nrw.de/datenschutz/wirtschaft/datenschutz-folgenabschaetzung',
publicSectorListUrl: 'https://www.ldi.nrw.de/liste-von-verarbeitungsvorgaengen-nach-art-35-abs-4-ds-gvo-fuer-den-oeffentlichen-bereich',
},
{
id: 'rp',
name: 'Landesbeauftragter für den Datenschutz und die Informationsfreiheit Rheinland-Pfalz',
shortName: 'LfDI RP',
state: 'Rheinland-Pfalz',
overviewUrl: 'https://www.datenschutz.rlp.de/themen/datenschutz-folgenabschaetzung',
},
{
id: 'sl',
name: 'Unabhängiges Datenschutzzentrum Saarland',
shortName: 'UDZ SL',
state: 'Saarland',
overviewUrl: 'https://www.datenschutz.saarland.de/themen/datenschutz-folgenabschaetzung',
privateSectorListUrl: 'https://www.datenschutz.saarland.de/fileadmin/user_upload/uds/alle_Dateien_und_Ordner_bis_2025/Download/dsfa_muss_liste_dsk_de.pdf',
},
{
id: 'sn',
name: 'Sächsische Datenschutz- und Transparenzbeauftragte',
shortName: 'SDTB',
state: 'Sachsen',
overviewUrl: 'https://www.datenschutz.sachsen.de/datenschutz-folgenabschaetzung.html',
additionalResources: [
{ title: 'Erforderlichkeit der DSFA', url: 'https://www.datenschutz.sachsen.de/erforderlichkeit.html' },
],
},
{
id: 'st',
name: 'Landesbeauftragter für den Datenschutz Sachsen-Anhalt',
shortName: 'LfD ST',
state: 'Sachsen-Anhalt',
overviewUrl: 'https://datenschutz.sachsen-anhalt.de/informationen/datenschutz-grundverordnung/liste-datenschutz-folgenabschaetzung',
publicSectorListUrl: 'https://datenschutz.sachsen-anhalt.de/fileadmin/Bibliothek/Landesaemter/LfD/Informationen/Internationales/Datenschutz-Grundverordnung/Liste_DSFA/Art-35-Liste-oeffentlicher_Bereich.pdf',
privateSectorListUrl: 'https://datenschutz.sachsen-anhalt.de/fileadmin/Bibliothek/Landesaemter/LfD/Informationen/Internationales/Datenschutz-Grundverordnung/Liste_DSFA/Art-35-Liste-nichtoeffentlicher_Bereich.pdf',
},
{
id: 'sh',
name: 'Unabhängiges Landeszentrum für Datenschutz Schleswig-Holstein',
shortName: 'ULD SH',
state: 'Schleswig-Holstein',
overviewUrl: 'https://www.datenschutzzentrum.de/datenschutzfolgenabschaetzung/',
privateSectorListUrl: 'https://www.datenschutzzentrum.de/uploads/datenschutzfolgenabschaetzung/20180525_LfD-SH_DSFA_Muss-Liste_V1.0.pdf',
additionalResources: [
{ title: 'Begleittext zur DSFA-Liste', url: 'https://www.datenschutzzentrum.de/uploads/dsgvo/2018_0807_LfD-SH_DSFA_Begleittext_V1.0a.pdf' },
],
},
{
id: 'th',
name: 'Thüringer Landesbeauftragter für den Datenschutz und die Informationsfreiheit',
shortName: 'TLfDI',
state: 'Thüringen',
overviewUrl: 'https://www.tlfdi.de/datenschutz/datenschutz-folgenabschaetzung/',
privateSectorListUrl: 'https://tlfdi.de/fileadmin/tlfdi/datenschutz/dsfa_muss-liste_04_07_18.pdf',
additionalResources: [
{ title: 'Handreichung DS-FA (nicht-öffentlich)', url: 'https://tlfdi.de/fileadmin/tlfdi/datenschutz/handreichung_ds-fa.pdf' },
{ title: 'Handreichung DS-FA (öffentlich)', url: 'https://tlfdi.de/fileadmin/tlfdi/Europa/Handreichung_zur_Datenschutz-Folgenabschaetzung_oeffentlicher_Bereich.pdf' },
],
},
]

View File

@@ -0,0 +1,109 @@
/**
* DSFA Core Types - Base enums, type aliases, and constants
*
* SDM goals, status labels, risk levels, legal bases, affected rights.
*/
// =============================================================================
// SDM GEWAEHRLEISTUNGSZIELE (Standard-Datenschutzmodell V2.0)
// =============================================================================
export type SDMGoal =
| 'datenminimierung'
| 'verfuegbarkeit'
| 'integritaet'
| 'vertraulichkeit'
| 'nichtverkettung'
| 'transparenz'
| 'intervenierbarkeit'
export const SDM_GOALS: Record<SDMGoal, { name: string; description: string; article: string }> = {
datenminimierung: {
name: 'Datenminimierung',
description: 'Verarbeitung personenbezogener Daten auf das dem Zweck angemessene, erhebliche und notwendige Mass beschraenken.',
article: 'Art. 5 Abs. 1 lit. c DSGVO',
},
verfuegbarkeit: {
name: 'Verfuegbarkeit',
description: 'Personenbezogene Daten muessen dem Verantwortlichen zur Verfuegung stehen und ordnungsgemaess im vorgesehenen Prozess verwendet werden koennen.',
article: 'Art. 32 Abs. 1 lit. b DSGVO',
},
integritaet: {
name: 'Integritaet',
description: 'Personenbezogene Daten bleiben waehrend der Verarbeitung unversehrt, vollstaendig und aktuell.',
article: 'Art. 5 Abs. 1 lit. d DSGVO',
},
vertraulichkeit: {
name: 'Vertraulichkeit',
description: 'Kein unbefugter Zugriff auf personenbezogene Daten. Nur befugte Personen koennen auf Daten zugreifen.',
article: 'Art. 32 Abs. 1 lit. b DSGVO',
},
nichtverkettung: {
name: 'Nichtverkettung',
description: 'Personenbezogene Daten duerfen nicht ohne Weiteres fuer einen anderen als den erhobenen Zweck zusammengefuehrt werden (Zweckbindung).',
article: 'Art. 5 Abs. 1 lit. b DSGVO',
},
transparenz: {
name: 'Transparenz',
description: 'Die Verarbeitung personenbezogener Daten muss fuer Betroffene und Aufsichtsbehoerden nachvollziehbar sein.',
article: 'Art. 5 Abs. 1 lit. a DSGVO',
},
intervenierbarkeit: {
name: 'Intervenierbarkeit',
description: 'Den Betroffenen werden wirksame Moeglichkeiten der Einflussnahme (Auskunft, Berichtigung, Loeschung, Widerspruch) auf die Verarbeitung gewaehrt.',
article: 'Art. 15-21 DSGVO',
},
}
// =============================================================================
// ENUMS & CONSTANTS
// =============================================================================
export type DSFAStatus = 'draft' | 'in_review' | 'approved' | 'rejected' | 'needs_update'
export type DSFARiskLevel = 'low' | 'medium' | 'high' | 'very_high'
export type DSFARiskCategory = 'confidentiality' | 'integrity' | 'availability' | 'rights_freedoms'
export type DSFAMitigationType = 'technical' | 'organizational' | 'legal'
export type DSFAMitigationStatus = 'planned' | 'in_progress' | 'implemented' | 'verified'
export const DSFA_STATUS_LABELS: Record<DSFAStatus, string> = {
draft: 'Entwurf',
in_review: 'In Prüfung',
approved: 'Genehmigt',
rejected: 'Abgelehnt',
needs_update: 'Überarbeitung erforderlich',
}
export const DSFA_RISK_LEVEL_LABELS: Record<DSFARiskLevel, string> = {
low: 'Niedrig',
medium: 'Mittel',
high: 'Hoch',
very_high: 'Sehr Hoch',
}
export const DSFA_LEGAL_BASES = {
consent: 'Art. 6 Abs. 1 lit. a DSGVO - Einwilligung',
contract: 'Art. 6 Abs. 1 lit. b DSGVO - Vertrag',
legal_obligation: 'Art. 6 Abs. 1 lit. c DSGVO - Rechtliche Verpflichtung',
vital_interests: 'Art. 6 Abs. 1 lit. d DSGVO - Lebenswichtige Interessen',
public_interest: 'Art. 6 Abs. 1 lit. e DSGVO - Öffentliches Interesse',
legitimate_interest: 'Art. 6 Abs. 1 lit. f DSGVO - Berechtigtes Interesse',
}
export const DSFA_AFFECTED_RIGHTS = [
{ id: 'right_to_information', label: 'Recht auf Information (Art. 13/14)' },
{ id: 'right_of_access', label: 'Auskunftsrecht (Art. 15)' },
{ id: 'right_to_rectification', label: 'Recht auf Berichtigung (Art. 16)' },
{ id: 'right_to_erasure', label: 'Recht auf Löschung (Art. 17)' },
{ id: 'right_to_restriction', label: 'Recht auf Einschränkung (Art. 18)' },
{ id: 'right_to_data_portability', label: 'Recht auf Datenübertragbarkeit (Art. 20)' },
{ id: 'right_to_object', label: 'Widerspruchsrecht (Art. 21)' },
{ id: 'right_not_to_be_profiled', label: 'Recht bzgl. Profiling (Art. 22)' },
{ id: 'freedom_of_expression', label: 'Meinungsfreiheit' },
{ id: 'freedom_of_association', label: 'Versammlungsfreiheit' },
{ id: 'non_discrimination', label: 'Nichtdiskriminierung' },
{ id: 'data_security', label: 'Datensicherheit' },
]

View File

@@ -0,0 +1,202 @@
/**
* DSFA Risk Helpers - Risk matrix, calculation functions, and utility helpers
*
* Risk matrix cells, risk level calculation, WP248 checks,
* Art. 36 consultation, authority lookups, review helpers, AI triggers.
*/
import type { DSFARiskLevel } from './types-core'
import type { DSFAConsultationRequirement, DSFAReviewTrigger, DSFAReviewSchedule } from './types-assessment'
import { DSFA_AUTHORITY_RESOURCES } from './types-authorities'
import type { DSFAAuthorityResource } from './types-authorities'
import { WP248_CRITERIA, ART35_ABS3_CASES, AI_DSFA_TRIGGERS } from './types-wp248'
// =============================================================================
// RISK MATRIX HELPERS
// =============================================================================
export interface RiskMatrixCell {
likelihood: 'low' | 'medium' | 'high'
impact: 'low' | 'medium' | 'high'
level: DSFARiskLevel
score: number
}
export const RISK_MATRIX: RiskMatrixCell[] = [
// Low likelihood
{ likelihood: 'low', impact: 'low', level: 'low', score: 10 },
{ likelihood: 'low', impact: 'medium', level: 'low', score: 20 },
{ likelihood: 'low', impact: 'high', level: 'medium', score: 40 },
// Medium likelihood
{ likelihood: 'medium', impact: 'low', level: 'low', score: 20 },
{ likelihood: 'medium', impact: 'medium', level: 'medium', score: 50 },
{ likelihood: 'medium', impact: 'high', level: 'high', score: 70 },
// High likelihood
{ likelihood: 'high', impact: 'low', level: 'medium', score: 40 },
{ likelihood: 'high', impact: 'medium', level: 'high', score: 70 },
{ likelihood: 'high', impact: 'high', level: 'very_high', score: 90 },
]
export function calculateRiskLevel(
likelihood: 'low' | 'medium' | 'high',
impact: 'low' | 'medium' | 'high'
): { level: DSFARiskLevel; score: number } {
const cell = RISK_MATRIX.find(c => c.likelihood === likelihood && c.impact === impact)
return cell ? { level: cell.level, score: cell.score } : { level: 'medium', score: 50 }
}
// =============================================================================
// HELPER FUNCTIONS
// =============================================================================
/**
* Prüft anhand der WP248-Kriterien, ob eine DSFA erforderlich ist.
* Regel: Bei >= 2 erfüllten Kriterien ist DSFA in den meisten Fällen erforderlich.
* @param criteriaIds Array der erfüllten Kriterien-IDs (z.B. ['K1', 'K4'])
* @returns Objekt mit Ergebnis und Begründung
*/
export function checkDSFARequiredByWP248(criteriaIds: string[]): {
required: boolean
confidence: 'definite' | 'likely' | 'possible' | 'unlikely'
reason: string
} {
const count = criteriaIds.length
if (count >= 2) {
return {
required: true,
confidence: 'definite',
reason: `${count} WP248-Kriterien erfüllt (>= 2). DSFA ist in den meisten Fällen erforderlich.`,
}
}
if (count === 1) {
return {
required: false,
confidence: 'possible',
reason: '1 WP248-Kriterium erfüllt. DSFA kann je nach Risiko dennoch erforderlich sein. Einzelfallprüfung empfohlen.',
}
}
return {
required: false,
confidence: 'unlikely',
reason: 'Keine WP248-Kriterien erfüllt. DSFA wahrscheinlich nicht erforderlich, sofern kein Art. 35 Abs. 3 Fall vorliegt.',
}
}
/**
* Prüft, ob eine Konsultation der Aufsichtsbehörde gem. Art. 36 DSGVO erforderlich ist.
* Erforderlich wenn: Hohes Restrisiko trotz geplanter Maßnahmen.
*/
export function checkArt36ConsultationRequired(
residualRiskLevel: DSFARiskLevel,
mitigationsImplemented: boolean
): DSFAConsultationRequirement {
const highResidual = residualRiskLevel === 'high' || residualRiskLevel === 'very_high'
const consultationRequired = highResidual && mitigationsImplemented
return {
high_residual_risk: highResidual,
consultation_required: consultationRequired,
consultation_reason: consultationRequired
? 'Trotz geplanter Maßnahmen verbleibt ein hohes Restrisiko. Gem. Art. 36 Abs. 1 DSGVO ist vor der Verarbeitung die Aufsichtsbehörde zu konsultieren.'
: highResidual
? 'Hohes Restrisiko festgestellt, aber Maßnahmen noch nicht vollständig umgesetzt.'
: undefined,
authority_notified: false,
waiting_period_observed: false,
}
}
/**
* Gibt die zuständige Aufsichtsbehörde für ein Bundesland zurück.
*/
export function getAuthorityResource(stateId: string): DSFAAuthorityResource | undefined {
return DSFA_AUTHORITY_RESOURCES.find(r => r.id === stateId)
}
/**
* Gibt alle Bundesländer als Auswahlliste zurück.
*/
export function getFederalStateOptions(): Array<{ value: string; label: string }> {
return DSFA_AUTHORITY_RESOURCES.map(r => ({
value: r.id,
label: r.state,
}))
}
/**
* Prüft, ob ein Review-Trigger eine Aktualisierung der DSFA erfordert.
*/
export function checkReviewRequired(triggers: DSFAReviewTrigger[]): {
required: boolean
pendingTriggers: DSFAReviewTrigger[]
} {
const pendingTriggers = triggers.filter(t => t.review_required && !t.review_completed)
return {
required: pendingTriggers.length > 0,
pendingTriggers,
}
}
/**
* Berechnet das nächste Review-Datum basierend auf dem Schedule.
*/
export function calculateNextReviewDate(schedule: DSFAReviewSchedule): Date {
const lastReview = schedule.last_review_date
? new Date(schedule.last_review_date)
: new Date()
const nextReview = new Date(lastReview)
nextReview.setMonth(nextReview.getMonth() + schedule.review_frequency_months)
return nextReview
}
/**
* Prüft, ob KI-spezifische DSFA-Trigger erfüllt sind.
*/
export function checkAIDSFATriggers(
aiTriggerIds: string[]
): { triggered: boolean; triggers: typeof AI_DSFA_TRIGGERS } {
const triggered = AI_DSFA_TRIGGERS.filter(t => aiTriggerIds.includes(t.id))
return {
triggered: triggered.length > 0,
triggers: triggered,
}
}
/**
* Generiert eine Checkliste für die Schwellwertanalyse.
*/
export function generateThresholdAnalysisChecklist(): Array<{
category: string
items: Array<{ id: string; label: string; description: string }>
}> {
return [
{
category: 'WP248 Kriterien (Art.-29-Datenschutzgruppe)',
items: WP248_CRITERIA.map(c => ({
id: c.id,
label: `${c.code}: ${c.title}`,
description: c.description,
})),
},
{
category: 'Art. 35 Abs. 3 DSGVO Regelbeispiele',
items: ART35_ABS3_CASES.map(c => ({
id: c.id,
label: `lit. ${c.lit}: ${c.title}`,
description: c.description,
})),
},
{
category: 'KI-spezifische Trigger (Deutsche DSFA-Liste)',
items: AI_DSFA_TRIGGERS.map(t => ({
id: t.id,
label: t.title,
description: t.description,
})),
},
]
}

View File

@@ -0,0 +1,95 @@
/**
* DSFA UI Types - Section configuration for the DSFA wizard UI
*
* Defines the section structure, labels, and GDPR references
* used by the frontend wizard components.
*/
// =============================================================================
// HELPER TYPES FOR UI
// =============================================================================
export interface DSFASectionConfig {
number: number
title: string
titleDE: string
description: string
gdprRef: string
fields: string[]
required: boolean
}
export const DSFA_SECTIONS: DSFASectionConfig[] = [
{
number: 0,
title: 'Threshold Analysis',
titleDE: 'Schwellwertanalyse',
description: 'Prüfen Sie anhand der WP248-Kriterien und Art. 35 Abs. 3, ob eine DSFA erforderlich ist. Die Entscheidung ist zu dokumentieren.',
gdprRef: 'Art. 35 Abs. 1 DSGVO, WP248 rev.01',
fields: ['threshold_analysis', 'wp248_criteria_met', 'art35_abs3_triggered'],
required: true,
},
{
number: 1,
title: 'Processing Description',
titleDE: 'Systematische Beschreibung',
description: 'Beschreiben Sie die geplante Verarbeitung, ihren Zweck, die Datenkategorien und Rechtsgrundlage.',
gdprRef: 'Art. 35 Abs. 7 lit. a DSGVO',
fields: ['processing_description', 'processing_purpose', 'data_categories', 'data_subjects', 'recipients', 'legal_basis'],
required: true,
},
{
number: 2,
title: 'Necessity & Proportionality',
titleDE: 'Notwendigkeit & Verhältnismäßigkeit',
description: 'Begründen Sie, warum die Verarbeitung notwendig ist und welche Alternativen geprüft wurden.',
gdprRef: 'Art. 35 Abs. 7 lit. b DSGVO',
fields: ['necessity_assessment', 'proportionality_assessment', 'data_minimization', 'alternatives_considered'],
required: true,
},
{
number: 3,
title: 'Risk Assessment',
titleDE: 'Risikobewertung',
description: 'Identifizieren und bewerten Sie die Risiken für die Rechte und Freiheiten der Betroffenen.',
gdprRef: 'Art. 35 Abs. 7 lit. c DSGVO',
fields: ['risks', 'overall_risk_level', 'risk_score', 'affected_rights', 'involves_ai', 'ai_trigger_ids'],
required: true,
},
{
number: 4,
title: 'Mitigation Measures',
titleDE: 'Abhilfemaßnahmen',
description: 'Definieren Sie technische und organisatorische Maßnahmen zur Risikominimierung und bewerten Sie das Restrisiko.',
gdprRef: 'Art. 35 Abs. 7 lit. d DSGVO',
fields: ['mitigations', 'tom_references', 'residual_risk_level'],
required: true,
},
{
number: 5,
title: 'Stakeholder Consultation',
titleDE: 'Betroffenenperspektive',
description: 'Dokumentieren Sie, ob und wie die Standpunkte der Betroffenen eingeholt wurden (z.B. Betriebsrat, Nutzerumfragen).',
gdprRef: 'Art. 35 Abs. 9 DSGVO',
fields: ['stakeholder_consultations', 'stakeholder_consultation_not_appropriate', 'stakeholder_consultation_not_appropriate_reason'],
required: false,
},
{
number: 6,
title: 'DPO Opinion & Authority Consultation',
titleDE: 'DSB-Stellungnahme & Behördenkonsultation',
description: 'Dokumentieren Sie die Konsultation des DSB und prüfen Sie, ob bei hohem Restrisiko eine Behördenkonsultation erforderlich ist.',
gdprRef: 'Art. 35 Abs. 2, Art. 36 DSGVO',
fields: ['dpo_consulted', 'dpo_opinion', 'consultation_requirement', 'authority_consulted', 'authority_reference'],
required: true,
},
{
number: 7,
title: 'Review & Maintenance',
titleDE: 'Fortschreibung & Review',
description: 'Planen Sie regelmäßige Überprüfungen und dokumentieren Sie Änderungen, die eine Aktualisierung der DSFA erfordern.',
gdprRef: 'Art. 35 Abs. 11 DSGVO',
fields: ['review_schedule', 'review_triggers', 'version'],
required: true,
},
]

View File

@@ -0,0 +1,183 @@
/**
* DSFA WP248 Types - Threshold analysis criteria, Art. 35 cases, AI triggers
*
* WP248 rev.01 criteria, DSK Kurzpapier Nr. 5, Art. 35 Abs. 3 DSGVO cases,
* and AI-specific DSFA triggers.
*/
// =============================================================================
// WP248 REV.01 KRITERIEN (Schwellwertanalyse)
// Quelle: Artikel-29-Datenschutzgruppe, bestätigt durch EDSA
// =============================================================================
export interface WP248Criterion {
id: string
code: string
title: string
description: string
examples: string[]
gdprRef?: string
}
/**
* WP248 rev.01 Kriterien zur Bestimmung der DSFA-Pflicht
* Regel: Bei >= 2 erfüllten Kriterien ist DSFA in den meisten Fällen erforderlich
*/
export const WP248_CRITERIA: WP248Criterion[] = [
{
id: 'scoring_profiling',
code: 'K1',
title: 'Bewertung oder Scoring',
description: 'Einschließlich Profiling und Prognosen, insbesondere zu Arbeitsleistung, wirtschaftlicher Lage, Gesundheit, persönlichen Vorlieben, Zuverlässigkeit, Verhalten, Aufenthaltsort oder Ortswechsel.',
examples: ['Bonitätsprüfung', 'Leistungsbeurteilung', 'Verhaltensanalyse'],
gdprRef: 'Art. 35 Abs. 3 lit. a DSGVO',
},
{
id: 'automated_decision',
code: 'K2',
title: 'Automatisierte Entscheidungsfindung mit Rechtswirkung',
description: 'Automatisierte Verarbeitung, die als Grundlage für Entscheidungen dient, die Rechtswirkung gegenüber natürlichen Personen entfalten oder diese erheblich beeinträchtigen.',
examples: ['Automatische Kreditvergabe', 'Automatische Bewerbungsablehnung', 'Algorithmenbasierte Preisgestaltung'],
gdprRef: 'Art. 22 DSGVO',
},
{
id: 'systematic_monitoring',
code: 'K3',
title: 'Systematische Überwachung',
description: 'Verarbeitung zur Beobachtung, Überwachung oder Kontrolle von betroffenen Personen, einschließlich Datenerhebung über Netzwerke oder systematische Überwachung öffentlicher Bereiche.',
examples: ['Videoüberwachung', 'WLAN-Tracking', 'GPS-Ortung', 'Mitarbeiterüberwachung'],
gdprRef: 'Art. 35 Abs. 3 lit. c DSGVO',
},
{
id: 'sensitive_data',
code: 'K4',
title: 'Sensible Daten oder höchst persönliche Daten',
description: 'Verarbeitung besonderer Kategorien personenbezogener Daten (Art. 9), strafrechtlicher Daten (Art. 10) oder anderer höchst persönlicher Daten wie Kommunikationsinhalte, Standortdaten, Finanzinformationen.',
examples: ['Gesundheitsdaten', 'Biometrische Daten', 'Genetische Daten', 'Politische Meinungen', 'Gewerkschaftszugehörigkeit'],
gdprRef: 'Art. 9, Art. 10 DSGVO',
},
{
id: 'large_scale',
code: 'K5',
title: 'Datenverarbeitung in großem Umfang',
description: 'Berücksichtigt werden: Zahl der Betroffenen, Datenmenge, Dauer der Verarbeitung, geografische Reichweite.',
examples: ['Landesweite Datenbanken', 'Millionen von Nutzern', 'Mehrjährige Speicherung'],
gdprRef: 'Erwägungsgrund 91 DSGVO',
},
{
id: 'matching_combining',
code: 'K6',
title: 'Abgleichen oder Zusammenführen von Datensätzen',
description: 'Datensätze aus verschiedenen Quellen, die für unterschiedliche Zwecke und/oder von verschiedenen Verantwortlichen erhoben wurden, werden abgeglichen oder zusammengeführt.',
examples: ['Data Warehousing', 'Big Data Analytics', 'Zusammenführung von Online-/Offline-Daten'],
},
{
id: 'vulnerable_subjects',
code: 'K7',
title: 'Daten zu schutzbedürftigen Betroffenen',
description: 'Verarbeitung von Daten schutzbedürftiger Personen, bei denen ein Ungleichgewicht zwischen Betroffenem und Verantwortlichem besteht.',
examples: ['Kinder/Minderjährige', 'Arbeitnehmer', 'Patienten', 'Ältere Menschen', 'Asylbewerber'],
gdprRef: 'Erwägungsgrund 75 DSGVO',
},
{
id: 'innovative_technology',
code: 'K8',
title: 'Innovative Nutzung oder Anwendung neuer technologischer oder organisatorischer Lösungen',
description: 'Einsatz neuer Technologien kann neue Formen der Datenerhebung und -nutzung mit sich bringen, möglicherweise mit hohem Risiko für Rechte und Freiheiten.',
examples: ['Künstliche Intelligenz', 'Machine Learning', 'IoT-Geräte', 'Biometrische Erkennung', 'Blockchain'],
gdprRef: 'Erwägungsgrund 89, 91 DSGVO',
},
{
id: 'preventing_rights',
code: 'K9',
title: 'Verarbeitung, die Betroffene an der Ausübung eines Rechts oder der Nutzung einer Dienstleistung hindert',
description: 'Verarbeitungsvorgänge, die darauf abzielen, einer Person den Zugang zu einer Dienstleistung oder den Abschluss eines Vertrags zu ermöglichen oder zu verweigern.',
examples: ['Zugang zu Sozialleistungen', 'Kreditvergabe', 'Versicherungsabschluss'],
gdprRef: 'Art. 22 DSGVO',
},
]
// =============================================================================
// DSK KURZPAPIER NR. 5 REFERENZEN
// =============================================================================
export const DSK_KURZPAPIER_5 = {
title: 'Kurzpapier Nr. 5: Datenschutz-Folgenabschätzung nach Art. 35 DS-GVO',
source: 'Datenschutzkonferenz (DSK)',
url: 'https://www.datenschutzkonferenz-online.de/media/kp/dsk_kpnr_5.pdf',
license: 'Datenlizenz Deutschland Namensnennung Version 2.0 (DL-DE BY 2.0)',
licenseUrl: 'https://www.govdata.de/dl-de/by-2-0',
processSteps: [
{ step: 1, title: 'Projektteam bilden', description: 'Interdisziplinäres Team aus Datenschutz, Fachprozess, IT/Sicherheit' },
{ step: 2, title: 'Verarbeitung abgrenzen', description: 'Scope definieren, Datenflüsse und Zwecke beschreiben' },
{ step: 3, title: 'Prüfung der Notwendigkeit', description: 'Alternativen prüfen, Datenminimierung bewerten' },
{ step: 4, title: 'Risiken identifizieren', description: 'Risikoquellen ermitteln, Schäden bewerten' },
{ step: 5, title: 'Maßnahmen festlegen', description: 'TOM definieren, Restrisiko bewerten' },
{ step: 6, title: 'Bericht erstellen', description: 'DSFA-Bericht dokumentieren, ggf. veröffentlichen' },
{ step: 7, title: 'Fortschreibung', description: 'DSFA bei Änderungen aktualisieren' },
],
}
// =============================================================================
// ART. 35 ABS. 3 DSGVO - REGELBEISPIELE
// =============================================================================
export const ART35_ABS3_CASES = [
{
id: 'profiling_legal_effects',
lit: 'a',
title: 'Profiling mit Rechtswirkung',
description: 'Systematische und umfassende Bewertung persönlicher Aspekte natürlicher Personen, die sich auf automatisierte Verarbeitung einschließlich Profiling gründet und die ihrerseits als Grundlage für Entscheidungen dient, die Rechtswirkung gegenüber natürlichen Personen entfalten oder diese in ähnlich erheblicher Weise beeinträchtigen.',
gdprRef: 'Art. 35 Abs. 3 lit. a DSGVO',
},
{
id: 'special_categories',
lit: 'b',
title: 'Besondere Datenkategorien in großem Umfang',
description: 'Umfangreiche Verarbeitung besonderer Kategorien von personenbezogenen Daten gemäß Artikel 9 Absatz 1 oder von personenbezogenen Daten über strafrechtliche Verurteilungen und Straftaten gemäß Artikel 10.',
gdprRef: 'Art. 35 Abs. 3 lit. b DSGVO',
},
{
id: 'public_monitoring',
lit: 'c',
title: 'Systematische Überwachung öffentlicher Bereiche',
description: 'Systematische umfangreiche Überwachung öffentlich zugänglicher Bereiche.',
gdprRef: 'Art. 35 Abs. 3 lit. c DSGVO',
},
]
// =============================================================================
// KI-SPEZIFISCHE DSFA-TRIGGER
// Quelle: Deutsche DSFA-Liste (nicht-öffentlicher Bereich)
// =============================================================================
export const AI_DSFA_TRIGGERS = [
{
id: 'ai_interaction',
title: 'KI zur Steuerung der Interaktion mit Betroffenen',
description: 'Einsatz von künstlicher Intelligenz zur Steuerung der Interaktion mit betroffenen Personen.',
examples: ['KI-gestützter Kundensupport', 'Chatbots mit personenbezogener Verarbeitung', 'Automatisierte Kommunikation'],
requiresDSFA: true,
},
{
id: 'ai_personal_aspects',
title: 'KI zur Bewertung persönlicher Aspekte',
description: 'Einsatz von künstlicher Intelligenz zur Bewertung persönlicher Aspekte natürlicher Personen.',
examples: ['Automatisierte Stimmungsanalyse', 'Verhaltensvorhersagen', 'Persönlichkeitsprofile'],
requiresDSFA: true,
},
{
id: 'ai_decision_making',
title: 'KI-basierte automatisierte Entscheidungen',
description: 'Automatisierte Entscheidungsfindung auf Basis von KI mit erheblicher Auswirkung auf Betroffene.',
examples: ['Automatische Kreditvergabe', 'KI-basiertes Recruiting', 'Algorithmenbasierte Preisgestaltung'],
requiresDSFA: true,
},
{
id: 'ai_training_personal_data',
title: 'KI-Training mit personenbezogenen Daten',
description: 'Training von KI-Modellen mit personenbezogenen Daten, insbesondere sensiblen Daten.',
examples: ['Training mit Gesundheitsdaten', 'Fine-Tuning mit Kundendaten', 'ML mit biometrischen Daten'],
requiresDSFA: true,
},
]

File diff suppressed because it is too large Load Diff