Skip to content

fix: resolve issues #652–#656 - #658

Merged
ndycode merged 2 commits into
mainfrom
fix/issue-652-incognito-login
Aug 8, 2026
Merged

fix: resolve issues #652–#656#658
ndycode merged 2 commits into
mainfrom
fix/issue-652-incognito-login

Conversation

@ndycode

@ndycode ndycode commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Summary

This PR implements and tests the five related account-management and runtime-rotation issues:

Follow-up validation fixes included in this PR:

  • Direct storage-path overrides now take precedence over stale AsyncLocalStorage contexts created by earlier async work.
  • Windows app-server helper shims use an independent codex.exe copy instead of a hard link to the running Node image, allowing graceful cleanup without EPERM locks.
  • Regression coverage protects both behaviors.

Verification

  • npm run build
  • npm run typecheck
  • npm run typecheck:scripts
  • npm run lint:ts
  • npm run lint:scripts
  • git diff --check
  • npm test ✅ — 337 test files passed, 1 skipped; 5,313 tests passed, 4 skipped

Fixes #652
Fixes #653
Fixes #654
Fixes #655
Fixes #656

note: greptile review for oc-chatgpt-multi-auth. cite files like lib/foo.ts:123. confirm regression tests + windows concurrency/token redaction coverage.

Greptile Summary

this pr addresses account rotation, token invalidation, quota scheduling, oauth guidance, uninstall cleanup, and runtime process ownership.

  • adds persistent account record identifiers and invalidation diagnostics
  • aligns why-selected with production availability and policy gates
  • hardens router and helper shutdown, but leaves a process-exit concurrency window between verification and signaling
  • expands vitest coverage across the affected account, runtime, storage, and uninstall paths; the identity-verification-to-signal race itself has no deterministic regression coverage

Confidence Score: 4/5

the pr is not yet safe to merge because unbind can still terminate an unrelated process if pid reuse occurs between ownership verification and signaling.

process ownership is checked before a separate pid-only stop operation, leaving a concurrency window where a replacement process can receive sigterm or sigkill and, on windows, taskkill can terminate its full process tree.

Files Needing Attention: lib/runtime/app-bind.ts

Important Files Changed

Filename Overview
lib/runtime/app-bind.ts adds strong tokenized ownership checks, but signaling remains separated from verification by a pid-reuse concurrency window that is especially destructive on windows.
lib/runtime-rotation-proxy.ts switches quota scheduler state to stable per-record keys and integrates token-invalidation routing gates without an accepted blocking issue.
lib/accounts.ts persists stable record ids and token-invalidation state while preserving identity across refreshes and reloads.

Sequence Diagram

sequenceDiagram
  participant U as unbind
  participant P as identity probe
  participant R as owned router
  participant X as replacement process
  participant K as stop routine
  U->>P: verify pid, token, command, start time
  P-->>U: owned
  R--xR: exits
  X->>X: reuses pid
  U->>K: stop(pid)
  K->>X: taskkill /t /f or signal
Loading

Fix All in Codex

Prompt To Fix All With AI
### Issue 1
lib/runtime/app-bind.ts:747
**pid reuse bypasses ownership verification**

if the verified router exits and its pid is reused before `stopDetachedProcess` signals it, the replacement process is terminated because ownership is not revalidated after the fresh liveness check. on windows, `taskkill /t /f` terminates the replacement process and its entire process tree.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (10): Last reviewed commit: "fix: resolve issues 652 through 656" | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

Context used (3)

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

this is a major account-management and runtime-routing fix set, not a blocker. focused regression tests cover all five reported fixes. no direct security or data-loss regression is reported, but persisted token invalidation and process ownership checks require careful review. concurrency and some windows failure paths remain limited.

key changes

  • manual and incognito oauth flows display the complete authorization URL when browser and clipboard fallbacks fail (lib/codex-manager/login-oauth.ts:1, test/login-oauth-callback-guidance.test.ts:1).
  • uninstall removes current and legacy scoped package entries, caches, commands, binaries, and runtime artifacts (lib/codex-manager/commands/uninstall.ts:1, scripts/preuninstall.js:1, test/uninstall-command.test.ts:1).
  • runtime shutdown validates process identity, uses graceful termination with escalation, and supports windows process-tree termination (lib/runtime/app-bind.ts:1, scripts/codex-app-router.js:1, test/app-bind.test.ts:1).
  • why-selected mirrors live routing with availability gates, policy blocks, score boosts, cooldowns, circuit breakers, and auth invalidation (lib/codex-manager.ts:1, lib/rotation.ts:1, lib/policy/runtime-policy.ts:1, test/codex-manager-selection-diagnostics.test.ts:1).
  • upstream token invalidation is persisted, surfaced in diagnostics and status output, excluded from routing, and cleared after successful refresh or login (lib/accounts.ts:1, lib/runtime/rotation-token-refresh.ts:1, lib/codex-manager/commands/status.ts:1, lib/codex-manager/health-check.ts:1, test/rotation-token-refresh.test.ts:1).
  • quota deferral trusts valid reset timestamps and allows waits up to seven days. missing, stale, invalid, or untrusted data uses the configured fallback (lib/preemptive-quota-scheduler.ts:1, lib/runtime-rotation-proxy.ts:1, test/preemptive-quota-scheduler.test.ts:1).
  • storage-path state prevents stale asynchronous context from overriding a direct path override (lib/storage/path-state.ts:1, lib/storage.ts:1, test/storage.test.ts:1).
  • windows helper cleanup copies an independent codex.exe, retries transient file-operation failures, and removes helper artifacts after shutdown (scripts/codex.js:1, test/codex-bin-wrapper.test.ts:1).

review focus and risks

  • review the async contract change in buildSelectAccountTraced and selectAccountTraced. all callers must await policy evaluation (lib/codex-manager.ts:1, lib/codex-manager/commands/why-selected.ts:1`).
  • review invalidation persistence, transactional reconciliation, and rollback. concurrent refresh, login, selection, and marker-clear operations could clear a newer invalidation marker. coverage includes one stale-save regression, but no concurrency stress test is identified (lib/accounts.ts:1, lib/storage/flagged-storage.ts:1, test/accounts.test.ts:1).
  • review windows cleanup for stale pids, identity mismatches, taskkill failures, locked descendants, orphaned directories, and helper metadata races (lib/runtime/app-bind.ts:1, scripts/codex.js:1, test/app-bind.test.ts:1).
  • review reset timestamp validation and clock-skew assumptions. an incorrect trust decision can defer an account for up to seven days (lib/preemptive-quota-scheduler.ts:1, test/preemptive-quota-scheduler.test.ts:1).
  • the repository currently lists 347 test files. the reported validation result states that 337 test files passed, with 5,313 tests passed and 4 skipped. focused regression coverage includes oauth callbacks, uninstall behavior, selection diagnostics, token invalidation, quota scheduling, runtime proxy behavior, process identity, and storage-path precedence.

Walkthrough

this pr persists oauth invalidation state, applies policy-aware selection, adds window-aware quota deferral, hardens runtime shutdown, supports legacy package cleanup, fixes oauth callback guidance, and protects direct storage-path overrides.

Changes

account invalidation and selection

Layer / File(s) Summary
persist and apply authentication invalidation
lib/accounts.ts, lib/schemas.ts, lib/storage/*, lib/runtime/rotation-token-refresh.ts, lib/runtime-rotation-proxy.ts
accounts persist invalidation timestamps, error codes, and stable record ids. invalidated accounts are excluded from selection. successful refresh and login clear the state.
policy-aware selection diagnostics
lib/codex-manager.ts, lib/policy/runtime-policy.ts, lib/rotation.ts, lib/runtime/rotation-account-selection.ts, lib/codex-manager/commands/why-selected.ts
selection applies policy blocks, skip reasons, and score boosts. traced selection supports asynchronous evaluation.
status and health output
lib/codex-manager/commands/status.ts, lib/codex-manager/health-check.ts, lib/forecast.ts, lib/parallel-probe.ts, test/codex-manager-selection-diagnostics.test.ts, test/codex-manager-status-command.test.ts
status, health, forecast, and probe paths report invalidated accounts with AUTH_INVALIDATION_MARKER.

quota scheduling

Layer / File(s) Summary
validate quota reset windows
lib/preemptive-quota-scheduler.ts, lib/config.ts, lib/codex-manager/backend-settings-schema.ts, docs/development/CONFIG_FIELDS.md, test/preemptive-quota-scheduler.test.ts
trusted future reset times control deferral up to seven days. missing, invalid, stale, or future-dated data uses the configured fallback.
wire quota scheduling into runtime rotation
lib/runtime-rotation-proxy.ts, lib/runtime/rotation-proxy-state.ts, test/runtime-rotation-proxy.test.ts, test/rotation-proxy-state.test.ts
the runtime proxy creates the scheduler, applies deferral before token use, records upstream quota snapshots, and preserves stable schedule keys.

runtime lifecycle and storage state

Layer / File(s) Summary
stop runtime processes and clean bind artifacts
lib/runtime/app-bind.ts, scripts/codex-app-router.js, scripts/codex.js, test/app-bind.test.ts, test/codex-app-router.test.ts, test/codex-bin-wrapper.test.ts
shutdown validates process identity, uses platform-specific termination, records router start times, retries cleanup, and removes helper artifacts.
track direct storage-path overrides
lib/storage.ts, lib/storage/path-state.ts, test/storage.test.ts
direct storage-path updates use generation-tracked state and take precedence over stale asynchronous context state.

legacy package lifecycle and oauth guidance

Layer / File(s) Summary
support legacy package cleanup
lib/codex-manager/commands/uninstall.ts, scripts/install-codex-auth-utils.js, scripts/preuninstall.js, scripts/postinstall.js, test/uninstall-command.test.ts, test/postinstall.test.ts, test/preuninstall.test.ts
install and uninstall flows recognize the legacy package, filter entries, resolve its cache, report cleanup, and remove its files.
adjust oauth url display
lib/codex-manager/login-oauth.ts, test/login-oauth-callback-guidance.test.ts
manual login and failed clipboard fallback output the complete authorization url.

estimated code review effort: 5 (critical) | ~120 minutes

possibly related prs

suggested labels: bug

suggested reviewers: claude

📋 Issue Planner

Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).

View plan for ticket: #653

✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/issue-652-incognito-login
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch fix/issue-652-incognito-login

Comment thread lib/runtime/app-bind.ts
Comment thread lib/runtime-rotation-proxy.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/accounts.ts`:
- Around line 1434-1435: Update the routine account-save reconciliation around
the token-field merge to preserve a valid persisted auth invalidation marker
when the in-memory snapshot is marker-free; do not clear disk invalidation
during ordinary saves. Keep the successful refresh transaction as the explicit
path that removes the marker, and add a deterministic two-AccountManager
concurrency regression test ordering invalidation before the stale routine save,
covering the Windows filesystem path.

In `@lib/codex-manager.ts`:
- Around line 430-462: Update the policy handling in the selection-trace flow
around evaluateRuntimePolicy and selectHybridAccountTraced so policy.allowed ===
false prevents any account from being selected, either by blocking every
candidate or returning a no-selection trace. Preserve existing per-account auth
invalidation handling, and add Vitest regression coverage in
codex-manager-selection-diagnostics.test.ts for globally denied models and
budget-blocked requests, including auth-rotation routing coverage as required.

In `@lib/runtime/app-bind.ts`:
- Around line 715-719: Correct the error handling in the SIGKILL catch around
kill and the analogous SIGTERM catch: return immediately only for ignorable
ESRCH/EPERM cases, while allowing unexpected errors to propagate or be reported
through options.log. Remove the dead platform !== "win32" guard and ensure ESRCH
does not proceed to another wait because the process has already exited.
- Around line 623-638: Update runWindowsTaskkill to enforce a finite timeout
while waiting for taskkill, ensuring the promise resolves even if neither error
nor close fires; clear the timer when finishing and preserve single-settlement
behavior. Capture and report the taskkill outcome, including timeout, error, and
nonzero exit status, so stopDetachedProcess and
unbindCodexAppRuntimeRotationLocked can distinguish unsuccessful termination
from success.
- Around line 991-999: Update the cleanup loop around helperStatusPath so it
only unlinks the helper status file after the helper has been confirmed stopped.
Preserve the existing behavior for bind and log paths, and retain helper status
files when stop logic skips a different kind or reports that the helper is still
alive.
- Around line 117-130: Decide whether the new exported symbols
DetachedProcessStopOptions, RuntimeRotationAppHelperStatus, and the related
app-bind stop functions are public APIs; if so, re-export them through
lib/index.ts or an appropriate package subpath, otherwise remove their public
exports and keep them scoped to existing app-bind consumers.
- Around line 691-710: Update the process termination flow around kill and
waitForDetachedProcessExit to bypass kill(pid, "SIGTERM") on Windows and invoke
taskkill(pid) directly, ensuring the detached tree is terminated even if the
target exits immediately. Preserve the existing non-Windows signal and fallback
behavior, and add a Windows regression in the relevant app-bind test covering
immediate liveness loss and asserting taskkill is called.

In `@scripts/install-codex-auth-utils.js`:
- Line 87: Add a deterministic Vitest case covering both resolveInstallPaths and
resolveUninstallPaths with platform set to "win32" and matching
APPDATA/LOCALAPPDATA values. Assert that the current and legacy cache paths
produced by the two resolvers match, including the cacheLegacyNodeModules path,
without relying on process.platform.

In `@scripts/preuninstall.js`:
- Around line 207-214: Extend the Vitest coverage in the preuninstall test suite
to seed both cacheNodeModules and cacheLegacyNodeModules, inject one transient
EBUSY, EPERM, or ENOTEMPTY failure during removal, and assert that both
directories are ultimately deleted. Keep the test deterministic and exercise the
withFileOperationRetry path used by the legacy-cache cleanup.

In `@test/app-bind.test.ts`:
- Around line 336-415: Add integration regression cases around
unbindCodexAppRuntimeRotation that place runtime-rotation-app-helper.json beside
the bind directory: verify a matching running helper is discovered and its
status file removed, a foreign kind leaves the file intact, and malformed or
absent JSON still completes while restoring config.toml. Also add coverage for
the injected kill path where kill throws an ESRCH error, preserving the
ignorable-error behavior in stopRuntimeRotationAppHelperProcess.

In `@test/preemptive-quota-scheduler.test.ts`:
- Around line 239-258: Add a regression test alongside the existing
stale/reset-data cases for a snapshot with updatedAt set to now + 1, and assert
getDeferral returns defer: true with waitMs equal to the configured
maxDeferralMs and reason "quota-near-exhaustion". Use PreemptiveQuotaScheduler
and the existing update/getDeferral setup to verify future-dated snapshots use
the fallback delay.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: b41ff91b-4397-4647-ac0e-72ab98f7d5fe

📥 Commits

Reviewing files that changed from the base of the PR and between 962c6b4 and 4426904.

📒 Files selected for processing (38)
  • docs/development/CONFIG_FIELDS.md
  • lib/accounts.ts
  • lib/codex-manager.ts
  • lib/codex-manager/account-pool-write.ts
  • lib/codex-manager/backend-settings-schema.ts
  • lib/codex-manager/commands/status.ts
  • lib/codex-manager/commands/uninstall.ts
  • lib/codex-manager/commands/why-selected.ts
  • lib/codex-manager/health-check.ts
  • lib/codex-manager/login-oauth.ts
  • lib/config.ts
  • lib/forecast.ts
  • lib/parallel-probe.ts
  • lib/policy/runtime-policy.ts
  • lib/preemptive-quota-scheduler.ts
  • lib/rotation.ts
  • lib/runtime-rotation-proxy.ts
  • lib/runtime/app-bind.ts
  • lib/runtime/rotation-account-selection.ts
  • lib/runtime/rotation-proxy-state.ts
  • lib/runtime/rotation-token-refresh.ts
  • lib/schemas.ts
  • lib/storage/flagged-storage.ts
  • lib/storage/public-types.ts
  • scripts/install-codex-auth-utils.js
  • scripts/postinstall.js
  • scripts/preuninstall.js
  • test/app-bind.test.ts
  • test/codex-manager-cli.test.ts
  • test/codex-manager-selection-diagnostics.test.ts
  • test/codex-manager-status-command.test.ts
  • test/login-oauth-callback-guidance.test.ts
  • test/postinstall.test.ts
  • test/preemptive-quota-scheduler.test.ts
  • test/rotation-proxy-state.test.ts
  • test/rotation-token-refresh.test.ts
  • test/runtime-rotation-proxy.test.ts
  • test/uninstall-command.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (27)
test/**/*.test.ts

📄 CodeRabbit inference engine (test/AGENTS.md)

test/**/*.test.ts: Write Vitest test suites with globals enabled (describe, it, expect)
Maintain 80%+ coverage threshold across statements, branches, functions, and lines
Use removeWithRetry() for Windows filesystem cleanup instead of bare fs.rm to handle EBUSY, EPERM, and ENOTEMPTY errors
Do not rely on dist/ in tests; use source files instead
Do not skip tests without justification
Relax lint rules for test files as configured in eslint.config.js

Files:

  • test/rotation-proxy-state.test.ts
  • test/codex-manager-status-command.test.ts
  • test/postinstall.test.ts
  • test/rotation-token-refresh.test.ts
  • test/preemptive-quota-scheduler.test.ts
  • test/uninstall-command.test.ts
  • test/codex-manager-cli.test.ts
  • test/codex-manager-selection-diagnostics.test.ts
  • test/app-bind.test.ts
  • test/login-oauth-callback-guidance.test.ts
  • test/runtime-rotation-proxy.test.ts
test/**/rotation*.test.ts

📄 CodeRabbit inference engine (test/AGENTS.md)

Test account selection and rotation logic in rotation.test.ts and rotation-integration.test.ts

Files:

  • test/rotation-proxy-state.test.ts
  • test/rotation-token-refresh.test.ts
**/*.{ts,js,mjs}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,js,mjs}: Use ESM modules throughout the project; the package is configured with "type": "module".
Do not use as any, @ts-ignore, or @ts-expect-error.

Files:

  • test/rotation-proxy-state.test.ts
  • scripts/preuninstall.js
  • lib/parallel-probe.ts
  • lib/codex-manager/backend-settings-schema.ts
  • lib/runtime/rotation-token-refresh.ts
  • lib/forecast.ts
  • lib/runtime/rotation-proxy-state.ts
  • test/codex-manager-status-command.test.ts
  • lib/storage/flagged-storage.ts
  • lib/codex-manager/login-oauth.ts
  • test/postinstall.test.ts
  • lib/codex-manager/health-check.ts
  • lib/codex-manager/commands/status.ts
  • lib/storage/public-types.ts
  • lib/codex-manager/commands/why-selected.ts
  • lib/config.ts
  • scripts/postinstall.js
  • test/rotation-token-refresh.test.ts
  • lib/codex-manager/account-pool-write.ts
  • test/preemptive-quota-scheduler.test.ts
  • test/uninstall-command.test.ts
  • lib/runtime/rotation-account-selection.ts
  • test/codex-manager-cli.test.ts
  • test/codex-manager-selection-diagnostics.test.ts
  • test/app-bind.test.ts
  • lib/codex-manager.ts
  • lib/rotation.ts
  • lib/schemas.ts
  • scripts/install-codex-auth-utils.js
  • test/login-oauth-callback-guidance.test.ts
  • lib/runtime-rotation-proxy.ts
  • lib/policy/runtime-policy.ts
  • lib/accounts.ts
  • lib/codex-manager/commands/uninstall.ts
  • lib/preemptive-quota-scheduler.ts
  • test/runtime-rotation-proxy.test.ts
  • lib/runtime/app-bind.ts
test/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Windows-sensitive filesystem tests and helpers must use retry handling for transient lock-related cleanup and write failures.

Files:

  • test/rotation-proxy-state.test.ts
  • test/codex-manager-status-command.test.ts
  • test/postinstall.test.ts
  • test/rotation-token-refresh.test.ts
  • test/preemptive-quota-scheduler.test.ts
  • test/uninstall-command.test.ts
  • test/codex-manager-cli.test.ts
  • test/codex-manager-selection-diagnostics.test.ts
  • test/app-bind.test.ts
  • test/login-oauth-callback-guidance.test.ts
  • test/runtime-rotation-proxy.test.ts
**/*

📄 CodeRabbit inference engine (AGENTS.md)

Source changes belong in index.ts, lib/, and scripts/; dist/ is generated output and local temporary/cache directories must not be edited.

Files:

  • test/rotation-proxy-state.test.ts
  • scripts/preuninstall.js
  • lib/parallel-probe.ts
  • lib/codex-manager/backend-settings-schema.ts
  • lib/runtime/rotation-token-refresh.ts
  • lib/forecast.ts
  • lib/runtime/rotation-proxy-state.ts
  • test/codex-manager-status-command.test.ts
  • lib/storage/flagged-storage.ts
  • lib/codex-manager/login-oauth.ts
  • test/postinstall.test.ts
  • docs/development/CONFIG_FIELDS.md
  • lib/codex-manager/health-check.ts
  • lib/codex-manager/commands/status.ts
  • lib/storage/public-types.ts
  • lib/codex-manager/commands/why-selected.ts
  • lib/config.ts
  • scripts/postinstall.js
  • test/rotation-token-refresh.test.ts
  • lib/codex-manager/account-pool-write.ts
  • test/preemptive-quota-scheduler.test.ts
  • test/uninstall-command.test.ts
  • lib/runtime/rotation-account-selection.ts
  • test/codex-manager-cli.test.ts
  • test/codex-manager-selection-diagnostics.test.ts
  • test/app-bind.test.ts
  • lib/codex-manager.ts
  • lib/rotation.ts
  • lib/schemas.ts
  • scripts/install-codex-auth-utils.js
  • test/login-oauth-callback-guidance.test.ts
  • lib/runtime-rotation-proxy.ts
  • lib/policy/runtime-policy.ts
  • lib/accounts.ts
  • lib/codex-manager/commands/uninstall.ts
  • lib/preemptive-quota-scheduler.ts
  • test/runtime-rotation-proxy.test.ts
  • lib/runtime/app-bind.ts
**/*.{js,ts,mjs,cjs}

📄 CodeRabbit inference engine (README.md)

**/*.{js,ts,mjs,cjs}: Do not publish or replace a global codex binary; official OpenAI installation paths must retain ownership of the codex command.
Keep OAuth credentials local and restrict runtime rotation and local bridges to loopback interfaces.
Require hashed local client tokens to protect the optional loopback bridge.
Responses background: true compatibility must remain opt-in; requests using it must use stateful store=true routing rather than stateless store=false routing.
Never run npm install or update commands automatically; only display a manual upgrade notice when appropriate.
Experimental synchronization and backup flows must be non-destructive by default: preview before applying sync, preserve destination-only accounts, and fail safely on backup filename collisions.
Keep account storage project-scoped under the configured multi-auth root when operating in repo-specific workflows.

Files:

  • test/rotation-proxy-state.test.ts
  • scripts/preuninstall.js
  • lib/parallel-probe.ts
  • lib/codex-manager/backend-settings-schema.ts
  • lib/runtime/rotation-token-refresh.ts
  • lib/forecast.ts
  • lib/runtime/rotation-proxy-state.ts
  • test/codex-manager-status-command.test.ts
  • lib/storage/flagged-storage.ts
  • lib/codex-manager/login-oauth.ts
  • test/postinstall.test.ts
  • lib/codex-manager/health-check.ts
  • lib/codex-manager/commands/status.ts
  • lib/storage/public-types.ts
  • lib/codex-manager/commands/why-selected.ts
  • lib/config.ts
  • scripts/postinstall.js
  • test/rotation-token-refresh.test.ts
  • lib/codex-manager/account-pool-write.ts
  • test/preemptive-quota-scheduler.test.ts
  • test/uninstall-command.test.ts
  • lib/runtime/rotation-account-selection.ts
  • test/codex-manager-cli.test.ts
  • test/codex-manager-selection-diagnostics.test.ts
  • test/app-bind.test.ts
  • lib/codex-manager.ts
  • lib/rotation.ts
  • lib/schemas.ts
  • scripts/install-codex-auth-utils.js
  • test/login-oauth-callback-guidance.test.ts
  • lib/runtime-rotation-proxy.ts
  • lib/policy/runtime-policy.ts
  • lib/accounts.ts
  • lib/codex-manager/commands/uninstall.ts
  • lib/preemptive-quota-scheduler.ts
  • test/runtime-rotation-proxy.test.ts
  • lib/runtime/app-bind.ts
test/**

⚙️ CodeRabbit configuration file

tests must stay deterministic and use vitest. demand regression cases that reproduce concurrency bugs, token refresh races, and windows filesystem behavior. reject changes that mock real secrets or skip assertions.

Files:

  • test/rotation-proxy-state.test.ts
  • test/codex-manager-status-command.test.ts
  • test/postinstall.test.ts
  • test/rotation-token-refresh.test.ts
  • test/preemptive-quota-scheduler.test.ts
  • test/uninstall-command.test.ts
  • test/codex-manager-cli.test.ts
  • test/codex-manager-selection-diagnostics.test.ts
  • test/app-bind.test.ts
  • test/login-oauth-callback-guidance.test.ts
  • test/runtime-rotation-proxy.test.ts
scripts/**/*.js

📄 CodeRabbit inference engine (AGENTS.md)

Windows-sensitive cleanup and write operations must retry transient EBUSY, EPERM, and ENOTEMPTY failures where applicable.

Files:

  • scripts/preuninstall.js
  • scripts/postinstall.js
  • scripts/install-codex-auth-utils.js
lib/**/*.ts

📄 CodeRabbit inference engine (lib/AGENTS.md)

lib/**/*.ts: Route all public exports through lib/index.ts or documented package subpaths.
Keep module dependencies acyclic and preserve the layering types/constants → storage → accounts → runtime → manager/CLI; lower layers must not import higher layers.
Preserve runtime rotation pass-through semantics except for intentionally changed auth or provider headers.
Deduplicate emails using normalizeEmailKey(), which trims and lowercases the email.
Use classes for state requiring multiple independent instances or dependency injection, including AccountManager, CircuitBreaker, SessionAffinityStore, and the CodexError hierarchy. Reserve module-level state for genuinely process-global concerns and provide a test reset helper for such state.
Never import from dist/ in source tests or library code.
Never suppress type errors.
Never patch official Codex application binaries for desktop routing.
Never use bare recursive cleanup in Windows-sensitive paths without retry handling.

Files:

  • lib/parallel-probe.ts
  • lib/codex-manager/backend-settings-schema.ts
  • lib/runtime/rotation-token-refresh.ts
  • lib/forecast.ts
  • lib/runtime/rotation-proxy-state.ts
  • lib/storage/flagged-storage.ts
  • lib/codex-manager/login-oauth.ts
  • lib/codex-manager/health-check.ts
  • lib/codex-manager/commands/status.ts
  • lib/storage/public-types.ts
  • lib/codex-manager/commands/why-selected.ts
  • lib/config.ts
  • lib/codex-manager/account-pool-write.ts
  • lib/runtime/rotation-account-selection.ts
  • lib/codex-manager.ts
  • lib/rotation.ts
  • lib/schemas.ts
  • lib/runtime-rotation-proxy.ts
  • lib/policy/runtime-policy.ts
  • lib/accounts.ts
  • lib/codex-manager/commands/uninstall.ts
  • lib/preemptive-quota-scheduler.ts
  • lib/runtime/app-bind.ts
lib/**

⚙️ CodeRabbit configuration file

focus on auth rotation, windows filesystem IO, and concurrency. verify every change cites affected tests (vitest) and that new queues handle EBUSY/429 scenarios. check for logging that leaks tokens or emails.

Files:

  • lib/parallel-probe.ts
  • lib/codex-manager/backend-settings-schema.ts
  • lib/runtime/rotation-token-refresh.ts
  • lib/forecast.ts
  • lib/runtime/rotation-proxy-state.ts
  • lib/storage/flagged-storage.ts
  • lib/codex-manager/login-oauth.ts
  • lib/codex-manager/health-check.ts
  • lib/codex-manager/commands/status.ts
  • lib/storage/public-types.ts
  • lib/codex-manager/commands/why-selected.ts
  • lib/config.ts
  • lib/codex-manager/account-pool-write.ts
  • lib/runtime/rotation-account-selection.ts
  • lib/codex-manager.ts
  • lib/rotation.ts
  • lib/schemas.ts
  • lib/runtime-rotation-proxy.ts
  • lib/policy/runtime-policy.ts
  • lib/accounts.ts
  • lib/codex-manager/commands/uninstall.ts
  • lib/preemptive-quota-scheduler.ts
  • lib/runtime/app-bind.ts
lib/{runtime-rotation-proxy.ts,runtime/**/*.ts}

📄 CodeRabbit inference engine (lib/AGENTS.md)

Runtime rotation must fail open to normal official Codex forwarding when startup helpers are unavailable.

Files:

  • lib/runtime/rotation-token-refresh.ts
  • lib/runtime/rotation-proxy-state.ts
  • lib/runtime/rotation-account-selection.ts
  • lib/runtime-rotation-proxy.ts
  • lib/runtime/app-bind.ts
lib/runtime/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Do not patch official Codex app binaries; use the reversible app-bind or launcher-helper mechanisms instead.

Files:

  • lib/runtime/rotation-token-refresh.ts
  • lib/runtime/rotation-proxy-state.ts
  • lib/runtime/rotation-account-selection.ts
  • lib/runtime/app-bind.ts
lib/{storage/**/*.ts,storage.ts,runtime-paths.ts}

📄 CodeRabbit inference engine (lib/AGENTS.md)

lib/{storage/**/*.ts,storage.ts,runtime-paths.ts}: Resolve project storage identity with resolveProjectStorageIdentityRoot; never derive project pools directly from raw worktree paths.
Never key project storage directly by worktree path.

Files:

  • lib/storage/flagged-storage.ts
  • lib/storage/public-types.ts
lib/storage/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Do not key project storage by worktree path; use resolveProjectStorageIdentityRoot.

Files:

  • lib/storage/flagged-storage.ts
  • lib/storage/public-types.ts
docs/**/*.md

📄 CodeRabbit inference engine (docs/STYLE_GUIDE.md)

docs/**/*.md: User-facing documentation should follow the page template: Title and one-line lead, Quick path commands, Core operational workflow, Troubleshooting or failure handling, and Related links
Use short sections and scan-friendly tables in documentation where they improve clarity
Prefer direct, actionable language in documentation
Use runnable command examples in documentation
Explain expected outcomes after critical commands in documentation
Keep terminology consistent with runtime names in documentation
Avoid speculative language when behavior is deterministic in documentation
Put the user problem in the first paragraph before implementation detail
Use descriptive page titles such as codex-multi-auth Features instead of generic titles on public docs
Do not repeat keyword lists in every section; search terms should appear only where they help a developer understand the page
Canonical command family is codex-multi-auth ...
Canonical runtime root is ~/.codex/multi-auth
Runtime rotation must be described as default-on unless the release policy changes
Legacy command/path references belong only in migration contexts in documentation
Compatibility aliases (codex multi auth, codex multi-auth, codex multiauth) belong only in command reference, troubleshooting, or migration contexts
Keep command flags aligned with runtime usage text in documentation
Avoid non-runnable command snippets in documentation
Avoid conflicting path guidance across documentation
Avoid legacy-first onboarding language in documentation

Organize repository documentation according to the defined layers: product entry, user operations, reference, and development.

docs/**/*.md: Do not describe codex-multi-auth as replacing @openai/codex or publishing the global codex binary; preserve the official CLI's ownership of codex.
Use codex-multi-auth for account management, and reserve codex-multi-auth-codex or mcodex for intentionally forwarding official Codex commands th...

Files:

  • docs/development/CONFIG_FIELDS.md
docs/development/CONFIG_FIELDS.md

📄 CodeRabbit inference engine (docs/development/RUNBOOK_ADD_CONFIG_FIELD.md)

Update docs/development/CONFIG_FIELDS.md with field inventory details when adding new configuration fields

Maintain full field inventory in docs/development/CONFIG_FIELDS.md

Files:

  • docs/development/CONFIG_FIELDS.md
docs/development/**/*.md

📄 CodeRabbit inference engine (docs/DOCUMENTATION.md)

Keep internal architecture, configuration flow, repository ownership, testing, parity, metadata, and audit guidance in development documentation.

Prefer current architecture and reference documentation over historical plans and audit snapshots when describing the present system.

Files:

  • docs/development/CONFIG_FIELDS.md
docs/development/**/*

📄 CodeRabbit inference engine (docs/development/CONFIG_FLOW.md)

docs/development/**/*: Resolve the runtime root directory in this order: CODEX_MULTI_AUTH_DIR; explicit non-default CODEX_HOME/multi-auth; existing account-storage roots under CODEX_HOME or ~/.codex; canonical ~/.codex/multi-auth; and legacy paths only when storage signals exist.
Read dashboardDisplaySettings and pluginConfig from settings.json, while preserving legacy compatibility loading and migration.
Resolve pluginConfig values using this precedence: existing CODEX_MULTI_AUTH_CONFIG_PATH file, valid unified settings.json configuration, legacy compatibility configuration, then DEFAULT_PLUGIN_CONFIG; apply environment-variable overrides afterward.
Ignore a configured but nonexistent CODEX_MULTI_AUTH_CONFIG_PATH during loading, but create it on the first save while the variable remains set.
Resolve dashboard display values from persisted dashboardDisplaySettings, followed by normalization and fallback defaults.
Resolve account storage by selecting the root directory, using the global accounts file by default, using a project-namespaced path when project-scoped mode is active, and attempting applicable legacy project-file migration.
Normalize standalone codex-multi-auth bare subcommands to auth ... before dispatch; normalize wrapper aliases; run auth-manager commands locally; forward out-of-scope wrapper commands to the official Codex CLI.
For forwarded request-bearing commands, honor runtime rotation: resolve CODEX_MULTI_AUTH_RUNTIME_ROTATION_PROXY, then pluginConfig.codexRuntimeRotationProxy, which defaults to enabled.
When rotation is enabled for a requesting command, use a per-process-token loopback Responses proxy, a temporary shadow CODEX_HOME, and a rewritten config.toml; synchronize refreshed official Codex state on exit and remove the shadow home.
The runtime proxy must select or refresh managed accounts and rotate on rate-limit, authentication, network, or server failures before streaming begins.
The plugin host m...

Files:

  • docs/development/CONFIG_FIELDS.md
docs/development/**/*.{md,mdx}

📄 CodeRabbit inference engine (docs/development/TESTING.md)

When documentation changes, verify every command snippet is runnable, path references match runtime modules, cross-links are valid, and the feature matrix matches implemented features.

Files:

  • docs/development/CONFIG_FIELDS.md
docs/**/*.{md,mdx}

📄 CodeRabbit inference engine (docs/troubleshooting.md)

Document that codex-multi-auth-codex is the optional forwarding wrapper, while codex-multi-auth is the canonical account-manager command family; the package does not publish a global codex binary.

Document the canonical command names, runtime paths, configuration precedence, storage migration behavior, and upgrade procedures consistently across the referenced documentation.

Files:

  • docs/development/CONFIG_FIELDS.md
docs/**

⚙️ CodeRabbit configuration file

keep README, SECURITY, and docs consistent with actual CLI flags and workflows. whenever behavior changes, require updated upgrade notes and mention new npm scripts.

Files:

  • docs/development/CONFIG_FIELDS.md
test/**/codex-manager-cli.test.ts

📄 CodeRabbit inference engine (test/AGENTS.md)

Test CLI settings management across 5 panels with Q cancel handling in codex-manager-cli.test.ts

Files:

  • test/codex-manager-cli.test.ts
lib/{runtime-rotation-proxy.ts,local-bridge.ts,request/**/*.ts}

📄 CodeRabbit inference engine (lib/AGENTS.md)

Do not forward stale decoded content-encoding metadata when Node fetch has already decoded response bytes.

Files:

  • lib/runtime-rotation-proxy.ts
lib/{runtime-rotation-proxy.ts,local-bridge.ts}

📄 CodeRabbit inference engine (lib/AGENTS.md)

lib/{runtime-rotation-proxy.ts,local-bridge.ts}: Runtime proxy client-facing headers and responses must never expose account emails or tokens.
Never include account emails or tokens in runtime proxy client responses.

Files:

  • lib/runtime-rotation-proxy.ts
lib/runtime-rotation-proxy.ts

📄 CodeRabbit inference engine (AGENTS.md)

lib/runtime-rotation-proxy.ts: Keep runtime rotation enabled by default, use loopback-only networking, and use a per-process client token.
Do not expose account emails or tokens in runtime proxy response headers or logs.
The runtime proxy may forward only Responses API and model-discovery requests.

Files:

  • lib/runtime-rotation-proxy.ts
lib/{accounts.ts,accounts/**/*.ts}

📄 CodeRabbit inference engine (lib/AGENTS.md)

Maintain account health on a 0–100 scale and update it through account manager APIs.

Files:

  • lib/accounts.ts
lib/accounts.ts

📄 CodeRabbit inference engine (AGENTS.md)

Email deduplication must be case-insensitive using normalizeEmailKey() (trim and lowercase).

Files:

  • lib/accounts.ts
🧠 Learnings (2)
📚 Learning: 2026-06-04T06:14:18.093Z
Learnt from: ndycode
Repo: ndycode/codex-multi-auth PR: 510
File: test/scheduling-strategy-config.test.ts:1-1
Timestamp: 2026-06-04T06:14:18.093Z
Learning: In ndycode/codex-multi-auth, do not flag explicit imports from "vitest" (e.g., describe, it, expect, beforeEach/afterEach, etc.) in test files as issues—even if the Vitest config sets `globals: true`. The repo’s established convention is to keep these imports for consistency with neighboring tests; removing them would make files outliers.

Applied to files:

  • test/rotation-proxy-state.test.ts
  • test/codex-manager-status-command.test.ts
  • test/postinstall.test.ts
  • test/rotation-token-refresh.test.ts
  • test/preemptive-quota-scheduler.test.ts
  • test/uninstall-command.test.ts
  • test/codex-manager-cli.test.ts
  • test/codex-manager-selection-diagnostics.test.ts
  • test/app-bind.test.ts
  • test/login-oauth-callback-guidance.test.ts
  • test/runtime-rotation-proxy.test.ts
📚 Learning: 2026-06-04T06:14:24.975Z
Learnt from: ndycode
Repo: ndycode/codex-multi-auth PR: 510
File: test/runtime-rotation-proxy.test.ts:2478-2491
Timestamp: 2026-06-04T06:14:24.975Z
Learning: In ndycode/codex-multi-auth test files (e.g. `test/*.test.ts`), when creating V3 storage fixtures for accounts, it’s an intentional convention to use `as never` for deliberately minimal stored-account objects that only include `refreshToken`, `addedAt`, and `lastUsed`. Do not treat `as never` here as a type-safety problem: optional/other fields are expected to be populated by the runtime during execution, and the cast is used solely to keep the fixture minimal and consistent across existing tests.

Applied to files:

  • test/rotation-proxy-state.test.ts
  • test/codex-manager-status-command.test.ts
  • test/postinstall.test.ts
  • test/rotation-token-refresh.test.ts
  • test/preemptive-quota-scheduler.test.ts
  • test/uninstall-command.test.ts
  • test/codex-manager-cli.test.ts
  • test/codex-manager-selection-diagnostics.test.ts
  • test/app-bind.test.ts
  • test/login-oauth-callback-guidance.test.ts
  • test/runtime-rotation-proxy.test.ts
🪛 ast-grep (0.45.0)
lib/runtime/app-bind.ts

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

🔇 Additional comments (40)
lib/codex-manager/login-oauth.ts (1)

265-265: LGTM!

Also applies to: 309-325

test/login-oauth-callback-guidance.test.ts (1)

8-66: LGTM!

Also applies to: 110-113, 155-190

lib/preemptive-quota-scheduler.ts (1)

1-1: LGTM!

Also applies to: 32-60, 322-335

test/preemptive-quota-scheduler.test.ts (1)

177-237: LGTM!

Also applies to: 260-274

lib/codex-manager/backend-settings-schema.ts (1)

279-279: LGTM!

lib/config.ts (1)

1821-1823: LGTM!

docs/development/CONFIG_FIELDS.md (1)

161-163: LGTM!

test/rotation-proxy-state.test.ts (1)

3-3: LGTM!

Also applies to: 67-67

lib/accounts.ts (1)

242-271: LGTM!

Also applies to: 520-521, 650-679, 796-796, 831-831, 889-889, 946-946, 1256-1308, 1501-1555, 1604-1605

lib/rotation.ts (1)

372-373: LGTM!

Also applies to: 405-406, 484-487, 627-631, 659-677

lib/codex-manager/commands/why-selected.ts (1)

33-33: LGTM!

Also applies to: 141-141

lib/codex-manager/commands/status.ts (1)

2-2: LGTM!

Also applies to: 91-96

lib/codex-manager/health-check.ts (1)

2-2: LGTM!

Also applies to: 45-54, 180-180, 223-230, 295-295, 309-322

lib/forecast.ts (1)

1-5: LGTM!

Also applies to: 211-219

lib/parallel-probe.ts (1)

145-149: LGTM!

test/codex-manager-cli.test.ts (1)

170-193: LGTM!

test/codex-manager-selection-diagnostics.test.ts (1)

1-172: LGTM!

test/codex-manager-status-command.test.ts (1)

11-11: LGTM!

Also applies to: 213-232

test/rotation-token-refresh.test.ts (1)

41-59: LGTM!

Also applies to: 71-78, 258-302

lib/codex-manager/account-pool-write.ts (1)

138-139: LGTM!

Also applies to: 196-197

lib/schemas.ts (1)

178-179: LGTM!

lib/storage/public-types.ts (1)

47-50: LGTM!

lib/storage/flagged-storage.ts (1)

85-94: LGTM!

Also applies to: 134-135

lib/runtime/rotation-token-refresh.ts (1)

105-107: LGTM!

lib/runtime-rotation-proxy.ts (1)

23-26: LGTM!

Also applies to: 52-55, 711-720, 751-751, 1074-1096, 1209-1228, 1355-1358, 1448-1454

lib/policy/runtime-policy.ts (1)

42-42: LGTM!

Also applies to: 151-151, 194-200, 237-237, 251-251

lib/runtime/rotation-account-selection.ts (1)

161-162: LGTM!

lib/runtime/rotation-proxy-state.ts (1)

2-2: LGTM!

Also applies to: 36-36

test/runtime-rotation-proxy.test.ts (1)

1415-1437: LGTM!

Also applies to: 2403-2406, 2490-2493

lib/runtime/app-bind.ts (4)

4-11: LGTM!


371-371: LGTM!

Also applies to: 535-537, 878-878


729-754: LGTM!


928-932: 🗄️ Data Integrity & Integration

no change needed. lib/runtime/app-bind.ts:421-429 resolves paths.bindDir under the same mode = (env.CODEX_MULTI_AUTH_APP_BIND_CODEX_HOME ?? "").trim() || join(home, ".codex"); multiAuthDir = (...) || getCodexMultiAuthDir(); so dirname(paths.bindDir) maps to the canonical multi-auth helper-status location.

lib/codex-manager/commands/uninstall.ts (1)

9-10: LGTM!

Also applies to: 31-36, 47-49, 83-83, 290-292, 304-308, 355-357

scripts/install-codex-auth-utils.js (2)

9-10: LGTM!

Also applies to: 98-100


109-111: 🎯 Functional Correctness

no change needed.

test/install-codex-auth.test.ts:65-74 covers duplicate entries and unrelated entries, and test/install-codex-auth.test.ts:76-81 covers preservation of other entries through removePluginFromList, which exercises the same legacy-removal logic used by normalizePluginList.

scripts/postinstall.js (1)

36-37: LGTM!

scripts/preuninstall.js (1)

192-194: LGTM!

test/uninstall-command.test.ts (1)

61-70: LGTM!

Also applies to: 166-166, 245-261, 263-278, 299-299, 308-308

test/postinstall.test.ts (1)

1-24: LGTM!

Comment thread lib/accounts.ts Outdated
Comment thread lib/codex-manager.ts
Comment thread lib/runtime/app-bind.ts
Comment thread lib/runtime/app-bind.ts Outdated
Comment thread lib/runtime/app-bind.ts Outdated
Comment thread lib/runtime/app-bind.ts Outdated
Comment thread scripts/install-codex-auth-utils.js
Comment thread scripts/preuninstall.js
Comment thread test/app-bind.test.ts
Comment thread test/preemptive-quota-scheduler.test.ts
@ndycode
ndycode force-pushed the fix/issue-652-incognito-login branch from 4426904 to baf7bef Compare August 8, 2026 11:39

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/runtime-rotation-proxy.ts`:
- Around line 177-179: Update the email branch of the schedule-key construction
to use normalizeEmailKey() instead of local trim().toLowerCase() logic, while
preserving the existing refresh-token fallback and email: key prefix.

In `@lib/runtime/app-bind.ts`:
- Around line 690-741: Update the POSIX branch of readProcessIdentity to parse
ps lstart output explicitly using its documented format instead of relying on
Date.parse. Ensure valid lstart values produce the correct timestamp so
verifyRuntimeHelperProcessIdentity can validate live helpers, and add coverage
using representative actual lstart output.

In `@test/app-bind.test.ts`:
- Around line 362-390: Strengthen the Windows regression test for
stopRuntimeRotationAppHelperProcess by making the kill mock set alive to false
immediately when SIGTERM is issued, then continue asserting that
runWindowsTaskkill is called with PID 4343. Preserve the existing SIGTERM
assertion so the test verifies taskkill still runs after the process exits
during the graceful wait.

In `@test/runtime-rotation-proxy.test.ts`:
- Around line 2448-2451: Extend the regression coverage around the token-refresh
behavior in the relevant runtime rotation test by adding a 401 fixture with a
distinct invalidation code recognized by isTokenInvalidationError(). Trigger the
account invalidation flow and assert that accountManager.getAccountByIndex(0)
persists that exact code in authInvalidationErrorCode, alongside
authInvalidatedAt, rather than only covering the token_invalidated fallback.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 56efd8b3-fc0d-4206-9fd8-c13025f2d27a

📥 Commits

Reviewing files that changed from the base of the PR and between 4426904 and baf7bef.

📒 Files selected for processing (4)
  • lib/runtime-rotation-proxy.ts
  • lib/runtime/app-bind.ts
  • test/app-bind.test.ts
  • test/runtime-rotation-proxy.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (13)
test/**/*.test.ts

📄 CodeRabbit inference engine (test/AGENTS.md)

test/**/*.test.ts: Write Vitest test suites with globals enabled (describe, it, expect)
Maintain 80%+ coverage threshold across statements, branches, functions, and lines
Use removeWithRetry() for Windows filesystem cleanup instead of bare fs.rm to handle EBUSY, EPERM, and ENOTEMPTY errors
Do not rely on dist/ in tests; use source files instead
Do not skip tests without justification
Relax lint rules for test files as configured in eslint.config.js

Files:

  • test/runtime-rotation-proxy.test.ts
  • test/app-bind.test.ts
**/*.{ts,js,mjs}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,js,mjs}: Use ESM modules throughout the project; the package is configured with "type": "module".
Do not use as any, @ts-ignore, or @ts-expect-error.

Files:

  • test/runtime-rotation-proxy.test.ts
  • test/app-bind.test.ts
  • lib/runtime-rotation-proxy.ts
  • lib/runtime/app-bind.ts
test/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Windows-sensitive filesystem tests and helpers must use retry handling for transient lock-related cleanup and write failures.

Files:

  • test/runtime-rotation-proxy.test.ts
  • test/app-bind.test.ts
**/*

📄 CodeRabbit inference engine (AGENTS.md)

Source changes belong in index.ts, lib/, and scripts/; dist/ is generated output and local temporary/cache directories must not be edited.

Files:

  • test/runtime-rotation-proxy.test.ts
  • test/app-bind.test.ts
  • lib/runtime-rotation-proxy.ts
  • lib/runtime/app-bind.ts
**/*.{js,ts,mjs,cjs}

📄 CodeRabbit inference engine (README.md)

**/*.{js,ts,mjs,cjs}: Do not publish or replace a global codex binary; official OpenAI installation paths must retain ownership of the codex command.
Keep OAuth credentials local and restrict runtime rotation and local bridges to loopback interfaces.
Require hashed local client tokens to protect the optional loopback bridge.
Responses background: true compatibility must remain opt-in; requests using it must use stateful store=true routing rather than stateless store=false routing.
Never run npm install or update commands automatically; only display a manual upgrade notice when appropriate.
Experimental synchronization and backup flows must be non-destructive by default: preview before applying sync, preserve destination-only accounts, and fail safely on backup filename collisions.
Keep account storage project-scoped under the configured multi-auth root when operating in repo-specific workflows.

Files:

  • test/runtime-rotation-proxy.test.ts
  • test/app-bind.test.ts
  • lib/runtime-rotation-proxy.ts
  • lib/runtime/app-bind.ts
test/**

⚙️ CodeRabbit configuration file

tests must stay deterministic and use vitest. demand regression cases that reproduce concurrency bugs, token refresh races, and windows filesystem behavior. reject changes that mock real secrets or skip assertions.

Files:

  • test/runtime-rotation-proxy.test.ts
  • test/app-bind.test.ts
lib/**/*.ts

📄 CodeRabbit inference engine (lib/AGENTS.md)

lib/**/*.ts: Route all public exports through lib/index.ts or documented package subpaths.
Keep module dependencies acyclic and preserve the layering types/constants → storage → accounts → runtime → manager/CLI; lower layers must not import higher layers.
Preserve runtime rotation pass-through semantics except for intentionally changed auth or provider headers.
Deduplicate emails using normalizeEmailKey(), which trims and lowercases the email.
Use classes for state requiring multiple independent instances or dependency injection, including AccountManager, CircuitBreaker, SessionAffinityStore, and the CodexError hierarchy. Reserve module-level state for genuinely process-global concerns and provide a test reset helper for such state.
Never import from dist/ in source tests or library code.
Never suppress type errors.
Never patch official Codex application binaries for desktop routing.
Never use bare recursive cleanup in Windows-sensitive paths without retry handling.

Files:

  • lib/runtime-rotation-proxy.ts
  • lib/runtime/app-bind.ts
lib/{runtime-rotation-proxy.ts,local-bridge.ts,request/**/*.ts}

📄 CodeRabbit inference engine (lib/AGENTS.md)

Do not forward stale decoded content-encoding metadata when Node fetch has already decoded response bytes.

Files:

  • lib/runtime-rotation-proxy.ts
lib/{runtime-rotation-proxy.ts,local-bridge.ts}

📄 CodeRabbit inference engine (lib/AGENTS.md)

lib/{runtime-rotation-proxy.ts,local-bridge.ts}: Runtime proxy client-facing headers and responses must never expose account emails or tokens.
Never include account emails or tokens in runtime proxy client responses.

Files:

  • lib/runtime-rotation-proxy.ts
lib/{runtime-rotation-proxy.ts,runtime/**/*.ts}

📄 CodeRabbit inference engine (lib/AGENTS.md)

Runtime rotation must fail open to normal official Codex forwarding when startup helpers are unavailable.

Files:

  • lib/runtime-rotation-proxy.ts
  • lib/runtime/app-bind.ts
lib/runtime-rotation-proxy.ts

📄 CodeRabbit inference engine (AGENTS.md)

lib/runtime-rotation-proxy.ts: Keep runtime rotation enabled by default, use loopback-only networking, and use a per-process client token.
Do not expose account emails or tokens in runtime proxy response headers or logs.
The runtime proxy may forward only Responses API and model-discovery requests.

Files:

  • lib/runtime-rotation-proxy.ts
lib/**

⚙️ CodeRabbit configuration file

focus on auth rotation, windows filesystem IO, and concurrency. verify every change cites affected tests (vitest) and that new queues handle EBUSY/429 scenarios. check for logging that leaks tokens or emails.

Files:

  • lib/runtime-rotation-proxy.ts
  • lib/runtime/app-bind.ts
lib/runtime/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Do not patch official Codex app binaries; use the reversible app-bind or launcher-helper mechanisms instead.

Files:

  • lib/runtime/app-bind.ts
🧠 Learnings (2)
📚 Learning: 2026-06-04T06:14:18.093Z
Learnt from: ndycode
Repo: ndycode/codex-multi-auth PR: 510
File: test/scheduling-strategy-config.test.ts:1-1
Timestamp: 2026-06-04T06:14:18.093Z
Learning: In ndycode/codex-multi-auth, do not flag explicit imports from "vitest" (e.g., describe, it, expect, beforeEach/afterEach, etc.) in test files as issues—even if the Vitest config sets `globals: true`. The repo’s established convention is to keep these imports for consistency with neighboring tests; removing them would make files outliers.

Applied to files:

  • test/runtime-rotation-proxy.test.ts
  • test/app-bind.test.ts
📚 Learning: 2026-06-04T06:14:24.975Z
Learnt from: ndycode
Repo: ndycode/codex-multi-auth PR: 510
File: test/runtime-rotation-proxy.test.ts:2478-2491
Timestamp: 2026-06-04T06:14:24.975Z
Learning: In ndycode/codex-multi-auth test files (e.g. `test/*.test.ts`), when creating V3 storage fixtures for accounts, it’s an intentional convention to use `as never` for deliberately minimal stored-account objects that only include `refreshToken`, `addedAt`, and `lastUsed`. Do not treat `as never` here as a type-safety problem: optional/other fields are expected to be populated by the runtime during execution, and the cast is used solely to keep the fixture minimal and consistent across existing tests.

Applied to files:

  • test/runtime-rotation-proxy.test.ts
  • test/app-bind.test.ts
🪛 ast-grep (0.45.0)
lib/runtime/app-bind.ts

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

🔇 Additional comments (13)
lib/runtime-rotation-proxy.ts (1)

23-26: LGTM!

Also applies to: 52-55, 725-765, 1088-1114, 1227-1246, 1373-1376, 1466-1472

test/runtime-rotation-proxy.test.ts (1)

9-14: LGTM!

Also applies to: 1417-1481, 2535-2538

lib/runtime/app-bind.ts (9)

121-140: still unrouted. lib/runtime/app-bind.ts:121 and lib/runtime/app-bind.ts:134 export DetachedProcessStopOptions and RuntimeRotationAppHelperStatus, and lib/runtime/app-bind.ts:780/lib/runtime/app-bind.ts:849 export the stop functions, but no barrel or package subpath exposes them. route them through lib/index.ts or keep them internal.

As per coding guidelines: "Route all public exports through lib/index.ts or documented package subpaths."

Source: Coding guidelines


633-648: unchanged from the last round. lib/runtime/app-bind.ts:634 resolves only on error or close, so a wedged taskkill blocks unbindCodexAppRuntimeRotationLocked at lib/runtime/app-bind.ts:1036 forever on windows. the exit code is also discarded, so access-denied looks like a clean tree kill. bound the wait and report the outcome.


794-813: still ordered wrong for windows. lib/runtime/app-bind.ts:795 sends SIGTERM before any taskkill. node terminates only the target pid on win32 and leaves detached descendants running. once the target exits, waitForDetachedProcessExit returns true at lib/runtime/app-bind.ts:806 and the function returns before the taskkill at lib/runtime/app-bind.ts:811, so the tracked tree is orphaned. call taskkill(pid) directly on win32.


818-822: the inverted branch is still here. at lib/runtime/app-bind.ts:821 an unexpected kill failure returns silently, while ESRCH/EPERM falls through to a second wait. invert it: return for ignorable codes, and propagate or log unexpected errors through options.log. the same shape sits in the SIGTERM catch at lib/runtime/app-bind.ts:801.


1102-1114: unchanged. lib/runtime/app-bind.ts:1106 unlinks helperStatusPath unconditionally, even when the gate at lib/runtime/app-bind.ts:1048-1051 skipped a foreign kind, and even when the warning at lib/runtime/app-bind.ts:1053-1057 reported that the helper is still alive. that file lives outside paths.bindDir and is the shared discovery artifact, so deleting it strands a live helper. gate the unlink on a confirmed stop.


4-11: LGTM!

Also applies to: 22-25


381-381: LGTM!

Also applies to: 545-547


832-869: LGTM!

Also applies to: 993-993


1115-1121: 🩺 Stability & Availability

no change needed: the app bind lock does not live inside paths.bindDir.

withAppBindLock(paths.bindDir, ...) at lib/runtime/app-bind.ts:906 and lib/runtime/app-bind.ts:1024 uses the paths.bindDir string only as a shared async lock key; no lock artifacts are created under paths.bindDir, so the recursive removal does not delete the held lock.

			> Likely an incorrect or invalid review comment.
test/app-bind.test.ts (2)

392-462: coverage gap is unchanged from the last round. test/app-bind.test.ts:392-462 exercises stopRuntimeRotationAppHelperProcess in isolation with injected handlers only. the code this pr added for #653 is still untested: status-file discovery at lib/runtime/app-bind.ts:1043-1047, the kind/state gate at lib/runtime/app-bind.ts:1048-1051, and the status-file removal at lib/runtime/app-bind.ts:1106. add unbind cases that write a runtime-rotation-app-helper.json fixture next to the bind directory, plus an ESRCH case where the injected kill throws, to lock in the ignorable-error contract at lib/runtime/app-bind.ts:743-749.

As per path instructions for test/**: "demand regression cases that reproduce concurrency bugs, token refresh races, and windows filesystem behavior."

Source: Path instructions


8-16: LGTM!

Also applies to: 333-334

Comment thread lib/runtime-rotation-proxy.ts Outdated
Comment thread lib/runtime/app-bind.ts
Comment thread test/app-bind.test.ts Outdated
Comment thread test/runtime-rotation-proxy.test.ts
@ndycode
ndycode force-pushed the fix/issue-652-incognito-login branch from baf7bef to 4735b99 Compare August 8, 2026 11:48
Comment thread lib/runtime/app-bind.ts Outdated
Comment thread lib/runtime-rotation-proxy.ts Outdated
@ndycode
ndycode force-pushed the fix/issue-652-incognito-login branch 2 times, most recently from a580528 to 2f47e24 Compare August 8, 2026 11:57
Comment thread lib/runtime/app-bind.ts Outdated
Comment thread lib/runtime-rotation-proxy.ts Outdated
@ndycode
ndycode force-pushed the fix/issue-652-incognito-login branch from 2f47e24 to dabb578 Compare August 8, 2026 12:33

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (2)
lib/runtime/app-bind.ts (2)

1200-1208: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

the cleanup loop deletes helperStatusPath and paths.statusPath even when the process is still running. two paths reach here with a live process: the identity gate at lib/runtime/app-bind.ts:654 and lib/runtime/app-bind.ts:678 returns false whenever the probe times out or ps/powershell.exe is unavailable, and the warnings at lib/runtime/app-bind.ts:1131-1135 and lib/runtime/app-bind.ts:1147-1151 only log. after the unlink plus the recursive rm(paths.bindDir) at lib/runtime/app-bind.ts:1211, no later unbind-app or status command can find that orphan router or helper.

gate both status removals on a confirmed stop. stopRuntimeRotationRouterProcess and stopRuntimeRotationAppHelperProcess already return that boolean; capture it in unbindCodexAppRuntimeRotationLocked and keep the status file when the process is still alive or the identity check refused to act. the same applies to a foreign kind, which lib/runtime/app-bind.ts:1142-1145 deliberately skips.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/runtime/app-bind.ts` around lines 1200 - 1208, Update
unbindCodexAppRuntimeRotationLocked to capture the confirmed-stop booleans
returned by stopRuntimeRotationRouterProcess and
stopRuntimeRotationAppHelperProcess. Gate removal of helperStatusPath and
paths.statusPath on the corresponding process having been confirmed stopped,
preserving those files when identity checks time out, process probes are
unavailable, the process remains alive, or a foreign kind is skipped; ensure the
subsequent bind-directory cleanup cannot remove these status files in those
cases.

887-894: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

the windows ordering issue is not fixed. lib/runtime/app-bind.ts:876 sends SIGTERM, which node maps to an unconditional kill of that pid only. if the root exits inside the graceful window, waitForDetachedProcessExit returns true at lib/runtime/app-bind.ts:887 and the function returns before the taskkill at lib/runtime/app-bind.ts:892, so detached descendants survive. skip the signal when platform === "win32" and call taskkill(pid) first.

the windows test at test/app-bind.test.ts:363-391 keeps alive true until taskkill runs, so it cannot catch this. add a case where kill flips alive to false and still assert taskkill ran.

🐛 tree kill first on windows
 	if (!isAlive(pid)) return;
+	if (platform === "win32") {
+		// node's SIGTERM emulation kills only the target pid, so detached
+		// descendants would be orphaned. taskkill /T owns the tree.
+		await taskkill(pid);
+		await waitForDetachedProcessExit(pid, options);
+		return;
+	}
 	try {
 		kill(pid, "SIGTERM");
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/runtime/app-bind.ts` around lines 887 - 894, Update the detached-process
shutdown flow around waitForDetachedProcessExit so Windows skips the initial
SIGTERM and invokes taskkill(pid) first, ensuring the process tree is terminated
even when the root exits during the graceful wait. Preserve the existing
non-Windows graceful shutdown path. Extend the Windows coverage in the relevant
app-bind tests with a case where kill sets alive to false, and still assert
taskkill executes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/codex.js`:
- Around line 3660-3671: The Windows shim replacement in the executable setup
must retry transient filesystem failures. Update the preceding stale-shim
deletion and the Windows copy in the visible setup flow to use the existing
retry handling for EBUSY, EPERM, and ENOTEMPTY where applicable, preserving the
independent copied executable behavior. Add a deterministic Vitest regression in
the app-router tests covering startup with a locked stale shim.

In `@test/app-bind.test.ts`:
- Around line 525-603: Update the “validates legacy router timestamps and
command identity before stopping” test to inject deterministic mock
process-identity handlers into stopRuntimeRotationRouterProcess, preventing
calls to the host ps/PowerShell probe while preserving the timestamp and
command-mismatch assertions. Keep the real spawned subprocess and final
successful stop assertion, and retain createTempRoot cleanup using the existing
withFileOperationRetry pattern.

In `@test/storage.test.ts`:
- Around line 78-83: Replace the cleanup call to setStoragePathDirectState with
setStoragePathState, ensuring directStorageStateOverride is cleared rather than
installing a null override. Preserve deterministic test cleanup so later tests
and async-context concurrency cases use the correct storage state.

---

Duplicate comments:
In `@lib/runtime/app-bind.ts`:
- Around line 1200-1208: Update unbindCodexAppRuntimeRotationLocked to capture
the confirmed-stop booleans returned by stopRuntimeRotationRouterProcess and
stopRuntimeRotationAppHelperProcess. Gate removal of helperStatusPath and
paths.statusPath on the corresponding process having been confirmed stopped,
preserving those files when identity checks time out, process probes are
unavailable, the process remains alive, or a foreign kind is skipped; ensure the
subsequent bind-directory cleanup cannot remove these status files in those
cases.
- Around line 887-894: Update the detached-process shutdown flow around
waitForDetachedProcessExit so Windows skips the initial SIGTERM and invokes
taskkill(pid) first, ensuring the process tree is terminated even when the root
exits during the graceful wait. Preserve the existing non-Windows graceful
shutdown path. Extend the Windows coverage in the relevant app-bind tests with a
case where kill sets alive to false, and still assert taskkill executes.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 532e8aae-06fa-4bae-a66d-0c11500dd3d7

📥 Commits

Reviewing files that changed from the base of the PR and between baf7bef and dabb578.

📒 Files selected for processing (9)
  • lib/runtime/app-bind.ts
  • lib/storage.ts
  • lib/storage/path-state.ts
  • scripts/codex-app-router.js
  • scripts/codex.js
  • test/app-bind.test.ts
  • test/codex-app-router.test.ts
  • test/codex-bin-wrapper.test.ts
  • test/storage.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (16)
test/**/*.test.ts

📄 CodeRabbit inference engine (test/AGENTS.md)

test/**/*.test.ts: Write Vitest test suites with globals enabled (describe, it, expect)
Maintain 80%+ coverage threshold across statements, branches, functions, and lines
Use removeWithRetry() for Windows filesystem cleanup instead of bare fs.rm to handle EBUSY, EPERM, and ENOTEMPTY errors
Do not rely on dist/ in tests; use source files instead
Do not skip tests without justification
Relax lint rules for test files as configured in eslint.config.js

Files:

  • test/codex-app-router.test.ts
  • test/codex-bin-wrapper.test.ts
  • test/storage.test.ts
  • test/app-bind.test.ts
**/*.{ts,js,mjs}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,js,mjs}: Use ESM modules throughout the project; the package is configured with "type": "module".
Do not use as any, @ts-ignore, or @ts-expect-error.

Files:

  • test/codex-app-router.test.ts
  • test/codex-bin-wrapper.test.ts
  • lib/storage.ts
  • test/storage.test.ts
  • lib/storage/path-state.ts
  • scripts/codex.js
  • scripts/codex-app-router.js
  • test/app-bind.test.ts
  • lib/runtime/app-bind.ts
test/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Windows-sensitive filesystem tests and helpers must use retry handling for transient lock-related cleanup and write failures.

Files:

  • test/codex-app-router.test.ts
  • test/codex-bin-wrapper.test.ts
  • test/storage.test.ts
  • test/app-bind.test.ts
**/*

📄 CodeRabbit inference engine (AGENTS.md)

Source changes belong in index.ts, lib/, and scripts/; dist/ is generated output and local temporary/cache directories must not be edited.

Files:

  • test/codex-app-router.test.ts
  • test/codex-bin-wrapper.test.ts
  • lib/storage.ts
  • test/storage.test.ts
  • lib/storage/path-state.ts
  • scripts/codex.js
  • scripts/codex-app-router.js
  • test/app-bind.test.ts
  • lib/runtime/app-bind.ts
**/*.{js,ts,mjs,cjs}

📄 CodeRabbit inference engine (README.md)

**/*.{js,ts,mjs,cjs}: Do not publish or replace a global codex binary; official OpenAI installation paths must retain ownership of the codex command.
Keep OAuth credentials local and restrict runtime rotation and local bridges to loopback interfaces.
Require hashed local client tokens to protect the optional loopback bridge.
Responses background: true compatibility must remain opt-in; requests using it must use stateful store=true routing rather than stateless store=false routing.
Never run npm install or update commands automatically; only display a manual upgrade notice when appropriate.
Experimental synchronization and backup flows must be non-destructive by default: preview before applying sync, preserve destination-only accounts, and fail safely on backup filename collisions.
Keep account storage project-scoped under the configured multi-auth root when operating in repo-specific workflows.

Files:

  • test/codex-app-router.test.ts
  • test/codex-bin-wrapper.test.ts
  • lib/storage.ts
  • test/storage.test.ts
  • lib/storage/path-state.ts
  • scripts/codex.js
  • scripts/codex-app-router.js
  • test/app-bind.test.ts
  • lib/runtime/app-bind.ts
test/**

⚙️ CodeRabbit configuration file

tests must stay deterministic and use vitest. demand regression cases that reproduce concurrency bugs, token refresh races, and windows filesystem behavior. reject changes that mock real secrets or skip assertions.

Files:

  • test/codex-app-router.test.ts
  • test/codex-bin-wrapper.test.ts
  • test/storage.test.ts
  • test/app-bind.test.ts
test/**/codex-bin-wrapper.test.ts

📄 CodeRabbit inference engine (test/AGENTS.md)

Test bin wrapper lazy-load and missing dist handling with concurrent invocations in codex-bin-wrapper.test.ts

Files:

  • test/codex-bin-wrapper.test.ts
lib/**/*.ts

📄 CodeRabbit inference engine (lib/AGENTS.md)

lib/**/*.ts: Route all public exports through lib/index.ts or documented package subpaths.
Keep module dependencies acyclic and preserve the layering types/constants → storage → accounts → runtime → manager/CLI; lower layers must not import higher layers.
Preserve runtime rotation pass-through semantics except for intentionally changed auth or provider headers.
Deduplicate emails using normalizeEmailKey(), which trims and lowercases the email.
Use classes for state requiring multiple independent instances or dependency injection, including AccountManager, CircuitBreaker, SessionAffinityStore, and the CodexError hierarchy. Reserve module-level state for genuinely process-global concerns and provide a test reset helper for such state.
Never import from dist/ in source tests or library code.
Never suppress type errors.
Never patch official Codex application binaries for desktop routing.
Never use bare recursive cleanup in Windows-sensitive paths without retry handling.

Files:

  • lib/storage.ts
  • lib/storage/path-state.ts
  • lib/runtime/app-bind.ts
lib/{storage/**/*.ts,storage.ts,runtime-paths.ts}

📄 CodeRabbit inference engine (lib/AGENTS.md)

lib/{storage/**/*.ts,storage.ts,runtime-paths.ts}: Resolve project storage identity with resolveProjectStorageIdentityRoot; never derive project pools directly from raw worktree paths.
Never key project storage directly by worktree path.

Files:

  • lib/storage.ts
  • lib/storage/path-state.ts
lib/**

⚙️ CodeRabbit configuration file

focus on auth rotation, windows filesystem IO, and concurrency. verify every change cites affected tests (vitest) and that new queues handle EBUSY/429 scenarios. check for logging that leaks tokens or emails.

Files:

  • lib/storage.ts
  • lib/storage/path-state.ts
  • lib/runtime/app-bind.ts
test/**/storage*.test.ts

📄 CodeRabbit inference engine (test/AGENTS.md)

Test V3 storage, worktree migration, and concurrent load scenarios in storage.test.ts and storage-async.test.ts

Files:

  • test/storage.test.ts
lib/storage/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Do not key project storage by worktree path; use resolveProjectStorageIdentityRoot.

Files:

  • lib/storage/path-state.ts
scripts/codex*.js

📄 CodeRabbit inference engine (AGENTS.md)

The wrapper must not reimplement general Codex commands; authentication commands are handled locally and non-authentication commands must forward to the official Codex CLI.

Files:

  • scripts/codex.js
  • scripts/codex-app-router.js
scripts/**/*.js

📄 CodeRabbit inference engine (AGENTS.md)

Windows-sensitive cleanup and write operations must retry transient EBUSY, EPERM, and ENOTEMPTY failures where applicable.

Files:

  • scripts/codex.js
  • scripts/codex-app-router.js
lib/{runtime-rotation-proxy.ts,runtime/**/*.ts}

📄 CodeRabbit inference engine (lib/AGENTS.md)

Runtime rotation must fail open to normal official Codex forwarding when startup helpers are unavailable.

Files:

  • lib/runtime/app-bind.ts
lib/runtime/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Do not patch official Codex app binaries; use the reversible app-bind or launcher-helper mechanisms instead.

Files:

  • lib/runtime/app-bind.ts
🧠 Learnings (2)
📚 Learning: 2026-06-04T06:14:18.093Z
Learnt from: ndycode
Repo: ndycode/codex-multi-auth PR: 510
File: test/scheduling-strategy-config.test.ts:1-1
Timestamp: 2026-06-04T06:14:18.093Z
Learning: In ndycode/codex-multi-auth, do not flag explicit imports from "vitest" (e.g., describe, it, expect, beforeEach/afterEach, etc.) in test files as issues—even if the Vitest config sets `globals: true`. The repo’s established convention is to keep these imports for consistency with neighboring tests; removing them would make files outliers.

Applied to files:

  • test/codex-app-router.test.ts
  • test/codex-bin-wrapper.test.ts
  • test/storage.test.ts
  • test/app-bind.test.ts
📚 Learning: 2026-06-04T06:14:24.975Z
Learnt from: ndycode
Repo: ndycode/codex-multi-auth PR: 510
File: test/runtime-rotation-proxy.test.ts:2478-2491
Timestamp: 2026-06-04T06:14:24.975Z
Learning: In ndycode/codex-multi-auth test files (e.g. `test/*.test.ts`), when creating V3 storage fixtures for accounts, it’s an intentional convention to use `as never` for deliberately minimal stored-account objects that only include `refreshToken`, `addedAt`, and `lastUsed`. Do not treat `as never` here as a type-safety problem: optional/other fields are expected to be populated by the runtime during execution, and the cast is used solely to keep the fixture minimal and consistent across existing tests.

Applied to files:

  • test/codex-app-router.test.ts
  • test/codex-bin-wrapper.test.ts
  • test/storage.test.ts
  • test/app-bind.test.ts
🪛 ast-grep (0.45.0)
test/codex-app-router.test.ts

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn, spawnSync, type ChildProcessWithoutNullStreams } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

test/codex-bin-wrapper.test.ts

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { type SpawnSyncReturns, spawn, spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

lib/runtime/app-bind.ts

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

🔇 Additional comments (13)
lib/storage.ts (1)

111-111: LGTM!

Also applies to: 610-615

lib/storage/path-state.ts (1)

10-73: LGTM!

test/storage.test.ts (1)

7-12: LGTM!

Also applies to: 50-76

lib/runtime/app-bind.ts (4)

122-141: the new public shapes DetachedProcessStopOptions and RuntimeRotationAppHelperStatus, plus stopDetachedProcess at lib/runtime/app-bind.ts:861 and stopRuntimeRotationAppHelperProcess at lib/runtime/app-bind.ts:930, are still exported without a barrel route. add them to lib/index.ts or a documented subpath, or drop the export keyword and keep them internal to app-bind consumers.

as per coding guidelines: "Route all public exports through lib/index.ts or documented package subpaths."

Source: Coding guidelines


693-708: runWindowsTaskkill at lib/runtime/app-bind.ts:693-708 still resolves only on error or close, with no timer. stopDetachedProcess awaits it, and unbindCodexAppRuntimeRotationLocked at lib/runtime/app-bind.ts:1126 awaits that, so a wedged taskkill hangs unbind on windows. the exit code is also discarded, so access-denied looks identical to a clean tree kill.


778-788: the posix branch still calls Date.parse on ps -o lstart= output at lib/runtime/app-bind.ts:783. that format is not the ecmascript date-time string format, so parsing is implementation-defined. on any runtime that returns NaN, verifyRuntimeProcessIdentity returns false and stopRuntimeRotationAppHelperProcess skips a live helper. prefer ps -o lstart= replaced by an epoch-based field (for example ps -o etimes= or lstart parsed explicitly) and add a case with real lstart text.

#!/bin/bash
# check whether any test exercises the real posix identity probe output
rg -n 'lstart|etimes|readProcessIdentity|verifyRuntimeProcessIdentity' test lib --type=ts

4-11: LGTM!

Also applies to: 22-25, 78-78, 370-370, 383-383, 547-549, 628-683, 824-859, 913-957, 1081-1083

scripts/codex-app-router.js (1)

136-142: LGTM!

Also applies to: 158-158, 242-242, 252-258, 289-295

test/app-bind.test.ts (1)

6-17: LGTM!

Also applies to: 334-335, 337-361, 393-464, 466-523, 775-775, 804-807, 832-832

test/codex-app-router.test.ts (1)

135-135: LGTM!

test/codex-bin-wrapper.test.ts (1)

496-499: LGTM!

scripts/codex.js (2)

4161-4165: LGTM!


4179-4194: 🩺 Stability & Availability

no change needed: helper shutdown is bounded.

waitForRuntimeRotationAppHelperExit in scripts/codex.js:4006-4017 uses a 2s timeout before stopRuntimeRotationAppHelper sends SIGKILL, so an ignored SIGTERM does not leave cleanup awaiting indefinitely. no regression case is required here.

Comment thread scripts/codex.js Outdated
Comment thread test/app-bind.test.ts
Comment thread test/storage.test.ts Outdated
@ndycode
ndycode force-pushed the fix/issue-652-incognito-login branch from dabb578 to 5439882 Compare August 8, 2026 13:13
Comment thread lib/runtime-rotation-proxy.ts Outdated
Comment thread lib/runtime/app-bind.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/runtime-rotation-proxy.ts`:
- Around line 1377-1380: In lib/runtime-rotation-proxy.ts lines 1377-1380, after
accountManager.markAuthInvalidated(), await the durable account-storage save
before sending the 401 invalidation response. In
test/runtime-rotation-proxy.test.ts lines 2497-2534, reload persisted storage
through a fresh AccountManager and assert that authInvalidatedAt and the
upstream error code are preserved.

In `@lib/runtime/app-bind.ts`:
- Around line 753-786: Update lib/runtime/app-bind.ts lines 753-786 around
runProcessIdentityProbe and unbindCodexAppRuntimeRotation to report probe
failures through options.log, distinguish unavailable probes from identity
mismatches, and increase PROCESS_IDENTITY_PROBE_TIMEOUT_MS for the Windows
PowerShell path; add an AppBindOptions identity-verifier injection seam. Update
test/app-bind.test.ts lines 715-775 to inject the verifier instead of spawning a
real child through the host ps or powershell.exe.

In `@scripts/codex.js`:
- Around line 113-121: Coerce the parsed environment-variable counters to a
finite nonnegative value when initializing
appServerShimFileCleanupBusyFailuresRemaining and
appServerShimCopyBusyFailuresRemaining. Ensure malformed values such as NaN
become zero so maybeThrowSimulatedAppServerShimFileError can terminate normally,
while preserving valid configured failure counts.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 20ca5b80-1fae-47ba-bf27-40addbcd32f2

📥 Commits

Reviewing files that changed from the base of the PR and between dabb578 and 5439882.

📒 Files selected for processing (16)
  • lib/accounts.ts
  • lib/codex-manager.ts
  • lib/index.ts
  • lib/runtime-rotation-proxy.ts
  • lib/runtime/app-bind.ts
  • scripts/codex-app-router.js
  • scripts/codex.js
  • test/accounts.test.ts
  • test/app-bind.test.ts
  • test/codex-bin-wrapper.test.ts
  • test/codex-manager-selection-diagnostics.test.ts
  • test/preemptive-quota-scheduler.test.ts
  • test/preuninstall.test.ts
  • test/runtime-rotation-proxy.test.ts
  • test/storage.test.ts
  • test/uninstall-command.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (19)
lib/**/*.ts

📄 CodeRabbit inference engine (lib/AGENTS.md)

lib/**/*.ts: Route all public exports through lib/index.ts or documented package subpaths.
Keep module dependencies acyclic and preserve the layering types/constants → storage → accounts → runtime → manager/CLI; lower layers must not import higher layers.
Preserve runtime rotation pass-through semantics except for intentionally changed auth or provider headers.
Deduplicate emails using normalizeEmailKey(), which trims and lowercases the email.
Use classes for state requiring multiple independent instances or dependency injection, including AccountManager, CircuitBreaker, SessionAffinityStore, and the CodexError hierarchy. Reserve module-level state for genuinely process-global concerns and provide a test reset helper for such state.
Never import from dist/ in source tests or library code.
Never suppress type errors.
Never patch official Codex application binaries for desktop routing.
Never use bare recursive cleanup in Windows-sensitive paths without retry handling.

Files:

  • lib/index.ts
  • lib/codex-manager.ts
  • lib/runtime-rotation-proxy.ts
  • lib/accounts.ts
  • lib/runtime/app-bind.ts
**/*.{ts,js,mjs}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,js,mjs}: Use ESM modules throughout the project; the package is configured with "type": "module".
Do not use as any, @ts-ignore, or @ts-expect-error.

Files:

  • lib/index.ts
  • test/storage.test.ts
  • test/preuninstall.test.ts
  • test/codex-manager-selection-diagnostics.test.ts
  • test/codex-bin-wrapper.test.ts
  • test/accounts.test.ts
  • test/uninstall-command.test.ts
  • test/preemptive-quota-scheduler.test.ts
  • lib/codex-manager.ts
  • lib/runtime-rotation-proxy.ts
  • scripts/codex.js
  • test/runtime-rotation-proxy.test.ts
  • scripts/codex-app-router.js
  • lib/accounts.ts
  • lib/runtime/app-bind.ts
  • test/app-bind.test.ts
**/*

📄 CodeRabbit inference engine (AGENTS.md)

Source changes belong in index.ts, lib/, and scripts/; dist/ is generated output and local temporary/cache directories must not be edited.

Files:

  • lib/index.ts
  • test/storage.test.ts
  • test/preuninstall.test.ts
  • test/codex-manager-selection-diagnostics.test.ts
  • test/codex-bin-wrapper.test.ts
  • test/accounts.test.ts
  • test/uninstall-command.test.ts
  • test/preemptive-quota-scheduler.test.ts
  • lib/codex-manager.ts
  • lib/runtime-rotation-proxy.ts
  • scripts/codex.js
  • test/runtime-rotation-proxy.test.ts
  • scripts/codex-app-router.js
  • lib/accounts.ts
  • lib/runtime/app-bind.ts
  • test/app-bind.test.ts
**/*.{js,ts,mjs,cjs}

📄 CodeRabbit inference engine (README.md)

**/*.{js,ts,mjs,cjs}: Do not publish or replace a global codex binary; official OpenAI installation paths must retain ownership of the codex command.
Keep OAuth credentials local and restrict runtime rotation and local bridges to loopback interfaces.
Require hashed local client tokens to protect the optional loopback bridge.
Responses background: true compatibility must remain opt-in; requests using it must use stateful store=true routing rather than stateless store=false routing.
Never run npm install or update commands automatically; only display a manual upgrade notice when appropriate.
Experimental synchronization and backup flows must be non-destructive by default: preview before applying sync, preserve destination-only accounts, and fail safely on backup filename collisions.
Keep account storage project-scoped under the configured multi-auth root when operating in repo-specific workflows.

Files:

  • lib/index.ts
  • test/storage.test.ts
  • test/preuninstall.test.ts
  • test/codex-manager-selection-diagnostics.test.ts
  • test/codex-bin-wrapper.test.ts
  • test/accounts.test.ts
  • test/uninstall-command.test.ts
  • test/preemptive-quota-scheduler.test.ts
  • lib/codex-manager.ts
  • lib/runtime-rotation-proxy.ts
  • scripts/codex.js
  • test/runtime-rotation-proxy.test.ts
  • scripts/codex-app-router.js
  • lib/accounts.ts
  • lib/runtime/app-bind.ts
  • test/app-bind.test.ts
lib/**

⚙️ CodeRabbit configuration file

focus on auth rotation, windows filesystem IO, and concurrency. verify every change cites affected tests (vitest) and that new queues handle EBUSY/429 scenarios. check for logging that leaks tokens or emails.

Files:

  • lib/index.ts
  • lib/codex-manager.ts
  • lib/runtime-rotation-proxy.ts
  • lib/accounts.ts
  • lib/runtime/app-bind.ts
test/**/*.test.ts

📄 CodeRabbit inference engine (test/AGENTS.md)

test/**/*.test.ts: Write Vitest test suites with globals enabled (describe, it, expect)
Maintain 80%+ coverage threshold across statements, branches, functions, and lines
Use removeWithRetry() for Windows filesystem cleanup instead of bare fs.rm to handle EBUSY, EPERM, and ENOTEMPTY errors
Do not rely on dist/ in tests; use source files instead
Do not skip tests without justification
Relax lint rules for test files as configured in eslint.config.js

Files:

  • test/storage.test.ts
  • test/preuninstall.test.ts
  • test/codex-manager-selection-diagnostics.test.ts
  • test/codex-bin-wrapper.test.ts
  • test/accounts.test.ts
  • test/uninstall-command.test.ts
  • test/preemptive-quota-scheduler.test.ts
  • test/runtime-rotation-proxy.test.ts
  • test/app-bind.test.ts
test/**/storage*.test.ts

📄 CodeRabbit inference engine (test/AGENTS.md)

Test V3 storage, worktree migration, and concurrent load scenarios in storage.test.ts and storage-async.test.ts

Files:

  • test/storage.test.ts
test/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Windows-sensitive filesystem tests and helpers must use retry handling for transient lock-related cleanup and write failures.

Files:

  • test/storage.test.ts
  • test/preuninstall.test.ts
  • test/codex-manager-selection-diagnostics.test.ts
  • test/codex-bin-wrapper.test.ts
  • test/accounts.test.ts
  • test/uninstall-command.test.ts
  • test/preemptive-quota-scheduler.test.ts
  • test/runtime-rotation-proxy.test.ts
  • test/app-bind.test.ts
test/**

⚙️ CodeRabbit configuration file

tests must stay deterministic and use vitest. demand regression cases that reproduce concurrency bugs, token refresh races, and windows filesystem behavior. reject changes that mock real secrets or skip assertions.

Files:

  • test/storage.test.ts
  • test/preuninstall.test.ts
  • test/codex-manager-selection-diagnostics.test.ts
  • test/codex-bin-wrapper.test.ts
  • test/accounts.test.ts
  • test/uninstall-command.test.ts
  • test/preemptive-quota-scheduler.test.ts
  • test/runtime-rotation-proxy.test.ts
  • test/app-bind.test.ts
test/**/codex-bin-wrapper.test.ts

📄 CodeRabbit inference engine (test/AGENTS.md)

Test bin wrapper lazy-load and missing dist handling with concurrent invocations in codex-bin-wrapper.test.ts

Files:

  • test/codex-bin-wrapper.test.ts
lib/{runtime-rotation-proxy.ts,local-bridge.ts,request/**/*.ts}

📄 CodeRabbit inference engine (lib/AGENTS.md)

Do not forward stale decoded content-encoding metadata when Node fetch has already decoded response bytes.

Files:

  • lib/runtime-rotation-proxy.ts
lib/{runtime-rotation-proxy.ts,local-bridge.ts}

📄 CodeRabbit inference engine (lib/AGENTS.md)

lib/{runtime-rotation-proxy.ts,local-bridge.ts}: Runtime proxy client-facing headers and responses must never expose account emails or tokens.
Never include account emails or tokens in runtime proxy client responses.

Files:

  • lib/runtime-rotation-proxy.ts
lib/{runtime-rotation-proxy.ts,runtime/**/*.ts}

📄 CodeRabbit inference engine (lib/AGENTS.md)

Runtime rotation must fail open to normal official Codex forwarding when startup helpers are unavailable.

Files:

  • lib/runtime-rotation-proxy.ts
  • lib/runtime/app-bind.ts
lib/runtime-rotation-proxy.ts

📄 CodeRabbit inference engine (AGENTS.md)

lib/runtime-rotation-proxy.ts: Keep runtime rotation enabled by default, use loopback-only networking, and use a per-process client token.
Do not expose account emails or tokens in runtime proxy response headers or logs.
The runtime proxy may forward only Responses API and model-discovery requests.

Files:

  • lib/runtime-rotation-proxy.ts
scripts/codex*.js

📄 CodeRabbit inference engine (AGENTS.md)

The wrapper must not reimplement general Codex commands; authentication commands are handled locally and non-authentication commands must forward to the official Codex CLI.

Files:

  • scripts/codex.js
  • scripts/codex-app-router.js
scripts/**/*.js

📄 CodeRabbit inference engine (AGENTS.md)

Windows-sensitive cleanup and write operations must retry transient EBUSY, EPERM, and ENOTEMPTY failures where applicable.

Files:

  • scripts/codex.js
  • scripts/codex-app-router.js
lib/{accounts.ts,accounts/**/*.ts}

📄 CodeRabbit inference engine (lib/AGENTS.md)

Maintain account health on a 0–100 scale and update it through account manager APIs.

Files:

  • lib/accounts.ts
lib/accounts.ts

📄 CodeRabbit inference engine (AGENTS.md)

Email deduplication must be case-insensitive using normalizeEmailKey() (trim and lowercase).

Files:

  • lib/accounts.ts
lib/runtime/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Do not patch official Codex app binaries; use the reversible app-bind or launcher-helper mechanisms instead.

Files:

  • lib/runtime/app-bind.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-08-08T13:13:48.685Z
Learning: Use `~/.codex/multi-auth/settings.json` as the canonical settings file, with top-level `version`, `dashboardDisplaySettings`, and `pluginConfig` fields.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-08-08T13:13:48.685Z
Learning: Treat `pluginConfig` as the persisted compatibility name for runtime settings, and support its documented environment-variable overrides through `lib/config.ts` accessors.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-08-08T13:13:48.685Z
Learning: Do not manually edit refresh lease/state files or active shadow-home lock metadata while the CLI is running.
📚 Learning: 2026-06-04T06:14:18.093Z
Learnt from: ndycode
Repo: ndycode/codex-multi-auth PR: 510
File: test/scheduling-strategy-config.test.ts:1-1
Timestamp: 2026-06-04T06:14:18.093Z
Learning: In ndycode/codex-multi-auth, do not flag explicit imports from "vitest" (e.g., describe, it, expect, beforeEach/afterEach, etc.) in test files as issues—even if the Vitest config sets `globals: true`. The repo’s established convention is to keep these imports for consistency with neighboring tests; removing them would make files outliers.

Applied to files:

  • test/storage.test.ts
  • test/preuninstall.test.ts
  • test/codex-manager-selection-diagnostics.test.ts
  • test/codex-bin-wrapper.test.ts
  • test/accounts.test.ts
  • test/uninstall-command.test.ts
  • test/preemptive-quota-scheduler.test.ts
  • test/runtime-rotation-proxy.test.ts
  • test/app-bind.test.ts
📚 Learning: 2026-06-04T06:14:24.975Z
Learnt from: ndycode
Repo: ndycode/codex-multi-auth PR: 510
File: test/runtime-rotation-proxy.test.ts:2478-2491
Timestamp: 2026-06-04T06:14:24.975Z
Learning: In ndycode/codex-multi-auth test files (e.g. `test/*.test.ts`), when creating V3 storage fixtures for accounts, it’s an intentional convention to use `as never` for deliberately minimal stored-account objects that only include `refreshToken`, `addedAt`, and `lastUsed`. Do not treat `as never` here as a type-safety problem: optional/other fields are expected to be populated by the runtime during execution, and the cast is used solely to keep the fixture minimal and consistent across existing tests.

Applied to files:

  • test/storage.test.ts
  • test/preuninstall.test.ts
  • test/codex-manager-selection-diagnostics.test.ts
  • test/codex-bin-wrapper.test.ts
  • test/accounts.test.ts
  • test/uninstall-command.test.ts
  • test/preemptive-quota-scheduler.test.ts
  • test/runtime-rotation-proxy.test.ts
  • test/app-bind.test.ts
🪛 ast-grep (0.45.0)
test/codex-bin-wrapper.test.ts

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { type SpawnSyncReturns, spawn, spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { type SpawnSyncReturns, spawn, spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { type SpawnSyncReturns, spawn, spawnSync } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

lib/runtime/app-bind.ts

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

🪛 OpenGrep (1.26.0)
lib/runtime/app-bind.ts

[ERROR] 846-848: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.

(coderabbit.command-injection.exec-js)

🔇 Additional comments (19)
lib/accounts.ts (1)

242-244: LGTM!

Also applies to: 270-271, 520-521, 650-650, 663-679, 796-796, 831-831, 889-889, 946-946, 1256-1276, 1308-1308, 1367-1384, 1452-1453, 1519-1520, 1537-1539, 1560-1573, 1622-1623

lib/codex-manager.ts (1)

2-3: LGTM!

Also applies to: 66-70, 397-472

lib/index.ts (1)

36-36: LGTM!

lib/runtime-rotation-proxy.ts (1)

1-1: LGTM!

Also applies to: 23-26, 52-58, 170-186, 729-738, 769-769, 1092-1118, 1231-1250, 1470-1476

test/accounts.test.ts (1)

35-35: LGTM!

Also applies to: 2427-2427, 2461-2505

test/codex-manager-selection-diagnostics.test.ts (1)

1-234: LGTM!

test/preemptive-quota-scheduler.test.ts (1)

260-292: LGTM!

test/runtime-rotation-proxy.test.ts (1)

9-14: LGTM!

Also applies to: 1417-1531, 2612-2615

lib/runtime/app-bind.ts (2)

638-714: 📐 Maintainability & Code Quality

new public exports still bypass lib/index.ts.

stopRuntimeRotationRouterProcess, parsePosixProcessStartTime, and stopDetachedProcess are exported from lib/runtime/app-bind.ts but no barrel or documented subpath exposes them. this repeats the earlier finding on this file.

as per coding guidelines, "Route all public exports through lib/index.ts or documented package subpaths."

Also applies to: 844-844, 1012-1017

Source: Coding guidelines


22-26: LGTM!

Also applies to: 79-83, 127-149, 393-393, 557-559, 716-746, 844-884, 965-1010, 1079-1115, 1314-1429

scripts/codex-app-router.js (2)

136-144: LGTM!

Also applies to: 160-166, 250-250, 260-268


296-309: 🗄️ Data Integrity & Integration

router argv includes --status; no change needed.

lib/runtime/app-bind.ts:572-595 spawns and regenerates startup/launch-agent args with --status "${state.statusPath}" alongside --state.

scripts/codex.js (2)

203-215: LGTM!

Also applies to: 3698-3726, 3904-3904, 4217-4221, 4235-4250


183-201: 🩺 Stability & Availability

retry predicate already covers Windows file operation codes.

scripts/codex.js:34 defines RETRYABLE_SHADOW_HOME_CLEANUP_CODES as ["EBUSY", "EPERM", "ENOTEMPTY"], and scripts/codex.js:153 proxies it through isRetryableShadowHomeCleanupError used by scripts/codex.js:3698 and scripts/codex.js:3714.

test/app-bind.test.ts (1)

6-27: LGTM!

Also applies to: 82-107, 160-173, 383-469, 471-560, 562-619, 621-713, 777-806, 837-861, 1033-1033, 1062-1065, 1090-1090

test/codex-bin-wrapper.test.ts (1)

496-499: LGTM!

Also applies to: 2405-2405, 2477-2479

test/preuninstall.test.ts (1)

9-34: LGTM!

Also applies to: 93-126

test/storage.test.ts (1)

7-12: LGTM!

Also applies to: 50-86

test/uninstall-command.test.ts (1)

5-5: LGTM!

Also applies to: 62-71, 112-128, 184-184, 263-279, 286-296, 317-317, 326-326

Comment thread lib/runtime-rotation-proxy.ts
Comment thread lib/runtime/app-bind.ts
Comment thread scripts/codex.js Outdated
@ndycode
ndycode force-pushed the fix/issue-652-incognito-login branch from 5439882 to cfbec35 Compare August 8, 2026 13:31
Comment thread lib/runtime-rotation-proxy.ts
Comment thread lib/runtime/app-bind.ts
@ndycode
ndycode force-pushed the fix/issue-652-incognito-login branch from cfbec35 to cf1148c Compare August 8, 2026 13:59

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/accounts.ts`:
- Around line 1321-1325: Normalize invalidation timestamps across
lib/accounts.ts:1321-1325, lib/schemas.ts:179-180, and
lib/storage/flagged-storage.ts:85-94: update isAccountAuthInvalidated to require
a finite value greater than zero, and reject or remove zero and negative
timestamps during account-state loading and flagged-account normalization. Add
regression coverage for zero and negative timestamps, including auth rotation,
Windows filesystem I/O, and concurrency paths.

In `@lib/runtime/app-bind.ts`:
- Around line 1503-1523: Update the helper ownership decision in the runtime
rotation cleanup flow around stopRuntimeRotationAppHelperProcess so a live
helper with no identityToken can be stopped after verifyRuntimeProcessIdentity
succeeds, even when helperOwner is null. Preserve strict identityToken ownership
matching when the status includes a token, and update the existing token-less
test plus add coverage for stopping a verified live token-less helper.

In `@scripts/codex.js`:
- Around line 4168-4189: The runtime rotation helper owner token is written to a
shared fixed path before spawn, allowing concurrent launchers to overwrite one
another and orphan a running helper. Update writeRuntimeRotationAppHelperOwner
and the spawn/ready flow to use a launcher-, helper-, or PID-specific ownership
key, or persist ownership only after the helper successfully reports ready.
Preserve ownership matching in the app-binding flow, and add a regression test
covering concurrent launches that previously replaced the owner token.

In `@test/app-bind.test.ts`:
- Around line 894-924: Update the affected app-bind tests around
unbindCodexAppRuntimeRotation to use a short-lived sleeper child’s PID instead
of process.pid in runtime-helper status fixtures, and ensure the child is
cleaned up. In the stop-failure case around the replacement/ownerless fixture,
inject verifyProcessIdentity so the test does not invoke host ps or
powershell.exe; preserve the assertions that validate the intended rejection
behavior.
- Around line 824-892: Update the owned-helper test around child creation and
unbindCodexAppRuntimeRotation to await the fixture child’s exit event after
signaling it to stop, before invoking unbind. Preserve the existing cleanup
fallback for failures, and keep the status-file assertion deterministic without
relying on process reaping timing.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d20e1574-15c3-445d-8599-4bee9ced217f

📥 Commits

Reviewing files that changed from the base of the PR and between 5439882 and cf1148c.

📒 Files selected for processing (13)
  • README.md
  • docs/reference/storage-paths.md
  • lib/accounts.ts
  • lib/runtime-constants.ts
  • lib/runtime-rotation-proxy.ts
  • lib/runtime/app-bind.ts
  • lib/schemas.ts
  • lib/storage/flagged-storage.ts
  • lib/storage/public-types.ts
  • scripts/codex-app-router.js
  • scripts/codex.js
  • test/app-bind.test.ts
  • test/runtime-rotation-proxy.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (23)
**/*

📄 CodeRabbit inference engine (AGENTS.md)

Source changes belong in index.ts, lib/, and scripts/; dist/ is generated output and local temporary/cache directories must not be edited.

Files:

  • README.md
  • lib/runtime-constants.ts
  • lib/storage/public-types.ts
  • docs/reference/storage-paths.md
  • scripts/codex-app-router.js
  • test/runtime-rotation-proxy.test.ts
  • lib/schemas.ts
  • scripts/codex.js
  • lib/runtime-rotation-proxy.ts
  • test/app-bind.test.ts
  • lib/storage/flagged-storage.ts
  • lib/accounts.ts
  • lib/runtime/app-bind.ts
lib/**/*.ts

📄 CodeRabbit inference engine (lib/AGENTS.md)

lib/**/*.ts: Route all public exports through lib/index.ts or documented package subpaths.
Keep module dependencies acyclic and preserve the layering types/constants → storage → accounts → runtime → manager/CLI; lower layers must not import higher layers.
Preserve runtime rotation pass-through semantics except for intentionally changed auth or provider headers.
Deduplicate emails using normalizeEmailKey(), which trims and lowercases the email.
Use classes for state requiring multiple independent instances or dependency injection, including AccountManager, CircuitBreaker, SessionAffinityStore, and the CodexError hierarchy. Reserve module-level state for genuinely process-global concerns and provide a test reset helper for such state.
Never import from dist/ in source tests or library code.
Never suppress type errors.
Never patch official Codex application binaries for desktop routing.
Never use bare recursive cleanup in Windows-sensitive paths without retry handling.

Files:

  • lib/runtime-constants.ts
  • lib/storage/public-types.ts
  • lib/schemas.ts
  • lib/runtime-rotation-proxy.ts
  • lib/storage/flagged-storage.ts
  • lib/accounts.ts
  • lib/runtime/app-bind.ts
**/*.{ts,js,mjs}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,js,mjs}: Use ESM modules throughout the project; the package is configured with "type": "module".
Do not use as any, @ts-ignore, or @ts-expect-error.

Files:

  • lib/runtime-constants.ts
  • lib/storage/public-types.ts
  • scripts/codex-app-router.js
  • test/runtime-rotation-proxy.test.ts
  • lib/schemas.ts
  • scripts/codex.js
  • lib/runtime-rotation-proxy.ts
  • test/app-bind.test.ts
  • lib/storage/flagged-storage.ts
  • lib/accounts.ts
  • lib/runtime/app-bind.ts
**/*.{js,ts,mjs,cjs}

📄 CodeRabbit inference engine (README.md)

**/*.{js,ts,mjs,cjs}: Keep OAuth credentials and account state local; runtime rotation and local bridges must be loopback-only.
Do not patch official Codex app binaries; use reversible packaged app-bind and user-level launcher helpers instead.
Protect local bridge access with hashed local client tokens.
Use stateless store=false Responses routing by default; enable stateful store=true only when callers explicitly opt into background: true compatibility.
Never run npm install or update commands automatically; version checks may only display a manual notice on an interactive TTY or when CODEX_MULTI_AUTH_DEBUG=1.
Experimental synchronization and backup flows must be non-destructive by default: preview before applying, preserve destination-only accounts, and fail safely on filename collisions.
Bound forwarded request retries and account rotation; disable whole-pool replay when all accounts are rate-limited and apply cooldowns after repeated cross-account 5xx bursts.
Stagger proactive credential refreshes to reduce background refresh bursts.

Files:

  • lib/runtime-constants.ts
  • lib/storage/public-types.ts
  • scripts/codex-app-router.js
  • test/runtime-rotation-proxy.test.ts
  • lib/schemas.ts
  • scripts/codex.js
  • lib/runtime-rotation-proxy.ts
  • test/app-bind.test.ts
  • lib/storage/flagged-storage.ts
  • lib/accounts.ts
  • lib/runtime/app-bind.ts
lib/**

⚙️ CodeRabbit configuration file

focus on auth rotation, windows filesystem IO, and concurrency. verify every change cites affected tests (vitest) and that new queues handle EBUSY/429 scenarios. check for logging that leaks tokens or emails.

Files:

  • lib/runtime-constants.ts
  • lib/storage/public-types.ts
  • lib/schemas.ts
  • lib/runtime-rotation-proxy.ts
  • lib/storage/flagged-storage.ts
  • lib/accounts.ts
  • lib/runtime/app-bind.ts
lib/{storage/**/*.ts,storage.ts,runtime-paths.ts}

📄 CodeRabbit inference engine (lib/AGENTS.md)

lib/{storage/**/*.ts,storage.ts,runtime-paths.ts}: Resolve project storage identity with resolveProjectStorageIdentityRoot; never derive project pools directly from raw worktree paths.
Never key project storage directly by worktree path.

Files:

  • lib/storage/public-types.ts
  • lib/storage/flagged-storage.ts
lib/storage/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Do not key project storage by worktree path; use resolveProjectStorageIdentityRoot.

Files:

  • lib/storage/public-types.ts
  • lib/storage/flagged-storage.ts
docs/**/*.md

📄 CodeRabbit inference engine (docs/STYLE_GUIDE.md)

docs/**/*.md: User-facing documentation should follow the page template: Title and one-line lead, Quick path commands, Core operational workflow, Troubleshooting or failure handling, and Related links
Use short sections and scan-friendly tables in documentation where they improve clarity
Prefer direct, actionable language in documentation
Use runnable command examples in documentation
Explain expected outcomes after critical commands in documentation
Keep terminology consistent with runtime names in documentation
Avoid speculative language when behavior is deterministic in documentation
Put the user problem in the first paragraph before implementation detail
Use descriptive page titles such as codex-multi-auth Features instead of generic titles on public docs
Do not repeat keyword lists in every section; search terms should appear only where they help a developer understand the page
Canonical command family is codex-multi-auth ...
Canonical runtime root is ~/.codex/multi-auth
Runtime rotation must be described as default-on unless the release policy changes
Legacy command/path references belong only in migration contexts in documentation
Compatibility aliases (codex multi auth, codex multi-auth, codex multiauth) belong only in command reference, troubleshooting, or migration contexts
Keep command flags aligned with runtime usage text in documentation
Avoid non-runnable command snippets in documentation
Avoid conflicting path guidance across documentation
Avoid legacy-first onboarding language in documentation

Organize repository documentation according to the defined layers: product entry, user operations, reference, and development.

docs/**/*.md: Do not describe codex-multi-auth as replacing @openai/codex or publishing the global codex binary; preserve the official CLI's ownership of codex.
Use codex-multi-auth for account management, and reserve codex-multi-auth-codex or mcodex for intentionally forwarding official Codex commands th...

Files:

  • docs/reference/storage-paths.md
docs/reference/**/*.md

📄 CodeRabbit inference engine (docs/STYLE_GUIDE.md)

New flags/settings/paths must be reflected in docs/reference/*

docs/reference/**/*.md: Keep command, API, error-contract, settings, and storage-path details in the canonical reference documentation.
Document compatibility aliases (codex multi auth, codex multi-auth, and codex multiauth) only in command-reference, troubleshooting, or migration sections.

Files:

  • docs/reference/storage-paths.md
docs/**/*.{md,mdx}

📄 CodeRabbit inference engine (docs/troubleshooting.md)

Document that codex-multi-auth-codex is the optional forwarding wrapper, while codex-multi-auth is the canonical account-manager command family; the package does not publish a global codex binary.

Document the canonical command names, runtime paths, configuration precedence, storage migration behavior, and upgrade procedures consistently across the referenced documentation.

Files:

  • docs/reference/storage-paths.md
docs/**

⚙️ CodeRabbit configuration file

keep README, SECURITY, and docs consistent with actual CLI flags and workflows. whenever behavior changes, require updated upgrade notes and mention new npm scripts.

Files:

  • docs/reference/storage-paths.md
scripts/codex*.js

📄 CodeRabbit inference engine (AGENTS.md)

The wrapper must not reimplement general Codex commands; authentication commands are handled locally and non-authentication commands must forward to the official Codex CLI.

Files:

  • scripts/codex-app-router.js
  • scripts/codex.js
scripts/**/*.js

📄 CodeRabbit inference engine (AGENTS.md)

Windows-sensitive cleanup and write operations must retry transient EBUSY, EPERM, and ENOTEMPTY failures where applicable.

Files:

  • scripts/codex-app-router.js
  • scripts/codex.js
test/**/*.test.ts

📄 CodeRabbit inference engine (test/AGENTS.md)

test/**/*.test.ts: Write Vitest test suites with globals enabled (describe, it, expect)
Maintain 80%+ coverage threshold across statements, branches, functions, and lines
Use removeWithRetry() for Windows filesystem cleanup instead of bare fs.rm to handle EBUSY, EPERM, and ENOTEMPTY errors
Do not rely on dist/ in tests; use source files instead
Do not skip tests without justification
Relax lint rules for test files as configured in eslint.config.js

Files:

  • test/runtime-rotation-proxy.test.ts
  • test/app-bind.test.ts
test/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Windows-sensitive filesystem tests and helpers must use retry handling for transient lock-related cleanup and write failures.

Files:

  • test/runtime-rotation-proxy.test.ts
  • test/app-bind.test.ts
test/**

⚙️ CodeRabbit configuration file

tests must stay deterministic and use vitest. demand regression cases that reproduce concurrency bugs, token refresh races, and windows filesystem behavior. reject changes that mock real secrets or skip assertions.

Files:

  • test/runtime-rotation-proxy.test.ts
  • test/app-bind.test.ts
lib/{runtime-rotation-proxy.ts,local-bridge.ts,request/**/*.ts}

📄 CodeRabbit inference engine (lib/AGENTS.md)

Do not forward stale decoded content-encoding metadata when Node fetch has already decoded response bytes.

Files:

  • lib/runtime-rotation-proxy.ts
lib/{runtime-rotation-proxy.ts,local-bridge.ts}

📄 CodeRabbit inference engine (lib/AGENTS.md)

lib/{runtime-rotation-proxy.ts,local-bridge.ts}: Runtime proxy client-facing headers and responses must never expose account emails or tokens.
Never include account emails or tokens in runtime proxy client responses.

Files:

  • lib/runtime-rotation-proxy.ts
lib/{runtime-rotation-proxy.ts,runtime/**/*.ts}

📄 CodeRabbit inference engine (lib/AGENTS.md)

Runtime rotation must fail open to normal official Codex forwarding when startup helpers are unavailable.

Files:

  • lib/runtime-rotation-proxy.ts
  • lib/runtime/app-bind.ts
lib/runtime-rotation-proxy.ts

📄 CodeRabbit inference engine (AGENTS.md)

lib/runtime-rotation-proxy.ts: Keep runtime rotation enabled by default, use loopback-only networking, and use a per-process client token.
Do not expose account emails or tokens in runtime proxy response headers or logs.
The runtime proxy may forward only Responses API and model-discovery requests.

Files:

  • lib/runtime-rotation-proxy.ts
lib/{accounts.ts,accounts/**/*.ts}

📄 CodeRabbit inference engine (lib/AGENTS.md)

Maintain account health on a 0–100 scale and update it through account manager APIs.

Files:

  • lib/accounts.ts
lib/accounts.ts

📄 CodeRabbit inference engine (AGENTS.md)

Email deduplication must be case-insensitive using normalizeEmailKey() (trim and lowercase).

Files:

  • lib/accounts.ts
lib/runtime/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Do not patch official Codex app binaries; use the reversible app-bind or launcher-helper mechanisms instead.

Files:

  • lib/runtime/app-bind.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-08-08T13:59:48.826Z
Learning: Use the official OpenAI installation path for the `codex` command and invoke this package through `codex-multi-auth` or the intentional forwarding wrappers.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-08-08T13:59:48.826Z
Learning: The package is intended for personal development use; production or commercial workloads should use the OpenAI Platform API.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-08-08T13:59:57.574Z
Learning: Do not manually edit refresh lease/state files while the CLI is running.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-08-08T13:59:57.574Z
Learning: Existing stateless pipelines should leave `backgroundResponses` disabled; enable it only for callers that require stateful background responses and validate one end-to-end request before broad rollout.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-08-08T14:00:08.875Z
Learning: Treat `~/.codex/multi-auth` contents as project-managed, while `~/.codex/accounts.json`, `~/.codex/auth.json`, and `~/.codex/config.toml` remain official Codex CLI files; do not overwrite unrelated ownership boundaries.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-08-08T14:00:08.875Z
Learning: Never read or write the OS keychain or `security` CLI; use the file-backed Codex auth store and preserve official CLI file locations.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-08-08T14:00:08.875Z
Learning: Reconcile the persisted top-level `cli_auth_credentials_store` value to `"file"` at first-run setup, wrapper startup, and `doctor --fix`, while leaving profile-level values unchanged and preserving line endings and accepted TOML quote styles.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-08-08T14:00:08.875Z
Learning: Honor `CODEX_MULTI_AUTH_FORCE_FILE_AUTH_STORE=0` and `CODEX_MULTI_AUTH_ENFORCE_CLI_FILE_AUTH_STORE=0` with their documented scopes: the former disables wrapper injection and startup reconciliation; the latter disables config rewrites while retaining per-invocation overrides.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-08-08T14:00:08.875Z
Learning: Use atomic writes and appropriate retry handling for configuration and account state; failures during first-run setup or wrapper reconciliation must be swallowed or debug-logged so they do not block the user command.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-08-08T14:00:08.875Z
Learning: Exclude `.reset-intent` markers and cache-like artifacts from recovery candidates; suppress flagged-account backup recovery while the flagged reset marker remains present.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-08-08T14:00:08.875Z
Learning: Named backup exports must use only letters, numbers, `_`, and `-`; reject path separators, `..`, `.rotate.`, `.tmp`, and `.wal`, append `.json` when omitted, and do not overwrite existing files except through an explicit lower-level force path.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-08-08T14:00:08.875Z
Learning: The local bridge must be loopback-only, expose only `/health`, `/v1/models`, and `/v1/responses`, and persist token hashes rather than plaintext tokens; plaintext tokens may be shown only during create or rotate commands.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-08-08T14:00:08.875Z
Learning: Enforce pause and drain entries from `account-policies.json` at selection time through `evaluateRuntimePolicy`, excluding blocked accounts from hybrid rotation.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-08-08T14:00:08.875Z
Learning: Maintain compatibility paths only for migration reads; canonical new storage must use the documented `~/.codex/multi-auth` layout and its canonical filenames.
📚 Learning: 2026-06-04T06:14:18.093Z
Learnt from: ndycode
Repo: ndycode/codex-multi-auth PR: 510
File: test/scheduling-strategy-config.test.ts:1-1
Timestamp: 2026-06-04T06:14:18.093Z
Learning: In ndycode/codex-multi-auth, do not flag explicit imports from "vitest" (e.g., describe, it, expect, beforeEach/afterEach, etc.) in test files as issues—even if the Vitest config sets `globals: true`. The repo’s established convention is to keep these imports for consistency with neighboring tests; removing them would make files outliers.

Applied to files:

  • test/runtime-rotation-proxy.test.ts
  • test/app-bind.test.ts
📚 Learning: 2026-06-04T06:14:24.975Z
Learnt from: ndycode
Repo: ndycode/codex-multi-auth PR: 510
File: test/runtime-rotation-proxy.test.ts:2478-2491
Timestamp: 2026-06-04T06:14:24.975Z
Learning: In ndycode/codex-multi-auth test files (e.g. `test/*.test.ts`), when creating V3 storage fixtures for accounts, it’s an intentional convention to use `as never` for deliberately minimal stored-account objects that only include `refreshToken`, `addedAt`, and `lastUsed`. Do not treat `as never` here as a type-safety problem: optional/other fields are expected to be populated by the runtime during execution, and the cast is used solely to keep the fixture minimal and consistent across existing tests.

Applied to files:

  • test/runtime-rotation-proxy.test.ts
  • test/app-bind.test.ts
🪛 ast-grep (0.45.0)
lib/runtime/app-bind.ts

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)


[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "node:child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

🪛 OpenGrep (1.26.0)
lib/runtime/app-bind.ts

[ERROR] 936-938: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.

(coderabbit.command-injection.exec-js)

🔇 Additional comments (31)
README.md (1)

261-261: LGTM!

docs/reference/storage-paths.md (1)

43-43: LGTM!

lib/accounts.ts (1)

2-2: LGTM!

Also applies to: 113-142, 273-303, 528-556, 570-577, 612-619, 701-701, 714-730, 847-847, 882-882, 940-940, 997-997, 1307-1319, 1359-1359, 1418-1435, 1486-1505, 1571-1625, 1674-1675

lib/schemas.ts (1)

164-164: LGTM!

Also applies to: 180-180

lib/storage/flagged-storage.ts (1)

96-100: LGTM!

Also applies to: 138-139

lib/storage/public-types.ts (1)

25-26: LGTM!

Also applies to: 49-52

lib/runtime-rotation-proxy.ts (1)

1-1: LGTM!

Also applies to: 23-26, 52-58, 170-199, 742-782, 1105-1131, 1244-1263, 1390-1403, 1486-1492

test/runtime-rotation-proxy.test.ts (1)

9-14: LGTM!

Also applies to: 1417-1603, 2569-2626, 2703-2706

lib/runtime-constants.ts (1)

6-9: LGTM!

lib/runtime/app-bind.ts (12)

4-14: LGTM!

Also applies to: 25-30, 74-75, 85-91, 122-128, 140-169


323-323: LGTM!

Also applies to: 358-358, 402-405, 418-418


518-518: LGTM!

Also applies to: 538-539, 611-612


584-586: LGTM!


667-757: LGTM!


759-789: LGTM!


796-916: LGTM!


918-1000: LGTM!


1002-1088: LGTM!


1090-1202: LGTM!


1204-1301: LGTM!


1380-1380: LGTM!

Also applies to: 1426-1432, 1474-1502, 1524-1550, 1593-1614

scripts/codex-app-router.js (1)

39-39: LGTM!

Also applies to: 62-66, 142-175, 259-259, 269-278, 309-319

scripts/codex.js (4)

83-84: LGTM!

Also applies to: 115-125, 138-154, 192-223


3707-3735: LGTM!


3779-3783: LGTM!

Also applies to: 3897-3912, 3937-3938, 3956-3956, 3973-3973


4259-4263: LGTM!

Also applies to: 4277-4292, 5295-5295

test/app-bind.test.ts (5)

6-28: LGTM!

Also applies to: 83-138, 191-204


372-372: LGTM!

Also applies to: 389-390, 414-415


417-728: LGTM!


730-822: LGTM!


926-955: LGTM!

Also applies to: 986-1010, 1182-1182, 1211-1214, 1239-1239

Comment thread lib/accounts.ts
Comment thread lib/runtime/app-bind.ts
Comment thread scripts/codex.js
Comment thread test/app-bind.test.ts
Comment thread test/app-bind.test.ts
@ndycode
ndycode force-pushed the fix/issue-652-incognito-login branch from cf1148c to 0f6038a Compare August 8, 2026 14:24
Comment thread lib/runtime/app-bind.ts
if (!verified) {
return false;
}
return stopDetachedProcess(router.pid, platform, options);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 pid reuse bypasses ownership verification

if the verified router exits and its pid is reused before stopDetachedProcess signals it, the replacement process is terminated because ownership is not revalidated after the fresh liveness check. on windows, taskkill /t /f terminates the replacement process and its entire process tree.

Knowledge Base Used: Runtime Services

Prompt To Fix With AI
This is a comment left during a code review.
Path: lib/runtime/app-bind.ts
Line: 747

Comment:
**pid reuse bypasses ownership verification**

if the verified router exits and its pid is reused before `stopDetachedProcess` signals it, the replacement process is terminated because ownership is not revalidated after the fresh liveness check. on windows, `taskkill /t /f` terminates the replacement process and its entire process tree.

**Knowledge Base Used:** [Runtime Services](https://app.greptile.com/zeian/-/custom-context/knowledge-base/ndycode/codex-multi-auth/-/docs/runtime-services.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex

@ndycode
ndycode merged commit a83d63e into main Aug 8, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant