import { Request } from 'express'; import { Config } from '@backstage/config'; import { AuthService, PermissionsService } from '@backstage/backend-plugin-api'; import { BasicPermission } from '@backstage/plugin-permission-common'; import { CatalogClient } from '@backstage/catalog-client'; /** * Default hard ceiling (USD) for an admin-set team budget when * `litellm.teamAdmin.maxBudgetCeiling` is not configured. Chosen so the * feature is usable out of the box without letting an admin set an unbounded * team budget by omission. */ export declare const DEFAULT_TEAM_BUDGET_CEILING = 1000; /** * Governance limits for the team-administration feature. Every field is * fail-closed: an unset array means "nothing allowed", an unset boolean means * "deny", and an unset ceiling means "no admin-settable budget". An absent * `litellm.teamAdmin` block therefore leaves the feature completely dark. */ export interface TeamAdminConfig { /** * Backstage group entity ref whose members may manage teams, * e.g. "group:default/litellm-team-admins". * Undefined => feature stays disabled. */ group?: string; /** * LiteLLM model names an admin may assign to a team. * Empty => none assignable (fail-closed). */ allowedModels: string[]; /** * LiteLLM model access-group names an admin may assign. * Empty => none. */ allowedModelAccessGroups: string[]; /** * Hard USD ceiling for a team's max_budget an admin may set. Always a * number — defaults to DEFAULT_TEAM_BUDGET_CEILING when not configured. */ maxBudgetCeiling: number; /** * Allow an admin to create a team with no budget cap. */ allowUnlimitedBudget: boolean; /** * Vector-store ids/names an admin may attach as team knowledge bases. * Empty => none. */ allowedVectorStores: string[]; /** * MCP server ids/names an admin may attach to a team. * Empty => none. */ allowedMcpServers: string[]; /** * MCP access-group names an admin may attach. * Empty => none. */ allowedMcpAccessGroups: string[]; /** * Allow an admin to delete a team (vs. only block/deactivate). */ allowTeamDelete: boolean; } /** * Whether team-management routes should be mounted. * Requires permission.enabled AND a designated admin group. * Returns false when either is missing (fail-closed). */ export declare function isTeamManagementEnabled(config: Config): boolean; /** * Whether the object-permission routes (knowledge bases / MCP servers) should * be mounted. Requires team management to be enabled AND an explicit * `litellm.teamAdmin.objectPermissions.enabled: true` opt-in, because these * routes grant data access (vector stores) and tool execution (MCP) to every * team key. Fail-closed: any missing piece disables the whole surface. */ export declare function isObjectPermissionsEnabled(config: Config): boolean; /** * Discriminated result: either successful auth or a failure with HTTP status + error message. */ export type TeamAdminCheck = { ok: true; userEntityRef: string; } | { ok: false; status: 401 | 403; error: string; }; /** * Layered fail-closed authz check for team-management operations. * * This is the security primitive that gates all team-write routes. It checks in order: * 1. Authentication (user identity from token) * 2. Group membership (user in the designated litellm-team-admins group) * 3. Permission framework decision (via assertPermission, defaults to DENY if no policy) * * ALL three must pass. The group membership check exists because the permission * framework alone cannot be trusted — its default depends on the policy engine * (permissive if unconfigured), so we layer a guaranteed group check on top. * * Callers: check `result.ok` and respond with `status` + `error` when false. */ export declare function assertTeamAdmin(opts: { req: Request; auth: AuthService; permissions: PermissionsService; catalogClient: CatalogClient; teamAdminGroup: string; permission: BasicPermission; logger: any; }): Promise; /** * Reads the team-admin governance block from config, applying fail-closed * defaults for every field: unset arrays remain empty (nothing allowed), unset * booleans stay false (deny by default), and an undefined ceiling means no * admin-settable budget. * * Fail-closed rationale: a governance feature is only safe when absent config * defaults to "deny all". An unconfigured teamAdmin block must leave the feature * completely dark, ready to be explicitly enabled only once an operator has * reviewed and understood the delegation policy. */ export declare function readTeamAdminConfig(config: Config): TeamAdminConfig; export interface TeamWriteInput { team_alias?: string; models?: string[]; max_budget?: number | null; budget_duration?: string; tpm_limit?: number; rpm_limit?: number; } export type TeamWriteValidation = { ok: true; value: { team_alias: string; models: string[]; max_budget?: number; budget_duration?: string; tpm_limit?: number; rpm_limit?: number; }; } | { ok: false; error: string; }; export declare function validateTeamWriteInput(input: TeamWriteInput, cfg: TeamAdminConfig): TeamWriteValidation; export type TeamPatchValidation = { ok: true; value: Record; } | { ok: false; error: string; }; export declare function validateTeamPatchInput(input: TeamWriteInput & { blocked?: boolean; }, cfg: TeamAdminConfig): TeamPatchValidation;