fix(proxy): enforce virtual key budgets for JEV test routing - #41879
Conversation
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
|
bugbot run |
|
The proxy-infra failure reproduces on unchanged base |
|
@veria-ai please review 0ac0362: JEV Test Routing now checks existing virtual-key budgets before evaluation, with provider-invocation regression coverage |
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
bugbot run |
|
@veria-ai please review b9e5bb3: the budget admission fix is unchanged; its regression fixture now permits the companion feature's evaluation dependency |
|
@greptileai review the updated fixture and admission scope. Successful-preview spend accounting lives in companion #41886, which will ship alongside this fix |
|
bugbot run |
|
@greptileai @veria-ai Please review 503ab0b after the main refresh. Budget admission and invocation-count regression tests remain unchanged |
PR overviewAll previously flagged issues have been addressed. No open security concerns remain on this pull request. Security reviewNo open security issues remain on this pull request. Fixed/addressed: 1 · PR risk: 0/10 |
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
bugbot run |
|
@greptileai @veria-ai Please review 3b0d32e: JEV previews hard-block exhausted throttled keys. The regression failed before, all 176 endpoint tests and make check pass |
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 3b0d32e. Configure here.
Backport of upstream BerriAI#41879 (merge 1e161f5). A Jev routing test calls the paid TypeSafe API even when no tier model is invoked, so the key-budget check now runs for classifier_type 'jev' and refuses exhausted throttle-enabled keys. Tests adapted: preview_auto_router_routing takes no http_request on 1.101. Drop this commit when rebasing onto a release that contains BerriAI#41879. (cherry picked from commit 1e161f5) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Backport of upstream BerriAI#41739 (open, unmerged; commit 36601dd), fixing BerriAI#41713. JevClassifierConfig now requires api_key or TYPESAFE_API_KEY, so /auto_router/validate_complexity_router_config reports the missing key and /auto_router/test_routing refuses the config instead of answering a bare 500. Over HTTP that refusal is a 422 from request-body validation (the proxy maps validation errors to 400 only under /management/v1); the ComplexityRouter construction moved inside the try only matters for configs that bypass body validation. Adapted to the 1.101 base: - The team-member permission tests from the PR are not carried (auto_router_permissions.py does not exist on 1.101). - preview_auto_router_routing takes no http_request on 1.101. - The BerriAI#41879 budget tests now set TYPESAFE_API_KEY, which this validator requires; the two upstream PRs were written independently. Drop this commit when rebasing onto a release that contains BerriAI#41713's fix. (cherry picked from commit 36601dd) Co-Authored-By: wofiporia <1029687661@qq.com> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
TLDR
Problem this solves:
How it solves it:
budget_throttle_pctUser Flow
Before: a proxy admin's restricted virtual key can run paid JEV tests after its budget is exhausted
max_budget=0,rpm_limit=100andmetadata.throttle_on_budget_exceeded=truePOST http://127.0.0.1:4011/auto_router/test_routingwith"classifier_type":"jev""cause":"jev_classifier"After: the same key receives the existing budget error before JEV evaluation
max_budget=0,rpm_limit=100andmetadata.throttle_on_budget_exceeded=truePOST http://127.0.0.1:4011/auto_router/test_routingwith"classifier_type":"jev""type":"budget_exceeded"Relevant issues
Builds on #41607 and #41615. Merge before #41886
Affected release
Linear ticket
Pre-Submission checklist
Tip
3b0d32ec6f14979687d4bb76f51db5f9427a131a: all 176 endpoint tests andmake checkpass, including Python lint/type checks, test-quality checks and generated API-type synchronization. On preceding tip503ab0b373, the new zero/exhausted throttle regressions failed withDID NOT RAISE, while funded/unlimited controls passed. Denied cases assert no provider invocationAt this exact tip, CI reports 88 passed, zero failed, zero pending and one skipped check. Greptile reports 5/5, Bugbot reports no new issues, and Veria reports no open security issues with risk 0/10. The final review-thread sweep found no unresolved threads. Current main independently replaced the obsolete login-throttle test; this PR does not modify it
Delays in PR merge?
If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review)
Screenshots / Proof of Fix
Refreshed live proof on September 19 compares merge base
4487a9915b30b7188f254630bb0f0294800d3072with fixed tip3b0d32ec6f14979687d4bb76f51db5f9427a131a. Both ran against an isolated local PostgreSQL database and the real TypeSafe System One API. TypeSafe credentials came from the QA vault. The master key created local admin users and virtual keys; every routing request used a distinct virtual keyThe proxy's
budget_exceeded_throttle_percentagewas0.1. Each key hadrpm_limit=100andmetadata.throttle_on_budget_exceeded=true. The four budget/spend pairs were(0,0),(1,2),(1,0)and(null,0)Reproduce the calls against each revision:
qa-nanowas configured asopenai/gpt-5.4-nano. Test Routing only classified; it did not call that completion deployment. Repeat key creation with the remaining budget/spend pairs above4487a9915b3b0d32ec6fjev_classifierbudget_exceededjev_classifierbudget_exceededjev_classifierjev_classifierjev_classifierjev_classifierThe after-run error for the throttle case is:
{"error":{"message":"Budget has been exceeded! JEV Test Routing requires available budget.","type":"budget_exceeded","param":null,"code":"400"}}The UI/gateway rehearsal for #41886 separately verified ordinary zero budgets, funded-key spend settlement, and a tiny budget that passed once then rejected the next request. This PR adds admission only; classifier accounting is in #41886
Type
Bug Fix
Caveats (if any)
Severe
Low
Final Attestation
Note
Medium Risk
Changes proxy authorization on a management endpoint that gates paid JEV evaluations; scope is narrow but affects budget and throttle behavior for virtual keys.
Overview
JEV auto-router test routing (
POST /auto_router/test_routing) no longer skips virtual-key budget checks when the config uses a JEV classifier. Previously,_authorize_models_this_test_can_callreturned early when there was no billable LLM/embedding model in the test path, so zero or exhausted keys could still invoke the paid JEV provider.The guard now continues for
classifier_type == "jev", runs the existing_virtual_key_max_budget_check, and hard-blocks keys that would normally be throttled after budget exhaustion (budget_throttle_pctset) with a dedicatedbudget_exceedederror. Heuristic dry runs stay free (unchanged behavior, now covered by parametrized tests).New unit tests assert denial before
JevClassifierClient.evaluatefor zero/exhausted budgets and for throttle-enabled keys, while allowing runs when budget remains or is unlimited.Reviewed by Cursor Bugbot for commit 3b0d32e. Bugbot is set up for automated code reviews on this repo. Configure here.
Link to Devin session: https://app.devin.ai/sessions/a5c5a748d13446f6aac6f5841dfc283b
Open in Devin Desktop: https://app.devin.ai/desktop/session/a5c5a748d13446f6aac6f5841dfc283b?variant=devin
Requested by: @moe-berri
Link to Devin session: https://app.devin.ai/sessions/bfc739cc228944f49a2e5017a9b23a66
Open in Devin Desktop: https://app.devin.ai/desktop/session/bfc739cc228944f49a2e5017a9b23a66?variant=devin