Configurable per-organization retention period, daily job, reuses the existing hard-delete path from PROJ-3 instead of introducing a new one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0143yYvjesjHndBACoweyK67
4.2 KiB
PROJ-12: Automatische Löschfrist für ausgetretene Mitglieder (DSGVO)
Status: Planned Created: 2026-09-11
Summary
Mitglieder mit Status left (Austritt) werden aktuell unbegrenzt aufbewahrt — PROJ-3 sperrt nur den API-/Matrix-Zugriff, löscht aber keine Daten. Das verletzt den DSGVO-Grundsatz der Speicherbegrenzung (Art. 5 Abs. 1 lit. e, Art. 17): sobald kein Zweck mehr besteht (keine Mitgliedschaft, keine gesetzliche Aufbewahrungspflicht für reine Mitgliederdaten ohne Beitrags-/Buchhaltungsbezug — siehe PRD Non-Goals), müssen die Daten gelöscht werden. Dieses Feature führt eine vereinskonfigurierbare Aufbewahrungsfrist ein, nach der left-Mitglieder automatisch über den bestehenden DELETE /api/members/:memberId-Pfad (PROJ-3) hart gelöscht werden.
Dependencies
- Requires: PROJ-3 (Mitgliederverwaltung) — nutzt den bestehenden harten Lösch-Pfad (Matrix-Erase, Cascade-Deletes, Audit-Log) 1:1, nur automatisch statt manuell ausgelöst
- Requires: PROJ-2 (Verein anlegen) — Frist wird pro Organisation konfiguriert
User Stories
- Als Vereinsadmin will ich pro Verein festlegen, nach wie vielen Tagen ausgetretene Mitglieder automatisch gelöscht werden, damit ich die Satzung/Aufbewahrungspraxis meines Vereins abbilden kann.
- Als Vereinsadmin will ich einen sinnvollen Standardwert vorfinden, falls ich die Einstellung nicht bewusst ändere, damit DSGVO-Konformität nicht von mir vergessen werden kann.
- Als System will ich täglich prüfen, welche
left-Mitglieder die Frist ihrer Organisation überschritten haben, und sie automatisch löschen. - Als Vereinsadmin will ich im Audit-Log sehen, dass ein Mitglied automatisch (nicht manuell) gelöscht wurde, um den Vorgang nachvollziehen zu können.
Acceptance Criteria
organizations-Tabelle bekommt FeldmemberRetentionDays(integer, not null, Default 90)- Neues UI-Feld in den Organisationseinstellungen zum Ändern der Frist (nur Org-Admin)
- Täglicher Hintergrund-Job (analog
startReconciliationWorker-Pattern insync-worker.ts) prüftmembersmitstatus = 'left', derenupdatedAt(Zeitpunkt des Status-Wechsels) älter ist alsorganizations.memberRetentionDays - Betroffene Mitglieder werden über denselben Pfad wie manuelles Löschen entfernt (Matrix-Erase, Cascade-Deletes für Team-Zuordnungen/Rollen/Eltern-Verknüpfungen)
- Audit-Log-Eintrag
action: "member.auto_deleted"mitactorUserId: null(System-Aktion, kein menschlicher Akteur), Metadata enthält die angewandte Frist - Keine Benachrichtigung an Admin vor der Löschung (bewusst still im Hintergrund)
- Reaktivierung vor Fristablauf (Status zurück auf
active) bricht die geplante Löschung ab — Job muss den aktuellen Status zum Ausführungszeitpunkt prüfen, nicht nur einmalig einplanen
Edge Cases
members.updatedAtexistiert aktuell nicht im Schema (nurcreatedAt) — muss ergänzt werden, sonst kein verlässlicher Zeitpunkt für "seit wannleft"- Mitglied wird mehrfach
left→active→left— Frist zählt ab dem letzten Wechsel zuleft, nicht kumulativ - Sehr kurze Frist (z.B. 0 oder negative Werte) — Validierung auf Minimum (z.B. ≥ 1 Tag) im Backend
- Job läuft während laufender manueller Löschung desselben Mitglieds —
DELETE-Route ist idempotent genug (member existiert nicht mehr → 404), Job sollte 404 vom eigenen internen Aufruf abfangen statt zu crashen - Synapse nicht erreichbar während Auto-Löschung — gleiches Verhalten wie beim manuellen Löschen: Matrix-Erase-Fehler wird geloggt, DB-Löschung läuft trotzdem durch (siehe bestehendes
try/catchin PROJ-3)
Non-Goals (für dieses Feature)
- Self-Service-Löschantrag durch das Mitglied selbst (Art. 17-Betroffenenrecht als eigener Flow) — separates Feature
- Aufbewahrung von Beitrags-/Buchhaltungsdaten (10-Jahres-Frist nach §147 AO) — laut PRD Non-Goal (kein Buchhaltungsmodul), betrifft dieses Feature nicht
- Anonymisierung statt Löschung als Alternative — MVP macht hartes Löschen, kein Soft-Anonymisieren
Notes
Direkt aus DSGVO-Rückfrage im Chat entstanden, kein formaler Requirements-Workshop nötig — Scope ist klar umrissen durch bestehenden Lösch-Pfad aus PROJ-3.