Uh oh!
There was an error while loading. Please reload this page.
Codex live cwd from session rollout: close .hypignore leak for subscription route (LLP 0083) - #266
Conversation
…iption route (LLP 0083) ChatGPT-subscription-routed Codex traffic (provider='chatgpt', /backend-api/codex/*) carries no in-band cwd — codex-tui sends no x-codex-turn-metadata header and the subscription protocol has no metadata.cwd — so the live exchange projector recorded cwd = NULL on every row and `.hypignore` folder policy failed OPEN for the whole traffic class (LLP 0049 R1 leak). It also diverged from backfill, which reads the rollout and DOES honor the policy for the same session. Give the Codex live projector the enrichment it turned out to need: when the request carries no cwd, resolve it from the session's rollout (session_meta.cwd, the same source backfill reads), keyed on the session id the adapter already resolves and matched via the shared sessionIdFromPath helper. The in-band value stays the fast path (lazy `??`, no scan when present); the rollout is read first-line-only and cached per session id, so the capture hot path stays bounded (LLP 0049 R6). The one resolved cwd feeds both the .hypignore drop and the stamped row, so live rows now carry the cwd backfill sees. - codex/src/rollout-cwd.js: new createRolloutCwdResolver (sync, cached). - codex/src/exchange-projector.js: rollout cwd fallback; resolveRecordedContext now takes the resolved cwd. - codex/src/index.js: wire the resolver to <codexHome>/sessions. - codex/src/backfill.js: export sessionIdFromPath for reuse. - LLP 0083 (decision) mints the choice; LLP 0049/0050 carry forward-refs. - test/plugins/codex-rollout-cwd.test.js: regression (fail-open -> dropped) plus resolver unit tests. Fixes#257 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
philcunliffe
commented
Jul 7, 2026
🔍 neutral review (Codex + Claude) — request_changesRound 1, head Codex (independent second family) surfaced two robustness/scale issues in the new Major 1 — a transient miss is cached as fail-open forever ( |
…okup (PR #266 review round 1) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
philcunliffe
commented
Jul 7, 2026
🔍 neutral review round 2 — approveRound-2 verification of the round-1 fixes — head Round-1 findings — resolved
Also fixed an inline (Round 2 was a focused verification of the bounded fix against the actual code — the round-1 Codex + Claude dual pass raised these findings; this round confirms they're resolved with no regressions. CI's Verdict: approve. Round-1 findings resolved, no new findings. Review rounds complete (N=2). Held for a human to merge — merging closes #257 ( Automated neutral review. |
Problem
ChatGPT-subscription-routed Codex traffic (
provider='chatgpt',/backend-api/codex/*) recorded every row withcwd = NULL, so the.hypignorefolder policy was a silent no-op for a whole traffic class — enforcement failed open (LLP 0049 R1 leak). The Codex live projector resolved cwd only from the in-flight request (x-codex-turn-metadataheader, then bodycwd/metadata.cwd/metadata.user_id.cwd) and skipped the policy check when none was found. The API-key route happens to carry cwd in-band, so this enrichment was never built; the subscription protocol has no such field andcodex-tuidoes not send the header. It also diverged from backfill, which reads the rollout and does honor the policy for the same session.The cwd existed locally the whole time: Codex writes
session_meta.cwdinto its rollout (<sessionsDir>/…/rollout-<ts>-<session_id>.jsonl, line 1) at session start, for both auth modes.Fix
Give the Codex live projector the rollout-based cwd fallback (symmetric to the Claude
session-context.jsonlsidecar):codex/src/rollout-cwd.js— newcreateRolloutCwdResolver: finds the rollout whose filename embeds the session id (via the sharedsessionIdFromPath), reads the firstsession_metaline'scwd, caches per session id (incl. misses) so the capture hot path stays bounded (LLP 0049 R6). First-line-only, synchronous — matches the adapter's existing synchronous usage-policy seam.exchange-projector.js— in-band cwd stays the fast path; the rollout is consulted lazily (??) only on a miss and only for real Codex sessions. The one resolved cwd feeds both the.hypignoredrop and the stamped row, so live rows now carry the cwd backfill sees (closes the live/backfill inconsistency).index.js— wires the resolver to<codexHome>/sessions.backfill.js— exportssessionIdFromPathfor reuse.Docs
Tests
test/plugins/codex-rollout-cwd.test.js: the primary regression asserts a subscription-route exchange with no in-band cwd is now.hypignore-dropped via the rollout cwd and stamps that cwd on the row (both failed on pre-fix code); plus a fast-path test andcreateRolloutCwdResolverunit tests over a real on-disk rollout.Checks:
npm test(1873 pass / 0 fail / 1 pre-existing skip),npm run typecheck(clean),npm run build:types(clean).Fixes#257