- Fixed stream forwarding stalling indefinitely for slow clients.
forwardStreamingResponsenow checks the return value ofres.write()and awaitsdrainbefore reading the next upstream chunk, preventing unbounded in-process buffering when the client socket falls behind.
- Converted the two startup guards in
startRuntimeRotationProxyfrom bareErrorthrows toCodexValidationErrorwith machine-readablefield/expected/contextmetadata. Error messages are byte-identical; callers can now branch oninstanceof CodexValidationErrorand stable field names instead of message text (audit §4.3, #586).
- Fixed multi-tier account deduplication.
deduplicateAccountsByIdentitynow runs fixpoint iteration: a single pass was not enough when a newest-wins merge could install an account that itself duplicated an earlier survivor through a different identity tier (e.g. an email-tier merge installs an account whoseaccountId + refreshTokenalready matches an earlier entry). The wrapper now loops until the array is stable; every pass strictly shrinks it by at least one entry, so it terminates in at mostaccounts.lengthpasses. - Added
vi.restoreAllMocks()tostorage.test.tsafterEachto prevent a failing test's leakedfsspy from cascading into every subsequent storage test in the same worker.
- Migrated the last two hand-rolled retry loops to the shared
withRetryhelper inlib/fs-retry.ts: the temp→final account-save rename (storage.ts) and the config env-path CAS loop (config.ts). Inter-attempt delay schedules are unchanged; only the wasted trailing sleep after a final failure is removed. - Converted
savePluginConfig's "unreadable config file" abort from a bareErrorto a typedStorageErrorwithcode: "UNREADABLE"and the file path. Callers can now branch oninstanceof StorageErrorinstead of message text (#588, audit §4.3).
- All atomic write helpers now use
crypto.randomBytesinstead ofMath.random()for staging-path nonces, preventing a local attacker from predicting the next staging path (#517).
- Removed 852 lines of dead code: seven orphaned modules with no live importers deleted (#554, #558).
- Pruned unused exports and types flagged by knip; added
knip.jsoncconfig for ongoing dead-code analysis (#555, #556, #557). isRetryableStorageWriteError,copyDashboardSettingValue,mergeDashboardSettingsForKeys, andDEFAULT_STATUSLINE_FIELDSexported from their respective modules for direct test access.- Synced plugin manifest and
AGENTS.mdpackage-version claim tov2.3.0-beta.3.
- 20 new direct test suites covering: login-oauth, login-menu actions/flow/data, persist-selected, health-check, forecast-report-shared, settings write-queue, rotation selection/state/token-refresh, auth-menu builder, model-fallback property, write-queue property, rate-limit helpers, usage-ledger redaction, settings preview builders, and settings-hub shared helpers.
- Property-based test suite for
deduplicateAccountsByIdentity: covers order-independence and convergence across all permutations using fast-check. shouldRetryFileOperation,fs-retry, andtemp-pathcovered with new unit suites.
- Prerelease published under the
betadist-tag (npm i -g codex-multi-auth@beta). - The #509 sequential drain-first feature and all fixes from
2.3.0-beta.2are included.