From 70d7e7abf6e4792b6aaf2452df6420036b73adeb Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 28 Sep 2026 18:48:40 -0700 Subject: [PATCH] test(e2e): seed OAuth authority-chain shared store through its owner oauth-refresh-authority-chain.e2e failed 2 of 3 cases in the 2026.9.7 repo E2E Gateway 4/4 lane (readSharedCredential returned undefined). The fixture wrote the shared auth store straight into the state database without initializing shared-auth ownership, so the test process resolved and cached legacy-main ownership while the Gateway later published state-db ownership; the test then read the empty legacy store. The connect-time ownership reload no longer covered that gap. Product rotation and mismatch fencing behaved correctly. Seed every scenario (including the empty logout store) through runAuthProfileWriteTransaction so the test and the Gateway select the same canonical owner before any turn, and drop the obsolete reload. All behavior assertions are unchanged. Proof: reproduced 2 failed / 1 passed on origin/main; after the change the file passes 3/3 (119 s wall, includes Gateway restart and logout), owner auth-profile tests 7/7. --- .../oauth-refresh-authority-chain.e2e.test.ts | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/test/oauth-refresh-authority-chain.e2e.test.ts b/test/oauth-refresh-authority-chain.e2e.test.ts index 84c1fcd3b095..24b4055aa26e 100644 --- a/test/oauth-refresh-authority-chain.e2e.test.ts +++ b/test/oauth-refresh-authority-chain.e2e.test.ts @@ -8,19 +8,18 @@ import { isOAuthRefreshFence, isPendingOAuthRefreshFence, } from "../src/agents/auth-profiles/oauth-refresh-marker.js"; -import { reloadSharedAuthStoreOwnership } from "../src/agents/auth-profiles/path-resolve.js"; import { loadPersistedAuthProfileStore, loadPersistedSharedAuthProfileStore, } from "../src/agents/auth-profiles/persisted.js"; -import { writePersistedAuthProfileStoreRaw } from "../src/agents/auth-profiles/sqlite.js"; +import { + runAuthProfileWriteTransaction, + writePersistedAuthProfileStoreRaw, +} from "../src/agents/auth-profiles/sqlite.js"; import type { AuthProfileStore, OAuthCredential } from "../src/agents/auth-profiles/types.js"; import { connectGatewayClient, disconnectGatewayClient } from "../src/gateway/test-helpers.e2e.js"; import { closeOpenClawAgentDatabasesForTest } from "../src/state/openclaw-agent-db.js"; -import { - closeOpenClawStateDatabaseForTest, - runOpenClawStateWriteTransaction, -} from "../src/state/openclaw-state-db.js"; +import { closeOpenClawStateDatabaseForTest } from "../src/state/openclaw-state-db.js"; import { writeOpenAiResponsesText } from "./helpers/openai-responses-sse.js"; import { createOpenClawTestInstance, @@ -130,7 +129,7 @@ function authStore(credential?: OAuthCredential): AuthProfileStore { return { version: 1, profiles: credential ? { [PROFILE_ID]: credential } : {}, - order: { [PROVIDER_ID]: [PROFILE_ID] }, + ...(credential ? { order: { [PROVIDER_ID]: [PROFILE_ID] } } : {}), }; } @@ -410,7 +409,8 @@ async function createScenario(name: string): Promise { } function writeSharedStore(instance: OpenClawTestInstance, store: AuthProfileStore): void { - runOpenClawStateWriteTransaction( + runAuthProfileWriteTransaction( + undefined, (database) => writePersistedAuthProfileStoreRaw(store, undefined, database), { env: instance.env }, ); @@ -422,9 +422,7 @@ async function seedScenario(params: { owner: OAuthCredential; peer: OAuthCredential; }): Promise { - if (params.shared) { - writeSharedStore(params.instance, authStore(params.shared)); - } + writeSharedStore(params.instance, authStore(params.shared)); await params.instance.state.writeAuthProfiles(authStore(params.owner), "owner"); await params.instance.state.writeAuthProfiles(authStore(params.peer), "peer"); closeOpenClawAgentDatabasesForTest(params.instance.stateDir); @@ -468,8 +466,6 @@ function expectAuthError(result: AgentResult, message: string): void { } async function connect(instance: OpenClawTestInstance) { - // Gateway startup can publish shared-auth ownership from its separate process. - reloadSharedAuthStoreOwnership(instance.env); const client = await connectGatewayClient({ url: instance.url, token: instance.gatewayToken,