Skip to content

Identity, Organization e Team ​

Ambito: namespaced · Con licenza (funzionalità identity-management + limiti organizations / teams)

Queste risorse gestiscono le identità tra i componenti della piattaforma — il gateway (LiteLLM o Wäg), Langfuse e LibreChat — come oggetti Kubernetes, così che accessi e tenancy siano dichiarativi e verificabili anziché configurati a mano in ciascuno strumento.

RisorsaGestisce
UserUna persona / postazione — la chiave naturale (email) che collega tra loro gli account di quella persona
IdentityUn account per backend di una persona, sul gateway, su Observability (Langfuse) o su LibreChat
OrganizationUn tenant di primo livello / confine di fatturazione
TeamUn gruppo all'interno di un'organizzazione, con budget e accesso ai modelli

Persone e account

Uno User è una persona (una postazione licenziata). Una Identity è uno degli account backend di quella persona. Il limite users della licenza conta le postazioni User; gli account Identity non sono soggetti a limiti, e ciascuno deve puntare a uno User tramite userRef. Una persona con una chiave del gateway, un'adesione a Langfuse e un login LibreChat è una postazione, tre oggetti Identity.

Identity ​

Una Identity crea un singolo account per una persona su un backend. Il suo spec.type seleziona il componente in cui risiede l'account:

typeEmette
gatewayConsigliato. Segue il spec.type del Gateway referenziato — vedi Scelta del backend
litellmRisorse utente LiteLLM (LiteLLMUser), verificate rispetto al Gateway referenziato
waegUtente della console Wäg (WaegUser), verificato rispetto al Gateway referenziato — vedi Account Wäg
observabilityAdesione all'organizzazione Langfuse dell'Observability (richiede una licenza Langfuse Enterprise)
librechatConfigurazione utente / ruolo di LibreChat

Spec ​

CampoTipoDescrizione
typeenum (obbligatorio)gateway / litellm / waeg / observability / librechat
userRef{ name } (obbligatorio)Lo User proprietario nello stesso namespace
emailstring (opzionale)Email dell'account; per impostazione predefinita è lo spec.email dello User proprietario
displayNamestringNome leggibile
userIdstringID utente esterno stabile per il backend
rolestringRuolo nel backend. Su Wäg, esattamente admin o platform_admin concede il privilegio di platform-admin a livello di cluster — nient'altro viene dedotto
budgetobjectBudget per account (dove il backend lo supporta; non applicato su Wäg)
teamRefslistTeam a cui appartiene questo account (LiteLLM; non applicato su Wäg)
gatewayRefObjectRefIl Gateway su cui risiede questo account. Obbligatorio per type: gateway / litellm / waeg, e deve trovarsi nello stesso namespace — vedi Regole di ammissione
observabilityRefObjectRefUn Observability (per type: observability)
chatUIRefObjectRefUna ChatUI (per type: librechat)
passwordSecretRefSecretKeyRefSecret della password (per type: librechat)

Scelta del backend: type: gateway ​

Identity, Organization e Team accettano tutte type: gateway, ed è il valore da usare per le nuove risorse. Una risorsa di identità basata sul gateway punta a un Gateway — e quel Gateway sa già quale implementazione esegue. Con type: gateway l'operatore legge il backend dal spec.type del Gateway referenziato, l'unica fonte che non può divergere.

yaml
spec:
  type: gateway               # resolved from the Gateway below
  gatewayRef: { name: forge-gateway }

I valori con il nome del prodotto litellm e waeg funzionano ancora e non ne è prevista la rimozione. Ciò che è cambiato è che ora vengono verificati rispetto al Gateway invece di essere accettati sulla fiducia. Dichiarare un tipo che contraddice il Gateway viene rifiutato con Ready=False:

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 gateway

Il messaggio indica il tipo dichiarato, il Gateway, il tipo effettivo del Gateway e entrambe le vie d'uscita: seguire il Gateway con type: gateway, oppure puntare gatewayRef a un gateway del tipo dichiarato.

Perché esiste questo controllo

In passato nulla confrontava i due valori. Una Organization / Team / Identity che dichiarava type: litellm verso un gateway Wäg veniva accettata, e l'operatore emetteva un LiteLLMOrganization / LiteLLMTeam / LiteLLMUser il cui instanceRef indicava un'istanza Wäg — un oggetto che non si lega a nulla e non si materializza in alcun gateway.

Su un cluster in cui sono installati entrambi gli operatori, quell'apply va a buon fine: il CRD esiste, l'oggetto viene memorizzato e nulla fa mai emergere l'errore. L'account semplicemente non compare mai nel gateway. La discrepanza ora produce un rifiuto invece di un oggetto silenziosamente orfano.

Regole di ammissione ​

Due regole vengono applicate dall'API server su Identity, Team eOrganization, così che un riferimento errato venga rifiutato già al kubectl apply invece che ore dopo in una status condition.

1. Un tipo basato sul gateway richiede gatewayRef.

type gateway/litellm/waeg requires gatewayRef

In passato gatewayRef era opzionale su ognuna di queste risorse. Un Team con type: waeg e senza gatewayRef veniva ammesso e falliva solo al reconcile con "a gateway-backed identity resource requires gatewayRef" — la stessa informazione, ore dopo.

2. gatewayRef.namespace deve essere vuoto.

gatewayRef.namespace must be empty: the Gateway must live in the same namespace as this resource

Sia il litellm-operator sia il waeg-operator risolvono l'instanceRef upstream localmente al namespace, quindi un gatewayRef cross-namespace non potrebbe mai legarsi a nulla. Colloca il Gateway nello stesso namespace delle risorse di identità che lo referenziano, e imposta solo { name: … }.

Account LibreChat ​

LibreChat non dispone di un'API per creare account, quindi una Identity con type: librechat viene creata eseguendo lo script create-user incluso in LibreChat come Job Kubernetes di breve durata. Il Job è clonato dal container LibreChat in esecuzione (stessa immagine e stesso ambiente), quindi raggiunge automaticamente lo stesso MongoDB.

  • La ChatUI referenziata (spec.chatUIRef) deve essere Ready e trovarsi nello stesso namespace della Identity.
  • Il provisioning è idempotente e solo in creazione: un account esistente viene considerato un successo, e le modifiche successive alla Identity non alterano un account già esistente.
  • Password: imposta spec.passwordSecretRef (chiave password per impostazione predefinita) per usare una password nota. Se lo ometti, l'operatore ne genera una e la memorizza in un Secret di sua proprietà chiamato <identity>-librechat-password (chiave password). Recuperala con kubectl get secret <identity>-librechat-password -o jsonpath='{.data.password}' | base64 -d e ruotala dopo il primo login. La password non viene mai passata sulla riga di comando.

Account Wäg ​

Identity, Team e Organization sono pienamente supportate su un gateway Wäg. Emettono WaegUser, WaegTeam, WaegOrganization e le policy WaegBudget con scope di organizzazione e di team (tutte in gateway.waeg.ai/v1alpha1).

Password della console. Wäg richiede una password per creare un utente della console. Per una Identity basata su Wäg l'operatore ne genera una in un Secret di sua proprietà chiamato <identity-name>-waeg-password, chiave password, e vi fa puntare il WaegUser tramite spec.passwordSecretRef. Rileggila per il primo login della persona con:

bash
kubectl get secret <identity>-waeg-password \
  -o jsonpath='{.data.password}' | base64 -d

Il Secret viene generato una sola volta e mai ruotato automaticamente — ruotare il Secret ruota la password della console. Non serve impostare nient'altro; non esiste alcun campo per fornire una password propria per un account Wäg.

Ready significa che l'account esiste. Una risorsa di identità Wäg riporta Ready solo quando il WaegUser emesso riporta a sua volta Synced=True. In passato l'applicazione del CR upstream veniva considerata un successo, il che nascondeva esattamente il problema descritto sopra: senza Secret della password il WaegUser restava permanentemente in Synced=False — "passwordSecretRef is required to create a new console user", mentre la Identity appariva verde e l'account della console non esisteva. Una Identity verde ora significa che il gateway ha accettato l'account.

Membri del team. Wäg identifica un membro del team tramite WaegUser, mai tramite email. Per un membro che ha anche una Identity sullo stesso gateway, il team punta al WaegUser di quella Identity — un solo utente della console per persona. Solo un indirizzo senza Identity ottiene un WaegUser di adesione separato (chiamato <team>-<email-slug>), che viene nuovamente eliminato quando l'indirizzo lascia il team. Rimuoverlo non elimina mai l'account Wäg della persona: Wäg elimina un utente della directory solo quando è stato creato dal CR che viene eliminato, cosa che un utente di adesione (che non ha password) non fa mai.

Non applicati su Wäg — ciascuno viene segnalato come Event (UnsupportedByBackend), mai ignorato silenziosamente:

CampoMotivo
Identity.spec.teamRefsWäg mantiene l'adesione sul team, non sull'utente. Aggiungi invece l'indirizzo della persona a spec.members del Team
Identity.spec.budgetUn limite per utente in Wäg è un WaegBudget con scope: user, che questo operatore non emette
Organization.spec.membersWaegOrganization non modella membri — l'adesione all'organizzazione è un endpoint dell'Admin API senza CR. I members di un Team vengono applicati
spec.budget.budgetDuration (Organization / Team)Le policy di budget di Wäg non hanno un campo per il periodo
spec.budget.models (Organization / Team)Le allow-list dei modelli sono l'ACL separata WaegModelAccess, non un campo del budget

Organization e Team ​

RisorsaGestisce
OrganizationUn tenant di primo livello / confine di fatturazione
TeamUn gruppo all'interno di un'organizzazione, con budget e accesso ai modelli

Ciascuna porta un type che seleziona l'identità di quale componente gestisce:

typeEmette
gatewayConsigliato. Segue il spec.type del Gateway referenziato
litellmLiteLLMOrganization / LiteLLMTeam
waegWaegOrganization / WaegTeam, più la policy WaegBudget corrispondente
observabilityRisorse Langfuse di organizzazione / progetto / adesione (i team sono predisposti come scaffold)

Entrambe accettano un gatewayRef — obbligatorio per gateway / litellm / waeg, e solo nello stesso namespace (Regole di ammissione). Organization espone inoltre un observabilityRef per puntare al workload Observability quando type: observability.

Un Team fa riferimento al proprio genitore tramite spec.organizationRef ({ name }, stesso namespace). Su LiteLLM il genitore è opzionale; su Wäg è obbligatorio — i team Wäg sono sempre radicati in un'organizzazione. Un Team type: waeg che ne è privo viene rifiutato in fase di ammissione (spec.organizationRef: Required value); un Team type: gateway su un gateway Wäg viene invece rifiutato al reconcile, poiché l'ammissione non può vedere il tipo del Gateway. Il tipo del genitore viene risolto allo stesso modo, quindi una Organization di type: gateway su un gateway Wäg è un genitore valido per un team Wäg; una Organization sull'altro prodotto viene segnalata come discrepanza.

Esempio ​

Un Gateway, un'organizzazione, un team, una persona — e nessuna delle risorse di identità nomina il prodotto del gateway. Passare il Gateway tra litellm e waeg lascia invariate tutte e quattro.

yaml
apiVersion: core.navique.com/v1alpha1
kind: Organization
metadata:
  name: acme
  namespace: forge
spec:
  type: gateway                        # resolved from the Gateway
  gatewayRef: { name: forge-gateway }  # same namespace — no `namespace:` field
  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 }      # required on Wäg, optional on LiteLLM
  displayName: Platform Team
  members:
    - email: alice@example.com         # on Wäg, membership lives here
      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 }             # the licensed seat, same namespace
  gatewayRef: { name: forge-gateway }
  role: admin
  # email omitted → inherits alice@example.com from the User

Su un gateway type: waeg questo produce anche la password della console generata in alice-gateway-waeg-password — vedi Account Wäg.

Relazione con il Gateway ​

Un Gateway può dichiarare inline una organization e dei teams[]. Le risorse di identità sono il meccanismo più ampio e trasversale ai componenti: consentono di gestire organizzazioni, team, persone (User) e i loro account backend (Identity) una sola volta e di vederli riflessi in modo coerente su gateway, Langfuse e LibreChat, anche su più gateway.

Licenze ​

La gestione delle identità fa parte della proposta multi-tenancy e richiede la funzionalità identity-management più i relativi limiti di istanze organizations / teams nella License. Il limite users conta le postazioni User — non gli account Identity, che non sono soggetti a limiti. Nella Community edition, usa organization / teams[] inline su un singolo Gateway.

Vedi Edizioni e licenze.

Nucleo open source sotto AGPL-3.0. I componenti Enterprise sono proprietari e soggetti a licenza.