> [← open.SERVICE v2](<Überblick.md>)
# Berechtigungen
## Drei Ebenen
**1 · Mandantentrennung.** Je `OD3_Service_*`-Klasse ein Server-Hook, der `tenant`
setzt, den Ersteller einträgt und die Rollen-ACL schreibt. Für **Wartungspläne und
Vorlagen** bekommt die allgemeine Mandanten-Rolle dabei kein Leserecht: ein Plan
ist nicht mandantenweit sichtbar, sondern nur für die, die an ihm hängen. Es gibt
kein `beforeFind` — Sichtbarkeit hängt vollständig an der ACL des jeweiligen
Objekts.
**2 · Capabilities** (`OD3_Permission`). Sie beantworten „darf jemand *so etwas*"
und werden beim Serverstart je Mandant registriert. `usePermission` ist strikt: ist
ein Key nicht registriert **und** einer Rolle zugewiesen, blendet sich die Aktion
aus.
**3 · ACL je Datensatz.** Sie beantwortet „darf jemand *diesen* Plan" und wird bei
jedem Speichern aus Ersteller und Zuweisungen neu abgeleitet. Eine entzogene
Zuweisung wirkt damit sofort.
## Der Katalog
| Key | Zweck |
| --------------------------------------------------- | ----------------------------------------------------- |
| `openservice-schedule:can-access-schedule-plugin` | Zugang zum Wartungsmodul (Routen und Menü) |
| `openservice-schedule:can-create-schedule` | Plan anlegen |
| `openservice-schedule:can-delete-schedule` | Plan archivieren |
| `openservice-schedule:can-perform-execution` | Durchführung |
| `openservice-schedule:can-manage-template` | Vorlagenkatalog |
| `service:can-read-ticket` | Tickets sehen |
| `service:can-create-ticket` | Tickets anlegen |
| `service:can-edit-ticket` | Tickets bearbeiten |
| `service:can-delete-ticket` | Tickets löschen |
| `service:can-assign-ticket` | Tickets zuweisen |
| `service:can-manage-masterdata` | Stammdaten |
| `service:can-manage-formconfig` | Ticketformulare |
| `service:can-create-tag` | Tag aus einem Tag-Feld heraus anlegen |
| `service:can-view-analytics` | Auswertungen |
**Zwei Namensräume.** Die Wartungs-Keys tragen den Präfix
`openservice-schedule:`, alles modulübergreifend Geteilte bleibt bei `service:`.
Der Präfix ist zugleich der i18n-Namespace, unter dem die Rechteverwaltung Label
und Beschreibung eines Keys sucht. Wer einen Key hinzufügt oder umbenennt, fasst
Server-Enum, Frontend-Katalog und die Übersetzungsdateien gemeinsam an.
**Jede Route und jeder Menüeintrag des Wartungsmoduls hängt an
`can-access-schedule-plugin`.** Fehlt der Key, existiert das Modul für diesen
Benutzer nicht.
> [!info] Es gibt kein `can-read-schedule` und kein `can-edit-schedule`
> Beide würden eine Frage beantworten, die schon die ACL beantwortet — und zwar
> **pro Datensatz**, während eine Capability nur global antworten kann. Sie
> widersprächen sich in dem Moment, in dem jemand einem Plan zugewiesen wird, ohne
> die Capability zu halten: das UI würde sperren, was der Server erlaubt.
>
> `create` bleibt eine Capability, weil es beim Anlegen noch keinen Datensatz
> gibt, dessen ACL man fragen könnte.
## Wer einen Plan sieht
Die ACL, die der Server schreibt:
| Wer | Woher | Recht |
| -------------------------------------- | --------------------------------------- | ----- |
| Ersteller | `user` (server-gesetzt, unveränderlich) | r + w |
| `od-admin`, `od-tenant-admin-<tenant>` | immer | r + w |
| `assignedRoles`, `escalationRoles` | Rollen-Relation am Plan | r |
| `assignedUsers` | User-Relation am Plan | r |
Gebaut wird sie serverseitig im `afterSave` — Relationen sind erst nach dem
Speichern lesbar. Sie wird bei jedem Lauf **neu gebaut, nicht ergänzt**: eine ACL
merkt sich nicht, *warum* ein Grant besteht, und Ergänzen wäre eine Einbahnstraße —
eine vom Plan entfernte Rolle würde ihn für immer weiterlesen. Administratoren
kommen in jedem Fall wieder dazu; aussperren lassen sie sich nicht.
**Bearbeiten fragt die ACL, nicht die Capability.** Im Frontend ist
`schedule.readonly` die Bedingung für Bearbeiten, Verschieben und Archivieren; nur
das Archivieren prüft zusätzlich `can-delete-schedule`.
Der Dialog **„Sichtbarkeit prüfen"** im Aktionsmenü liest die ACL und nicht die
Zuweisungen: gezeigt wird, was der Server durchsetzt. Administrator-Grants sind
ausgeblendet, weil sie auf jedem Datensatz stehen.
> [!note] Eine Zuweisung gibt Leserecht, kein Schreibrecht
> Wer einem Plan zugewiesen ist, kann ihn ansehen und abarbeiten, aber nicht
> ändern. Schreiben darf der Ersteller — und Administratoren.
## Löschen
Das Löschen eines Plans prüft serverseitig `can-delete-schedule`. Das ist nötig,
weil ein ACL-`write` in Parse Ändern **und** Löschen abdeckt — ein ausgeblendeter
Knopf allein genügt dafür nicht.
Derselbe Hook verweigert das Löschen eines Plans, zu dem Durchführungen
existieren, damit kein Protokoll ins Leere zeigt. Dafür gibt es das Archivieren
über `deletedAt`.