v6.8.1
Published to npm as oc-codex-multi-auth@6.8.1.
npm install -g oc-codex-multi-auth@6.8.1
Fixed
gpt-5.6-sol no longer hard-fails for accounts outside the GPT-5.6 preview (#196, #197)
6.7.0 documented that an account without 5.6 access degrades gpt-5.6-sol → gpt-5.6-terra → gpt-5.6-luna → gpt-5.5, but the chain was only traversed under unsupportedCodexPolicy: "fallback" — the default-selector auto-fallback allowlist listed only gpt-5.5 and gpt-5-codex, so under the default strict policy a Sol request burned through every pooled account and returned an entitlement error. The three 5.6 tiers now auto-degrade out of the box, exactly as documented. Opt out with CODEX_AUTH_DISABLE_GPT56_AUTO_FALLBACK=1. Bare gpt-5.6 is also canonicalized to gpt-5.6-sol inside the fallback resolver, so custom chains keyed as gpt-5.6 resolve correctly.
The carried-over reasoning effort is also re-clamped per fallback hop: gpt-5.6-sol-max degrading to gpt-5.5 previously sent max — an effort only 5.6 accepts — to the fallback target, turning the graceful degrade into a hard 400. (#198)
Multi-process refresh-token clobber (#198)
A process persisting its in-memory account pool blind-overwrote the accounts file, including a refresh token another process had rotated after this process loaded its snapshot. Refresh tokens are single-use, so the clobbered token was dead on arrival — the next refresh with it failed and the auth-failure path eventually removed a still-valid workspace. Accounts now carry a persisted tokenRotatedAt stamp (written on rotation, propagated to token-sharing siblings, and stamped by codex-refresh too), and every save runs as a read-modify-write transaction under the storage lock that adopts newer on-disk credentials into both the persisted payload and live memory. Files from older builds have no stamp and keep the previous behavior. Two sibling defects of the same class are fixed alongside: the refresh queue re-consumed a just-rotated single-use token for callers arriving right after the rotation settled (now served the settled result for 30s), and the mutating tools (codex-switch/codex-remove/codex-label/codex-refresh) saved stale snapshots that silently overwrote concurrent rotation state — they now mutate inside a single storage transaction. codex-keychain migrate/rollback also actually run under the storage lock their docstring claimed, with hardened rollback error paths.
Truncated SSE streams are no longer reported as successes (#198)
A non-streaming response whose SSE stream ended without any terminal event was returned as raw SSE text at the original 2xx status — the rotation loop credited the account with a success for a failed turn and the client got an unparseable body. Such streams now surface as a 502 incomplete_stream error; bodies with no SSE framing still pass through as plain JSON.
Uncapped retry-after headers (#198)
The body retry_after_ms/retry_after fields were capped at 5 minutes but the equivalent headers were not, so a bogus header (e.g. retry-after: 86400) benched a healthy account for hours, persisted across processes. Header values now get the same cap; quota reset-at headers remain uncapped since those windows legitimately reset hours out.
TUI status line no longer trusts idle-stale quota snapshots (#198)
The 5-minute refresh returned any fingerprint-matching shared snapshot as current with no age check, so once the cache file existed the /wham/usage fetch never ran again — an hours-old percentage (with a reset time already in the past) rendered as fresh. Snapshots older than one refresh interval now trigger a live re-fetch and render as stale only as a fallback.
codex-reset redeem idempotency actually works now (#198)
The documented double-spend protection was inert: each attempt sent a fresh random redeem_request_id, so the backend could never recognize a retry. The key is now derived deterministically from the credit id, and a failed consume POST reports the redemption outcome as unknown (redeemed: null) instead of false — the request may have reached the backend, and claiming failure could push the user to spend a second credit.
Smaller fixes (#198)
- Proactive token refresh no longer skips accounts that have a refresh token but neither access token nor expiry.
codex-switch/codex-remove/codex-labelreject fractional account indices instead of silently flooring them, and a failed persist is reported as a failed operation rather than a success with a caveat.
Full details in the CHANGELOG.