You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The model router publishes exactly ods/current and default from /v1/models, but its forwarding route accepted any model value and silently mapped it to the active runtime. Clients could believe a concrete or misspelled model was honored while ODS served a different model and rewrote the response back to the unsupported name.
Root cause and invariant
The request body used str(payload.get(model) or PUBLIC_ALIASES[0]), coercing arbitrary strings, numbers, booleans, and containers into apparent aliases. The invariant is that the forwarding boundary accepts only aliases the discovery endpoint advertises; the existing missing/empty-model compatibility default remains ods/current.
Unsupported values now receive an OpenAI-shaped 400 before queue admission or any upstream request.
Overlap check
Searched open and closed PRs for model router unsupported alias, public model alias validation, and the changed production file. Open same-file PRs are #2843 (MLX runtime family) and #2719 (internal-key auth); neither validates the public model contract. No semantic match was found.
Regression coverage
The FastAPI contract suite now submits a concrete runtime ID, an unknown string, a number, a boolean, and a list. Each must return 400 invalid_request_error and the mock upstream must receive zero calls. Existing coverage proves both advertised aliases continue to route and rewrite correctly.
This deliberately closes an undocumented permissive behavior. Clients selecting a concrete runtime must use the switchboard/control plane, then call the stable alias. Revert restores permissive alias coercion; no state or config migration is involved.
Validated merge order: #2989 ? #2990 ? #2993 ? #2991 ? #2992 ? #2994 ? #2995 ? #2996 ? #2997 ? #2998. The changes are independently useful; this order only reconciles shared model-router and magic-link files.
Synthetic integration head: origin/batch/quality-ten-20260822-round2-integration at 91eb730d. The only textual conflict was the two model-router tests inserting at the same class boundary; the integration resolution retains both contracts. Magic-link changes merged cleanly.
All required GitHub checks are green across the batch. #2992 initially hit a transient openSUSE repository/mirror failure while installing rsync; a clearly labeled empty retry commit reran the unchanged tree, and openSUSE plus the full matrix passed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why this matters
The model router publishes exactly
ods/currentanddefaultfrom/v1/models, but its forwarding route accepted anymodelvalue and silently mapped it to the active runtime. Clients could believe a concrete or misspelled model was honored while ODS served a different model and rewrote the response back to the unsupported name.Root cause and invariant
The request body used
str(payload.get(model) or PUBLIC_ALIASES[0]), coercing arbitrary strings, numbers, booleans, and containers into apparent aliases. The invariant is that the forwarding boundary accepts only aliases the discovery endpoint advertises; the existing missing/empty-model compatibility default remainsods/current.Unsupported values now receive an OpenAI-shaped 400 before queue admission or any upstream request.
Overlap check
Searched open and closed PRs for
model router unsupported alias,public model alias validation, and the changed production file. Open same-file PRs are #2843 (MLX runtime family) and #2719 (internal-key auth); neither validates the public model contract. No semantic match was found.Regression coverage
The FastAPI contract suite now submits a concrete runtime ID, an unknown string, a number, a boolean, and a list. Each must return 400
invalid_request_errorand the mock upstream must receive zero calls. Existing coverage proves both advertised aliases continue to route and rewrite correctly.Validation
pytest -q ods/extensions/services/model-router/tests/test_router.py -x— 53 passedpython -m py_compile ods/extensions/services/model-router/app/main.py ods/extensions/services/model-router/tests/test_router.pygit diff --checkTradeoffs and rollback
This deliberately closes an undocumented permissive behavior. Clients selecting a concrete runtime must use the switchboard/control plane, then call the stable alias. Revert restores permissive alias coercion; no state or config migration is involved.