File-backed desktop OpenAI OAuth must not later fall through to stale secure-storage credentials when a process launches without OPENAI_CODEX_OAUTH_FILE. The file-backed save and delete paths now leave a local marker that disables legacy secure-storage reads for that config directory, while an explicit secure-storage save clears the marker.
Constraint: Avoid synchronous macOS keychain work on the file-backed token save path.
Rejected: Delete secure-storage credentials during file-backed save | it adds keychain latency and can block the desktop OAuth write path.
Confidence: high
Scope-risk: narrow
Tested: bun test src/services/openaiAuth/storage.test.ts src/server/__tests__/haha-openai-oauth-service.test.ts src/server/__tests__/haha-openai-oauth-api.test.ts
Tested: git diff --check
The sync token reader memoized raw path strings and reserved '__secure-storage__' as the secure-storage discriminator. That allowed a real OPENAI_CODEX_OAUTH_FILE value with the same relative path to bypass the file branch and return secure-storage data instead.
Use structured cache keys so file-backed lookups always memoize under a prefixed path while secure storage keeps a dedicated discriminator. Add a regression that seeds different secure-storage and file tokens for '__secure-storage__' and proves both sync and async getters honor the env-pinned file.
Constraint: OPENAI_CODEX_OAUTH_FILE must remain authoritative even for relative paths that match internal sentinel names
Rejected: Keep the raw sentinel and special-case path equality | still leaves memoization coupled to a valid user-controlled filename
Directive: Preserve the file-vs-secure-storage branch split whenever sync cache keys change so env-pinned file authority stays collision-proof
Confidence: high
Scope-risk: narrow
Tested: bun test src/services/openaiAuth/storage.test.ts --test-name-pattern "prefers env-pinned file authority when OPENAI_CODEX_OAUTH_FILE matches the secure-storage sentinel"
Tested: bun test src/services/openaiAuth/storage.test.ts src/server/__tests__/haha-openai-oauth-service.test.ts
Tested: bun test src/services/openaiAuth/storage.test.ts src/server/__tests__/haha-openai-oauth-service.test.ts src/server/__tests__/haha-openai-oauth-api.test.ts
Tested: git diff --check
When OPENAI_CODEX_OAUTH_FILE is set, the override file must stay the only source of truth. Reads now short-circuit to that file path, sync caching keys off the resolved override path, and failed atomic writes remove their tmp files before returning control.
Constraint: OPENAI_CODEX_OAUTH_FILE must override shared secure storage even when the file is missing or corrupt
Rejected: Keep zero-arg memoization and rely on manual cache clears | callers can switch override paths without touching the cache
Confidence: high
Scope-risk: narrow
Directive: Do not reintroduce secure-storage fallback while the override env var is set
Tested: bun test src/services/openaiAuth/storage.test.ts src/server/__tests__/haha-openai-oauth-service.test.ts
Tested: bun test src/services/openaiAuth/storage.test.ts src/server/__tests__/haha-openai-oauth-service.test.ts src/server/__tests__/haha-openai-oauth-api.test.ts
Tested: bun run check:server
Tested: git diff --check
Desktop OpenAI authorization lived in the cc-haha token file while the runtime only read secure storage, so desktop-managed logins could not refresh or authenticate CLI/runtime paths consistently. This teaches runtime storage to honor the explicit desktop token-file env, preserves refresh metadata when OpenAI omits fields, and keeps the desktop service writing the same compatible token shape.
Constraint: Desktop sessions must survive macOS Keychain ACL failures by using the desktop-managed token file when it is explicitly configured
Rejected: Keep refresh writes in secure storage only | runtime and desktop would remain split and refreshed tokens would drift
Confidence: high
Scope-risk: moderate
Tested: bun test src/services/openaiAuth/storage.test.ts src/server/__tests__/haha-openai-oauth-service.test.ts
Tested: git diff --check