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
remote-provider-egress is the production boundary between OpenAI-compatible clients and a configured remote runtime. The catch-all route validated the path and body but discarded the incoming query string, so provider features expressed as encoded or repeated query parameters silently changed in transit.
Root cause and invariant
The FastAPI handler passed only /{full_path} into prepare_upstream_request, and _join_openai_path built a URL from that path alone. The invariant is: after the path allowlist is applied, the original raw query string must reach the same upstream request without decoding, reordering, or collapsing repeated keys.
This change passes Starlette's raw ASCII query string into the pure request-preparation helper and composes it with urllib.parse, while path authorization remains exact and unchanged.
Overlap check
Searched open and closed PRs for remote provider egress query string, egress query passthrough, and the changed production files. Open PRs touching app/main.py are #2733 (caller auth), #2708 (bounded request bodies), #2702 (client LRU), and #2700 (non-blocking probes). None preserves query semantics; ods/bin/remote_provider/egress.py has no overlapping open PR.
Regression coverage
The request-preparation contract now exercises an encoded value plus a repeated key and asserts the exact upstream URL. This is the nearest deterministic boundary before the HTTP client sends the production request, and the FastAPI handler is wired to supply the raw ASGI query bytes.
No query parameters are interpreted or trusted by ODS; they remain provider-owned data after the existing path, route, DNS, body, and credential controls pass. Rollback is a clean revert of this commit, restoring the prior query-dropping behavior.
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
remote-provider-egressis the production boundary between OpenAI-compatible clients and a configured remote runtime. The catch-all route validated the path and body but discarded the incoming query string, so provider features expressed as encoded or repeated query parameters silently changed in transit.Root cause and invariant
The FastAPI handler passed only
/{full_path}intoprepare_upstream_request, and_join_openai_pathbuilt a URL from that path alone. The invariant is: after the path allowlist is applied, the original raw query string must reach the same upstream request without decoding, reordering, or collapsing repeated keys.This change passes Starlette's raw ASCII query string into the pure request-preparation helper and composes it with
urllib.parse, while path authorization remains exact and unchanged.Overlap check
Searched open and closed PRs for
remote provider egress query string,egress query passthrough, and the changed production files. Open PRs touchingapp/main.pyare #2733 (caller auth), #2708 (bounded request bodies), #2702 (client LRU), and #2700 (non-blocking probes). None preserves query semantics;ods/bin/remote_provider/egress.pyhas no overlapping open PR.Regression coverage
The request-preparation contract now exercises an encoded value plus a repeated key and asserts the exact upstream URL. This is the nearest deterministic boundary before the HTTP client sends the production request, and the FastAPI handler is wired to supply the raw ASGI query bytes.
Validation
python ods/tests/contracts/test-remote-provider-egress-service.py— 16 passedpython -m py_compile ods/bin/remote_provider/egress.py ods/extensions/services/remote-provider-egress/app/main.pygit diff --checkTradeoffs and rollback
No query parameters are interpreted or trusted by ODS; they remain provider-owned data after the existing path, route, DNS, body, and credential controls pass. Rollback is a clean revert of this commit, restoring the prior query-dropping behavior.