Audit-Log / lückenlose Dokumentation (G-4)
Bezug: G-4, R8, OP-AUDIT-1 · Status: Gebaut (Slice 6, 0.5.0) — append-only D1-Store mit
SHA-256-Hash-Verkettung; Retention/Archiv-Strategie definiert (Umsetzung offen, OP-AUDIT-1 Rest).
Warum
Medidentas koordiniert rechtsrelevante Vorgänge (Beratung, Verträge, Unterschriften, Fristen). G-4 verlangt eine lückenlose, manipulationssichere, auditierbare Historie — Grundlage für Nachweis im Streitfall, Aufsicht und interne Revision. Das Audit-Log ist append-only und nicht reverse-engineerbar (aus dem Log darf sich der ursprüngliche Zustand nachvollziehen lassen, aber das Log selbst ist nicht nachträglich umschreibbar).
Event-Modell (Skizze)
- Append-only: nur Insert, kein Update/Delete im Normalbetrieb.
- PII-arm: im Diff nur das Nötigste; sensible Inhalte als Referenz, nicht im Klartext (G-5).
- Korrelation:
trace_idverbindet Events über NextCloud-/Signatur-Webhooks hinweg.
Anforderungen
| Thema | Anforderung |
|---|---|
| Integrität | append-only; optional Hash-Verkettung (jedes Event referenziert Hash des Vorgängers) für Manipulationsschutz |
| Retention | je Entity-Typ definierte Aufbewahrungsfrist (GoBD/§147 AO + branchenspez.); Löschung erst nach Frist (Sperre statt Hard-Delete) |
| Residenz | EU-/CH-Speicherung (G-5) |
| Abfragbarkeit | nach Mandant/Entity/Zeitraum (Cockpit, Revision) |
| Backup/Restore | Restore-Punkt rekonstruierbar; Audit-Log bleibt dabei append-only |
Abgrenzung
- Audit-Log ≠ Anwendungs-Log (Observability, OP-OBS-1): Das Audit-Log ist fachlich/rechtlich (wer hat wann was getan); das Observability-Logging ist technisch (Performance, Fehler). Beide PII-arm, aber getrennt.
Umgesetzt (Slice 6, 0.5.0)
- Append-only D1-Store (
audit_event, Migration v4): nur Insert; Repo bietetappendAuditEvent+listAuditEvents(kein Update/Delete). - Hash-Verkettung (
domain/audit.ts):hash = SHA-256(vorherHash | ts | actor | mandantId | entitaet | entitaetId | aktion | details);pruefeKette()erkennt Änderung und Löschung (Tamper-Evidence). IDs sind streng monoton (ULID-monotonicFactory) → Lese-Reihenfolge = Ketten-Reihenfolge. - Quer verdrahtet (
api/audit-log.ts,AuditRecorder): jeder zustandsändernde Dienst (Mandant, Onboarding, Dokument, Signatur) schreibt ein PII-armes Event (nur IDs/Status/Enums, G-5). - API:
GET /api/mandanten/:id/audit,GET /api/audit,GET /api/audit/verify(Integritätsprüfung). Felder R8-F01..11. Client: „Verlauf"-Sektion im Mandant-Detail.
Retention-Matrix (Default, OP-AUDIT-1 — admin-/branchenspezifisch verfeinerbar)
| Entitäts-/Dokumenttyp | Mindest-Aufbewahrung | Grundlage |
|---|---|---|
| Verträge, Vollmachten, signierte Dokumente | 10 Jahre | GoBD/§147 AO, HGB |
| Beratungsdokumentation | mind. 5 Jahre (branchenspez. länger) | VVG/FinVermV, Aufsicht |
| Onboarding-/Prozess-Events | 6 Jahre | GoBD/§147 AO (Geschäftsbriefe) |
| Wiedervorlagen/Aufgaben (rein intern) | nach Zweckfortfall, ≤ 3 Jahre | Datenminimierung (G-5) |
„Löschung" = Sperrung/Anonymisierung nach Frist, nie Hard-Delete vor Fristende (Audit bleibt append-only).
Offene Punkte
- OP-AUDIT-1 (Rest): Archiv-/Cold-Storage (Export der gealterten Kette nach Cloudflare R2 +
Hash-Anker), Restore-Strategie, Concurrency-Härtung (globale Kette unter parallelen Writes →
Transaktion/Sequenz oder per-Mandant-Kette), Anbindung an
trace_idaus NextCloud-/Signatur-Webhooks.