M8: Loesch-/Anonymisierungsprozess fuer Teilnehmer und Mandanten
Zwei getrennte Flows: - Teilnehmer anonymisieren statt loeschen (ledger_anonymize_participant): Name/E-Mail/PayPal-Name werden durch einen Platzhalter ersetzt, das Mitglied deaktiviert und vom Login-Konto getrennt. Buchungshistorie bleibt fuer die Kassenfuehrung erhalten, konsistent mit dem Storno-statt-Delete-Prinzip. Default-Mandant spiegelt die Anonymisierung in kl_Mitarbeiter (Email dort NOT NULL UNIQUE, bekommt Platzhalter statt NULL). Inhaber kann nicht anonymisiert werden. - Mandant vollstaendig loeschen (mandant-loeschen.php, nur Inhaber): erfordert exakte Eingabe des Kundenkuerzels, loescht die tenants-Zeile; alle tenant-scoped Tabellen kaskadieren per Fremdschluessel. users bleiben bestehen (koennen zu mehreren Mandanten gehoeren). Der migrierte Default-Mandant ist ausgenommen, da seine kl_Mitarbeiter- Historie sonst verwaisen wuerde. Live getestet: Mitglied mit Buchungshistorie anonymisiert (Historie blieb erhalten), Mandantenloeschung mit falscher/richtiger Bestaetigung geprueft, vollstaendiger Cascade-Delete ueber alle tenant-scoped Tabellen verifiziert, globale users-Zeile bleibt korrekt erhalten. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+47
-2
@@ -149,17 +149,62 @@ scripts/http-smoke.php
|
||||
geprüft, verifiziert dass keine Passwörter enthalten sind. Testdaten
|
||||
anschließend entfernt.
|
||||
|
||||
## Lösch-/Anonymisierungsprozess
|
||||
|
||||
Umgesetzte Dateien:
|
||||
|
||||
```text
|
||||
app/ledger.php (ledger_anonymize_participant)
|
||||
mitarbeiterverwalten.php
|
||||
mandant-loeschen.php
|
||||
konto.php
|
||||
scripts/http-smoke.php
|
||||
```
|
||||
|
||||
Zwei getrennte Flows, je nachdem was gelöscht werden soll:
|
||||
|
||||
- **Teilnehmer anonymisieren** statt löschen: Name, E-Mail und PayPal-Name
|
||||
werden durch einen nicht-identifizierenden Platzhalter ersetzt, das
|
||||
Mitglied wird deaktiviert und vom Login-Konto getrennt
|
||||
(`ledger_anonymize_participant()`). Die Ledger-Historie (Buchungen)
|
||||
bleibt für die Kassenführung erhalten – konsistent mit dem
|
||||
„keine harten Deletes"-Prinzip für Buchungen. Für den Default-Mandanten
|
||||
wird die verknüpfte `kl_Mitarbeiter`-Zeile mitanonymisiert (`Email` ist
|
||||
dort NOT NULL UNIQUE, bekommt also einen Platzhalter statt NULL). Der
|
||||
Inhaber kann nicht anonymisiert werden. Button „Anonymisieren" mit
|
||||
JS-Bestätigungsdialog in `mitarbeiterverwalten.php`.
|
||||
- **Mandant vollständig löschen**: neue Seite `mandant-loeschen.php`
|
||||
(nur Inhaber). Erfordert die exakte Eingabe des Kundenkürzels zur
|
||||
Bestätigung. Löscht die `tenants`-Zeile; alle tenant-scoped Tabellen
|
||||
(`participants`, `ledger_entries`, `notices`, `tenant_memberships`,
|
||||
`audit_log`, `outbound_emails`, `payment_import_batches`/`_rows`,
|
||||
`tenant_settings`) sind per Fremdschlüssel `ON DELETE CASCADE`
|
||||
verknüpft und verschwinden automatisch mit. `users` bleiben bestehen,
|
||||
da ein Login-Konto zu mehreren Mandanten gehören kann. Der migrierte
|
||||
Default-Mandant ist von dieser Selbstbedienungs-Löschung ausgenommen
|
||||
(seine `kl_Mitarbeiter`-Historie hat keinen Fremdschlüssel zu `tenants`
|
||||
und würde verwaisen); dafür verweist die Seite an den Betreiber.
|
||||
- Beide Aktionen werden auditiert (`participant.anonymized`; die
|
||||
Mandantenlöschung selbst nicht, da mit ihr auch das Audit-Log dieses
|
||||
Mandanten verschwindet – das ist beabsichtigt, echte Löschung soll
|
||||
keine Spuren hinterlassen).
|
||||
|
||||
Live getestet: Mitglied mit Buchungshistorie angelegt, anonymisiert –
|
||||
Name/E-Mail weg, Jahresstriche unverändert erhalten. Mandantenlöschung mit
|
||||
falscher Bestätigung abgewiesen, mit korrekter Bestätigung vollständig
|
||||
durchgeführt; anschließend geprüft, dass wirklich alle tenant-scoped
|
||||
Tabellen leer sind und die globale `users`-Zeile erhalten bleibt.
|
||||
|
||||
## Prüfstatus
|
||||
|
||||
- Golden Master: grün mit 104 Assertions.
|
||||
- M4 Ledger-Migration: grün mit 73 Assertions.
|
||||
- M3 Settings-Flow: grün mit 13 Assertions.
|
||||
- HTTP-Smoke: grün mit 27 geprüften Seiten.
|
||||
- HTTP-Smoke: grün mit 28 geprüften Seiten.
|
||||
- M8 Mandanten-Isolation: grün mit 10 Assertions.
|
||||
- M8 Rollenmatrix: grün mit 55 Assertions.
|
||||
|
||||
## Noch offen in M8
|
||||
|
||||
- Content-Security-Policy (braucht Template-Bereinigung der Inline-Styles).
|
||||
- Lösch-/Anonymisierungsprozess für Teilnehmer und Kunden.
|
||||
- Backup-/Restore-Prozess und Monitoring/Fehlerlogging dokumentieren.
|
||||
|
||||
@@ -652,7 +652,12 @@ Schritte:
|
||||
des eigenen Mandanten (Stammdaten, Teilnehmer, Mitglieder/Rollen,
|
||||
Buchungen, Hinweise, Importe, Mail-Log, Admin-Protokoll) ohne
|
||||
Passwörter, protokolliert im Audit-Log.
|
||||
- Lösch-/Anonymisierungsprozess für Teilnehmer und Kunden.
|
||||
- Lösch-/Anonymisierungsprozess für Teilnehmer und Kunden: erledigt.
|
||||
Teilnehmer werden anonymisiert statt gelöscht (Buchungshistorie bleibt
|
||||
für die Kassenführung erhalten), Mandanten können sich über
|
||||
`mandant-loeschen.php` mit Bestätigungseingabe vollständig selbst
|
||||
löschen (Cascade über Fremdschlüssel); der migrierte Default-Mandant
|
||||
ist davon ausgenommen.
|
||||
- Rate-Limits und Security Headers: erledigt. Globale Security-Headers
|
||||
über `app/bootstrap.php` (ohne CSP, siehe `docs/m8-haertung.md`),
|
||||
DB-gestützte Rate-Limits für Login, Registrierung und Passwort-Reset.
|
||||
|
||||
Reference in New Issue
Block a user