fix(binding-llm): llm server options.authorization guard support - #2591
Merged
Merged
Conversation
jfallows
force-pushed
the
claude/wonderful-cerf-k273d3
branch
from
September 18, 2026 04:12
65def80 to
e7a57df
Compare
This was referenced Sep 18, 2026
Wires `llm server` into the options.authorization convention (guard name + credentials template), mirroring binding-mcp's server-side pattern. The dialect resolved for a request selects which header carries credentials (Authorization for openai, x-api-key for anthropic) via a new LlmDialect.credentialsHeader() extension point; a request whose header doesn't match the configured template, or whose extracted token the guard rejects, is turned away with a 401 response shaped in the resolved dialect's own JSON error envelope (LlmDialect.unauthorizedBody()). Adds LlmAuthorizationConfig/Builder (config surface), LlmBindingConfig guard resolution + authorize(), and LlmServerFactory's LlmUnauthorizedResponder for the reject path, plus config adapter tests and IT coverage (accept/reject, both dialects) mirroring binding-mcp's authorization IT pattern. Fixes #2498 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017zzRpze4nXEv4dbNjkRSVk
jacoco flagged binding-llm.conf at 0.97 instruction coverage (rule requires 1.00): LlmAuthorizationConfig.builder() (no-arg) and LlmAuthorizationConfigBuilder.thisType() were never exercised, since every existing usage goes through LlmOptionsConfigBuilder.authorization() (the mapper-taking overload). Adds the same builder()/inject() coverage pair LlmOptionsConfigTest already uses for LlmOptionsConfig and LlmServerConfig. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017zzRpze4nXEv4dbNjkRSVk
jfallows
force-pushed
the
claude/wonderful-cerf-k273d3
branch
from
September 30, 2026 14:16
986ec91 to
8ebc29c
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.
Description
Wires
llm serverinto the existingoptions.authorizationconvention (guard name +credentialstemplate) to validate inbound request credentials, matchingbinding-mcp's server-side pattern (options.authorizationon themcp(server)binding,McpOptionsConfigAdapter/McpServerFactory).LlmAuthorizationConfig/LlmAuthorizationConfigBuilderand wiredauthorizationintoLlmOptionsConfig/LlmOptionsConfigBuilder/LlmOptionsConfigAdapter, mirroringMcpAuthorizationConfig's shape (guard name as JSON key,credentialstemplate defaulting toBearer {credentials}).llm.schema.patch.jsonwithoptions.authorizationunder thekind: serverbranch, following the samepatternProperties-by-guard-name shapebinding-mcpuses.LlmDialect.credentialsHeader()andLlmDialect.unauthorizedBody()extension points (default methods), overridden per dialect:LlmOpenaiDialectexpects credentials inauthorizationand returns an OpenAI-shapedinvalid_api_keyerror body;LlmAnthropicDialectexpectsx-api-keyand returns an Anthropic-shapedauthentication_errorbody.LlmBindingConfigresolves the configured guard and compiles the credentials template into a matcher (same idiom asMcpBindingConfig), exposingauthorize(...)to check a request's dialect-selected header against it and callGuardHandler.reauthorize/deauthorizedirectly — no new guard mechanism.LlmServerFactorycallsauthorize(...)once the dialect is resolved; a rejected request never reaches app0 and instead gets a401response shaped in the resolved dialect's own JSON error envelope via a newLlmUnauthorizedResponder. An accepted request's guard session is deauthorized when the stream closes.Test plan
LlmOptionsConfigAdapterTestwith read/write coverage foroptions.authorization(default and explicit credentials templates); addedLlmAuthorizationConfig/Builderfactory coverage (builder()/inject()) toLlmOptionsConfigTestfor 100% instruction coverage.binding-mcp's authorization IT pattern — new pairedclient.rpt/server.rptscenarios underincubator/binding-llm.specfor both dialects:openai.request.guarded,anthropic.request.guarded(accept),openai.request.rejected.authorization,anthropic.request.rejected.authorization(reject), plus aserver.guarded.yamlfixture usingtype: testguard per repo convention.NetworkIT(peer-to-peer self-consistency, required perspecs/AGENTS.md) andLlmServerIT(live-engine)../mvnw verify -pl incubator/binding-llm— full module green includingLlmClientIT(its earlier failures were fixed upstream in fix(binding-llm): coherent, extensible dialect schema for cross-dialect translation #2590)../mvnw verify -pl incubator/binding-llm.spec -Dit.test=NetworkIT,ApplicationIT— 26/26 and 19/19 pass../mvnw checkstyle:check/license:check— clean on changed files.Fixes #2498
🤖 Generated with Claude Code
https://claude.ai/code/session_017zzRpze4nXEv4dbNjkRSVk
Generated by Claude Code