Commit graph

35941 commits

Author SHA1 Message Date
yuneng-jiang
9cfc5b97de [Fix] Search Tools: Handle wildcard "*" default in permissions and move auth helper
The DB migration sets search_tools DEFAULT ARRAY['*'], but the auth check
and listing filter treated "*" as a literal name, causing 401s and empty
list responses for all callers with the default permission.

- Add wildcard handling in _can_object_call_search_tools
- Add _normalize_search_tools_wildcard to convert ["*"] → None (no restriction)
- Move get_allowed_search_tool_names from endpoints.py to auth_checks.py
  to eliminate cross-router import between search_tool_management and endpoints

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 17:50:25 -07:00
yuneng-jiang
d8704a59db poetry lock 2026-03-21 17:43:59 -07:00
yuneng-jiang
0ca2472d83 fix(types): resolve mypy errors in search_tool_management.py
Add type casts for TypedDict .get() calls and rename loop variable to
avoid type shadowing between config and DB search tool iterations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 17:31:48 -07:00
yuneng-jiang
5da2f35fd3 adding build 2026-03-21 17:28:26 -07:00
yuneng-jiang
b69fd49af6 bump: version 0.4.58 → 0.4.59 2026-03-21 17:28:01 -07:00
yuneng-jiang
efa5a3fc69 [Feature] UI - Search Tools: Add permissions UI, modernize page, infinite team dropdown
Add search_tools permission support across the UI (key create/edit, team create,
object permissions view) with breaking-change alerts for the new least-privilege
default. Modernize the Search Tools page with AntD Tabs, a Test playground tab,
and ProviderLogo integration. Migrate TeamDropdown to self-fetching infinite
scroll pattern using useInfiniteTeams hook. Scope search tools visibility for
internal users based on their team memberships.

Backend: Add search_tools field to Prisma schema (all copies), Pydantic models
(ObjectPermissionBase + ObjectPermissionTable), and allowed routes for virtual
keys. Add permission filtering to /search_tools/list endpoint. Include
object_permission in team list v2 queries.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 17:23:49 -07:00
yuneng-jiang
75bd742d18
Merge pull request #24239 from BerriAI/litellm_ui_vitest_coverage
[Test] UI: Add vitest coverage for 10 untested components
2026-03-21 14:38:35 -07:00
yuneng-jiang
9f7e65a92d fix(test): add missing team_id to MCP mock tests and update auth test
Tests using MagicMock for MCPServerTable were missing the new team_id
field, causing Pydantic validation errors. Updated auth failure test
to expect 400 (team_id required) instead of 403 since non-admin users
now must provide team_id before permission checks.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 14:26:36 -07:00
yuneng-jiang
33aa190b16 fix(test): add missing team_id to MCP sigv4 test mocks
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 14:21:04 -07:00
yuneng-jiang
dae638b2f0 fix(test): update internal user test to match new create flow
Internal users can now see the create modal (with a team selection
prompt). Updated the test from asserting the modal is hidden to
asserting the team selection prompt is shown.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 14:14:34 -07:00
yuneng-jiang
1a63a7bab8 fix(test): update mcp_servers tests for removed Alias column and Team header
- Remove assertions for alias text (column was removed)
- Disambiguate "Team" filter label from "Team (Owner)" column header

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 14:11:54 -07:00
yuneng-jiang
5c953c6b61 fix(ui): handle nullable userRole after removing early return guard
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 14:04:58 -07:00
yuneng-jiang
8366d24e22 fix(ui): use old leftnav (SidebarProvider) in dashboard layout for path-routed pages
The dashboard layout was using Sidebar2, which routed all entries to
path-based URLs like /ui/keys — but only api-reference has been migrated.
Switch back to the old leftnav so unmigrated pages navigate to the legacy
root page (?page=X) and migrated pages use path routing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 13:14:56 -07:00
yuneng-jiang
83eac06b32 feat(ui): add TeamDropdown to MCP create form, fix health recheck cache
- Add TeamDropdown as first field in create MCP server form
- For internal users, hide form fields until team is selected
- Fix useMCPServerHealth to append new servers to cache on recheck

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 13:12:36 -07:00
yuneng-jiang
456e326c95 fix(ui): reduce MCP table columns and add explicit column widths
Removed low-value columns (Alias, Auth Type, Updated) to reduce
horizontal overflow. Added explicit size hints to remaining columns.
DataTable now applies column sizes to header and body cells.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 13:11:22 -07:00
yuneng-jiang
a022956724 fix: propagate team_id through MCPServer registry and list responses
Added team_id to the MCPServer model class, build_mcp_server_from_table,
and _build_mcp_server_table so team_id flows from DB → registry →
list endpoint responses.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 13:08:00 -07:00
yuneng-jiang
478ec3d392 fix(ui): remove early loading return, let DataTable handle loading state
The early return on missing auth params blocked the entire page from
rendering. The hooks already guard on accessToken being available, and
DataTable shows its own loading state via isLoading prop.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 13:04:30 -07:00
yuneng-jiang
baa1fa4151 feat(ui): add Team (Owner) column to MCP servers table
Shows the owning team alias resolved from team_id. Global servers
(team_id=null) display "Global". Header includes info icon explaining
that only servers from teams with mcp:read permission are visible.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 13:03:25 -07:00
yuneng-jiang
79ca00bbec fix(ui): show helpful empty state for internal users without MCP access
The list endpoint returns an empty list (not 403) when a user has no
MCP servers available. For internal users, show a message suggesting
they may need mcp:read permission or team MCP server assignments.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 12:59:44 -07:00
yuneng-jiang
017d87b7ab fix(ui): show helpful error when user lacks MCP read permission
Replace "Missing required authentication parameters" with a loading
state. When the MCP servers fetch fails (e.g. 403), show a clear
error message with steps on how to get mcp:read permission.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 12:58:38 -07:00
yuneng-jiang
535c368f3b fix: proxy admin delete now cleans up ObjectPermissionTable
When a proxy admin deleted an MCP server, team_id was None so
remove_mcp_server_from_team was skipped, leaving stale server IDs
in the team's ObjectPermissionTable. Now fetches the server's
team_id before deletion to ensure cleanup.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 12:50:12 -07:00
yuneng-jiang
e4611faf58 fix: invalidate ObjectPermissionTable cache alongside team cache
_invalidate_team_cache only cleared the team object cache but not the
ObjectPermissionTable cache. After add_mcp_server_to_team, the team
was re-fetched from DB but its object_permission was served from stale
cache, causing newly created servers to not appear in the list.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 12:46:33 -07:00
yuneng-jiang
bb019c8920 fix: ownership transfer DB writes and registry reload ordering
Move team_id clear-to-null and ObjectPermissionTable sync before
registry reload so the cache reflects the new ownership state.
Also update the response object when clearing team_id to null.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 12:36:50 -07:00
yuneng-jiang
bdab813f21 test: add MCP server team ownership tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 12:28:24 -07:00
yuneng-jiang
5151a835a3 chore: remove unused get_objectpermissions_for_mcp_server import 2026-03-21 12:24:48 -07:00
yuneng-jiang
f51078761a types(ui): add team_id to MCPServer interface 2026-03-21 12:24:41 -07:00
yuneng-jiang
4dd2089eee feat: update endpoint uses server.team_id for auth, supports ownership transfer
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 12:24:00 -07:00
yuneng-jiang
c99257ddd4 feat: delete endpoint uses server.team_id for ownership auth
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 12:20:43 -07:00
yuneng-jiang
9ff49bc75b feat: set team_id ownership on MCP server creation, registration, and approval
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 12:18:01 -07:00
yuneng-jiang
cc17c370de types: add team_id to MCPServerTable and UpdateMCPServerRequest models 2026-03-21 12:15:09 -07:00
yuneng-jiang
c893324a5b schema: add team_id column to LiteLLM_MCPServerTable for ownership tracking 2026-03-21 12:14:49 -07:00
yuneng-jiang
334c455150 db: persist team_id on MCP server create and update 2026-03-21 12:14:43 -07:00
yuneng-jiang
31bc13eb17 Merge branch 'main' into litellm_yj_march_20_2026 2026-03-21 10:27:05 -07:00
yuneng-jiang
185db1941f
Merge pull request #24075 from BerriAI/litellm_search-tool-permissions-f5e4
[Feature] Search Tools: Add access control via object permissions
2026-03-21 10:23:08 -07:00
yuneng-jiang
9051bf1e63 chore: remove migration file (will be created via standard process)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 10:07:15 -07:00
yuneng-jiang
2c4be6f5c7 fix: nullable schema, remove dead code, add return type annotation
- Make search_tools String[]? (nullable) in all 3 schema.prisma files
  so Prisma preserves NULL from DB instead of coercing to []
- Remove get_permitted_search_tool_names (dead code — never called
  from any production path) and its tests
- Add -> bool return type annotation to _can_object_call_search_tools

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 10:02:47 -07:00
yuneng-jiang
9019207111 fix: revert out-of-scope changes, fix remaining review feedback
- Revert MCP management endpoint changes: team-scoped CRUD depends on
  check_member_permission, add_mcp_server_to_team, remove_mcp_server_from_team
  which exist only in the base branch, not main. Importing them crashes
  all MCP endpoints on main.
- Revert ObjectPermissionTable default changes for pre-existing fields
  (mcp_servers, mcp_access_groups, vector_stores, agents, agent_access_groups)
  back to [] to avoid backwards-incompatible behavior change. Only
  search_tools (new field) uses None default.
- Restore vector store access check: [] = allow all (existing behavior)
- Restore vector store test assertion
- Revert common_utils.py inline import changes (infrastructure not in scope)
- Add ValueError fallback to get_search_tool_access_error_type_for_object
  for unrecognized object_type values

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 09:42:49 -07:00
yuneng-jiang
d1a0b94919 fix: address greptile feedback on search_tools RBAC
- Migration: remove DEFAULT ARRAY[]::TEXT[] so existing rows get NULL
  (NULL = all access) instead of [] (no access)
- Schema: remove @default([]) for search_tools in all 3 schema.prisma files
- Use cached get_object_permission instead of raw DB queries in
  search_tool_access_check and _get_allowed_search_tool_names
- Reject requests with missing search_tool_name (400) instead of
  silently bypassing access control
- Fix vector store test: [] now correctly denies access (not allows)
- Update search_tool_access_check tests to mock get_object_permission

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 09:28:08 -07:00
yuneng-jiang
071e590f80
Merge pull request #24274 from BerriAI/litellm_mcp_team_member_ui
[Feature] UI - MCP: Team member permissions drawer and CRUD access
2026-03-21 09:06:10 -07:00
yuneng-jiang
bca07dca61 fix: change ObjectPermissionTable defaults from [] to None, add team-scoped MCP RBAC
- Change all ObjectPermissionTable array field defaults from [] to None
  (None = all access / no restriction, [] = no access)
- Update vector store access check: [] now denies access instead of allowing all
- Add team-scoped MCP server management (create/update/delete) with
  granular permissions (mcp:create, mcp:update, mcp:delete)
- Auto-assign created servers to team's ObjectPermissionTable
- Auto-remove deleted servers from team's ObjectPermissionTable
- Fix unreachable special MCP server name guard in add_mcp_server
- Fix server_id validation ordering in edit_mcp_server
- Fix description typo on PUT /server endpoint
- Move inline imports to module level in common_utils.py (CLAUDE.md)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 00:37:20 -07:00
yuneng-jiang
5905100cdc address greptile review feedback (greploop iteration 3)
- Fix double error handling in getTeamPermissionsCall: return empty data
  on HTTP error instead of calling handleError + throwing, preventing
  duplicate error notifications

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 00:35:54 -07:00
yuneng-jiang
290706a708 address greptile review feedback (greploop iteration 3)
- Fix double error handling in getTeamPermissionsCall: return empty data
  on HTTP error instead of calling handleError + throwing, preventing
  duplicate error notifications

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 00:35:36 -07:00
yuneng-jiang
24be81094b address greptile review feedback (greploop iteration 2)
- Fix unknown permissions duplication: seed selected state with only known
  permissions so existingUnknown and selected are disjoint on save
- Disable Add MCP Server button for non-admins without a team selected,
  show tooltip explaining they need to select a team first

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 00:28:27 -07:00
yuneng-jiang
42fe911e1c address greptile review feedback (greploop iteration 1)
- Separate save failure from refresh failure: close drawer after successful
  save even if teamInfoCall refresh fails
- Preserve unknown permissions not in availablePermissions when saving,
  preventing silent drops of permissions from newer backend versions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 00:21:39 -07:00
yuneng-jiang
4f98b4ea3c address greptile review feedback
- Type onUpdate as () => Promise<void> and await it before closing drawer
- Replace accessToken! assertion with explicit null guard
- Gate fetchAvailableTeamMemberPermissions behind canEditTeam check
- Pass team_id for admins too when a team is selected in the filter

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 23:59:42 -07:00
yuneng-jiang
18fae5377e [Feature] UI - MCP: Team member permissions drawer and CRUD access
Add UI support for the MCP team management permissions introduced in PR #24266.

- Add MemberPermissionsDrawer component (Ant Design Drawer) for managing
  per-member MCP permissions (mcp:read, mcp:create, mcp:update, mcp:delete)
- Add permissions button to team member table actions column
- Fetch available permissions from GET /team/available_permissions
- Pass extra_permissions in team member update API calls
- Allow all users to create MCP servers directly (backend enforces permissions)
- Pass team_id when non-admin users create MCP servers

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 23:52:55 -07:00
yuneng-jiang
db8050bb60
Merge pull request #24259 from BerriAI/litellm_ui_refactor_policy_versions_hook
[Refactor] UI - Policies: Extract usePolicyVersions Hook
2026-03-20 23:45:31 -07:00
yuneng-jiang
492c0cd3ba address greptile review feedback (greploop iteration 3)
- Move callbacks outside try/catch so only mutation errors are caught,
  not errors from onVersionCreated/onVersionStatusUpdated callbacks
- Replace policyName! non-null assertion with DISABLED_POLICY_KEY
  sentinel to avoid undefined in cache keys when query is disabled

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 23:39:01 -07:00
yuneng-jiang
41d12ed106 address greptile review feedback (greploop iteration 2)
- Add PolicyVersionsData type for select output; specify TData generic
  so consumers get Policy[] (not Policy[] | undefined) for versions
- Remove empty-string queryKey fallback — use policyName! since
  enabled:false prevents fetch when policyName is null
- Add cache invalidation tests for both mutation hooks
- Add explanatory comment for ?? [] fallback in component

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 23:33:50 -07:00
yuneng-jiang
80e55804af [Fix] UI - Policies: Type accuracy and mutation guard for usePolicyVersions
- Make PolicyVersionsResponse.versions optional (Policy[] | undefined)
  to match real API shape — select fallback handles normalization
- Add policyName guard to useUpdatePolicyVersionStatus mutationFn
  to fail loudly instead of silently skipping cache invalidation
- Add test for null policyName in updateStatus mutation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 23:27:02 -07:00