Request-Pipeline
Die gemeinsamen Authentifizierungs-, Autorisierungs- und Rate-Limit-Schranken, die jede API-Anfrage durchläuft.
Jede API-Anfrage durchläuft dieselbe Abfolge von Prüfungen, bevor irgendeine Geschäftslogik ausgeführt wird. Diese Schranken sind einzelne, wiederverwendbare Implementierungen — kein routenspezifischer Code —, sodass die Sicherheit über die gesamte Oberfläche hinweg einheitlich funktioniert.
Die Schranken
Middleware — prüft das Vorhandensein einer Session, wendet die Content Security Policy an und bricht bei aktivem Wartungsmodus frühzeitig ab.
Authentifizierung — verifiziert den Firebase-Session-Cookie (oder ein internes
JWT für Service-to-Service-Aufrufe) und gleicht den Datenbankbenutzer ab. Schlägt mit
401 fehl.
Autorisierung (RBAC) — ermittelt die höchste Berechtigung des Aufrufers für die
Zielentität (read < write < admin), beschränkt auf den Workspace. Schlägt mit
403 fehl.
Rate-Limiting — ein Sliding-Window-Zähler für aufwändige und öffentliche
Routen. Schlägt mit 429 fehl.
Handler — die validierte Anfrage erreicht die Zod-geprüfte Geschäftslogik.
Anfrage-Ablauf
sequenceDiagram
autonumber
actor C as Caller
participant E as Edge
participant G as API Guards
participant A as Auth
participant Z as RBAC
participant L as Rate Limiter
participant H as Handler
C->>E: HTTPS request
E->>G: Route handler
G->>A: requireApiAuth()
A-->>G: session or null
alt not authenticated
G-->>C: 401 Unauthorized
else authenticated
G->>Z: requireWorkspaceAccess(min)
Z-->>G: permission or null
alt insufficient permission
G-->>C: 403 Forbidden
else authorized
G->>L: checkRateLimit(key)
alt limit exceeded
L-->>C: 429 Too Many Requests
else within limit
G->>H: validated request
H-->>C: 200 + data
end
end
endRate-Limit-Speicher
Der Limiter verwendet standardmäßig ein prozesslokales In-Memory-Fenster. Wenn eine Redis-URL konfiguriert ist, wechselt er zu einem Memorystore-gestützten Sliding Window (atomares Lua), das über alle Serverinstanzen hinweg gemeinsam genutzt wird – sodass ein einzelner Benutzer sein Limit nicht durch das Verteilen von Anfragen auf Replikate umgehen kann.
Der Redis-Client verbindet sich verzögert, und der Limiter fällt offen auf den Arbeitsspeicher zurück — ein Cache-Ausfall kann weder den Start zum Absturz bringen noch eine Anfrage mit einem 500er beantworten. Er degradiert auf instanzspezifische Limits, bis Redis sich erholt.
Mandantenisolierung
Die Autorisierung ist stets workspace-bezogen. Eine Berechtigung ist eine Zeile, die durch
(userId, entityType, entityId) indiziert wird, und der Executor fädelt userId und workspaceId
durch den gesamten Ablauf — sodass ein Workflow ausschließlich Daten innerhalb der eigenen
Mandantengrenze lesen und schreiben kann. Siehe Multi-Tenancy.