Repository navigation
feat!: the membership token travels in x-httpeers-token, never Authorization - #9
Merged
Merged
Conversation
…ization Authorization belongs to the application a mesh request is addressed to. While the mesh kept its token there, the two collided: LiteLLM's Playground (the OpenAI SDK) sends its own key as Authorization: Bearer sk-..., the ServiceWorker edge would not overwrite a page's Authorization, so no mesh token was attached and withAccess refused the LiteLLM key as 401 "malformed token" -- LiteLLM never saw the call. - httpeers-core: MESH_TOKEN_HEADER (x-httpeers-token, bare token), setMeshToken/readMeshToken, and MESH_CREDENTIAL_HEADERS -- the mesh headers a request leaving the mesh must not carry. - httpeers-access: withAccess reads only MESH_TOKEN_HEADER. - httpeers-member: peerRequest and the edge write it; the edge attaches the token whatever the page put in Authorization, and still never overwrites a membership token the page set itself. - httpeers-ghost: the pin writes the viewer's token there. - hub llm passthrough: strips MESH_CREDENTIAL_HEADERS; any Bearer key in Authorization moves to x-litellm-api-key; Authorization never reaches LiteLLM. - conformance: a source scan pins that no library touches Authorization and only httpeers-core spells the header name. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…peers-token - demos proxy page: its upstream strips MESH_CREDENTIAL_HEADERS. The proxy now forwards what it is not told to strip, so without this every visitor's membership token would reach whatever origin a route names. The builder moved to shared/proxy-upstream.ts so that is tested. - llm-chat, LiteLLM config: the reasons given for x-litellm-api-key no longer mention a mesh token in Authorization; behaviour is unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…lication's Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
0.2.0 is the release where urlUpstream forwards Authorization, which the demos proxy and the hub passthrough now rely on. On 0.x, ^0.1.0 never matches it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
mkotelnikov
force-pushed
the
mesh-auth-header
branch
from
September 19, 2026 13:24
5740ff3 to
af876b7
Compare
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.
Why
LiteLLM's Playground, opened through the mesh (
/peers/<hub>/llm/ui/), failed every call with401 "malformed token". The Playground sends its key through the OpenAI SDK, which always puts it inAuthorization: Bearer sk-…. The mesh token was in the same header, and the ServiceWorker edge never overwrites a page'sAuthorization. So no mesh token was attached, andwithAccesstried to verify the LiteLLM key as a mesh token. LiteLLM never saw the request.Authorizationbelongs to the application a request is addressed to. The mesh now uses its own header for its token.What changes
MESH_TOKEN_HEADER=x-httpeers-token(the bare token, noBearerprefix),setMeshToken/readMeshToken, andMESH_CREDENTIAL_HEADERS(the token header plusx-httpeers-peer), which lists the headers a request leaving the mesh must not carry.withAccessreads onlyMESH_TOKEN_HEADER. A token sent inAuthorizationis treated as absent, andAuthorizationis left on the request for the handler.peerRequestand the edge write the new header. The edge attaches the token whatever the page put inAuthorization, and still never overwrites a mesh token the page set itself.MESH_CREDENTIAL_HEADERS. ABearervalue inAuthorizationmoves tox-litellm-api-key(the header the appliance's LiteLLM reads) when that header is absent.Authorizationnever reaches LiteLLM.MESH_CREDENTIAL_HEADERS. The builder moved toshared/proxy-upstream.tsso it can be tested.Authorization, or spells the header name outsidehttpeers-core.docs/security-model.md, and the LiteLLM config comments.All tests were written first and watched fail.
tests/llm-mesh-credentials.test.tsreproduces the Playground request end to end throughwithAccessand the llm module.Breaking: deploy the hub and the pages together
An old page sends its token in
Authorization, and a new hub refuses it with401 "membership token required". The reverse mismatch fails the same way. The hub and the static pages must be redeployed together.Related
mesh-auth-header:urlUpstreamstops droppingauthorization. This PR does not depend on it: with the publishedwebrun-http-proxy0.1.0, the passthrough moves the key before the proxy dropsauthorization, and the mesh headers are stripped either way.mesh-auth-header: dated amendments to the design specs.Verification
A clean
pnpm -r run build,test,typecheckandlint:checkof the httpeers + webrun-wire assembly all pass, with the same skips asmain. Not yet checked against the live server.🤖 Generated with Claude Code