dak.c2s/docs/plans/2026-02-26-dak-datenschutz-design.md
CCS Admin 030fab72e4 docs: add DAK-Datenschutz design for role-based data masking
Design for hiding personal data (name, birthdate) from dak_mitarbeiter
users with backend-enforced filtering and a time-limited disclosure
request mechanism for KVNR error resolution.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 15:56:48 +00:00

106 lines
4.3 KiB
Markdown

# DAK-Datenschutz: Rollenbasierte Datenmaskierung
## Ziel
DAK-Mitarbeiter (`dak_mitarbeiter`) duerfen personenbezogene Daten (Nachname, Vorname, Geburtsdatum) nicht einsehen. Die Maskierung erfolgt auf Backend-Ebene (DSGVO-konform). Bei Bedarf (z.B. KVNR-Fehler) kann ein DAK-Mitarbeiter eine zeitlich begrenzte Freigabe beim Admin anfordern.
## Architektur
**Ansatz: Backend-Filterung** — Das Backend entfernt sensible Felder aus der API-Antwort fuer `dak_mitarbeiter`. Zwei Serialisierungspfade je nach Rolle. Kein Frontend-only-Masking, da technisch versierte Nutzer sonst per DevTools an die Daten kaemen.
## 1. Backend-Serialisierung
### Zwei Response-Pfade
- **Admin:** Voller `CaseResponse` wie bisher (alle Felder).
- **dak_mitarbeiter:** Felder `nachname`, `vorname`, `geburtsdatum` werden auf `null` gesetzt, es sei denn eine aktive Freigabe existiert. Zusaetzliches Feld `disclosure_granted: bool` in der Response.
### Suchfunktion
Der `search`-Query-Parameter durchsucht aktuell: nachname, vorname, fall_id, kvnr. Fuer `dak_mitarbeiter` wird die Suche auf **fall_id und kvnr** beschraenkt.
## 2. Freigabe-Mechanismus (Disclosure Requests)
### Neues Modell: `DisclosureRequest`
Tabelle `disclosure_requests`:
| Feld | Typ | Beschreibung |
|------|-----|-------------|
| id | int (PK) | Auto-increment |
| case_id | int (FK -> cases) | Betroffener Fall |
| requester_id | int (FK -> users) | DAK-Mitarbeiter |
| reason | str | Begruendung |
| status | str | pending / approved / rejected |
| reviewed_by | int (FK -> users, nullable) | Admin der entscheidet |
| reviewed_at | datetime (nullable) | Zeitpunkt der Entscheidung |
| expires_at | datetime (nullable) | 24h nach Genehmigung |
| created_at | datetime | Anfragezeitpunkt |
### Ablauf
1. DAK-Mitarbeiter sieht Fall -> klickt "Personendaten anfordern"
2. Gibt Begruendung ein -> `POST /cases/{case_id}/disclosure-request`
3. Admin erhaelt Notification (Typ `disclosure_request`)
4. Admin sieht offene Anfragen unter `/admin/disclosures`
5. Admin genehmigt/lehnt ab -> `PUT /admin/disclosure-requests/{id}`
6. Bei Genehmigung: `expires_at` = now() + 24h
7. DAK-Mitarbeiter erhaelt Notification ueber Ergebnis
8. Backend prueft bei jedem Case-Abruf: aktive Freigabe vorhanden? -> Personendaten werden mitgeliefert
### Zeitliche Begrenzung
Freigaben laufen nach 24 Stunden automatisch ab. Pruefung bei jedem API-Aufruf: `status == 'approved' AND expires_at > now()`. Kein Cronjob noetig.
## 3. Neue API-Endpoints
| Methode | Route | Rolle | Beschreibung |
|---------|-------|-------|-------------|
| POST | `/cases/{case_id}/disclosure-request` | dak_mitarbeiter | Freigabe anfordern |
| GET | `/admin/disclosure-requests` | admin | Offene Anfragen auflisten |
| GET | `/admin/disclosure-requests/count` | admin | Anzahl offener Anfragen (Badge) |
| PUT | `/admin/disclosure-requests/{id}` | admin | Genehmigen/Ablehnen |
### Bestehende Endpoints — Anpassungen
- `GET /cases/`, `GET /cases/{id}`, `GET /cases/pending-icd` — Rollenpruefung, Feldern maskieren
- Search-Parameter: nachname/vorname aus OR-Suche entfernen fuer dak_mitarbeiter
### Validierung
- Doppelte pending-Anfrage fuer gleichen Fall/User -> 409 Conflict
- Aktive (nicht abgelaufene) Freigabe existiert bereits -> 409 Conflict
- Fall nicht gefunden -> 404
## 4. Frontend-Anpassungen
### Fallliste (CasesPage)
**dak_mitarbeiter:**
- Spalten Nachname/Vorname komplett ausgeblendet (nicht gerendert)
- Suchfeld-Placeholder: "Fall-ID, KVNR..."
- Sichtbare Spalten: Datum, KVNR, Fallgruppe, ICD, Gutachten, Status
**admin:** Keine Aenderung.
### Falldetail (CaseDetail Sheet)
**dak_mitarbeiter:**
- Felder nachname, vorname, geburtsdatum ausgeblendet
- Ausnahme: Bei `disclosure_granted === true` -> Felder anzeigen mit Badge "Freigabe aktiv (laeuft ab um XX:XX)"
- Button "Personendaten anfordern" -> Dialog mit Textfeld fuer Begruendung
- Bei pending-Anfrage -> Button disabled mit "Anfrage ausstehend"
**admin:** Keine Aenderung.
### Admin-Bereich
- Neuer Sidebar-Eintrag: "Freigabe-Anfragen" (`/admin/disclosures`) mit Badge-Counter
- Listenseite mit offenen Requests: Fall-ID, Anfragender User, Begruendung, Datum
- Approve/Reject-Buttons pro Anfrage
### Notifications
Bestehendes Notification-System wird erweitert:
- DAK-Mitarbeiter: "Ihre Freigabe fuer Fall XYZ wurde genehmigt/abgelehnt"
- Admin: "Neue Freigabe-Anfrage von [Username] fuer Fall XYZ"