@acarmisc/backstage-plugin-litellm-backend 0.8.2 → 0.10.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/dist/index.d.ts CHANGED
@@ -5,5 +5,8 @@ export * from './types';
5
5
  export { LiteLLMClient } from './client';
6
6
  export { resolveUserId, resolveUserProfile, toLiteLLMUserId, getOrProvisionUser, provisionUser, readProvisioningDefaults, readRoleConfigs, applyRoleOverrides, resolveUserRole, ProvisioningError, } from './provisioning';
7
7
  export type { BackstageUserProfile } from './provisioning';
8
+ export { readTeamAdminConfig, isTeamManagementEnabled, assertTeamAdmin, validateTeamWriteInput, validateTeamPatchInput, } from './teamAdmin';
9
+ export type { TeamAdminConfig, TeamAdminCheck, TeamWriteInput, TeamWriteValidation, TeamPatchValidation } from './teamAdmin';
8
10
  export { KeycloakJWTVerifier, newDefaultVerifier, readBridgeConfig, resolveBridgeUserId, getOrProvisionUserFromClaims, bridgeListKeys, bridgeGenerateKey, } from './bridge';
9
11
  export type { BridgeClaims, TokenVerifier, BridgeConfig, KeycloakJWTVerifierOptions, } from './bridge';
12
+ export { litellmPermissions, litellmKeyCreatePermission, litellmKeyRevokePermission, litellmKeyManagePermission, litellmAuditReadPermission, litellmTeamCreatePermission, litellmTeamManagePermission, litellmTeamMembersManagePermission, litellmTeamKnowledgebaseManagePermission, litellmTeamMcpManagePermission, litellmTeamDeletePermission, } from './permissions';
package/dist/index.js CHANGED
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.bridgeGenerateKey = exports.bridgeListKeys = exports.getOrProvisionUserFromClaims = exports.resolveBridgeUserId = exports.readBridgeConfig = exports.newDefaultVerifier = exports.KeycloakJWTVerifier = exports.ProvisioningError = exports.resolveUserRole = exports.applyRoleOverrides = exports.readRoleConfigs = exports.readProvisioningDefaults = exports.provisionUser = exports.getOrProvisionUser = exports.toLiteLLMUserId = exports.resolveUserProfile = exports.resolveUserId = exports.LiteLLMClient = exports.createRouter = exports.default = exports.litellmPlugin = void 0;
17
+ exports.litellmTeamDeletePermission = exports.litellmTeamMcpManagePermission = exports.litellmTeamKnowledgebaseManagePermission = exports.litellmTeamMembersManagePermission = exports.litellmTeamManagePermission = exports.litellmTeamCreatePermission = exports.litellmAuditReadPermission = exports.litellmKeyManagePermission = exports.litellmKeyRevokePermission = exports.litellmKeyCreatePermission = exports.litellmPermissions = exports.bridgeGenerateKey = exports.bridgeListKeys = exports.getOrProvisionUserFromClaims = exports.resolveBridgeUserId = exports.readBridgeConfig = exports.newDefaultVerifier = exports.KeycloakJWTVerifier = exports.validateTeamPatchInput = exports.validateTeamWriteInput = exports.assertTeamAdmin = exports.isTeamManagementEnabled = exports.readTeamAdminConfig = exports.ProvisioningError = exports.resolveUserRole = exports.applyRoleOverrides = exports.readRoleConfigs = exports.readProvisioningDefaults = exports.provisionUser = exports.getOrProvisionUser = exports.toLiteLLMUserId = exports.resolveUserProfile = exports.resolveUserId = exports.LiteLLMClient = exports.createRouter = exports.default = exports.litellmPlugin = void 0;
18
18
  var plugin_1 = require("./plugin");
19
19
  Object.defineProperty(exports, "litellmPlugin", { enumerable: true, get: function () { return plugin_1.litellmPlugin; } });
20
20
  var plugin_2 = require("./plugin");
@@ -35,6 +35,12 @@ Object.defineProperty(exports, "readRoleConfigs", { enumerable: true, get: funct
35
35
  Object.defineProperty(exports, "applyRoleOverrides", { enumerable: true, get: function () { return provisioning_1.applyRoleOverrides; } });
36
36
  Object.defineProperty(exports, "resolveUserRole", { enumerable: true, get: function () { return provisioning_1.resolveUserRole; } });
37
37
  Object.defineProperty(exports, "ProvisioningError", { enumerable: true, get: function () { return provisioning_1.ProvisioningError; } });
38
+ var teamAdmin_1 = require("./teamAdmin");
39
+ Object.defineProperty(exports, "readTeamAdminConfig", { enumerable: true, get: function () { return teamAdmin_1.readTeamAdminConfig; } });
40
+ Object.defineProperty(exports, "isTeamManagementEnabled", { enumerable: true, get: function () { return teamAdmin_1.isTeamManagementEnabled; } });
41
+ Object.defineProperty(exports, "assertTeamAdmin", { enumerable: true, get: function () { return teamAdmin_1.assertTeamAdmin; } });
42
+ Object.defineProperty(exports, "validateTeamWriteInput", { enumerable: true, get: function () { return teamAdmin_1.validateTeamWriteInput; } });
43
+ Object.defineProperty(exports, "validateTeamPatchInput", { enumerable: true, get: function () { return teamAdmin_1.validateTeamPatchInput; } });
38
44
  var bridge_1 = require("./bridge");
39
45
  Object.defineProperty(exports, "KeycloakJWTVerifier", { enumerable: true, get: function () { return bridge_1.KeycloakJWTVerifier; } });
40
46
  Object.defineProperty(exports, "newDefaultVerifier", { enumerable: true, get: function () { return bridge_1.newDefaultVerifier; } });
@@ -43,3 +49,15 @@ Object.defineProperty(exports, "resolveBridgeUserId", { enumerable: true, get: f
43
49
  Object.defineProperty(exports, "getOrProvisionUserFromClaims", { enumerable: true, get: function () { return bridge_1.getOrProvisionUserFromClaims; } });
44
50
  Object.defineProperty(exports, "bridgeListKeys", { enumerable: true, get: function () { return bridge_1.bridgeListKeys; } });
45
51
  Object.defineProperty(exports, "bridgeGenerateKey", { enumerable: true, get: function () { return bridge_1.bridgeGenerateKey; } });
52
+ var permissions_1 = require("./permissions");
53
+ Object.defineProperty(exports, "litellmPermissions", { enumerable: true, get: function () { return permissions_1.litellmPermissions; } });
54
+ Object.defineProperty(exports, "litellmKeyCreatePermission", { enumerable: true, get: function () { return permissions_1.litellmKeyCreatePermission; } });
55
+ Object.defineProperty(exports, "litellmKeyRevokePermission", { enumerable: true, get: function () { return permissions_1.litellmKeyRevokePermission; } });
56
+ Object.defineProperty(exports, "litellmKeyManagePermission", { enumerable: true, get: function () { return permissions_1.litellmKeyManagePermission; } });
57
+ Object.defineProperty(exports, "litellmAuditReadPermission", { enumerable: true, get: function () { return permissions_1.litellmAuditReadPermission; } });
58
+ Object.defineProperty(exports, "litellmTeamCreatePermission", { enumerable: true, get: function () { return permissions_1.litellmTeamCreatePermission; } });
59
+ Object.defineProperty(exports, "litellmTeamManagePermission", { enumerable: true, get: function () { return permissions_1.litellmTeamManagePermission; } });
60
+ Object.defineProperty(exports, "litellmTeamMembersManagePermission", { enumerable: true, get: function () { return permissions_1.litellmTeamMembersManagePermission; } });
61
+ Object.defineProperty(exports, "litellmTeamKnowledgebaseManagePermission", { enumerable: true, get: function () { return permissions_1.litellmTeamKnowledgebaseManagePermission; } });
62
+ Object.defineProperty(exports, "litellmTeamMcpManagePermission", { enumerable: true, get: function () { return permissions_1.litellmTeamMcpManagePermission; } });
63
+ Object.defineProperty(exports, "litellmTeamDeletePermission", { enumerable: true, get: function () { return permissions_1.litellmTeamDeletePermission; } });
@@ -0,0 +1,11 @@
1
+ export declare const litellmKeyCreatePermission: import("@backstage/plugin-permission-common").BasicPermission;
2
+ export declare const litellmKeyRevokePermission: import("@backstage/plugin-permission-common").BasicPermission;
3
+ export declare const litellmKeyManagePermission: import("@backstage/plugin-permission-common").BasicPermission;
4
+ export declare const litellmAuditReadPermission: import("@backstage/plugin-permission-common").BasicPermission;
5
+ export declare const litellmTeamCreatePermission: import("@backstage/plugin-permission-common").BasicPermission;
6
+ export declare const litellmTeamManagePermission: import("@backstage/plugin-permission-common").BasicPermission;
7
+ export declare const litellmTeamMembersManagePermission: import("@backstage/plugin-permission-common").BasicPermission;
8
+ export declare const litellmTeamKnowledgebaseManagePermission: import("@backstage/plugin-permission-common").BasicPermission;
9
+ export declare const litellmTeamMcpManagePermission: import("@backstage/plugin-permission-common").BasicPermission;
10
+ export declare const litellmTeamDeletePermission: import("@backstage/plugin-permission-common").BasicPermission;
11
+ export declare const litellmPermissions: import("@backstage/plugin-permission-common").BasicPermission[];
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.litellmPermissions = exports.litellmTeamDeletePermission = exports.litellmTeamMcpManagePermission = exports.litellmTeamKnowledgebaseManagePermission = exports.litellmTeamMembersManagePermission = exports.litellmTeamManagePermission = exports.litellmTeamCreatePermission = exports.litellmAuditReadPermission = exports.litellmKeyManagePermission = exports.litellmKeyRevokePermission = exports.litellmKeyCreatePermission = void 0;
4
+ const plugin_permission_common_1 = require("@backstage/plugin-permission-common");
5
+ exports.litellmKeyCreatePermission = (0, plugin_permission_common_1.createPermission)({
6
+ name: 'litellm.key.create',
7
+ attributes: { action: 'create' },
8
+ });
9
+ exports.litellmKeyRevokePermission = (0, plugin_permission_common_1.createPermission)({
10
+ name: 'litellm.key.revoke',
11
+ attributes: { action: 'delete' },
12
+ });
13
+ exports.litellmKeyManagePermission = (0, plugin_permission_common_1.createPermission)({
14
+ name: 'litellm.key.manage',
15
+ attributes: { action: 'update' },
16
+ });
17
+ exports.litellmAuditReadPermission = (0, plugin_permission_common_1.createPermission)({
18
+ name: 'litellm.audit.read',
19
+ attributes: { action: 'read' },
20
+ });
21
+ // Team-management permissions — delegated to litellm-team-admins group
22
+ exports.litellmTeamCreatePermission = (0, plugin_permission_common_1.createPermission)({
23
+ name: 'litellm.team.create',
24
+ attributes: { action: 'create' },
25
+ });
26
+ exports.litellmTeamManagePermission = (0, plugin_permission_common_1.createPermission)({
27
+ name: 'litellm.team.manage',
28
+ attributes: { action: 'update' },
29
+ });
30
+ exports.litellmTeamMembersManagePermission = (0, plugin_permission_common_1.createPermission)({
31
+ name: 'litellm.team.members.manage',
32
+ attributes: { action: 'update' },
33
+ });
34
+ exports.litellmTeamKnowledgebaseManagePermission = (0, plugin_permission_common_1.createPermission)({
35
+ name: 'litellm.team.knowledgebase.manage',
36
+ attributes: { action: 'update' },
37
+ });
38
+ exports.litellmTeamMcpManagePermission = (0, plugin_permission_common_1.createPermission)({
39
+ name: 'litellm.team.mcp.manage',
40
+ attributes: { action: 'update' },
41
+ });
42
+ exports.litellmTeamDeletePermission = (0, plugin_permission_common_1.createPermission)({
43
+ name: 'litellm.team.delete',
44
+ attributes: { action: 'delete' },
45
+ });
46
+ exports.litellmPermissions = [
47
+ exports.litellmKeyCreatePermission,
48
+ exports.litellmKeyRevokePermission,
49
+ exports.litellmKeyManagePermission,
50
+ exports.litellmAuditReadPermission,
51
+ exports.litellmTeamCreatePermission,
52
+ exports.litellmTeamManagePermission,
53
+ exports.litellmTeamMembersManagePermission,
54
+ exports.litellmTeamKnowledgebaseManagePermission,
55
+ exports.litellmTeamMcpManagePermission,
56
+ exports.litellmTeamDeletePermission,
57
+ ];
package/dist/plugin.js CHANGED
@@ -4,6 +4,7 @@ exports.litellmPlugin = void 0;
4
4
  const backend_plugin_api_1 = require("@backstage/backend-plugin-api");
5
5
  const router_1 = require("./router");
6
6
  const bridge_1 = require("./bridge");
7
+ const permissions_1 = require("./permissions");
7
8
  exports.litellmPlugin = (0, backend_plugin_api_1.createBackendPlugin)({
8
9
  pluginId: 'litellm',
9
10
  register(reg) {
@@ -14,9 +15,18 @@ exports.litellmPlugin = (0, backend_plugin_api_1.createBackendPlugin)({
14
15
  logger: backend_plugin_api_1.coreServices.logger,
15
16
  auth: backend_plugin_api_1.coreServices.auth,
16
17
  discovery: backend_plugin_api_1.coreServices.discovery,
18
+ permissions: backend_plugin_api_1.coreServices.permissions,
19
+ permissionsRegistry: backend_plugin_api_1.coreServices.permissionsRegistry,
17
20
  },
18
- async init({ httpRouter, config, logger, auth, discovery }) {
19
- const router = await (0, router_1.createRouter)({ config, logger, auth, discovery });
21
+ async init({ httpRouter, config, logger, auth, discovery, permissions, permissionsRegistry, }) {
22
+ permissionsRegistry.addPermissions(permissions_1.litellmPermissions);
23
+ const router = await (0, router_1.createRouter)({
24
+ config,
25
+ logger,
26
+ auth,
27
+ discovery,
28
+ permissions,
29
+ });
20
30
  httpRouter.use(router);
21
31
  // The CLI bridge verifies raw Keycloak JWTs itself (it does NOT use a
22
32
  // Backstage-issued token). Exempt its routes from the default auth
@@ -1,5 +1,5 @@
1
1
  import { Config } from '@backstage/config';
2
- import { AuthService } from '@backstage/backend-plugin-api';
2
+ import { AuthService, BackstageCredentials } from '@backstage/backend-plugin-api';
3
3
  import { CatalogClient } from '@backstage/catalog-client';
4
4
  import { Request } from 'express';
5
5
  import { LiteLLMClient } from './client';
@@ -45,6 +45,11 @@ export declare function readProvisioningDefaults(config: Config): {
45
45
  * the request carries no user credential (service-to-service calls).
46
46
  */
47
47
  export declare function resolveUserId(req: Request, auth: AuthService): Promise<string | undefined>;
48
+ /**
49
+ * Like resolveUserId, but returns the raw BackstageCredentials object
50
+ * (rather than just the entity ref) for passing into PermissionsService.authorize().
51
+ */
52
+ export declare function resolveCredentials(req: Request, auth: AuthService): Promise<BackstageCredentials | undefined>;
48
53
  /**
49
54
  * Profile data extracted from a Backstage Catalog User entity, used to
50
55
  * populate user_email / user_alias on the LiteLLM record.
@@ -6,6 +6,7 @@ exports.readRoleConfigs = readRoleConfigs;
6
6
  exports.applyRoleOverrides = applyRoleOverrides;
7
7
  exports.readProvisioningDefaults = readProvisioningDefaults;
8
8
  exports.resolveUserId = resolveUserId;
9
+ exports.resolveCredentials = resolveCredentials;
9
10
  exports.resolveUserProfile = resolveUserProfile;
10
11
  exports.provisionUser = provisionUser;
11
12
  exports.getOrProvisionUser = getOrProvisionUser;
@@ -116,6 +117,21 @@ async function resolveUserId(req, auth) {
116
117
  }
117
118
  return undefined;
118
119
  }
120
+ /**
121
+ * Like resolveUserId, but returns the raw BackstageCredentials object
122
+ * (rather than just the entity ref) for passing into PermissionsService.authorize().
123
+ */
124
+ async function resolveCredentials(req, auth) {
125
+ const rawToken = req.headers.authorization?.slice(7);
126
+ if (!rawToken)
127
+ return undefined;
128
+ try {
129
+ return await auth.authenticate(rawToken);
130
+ }
131
+ catch {
132
+ return undefined;
133
+ }
134
+ }
119
135
  /**
120
136
  * Looks up the catalog User entity for the authenticated user and returns
121
137
  * the profile block. Returns an empty object when the user has no catalog
package/dist/router.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { Router } from 'express';
2
2
  import { Config } from '@backstage/config';
3
- import { AuthService, DiscoveryService } from '@backstage/backend-plugin-api';
3
+ import { AuthService, DiscoveryService, PermissionsService } from '@backstage/backend-plugin-api';
4
+ import { CatalogClient } from '@backstage/catalog-client';
4
5
  import { LiteLLMClient } from './client';
5
6
  import { ProvisioningError } from './provisioning';
6
7
  import { TokenVerifier } from './bridge';
@@ -10,8 +11,11 @@ export interface RouterOptions {
10
11
  logger: any;
11
12
  auth: AuthService;
12
13
  discovery: DiscoveryService;
14
+ permissions: PermissionsService;
13
15
  /** Override the LiteLLM client (tests). Defaults to one built from config. */
14
16
  client?: LiteLLMClient;
17
+ /** Override the catalog client (tests). Defaults to one built from discovery. */
18
+ catalogClient?: CatalogClient;
15
19
  /** Override the bridge token verifier (tests). Defaults to a Keycloak JWKS verifier. */
16
20
  tokenVerifier?: TokenVerifier;
17
21
  }