Zum Inhalt springen

Rollen & Capabilities

Diese Seite beschreibt das Rollen- und Berechtigungsmodell auf technischer Ebene. Sie richtet sich an Entwickler. Die nutzerorientierte Variante steht unter Rollen & Berechtigungen.

KanzleiSynchron unterscheidet zwei Achsen (backend/api/src/auth.rs), und ein Nutzer hat genau eine Rollesuper_admin ist die bewusste Ausnahme, die beide Achsen umfasst:

  • Mandanten-Rollen — Nutzer eines Mandanten. Die App: Importe, Einstellungen, Team, Perioden, Ausnahmen.
  • Ops-Rollen — KS-internes Personal. Zugriff nur über /ops/** (die mandantenübergreifende Konsole), keine Mandanten-Nutzer.

super_admin ist die eine Rolle auf beiden Ebenen: ein Fleet-Ops-Superuser und voller Eigentümer des EIGENEN Mandanten. capabilities_for_role("super_admin") liefert das Ops-Capability-Set vereinigt mit den vollen Owner-tenant.*-Caps (merge_caps(ops_caps_dev_admin(), owner_caps())), sodass der Plattform-Superuser hochladen, das Team des eigenen Mandanten verwalten und die Danger-Zone erreichen kann. Das gewährt keine mandantenübergreifende Datenänderung — die Kunden-/Mandanten-Routen beschränken jede Abfrage und jeden Schreibvorgang auf user.tenant_id, die unveränderte Sicherheitsgrenze. dev_admin bleibt rein Ops; merchant_admin ist nur die App.

Es werden keine Standard-Zugangsdaten ausgeliefert. Nutzer registrieren sich selbst unter /sign-up:

  • Bei einem frischen Deploy wird die erste Registrierung automatisch zu merchant_admin auf dem Standard-Mandanten befördert (kein SQL nötig, damit Onboarding + App funktionieren). Sie erhält nie automatisch super_admin.
  • Jede spätere Registrierung startet als pending (null Rechte): von allem außer /me und /auth ausgeschlossen, mit 403 "Your account is awaiting activation by a tenant administrator". Der Onboarding-Schritt Loslegen erfordert merchant_admin.

Einen Pending-Nutzer befördern Sie entweder in der App (ein bestehender Admin über Einstellungen → Team) oder per Betreiber-Befehl auf dem VPS:

Terminal-Fenster
sudo ./ks-setup-helper.sh --grant-admin <email> [--grant-role merchant_admin|super_admin]

Standardrolle ist merchant_admin; mit --grant-role super_admin wird die /ops-Konsole gewährt. --dry-run zeigt eine Vorschau, ohne die DB zu verändern.

Die Mandanten-Ebene hat diese Rollen: owner, merchant_admin (= Admin), accountant (= Mitglied), reviewer, viewer und pending. Das Einladungsformular unter /settings/team (frontend/src/app/(app)/settings/team/page.tsx) bietet die zuweisbare Teilmenge an:

Rollen-SchlüsselAnzeigenameDarf
merchant_adminKanzlei-AdminTeam einladen/sperren, Mandanteneinstellungen ändern, Löschung (Erasure) auslösen. Admin / Eigentümer eines Mandanten.
reviewerSachbearbeiter / MitarbeiterTägliche Arbeit: Importe, Abstimmung, Ausnahmen. Kein Team-Management, keine Einstellungsänderung.
viewerBetrachterNur lesend.
pendingPendingSelbst registriert, null Rechte bis zur Beförderung.

Das Frontend gated Admin-Oberflächen über frontend/src/lib/role-capabilities.ts statt über harte Rollen-Vergleiche:

HelferErlaubt für
canViewAdmin(r)super_admin, support, compliance_officer, read_only, merchant_admin
canMutateTenant(r)super_admin, merchant_admin
canManageTeam(r)super_admin, merchant_admin
canRunErasure(r)super_admin, compliance_officer, merchant_admin

Zusätzlich liefert /me ein capabilities: string[]-Array. Ops-Nutzer haben role: null und ein separates ops_role, weshalb rollenbasierte Gates für sie fail-closed sind; verwende daher hasCapability(caps, cap) mit den Konstanten aus OPS_CAPS / TENANT_CAPS.

Vier abgestufte interne Rollen ersetzen das frühere breite internal_ops (backend/api/src/auth.rs, Sprint 10 §13.2). merchant_admin bleibt als Migrationspfad in allen Ops-Gates zugelassen.

RolleMandantenDPR / ErasureIssuesMutieren?
super_adminjajajaja
supportlesenneinjaIssues
compliance_officerlesenjalesenDPR
read_onlylesenlesenlesennein

Die Backend-Gates dazu:

  • require_super_adminsuper_admin (plus merchant_admin für Kompatibilität).
  • require_supportsuper_admin oder support.
  • require_compliancesuper_admin oder compliance_officer (DPR-Akten, DSGVO-Art.-17-Löschung).
  • require_read_only_ok — alle Ops-Rollen dürfen lesende GETs; read_only scheitert an den mutierenden Gates.

OPS_ROLES umfasst super_admin, support, compliance_officer, read_only und das aus Kompatibilitätsgründen geführte internal_ops. Nur super_admin trägt zusätzlich die Owner-tenant.*-Caps für den eigenen Mandanten (siehe die Vereinigung oben); die übrigen Ops-Rollen haben keine App-Fähigkeit.

set_user_role (backend/api/src/routes/admin.rs) erlaubt einem super_admin, die Ops-Rollen zuzuweisen, und das /ops-Übersicht-Dropdown (frontend/src/app/ops/overview/page.tsx) bietet sie an. Zwei Sicherungen greifen: Ein systemweites pg_advisory_xact_lock wird vor der systemweiten super_admin-Zählung genommen, sodass die Letzter-super_admin-Prüfung kein mandantenübergreifendes TOCTOU hat (der einzige super_admin im System lässt sich nicht herabstufen), und das Gewähren einer Ops-Rolle schreibt eine eigene OPS_ROLE_GRANT-Audit-Zeile (gewöhnliche Mandanten-Rollenwechsel bleiben ROLE_CHANGE). resolve_tenant_role verwendet jetzt ein deterministisches ORDER BY (höchst-privilegiert, dann stabil), sodass ein Nutzer mit mehr als einer tenant_users-Zeile vorhersehbar aufgelöst wird.

Der Periodenabschluss erfordert, dass eine andere Person abschließt als die, die die Periode angelegt hat. Daraus folgt: Ein Mandant braucht mindestens zwei Nutzer mit Zugriff, sonst lässt sich der Abschluss nicht durchführen. Mehr dazu unter Rollen & Berechtigungen.