Identity, Organization & Team
Geltungsbereich: namespaced · Lizenziert (Feature identity-management + organizations- / teams-Obergrenzen)
Diese Ressourcen verwalten Identitäten über die Komponenten der Plattform hinweg — das Gateway (LiteLLM oder Wäg), Langfuse und LibreChat — als Kubernetes-Objekte, sodass Zugriff und Mandantenzuordnung deklarativ und prüfbar sind, statt in jedem Werkzeug von Hand konfiguriert zu werden.
| Ressource | Verwaltet |
|---|---|
User | Eine Person / ein Sitzplatz — der natürliche Schlüssel (E-Mail), der die Konten dieser Person zusammenführt |
Identity | Ein Konto pro Backend für eine Person, auf dem Gateway, Observability (Langfuse) oder LibreChat |
Organization | Eine übergeordnete Mandanten- / Abrechnungsgrenze |
Team | Eine Gruppe innerhalb einer Organisation, mit Budgets und Modellzugriff |
Personen vs. Konten
Ein User ist eine Person (ein lizenzierter Sitzplatz). Eine Identity ist eines der Backend-Konten dieser Person. Die Lizenzobergrenze users zählt User-Sitzplätze; Identity-Konten sind unbegrenzt und müssen jeweils über userRef auf einen User verweisen. Eine Person mit einem Gateway-Key, einer Langfuse-Mitgliedschaft und einem LibreChat-Login ist ein Sitzplatz, drei Identity-Objekte.
Identity
Eine Identity stellt ein einzelnes Konto für eine Person auf einem Backend bereit. Ihr spec.type wählt aus, in welcher Komponente das Konto lebt:
type | Emittiert |
|---|---|
gateway | Empfohlen. Folgt dem spec.type des referenzierten Gateway — siehe Backend-Auswahl |
litellm | LiteLLM-Benutzerressourcen (LiteLLMUser), geprüft gegen das referenzierte Gateway |
waeg | Wäg-Konsolenbenutzer (WaegUser), geprüft gegen das referenzierte Gateway — siehe Wäg-Konten |
observability | Mitgliedschaft in der Langfuse-Organisation der Observability (erfordert eine Langfuse-Enterprise-Lizenz) |
librechat | LibreChat-Konfiguration für Benutzer / Rolle |
Spec
| Feld | Typ | Beschreibung |
|---|---|---|
type | enum (erforderlich) | gateway / litellm / waeg / observability / librechat |
userRef | { name } (erforderlich) | Der besitzende User im selben Namespace |
email | string (optional) | Konto-E-Mail; standardmäßig die spec.email des besitzenden User |
displayName | string | Menschenlesbarer Name |
userId | string | Stabile externe Benutzer-ID für das Backend |
role | string | Backend-Rolle. Auf Wäg gewährt genau admin oder platform_admin das clusterweite Platform-Admin-Privileg — nichts anderes wird abgeleitet |
budget | object | Budget pro Konto (sofern das Backend es unterstützt; auf Wäg nicht angewendet) |
teamRefs | list | Teams, denen dieses Konto angehört (LiteLLM; auf Wäg nicht angewendet) |
gatewayRef | ObjectRef | Das Gateway, auf dem dieses Konto lebt. Erforderlich für type: gateway / litellm / waeg, und es muss im selben Namespace liegen — siehe Admission-Regeln |
observabilityRef | ObjectRef | Ein Observability (für type: observability) |
chatUIRef | ObjectRef | Ein ChatUI (für type: librechat) |
passwordSecretRef | SecretKeyRef | Passwort-Secret (für type: librechat) |
Backend-Auswahl: type: gateway
Identity, Organization und Team akzeptieren alle type: gateway, und das ist der Wert, den Sie für neue Ressourcen verwenden sollten. Eine gateway-gestützte Identitätsressource zielt auf ein Gateway — und dieses Gateway weiß bereits, welche Implementierung es betreibt. Mit type: gateway liest der Operator das Backend aus dem spec.type des referenzierten Gateways, der einzigen Quelle, die nicht auseinanderdriften kann.
spec:
type: gateway # aus dem untenstehenden Gateway aufgelöst
gatewayRef: { name: forge-gateway }Die produktbenannten Werte litellm und waeg funktionieren weiterhin und sind nicht zur Entfernung vorgesehen. Geändert hat sich, dass sie nun gegen das Gateway geprüft statt geglaubt werden. Ein Typ, der dem Gateway widerspricht, wird mit Ready=False abgelehnt:
type=litellm does not match Gateway "forge-gateway", which is type=waeg —
set type: gateway to follow the Gateway, or point gatewayRef at a litellm gatewayDie Meldung nennt den deklarierten Typ, das Gateway, den tatsächlichen Typ des Gateways und beide Auswege: mit type: gateway dem Gateway folgen, oder gatewayRef auf ein Gateway des deklarierten Typs richten.
Warum es diese Prüfung gibt
Bislang verglich nichts die beiden Werte. Eine Organization / ein Team / eine Identity mit type: litellm gegen ein Wäg-Gateway wurde akzeptiert, und der Operator emittierte eine LiteLLMOrganization / LiteLLMTeam / LiteLLMUser, deren instanceRef auf eine Wäg-Instanz zeigte — ein Objekt, das sich an nichts bindet und in keinem Gateway materialisiert.
Auf einem Cluster, auf dem beide Operatoren installiert sind, gelingt dieses Apply: Die CRD existiert, das Objekt wird gespeichert, und nichts macht den Fehler jemals sichtbar. Das Konto erscheint im Gateway schlicht nie. Die Abweichung ist jetzt eine Ablehnung statt eines stillschweigend verwaisten Objekts.
Admission-Regeln
Zwei Regeln werden vom API-Server auf Identity, Team und Organization durchgesetzt, sodass eine falsche Referenz bereits beim kubectl apply abgelehnt wird statt Stunden später in einer Statusbedingung.
1. Ein gateway-gestützter Typ erfordert gatewayRef.
type gateway/litellm/waeg requires gatewayRefgatewayRef war auf jeder dieser Ressourcen bisher optional. Ein Team mit type: waeg und ohne gatewayRef wurde zugelassen und scheiterte erst beim Reconcile mit "a gateway-backed identity resource requires gatewayRef" — dieselbe Information, nur Stunden später.
2. gatewayRef.namespace muss leer sein.
gatewayRef.namespace must be empty: the Gateway must live in the same namespace as this resourceSowohl der litellm-operator als auch der waeg-operator lösen den vorgelagerten instanceRef namespace-lokal auf, ein namespaceübergreifender gatewayRef konnte sich also niemals an etwas binden. Legen Sie das Gateway in denselben Namespace wie die Identitätsressourcen, die darauf zielen, und setzen Sie nur { name: … }.
LibreChat-Konten
LibreChat bietet keine API zum Anlegen von Konten. Eine Identity mit type: librechat wird daher bereitgestellt, indem das mitgelieferte create-user-Skript von LibreChat als kurzlebiger Kubernetes-Job ausgeführt wird. Der Job wird aus dem laufenden LibreChat-Container geklont (gleiches Image und gleiche Umgebung) und erreicht so automatisch dieselbe MongoDB.
- Der referenzierte
ChatUI(spec.chatUIRef) muss Ready sein und sich im selben Namespace wie dieIdentitybefinden. - Die Bereitstellung ist idempotent und erfolgt nur einmalig (create-only): Ein bereits vorhandenes Konto gilt als Erfolg, und spätere Änderungen an der
Identityändern ein bereits existierendes Konto nicht. - Passwort: Setzen Sie
spec.passwordSecretRef(Schlüssel standardmäßigpassword), um ein bekanntes Passwort zu verwenden. Lassen Sie es weg, erzeugt der Operator eines und legt es in einem eigenen Secret namens<identity>-librechat-password(Schlüsselpassword) ab. Auslesen mitkubectl get secret <identity>-librechat-password -o jsonpath='{.data.password}' | base64 -dund nach der ersten Anmeldung rotieren. Das Passwort wird nie über die Kommandozeile übergeben.
Wäg-Konten
Identity, Team und Organization werden auf einem Wäg-Gateway vollständig unterstützt. Sie emittieren WaegUser, WaegTeam, WaegOrganization sowie die org- und team-bezogenen WaegBudget-Richtlinien (alle in gateway.waeg.ai/v1alpha1).
Konsolen-Passwort. Wäg benötigt ein Passwort, um einen Konsolenbenutzer anzulegen. Für eine Wäg-gestützte Identity erzeugt der Operator eines in einem eigenen Secret namens <identity-name>-waeg-password, Schlüssel password, und richtet den WaegUser über spec.passwordSecretRef darauf aus. Für die erste Anmeldung der Person lesen Sie es so aus:
kubectl get secret <identity>-waeg-password \
-o jsonpath='{.data.password}' | base64 -dDas Secret wird einmalig erzeugt und nie automatisch rotiert — eine Rotation des Secrets rotiert das Konsolen-Passwort. Mehr ist nicht zu setzen; es gibt kein Feld, um für ein Wäg-Konto ein eigenes Passwort vorzugeben.
Ready bedeutet, dass das Konto existiert. Eine Wäg-Identitätsressource meldet erst dann Ready, wenn der emittierte WaegUser selbst Synced=True meldet. Das Anwenden der vorgelagerten CR galt früher als Erfolg, was genau den obigen Fehler verdeckte: Ohne Passwort-Secret blieb der WaegUser dauerhaft bei Synced=False — "passwordSecretRef is required to create a new console user", während die Identity grün war und das Konsolenkonto nicht existierte. Eine grüne Identity bedeutet jetzt, dass das Gateway das Konto angenommen hat.
Team-Mitglieder. Wäg adressiert ein Team-Mitglied über einen WaegUser, niemals über die E-Mail. Hat ein Mitglied auch eine Identity am selben Gateway, verweist das Team auf den WaegUser dieser Identity — ein Konsolenbenutzer pro Person. Nur eine Adresse ohne Identity erhält einen eigenen Mitgliedschafts-WaegUser (Name <team>-<email-slug>), der wieder gelöscht wird, sobald die Adresse das Team verlässt. Das Löschen entfernt nie das Wäg-Konto der Person: Wäg löscht einen Verzeichnisbenutzer nur, wenn die gelöschte CR ihn angelegt hat — was ein Mitgliedschafts-WaegUser (ohne Passwort) nie tut.
Auf Wäg nicht angewendet — jedes davon wird als Event gemeldet (UnsupportedByBackend), niemals stillschweigend verworfen:
| Feld | Warum |
|---|---|
Identity.spec.teamRefs | Wäg führt die Mitgliedschaft am Team, nicht am Benutzer. Tragen Sie die Adresse der Person stattdessen in spec.members des Team ein |
Identity.spec.budget | Ein Wäg-Limit pro Benutzer ist ein WaegBudget mit scope: user, das dieser Operator nicht emittiert |
Organization.spec.members | WaegOrganization kennt keine Mitglieder — Org-Mitgliedschaft ist ein Admin-API-Endpunkt ohne CR. Die members eines Team werden angewendet |
spec.budget.budgetDuration (Organization / Team) | Wäg-Budget-Richtlinien haben kein Zeitraumfeld |
spec.budget.models (Organization / Team) | Modell-Allowlists sind die separate WaegModelAccess-ACL, kein Budgetfeld |
Organization & Team
| Ressource | Verwaltet |
|---|---|
Organization | Eine übergeordnete Mandanten- / Abrechnungsgrenze |
Team | Eine Gruppe innerhalb einer Organisation, mit Budgets und Modellzugriff |
Jede trägt einen type, der auswählt, welche Komponenten-Identität sie steuert:
type | Emittiert |
|---|---|
gateway | Empfohlen. Folgt dem spec.type des referenzierten Gateway |
litellm | LiteLLMOrganization / LiteLLMTeam |
waeg | WaegOrganization / WaegTeam sowie die passende WaegBudget-Richtlinie |
observability | Langfuse-Ressourcen für Org / Projekt / Mitgliedschaft (Teams sind Gerüst) |
Beide akzeptieren einen gatewayRef — erforderlich für gateway / litellm / waeg und ausschließlich im selben Namespace (Admission-Regeln). Organization stellt außerdem einen observabilityRef bereit, der bei type: observability auf den Observability-Workload zeigt.
Ein Team referenziert seine übergeordnete Organisation über spec.organizationRef ({ name }, selber Namespace). Auf LiteLLM ist die Organisation optional, auf Wäg ist sie erforderlich — Wäg-Teams sind immer an einer Organisation verwurzelt. Ein type: waeg-Team ohne sie wird bei der Admission abgelehnt (spec.organizationRef: Required value); ein type: gateway-Team auf einem Wäg-Gateway wird stattdessen beim Reconcile abgelehnt, da die Admission den Typ des Gateways nicht sieht. Der Typ der übergeordneten Organisation wird ebenso aufgelöst: Eine Organization mit type: gateway auf einem Wäg-Gateway ist ein gültiger Parent für ein Wäg-Team, eine Organization des anderen Produkts wird als Abweichung gemeldet.
Beispiel
Ein Gateway, eine Organisation, ein Team, eine Person — und keine der Identitätsressourcen nennt das Gateway-Produkt. Ein Wechsel des Gateway zwischen litellm und waeg lässt alle vier unverändert.
apiVersion: core.navique.com/v1alpha1
kind: Organization
metadata:
name: acme
namespace: forge
spec:
type: gateway # aus dem Gateway aufgelöst
gatewayRef: { name: forge-gateway } # selber Namespace — kein Feld `namespace:`
displayName: ACME Corp
budget:
maxBudget: 500
---
apiVersion: core.navique.com/v1alpha1
kind: Team
metadata:
name: platform
namespace: forge
spec:
type: gateway
gatewayRef: { name: forge-gateway }
organizationRef: { name: acme } # auf Wäg erforderlich, auf LiteLLM optional
displayName: Platform Team
members:
- email: alice@example.com # auf Wäg liegt die Mitgliedschaft hier
role: admin
---
apiVersion: core.navique.com/v1alpha1
kind: User
metadata:
name: alice
namespace: forge
spec:
email: alice@example.com
displayName: Alice Example
---
apiVersion: core.navique.com/v1alpha1
kind: Identity
metadata:
name: alice-gateway
namespace: forge
spec:
type: gateway
userRef: { name: alice } # der lizenzierte Sitzplatz, selber Namespace
gatewayRef: { name: forge-gateway }
role: admin
# email weggelassen → erbt alice@example.com vom UserAuf einem Gateway mit type: waeg entsteht dabei zusätzlich das erzeugte Konsolen-Passwort in alice-gateway-waeg-password — siehe Wäg-Konten.
Verhältnis zum Gateway
Ein Gateway kann eine inline definierte organization und teams[] deklarieren. Die Identitätsressourcen sind der breitere, komponentenübergreifende Mechanismus: Sie ermöglichen es, Organisationen, Teams, Personen (User) und ihre Backend-Konten (Identity) einmal zu verwalten und sie konsistent über das Gateway, Langfuse und LibreChat hinweg widerzuspiegeln, auch über mehrere Gateways hinweg.
Lizenzierung
Identitätsverwaltung ist Teil des Werts multi-tenancy und erfordert das Feature identity-management zuzüglich der relevanten organizations- / teams-Instanzobergrenzen in der License. Die users-Obergrenze zählt User-Sitzplätze — nicht Identity-Konten, die unbegrenzt sind. In der Community Edition verwenden Sie die inline definierten organization / teams[] auf einem einzelnen Gateway.
Siehe Editionen & Lizenzierung.