Skip to content

Latest commit

 

History

History
148 lines (108 loc) · 11.4 KB

File metadata and controls

148 lines (108 loc) · 11.4 KB

Release v1.3.0

Release line: stable

This minor release lands the Phase 1 post-audit hardening pass: 20 focused PRs addressing 49 findings from the 2026-04-17 master audit, spanning path-guard hardening, OAuth hygiene, routing correctness, storage atomicity, schema discipline, and CLI diagnostics.

Scope

  • Published package version: 1.3.0
  • Previous stable release: v1.2.7
  • Base audit: docs/audits/MASTER_AUDIT.md (commit range v1.2.4..v1.3.0)
  • Total PRs merged: 20 (#393 docs, #394-#412 implementation) + 7 post-audit remediation commits + 1 follow-up PR (#413)
  • Tests: 3345 → 3527 (+182)
  • Semver rationale: minor bump. No breaking public-API changes. One opt-in feature flag (routingMutex) added with legacy default.

What Changed

Security & Path Hardening

  • resolvePath() now rejects lookalike-prefix paths (e.g. HomeX vs Home/) using path.relative() comparison — blocks a sandbox-escape class (AUDIT-C1 / AUDIT-H1) (PR-A)
  • OAuth URLs redacted in user-facing login output — prevents token-leak via clipboard or terminal scrollback (AUDIT-H4) (PR-B)
  • AUTH_REDIRECT single source of truth — OAuth callback host unified to 127.0.0.1:1455 across bind, copy, and HTML; removes 4 duplicate hardcoded sites (AUDIT-H5 / M14 / M30) (PR-C)

Routing & Account Selection

  • Hybrid selector returns null when no accounts are available (was returning a stale fallback) (AUDIT-H2) (PR-D)
  • Short-429 retry now marks the account unavailable BEFORE the retry sleep, closing a TOCTOU window that let two requests race to the same rate-limited account (AUDIT-H3) (PR-E)
  • Active-account pointer normalization on disable/remove — prevents a dangling pointer when the active account is administratively removed (AUDIT-H10) (PR-F)
  • Routing mutex + SelectionRecord type — opt-in routingMutex: "enabled" | "legacy" config flag wraps cursor mutation in an async mutex. Default is "legacy" for one release cycle; enable via CODEX_AUTH_ROUTING_MUTEX=enabled. Four property tests (400 generated cases, fast-check) prove linearizability under concurrent requests (AUDIT-M06 / D-02 / D-09) (PR-N)

Storage & Recovery

  • Recovery storage migrated to atomic write + retry-safe delete pattern (AUDIT-M01) (PR-H)
  • Account-clear ordering now writes the reset marker BEFORE deletion and retries EPERM on read (AUDIT-M04 / M05) (PR-I)
  • Per-project vs CLI-sync config conflict now surfaced to the user instead of silently bypassing project-scoped isolation (AUDIT-M09) (PR-J)
  • Zod at JSON.parse boundaries — storage reads are now Zod-validated at 12 sites in lib/storage/**. New safeParseJson<T>(raw, schema, context) helper guards both SyntaxError and schema violations. V3 storage schema is the authoritative normalizer via AnyAccountStorageSchema. Recovery + request + config Zod migration deferred to follow-up PRs (AUDIT-M20) (PR-L)

Request Pipeline & SSE

  • Malformed SSE JSON chunks now surface as structured warnings instead of silent buffer drops. 10MB buffer cap documented. Deprecation/sunset headers logged uniformly across success AND failure paths (AUDIT-H9 / M16 / M18 / M34) (PR-K)

CLI Dashboard & Diagnostics

  • codex auth why-selected [--now|--last] [--json] — new diagnostic command surfacing per-candidate hybrid scoring breakdown (health, tokens, freshness, capability boost, PID bonus, final score) with reason text explaining the selection decision (PR-P)
  • codex auth verify [--paths|--flagged|--all] [--json] — new self-test command that walks the storage path resolution chain and exercises resolvePath() sandbox with known-good and known-bad inputs. Confirms the PR-A lookalike-prefix fix is live. verify-flagged kept as back-compat alias (PR-P)
  • lib/codex-manager/settings-hub.ts (808 LOC) split into 5 sub-concern files under lib/codex-manager/settings-hub/: dashboard, backend, experimental, shared, index. Each <500 LOC. Old file kept as a 9-line re-export stub for test compat. lib/AGENTS.md updated to retire the stale 2100-LOC claim (AUDIT-M24 / G-01 / JN-03) (PR-M)

Observability

  • getAccountHealth() reads the tracker directly; documents the field-name drift vs ManagedAccount. CHANGELOG.md updated (AUDIT-M08 / D-04) (PR-O)

Tooling, Docs & Tests

  • pack:check + tmp hygienenpm run pack:check now builds first and tests use os.tmpdir(); 6 stray tmp* directories at repo root cleaned up (AUDIT-H7 / M31) (PR-G)
  • Dual-linter scope documented — ESLint vs Biome boundaries clarified; husky prepare hook side-effect documented (AUDIT-M21 / M22 / M23 partial) (PR-T)
  • Truthup docs passlib/AGENTS.md staleness fixed; docs/reference/storage-paths.md deriveProjectKey typo corrected; CHANGELOG drift analysis deferred (AUDIT-H8 / M32 / L04) (PR-Q)
  • Phase 1 regression suite — locked in audit invariants (PKCE S256, state entropy, SSE failover) (AUDIT-L01 / M03 partial) (PR-S)
  • Master audit reportdocs/audits/MASTER_AUDIT.md + docs/audits/evidence/findings-index.json published (PR #393)

Config Changes

  • NEW: PluginConfig.routingMutex: "enabled" | "legacy" — default "legacy". Env override: CODEX_AUTH_ROUTING_MUTEX. Recommended flip to "enabled" default in v1.4.0 after one release cycle of opt-in use.

Known Deferred (Phase 1.5 / Phase 2)

Per .sisyphus/notepads/phase1-implementation/f1-defer-notes.md, the following audit findings have explicit defer rationale and are tracked for a follow-up "Audit follow-up" ticket:

  • MEDIUM (11): M07 (tracker persistence), M10 (stream failover policy), M11 (callback graceful close), M12 (JWT exp decode), M15 (manual-paste UX), M17 (observability envelope), M26 (--json coverage audit), M27 (codex-cli vs codex-manager boundary docs), M28 (experimental stability policy), M29 (error taxonomy), M33 (semver verification — THIS release)
  • LOW (11): L02, L03, L05, L06, L07, L08, L09, L10, L12, L13, L14 — batch-deferred to single janitorial PR

Post-Audit Remediation Commits

After the 20 PRs landed, a full 7-risk-category audit was run against every PR. Findings: 0 CRITICAL, 13 HIGH (all addressed), 31 MEDIUM (report-only per tier policy), 29 LOW. Per-PR JSON reports at .sisyphus/notepads/phase1-audit/reports/pr###.json. Triage: .sisyphus/notepads/phase1-audit/TRIAGE-SUMMARY.md.

The following 7 fix commits were pushed on top of the original PR heads to close the HIGH findings:

PR Fix commit Addressed
#412 21c466a Property tests now use external concurrency observer (proves mutex actually serializes)
#401 f877c85 Completed atomic write migration (injectTextPart, prependThinkingPart) + renameSync retry on EBUSY/EPERM
#410 b3c2945 verify --paths sandbox probe hardened against cwd=/ edge case + new commands documented
#399 d7af34d All-disabled dangle + cursorByFamily divergence + 3 edge-case regression tests
#396 f18d721 lib/ui/copy.ts routed through AUTH_REDIRECT SSOT
#396 475ea37 Added AUTH_REDIRECT to codex-manager-cli test mock (follow-up to f18d721)
#406 d9f7253 Dual-linter docs corrected to match actual wiring (ESLint-only in lint-staged; Biome manual; CI enforcement confirmed in ci.yml + pr-ci.yml)

Residual Known Deferred

  • Pre-existing removeAccount dangle (lib/accounts/pointer.ts): when the active account is removed and it was the last in its family array, the pointer is set to -1 instead of falling back to another remaining account in that family. Out of scope for PR #399 per tier policy (pre-existing). Follow-up PR #413 closes this specific case with its own regression tests.

Validation

  • npm test — 3527 tests pass (was 3345, +182)
  • npm run typecheck — exit 0
  • npm run lint — exit 0
  • npm run audit:ci — 0 vulnerabilities
  • npm run pack:check — 822KB / 968 files (under budget)
  • npm run vendor:verify — 2 components / 8 files verified
  • npm run clean:repo:check — green
  • npm run build — exit 0

Semver Verification (AUDIT-M33)

Commit range v1.2.4..v1.3.0 audited for silent breaking changes:

  • v1.2.4 → v1.2.5: observability wording clarifications — docs only
  • v1.2.5 → v1.2.6: forwarded observability fix — patch-appropriate
  • v1.2.6 → v1.2.7: native Codex CLI install support — wrapper additive, no removal
  • v1.2.7 → v1.3.0: Phase 1 post-audit — MINOR appropriate:
    • New public surface: codex auth why-selected, codex auth verify commands
    • New opt-in flag: routingMutex (default legacy = zero behavior change)
    • New types exported: SelectionRecord, HybridSelectionCandidateTrace, HybridSelectionTraceResult, FlaggedAccountStorageV1Schema, AccountsJournalEntrySchema
    • No removed exports, no changed function signatures, no changed storage format
    • verify-flagged preserved as alias (no breaking removal)

Conclusion: minor bump is correct; no major bump justified.

Related

  • Audit report: docs/audits/MASTER_AUDIT.md
  • Audit findings index: docs/audits/evidence/findings-index.json
  • Previous release notes: docs/releases/v1.2.7.md

PR Index

PR # Branch Title
#393 docs/master-repository-audit-2026-04-17 docs(audit): add master repository audit report and evidence
#394 fix/phase1-tests-green-and-resolvepath fix(phase1): reject resolvePath lookalike-prefix paths + restore auth list reset message
#395 fix/oauth-url-redaction fix(auth): redact OAuth URL in user-facing login output
#396 refactor/redirect-uri-ssot refactor(auth): introduce AUTH_REDIRECT single source of truth
#397 fix/hybrid-selector-null-contract fix(routing): hybrid selector returns null when no accounts are available
#398 fix/short-429-race fix(routing): mark account unavailable before short-429 retry sleep
#399 fix/active-pointer-normalization fix(accounts): normalize active pointer when the active account is disabled
#400 fix/release-hygiene fix(release): pack:check builds first + tests use os.tmpdir
#401 fix/recovery-atomic-writes fix(recovery): atomic writes + retry-safe deletes for recovery storage (R6)
#402 fix/storage-clear-ordering fix(storage): write reset marker before deletions + retry EPERM on read
#403 fix/project-scope-no-silent-bypass fix(routing): surface the per-project vs CLI-sync config conflict
#404 fix/request-observability fix(request): surface malformed SSE JSON chunks as structured warnings
#405 docs/truthup docs: truthup AGENTS.md staleness + deriveProjectKey typo
#406 chore/config-hygiene chore(config): document dual-linter scope + husky prepare-hook side effect
#407 test/audit-regression-suite test(audit): add Phase 1 regression suite locking in audit invariants
#408 refactor/health-unify docs(health): document field-name drift vs ManagedAccount (AUDIT-M08)
#409 refactor/zod-storage-boundaries refactor(types): add Zod safeParseJson at storage JSON boundaries
#410 feat/cli-why-selected-and-verify-paths feat(cli): add codex auth why-selected and verify --paths commands
#411 refactor/settings-hub-split refactor(codex-manager): split settings-hub.ts into 5 sub-concern files
#412 refactor/routing-mutex refactor(routing): add feature-flagged routing mutex and SelectionRecord
#413 fix/active-pointer-followup fix(accounts): resolve residual removeAccount dangle (follow-up to #399)