diff --git a/src/gateway/credentials.test.ts b/src/gateway/credentials.test.ts index 83ac99dbc80..1de2ce06541 100644 --- a/src/gateway/credentials.test.ts +++ b/src/gateway/credentials.test.ts @@ -86,6 +86,42 @@ describe("resolveGatewayCredentialsFromConfig", () => { expectEnvGatewayCredentials(resolved); }); + it("falls back to remote credentials in local mode when local auth is missing", () => { + const resolved = resolveGatewayCredentialsFromConfig({ + cfg: cfg({ + gateway: { + mode: "local", + remote: { token: "remote-token", password: "remote-password" }, + auth: {}, + }, + }), + env: {} as NodeJS.ProcessEnv, + includeLegacyEnv: false, + }); + expect(resolved).toEqual({ + token: "remote-token", + password: "remote-password", + }); + }); + + it("keeps local credentials ahead of remote fallback in local mode", () => { + const resolved = resolveGatewayCredentialsFromConfig({ + cfg: cfg({ + gateway: { + mode: "local", + remote: { token: "remote-token", password: "remote-password" }, + auth: { token: "local-token", password: "local-password" }, + }, + }), + env: {} as NodeJS.ProcessEnv, + includeLegacyEnv: false, + }); + expect(resolved).toEqual({ + token: "local-token", + password: "local-password", + }); + }); + it("uses remote-mode remote credentials before env and local config", () => { const resolved = resolveRemoteModeWithRemoteCredentials(); expect(resolved).toEqual({ diff --git a/src/gateway/credentials.ts b/src/gateway/credentials.ts index ff974728360..ace7ba4fd27 100644 --- a/src/gateway/credentials.ts +++ b/src/gateway/credentials.ts @@ -116,7 +116,7 @@ export function resolveGatewayCredentialsFromConfig(params: { const mode: GatewayCredentialMode = params.modeOverride ?? (params.cfg.gateway?.mode === "remote" ? "remote" : "local"); - const remote = mode === "remote" ? params.cfg.gateway?.remote : undefined; + const remote = params.cfg.gateway?.remote; const envToken = readGatewayTokenEnv(env, includeLegacyEnv); const envPassword = readGatewayPasswordEnv(env, includeLegacyEnv); @@ -129,9 +129,14 @@ export function resolveGatewayCredentialsFromConfig(params: { const localPasswordPrecedence = params.localPasswordPrecedence ?? "env-first"; if (mode === "local") { + // In local mode, prefer gateway.auth.token, but also accept gateway.remote.token + // as a fallback for cron commands and other local gateway clients. + // This allows users in remote mode to use a single token for all operations. + const fallbackToken = localToken ?? remoteToken; + const fallbackPassword = localPassword ?? remotePassword; const localResolved = resolveGatewayCredentialsFromValues({ - configToken: localToken, - configPassword: localPassword, + configToken: fallbackToken, + configPassword: fallbackPassword, env, includeLegacyEnv, tokenPrecedence: localTokenPrecedence,