Repository navigation
Send a Host-supplied plan proof to the Gateway, and contact a loopback Gateway directly - #14
Draft
sublimator wants to merge 2 commits into
Draft
sublimator wants to merge 2 commits into
sublimator wants to merge 2 commits into
Conversation
The ChatGPT plan extension proposed for `runvil-gateway` serves a plan model only to a caller that presents the plan proof of the Gateway's current boot, in the header `X-Runvil-Plan-Proof`. `harness-gateway-client` could not send one. A Host now passes the proof to `GatewayChat::with_plan_proof` or `GatewayBroker::with_plan_proof`, and the client sends it on each model round and on the model list. - `PLAN_PROOF_HEADER` names the header. A client that was given no proof omits it, so its requests are the ones it sent before. - The proof is a `SecretString` and is not a bearer. `Authorization` is unchanged, and `Debug` prints `<redacted>` for the proof on `GatewayChat` and on `GatewayBroker`. - `fetch_model_catalog_with_plan_proof` sends the proof on its one request, and `fetch_model_catalog` sends none. Both call the private `fetch_catalog`. - The crate reads no file and no environment variable for the proof. `GatewayChat::from_env` gains no variable, and `GatewaySearch` sends no proof. - `build_request_body` is unchanged, because the proof is a header. - New tests pin the header beside the bearer, the header on a keyless client, its absence without the call and through `from_env`, the model list with and without a proof, and the redaction. Plan: /plan/2026-11-14-1-plan-proof-and-direct-loopback.plan.md
Every client in `harness-gateway-client` was `reqwest::Client::new()`, which uses the process's proxy settings and follows redirects. A request to a Gateway on the local machine could go out through `HTTP_PROXY` or `ALL_PROXY` with the bearer key and the plan proof in it, and a redirect could send the plan proof and the request body to another server. A loopback Gateway is now contacted with no proxy, and a redirect comes back as its own status. Any other address keeps reqwest's defaults. - `transport::http_client` builds the client from `GatewayEndpoint::is_loopback`. For a loopback endpoint it sets `no_proxy()` and `redirect::Policy::none()`. A failed build panics, because a fall back to the default client would bring both back. - `GatewayChat::new`, `GatewayChat::keyless`, and `GatewaySearch` use it. The catalog keeps two process-wide clients, one for a loopback Gateway and one for any other. - `fetch_model_catalog` and `fetch_model_catalog_with_plan_proof` validate `base_url` with `GatewayEndpoint::new` before any request. A root that is not http or https, names no host, embeds credentials, or has a query or a fragment returns `InvalidValue`. It was sent as written. - `tests/loopback_direct.rs` gives a chat round, a catalog fetch, and a search a redirect from a loopback Gateway, and the target must receive nothing. It runs the same three in a child process with `HTTP_PROXY` and `ALL_PROXY` set to a counting listener, after a plain reqwest client proves that the listener is consulted. - `an_invalid_loopback_catalog_root_is_refused_before_any_request` pins the refusal for a query, a fragment, and credentials, and that the error repeats none of the input. Plan: /plan/2026-11-14-1-plan-proof-and-direct-loopback.plan.md
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
|
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Draft, for reference. One of three drafts that together add Sign in with
ChatGPT. The others are cppalliance/runvil-gateway#35 and cppalliance/runvil-workshop#22. This is the
smallest, and Workshop's draft pins it. Use it or not.
What it does
Two commits on
9dd953b5, both inharness-gateway-client.sends it as
X-Runvil-Plan-Proofon model rounds and on the model list.The Gateway serves a person's ChatGPT-plan models only to a caller that
presents the proof it published for its current boot. Without a proof the
client sends what it sent before.
Debugredacts the proof like the key.no redirect and ignores the process proxy. A bearer or a proof then cannot
be carried to another server. Any other Gateway keeps today's behaviour.
fetch_model_catalognow validates its API rootthe way a chat endpoint is validated. A root with a query, a fragment or
credentials is refused with
InvalidValue. It used to be sent as written.build_request_bodyis untouched, because the proof is a header. The plannote is
plan/2026-11-14-1-plan-proof-and-direct-loopback.plan.md.One choice a reviewer may question: a loopback client that cannot be built
panics.
reqwest::Client::newalready panics on the same failure, andreturning the error would change the constructors' signatures.
How it was checked
On macOS arm64 only.
AGENTS.md, pluscargo denyandcargo audit. Thefacade check reports 0 violations and unchanged listings.
harness-test-pluginlifecycle::the_fixture_is_loaded_invoked_unloaded_once_and_closed. Itfails the same way on
9dd953b5itself on this Mac.no_proxy()is removed, and the redirect testsfail when the redirect policy is removed.
Not done