# 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"]
```
