litellm/tests/unit/proxy/auth
Juan V. 60601ca995
feat(pass-through): add eu/jev decision API pass-through with spend tracking (#46875)
* feat(pass-through): add eu/jev decision API pass-through with spend tracking

Adds a /eu_jev/{endpoint:path} pass-through route for eu/jev, an EU-hosted
decision API that speaks the same POST /v1/systemone contract as TypeSafe.
It reads EU_JEV_API_KEY and EU_JEV_API_BASE (defaults to
https://jev.bevel.software), books spend through the shared decision logging
handler, and prices eu_jev/eu-jeff-1.0.0 and eu_jev/eu-jeff-latest from the
cost map

* fix(pass-through): default eu_jev to its canonical eu-jev.com origin

* fix(pass-through): reject custom_body on the eu_jev route

A key limited to other models could send an eu/jev request through
custom_body, because auth checks the outer body while the shared
pass-through forwards custom_body upstream. The route now answers 400
before anything is forwarded, the same way validate_oss_request guards
the laya and bespoke routes

* fix(pass-through): give the eu_jev route request and 200 response schemas

The OpenAPI docs gate flagged POST /eu_jev/{endpoint} for OA001 and
OA003. The route now documents the eu/jev System One request body and
its 200 answer, usage and meta shape, taken from the eu/jev OpenAPI
document. The lazy OpenAPI snapshot and the dashboard API types are
regenerated with python -m litellm.proxy._lazy_openapi_snapshot and
npm run gen:api

* fix(pass-through): reject streaming on the eu_jev route

A body with stream=true switched the route to streaming, which skips the
decision spend tracking. Reject it with a 400, as validate_oss_request does
for laya and bespoke.

* fix(pass-through): type the eu_jev request body like the other decision routes

* fix(pass-through): check eu_jev decisions against the model eu/jev runs

Serve only POST /eu_jev/v1/systemone, eu/jev's one endpoint, resolve an omitted
model and the legacy names to eu-jeff-latest for key model checks and pricing,
check scopes under eu_jev/<model> like Laya and Bespoke, and answer 503 when
EU_JEV_API_KEY is unset

* fix(pass-through): apply eu_jev key limits, register eu_jev, price unlisted releases

Pre-call hooks and guardrails now see the body model as eu_jev/<release>, so
model_rpm_limit and model_tpm_limit set on eu_jev/eu-jeff-latest apply, and
upstream still gets the client's exact body. eu_jev is a registered decisions
provider, so access groups, config deployments, /v1/systemone and /v1/decisions
accept it, and the Admin UI can add it. A release without its own cost map row
is priced as eu-jeff-latest instead of $0

* fix(eu_jev): use the pass-through deployment's api_base and accept provider-prefixed models

* fix(eu_jev): declare /v1/systemone on the eu/jev cost map entries so the generated endpoint table keeps it

* fix(eu_jev): take pass-through credentials only from proxy-wide deployments

The eu/jev route now ignores team-scoped deployments when it picks the
upstream key and base, so one team's deployment can no longer redirect
another team's calls, and a base ending in /v1 is not doubled

* fix(eu_jev): let a configured pass-through at /eu_jev/v1/systemone keep serving it

Scope the mapped pass-through and gateway allowlist entries to the decision
route instead of the whole /eu_jev prefix, so custom routes under /eu_jev keep
their auth, metering, and gateway behavior from before this PR

* fix(eu_jev): treat /eu_jev/v1/systemone as a provider route only while the built-in route serves it

Drop the decision path from the mapped pass-through list and classify it with one
check that asks the pass-through registry, so an operator's own pass-through at that
path keeps its auth, metering, LLM-route status and litellm_user_api_key handling
from before this PR. The built-in route now yields on a per-request root path and
on any configured method, and the gateway keeps only the exact decision path

* fix(eu_jev): find a configured route at the decision path with or without a trailing slash, and stop a deleted one forwarding

* test(eu_jev): annotate new test variables with Final

* fix(proxy): keep eu/jev pass-through routing stable during updates and method mismatches

Swap an updated pass-through's routes with no await between removal and
re-registration, so the built-in eu/jev route never sees the path as
unconfigured mid-update. The built-in eu/jev handler no longer takes a
configured route's target, and the built-in route also yields on a
method-only match, so GET and PUT on the no-slash form of a slash route
redirect again.

* test(pass-through): annotate the route-swap test's locals as Final

* fix(pass-through): keep an updated auth route's LLM API route checks on the updating worker

* fix(eu_jev): leave a null model out of the upstream decision request

A JSON model of null is limited and counted as eu-jeff-latest, so send the
request upstream without a model field, the way an omitted model goes, since
eu/jev answers a null model with 400 Unknown model

* fix(pass-through): keep route checks on a path another auth endpoint still serves after an update

Forward a non-string eu/jev model unchanged so eu/jev rejects it, and drop only a null or missing one

* test(eu_jev): keep the non-string model test in the eu/jev route test file so a CI shard runs it

* refactor(eu_jev): build the scoped pass-through body as a new dict instead of updating it in place

---------

Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com>
2026-10-29 17:52:43 -07:00
..
__init__.py ci: move tests/proxy_unit_tests to tests/unit/proxy and run the proxy-db shards from litellm-tests (#42903) 2026-09-24 22:59:11 +00:00
test_admin_viewer_handler_access.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_auth_checks.py fix(proxy): let typesafe/* allowlists cover /typesafe Jev calls and list Jev in the model picker (#47697) 2026-10-28 20:19:58 -07:00
test_auth_checks_object_access_and_lookup.py fix(proxy): enforce team and key Allowed Vector Stores when no vector store registry is loaded (#48915) 2026-10-28 23:25:14 -07:00
test_auth_exception_handler.py fix(auth): log routine 401 rejections as one warning without a traceback (#48613) 2026-10-27 12:46:22 -07:00
test_auth_hot_path_network_requests.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_auth_object_prefetch.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_auth_utils.py feat(pass-through): add eu/jev decision API pass-through with spend tracking (#46875) 2026-10-29 17:52:43 -07:00
test_authorization.py fix(proxy): share ownership permissions for spend logs and traces (#44239) 2026-10-03 01:38:54 +00:00
test_banned_params_extra_body.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_cli_auth.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_custom_auth_end_user_budget.py refactor(proxy): expose public names for private proxy helpers (#45170) 2026-10-07 18:59:27 -07:00
test_default_end_user_budget_simple.py refactor(proxy): expose public names for private proxy helpers (#45170) 2026-10-07 18:59:27 -07:00
test_fallback_budget.py fix(router): report fallbacks skipped for access or budget instead of calling them failed (#46291) 2026-10-14 15:08:47 -07:00
test_fallback_model_access.py fix(proxy): enforce fallback model access by default (#46127) 2026-10-13 07:58:53 -07:00
test_handle_jwt.py fix(rag)!: use team provider credentials and allow viewer and JWT team access (#45497) 2026-10-17 23:51:48 +00:00
test_info_routes.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_jwt.py fix(proxy): refresh cached team on /team/block and /team/unblock (#35643) 2026-10-19 22:50:33 +00:00
test_litellm_license.py fix(proxy): stop logging license values during verification (#44956) 2026-10-06 17:05:07 -07:00
test_login_utils.py test: fix flaky spend-log cleanup budget, login lockout, and wedged Redis tests (#47108) 2026-10-29 03:46:32 -07:00
test_master_key_boot_check.py fix(security): remove the publicly known master key from the repo (#44718) 2026-10-06 10:55:24 -07:00
test_mcp_ip_filtering.py refactor(mcp): drop the experimental label from the MCP server and client paths (#48513) 2026-10-27 17:47:50 +00:00
test_model_access_group_budgets.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_model_checks.py fix(proxy)!: list every priced Vertex family under a vertex_ai/* grant (#41959) 2026-10-29 00:31:04 -07:00
test_model_checks_fallbacks.py refactor(router): move router callers onto the entry points and invert the proxy imports (#48847) 2026-10-29 17:26:33 +00:00
test_models_fallback_endpoint.py refactor(router): move router callers onto the entry points and invert the proxy imports (#48847) 2026-10-29 17:26:33 +00:00
test_multi_budget_windows.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_multipart_bypass_repro.py ci: move tests/proxy_unit_tests to tests/unit/proxy and run the proxy-db shards from litellm-tests (#42903) 2026-09-24 22:59:11 +00:00
test_network.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_oauth2_proxy_hook.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_object_permission_loading.py refactor(proxy): expose public names for private proxy helpers (#45170) 2026-10-07 18:59:27 -07:00
test_onboarding.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_organization_budget_enforcement.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_password_hashing.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_password_policy.py feat(proxy): add LITELLM_OFFLINE_MODE, one switch for the fetches LiteLLM makes on its own (#48096) 2026-10-23 16:54:19 -07:00
test_personal_key_team_model_access.py feat(proxy): let personal keys inherit model access from the owner's current teams (#43692) 2026-10-13 00:17:35 +00:00
test_proxy_routes.py refactor(proxy): expose public names for private proxy helpers (#45170) 2026-10-07 18:59:27 -07:00
test_rds_iam_token.py fix(proxy): preserve AWS session tokens for RDS IAM auth (#46559) 2026-10-15 22:51:39 +00:00
test_resolvers_exceptions.py fix(auth): return a generic 401 for an unknown key (#39787) 2026-10-15 01:05:25 -07:00
test_resolvers_grants.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_resolvers_models.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_resolvers_seam.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_resolvers_store.py fix(auth): return a generic 401 for an unknown key (#39787) 2026-10-15 01:05:25 -07:00
test_route_checks.py feat(pass-through): add eu/jev decision API pass-through with spend tracking (#46875) 2026-10-29 17:52:43 -07:00
test_router_override_fallback_auth.py refactor(proxy): expose public names for private proxy helpers (#45170) 2026-10-07 18:59:27 -07:00
test_search_tool_deny_by_default.py fix(proxy): scope dashboard search grants to user (#48464) 2026-10-26 15:01:40 -07:00
test_team_grants.py test(proxy): move auth, hooks, policy_engine and client tests into tests/unit/proxy (#43998) 2026-10-01 10:11:45 -07:00
test_team_member_budget.py feat(teams): show caller member spend and budget on Your Teams (#45674) 2026-10-24 17:09:55 -07:00
test_unmapped_model_budget_enforcement.py refactor(router): move router callers onto the entry points and invert the proxy imports (#48847) 2026-10-29 17:26:33 +00:00
test_user_api_key_auth.py feat(proxy)!: model family and access group entries in model_max_budget (#47722) 2026-10-28 15:40:57 -07:00
test_user_api_key_auth_request_flow.py fix(proxy)!: enforce an end user's per-model budget from their linked budget (#48815) 2026-10-28 21:24:11 -07:00