Skip to content

Commit 92d0f6f

Browse files
ndycodeclaude
andcommitted
docs(release): write the v2.8.4 notes and changelog entry
Replaces the placeholder created by the version bump, now that 2.8.4 is published to npm. Covers both #659 reproductions from the server's point of view (the lstat-strict app-server-control check and the frozen thread index), the three app-helper behaviours that were wrong for a resident server, and the operator-visible consequences: no shadow home, a helper stopped with the server rather than idled out, and a proxy failure that now fails the server instead of running it unrotated. Credits @possibilities for the report and the original patch in #660. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KT5pNBtZ151FSC6KBA32sk
1 parent 8cb3cb5 commit 92d0f6f

2 files changed

Lines changed: 109 additions & 4 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,28 @@ 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.8.4] - 2026-08-12
11+
12+
A corrective release for the `codex app-server` transport. No user configuration migration is required. It closes [#659](https://github.com/ndycode/codex-multi-auth/issues/659) and landed as [#662](https://github.com/ndycode/codex-multi-auth/pull/662); see [docs/releases/v2.8.4.md](docs/releases/v2.8.4.md) for full details.
13+
14+
### Fixed
15+
16+
- **`codex app-server` could not run on the shadow `CODEX_HOME`.** The shadow mirror links directories, so Codex's strict `lstat` check on `<CODEX_HOME>/app-server-control` refused to start the server on any machine that had previously run one; a server that did start held a frozen snapshot of the thread index for its whole life and discarded threads it created. `app-server` now takes the canonical-home transport already used by the interactive TUI and `resume`/`fork`, with rotation carried as `-c` overrides ([#659](https://github.com/ndycode/codex-multi-auth/issues/659), [#662](https://github.com/ndycode/codex-multi-auth/pull/662))
17+
- **The app-server CLI shim leaked a rotation-disabling environment into forwarded children.** The shim is reachable only from the app-helper, so routing a command through that helper silently stamped `CODEX_MULTI_AUTH_RUNTIME_ROTATION_PROXY=0`, `CODEX_CLI_PATH`, and a preload `NODE_OPTIONS` onto the environment Codex passes to shell tools and MCP servers. It is no longer installed for a wrapper-invoked `app-server`, which already carries the overrides on its command line; `codex app` and the interactive branches are unchanged ([#662](https://github.com/ndycode/codex-multi-auth/pull/662))
18+
- **A short-lived `app-server` stranded its rotation helper for the full 12-hour idle timeout.** An explicit `detachOnExit: false` is now honored instead of being overridden by the clean-exit grace window, and that window's clock starts when the helper reports ready rather than before a launch bounded at 15 seconds ([#662](https://github.com/ndycode/codex-multi-auth/pull/662))
19+
- **A rotation helper that failed to start surfaced as an unhandled rejection.** The helper branches now emit a diagnostic and exit 1, releasing the compatibility home first, instead of printing a raw stack trace and leaking a temporary directory ([#662](https://github.com/ndycode/codex-multi-auth/pull/662))
20+
21+
### Changed
22+
23+
- `app-server` requests `account/read`, `getAuthStatus`, and `account/rateLimits/read` rewriting explicitly rather than inferring it from an environment variable the removed shim used to set. Stdio clients see unchanged responses ([#662](https://github.com/ndycode/codex-multi-auth/pull/662))
24+
- A rotation proxy that cannot start now fails an `app-server` hard rather than silently running it unrotated, matching how `--account` already behaves ([#662](https://github.com/ndycode/codex-multi-auth/pull/662))
25+
- The helper's startup stdout/stderr buffers stop accumulating once startup settles, so a wrapper supervising a resident server for days does not grow them without bound ([#662](https://github.com/ndycode/codex-multi-auth/pull/662))
26+
27+
### Regression coverage
28+
29+
- Five wrapper tests cover canonical-home routing, a real `app-server-control` directory and a live thread index, the absence of every shim side effect, helper reaping on clean and non-zero exits, the startup-failure diagnostic and its compatibility-home release, and `--account` propagation across the detached helper boundary. Reaping is asserted by polling the helper pid, since Windows hard-terminates the helper before its cleanup handler runs.
30+
- The full suite passes with 337 test files passing and 1 skipped, for 5,364 tests passing and 4 skipped; coverage remains above the project thresholds.
31+
1032
## [2.8.3] - 2026-08-09
1133

1234
A follow-up patch release for quota presentation. No user configuration migration is required. It landed as [#657](https://github.com/ndycode/codex-multi-auth/pull/657); see [docs/releases/v2.8.3.md](docs/releases/v2.8.3.md) for full details.

‎docs/releases/v2.8.4.md‎

Lines changed: 87 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,99 @@
11
# v2.8.4
22

3-
A patch release. No user configuration migration is required.
3+
A corrective release. No new features and no configuration changes.
44

5-
Landed as [#662](https://github.com/ndycode/codex-multi-auth/pull/662).
5+
`codex app-server` was unusable through the wrapper with runtime rotation enabled — which, since rotation is on by default, means it was unusable. On any machine that had ever run an app-server it refused to start; where it did start, every attached client drove threads against a frozen copy of the thread index. This is the third command to move onto the canonical Codex home, after the interactive TUI in v2.8.0 and `resume`/`fork` in v2.8.1, and for the same underlying reason.
6+
7+
Closes [#659](https://github.com/ndycode/codex-multi-auth/issues/659). Landed as [#662](https://github.com/ndycode/codex-multi-auth/pull/662).
8+
9+
Reported with a complete reproduction by [@possibilities](https://github.com/possibilities), who also sent the original patch in [#660](https://github.com/ndycode/codex-multi-auth/pull/660).
10+
11+
## `app-server`
12+
13+
### The server refused to start
14+
15+
```console
16+
$ codex-multi-auth-codex --account <id> app-server --listen unix:///path/to/a.sock
17+
Error: socket directory path exists and is not a directory: \
18+
/Users/user/.codex/multi-auth/runtime-shadow-homes/codex-multi-auth-runtime-home-XXXXXX/app-server-control
19+
```
20+
21+
Exit 1, no server. Codex requires `<CODEX_HOME>/app-server-control` to be a directory and checks it with a strict `lstat`. Codex itself creates that directory the first time an app-server runs, so most real homes have one — and the shadow mirror links directories rather than copying them, so the shadow home got a symlink at exactly that path. Deleting `~/.codex/app-server-control` made it start again, which is what pinned the mirror's symlink as the trigger.
22+
23+
### A server that did start served a frozen thread index
24+
25+
The shadow mirror snapshots `state_N.sqlite` rather than linking it. For `resume` that was [#647](https://github.com/ndycode/codex-multi-auth/issues/647): the requested thread was absent and the TUI hung. For an app-server the same divergence is worse in kind rather than degree — it is held for the entire life of the process and handed to every client that attaches, and any thread the server creates is written into a copy that is discarded at exit.
26+
27+
Both failures have one cause, and one fix. `app-server` now takes the canonical-home transport that the bare TUI and `resume`/`fork` already use: a real `app-server-control` directory, the live thread index, and sessions that persist. Rotation stays on and travels as `-c` overrides, so the canonical `config.toml` is never rewritten ([#662](https://github.com/ndycode/codex-multi-auth/pull/662)).
28+
29+
## Rotation helper
30+
31+
Moving a command onto the canonical-home transport also moves it onto the shared app-helper, and three of that helper's behaviours were wrong for a resident server rather than merely suboptimal.
32+
33+
### The app-server CLI shim is no longer installed for a wrapper-invoked server
34+
35+
The shim exists for one purpose: letting the Codex **desktop app** have its own `codex app-server` spawn intercepted through `CODEX_CLI_PATH`. It is reachable only from the app-helper, so any command routed through that helper picks it up silently — and it stamps three things onto the environment the forwarded child inherits:
36+
37+
| Variable | Value | Why it matters for a resident server |
38+
| --- | --- | --- |
39+
| `CODEX_MULTI_AUTH_RUNTIME_ROTATION_PROXY` | `0` | Codex passes its environment to shell tools and MCP servers, so every nested `codex-multi-auth-codex` or `mcodex` run reads rotation as disabled and bills whatever account the official CLI resolves. A nested `--account` fails outright. |
40+
| `CODEX_CLI_PATH` | the shim directory | The file named `codex` there is a copy of `node`. Anything resolving the CLI through this variable and running a subcommand other than `app-server` executes bare node with no script. |
41+
| `NODE_OPTIONS` | `--import=<shim>/…preload.mjs` | Inherited by every Node subprocess the server spawns — on a directory removed at wrapper exit and swept on the next helper start. |
42+
43+
A wrapper-invoked app-server is already launched with the rotation overrides on its own command line and never needs the interception, so it no longer pays for the shim or inherits any of that. On Windows it also no longer copies the ~100 MB Node image into a per-pid directory on every launch. `codex app` and the interactive branches, which do need the shim, are unchanged.
44+
45+
Because there is then no `CODEX_MULTI_AUTH_APP_SERVER_ACCOUNT_LABEL` in the environment, the branch requests `account/read`, `getAuthStatus`, and `account/rateLimits/read` rewriting explicitly instead of inferring it from that variable. Stdio clients see the same responses as before.
46+
47+
### A short-lived server no longer strands its helper
48+
49+
The helper detached on any clean exit inside a five-second window, regardless of what the caller asked for. A client that attached, ran one query, and disconnected therefore left a helper running for the full 12-hour idle timeout with nothing left to refresh its activity clock. A supervisor restarting the server stranded one per cycle. A resident server now owns its proxy for its whole lifetime and stops it on exit; the interactive TUI, which detaches deliberately, is unaffected.
50+
51+
The window's clock also started before the helper was launched rather than after it reported ready. Launching is bounded at 15 seconds, so on a cold or loaded machine the entire grace period could elapse during startup — and `codex app`, which relies on the window rather than an explicit flag, would kill the helper it had just handed the desktop app off to.
52+
53+
### A helper that cannot start now fails cleanly
54+
55+
The shadow path degrades to rotation-off when its proxy will not start. The helper branches have no such shape to fall back to, and the failure surfaced as `ERR_UNHANDLED_REJECTION` with a raw stack trace, leaking the compatibility home the caller had already built. It is now a one-line diagnostic and exit 1, with the compatibility home released first.
56+
57+
The hard failure is deliberate. A resident server that quietly loses rotation serves every attached client on whatever account the official CLI resolves — a billing error you would not see, where a failed launch is one you would. This matches how `--account` has always behaved.
658

759
## Upgrade notes
860

9-
No migration is required. Install the package and confirm the version:
61+
No migration is required, and no settings were added, renamed, or repurposed:
1062

1163
```bash
1264
npm i -g codex-multi-auth
1365
codex-multi-auth --version
1466
```
1567

16-
The command should report `2.8.4`.
68+
That should report `2.8.4`. Then confirm the fix against a real socket path:
69+
70+
```bash
71+
codex-multi-auth-codex app-server --listen unix:///tmp/codex-app-server.sock
72+
```
73+
74+
It should start instead of exiting 1 on `app-server-control`, and attached clients should see your existing threads.
75+
76+
Note that Codex applies the same strict `lstat` check to the listen socket's own parent directory, so `--listen unix:///tmp/x.sock` fails on macOS because `/tmp` is a symlink to `/private/tmp`. Use a real path — that behaviour is Codex's and is unrelated to this fix.
77+
78+
Three consequences are worth knowing rather than discovering:
79+
80+
- `app-server` no longer creates a shadow home under `<CODEX_HOME>/multi-auth/runtime-shadow-homes/`, or a shim directory under `app-server-shims/`. It reads and writes your canonical home in place, which is what makes threads persist.
81+
- Its rotation helper is stopped when the server exits rather than left to idle out. This is the opposite of the interactive TUI, and it is intentional.
82+
- A rotation proxy that cannot start now fails the server rather than silently running it unrotated.
83+
84+
If you had been running `CODEX_MULTI_AUTH_RUNTIME_ROTATION_PROXY=0` to get an app-server to start at all, drop it — that workaround bought a working server by turning off account rotation:
85+
86+
```bash
87+
unset CODEX_MULTI_AUTH_RUNTIME_ROTATION_PROXY
88+
codex-multi-auth rotation status
89+
```
90+
91+
That should report the runtime rotation proxy as enabled.
92+
93+
## Regression coverage
94+
95+
Five wrapper tests cover the canonical-home routing, a real `app-server-control` directory and a live thread index the server can append to, the absence of every shim side effect, helper reaping on both clean and non-zero server exits, the clean-diagnostic startup-failure path with its compatibility-home release, and `--account` propagation across the detached helper boundary.
96+
97+
Helper reaping is asserted by polling the helper pid rather than by waiting for a shutdown marker, because Windows hard-terminates the helper and it never reaches its own cleanup handler. None of the tests shortens the idle timeout, so a stranded helper fails them instead of passing quietly.
98+
99+
The full local suite passed with 337 test files passing and 1 skipped, for 5,364 tests passing and 4 skipped.

0 commit comments

Comments
 (0)