Skip to content

Commit 6ede089

Browse files
committed
chore(release): bump version to v2.3.0-beta.2
1 parent 8d36a74 commit 6ede089

5 files changed

Lines changed: 142 additions & 4 deletions

File tree

CHANGELOG.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,33 @@ This repository's current stable release line is `2.x`.
77
Current stable release notes live in `docs/releases/`.
88
This top-level changelog preserves the foundational `0.x` milestones and points older iteration history to `docs/releases/legacy-pre-0.1-history.md`.
99

10+
## [2.3.0-beta.2] - 2026-06-11
11+
12+
Repository audit (34 PRs), 4 correctness bug fixes, security hardening, and major
13+
`codex-manager.ts` / `runtime-rotation-proxy.ts` decomposition.
14+
See [docs/releases/v2.3.0-beta.2.md](docs/releases/v2.3.0-beta.2.md) for full details.
15+
16+
### Fixed
17+
18+
- Sequential scheduling pointer corruption: `persistRuntimeActiveAccount` advanced
19+
the drain-first primary in legacy routing mode even when `schedulingStrategy:
20+
"sequential"` was set, breaking the #509 invariant
21+
- Flagged accounts lost `workspaces`/`currentWorkspaceIndex` on flag→restore
22+
round-trip due to `normalizeFlaggedStorage` omitting those fields
23+
- Quota cache wipe on transient disk failure: dead `catch` in
24+
`refreshQuotaCacheForMenu` caused empty-load to save only current-run entries
25+
- Expired token forwarded after failed refresh commit when
26+
`commitRefreshedAuthOnce` returned `null`
27+
28+
### Security
29+
30+
- Temp-file staging paths now use `crypto.randomBytes` instead of `Math.random()`
31+
- CI action steps pinned to exact commit SHAs
32+
- Private account response headers blocked by prefix match (not allowlist)
33+
- Stream stall `withTimeout` ordering fixed: reject before `onTimeout`
34+
35+
---
36+
1037
## [2.2.2] - 2026-06-03
1138

1239
Patch release for a stale runtime-overlay false positive in `forecast --live`.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ codex-multi-auth doctor --json
383383

384384
## Release Notes
385385

386-
- Current prerelease: [docs/releases/v2.3.0-beta.1.md](docs/releases/v2.3.0-beta.1.md) — install via `npm i -g codex-multi-auth@beta`
386+
- Current prerelease: [docs/releases/v2.3.0-beta.2.md](docs/releases/v2.3.0-beta.2.md) — install via `npm i -g codex-multi-auth@beta`
387387
- Current stable: [docs/releases/v2.2.2.md](docs/releases/v2.2.2.md) — install via `npm i -g codex-multi-auth`
388388
- Previous stable: [docs/releases/v2.2.1.md](docs/releases/v2.2.1.md)
389389
- Previous stable: [docs/releases/v2.2.0.md](docs/releases/v2.2.0.md)

docs/releases/v2.3.0-beta.2.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
## Repository Audit & Code Quality (34 PRs merged)
2+
3+
This beta incorporates a comprehensive repository audit — 34 stacked PRs covering
4+
security hardening, refactoring, and test infrastructure — plus 4 correctness bugs
5+
found during post-merge stress testing.
6+
7+
### Bug Fixes
8+
9+
- **Sequential scheduling pointer corruption**`persistRuntimeActiveAccount` was
10+
advancing the drain-first primary pointer via `markSwitchedLocked` in legacy
11+
routing mode even when `schedulingStrategy: "sequential"` was configured. A
12+
transient within-request fallback to a different account permanently moved the
13+
sequential primary, breaking the #509 drain-first invariant. The same guard
14+
already present in the enabled-mutex branch is now applied consistently.
15+
16+
- **Flagged accounts lose workspace data on restore**`normalizeFlaggedStorage`
17+
built a hardcoded field list that omitted `workspaces`, `currentWorkspaceIndex`,
18+
`accessToken`, and `expiresAt`, defeating the Zod schema's `.passthrough()` intent.
19+
Multi-workspace accounts that were flagged and later restored permanently lost their
20+
workspace list and active-workspace index. All four fields are now preserved on
21+
round-trip.
22+
23+
- **Quota cache wipe on transient disk failure**`refreshQuotaCacheForMenu` had a
24+
dead `catch` block because `loadQuotaCache()` never throws (it returns empty maps
25+
on any read failure). When a transient lock or corruption caused the persisted
26+
cache to come back empty, only the current run's probed entries were written back,
27+
silently wiping every other account's still-valid quota data. The empty-load case
28+
is now detected explicitly and falls back to the full in-memory snapshot.
29+
30+
- **Expired token forwarded after failed refresh commit**`ensureFreshAccessToken`
31+
could return an expired access token when `commitRefreshedAuthOnce` returned `null`
32+
(account not found in storage after persist). The fallback to the original account
33+
object used its stale `.access` field, causing a downstream 401 and incorrectly
34+
triggering invalidation-cooldown logic. The freshly-minted token from the refresh
35+
result is now used in the null-commit case.
36+
37+
### Security
38+
39+
- **Cryptographic temp-file paths** — All atomic write helpers (`storage.ts`,
40+
`recovery/storage.ts`, `quota-cache.ts`, `unified-settings.ts`, etc.) now use
41+
`crypto.randomBytes` instead of `Math.random()` for staging-path nonces,
42+
preventing a local attacker who can observe one staged path from predicting the
43+
next one (#517).
44+
45+
- **CI action SHA pinning** — All GitHub Actions workflow steps are pinned to exact
46+
commit SHAs (e.g. `actions/checkout@<sha>`) rather than floating version tags,
47+
hardening against supply-chain tag drift (#519).
48+
49+
- **Private account headers blocked by prefix** — Upstream response headers matching
50+
`x-codex-multi-auth-account-*` are now blocked by prefix rather than an allowlist,
51+
so any future header added under that namespace is blocked by default rather than
52+
leaking until someone extends a list (#546).
53+
54+
- **Stream stall now fails correctly**`withTimeout` rejected *after* calling
55+
`onTimeout`, which could cancel the stream reader and cause it to resolve cleanly,
56+
turning a stall into a silent success. Reject is now issued *before* `onTimeout`
57+
(#546).
58+
59+
### Refactoring
60+
61+
- **`codex-manager.ts` decomposed** (phases 1–4) — The 2,266-line monolith is now
62+
690 lines (-82%). Login control loop, OAuth machinery, command registry, and
63+
formatter modules are extracted into `lib/codex-manager/` submodules (#525, #535,
64+
#540, #547).
65+
66+
- **`runtime-rotation-proxy.ts` decomposed** (phases 1–2) — Rate-limit decision
67+
logic, stream-failover runtime, and rotation-proxy closure state are extracted into
68+
`lib/request/` and `lib/runtime/` submodules (#532, #548).
69+
70+
- **Import cycles eliminated**`eslint-plugin-import-x` no-cycle rule is now
71+
enforced in CI; all detected cycles were resolved (#541).
72+
73+
- **`isRecord` deduplication** — Local `isRecord` guards scattered across
74+
`runtime-current-account.ts`, `codex-manager/commands/rotation.ts`, and
75+
`refresh-lease.ts` are replaced with the canonical `lib/utils.ts` version, which
76+
correctly rejects arrays (the local copies didn't) (#544, #545).
77+
78+
### Testing
79+
80+
- **Mock factory infrastructure** — Shared `cli-test-fixtures` mock factories
81+
consolidate per-suite boilerplate across all manager test suites (#537, #539, #550).
82+
83+
- **CLI output contracts** — Machine-readable JSON surface (`status`, `report`,
84+
`doctor`, `forecast`, `why-selected`) is pinned with snapshot tests (#533).
85+
86+
- **Coverage gaps filled** — New test suites for `snapshot-inspectors`,
87+
`runtime-current-account`, `usage` and `models` commands, `isRecord` array
88+
rejection, `refresh-lease` array-payload rejection, `shouldRetryFileOperation`,
89+
`temp-path`, `fs-retry` helpers, and `flagged-storage` enum additions (#543, #544,
90+
#545, #517, #526, #516).
91+
92+
### Build / Packaging
93+
94+
- **Source maps removed from published package** — Declaration maps kept for
95+
go-to-definition; JS source maps stripped, reducing package size (#527).
96+
97+
- **`@types/node` pinned** — Pinned to the supported runtime floor major to prevent
98+
silent type drift from newer Node API additions (#528).
99+
100+
- **`engines.node` floor raised** — Requires `>=18.17.0` (reflects the actual tested
101+
minimum, aligns with `undici@6` and the `node18-smoke` CI job) (#518).
102+
103+
- **Config schema generated from Zod**`config/schema/config.schema.json` is now
104+
generated from the Zod schema with a drift-guard test (#536).
105+
106+
### Notes
107+
108+
- Prerelease published under the `beta` dist-tag
109+
(`npm i -g codex-multi-auth@beta`).
110+
- The #509 sequential drain-first feature from `2.3.0-beta.0` is unchanged and the
111+
pointer-corruption bug above is now fixed.

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "codex-multi-auth",
3-
"version": "2.3.0-beta.1",
3+
"version": "2.3.0-beta.2",
44
"description": "Codex CLI multi-account OAuth manager with account switching, health checks, runtime rotation, diagnostics, and recovery tools for @openai/codex",
55
"main": "./dist/index.js",
66
"types": "./dist/index.d.ts",

0 commit comments

Comments
 (0)