[litellm-agent] Staging → litellm_internal_staging (5/7/2026) - #27375
Conversation
…tiple deployments share a model_name When two or more deployments share a 'model_name' (e.g. wildcard 'openai/*' with multiple 'api_base' values configured for failover), clicking 'Test Connection' on a specific row in the UI silently probed 'deployments[0]' instead of the row the user actually selected. Root cause: - Backend (_health_endpoints.py): the route handler picked litellm_params via 'get_model_list(model_name=...)' and unconditionally took the first match, ignoring 'model_info.id' that came in on the request body. - UI (model_info_view.tsx): the Test Connection click handler did not forward the clicked row's 'model_info.id' at all, leaving the backend with no way to disambiguate. Fix: - Backend: when 'model_info.id' is provided, resolve the deployment via the router's existing O(1) 'get_deployment(model_id=...)' helper. Falls back to the legacy model_name lookup when no id is supplied, preserving behavior for callers that don't pass one (Add Model wizard, curl users). - UI: forward 'localModelData.model_info?.id' in the model_info payload. Tests: - Backend: 2 new tests in test_health_endpoints.py covering the duplicate-model_name disambiguation path and the no-id legacy path. - UI: 1 new vitest case asserting the click handler payload contains 'id'.
…g Tick The 30s DB poll only added/updated guardrails; it never removed entries deleted on another pod. Stale DB-backed entries then leaked into list responses labeled as "config" because the list endpoint inferred source from set-difference. Track provenance explicitly on InMemoryGuardrailHandler (source: db|config) and reconcile DB-sourced entries against the latest DB result on each polling tick. List/info endpoints read source directly instead of inferring.
…itellm_/amazing-sanderson-68ea16
The SSO callback flow (`generic_response_convertor` → `add_missing_team_member`) was reading only the plural `team_ids_jwt_field` claim. IdPs that populate the singular `team_id_jwt_field` instead (Okta/Auth0 group → primary team) had their users created via SSO with `teams: []` — never assigned to the team named in the JWT, regardless of how the user_metadata changed across logins. Adds `JWTHandler.get_all_jwt_team_ids()` returning the deduplicated union of both claim sources, and threads it through both branches that build `all_teams` in `generic_response_convertor`. JWT bearer auth path is intentionally unchanged — pending customer feedback on whether membership reconciliation there should be moved or stay additive.
… Cover Stale-DB List/Info Branches Per Greptile review: the early-return path in initialize_guardrail silently dropped the source argument, so a racing polling tick or a hot-reload could leave an entry's provenance stuck on the wrong value. Write to _sources before returning so the caller's intent always wins. Also adds two endpoint-level tests that exercise the new branches the fix introduced: list_guardrails_v2 must skip in-memory entries tagged source='db' that are missing from the live DB result, and get_guardrail_info must 404 (not return as 'config') for stale DB-backed entries.
Greptile flagged that the helper was delegating to JWTHandler.get_team_id, which falls back to litellm_jwtauth.team_id_default when the JWT claim is missing or the field isn't configured. The plural-only get_team_ids_from_jwt that the SSO path used historically has no such fallback, so threading get_all_jwt_team_ids through generic_response_convertor would silently start adding SSO users to the default team for any tenant that had team_id_default configured — an undocumented backwards-incompatible change. Read the singular team_id_jwt_field claim directly via get_nested_value instead, so the helper returns only what's actually in the token. Added a test that pins this behavior across both configurations of the default (team_id_jwt_field set + missing claim, and team_id_jwt_field unset). Also dropped @pytest.mark.asyncio from the sync test (P2 nit).
…27370) Squash-merged by litellm-agent from Bytechoreographer's PR.
|
@greptile please review |
|
|
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
Greptile SummaryThis staging PR collects several independent bug fixes and feature additions across the proxy auth, guardrail, health, and UI layers. Each change is accompanied by focused mock-only unit tests.
Confidence Score: 5/5All changes are well-scoped bug fixes with accompanying mock tests; no auth bypass, data loss, or backwards-incompatible behavior was found. The OAuth redirect expansion is correctly gated by the existing trusted-proxy check, so X-Forwarded-* header injection cannot widen the allowed origin set. The guardrail reconciliation logic correctly distinguishes DB vs config provenance and only evicts entries that are both DB-tagged and absent from the DB query. The JWT team union preserves the documented contract (no team_id_default leakage). All behavioral changes are covered by isolated unit tests with no real network calls. No files require special attention.
|
| Filename | Overview |
|---|---|
| litellm/proxy/_experimental/mcp_server/oauth_utils.py | Adds get_request_base_url (moved from discoverable_endpoints) and new validate_trusted_redirect_uri that accepts same-origin redirects in addition to loopback, with proper header-injection protection via trusted-proxy gating. |
| litellm/proxy/_experimental/mcp_server/discoverable_endpoints.py | Switches redirect URI validation from loopback-only to same-origin-or-loopback; adds request: Request parameter to the callback endpoint for origin determination. |
| litellm/proxy/auth/handle_jwt.py | Adds get_all_jwt_team_ids that unions plural team_ids_jwt_field and singular team_id_jwt_field claims, fixing silent drops for Okta/Auth0-style IdPs that populate only the singular field. |
| litellm/proxy/guardrails/guardrail_registry.py | Adds provenance tracking (_sources dict, get_source, reconcile_db_guardrails) to distinguish DB-backed from config-loaded guardrails, enabling clean cross-pod deletion reconciliation. |
| litellm/proxy/guardrails/guardrail_endpoints.py | Filters stale DB-backed in-memory guardrails from list/get endpoints, and marks guardrails created via API as source=db. |
| litellm/proxy/health_endpoints/_health_endpoints.py | Disambiguates test-connection by model_info.id first before falling back to model_name lookup, fixing wildcard deployments that share the same name. |
| litellm/proxy/management_endpoints/tag_management_endpoints.py | Adds optional start_date/end_date query params to /tag/list with format and range validation, passed into the Prisma group_by WHERE clause for efficient date-window filtering. |
| litellm/proxy/management_endpoints/ui_sso.py | Updates generic_response_convertor to call get_all_jwt_team_ids instead of get_team_ids_from_jwt so the singular team_id claim is included in SSO team membership. |
| litellm/proxy/proxy_server.py | Adds DB guardrail reconciliation pass on each polling tick, collecting IDs from the DB query and calling reconcile_db_guardrails to evict stale entries. |
| ui/litellm-dashboard/src/components/networking.tsx | Extends tagListCall to accept optional startTime/endTime Date params and appends them as start_date/end_date query params when both are provided. |
| ui/litellm-dashboard/src/components/UsagePage/components/UsagePageView.tsx | Refactors tag list fetch to pass the current date range and adds cancellation via cancelled flag, with accessToken/startTime/endTime in the dependency array. |
| ui/litellm-dashboard/src/components/model_info_view.tsx | Passes model_info.id in the test-connection call to disambiguate wildcard deployments with shared model names. |
| ui/litellm-dashboard/src/components/templates/key_info_view.tsx | Minor layout fix: changes outer div from h-screen to h-full overflow-y-auto and removes redundant overflow-y-auto max-h-[65vh] from the Settings Panel Card. |
Reviews (2): Last reviewed commit: "fix(ui): tag filter dropdown on Usage pa..." | Re-trigger Greptile
…ge (#26847) Squash-merged by litellm-agent from Bytechoreographer's PR.
|
@greptile please review |
|
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit fbafae0. Configure here.
158b0c2
into
shin_agent_oss_staging_05_07_2026
|
🤖 litellm-agent: Squash-merged into staging branch Triage Summary Merge Confidence: 5/5 ✅ READY All checks green. Greptile 5/5, no blocking pattern findings, CircleCI passed. |
…I#27375) Squash-merged by litellm-agent from oss-pr-review-agent-shin[bot]'s PR.
Automated staging PR created by litellm-agent.
This branch collects PRs approved by the agent on 5/7/2026.
Note
Medium Risk
Touches OAuth redirect validation and callback handling (security-sensitive) and changes guardrail reconciliation logic across pods; also adjusts management/health endpoints and UI calls, which could impact admin workflows if edge cases are missed.
Overview
MCP OAuth proxy hardening + UI support: OAuth
redirect_urivalidation is expanded from loopback-only to loopback OR same-origin, with re-validation on/callbackto block open-redirect/code-theft while allowing the proxy UI callback. Base-URL reconstruction (get_request_base_url) is centralized inoauth_utils, and new tests cover trusted redirect behavior.Guardrails multi-pod correctness: In-memory guardrails are now tagged with a source (
dbvsconfig), DB-loaded guardrails are initialized withsource="db", and a new reconciliation pass purges stale DB-backed guardrails that were deleted in another pod. Endpoints are updated to avoid returning stale DB-backed in-memory entries as if they were config guardrails, with added coverage.Operational UX improvements:
/health/test_connectionnow prefersmodel_info.idto select the exact deployment when model names are duplicated (UI passes the id; backend resolves viallm_router.get_deployment)./tag/listadds optionalstart_date/end_datequery params (validated) to filter dynamic tags by date window, and the dashboard tag fetch now passes the active date range.SSO/JWT team mapping: Adds
get_all_jwt_team_ids()to union singular and plural team claims and switches SSO team extraction to use it, with regression tests.Minor UI layout tweak: Key info view layout is adjusted to use scrollable full-height containers.
Reviewed by Cursor Bugbot for commit fbafae0. Bugbot is set up for automated code reviews on this repo. Configure here.