Commit graph

108 commits

Author SHA1 Message Date
user
aee064ad37
Merge remote-tracking branch 'upstream/litellm_internal_staging' into fix/managed-resource-service-account-isolation 2026-05-05 01:29:05 +00:00
user
83971a8712 fix(proxy): normalize managed resource team owner field 2026-05-04 17:05:50 -07:00
shin-berri
38ddcdabdb
Merge pull request #27032 from BerriAI/litellm_yj_may1_2
[Infra] Merge dev branch
2026-05-01 19:39:42 -07:00
yuneng-jiang
5614469f22
Merge pull request #26825 from stuxf/fix/oauth2-proxy-header-forgery
chore(auth): require trusted proxy for header identity auth
2026-05-01 18:47:58 -07:00
yuneng-jiang
e78d87ee00
Merge pull request #27011 from stuxf/fix/project-update-cross-team-hijack
fix(proxy): close project hijacking and key org IDOR (VERIA-55)
2026-05-01 18:01:06 -07:00
user
1b2756811e
fix(proxy): close project hijacking and key org IDOR
Two related authorization gaps in management endpoints:

1. `/project/update` evaluated permission against the team_id supplied in
   the request body. By passing `data.team_id` pointing at a team they
   admin, a caller could hijack any project — `_check_user_permission_for_project`
   was given the attacker's team_object and happily checked admin
   membership against that. Drop the team_object kwarg so the helper
   re-fetches the existing project's team. Also require admin rights on
   the destination team when reassigning a project across teams, so a
   team admin cannot shed projects into another team's namespace.

2. `/key/update` accepted any `organization_id` and only checked that
   the org existed before applying limits. A caller could thereby point
   their key at an arbitrary org. Add `_validate_caller_can_assign_key_org`
   which enforces the same membership rule already applied on the
   `/key/list` filter path (`validate_key_list_check`); proxy admins and
   no-change updates skip the check.

Tests cover both helpers in isolation: existing-team-admin allow,
unrelated-team admin deny, proxy-admin shortcut, org-member allow,
non-member deny, missing user_id deny, no-memberships deny.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 21:32:38 +00:00
user
84fede37b4
fix(proxy): isolate managed resources for service-account API keys
Service-account API keys are issued without a `user_id`, and managed
file/batch/vector-store ownership checks compared
`resource.created_by == user_api_key_dict.user_id`. Because Python
evaluates `None == None` as True, any service-account key passed
ownership checks for any resource also created without a user id, and
listing endpoints skipped the `created_by` filter entirely when the
caller had no user id — returning every tenant's records.

Replace the bare equality with an identity-aware helper:

- Admins (PROXY_ADMIN, PROXY_ADMIN_VIEW_ONLY) keep their unscoped view.
- Callers with a `user_id` are scoped to records they created.
- Callers without a `user_id` but with a `team_id` are scoped to records
  created within their team via a new `created_by_team_id` column.
- Callers with no admin role and no identifying ids are denied — the
  listing path returns an empty page without issuing a query.

Schema migration adds `created_by_team_id` to LiteLLM_ManagedFileTable,
LiteLLM_ManagedObjectTable, and LiteLLM_ManagedVectorStoreTable, plus
indexes for the new filter. Writes in BaseManagedResource and the
enterprise managed_files hook now stamp the column from
`user_api_key_dict.team_id`. Reads in `can_user_access_unified_resource_id`,
`can_user_call_unified_file_id`, `can_user_call_unified_object_id`,
`list_user_resources`, `list_user_batches`, and `get_user_created_file_ids`
all delegate to the new helper.

Tests cover the helper in isolation, the base-class listing/access paths,
and the enterprise file-access hook (including a regression test for the
original `None == None` bypass).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 20:22:37 +00:00
ishaan-berri
32704ff7b2
fix(projects): project dropdown empty for internal_user (3 bugs) (#26664)
* fix(projects): fire useProjects hook for all authenticated users, not just admins

* fix(routes): add /project/list and /project/info to internal_user_routes allowlist

* fix(projects): use members_with_roles + LiteLLM_UserTable.teams for membership checks

* feat(ui): add "Your Usage" view for admin users on usage page

Admins were forced to use the global usage view with no way to scope it
to their own activity without manually searching for themselves in the
user filter dropdown.

Adds a new "Your Usage" option (admin-only) to the usage view selector.
When selected, it locks the data to the admin's own user_id and hides
the "Filter by user" dropdown.

* feat(ui): wire my-usage view to admin's own user_id in UsagePageView

When usageView is "my-usage", effectiveUserId resolves to the logged-in
admin's own userID. The "Filter by user" dropdown is hidden in this
view (only shown for "global").

* add: screenshots for usage page Your Usage admin fix

* fix(ui): gate useProjects on admin roles to fix failing unit test

* feat(proxy): add /project/list and /project/info to internal user routes

* fix(enterprise): use members_with_roles and litellm_usertable.teams for project access checks

* remove .github screenshots and workflow file from PR
2026-05-01 11:42:22 -07:00
user
2f4641752b chore(auth): require trusted proxy for header identity auth 2026-04-29 21:20:21 -07:00
Yuneng Jiang
000ce70127
Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_migration_projects
# Conflicts:
#	litellm/proxy/ui_crud_endpoints/proxy_setting_endpoints.py
#	uv.lock
2026-04-24 12:52:10 -07:00
Yuneng Jiang
937d81331f
[Refactor] Proxy: tighten UI settings extras registry
- drop unused Any annotation on register_extra_ui_setting's field
  param; type it as FieldInfo and have enterprise callers construct
  FieldInfo directly (pydantic.Field's stub reports the default's
  type, which doesn't match FieldInfo)
- cache the effective UISettings class and invalidate it inside
  register_extra_ui_setting so GET /get/ui_settings does not rebuild
  a pydantic model on every request
- annotate _EXTRA_UI_SETTINGS_FIELDS with a concrete
  Dict[str, Tuple[Any, FieldInfo]] instead of bare Dict[str, tuple];
  the annotation remains Any because pydantic field annotations
  include generics (Optional[X], List[X]) that are not instances of
  type
2026-04-13 21:58:02 -07:00
Yuneng Jiang
d3a1f63af2
[Refactor] Proxy: move projects management to enterprise package
Remove the /project/* management endpoints and the enable_projects_ui
admin-settings flag from the OSS litellm package. Project endpoints now
live under litellm_enterprise and are wired through the existing
enterprise router; OSS builds return 404 for every /project/* route.

The enable_projects_ui UI flag is registered back onto UISettings via a
small extension registry when the enterprise package is imported, so the
admin toggle and downstream key/sidebar gating continue to work in
enterprise builds. On OSS, explicit PATCH attempts with the flag return
403 with a clear enterprise-only message instead of being silently
dropped.

Pydantic request/response types (NewProjectRequest, UpdateProjectRequest,
DeleteProjectRequest, NewProjectResponse) stay in litellm/proxy/_types.py
because management_endpoints/common_utils.py and pydantic-shape tests
import them. LiteLLM_ProjectTable and all FK columns in schema.prisma
are unchanged.
2026-04-13 21:41:12 -07:00
ishaan-berri
7a9a9f0c79
fix: batch-limit stale managed object cleanup to prevent 300K row UPD… (#25258)
* fix: batch-limit stale managed object cleanup to prevent 300K row UPDATE (#25257)

* Add STALE_OBJECT_CLEANUP_BATCH_SIZE constant

Configurable batch limit (default 1000) for stale managed object cleanup,
preventing unbounded UPDATE queries from hitting 300K+ rows at once.

* Batch-limit stale managed object cleanup with single bounded SQL query

Two fixes to _cleanup_stale_managed_objects:

1. Replace unbounded update_many with a single execute_raw using a
   subquery LIMIT, capping each poll cycle to STALE_OBJECT_CLEANUP_BATCH_SIZE
   rows. Zero rows loaded into Python memory — everything stays in Postgres.
   Uses the same PostgreSQL raw-SQL pattern as spend_log_cleanup.py
   (the proxy requires PostgreSQL per schema.prisma).

2. Extract _expire_stale_rows as a separate method for testability.

Keeps the file_purpose='response' filter to avoid incorrectly expiring
long-running batch or fine-tune jobs that legitimately exceed the
staleness cutoff.

* docs: add STALE_OBJECT_CLEANUP_BATCH_SIZE to env vars reference

* test: remove deprecated embed-english-v2.0 cohere embedding tests
2026-04-06 19:11:55 -07:00
Sameer Kankute
bbd8ca3b3d
feat(prometheus): add metrics for managed batch lifecycle
- Add Prometheus metrics for managed batch and file operations
- Track batch creation, file size, duration, and deletion events
- Add CheckBatchCost polling metrics (jobs polled/processed, errors)
- Record metrics in managed_files hook and check_batch_cost utility
- Metrics include labels for model, provider, user, and status

Made-with: Cursor
2026-03-27 20:30:09 +05:30
Sameer Kankute
32ded9b2f8 fix double-billing issue 2026-03-18 12:47:42 +05:30
Sameer Kankute
7660f39fdb fix(file_search): promote DB helper, suppress sub-call billing, add queries-plural test
- Promote _fetch_managed_vector_stores_by_uuids from @staticmethod to a module-level
  async helper get_managed_vector_store_rows_by_uuids, following the same standalone
  helper pattern as get_team_object / get_key_object so the hot-path DB read is a
  named importable function rather than an inline prisma_client.db.* call
- Pass no-log=True to both inner _call_aresponses sub-calls so they do not fire
  independent billing/monitoring callbacks; cost is accumulated in the synthesized
  response's _hidden_params for the outer responses() call
- Add test_H11b covering the primary queries (plural array) function-tool schema,
  complementing H11 which exercises only the backward-compat singular query path

Made-with: Cursor
2026-03-18 11:38:49 +05:30
Sameer Kankute
76176f2a64 fix(file_search): restore should_use_emulated helper, fix dedup, extract DB helper, clean docstring
- Re-add should_use_emulated_file_search() to emulated_handler.py so H5/H6/H7/H13 tests don't fail with ImportError
- Remove per-file-id deduplication from _build_search_results_for_include so all chunks are returned (matching OpenAI native file_search behaviour); update test_H14 to assert 2 results
- Extract raw prisma DB query in check_vector_store_ids_access into a static _fetch_managed_vector_stores_by_uuids helper so the hot request path uses a named, testable function instead of an inline prisma_client.db.* call
- Remove developer-local path from test module docstring

Made-with: Cursor
2026-03-18 11:26:27 +05:30
Sameer Kankute
c735251570 feat(responses): file_search support — Phase 1 native passthrough + Phase 2 emulated fallback
Phase 1 (native passthrough):
- _decode_vector_store_ids_in_tools(): decode LiteLLM-managed unified
  vector_store_ids to provider-native IDs in file_search tools
- Split update_responses_tools_with_model_file_ids() into decode pass
  (always runs) + code_interpreter mapping pass (guarded)
- BaseResponsesAPIConfig.supports_native_file_search() → False by default;
  OpenAIResponsesAPIConfig overrides to True
- ManagedFiles.async_pre_call_hook(): batch team-level access check for
  unified vector_store_ids in file_search tools (no N+1)
- Docs: file_search section in response_api.md

Phase 2 (emulated fallback for non-native providers):
- litellm/responses/file_search/emulated_handler.py: converts file_search
  tool → function tool, intercepts tool call, runs asearch(), makes
  follow-up call, synthesizes OpenAI-format output (file_search_call +
  message + file_citation annotations)
- responses/main.py: routes to emulated handler when provider doesn't
  support file_search natively

Tests: 41 unit tests across 8 families (A-H) in test_file_search_responses.py

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 11:41:44 +05:30
Sameer Kankute
ab377f396e
Merge pull request #23718 from BerriAI/litellm_fix_vertex_ai_batch
Fix: Vertex ai Batch Output File Download Fails with 500
2026-03-16 19:05:49 +05:30
Sameer Kankute
22b333cae6 Fix downloading vertex ai files 2026-03-16 12:08:06 +05:30
yuneng-jiang
4fc0975d22 Fix flaky e2e batch test: set batch_processed=True on completion in retrieve_batch
The retrieve_batch endpoint sets batch status to "complete" but never set
batch_processed=True, permanently blocking file deletion. CheckBatchCost
(the safety net) also excluded completed batches from its primary query,
so batch_processed was never set by either path.

Three fixes:
1. update_batch_in_database sets batch_processed=True when status reaches
   "complete", with old-schema fallback retry
2. CheckBatchCost primary query no longer excludes complete/completed
   (batch_processed=False filter prevents reprocessing)
3. retrieve_batch early-return now includes "complete" (DB-normalized
   spelling) to avoid unnecessary provider re-polls

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 18:18:32 -07:00
Ishaan Jaff
1b96064600
fix(proxy): prevent OOM/Prisma connection loss from unbounded managed-object poll (#23472)
* fix(proxy): cap managed-object poll size + expire stale rows + kill-switch flag to prevent OOM/Prisma connection loss

* fix(constants): simplify PROXY_BATCH_POLLING_ENABLED readability

* docs+test: document new polling env vars, add pagination+stale-cleanup tests

* fix: exclude stale_expired from batch poll queries; fix update_many assertions in tests

* fix: scope stale cleanup to file_purpose, fix file_object mocks, add CheckBatchCost tests

* fix: avoid duplicate cost logging in fallback path; guard integer constants against zero/negative values

* fix: cache _has_batch_processed_column; guard cleanup from aborting poll; narrow fallback except

* fix: add complete/completed to primary query not_in; fix vacuous test assertion

- Primary find_many was missing "complete" and "completed" in its not_in
  filter, creating asymmetry with the fallback query. A job whose status
  was set to "complete" but whose batch_processed flag update failed would
  be silently re-fetched and re-processed every cycle, emitting duplicate
  cost logs.

- test_fallback_completion_update_omits_batch_processed patched
  _is_base64_encoded_unified_file_id to return None, causing an immediate
  continue — so update() was never called and the assertion looped over an
  empty list (vacuously true). Rewrote the test to mock the full
  completion pipeline, verify update() is called exactly once, and assert
  batch_processed is absent from the update data.

- Added symmetric test (primary path) proving batch_processed IS included
  when the column exists.

Made-with: Cursor
2026-03-13 11:01:40 -07:00
Ryan Crabbe
c4db53a98a Address review feedback: remove dead code, add error handling, strengthen test assertions
- Remove unused `completed_jobs` list (dead code after per-job update refactor)
- Wrap DB update in try/except to prevent one failed update from aborting remaining jobs
- Add test assertions verifying batch_processed, status, and file_object are written to DB
2026-03-06 09:25:50 -08:00
Ryan Crabbe
3d55f7f6ab Fix batch list showing stale "validating" status after completion
CheckBatchCost poller updated the status column but not the file_object
JSON column. The list_batches endpoint reads status from file_object,
so batches appeared stuck in "validating" even after Azure reported
them as completed. Now update file_object alongside status in the
per-job DB write.
2026-03-06 08:54:21 -08:00
yuneng-jiang
ba7a6d9bfd
Merge pull request #22476 from BerriAI/litellm_audit_pagination_fix
[Fix] UI - Audit Logs: Server-side pagination, filtering, and drawer view
2026-03-03 16:52:33 -08:00
yuneng-jiang
657a60ea5b fix(audit): AND semantics for combined JSON filters; remove unused allTeams prop
- Fix object_team_id + object_key_hash combining incorrectly as OR — each
  filter now adds an AND clause wrapping an internal OR over before_value
  and updated_values, so both conditions must be satisfied simultaneously
- Rename helper to _build_json_field_or_condition to reflect its purpose
- Remove allTeams from AuditLogsProps and its call site in index.tsx

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-03 14:24:55 -08:00
yuneng-jiang
705ef64ffc fix(ui): Audit logs - server-side pagination, filtering, and drawer view
- Replace client-side full-fetch loop with single react-query call using
  keepPreviousData; remove 5-second polling
- All filters (object ID, action, table, changed_by, team ID, key hash)
  now passed as query params to the backend
- Add object_team_id and object_key_hash params to /audit endpoint using
  Prisma JSON path filtering (PostgreSQL) to search inside before_value
  and updated_values JSON columns
- Migrate table from custom TanStack DataTable to AntD Table with
  server-side pagination
- Replace inline row expansion with a right-side AntD Drawer showing
  metadata and before/after diff
- Refactor uiAuditLogsCall to accept a structured options object

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 18:19:07 -08:00
Ephrim Stanley
35f6fd4223 Managed batches fixes for Gemini/Vertex 2026-02-28 20:21:04 -05:00
Ephrim Stanley
27a33565e7 State management fixes for CheckBatchCost - Address greptile comments 2026-02-23 07:52:58 -05:00
Ephrim Stanley
7b5dc3fb9c State management fixes for CheckBatchCost 2026-02-23 07:16:25 -05:00
Sameer Kankute
03f5717456 Fixes based on greptile reviews 2026-02-18 12:19:11 +05:30
Sameer Kankute
9f5580fddd Fixes based on greptile reviews 2026-02-18 11:55:06 +05:30
Sameer Kankute
8f80b1085e Add File deletion criteria with batch references 2026-02-18 11:39:32 +05:30
Sameer Kankute
791cef6d99 fix test_chat_completion 2026-02-17 20:26:28 +05:30
Ephrim Stanley
a3762e7d49 Addressed greptile comments to extract common helpers and return 404 2026-02-16 07:58:04 -05:00
Ephrim Stanley
7d794b567c fix: thread deployment model_info through batch cost calculation
batch_cost_calculator only checked the global cost map, ignoring
deployment-level custom pricing (input_cost_per_token_batches etc.).
Add optional model_info param through the batch cost chain and pass
it from CheckBatchCost.
2026-02-15 14:53:30 -05:00
Ephrim Stanley
a5626768a3 Add comments 2026-02-14 19:46:56 -05:00
Ephrim Stanley
4d87cb8fe3 Fix deleted managed files returning 403 instead of 404 2026-02-14 19:12:03 -05:00
Ephrim Stanley
e59c8d22af fix: afile_retrieve returns unified ID for batch output files 2026-02-14 10:07:12 -05:00
Ephrim Stanley
5433ae7e8c Fix: bypass managed files access check in batch polling by calling afile_content directly 2026-02-14 00:30:35 -05:00
Ephrim Stanley
358180eb2d Fix: pass deployment credentials to afile_retrieve in managed_files post-call hook 2026-02-14 00:16:34 -05:00
Sameer Kankute
aaf5938864
Merge pull request #21089 from BerriAI/litellm_vector_store_endpoints
Add target_model_names for vector store endpoints
2026-02-13 22:18:29 +05:30
Sameer Kankute
4ad0ecd9eb Fix mypy issues 2026-02-13 22:02:27 +05:30
Shivam Rawat
1321cd276b removed /models and v1/models from llm api routes (#20988) 2026-02-13 18:32:41 +05:30
Sameer Kankute
fa48166b10 Add _PROXY_LiteLLMManagedVectorStores class 2026-02-13 09:57:17 +05:30
Sameer Kankute
ce4bebbedf Changed asyncio.create_task() to await for storing batch objects 2026-02-10 12:42:39 +05:30
Sameer Kankute
9bdb163269 Add error file ids as managed files 2026-02-10 12:06:40 +05:30
Sameer Kankute
8b3213ce5c Add mapping for responses tools in file ids 2026-02-04 13:12:45 +05:30
Sameer Kankute
410e54648c Fix: Managed Batches: Inconsistent State Management for list and cancel batches 2026-02-03 14:47:28 +05:30
shin-bot-litellm
5434b66b9c
litellm_fix(mypy): fix remaining type errors (#20164)
- route_llm_request.py: add acancel_batch and afile_delete to route_type Literal
- router.py: add SearchToolInfoTypedDict and search_tool_info to SearchToolTypedDict
- gemini/files/transformation.py: fix validate_environment signature to match base class
- responses transformation.py: fix Dict type annotations to use int instead of Optional[int]
- vector_stores/endpoints.py: add team_id and user_id to LiteLLM_ManagedVectorStoresTable constructor

Co-authored-by: shin-bot-litellm <shin-bot-litellm@users.noreply.github.com>
2026-01-31 10:25:23 -08:00