Aufsicht und Eingriff getrennt: neuer Haken "Audit-Betrieb"

Die DSGVO-Rolle trug audit:* komplett, also auch audit:admin. Ein
DSGVO-Beauftragter konnte damit seal-backlog, rehash und cleanup - seine
eigene Beweisgrundlage ersetzen. Wer das Protokoll beaufsichtigt, darf es
nicht umschreiben koennen. Dieselbe Klasse wie R184-02: falsche Domaene,
zu breit gebuendelt.

Der naheliegende Fix waere falsch gewesen. audit:admin einfach aus der
DSGVO-Rolle zu streichen haette es heimatlos gemacht: Die Admin-Rolle ist
ausdruecklich ohne audit/gdpr gebaut, einzige verbleibende Quelle waere
der Entwicklerzugriff - der alles gibt. Prod versiegeln haette dann
Vollzugriff vorausgesetzt.

Deshalb eine eigene versteckte Rolle "Audit-Betrieb" (audit:read +
audit:admin), zugewiesen ueber eine Checkbox wie DSGVO/Entwickler. DSGVO
behaelt audit:read + audit:export + gdpr:*. Fuer kein bestehendes Konto
weitet sich etwas aus; es wird enger, und wer eingreifen koennen soll,
bekommt es ausdruecklich.

Keine zusaetzliche Rechte-Huerde davor, weil das am Henne-Ei-Problem
scheitert: Nach der Aufteilung haelt zunaechst niemand audit:admin,
koennte ihn also auch niemand vergeben. Stattdessen wird die Vergabe
laut - CRITICAL im Protokoll und PERMISSION_CHANGED/CRITICAL im
Alarmkanal, samt Kennzeichen, ob sich jemand den Haken selbst gesetzt hat.

Nebenbei geschlossen: setUserGdprAccess() legte die DSGVO-Rolle im
Notfallpfad mit audit:* komplett an - eine zweite Liste, die dasselbe
bedeuten sollte und die Buendelung stillschweigend zurueckgebracht haette.

ACHTUNG beim Deploy: Bestehende DSGVO-Konten verlieren audit:admin. Wer
Prod versiegeln will, muss sich vorher "Audit-Betrieb" ankreuzen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-26 17:16:27 +02:00
co-authored by Claude Opus 5
parent 909e523634
commit fc6f39eba0
8 changed files with 232 additions and 21 deletions
+37
View File
@@ -97,6 +97,43 @@ isolierte Instanz (keine Multi-Tenancy im Code), Provisioning + Abrechnung
## ✅ Erledigt
- [x] **⚖️ Aufsicht und Eingriff getrennt: neuer Haken „Audit-Betrieb"** (2026-08-26)
- Die DSGVO-Rolle trug `audit:*` **komplett**, also auch `audit:admin`. Ein
DSGVO-Beauftragter konnte damit `seal-backlog`, `rehash` und `cleanup`
seine eigene Beweisgrundlage ersetzen. Wer das Protokoll beaufsichtigt,
darf es nicht umschreiben können. Dieselbe Klasse wie R184-02: falsche
Domäne, zu breit gebündelt.
- **Der naheliegende Fix wäre falsch gewesen.** `audit:admin` einfach aus
der DSGVO-Rolle zu streichen hätte es heimatlos gemacht: Die Admin-Rolle
ist ausdrücklich **ohne** `audit`/`gdpr` gebaut, einzige verbleibende
Quelle wäre der Entwicklerzugriff der *alles* gibt. Prod versiegeln
hätte dann Vollzugriff vorausgesetzt.
- Deshalb eine eigene versteckte Rolle **`Audit-Betrieb`**
(`audit:read` + `audit:admin`), zugewiesen über eine Checkbox wie
DSGVO/Entwickler. DSGVO behält `audit:read` + `audit:export` + `gdpr:*`.
**Für kein bestehendes Konto weitet sich etwas aus** im Gegenteil, es
wird enger, und wer eingreifen können soll, bekommt es ausdrücklich.
- **Keine zusätzliche Rechte-Hürde davor**, weil das am Henne-Ei-Problem
scheitert: Nach der Aufteilung hält zunächst niemand `audit:admin`, könnte
ihn also auch niemand vergeben. Stattdessen wird die Vergabe **laut**
CRITICAL im Protokoll **und** `PERMISSION_CHANGED`/CRITICAL im Alarmkanal,
inklusive Kennzeichen, ob sich jemand den Haken selbst gesetzt hat.
- Nebenbei geschlossen: `setUserGdprAccess()` legte die DSGVO-Rolle im
Notfallpfad mit `audit:*` komplett an eine zweite Liste, die dasselbe
bedeuten sollte und die Bündelung stillschweigend zurückgebracht hätte.
- **⚠️ Beim Deploy:** Bestehende DSGVO-Konten verlieren `audit:admin`. Wer
Prod versiegeln will, muss sich vorher „Audit-Betrieb" ankreuzen.
- **Gemeldet, nicht geändert:** Jeder mit `users:update` (also Admin) kann
sich DSGVO oder Entwicklerzugriff selbst vergeben Entwickler heißt
*alle* Rechte. Das ist vorbestehend und gehört ins Rollenmodell-Thema des
Pentesters.
- Dateien: `backend/prisma/sync-roles.ts`,
`backend/src/services/user.service.ts`,
`backend/src/controllers/user.controller.ts`,
`backend/src/utils/sanitize.ts`,
`frontend/src/pages/users/UserList.tsx`,
`frontend/src/services/api.ts`, `tools/audit-notary/README.md`
- [x] **🏷️ Siegel über null Blättern meldet nicht mehr „intakt"** (2026-08-26)
- Ein Bestandssiegel, das zum Zeitpunkt des Siegelns keinen Altbestand
vorfand, ist rechnerisch tadellos und schützt **nichts**. Gemeldet wurde