Commit Graph
459 Commits
Author SHA1 Message Date
Ryan Crabbe fdd2672e93 feat: add POST /team/permissions_bulk_update endpoint
Adds a new endpoint to bulk-update team_member_permissions across
teams. Supports apply_to_all_teams (with cursor-based pagination)
or a specific list of team_ids. Merges new permissions into each
team's existing set rather than overwriting.

Also fixes test isolation bug in test_get_prompt_info_by_base_id
where leaked prisma_client state from other tests caused a
TypeError on await.
2026-04-06 17:45:35 -07:00
Yuneng JiangandClaude Opus 4.6 566a04126f test: add unit tests for _get_team_deployments filtering logic
Tests cover: matching deployments, wrong team_id filtering, string-encoded
model_info, empty results, invalid model_info, and mixed deployment filtering.
Also updates MockPrismaClient.find_many to support the new startswith query.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 14:34:39 -07:00
ryan-crabbe-berriandGitHub 0331fb5a8f Merge pull request #25027 from BerriAI/litellm_add-access-group-to-model
feat(teams): resolve access group resources in team endpoints
2026-04-03 17:22:47 -07:00
Ryan Crabbe 93369bf60d perf(teams): batch-fetch access groups in single DB query
Replace per-ID _resolve_access_group_resources loop with a single
find_many call that deduplicates IDs across all teams. Removes the
N+1 query pattern on cold cache for the team list endpoint.
2026-04-03 17:13:56 -07:00
Ryan Crabbe 38f6c9491d fix(tests): correct mock targets in TestResolveAccessGroupResources
Three tests were patching the non-existent `get_access_object` instead
of `_get_access_object` (the lazy-import wrapper), causing AttributeError.
Also added missing `prisma_client` mock so tests get past the early-exit
guard and actually exercise the resolution logic.
2026-04-03 16:16:55 -07:00
+1
ishaan-berriGitHubmichelligabrieleSameer KankuteredhelixSynergyTalha AnwarClaude Opus 4.6madhu19991Srikanth @adobe <devarakondasrikanth@users.noreply.github.com>github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
c6aa3ea452 Litellm ishaan april1 try2 (#25110)
* Litellm ishaan april1 (#25103)

* fix(proxy): enforce upperbound key params on key/update and add custom_key_update hook

The /key/update endpoint did not enforce upperbound_key_generate_params,
allowing users to bypass configured limits (tpm_limit, rpm_limit,
max_budget, duration, budget_duration) by updating an existing key
instead of generating a new one.

Extract the upperbound enforcement logic from _common_key_generation_helper()
into a standalone _enforce_upperbound_key_params() function and call it from
both the generate and update paths. For updates, None values are skipped
(not filled with defaults) since they mean "don't change this field".

Also adds a custom_key_update config option and user_custom_key_update global,
mirroring the existing custom_key_generate pattern, so custom key validation
logic can fire during key updates as well.

* fix(proxy): invoke custom_key_update hook in bulk update path

The user_custom_key_update hook was only called in update_key_fn
(single key update) but not in _process_single_key_update (bulk
update path), allowing custom validation to be bypassed via the
/key/update/bulk endpoint. Mirror the hook invocation in both paths.

* fix(proxy): pass UpdateKeyRequest to hook in bulk path, not BulkUpdateKeyRequestItem

Move the custom_key_update hook invocation to after UpdateKeyRequest
is constructed so the hook receives the same type in both single and
bulk update paths. Previously the bulk path passed
BulkUpdateKeyRequestItem (5 fields only), which would cause
AttributeError for hooks accessing fields like tpm_limit or models.

* fix(bedrock): promote cache usage to message_delta for Claude Code (#24850)

Ensure Bedrock/Anthropic-compatible streaming exposes cache usage where Claude Code reads it by promoting message_stop usage onto message_delta and preserving usage fields in fake-streamed message_delta events.

Made-with: Cursor

* fix(search): Support self-hosted Firecrawl response format in search transform (#24866)

The `transform_search_response` method only handled Firecrawl Cloud (v2)
response format where `data` is a dict with `web`/`news` keys. Self-hosted
Firecrawl (v1) returns `data` as a flat list of result objects, causing an
`AttributeError: 'list' object has no attribute 'get'`.

Detect the response format by checking if `data` is a list (self-hosted)
or dict (cloud) and handle both cases.

Cloud format:  {"data": {"web": [...], "news": [...]}}
Self-hosted:   {"success": true, "data": [{"url": "...", "title": "...", ...}]}

Co-authored-by: Synergy <synergyoclaw@gmail.com>

* feat: add environment and user tracking to prompt management (#24855)

* feat: add environment and user tracking to prompt management

- Add environment (development/staging/production) and created_by columns to LiteLLM_PromptTable
- Update unique constraint to [prompt_id, version, environment]
- All CRUD endpoints support environment filtering and user tracking
- Redesigned prompt detail page with environment tabs and version history
- UI: environment filter on list page, environment selector in editor
- 8 new tests for environment and user tracking

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: Black formatting and add environments to PromptInfoResponse TypeScript type

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address Greptile review findings

- P1: delete_prompt scopes in-memory cleanup to environment when provided
- P2: dotprompt_content parsed directly regardless of environment flag
- P2: use distinct for environments query
- P2: fix double-fetch on initial mount in prompt_info.tsx
- fix: remove unsupported select kwarg from find_many

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address remaining Greptile review comments

- Remove unused useCallback import (index.tsx)
- Remove unused ENV_COLORS variable (prompt_info.tsx)
- P1: in-memory fallback in get_prompt_versions now respects environment filter
- P1: reset selectedEnv when promptId changes to avoid stale state
- Cyclic imports are pre-existing pattern, not introduced by this PR

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: scope patch_prompt to environment using primary key

- Add environment query param to patch_prompt endpoint
- Look up target row by composite key (prompt_id + version + environment)
- Update by primary key (id) to target exactly one row
- Fixes Greptile finding: patch with multiple environments no longer ambiguous

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: use actual start_time for failed request spend logs (#24906)

async_post_call_failure_hook set both start_time and end_time to
datetime.now(), making all failed requests show duration=0. Use the
actual start_time from litellm_logging_obj instead, so spend logs
reflect the real request duration on timeout and other failures.

Fixes #24888

* feat(bedrock): add nova canvas image edit support (#24869)

* feat(bedrock): add nova canvas image edit support

* fix(bedrock): support PathLike inputs for nova image edit

* chore: sync schema.prisma copies from root

* fix(mypy): correct type-ignore code for delta_usage arg-type

* fix(mypy): cast status_code to str, suppress intentional str yield

* fix(lint): extract _create_content_block_chunks to fix PLR0915

* fix(lint): extract helpers to fix PLR0915 in prompt endpoints

---------

Co-authored-by: michelligabriele <gabriele.michelli@icloud.com>
Co-authored-by: Sameer Kankute <sameer@berri.ai>
Co-authored-by: redhelix <amin.lalji@gmail.com>
Co-authored-by: Synergy <synergyoclaw@gmail.com>
Co-authored-by: Talha Anwar <37379131+talhaanwarch@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: madhu19991 <madhu@thunkai.com>
Co-authored-by: Srikanth @adobe <devarakondasrikanth@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* fix(test): update model armor streaming test to handle string or int error code

---------

Co-authored-by: michelligabriele <gabriele.michelli@icloud.com>
Co-authored-by: Sameer Kankute <sameer@berri.ai>
Co-authored-by: redhelix <amin.lalji@gmail.com>
Co-authored-by: Synergy <synergyoclaw@gmail.com>
Co-authored-by: Talha Anwar <37379131+talhaanwarch@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: madhu19991 <madhu@thunkai.com>
Co-authored-by: Srikanth @adobe <devarakondasrikanth@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-04-03 14:57:44 -07:00
Ryan Crabbe bbe708b093 perf(teams): single-pass access group resolution + asyncio.gather in list endpoint
- Fetch each access group object once and extract all 3 resource fields
  in a single pass instead of 3 separate calls (3N → N lookups)
- Use asyncio.gather to resolve access groups across teams concurrently
  in list_team_v2 instead of sequential awaits
- Add 5 unit tests for _resolve_access_group_resources
2026-04-02 14:52:32 -07:00
David ChenandGitHub d1df4e838b Litellm fix update bedrock models (#24947)
* update bedrock models in tests

* updated more tests and model_prices_and_context_window

* fix model id and pricing

* replace more sonnet models

* update tests

* git push

* update pricing

* flaky total cost

* monkey patch

* relax the cost change

* fix and revert some changes

* revert the pricing

* chore: move cost/pricing changes to bedrock-cost-fixes branch

* chore: split Bedrock file-api beta stripping to separate branch

Removes strip_unsupported_file_api_betas_for_bedrock_invoke from this branch;
see litellm_bedrock_invoke_strip_file_api_betas for that fix.

Made-with: Cursor
2026-04-01 19:22:54 -07:00
ryan-crabbe-berriandGitHub 2f1cfb0548 Merge pull request #24751 from BerriAI/litellm_ryan-march-28
litellm ryan march 28
2026-03-31 17:25:30 -07:00
Yuneng JiangandClaude Opus 4.6 e014dfb8e0 fix: mock encrypt_value_helper in lifecycle test
CI fails because LITELLM_MASTER_KEY is not set, causing
encrypt_value_helper to error on NoneType.encode(). Patch it
to pass through values unencrypted in the test.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 21:36:40 -07:00
Yuneng JiangandClaude Opus 4.6 b48c037712 test: replace test_add_and_delete_models integration test with mock
Skip the integration test that requires a live proxy and OPENAI_API_KEY
(removed from CI/CD). Add deterministic mock test covering the same
add → delete → double-delete-fails lifecycle.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 21:30:57 -07:00
Ryan Crabbe a59acc8f8a [Fix] Derive use_substring_matching from role, not auto-set path
Substring matching for user_id and key_alias on /key/list is now gated
by caller role (admin only) rather than by whether user_id was auto-set.
This closes the gap where a non-admin explicitly passing their own
user_id still got contains-based filtering, which could surface keys
belonging to other users with overlapping IDs.

Adds three unit tests covering the substring, exact-match, and default
code paths in _build_key_filter_conditions. Restores the existing
member-team test to assert exact matching as a security regression guard.
2026-03-28 16:50:09 -07:00
Ryan Crabbe 65df501f15 Simplify substring search — remove admin-only gating
Substring matching for user_id and key_alias now applies unconditionally.
The admin-only flag was unnecessary since user_ids are typically UUIDs/emails
where substring collisions are not a practical concern. Updated existing test
to assert the new filter structure.
2026-03-28 14:50:31 -07:00
ryan-crabbe-berriandGitHub 2eb3c20e76 Merge pull request #24718 from BerriAI/litellm_ryan-march-26
litellm ryan march 26
2026-03-28 09:01:11 -07:00
Ryan Crabbe e24819afef fix(sso): pass decoded JWT access token to role mapping during SSO login
During SSO login, bearer tokens are stripped from the OAuth response
before role mapping runs. Custom role claims encoded inside the JWT
access token are lost, so map_jwt_role_to_litellm_role() returns None
and the user falls back to internal_user_viewer.

process_sso_jwt_access_token() now returns the decoded JWT payload, and
a new _sync_user_role_from_jwt_role_map() receives it so
jwt_litellm_role_map works correctly during SSO login.
2026-03-27 13:50:30 -07:00
yuneng-jiangandGitHub 1b111d23f3 Merge pull request #24688 from Sameerlite/litellm_litellm_team-model-group-name-routing-fix
fix(team-routing): preserve sibling deployment candidates for team public models
2026-03-27 12:00:34 -07:00
Sameer KankuteandClaude Opus 4.6 8112fbf274 fix(proxy): sanitize user_id input and block dangerous env var keys
Add input validation to get_user_id_from_request (length limit, control char rejection) and a blocklist of dangerous environment variable keys in _load_environment_variables to prevent PATH/LD_PRELOAD/PYTHONPATH override via config.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-27 20:38:36 +05:30
Sameer Kankute 2321d77599 fix(router): address remaining Greptile review comments
- Cache LITELLM_ENABLE_TEAM_STALE_ALIAS_BYPASS at module level to avoid hot-path secret lookups
- Add clarifying comments for should_include_deployment team isolation logic
- Add negative assertion for update_team.assert_not_called() in test
- Add docstring clarification for _get_team_deployments helper pattern
- Add explicit assertion message in test_get_model_list_alias_optimization

Made-with: Cursor
2026-03-27 20:11:28 +05:30
Sameer Kankute 1a0b30aaac Fix greptile reviews and mock test 2026-03-27 20:11:28 +05:30
Sameer Kankute c6cc0341f6 Fix greptile reviews and mock test 2026-03-27 20:11:28 +05:30
Sameer Kankute 316a742945 Fix greptile comments 2026-03-27 20:11:28 +05:30
Sameer Kankute 173695f5e0 Fix greptile comments 2026-03-27 20:11:27 +05:30
Sameer Kankute e8fb7762b3 perf(routing): optimize team model checks and improve test coverage
- Use O(1) team index lookup instead of map_team_model in alias guard
- Fix MockPrismaClient to validate where clause filters
- Add comment explaining DB query trade-off for team deployments

Made-with: Cursor
2026-03-27 20:11:27 +05:30
Sameer Kankute 8aa58bdcaa fix(routing): prevent stale model_aliases from interfering with team routing
- Skip model_aliases rewrite if model resolves to team deployments
- Add test coverage for sibling-preservation branch
- Update MockPrismaClient to support sibling deployment scenarios

Made-with: Cursor
2026-03-27 20:11:27 +05:30
Sameer Kankute f5b7298854 fix(management): query DB directly for sibling deployments on rename
- Add clarifying comments to test assertions
- Query prisma DB instead of in-memory router to avoid stale state
- Prevents incorrect deletion of old public name when siblings exist

Made-with: Cursor
2026-03-27 20:11:27 +05:30
Sameer Kankute aeb932d707 fix(team-routing): keep team model routing on public names
Remove team model_alias rewrites and resolve team deployments by team_public_model_name with team_id so sibling deployments stay in the routing candidate pool, with explicit logs showing candidate selection before load balancing.

Made-with: Cursor
2026-03-27 20:11:27 +05:30
Sameer Kankute 5534b40ab3 fix(team-routing): use deterministic team model group names
Use a deterministic internal model_name for team-scoped deployments so sibling deployments with the same public model share a routing group. This makes team alias writes idempotent and preserves multi-deployment failover/load balancing behavior.

Made-with: Cursor
2026-03-27 20:11:27 +05:30
Ryan Crabbe 0aadf51342 fix(proxy): ignore return_to in SSO when control_plane_url is not configured
Instead of returning a 400 error when return_to is passed without
control_plane_url configured, silently ignore it and proceed with
the normal same-origin SSO flow.
2026-03-23 21:54:29 -07:00
yuneng-jiang 9963b31e07 Revert "fix(proxy): restore per-entity breakdown in aggregated daily activity endpoint"
This reverts commit 9c3fab24ad.
2026-03-21 21:37:29 -07:00
yuneng-jiangandGitHub 2b889f1627 Merge pull request #23471 from michelligabriele/fix/aggregated-activity-entity-breakdown
fix(proxy): restore per-entity breakdown in aggregated daily activity endpoint
2026-03-21 14:59:41 -07:00
ryan-crabbeandGitHub 59b4a05782 Merge branch 'main' into litellm_ryan_march_18 2026-03-20 13:36:37 -07:00
yuneng-jiangandGitHub 5927a77a14 Merge branch 'main' into fix/aggregated-activity-entity-breakdown 2026-03-20 11:50:59 -07:00
yuneng-jiangandGitHub f884e4ac66 Merge branch 'main' into fix/team-member-budget-duration-on-create 2026-03-20 11:48:08 -07:00
Ryan Crabbe ad43a35d76 feat: add control plane for multi-proxy worker management
Adds a control plane capability that enables a central admin instance
to manage multiple regional worker proxies from a single UI.

Backend:
- Worker registry loaded from YAML config (worker_id, name, url)
- /.well-known/litellm-ui-config exposes is_control_plane and workers list
- /v3/login + /v3/login/exchange: opaque code exchange for cross-origin
  username/password auth (JWT never in URL/logs, single-use 60s TTL)
- SSO cookie handoff with return_to → opaque code → exchange
- _validate_return_to: full origin validation (scheme+hostname+port)
- Startup warning when control_plane_url set without Redis
- Both /v3 endpoints gated behind control_plane_url config

Frontend:
- Worker selector dropdown on login page (gated behind is_control_plane)
- Cross-origin SSO code exchange handling on callback
- switchToWorkerUrl: localStorage-persisted worker URL for API calls
- useWorker hook: shared worker state management
- WorkerDropdown in navbar for switching workers
- Logout/switch clears worker state from localStorage

Tests:
- 7 tests for /v3/login + /v3/login/exchange
- 10 tests for _validate_return_to
- 2 tests for control plane discovery endpoint
2026-03-19 22:50:19 -07:00
yuneng-jiangandClaude Opus 4.6 05620c87e3 [Fix] Update bulk key update tests for find_unique refactor
Tests were outdated after _get_and_validate_existing_key was refactored
to use prisma_client.db.litellm_verificationtoken.find_unique() and
ProxyException. Also add ProxyException handling in bulk_update_keys
error extractor so error messages aren't empty.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 15:34:44 -07:00
yuneng-jiang e86ca7f34d Revert "[Fix] Update tests for _get_and_validate_existing_key refactor"
This reverts commit cf63697703.
2026-03-19 14:32:14 -07:00
yuneng-jiangandClaude Opus 4.6 cf63697703 [Fix] Update tests for _get_and_validate_existing_key refactor
Tests were outdated after _get_and_validate_existing_key was refactored
to use prisma_client.db.litellm_verificationtoken.find_unique() instead
of prisma_client.get_data(), and to raise ProxyException instead of
HTTPException. Also fix bulk_update_keys error handler to extract
ProxyException.message (str(ProxyException) returns empty string).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 12:41:11 -07:00
yuneng-jiang afb35204ce Merge remote-tracking branch 'origin' into litellm_yj_march_18_2026 2026-03-19 11:53:58 -07:00
81dadb698a Ishaan - March 18th changes (#24056)
* add DD Tracing (#24033)

* feat(models): add Azure GPT-5.4 mini and nano variants (#24045)

Add `azure/gpt-5.4-mini` and `azure/gpt-5.4-nano` to the model
database with official pricing from Azure OpenAI:

- GPT-5.4 mini: $0.75/M input, $0.075/M cached, $4.5/M output
- GPT-5.4 nano: $0.20/M input, $0.02/M cached, $1.25/M output

Both models support:
- 1.05M input / 128K output context window
- Chat, batch, and responses endpoints
- Function calling, tools, vision, reasoning
- Prompt caching with automatic tiered pricing

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* Add new model pricing details for volcengine Doubao-Seed-2.0 series (#23871)

Add entries for volcengine Doubao-Seed-2.0 series

* fix(mcp): support refresh_token grant type in OAuth token endpoint (#23701)

* fix(mcp): support refresh_token grant type in OAuth token endpoint (#23700)

The .well-known/oauth-authorization-server metadata advertises
refresh_token as a supported grant type, but the token endpoint
rejected it with HTTP 400. This adds refresh_token grant support
so MCP clients can refresh expired tokens without re-authenticating.

* test(mcp): add tests for refresh_token grant type in OAuth token endpoint

* fix(mcp): move code_verifier guard into authorization_code branch

code_verifier is only relevant for authorization_code grants (PKCE).
Move it inside the else branch so it doesn't apply to refresh_token.

* fix(mcp): guard None client_secret and forward scope in token exchange

- Conditionally include client_secret in form data to prevent httpx
  from sending the literal string "None" (applies to both
  authorization_code and refresh_token branches)
- Forward optional scope parameter per RFC 6749 §6, allowing clients
  to request a subset of originally-granted scopes on refresh

* fix(mcp): validate code param in authorization_code grant

Guard against None code being form-encoded as literal string "None"
by httpx, symmetric with the existing refresh_token guard.

* docs: add incident report for guardrail logging secret exposure (#24059)

Add blog post documenting the guardrail logging path exposing internal
request data (e.g. Authorization headers) in spend logs and OTEL traces.
Fix available in LiteLLM 1.82.3+.

Made-with: Cursor

* [Fix] Datadog LLM Observability tags format (env, service, version missing) (#23673)

* tag fix

* greptile comment

* fix(ci): stabilize 6 failing CI jobs

1. mypy: remove duplicate type annotation for token_data in discoverable_endpoints.py
2. integrations tests: add parameterized to CI test deps
3. doc quality: document OTEL_IGNORE_CONTEXT_PROPAGATION env key
4. security: allowlist CVE-2026-2673, CVE-2026-3644, CVE-2026-4224 (no fix available)
5. proxy_store_model_in_db: fix missing x-litellm-call-id header on error responses
6. google tests: add --retries 3 for transient Vertex AI rate limits

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

* fix(streaming): handle RuntimeError during model_copy in streaming handler

The race condition occurs when model_copy(deep=True) tries to deepcopy
_hidden_params dict while it's being concurrently modified by logging
callbacks. Fall back to shallow copy if the deep copy fails.

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

* fix(cost): handle non-string traffic_type in cost calculator + add retries

1. Fix AttributeError in _map_traffic_type_to_service_tier when traffic_type
   is an integer (cast to str before calling .upper()). This was causing
   pass-through vertex spend logging to fail silently.
2. Add --retries to llm_translation_testing for flaky external API calls.

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

---------

Co-authored-by: Emerson Gomes <emerson.gomes@thalesgroup.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: ExMatics HydrogenC <33123710+HydrogenC@users.noreply.github.com>
Co-authored-by: Jack Venberg <jack.venberg@rover.com>
Co-authored-by: milan-berri <milan@berri.ai>
Co-authored-by: Shivam Rawat <161387515+shivamrawat1@users.noreply.github.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
2026-03-19 10:20:35 -07:00
yuneng-jiangandClaude Opus 4.6 eceb4981b8 fix: address review feedback - dedup logic, use module-level helper, add test
- Deduplicate: update_key_fn now delegates to _get_and_validate_existing_key()
  instead of inlining its own copy of the lookup logic
- Use _hash_token_if_needed (already imported at module level) instead of
  inline `from proxy_server import hash_token` + manual conditional
- Fix stale docstring: _get_and_validate_existing_key raises ProxyException,
  not HTTPException
- Add unit test: test_update_key_nonexistent_key_returns_404

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 17:03:43 -07:00
Cursor Agentandyuneng-jiang f9e57c700a merge: resolve conflicts with litellm_yj_march_18_2026 base branch
Incorporate new _check_key_admin_access() calls from the base branch
into block_key/unblock_key alongside our existence-check fix.

Update test mocks: replace references to removed get_key_object and
_cache_key_object with _delete_cache_key_object in both the shared
_setup_block_unblock_mocks helper and individual test functions.

Co-authored-by: yuneng-jiang <yuneng-jiang@users.noreply.github.com>
2026-03-18 23:09:52 +00:00
yuneng-jiang 441f768abd Merge remote-tracking branch 'origin' into litellm_yj_march_17_2026 2026-03-18 12:07:50 -07:00
Cursor Agentandyuneng-jiang 5e7645a99b chore: remove unused imports (get_key_object, _cache_key_object)
These were only used in block_key/unblock_key for cache refresh,
which now uses _delete_cache_key_object instead.

Co-authored-by: yuneng-jiang <yuneng-jiang@users.noreply.github.com>
2026-03-18 08:47:44 +00:00
Cursor Agentandyuneng-jiang b428cfb4a4 test: add unit tests for block_key/unblock_key with non-existent keys
- test_block_key_nonexistent_key_returns_404: verifies block_key returns
  404 (not misleading 401) when the key doesn't exist in the DB
- test_unblock_key_nonexistent_key_returns_404: same for unblock_key
- test_block_key_existing_key_succeeds: verifies block_key succeeds and
  invalidates cache for existing keys
- Update test_unblock_key_supports_both_sk_and_hashed_tokens to reflect
  the new cache invalidation pattern (_delete_cache_key_object instead
  of get_key_object + _cache_key_object)

Co-authored-by: yuneng-jiang <yuneng-jiang@users.noreply.github.com>
2026-03-18 08:44:22 +00:00
yuneng-jiang b0990e2684 Revert "fix: prevent body 'key' field from overriding Authorization header in auth"
This reverts commit 2c874a7f3c.
2026-03-17 23:02:54 -07:00
yuneng-jiangandGitHub d2e77e74ee Merge pull request #23938 from BerriAI/litellm_/sweet-austin
[Feature] /v2/team/list: Add org admin access control, members_count, and indexes
2026-03-17 23:01:41 -07:00
yuneng-jiangandClaude Opus 4.6 2c874a7f3c fix: prevent body 'key' field from overriding Authorization header in auth
On /key/block, /key/unblock, and /key/update, the request body 'key'
field could contaminate the api_key Security dependency, causing the
auth layer to authenticate against the target key instead of the
caller's bearer token. This returned 401 for a nonexistent body key
even when the Authorization header contained a valid master key.

Added a guard in user_api_key_auth that re-reads the Authorization
header directly from the request, ensuring the header is always the
authoritative source for authentication.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 23:00:05 -07:00
yuneng-jiangandClaude Opus 4.6 41a7747e8c fix: document org scope behavior, fix test mocks, add org admin tests
- Document intentional legacy-matching behavior: when user_id is
  provided to an org admin, no org filter is applied (returns all of
  that user's teams across all orgs, same as legacy endpoint)
- Fix two existing security tests to properly patch user_api_key_cache,
  proxy_logging_obj, and get_user_object instead of relying on
  incidental error handling
- Add three new org admin test cases:
  - Org admin sees org-scoped teams (200 with correct where clause)
  - Org admin rejected when filtering by other org (403)
  - Org admin with user_id filter returns target user's teams

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 21:56:57 -07:00
yuneng-jiangandClaude Opus 4.6 0485a1859a fix: use get_user_object helper, preserve caller org_id filter
- Replace raw find_unique with get_user_object in
  _build_team_list_where_conditions for cache/metrics consistency
- Remove over-complex OR clause for org admin + user_id: when user_id
  is provided, filter by that user's direct team memberships (same as
  regular users) since the access control gate already verified the
  org admin's authority
- Preserve caller-supplied organization_id instead of overwriting with
  org_admin_org_ids
- Update test mock to match get_user_object call path

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 21:19:42 -07:00
yuneng-jiangandClaude Opus 4.6 53d96c8353 [Feature] Disable custom API key values via UI setting
Add disable_custom_api_keys UI setting that prevents users from specifying
custom key values during key generation and regeneration. When enabled, all
keys must be auto-generated, eliminating the risk of key hash collisions
in multi-tenant environments.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 21:35:21 -07:00