Auto refresh
- New refreshCodexAccount(index) calls https://auth.openai.com/oauth/token
with grant_type=refresh_token and persists rotated tokens back to
~/.codex-accounts/{N}/auth.json. JWT's subscription_active_until
reflects the latest plan state OpenAI hands back.
- startCodexAccountRefreshLoop() runs every 6h (first run delayed 60s
after boot to keep startup snappy). Hooked into main()/shutdown()
alongside the existing claude token refresh loop.
Manual controls (Settings → 계정 → Codex)
- "갱신" button per row: forces an immediate refresh for that account.
- "전체 갱신" button: refreshes all codex accounts in sequence.
- "전환" button: writes data/codex-rotation-state.json so the next codex
spawn picks the chosen account. Active account marked with a green-
bordered card and "사용중" badge.
Endpoints
- POST /api/settings/accounts/codex/{i}/refresh
- POST /api/settings/accounts/codex/refresh-all
- PUT /api/settings/accounts/codex/current { index }
- GET /api/settings/accounts now also returns codexCurrentIndex.
Why
JWTs cache subscription state at issue-time. When a Pro plan lapses or
a user upgrades/downgrades, the dashboard kept showing stale data until
the user logged in again. Periodic refresh + explicit "갱신" button
keeps the displayed state honest, and the manual switch unblocks the
user when rotation lands on a known-bad account.
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>