@acarmisc/backstage-plugin-litellm-backend 0.6.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config.d.ts +21 -0
- package/dist/index.cjs.js +13 -4
- package/dist/index.cjs.js.map +2 -2
- package/dist/openapi.js +6 -2
- package/dist/router.js +6 -1
- package/package.json +1 -1
package/config.d.ts
CHANGED
|
@@ -127,6 +127,27 @@ export interface Config {
|
|
|
127
127
|
group?: string;
|
|
128
128
|
};
|
|
129
129
|
|
|
130
|
+
/**
|
|
131
|
+
* Controls for the "Generate New Key" form in the frontend.
|
|
132
|
+
*/
|
|
133
|
+
keyGeneration?: {
|
|
134
|
+
/**
|
|
135
|
+
* When true, users can tick an "Unlimited budget" checkbox that skips
|
|
136
|
+
* the max-budget cap entirely. The checkbox is hidden from the form
|
|
137
|
+
* when this is false, so a budget is always required.
|
|
138
|
+
* @default false
|
|
139
|
+
*/
|
|
140
|
+
allowUnlimitedBudget?: boolean;
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* When true (the default), a team must be selected before a key can
|
|
144
|
+
* be generated. Set to false to let users generate personal,
|
|
145
|
+
* team-less keys.
|
|
146
|
+
* @default true
|
|
147
|
+
*/
|
|
148
|
+
teamRequired?: boolean;
|
|
149
|
+
};
|
|
150
|
+
|
|
130
151
|
bridge?: {
|
|
131
152
|
/**
|
|
132
153
|
* When true, mount the /bridge/keys, /bridge/keys (POST), /bridge/models
|
package/dist/index.cjs.js
CHANGED
|
@@ -511,12 +511,16 @@ var openApiSpec = {
|
|
|
511
511
|
"/config": {
|
|
512
512
|
get: {
|
|
513
513
|
tags: ["System"],
|
|
514
|
-
summary: "Public LiteLLM proxy base URL
|
|
514
|
+
summary: "Public LiteLLM proxy base URL and key-generation form settings",
|
|
515
515
|
responses: {
|
|
516
516
|
"200": {
|
|
517
|
-
description: "
|
|
517
|
+
description: "Frontend config",
|
|
518
518
|
content: { "application/json": { schema: { type: "object", properties: {
|
|
519
|
-
baseUrl: { type: "string" }
|
|
519
|
+
baseUrl: { type: "string" },
|
|
520
|
+
keyGeneration: { type: "object", properties: {
|
|
521
|
+
allowUnlimitedBudget: { type: "boolean" },
|
|
522
|
+
teamRequired: { type: "boolean" }
|
|
523
|
+
} }
|
|
520
524
|
} } } }
|
|
521
525
|
}
|
|
522
526
|
}
|
|
@@ -2465,6 +2469,8 @@ async function createRouter(options) {
|
|
|
2465
2469
|
const { enabled: provisioningEnabled, defaults: provisioningDefaults } = readProvisioningDefaults(config);
|
|
2466
2470
|
const roleConfigs = readRoleConfigs(config);
|
|
2467
2471
|
const auditGroup = config.getOptionalString("litellm.audit.group");
|
|
2472
|
+
const allowUnlimitedBudget = config.getOptionalBoolean("litellm.keyGeneration.allowUnlimitedBudget") ?? false;
|
|
2473
|
+
const teamRequired = config.getOptionalBoolean("litellm.keyGeneration.teamRequired") ?? true;
|
|
2468
2474
|
const catalogClient = new import_catalog_client.CatalogClient({ discoveryApi: discovery });
|
|
2469
2475
|
if (provisioningEnabled) {
|
|
2470
2476
|
logger.info(
|
|
@@ -2477,7 +2483,10 @@ async function createRouter(options) {
|
|
|
2477
2483
|
res.json({ status: "ok", provisioning: provisioningEnabled });
|
|
2478
2484
|
});
|
|
2479
2485
|
router.get("/config", (_req, res) => {
|
|
2480
|
-
res.json({
|
|
2486
|
+
res.json({
|
|
2487
|
+
baseUrl: publicBaseUrl,
|
|
2488
|
+
keyGeneration: { allowUnlimitedBudget, teamRequired }
|
|
2489
|
+
});
|
|
2481
2490
|
});
|
|
2482
2491
|
router.get("/openapi.json", (_req, res) => {
|
|
2483
2492
|
res.json(openApiSpec);
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts", "../src/plugin.ts", "../src/router.ts", "../src/client.ts", "../src/openapi.ts", "../src/provisioning.ts", "../node_modules/jose/dist/node/esm/runtime/base64url.js", "../node_modules/jose/dist/node/esm/lib/buffer_utils.js", "../node_modules/jose/dist/node/esm/util/errors.js", "../node_modules/jose/dist/node/esm/runtime/is_key_object.js", "../node_modules/jose/dist/node/esm/runtime/webcrypto.js", "../node_modules/jose/dist/node/esm/lib/crypto_key.js", "../node_modules/jose/dist/node/esm/lib/invalid_key_input.js", "../node_modules/jose/dist/node/esm/runtime/is_key_like.js", "../node_modules/jose/dist/node/esm/lib/is_disjoint.js", "../node_modules/jose/dist/node/esm/lib/is_object.js", "../node_modules/jose/dist/node/esm/runtime/get_named_curve.js", "../node_modules/jose/dist/node/esm/lib/is_jwk.js", "../node_modules/jose/dist/node/esm/runtime/check_key_length.js", "../node_modules/jose/dist/node/esm/runtime/jwk_to_key.js", "../node_modules/jose/dist/node/esm/key/import.js", "../node_modules/jose/dist/node/esm/lib/check_key_type.js", "../node_modules/jose/dist/node/esm/lib/validate_crit.js", "../node_modules/jose/dist/node/esm/lib/validate_algorithms.js", "../node_modules/jose/dist/node/esm/runtime/verify.js", "../node_modules/jose/dist/node/esm/runtime/dsa_digest.js", "../node_modules/jose/dist/node/esm/runtime/node_key.js", "../node_modules/jose/dist/node/esm/runtime/sign.js", "../node_modules/jose/dist/node/esm/runtime/hmac_digest.js", "../node_modules/jose/dist/node/esm/runtime/get_sign_verify_key.js", "../node_modules/jose/dist/node/esm/jws/flattened/verify.js", "../node_modules/jose/dist/node/esm/jws/compact/verify.js", "../node_modules/jose/dist/node/esm/lib/epoch.js", "../node_modules/jose/dist/node/esm/lib/secs.js", "../node_modules/jose/dist/node/esm/lib/jwt_claims_set.js", "../node_modules/jose/dist/node/esm/jwt/verify.js", "../node_modules/jose/dist/node/esm/jwks/local.js", "../node_modules/jose/dist/node/esm/runtime/fetch_jwks.js", "../node_modules/jose/dist/node/esm/jwks/remote.js", "../src/bridge.ts"],
|
|
4
|
-
"sourcesContent": ["export { litellmPlugin } from './plugin';\nexport { litellmPlugin as default } from './plugin';\nexport { createRouter } from './router';\nexport * from './types';\nexport { LiteLLMClient } from './client';\nexport {\n resolveUserId,\n resolveUserProfile,\n toLiteLLMUserId,\n getOrProvisionUser,\n provisionUser,\n readProvisioningDefaults,\n readRoleConfigs,\n applyRoleOverrides,\n resolveUserRole,\n ProvisioningError,\n} from './provisioning';\nexport type { BackstageUserProfile } from './provisioning';\nexport {\n KeycloakJWTVerifier,\n newDefaultVerifier,\n readBridgeConfig,\n resolveBridgeUserId,\n getOrProvisionUserFromClaims,\n bridgeListKeys,\n bridgeGenerateKey,\n} from './bridge';\nexport type {\n BridgeClaims,\n TokenVerifier,\n BridgeConfig,\n KeycloakJWTVerifierOptions,\n} from './bridge';\n", "import { coreServices, createBackendPlugin } from '@backstage/backend-plugin-api';\nimport { createRouter } from './router';\nimport { readBridgeConfig } from './bridge';\n\nexport const litellmPlugin = createBackendPlugin({\n pluginId: 'litellm',\n register(reg) {\n reg.registerInit({\n deps: {\n httpRouter: coreServices.httpRouter,\n config: coreServices.rootConfig,\n logger: coreServices.logger,\n auth: coreServices.auth,\n discovery: coreServices.discovery,\n },\n async init({ httpRouter, config, logger, auth, discovery }) {\n const router = await createRouter({ config, logger, auth, discovery });\n httpRouter.use(router);\n\n // The CLI bridge verifies raw Keycloak JWTs itself (it does NOT use a\n // Backstage-issued token). Exempt its routes from the default auth\n // policy, otherwise the framework rejects the Keycloak Bearer with\n // \"Illegal token\" before the bridge verifier ever runs.\n if (readBridgeConfig(config).enabled) {\n for (const path of [\n '/bridge/health',\n '/bridge/keys',\n '/bridge/models',\n ]) {\n httpRouter.addAuthPolicy({ path, allow: 'unauthenticated' });\n }\n }\n },\n });\n },\n});\n", "import express, { Router, Request, Response } from 'express';\nimport { Config } from '@backstage/config';\nimport { AuthService, DiscoveryService } from '@backstage/backend-plugin-api';\nimport { CatalogClient } from '@backstage/catalog-client';\nimport { LiteLLMClient } from './client';\nimport { openApiSpec } from './openapi';\nimport {\n VirtualKey,\n ModelInfo,\n UsageMetrics,\n TeamInfo,\n GenerateKeyRequest,\n GenerateKeyResponse,\n UpdateKeyRequest,\n} from './types';\nimport {\n toLiteLLMUserId,\n resolveUserId,\n resolveUserProfile,\n getOrProvisionUser,\n readProvisioningDefaults,\n readRoleConfigs,\n applyRoleOverrides,\n isUserMemberOfGroup,\n ProvisioningError,\n} from './provisioning';\nimport {\n BridgeAuthError,\n BridgeClaims,\n TokenVerifier,\n bridgeGenerateKey,\n bridgeListKeys,\n newDefaultVerifier,\n readBridgeConfig,\n} from './bridge';\n\nexport { ProvisioningError };\n\nexport interface RouterOptions {\n config: Config;\n logger: any;\n auth: AuthService;\n discovery: DiscoveryService;\n /** Override the LiteLLM client (tests). Defaults to one built from config. */\n client?: LiteLLMClient;\n /** Override the bridge token verifier (tests). Defaults to a Keycloak JWKS verifier. */\n tokenVerifier?: TokenVerifier;\n}\n\nexport async function createRouter(options: RouterOptions): Promise<Router> {\n const { config, logger, auth, discovery } = options;\n\n const baseUrl = config.getString('litellm.baseUrl');\n const masterKey = config.getString('litellm.masterKey');\n const userIdDomain = config.getOptionalString('litellm.userIdDomain');\n // Publicly reachable LiteLLM proxy URL, used to build ready-to-paste\n // snippets in the frontend. Falls back to baseUrl (the internal URL the\n // backend calls) when the operator has not configured a public one.\n const publicBaseUrl = config.getOptionalString('litellm.publicBaseUrl') ?? baseUrl;\n const client = options.client ?? new LiteLLMClient({ baseUrl, masterKey });\n const { enabled: provisioningEnabled, defaults: provisioningDefaults } =\n readProvisioningDefaults(config);\n const roleConfigs = readRoleConfigs(config);\n const auditGroup = config.getOptionalString('litellm.audit.group');\n const catalogClient = new CatalogClient({ discoveryApi: discovery });\n\n if (provisioningEnabled) {\n logger.info(\n `LiteLLM auto-provisioning enabled \u2014 defaults: budget=$${\n provisioningDefaults.maxBudget\n }/${provisioningDefaults.budgetDuration}, models=${\n provisioningDefaults.models.length\n ? provisioningDefaults.models.join(',')\n : 'all'\n }, teams=[${provisioningDefaults.teams.join(',')}]`,\n );\n }\n\n const router = Router();\n // JSON body parser. Without this, every POST/PUT endpoint sees an empty\n // req.body. Backstage's httpRouter does not apply a body parser at the\n // plugin-router level, so each plugin must attach its own.\n router.use(express.json());\n\n router.get('/health', (_req: Request, res: Response) => {\n res.json({ status: 'ok', provisioning: provisioningEnabled });\n });\n\n // Exposes the public LiteLLM proxy URL so the frontend can build\n // ready-to-paste curl / OpenAI-SDK snippets for freshly generated keys.\n router.get('/config', (_req: Request, res: Response) => {\n res.json({ baseUrl: publicBaseUrl });\n });\n\n // Self-hosted OpenAPI 3.1 contract \u2014 lets integrators read a spec instead\n // of router.ts. No swagger-ui dependency; serve the JSON and point external\n // renderers (Stoplight, Swagger UI hosted elsewhere) at this endpoint.\n router.get('/openapi.json', (_req: Request, res: Response) => {\n res.json(openApiSpec);\n });\n\n // Provisioning dry-run: resolves which role a Backstage group maps to and\n // echoes the effective defaults, collapsing the config \u2192 deploy \u2192 test loop\n // into one request. Admin-gated by the audit group (same RBAC as /audit).\n router.get('/provisioning/preview', async (req: Request, res: Response) => {\n if (!auditGroup) {\n res.status(403).json({ error: 'Preview is not configured (litellm.audit.group not set)' });\n return;\n }\n const tokenEntityRef = await resolveUserId(req, auth);\n if (!tokenEntityRef) {\n res.status(401).json({ error: 'Authentication required' });\n return;\n }\n const allowed = await isUserMemberOfGroup(\n tokenEntityRef,\n auditGroup,\n catalogClient,\n auth,\n logger,\n );\n if (!allowed) {\n res.status(403).json({ error: 'Access denied: not a member of the audit group' });\n return;\n }\n const group = (req.query.group as string | undefined)?.trim();\n if (!group) {\n res.status(400).json({ error: 'group query parameter is required (e.g. group=group:default/ai-platform)' });\n return;\n }\n if (!roleConfigs.length) {\n res.json({\n group,\n matched_role: null,\n effective_defaults: provisioningDefaults,\n note: 'No litellm.provisioning.roles configured \u2014 every group receives the base defaults.',\n });\n return;\n }\n try {\n const matched = roleConfigs.find(rc => rc.group === group);\n const effective = matched\n ? applyRoleOverrides(provisioningDefaults, matched)\n : provisioningDefaults;\n res.json({\n group,\n matched_role: matched?.group ?? null,\n effective_defaults: effective,\n });\n } catch (error: any) {\n logger.error('Failed to resolve provisioning preview', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n router.get('/user/info', async (req: Request, res: Response) => {\n try {\n const tokenEntityRef = await resolveUserId(req, auth);\n const userId = tokenEntityRef\n ? toLiteLLMUserId(tokenEntityRef, userIdDomain)\n : (req.query.user_id as string | undefined);\n\n const userInfo = await getOrProvisionUser(\n client,\n tokenEntityRef,\n userId,\n provisioningEnabled,\n provisioningDefaults,\n roleConfigs,\n catalogClient,\n auth,\n logger,\n );\n const canViewAudit =\n auditGroup && tokenEntityRef\n ? await isUserMemberOfGroup(\n tokenEntityRef,\n auditGroup,\n catalogClient,\n auth,\n logger,\n )\n : false;\n res.json({ ...userInfo, can_view_audit: canViewAudit });\n } catch (error: any) {\n if (error instanceof ProvisioningError) {\n res.status(error.status).json(error.body);\n return;\n }\n logger.error('Failed to fetch user info', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n router.get('/keys', async (req: Request, res: Response) => {\n try {\n const tokenEntityRef = await resolveUserId(req, auth);\n const userId = tokenEntityRef\n ? toLiteLLMUserId(tokenEntityRef, userIdDomain)\n : (req.query.user_id as string | undefined);\n\n await getOrProvisionUser(\n client,\n tokenEntityRef,\n userId,\n provisioningEnabled,\n provisioningDefaults,\n roleConfigs,\n catalogClient,\n auth,\n logger,\n );\n\n const keys: VirtualKey[] = await client.listKeys(userId);\n res.json(keys);\n } catch (error: any) {\n if (error instanceof ProvisioningError) {\n res.status(error.status).json(error.body);\n return;\n }\n logger.error('Failed to list keys', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n // \u2500\u2500 Key ownership guard \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n //\n // Every key-mutation route below runs under the LiteLLM master key, so\n // without an explicit check any authenticated Backstage user could act on\n // any key whose token they learn (audit logs expose truncated tokens, and\n // anyone who has held the raw key knows it). We fetch the caller's own key\n // list and 403 if the target token isn't in it.\n //\n // Returns the caller's LiteLLM user_id (when resolvable) so handlers can\n // stamp it in logs without re-deriving it.\n async function authorizeKeyAction(\n req: Request,\n keyId: string,\n ): Promise<{ tokenEntityRef: string | undefined; userId: string | undefined }> {\n const tokenEntityRef = await resolveUserId(req, auth);\n const userId = tokenEntityRef\n ? toLiteLLMUserId(tokenEntityRef, userIdDomain)\n : (req.query.user_id as string | undefined);\n if (!userId) {\n throw { status: 403, body: { error: 'Cannot verify key ownership without an authenticated user' } };\n }\n const ownKeys = await client.listKeys(userId);\n const owns = ownKeys.some(k => (k.token ?? k.key) === keyId);\n if (!owns) {\n throw { status: 403, body: { error: 'Access denied: key does not belong to the caller' } };\n }\n return { tokenEntityRef, userId };\n }\n\n // Normalize the ownership-guard rejection shape into a response.\n function sendOwnershipError(err: any, res: Response): boolean {\n if (err && typeof err.status === 'number' && err.body) {\n res.status(err.status).json(err.body);\n return true;\n }\n return false;\n }\n\n router.post('/keys/generate', async (req: Request, res: Response) => {\n try {\n // Only alias is hard-required. max_budget is optional: a positive\n // number caps spend, while null/undefined means \"unlimited\" (LiteLLM\n // supports null). An empty models array is intentional \u2014 in LiteLLM\n // `models: []` means \"all models the user can access\" which is the\n // desired default. Forcing a selection up front is too restrictive for\n // the common case.\n const body = (req.body ?? {}) as GenerateKeyRequest;\n const missing: string[] = [];\n if (!body.alias?.trim()) missing.push('alias');\n if (\n body.max_budget !== null &&\n body.max_budget !== undefined &&\n (typeof body.max_budget !== 'number' || body.max_budget <= 0)\n ) {\n missing.push('max_budget (positive number, or null for unlimited)');\n }\n if (missing.length) {\n res.status(400).json({\n error: 'Missing required fields',\n hint: `Required: ${missing.join(', ')}`,\n });\n return;\n }\n\n const tokenEntityRef = await resolveUserId(req, auth);\n const resolvedUserId = tokenEntityRef\n ? toLiteLLMUserId(tokenEntityRef, userIdDomain)\n : undefined;\n\n if (resolvedUserId) {\n await getOrProvisionUser(\n client,\n tokenEntityRef,\n resolvedUserId,\n provisioningEnabled,\n provisioningDefaults,\n roleConfigs,\n catalogClient,\n auth,\n logger,\n );\n }\n\n // Stamp ownership into LiteLLM key metadata. LiteLLM's native\n // `created_by` column is only populated when the caller authenticates\n // via JWT/SSO; we always call with the master key, so that column\n // stays null. Enriching `metadata` makes the owner identity visible\n // in LiteLLM's UI and queryable via API.\n const profile = tokenEntityRef\n ? await resolveUserProfile(tokenEntityRef, catalogClient, auth, logger)\n : {};\n const enrichedMetadata = {\n ...(body.metadata ?? {}),\n created_by_backstage_user: tokenEntityRef ?? 'unknown',\n ...(profile.email && { created_by_email: profile.email }),\n ...(profile.displayName && {\n created_by_display_name: profile.displayName,\n }),\n created_via: 'backstage',\n created_at_iso: new Date().toISOString(),\n };\n\n const request: GenerateKeyRequest = {\n ...body,\n metadata: enrichedMetadata,\n ...(resolvedUserId && { user_id: resolvedUserId }),\n };\n const result: GenerateKeyResponse = await client.generateKey(request);\n logger.info({ action: 'key.generate', userId: resolvedUserId ?? 'unknown', keyAlias: body.alias });\n res.json(result);\n } catch (error: any) {\n if (error instanceof ProvisioningError) {\n res.status(error.status).json(error.body);\n return;\n }\n // LiteLLM's enterprise team-key hook silently overrides the requested\n // `duration` with the team's `metadata.team_member_key_duration` when a\n // team_id is set, before parsing it. A malformed value there 500s with\n // this exact message regardless of what we sent \u2014 surface that instead\n // of the opaque passthrough so it's actionable from the LiteLLM side.\n if (\n typeof error.message === 'string' &&\n error.message.includes('Invalid duration format') &&\n req.body?.team_id\n ) {\n res.status(502).json({\n error:\n 'LiteLLM rejected the key duration for this team. The team has a ' +\n '\"Team Member Key Duration\" set in LiteLLM that is not in a valid ' +\n '<number><unit> format (e.g. \"30d\") and overrides whatever duration ' +\n 'is requested. Fix or clear it in LiteLLM under Teams \u2192 this team \u2192 ' +\n 'Team Settings, then retry.',\n teamId: req.body.team_id,\n });\n return;\n }\n logger.error('Failed to generate key', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n router.post('/keys/:keyId/update', async (req: Request, res: Response) => {\n try {\n const { keyId } = req.params;\n if (!keyId) {\n res.status(400).json({ error: 'keyId is required' });\n return;\n }\n const { tokenEntityRef } = await authorizeKeyAction(req, keyId);\n const request: UpdateKeyRequest = { ...req.body, key: keyId };\n const result = await client.updateKey(request);\n logger.info({ action: 'key.update', userId: tokenEntityRef ?? 'unknown', keyId });\n res.json(result);\n } catch (error: any) {\n if (sendOwnershipError(error, res)) return;\n logger.error('Failed to update key', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n router.delete('/keys/:keyId', async (req: Request, res: Response) => {\n try {\n const { keyId } = req.params;\n if (!keyId) {\n res.status(400).json({ error: 'keyId is required' });\n return;\n }\n const { tokenEntityRef } = await authorizeKeyAction(req, keyId);\n await client.deleteKeys({ keys: [keyId] });\n logger.info({ action: 'key.delete', userId: tokenEntityRef ?? 'unknown', keyId });\n res.json({ success: true });\n } catch (error: any) {\n if (sendOwnershipError(error, res)) return;\n logger.error('Failed to delete key', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n router.post('/keys/:keyId/block', async (req: Request, res: Response) => {\n try {\n const { keyId } = req.params;\n const { tokenEntityRef } = await authorizeKeyAction(req, keyId);\n await client.blockKey(keyId);\n logger.info({ action: 'key.block', userId: tokenEntityRef ?? 'unknown', keyId });\n res.json({ success: true });\n } catch (error: any) {\n if (sendOwnershipError(error, res)) return;\n logger.error('Failed to block key', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n router.post('/keys/:keyId/unblock', async (req: Request, res: Response) => {\n try {\n const { keyId } = req.params;\n const { tokenEntityRef } = await authorizeKeyAction(req, keyId);\n await client.unblockKey(keyId);\n logger.info({ action: 'key.unblock', userId: tokenEntityRef ?? 'unknown', keyId });\n res.json({ success: true });\n } catch (error: any) {\n if (sendOwnershipError(error, res)) return;\n logger.error('Failed to unblock key', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n router.post('/keys/:keyId/reset_spend', async (req: Request, res: Response) => {\n try {\n const { keyId } = req.params;\n const { tokenEntityRef } = await authorizeKeyAction(req, keyId);\n await client.resetKeySpend(keyId);\n logger.info({ action: 'key.reset_spend', userId: tokenEntityRef ?? 'unknown', keyId });\n res.json({ success: true });\n } catch (error: any) {\n if (sendOwnershipError(error, res)) return;\n logger.error('Failed to reset key spend', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n router.get('/audit', async (req: Request, res: Response) => {\n if (!auditGroup) {\n res.status(403).json({ error: 'Audit log is not configured (litellm.audit.group not set)' });\n return;\n }\n const tokenEntityRef = await resolveUserId(req, auth);\n if (!tokenEntityRef) {\n res.status(401).json({ error: 'Authentication required' });\n return;\n }\n const allowed = await isUserMemberOfGroup(\n tokenEntityRef,\n auditGroup,\n catalogClient,\n auth,\n logger,\n );\n if (!allowed) {\n res.status(403).json({ error: 'Access denied: not a member of the audit group' });\n return;\n }\n try {\n const { page, page_size, start_date, end_date, action, table_name, changed_by } =\n req.query as Record<string, string | undefined>;\n const result = await client.getAuditLogs({\n page: page ? Number(page) : undefined,\n page_size: page_size ? Number(page_size) : 25,\n start_date,\n end_date,\n action,\n table_name,\n changed_by,\n });\n res.json(result);\n } catch (error: any) {\n logger.error('Failed to fetch audit logs', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n router.get('/models', async (_req: Request, res: Response) => {\n try {\n const models: ModelInfo[] = await client.listModels();\n res.json(models);\n } catch (error: any) {\n logger.error('Failed to list models', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n router.get('/teams', async (req: Request, res: Response) => {\n try {\n const tokenEntityRef = await resolveUserId(req, auth);\n const userId = tokenEntityRef\n ? toLiteLLMUserId(tokenEntityRef, userIdDomain)\n : (req.query.user_id as string | undefined);\n\n const userInfo = await getOrProvisionUser(\n client,\n tokenEntityRef,\n userId,\n provisioningEnabled,\n provisioningDefaults,\n roleConfigs,\n catalogClient,\n auth,\n logger,\n );\n\n if (!userInfo?.teams?.length) {\n res.json([]);\n return;\n }\n\n const teams = await Promise.all(\n userInfo.teams.map(teamId =>\n client.getTeamInfo(teamId).catch(err => {\n logger.warn(`Failed to fetch team ${teamId}: ${err.message}`);\n return null;\n }),\n ),\n );\n res.json(teams.filter(Boolean) as TeamInfo[]);\n } catch (error: any) {\n if (error instanceof ProvisioningError) {\n res.status(error.status).json(error.body);\n return;\n }\n logger.error('Failed to fetch teams', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n router.get('/teams/:teamId/usage', async (req: Request, res: Response) => {\n try {\n const { teamId } = req.params;\n const { start_date, end_date } = req.query;\n if (!start_date || !end_date) {\n res.status(400).json({ error: 'start_date and end_date are required' });\n return;\n }\n const usage: UsageMetrics = await client.getTeamUsage(\n teamId,\n start_date as string,\n end_date as string,\n );\n res.json(usage);\n } catch (error: any) {\n logger.error('Failed to fetch team usage', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n router.get('/usage', async (req: Request, res: Response) => {\n try {\n const { start_date, end_date } = req.query;\n if (!start_date || !end_date) {\n res.status(400).json({ error: 'start_date and end_date are required' });\n return;\n }\n const tokenEntityRef = await resolveUserId(req, auth);\n const userId = tokenEntityRef\n ? toLiteLLMUserId(tokenEntityRef, userIdDomain)\n : (req.query.user_id as string | undefined);\n\n if (userId) {\n await getOrProvisionUser(\n client,\n tokenEntityRef,\n userId,\n provisioningEnabled,\n provisioningDefaults,\n roleConfigs,\n catalogClient,\n auth,\n logger,\n );\n }\n\n const usage: UsageMetrics = await client.getUsage(\n start_date as string,\n end_date as string,\n userId,\n );\n res.json(usage);\n } catch (error: any) {\n if (error instanceof ProvisioningError) {\n res.status(error.status).json(error.body);\n return;\n }\n logger.error('Failed to fetch usage', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n // ---------------------------------------------------------------------------\n // Bridge endpoints (CLI / Abby)\n //\n // Authenticated by a Keycloak access token (JWKS-verified), NOT by Backstage's\n // own auth. Lets CLI clients list/mint virtual keys without holding the master\n // key. Gated by litellm.bridge.enabled; the verifier needs litellm.bridge.issuer.\n const bridgeCfg = readBridgeConfig(config);\n let tokenVerifier: TokenVerifier | undefined = options.tokenVerifier;\n if (bridgeCfg.enabled && !tokenVerifier) {\n try {\n tokenVerifier = newDefaultVerifier(bridgeCfg);\n } catch (e) {\n logger.error(\n `LiteLLM bridge enabled but misconfigured: ${(e as Error).message}`,\n );\n }\n }\n\n if (bridgeCfg.enabled && tokenVerifier) {\n const requireClaims = async (req: Request): Promise<BridgeClaims> => {\n const header = req.headers.authorization ?? '';\n const token = header.startsWith('Bearer ') ? header.slice(7) : '';\n if (!token) throw new BridgeAuthError('missing Bearer token');\n return tokenVerifier!.verify(token);\n };\n\n const handleBridgeError = (error: any, res: Response) => {\n if (error instanceof BridgeAuthError) {\n res.status(401).json({ error: 'unauthorized', hint: error.message });\n return;\n }\n if (error instanceof ProvisioningError) {\n res.status(error.status).json(error.body);\n return;\n }\n logger.error('Bridge request failed', error);\n res.status(500).json({ error: error.message });\n };\n\n router.get('/bridge/health', (_req: Request, res: Response) => {\n res.json({ status: 'ok', bridge: true, clientId: bridgeCfg.clientId });\n });\n\n router.get('/bridge/keys', async (req: Request, res: Response) => {\n try {\n const claims = await requireClaims(req);\n const keys = await bridgeListKeys(\n client,\n claims,\n provisioningEnabled,\n provisioningDefaults,\n logger,\n userIdDomain,\n );\n res.json(keys);\n } catch (error: any) {\n handleBridgeError(error, res);\n }\n });\n\n router.post('/bridge/keys', async (req: Request, res: Response) => {\n try {\n const claims = await requireClaims(req);\n const result = await bridgeGenerateKey(\n client,\n claims,\n provisioningEnabled,\n provisioningDefaults,\n logger,\n (req.body ?? {}) as Partial<GenerateKeyRequest>,\n userIdDomain,\n );\n res.json(result);\n } catch (error: any) {\n handleBridgeError(error, res);\n }\n });\n\n router.get('/bridge/models', async (req: Request, res: Response) => {\n try {\n await requireClaims(req); // authenticate only\n const models = await client.listModels();\n res.json(models);\n } catch (error: any) {\n handleBridgeError(error, res);\n }\n });\n } else if (bridgeCfg.enabled) {\n logger.warn(\n 'litellm.bridge.enabled is true but no verifier could be built \u2014 bridge endpoints not mounted',\n );\n }\n\n return router;\n}\n", "import {\n LiteLLMConfig,\n UserInfo,\n VirtualKey,\n LiteLLMUserKey,\n ModelInfo,\n UsageMetrics,\n TeamInfo,\n GenerateKeyRequest,\n GenerateKeyResponse,\n UpdateKeyRequest,\n DeleteKeyRequest,\n CreateUserRequest,\n CreateUserResponse,\n AuditLogsParams,\n PaginatedAuditLogs,\n} from './types';\n\nconst DEFAULT_TIMEOUT = 30000;\n\nexport class LiteLLMClient {\n private baseUrl: string;\n private masterKey: string;\n private timeout: number;\n\n constructor(config: LiteLLMConfig, timeout = DEFAULT_TIMEOUT) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.masterKey = config.masterKey;\n this.timeout = timeout;\n }\n\n private async request<T>(\n path: string,\n options: RequestInit = {},\n ): Promise<T> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n // Auth note: the LiteLLM OpenAPI spec declares the security scheme as an\n // `x-litellm-api-key` header, but Bearer + master key is the deliberate,\n // production-tested choice \u2014 LiteLLM's proxy accepts both, and Bearer is\n // what every observed deployment actually uses. Do not \"correct\" this to\n // match the spec literally without testing against a live gateway.\n const response = await fetch(`${this.baseUrl}${path}`, {\n ...options,\n signal: controller.signal,\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.masterKey}`,\n ...options.headers,\n },\n });\n\n if (!response.ok) {\n const errorBody = await response.text();\n const err = new Error(\n `LiteLLM API error: ${response.status} ${response.statusText} - ${errorBody}`,\n );\n (err as any).status = response.status;\n throw err;\n }\n\n return response.json();\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * Returns null when the user is not found in LiteLLM (404).\n * Throws on all other errors so callers know something went wrong.\n *\n * LiteLLM's `/user/info` wraps the user row inside `user_info` and returns\n * `teams` as an array of full team objects, not team_id strings. We flatten\n * `user_info` onto the top level and reduce `teams` to a string[] of ids so\n * the rest of the code can rely on the UserInfo contract.\n */\n async getUserInfo(userId?: string): Promise<UserInfo | null> {\n const query = userId ? `?user_id=${encodeURIComponent(userId)}` : '';\n try {\n const raw = await this.request<any>(`/user/info${query}`);\n const inner = raw?.user_info ?? {};\n const teamIds: string[] = Array.isArray(raw?.teams)\n ? raw.teams\n .map((t: any) => (typeof t === 'string' ? t : t?.team_id))\n .filter((t: unknown): t is string => typeof t === 'string')\n : [];\n return {\n user_id: raw?.user_id ?? inner.user_id ?? userId ?? '',\n user_email: inner.user_email ?? raw?.user_email,\n email: inner.email ?? raw?.email,\n teams: teamIds,\n models: inner.models ?? raw?.models,\n max_budget: inner.max_budget ?? raw?.max_budget,\n spend: inner.spend ?? raw?.spend,\n current_spend: inner.current_spend ?? raw?.current_spend,\n soft_limit: inner.soft_limit ?? raw?.soft_limit,\n hard_limit: inner.hard_limit ?? raw?.hard_limit,\n };\n } catch (err: any) {\n if (err.status === 404) return null;\n throw err;\n }\n }\n\n async createUser(payload: CreateUserRequest): Promise<CreateUserResponse> {\n return this.request<CreateUserResponse>('/user/new', {\n method: 'POST',\n body: JSON.stringify(payload),\n });\n }\n\n /**\n * Updates an existing LiteLLM user record. Used as a defensive follow-up\n * after /user/new because the upsert path of /user/new has been observed\n * to silently drop fields like user_role under concurrent inserts.\n */\n async updateUser(\n payload: Partial<CreateUserRequest> & { user_id: string },\n ): Promise<unknown> {\n return this.request<unknown>('/user/update', {\n method: 'POST',\n body: JSON.stringify(payload),\n });\n }\n\n /**\n * Returns the keys belonging to a user.\n *\n * Implementation note: LiteLLM's `/key/info` endpoint requires a `key`\n * hash and returns 404 when only `user_id` is passed. The correct way\n * to enumerate a user's keys is `/user/info?user_id=X`, which embeds\n * a `keys` array with per-key metadata. We unwrap that array and\n * normalise field names to match the frontend VirtualKey shape\n * (LiteLLM exposes `key_name` for the masked display value and\n * `expires` instead of `expires_at`).\n */\n async listKeys(userId?: string): Promise<VirtualKey[]> {\n if (!userId) return [];\n try {\n const response = await this.request<{ keys?: LiteLLMUserKey[] }>(\n `/user/info?user_id=${encodeURIComponent(userId)}`,\n );\n const rawKeys = response.keys ?? [];\n return rawKeys.map(this.toVirtualKey);\n } catch (err: any) {\n if (err.status === 404 || err.message.includes('not found')) {\n return [];\n }\n throw err;\n }\n }\n\n private toVirtualKey(k: LiteLLMUserKey): VirtualKey {\n return {\n key: k.key_name ?? k.token,\n token: k.token,\n key_alias: k.key_alias ?? undefined,\n created_at: k.created_at,\n expires_at: k.expires ?? undefined,\n spend: k.spend ?? 0,\n max_budget: k.max_budget ?? undefined,\n tpm_limit: k.tpm_limit ?? undefined,\n rpm_limit: k.rpm_limit ?? undefined,\n models: k.models ?? [],\n user_id: k.user_id ?? undefined,\n blocked: k.blocked ?? undefined,\n };\n }\n\n /**\n * Creates a new virtual key on the LiteLLM proxy.\n *\n * Implementation notes \u2014 both required to avoid silently-empty keys:\n * 1. The body must be the plain payload. An earlier version wrapped\n * it as `{ json: request }`; LiteLLM doesn't unwrap that envelope\n * and treats the request as having no fields, returning a key\n * with null alias / models / budget / limits.\n * 2. LiteLLM expects `key_alias`, not `alias`. Without the rename,\n * the alias the user typed is dropped on the floor.\n */\n async generateKey(request: GenerateKeyRequest): Promise<GenerateKeyResponse> {\n const { alias, ...rest } = request;\n const payload = {\n ...rest,\n ...(alias && { key_alias: alias }),\n };\n return this.request<GenerateKeyResponse>('/key/generate', {\n method: 'POST',\n body: JSON.stringify(payload),\n });\n }\n\n async updateKey(request: UpdateKeyRequest): Promise<VirtualKey> {\n return this.request<VirtualKey>('/key/update', {\n method: 'POST',\n body: JSON.stringify(request),\n });\n }\n\n async deleteKeys(request: DeleteKeyRequest): Promise<{ success: boolean }> {\n return this.request<{ success: boolean }>('/key/delete', {\n method: 'POST',\n body: JSON.stringify(request),\n });\n }\n\n async blockKey(key: string): Promise<unknown> {\n return this.request('/key/block', {\n method: 'POST',\n body: JSON.stringify({ key }),\n });\n }\n\n async unblockKey(key: string): Promise<unknown> {\n return this.request('/key/unblock', {\n method: 'POST',\n body: JSON.stringify({ key }),\n });\n }\n\n async resetKeySpend(key: string): Promise<unknown> {\n return this.request(`/key/${encodeURIComponent(key)}/reset_spend`, {\n method: 'POST',\n body: JSON.stringify({ reset_to: 0 }),\n });\n }\n\n async getAuditLogs(params: AuditLogsParams): Promise<PaginatedAuditLogs> {\n const query = new URLSearchParams();\n if (params.page !== undefined) query.set('page', String(params.page));\n if (params.page_size !== undefined) query.set('page_size', String(params.page_size));\n if (params.start_date) query.set('start_date', params.start_date);\n if (params.end_date) query.set('end_date', params.end_date);\n if (params.action) query.set('action', params.action);\n if (params.table_name) query.set('table_name', params.table_name);\n if (params.changed_by) query.set('changed_by', params.changed_by);\n if (params.sort_by) query.set('sort_by', params.sort_by);\n if (params.sort_order) query.set('sort_order', params.sort_order);\n return this.request<PaginatedAuditLogs>(`/audit?${query.toString()}`);\n }\n\n /**\n * Returns the proxy's model catalogue normalised to the ModelInfo shape.\n *\n * Prefers `/model/info` which exposes `model_name`, `mode`, capability flags\n * and per-token costs. Falls back to OpenAI-compatible `/models` (which only\n * returns `{id}`) so the dropdown still works on installs where `/model/info`\n * isn't reachable. Without this normalisation the UI saw blank labels and\n * a single \"other\" group because `/models` doesn't populate `model_name`\n * or `mode`.\n */\n async listModels(): Promise<ModelInfo[]> {\n try {\n const response = await this.request<{ data?: any[] }>('/model/info');\n const data = Array.isArray(response?.data) ? response.data : [];\n const normalised = data.map((m: any) => {\n const info = m.model_info ?? {};\n const params = m.litellm_params ?? {};\n return {\n model_name: m.model_name ?? params.model ?? info.id ?? '',\n mode: info.mode ?? m.mode ?? 'chat',\n supports_function_calling:\n info.supports_function_calling ?? m.supports_function_calling,\n supports_vision: info.supports_vision ?? m.supports_vision,\n input_cost_per_token:\n info.input_cost_per_token ?? params.input_cost_per_token,\n output_cost_per_token:\n info.output_cost_per_token ?? params.output_cost_per_token,\n max_input_tokens: info.max_input_tokens ?? m.max_input_tokens,\n max_output_tokens: info.max_output_tokens ?? m.max_output_tokens,\n } as ModelInfo;\n });\n const filtered = normalised.filter(m => m.model_name);\n if (filtered.length) return filtered;\n } catch {\n // fall through to /models\n }\n const fallback = await this.request<{ data?: any[] } | any[]>('/models');\n const data = Array.isArray(fallback)\n ? fallback\n : Array.isArray(fallback?.data)\n ? fallback!.data!\n : [];\n return data\n .map((m: any) => ({\n model_name: m.model_name ?? m.id ?? '',\n mode: m.mode ?? 'chat',\n supports_function_calling: m.supports_function_calling,\n supports_vision: m.supports_vision,\n }))\n .filter((m: ModelInfo) => m.model_name);\n }\n\n /**\n * LiteLLM's `/team/info` wraps the team row inside `team_info` (alongside\n * sibling `keys` / `team_memberships` arrays), the same shape as\n * `/user/info` wrapping the user row inside `user_info`. Without unwrapping,\n * `team_alias`, `members_with_roles`, `models`, budgets and limits are all\n * undefined, so the UI fell back to displaying the raw team_id / \"Untitled\n * team\".\n */\n async getTeamInfo(teamId: string): Promise<TeamInfo> {\n const raw = await this.request<any>(\n `/team/info?team_id=${encodeURIComponent(teamId)}`,\n );\n const inner = raw?.team_info ?? {};\n return {\n team_id: raw?.team_id ?? inner.team_id ?? teamId,\n team_alias: inner.team_alias ?? raw?.team_alias,\n max_budget: inner.max_budget ?? raw?.max_budget,\n spend: inner.spend ?? raw?.spend ?? 0,\n members_with_roles: inner.members_with_roles ?? raw?.members_with_roles,\n models: inner.models ?? raw?.models,\n tpm_limit: inner.tpm_limit ?? raw?.tpm_limit,\n rpm_limit: inner.rpm_limit ?? raw?.rpm_limit,\n };\n }\n\n private emptyUsage(): UsageMetrics {\n return {\n total_spend: 0,\n total_tokens: 0,\n prompt_tokens: 0,\n completion_tokens: 0,\n api_requests: 0,\n successful_requests: 0,\n failed_requests: 0,\n usage_by_model: {},\n usage_by_key: {},\n daily_usage: [],\n daily_by_model: [],\n };\n }\n\n /**\n * Transforms LiteLLM's SpendAnalyticsPaginatedResponse into the flatter\n * UsageMetrics shape consumed by the frontend charts.\n *\n * Source shape (per result row):\n * { date, metrics, breakdown: { models: { [name]: { metrics, api_key_breakdown: { [keyHash]: { metrics, metadata } } } } } }\n *\n * We fan that out into three views the UI consumes:\n * - daily_usage \u2192 spend + request trends over time\n * - usage_by_model \u2192 which models drove cost / traffic\n * - usage_by_key \u2192 which keys drove cost / traffic (with key_alias + team_id from metadata)\n */\n private transformDailyActivity(response: any): UsageMetrics {\n const results: any[] = Array.isArray(response?.results)\n ? response.results\n : [];\n const meta = response?.metadata ?? {};\n\n const daily_usage = results\n .map(r => ({\n date: r.date,\n spend: r.metrics?.spend ?? 0,\n total_tokens: r.metrics?.total_tokens ?? 0,\n prompt_tokens: r.metrics?.prompt_tokens ?? 0,\n completion_tokens: r.metrics?.completion_tokens ?? 0,\n api_requests: r.metrics?.api_requests ?? 0,\n successful_requests: r.metrics?.successful_requests ?? 0,\n failed_requests: r.metrics?.failed_requests ?? 0,\n }))\n .sort((a, b) => a.date.localeCompare(b.date));\n\n const usage_by_model: UsageMetrics['usage_by_model'] = {};\n const usage_by_key: UsageMetrics['usage_by_key'] = {};\n const daily_by_model: UsageMetrics['daily_by_model'] = [];\n\n const emptyModelBucket = () => ({\n total_spend: 0,\n total_tokens: 0,\n prompt_tokens: 0,\n completion_tokens: 0,\n api_requests: 0,\n successful_requests: 0,\n failed_requests: 0,\n });\n\n for (const r of results) {\n const models = r.breakdown?.models ?? {};\n for (const [name, entry] of Object.entries<any>(models)) {\n const m = entry?.metrics ?? {};\n const bucket = usage_by_model[name] ?? emptyModelBucket();\n bucket.total_spend += m.spend ?? 0;\n bucket.total_tokens += m.total_tokens ?? 0;\n bucket.prompt_tokens += m.prompt_tokens ?? 0;\n bucket.completion_tokens += m.completion_tokens ?? 0;\n bucket.api_requests += m.api_requests ?? 0;\n bucket.successful_requests += m.successful_requests ?? 0;\n bucket.failed_requests += m.failed_requests ?? 0;\n usage_by_model[name] = bucket;\n\n daily_by_model.push({\n date: r.date,\n model: name,\n spend: m.spend ?? 0,\n prompt_tokens: m.prompt_tokens ?? 0,\n completion_tokens: m.completion_tokens ?? 0,\n total_tokens: m.total_tokens ?? 0,\n api_requests: m.api_requests ?? 0,\n successful_requests: m.successful_requests ?? 0,\n failed_requests: m.failed_requests ?? 0,\n });\n\n const keyMap = entry?.api_key_breakdown ?? {};\n for (const [keyHash, keyEntry] of Object.entries<any>(keyMap)) {\n const km = keyEntry?.metrics ?? {};\n const kmeta = keyEntry?.metadata ?? {};\n const kb = usage_by_key[keyHash] ?? {\n key_alias: kmeta.key_alias,\n team_id: kmeta.team_id ?? null,\n models: [] as string[],\n ...emptyModelBucket(),\n };\n if (!kb.key_alias && kmeta.key_alias) kb.key_alias = kmeta.key_alias;\n if (kb.team_id == null && kmeta.team_id) kb.team_id = kmeta.team_id;\n if (!kb.models.includes(name)) kb.models.push(name);\n kb.total_spend += km.spend ?? 0;\n kb.total_tokens += km.total_tokens ?? 0;\n kb.prompt_tokens += km.prompt_tokens ?? 0;\n kb.completion_tokens += km.completion_tokens ?? 0;\n kb.api_requests += km.api_requests ?? 0;\n kb.successful_requests += km.successful_requests ?? 0;\n kb.failed_requests += km.failed_requests ?? 0;\n usage_by_key[keyHash] = kb;\n }\n }\n }\n\n return {\n total_spend: meta.total_spend ?? 0,\n total_tokens: meta.total_tokens ?? 0,\n prompt_tokens: meta.total_prompt_tokens ?? 0,\n completion_tokens: meta.total_completion_tokens ?? 0,\n api_requests: meta.total_api_requests ?? 0,\n successful_requests: meta.total_successful_requests ?? 0,\n failed_requests: meta.total_failed_requests ?? 0,\n usage_by_model,\n usage_by_key,\n daily_usage,\n daily_by_model,\n };\n }\n\n async getUsage(\n startDate: string,\n endDate: string,\n userId?: string,\n ): Promise<UsageMetrics> {\n const params = new URLSearchParams({\n start_date: startDate,\n end_date: endDate,\n page_size: '100',\n });\n if (userId) params.append('user_id', userId);\n try {\n const response = await this.request<any>(\n `/user/daily/activity?${params.toString()}`,\n );\n return this.transformDailyActivity(response);\n } catch (err: any) {\n if (err.status === 404 || err.message.includes('not found')) {\n return this.emptyUsage();\n }\n throw err;\n }\n }\n\n async getTeamUsage(\n teamId: string,\n startDate: string,\n endDate: string,\n ): Promise<UsageMetrics> {\n const params = new URLSearchParams({\n start_date: startDate,\n end_date: endDate,\n team_ids: teamId,\n page_size: '100',\n });\n try {\n const response = await this.request<any>(\n `/team/daily/activity?${params.toString()}`,\n );\n return this.transformDailyActivity(response);\n } catch (err: any) {\n if (err.status === 404 || err.message.includes('not found')) {\n return this.emptyUsage();\n }\n throw err;\n }\n }\n}\n", "// OpenAPI 3.1 contract for the plugin's own backend surface.\n//\n// Kept as a TypeScript object so the router can serve it at\n// GET /api/litellm/openapi.json without a YAML parser dependency, and so\n// a future tool can regenerate the README endpoint table from it.\n//\n// Conventions:\n// - Every UI route authenticates via a Backstage user bearer token\n// (Authorization: Bearer <backstage-token>). The bridge routes use a\n// raw Keycloak access token instead and are gated by\n// litellm.bridge.enabled.\n// - Key-mutation routes 403 when the target key does not belong to the\n// caller (ownership guard; see router.ts authorizeKeyAction).\n\nexport interface OpenApiSpec {\n openapi: string;\n info: { title: string; version: string; description: string };\n servers: { url: string; description: string }[];\n tags: { name: string; description: string }[];\n paths: Record<string, Record<string, any>>;\n components: { securitySchemes: Record<string, any> };\n}\n\nexport const openApiSpec: OpenApiSpec = {\n openapi: '3.1.0',\n info: {\n title: 'LiteLLM Governance Plugin API',\n version: '0.1.0',\n description:\n 'Backstage backend surface for the LiteLLM governance plugin. ' +\n 'UI routes authenticate via the Backstage identity system; CLI bridge ' +\n 'routes authenticate with a Keycloak access token.',\n },\n servers: [\n { url: '/api/litellm', description: 'Backstage backend plugin mount point' },\n ],\n tags: [\n { name: 'System', description: 'Health and configuration' },\n { name: 'User', description: 'Current user info and provisioning' },\n { name: 'Keys', description: 'Virtual key lifecycle' },\n { name: 'Models', description: 'Model catalogue' },\n { name: 'Teams', description: 'Team membership and usage' },\n { name: 'Usage', description: 'Spend and traffic analytics' },\n { name: 'Audit', description: 'Audit logs (RBAC-gated)' },\n { name: 'Provisioning', description: 'Provisioning dry-run (RBAC-gated)' },\n { name: 'Bridge', description: 'CLI bridge (Keycloak-token auth)' },\n ],\n paths: {\n '/health': {\n get: {\n tags: ['System'],\n summary: 'Health check',\n responses: {\n '200': {\n description: 'Plugin health',\n content: { 'application/json': { schema: { type: 'object', properties: {\n status: { type: 'string' },\n provisioning: { type: 'boolean' },\n } } } },\n },\n },\n },\n },\n '/config': {\n get: {\n tags: ['System'],\n summary: 'Public LiteLLM proxy base URL (for snippet generation)',\n responses: {\n '200': {\n description: 'Proxy URL',\n content: { 'application/json': { schema: { type: 'object', properties: {\n baseUrl: { type: 'string' },\n } } } },\n },\n },\n },\n },\n '/openapi.json': {\n get: {\n tags: ['System'],\n summary: 'This OpenAPI document',\n responses: { '200': { description: 'OpenAPI 3.1 JSON' } },\n },\n },\n '/user/info': {\n get: {\n tags: ['User'],\n summary: \"Get the current user's info and quotas\",\n responses: {\n '200': { description: 'User info' },\n '404': { description: 'User not found in LiteLLM (provisioning disabled)' },\n },\n },\n },\n '/keys': {\n get: {\n tags: ['Keys'],\n summary: \"List the caller's virtual keys\",\n responses: { '200': { description: 'Array of keys' } },\n },\n },\n '/keys/generate': {\n post: {\n tags: ['Keys'],\n summary: 'Generate a new virtual key',\n requestBody: {\n required: true,\n content: { 'application/json': { schema: { type: 'object', properties: {\n alias: { type: 'string' },\n models: { type: 'array', items: { type: 'string' } },\n team_id: { type: 'string' },\n duration: { type: 'string' },\n max_budget: { type: 'number', nullable: true, description: 'Positive number caps spend; null = unlimited' },\n tpm_limit: { type: 'number' },\n rpm_limit: { type: 'number' },\n } } } },\n },\n responses: {\n '200': { description: 'Generated key (includes the raw secret \u2014 shown once)' },\n '400': { description: 'Missing required fields' },\n },\n },\n },\n '/keys/{keyId}': {\n delete: {\n tags: ['Keys'],\n summary: 'Revoke/delete a virtual key (caller must own it)',\n parameters: [{ name: 'keyId', in: 'path', required: true, schema: { type: 'string' } }],\n responses: { '200': { description: 'Deleted' }, '403': { description: 'Not the key owner' } },\n },\n },\n '/keys/{keyId}/update': {\n post: {\n tags: ['Keys'],\n summary: 'Update alias / models / budget / limits (caller must own it)',\n parameters: [{ name: 'keyId', in: 'path', required: true, schema: { type: 'string' } }],\n requestBody: { content: { 'application/json': { schema: { type: 'object' } } } },\n responses: { '200': { description: 'Updated' }, '403': { description: 'Not the key owner' } },\n },\n },\n '/keys/{keyId}/block': {\n post: {\n tags: ['Keys'],\n summary: 'Suspend a key without revoking (caller must own it)',\n parameters: [{ name: 'keyId', in: 'path', required: true, schema: { type: 'string' } }],\n responses: { '200': { description: 'Blocked' }, '403': { description: 'Not the key owner' } },\n },\n },\n '/keys/{keyId}/unblock': {\n post: {\n tags: ['Keys'],\n summary: 'Re-enable a blocked key (caller must own it)',\n parameters: [{ name: 'keyId', in: 'path', required: true, schema: { type: 'string' } }],\n responses: { '200': { description: 'Unblocked' }, '403': { description: 'Not the key owner' } },\n },\n },\n '/keys/{keyId}/reset_spend': {\n post: {\n tags: ['Keys'],\n summary: 'Zero out a key spend counter (caller must own it)',\n parameters: [{ name: 'keyId', in: 'path', required: true, schema: { type: 'string' } }],\n responses: { '200': { description: 'Spend reset' }, '403': { description: 'Not the key owner' } },\n },\n },\n '/models': {\n get: {\n tags: ['Models'],\n summary: 'List available LLM models',\n responses: { '200': { description: 'Model catalogue' } },\n },\n },\n '/teams': {\n get: {\n tags: ['Teams'],\n summary: 'List teams the current user belongs to',\n responses: { '200': { description: 'Array of teams' } },\n },\n },\n '/teams/{teamId}/usage': {\n get: {\n tags: ['Teams'],\n summary: 'Usage metrics for a team',\n parameters: [\n { name: 'teamId', in: 'path', required: true, schema: { type: 'string' } },\n { name: 'start_date', in: 'query', required: true, schema: { type: 'string' } },\n { name: 'end_date', in: 'query', required: true, schema: { type: 'string' } },\n ],\n responses: { '200': { description: 'Team usage' }, '400': { description: 'Missing date range' } },\n },\n },\n '/usage': {\n get: {\n tags: ['Usage'],\n summary: 'Usage metrics for the current user',\n parameters: [\n { name: 'start_date', in: 'query', required: true, schema: { type: 'string' } },\n { name: 'end_date', in: 'query', required: true, schema: { type: 'string' } },\n ],\n responses: { '200': { description: 'Usage metrics' }, '400': { description: 'Missing date range' } },\n },\n },\n '/audit': {\n get: {\n tags: ['Audit'],\n summary: 'Audit logs (gated by litellm.audit.group membership)',\n parameters: [\n { name: 'page', in: 'query', schema: { type: 'integer' } },\n { name: 'page_size', in: 'query', schema: { type: 'integer' } },\n { name: 'start_date', in: 'query', schema: { type: 'string' } },\n { name: 'end_date', in: 'query', schema: { type: 'string' } },\n { name: 'action', in: 'query', schema: { type: 'string' } },\n { name: 'table_name', in: 'query', schema: { type: 'string' } },\n { name: 'changed_by', in: 'query', schema: { type: 'string' } },\n ],\n responses: { '200': { description: 'Paginated audit logs' }, '403': { description: 'Not configured or not authorized' } },\n },\n },\n '/provisioning/preview': {\n get: {\n tags: ['Provisioning'],\n summary: 'Resolve which role a Backstage group maps to (dry-run)',\n parameters: [\n { name: 'group', in: 'query', required: true, schema: { type: 'string' }, description: 'e.g. group:default/ai-platform' },\n ],\n responses: {\n '200': { description: 'Resolved role and effective defaults' },\n '400': { description: 'Missing group parameter' },\n '403': { description: 'Not configured or not authorized' },\n },\n },\n },\n '/bridge/health': {\n get: {\n tags: ['Bridge'],\n summary: 'Bridge health + configured clientId (no auth)',\n responses: { '200': { description: 'Bridge health' } },\n },\n },\n '/bridge/keys': {\n get: {\n tags: ['Bridge'],\n summary: 'List the caller virtual keys (Keycloak token auth)',\n responses: { '200': { description: 'Array of keys' }, '401': { description: 'Invalid token' } },\n },\n post: {\n tags: ['Bridge'],\n summary: 'Mint a virtual key for the caller (Keycloak token auth)',\n requestBody: { content: { 'application/json': { schema: { type: 'object' } } } },\n responses: { '200': { description: 'Generated key' }, '401': { description: 'Invalid token' } },\n },\n },\n '/bridge/models': {\n get: {\n tags: ['Bridge'],\n summary: 'List available LLM models (Keycloak token auth)',\n responses: { '200': { description: 'Model catalogue' }, '401': { description: 'Invalid token' } },\n },\n },\n },\n components: {\n securitySchemes: {\n backstageUserToken: {\n type: 'http',\n scheme: 'bearer',\n description: 'Backstage-issued user token (Authorization: Bearer <token>).',\n },\n keycloakAccessToken: {\n type: 'http',\n scheme: 'bearer',\n description: 'Raw Keycloak access token. Bridge routes only; verified against the realm JWKS.',\n },\n },\n },\n};", "import { Config } from '@backstage/config';\nimport { AuthService } from '@backstage/backend-plugin-api';\nimport { CatalogClient } from '@backstage/catalog-client';\nimport { Request } from 'express';\nimport { LiteLLMClient } from './client';\nimport { UserInfo, ProvisioningDefaults, RoleConfig } from './types';\n\n/**\n * Converts a Backstage user entity ref to a LiteLLM user_id.\n *\n * When userIdDomain is configured, the entity name is suffixed with the domain\n * so that LiteLLM user_ids match the organisation's email addresses:\n * \"user:default/andrea.carmisciano\" + \"abstract.it\"\n * \u2192 \"andrea.carmisciano@abstract.it\"\n *\n * Without a domain the bare entity name is returned unchanged, which works for\n * deployments where LiteLLM users were created with plain usernames.\n */\nexport function toLiteLLMUserId(\n userEntityRef: string,\n userIdDomain?: string,\n): string {\n const name = userEntityRef.split('/').pop() ?? userEntityRef;\n // Defensive: if the entity name is already email-shaped (e.g. when the\n // Keycloak provider imports usernames as full emails without our\n // name-rewrite transformer running, or when a catalog change leaves\n // an entity ref like \"user:default/foo@bar.it\"), do NOT append the\n // userIdDomain \u2014 that produced \"foo@bar.it@bar.it\" in production.\n if (name.includes('@')) return name;\n return userIdDomain ? `${name}@${userIdDomain}` : name;\n}\n\n/**\n * Reads the provisioning block from config, applying safe defaults for every\n * field so the feature works out-of-the-box without any YAML required.\n *\n * Safe defaults rationale:\n * maxBudget: $10 \u2014 prevents runaway spend on a forgotten test account\n * budgetDuration: 30d \u2014 monthly reset, aligns with typical billing cycles\n * models: [] \u2014 empty means all proxy models are allowed;\n * restrict here or at team level for tighter control\n * teams: [] \u2014 no automatic team assignment; add IDs to enrol users\n * tpmLimit: none \u2014 LiteLLM global / team limits still apply\n * rpmLimit: none \u2014 same\n * metadata: backstage source tag only\n */\nexport function readRoleConfigs(config: Config): RoleConfig[] {\n const raw = config.getOptional<any[]>('litellm.provisioning.roles');\n if (!raw?.length) return [];\n return raw.map((r: any) => ({\n group: r.group as string,\n maxBudget: r.maxBudget,\n budgetDuration: r.budgetDuration,\n models: r.models,\n teams: r.teams,\n tpmLimit: r.tpmLimit,\n rpmLimit: r.rpmLimit,\n userRole: r.userRole,\n metadata: r.metadata,\n }));\n}\n\n/**\n * Merges role config over defaults. Role fields override defaults only when explicitly set.\n */\nexport function applyRoleOverrides(\n defaults: ProvisioningDefaults,\n role: RoleConfig,\n): ProvisioningDefaults {\n return {\n maxBudget: role.maxBudget ?? defaults.maxBudget,\n budgetDuration: role.budgetDuration ?? defaults.budgetDuration,\n models: role.models ?? defaults.models,\n teams: role.teams ?? defaults.teams,\n tpmLimit: role.tpmLimit ?? defaults.tpmLimit,\n rpmLimit: role.rpmLimit ?? defaults.rpmLimit,\n userRole: role.userRole ?? defaults.userRole,\n metadata: { ...defaults.metadata, ...(role.metadata ?? {}) },\n };\n}\n\nexport function readProvisioningDefaults(config: Config): {\n enabled: boolean;\n defaults: ProvisioningDefaults;\n} {\n const enabled =\n config.getOptionalBoolean('litellm.provisioning.enabled') ?? false;\n const defaults: ProvisioningDefaults = {\n maxBudget:\n config.getOptionalNumber('litellm.provisioning.defaults.maxBudget') ?? 10,\n budgetDuration:\n config.getOptionalString(\n 'litellm.provisioning.defaults.budgetDuration',\n ) ?? '30d',\n models:\n config.getOptionalStringArray('litellm.provisioning.defaults.models') ??\n [],\n teams:\n config.getOptionalStringArray('litellm.provisioning.defaults.teams') ??\n [],\n tpmLimit: config.getOptionalNumber(\n 'litellm.provisioning.defaults.tpmLimit',\n ),\n rpmLimit: config.getOptionalNumber(\n 'litellm.provisioning.defaults.rpmLimit',\n ),\n userRole:\n config.getOptionalString('litellm.provisioning.defaults.userRole') ??\n 'internal_user',\n metadata:\n config.getOptional<Record<string, string>>(\n 'litellm.provisioning.defaults.metadata',\n ) ?? {},\n };\n return { enabled, defaults };\n}\n\n/**\n * Extracts the authenticated Backstage user identity from the request token.\n * Returns the userEntityRef (e.g. \"user:default/john.doe\") or undefined when\n * the request carries no user credential (service-to-service calls).\n */\nexport async function resolveUserId(\n req: Request,\n auth: AuthService,\n): Promise<string | undefined> {\n const rawToken = req.headers.authorization?.slice(7);\n if (!rawToken) return undefined;\n try {\n const credentials = await auth.authenticate(rawToken);\n const principal = credentials.principal as any;\n if (principal?.type === 'user') {\n return principal.userEntityRef as string;\n }\n } catch {\n // invalid or service token \u2014 caller gets query-param fallback\n }\n return undefined;\n}\n\n/**\n * Profile data extracted from a Backstage Catalog User entity, used to\n * populate user_email / user_alias on the LiteLLM record.\n */\nexport interface BackstageUserProfile {\n email?: string;\n displayName?: string;\n}\n\n/**\n * Looks up the catalog User entity for the authenticated user and returns\n * the profile block. Returns an empty object when the user has no catalog\n * entity (e.g. dangerouslyAllowSignInWithoutUserInCatalog was used) \u2014 the\n * caller falls back to deriving identity from userIdDomain.\n */\nexport async function resolveUserProfile(\n userEntityRef: string,\n catalogClient: CatalogClient,\n auth: AuthService,\n logger: any,\n): Promise<BackstageUserProfile> {\n try {\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: await auth.getOwnServiceCredentials(),\n targetPluginId: 'catalog',\n });\n const entity = await catalogClient.getEntityByRef(userEntityRef, { token });\n const profile = (entity?.spec as any)?.profile ?? {};\n return {\n email: profile.email,\n displayName: profile.displayName,\n };\n } catch (err: any) {\n logger.warn(\n `Could not fetch catalog profile for ${userEntityRef}: ${err.message}`,\n );\n return {};\n }\n}\n\n/**\n * Creates a LiteLLM user for the given Backstage identity using the configured\n * defaults. Returns the UserInfo of the newly created account.\n */\nexport async function provisionUser(\n client: LiteLLMClient,\n userId: string,\n defaults: ProvisioningDefaults,\n profile: BackstageUserProfile,\n backstageEntity: string | undefined,\n logger: any,\n): Promise<UserInfo | null> {\n const payload = {\n user_id: userId,\n ...(profile.email && { user_email: profile.email }),\n ...(profile.displayName && { user_alias: profile.displayName }),\n max_budget: defaults.maxBudget,\n budget_duration: defaults.budgetDuration,\n models: defaults.models,\n teams: defaults.teams,\n ...(defaults.tpmLimit !== undefined && { tpm_limit: defaults.tpmLimit }),\n ...(defaults.rpmLimit !== undefined && { rpm_limit: defaults.rpmLimit }),\n ...(defaults.userRole && { user_role: defaults.userRole }),\n auto_create_key: false,\n metadata: {\n ...defaults.metadata,\n provisioned_by: 'backstage',\n provisioned_at: new Date().toISOString(),\n backstage_entity: backstageEntity ?? userId,\n ...(profile.email && { backstage_email: profile.email }),\n ...(profile.displayName && {\n backstage_display_name: profile.displayName,\n }),\n },\n };\n\n logger.info(\n `Provisioning new LiteLLM user for Backstage identity: ${userId}` +\n (profile.email ? ` (email=${profile.email})` : ''),\n );\n try {\n await client.createUser(payload);\n // Defensive /user/update: LiteLLM's /user/new upsert path has been\n // observed to drop user_role under concurrent inserts (the first\n // call sets the field, a racing second call upserts and clears it).\n // Re-asserting the role-bearing fields immediately after creation\n // is cheap and makes the role guarantee robust.\n if (defaults.userRole) {\n try {\n await client.updateUser({\n user_id: userId,\n user_role: defaults.userRole,\n ...(profile.email && { user_email: profile.email }),\n ...(profile.displayName && { user_alias: profile.displayName }),\n });\n } catch (updateErr: any) {\n logger.warn(\n `Defensive /user/update after provisioning ${userId} failed: ${updateErr.message}`,\n );\n }\n }\n // Fetch the freshly-created user record to return consistent UserInfo shape\n return await client.getUserInfo(userId);\n } catch (err: any) {\n logger.error(`Failed to provision LiteLLM user ${userId}: ${err.message}`);\n throw err;\n }\n}\n\n/**\n * Module-scope single-flight cache keyed by LiteLLM user_id. Coalesces\n * concurrent provisioning attempts for the same user so /user/new fires\n * at most once per user across parallel requests. Without this, an\n * authenticated page load that fires /keys, /teams and /usage in\n * parallel triggers three concurrent /user/new calls; LiteLLM's\n * upsert path then creates one default key per call (so the user lands\n * with 3 unexpected keys) and may silently lose user_role.\n *\n * Cache entries are removed once the promise settles, so subsequent\n * requests for a re-deleted user can still trigger fresh provisioning.\n */\nconst provisioningInFlight = new Map<string, Promise<UserInfo>>();\n\n/**\n * Strips any echoed Authorization bearer token from upstream LiteLLM error\n * messages before they're shipped back to the browser. LiteLLM normally does\n * not echo the master key, but defense in depth: never let a `Bearer \u2026`\n * substring travel out in a response body.\n */\nfunction sanitizeUpstreamMessage(message: string): string {\n if (!message) return 'unknown error';\n return message\n .replace(/Bearer\\s+[A-Za-z0-9._\\-+/=]+/g, 'Bearer [redacted]')\n .replace(/sk-[A-Za-z0-9_\\-]{8,}/g, 'sk-[redacted]')\n .slice(0, 500);\n}\n\nexport class ProvisioningError extends Error {\n status: number;\n body: { error: string; hint: string; provisioning: boolean };\n\n constructor(\n message: string,\n hint: string,\n provisioning: boolean,\n status = 404,\n ) {\n super(message);\n this.status = status;\n this.body = { error: message, hint, provisioning };\n }\n}\n\n/**\n * Ensures the LiteLLM user exists, returning its UserInfo.\n * When the user is missing and provisioning is enabled, attempts to create it.\n * When provisioning is disabled, throws a ProvisioningError with a clear message.\n */\nexport async function getOrProvisionUser(\n client: LiteLLMClient,\n tokenEntityRef: string | undefined,\n userId: string | undefined,\n provisioningEnabled: boolean,\n provisioningDefaults: ProvisioningDefaults,\n roleConfigs: RoleConfig[],\n catalogClient: CatalogClient,\n auth: AuthService,\n logger: any,\n): Promise<UserInfo> {\n if (!userId) {\n throw new ProvisioningError(\n 'User not found in LiteLLM',\n 'No user identity could be resolved from the request.',\n provisioningEnabled,\n );\n }\n\n const existing = await client.getUserInfo(userId);\n if (existing) {\n return existing;\n }\n\n if (!provisioningEnabled) {\n throw new ProvisioningError(\n 'User not found in LiteLLM',\n 'Enable litellm.provisioning.enabled in app-config.yaml or create the user manually',\n false,\n );\n }\n\n // Single-flight: if another request for the same userId is already\n // provisioning, await its result instead of starting a new /user/new.\n // This collapses the /keys + /teams + /usage page-load thundering\n // herd into a single LiteLLM round-trip.\n const pending = provisioningInFlight.get(userId);\n if (pending) {\n logger.info(\n `LiteLLM provisioning already in flight for ${userId} \u2014 joining`,\n );\n return pending;\n }\n\n const provisionPromise = (async () => {\n const catalogRef = tokenEntityRef ?? userId;\n const [matchedRole, profile] = await Promise.all([\n resolveUserRole(catalogRef, roleConfigs, catalogClient, auth, logger),\n tokenEntityRef\n ? resolveUserProfile(tokenEntityRef, catalogClient, auth, logger)\n : Promise.resolve<BackstageUserProfile>({}),\n ]);\n const effectiveDefaults = matchedRole\n ? applyRoleOverrides(provisioningDefaults, matchedRole)\n : provisioningDefaults;\n if (matchedRole) {\n logger.info(\n `User ${userId} matched role group ${matchedRole.group} \u2014 using role-specific provisioning`,\n );\n }\n try {\n const created = await provisionUser(\n client,\n userId,\n effectiveDefaults,\n profile,\n tokenEntityRef,\n logger,\n );\n if (!created) {\n throw new ProvisioningError(\n 'User not found in LiteLLM',\n 'Provisioning attempted but returned no user \u2014 check LiteLLM logs',\n true,\n );\n }\n return created;\n } catch (err: any) {\n // The single-flight cache should prevent the parallel-409 race,\n // but keep the recovery path: if /user/new still 409s (e.g.\n // multi-replica deploys where the lock is per-process), treat\n // it as \"user exists\" and re-fetch.\n if (err.status === 409 || /already exists/i.test(err.message ?? '')) {\n logger.info(\n `LiteLLM user ${userId} already exists during provisioning \u2014 re-fetching`,\n );\n const refetched = await client.getUserInfo(userId);\n if (refetched) {\n return refetched;\n }\n }\n if (err instanceof ProvisioningError) {\n throw err;\n }\n // Map upstream LiteLLM status to a Backstage-safe gateway status.\n // 401/403/5xx from LiteLLM mean the gateway (this plugin) cannot\n // talk to LiteLLM \u2014 they MUST NOT propagate as 401/403 to the\n // browser, otherwise Backstage's fetch middleware treats the\n // user's Backstage session as expired and forces a re-login.\n // Only safe client-semantic codes pass through.\n const upstreamStatus = err.status;\n const passThrough = [400, 404, 409, 422].includes(upstreamStatus)\n ? upstreamStatus\n : 502;\n throw new ProvisioningError(\n 'LiteLLM auto-provisioning failed',\n `LiteLLM upstream ${\n upstreamStatus ?? 'error'\n }: ${sanitizeUpstreamMessage(err.message)}`,\n true,\n passThrough,\n );\n }\n })();\n\n provisioningInFlight.set(userId, provisionPromise);\n try {\n return await provisionPromise;\n } finally {\n provisioningInFlight.delete(userId);\n }\n}\n\n/**\n * Returns true when the user is a member of the given Backstage group entity ref.\n * Used for RBAC gates (e.g. audit log visibility) without the role-config machinery.\n */\nexport async function isUserMemberOfGroup(\n userEntityRef: string,\n group: string,\n catalogClient: CatalogClient,\n auth: AuthService,\n logger: any,\n): Promise<boolean> {\n try {\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: await auth.getOwnServiceCredentials(),\n targetPluginId: 'catalog',\n });\n const entity = await catalogClient.getEntityByRef(userEntityRef, { token });\n const groups = (entity?.relations ?? [])\n .filter(r => r.type === 'memberOf')\n .map(r => r.targetRef);\n return groups.includes(group);\n } catch (err: any) {\n logger.warn(`Could not check group membership for ${userEntityRef}: ${err.message}`);\n return false;\n }\n}\n\n/**\n * Fetches the user's Backstage group memberships and returns the first matching\n * role config (priority order), or undefined when no role matches.\n */\nexport async function resolveUserRole(\n userEntityRef: string,\n roleConfigs: RoleConfig[],\n catalogClient: CatalogClient,\n auth: AuthService,\n logger: any,\n): Promise<RoleConfig | undefined> {\n if (!roleConfigs.length) return undefined;\n try {\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: await auth.getOwnServiceCredentials(),\n targetPluginId: 'catalog',\n });\n const entity = await catalogClient.getEntityByRef(userEntityRef, { token });\n const groups = (entity?.relations ?? [])\n .filter(r => r.type === 'memberOf')\n .map(r => r.targetRef);\n return roleConfigs.find(rc => groups.includes(rc.group));\n } catch (err: any) {\n logger.warn(\n `Could not resolve Backstage groups for ${userEntityRef}: ${err.message}`,\n );\n return undefined;\n }\n}\n", "import { Buffer } from 'node:buffer';\nimport { decoder } from '../lib/buffer_utils.js';\nfunction normalize(input) {\n let encoded = input;\n if (encoded instanceof Uint8Array) {\n encoded = decoder.decode(encoded);\n }\n return encoded;\n}\nconst encode = (input) => Buffer.from(input).toString('base64url');\nexport const decodeBase64 = (input) => new Uint8Array(Buffer.from(input, 'base64'));\nexport const encodeBase64 = (input) => Buffer.from(input).toString('base64');\nexport { encode };\nexport const decode = (input) => new Uint8Array(Buffer.from(normalize(input), 'base64url'));\n", "import digest from '../runtime/digest.js';\nexport const encoder = new TextEncoder();\nexport const decoder = new TextDecoder();\nconst MAX_INT32 = 2 ** 32;\nexport function concat(...buffers) {\n const size = buffers.reduce((acc, { length }) => acc + length, 0);\n const buf = new Uint8Array(size);\n let i = 0;\n for (const buffer of buffers) {\n buf.set(buffer, i);\n i += buffer.length;\n }\n return buf;\n}\nexport function p2s(alg, p2sInput) {\n return concat(encoder.encode(alg), new Uint8Array([0]), p2sInput);\n}\nfunction writeUInt32BE(buf, value, offset) {\n if (value < 0 || value >= MAX_INT32) {\n throw new RangeError(`value must be >= 0 and <= ${MAX_INT32 - 1}. Received ${value}`);\n }\n buf.set([value >>> 24, value >>> 16, value >>> 8, value & 0xff], offset);\n}\nexport function uint64be(value) {\n const high = Math.floor(value / MAX_INT32);\n const low = value % MAX_INT32;\n const buf = new Uint8Array(8);\n writeUInt32BE(buf, high, 0);\n writeUInt32BE(buf, low, 4);\n return buf;\n}\nexport function uint32be(value) {\n const buf = new Uint8Array(4);\n writeUInt32BE(buf, value);\n return buf;\n}\nexport function lengthAndInput(input) {\n return concat(uint32be(input.length), input);\n}\nexport async function concatKdf(secret, bits, value) {\n const iterations = Math.ceil((bits >> 3) / 32);\n const res = new Uint8Array(iterations * 32);\n for (let iter = 0; iter < iterations; iter++) {\n const buf = new Uint8Array(4 + secret.length + value.length);\n buf.set(uint32be(iter + 1));\n buf.set(secret, 4);\n buf.set(value, 4 + secret.length);\n res.set(await digest('sha256', buf), iter * 32);\n }\n return res.slice(0, bits >> 3);\n}\n", "export class JOSEError extends Error {\n static code = 'ERR_JOSE_GENERIC';\n code = 'ERR_JOSE_GENERIC';\n constructor(message, options) {\n super(message, options);\n this.name = this.constructor.name;\n Error.captureStackTrace?.(this, this.constructor);\n }\n}\nexport class JWTClaimValidationFailed extends JOSEError {\n static code = 'ERR_JWT_CLAIM_VALIDATION_FAILED';\n code = 'ERR_JWT_CLAIM_VALIDATION_FAILED';\n claim;\n reason;\n payload;\n constructor(message, payload, claim = 'unspecified', reason = 'unspecified') {\n super(message, { cause: { claim, reason, payload } });\n this.claim = claim;\n this.reason = reason;\n this.payload = payload;\n }\n}\nexport class JWTExpired extends JOSEError {\n static code = 'ERR_JWT_EXPIRED';\n code = 'ERR_JWT_EXPIRED';\n claim;\n reason;\n payload;\n constructor(message, payload, claim = 'unspecified', reason = 'unspecified') {\n super(message, { cause: { claim, reason, payload } });\n this.claim = claim;\n this.reason = reason;\n this.payload = payload;\n }\n}\nexport class JOSEAlgNotAllowed extends JOSEError {\n static code = 'ERR_JOSE_ALG_NOT_ALLOWED';\n code = 'ERR_JOSE_ALG_NOT_ALLOWED';\n}\nexport class JOSENotSupported extends JOSEError {\n static code = 'ERR_JOSE_NOT_SUPPORTED';\n code = 'ERR_JOSE_NOT_SUPPORTED';\n}\nexport class JWEDecryptionFailed extends JOSEError {\n static code = 'ERR_JWE_DECRYPTION_FAILED';\n code = 'ERR_JWE_DECRYPTION_FAILED';\n constructor(message = 'decryption operation failed', options) {\n super(message, options);\n }\n}\nexport class JWEInvalid extends JOSEError {\n static code = 'ERR_JWE_INVALID';\n code = 'ERR_JWE_INVALID';\n}\nexport class JWSInvalid extends JOSEError {\n static code = 'ERR_JWS_INVALID';\n code = 'ERR_JWS_INVALID';\n}\nexport class JWTInvalid extends JOSEError {\n static code = 'ERR_JWT_INVALID';\n code = 'ERR_JWT_INVALID';\n}\nexport class JWKInvalid extends JOSEError {\n static code = 'ERR_JWK_INVALID';\n code = 'ERR_JWK_INVALID';\n}\nexport class JWKSInvalid extends JOSEError {\n static code = 'ERR_JWKS_INVALID';\n code = 'ERR_JWKS_INVALID';\n}\nexport class JWKSNoMatchingKey extends JOSEError {\n static code = 'ERR_JWKS_NO_MATCHING_KEY';\n code = 'ERR_JWKS_NO_MATCHING_KEY';\n constructor(message = 'no applicable key found in the JSON Web Key Set', options) {\n super(message, options);\n }\n}\nexport class JWKSMultipleMatchingKeys extends JOSEError {\n [Symbol.asyncIterator];\n static code = 'ERR_JWKS_MULTIPLE_MATCHING_KEYS';\n code = 'ERR_JWKS_MULTIPLE_MATCHING_KEYS';\n constructor(message = 'multiple matching keys found in the JSON Web Key Set', options) {\n super(message, options);\n }\n}\nexport class JWKSTimeout extends JOSEError {\n static code = 'ERR_JWKS_TIMEOUT';\n code = 'ERR_JWKS_TIMEOUT';\n constructor(message = 'request timed out', options) {\n super(message, options);\n }\n}\nexport class JWSSignatureVerificationFailed extends JOSEError {\n static code = 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED';\n code = 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED';\n constructor(message = 'signature verification failed', options) {\n super(message, options);\n }\n}\n", "import * as util from 'node:util';\nexport default (obj) => util.types.isKeyObject(obj);\n", "import * as crypto from 'node:crypto';\nimport * as util from 'node:util';\nconst webcrypto = crypto.webcrypto;\nexport default webcrypto;\nexport const isCryptoKey = (key) => util.types.isCryptoKey(key);\n", "function unusable(name, prop = 'algorithm.name') {\n return new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`);\n}\nfunction isAlgorithm(algorithm, name) {\n return algorithm.name === name;\n}\nfunction getHashLength(hash) {\n return parseInt(hash.name.slice(4), 10);\n}\nfunction getNamedCurve(alg) {\n switch (alg) {\n case 'ES256':\n return 'P-256';\n case 'ES384':\n return 'P-384';\n case 'ES512':\n return 'P-521';\n default:\n throw new Error('unreachable');\n }\n}\nfunction checkUsage(key, usages) {\n if (usages.length && !usages.some((expected) => key.usages.includes(expected))) {\n let msg = 'CryptoKey does not support this operation, its usages must include ';\n if (usages.length > 2) {\n const last = usages.pop();\n msg += `one of ${usages.join(', ')}, or ${last}.`;\n }\n else if (usages.length === 2) {\n msg += `one of ${usages[0]} or ${usages[1]}.`;\n }\n else {\n msg += `${usages[0]}.`;\n }\n throw new TypeError(msg);\n }\n}\nexport function checkSigCryptoKey(key, alg, ...usages) {\n switch (alg) {\n case 'HS256':\n case 'HS384':\n case 'HS512': {\n if (!isAlgorithm(key.algorithm, 'HMAC'))\n throw unusable('HMAC');\n const expected = parseInt(alg.slice(2), 10);\n const actual = getHashLength(key.algorithm.hash);\n if (actual !== expected)\n throw unusable(`SHA-${expected}`, 'algorithm.hash');\n break;\n }\n case 'RS256':\n case 'RS384':\n case 'RS512': {\n if (!isAlgorithm(key.algorithm, 'RSASSA-PKCS1-v1_5'))\n throw unusable('RSASSA-PKCS1-v1_5');\n const expected = parseInt(alg.slice(2), 10);\n const actual = getHashLength(key.algorithm.hash);\n if (actual !== expected)\n throw unusable(`SHA-${expected}`, 'algorithm.hash');\n break;\n }\n case 'PS256':\n case 'PS384':\n case 'PS512': {\n if (!isAlgorithm(key.algorithm, 'RSA-PSS'))\n throw unusable('RSA-PSS');\n const expected = parseInt(alg.slice(2), 10);\n const actual = getHashLength(key.algorithm.hash);\n if (actual !== expected)\n throw unusable(`SHA-${expected}`, 'algorithm.hash');\n break;\n }\n case 'EdDSA': {\n if (key.algorithm.name !== 'Ed25519' && key.algorithm.name !== 'Ed448') {\n throw unusable('Ed25519 or Ed448');\n }\n break;\n }\n case 'Ed25519': {\n if (!isAlgorithm(key.algorithm, 'Ed25519'))\n throw unusable('Ed25519');\n break;\n }\n case 'ES256':\n case 'ES384':\n case 'ES512': {\n if (!isAlgorithm(key.algorithm, 'ECDSA'))\n throw unusable('ECDSA');\n const expected = getNamedCurve(alg);\n const actual = key.algorithm.namedCurve;\n if (actual !== expected)\n throw unusable(expected, 'algorithm.namedCurve');\n break;\n }\n default:\n throw new TypeError('CryptoKey does not support this operation');\n }\n checkUsage(key, usages);\n}\nexport function checkEncCryptoKey(key, alg, ...usages) {\n switch (alg) {\n case 'A128GCM':\n case 'A192GCM':\n case 'A256GCM': {\n if (!isAlgorithm(key.algorithm, 'AES-GCM'))\n throw unusable('AES-GCM');\n const expected = parseInt(alg.slice(1, 4), 10);\n const actual = key.algorithm.length;\n if (actual !== expected)\n throw unusable(expected, 'algorithm.length');\n break;\n }\n case 'A128KW':\n case 'A192KW':\n case 'A256KW': {\n if (!isAlgorithm(key.algorithm, 'AES-KW'))\n throw unusable('AES-KW');\n const expected = parseInt(alg.slice(1, 4), 10);\n const actual = key.algorithm.length;\n if (actual !== expected)\n throw unusable(expected, 'algorithm.length');\n break;\n }\n case 'ECDH': {\n switch (key.algorithm.name) {\n case 'ECDH':\n case 'X25519':\n case 'X448':\n break;\n default:\n throw unusable('ECDH, X25519, or X448');\n }\n break;\n }\n case 'PBES2-HS256+A128KW':\n case 'PBES2-HS384+A192KW':\n case 'PBES2-HS512+A256KW':\n if (!isAlgorithm(key.algorithm, 'PBKDF2'))\n throw unusable('PBKDF2');\n break;\n case 'RSA-OAEP':\n case 'RSA-OAEP-256':\n case 'RSA-OAEP-384':\n case 'RSA-OAEP-512': {\n if (!isAlgorithm(key.algorithm, 'RSA-OAEP'))\n throw unusable('RSA-OAEP');\n const expected = parseInt(alg.slice(9), 10) || 1;\n const actual = getHashLength(key.algorithm.hash);\n if (actual !== expected)\n throw unusable(`SHA-${expected}`, 'algorithm.hash');\n break;\n }\n default:\n throw new TypeError('CryptoKey does not support this operation');\n }\n checkUsage(key, usages);\n}\n", "function message(msg, actual, ...types) {\n types = types.filter(Boolean);\n if (types.length > 2) {\n const last = types.pop();\n msg += `one of type ${types.join(', ')}, or ${last}.`;\n }\n else if (types.length === 2) {\n msg += `one of type ${types[0]} or ${types[1]}.`;\n }\n else {\n msg += `of type ${types[0]}.`;\n }\n if (actual == null) {\n msg += ` Received ${actual}`;\n }\n else if (typeof actual === 'function' && actual.name) {\n msg += ` Received function ${actual.name}`;\n }\n else if (typeof actual === 'object' && actual != null) {\n if (actual.constructor?.name) {\n msg += ` Received an instance of ${actual.constructor.name}`;\n }\n }\n return msg;\n}\nexport default (actual, ...types) => {\n return message('Key must be ', actual, ...types);\n};\nexport function withAlg(alg, actual, ...types) {\n return message(`Key for the ${alg} algorithm must be `, actual, ...types);\n}\n", "import webcrypto, { isCryptoKey } from './webcrypto.js';\nimport isKeyObject from './is_key_object.js';\nexport default (key) => isKeyObject(key) || isCryptoKey(key);\nconst types = ['KeyObject'];\nif (globalThis.CryptoKey || webcrypto?.CryptoKey) {\n types.push('CryptoKey');\n}\nexport { types };\n", "const isDisjoint = (...headers) => {\n const sources = headers.filter(Boolean);\n if (sources.length === 0 || sources.length === 1) {\n return true;\n }\n let acc;\n for (const header of sources) {\n const parameters = Object.keys(header);\n if (!acc || acc.size === 0) {\n acc = new Set(parameters);\n continue;\n }\n for (const parameter of parameters) {\n if (acc.has(parameter)) {\n return false;\n }\n acc.add(parameter);\n }\n }\n return true;\n};\nexport default isDisjoint;\n", "function isObjectLike(value) {\n return typeof value === 'object' && value !== null;\n}\nexport default function isObject(input) {\n if (!isObjectLike(input) || Object.prototype.toString.call(input) !== '[object Object]') {\n return false;\n }\n if (Object.getPrototypeOf(input) === null) {\n return true;\n }\n let proto = input;\n while (Object.getPrototypeOf(proto) !== null) {\n proto = Object.getPrototypeOf(proto);\n }\n return Object.getPrototypeOf(input) === proto;\n}\n", "import { KeyObject } from 'node:crypto';\nimport { JOSENotSupported } from '../util/errors.js';\nimport { isCryptoKey } from './webcrypto.js';\nimport isKeyObject from './is_key_object.js';\nimport invalidKeyInput from '../lib/invalid_key_input.js';\nimport { types } from './is_key_like.js';\nimport { isJWK } from '../lib/is_jwk.js';\nexport const weakMap = new WeakMap();\nconst namedCurveToJOSE = (namedCurve) => {\n switch (namedCurve) {\n case 'prime256v1':\n return 'P-256';\n case 'secp384r1':\n return 'P-384';\n case 'secp521r1':\n return 'P-521';\n case 'secp256k1':\n return 'secp256k1';\n default:\n throw new JOSENotSupported('Unsupported key curve for this operation');\n }\n};\nconst getNamedCurve = (kee, raw) => {\n let key;\n if (isCryptoKey(kee)) {\n key = KeyObject.from(kee);\n }\n else if (isKeyObject(kee)) {\n key = kee;\n }\n else if (isJWK(kee)) {\n return kee.crv;\n }\n else {\n throw new TypeError(invalidKeyInput(kee, ...types));\n }\n if (key.type === 'secret') {\n throw new TypeError('only \"private\" or \"public\" type keys can be used for this operation');\n }\n switch (key.asymmetricKeyType) {\n case 'ed25519':\n case 'ed448':\n return `Ed${key.asymmetricKeyType.slice(2)}`;\n case 'x25519':\n case 'x448':\n return `X${key.asymmetricKeyType.slice(1)}`;\n case 'ec': {\n const namedCurve = key.asymmetricKeyDetails.namedCurve;\n if (raw) {\n return namedCurve;\n }\n return namedCurveToJOSE(namedCurve);\n }\n default:\n throw new TypeError('Invalid asymmetric key type for this operation');\n }\n};\nexport default getNamedCurve;\n", "import isObject from './is_object.js';\nexport function isJWK(key) {\n return isObject(key) && typeof key.kty === 'string';\n}\nexport function isPrivateJWK(key) {\n return key.kty !== 'oct' && typeof key.d === 'string';\n}\nexport function isPublicJWK(key) {\n return key.kty !== 'oct' && typeof key.d === 'undefined';\n}\nexport function isSecretJWK(key) {\n return isJWK(key) && key.kty === 'oct' && typeof key.k === 'string';\n}\n", "import { KeyObject } from 'node:crypto';\nexport default (key, alg) => {\n let modulusLength;\n try {\n if (key instanceof KeyObject) {\n modulusLength = key.asymmetricKeyDetails?.modulusLength;\n }\n else {\n modulusLength = Buffer.from(key.n, 'base64url').byteLength << 3;\n }\n }\n catch { }\n if (typeof modulusLength !== 'number' || modulusLength < 2048) {\n throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`);\n }\n};\n", "import { createPrivateKey, createPublicKey } from 'node:crypto';\nconst parse = (key) => {\n if (key.d) {\n return createPrivateKey({ format: 'jwk', key });\n }\n return createPublicKey({ format: 'jwk', key });\n};\nexport default parse;\n", "import { decode as decodeBase64URL } from '../runtime/base64url.js';\nimport { fromSPKI, fromPKCS8, fromX509 } from '../runtime/asn1.js';\nimport asKeyObject from '../runtime/jwk_to_key.js';\nimport { JOSENotSupported } from '../util/errors.js';\nimport isObject from '../lib/is_object.js';\nexport async function importSPKI(spki, alg, options) {\n if (typeof spki !== 'string' || spki.indexOf('-----BEGIN PUBLIC KEY-----') !== 0) {\n throw new TypeError('\"spki\" must be SPKI formatted string');\n }\n return fromSPKI(spki, alg, options);\n}\nexport async function importX509(x509, alg, options) {\n if (typeof x509 !== 'string' || x509.indexOf('-----BEGIN CERTIFICATE-----') !== 0) {\n throw new TypeError('\"x509\" must be X.509 formatted string');\n }\n return fromX509(x509, alg, options);\n}\nexport async function importPKCS8(pkcs8, alg, options) {\n if (typeof pkcs8 !== 'string' || pkcs8.indexOf('-----BEGIN PRIVATE KEY-----') !== 0) {\n throw new TypeError('\"pkcs8\" must be PKCS#8 formatted string');\n }\n return fromPKCS8(pkcs8, alg, options);\n}\nexport async function importJWK(jwk, alg) {\n if (!isObject(jwk)) {\n throw new TypeError('JWK must be an object');\n }\n alg ||= jwk.alg;\n switch (jwk.kty) {\n case 'oct':\n if (typeof jwk.k !== 'string' || !jwk.k) {\n throw new TypeError('missing \"k\" (Key Value) Parameter value');\n }\n return decodeBase64URL(jwk.k);\n case 'RSA':\n if ('oth' in jwk && jwk.oth !== undefined) {\n throw new JOSENotSupported('RSA JWK \"oth\" (Other Primes Info) Parameter value is not supported');\n }\n case 'EC':\n case 'OKP':\n return asKeyObject({ ...jwk, alg });\n default:\n throw new JOSENotSupported('Unsupported \"kty\" (Key Type) Parameter value');\n }\n}\n", "import { withAlg as invalidKeyInput } from './invalid_key_input.js';\nimport isKeyLike, { types } from '../runtime/is_key_like.js';\nimport * as jwk from './is_jwk.js';\nconst tag = (key) => key?.[Symbol.toStringTag];\nconst jwkMatchesOp = (alg, key, usage) => {\n if (key.use !== undefined && key.use !== 'sig') {\n throw new TypeError('Invalid key for this operation, when present its use must be sig');\n }\n if (key.key_ops !== undefined && key.key_ops.includes?.(usage) !== true) {\n throw new TypeError(`Invalid key for this operation, when present its key_ops must include ${usage}`);\n }\n if (key.alg !== undefined && key.alg !== alg) {\n throw new TypeError(`Invalid key for this operation, when present its alg must be ${alg}`);\n }\n return true;\n};\nconst symmetricTypeCheck = (alg, key, usage, allowJwk) => {\n if (key instanceof Uint8Array)\n return;\n if (allowJwk && jwk.isJWK(key)) {\n if (jwk.isSecretJWK(key) && jwkMatchesOp(alg, key, usage))\n return;\n throw new TypeError(`JSON Web Key for symmetric algorithms must have JWK \"kty\" (Key Type) equal to \"oct\" and the JWK \"k\" (Key Value) present`);\n }\n if (!isKeyLike(key)) {\n throw new TypeError(invalidKeyInput(alg, key, ...types, 'Uint8Array', allowJwk ? 'JSON Web Key' : null));\n }\n if (key.type !== 'secret') {\n throw new TypeError(`${tag(key)} instances for symmetric algorithms must be of type \"secret\"`);\n }\n};\nconst asymmetricTypeCheck = (alg, key, usage, allowJwk) => {\n if (allowJwk && jwk.isJWK(key)) {\n switch (usage) {\n case 'sign':\n if (jwk.isPrivateJWK(key) && jwkMatchesOp(alg, key, usage))\n return;\n throw new TypeError(`JSON Web Key for this operation be a private JWK`);\n case 'verify':\n if (jwk.isPublicJWK(key) && jwkMatchesOp(alg, key, usage))\n return;\n throw new TypeError(`JSON Web Key for this operation be a public JWK`);\n }\n }\n if (!isKeyLike(key)) {\n throw new TypeError(invalidKeyInput(alg, key, ...types, allowJwk ? 'JSON Web Key' : null));\n }\n if (key.type === 'secret') {\n throw new TypeError(`${tag(key)} instances for asymmetric algorithms must not be of type \"secret\"`);\n }\n if (usage === 'sign' && key.type === 'public') {\n throw new TypeError(`${tag(key)} instances for asymmetric algorithm signing must be of type \"private\"`);\n }\n if (usage === 'decrypt' && key.type === 'public') {\n throw new TypeError(`${tag(key)} instances for asymmetric algorithm decryption must be of type \"private\"`);\n }\n if (key.algorithm && usage === 'verify' && key.type === 'private') {\n throw new TypeError(`${tag(key)} instances for asymmetric algorithm verifying must be of type \"public\"`);\n }\n if (key.algorithm && usage === 'encrypt' && key.type === 'private') {\n throw new TypeError(`${tag(key)} instances for asymmetric algorithm encryption must be of type \"public\"`);\n }\n};\nfunction checkKeyType(allowJwk, alg, key, usage) {\n const symmetric = alg.startsWith('HS') ||\n alg === 'dir' ||\n alg.startsWith('PBES2') ||\n /^A\\d{3}(?:GCM)?KW$/.test(alg);\n if (symmetric) {\n symmetricTypeCheck(alg, key, usage, allowJwk);\n }\n else {\n asymmetricTypeCheck(alg, key, usage, allowJwk);\n }\n}\nexport default checkKeyType.bind(undefined, false);\nexport const checkKeyTypeWithJwk = checkKeyType.bind(undefined, true);\n", "import { JOSENotSupported } from '../util/errors.js';\nfunction validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) {\n if (joseHeader.crit !== undefined && protectedHeader?.crit === undefined) {\n throw new Err('\"crit\" (Critical) Header Parameter MUST be integrity protected');\n }\n if (!protectedHeader || protectedHeader.crit === undefined) {\n return new Set();\n }\n if (!Array.isArray(protectedHeader.crit) ||\n protectedHeader.crit.length === 0 ||\n protectedHeader.crit.some((input) => typeof input !== 'string' || input.length === 0)) {\n throw new Err('\"crit\" (Critical) Header Parameter MUST be an array of non-empty strings when present');\n }\n let recognized;\n if (recognizedOption !== undefined) {\n recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]);\n }\n else {\n recognized = recognizedDefault;\n }\n for (const parameter of protectedHeader.crit) {\n if (!recognized.has(parameter)) {\n throw new JOSENotSupported(`Extension Header Parameter \"${parameter}\" is not recognized`);\n }\n if (joseHeader[parameter] === undefined) {\n throw new Err(`Extension Header Parameter \"${parameter}\" is missing`);\n }\n if (recognized.get(parameter) && protectedHeader[parameter] === undefined) {\n throw new Err(`Extension Header Parameter \"${parameter}\" MUST be integrity protected`);\n }\n }\n return new Set(protectedHeader.crit);\n}\nexport default validateCrit;\n", "const validateAlgorithms = (option, algorithms) => {\n if (algorithms !== undefined &&\n (!Array.isArray(algorithms) || algorithms.some((s) => typeof s !== 'string'))) {\n throw new TypeError(`\"${option}\" option must be an array of strings`);\n }\n if (!algorithms) {\n return undefined;\n }\n return new Set(algorithms);\n};\nexport default validateAlgorithms;\n", "import * as crypto from 'node:crypto';\nimport { promisify } from 'node:util';\nimport nodeDigest from './dsa_digest.js';\nimport nodeKey from './node_key.js';\nimport sign from './sign.js';\nimport getVerifyKey from './get_sign_verify_key.js';\nconst oneShotVerify = promisify(crypto.verify);\nconst verify = async (alg, key, signature, data) => {\n const k = getVerifyKey(alg, key, 'verify');\n if (alg.startsWith('HS')) {\n const expected = await sign(alg, k, data);\n const actual = signature;\n try {\n return crypto.timingSafeEqual(actual, expected);\n }\n catch {\n return false;\n }\n }\n const algorithm = nodeDigest(alg);\n const keyInput = nodeKey(alg, k);\n try {\n return await oneShotVerify(algorithm, data, keyInput, signature);\n }\n catch {\n return false;\n }\n};\nexport default verify;\n", "import { JOSENotSupported } from '../util/errors.js';\nexport default function dsaDigest(alg) {\n switch (alg) {\n case 'PS256':\n case 'RS256':\n case 'ES256':\n case 'ES256K':\n return 'sha256';\n case 'PS384':\n case 'RS384':\n case 'ES384':\n return 'sha384';\n case 'PS512':\n case 'RS512':\n case 'ES512':\n return 'sha512';\n case 'Ed25519':\n case 'EdDSA':\n return undefined;\n default:\n throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`);\n }\n}\n", "import { constants, KeyObject } from 'node:crypto';\nimport getNamedCurve from './get_named_curve.js';\nimport { JOSENotSupported } from '../util/errors.js';\nimport checkKeyLength from './check_key_length.js';\nconst ecCurveAlgMap = new Map([\n ['ES256', 'P-256'],\n ['ES256K', 'secp256k1'],\n ['ES384', 'P-384'],\n ['ES512', 'P-521'],\n]);\nexport default function keyForCrypto(alg, key) {\n let asymmetricKeyType;\n let asymmetricKeyDetails;\n let isJWK;\n if (key instanceof KeyObject) {\n asymmetricKeyType = key.asymmetricKeyType;\n asymmetricKeyDetails = key.asymmetricKeyDetails;\n }\n else {\n isJWK = true;\n switch (key.kty) {\n case 'RSA':\n asymmetricKeyType = 'rsa';\n break;\n case 'EC':\n asymmetricKeyType = 'ec';\n break;\n case 'OKP': {\n if (key.crv === 'Ed25519') {\n asymmetricKeyType = 'ed25519';\n break;\n }\n if (key.crv === 'Ed448') {\n asymmetricKeyType = 'ed448';\n break;\n }\n throw new TypeError('Invalid key for this operation, its crv must be Ed25519 or Ed448');\n }\n default:\n throw new TypeError('Invalid key for this operation, its kty must be RSA, OKP, or EC');\n }\n }\n let options;\n switch (alg) {\n case 'Ed25519':\n if (asymmetricKeyType !== 'ed25519') {\n throw new TypeError(`Invalid key for this operation, its asymmetricKeyType must be ed25519`);\n }\n break;\n case 'EdDSA':\n if (!['ed25519', 'ed448'].includes(asymmetricKeyType)) {\n throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be ed25519 or ed448');\n }\n break;\n case 'RS256':\n case 'RS384':\n case 'RS512':\n if (asymmetricKeyType !== 'rsa') {\n throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be rsa');\n }\n checkKeyLength(key, alg);\n break;\n case 'PS256':\n case 'PS384':\n case 'PS512':\n if (asymmetricKeyType === 'rsa-pss') {\n const { hashAlgorithm, mgf1HashAlgorithm, saltLength } = asymmetricKeyDetails;\n const length = parseInt(alg.slice(-3), 10);\n if (hashAlgorithm !== undefined &&\n (hashAlgorithm !== `sha${length}` || mgf1HashAlgorithm !== hashAlgorithm)) {\n throw new TypeError(`Invalid key for this operation, its RSA-PSS parameters do not meet the requirements of \"alg\" ${alg}`);\n }\n if (saltLength !== undefined && saltLength > length >> 3) {\n throw new TypeError(`Invalid key for this operation, its RSA-PSS parameter saltLength does not meet the requirements of \"alg\" ${alg}`);\n }\n }\n else if (asymmetricKeyType !== 'rsa') {\n throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be rsa or rsa-pss');\n }\n checkKeyLength(key, alg);\n options = {\n padding: constants.RSA_PKCS1_PSS_PADDING,\n saltLength: constants.RSA_PSS_SALTLEN_DIGEST,\n };\n break;\n case 'ES256':\n case 'ES256K':\n case 'ES384':\n case 'ES512': {\n if (asymmetricKeyType !== 'ec') {\n throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be ec');\n }\n const actual = getNamedCurve(key);\n const expected = ecCurveAlgMap.get(alg);\n if (actual !== expected) {\n throw new TypeError(`Invalid key curve for the algorithm, its curve must be ${expected}, got ${actual}`);\n }\n options = { dsaEncoding: 'ieee-p1363' };\n break;\n }\n default:\n throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`);\n }\n if (isJWK) {\n return { format: 'jwk', key, ...options };\n }\n return options ? { ...options, key } : key;\n}\n", "import * as crypto from 'node:crypto';\nimport { promisify } from 'node:util';\nimport nodeDigest from './dsa_digest.js';\nimport hmacDigest from './hmac_digest.js';\nimport nodeKey from './node_key.js';\nimport getSignKey from './get_sign_verify_key.js';\nconst oneShotSign = promisify(crypto.sign);\nconst sign = async (alg, key, data) => {\n const k = getSignKey(alg, key, 'sign');\n if (alg.startsWith('HS')) {\n const hmac = crypto.createHmac(hmacDigest(alg), k);\n hmac.update(data);\n return hmac.digest();\n }\n return oneShotSign(nodeDigest(alg), data, nodeKey(alg, k));\n};\nexport default sign;\n", "import { JOSENotSupported } from '../util/errors.js';\nexport default function hmacDigest(alg) {\n switch (alg) {\n case 'HS256':\n return 'sha256';\n case 'HS384':\n return 'sha384';\n case 'HS512':\n return 'sha512';\n default:\n throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`);\n }\n}\n", "import { KeyObject, createSecretKey } from 'node:crypto';\nimport { isCryptoKey } from './webcrypto.js';\nimport { checkSigCryptoKey } from '../lib/crypto_key.js';\nimport invalidKeyInput from '../lib/invalid_key_input.js';\nimport { types } from './is_key_like.js';\nimport * as jwk from '../lib/is_jwk.js';\nexport default function getSignVerifyKey(alg, key, usage) {\n if (key instanceof Uint8Array) {\n if (!alg.startsWith('HS')) {\n throw new TypeError(invalidKeyInput(key, ...types));\n }\n return createSecretKey(key);\n }\n if (key instanceof KeyObject) {\n return key;\n }\n if (isCryptoKey(key)) {\n checkSigCryptoKey(key, alg, usage);\n return KeyObject.from(key);\n }\n if (jwk.isJWK(key)) {\n if (alg.startsWith('HS')) {\n return createSecretKey(Buffer.from(key.k, 'base64url'));\n }\n return key;\n }\n throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array', 'JSON Web Key'));\n}\n", "import { decode as base64url } from '../../runtime/base64url.js';\nimport verify from '../../runtime/verify.js';\nimport { JOSEAlgNotAllowed, JWSInvalid, JWSSignatureVerificationFailed } from '../../util/errors.js';\nimport { concat, encoder, decoder } from '../../lib/buffer_utils.js';\nimport isDisjoint from '../../lib/is_disjoint.js';\nimport isObject from '../../lib/is_object.js';\nimport { checkKeyTypeWithJwk } from '../../lib/check_key_type.js';\nimport validateCrit from '../../lib/validate_crit.js';\nimport validateAlgorithms from '../../lib/validate_algorithms.js';\nimport { isJWK } from '../../lib/is_jwk.js';\nimport { importJWK } from '../../key/import.js';\nexport async function flattenedVerify(jws, key, options) {\n if (!isObject(jws)) {\n throw new JWSInvalid('Flattened JWS must be an object');\n }\n if (jws.protected === undefined && jws.header === undefined) {\n throw new JWSInvalid('Flattened JWS must have either of the \"protected\" or \"header\" members');\n }\n if (jws.protected !== undefined && typeof jws.protected !== 'string') {\n throw new JWSInvalid('JWS Protected Header incorrect type');\n }\n if (jws.payload === undefined) {\n throw new JWSInvalid('JWS Payload missing');\n }\n if (typeof jws.signature !== 'string') {\n throw new JWSInvalid('JWS Signature missing or incorrect type');\n }\n if (jws.header !== undefined && !isObject(jws.header)) {\n throw new JWSInvalid('JWS Unprotected Header incorrect type');\n }\n let parsedProt = {};\n if (jws.protected) {\n try {\n const protectedHeader = base64url(jws.protected);\n parsedProt = JSON.parse(decoder.decode(protectedHeader));\n }\n catch {\n throw new JWSInvalid('JWS Protected Header is invalid');\n }\n }\n if (!isDisjoint(parsedProt, jws.header)) {\n throw new JWSInvalid('JWS Protected and JWS Unprotected Header Parameter names must be disjoint');\n }\n const joseHeader = {\n ...parsedProt,\n ...jws.header,\n };\n const extensions = validateCrit(JWSInvalid, new Map([['b64', true]]), options?.crit, parsedProt, joseHeader);\n let b64 = true;\n if (extensions.has('b64')) {\n b64 = parsedProt.b64;\n if (typeof b64 !== 'boolean') {\n throw new JWSInvalid('The \"b64\" (base64url-encode payload) Header Parameter must be a boolean');\n }\n }\n const { alg } = joseHeader;\n if (typeof alg !== 'string' || !alg) {\n throw new JWSInvalid('JWS \"alg\" (Algorithm) Header Parameter missing or invalid');\n }\n const algorithms = options && validateAlgorithms('algorithms', options.algorithms);\n if (algorithms && !algorithms.has(alg)) {\n throw new JOSEAlgNotAllowed('\"alg\" (Algorithm) Header Parameter value not allowed');\n }\n if (b64) {\n if (typeof jws.payload !== 'string') {\n throw new JWSInvalid('JWS Payload must be a string');\n }\n }\n else if (typeof jws.payload !== 'string' && !(jws.payload instanceof Uint8Array)) {\n throw new JWSInvalid('JWS Payload must be a string or an Uint8Array instance');\n }\n let resolvedKey = false;\n if (typeof key === 'function') {\n key = await key(parsedProt, jws);\n resolvedKey = true;\n checkKeyTypeWithJwk(alg, key, 'verify');\n if (isJWK(key)) {\n key = await importJWK(key, alg);\n }\n }\n else {\n checkKeyTypeWithJwk(alg, key, 'verify');\n }\n const data = concat(encoder.encode(jws.protected ?? ''), encoder.encode('.'), typeof jws.payload === 'string' ? encoder.encode(jws.payload) : jws.payload);\n let signature;\n try {\n signature = base64url(jws.signature);\n }\n catch {\n throw new JWSInvalid('Failed to base64url decode the signature');\n }\n const verified = await verify(alg, key, signature, data);\n if (!verified) {\n throw new JWSSignatureVerificationFailed();\n }\n let payload;\n if (b64) {\n try {\n payload = base64url(jws.payload);\n }\n catch {\n throw new JWSInvalid('Failed to base64url decode the payload');\n }\n }\n else if (typeof jws.payload === 'string') {\n payload = encoder.encode(jws.payload);\n }\n else {\n payload = jws.payload;\n }\n const result = { payload };\n if (jws.protected !== undefined) {\n result.protectedHeader = parsedProt;\n }\n if (jws.header !== undefined) {\n result.unprotectedHeader = jws.header;\n }\n if (resolvedKey) {\n return { ...result, key };\n }\n return result;\n}\n", "import { flattenedVerify } from '../flattened/verify.js';\nimport { JWSInvalid } from '../../util/errors.js';\nimport { decoder } from '../../lib/buffer_utils.js';\nexport async function compactVerify(jws, key, options) {\n if (jws instanceof Uint8Array) {\n jws = decoder.decode(jws);\n }\n if (typeof jws !== 'string') {\n throw new JWSInvalid('Compact JWS must be a string or Uint8Array');\n }\n const { 0: protectedHeader, 1: payload, 2: signature, length } = jws.split('.');\n if (length !== 3) {\n throw new JWSInvalid('Invalid Compact JWS');\n }\n const verified = await flattenedVerify({ payload, protected: protectedHeader, signature }, key, options);\n const result = { payload: verified.payload, protectedHeader: verified.protectedHeader };\n if (typeof key === 'function') {\n return { ...result, key: verified.key };\n }\n return result;\n}\n", "export default (date) => Math.floor(date.getTime() / 1000);\n", "const minute = 60;\nconst hour = minute * 60;\nconst day = hour * 24;\nconst week = day * 7;\nconst year = day * 365.25;\nconst REGEX = /^(\\+|\\-)? ?(\\d+|\\d+\\.\\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)(?: (ago|from now))?$/i;\nexport default (str) => {\n const matched = REGEX.exec(str);\n if (!matched || (matched[4] && matched[1])) {\n throw new TypeError('Invalid time period format');\n }\n const value = parseFloat(matched[2]);\n const unit = matched[3].toLowerCase();\n let numericDate;\n switch (unit) {\n case 'sec':\n case 'secs':\n case 'second':\n case 'seconds':\n case 's':\n numericDate = Math.round(value);\n break;\n case 'minute':\n case 'minutes':\n case 'min':\n case 'mins':\n case 'm':\n numericDate = Math.round(value * minute);\n break;\n case 'hour':\n case 'hours':\n case 'hr':\n case 'hrs':\n case 'h':\n numericDate = Math.round(value * hour);\n break;\n case 'day':\n case 'days':\n case 'd':\n numericDate = Math.round(value * day);\n break;\n case 'week':\n case 'weeks':\n case 'w':\n numericDate = Math.round(value * week);\n break;\n default:\n numericDate = Math.round(value * year);\n break;\n }\n if (matched[1] === '-' || matched[4] === 'ago') {\n return -numericDate;\n }\n return numericDate;\n};\n", "import { JWTClaimValidationFailed, JWTExpired, JWTInvalid } from '../util/errors.js';\nimport { decoder } from './buffer_utils.js';\nimport epoch from './epoch.js';\nimport secs from './secs.js';\nimport isObject from './is_object.js';\nconst normalizeTyp = (value) => value.toLowerCase().replace(/^application\\//, '');\nconst checkAudiencePresence = (audPayload, audOption) => {\n if (typeof audPayload === 'string') {\n return audOption.includes(audPayload);\n }\n if (Array.isArray(audPayload)) {\n return audOption.some(Set.prototype.has.bind(new Set(audPayload)));\n }\n return false;\n};\nexport default (protectedHeader, encodedPayload, options = {}) => {\n let payload;\n try {\n payload = JSON.parse(decoder.decode(encodedPayload));\n }\n catch {\n }\n if (!isObject(payload)) {\n throw new JWTInvalid('JWT Claims Set must be a top-level JSON object');\n }\n const { typ } = options;\n if (typ &&\n (typeof protectedHeader.typ !== 'string' ||\n normalizeTyp(protectedHeader.typ) !== normalizeTyp(typ))) {\n throw new JWTClaimValidationFailed('unexpected \"typ\" JWT header value', payload, 'typ', 'check_failed');\n }\n const { requiredClaims = [], issuer, subject, audience, maxTokenAge } = options;\n const presenceCheck = [...requiredClaims];\n if (maxTokenAge !== undefined)\n presenceCheck.push('iat');\n if (audience !== undefined)\n presenceCheck.push('aud');\n if (subject !== undefined)\n presenceCheck.push('sub');\n if (issuer !== undefined)\n presenceCheck.push('iss');\n for (const claim of new Set(presenceCheck.reverse())) {\n if (!(claim in payload)) {\n throw new JWTClaimValidationFailed(`missing required \"${claim}\" claim`, payload, claim, 'missing');\n }\n }\n if (issuer &&\n !(Array.isArray(issuer) ? issuer : [issuer]).includes(payload.iss)) {\n throw new JWTClaimValidationFailed('unexpected \"iss\" claim value', payload, 'iss', 'check_failed');\n }\n if (subject && payload.sub !== subject) {\n throw new JWTClaimValidationFailed('unexpected \"sub\" claim value', payload, 'sub', 'check_failed');\n }\n if (audience &&\n !checkAudiencePresence(payload.aud, typeof audience === 'string' ? [audience] : audience)) {\n throw new JWTClaimValidationFailed('unexpected \"aud\" claim value', payload, 'aud', 'check_failed');\n }\n let tolerance;\n switch (typeof options.clockTolerance) {\n case 'string':\n tolerance = secs(options.clockTolerance);\n break;\n case 'number':\n tolerance = options.clockTolerance;\n break;\n case 'undefined':\n tolerance = 0;\n break;\n default:\n throw new TypeError('Invalid clockTolerance option type');\n }\n const { currentDate } = options;\n const now = epoch(currentDate || new Date());\n if ((payload.iat !== undefined || maxTokenAge) && typeof payload.iat !== 'number') {\n throw new JWTClaimValidationFailed('\"iat\" claim must be a number', payload, 'iat', 'invalid');\n }\n if (payload.nbf !== undefined) {\n if (typeof payload.nbf !== 'number') {\n throw new JWTClaimValidationFailed('\"nbf\" claim must be a number', payload, 'nbf', 'invalid');\n }\n if (payload.nbf > now + tolerance) {\n throw new JWTClaimValidationFailed('\"nbf\" claim timestamp check failed', payload, 'nbf', 'check_failed');\n }\n }\n if (payload.exp !== undefined) {\n if (typeof payload.exp !== 'number') {\n throw new JWTClaimValidationFailed('\"exp\" claim must be a number', payload, 'exp', 'invalid');\n }\n if (payload.exp <= now - tolerance) {\n throw new JWTExpired('\"exp\" claim timestamp check failed', payload, 'exp', 'check_failed');\n }\n }\n if (maxTokenAge) {\n const age = now - payload.iat;\n const max = typeof maxTokenAge === 'number' ? maxTokenAge : secs(maxTokenAge);\n if (age - tolerance > max) {\n throw new JWTExpired('\"iat\" claim timestamp check failed (too far in the past)', payload, 'iat', 'check_failed');\n }\n if (age < 0 - tolerance) {\n throw new JWTClaimValidationFailed('\"iat\" claim timestamp check failed (it should be in the past)', payload, 'iat', 'check_failed');\n }\n }\n return payload;\n};\n", "import { compactVerify } from '../jws/compact/verify.js';\nimport jwtPayload from '../lib/jwt_claims_set.js';\nimport { JWTInvalid } from '../util/errors.js';\nexport async function jwtVerify(jwt, key, options) {\n const verified = await compactVerify(jwt, key, options);\n if (verified.protectedHeader.crit?.includes('b64') && verified.protectedHeader.b64 === false) {\n throw new JWTInvalid('JWTs MUST NOT use unencoded payload');\n }\n const payload = jwtPayload(verified.protectedHeader, verified.payload, options);\n const result = { payload, protectedHeader: verified.protectedHeader };\n if (typeof key === 'function') {\n return { ...result, key: verified.key };\n }\n return result;\n}\n", "import { importJWK } from '../key/import.js';\nimport { JWKSInvalid, JOSENotSupported, JWKSNoMatchingKey, JWKSMultipleMatchingKeys, } from '../util/errors.js';\nimport isObject from '../lib/is_object.js';\nfunction getKtyFromAlg(alg) {\n switch (typeof alg === 'string' && alg.slice(0, 2)) {\n case 'RS':\n case 'PS':\n return 'RSA';\n case 'ES':\n return 'EC';\n case 'Ed':\n return 'OKP';\n default:\n throw new JOSENotSupported('Unsupported \"alg\" value for a JSON Web Key Set');\n }\n}\nfunction isJWKSLike(jwks) {\n return (jwks &&\n typeof jwks === 'object' &&\n Array.isArray(jwks.keys) &&\n jwks.keys.every(isJWKLike));\n}\nfunction isJWKLike(key) {\n return isObject(key);\n}\nfunction clone(obj) {\n if (typeof structuredClone === 'function') {\n return structuredClone(obj);\n }\n return JSON.parse(JSON.stringify(obj));\n}\nclass LocalJWKSet {\n _jwks;\n _cached = new WeakMap();\n constructor(jwks) {\n if (!isJWKSLike(jwks)) {\n throw new JWKSInvalid('JSON Web Key Set malformed');\n }\n this._jwks = clone(jwks);\n }\n async getKey(protectedHeader, token) {\n const { alg, kid } = { ...protectedHeader, ...token?.header };\n const kty = getKtyFromAlg(alg);\n const candidates = this._jwks.keys.filter((jwk) => {\n let candidate = kty === jwk.kty;\n if (candidate && typeof kid === 'string') {\n candidate = kid === jwk.kid;\n }\n if (candidate && typeof jwk.alg === 'string') {\n candidate = alg === jwk.alg;\n }\n if (candidate && typeof jwk.use === 'string') {\n candidate = jwk.use === 'sig';\n }\n if (candidate && Array.isArray(jwk.key_ops)) {\n candidate = jwk.key_ops.includes('verify');\n }\n if (candidate) {\n switch (alg) {\n case 'ES256':\n candidate = jwk.crv === 'P-256';\n break;\n case 'ES256K':\n candidate = jwk.crv === 'secp256k1';\n break;\n case 'ES384':\n candidate = jwk.crv === 'P-384';\n break;\n case 'ES512':\n candidate = jwk.crv === 'P-521';\n break;\n case 'Ed25519':\n candidate = jwk.crv === 'Ed25519';\n break;\n case 'EdDSA':\n candidate = jwk.crv === 'Ed25519' || jwk.crv === 'Ed448';\n break;\n }\n }\n return candidate;\n });\n const { 0: jwk, length } = candidates;\n if (length === 0) {\n throw new JWKSNoMatchingKey();\n }\n if (length !== 1) {\n const error = new JWKSMultipleMatchingKeys();\n const { _cached } = this;\n error[Symbol.asyncIterator] = async function* () {\n for (const jwk of candidates) {\n try {\n yield await importWithAlgCache(_cached, jwk, alg);\n }\n catch { }\n }\n };\n throw error;\n }\n return importWithAlgCache(this._cached, jwk, alg);\n }\n}\nasync function importWithAlgCache(cache, jwk, alg) {\n const cached = cache.get(jwk) || cache.set(jwk, {}).get(jwk);\n if (cached[alg] === undefined) {\n const key = await importJWK({ ...jwk, ext: true }, alg);\n if (key instanceof Uint8Array || key.type !== 'public') {\n throw new JWKSInvalid('JSON Web Key Set members must be public keys');\n }\n cached[alg] = key;\n }\n return cached[alg];\n}\nexport function createLocalJWKSet(jwks) {\n const set = new LocalJWKSet(jwks);\n const localJWKSet = async (protectedHeader, token) => set.getKey(protectedHeader, token);\n Object.defineProperties(localJWKSet, {\n jwks: {\n value: () => clone(set._jwks),\n enumerable: true,\n configurable: false,\n writable: false,\n },\n });\n return localJWKSet;\n}\n", "import * as http from 'node:http';\nimport * as https from 'node:https';\nimport { once } from 'node:events';\nimport { JOSEError, JWKSTimeout } from '../util/errors.js';\nimport { concat, decoder } from '../lib/buffer_utils.js';\nconst fetchJwks = async (url, timeout, options) => {\n let get;\n switch (url.protocol) {\n case 'https:':\n get = https.get;\n break;\n case 'http:':\n get = http.get;\n break;\n default:\n throw new TypeError('Unsupported URL protocol.');\n }\n const { agent, headers } = options;\n const req = get(url.href, {\n agent,\n timeout,\n headers,\n });\n const [response] = (await Promise.race([once(req, 'response'), once(req, 'timeout')]));\n if (!response) {\n req.destroy();\n throw new JWKSTimeout();\n }\n if (response.statusCode !== 200) {\n throw new JOSEError('Expected 200 OK from the JSON Web Key Set HTTP response');\n }\n const parts = [];\n for await (const part of response) {\n parts.push(part);\n }\n try {\n return JSON.parse(decoder.decode(concat(...parts)));\n }\n catch {\n throw new JOSEError('Failed to parse the JSON Web Key Set HTTP response as JSON');\n }\n};\nexport default fetchJwks;\n", "import fetchJwks from '../runtime/fetch_jwks.js';\nimport { JWKSNoMatchingKey } from '../util/errors.js';\nimport { createLocalJWKSet } from './local.js';\nimport isObject from '../lib/is_object.js';\nfunction isCloudflareWorkers() {\n return (typeof WebSocketPair !== 'undefined' ||\n (typeof navigator !== 'undefined' && navigator.userAgent === 'Cloudflare-Workers') ||\n (typeof EdgeRuntime !== 'undefined' && EdgeRuntime === 'vercel'));\n}\nlet USER_AGENT;\nif (typeof navigator === 'undefined' || !navigator.userAgent?.startsWith?.('Mozilla/5.0 ')) {\n const NAME = 'jose';\n const VERSION = 'v5.10.0';\n USER_AGENT = `${NAME}/${VERSION}`;\n}\nexport const jwksCache = Symbol();\nfunction isFreshJwksCache(input, cacheMaxAge) {\n if (typeof input !== 'object' || input === null) {\n return false;\n }\n if (!('uat' in input) || typeof input.uat !== 'number' || Date.now() - input.uat >= cacheMaxAge) {\n return false;\n }\n if (!('jwks' in input) ||\n !isObject(input.jwks) ||\n !Array.isArray(input.jwks.keys) ||\n !Array.prototype.every.call(input.jwks.keys, isObject)) {\n return false;\n }\n return true;\n}\nclass RemoteJWKSet {\n _url;\n _timeoutDuration;\n _cooldownDuration;\n _cacheMaxAge;\n _jwksTimestamp;\n _pendingFetch;\n _options;\n _local;\n _cache;\n constructor(url, options) {\n if (!(url instanceof URL)) {\n throw new TypeError('url must be an instance of URL');\n }\n this._url = new URL(url.href);\n this._options = { agent: options?.agent, headers: options?.headers };\n this._timeoutDuration =\n typeof options?.timeoutDuration === 'number' ? options?.timeoutDuration : 5000;\n this._cooldownDuration =\n typeof options?.cooldownDuration === 'number' ? options?.cooldownDuration : 30000;\n this._cacheMaxAge = typeof options?.cacheMaxAge === 'number' ? options?.cacheMaxAge : 600000;\n if (options?.[jwksCache] !== undefined) {\n this._cache = options?.[jwksCache];\n if (isFreshJwksCache(options?.[jwksCache], this._cacheMaxAge)) {\n this._jwksTimestamp = this._cache.uat;\n this._local = createLocalJWKSet(this._cache.jwks);\n }\n }\n }\n coolingDown() {\n return typeof this._jwksTimestamp === 'number'\n ? Date.now() < this._jwksTimestamp + this._cooldownDuration\n : false;\n }\n fresh() {\n return typeof this._jwksTimestamp === 'number'\n ? Date.now() < this._jwksTimestamp + this._cacheMaxAge\n : false;\n }\n async getKey(protectedHeader, token) {\n if (!this._local || !this.fresh()) {\n await this.reload();\n }\n try {\n return await this._local(protectedHeader, token);\n }\n catch (err) {\n if (err instanceof JWKSNoMatchingKey) {\n if (this.coolingDown() === false) {\n await this.reload();\n return this._local(protectedHeader, token);\n }\n }\n throw err;\n }\n }\n async reload() {\n if (this._pendingFetch && isCloudflareWorkers()) {\n this._pendingFetch = undefined;\n }\n const headers = new Headers(this._options.headers);\n if (USER_AGENT && !headers.has('User-Agent')) {\n headers.set('User-Agent', USER_AGENT);\n this._options.headers = Object.fromEntries(headers.entries());\n }\n this._pendingFetch ||= fetchJwks(this._url, this._timeoutDuration, this._options)\n .then((json) => {\n this._local = createLocalJWKSet(json);\n if (this._cache) {\n this._cache.uat = Date.now();\n this._cache.jwks = json;\n }\n this._jwksTimestamp = Date.now();\n this._pendingFetch = undefined;\n })\n .catch((err) => {\n this._pendingFetch = undefined;\n throw err;\n });\n await this._pendingFetch;\n }\n}\nexport function createRemoteJWKSet(url, options) {\n const set = new RemoteJWKSet(url, options);\n const remoteJWKSet = async (protectedHeader, token) => set.getKey(protectedHeader, token);\n Object.defineProperties(remoteJWKSet, {\n coolingDown: {\n get: () => set.coolingDown(),\n enumerable: true,\n configurable: false,\n },\n fresh: {\n get: () => set.fresh(),\n enumerable: true,\n configurable: false,\n },\n reload: {\n value: () => set.reload(),\n enumerable: true,\n configurable: false,\n writable: false,\n },\n reloading: {\n get: () => !!set._pendingFetch,\n enumerable: true,\n configurable: false,\n },\n jwks: {\n value: () => set._local?.jwks(),\n enumerable: true,\n configurable: false,\n writable: false,\n },\n });\n return remoteJWKSet;\n}\nexport const experimental_jwksCache = jwksCache;\n", "/**\n * Bridge \u2014 lets CLI clients (Abby) list/mint LiteLLM virtual keys without ever\n * holding the LiteLLM master key.\n *\n * Trust model: the Backstage backend holds the master key (as it already does\n * for the UI). A CLI authenticates with its Keycloak access token (the same\n * Keycloak realm Backstage uses). This module verifies that JWT against the\n * realm JWKS, resolves the caller to a LiteLLM user_id, ensures that user\n * exists (provisioning from claims if enabled), and then lists/generates keys\n * via the existing master-key-authed {@link LiteLLMClient}.\n *\n * Unlike the UI endpoints in router.ts, the bridge routes do NOT call\n * Backstage's `auth.authenticate` (which expects a Backstage-issued token);\n * they verify the raw Keycloak JWT themselves.\n */\nimport { createRemoteJWKSet, jwtVerify, JWTPayload } from 'jose';\nimport { Config } from '@backstage/config';\nimport { LiteLLMClient } from './client';\nimport {\n GenerateKeyRequest,\n GenerateKeyResponse,\n ProvisioningDefaults,\n UserInfo,\n VirtualKey,\n} from './types';\nimport { ProvisioningError, provisionUser, toLiteLLMUserId } from './provisioning';\n\n/** Claims extracted from a verified Keycloak access token. */\nexport interface BridgeClaims {\n sub: string;\n email?: string;\n preferred_username?: string;\n name?: string;\n /** Authorized party \u2014 Keycloak sets this to the client_id of the requester. */\n azp?: string;\n aud?: string | string[];\n}\n\n/** A token verifier pluggable for tests. */\nexport interface TokenVerifier {\n verify(token: string): Promise<BridgeClaims>;\n}\n\nexport interface BridgeConfig {\n enabled: boolean;\n /** Keycloak realm issuer, e.g. https://auth.ces.abssrv.it/realms/solution-innovation. */\n issuer?: string;\n /** OIDC public client the CLI uses; checked against azp / aud. */\n clientId: string;\n}\n\nexport function readBridgeConfig(config: Config): BridgeConfig {\n const enabled =\n config.getOptionalBoolean('litellm.bridge.enabled') ?? false;\n const issuer = config.getOptionalString('litellm.bridge.issuer');\n const clientId =\n config.getOptionalString('litellm.bridge.clientId') ?? 'abby-cli';\n return { enabled, issuer, clientId };\n}\n\n/** Thrown when the bridge is misconfigured (e.g. enabled without an issuer). */\nexport class BridgeConfigError extends Error {}\n\n/** Thrown when a presented token fails verification \u2192 maps to HTTP 401. */\nexport class BridgeAuthError extends Error {\n readonly status = 401;\n}\n\nexport interface KeycloakJWTVerifierOptions {\n issuer: string;\n clientId: string;\n}\n\n/**\n * Verifies a Keycloak access token against the realm JWKS and ensures it was\n * issued for {@link clientId} (via azp, falling back to aud). Uses jose's\n * remote JWKS client (cached, with cooldown on errors).\n */\nexport class KeycloakJWTVerifier implements TokenVerifier {\n private readonly issuer: string;\n private readonly clientId: string;\n private readonly jwks: ReturnType<typeof createRemoteJWKSet>;\n\n constructor(opts: KeycloakJWTVerifierOptions) {\n this.issuer = opts.issuer.replace(/\\/$/, '');\n this.clientId = opts.clientId;\n this.jwks = createRemoteJWKSet(\n new URL(`${this.issuer}/protocol/openid-connect/certs`),\n );\n }\n\n async verify(token: string): Promise<BridgeClaims> {\n let payload: JWTPayload;\n try {\n const result = await jwtVerify(token, this.jwks, {\n issuer: this.issuer,\n });\n payload = result.payload;\n } catch (err) {\n // Expired, bad signature, wrong issuer, malformed, JWKS unreachable, etc.\n throw new BridgeAuthError(\n `invalid keycloak token: ${(err as Error).message ?? err}`,\n );\n }\n const azp = (payload as Record<string, unknown>).azp as\n | string\n | undefined;\n const aud = payload.aud;\n const audMatches = Array.isArray(aud)\n ? aud.includes(this.clientId)\n : aud === this.clientId;\n if (azp !== this.clientId && !audMatches) {\n throw new BridgeAuthError(\n `token not issued for client \"${this.clientId}\" (azp=${azp ?? 'none'})`,\n );\n }\n return {\n sub: payload.sub ?? '',\n email: payload.email as string | undefined,\n preferred_username: (payload as Record<string, unknown>)\n .preferred_username as string | undefined,\n name: payload.name as string | undefined,\n azp,\n aud,\n };\n }\n}\n\n/** Builds the default verifier from config, or throws BridgeConfigError. */\nexport function newDefaultVerifier(cfg: BridgeConfig): TokenVerifier {\n if (!cfg.issuer) {\n throw new BridgeConfigError(\n 'litellm.bridge.issuer is required when litellm.bridge.enabled is true ' +\n '(e.g. https://auth.ces.abssrv.it/realms/solution-innovation)',\n );\n }\n return new KeycloakJWTVerifier({ issuer: cfg.issuer, clientId: cfg.clientId });\n}\n\n/**\n * Resolves the LiteLLM user_id from the verified claims, matching exactly how\n * the UI derives it so the bridge addresses the *same* LiteLLM user (not a\n * duplicate). The UI uses toLiteLLMUserId(entityRef, userIdDomain) where the\n * Backstage entity name has been rewritten by the Keycloak user transformer:\n * because the catalog rejects '@' in entity names, usernames imported as full\n * emails are stored as their local-part. We replicate that here \u2014 strip the\n * '@domain' off the username, then apply the same userIdDomain rule.\n */\nexport function resolveBridgeUserId(\n claims: BridgeClaims,\n userIdDomain?: string,\n): string {\n const raw = claims.preferred_username ?? claims.email ?? claims.sub;\n const entityName = raw.includes('@') ? raw.split('@')[0] : raw;\n return toLiteLLMUserId(entityName, userIdDomain);\n}\n\n/**\n * Ensures a LiteLLM user exists for the verified identity. If the user is\n * missing and provisioning is enabled, creates it from the JWT claims (email +\n * name); if provisioning is disabled, throws a 404 telling the caller to log\n * in to Backstage first (the UI is the primary provisioning entry point).\n */\nexport async function getOrProvisionUserFromClaims(\n client: LiteLLMClient,\n claims: BridgeClaims,\n provisioningEnabled: boolean,\n provisioningDefaults: ProvisioningDefaults,\n logger: { info: (...args: unknown[]) => void },\n userIdDomain?: string,\n): Promise<UserInfo> {\n const userId = resolveBridgeUserId(claims, userIdDomain);\n const existing = await client.getUserInfo(userId);\n if (existing) return existing;\n\n if (!provisioningEnabled) {\n throw new ProvisioningError(\n 'User not found in LiteLLM',\n 'No LiteLLM user for this identity. Log in to Backstage once to be provisioned, or enable litellm.provisioning.enabled.',\n false,\n );\n }\n\n const profile = {\n email: claims.email ?? claims.preferred_username,\n displayName: claims.name ?? claims.preferred_username,\n };\n const created = await provisionUser(\n client,\n userId,\n provisioningDefaults,\n profile,\n undefined,\n logger,\n );\n if (!created) {\n throw new ProvisioningError(\n 'User not found in LiteLLM',\n 'Provisioning attempted but returned no user \u2014 check LiteLLM logs',\n true,\n 500,\n );\n }\n return created;\n}\n\n/** Lists the caller's virtual keys (provisioning the user first if needed). */\nexport async function bridgeListKeys(\n client: LiteLLMClient,\n claims: BridgeClaims,\n provisioningEnabled: boolean,\n provisioningDefaults: ProvisioningDefaults,\n logger: { info: (...args: unknown[]) => void },\n userIdDomain?: string,\n): Promise<VirtualKey[]> {\n await getOrProvisionUserFromClaims(\n client,\n claims,\n provisioningEnabled,\n provisioningDefaults,\n logger,\n userIdDomain,\n );\n return client.listKeys(resolveBridgeUserId(claims, userIdDomain));\n}\n\n/** Mints a new virtual key for the caller (provisioning the user first if needed). */\nexport async function bridgeGenerateKey(\n client: LiteLLMClient,\n claims: BridgeClaims,\n provisioningEnabled: boolean,\n provisioningDefaults: ProvisioningDefaults,\n logger: { info: (...args: unknown[]) => void },\n request: Partial<GenerateKeyRequest>,\n userIdDomain?: string,\n): Promise<GenerateKeyResponse> {\n await getOrProvisionUserFromClaims(\n client,\n claims,\n provisioningEnabled,\n provisioningDefaults,\n logger,\n userIdDomain,\n );\n const userId = resolveBridgeUserId(claims, userIdDomain);\n const enriched: GenerateKeyRequest = {\n ...request,\n user_id: userId,\n metadata: {\n ...(request.metadata ?? {}),\n created_via: 'abby-cli',\n created_by: userId,\n created_at_iso: new Date().toISOString(),\n },\n };\n return client.generateKey(enriched);\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["export { litellmPlugin } from './plugin';\nexport { litellmPlugin as default } from './plugin';\nexport { createRouter } from './router';\nexport * from './types';\nexport { LiteLLMClient } from './client';\nexport {\n resolveUserId,\n resolveUserProfile,\n toLiteLLMUserId,\n getOrProvisionUser,\n provisionUser,\n readProvisioningDefaults,\n readRoleConfigs,\n applyRoleOverrides,\n resolveUserRole,\n ProvisioningError,\n} from './provisioning';\nexport type { BackstageUserProfile } from './provisioning';\nexport {\n KeycloakJWTVerifier,\n newDefaultVerifier,\n readBridgeConfig,\n resolveBridgeUserId,\n getOrProvisionUserFromClaims,\n bridgeListKeys,\n bridgeGenerateKey,\n} from './bridge';\nexport type {\n BridgeClaims,\n TokenVerifier,\n BridgeConfig,\n KeycloakJWTVerifierOptions,\n} from './bridge';\n", "import { coreServices, createBackendPlugin } from '@backstage/backend-plugin-api';\nimport { createRouter } from './router';\nimport { readBridgeConfig } from './bridge';\n\nexport const litellmPlugin = createBackendPlugin({\n pluginId: 'litellm',\n register(reg) {\n reg.registerInit({\n deps: {\n httpRouter: coreServices.httpRouter,\n config: coreServices.rootConfig,\n logger: coreServices.logger,\n auth: coreServices.auth,\n discovery: coreServices.discovery,\n },\n async init({ httpRouter, config, logger, auth, discovery }) {\n const router = await createRouter({ config, logger, auth, discovery });\n httpRouter.use(router);\n\n // The CLI bridge verifies raw Keycloak JWTs itself (it does NOT use a\n // Backstage-issued token). Exempt its routes from the default auth\n // policy, otherwise the framework rejects the Keycloak Bearer with\n // \"Illegal token\" before the bridge verifier ever runs.\n if (readBridgeConfig(config).enabled) {\n for (const path of [\n '/bridge/health',\n '/bridge/keys',\n '/bridge/models',\n ]) {\n httpRouter.addAuthPolicy({ path, allow: 'unauthenticated' });\n }\n }\n },\n });\n },\n});\n", "import express, { Router, Request, Response } from 'express';\nimport { Config } from '@backstage/config';\nimport { AuthService, DiscoveryService } from '@backstage/backend-plugin-api';\nimport { CatalogClient } from '@backstage/catalog-client';\nimport { LiteLLMClient } from './client';\nimport { openApiSpec } from './openapi';\nimport {\n VirtualKey,\n ModelInfo,\n UsageMetrics,\n TeamInfo,\n GenerateKeyRequest,\n GenerateKeyResponse,\n UpdateKeyRequest,\n} from './types';\nimport {\n toLiteLLMUserId,\n resolveUserId,\n resolveUserProfile,\n getOrProvisionUser,\n readProvisioningDefaults,\n readRoleConfigs,\n applyRoleOverrides,\n isUserMemberOfGroup,\n ProvisioningError,\n} from './provisioning';\nimport {\n BridgeAuthError,\n BridgeClaims,\n TokenVerifier,\n bridgeGenerateKey,\n bridgeListKeys,\n newDefaultVerifier,\n readBridgeConfig,\n} from './bridge';\n\nexport { ProvisioningError };\n\nexport interface RouterOptions {\n config: Config;\n logger: any;\n auth: AuthService;\n discovery: DiscoveryService;\n /** Override the LiteLLM client (tests). Defaults to one built from config. */\n client?: LiteLLMClient;\n /** Override the bridge token verifier (tests). Defaults to a Keycloak JWKS verifier. */\n tokenVerifier?: TokenVerifier;\n}\n\nexport async function createRouter(options: RouterOptions): Promise<Router> {\n const { config, logger, auth, discovery } = options;\n\n const baseUrl = config.getString('litellm.baseUrl');\n const masterKey = config.getString('litellm.masterKey');\n const userIdDomain = config.getOptionalString('litellm.userIdDomain');\n // Publicly reachable LiteLLM proxy URL, used to build ready-to-paste\n // snippets in the frontend. Falls back to baseUrl (the internal URL the\n // backend calls) when the operator has not configured a public one.\n const publicBaseUrl = config.getOptionalString('litellm.publicBaseUrl') ?? baseUrl;\n const client = options.client ?? new LiteLLMClient({ baseUrl, masterKey });\n const { enabled: provisioningEnabled, defaults: provisioningDefaults } =\n readProvisioningDefaults(config);\n const roleConfigs = readRoleConfigs(config);\n const auditGroup = config.getOptionalString('litellm.audit.group');\n const allowUnlimitedBudget = config.getOptionalBoolean('litellm.keyGeneration.allowUnlimitedBudget') ?? false;\n const teamRequired = config.getOptionalBoolean('litellm.keyGeneration.teamRequired') ?? true;\n const catalogClient = new CatalogClient({ discoveryApi: discovery });\n\n if (provisioningEnabled) {\n logger.info(\n `LiteLLM auto-provisioning enabled \u2014 defaults: budget=$${\n provisioningDefaults.maxBudget\n }/${provisioningDefaults.budgetDuration}, models=${\n provisioningDefaults.models.length\n ? provisioningDefaults.models.join(',')\n : 'all'\n }, teams=[${provisioningDefaults.teams.join(',')}]`,\n );\n }\n\n const router = Router();\n // JSON body parser. Without this, every POST/PUT endpoint sees an empty\n // req.body. Backstage's httpRouter does not apply a body parser at the\n // plugin-router level, so each plugin must attach its own.\n router.use(express.json());\n\n router.get('/health', (_req: Request, res: Response) => {\n res.json({ status: 'ok', provisioning: provisioningEnabled });\n });\n\n // Exposes the public LiteLLM proxy URL so the frontend can build\n // ready-to-paste curl / OpenAI-SDK snippets for freshly generated keys.\n router.get('/config', (_req: Request, res: Response) => {\n res.json({\n baseUrl: publicBaseUrl,\n keyGeneration: { allowUnlimitedBudget, teamRequired },\n });\n });\n\n // Self-hosted OpenAPI 3.1 contract \u2014 lets integrators read a spec instead\n // of router.ts. No swagger-ui dependency; serve the JSON and point external\n // renderers (Stoplight, Swagger UI hosted elsewhere) at this endpoint.\n router.get('/openapi.json', (_req: Request, res: Response) => {\n res.json(openApiSpec);\n });\n\n // Provisioning dry-run: resolves which role a Backstage group maps to and\n // echoes the effective defaults, collapsing the config \u2192 deploy \u2192 test loop\n // into one request. Admin-gated by the audit group (same RBAC as /audit).\n router.get('/provisioning/preview', async (req: Request, res: Response) => {\n if (!auditGroup) {\n res.status(403).json({ error: 'Preview is not configured (litellm.audit.group not set)' });\n return;\n }\n const tokenEntityRef = await resolveUserId(req, auth);\n if (!tokenEntityRef) {\n res.status(401).json({ error: 'Authentication required' });\n return;\n }\n const allowed = await isUserMemberOfGroup(\n tokenEntityRef,\n auditGroup,\n catalogClient,\n auth,\n logger,\n );\n if (!allowed) {\n res.status(403).json({ error: 'Access denied: not a member of the audit group' });\n return;\n }\n const group = (req.query.group as string | undefined)?.trim();\n if (!group) {\n res.status(400).json({ error: 'group query parameter is required (e.g. group=group:default/ai-platform)' });\n return;\n }\n if (!roleConfigs.length) {\n res.json({\n group,\n matched_role: null,\n effective_defaults: provisioningDefaults,\n note: 'No litellm.provisioning.roles configured \u2014 every group receives the base defaults.',\n });\n return;\n }\n try {\n const matched = roleConfigs.find(rc => rc.group === group);\n const effective = matched\n ? applyRoleOverrides(provisioningDefaults, matched)\n : provisioningDefaults;\n res.json({\n group,\n matched_role: matched?.group ?? null,\n effective_defaults: effective,\n });\n } catch (error: any) {\n logger.error('Failed to resolve provisioning preview', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n router.get('/user/info', async (req: Request, res: Response) => {\n try {\n const tokenEntityRef = await resolveUserId(req, auth);\n const userId = tokenEntityRef\n ? toLiteLLMUserId(tokenEntityRef, userIdDomain)\n : (req.query.user_id as string | undefined);\n\n const userInfo = await getOrProvisionUser(\n client,\n tokenEntityRef,\n userId,\n provisioningEnabled,\n provisioningDefaults,\n roleConfigs,\n catalogClient,\n auth,\n logger,\n );\n const canViewAudit =\n auditGroup && tokenEntityRef\n ? await isUserMemberOfGroup(\n tokenEntityRef,\n auditGroup,\n catalogClient,\n auth,\n logger,\n )\n : false;\n res.json({ ...userInfo, can_view_audit: canViewAudit });\n } catch (error: any) {\n if (error instanceof ProvisioningError) {\n res.status(error.status).json(error.body);\n return;\n }\n logger.error('Failed to fetch user info', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n router.get('/keys', async (req: Request, res: Response) => {\n try {\n const tokenEntityRef = await resolveUserId(req, auth);\n const userId = tokenEntityRef\n ? toLiteLLMUserId(tokenEntityRef, userIdDomain)\n : (req.query.user_id as string | undefined);\n\n await getOrProvisionUser(\n client,\n tokenEntityRef,\n userId,\n provisioningEnabled,\n provisioningDefaults,\n roleConfigs,\n catalogClient,\n auth,\n logger,\n );\n\n const keys: VirtualKey[] = await client.listKeys(userId);\n res.json(keys);\n } catch (error: any) {\n if (error instanceof ProvisioningError) {\n res.status(error.status).json(error.body);\n return;\n }\n logger.error('Failed to list keys', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n // \u2500\u2500 Key ownership guard \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n //\n // Every key-mutation route below runs under the LiteLLM master key, so\n // without an explicit check any authenticated Backstage user could act on\n // any key whose token they learn (audit logs expose truncated tokens, and\n // anyone who has held the raw key knows it). We fetch the caller's own key\n // list and 403 if the target token isn't in it.\n //\n // Returns the caller's LiteLLM user_id (when resolvable) so handlers can\n // stamp it in logs without re-deriving it.\n async function authorizeKeyAction(\n req: Request,\n keyId: string,\n ): Promise<{ tokenEntityRef: string | undefined; userId: string | undefined }> {\n const tokenEntityRef = await resolveUserId(req, auth);\n const userId = tokenEntityRef\n ? toLiteLLMUserId(tokenEntityRef, userIdDomain)\n : (req.query.user_id as string | undefined);\n if (!userId) {\n throw { status: 403, body: { error: 'Cannot verify key ownership without an authenticated user' } };\n }\n const ownKeys = await client.listKeys(userId);\n const owns = ownKeys.some(k => (k.token ?? k.key) === keyId);\n if (!owns) {\n throw { status: 403, body: { error: 'Access denied: key does not belong to the caller' } };\n }\n return { tokenEntityRef, userId };\n }\n\n // Normalize the ownership-guard rejection shape into a response.\n function sendOwnershipError(err: any, res: Response): boolean {\n if (err && typeof err.status === 'number' && err.body) {\n res.status(err.status).json(err.body);\n return true;\n }\n return false;\n }\n\n router.post('/keys/generate', async (req: Request, res: Response) => {\n try {\n // Only alias is hard-required. max_budget is optional: a positive\n // number caps spend, while null/undefined means \"unlimited\" (LiteLLM\n // supports null). An empty models array is intentional \u2014 in LiteLLM\n // `models: []` means \"all models the user can access\" which is the\n // desired default. Forcing a selection up front is too restrictive for\n // the common case.\n const body = (req.body ?? {}) as GenerateKeyRequest;\n const missing: string[] = [];\n if (!body.alias?.trim()) missing.push('alias');\n if (\n body.max_budget !== null &&\n body.max_budget !== undefined &&\n (typeof body.max_budget !== 'number' || body.max_budget <= 0)\n ) {\n missing.push('max_budget (positive number, or null for unlimited)');\n }\n if (missing.length) {\n res.status(400).json({\n error: 'Missing required fields',\n hint: `Required: ${missing.join(', ')}`,\n });\n return;\n }\n\n const tokenEntityRef = await resolveUserId(req, auth);\n const resolvedUserId = tokenEntityRef\n ? toLiteLLMUserId(tokenEntityRef, userIdDomain)\n : undefined;\n\n if (resolvedUserId) {\n await getOrProvisionUser(\n client,\n tokenEntityRef,\n resolvedUserId,\n provisioningEnabled,\n provisioningDefaults,\n roleConfigs,\n catalogClient,\n auth,\n logger,\n );\n }\n\n // Stamp ownership into LiteLLM key metadata. LiteLLM's native\n // `created_by` column is only populated when the caller authenticates\n // via JWT/SSO; we always call with the master key, so that column\n // stays null. Enriching `metadata` makes the owner identity visible\n // in LiteLLM's UI and queryable via API.\n const profile = tokenEntityRef\n ? await resolveUserProfile(tokenEntityRef, catalogClient, auth, logger)\n : {};\n const enrichedMetadata = {\n ...(body.metadata ?? {}),\n created_by_backstage_user: tokenEntityRef ?? 'unknown',\n ...(profile.email && { created_by_email: profile.email }),\n ...(profile.displayName && {\n created_by_display_name: profile.displayName,\n }),\n created_via: 'backstage',\n created_at_iso: new Date().toISOString(),\n };\n\n const request: GenerateKeyRequest = {\n ...body,\n metadata: enrichedMetadata,\n ...(resolvedUserId && { user_id: resolvedUserId }),\n };\n const result: GenerateKeyResponse = await client.generateKey(request);\n logger.info({ action: 'key.generate', userId: resolvedUserId ?? 'unknown', keyAlias: body.alias });\n res.json(result);\n } catch (error: any) {\n if (error instanceof ProvisioningError) {\n res.status(error.status).json(error.body);\n return;\n }\n // LiteLLM's enterprise team-key hook silently overrides the requested\n // `duration` with the team's `metadata.team_member_key_duration` when a\n // team_id is set, before parsing it. A malformed value there 500s with\n // this exact message regardless of what we sent \u2014 surface that instead\n // of the opaque passthrough so it's actionable from the LiteLLM side.\n if (\n typeof error.message === 'string' &&\n error.message.includes('Invalid duration format') &&\n req.body?.team_id\n ) {\n res.status(502).json({\n error:\n 'LiteLLM rejected the key duration for this team. The team has a ' +\n '\"Team Member Key Duration\" set in LiteLLM that is not in a valid ' +\n '<number><unit> format (e.g. \"30d\") and overrides whatever duration ' +\n 'is requested. Fix or clear it in LiteLLM under Teams \u2192 this team \u2192 ' +\n 'Team Settings, then retry.',\n teamId: req.body.team_id,\n });\n return;\n }\n logger.error('Failed to generate key', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n router.post('/keys/:keyId/update', async (req: Request, res: Response) => {\n try {\n const { keyId } = req.params;\n if (!keyId) {\n res.status(400).json({ error: 'keyId is required' });\n return;\n }\n const { tokenEntityRef } = await authorizeKeyAction(req, keyId);\n const request: UpdateKeyRequest = { ...req.body, key: keyId };\n const result = await client.updateKey(request);\n logger.info({ action: 'key.update', userId: tokenEntityRef ?? 'unknown', keyId });\n res.json(result);\n } catch (error: any) {\n if (sendOwnershipError(error, res)) return;\n logger.error('Failed to update key', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n router.delete('/keys/:keyId', async (req: Request, res: Response) => {\n try {\n const { keyId } = req.params;\n if (!keyId) {\n res.status(400).json({ error: 'keyId is required' });\n return;\n }\n const { tokenEntityRef } = await authorizeKeyAction(req, keyId);\n await client.deleteKeys({ keys: [keyId] });\n logger.info({ action: 'key.delete', userId: tokenEntityRef ?? 'unknown', keyId });\n res.json({ success: true });\n } catch (error: any) {\n if (sendOwnershipError(error, res)) return;\n logger.error('Failed to delete key', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n router.post('/keys/:keyId/block', async (req: Request, res: Response) => {\n try {\n const { keyId } = req.params;\n const { tokenEntityRef } = await authorizeKeyAction(req, keyId);\n await client.blockKey(keyId);\n logger.info({ action: 'key.block', userId: tokenEntityRef ?? 'unknown', keyId });\n res.json({ success: true });\n } catch (error: any) {\n if (sendOwnershipError(error, res)) return;\n logger.error('Failed to block key', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n router.post('/keys/:keyId/unblock', async (req: Request, res: Response) => {\n try {\n const { keyId } = req.params;\n const { tokenEntityRef } = await authorizeKeyAction(req, keyId);\n await client.unblockKey(keyId);\n logger.info({ action: 'key.unblock', userId: tokenEntityRef ?? 'unknown', keyId });\n res.json({ success: true });\n } catch (error: any) {\n if (sendOwnershipError(error, res)) return;\n logger.error('Failed to unblock key', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n router.post('/keys/:keyId/reset_spend', async (req: Request, res: Response) => {\n try {\n const { keyId } = req.params;\n const { tokenEntityRef } = await authorizeKeyAction(req, keyId);\n await client.resetKeySpend(keyId);\n logger.info({ action: 'key.reset_spend', userId: tokenEntityRef ?? 'unknown', keyId });\n res.json({ success: true });\n } catch (error: any) {\n if (sendOwnershipError(error, res)) return;\n logger.error('Failed to reset key spend', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n router.get('/audit', async (req: Request, res: Response) => {\n if (!auditGroup) {\n res.status(403).json({ error: 'Audit log is not configured (litellm.audit.group not set)' });\n return;\n }\n const tokenEntityRef = await resolveUserId(req, auth);\n if (!tokenEntityRef) {\n res.status(401).json({ error: 'Authentication required' });\n return;\n }\n const allowed = await isUserMemberOfGroup(\n tokenEntityRef,\n auditGroup,\n catalogClient,\n auth,\n logger,\n );\n if (!allowed) {\n res.status(403).json({ error: 'Access denied: not a member of the audit group' });\n return;\n }\n try {\n const { page, page_size, start_date, end_date, action, table_name, changed_by } =\n req.query as Record<string, string | undefined>;\n const result = await client.getAuditLogs({\n page: page ? Number(page) : undefined,\n page_size: page_size ? Number(page_size) : 25,\n start_date,\n end_date,\n action,\n table_name,\n changed_by,\n });\n res.json(result);\n } catch (error: any) {\n logger.error('Failed to fetch audit logs', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n router.get('/models', async (_req: Request, res: Response) => {\n try {\n const models: ModelInfo[] = await client.listModels();\n res.json(models);\n } catch (error: any) {\n logger.error('Failed to list models', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n router.get('/teams', async (req: Request, res: Response) => {\n try {\n const tokenEntityRef = await resolveUserId(req, auth);\n const userId = tokenEntityRef\n ? toLiteLLMUserId(tokenEntityRef, userIdDomain)\n : (req.query.user_id as string | undefined);\n\n const userInfo = await getOrProvisionUser(\n client,\n tokenEntityRef,\n userId,\n provisioningEnabled,\n provisioningDefaults,\n roleConfigs,\n catalogClient,\n auth,\n logger,\n );\n\n if (!userInfo?.teams?.length) {\n res.json([]);\n return;\n }\n\n const teams = await Promise.all(\n userInfo.teams.map(teamId =>\n client.getTeamInfo(teamId).catch(err => {\n logger.warn(`Failed to fetch team ${teamId}: ${err.message}`);\n return null;\n }),\n ),\n );\n res.json(teams.filter(Boolean) as TeamInfo[]);\n } catch (error: any) {\n if (error instanceof ProvisioningError) {\n res.status(error.status).json(error.body);\n return;\n }\n logger.error('Failed to fetch teams', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n router.get('/teams/:teamId/usage', async (req: Request, res: Response) => {\n try {\n const { teamId } = req.params;\n const { start_date, end_date } = req.query;\n if (!start_date || !end_date) {\n res.status(400).json({ error: 'start_date and end_date are required' });\n return;\n }\n const usage: UsageMetrics = await client.getTeamUsage(\n teamId,\n start_date as string,\n end_date as string,\n );\n res.json(usage);\n } catch (error: any) {\n logger.error('Failed to fetch team usage', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n router.get('/usage', async (req: Request, res: Response) => {\n try {\n const { start_date, end_date } = req.query;\n if (!start_date || !end_date) {\n res.status(400).json({ error: 'start_date and end_date are required' });\n return;\n }\n const tokenEntityRef = await resolveUserId(req, auth);\n const userId = tokenEntityRef\n ? toLiteLLMUserId(tokenEntityRef, userIdDomain)\n : (req.query.user_id as string | undefined);\n\n if (userId) {\n await getOrProvisionUser(\n client,\n tokenEntityRef,\n userId,\n provisioningEnabled,\n provisioningDefaults,\n roleConfigs,\n catalogClient,\n auth,\n logger,\n );\n }\n\n const usage: UsageMetrics = await client.getUsage(\n start_date as string,\n end_date as string,\n userId,\n );\n res.json(usage);\n } catch (error: any) {\n if (error instanceof ProvisioningError) {\n res.status(error.status).json(error.body);\n return;\n }\n logger.error('Failed to fetch usage', error);\n res.status(500).json({ error: error.message });\n }\n });\n\n // ---------------------------------------------------------------------------\n // Bridge endpoints (CLI / Abby)\n //\n // Authenticated by a Keycloak access token (JWKS-verified), NOT by Backstage's\n // own auth. Lets CLI clients list/mint virtual keys without holding the master\n // key. Gated by litellm.bridge.enabled; the verifier needs litellm.bridge.issuer.\n const bridgeCfg = readBridgeConfig(config);\n let tokenVerifier: TokenVerifier | undefined = options.tokenVerifier;\n if (bridgeCfg.enabled && !tokenVerifier) {\n try {\n tokenVerifier = newDefaultVerifier(bridgeCfg);\n } catch (e) {\n logger.error(\n `LiteLLM bridge enabled but misconfigured: ${(e as Error).message}`,\n );\n }\n }\n\n if (bridgeCfg.enabled && tokenVerifier) {\n const requireClaims = async (req: Request): Promise<BridgeClaims> => {\n const header = req.headers.authorization ?? '';\n const token = header.startsWith('Bearer ') ? header.slice(7) : '';\n if (!token) throw new BridgeAuthError('missing Bearer token');\n return tokenVerifier!.verify(token);\n };\n\n const handleBridgeError = (error: any, res: Response) => {\n if (error instanceof BridgeAuthError) {\n res.status(401).json({ error: 'unauthorized', hint: error.message });\n return;\n }\n if (error instanceof ProvisioningError) {\n res.status(error.status).json(error.body);\n return;\n }\n logger.error('Bridge request failed', error);\n res.status(500).json({ error: error.message });\n };\n\n router.get('/bridge/health', (_req: Request, res: Response) => {\n res.json({ status: 'ok', bridge: true, clientId: bridgeCfg.clientId });\n });\n\n router.get('/bridge/keys', async (req: Request, res: Response) => {\n try {\n const claims = await requireClaims(req);\n const keys = await bridgeListKeys(\n client,\n claims,\n provisioningEnabled,\n provisioningDefaults,\n logger,\n userIdDomain,\n );\n res.json(keys);\n } catch (error: any) {\n handleBridgeError(error, res);\n }\n });\n\n router.post('/bridge/keys', async (req: Request, res: Response) => {\n try {\n const claims = await requireClaims(req);\n const result = await bridgeGenerateKey(\n client,\n claims,\n provisioningEnabled,\n provisioningDefaults,\n logger,\n (req.body ?? {}) as Partial<GenerateKeyRequest>,\n userIdDomain,\n );\n res.json(result);\n } catch (error: any) {\n handleBridgeError(error, res);\n }\n });\n\n router.get('/bridge/models', async (req: Request, res: Response) => {\n try {\n await requireClaims(req); // authenticate only\n const models = await client.listModels();\n res.json(models);\n } catch (error: any) {\n handleBridgeError(error, res);\n }\n });\n } else if (bridgeCfg.enabled) {\n logger.warn(\n 'litellm.bridge.enabled is true but no verifier could be built \u2014 bridge endpoints not mounted',\n );\n }\n\n return router;\n}\n", "import {\n LiteLLMConfig,\n UserInfo,\n VirtualKey,\n LiteLLMUserKey,\n ModelInfo,\n UsageMetrics,\n TeamInfo,\n GenerateKeyRequest,\n GenerateKeyResponse,\n UpdateKeyRequest,\n DeleteKeyRequest,\n CreateUserRequest,\n CreateUserResponse,\n AuditLogsParams,\n PaginatedAuditLogs,\n} from './types';\n\nconst DEFAULT_TIMEOUT = 30000;\n\nexport class LiteLLMClient {\n private baseUrl: string;\n private masterKey: string;\n private timeout: number;\n\n constructor(config: LiteLLMConfig, timeout = DEFAULT_TIMEOUT) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '');\n this.masterKey = config.masterKey;\n this.timeout = timeout;\n }\n\n private async request<T>(\n path: string,\n options: RequestInit = {},\n ): Promise<T> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n // Auth note: the LiteLLM OpenAPI spec declares the security scheme as an\n // `x-litellm-api-key` header, but Bearer + master key is the deliberate,\n // production-tested choice \u2014 LiteLLM's proxy accepts both, and Bearer is\n // what every observed deployment actually uses. Do not \"correct\" this to\n // match the spec literally without testing against a live gateway.\n const response = await fetch(`${this.baseUrl}${path}`, {\n ...options,\n signal: controller.signal,\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.masterKey}`,\n ...options.headers,\n },\n });\n\n if (!response.ok) {\n const errorBody = await response.text();\n const err = new Error(\n `LiteLLM API error: ${response.status} ${response.statusText} - ${errorBody}`,\n );\n (err as any).status = response.status;\n throw err;\n }\n\n return response.json();\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * Returns null when the user is not found in LiteLLM (404).\n * Throws on all other errors so callers know something went wrong.\n *\n * LiteLLM's `/user/info` wraps the user row inside `user_info` and returns\n * `teams` as an array of full team objects, not team_id strings. We flatten\n * `user_info` onto the top level and reduce `teams` to a string[] of ids so\n * the rest of the code can rely on the UserInfo contract.\n */\n async getUserInfo(userId?: string): Promise<UserInfo | null> {\n const query = userId ? `?user_id=${encodeURIComponent(userId)}` : '';\n try {\n const raw = await this.request<any>(`/user/info${query}`);\n const inner = raw?.user_info ?? {};\n const teamIds: string[] = Array.isArray(raw?.teams)\n ? raw.teams\n .map((t: any) => (typeof t === 'string' ? t : t?.team_id))\n .filter((t: unknown): t is string => typeof t === 'string')\n : [];\n return {\n user_id: raw?.user_id ?? inner.user_id ?? userId ?? '',\n user_email: inner.user_email ?? raw?.user_email,\n email: inner.email ?? raw?.email,\n teams: teamIds,\n models: inner.models ?? raw?.models,\n max_budget: inner.max_budget ?? raw?.max_budget,\n spend: inner.spend ?? raw?.spend,\n current_spend: inner.current_spend ?? raw?.current_spend,\n soft_limit: inner.soft_limit ?? raw?.soft_limit,\n hard_limit: inner.hard_limit ?? raw?.hard_limit,\n };\n } catch (err: any) {\n if (err.status === 404) return null;\n throw err;\n }\n }\n\n async createUser(payload: CreateUserRequest): Promise<CreateUserResponse> {\n return this.request<CreateUserResponse>('/user/new', {\n method: 'POST',\n body: JSON.stringify(payload),\n });\n }\n\n /**\n * Updates an existing LiteLLM user record. Used as a defensive follow-up\n * after /user/new because the upsert path of /user/new has been observed\n * to silently drop fields like user_role under concurrent inserts.\n */\n async updateUser(\n payload: Partial<CreateUserRequest> & { user_id: string },\n ): Promise<unknown> {\n return this.request<unknown>('/user/update', {\n method: 'POST',\n body: JSON.stringify(payload),\n });\n }\n\n /**\n * Returns the keys belonging to a user.\n *\n * Implementation note: LiteLLM's `/key/info` endpoint requires a `key`\n * hash and returns 404 when only `user_id` is passed. The correct way\n * to enumerate a user's keys is `/user/info?user_id=X`, which embeds\n * a `keys` array with per-key metadata. We unwrap that array and\n * normalise field names to match the frontend VirtualKey shape\n * (LiteLLM exposes `key_name` for the masked display value and\n * `expires` instead of `expires_at`).\n */\n async listKeys(userId?: string): Promise<VirtualKey[]> {\n if (!userId) return [];\n try {\n const response = await this.request<{ keys?: LiteLLMUserKey[] }>(\n `/user/info?user_id=${encodeURIComponent(userId)}`,\n );\n const rawKeys = response.keys ?? [];\n return rawKeys.map(this.toVirtualKey);\n } catch (err: any) {\n if (err.status === 404 || err.message.includes('not found')) {\n return [];\n }\n throw err;\n }\n }\n\n private toVirtualKey(k: LiteLLMUserKey): VirtualKey {\n return {\n key: k.key_name ?? k.token,\n token: k.token,\n key_alias: k.key_alias ?? undefined,\n created_at: k.created_at,\n expires_at: k.expires ?? undefined,\n spend: k.spend ?? 0,\n max_budget: k.max_budget ?? undefined,\n tpm_limit: k.tpm_limit ?? undefined,\n rpm_limit: k.rpm_limit ?? undefined,\n models: k.models ?? [],\n user_id: k.user_id ?? undefined,\n blocked: k.blocked ?? undefined,\n };\n }\n\n /**\n * Creates a new virtual key on the LiteLLM proxy.\n *\n * Implementation notes \u2014 both required to avoid silently-empty keys:\n * 1. The body must be the plain payload. An earlier version wrapped\n * it as `{ json: request }`; LiteLLM doesn't unwrap that envelope\n * and treats the request as having no fields, returning a key\n * with null alias / models / budget / limits.\n * 2. LiteLLM expects `key_alias`, not `alias`. Without the rename,\n * the alias the user typed is dropped on the floor.\n */\n async generateKey(request: GenerateKeyRequest): Promise<GenerateKeyResponse> {\n const { alias, ...rest } = request;\n const payload = {\n ...rest,\n ...(alias && { key_alias: alias }),\n };\n return this.request<GenerateKeyResponse>('/key/generate', {\n method: 'POST',\n body: JSON.stringify(payload),\n });\n }\n\n async updateKey(request: UpdateKeyRequest): Promise<VirtualKey> {\n return this.request<VirtualKey>('/key/update', {\n method: 'POST',\n body: JSON.stringify(request),\n });\n }\n\n async deleteKeys(request: DeleteKeyRequest): Promise<{ success: boolean }> {\n return this.request<{ success: boolean }>('/key/delete', {\n method: 'POST',\n body: JSON.stringify(request),\n });\n }\n\n async blockKey(key: string): Promise<unknown> {\n return this.request('/key/block', {\n method: 'POST',\n body: JSON.stringify({ key }),\n });\n }\n\n async unblockKey(key: string): Promise<unknown> {\n return this.request('/key/unblock', {\n method: 'POST',\n body: JSON.stringify({ key }),\n });\n }\n\n async resetKeySpend(key: string): Promise<unknown> {\n return this.request(`/key/${encodeURIComponent(key)}/reset_spend`, {\n method: 'POST',\n body: JSON.stringify({ reset_to: 0 }),\n });\n }\n\n async getAuditLogs(params: AuditLogsParams): Promise<PaginatedAuditLogs> {\n const query = new URLSearchParams();\n if (params.page !== undefined) query.set('page', String(params.page));\n if (params.page_size !== undefined) query.set('page_size', String(params.page_size));\n if (params.start_date) query.set('start_date', params.start_date);\n if (params.end_date) query.set('end_date', params.end_date);\n if (params.action) query.set('action', params.action);\n if (params.table_name) query.set('table_name', params.table_name);\n if (params.changed_by) query.set('changed_by', params.changed_by);\n if (params.sort_by) query.set('sort_by', params.sort_by);\n if (params.sort_order) query.set('sort_order', params.sort_order);\n return this.request<PaginatedAuditLogs>(`/audit?${query.toString()}`);\n }\n\n /**\n * Returns the proxy's model catalogue normalised to the ModelInfo shape.\n *\n * Prefers `/model/info` which exposes `model_name`, `mode`, capability flags\n * and per-token costs. Falls back to OpenAI-compatible `/models` (which only\n * returns `{id}`) so the dropdown still works on installs where `/model/info`\n * isn't reachable. Without this normalisation the UI saw blank labels and\n * a single \"other\" group because `/models` doesn't populate `model_name`\n * or `mode`.\n */\n async listModels(): Promise<ModelInfo[]> {\n try {\n const response = await this.request<{ data?: any[] }>('/model/info');\n const data = Array.isArray(response?.data) ? response.data : [];\n const normalised = data.map((m: any) => {\n const info = m.model_info ?? {};\n const params = m.litellm_params ?? {};\n return {\n model_name: m.model_name ?? params.model ?? info.id ?? '',\n mode: info.mode ?? m.mode ?? 'chat',\n supports_function_calling:\n info.supports_function_calling ?? m.supports_function_calling,\n supports_vision: info.supports_vision ?? m.supports_vision,\n input_cost_per_token:\n info.input_cost_per_token ?? params.input_cost_per_token,\n output_cost_per_token:\n info.output_cost_per_token ?? params.output_cost_per_token,\n max_input_tokens: info.max_input_tokens ?? m.max_input_tokens,\n max_output_tokens: info.max_output_tokens ?? m.max_output_tokens,\n } as ModelInfo;\n });\n const filtered = normalised.filter(m => m.model_name);\n if (filtered.length) return filtered;\n } catch {\n // fall through to /models\n }\n const fallback = await this.request<{ data?: any[] } | any[]>('/models');\n const data = Array.isArray(fallback)\n ? fallback\n : Array.isArray(fallback?.data)\n ? fallback!.data!\n : [];\n return data\n .map((m: any) => ({\n model_name: m.model_name ?? m.id ?? '',\n mode: m.mode ?? 'chat',\n supports_function_calling: m.supports_function_calling,\n supports_vision: m.supports_vision,\n }))\n .filter((m: ModelInfo) => m.model_name);\n }\n\n /**\n * LiteLLM's `/team/info` wraps the team row inside `team_info` (alongside\n * sibling `keys` / `team_memberships` arrays), the same shape as\n * `/user/info` wrapping the user row inside `user_info`. Without unwrapping,\n * `team_alias`, `members_with_roles`, `models`, budgets and limits are all\n * undefined, so the UI fell back to displaying the raw team_id / \"Untitled\n * team\".\n */\n async getTeamInfo(teamId: string): Promise<TeamInfo> {\n const raw = await this.request<any>(\n `/team/info?team_id=${encodeURIComponent(teamId)}`,\n );\n const inner = raw?.team_info ?? {};\n return {\n team_id: raw?.team_id ?? inner.team_id ?? teamId,\n team_alias: inner.team_alias ?? raw?.team_alias,\n max_budget: inner.max_budget ?? raw?.max_budget,\n spend: inner.spend ?? raw?.spend ?? 0,\n members_with_roles: inner.members_with_roles ?? raw?.members_with_roles,\n models: inner.models ?? raw?.models,\n tpm_limit: inner.tpm_limit ?? raw?.tpm_limit,\n rpm_limit: inner.rpm_limit ?? raw?.rpm_limit,\n };\n }\n\n private emptyUsage(): UsageMetrics {\n return {\n total_spend: 0,\n total_tokens: 0,\n prompt_tokens: 0,\n completion_tokens: 0,\n api_requests: 0,\n successful_requests: 0,\n failed_requests: 0,\n usage_by_model: {},\n usage_by_key: {},\n daily_usage: [],\n daily_by_model: [],\n };\n }\n\n /**\n * Transforms LiteLLM's SpendAnalyticsPaginatedResponse into the flatter\n * UsageMetrics shape consumed by the frontend charts.\n *\n * Source shape (per result row):\n * { date, metrics, breakdown: { models: { [name]: { metrics, api_key_breakdown: { [keyHash]: { metrics, metadata } } } } } }\n *\n * We fan that out into three views the UI consumes:\n * - daily_usage \u2192 spend + request trends over time\n * - usage_by_model \u2192 which models drove cost / traffic\n * - usage_by_key \u2192 which keys drove cost / traffic (with key_alias + team_id from metadata)\n */\n private transformDailyActivity(response: any): UsageMetrics {\n const results: any[] = Array.isArray(response?.results)\n ? response.results\n : [];\n const meta = response?.metadata ?? {};\n\n const daily_usage = results\n .map(r => ({\n date: r.date,\n spend: r.metrics?.spend ?? 0,\n total_tokens: r.metrics?.total_tokens ?? 0,\n prompt_tokens: r.metrics?.prompt_tokens ?? 0,\n completion_tokens: r.metrics?.completion_tokens ?? 0,\n api_requests: r.metrics?.api_requests ?? 0,\n successful_requests: r.metrics?.successful_requests ?? 0,\n failed_requests: r.metrics?.failed_requests ?? 0,\n }))\n .sort((a, b) => a.date.localeCompare(b.date));\n\n const usage_by_model: UsageMetrics['usage_by_model'] = {};\n const usage_by_key: UsageMetrics['usage_by_key'] = {};\n const daily_by_model: UsageMetrics['daily_by_model'] = [];\n\n const emptyModelBucket = () => ({\n total_spend: 0,\n total_tokens: 0,\n prompt_tokens: 0,\n completion_tokens: 0,\n api_requests: 0,\n successful_requests: 0,\n failed_requests: 0,\n });\n\n for (const r of results) {\n const models = r.breakdown?.models ?? {};\n for (const [name, entry] of Object.entries<any>(models)) {\n const m = entry?.metrics ?? {};\n const bucket = usage_by_model[name] ?? emptyModelBucket();\n bucket.total_spend += m.spend ?? 0;\n bucket.total_tokens += m.total_tokens ?? 0;\n bucket.prompt_tokens += m.prompt_tokens ?? 0;\n bucket.completion_tokens += m.completion_tokens ?? 0;\n bucket.api_requests += m.api_requests ?? 0;\n bucket.successful_requests += m.successful_requests ?? 0;\n bucket.failed_requests += m.failed_requests ?? 0;\n usage_by_model[name] = bucket;\n\n daily_by_model.push({\n date: r.date,\n model: name,\n spend: m.spend ?? 0,\n prompt_tokens: m.prompt_tokens ?? 0,\n completion_tokens: m.completion_tokens ?? 0,\n total_tokens: m.total_tokens ?? 0,\n api_requests: m.api_requests ?? 0,\n successful_requests: m.successful_requests ?? 0,\n failed_requests: m.failed_requests ?? 0,\n });\n\n const keyMap = entry?.api_key_breakdown ?? {};\n for (const [keyHash, keyEntry] of Object.entries<any>(keyMap)) {\n const km = keyEntry?.metrics ?? {};\n const kmeta = keyEntry?.metadata ?? {};\n const kb = usage_by_key[keyHash] ?? {\n key_alias: kmeta.key_alias,\n team_id: kmeta.team_id ?? null,\n models: [] as string[],\n ...emptyModelBucket(),\n };\n if (!kb.key_alias && kmeta.key_alias) kb.key_alias = kmeta.key_alias;\n if (kb.team_id == null && kmeta.team_id) kb.team_id = kmeta.team_id;\n if (!kb.models.includes(name)) kb.models.push(name);\n kb.total_spend += km.spend ?? 0;\n kb.total_tokens += km.total_tokens ?? 0;\n kb.prompt_tokens += km.prompt_tokens ?? 0;\n kb.completion_tokens += km.completion_tokens ?? 0;\n kb.api_requests += km.api_requests ?? 0;\n kb.successful_requests += km.successful_requests ?? 0;\n kb.failed_requests += km.failed_requests ?? 0;\n usage_by_key[keyHash] = kb;\n }\n }\n }\n\n return {\n total_spend: meta.total_spend ?? 0,\n total_tokens: meta.total_tokens ?? 0,\n prompt_tokens: meta.total_prompt_tokens ?? 0,\n completion_tokens: meta.total_completion_tokens ?? 0,\n api_requests: meta.total_api_requests ?? 0,\n successful_requests: meta.total_successful_requests ?? 0,\n failed_requests: meta.total_failed_requests ?? 0,\n usage_by_model,\n usage_by_key,\n daily_usage,\n daily_by_model,\n };\n }\n\n async getUsage(\n startDate: string,\n endDate: string,\n userId?: string,\n ): Promise<UsageMetrics> {\n const params = new URLSearchParams({\n start_date: startDate,\n end_date: endDate,\n page_size: '100',\n });\n if (userId) params.append('user_id', userId);\n try {\n const response = await this.request<any>(\n `/user/daily/activity?${params.toString()}`,\n );\n return this.transformDailyActivity(response);\n } catch (err: any) {\n if (err.status === 404 || err.message.includes('not found')) {\n return this.emptyUsage();\n }\n throw err;\n }\n }\n\n async getTeamUsage(\n teamId: string,\n startDate: string,\n endDate: string,\n ): Promise<UsageMetrics> {\n const params = new URLSearchParams({\n start_date: startDate,\n end_date: endDate,\n team_ids: teamId,\n page_size: '100',\n });\n try {\n const response = await this.request<any>(\n `/team/daily/activity?${params.toString()}`,\n );\n return this.transformDailyActivity(response);\n } catch (err: any) {\n if (err.status === 404 || err.message.includes('not found')) {\n return this.emptyUsage();\n }\n throw err;\n }\n }\n}\n", "// OpenAPI 3.1 contract for the plugin's own backend surface.\n//\n// Kept as a TypeScript object so the router can serve it at\n// GET /api/litellm/openapi.json without a YAML parser dependency, and so\n// a future tool can regenerate the README endpoint table from it.\n//\n// Conventions:\n// - Every UI route authenticates via a Backstage user bearer token\n// (Authorization: Bearer <backstage-token>). The bridge routes use a\n// raw Keycloak access token instead and are gated by\n// litellm.bridge.enabled.\n// - Key-mutation routes 403 when the target key does not belong to the\n// caller (ownership guard; see router.ts authorizeKeyAction).\n\nexport interface OpenApiSpec {\n openapi: string;\n info: { title: string; version: string; description: string };\n servers: { url: string; description: string }[];\n tags: { name: string; description: string }[];\n paths: Record<string, Record<string, any>>;\n components: { securitySchemes: Record<string, any> };\n}\n\nexport const openApiSpec: OpenApiSpec = {\n openapi: '3.1.0',\n info: {\n title: 'LiteLLM Governance Plugin API',\n version: '0.1.0',\n description:\n 'Backstage backend surface for the LiteLLM governance plugin. ' +\n 'UI routes authenticate via the Backstage identity system; CLI bridge ' +\n 'routes authenticate with a Keycloak access token.',\n },\n servers: [\n { url: '/api/litellm', description: 'Backstage backend plugin mount point' },\n ],\n tags: [\n { name: 'System', description: 'Health and configuration' },\n { name: 'User', description: 'Current user info and provisioning' },\n { name: 'Keys', description: 'Virtual key lifecycle' },\n { name: 'Models', description: 'Model catalogue' },\n { name: 'Teams', description: 'Team membership and usage' },\n { name: 'Usage', description: 'Spend and traffic analytics' },\n { name: 'Audit', description: 'Audit logs (RBAC-gated)' },\n { name: 'Provisioning', description: 'Provisioning dry-run (RBAC-gated)' },\n { name: 'Bridge', description: 'CLI bridge (Keycloak-token auth)' },\n ],\n paths: {\n '/health': {\n get: {\n tags: ['System'],\n summary: 'Health check',\n responses: {\n '200': {\n description: 'Plugin health',\n content: { 'application/json': { schema: { type: 'object', properties: {\n status: { type: 'string' },\n provisioning: { type: 'boolean' },\n } } } },\n },\n },\n },\n },\n '/config': {\n get: {\n tags: ['System'],\n summary: 'Public LiteLLM proxy base URL and key-generation form settings',\n responses: {\n '200': {\n description: 'Frontend config',\n content: { 'application/json': { schema: { type: 'object', properties: {\n baseUrl: { type: 'string' },\n keyGeneration: { type: 'object', properties: {\n allowUnlimitedBudget: { type: 'boolean' },\n teamRequired: { type: 'boolean' },\n } },\n } } } },\n },\n },\n },\n },\n '/openapi.json': {\n get: {\n tags: ['System'],\n summary: 'This OpenAPI document',\n responses: { '200': { description: 'OpenAPI 3.1 JSON' } },\n },\n },\n '/user/info': {\n get: {\n tags: ['User'],\n summary: \"Get the current user's info and quotas\",\n responses: {\n '200': { description: 'User info' },\n '404': { description: 'User not found in LiteLLM (provisioning disabled)' },\n },\n },\n },\n '/keys': {\n get: {\n tags: ['Keys'],\n summary: \"List the caller's virtual keys\",\n responses: { '200': { description: 'Array of keys' } },\n },\n },\n '/keys/generate': {\n post: {\n tags: ['Keys'],\n summary: 'Generate a new virtual key',\n requestBody: {\n required: true,\n content: { 'application/json': { schema: { type: 'object', properties: {\n alias: { type: 'string' },\n models: { type: 'array', items: { type: 'string' } },\n team_id: { type: 'string' },\n duration: { type: 'string' },\n max_budget: { type: 'number', nullable: true, description: 'Positive number caps spend; null = unlimited' },\n tpm_limit: { type: 'number' },\n rpm_limit: { type: 'number' },\n } } } },\n },\n responses: {\n '200': { description: 'Generated key (includes the raw secret \u2014 shown once)' },\n '400': { description: 'Missing required fields' },\n },\n },\n },\n '/keys/{keyId}': {\n delete: {\n tags: ['Keys'],\n summary: 'Revoke/delete a virtual key (caller must own it)',\n parameters: [{ name: 'keyId', in: 'path', required: true, schema: { type: 'string' } }],\n responses: { '200': { description: 'Deleted' }, '403': { description: 'Not the key owner' } },\n },\n },\n '/keys/{keyId}/update': {\n post: {\n tags: ['Keys'],\n summary: 'Update alias / models / budget / limits (caller must own it)',\n parameters: [{ name: 'keyId', in: 'path', required: true, schema: { type: 'string' } }],\n requestBody: { content: { 'application/json': { schema: { type: 'object' } } } },\n responses: { '200': { description: 'Updated' }, '403': { description: 'Not the key owner' } },\n },\n },\n '/keys/{keyId}/block': {\n post: {\n tags: ['Keys'],\n summary: 'Suspend a key without revoking (caller must own it)',\n parameters: [{ name: 'keyId', in: 'path', required: true, schema: { type: 'string' } }],\n responses: { '200': { description: 'Blocked' }, '403': { description: 'Not the key owner' } },\n },\n },\n '/keys/{keyId}/unblock': {\n post: {\n tags: ['Keys'],\n summary: 'Re-enable a blocked key (caller must own it)',\n parameters: [{ name: 'keyId', in: 'path', required: true, schema: { type: 'string' } }],\n responses: { '200': { description: 'Unblocked' }, '403': { description: 'Not the key owner' } },\n },\n },\n '/keys/{keyId}/reset_spend': {\n post: {\n tags: ['Keys'],\n summary: 'Zero out a key spend counter (caller must own it)',\n parameters: [{ name: 'keyId', in: 'path', required: true, schema: { type: 'string' } }],\n responses: { '200': { description: 'Spend reset' }, '403': { description: 'Not the key owner' } },\n },\n },\n '/models': {\n get: {\n tags: ['Models'],\n summary: 'List available LLM models',\n responses: { '200': { description: 'Model catalogue' } },\n },\n },\n '/teams': {\n get: {\n tags: ['Teams'],\n summary: 'List teams the current user belongs to',\n responses: { '200': { description: 'Array of teams' } },\n },\n },\n '/teams/{teamId}/usage': {\n get: {\n tags: ['Teams'],\n summary: 'Usage metrics for a team',\n parameters: [\n { name: 'teamId', in: 'path', required: true, schema: { type: 'string' } },\n { name: 'start_date', in: 'query', required: true, schema: { type: 'string' } },\n { name: 'end_date', in: 'query', required: true, schema: { type: 'string' } },\n ],\n responses: { '200': { description: 'Team usage' }, '400': { description: 'Missing date range' } },\n },\n },\n '/usage': {\n get: {\n tags: ['Usage'],\n summary: 'Usage metrics for the current user',\n parameters: [\n { name: 'start_date', in: 'query', required: true, schema: { type: 'string' } },\n { name: 'end_date', in: 'query', required: true, schema: { type: 'string' } },\n ],\n responses: { '200': { description: 'Usage metrics' }, '400': { description: 'Missing date range' } },\n },\n },\n '/audit': {\n get: {\n tags: ['Audit'],\n summary: 'Audit logs (gated by litellm.audit.group membership)',\n parameters: [\n { name: 'page', in: 'query', schema: { type: 'integer' } },\n { name: 'page_size', in: 'query', schema: { type: 'integer' } },\n { name: 'start_date', in: 'query', schema: { type: 'string' } },\n { name: 'end_date', in: 'query', schema: { type: 'string' } },\n { name: 'action', in: 'query', schema: { type: 'string' } },\n { name: 'table_name', in: 'query', schema: { type: 'string' } },\n { name: 'changed_by', in: 'query', schema: { type: 'string' } },\n ],\n responses: { '200': { description: 'Paginated audit logs' }, '403': { description: 'Not configured or not authorized' } },\n },\n },\n '/provisioning/preview': {\n get: {\n tags: ['Provisioning'],\n summary: 'Resolve which role a Backstage group maps to (dry-run)',\n parameters: [\n { name: 'group', in: 'query', required: true, schema: { type: 'string' }, description: 'e.g. group:default/ai-platform' },\n ],\n responses: {\n '200': { description: 'Resolved role and effective defaults' },\n '400': { description: 'Missing group parameter' },\n '403': { description: 'Not configured or not authorized' },\n },\n },\n },\n '/bridge/health': {\n get: {\n tags: ['Bridge'],\n summary: 'Bridge health + configured clientId (no auth)',\n responses: { '200': { description: 'Bridge health' } },\n },\n },\n '/bridge/keys': {\n get: {\n tags: ['Bridge'],\n summary: 'List the caller virtual keys (Keycloak token auth)',\n responses: { '200': { description: 'Array of keys' }, '401': { description: 'Invalid token' } },\n },\n post: {\n tags: ['Bridge'],\n summary: 'Mint a virtual key for the caller (Keycloak token auth)',\n requestBody: { content: { 'application/json': { schema: { type: 'object' } } } },\n responses: { '200': { description: 'Generated key' }, '401': { description: 'Invalid token' } },\n },\n },\n '/bridge/models': {\n get: {\n tags: ['Bridge'],\n summary: 'List available LLM models (Keycloak token auth)',\n responses: { '200': { description: 'Model catalogue' }, '401': { description: 'Invalid token' } },\n },\n },\n },\n components: {\n securitySchemes: {\n backstageUserToken: {\n type: 'http',\n scheme: 'bearer',\n description: 'Backstage-issued user token (Authorization: Bearer <token>).',\n },\n keycloakAccessToken: {\n type: 'http',\n scheme: 'bearer',\n description: 'Raw Keycloak access token. Bridge routes only; verified against the realm JWKS.',\n },\n },\n },\n};", "import { Config } from '@backstage/config';\nimport { AuthService } from '@backstage/backend-plugin-api';\nimport { CatalogClient } from '@backstage/catalog-client';\nimport { Request } from 'express';\nimport { LiteLLMClient } from './client';\nimport { UserInfo, ProvisioningDefaults, RoleConfig } from './types';\n\n/**\n * Converts a Backstage user entity ref to a LiteLLM user_id.\n *\n * When userIdDomain is configured, the entity name is suffixed with the domain\n * so that LiteLLM user_ids match the organisation's email addresses:\n * \"user:default/andrea.carmisciano\" + \"abstract.it\"\n * \u2192 \"andrea.carmisciano@abstract.it\"\n *\n * Without a domain the bare entity name is returned unchanged, which works for\n * deployments where LiteLLM users were created with plain usernames.\n */\nexport function toLiteLLMUserId(\n userEntityRef: string,\n userIdDomain?: string,\n): string {\n const name = userEntityRef.split('/').pop() ?? userEntityRef;\n // Defensive: if the entity name is already email-shaped (e.g. when the\n // Keycloak provider imports usernames as full emails without our\n // name-rewrite transformer running, or when a catalog change leaves\n // an entity ref like \"user:default/foo@bar.it\"), do NOT append the\n // userIdDomain \u2014 that produced \"foo@bar.it@bar.it\" in production.\n if (name.includes('@')) return name;\n return userIdDomain ? `${name}@${userIdDomain}` : name;\n}\n\n/**\n * Reads the provisioning block from config, applying safe defaults for every\n * field so the feature works out-of-the-box without any YAML required.\n *\n * Safe defaults rationale:\n * maxBudget: $10 \u2014 prevents runaway spend on a forgotten test account\n * budgetDuration: 30d \u2014 monthly reset, aligns with typical billing cycles\n * models: [] \u2014 empty means all proxy models are allowed;\n * restrict here or at team level for tighter control\n * teams: [] \u2014 no automatic team assignment; add IDs to enrol users\n * tpmLimit: none \u2014 LiteLLM global / team limits still apply\n * rpmLimit: none \u2014 same\n * metadata: backstage source tag only\n */\nexport function readRoleConfigs(config: Config): RoleConfig[] {\n const raw = config.getOptional<any[]>('litellm.provisioning.roles');\n if (!raw?.length) return [];\n return raw.map((r: any) => ({\n group: r.group as string,\n maxBudget: r.maxBudget,\n budgetDuration: r.budgetDuration,\n models: r.models,\n teams: r.teams,\n tpmLimit: r.tpmLimit,\n rpmLimit: r.rpmLimit,\n userRole: r.userRole,\n metadata: r.metadata,\n }));\n}\n\n/**\n * Merges role config over defaults. Role fields override defaults only when explicitly set.\n */\nexport function applyRoleOverrides(\n defaults: ProvisioningDefaults,\n role: RoleConfig,\n): ProvisioningDefaults {\n return {\n maxBudget: role.maxBudget ?? defaults.maxBudget,\n budgetDuration: role.budgetDuration ?? defaults.budgetDuration,\n models: role.models ?? defaults.models,\n teams: role.teams ?? defaults.teams,\n tpmLimit: role.tpmLimit ?? defaults.tpmLimit,\n rpmLimit: role.rpmLimit ?? defaults.rpmLimit,\n userRole: role.userRole ?? defaults.userRole,\n metadata: { ...defaults.metadata, ...(role.metadata ?? {}) },\n };\n}\n\nexport function readProvisioningDefaults(config: Config): {\n enabled: boolean;\n defaults: ProvisioningDefaults;\n} {\n const enabled =\n config.getOptionalBoolean('litellm.provisioning.enabled') ?? false;\n const defaults: ProvisioningDefaults = {\n maxBudget:\n config.getOptionalNumber('litellm.provisioning.defaults.maxBudget') ?? 10,\n budgetDuration:\n config.getOptionalString(\n 'litellm.provisioning.defaults.budgetDuration',\n ) ?? '30d',\n models:\n config.getOptionalStringArray('litellm.provisioning.defaults.models') ??\n [],\n teams:\n config.getOptionalStringArray('litellm.provisioning.defaults.teams') ??\n [],\n tpmLimit: config.getOptionalNumber(\n 'litellm.provisioning.defaults.tpmLimit',\n ),\n rpmLimit: config.getOptionalNumber(\n 'litellm.provisioning.defaults.rpmLimit',\n ),\n userRole:\n config.getOptionalString('litellm.provisioning.defaults.userRole') ??\n 'internal_user',\n metadata:\n config.getOptional<Record<string, string>>(\n 'litellm.provisioning.defaults.metadata',\n ) ?? {},\n };\n return { enabled, defaults };\n}\n\n/**\n * Extracts the authenticated Backstage user identity from the request token.\n * Returns the userEntityRef (e.g. \"user:default/john.doe\") or undefined when\n * the request carries no user credential (service-to-service calls).\n */\nexport async function resolveUserId(\n req: Request,\n auth: AuthService,\n): Promise<string | undefined> {\n const rawToken = req.headers.authorization?.slice(7);\n if (!rawToken) return undefined;\n try {\n const credentials = await auth.authenticate(rawToken);\n const principal = credentials.principal as any;\n if (principal?.type === 'user') {\n return principal.userEntityRef as string;\n }\n } catch {\n // invalid or service token \u2014 caller gets query-param fallback\n }\n return undefined;\n}\n\n/**\n * Profile data extracted from a Backstage Catalog User entity, used to\n * populate user_email / user_alias on the LiteLLM record.\n */\nexport interface BackstageUserProfile {\n email?: string;\n displayName?: string;\n}\n\n/**\n * Looks up the catalog User entity for the authenticated user and returns\n * the profile block. Returns an empty object when the user has no catalog\n * entity (e.g. dangerouslyAllowSignInWithoutUserInCatalog was used) \u2014 the\n * caller falls back to deriving identity from userIdDomain.\n */\nexport async function resolveUserProfile(\n userEntityRef: string,\n catalogClient: CatalogClient,\n auth: AuthService,\n logger: any,\n): Promise<BackstageUserProfile> {\n try {\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: await auth.getOwnServiceCredentials(),\n targetPluginId: 'catalog',\n });\n const entity = await catalogClient.getEntityByRef(userEntityRef, { token });\n const profile = (entity?.spec as any)?.profile ?? {};\n return {\n email: profile.email,\n displayName: profile.displayName,\n };\n } catch (err: any) {\n logger.warn(\n `Could not fetch catalog profile for ${userEntityRef}: ${err.message}`,\n );\n return {};\n }\n}\n\n/**\n * Creates a LiteLLM user for the given Backstage identity using the configured\n * defaults. Returns the UserInfo of the newly created account.\n */\nexport async function provisionUser(\n client: LiteLLMClient,\n userId: string,\n defaults: ProvisioningDefaults,\n profile: BackstageUserProfile,\n backstageEntity: string | undefined,\n logger: any,\n): Promise<UserInfo | null> {\n const payload = {\n user_id: userId,\n ...(profile.email && { user_email: profile.email }),\n ...(profile.displayName && { user_alias: profile.displayName }),\n max_budget: defaults.maxBudget,\n budget_duration: defaults.budgetDuration,\n models: defaults.models,\n teams: defaults.teams,\n ...(defaults.tpmLimit !== undefined && { tpm_limit: defaults.tpmLimit }),\n ...(defaults.rpmLimit !== undefined && { rpm_limit: defaults.rpmLimit }),\n ...(defaults.userRole && { user_role: defaults.userRole }),\n auto_create_key: false,\n metadata: {\n ...defaults.metadata,\n provisioned_by: 'backstage',\n provisioned_at: new Date().toISOString(),\n backstage_entity: backstageEntity ?? userId,\n ...(profile.email && { backstage_email: profile.email }),\n ...(profile.displayName && {\n backstage_display_name: profile.displayName,\n }),\n },\n };\n\n logger.info(\n `Provisioning new LiteLLM user for Backstage identity: ${userId}` +\n (profile.email ? ` (email=${profile.email})` : ''),\n );\n try {\n await client.createUser(payload);\n // Defensive /user/update: LiteLLM's /user/new upsert path has been\n // observed to drop user_role under concurrent inserts (the first\n // call sets the field, a racing second call upserts and clears it).\n // Re-asserting the role-bearing fields immediately after creation\n // is cheap and makes the role guarantee robust.\n if (defaults.userRole) {\n try {\n await client.updateUser({\n user_id: userId,\n user_role: defaults.userRole,\n ...(profile.email && { user_email: profile.email }),\n ...(profile.displayName && { user_alias: profile.displayName }),\n });\n } catch (updateErr: any) {\n logger.warn(\n `Defensive /user/update after provisioning ${userId} failed: ${updateErr.message}`,\n );\n }\n }\n // Fetch the freshly-created user record to return consistent UserInfo shape\n return await client.getUserInfo(userId);\n } catch (err: any) {\n logger.error(`Failed to provision LiteLLM user ${userId}: ${err.message}`);\n throw err;\n }\n}\n\n/**\n * Module-scope single-flight cache keyed by LiteLLM user_id. Coalesces\n * concurrent provisioning attempts for the same user so /user/new fires\n * at most once per user across parallel requests. Without this, an\n * authenticated page load that fires /keys, /teams and /usage in\n * parallel triggers three concurrent /user/new calls; LiteLLM's\n * upsert path then creates one default key per call (so the user lands\n * with 3 unexpected keys) and may silently lose user_role.\n *\n * Cache entries are removed once the promise settles, so subsequent\n * requests for a re-deleted user can still trigger fresh provisioning.\n */\nconst provisioningInFlight = new Map<string, Promise<UserInfo>>();\n\n/**\n * Strips any echoed Authorization bearer token from upstream LiteLLM error\n * messages before they're shipped back to the browser. LiteLLM normally does\n * not echo the master key, but defense in depth: never let a `Bearer \u2026`\n * substring travel out in a response body.\n */\nfunction sanitizeUpstreamMessage(message: string): string {\n if (!message) return 'unknown error';\n return message\n .replace(/Bearer\\s+[A-Za-z0-9._\\-+/=]+/g, 'Bearer [redacted]')\n .replace(/sk-[A-Za-z0-9_\\-]{8,}/g, 'sk-[redacted]')\n .slice(0, 500);\n}\n\nexport class ProvisioningError extends Error {\n status: number;\n body: { error: string; hint: string; provisioning: boolean };\n\n constructor(\n message: string,\n hint: string,\n provisioning: boolean,\n status = 404,\n ) {\n super(message);\n this.status = status;\n this.body = { error: message, hint, provisioning };\n }\n}\n\n/**\n * Ensures the LiteLLM user exists, returning its UserInfo.\n * When the user is missing and provisioning is enabled, attempts to create it.\n * When provisioning is disabled, throws a ProvisioningError with a clear message.\n */\nexport async function getOrProvisionUser(\n client: LiteLLMClient,\n tokenEntityRef: string | undefined,\n userId: string | undefined,\n provisioningEnabled: boolean,\n provisioningDefaults: ProvisioningDefaults,\n roleConfigs: RoleConfig[],\n catalogClient: CatalogClient,\n auth: AuthService,\n logger: any,\n): Promise<UserInfo> {\n if (!userId) {\n throw new ProvisioningError(\n 'User not found in LiteLLM',\n 'No user identity could be resolved from the request.',\n provisioningEnabled,\n );\n }\n\n const existing = await client.getUserInfo(userId);\n if (existing) {\n return existing;\n }\n\n if (!provisioningEnabled) {\n throw new ProvisioningError(\n 'User not found in LiteLLM',\n 'Enable litellm.provisioning.enabled in app-config.yaml or create the user manually',\n false,\n );\n }\n\n // Single-flight: if another request for the same userId is already\n // provisioning, await its result instead of starting a new /user/new.\n // This collapses the /keys + /teams + /usage page-load thundering\n // herd into a single LiteLLM round-trip.\n const pending = provisioningInFlight.get(userId);\n if (pending) {\n logger.info(\n `LiteLLM provisioning already in flight for ${userId} \u2014 joining`,\n );\n return pending;\n }\n\n const provisionPromise = (async () => {\n const catalogRef = tokenEntityRef ?? userId;\n const [matchedRole, profile] = await Promise.all([\n resolveUserRole(catalogRef, roleConfigs, catalogClient, auth, logger),\n tokenEntityRef\n ? resolveUserProfile(tokenEntityRef, catalogClient, auth, logger)\n : Promise.resolve<BackstageUserProfile>({}),\n ]);\n const effectiveDefaults = matchedRole\n ? applyRoleOverrides(provisioningDefaults, matchedRole)\n : provisioningDefaults;\n if (matchedRole) {\n logger.info(\n `User ${userId} matched role group ${matchedRole.group} \u2014 using role-specific provisioning`,\n );\n }\n try {\n const created = await provisionUser(\n client,\n userId,\n effectiveDefaults,\n profile,\n tokenEntityRef,\n logger,\n );\n if (!created) {\n throw new ProvisioningError(\n 'User not found in LiteLLM',\n 'Provisioning attempted but returned no user \u2014 check LiteLLM logs',\n true,\n );\n }\n return created;\n } catch (err: any) {\n // The single-flight cache should prevent the parallel-409 race,\n // but keep the recovery path: if /user/new still 409s (e.g.\n // multi-replica deploys where the lock is per-process), treat\n // it as \"user exists\" and re-fetch.\n if (err.status === 409 || /already exists/i.test(err.message ?? '')) {\n logger.info(\n `LiteLLM user ${userId} already exists during provisioning \u2014 re-fetching`,\n );\n const refetched = await client.getUserInfo(userId);\n if (refetched) {\n return refetched;\n }\n }\n if (err instanceof ProvisioningError) {\n throw err;\n }\n // Map upstream LiteLLM status to a Backstage-safe gateway status.\n // 401/403/5xx from LiteLLM mean the gateway (this plugin) cannot\n // talk to LiteLLM \u2014 they MUST NOT propagate as 401/403 to the\n // browser, otherwise Backstage's fetch middleware treats the\n // user's Backstage session as expired and forces a re-login.\n // Only safe client-semantic codes pass through.\n const upstreamStatus = err.status;\n const passThrough = [400, 404, 409, 422].includes(upstreamStatus)\n ? upstreamStatus\n : 502;\n throw new ProvisioningError(\n 'LiteLLM auto-provisioning failed',\n `LiteLLM upstream ${\n upstreamStatus ?? 'error'\n }: ${sanitizeUpstreamMessage(err.message)}`,\n true,\n passThrough,\n );\n }\n })();\n\n provisioningInFlight.set(userId, provisionPromise);\n try {\n return await provisionPromise;\n } finally {\n provisioningInFlight.delete(userId);\n }\n}\n\n/**\n * Returns true when the user is a member of the given Backstage group entity ref.\n * Used for RBAC gates (e.g. audit log visibility) without the role-config machinery.\n */\nexport async function isUserMemberOfGroup(\n userEntityRef: string,\n group: string,\n catalogClient: CatalogClient,\n auth: AuthService,\n logger: any,\n): Promise<boolean> {\n try {\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: await auth.getOwnServiceCredentials(),\n targetPluginId: 'catalog',\n });\n const entity = await catalogClient.getEntityByRef(userEntityRef, { token });\n const groups = (entity?.relations ?? [])\n .filter(r => r.type === 'memberOf')\n .map(r => r.targetRef);\n return groups.includes(group);\n } catch (err: any) {\n logger.warn(`Could not check group membership for ${userEntityRef}: ${err.message}`);\n return false;\n }\n}\n\n/**\n * Fetches the user's Backstage group memberships and returns the first matching\n * role config (priority order), or undefined when no role matches.\n */\nexport async function resolveUserRole(\n userEntityRef: string,\n roleConfigs: RoleConfig[],\n catalogClient: CatalogClient,\n auth: AuthService,\n logger: any,\n): Promise<RoleConfig | undefined> {\n if (!roleConfigs.length) return undefined;\n try {\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: await auth.getOwnServiceCredentials(),\n targetPluginId: 'catalog',\n });\n const entity = await catalogClient.getEntityByRef(userEntityRef, { token });\n const groups = (entity?.relations ?? [])\n .filter(r => r.type === 'memberOf')\n .map(r => r.targetRef);\n return roleConfigs.find(rc => groups.includes(rc.group));\n } catch (err: any) {\n logger.warn(\n `Could not resolve Backstage groups for ${userEntityRef}: ${err.message}`,\n );\n return undefined;\n }\n}\n", "import { Buffer } from 'node:buffer';\nimport { decoder } from '../lib/buffer_utils.js';\nfunction normalize(input) {\n let encoded = input;\n if (encoded instanceof Uint8Array) {\n encoded = decoder.decode(encoded);\n }\n return encoded;\n}\nconst encode = (input) => Buffer.from(input).toString('base64url');\nexport const decodeBase64 = (input) => new Uint8Array(Buffer.from(input, 'base64'));\nexport const encodeBase64 = (input) => Buffer.from(input).toString('base64');\nexport { encode };\nexport const decode = (input) => new Uint8Array(Buffer.from(normalize(input), 'base64url'));\n", "import digest from '../runtime/digest.js';\nexport const encoder = new TextEncoder();\nexport const decoder = new TextDecoder();\nconst MAX_INT32 = 2 ** 32;\nexport function concat(...buffers) {\n const size = buffers.reduce((acc, { length }) => acc + length, 0);\n const buf = new Uint8Array(size);\n let i = 0;\n for (const buffer of buffers) {\n buf.set(buffer, i);\n i += buffer.length;\n }\n return buf;\n}\nexport function p2s(alg, p2sInput) {\n return concat(encoder.encode(alg), new Uint8Array([0]), p2sInput);\n}\nfunction writeUInt32BE(buf, value, offset) {\n if (value < 0 || value >= MAX_INT32) {\n throw new RangeError(`value must be >= 0 and <= ${MAX_INT32 - 1}. Received ${value}`);\n }\n buf.set([value >>> 24, value >>> 16, value >>> 8, value & 0xff], offset);\n}\nexport function uint64be(value) {\n const high = Math.floor(value / MAX_INT32);\n const low = value % MAX_INT32;\n const buf = new Uint8Array(8);\n writeUInt32BE(buf, high, 0);\n writeUInt32BE(buf, low, 4);\n return buf;\n}\nexport function uint32be(value) {\n const buf = new Uint8Array(4);\n writeUInt32BE(buf, value);\n return buf;\n}\nexport function lengthAndInput(input) {\n return concat(uint32be(input.length), input);\n}\nexport async function concatKdf(secret, bits, value) {\n const iterations = Math.ceil((bits >> 3) / 32);\n const res = new Uint8Array(iterations * 32);\n for (let iter = 0; iter < iterations; iter++) {\n const buf = new Uint8Array(4 + secret.length + value.length);\n buf.set(uint32be(iter + 1));\n buf.set(secret, 4);\n buf.set(value, 4 + secret.length);\n res.set(await digest('sha256', buf), iter * 32);\n }\n return res.slice(0, bits >> 3);\n}\n", "export class JOSEError extends Error {\n static code = 'ERR_JOSE_GENERIC';\n code = 'ERR_JOSE_GENERIC';\n constructor(message, options) {\n super(message, options);\n this.name = this.constructor.name;\n Error.captureStackTrace?.(this, this.constructor);\n }\n}\nexport class JWTClaimValidationFailed extends JOSEError {\n static code = 'ERR_JWT_CLAIM_VALIDATION_FAILED';\n code = 'ERR_JWT_CLAIM_VALIDATION_FAILED';\n claim;\n reason;\n payload;\n constructor(message, payload, claim = 'unspecified', reason = 'unspecified') {\n super(message, { cause: { claim, reason, payload } });\n this.claim = claim;\n this.reason = reason;\n this.payload = payload;\n }\n}\nexport class JWTExpired extends JOSEError {\n static code = 'ERR_JWT_EXPIRED';\n code = 'ERR_JWT_EXPIRED';\n claim;\n reason;\n payload;\n constructor(message, payload, claim = 'unspecified', reason = 'unspecified') {\n super(message, { cause: { claim, reason, payload } });\n this.claim = claim;\n this.reason = reason;\n this.payload = payload;\n }\n}\nexport class JOSEAlgNotAllowed extends JOSEError {\n static code = 'ERR_JOSE_ALG_NOT_ALLOWED';\n code = 'ERR_JOSE_ALG_NOT_ALLOWED';\n}\nexport class JOSENotSupported extends JOSEError {\n static code = 'ERR_JOSE_NOT_SUPPORTED';\n code = 'ERR_JOSE_NOT_SUPPORTED';\n}\nexport class JWEDecryptionFailed extends JOSEError {\n static code = 'ERR_JWE_DECRYPTION_FAILED';\n code = 'ERR_JWE_DECRYPTION_FAILED';\n constructor(message = 'decryption operation failed', options) {\n super(message, options);\n }\n}\nexport class JWEInvalid extends JOSEError {\n static code = 'ERR_JWE_INVALID';\n code = 'ERR_JWE_INVALID';\n}\nexport class JWSInvalid extends JOSEError {\n static code = 'ERR_JWS_INVALID';\n code = 'ERR_JWS_INVALID';\n}\nexport class JWTInvalid extends JOSEError {\n static code = 'ERR_JWT_INVALID';\n code = 'ERR_JWT_INVALID';\n}\nexport class JWKInvalid extends JOSEError {\n static code = 'ERR_JWK_INVALID';\n code = 'ERR_JWK_INVALID';\n}\nexport class JWKSInvalid extends JOSEError {\n static code = 'ERR_JWKS_INVALID';\n code = 'ERR_JWKS_INVALID';\n}\nexport class JWKSNoMatchingKey extends JOSEError {\n static code = 'ERR_JWKS_NO_MATCHING_KEY';\n code = 'ERR_JWKS_NO_MATCHING_KEY';\n constructor(message = 'no applicable key found in the JSON Web Key Set', options) {\n super(message, options);\n }\n}\nexport class JWKSMultipleMatchingKeys extends JOSEError {\n [Symbol.asyncIterator];\n static code = 'ERR_JWKS_MULTIPLE_MATCHING_KEYS';\n code = 'ERR_JWKS_MULTIPLE_MATCHING_KEYS';\n constructor(message = 'multiple matching keys found in the JSON Web Key Set', options) {\n super(message, options);\n }\n}\nexport class JWKSTimeout extends JOSEError {\n static code = 'ERR_JWKS_TIMEOUT';\n code = 'ERR_JWKS_TIMEOUT';\n constructor(message = 'request timed out', options) {\n super(message, options);\n }\n}\nexport class JWSSignatureVerificationFailed extends JOSEError {\n static code = 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED';\n code = 'ERR_JWS_SIGNATURE_VERIFICATION_FAILED';\n constructor(message = 'signature verification failed', options) {\n super(message, options);\n }\n}\n", "import * as util from 'node:util';\nexport default (obj) => util.types.isKeyObject(obj);\n", "import * as crypto from 'node:crypto';\nimport * as util from 'node:util';\nconst webcrypto = crypto.webcrypto;\nexport default webcrypto;\nexport const isCryptoKey = (key) => util.types.isCryptoKey(key);\n", "function unusable(name, prop = 'algorithm.name') {\n return new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`);\n}\nfunction isAlgorithm(algorithm, name) {\n return algorithm.name === name;\n}\nfunction getHashLength(hash) {\n return parseInt(hash.name.slice(4), 10);\n}\nfunction getNamedCurve(alg) {\n switch (alg) {\n case 'ES256':\n return 'P-256';\n case 'ES384':\n return 'P-384';\n case 'ES512':\n return 'P-521';\n default:\n throw new Error('unreachable');\n }\n}\nfunction checkUsage(key, usages) {\n if (usages.length && !usages.some((expected) => key.usages.includes(expected))) {\n let msg = 'CryptoKey does not support this operation, its usages must include ';\n if (usages.length > 2) {\n const last = usages.pop();\n msg += `one of ${usages.join(', ')}, or ${last}.`;\n }\n else if (usages.length === 2) {\n msg += `one of ${usages[0]} or ${usages[1]}.`;\n }\n else {\n msg += `${usages[0]}.`;\n }\n throw new TypeError(msg);\n }\n}\nexport function checkSigCryptoKey(key, alg, ...usages) {\n switch (alg) {\n case 'HS256':\n case 'HS384':\n case 'HS512': {\n if (!isAlgorithm(key.algorithm, 'HMAC'))\n throw unusable('HMAC');\n const expected = parseInt(alg.slice(2), 10);\n const actual = getHashLength(key.algorithm.hash);\n if (actual !== expected)\n throw unusable(`SHA-${expected}`, 'algorithm.hash');\n break;\n }\n case 'RS256':\n case 'RS384':\n case 'RS512': {\n if (!isAlgorithm(key.algorithm, 'RSASSA-PKCS1-v1_5'))\n throw unusable('RSASSA-PKCS1-v1_5');\n const expected = parseInt(alg.slice(2), 10);\n const actual = getHashLength(key.algorithm.hash);\n if (actual !== expected)\n throw unusable(`SHA-${expected}`, 'algorithm.hash');\n break;\n }\n case 'PS256':\n case 'PS384':\n case 'PS512': {\n if (!isAlgorithm(key.algorithm, 'RSA-PSS'))\n throw unusable('RSA-PSS');\n const expected = parseInt(alg.slice(2), 10);\n const actual = getHashLength(key.algorithm.hash);\n if (actual !== expected)\n throw unusable(`SHA-${expected}`, 'algorithm.hash');\n break;\n }\n case 'EdDSA': {\n if (key.algorithm.name !== 'Ed25519' && key.algorithm.name !== 'Ed448') {\n throw unusable('Ed25519 or Ed448');\n }\n break;\n }\n case 'Ed25519': {\n if (!isAlgorithm(key.algorithm, 'Ed25519'))\n throw unusable('Ed25519');\n break;\n }\n case 'ES256':\n case 'ES384':\n case 'ES512': {\n if (!isAlgorithm(key.algorithm, 'ECDSA'))\n throw unusable('ECDSA');\n const expected = getNamedCurve(alg);\n const actual = key.algorithm.namedCurve;\n if (actual !== expected)\n throw unusable(expected, 'algorithm.namedCurve');\n break;\n }\n default:\n throw new TypeError('CryptoKey does not support this operation');\n }\n checkUsage(key, usages);\n}\nexport function checkEncCryptoKey(key, alg, ...usages) {\n switch (alg) {\n case 'A128GCM':\n case 'A192GCM':\n case 'A256GCM': {\n if (!isAlgorithm(key.algorithm, 'AES-GCM'))\n throw unusable('AES-GCM');\n const expected = parseInt(alg.slice(1, 4), 10);\n const actual = key.algorithm.length;\n if (actual !== expected)\n throw unusable(expected, 'algorithm.length');\n break;\n }\n case 'A128KW':\n case 'A192KW':\n case 'A256KW': {\n if (!isAlgorithm(key.algorithm, 'AES-KW'))\n throw unusable('AES-KW');\n const expected = parseInt(alg.slice(1, 4), 10);\n const actual = key.algorithm.length;\n if (actual !== expected)\n throw unusable(expected, 'algorithm.length');\n break;\n }\n case 'ECDH': {\n switch (key.algorithm.name) {\n case 'ECDH':\n case 'X25519':\n case 'X448':\n break;\n default:\n throw unusable('ECDH, X25519, or X448');\n }\n break;\n }\n case 'PBES2-HS256+A128KW':\n case 'PBES2-HS384+A192KW':\n case 'PBES2-HS512+A256KW':\n if (!isAlgorithm(key.algorithm, 'PBKDF2'))\n throw unusable('PBKDF2');\n break;\n case 'RSA-OAEP':\n case 'RSA-OAEP-256':\n case 'RSA-OAEP-384':\n case 'RSA-OAEP-512': {\n if (!isAlgorithm(key.algorithm, 'RSA-OAEP'))\n throw unusable('RSA-OAEP');\n const expected = parseInt(alg.slice(9), 10) || 1;\n const actual = getHashLength(key.algorithm.hash);\n if (actual !== expected)\n throw unusable(`SHA-${expected}`, 'algorithm.hash');\n break;\n }\n default:\n throw new TypeError('CryptoKey does not support this operation');\n }\n checkUsage(key, usages);\n}\n", "function message(msg, actual, ...types) {\n types = types.filter(Boolean);\n if (types.length > 2) {\n const last = types.pop();\n msg += `one of type ${types.join(', ')}, or ${last}.`;\n }\n else if (types.length === 2) {\n msg += `one of type ${types[0]} or ${types[1]}.`;\n }\n else {\n msg += `of type ${types[0]}.`;\n }\n if (actual == null) {\n msg += ` Received ${actual}`;\n }\n else if (typeof actual === 'function' && actual.name) {\n msg += ` Received function ${actual.name}`;\n }\n else if (typeof actual === 'object' && actual != null) {\n if (actual.constructor?.name) {\n msg += ` Received an instance of ${actual.constructor.name}`;\n }\n }\n return msg;\n}\nexport default (actual, ...types) => {\n return message('Key must be ', actual, ...types);\n};\nexport function withAlg(alg, actual, ...types) {\n return message(`Key for the ${alg} algorithm must be `, actual, ...types);\n}\n", "import webcrypto, { isCryptoKey } from './webcrypto.js';\nimport isKeyObject from './is_key_object.js';\nexport default (key) => isKeyObject(key) || isCryptoKey(key);\nconst types = ['KeyObject'];\nif (globalThis.CryptoKey || webcrypto?.CryptoKey) {\n types.push('CryptoKey');\n}\nexport { types };\n", "const isDisjoint = (...headers) => {\n const sources = headers.filter(Boolean);\n if (sources.length === 0 || sources.length === 1) {\n return true;\n }\n let acc;\n for (const header of sources) {\n const parameters = Object.keys(header);\n if (!acc || acc.size === 0) {\n acc = new Set(parameters);\n continue;\n }\n for (const parameter of parameters) {\n if (acc.has(parameter)) {\n return false;\n }\n acc.add(parameter);\n }\n }\n return true;\n};\nexport default isDisjoint;\n", "function isObjectLike(value) {\n return typeof value === 'object' && value !== null;\n}\nexport default function isObject(input) {\n if (!isObjectLike(input) || Object.prototype.toString.call(input) !== '[object Object]') {\n return false;\n }\n if (Object.getPrototypeOf(input) === null) {\n return true;\n }\n let proto = input;\n while (Object.getPrototypeOf(proto) !== null) {\n proto = Object.getPrototypeOf(proto);\n }\n return Object.getPrototypeOf(input) === proto;\n}\n", "import { KeyObject } from 'node:crypto';\nimport { JOSENotSupported } from '../util/errors.js';\nimport { isCryptoKey } from './webcrypto.js';\nimport isKeyObject from './is_key_object.js';\nimport invalidKeyInput from '../lib/invalid_key_input.js';\nimport { types } from './is_key_like.js';\nimport { isJWK } from '../lib/is_jwk.js';\nexport const weakMap = new WeakMap();\nconst namedCurveToJOSE = (namedCurve) => {\n switch (namedCurve) {\n case 'prime256v1':\n return 'P-256';\n case 'secp384r1':\n return 'P-384';\n case 'secp521r1':\n return 'P-521';\n case 'secp256k1':\n return 'secp256k1';\n default:\n throw new JOSENotSupported('Unsupported key curve for this operation');\n }\n};\nconst getNamedCurve = (kee, raw) => {\n let key;\n if (isCryptoKey(kee)) {\n key = KeyObject.from(kee);\n }\n else if (isKeyObject(kee)) {\n key = kee;\n }\n else if (isJWK(kee)) {\n return kee.crv;\n }\n else {\n throw new TypeError(invalidKeyInput(kee, ...types));\n }\n if (key.type === 'secret') {\n throw new TypeError('only \"private\" or \"public\" type keys can be used for this operation');\n }\n switch (key.asymmetricKeyType) {\n case 'ed25519':\n case 'ed448':\n return `Ed${key.asymmetricKeyType.slice(2)}`;\n case 'x25519':\n case 'x448':\n return `X${key.asymmetricKeyType.slice(1)}`;\n case 'ec': {\n const namedCurve = key.asymmetricKeyDetails.namedCurve;\n if (raw) {\n return namedCurve;\n }\n return namedCurveToJOSE(namedCurve);\n }\n default:\n throw new TypeError('Invalid asymmetric key type for this operation');\n }\n};\nexport default getNamedCurve;\n", "import isObject from './is_object.js';\nexport function isJWK(key) {\n return isObject(key) && typeof key.kty === 'string';\n}\nexport function isPrivateJWK(key) {\n return key.kty !== 'oct' && typeof key.d === 'string';\n}\nexport function isPublicJWK(key) {\n return key.kty !== 'oct' && typeof key.d === 'undefined';\n}\nexport function isSecretJWK(key) {\n return isJWK(key) && key.kty === 'oct' && typeof key.k === 'string';\n}\n", "import { KeyObject } from 'node:crypto';\nexport default (key, alg) => {\n let modulusLength;\n try {\n if (key instanceof KeyObject) {\n modulusLength = key.asymmetricKeyDetails?.modulusLength;\n }\n else {\n modulusLength = Buffer.from(key.n, 'base64url').byteLength << 3;\n }\n }\n catch { }\n if (typeof modulusLength !== 'number' || modulusLength < 2048) {\n throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`);\n }\n};\n", "import { createPrivateKey, createPublicKey } from 'node:crypto';\nconst parse = (key) => {\n if (key.d) {\n return createPrivateKey({ format: 'jwk', key });\n }\n return createPublicKey({ format: 'jwk', key });\n};\nexport default parse;\n", "import { decode as decodeBase64URL } from '../runtime/base64url.js';\nimport { fromSPKI, fromPKCS8, fromX509 } from '../runtime/asn1.js';\nimport asKeyObject from '../runtime/jwk_to_key.js';\nimport { JOSENotSupported } from '../util/errors.js';\nimport isObject from '../lib/is_object.js';\nexport async function importSPKI(spki, alg, options) {\n if (typeof spki !== 'string' || spki.indexOf('-----BEGIN PUBLIC KEY-----') !== 0) {\n throw new TypeError('\"spki\" must be SPKI formatted string');\n }\n return fromSPKI(spki, alg, options);\n}\nexport async function importX509(x509, alg, options) {\n if (typeof x509 !== 'string' || x509.indexOf('-----BEGIN CERTIFICATE-----') !== 0) {\n throw new TypeError('\"x509\" must be X.509 formatted string');\n }\n return fromX509(x509, alg, options);\n}\nexport async function importPKCS8(pkcs8, alg, options) {\n if (typeof pkcs8 !== 'string' || pkcs8.indexOf('-----BEGIN PRIVATE KEY-----') !== 0) {\n throw new TypeError('\"pkcs8\" must be PKCS#8 formatted string');\n }\n return fromPKCS8(pkcs8, alg, options);\n}\nexport async function importJWK(jwk, alg) {\n if (!isObject(jwk)) {\n throw new TypeError('JWK must be an object');\n }\n alg ||= jwk.alg;\n switch (jwk.kty) {\n case 'oct':\n if (typeof jwk.k !== 'string' || !jwk.k) {\n throw new TypeError('missing \"k\" (Key Value) Parameter value');\n }\n return decodeBase64URL(jwk.k);\n case 'RSA':\n if ('oth' in jwk && jwk.oth !== undefined) {\n throw new JOSENotSupported('RSA JWK \"oth\" (Other Primes Info) Parameter value is not supported');\n }\n case 'EC':\n case 'OKP':\n return asKeyObject({ ...jwk, alg });\n default:\n throw new JOSENotSupported('Unsupported \"kty\" (Key Type) Parameter value');\n }\n}\n", "import { withAlg as invalidKeyInput } from './invalid_key_input.js';\nimport isKeyLike, { types } from '../runtime/is_key_like.js';\nimport * as jwk from './is_jwk.js';\nconst tag = (key) => key?.[Symbol.toStringTag];\nconst jwkMatchesOp = (alg, key, usage) => {\n if (key.use !== undefined && key.use !== 'sig') {\n throw new TypeError('Invalid key for this operation, when present its use must be sig');\n }\n if (key.key_ops !== undefined && key.key_ops.includes?.(usage) !== true) {\n throw new TypeError(`Invalid key for this operation, when present its key_ops must include ${usage}`);\n }\n if (key.alg !== undefined && key.alg !== alg) {\n throw new TypeError(`Invalid key for this operation, when present its alg must be ${alg}`);\n }\n return true;\n};\nconst symmetricTypeCheck = (alg, key, usage, allowJwk) => {\n if (key instanceof Uint8Array)\n return;\n if (allowJwk && jwk.isJWK(key)) {\n if (jwk.isSecretJWK(key) && jwkMatchesOp(alg, key, usage))\n return;\n throw new TypeError(`JSON Web Key for symmetric algorithms must have JWK \"kty\" (Key Type) equal to \"oct\" and the JWK \"k\" (Key Value) present`);\n }\n if (!isKeyLike(key)) {\n throw new TypeError(invalidKeyInput(alg, key, ...types, 'Uint8Array', allowJwk ? 'JSON Web Key' : null));\n }\n if (key.type !== 'secret') {\n throw new TypeError(`${tag(key)} instances for symmetric algorithms must be of type \"secret\"`);\n }\n};\nconst asymmetricTypeCheck = (alg, key, usage, allowJwk) => {\n if (allowJwk && jwk.isJWK(key)) {\n switch (usage) {\n case 'sign':\n if (jwk.isPrivateJWK(key) && jwkMatchesOp(alg, key, usage))\n return;\n throw new TypeError(`JSON Web Key for this operation be a private JWK`);\n case 'verify':\n if (jwk.isPublicJWK(key) && jwkMatchesOp(alg, key, usage))\n return;\n throw new TypeError(`JSON Web Key for this operation be a public JWK`);\n }\n }\n if (!isKeyLike(key)) {\n throw new TypeError(invalidKeyInput(alg, key, ...types, allowJwk ? 'JSON Web Key' : null));\n }\n if (key.type === 'secret') {\n throw new TypeError(`${tag(key)} instances for asymmetric algorithms must not be of type \"secret\"`);\n }\n if (usage === 'sign' && key.type === 'public') {\n throw new TypeError(`${tag(key)} instances for asymmetric algorithm signing must be of type \"private\"`);\n }\n if (usage === 'decrypt' && key.type === 'public') {\n throw new TypeError(`${tag(key)} instances for asymmetric algorithm decryption must be of type \"private\"`);\n }\n if (key.algorithm && usage === 'verify' && key.type === 'private') {\n throw new TypeError(`${tag(key)} instances for asymmetric algorithm verifying must be of type \"public\"`);\n }\n if (key.algorithm && usage === 'encrypt' && key.type === 'private') {\n throw new TypeError(`${tag(key)} instances for asymmetric algorithm encryption must be of type \"public\"`);\n }\n};\nfunction checkKeyType(allowJwk, alg, key, usage) {\n const symmetric = alg.startsWith('HS') ||\n alg === 'dir' ||\n alg.startsWith('PBES2') ||\n /^A\\d{3}(?:GCM)?KW$/.test(alg);\n if (symmetric) {\n symmetricTypeCheck(alg, key, usage, allowJwk);\n }\n else {\n asymmetricTypeCheck(alg, key, usage, allowJwk);\n }\n}\nexport default checkKeyType.bind(undefined, false);\nexport const checkKeyTypeWithJwk = checkKeyType.bind(undefined, true);\n", "import { JOSENotSupported } from '../util/errors.js';\nfunction validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) {\n if (joseHeader.crit !== undefined && protectedHeader?.crit === undefined) {\n throw new Err('\"crit\" (Critical) Header Parameter MUST be integrity protected');\n }\n if (!protectedHeader || protectedHeader.crit === undefined) {\n return new Set();\n }\n if (!Array.isArray(protectedHeader.crit) ||\n protectedHeader.crit.length === 0 ||\n protectedHeader.crit.some((input) => typeof input !== 'string' || input.length === 0)) {\n throw new Err('\"crit\" (Critical) Header Parameter MUST be an array of non-empty strings when present');\n }\n let recognized;\n if (recognizedOption !== undefined) {\n recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]);\n }\n else {\n recognized = recognizedDefault;\n }\n for (const parameter of protectedHeader.crit) {\n if (!recognized.has(parameter)) {\n throw new JOSENotSupported(`Extension Header Parameter \"${parameter}\" is not recognized`);\n }\n if (joseHeader[parameter] === undefined) {\n throw new Err(`Extension Header Parameter \"${parameter}\" is missing`);\n }\n if (recognized.get(parameter) && protectedHeader[parameter] === undefined) {\n throw new Err(`Extension Header Parameter \"${parameter}\" MUST be integrity protected`);\n }\n }\n return new Set(protectedHeader.crit);\n}\nexport default validateCrit;\n", "const validateAlgorithms = (option, algorithms) => {\n if (algorithms !== undefined &&\n (!Array.isArray(algorithms) || algorithms.some((s) => typeof s !== 'string'))) {\n throw new TypeError(`\"${option}\" option must be an array of strings`);\n }\n if (!algorithms) {\n return undefined;\n }\n return new Set(algorithms);\n};\nexport default validateAlgorithms;\n", "import * as crypto from 'node:crypto';\nimport { promisify } from 'node:util';\nimport nodeDigest from './dsa_digest.js';\nimport nodeKey from './node_key.js';\nimport sign from './sign.js';\nimport getVerifyKey from './get_sign_verify_key.js';\nconst oneShotVerify = promisify(crypto.verify);\nconst verify = async (alg, key, signature, data) => {\n const k = getVerifyKey(alg, key, 'verify');\n if (alg.startsWith('HS')) {\n const expected = await sign(alg, k, data);\n const actual = signature;\n try {\n return crypto.timingSafeEqual(actual, expected);\n }\n catch {\n return false;\n }\n }\n const algorithm = nodeDigest(alg);\n const keyInput = nodeKey(alg, k);\n try {\n return await oneShotVerify(algorithm, data, keyInput, signature);\n }\n catch {\n return false;\n }\n};\nexport default verify;\n", "import { JOSENotSupported } from '../util/errors.js';\nexport default function dsaDigest(alg) {\n switch (alg) {\n case 'PS256':\n case 'RS256':\n case 'ES256':\n case 'ES256K':\n return 'sha256';\n case 'PS384':\n case 'RS384':\n case 'ES384':\n return 'sha384';\n case 'PS512':\n case 'RS512':\n case 'ES512':\n return 'sha512';\n case 'Ed25519':\n case 'EdDSA':\n return undefined;\n default:\n throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`);\n }\n}\n", "import { constants, KeyObject } from 'node:crypto';\nimport getNamedCurve from './get_named_curve.js';\nimport { JOSENotSupported } from '../util/errors.js';\nimport checkKeyLength from './check_key_length.js';\nconst ecCurveAlgMap = new Map([\n ['ES256', 'P-256'],\n ['ES256K', 'secp256k1'],\n ['ES384', 'P-384'],\n ['ES512', 'P-521'],\n]);\nexport default function keyForCrypto(alg, key) {\n let asymmetricKeyType;\n let asymmetricKeyDetails;\n let isJWK;\n if (key instanceof KeyObject) {\n asymmetricKeyType = key.asymmetricKeyType;\n asymmetricKeyDetails = key.asymmetricKeyDetails;\n }\n else {\n isJWK = true;\n switch (key.kty) {\n case 'RSA':\n asymmetricKeyType = 'rsa';\n break;\n case 'EC':\n asymmetricKeyType = 'ec';\n break;\n case 'OKP': {\n if (key.crv === 'Ed25519') {\n asymmetricKeyType = 'ed25519';\n break;\n }\n if (key.crv === 'Ed448') {\n asymmetricKeyType = 'ed448';\n break;\n }\n throw new TypeError('Invalid key for this operation, its crv must be Ed25519 or Ed448');\n }\n default:\n throw new TypeError('Invalid key for this operation, its kty must be RSA, OKP, or EC');\n }\n }\n let options;\n switch (alg) {\n case 'Ed25519':\n if (asymmetricKeyType !== 'ed25519') {\n throw new TypeError(`Invalid key for this operation, its asymmetricKeyType must be ed25519`);\n }\n break;\n case 'EdDSA':\n if (!['ed25519', 'ed448'].includes(asymmetricKeyType)) {\n throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be ed25519 or ed448');\n }\n break;\n case 'RS256':\n case 'RS384':\n case 'RS512':\n if (asymmetricKeyType !== 'rsa') {\n throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be rsa');\n }\n checkKeyLength(key, alg);\n break;\n case 'PS256':\n case 'PS384':\n case 'PS512':\n if (asymmetricKeyType === 'rsa-pss') {\n const { hashAlgorithm, mgf1HashAlgorithm, saltLength } = asymmetricKeyDetails;\n const length = parseInt(alg.slice(-3), 10);\n if (hashAlgorithm !== undefined &&\n (hashAlgorithm !== `sha${length}` || mgf1HashAlgorithm !== hashAlgorithm)) {\n throw new TypeError(`Invalid key for this operation, its RSA-PSS parameters do not meet the requirements of \"alg\" ${alg}`);\n }\n if (saltLength !== undefined && saltLength > length >> 3) {\n throw new TypeError(`Invalid key for this operation, its RSA-PSS parameter saltLength does not meet the requirements of \"alg\" ${alg}`);\n }\n }\n else if (asymmetricKeyType !== 'rsa') {\n throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be rsa or rsa-pss');\n }\n checkKeyLength(key, alg);\n options = {\n padding: constants.RSA_PKCS1_PSS_PADDING,\n saltLength: constants.RSA_PSS_SALTLEN_DIGEST,\n };\n break;\n case 'ES256':\n case 'ES256K':\n case 'ES384':\n case 'ES512': {\n if (asymmetricKeyType !== 'ec') {\n throw new TypeError('Invalid key for this operation, its asymmetricKeyType must be ec');\n }\n const actual = getNamedCurve(key);\n const expected = ecCurveAlgMap.get(alg);\n if (actual !== expected) {\n throw new TypeError(`Invalid key curve for the algorithm, its curve must be ${expected}, got ${actual}`);\n }\n options = { dsaEncoding: 'ieee-p1363' };\n break;\n }\n default:\n throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`);\n }\n if (isJWK) {\n return { format: 'jwk', key, ...options };\n }\n return options ? { ...options, key } : key;\n}\n", "import * as crypto from 'node:crypto';\nimport { promisify } from 'node:util';\nimport nodeDigest from './dsa_digest.js';\nimport hmacDigest from './hmac_digest.js';\nimport nodeKey from './node_key.js';\nimport getSignKey from './get_sign_verify_key.js';\nconst oneShotSign = promisify(crypto.sign);\nconst sign = async (alg, key, data) => {\n const k = getSignKey(alg, key, 'sign');\n if (alg.startsWith('HS')) {\n const hmac = crypto.createHmac(hmacDigest(alg), k);\n hmac.update(data);\n return hmac.digest();\n }\n return oneShotSign(nodeDigest(alg), data, nodeKey(alg, k));\n};\nexport default sign;\n", "import { JOSENotSupported } from '../util/errors.js';\nexport default function hmacDigest(alg) {\n switch (alg) {\n case 'HS256':\n return 'sha256';\n case 'HS384':\n return 'sha384';\n case 'HS512':\n return 'sha512';\n default:\n throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`);\n }\n}\n", "import { KeyObject, createSecretKey } from 'node:crypto';\nimport { isCryptoKey } from './webcrypto.js';\nimport { checkSigCryptoKey } from '../lib/crypto_key.js';\nimport invalidKeyInput from '../lib/invalid_key_input.js';\nimport { types } from './is_key_like.js';\nimport * as jwk from '../lib/is_jwk.js';\nexport default function getSignVerifyKey(alg, key, usage) {\n if (key instanceof Uint8Array) {\n if (!alg.startsWith('HS')) {\n throw new TypeError(invalidKeyInput(key, ...types));\n }\n return createSecretKey(key);\n }\n if (key instanceof KeyObject) {\n return key;\n }\n if (isCryptoKey(key)) {\n checkSigCryptoKey(key, alg, usage);\n return KeyObject.from(key);\n }\n if (jwk.isJWK(key)) {\n if (alg.startsWith('HS')) {\n return createSecretKey(Buffer.from(key.k, 'base64url'));\n }\n return key;\n }\n throw new TypeError(invalidKeyInput(key, ...types, 'Uint8Array', 'JSON Web Key'));\n}\n", "import { decode as base64url } from '../../runtime/base64url.js';\nimport verify from '../../runtime/verify.js';\nimport { JOSEAlgNotAllowed, JWSInvalid, JWSSignatureVerificationFailed } from '../../util/errors.js';\nimport { concat, encoder, decoder } from '../../lib/buffer_utils.js';\nimport isDisjoint from '../../lib/is_disjoint.js';\nimport isObject from '../../lib/is_object.js';\nimport { checkKeyTypeWithJwk } from '../../lib/check_key_type.js';\nimport validateCrit from '../../lib/validate_crit.js';\nimport validateAlgorithms from '../../lib/validate_algorithms.js';\nimport { isJWK } from '../../lib/is_jwk.js';\nimport { importJWK } from '../../key/import.js';\nexport async function flattenedVerify(jws, key, options) {\n if (!isObject(jws)) {\n throw new JWSInvalid('Flattened JWS must be an object');\n }\n if (jws.protected === undefined && jws.header === undefined) {\n throw new JWSInvalid('Flattened JWS must have either of the \"protected\" or \"header\" members');\n }\n if (jws.protected !== undefined && typeof jws.protected !== 'string') {\n throw new JWSInvalid('JWS Protected Header incorrect type');\n }\n if (jws.payload === undefined) {\n throw new JWSInvalid('JWS Payload missing');\n }\n if (typeof jws.signature !== 'string') {\n throw new JWSInvalid('JWS Signature missing or incorrect type');\n }\n if (jws.header !== undefined && !isObject(jws.header)) {\n throw new JWSInvalid('JWS Unprotected Header incorrect type');\n }\n let parsedProt = {};\n if (jws.protected) {\n try {\n const protectedHeader = base64url(jws.protected);\n parsedProt = JSON.parse(decoder.decode(protectedHeader));\n }\n catch {\n throw new JWSInvalid('JWS Protected Header is invalid');\n }\n }\n if (!isDisjoint(parsedProt, jws.header)) {\n throw new JWSInvalid('JWS Protected and JWS Unprotected Header Parameter names must be disjoint');\n }\n const joseHeader = {\n ...parsedProt,\n ...jws.header,\n };\n const extensions = validateCrit(JWSInvalid, new Map([['b64', true]]), options?.crit, parsedProt, joseHeader);\n let b64 = true;\n if (extensions.has('b64')) {\n b64 = parsedProt.b64;\n if (typeof b64 !== 'boolean') {\n throw new JWSInvalid('The \"b64\" (base64url-encode payload) Header Parameter must be a boolean');\n }\n }\n const { alg } = joseHeader;\n if (typeof alg !== 'string' || !alg) {\n throw new JWSInvalid('JWS \"alg\" (Algorithm) Header Parameter missing or invalid');\n }\n const algorithms = options && validateAlgorithms('algorithms', options.algorithms);\n if (algorithms && !algorithms.has(alg)) {\n throw new JOSEAlgNotAllowed('\"alg\" (Algorithm) Header Parameter value not allowed');\n }\n if (b64) {\n if (typeof jws.payload !== 'string') {\n throw new JWSInvalid('JWS Payload must be a string');\n }\n }\n else if (typeof jws.payload !== 'string' && !(jws.payload instanceof Uint8Array)) {\n throw new JWSInvalid('JWS Payload must be a string or an Uint8Array instance');\n }\n let resolvedKey = false;\n if (typeof key === 'function') {\n key = await key(parsedProt, jws);\n resolvedKey = true;\n checkKeyTypeWithJwk(alg, key, 'verify');\n if (isJWK(key)) {\n key = await importJWK(key, alg);\n }\n }\n else {\n checkKeyTypeWithJwk(alg, key, 'verify');\n }\n const data = concat(encoder.encode(jws.protected ?? ''), encoder.encode('.'), typeof jws.payload === 'string' ? encoder.encode(jws.payload) : jws.payload);\n let signature;\n try {\n signature = base64url(jws.signature);\n }\n catch {\n throw new JWSInvalid('Failed to base64url decode the signature');\n }\n const verified = await verify(alg, key, signature, data);\n if (!verified) {\n throw new JWSSignatureVerificationFailed();\n }\n let payload;\n if (b64) {\n try {\n payload = base64url(jws.payload);\n }\n catch {\n throw new JWSInvalid('Failed to base64url decode the payload');\n }\n }\n else if (typeof jws.payload === 'string') {\n payload = encoder.encode(jws.payload);\n }\n else {\n payload = jws.payload;\n }\n const result = { payload };\n if (jws.protected !== undefined) {\n result.protectedHeader = parsedProt;\n }\n if (jws.header !== undefined) {\n result.unprotectedHeader = jws.header;\n }\n if (resolvedKey) {\n return { ...result, key };\n }\n return result;\n}\n", "import { flattenedVerify } from '../flattened/verify.js';\nimport { JWSInvalid } from '../../util/errors.js';\nimport { decoder } from '../../lib/buffer_utils.js';\nexport async function compactVerify(jws, key, options) {\n if (jws instanceof Uint8Array) {\n jws = decoder.decode(jws);\n }\n if (typeof jws !== 'string') {\n throw new JWSInvalid('Compact JWS must be a string or Uint8Array');\n }\n const { 0: protectedHeader, 1: payload, 2: signature, length } = jws.split('.');\n if (length !== 3) {\n throw new JWSInvalid('Invalid Compact JWS');\n }\n const verified = await flattenedVerify({ payload, protected: protectedHeader, signature }, key, options);\n const result = { payload: verified.payload, protectedHeader: verified.protectedHeader };\n if (typeof key === 'function') {\n return { ...result, key: verified.key };\n }\n return result;\n}\n", "export default (date) => Math.floor(date.getTime() / 1000);\n", "const minute = 60;\nconst hour = minute * 60;\nconst day = hour * 24;\nconst week = day * 7;\nconst year = day * 365.25;\nconst REGEX = /^(\\+|\\-)? ?(\\d+|\\d+\\.\\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)(?: (ago|from now))?$/i;\nexport default (str) => {\n const matched = REGEX.exec(str);\n if (!matched || (matched[4] && matched[1])) {\n throw new TypeError('Invalid time period format');\n }\n const value = parseFloat(matched[2]);\n const unit = matched[3].toLowerCase();\n let numericDate;\n switch (unit) {\n case 'sec':\n case 'secs':\n case 'second':\n case 'seconds':\n case 's':\n numericDate = Math.round(value);\n break;\n case 'minute':\n case 'minutes':\n case 'min':\n case 'mins':\n case 'm':\n numericDate = Math.round(value * minute);\n break;\n case 'hour':\n case 'hours':\n case 'hr':\n case 'hrs':\n case 'h':\n numericDate = Math.round(value * hour);\n break;\n case 'day':\n case 'days':\n case 'd':\n numericDate = Math.round(value * day);\n break;\n case 'week':\n case 'weeks':\n case 'w':\n numericDate = Math.round(value * week);\n break;\n default:\n numericDate = Math.round(value * year);\n break;\n }\n if (matched[1] === '-' || matched[4] === 'ago') {\n return -numericDate;\n }\n return numericDate;\n};\n", "import { JWTClaimValidationFailed, JWTExpired, JWTInvalid } from '../util/errors.js';\nimport { decoder } from './buffer_utils.js';\nimport epoch from './epoch.js';\nimport secs from './secs.js';\nimport isObject from './is_object.js';\nconst normalizeTyp = (value) => value.toLowerCase().replace(/^application\\//, '');\nconst checkAudiencePresence = (audPayload, audOption) => {\n if (typeof audPayload === 'string') {\n return audOption.includes(audPayload);\n }\n if (Array.isArray(audPayload)) {\n return audOption.some(Set.prototype.has.bind(new Set(audPayload)));\n }\n return false;\n};\nexport default (protectedHeader, encodedPayload, options = {}) => {\n let payload;\n try {\n payload = JSON.parse(decoder.decode(encodedPayload));\n }\n catch {\n }\n if (!isObject(payload)) {\n throw new JWTInvalid('JWT Claims Set must be a top-level JSON object');\n }\n const { typ } = options;\n if (typ &&\n (typeof protectedHeader.typ !== 'string' ||\n normalizeTyp(protectedHeader.typ) !== normalizeTyp(typ))) {\n throw new JWTClaimValidationFailed('unexpected \"typ\" JWT header value', payload, 'typ', 'check_failed');\n }\n const { requiredClaims = [], issuer, subject, audience, maxTokenAge } = options;\n const presenceCheck = [...requiredClaims];\n if (maxTokenAge !== undefined)\n presenceCheck.push('iat');\n if (audience !== undefined)\n presenceCheck.push('aud');\n if (subject !== undefined)\n presenceCheck.push('sub');\n if (issuer !== undefined)\n presenceCheck.push('iss');\n for (const claim of new Set(presenceCheck.reverse())) {\n if (!(claim in payload)) {\n throw new JWTClaimValidationFailed(`missing required \"${claim}\" claim`, payload, claim, 'missing');\n }\n }\n if (issuer &&\n !(Array.isArray(issuer) ? issuer : [issuer]).includes(payload.iss)) {\n throw new JWTClaimValidationFailed('unexpected \"iss\" claim value', payload, 'iss', 'check_failed');\n }\n if (subject && payload.sub !== subject) {\n throw new JWTClaimValidationFailed('unexpected \"sub\" claim value', payload, 'sub', 'check_failed');\n }\n if (audience &&\n !checkAudiencePresence(payload.aud, typeof audience === 'string' ? [audience] : audience)) {\n throw new JWTClaimValidationFailed('unexpected \"aud\" claim value', payload, 'aud', 'check_failed');\n }\n let tolerance;\n switch (typeof options.clockTolerance) {\n case 'string':\n tolerance = secs(options.clockTolerance);\n break;\n case 'number':\n tolerance = options.clockTolerance;\n break;\n case 'undefined':\n tolerance = 0;\n break;\n default:\n throw new TypeError('Invalid clockTolerance option type');\n }\n const { currentDate } = options;\n const now = epoch(currentDate || new Date());\n if ((payload.iat !== undefined || maxTokenAge) && typeof payload.iat !== 'number') {\n throw new JWTClaimValidationFailed('\"iat\" claim must be a number', payload, 'iat', 'invalid');\n }\n if (payload.nbf !== undefined) {\n if (typeof payload.nbf !== 'number') {\n throw new JWTClaimValidationFailed('\"nbf\" claim must be a number', payload, 'nbf', 'invalid');\n }\n if (payload.nbf > now + tolerance) {\n throw new JWTClaimValidationFailed('\"nbf\" claim timestamp check failed', payload, 'nbf', 'check_failed');\n }\n }\n if (payload.exp !== undefined) {\n if (typeof payload.exp !== 'number') {\n throw new JWTClaimValidationFailed('\"exp\" claim must be a number', payload, 'exp', 'invalid');\n }\n if (payload.exp <= now - tolerance) {\n throw new JWTExpired('\"exp\" claim timestamp check failed', payload, 'exp', 'check_failed');\n }\n }\n if (maxTokenAge) {\n const age = now - payload.iat;\n const max = typeof maxTokenAge === 'number' ? maxTokenAge : secs(maxTokenAge);\n if (age - tolerance > max) {\n throw new JWTExpired('\"iat\" claim timestamp check failed (too far in the past)', payload, 'iat', 'check_failed');\n }\n if (age < 0 - tolerance) {\n throw new JWTClaimValidationFailed('\"iat\" claim timestamp check failed (it should be in the past)', payload, 'iat', 'check_failed');\n }\n }\n return payload;\n};\n", "import { compactVerify } from '../jws/compact/verify.js';\nimport jwtPayload from '../lib/jwt_claims_set.js';\nimport { JWTInvalid } from '../util/errors.js';\nexport async function jwtVerify(jwt, key, options) {\n const verified = await compactVerify(jwt, key, options);\n if (verified.protectedHeader.crit?.includes('b64') && verified.protectedHeader.b64 === false) {\n throw new JWTInvalid('JWTs MUST NOT use unencoded payload');\n }\n const payload = jwtPayload(verified.protectedHeader, verified.payload, options);\n const result = { payload, protectedHeader: verified.protectedHeader };\n if (typeof key === 'function') {\n return { ...result, key: verified.key };\n }\n return result;\n}\n", "import { importJWK } from '../key/import.js';\nimport { JWKSInvalid, JOSENotSupported, JWKSNoMatchingKey, JWKSMultipleMatchingKeys, } from '../util/errors.js';\nimport isObject from '../lib/is_object.js';\nfunction getKtyFromAlg(alg) {\n switch (typeof alg === 'string' && alg.slice(0, 2)) {\n case 'RS':\n case 'PS':\n return 'RSA';\n case 'ES':\n return 'EC';\n case 'Ed':\n return 'OKP';\n default:\n throw new JOSENotSupported('Unsupported \"alg\" value for a JSON Web Key Set');\n }\n}\nfunction isJWKSLike(jwks) {\n return (jwks &&\n typeof jwks === 'object' &&\n Array.isArray(jwks.keys) &&\n jwks.keys.every(isJWKLike));\n}\nfunction isJWKLike(key) {\n return isObject(key);\n}\nfunction clone(obj) {\n if (typeof structuredClone === 'function') {\n return structuredClone(obj);\n }\n return JSON.parse(JSON.stringify(obj));\n}\nclass LocalJWKSet {\n _jwks;\n _cached = new WeakMap();\n constructor(jwks) {\n if (!isJWKSLike(jwks)) {\n throw new JWKSInvalid('JSON Web Key Set malformed');\n }\n this._jwks = clone(jwks);\n }\n async getKey(protectedHeader, token) {\n const { alg, kid } = { ...protectedHeader, ...token?.header };\n const kty = getKtyFromAlg(alg);\n const candidates = this._jwks.keys.filter((jwk) => {\n let candidate = kty === jwk.kty;\n if (candidate && typeof kid === 'string') {\n candidate = kid === jwk.kid;\n }\n if (candidate && typeof jwk.alg === 'string') {\n candidate = alg === jwk.alg;\n }\n if (candidate && typeof jwk.use === 'string') {\n candidate = jwk.use === 'sig';\n }\n if (candidate && Array.isArray(jwk.key_ops)) {\n candidate = jwk.key_ops.includes('verify');\n }\n if (candidate) {\n switch (alg) {\n case 'ES256':\n candidate = jwk.crv === 'P-256';\n break;\n case 'ES256K':\n candidate = jwk.crv === 'secp256k1';\n break;\n case 'ES384':\n candidate = jwk.crv === 'P-384';\n break;\n case 'ES512':\n candidate = jwk.crv === 'P-521';\n break;\n case 'Ed25519':\n candidate = jwk.crv === 'Ed25519';\n break;\n case 'EdDSA':\n candidate = jwk.crv === 'Ed25519' || jwk.crv === 'Ed448';\n break;\n }\n }\n return candidate;\n });\n const { 0: jwk, length } = candidates;\n if (length === 0) {\n throw new JWKSNoMatchingKey();\n }\n if (length !== 1) {\n const error = new JWKSMultipleMatchingKeys();\n const { _cached } = this;\n error[Symbol.asyncIterator] = async function* () {\n for (const jwk of candidates) {\n try {\n yield await importWithAlgCache(_cached, jwk, alg);\n }\n catch { }\n }\n };\n throw error;\n }\n return importWithAlgCache(this._cached, jwk, alg);\n }\n}\nasync function importWithAlgCache(cache, jwk, alg) {\n const cached = cache.get(jwk) || cache.set(jwk, {}).get(jwk);\n if (cached[alg] === undefined) {\n const key = await importJWK({ ...jwk, ext: true }, alg);\n if (key instanceof Uint8Array || key.type !== 'public') {\n throw new JWKSInvalid('JSON Web Key Set members must be public keys');\n }\n cached[alg] = key;\n }\n return cached[alg];\n}\nexport function createLocalJWKSet(jwks) {\n const set = new LocalJWKSet(jwks);\n const localJWKSet = async (protectedHeader, token) => set.getKey(protectedHeader, token);\n Object.defineProperties(localJWKSet, {\n jwks: {\n value: () => clone(set._jwks),\n enumerable: true,\n configurable: false,\n writable: false,\n },\n });\n return localJWKSet;\n}\n", "import * as http from 'node:http';\nimport * as https from 'node:https';\nimport { once } from 'node:events';\nimport { JOSEError, JWKSTimeout } from '../util/errors.js';\nimport { concat, decoder } from '../lib/buffer_utils.js';\nconst fetchJwks = async (url, timeout, options) => {\n let get;\n switch (url.protocol) {\n case 'https:':\n get = https.get;\n break;\n case 'http:':\n get = http.get;\n break;\n default:\n throw new TypeError('Unsupported URL protocol.');\n }\n const { agent, headers } = options;\n const req = get(url.href, {\n agent,\n timeout,\n headers,\n });\n const [response] = (await Promise.race([once(req, 'response'), once(req, 'timeout')]));\n if (!response) {\n req.destroy();\n throw new JWKSTimeout();\n }\n if (response.statusCode !== 200) {\n throw new JOSEError('Expected 200 OK from the JSON Web Key Set HTTP response');\n }\n const parts = [];\n for await (const part of response) {\n parts.push(part);\n }\n try {\n return JSON.parse(decoder.decode(concat(...parts)));\n }\n catch {\n throw new JOSEError('Failed to parse the JSON Web Key Set HTTP response as JSON');\n }\n};\nexport default fetchJwks;\n", "import fetchJwks from '../runtime/fetch_jwks.js';\nimport { JWKSNoMatchingKey } from '../util/errors.js';\nimport { createLocalJWKSet } from './local.js';\nimport isObject from '../lib/is_object.js';\nfunction isCloudflareWorkers() {\n return (typeof WebSocketPair !== 'undefined' ||\n (typeof navigator !== 'undefined' && navigator.userAgent === 'Cloudflare-Workers') ||\n (typeof EdgeRuntime !== 'undefined' && EdgeRuntime === 'vercel'));\n}\nlet USER_AGENT;\nif (typeof navigator === 'undefined' || !navigator.userAgent?.startsWith?.('Mozilla/5.0 ')) {\n const NAME = 'jose';\n const VERSION = 'v5.10.0';\n USER_AGENT = `${NAME}/${VERSION}`;\n}\nexport const jwksCache = Symbol();\nfunction isFreshJwksCache(input, cacheMaxAge) {\n if (typeof input !== 'object' || input === null) {\n return false;\n }\n if (!('uat' in input) || typeof input.uat !== 'number' || Date.now() - input.uat >= cacheMaxAge) {\n return false;\n }\n if (!('jwks' in input) ||\n !isObject(input.jwks) ||\n !Array.isArray(input.jwks.keys) ||\n !Array.prototype.every.call(input.jwks.keys, isObject)) {\n return false;\n }\n return true;\n}\nclass RemoteJWKSet {\n _url;\n _timeoutDuration;\n _cooldownDuration;\n _cacheMaxAge;\n _jwksTimestamp;\n _pendingFetch;\n _options;\n _local;\n _cache;\n constructor(url, options) {\n if (!(url instanceof URL)) {\n throw new TypeError('url must be an instance of URL');\n }\n this._url = new URL(url.href);\n this._options = { agent: options?.agent, headers: options?.headers };\n this._timeoutDuration =\n typeof options?.timeoutDuration === 'number' ? options?.timeoutDuration : 5000;\n this._cooldownDuration =\n typeof options?.cooldownDuration === 'number' ? options?.cooldownDuration : 30000;\n this._cacheMaxAge = typeof options?.cacheMaxAge === 'number' ? options?.cacheMaxAge : 600000;\n if (options?.[jwksCache] !== undefined) {\n this._cache = options?.[jwksCache];\n if (isFreshJwksCache(options?.[jwksCache], this._cacheMaxAge)) {\n this._jwksTimestamp = this._cache.uat;\n this._local = createLocalJWKSet(this._cache.jwks);\n }\n }\n }\n coolingDown() {\n return typeof this._jwksTimestamp === 'number'\n ? Date.now() < this._jwksTimestamp + this._cooldownDuration\n : false;\n }\n fresh() {\n return typeof this._jwksTimestamp === 'number'\n ? Date.now() < this._jwksTimestamp + this._cacheMaxAge\n : false;\n }\n async getKey(protectedHeader, token) {\n if (!this._local || !this.fresh()) {\n await this.reload();\n }\n try {\n return await this._local(protectedHeader, token);\n }\n catch (err) {\n if (err instanceof JWKSNoMatchingKey) {\n if (this.coolingDown() === false) {\n await this.reload();\n return this._local(protectedHeader, token);\n }\n }\n throw err;\n }\n }\n async reload() {\n if (this._pendingFetch && isCloudflareWorkers()) {\n this._pendingFetch = undefined;\n }\n const headers = new Headers(this._options.headers);\n if (USER_AGENT && !headers.has('User-Agent')) {\n headers.set('User-Agent', USER_AGENT);\n this._options.headers = Object.fromEntries(headers.entries());\n }\n this._pendingFetch ||= fetchJwks(this._url, this._timeoutDuration, this._options)\n .then((json) => {\n this._local = createLocalJWKSet(json);\n if (this._cache) {\n this._cache.uat = Date.now();\n this._cache.jwks = json;\n }\n this._jwksTimestamp = Date.now();\n this._pendingFetch = undefined;\n })\n .catch((err) => {\n this._pendingFetch = undefined;\n throw err;\n });\n await this._pendingFetch;\n }\n}\nexport function createRemoteJWKSet(url, options) {\n const set = new RemoteJWKSet(url, options);\n const remoteJWKSet = async (protectedHeader, token) => set.getKey(protectedHeader, token);\n Object.defineProperties(remoteJWKSet, {\n coolingDown: {\n get: () => set.coolingDown(),\n enumerable: true,\n configurable: false,\n },\n fresh: {\n get: () => set.fresh(),\n enumerable: true,\n configurable: false,\n },\n reload: {\n value: () => set.reload(),\n enumerable: true,\n configurable: false,\n writable: false,\n },\n reloading: {\n get: () => !!set._pendingFetch,\n enumerable: true,\n configurable: false,\n },\n jwks: {\n value: () => set._local?.jwks(),\n enumerable: true,\n configurable: false,\n writable: false,\n },\n });\n return remoteJWKSet;\n}\nexport const experimental_jwksCache = jwksCache;\n", "/**\n * Bridge \u2014 lets CLI clients (Abby) list/mint LiteLLM virtual keys without ever\n * holding the LiteLLM master key.\n *\n * Trust model: the Backstage backend holds the master key (as it already does\n * for the UI). A CLI authenticates with its Keycloak access token (the same\n * Keycloak realm Backstage uses). This module verifies that JWT against the\n * realm JWKS, resolves the caller to a LiteLLM user_id, ensures that user\n * exists (provisioning from claims if enabled), and then lists/generates keys\n * via the existing master-key-authed {@link LiteLLMClient}.\n *\n * Unlike the UI endpoints in router.ts, the bridge routes do NOT call\n * Backstage's `auth.authenticate` (which expects a Backstage-issued token);\n * they verify the raw Keycloak JWT themselves.\n */\nimport { createRemoteJWKSet, jwtVerify, JWTPayload } from 'jose';\nimport { Config } from '@backstage/config';\nimport { LiteLLMClient } from './client';\nimport {\n GenerateKeyRequest,\n GenerateKeyResponse,\n ProvisioningDefaults,\n UserInfo,\n VirtualKey,\n} from './types';\nimport { ProvisioningError, provisionUser, toLiteLLMUserId } from './provisioning';\n\n/** Claims extracted from a verified Keycloak access token. */\nexport interface BridgeClaims {\n sub: string;\n email?: string;\n preferred_username?: string;\n name?: string;\n /** Authorized party \u2014 Keycloak sets this to the client_id of the requester. */\n azp?: string;\n aud?: string | string[];\n}\n\n/** A token verifier pluggable for tests. */\nexport interface TokenVerifier {\n verify(token: string): Promise<BridgeClaims>;\n}\n\nexport interface BridgeConfig {\n enabled: boolean;\n /** Keycloak realm issuer, e.g. https://auth.ces.abssrv.it/realms/solution-innovation. */\n issuer?: string;\n /** OIDC public client the CLI uses; checked against azp / aud. */\n clientId: string;\n}\n\nexport function readBridgeConfig(config: Config): BridgeConfig {\n const enabled =\n config.getOptionalBoolean('litellm.bridge.enabled') ?? false;\n const issuer = config.getOptionalString('litellm.bridge.issuer');\n const clientId =\n config.getOptionalString('litellm.bridge.clientId') ?? 'abby-cli';\n return { enabled, issuer, clientId };\n}\n\n/** Thrown when the bridge is misconfigured (e.g. enabled without an issuer). */\nexport class BridgeConfigError extends Error {}\n\n/** Thrown when a presented token fails verification \u2192 maps to HTTP 401. */\nexport class BridgeAuthError extends Error {\n readonly status = 401;\n}\n\nexport interface KeycloakJWTVerifierOptions {\n issuer: string;\n clientId: string;\n}\n\n/**\n * Verifies a Keycloak access token against the realm JWKS and ensures it was\n * issued for {@link clientId} (via azp, falling back to aud). Uses jose's\n * remote JWKS client (cached, with cooldown on errors).\n */\nexport class KeycloakJWTVerifier implements TokenVerifier {\n private readonly issuer: string;\n private readonly clientId: string;\n private readonly jwks: ReturnType<typeof createRemoteJWKSet>;\n\n constructor(opts: KeycloakJWTVerifierOptions) {\n this.issuer = opts.issuer.replace(/\\/$/, '');\n this.clientId = opts.clientId;\n this.jwks = createRemoteJWKSet(\n new URL(`${this.issuer}/protocol/openid-connect/certs`),\n );\n }\n\n async verify(token: string): Promise<BridgeClaims> {\n let payload: JWTPayload;\n try {\n const result = await jwtVerify(token, this.jwks, {\n issuer: this.issuer,\n });\n payload = result.payload;\n } catch (err) {\n // Expired, bad signature, wrong issuer, malformed, JWKS unreachable, etc.\n throw new BridgeAuthError(\n `invalid keycloak token: ${(err as Error).message ?? err}`,\n );\n }\n const azp = (payload as Record<string, unknown>).azp as\n | string\n | undefined;\n const aud = payload.aud;\n const audMatches = Array.isArray(aud)\n ? aud.includes(this.clientId)\n : aud === this.clientId;\n if (azp !== this.clientId && !audMatches) {\n throw new BridgeAuthError(\n `token not issued for client \"${this.clientId}\" (azp=${azp ?? 'none'})`,\n );\n }\n return {\n sub: payload.sub ?? '',\n email: payload.email as string | undefined,\n preferred_username: (payload as Record<string, unknown>)\n .preferred_username as string | undefined,\n name: payload.name as string | undefined,\n azp,\n aud,\n };\n }\n}\n\n/** Builds the default verifier from config, or throws BridgeConfigError. */\nexport function newDefaultVerifier(cfg: BridgeConfig): TokenVerifier {\n if (!cfg.issuer) {\n throw new BridgeConfigError(\n 'litellm.bridge.issuer is required when litellm.bridge.enabled is true ' +\n '(e.g. https://auth.ces.abssrv.it/realms/solution-innovation)',\n );\n }\n return new KeycloakJWTVerifier({ issuer: cfg.issuer, clientId: cfg.clientId });\n}\n\n/**\n * Resolves the LiteLLM user_id from the verified claims, matching exactly how\n * the UI derives it so the bridge addresses the *same* LiteLLM user (not a\n * duplicate). The UI uses toLiteLLMUserId(entityRef, userIdDomain) where the\n * Backstage entity name has been rewritten by the Keycloak user transformer:\n * because the catalog rejects '@' in entity names, usernames imported as full\n * emails are stored as their local-part. We replicate that here \u2014 strip the\n * '@domain' off the username, then apply the same userIdDomain rule.\n */\nexport function resolveBridgeUserId(\n claims: BridgeClaims,\n userIdDomain?: string,\n): string {\n const raw = claims.preferred_username ?? claims.email ?? claims.sub;\n const entityName = raw.includes('@') ? raw.split('@')[0] : raw;\n return toLiteLLMUserId(entityName, userIdDomain);\n}\n\n/**\n * Ensures a LiteLLM user exists for the verified identity. If the user is\n * missing and provisioning is enabled, creates it from the JWT claims (email +\n * name); if provisioning is disabled, throws a 404 telling the caller to log\n * in to Backstage first (the UI is the primary provisioning entry point).\n */\nexport async function getOrProvisionUserFromClaims(\n client: LiteLLMClient,\n claims: BridgeClaims,\n provisioningEnabled: boolean,\n provisioningDefaults: ProvisioningDefaults,\n logger: { info: (...args: unknown[]) => void },\n userIdDomain?: string,\n): Promise<UserInfo> {\n const userId = resolveBridgeUserId(claims, userIdDomain);\n const existing = await client.getUserInfo(userId);\n if (existing) return existing;\n\n if (!provisioningEnabled) {\n throw new ProvisioningError(\n 'User not found in LiteLLM',\n 'No LiteLLM user for this identity. Log in to Backstage once to be provisioned, or enable litellm.provisioning.enabled.',\n false,\n );\n }\n\n const profile = {\n email: claims.email ?? claims.preferred_username,\n displayName: claims.name ?? claims.preferred_username,\n };\n const created = await provisionUser(\n client,\n userId,\n provisioningDefaults,\n profile,\n undefined,\n logger,\n );\n if (!created) {\n throw new ProvisioningError(\n 'User not found in LiteLLM',\n 'Provisioning attempted but returned no user \u2014 check LiteLLM logs',\n true,\n 500,\n );\n }\n return created;\n}\n\n/** Lists the caller's virtual keys (provisioning the user first if needed). */\nexport async function bridgeListKeys(\n client: LiteLLMClient,\n claims: BridgeClaims,\n provisioningEnabled: boolean,\n provisioningDefaults: ProvisioningDefaults,\n logger: { info: (...args: unknown[]) => void },\n userIdDomain?: string,\n): Promise<VirtualKey[]> {\n await getOrProvisionUserFromClaims(\n client,\n claims,\n provisioningEnabled,\n provisioningDefaults,\n logger,\n userIdDomain,\n );\n return client.listKeys(resolveBridgeUserId(claims, userIdDomain));\n}\n\n/** Mints a new virtual key for the caller (provisioning the user first if needed). */\nexport async function bridgeGenerateKey(\n client: LiteLLMClient,\n claims: BridgeClaims,\n provisioningEnabled: boolean,\n provisioningDefaults: ProvisioningDefaults,\n logger: { info: (...args: unknown[]) => void },\n request: Partial<GenerateKeyRequest>,\n userIdDomain?: string,\n): Promise<GenerateKeyResponse> {\n await getOrProvisionUserFromClaims(\n client,\n claims,\n provisioningEnabled,\n provisioningDefaults,\n logger,\n userIdDomain,\n );\n const userId = resolveBridgeUserId(claims, userIdDomain);\n const enriched: GenerateKeyRequest = {\n ...request,\n user_id: userId,\n metadata: {\n ...(request.metadata ?? {}),\n created_via: 'abby-cli',\n created_by: userId,\n created_at_iso: new Date().toISOString(),\n },\n };\n return client.generateKey(enriched);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["data", "message", "message", "message", "util", "webcrypto", "types", "types", "getNamedCurve", "types", "import_node_crypto", "import_node_crypto", "types", "crypto", "import_node_util", "import_node_crypto", "isJWK", "crypto", "import_node_crypto", "types", "sign", "verify", "jwk", "get", "express"]
|
|
7
7
|
}
|
package/dist/openapi.js
CHANGED
|
@@ -56,12 +56,16 @@ exports.openApiSpec = {
|
|
|
56
56
|
'/config': {
|
|
57
57
|
get: {
|
|
58
58
|
tags: ['System'],
|
|
59
|
-
summary: 'Public LiteLLM proxy base URL
|
|
59
|
+
summary: 'Public LiteLLM proxy base URL and key-generation form settings',
|
|
60
60
|
responses: {
|
|
61
61
|
'200': {
|
|
62
|
-
description: '
|
|
62
|
+
description: 'Frontend config',
|
|
63
63
|
content: { 'application/json': { schema: { type: 'object', properties: {
|
|
64
64
|
baseUrl: { type: 'string' },
|
|
65
|
+
keyGeneration: { type: 'object', properties: {
|
|
66
|
+
allowUnlimitedBudget: { type: 'boolean' },
|
|
67
|
+
teamRequired: { type: 'boolean' },
|
|
68
|
+
} },
|
|
65
69
|
} } } },
|
|
66
70
|
},
|
|
67
71
|
},
|
package/dist/router.js
CHANGED
|
@@ -55,6 +55,8 @@ async function createRouter(options) {
|
|
|
55
55
|
const { enabled: provisioningEnabled, defaults: provisioningDefaults } = (0, provisioning_1.readProvisioningDefaults)(config);
|
|
56
56
|
const roleConfigs = (0, provisioning_1.readRoleConfigs)(config);
|
|
57
57
|
const auditGroup = config.getOptionalString('litellm.audit.group');
|
|
58
|
+
const allowUnlimitedBudget = config.getOptionalBoolean('litellm.keyGeneration.allowUnlimitedBudget') ?? false;
|
|
59
|
+
const teamRequired = config.getOptionalBoolean('litellm.keyGeneration.teamRequired') ?? true;
|
|
58
60
|
const catalogClient = new catalog_client_1.CatalogClient({ discoveryApi: discovery });
|
|
59
61
|
if (provisioningEnabled) {
|
|
60
62
|
logger.info(`LiteLLM auto-provisioning enabled — defaults: budget=$${provisioningDefaults.maxBudget}/${provisioningDefaults.budgetDuration}, models=${provisioningDefaults.models.length
|
|
@@ -72,7 +74,10 @@ async function createRouter(options) {
|
|
|
72
74
|
// Exposes the public LiteLLM proxy URL so the frontend can build
|
|
73
75
|
// ready-to-paste curl / OpenAI-SDK snippets for freshly generated keys.
|
|
74
76
|
router.get('/config', (_req, res) => {
|
|
75
|
-
res.json({
|
|
77
|
+
res.json({
|
|
78
|
+
baseUrl: publicBaseUrl,
|
|
79
|
+
keyGeneration: { allowUnlimitedBudget, teamRequired },
|
|
80
|
+
});
|
|
76
81
|
});
|
|
77
82
|
// Self-hosted OpenAPI 3.1 contract — lets integrators read a spec instead
|
|
78
83
|
// of router.ts. No swagger-ui dependency; serve the JSON and point external
|