diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cf1383a2d9..1121fe4eb76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ Docs: https://docs.openclaw.ai ### Changes +- Gateway/startup: skip plugin-backed auth-profile overlays during startup secrets preflight, reducing gateway readiness latency while keeping reload and OAuth recovery paths overlay-capable. (#68327) Thanks @JIRBOY. + ### Fixes - CLI/update: treat inherited Gateway service markers as origin hints and only block package replacement when the managed Gateway is still live, so self-updates can stop the service and continue safely. (#75729) Thanks @hxy91819. diff --git a/src/gateway/server-startup-config.secrets.test.ts b/src/gateway/server-startup-config.secrets.test.ts index d11475be4cd..192790bb6f3 100644 --- a/src/gateway/server-startup-config.secrets.test.ts +++ b/src/gateway/server-startup-config.secrets.test.ts @@ -1,4 +1,5 @@ import { afterEach, describe, expect, it, vi } from "vitest"; +import { loadAuthProfileStoreWithoutExternalProfiles } from "../agents/auth-profiles.js"; import type { ConfigFileSnapshot, OpenClawConfig } from "../config/types.js"; import type { PreparedSecretsRuntimeSnapshot, SecretResolverWarning } from "../secrets/runtime.js"; import { KNOWN_WEAK_GATEWAY_TOKEN_PLACEHOLDERS } from "./known-weak-gateway-secrets.js"; @@ -105,6 +106,30 @@ describe("gateway startup config secret preflight", () => { expect(emitStateEvent).not.toHaveBeenCalled(); }); + it("uses persisted auth stores only for startup secret preflight", async () => { + const prepareRuntimeSecretsSnapshot = vi.fn(async ({ config }) => preparedSnapshot(config)); + const activateRuntimeSecrets = createRuntimeSecretsActivator({ + logSecrets: { + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + }, + emitStateEvent: vi.fn(), + prepareRuntimeSecretsSnapshot, + activateRuntimeSecretsSnapshot: vi.fn(), + }); + + await activateRuntimeSecrets(gatewayTokenConfig({}), { + reason: "startup", + activate: false, + }); + + expect(prepareRuntimeSecretsSnapshot).toHaveBeenCalledWith({ + config: expect.any(Object), + loadAuthStore: loadAuthProfileStoreWithoutExternalProfiles, + }); + }); + it("does not emit degraded or recovered events for warning-only secret reloads", async () => { const warning: SecretResolverWarning = { code: "WEB_SEARCH_KEY_UNRESOLVED_FALLBACK_USED", @@ -156,6 +181,9 @@ describe("gateway startup config secret preflight", () => { "[WEB_SEARCH_KEY_UNRESOLVED_FALLBACK_USED] web search provider fell back to environment credentials", ); expect(emitStateEvent).not.toHaveBeenCalled(); + expect(prepareRuntimeSecretsSnapshot).toHaveBeenCalledWith({ + config: expect.any(Object), + }); }); it.each(KNOWN_WEAK_GATEWAY_TOKEN_PLACEHOLDERS)( @@ -245,6 +273,7 @@ describe("gateway startup config secret preflight", () => { config: expect.not.objectContaining({ channels: expect.anything(), }), + loadAuthStore: loadAuthProfileStoreWithoutExternalProfiles, }); }); @@ -294,6 +323,7 @@ describe("gateway startup config secret preflight", () => { }), }), }), + loadAuthStore: loadAuthProfileStoreWithoutExternalProfiles, }); expect(activateRuntimeSecretsSnapshot).toHaveBeenCalledTimes(1); }); @@ -327,6 +357,7 @@ describe("gateway startup config secret preflight", () => { }), }), }), + loadAuthStore: loadAuthProfileStoreWithoutExternalProfiles, }); }); diff --git a/src/gateway/server-startup-config.ts b/src/gateway/server-startup-config.ts index 00b391fec39..96850931f09 100644 --- a/src/gateway/server-startup-config.ts +++ b/src/gateway/server-startup-config.ts @@ -1,3 +1,4 @@ +import { loadAuthProfileStoreWithoutExternalProfiles } from "../agents/auth-profiles.js"; import { formatCliCommand } from "../cli/command-format.js"; import { readConfigFileSnapshotWithPluginMetadata, @@ -366,8 +367,13 @@ export function createRuntimeSecretsActivator(params: { return async (config, activationParams) => await runWithSecretsActivationLock(async () => { try { + const startupPreflight = + activationParams.reason === "startup" || activationParams.reason === "restart-check"; const prepared = await prepareRuntimeSecretsSnapshot({ config: pruneSkippedStartupSecretSurfaces(config), + ...(startupPreflight + ? { loadAuthStore: loadAuthProfileStoreWithoutExternalProfiles } + : {}), }); assertRuntimeGatewayAuthNotKnownWeak(prepared.config); if (activationParams.activate) {