feat(identity): emit X-Client-ID header on every outbound request (v9)#177
Merged
Conversation
Every governed request now carries an X-Client-ID header alongside the existing Basic Auth + X-Axonflow-Client headers, matching the v9 identity contract on the platform (Epic getaxonflow/axonflow-enterprise#2230). The header value mirrors the SDK's Basic Auth username — smart default "community" when no clientId is configured. The agent's apiAuthMiddleware overwrites the header with its auth-derived value, so caller-supplied values are harmless (no spoofing surface). Backward-compatible with v8 agents (they ignore the unknown header). Bumps to v8.1.0. Tests in XClientIdHeaderTest.java assert header presence + value across community + configured-client paths, and pin that the SDK does NOT send legacy X-Tenant-ID. Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com>
Per CLAUDE.md HARD RULE #0: gate requires runtime-e2e/<feature>/ test for user-facing surface changes. Adds the v9 X-Client-ID counterpart to x-axonflow-client/ runner — spawns an in-process forwarding proxy (JDK HttpServer + HttpClient) that captures the outbound X-Client-ID off the wire and forwards to the real agent. Asserts captured value equals the configured clientId. Prereqs: AXONFLOW_AGENT_URL, AXONFLOW_TENANT_ID, AXONFLOW_TENANT_SECRET. Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com>
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.
Summary
Closes the SDK side of Epic #2230 (v9 identity cleanup), workstream B. Every governed request now carries an
X-Client-ID: <effective_client_id>header alongside the existing Basic Auth +X-Axonflow-Clientheaders."community"when noclientIdis configured.addAuthHeaders(AxonFlow.java), the canonical funnel for every governed request.apiAuthMiddleware(PR getaxonflow/axonflow-enterprise#2233) overwrites the header with its auth-derived value, so caller-supplied values are harmless (no spoofing surface).Bumps to v8.1.0.
Compatibility
R1 — mechanical
mvn testclean — 1239 tests passed, 0 failures, 0 errorsXClientIdHeaderTest.javacovers the new code pathR2 — functional (real HTTP transport via WireMock)
Tests in
XClientIdHeaderTest.javaroute a realproxyLLMCallthrough the SDK's OkHttp client at a WireMock-stubbed endpoint, then assert against headers WireMock captured off the wire. This is not a builder-state assertion in-memory — the test only sees the header if the SDK's HTTP client successfully wrote it to the socket. Mutation evidence below confirms.Captured outbound headers (WireMock log):
AuthorizationBasic Y29tbXVuaXR5Og==Basic YWNtZS1jb3JwOnNlY3JldA==X-Axonflow-Clientsdk-java/8.1.0sdk-java/8.1.0X-Client-IDcommunityacme-corpX-Tenant-IDR3 — hostile self-review
feedback_mutation_test_to_prove_assertion_not_tautological.md): removedbuilder.header("X-Client-ID", effectiveClientId);in scratch copy → 2/3 new tests FAILED (communityDefault,configuredClient). Restored. Assertions are not tautological.extraHeadersconfig field. Server-side, the agent'sapiAuthMiddlewareoverwrites the header regardless.X-Client-ID) and value shape (raw effective client_id, no prefix) match Go/Python/TS/Rust PRs in the same release train.noLegacyTenantHeader) pins that the SDK does NOT emitX-Tenant-ID— the agent accepts it as an alias through v9 for back-compat, but SDK-side we standardize onX-Client-ID.Workstream coordination
feedback_sub_sessions_admin_merge_when_ci_green_r3_done.md, this PR admin-merges on green CI + R3 done; no master gating.