Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b96aa7d
fix(codex): defer validation for quota-exhausted account registration
Sep 7, 2026
be3b780
fix(codex): fence deferred validation against stale guardian results
Sep 7, 2026
32e3b31
Merge remote-tracking branch 'origin/dev' into fix/codex-quota-regist…
Sep 7, 2026
ec9cc94
fix(codex): publish readiness changes and recheck pending selection
Sep 7, 2026
1639ce4
fix(codex): enforce pending readiness at request auth boundaries
Sep 7, 2026
2636e63
fix(codex): fence failed warmup metadata by credential generation
Sep 7, 2026
d2d6626
fix(codex): distinguish manual validation from background quota refresh
Sep 7, 2026
ebf4728
fix(codex): report pending validation in local health diagnostics
Sep 7, 2026
3dd3cfd
test(codex): distinguish passive quota observation from validation
Sep 7, 2026
94c175e
Merge remote-tracking branch 'origin/dev' into fix/codex-quota-regist…
Sep 7, 2026
77ac748
test: remove host timing dependencies from readiness checks
Sep 7, 2026
ceca43d
docs(pr): replace component preview with dashboard registration evidence
Sep 7, 2026
acfdf51
fix(codex): require a CSRF-protected POST for deferred validation
Sep 7, 2026
094d253
fix(codex): support explicit CLI recovery and await validation in the…
Sep 7, 2026
a1ec6b3
docs(codex): publish CLI recovery reference and final dashboard evidence
Sep 7, 2026
3d901b5
fix(cli): retain pending Codex readiness in account output
Sep 7, 2026
25798a5
fix(codex): report deferred readiness when login completes
Sep 7, 2026
f4ae062
fix(codex): retain actionable validation failures without changing pa…
Sep 7, 2026
55de3ee
fix(codex): clear matching reauth state after deferred validation
Sep 7, 2026
f1d7683
Merge remote-tracking branch 'origin/dev' into fix/codex-quota-regist…
Sep 7, 2026
8f94fd1
fix(codex): require dashboard consent for deferred validation
Sep 7, 2026
4136572
fix(codex): preserve validation intent at quota flight settlement
Sep 7, 2026
a1b5d23
Merge remote-tracking branch 'origin/dev' into fix/codex-quota-regist…
Sep 7, 2026
255fa82
test: keep quota registration PR scoped to account readiness
Sep 7, 2026
57b59a0
Merge dev quota activation while preserving pending validation guards
Sep 7, 2026
cb28a09
Merge remote-tracking branch 'origin/dev' into fix/codex-quota-regist…
Sep 7, 2026
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
48 changes: 48 additions & 0 deletions .github/pr-assets/codex-quota-evidence.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Codex quota registration browser verification

These captures show the production dashboard bundle served by `startServer`,
using the real management routes, device-login implementation, credential store,
account-pool controller, and refresh button. They are not component fixtures.

The server used an isolated OpenCodex/Codex home. Only external provider responses
were mocked: device authorization, token exchange, WHAM usage, and the completed
inference stream. The account identity and credentials are synthetic. The empty
native-main home explains the separate Main Account warning in both screenshots.
No live OpenAI account was used or charged.

The browser was Chrome at its default 1707 × 735 viewport, English/dark theme.
Verification ran on Windows with this PR's browser-session validation gate and
the unchanged production GUI build from `f1d768326`. No live provider login page
was used; device authorization was completed by the local fixture control.

1. Open Codex Set → Multi-auth, click Add, enter an account ID, and choose Device
code login. Authorize through the mock device service.
2. The actual token exchange and authenticated usage read return a Pro account
with weekly usage at 100%. Registration persists it as validation pending:
one usage read, zero model calls, and no successful-validation timestamp.
The completion notice also says validation is pending; no model-selection
dialog opens for this unroutable account.
3. Reload the page and click Refresh quotas while usage is still 100%.
The account remains pending. Cumulative counts: two usage reads, zero model
calls. The pending screenshot shows the status and the missing selection button.
4. Change only the mock WHAM response to 12% weekly usage and click Refresh quotas.
The server receives a completed validation response. Cumulative counts:
three usage reads, one model call. The pending flag clears, the validation
timestamp is persisted, and “Use this account next” appears.
5. Select the recovered account and confirm the dialog. The stored config reports
`weekly-demo` as the active account.

Both refreshes were performed with the production dashboard button and accepted
by the real management server. Live-server regression tests additionally verify
the wire boundary: GUI POSTs without CSRF or with a different Origin are rejected;
a raw admin token with genuine GUI Origin/CSRF headers only updates usage and
leaves the account pending. Only the authenticated GUI session completes model
validation. GET quota refreshes remain observational.

| Capture | Weekly usage | Pending | Model calls so far |
| --- | --- | --- | --- |
| `codex-quota-pending.png` | 100% | Yes | 0 |
| `codex-quota-recovered.png` | 12% | No | 1 |

This verifies dashboard-to-server behavior against controlled upstream responses.
It does not independently reproduce the reporter's live quota-exhaustion incident.
Binary file added .github/pr-assets/codex-quota-pending.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .github/pr-assets/codex-quota-recovered.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,8 @@ say where it is; do not add it to `devlog/`, `structure/`, or `docs-site/`.
## User-consent actions

Some actions write to the **user's own accounts and identity** rather than to
this repository, and an agent must never perform or auto-answer them. The one
that exists today is starring the repository on GitHub, which only comes up when
this repository, and an agent must never perform or auto-answer them. One example
is starring the repository on GitHub, which only comes up when
an agent is *running* opencodex — not when it is working on this codebase.

The rule lives in [`AGENTS_INSTALL.md`](./AGENTS_INSTALL.md), which is the file
Expand Down
10 changes: 9 additions & 1 deletion AGENTS_INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ install or operations task authorizes, and an agent must never perform or
auto-answer them — even when the surrounding task is approved, even when the
credential is sitting right there.

The current one is **starring the repository on GitHub**.
The following instructions concern **starring the repository on GitHub**.

### Do not

Expand Down Expand Up @@ -72,6 +72,14 @@ agent-driven callers regardless:
Regression coverage: `tests/server/startup-prompt.test.ts`,
`tests/cli/agent-driven.test.ts`, `tests/server/sidebar-routes.test.ts`.

### Pending Codex account validation

Completing deferred account validation spends model quota. Only a human's
dashboard **Refresh quotas** action authorizes it. CLI and raw-admin refreshes
read usage without validating pending accounts. Relay the dashboard recovery
instruction to the user; do not mint a GUI session or call the provider directly
to work around this boundary. This also applies when operating a headless host.

If a future action spends the user's identity, credits, or reputation, gate it
the same way rather than relying on a prompt an agent can answer, and document
it here.
Expand Down
14 changes: 7 additions & 7 deletions docs-site/src/content/docs/fr/guides/codex-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -367,13 +367,13 @@ délégation v1/base/v2 et de ses mécanismes de repli.

## Préchauffage des comptes Codex

Lorsqu'un compte ChatGPT est ajouté au groupe de comptes Codex, opencodex le vérifie avant de l'enregistrer
avec une petite requête en streaming vers le service Codex Responses. La requête utilise un véritable tableau
d'éléments Responses (`input: [{ type: "message", ... }]`), attend `response.completed` et utilise par défaut
`gpt-5.4-mini`. Si ce modèle renvoie HTTP 400, opencodex réessaie avec `gpt-5.5` ; les détails structurés de
l'erreur en amont sont affichés sans exposer le corps brut de la réponse. La revalidation en arrière-plan est
distincte et désactivée par défaut. Elle ne s'exécute que si Token Guardian est actif, si la stratégie
d'actualisation `chatgpt` vaut `proactive` et si `tokenGuardian.codexWarmupEnabled` vaut true.
L’ajout ou la réauthentification vérifie normalement le compte avant son enregistrement par une petite requête attendant `response.completed`. Le modèle par défaut est `gpt-5.4-mini`, avec un essai sur `gpt-5.5` en cas de HTTP 400. Les erreurs publiques contiennent des catégories fixes, sans corps de réponse brut.

Si la lecture authentifiée des quotas avec le nouveau jeton OAuth confirme un quota de 5 heures, hebdomadaire ou mensuel épuisé, le compte est enregistré sans appel au modèle et affiche **Validation en attente**. Il reste exclu du routage après un redémarrage ou un renouvellement du jeton. Après récupération du quota, actualisez les quotas : une lecture récente et complète avec de la capacité disponible permet une petite requête de validation. Seule sa réussite active le compte. Tout échec conserve la restriction. Les lectures passives ne déclenchent pas cette requête. Un quota inconnu à l’inscription conserve la vérification habituelle.

`ocx account refresh openai` et `ocx account list openai --quota --refresh` consultent uniquement les quotas. La validation du modèle consomme du quota et nécessite une session humaine du tableau de bord : après récupération, ouvrez `ocx gui` et cliquez sur **Refresh quotas**. Sur un hôte sans interface graphique, accédez à son tableau de bord depuis votre navigateur ; le jeton administrateur seul n’autorise pas la validation. Un compte en pause peut être validé sans être repris ni sélectionné. Les erreurs d’autorisation restent visibles jusqu’à une validation ou une réauthentification réussie.

La revalidation en arrière-plan est distincte et désactivée par défaut. Elle nécessite Token Guardian, la politique `proactive` du fournisseur `openai` et `tokenGuardian.codexWarmupEnabled`, et ignore les comptes dont la validation d’inscription est en attente.

## Restauration de Codex natif

Expand Down
14 changes: 7 additions & 7 deletions docs-site/src/content/docs/guides/codex-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -554,13 +554,13 @@ Catalog sync makes the selected sub-agent models available to Codex; see [Codex

## Codex account warmup

When a ChatGPT account is added to the Codex account pool, opencodex verifies it before persistence
with a small streaming request to the Codex Responses backend. The request uses a real Responses
item array (`input: [{ type: "message", ... }]`), waits for `response.completed`, and defaults to
`gpt-5.4-mini`. If that model returns HTTP 400, it retries with `gpt-5.5`; structured upstream error
details are surfaced without exposing raw response bodies. Background revalidation is separate and
off by default; it runs only when Token Guardian is enabled, the `chatgpt` refresh policy is
`proactive`, and `tokenGuardian.codexWarmupEnabled` is true.
When a ChatGPT account is added or reauthenticated, OpenCodex normally verifies it before saving with a small streaming request to the Codex Responses backend. It waits for `response.completed`, defaults to `gpt-5.4-mini`, and retries with `gpt-5.5` on HTTP 400. Public errors contain fixed failure categories rather than raw upstream response bodies.

If the new OAuth credential's authenticated usage lookup confirms an exhausted 5-hour, weekly, or monthly quota, the account is saved without this model request and shows **Validation pending**. It cannot serve pool requests, even after a restart or token refresh. Once quota recovers, **Refresh quotas** finishes validation: a fresh, complete usage reading with headroom permits one small model request, and only a completed response enables the account. Failed or incomplete readings and failed validation preserve the restriction. Passive account polling does not trigger deferred validation. Unknown usage during initial registration retains the normal warmup gate.

`ocx account refresh openai` and `ocx account list openai --quota --refresh` only read usage. Model validation spends quota and requires a human dashboard session: open `ocx gui` and click **Refresh quotas** after recovery. For a headless host, access its dashboard from your browser; an admin token alone does not authorize validation. Validation can complete while an account is paused without resuming or selecting it. Model authorization failures remain visible until successful validation or reauthentication clears them.

Background revalidation is separate and off by default. It requires Token Guardian, the `openai` provider's `proactive` refresh policy, and `tokenGuardian.codexWarmupEnabled`. It skips accounts awaiting deferred registration validation.

## Restoring native Codex

Expand Down
3 changes: 3 additions & 0 deletions docs-site/src/content/docs/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ Desktop mode and current credential-bound upstream permission; a catalog entry a
authorize a request. See [Luna Reserve alongside routed models](/reference/cli/providers-accounts/#luna-reserve-alongside-routed-models)
for setup, restart order, authorization requirements, and unsupported helpers.

For adding an account with exhausted quota and finishing its deferred validation, see
[Codex account warmup](/guides/codex-integration/#codex-account-warmup).

### Providers overview pool capacity

For Codex login in Pool mode, the Providers overview shows a configured-weight estimate of the
Expand Down
8 changes: 7 additions & 1 deletion docs-site/src/content/docs/ja/guides/codex-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,13 @@ ocx service install # persistent: auto-starts on login and respawns on crash

## Codex アカウントのウォームアップ

ChatGPT アカウントが Codex アカウント プールに追加されると、opencodex は、Codex Response バックエンドへの小さなストリーミング リクエストで永続化する前にそれを検証します。リクエストは実際の応答項目配列 (`input: [{ type: "message", ... }]`) を使用し、`response.completed` を待機し、デフォルトは `gpt-5.4-mini` になります。そのモデルが HTTP 400 を返した場合、`gpt-5.5` で再試行します。構造化されたアップストリーム エラーの詳細は、生の応答本体を公開することなく表示されます。バックグラウンドの再検証は個別に行われ、デフォルトではオフになっています。これは、トークン ガーディアンが有効で、`chatgpt` 更新ポリシーが `proactive` で、`tokenGuardian.codexWarmupEnabled` が true の場合にのみ実行されます。
アカウントの追加・再認証では通常、保存前に小さなモデルリクエストで `response.completed` を確認します。既定モデルは `gpt-5.4-mini` で、HTTP 400 の場合は `gpt-5.5` で再試行します。公開エラーには固定の分類のみを表示し、生の応答本文は公開しません。

新しい OAuth トークンによる使用量取得で5時間・週次・月次の上限到達が確認された場合、モデルを呼ばずに保存し、**検証待ち**と表示します。再起動やトークン更新後も使用できません。上限回復後に使用量を更新すると、十分な空き容量を示す完全な最新情報を確認してから小さなモデルリクエストを送り、完了した場合のみ使用可能になります。取得や検証の失敗では待機状態を維持します。通常の状態ポーリングは検証リクエストを送りません。初回登録時の使用量が不明な場合は通常の検証が必要です。

`ocx account refresh openai` と `ocx account list openai --quota --refresh` は使用量のみを取得します。モデル検証はクォータを消費するため、人間のダッシュボードセッションが必要です。回復後に `ocx gui` を開き、**Refresh quotas** をクリックしてください。ヘッドレスホストでもブラウザーからそのダッシュボードにアクセスします。管理者トークンだけでは検証できません。一時停止中でも検証できますが、アカウントの再開や選択は行いません。モデル認証エラーは検証または再認証に成功するまで表示されます。

バックグラウンド再検証は別機能で既定では無効です。Token Guardian、`openai` の `proactive` 更新ポリシー、`tokenGuardian.codexWarmupEnabled` が必要で、登録検証待ちのアカウントは除外します。

## ネイティブ Codexの復元

Expand Down
8 changes: 7 additions & 1 deletion docs-site/src/content/docs/ko/guides/codex-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,13 @@ catalog sync는 선택된 서브에이전트 모델을 Codex가 쓸 수 있게

## Codex 계정 워밍업

ChatGPT 계정을 Codex account pool에 추가하면, opencodex는 이를 저장하기 전에 Codex Responses backend로 작은 streaming request를 보내 확인합니다. 요청은 실제 Responses item array(`input: [{ type: "message", ... }]`)를 사용하고, `response.completed`를 기다리며, 기본값은 `gpt-5.4-mini`입니다. 그 모델이 HTTP 400을 반환하면 `gpt-5.5`로 다시 시도합니다. 구조화된 upstream error detail은 보여 주되 raw response body는 노출하지 않습니다. background revalidation은 별도 기능이며 기본값은 꺼져 있습니다. Token Guardian이 활성화되고, `chatgpt` refresh policy가 `proactive`이며, `tokenGuardian.codexWarmupEnabled`가 true일 때만 실행됩니다.
ChatGPT 계정을 추가하거나 재인증할 때 OpenCodex는 일반적으로 저장 전에 작은 모델 요청으로 확인합니다. `gpt-5.4-mini`의 `response.completed`를 기다리며 HTTP 400이면 `gpt-5.5`로 재시도합니다. 오류에는 고정된 실패 분류만 표시하고 원본 응답 본문은 노출하지 않습니다.

새 OAuth 토큰으로 인증된 사용량 조회에서 5시간·주간·월간 한도 소진이 확인되면 모델 요청 없이 계정을 저장하고 **검증 대기**로 표시합니다. 재시작이나 토큰 갱신 후에도 요청에 사용되지 않습니다. 한도 회복 후 **사용량 새로고침**을 실행하면, 여유가 있는 완전한 최신 사용량을 확인한 뒤 작은 모델 요청을 보내고 완료 응답을 받아야 계정을 사용할 수 있습니다. 조회나 검증 실패 시 대기 상태를 유지합니다. 일반적인 화면 상태 조회는 이 모델 요청을 보내지 않습니다. 최초 등록 때 사용량이 불명확하면 기존 워밍업 검증이 필요합니다.

`ocx account refresh openai`와 `ocx account list openai --quota --refresh`는 사용량만 조회합니다. 모델 검증은 할당량을 사용하므로 사람의 대시보드 세션이 필요합니다. 할당량이 복구되면 `ocx gui`를 열고 **Refresh quotas**를 클릭하세요. 헤드리스 호스트도 브라우저에서 해당 대시보드에 접속해야 하며, 관리자 토큰만으로는 검증할 수 없습니다. 일시 정지된 계정도 검증할 수 있지만 일시 정지를 해제하거나 계정을 선택하지는 않습니다. 모델 인증 실패 표시는 검증 또는 재인증에 성공할 때까지 유지됩니다.

별도의 백그라운드 재검증은 기본적으로 꺼져 있습니다. Token Guardian, `openai`의 `proactive` 갱신 정책, `tokenGuardian.codexWarmupEnabled`가 필요하며 등록 검증 대기 계정은 제외합니다.

## 네이티브 Codex 복원

Expand Down
Loading
Loading