Rechte und Tokens
Wer lesen und schreiben darf, steht in jeder Sammlung unter permissions.
Welchen Kopf du mitschickst, entscheidet, welche Rolle du bist.
Beispiele stammen aus content.yml, comment.yml, api/hooks/config.js und filter_public.js.
Permission-Blöcke
Abschnitt betitelt „Permission-Blöcke“# aus content.yml — öffentlich lesen, Rest für angemeldete Nutzer und Tokenpermissions: public: methods: get: true user: methods: get: true post: true put: true delete: true "token:${ADMIN_TOKEN}": methods: get: true post: true put: true delete: true| Block | Wer ist das | Beispiel |
|---|---|---|
public |
Anonyme Anfragen ohne Kopf | content, navigation: get: true |
user |
Angemeldet per JWT (X-Auth-Token) |
content, comment: volles CRUD |
"token:${ADMIN_TOKEN}" |
Skript mit statischem Token (Token-Kopf) |
alle Starter-Sammlungen: volles CRUD |
methodskenntget,post,put,delete.- Fehlt ein Block, darf die Rolle nichts.
tag.ymlhat zusätzlichpost/put/delete-Hooks (clear_cache.js), aber keinen Lese-Hook.
Token-Köpfe
Abschnitt betitelt „Token-Köpfe“Vier Köpfe, vier Zwecke. Verwechsle sie nicht.
| Kopf | Wert | Wofür |
|---|---|---|
Token |
ADMIN_TOKEN aus api/config.yml.env |
Sammlungs-CRUD, wenn der Permission-Schlüssel token:${ADMIN_TOKEN} heißt |
X-Auth-Token |
JWT nach Login | Nutzer-Aktionen (user:-Rechte) |
X-Admin-Token |
Server-Admin-Token | System-Ebene: Projekte, Reload, Server-Ops |
Authorization: Bearer … |
ADMIN_TOKEN |
Reverse-Proxy-Reload auf LIVE_URL/STAGING_URL (projektlokal, kein Server-API-Kopf) |
GET /api/v1/_/<namespace>/content?filter={"lang":"de"}# kein Kopf nötig — public.get ist truePOST /api/v1/_/<namespace>/commentToken: <ADMIN_TOKEN>{"contentId": "<id>", "author": "Demo", "message": "Hallo", "active": true}PUT /api/v1/_/<namespace>/content/<id>X-Auth-Token: <jwt>{"name": "Startseite"}active:true-Falle
Abschnitt betitelt „active:true-Falle“Anonyme Leser bekommen automatisch einen Zusatzfilter.
filter_public.js hängt ihn an jede Abfrage ohne Login:
// api/hooks/filter_public.js — nur ohne Login aktivhookResponse.filter = publishedFilter; // bzw. $and mit deinem filter// api/hooks/config.js — der Filter im Kernconst publishedFilter = { active: true, $or: [ { publication: { $exists: false } }, { publication: null }, // … plus Fenster publication.from <= jetzt <= publication.to ],}Das heißt: öffentlich sichtbar ist nur active: true innerhalb des Veröffentlichungsfensters.
| Sammlung | Falle | Folge ohne active:true |
|---|---|---|
content |
Feld active existiert, Hook filtert |
Seite öffentlich unsichtbar |
navigation |
Feld active existiert nicht im Schema, Hook filtert trotzdem |
Header/Footer öffentlich leer (count 0), SSR-Cache ohne Navigation |
medialib |
Feld active existiert nicht im Schema, Hook filtert trotzdem |
Lookups öffentlich unaufgelöst (nur IDs, kein _lookup), Hero zeigt Verlauf, Richtext-Bilder fehlen |
tag |
Kein Lese-Hook | Keine Falle — active unnötig |
comment |
Feld active existiert, Hook filtert |
Nur freigeschaltete Kommentare sind öffentlich |
Regel: Lege auf jedem content-, navigation-, medialib- und comment-Dokument active: true ab.
Mit Token oder JWT siehst du alles — prüfe Anonymes daher immer ohne Kopf (z. B. Inkognito-Fenster).
Orgs und Teams im Überblick
Abschnitt betitelt „Orgs und Teams im Überblick“Größere Installationen gruppieren Nutzer und Projekte:
- Org: Mandant oben (
matrixorga,matrixorgbim Test). - Team: Gruppe in einer Org, mit oder ohne Rechte (z. B.
teama1miteditor). - Projekt: hängt an einer Org (
orgId) und kennt seine Teams. - Org-Admin: Rolle
adminin einer Org — darf org-eigene Projekte, aber nichts in fremden Orgs.
Org A ─┬─ Team A1 (editor) ─┬─ Projekt A └─ Team A2 (ohne) ─┘Org B ─── Team B1 (editor) ─── Projekt BMitglieder von Team A1 kommen in Projekt A, aber nicht in Projekt B.
Ohne Org-Zugehörigkeit geht gar nichts.
Details regelt der Server-Code (access_control_matrix_test.go) — für normale Projekte reicht: ein Projekt, ein Team, ADMIN_TOKEN für Skripte.
Scope-Katalog (PATs)
Abschnitt betitelt „Scope-Katalog (PATs)“Persönliche Tokens (POST /api/v1/token, siehe System-Routen) tragen Scopes — Engpässe, die du pro Token vergibst.
GET /api/v1/token/_scopes listet, was du aktuell vergeben darfst (gleiche Quelle wie die Anlage-Prüfung).
| Gruppe | Beispiele | Bedeutung |
|---|---|---|
| System | user.read, project.create, team.delete, org.read, audit.read, llm.chat |
CRUD je Domäne (user, project, team, org); audit nur read, llm nur chat; Projekt-Admin zusätzlich project.reload, project.backup, project.regenerate-search, project.snapshot |
| Namespace | namespace → alles; namespace.shop → alle Sammlungen dort; namespace.shop.content → alle Aktionen dort; namespace.shop.content.read → genau eine Aktion; namespace.shop._actions.name.post → Aktions-Endpunkt |
Je länger, desto enger; * matcht genau ein Segment |
| Besitzer-Kürzel | Sammlungs-Kurzform ohne Aktion (z. B. namespace.shop.content) |
Alle Aktionen, die der Besitzer dort aktuell darf |
Die token-Collection-Felder im Überblick (token.go):
| Feld | Inhalt |
|---|---|
userId |
Besitzer (Nutzer-ID) |
name |
Anzeigename (required, 1–100 Zeichen) |
token |
Klartext — nur in der Anlage-Antwort (tibi_pat_<id>_<secret>), danach nie wieder |
tokenHash / tokenPrefix |
SHA-256-Hash (gespeichert) / Anzeige-Präfix (tibi_pat_ + 4 Zeichen) |
scopes |
String-Liste aus dem Katalog oben |
expiresAt |
Ablaufzeitpunkt; leer = kein Ablauf |
lastUsedAt |
Letzte Nutzung (wird bei Gebrauch aktualisiert) |
Projekt-Admin-Tokens
Abschnitt betitelt „Projekt-Admin-Tokens“Skripte mit X-Admin-Token brauchen je Aktion ein Flag im Projekt (tokens[] in der Projekt-Config, Schema project.schema.json):
| Flag | Erlaubt |
|---|---|
allowReload |
POST …/_/admin/reload (Config neu laden) |
allowRegenerateSearch |
POST …/_/admin/regenerate-search (Suchindex neu aufbauen) |
allowBackup |
Backup herunter- und wiederherstellen |
allowSnapshots |
Snapshots auslösen, listen, löschen, wiederherstellen, herunterladen |
tokens: - token: ersetze-mich-durch-zufall allowReload: true allowBackup: trueOhne das passende Flag antwortet der Endpunkt mit 403 — das Token ist dann zwar gültig, aber für diese Aktion nicht freigeschaltet.
Feld-Rechte pro Rolle (readonlyFields, hiddenFields, validProjections) stehen auf der eigenen Seite Feld-Rechte.
Fehlerbilder
Abschnitt betitelt „Fehlerbilder“| Antwort | Ursache | Lösung |
|---|---|---|
permission denied |
Rolle darf die Methode nicht oder Projektion ist fremd | permissions-Block und gesendeten Kopf prüfen |
project not found |
Namespace falsch oder Projekt nicht registriert | Neues Projekt Schritt 5 |
lookup permission denied |
Leserecht auf der Ziel-Sammlung fehlt | Ziel-Sammlung braucht public.get oder gleichen Kopf |
| Öffentlich leer, mit Token voll | active:true fehlt oder publication-Fenster liegt in der Zukunft/Vergangenheit |
active:true setzen, publication.from/publication.to prüfen |
| Falscher Kopf, richtige Rolle | z. B. Token: statt X-Auth-Token: bei Nutzer-Rechten |
Tabelle oben: Kopf an Rolle anpassen |
Verifiziert am e3f92eb 2026-10-17 (tibi-svelte-starter, Hooks und Permissions), am 68b4278 2026-10-17 (tibi-server, access_control_matrix_test.go, Lookup-/Projektions-Prüfung), am 68b4278 2026-10-17 (tibi-server, Scopes: scope.go, token.go, token_scope_catalog.go; Projekt-Token-Flags: project.go, project.schema.json)