Skip to content

Extract proxy auth into a token.Source abstraction#228

Merged
samcm merged 2 commits into
masterfrom
refactor-auth-tokensource
Jun 17, 2026
Merged

Extract proxy auth into a token.Source abstraction#228
samcm merged 2 commits into
masterfrom
refactor-auth-tokensource

Conversation

@samcm

@samcm samcm commented Jun 17, 2026

Copy link
Copy Markdown
Member

Token handling was split across two packages and implemented twice — the interactive grant in pkg/auth/{client,store}, and a separate in-memory client_credentials cache plus mode-branching and a mode-specific 401 retry living inside the proxy client. This introduces pkg/auth/token with one Source interface (Token/Invalidate) and a NewSource factory that owns the grant decision and builds the OAuth client + credential store, so the proxy resolves only its issuer and holds an opaque Source — the ccTokens cache, usesClientCredentials branching, and clientCredentialsToken all leave pkg/proxy. It also refreshes the access token proactively at 50% of its lifetime (shared client.ShouldRefresh policy, a one-line change to flip to 75%) rather than waiting for the 5-minute expiry buffer, and adds a uniform invalidate-and-retry-once on 401/403 across every server-to-proxy request path (ClickHouseQuery, Discover, the server-side query funnel, and the embedder), replacing the client_credentials-only retry so a server-side token revocation self-heals regardless of grant.

proxy.Service gains an Invalidate() method (used by the retry), which required a one-line addition to the existing proxy implementations and test fakes.

Token handling was split across two packages and implemented twice: the
interactive grant lived in pkg/auth/{client,store} while the proxy client
carried its own client_credentials token cache, mode branching, and a
mode-specific 401 retry. The proxy — whose job is to send authenticated
requests — knew which OAuth grant was in play and ran one of two token
caches.

Introduce pkg/auth/token with a single Source interface (Token /
Invalidate) and a NewSource factory that owns the grant decision and the
construction of the OAuth client and credential store. The proxy now
resolves only its issuer and holds an opaque Source; the ccTokens cache,
usesClientCredentials branching, and clientCredentialsToken all leave
pkg/proxy.

Refresh the access token proactively at 50% of its lifetime (shared
client.ShouldRefresh policy) instead of waiting for the 5-minute expiry
buffer, leaving a wide margin before expiry. Add a uniform
invalidate-and-retry-once on 401/403 across every server-to-proxy request
path (ClickHouseQuery, Discover, the server-side query funnel, and the
embedder), replacing the client_credentials-only retry, so a token
revoked before the local buffer self-heals regardless of grant.
@github-actions

github-actions Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

🐼 Smoke eval — da84747: ✅ 6/6 pass

📊 Interactive report — tokens p50 13,844 · tokens/solve 13,930.

Reference points: v0.33.0 100% · refactor-auth-tokensource@d822db0 100% · master@e46fe2b 100%.

question result tokens tools
forky_node_coverage 12,415 3
tracoor_node_coverage 13,117 4
mainnet_block_arrival_p50 17,338 12
list_datasources 11,395 1
block_count_24h 14,571 8
missed_slots_24h 14,741 6
🔭 Langfuse traces (6 runs; ⚠️ = failed)

The report walks this branch's commits against the master baseline and the most recent release. A self-contained copy is in the run's eval-smoke-* artifact.

Restores pre-refactor behaviour: the interactive refresh Source now
reloads the credential file on every Token call, so a login or logout
performed by the host CLI on the bind-mounted credentials file is
observed by a running server without a restart. Returns ErrNotAuthenticated
when the file is absent.
@samcm samcm merged commit 732d7b3 into master Jun 17, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant