From 030fab72e4b6432e30f1689227c16d433fe67b0d Mon Sep 17 00:00:00 2001 From: CCS Admin Date: Thu, 26 Feb 2026 15:56:48 +0000 Subject: [PATCH] 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 --- .../2026-02-26-dak-datenschutz-design.md | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 docs/plans/2026-02-26-dak-datenschutz-design.md diff --git a/docs/plans/2026-02-26-dak-datenschutz-design.md b/docs/plans/2026-02-26-dak-datenschutz-design.md new file mode 100644 index 0000000..f53cd09 --- /dev/null +++ b/docs/plans/2026-02-26-dak-datenschutz-design.md @@ -0,0 +1,106 @@ +# 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"