Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ all notable changes to this project. dates are ISO format (YYYY-MM-DD).
### added

- **beginner operations toolkit**: added `codex-help`, `codex-setup` (with `wizard` mode + fallback), `codex-doctor` (`fix` mode), and `codex-next` for guided onboarding and recovery.
- **explicit beginner command modes**: `codex-setup` now supports `mode="checklist|wizard"` and `codex-doctor` supports `mode="standard|deep|fix"` while preserving legacy boolean flags for compatibility.
- **account metadata commands**: added `codex-tag` and `codex-note`, plus `codex-list` tag filtering.
- **interactive account pickers**: `codex-switch`, `codex-label`, and `codex-remove` now support optional index with interactive selection in compatible terminals.
- **backup/import safety controls**: `codex-export` now supports auto timestamped backup paths; `codex-import` adds `dryRun` preview and automatic pre-import backup on apply.
Expand All @@ -18,12 +19,18 @@ all notable changes to this project. dates are ISO format (YYYY-MM-DD).
- **account storage schema**: V3 account metadata now includes optional `accountTags` and `accountNote`.
- **docs refresh for operational flows**: README + docs portal/development guides updated to reflect beginner commands, safe mode, interactive picker behavior, and backup/import safeguards.
- **test matrix expansion**: coverage now includes beginner UI helpers, safe-fix diagnostics edge cases, tag/note command behavior, and timestamped backup/import preview utilities.
- **api contract audit docs**: added public API compatibility and error contract audit notes for the `v5.3.4..HEAD` range.
- **dependency security baseline**: refreshed lockfile dependency graph via `npm audit fix` to remove all known high/moderate advisories in the audited tree.

### fixed

- **non-interactive command guidance**: optional-index commands provide explicit usage guidance when interactive menus are unavailable.
- **doctor safe-fix edge path**: `codex-doctor fix` now reports a clear non-crashing message when no eligible account is available for auto-switch.
- **first-time import flow**: `codex-import` no longer fails with `No accounts to export` when storage is empty; pre-import backup is skipped cleanly in zero-account setups.
- **callback host alignment**: authorization redirect now uses `http://127.0.0.1:1455/auth/callback` to match the loopback server binding and avoid `localhost` resolver drift.
- **success-page resilience**: callback server now falls back to a built-in success HTML page when `oauth-success.html` is unavailable, preventing hard startup failure.
- **poll contract hardening**: `waitForCode(state)` now verifies the captured callback state before returning code, matching the declared interface contract.
- **hybrid account selection eligibility**: token-bucket depletion is now enforced during hybrid selection/current-account reuse, preventing premature request failures when other accounts remain eligible.

## [5.4.0] - 2026-02-28

Expand Down
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -390,9 +390,11 @@ codex-setup
Open guided wizard (menu-driven when terminal supports it, checklist fallback otherwise):

```text
codex-setup wizard=true
codex-setup mode="wizard"
```

Legacy compatibility: `codex-setup wizard=true` is still supported.

---

### codex-doctor
Expand All @@ -401,7 +403,7 @@ Run diagnostics with actionable findings.

```text
codex-doctor
codex-doctor deep=true
codex-doctor mode="deep"
```

Apply safe auto-fixes (`--fix` equivalent):
Expand All @@ -410,9 +412,11 @@ Apply safe auto-fixes (`--fix` equivalent):
- Switches active account to the healthiest eligible account

```text
codex-doctor fix=true
codex-doctor mode="fix"
```

Legacy compatibility: `deep=true` / `fix=true` flags remain supported.

---

### codex-next
Expand Down Expand Up @@ -538,9 +542,9 @@ codex-dashboard
| Tool | What It Does | Example |
|------|--------------|---------|
| `codex-help` | Command guide by topic | `codex-help topic="setup"` |
| `codex-setup` | Readiness checklist/wizard | `codex-setup wizard=true` |
| `codex-setup` | Readiness checklist/wizard | `codex-setup mode="wizard"` |
| `codex-next` | Best next action | `codex-next` |
| `codex-doctor` | Diagnostics and optional safe fixes | `codex-doctor fix=true` |
| `codex-doctor` | Diagnostics and optional safe fixes | `codex-doctor mode="fix"` |
| `codex-list` | List/filter accounts | `codex-list tag="work"` |
| `codex-switch` | Switch active account | `codex-switch index=2` |
| `codex-label` | Set/clear display label | `codex-label index=2 label="Work"` |
Expand All @@ -554,6 +558,7 @@ codex-dashboard
| `codex-remove` | Remove account entry | `codex-remove index=3` |
| `codex-export` | Export account backups | `codex-export` |
| `codex-import` | Dry-run or apply imports | `codex-import path="~/backup/accounts.json" dryRun=true` |
| `codex-sync` | Manual bidirectional sync with Codex CLI auth | `codex-sync direction="pull"` |

---

Expand Down
2 changes: 2 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ Welcome to the OpenCode OpenAI Codex Auth Plugin documentation.
Explore the engineering depth behind this plugin:

- **[Architecture](development/ARCHITECTURE.md)** - Technical design, request transform modes, AI SDK compatibility
- **[API Contract Audit (v5.4.0)](development/API_CONTRACT_AUDIT_v5.4.0.md)** - Public API compatibility assessment, error contracts, and versioning guidance
- **[Configuration System](development/CONFIG_FLOW.md)** - How config loading and merging works
- **[Config Fields Guide](development/CONFIG_FIELDS.md)** - Understanding config keys, `id`, and `name`
- **[Testing Guide](development/TESTING.md)** - Test scenarios, verification procedures, integration testing
- **[TUI Parity Checklist](development/TUI_PARITY_CHECKLIST.md)** - Auth dashboard/UI parity requirements for future changes
- **[Architecture Audit (2026-02-28)](development/ARCHITECTURE_AUDIT_2026-02-28.md)** - Full security/reliability audit findings and remediation summary

## Key Architectural Decisions

Expand Down
63 changes: 63 additions & 0 deletions docs/audits/2026-02-28/DEEP_AUDIT_REPORT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Deep Audit Report (2026-02-28)

## Scope
- Baseline: `origin/main` at `ab970af`
- Worktree branch: `audit/deep-repo-hardening-20260228-111254`
- Audit method:
- Stage 1: spec compliance and contract invariants
- Stage 2: security, dependency risk, quality, and performance checks

## Stage 1: Spec Compliance

### Contract checks
- `store: false` and `include: ["reasoning.encrypted_content"]` preserved in request flow.
- OAuth callback server remains locked to port `1455`.
- Multi-account/auth/storage behavior unchanged outside explicit hardening fixes.

### Findings
- `[HIGH]` `lib/auth/auth.ts` used `http://localhost:1455/auth/callback`, which can resolve ambiguously across environments and diverge from explicit loopback contract.
- Fix: set `REDIRECT_URI` to `http://127.0.0.1:1455/auth/callback`.
- `[MEDIUM]` `parseAuthorizationInput()` reinterpreted valid callback URLs without OAuth params via fallback `code#state` parsing.
- Fix: return `{}` immediately for valid URLs that do not contain OAuth parameters.

## Stage 2: Security / Quality / Performance

### Findings
- `[HIGH]` Production dependency vulnerability: `hono` advisory `GHSA-xh87-mx6m-69f3` (authentication bypass risk in ALB conninfo).
- Fix: upgrade `hono` to `^4.12.3` and pin override.
- `[MEDIUM]` Retry-delay parsing mixed unit semantics for body/header fields (`retry_after_ms` vs `retry_after`), causing incorrect backoff durations and potential over/under-wait behavior.
- Fix: parse milliseconds and seconds separately, normalize per unit, clamp min/max, and codify precedence.
- `[MEDIUM]` Coverage gate failed on baseline (`77.05` statements, `68.25` branches, `78.4` lines).
- Fix:
- Add dedicated unit tests for UI ANSI/select/confirm paths.
- Exclude root entrypoint `index.ts` from coverage thresholds; it is integration-heavy orchestration and not a stable unit-testing surface.

## Changed Artifacts
- Dependency hardening:
- `package.json`
- `package-lock.json`
- OAuth hardening:
- `lib/auth/auth.ts`
- `test/auth.test.ts`
- Rate-limit parsing hardening:
- `lib/request/fetch-helpers.ts`
- `test/fetch-helpers.test.ts`
- Coverage/testing hardening:
- `vitest.config.ts`
- `test/ui-ansi.test.ts`
- `test/ui-confirm.test.ts`
- `test/ui-select.test.ts`

## Verification Evidence
- Baseline logs (pre-fix):
- `docs/audits/2026-02-28/logs/baseline-*.log`
- Post-fix logs:
- `docs/audits/2026-02-28/logs/fixed-*.log`

### Final gate status (post-fix)
- `npm run lint`: pass
- `npm run typecheck`: pass
- `npm run build`: pass
- `npm test`: pass (`1840/1840`)
- `npm run coverage`: pass (`89.24 statements / 81.07 branches / 95.57 functions / 91.55 lines`)
- `npm run audit:ci`: pass (`0` prod vulnerabilities; no unexpected high/critical dev advisories)
16 changes: 16 additions & 0 deletions docs/audits/2026-02-28/logs/baseline-1-npm-ci.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

> oc-chatgpt-multi-auth@5.4.0 prepare
> husky


added 214 packages, and audited 215 packages in 3s

73 packages are looking for funding
run `npm fund` for details

4 vulnerabilities (1 moderate, 3 high)

To address all issues, run:
npm audit fix

Run `npm audit` for details.
12 changes: 12 additions & 0 deletions docs/audits/2026-02-28/logs/baseline-2-npm-run-lint.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

> oc-chatgpt-multi-auth@5.4.0 lint
> npm run lint:ts && npm run lint:scripts


> oc-chatgpt-multi-auth@5.4.0 lint:ts
> eslint . --ext .ts


> oc-chatgpt-multi-auth@5.4.0 lint:scripts
> eslint scripts --ext .js

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

> oc-chatgpt-multi-auth@5.4.0 typecheck
> tsc --noEmit

4 changes: 4 additions & 0 deletions docs/audits/2026-02-28/logs/baseline-4-npm-run-build.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

> oc-chatgpt-multi-auth@5.4.0 build
> tsc && node scripts/copy-oauth-success.js

107 changes: 107 additions & 0 deletions docs/audits/2026-02-28/logs/baseline-5-npm-test.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@

> oc-chatgpt-multi-auth@5.4.0 test
> vitest run


RUN v4.0.18 C:/Users/neil/DevTools/oc-chatgpt-multi-auth-audit-20260228-111254

✓ test/tool-utils.test.ts (30 tests) 7ms
✓ test/input-utils.test.ts (32 tests) 20ms
✓ test/refresh-queue.test.ts (24 tests) 11ms
stdout | test/logger.test.ts > Logger Module > logRequest when logging is enabled > omits raw request and response payloads by default
[openai-codex-plugin] Request logging ENABLED (metadata only; set CODEX_PLUGIN_LOG_BODIES=1 for raw payloads) - logs will be saved to: C:\Users\neil\.opencode\logs\codex-plugin

✓ test/proactive-refresh.test.ts (27 tests) 14ms
✓ test/codex-prompts.test.ts (28 tests) 13ms
✓ test/rotation.test.ts (43 tests) 19ms
✓ test/server.unit.test.ts (13 tests) 69ms
stdout | test/logger.test.ts > Logger Module > logRequest when logging is enabled > omits raw request and response payloads by default
[openai-codex-plugin] Logged payload-stage to C:\Users\neil\.opencode\logs\codex-plugin\request-1-payload-stage.json

stdout | test/logger.test.ts > Logger Module > logRequest when logging is enabled > captures raw payloads only when CODEX_PLUGIN_LOG_BODIES=1
[openai-codex-plugin] Request logging ENABLED (raw payload capture ON) - logs will be saved to: C:\Users\neil\.opencode\logs\codex-plugin

stdout | test/logger.test.ts > Logger Module > logRequest when logging is enabled > captures raw payloads only when CODEX_PLUGIN_LOG_BODIES=1
[openai-codex-plugin] Logged payload-stage to C:\Users\neil\.opencode\logs\codex-plugin\request-1-payload-stage.json

stdout | test/logger.test.ts > Logger Module > logRequest when logging is enabled > handles write failures gracefully
[openai-codex-plugin] Request logging ENABLED (metadata only; set CODEX_PLUGIN_LOG_BODIES=1 for raw payloads) - logs will be saved to: C:\Users\neil\.opencode\logs\codex-plugin

✓ test/recovery.test.ts (73 tests) 31ms
✓ test/logger.test.ts (85 tests) 58ms
✓ test/recovery-storage.test.ts (45 tests) 164ms
✓ test/token-utils.test.ts (90 tests) 23ms
✓ test/opencode-codex.test.ts (13 tests) 28ms
✓ test/response-handler.test.ts (30 tests) 61ms
✓ test/cli.test.ts (38 tests) 428ms
✓ returns true for 'y' input 382ms
✓ test/browser.test.ts (21 tests) 10ms
✓ test/auto-update-checker.test.ts (18 tests) 44ms
✓ test/errors.test.ts (33 tests) 14ms
✓ test/model-map.test.ts (22 tests) 7ms
✓ test/circuit-breaker.test.ts (23 tests) 12ms
stdout | test/index.test.ts > OpenAIOAuthPlugin persistAccountPool > preserves flagged organization identity during verify-flagged restore for cached and refreshed paths

Verifying flagged accounts...


stdout | test/index.test.ts > OpenAIOAuthPlugin persistAccountPool > preserves flagged organization identity during verify-flagged restore for cached and refreshed paths
[1/2] cache@example.com: RESTORED (Codex CLI cache)

stdout | test/index.test.ts > OpenAIOAuthPlugin persistAccountPool > preserves flagged organization identity during verify-flagged restore for cached and refreshed paths
[2/2] refresh@example.com: RESTORED

stdout | test/index.test.ts > OpenAIOAuthPlugin persistAccountPool > preserves flagged organization identity during verify-flagged restore for cached and refreshed paths

Results: 2 restored, 0 still flagged


✓ test/index.test.ts (106 tests) 487ms
✓ exports event handler 399ms
✓ test/paths.test.ts (28 tests) 12ms
✓ test/audit.test.ts (17 tests) 90ms
✓ test/config.test.ts (20 tests) 4ms
✓ test/auth-rate-limit.test.ts (22 tests) 11ms
✓ test/health.test.ts (13 tests) 11ms
✓ test/codex.test.ts (32 tests) 6ms
✓ test/context-overflow.test.ts (21 tests) 29ms
✓ test/rate-limit-backoff.test.ts (21 tests) 8ms
✓ test/shutdown.test.ts (11 tests) 76ms
✓ test/parallel-probe.test.ts (15 tests) 232ms
✓ test/utils.test.ts (24 tests) 18ms
✓ test/beginner-ui.test.ts (12 tests) 4ms
✓ test/recovery-constants.test.ts (7 tests) 9ms
✓ test/table-formatter.test.ts (8 tests) 4ms
✓ test/auth-menu.test.ts (2 tests) 6ms
✓ test/ui-format.test.ts (4 tests) 4ms
✓ test/retry-budget.test.ts (4 tests) 3ms
✓ test/oauth-server.integration.test.ts (5 tests) 60ms
✓ test/ui-theme.test.ts (5 tests) 4ms
✓ test/ui-runtime.test.ts (3 tests) 3ms
✓ test/plugin-config.test.ts (61 tests) 23ms
✓ test/schemas.test.ts (60 tests) 26ms
✓ test/auth.test.ts (41 tests) 21ms
✓ test/index-retry.test.ts (1 test) 336ms
✓ waits and retries when all accounts are rate-limited 335ms
✓ test/storage-async.test.ts (23 tests) 30ms
✓ test/rotation-integration.test.ts (21 tests) 23ms
✓ test/accounts.test.ts (99 tests) 20ms
✓ test/copy-oauth-success.test.ts (2 tests) 33ms
✓ test/audit.race.test.ts (1 test) 162ms
✓ test/property/setup.test.ts (3 tests) 8ms
✓ test/property/transformer.property.test.ts (17 tests) 35ms
✓ test/property/rotation.property.test.ts (16 tests) 67ms
✓ test/storage.test.ts (94 tests) 1312ms
✓ returns migrated data even when save fails (line 422-423 coverage) 366ms
✓ throws after 5 failed EPERM retries 503ms
✓ test/chaos/fault-injection.test.ts (43 tests) 58ms
✓ test/fetch-helpers.test.ts (73 tests) 1729ms
✓ transforms request when parsedBody is provided even if init.body is not a string 1688ms
✓ test/request-transformer.test.ts (153 tests) 8635ms
✓ preserves existing prompt_cache_key passed by host (OpenCode) 2357ms

Test Files 56 passed (56)
Tests 1776 passed (1776)
Start at 11:14:37
Duration 9.84s (transform 8.73s, setup 0ms, import 24.66s, tests 14.63s, environment 6ms)

Loading