v0.27.0
Fixed
- Codex: two seats in the same ChatGPT Team workspace no longer collapse onto one slot. Team seats share a
chatgpt_account_id, and account lookup matched onaccountIdoremailand took the first hit — soccswap codex addmapped a second seat onto the first seat's slot and overwrote its tokens in place while reporting success,ccswap codex statusnamed the wrong seat as active, switching to the shadowed seat was a silent no-op, and switching away wrote the live login into the wrong slot's credential file. Stored logins were destroyed with no prompt. Reported, diagnosed and fixed by @JOhugo6 in #2, with eight regression tests that fail against 0.26.0. - Codex: a renamed login is no longer refresh-rotated while it is live. The stricter identity above means a login whose stored email has drifted matches no slot, so
accounts_snapshotread it as inactive; a 401 from its stored backup then reached_refresh_inactive_auth, which consumed the refresh token Codex was still holding and logged that session out. The guard is now the token itself, not the identity match.
Behavior
- A Codex login is identified by its
accountIdandemailtogether. Anything short of that exact pair is treated as unmanaged:ccswap codex addallocates a new slot instead of claiming an existing one, andccswap codex switchrefuses through the existing unmanaged-login guard rather than writing a login into a slot that may belong to someone else. - Consequence: the same email across two Team workspaces now keeps separate slots, and a login whose email changed needs a fresh
ccswap codex addrather than being adopted by its old slot. Failing toward a new slot is the safe direction — the alternative silently overwrote credentials.
Credits
Thanks to @JOhugo6 for a report that arrived with a reproduction, a root-cause trace to the exact call sites, and tests that bind the fix — including the mirrored collision their own first two revisions left standing.