mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-02 14:11:35 +00:00
fix(gateway): shutdown reports unresolved SecretRef warnings when channel credentials use exec/file refs (#112717)
* fix(gateway): clear secrets runtime snapshot only after channel teardown Shutdown cleared the secrets runtime snapshot in the close prelude, which also drops the pinned runtime config. The channels close step then lazily re-pins the raw config, so stopChannel's resolveAccount hit unresolved SecretRefs and every shutdown of a gateway with an exec/file SecretRef credential logged an unresolved-SecretRef WARN and completed with warnings. The failed resolveAccount also skipped the per-account stop bookkeeping (graceful wait, task/abort cleanup, stopped-runtime state) and the plugin stopAccount hook. Move the scrub into the close handler's finally block so it still always runs, but only after every step that can read credentials. Fixes #112681 * chore: drop release-owned changelog entry --------- Co-authored-by: FullerStackDev <263060202+fuller-stack-dev@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
5d4ff17d7d
commit
7072ba50e2
@@ -281,6 +281,45 @@ describe("createGatewayCloseHandler", () => {
|
||||
expect(stopChannel).toHaveBeenCalledWith("discord");
|
||||
});
|
||||
|
||||
it("clears the secrets runtime snapshot only after channels stop (#112681)", async () => {
|
||||
const events: string[] = [];
|
||||
const stopChannel = vi.fn(async (channelId: string) => {
|
||||
events.push(`channel:${channelId}`);
|
||||
});
|
||||
const clearSecretsRuntimeSnapshot = vi.fn(() => {
|
||||
events.push("clear-secrets");
|
||||
});
|
||||
const close = createGatewayCloseHandler(
|
||||
createGatewayCloseTestDeps({
|
||||
channelIds: ["telegram"],
|
||||
stopChannel,
|
||||
clearSecretsRuntimeSnapshot,
|
||||
}),
|
||||
);
|
||||
|
||||
await close({ reason: "test" });
|
||||
|
||||
expect(events).toEqual(["channel:telegram", "clear-secrets"]);
|
||||
});
|
||||
|
||||
it("clears the secrets runtime snapshot even when a channel stop fails", async () => {
|
||||
const clearSecretsRuntimeSnapshot = vi.fn();
|
||||
const close = createGatewayCloseHandler(
|
||||
createGatewayCloseTestDeps({
|
||||
channelIds: ["telegram"],
|
||||
stopChannel: vi.fn(async () => {
|
||||
throw new Error("stop failed");
|
||||
}),
|
||||
clearSecretsRuntimeSnapshot,
|
||||
}),
|
||||
);
|
||||
|
||||
const result = await close({ reason: "test" });
|
||||
|
||||
expect(clearSecretsRuntimeSnapshot).toHaveBeenCalledTimes(1);
|
||||
expect(result.warnings).toContain("channel/telegram");
|
||||
});
|
||||
|
||||
it("awaits post-ready sidecars before plugin services and channels", async () => {
|
||||
const events: string[] = [];
|
||||
let releaseSidecar!: () => void;
|
||||
|
||||
@@ -619,7 +619,6 @@ export async function runGatewayClosePrelude(params: {
|
||||
disposeBrowserAuthRateLimiter: () => void;
|
||||
stopChannelHealthMonitor?: () => Promise<void>;
|
||||
stopReadinessEventLoopHealth?: () => void;
|
||||
clearSecretsRuntimeSnapshot?: () => void;
|
||||
closeMcpServer?: () => Promise<void>;
|
||||
}): Promise<void> {
|
||||
params.stopDiagnostics?.();
|
||||
@@ -629,7 +628,6 @@ export async function runGatewayClosePrelude(params: {
|
||||
params.disposeBrowserAuthRateLimiter();
|
||||
await params.stopChannelHealthMonitor?.();
|
||||
params.stopReadinessEventLoopHealth?.();
|
||||
params.clearSecretsRuntimeSnapshot?.();
|
||||
await params.closeMcpServer?.().catch(() => {});
|
||||
}
|
||||
|
||||
@@ -674,6 +672,7 @@ export function createGatewayCloseHandler(
|
||||
bonjourStop: (() => Promise<void>) | null;
|
||||
tailscaleCleanup: (() => Promise<void>) | null;
|
||||
releasePluginRouteRegistry?: (() => void) | null;
|
||||
clearSecretsRuntimeSnapshot?: (() => void) | null;
|
||||
channelIds?: readonly ChannelId[];
|
||||
stopChannel: (name: ChannelId, accountId?: string) => Promise<void>;
|
||||
pluginServices: PluginServicesHandle | null;
|
||||
@@ -1043,6 +1042,13 @@ export function createGatewayCloseHandler(
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
// Channel and plugin teardown still resolve account credentials. Keep the
|
||||
// active snapshot until every teardown owner is done, then always scrub it.
|
||||
try {
|
||||
params.clearSecretsRuntimeSnapshot?.();
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
|
||||
const durationMs = Date.now() - start;
|
||||
|
||||
@@ -370,7 +370,6 @@ export async function prepareGatewayLifecycle(params: {
|
||||
await monitor?.waitForIdle();
|
||||
},
|
||||
stopReadinessEventLoopHealth: readinessEventLoopHealth.stop,
|
||||
clearSecretsRuntimeSnapshot,
|
||||
closeMcpServer: closeMcpLoopbackServerOnDemand,
|
||||
});
|
||||
};
|
||||
@@ -407,6 +406,7 @@ export async function prepareGatewayLifecycle(params: {
|
||||
bonjourStop: runtimeState.bonjourStop,
|
||||
tailscaleCleanup: runtimeState.tailscaleCleanup,
|
||||
releasePluginRouteRegistry,
|
||||
clearSecretsRuntimeSnapshot,
|
||||
channelIds,
|
||||
stopChannel,
|
||||
pluginServices: runtimeState.pluginServices,
|
||||
|
||||
Reference in New Issue
Block a user