Roles & capabilities
This page describes the role and permission model at a technical level. It is aimed at developers. The user-facing version is under Roles & permissions.
Two role axes
Section titled “Two role axes”KanzleiSynchron distinguishes two axes (backend/api/src/auth.rs):
- Tenant roles — users of a client (Mandant). Shown in the invite form under
/settings/team. - Internal ops roles — KS internal staff. Access only via
/ops/**, not tenant users.
Tenant roles
Section titled “Tenant roles”When inviting under /settings/team, exactly these three roles are offered (frontend/src/app/(app)/settings/team/page.tsx):
| Role key | Display name | May |
|---|---|---|
reviewer | Staff / clerk (Sachbearbeiter) | Daily work: imports, reconciliation, exceptions. No team management, no settings changes. |
merchant_admin | Firm admin (Kanzlei-Admin) | Invite/suspend team, change tenant settings, trigger erasure. Owner of a tenant. |
internal_ops | Internal operator | Cross-tenant visibility. Assigned at invite time by a merchant_admin. |
Capability helpers (frontend)
Section titled “Capability helpers (frontend)”The frontend gates admin surfaces through frontend/src/lib/role-capabilities.ts rather than hard role comparisons:
| Helper | Allowed for |
|---|---|
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 |
Additionally, /me returns a capabilities: string[] array. Ops users have role: null and a separate ops_role, so role-based gates fail-closed for them; use hasCapability(caps, cap) with the constants from OPS_CAPS / TENANT_CAPS instead.
Internal ops roles (backend)
Section titled “Internal ops roles (backend)”Four scoped internal roles replace the former broad internal_ops (backend/api/src/auth.rs, Sprint 10 §13.2). merchant_admin remains allowed in all ops gates as a migration path.
| Role | Tenants | DPR / erasure | Issues | Mutate? |
|---|---|---|---|---|
super_admin | yes | yes | yes | yes |
support | read | no | yes | issues |
compliance_officer | read | yes | read | DPR |
read_only | read | read | read | no |
The corresponding backend gates:
require_super_admin—super_admin(plusmerchant_adminfor compatibility).require_support—super_adminorsupport.require_compliance—super_adminorcompliance_officer(DPR records, GDPR Art. 17 erasure).require_read_only_ok— all ops roles may run read GETs;read_onlyfails the mutating gates.
OPS_ROLES covers super_admin, support, compliance_officer, read_only, and the compatibility-retained internal_ops.
Four-eyes principle
Section titled “Four-eyes principle”Closing a period requires that a different person closes it than the one who created it. It follows that a tenant needs at least two users with access, otherwise the close cannot be performed. More on this under Roles & permissions.