Files
kaffeekasse-saas/docs/backoffice.md
T
clemensandClaude Sonnet 5 cbe6547f3a Back-Office: globaler Platform-Admin-Zugang ueber alle Mandanten
Neue, bewusst von tenant_memberships/saas_user_has_role() komplett
getrennte Platform-Admin-Ebene (neue Tabelle platform_admins), damit die
bestehende, automatisiert getestete Mandanten-Isolation
(check-m8-tenant-isolation.php, check-m8-role-matrix.php) unangetastet
bleibt - Platform-Admin-Rechte wirken ausschliesslich auf den neuen
backoffice-*.php-Seiten.

- backoffice.php: Uebersicht aller Mandanten (Status, Teilnehmerzahl,
  Saldensumme).
- backoffice-mandant.php: reine Leseansicht eines Mandanten (Einstellungen,
  Mitglieder/Rollen, letzte Buchungen, letzte Admin-Aktionen). Bewusst
  kein Schreibzugriff von hier aus.
- backoffice-export.php: nutzt dieselbe app_export_tenant_data() wie der
  Selbstbedienungs-Export, ausgeloest durch den Platform-Admin fuer
  beliebige Mandanten.
- scripts/grant-platform-admin.php: CLI-only Bootstrap fuer den ersten
  Platform-Admin, bewusst keine Web-UI dafuer.
- Jede Back-Office-Ansicht/-Export wird im Audit-Log DES BETROFFENEN
  MANDANTEN protokolliert (Transparenzpflicht), nicht nur beim Betreiber.

Der bestehende Selbstbedienungs-Export (datenexport.php aus M8) bleibt
zusaetzlich bestehen statt ersetzt zu werden: der Mandant ist im AV-
Verhaeltnis Verantwortlicher, Art. 15/20/28 DSGVO verpflichten den
Auftragsverarbeiter zur Unterstuetzung bei Ausk''unfts-/Portabilitaets-
rechten - ein jederzeit verfuegbarer Mandanten-Export erfuellt das direkt.
Details und Begruendung in docs/backoffice.md.

Live getestet: Back-Office zeigt alle Mandanten korrekt (inkl. echter
Bestandsmandanten), Detail/Export fuer Test-Mandant funktioniert,
Audit-Log korrekt geschrieben. Kritischer Test bestanden: derselbe
Platform-Admin sieht auf normalen Mandanten-Seiten weiterhin nur seinen
eigenen Mandanten; ein eingeloggter Nicht-Platform-Admin bekommt 403.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16 22:18:48 +02:00

4.9 KiB
Raw Blame History

Back-Office (Platform-Admin)

Stand: 2026-07-16

Ergänzung außerhalb der ursprünglichen M0M9-Meilensteine: ein Betreiber-Zugang, der mandantenübergreifend alle Kunden einsehen kann getrennt von der normalen, streng mandantengebundenen Rollenlogik.

Design-Entscheidung: getrennt von tenant_memberships

Platform-Admin-Rechte sind bewusst kein Teil von saas_user_has_role()/tenant_memberships, sondern eine eigene, komplett separate Tabelle platform_admins (user_idusers.id). Das ist kein Zufall: Alle bestehenden Mandanten-Seiten und die automatisierten Isolationstests (scripts/check-m8-tenant-isolation.php, scripts/check-m8-role-matrix.php) verlassen sich darauf, dass ein Login niemals automatisch mandantenübergreifenden Zugriff bekommt. Ein Platform-Admin-Flag direkt in tenant_memberships oder users einzubauen hätte dieses Fundament unterlaufen können. Stattdessen prüft ausschließlich der neue Code-Pfad in app/platform-admin.php (app_require_platform_admin()) auf Back-Office-Seiten die Platform-Admin-Eigenschaft; alle bestehenden Seiten sind unverändert und bleiben strikt mandantengebunden.

Umgesetzte Dateien

database/migrations/0013_saas_platform_admins.sql
app/platform-admin.php
scripts/grant-platform-admin.php
backoffice.php
backoffice-mandant.php
backoffice-export.php

Erster Platform-Admin

Es gibt bewusst keine Weboberfläche, um den ersten Platform-Admin zu setzen das wäre ein öffentlich erreichbarer "werde Admin"-Endpunkt und ein erhebliches Risiko. Stattdessen: Person registriert sich normal als Mandant (oder nutzt einen bestehenden Login), danach per Shell-Zugriff auf dem Server:

php scripts/grant-platform-admin.php person@example.com

Das Skript prüft, dass der Account existiert, und legt nur dann den platform_admins-Eintrag an. Zugang entziehen aktuell nur per direktem DELETE FROM platform_admins WHERE user_id = ? (keine UI dafür aus demselben Grund wie beim Setzen).

Funktionsumfang

  • backoffice.php: Übersicht aller Mandanten mit Kürzel, Status, Erstelldatum, Teilnehmerzahl (aktiv/gesamt) und Saldensumme.
  • backoffice-mandant.php?tenant_id=X: reine Leseansicht eines einzelnen Mandanten Einstellungen, Mitglieder mit Rolle, letzte 20 Buchungen, letzte 20 Admin-Aktionen. Absichtlich kein Schreibzugriff auf Mandantendaten von hier aus, um das Risiko einer versehentlichen Fremdänderung auszuschließen.
  • backoffice-export.php: nutzt dieselbe app_export_tenant_data()- Funktion wie der Selbstbedienungs-Export, aber ausgelöst durch den Platform-Admin für einen beliebigen Mandanten.

Verhältnis zum Selbstbedienungs-Export (datenexport.php)

Bewusste Entscheidung: Der bestehende Selbstbedienungs-Export für Mandanten-Owner/Admin (datenexport.php, aus M8) bleibt zusätzlich bestehen, statt ihn durch das Back-Office zu ersetzen. Begründung: Der Mandant ist im Auftragsverarbeitungs-Verhältnis der Verantwortliche (Controller), der Betreiber dieser App der Auftragsverarbeiter (Processor). Art. 15/20 DSGVO geben den betroffenen Personen ein Auskunfts-/Portabilitätsrecht, und Art. 28 DSGVO verpflichtet den Auftragsverarbeiter, den Verantwortlichen bei der Erfüllung dieser Rechte zu unterstützen sowie Daten am Vertragsende zurückzugeben ein jederzeit verfügbarer Selbstbedienungs-Export erfüllt genau das. Das Back-Office ergänzt das um einen Betreiber-seitigen Zugriff für Support, Migrationen oder eigene Nachweispflichten, ersetzt den Mandanten-Selbstexport aber nicht.

Audit-Trail

Jede Back-Office-Ansicht und jeder Back-Office-Export wird im Audit-Log des betroffenen Mandanten protokolliert (backoffice.tenant_viewed, backoffice.tenant_exported, mit dem Platform-Admin als actor_user_id). Ein Mandant sieht damit über sein eigenes Protokoll (mandant-einstellungen.php), wann der Betreiber auf seine Daten zugegriffen hat Transparenzpflicht statt stiller Einsicht.

Prüfstatus

  • scripts/check-m8-tenant-isolation.php: weiterhin grün mit 10 Assertions das Back-Office berührt die geprüften Pfade nicht.
  • scripts/check-m8-role-matrix.php: weiterhin grün mit 55 Assertions.
  • HTTP-Smoke: grün mit 30 geprüften Seiten (zwei neue Login-Schutz-Checks für backoffice.php/backoffice-mandant.php).
  • Golden Master: grün mit 104 Assertions.

Live getestet: eigens angelegter Test-Mandant, per CLI-Skript zum Platform-Admin gemacht, Back-Office-Übersicht zeigt korrekt alle Mandanten (inklusive der echten Bestandsmandanten), Detailansicht und Export für den eigenen Test-Mandanten funktionieren, Audit-Log-Einträge korrekt geschrieben. Kritischer Isolationstest bestätigt: derselbe Platform-Admin sieht auf regulären Mandanten-Seiten (kaffeeliste.php) weiterhin ausschließlich seinen eigenen Mandanten. Ein zweiter, eingeloggter, aber nicht privilegierter Testnutzer bekommt auf backoffice.php korrekt 403 Forbidden. Alle Testdaten anschließend vollständig entfernt.