# DSFA — Datenschutz-Folgenabschätzung (Art. 35 DSGVO) Das DSFA-Modul implementiert die Datenschutz-Folgenabschätzung gemäß Art. 35 DSGVO. Es ist vollständig backend-persistent mit CRUD-Operationen, Audit-Log und Schnell-Statuswechsel. **Route:** `/sdk/dsfa` | **Backend:** `backend-compliance:8002` | **Migration:** `024_dsfa.sql` --- ## Übersicht | Checkpoint | Reviewer | Rechtsgrundlage | Status | |-----------|----------|-----------------|--------| | CP-DSFA (REQUIRED) | DSB | Art. 35 DSGVO | ✅ 100% | **Wann ist eine DSFA Pflicht?** Eine Datenschutz-Folgenabschätzung ist nach Art. 35 Abs. 1 DSGVO zwingend erforderlich, wenn eine Verarbeitungstätigkeit voraussichtlich ein **hohes Risiko** für die Rechte und Freiheiten natürlicher Personen mit sich bringt. Typische Fälle: - Automatisierte Entscheidungen / Profiling (Art. 35 Abs. 3a) - Umfangreiche Verarbeitung besonderer Kategorien (Art. 9/10 DSGVO) - Systematische Überwachung öffentlicher Bereiche (Art. 35 Abs. 3c) - KI-basierte Systeme im Hochrisiko-Bereich (EU AI Act) --- ## Funktionen - **CRUD-Operationen:** Anlegen, Lesen, Aktualisieren, Löschen von DSFA-Datensätzen - **Status-Workflow:** `draft` → `in-review` → `approved` / `needs-update` - **Risikostufen:** `low` / `medium` / `high` / `critical` - **Datenkategorien:** Mehrfachauswahl der verarbeiteten Datenkategorien (JSONB) - **Empfänger:** Dokumentation der Datenempfänger (JSONB) - **Schutzmaßnahmen:** Erfassung technischer und organisatorischer Maßnahmen (JSONB) - **Schnell-Statuswechsel:** PATCH-Endpoint für Status-Übergang ohne vollständiges Update - **Genehmigungsdokumentation:** `approved_by` + `approved_at` bei Status `approved` - **Audit-Log:** Nachvollziehbare Protokollierung aller Aktionen (CREATE / UPDATE / DELETE / STATUS_CHANGE) - **Statistiken:** Zähler nach Status und Risiko-Level - **Filter:** Liste filterbar nach `status`, `risk_level` - **Löschung:** DSGVO-Art.-17-konforme Löschung inkl. Audit-Log-Eintrag --- ## API-Endpoints | Methode | Pfad | Beschreibung | |---------|------|--------------| | `GET` | `/api/v1/dsfa` | Liste (Filter: tenant_id, status, risk_level, skip, limit) | | `POST` | `/api/v1/dsfa` | Neue DSFA anlegen → HTTP 201 | | `GET` | `/api/v1/dsfa/stats` | Statistiken nach Status und Risiko | | `GET` | `/api/v1/dsfa/audit-log` | Audit-Trail (limit, offset) | | `GET` | `/api/v1/dsfa/{id}` | Einzelne DSFA abrufen | | `PUT` | `/api/v1/dsfa/{id}` | DSFA vollständig aktualisieren | | `DELETE` | `/api/v1/dsfa/{id}` | DSFA löschen (Art. 17 DSGVO) | | `PATCH` | `/api/v1/dsfa/{id}/status` | Schnell-Statuswechsel | !!! info "Proxy-Route (Frontend)" Das Admin-Frontend ruft die Endpoints über den Next.js-Proxy auf: `/api/sdk/v1/dsfa/**` → `backend-compliance:8002/api/v1/dsfa/**` ### Query-Parameter (GET /api/v1/dsfa) | Parameter | Typ | Default | Beschreibung | |-----------|-----|---------|--------------| | `tenant_id` | string | `default` | Mandanten-ID | | `status` | string | — | Filter: draft, in-review, approved, needs-update | | `risk_level` | string | — | Filter: low, medium, high, critical | | `skip` | integer | 0 | Offset für Pagination | | `limit` | integer | 100 | Max. Einträge (max. 500) | ### Validierung Folgende Felder werden gegen erlaubte Werte geprüft (HTTP 422 bei Verstoß): | Feld | Erlaubte Werte | |------|----------------| | `status` | `draft`, `in-review`, `approved`, `needs-update` | | `risk_level` | `low`, `medium`, `high`, `critical` | --- ## Datenmodell ### DSFA-Objekt (Response) ```json { "id": "uuid", "tenant_id": "default", "title": "DSFA - Bewerber-Management-System", "description": "Datenschutz-Folgenabschätzung für KI-gestütztes Bewerber-Screening", "status": "in-review", "risk_level": "high", "processing_activity": "Automatisierte Bewertung von Bewerbungsunterlagen", "data_categories": ["Kontaktdaten", "Beruflicher Werdegang", "Qualifikationen"], "recipients": ["HR-Abteilung", "Fachabteilungen"], "measures": ["Verschlüsselung", "Zugriffskontrolle", "Menschliche Prüfung"], "approved_by": null, "approved_at": null, "created_by": "system", "created_at": "2026-03-04T10:00:00", "updated_at": "2026-03-04T10:00:00" } ``` ### Create-Request (POST) ```json { "title": "DSFA - Video-Überwachung Büro", "description": "Datenschutz-Folgenabschätzung für Videoüberwachung", "status": "draft", "risk_level": "medium", "processing_activity": "Videoüberwachung zu Sicherheitszwecken", "data_categories": ["Bilddaten", "Bewegungsdaten"], "recipients": ["Sicherheitsdienst"], "measures": ["Löschfristen", "Zugangsbeschränkung", "Hinweisschilder"], "created_by": "admin" } ``` ### Status-Update-Request (PATCH /{id}/status) ```json { "status": "approved", "approved_by": "DSB Müller" } ``` ### Stats-Response (GET /stats) ```json { "total": 5, "by_status": { "draft": 2, "in-review": 1, "approved": 2 }, "by_risk_level": { "low": 1, "medium": 2, "high": 2 }, "draft_count": 2, "in_review_count": 1, "approved_count": 2, "needs_update_count": 0 } ``` --- ## Status-Workflow ```mermaid stateDiagram-v2 [*] --> draft: Neu anlegen draft --> in-review: Zur Prüfung einreichen in-review --> approved: Genehmigen (approved_by pflichtend) in-review --> needs-update: Überarbeitung erforderlich needs-update --> in-review: Erneut einreichen approved --> needs-update: Erneut prüfen ``` Der Statuswechsel kann über den `PATCH /{id}/status`-Endpoint vorgenommen werden. Bei Status `approved` wird `approved_at` automatisch auf den aktuellen Zeitstempel gesetzt. --- ## DB-Tabellen | Tabelle | Modus | Migration | Beschreibung | |---------|-------|-----------|--------------| | `compliance_dsfas` | read/write | 024_dsfa.sql | DSFA-Datensätze mit JSONB-Feldern | | `compliance_dsfa_audit_log` | write | 024_dsfa.sql | Audit-Trail aller Aktionen | ### Schema: compliance_dsfas ```sql CREATE TABLE compliance_dsfas ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id VARCHAR(255) NOT NULL, title VARCHAR(500) NOT NULL, description TEXT DEFAULT '', status VARCHAR(50) NOT NULL DEFAULT 'draft', risk_level VARCHAR(50) NOT NULL DEFAULT 'low', processing_activity VARCHAR(500) DEFAULT '', data_categories JSONB DEFAULT '[]', recipients JSONB DEFAULT '[]', measures JSONB DEFAULT '[]', approved_by VARCHAR(255), approved_at TIMESTAMPTZ, created_by VARCHAR(255) DEFAULT 'system', created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); ``` --- ## Datei-Übersicht | Datei | Beschreibung | |-------|--------------| | `backend-compliance/migrations/024_dsfa.sql` | DB-Migration | | `backend-compliance/compliance/api/dsfa_routes.py` | FastAPI-Router (8 Endpoints) | | `admin-compliance/app/api/sdk/v1/dsfa/[[...path]]/route.ts` | Next.js Proxy | | `admin-compliance/app/sdk/dsfa/page.tsx` | Frontend (vollständig API-verdrahtet) | | `backend-compliance/tests/test_dsfa_routes.py` | 52 Unit-Tests | --- ## Tests ```bash # DSFA-Tests (52 Tests) cd backend-compliance && python3 -m pytest tests/test_dsfa_routes.py -v # Vollständiger Lauf python3 -m pytest tests/ -v --ignore=tests/test_company_profile_routes.py # → 680 Tests, alle grün ``` **Test-Klassen:** | Klasse | Tests | Thema | |--------|-------|-------| | `TestDSFACreate` | 6 | Schema-Defaults, Pflichtfelder, Arrays | | `TestDSFAUpdate` | 5 | Partial update, exclude_none | | `TestDSFAStatusUpdate` | 4 | Status + approved_by | | `TestGetTenantId` | 4 | Tenant-ID Fallback | | `TestDsfaToResponse` | 9 | Helper: null-safety, JSONB, ISO-Datum | | `TestValidStatusValues` | 6 | Erlaubte/verbotene Status-Werte | | `TestValidRiskLevels` | 6 | Erlaubte/verbotene Risiko-Stufen | | `TestDSFAStatsResponse` | 5 | Felder, Typen, Zähler | | `TestAuditLogEntry` | 4 | Schema, Null-Felder | | `TestDSFARouterConfig` | 3 | Prefix, Tags, Registrierung | --- ## Compliance-Kontext Die DSFA ist ein **REQUIRED**-Modul (Checkpoint CP-DSFA) — Bestandteil der Dokumentationsphase zusammen mit VVT (CP-VVT), Löschfristen (CP-LOSCH) und Einwilligungen (CP-CONS). Eine abgeschlossene DSFA liefert Evidence für: - **TOM-Modul:** Schutzmaßnahmen aus DSFA.measures → TOM-Einträge - **Audit Checklist:** DSFA-Abschluss ist Prüfpunkt im Audit - **Obligations:** Verpflichtung zur DSFA nach Art. 35 DSGVO - **VVT:** `dpia_required`-Flag in Verarbeitungstätigkeiten verweist auf DSFA-Einträge ```mermaid graph LR VVT["VVT (Art. 30)"] -->|dpia_required| DSFA["DSFA (Art. 35)"] DSFA --> TOM["TOM (Art. 32)"] DSFA --> Audit["Audit Checklist"] DSFA --> Obligation["Obligations"] ```