From dfa0026d20b4fd86f833a0f33b73ae9a2542acd2 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Thu, 29 Oct 2026 04:57:27 +0000 Subject: [PATCH 1/2] test(server): reproduce Codex shadow homes sharing the cloud config bundle cache These tests reproduce pingdotgg/t3code#26811: materializeCodexShadowHome links cloud-config-bundle-cache.json from the shared home into every shadow home and rejects a shadow home that holds its own copy, which disables the provider instance. Co-Authored-By: Claude Opus 5.5 --- .../provider/Drivers/CodexHomeLayout.test.ts | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/apps/server/src/provider/Drivers/CodexHomeLayout.test.ts b/apps/server/src/provider/Drivers/CodexHomeLayout.test.ts index 2bbcea20faa91..fe1d4cfc25275 100644 --- a/apps/server/src/provider/Drivers/CodexHomeLayout.test.ts +++ b/apps/server/src/provider/Drivers/CodexHomeLayout.test.ts @@ -165,6 +165,66 @@ it.layer(NodeServices.layer)("CodexHomeLayout", (it) => { }), ); + it.effect.skipIf(!symlinksSupported)( + "keeps a shadow home's own cloud config bundle cache", + () => + Effect.gen(function* () { + const fileSystem = yield* FileSystem.FileSystem; + const path = yield* Path.Path; + const sharedHome = yield* makeTempDir("t3code-codex-shared-"); + const shadowHome = yield* makeTempDir("t3code-codex-shadow-"); + const shadowCache = path.join(shadowHome, "cloud-config-bundle-cache.json"); + + yield* writeTextFile( + path.join(sharedHome, "cloud-config-bundle-cache.json"), + '{"account_id":"shared"}\n', + ); + yield* writeTextFile(shadowCache, '{"account_id":"shadow"}\n'); + const layout = yield* resolveCodexHomeLayout( + decodeCodexSettings({ homePath: sharedHome, shadowHomePath: shadowHome }), + ); + + yield* materializeCodexShadowHome(layout); + + expect(yield* fileSystem.readFileString(shadowCache)).toBe('{"account_id":"shadow"}\n'); + }), + ); + + it.effect.skipIf(!symlinksSupported)( + "does not share the cloud config bundle cache with shadow homes", + () => + Effect.gen(function* () { + const fileSystem = yield* FileSystem.FileSystem; + const path = yield* Path.Path; + const sharedHome = yield* makeTempDir("t3code-codex-shared-"); + const freshShadowHome = yield* makeTempDir("t3code-codex-shadow-"); + const linkedShadowHome = yield* makeTempDir("t3code-codex-shadow-"); + const sharedCache = path.join(sharedHome, "cloud-config-bundle-cache.json"); + + yield* writeTextFile(sharedCache, '{"account_id":"shared"}\n'); + yield* fileSystem.symlink( + sharedCache, + path.join(linkedShadowHome, "cloud-config-bundle-cache.json"), + ); + + for (const shadowHome of [freshShadowHome, linkedShadowHome]) { + yield* materializeCodexShadowHome( + yield* resolveCodexHomeLayout( + decodeCodexSettings({ homePath: sharedHome, shadowHomePath: shadowHome }), + ), + ); + } + + expect( + yield* fileSystem.exists(path.join(freshShadowHome, "cloud-config-bundle-cache.json")), + ).toBe(false); + expect( + yield* fileSystem.exists(path.join(linkedShadowHome, "cloud-config-bundle-cache.json")), + ).toBe(false); + expect(yield* fileSystem.readFileString(sharedCache)).toBe('{"account_id":"shared"}\n'); + }), + ); + it.effect.skipIf(!symlinksSupported)( "replaces a Codex-created local sqlite maintenance lock with the shared lock", () => From da0beb6eb5660e5bd2b157b88146e290c5fa4f7b Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Thu, 29 Oct 2026 05:00:12 +0000 Subject: [PATCH 2/2] fix(server): Codex shadow homes keep their own cloud config bundle cache Codex writes cloud-config-bundle-cache.json per auth identity. Linking it from the shared home made each shadow home read the main account's cache, and Codex's atomic refresh replaced the link with a regular file that the next shadow-home setup rejected as a conflict, disabling the provider instance. Treat it as a private shadow-home entry like models_cache.json: never linked, stale links to the shared copy removed, a shadow home's own file kept. Fixes pingdotgg/t3code#26811 Co-Authored-By: Claude Opus 5.5 --- apps/server/src/provider/Drivers/CodexHomeLayout.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/server/src/provider/Drivers/CodexHomeLayout.ts b/apps/server/src/provider/Drivers/CodexHomeLayout.ts index f6d2ba9d44cf5..7cc7b94521da6 100644 --- a/apps/server/src/provider/Drivers/CodexHomeLayout.ts +++ b/apps/server/src/provider/Drivers/CodexHomeLayout.ts @@ -30,7 +30,12 @@ const KNOWN_SHARED_DIRECTORIES = [ ] as const; // auth.lock guards the shadow home's private auth.json. -const PRIVATE_ENTRY_NAMES = new Set(["auth.json", "auth.lock", "models_cache.json"]); +const PRIVATE_ENTRY_NAMES = new Set([ + "auth.json", + "auth.lock", + "models_cache.json", + "cloud-config-bundle-cache.json", +]); // Finder maintains metadata separately for each directory, including shadow homes. const SHADOW_LOCAL_ENTRY_NAMES = new Set(["log", "memories", "tmp", ".DS_Store"]); // Shadow homes may create local runtime locks first; replace them with shared links because they guard shared state.