import { Config } from '@backstage/config'; import { LiteLLMClient } from './client'; import { GenerateKeyRequest, GenerateKeyResponse, ProvisioningDefaults, UserInfo, VirtualKey } from './types'; /** Claims extracted from a verified Keycloak access token. */ export interface BridgeClaims { sub: string; email?: string; preferred_username?: string; name?: string; /** Authorized party — Keycloak sets this to the client_id of the requester. */ azp?: string; aud?: string | string[]; } /** A token verifier pluggable for tests. */ export interface TokenVerifier { verify(token: string): Promise; } export interface BridgeConfig { enabled: boolean; /** Keycloak realm issuer, e.g. https://auth.example.com/realms/solution-innovation. */ issuer?: string; /** OIDC public client the CLI uses; checked against azp / aud. */ clientId: string; } export declare function readBridgeConfig(config: Config): BridgeConfig; /** Thrown when the bridge is misconfigured (e.g. enabled without an issuer). */ export declare class BridgeConfigError extends Error { } /** Thrown when a presented token fails verification → maps to HTTP 401. */ export declare class BridgeAuthError extends Error { readonly status = 401; } export interface KeycloakJWTVerifierOptions { issuer: string; clientId: string; } /** * Verifies a Keycloak access token against the realm JWKS and ensures it was * issued for {@link clientId} (via azp, falling back to aud). Uses jose's * remote JWKS client (cached, with cooldown on errors). */ export declare class KeycloakJWTVerifier implements TokenVerifier { private readonly issuer; private readonly clientId; private readonly jwks; constructor(opts: KeycloakJWTVerifierOptions); verify(token: string): Promise; } /** Builds the default verifier from config, or throws BridgeConfigError. */ export declare function newDefaultVerifier(cfg: BridgeConfig): TokenVerifier; /** * Resolves the LiteLLM user_id from the verified claims, matching exactly how * the UI derives it so the bridge addresses the *same* LiteLLM user (not a * duplicate). The UI uses toLiteLLMUserId(entityRef, userIdDomain) where the * Backstage entity name has been rewritten by the Keycloak user transformer: * because the catalog rejects '@' in entity names, usernames imported as full * emails are stored as their local-part. We replicate that here — strip the * '@domain' off the username, then apply the same userIdDomain rule. */ export declare function resolveBridgeUserId(claims: BridgeClaims, userIdDomain?: string): string; /** * Ensures a LiteLLM user exists for the verified identity. If the user is * missing and provisioning is enabled, creates it from the JWT claims (email + * name); if provisioning is disabled, throws a 404 telling the caller to log * in to Backstage first (the UI is the primary provisioning entry point). */ export declare function getOrProvisionUserFromClaims(client: LiteLLMClient, claims: BridgeClaims, provisioningEnabled: boolean, provisioningDefaults: ProvisioningDefaults, logger: { info: (...args: unknown[]) => void; }, userIdDomain?: string): Promise; /** Lists the caller's virtual keys (provisioning the user first if needed). */ export declare function bridgeListKeys(client: LiteLLMClient, claims: BridgeClaims, provisioningEnabled: boolean, provisioningDefaults: ProvisioningDefaults, logger: { info: (...args: unknown[]) => void; }, userIdDomain?: string): Promise; /** Mints a new virtual key for the caller (provisioning the user first if needed). */ export declare function bridgeGenerateKey(client: LiteLLMClient, claims: BridgeClaims, provisioningEnabled: boolean, provisioningDefaults: ProvisioningDefaults, logger: { info: (...args: unknown[]) => void; }, request: Partial, userIdDomain?: string): Promise;