From 7e4c7f0ea75c686ffc7b6f022c10cd5ae0f98386 Mon Sep 17 00:00:00 2001 From: "Vyctor H. Brzezowski" Date: Wed, 12 Aug 2026 02:30:46 -0300 Subject: [PATCH] refactor(gateway): make the resolved-auth getter the only WS auth input (#122310) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `attachGatewayWsConnectionHandler` took both a `resolvedAuth` snapshot and an optional `getResolvedAuth`, and used the snapshot for nothing except defaulting the getter. Every production caller already passed the getter, so the snapshot was a second signal for a fact that rotates on config reload — the exact shape that goes stale as sibling paths evolve. Collapse it to one required getter and drop the argument from `server-ws-runtime.ts` and `server-startup-finish.ts`. That also puts `server-startup-finish.ts` back under the 700-line cap, which the preflight change's `getResolvedAuth` pass-through had pushed one line over; the file was already sitting exactly at the limit on `main`. --- src/gateway/server-startup-finish.ts | 2 -- src/gateway/server-ws-runtime.ts | 1 - src/gateway/server/ws-connection.startup.test.ts | 4 ++-- src/gateway/server/ws-connection.test-helpers.ts | 2 +- src/gateway/server/ws-connection.test.ts | 1 - src/gateway/server/ws-connection.ts | 11 +++++++---- 6 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/gateway/server-startup-finish.ts b/src/gateway/server-startup-finish.ts index 668077179899..ecbc07718377 100644 --- a/src/gateway/server-startup-finish.ts +++ b/src/gateway/server-startup-finish.ts @@ -110,7 +110,6 @@ export async function finishGatewayStartup(params: { workerLiveEvents, earlyRuntime, cfgAtStart, - resolvedAuth, preauthConnectionBudget, releaseStartupAccountStarts, cronReconciliation, @@ -151,7 +150,6 @@ export async function finishGatewayStartup(params: { listPluginNodeCapabilities(pluginRuntime.registry), isCoreCanvasHostEnabled(getRuntimeConfig()), ), - resolvedAuth, getResolvedAuth, getRequiredSharedGatewaySessionGeneration: () => getRequiredSharedGatewaySessionGeneration(sharedGatewaySessionGenerationState), diff --git a/src/gateway/server-ws-runtime.ts b/src/gateway/server-ws-runtime.ts index 679e3e49041b..e4e03cdc337e 100644 --- a/src/gateway/server-ws-runtime.ts +++ b/src/gateway/server-ws-runtime.ts @@ -26,7 +26,6 @@ export function attachGatewayWsHandlers(params: GatewayWsRuntimeParams) { gatewayHost: params.gatewayHost, pluginSurfaceScheme: params.pluginSurfaceScheme, getPluginNodeCapabilities: params.getPluginNodeCapabilities, - resolvedAuth: params.resolvedAuth, getResolvedAuth: params.getResolvedAuth, getRequiredSharedGatewaySessionGeneration: params.getRequiredSharedGatewaySessionGeneration, rateLimiter: params.rateLimiter, diff --git a/src/gateway/server/ws-connection.startup.test.ts b/src/gateway/server/ws-connection.startup.test.ts index 1542514eaa4c..89eb1cb1eefd 100644 --- a/src/gateway/server/ws-connection.startup.test.ts +++ b/src/gateway/server/ws-connection.startup.test.ts @@ -37,7 +37,7 @@ describe("attachGatewayWsConnectionHandler startup readiness", () => { clients, socket, options: { - resolvedAuth: { mode: "token", allowTailscale: false, token: "test-token" }, + getResolvedAuth: () => ({ mode: "token", allowTailscale: false, token: "test-token" }), buildRequestContext: () => createGatewayWsTestRequestContext() as never, }, }); @@ -116,7 +116,7 @@ describe("attachGatewayWsConnectionHandler startup readiness", () => { attach: attachGatewayWsConnectionHandler, socket, options: { - resolvedAuth: { mode: "none", allowTailscale: false }, + getResolvedAuth: () => ({ mode: "none", allowTailscale: false }), isStartupPending: () => true, logWsControl: logWsControl as never, buildRequestContext: () => createGatewayWsTestRequestContext() as never, diff --git a/src/gateway/server/ws-connection.test-helpers.ts b/src/gateway/server/ws-connection.test-helpers.ts index 5c7214b63666..ef63c6cac0b5 100644 --- a/src/gateway/server/ws-connection.test-helpers.ts +++ b/src/gateway/server/ws-connection.test-helpers.ts @@ -106,7 +106,7 @@ export function attachGatewayWsForTest(params: { clients: clients as never, preauthConnectionBudget: { release: vi.fn() } as never, port: 19001, - resolvedAuth: createResolvedGatewayTokenAuth("token"), + getResolvedAuth: () => createResolvedGatewayTokenAuth("token"), preauthHandshakeTimeoutMs: 60_000, gatewayMethods: [], events: [], diff --git a/src/gateway/server/ws-connection.test.ts b/src/gateway/server/ws-connection.test.ts index 89109773c50b..6328f6cbf209 100644 --- a/src/gateway/server/ws-connection.test.ts +++ b/src/gateway/server/ws-connection.test.ts @@ -159,7 +159,6 @@ describe("attachGatewayWsConnectionHandler", () => { const { passed } = await connectTestWs({ options: { - resolvedAuth: initialAuth, getResolvedAuth: () => currentAuth, }, }); diff --git a/src/gateway/server/ws-connection.ts b/src/gateway/server/ws-connection.ts index 2a1a76ea3bef..c67c7860e009 100644 --- a/src/gateway/server/ws-connection.ts +++ b/src/gateway/server/ws-connection.ts @@ -160,8 +160,12 @@ type GatewayWsSharedHandlerParams = { gatewayHost?: string; pluginSurfaceScheme?: "http" | "https"; getPluginNodeCapabilities?: () => PluginNodeCapabilitySurface[]; - resolvedAuth: ResolvedGatewayAuth; - getResolvedAuth?: () => ResolvedGatewayAuth; + /** + * Auth is read per connection, not per process: a reload can rotate it while + * this handler stays attached. One getter keeps that the only source, so no + * caller can hand over a snapshot that silently outlives the config it came from. + */ + getResolvedAuth: () => ResolvedGatewayAuth; getRequiredSharedGatewaySessionGeneration?: () => string | undefined; /** Optional rate limiter for auth brute-force protection. */ rateLimiter?: AuthRateLimiter; @@ -240,8 +244,7 @@ export function attachGatewayWsConnectionHandler(params: AttachGatewayWsConnecti port, pluginSurfaceScheme, getPluginNodeCapabilities, - resolvedAuth, - getResolvedAuth = () => resolvedAuth, + getResolvedAuth, getRequiredSharedGatewaySessionGeneration = () => resolveSharedGatewaySessionGeneration( getResolvedAuth(),