8 Commits

  • Allow ChatGPT accounts without email (#28991)
    # Summary
    
    Codex required every ChatGPT account to have an email address. A
    service-account personal access token can return valid account metadata
    without one, so PAT login failed while decoding the metadata response.
    
    This change makes email optional in the account metadata type that owns
    it and preserves that absence through authentication, provider account
    state, the app-server API, generated clients, and TUI bootstrap.
    Existing accounts with email addresses keep the same behavior.
    
    ## Behavior-changing call sites
    
    | Call site | Behavior after this change |
    | --- | --- |
    | `login/src/auth/personal_access_token.rs` | PAT metadata accepts a
    missing or null email and retains `None`. |
    | `agent-identity/src/lib.rs` | Agent Identity JWT claims accept an
    omitted email. |
    | `login/src/auth/storage.rs` and `login/src/auth/agent_identity.rs` |
    Stored and managed Agent Identity records carry `Option<String>`.
    Deserialization maps the legacy empty-string sentinel to `None`. |
    | `login/src/auth/manager.rs` | `get_account_email` returns the stored
    option, and managed identity bootstrap no longer converts `None` to an
    empty string. |
    | `model-provider/src/provider.rs` and `protocol/src/account.rs` | A
    ChatGPT provider account requires a plan type but may carry no email. |
    | `app-server-protocol/src/protocol/v2/account.rs` | `account/read`
    keeps the `email` field on the wire and returns `null` when the account
    has no email. Generated TypeScript and JSON schemas describe a required,
    nullable field. |
    | `sdk/python/src/openai_codex/generated/v2_all.py` | The generated
    Python `ChatgptAccount` model accepts `None` for email. |
    | `tui/src/app_server_session.rs` | Email-less ChatGPT accounts
    bootstrap normally, keep external feedback routing, omit account-email
    telemetry, and display the plan in account status. |
    
    ## Design decisions
    
    - Missing email remains `None` at every layer. The code never uses an
    empty string as a substitute.
    - The app-server response includes `"email": null` instead of omitting
    the field. Clients retain a stable response shape.
    - Plan type remains required for provider account state. This change
    relaxes only the email assumption.
    
    ## Testing
    
    Tests: affected test targets compile, scoped Clippy and formatting pass,
    a focused TUI snapshot covers plan-only account status, real
    before/after PAT login smoke covers metadata without email, app-server
    smoke covers `account/read` with `email: null`, and a regression smoke
    covers an existing email-bearing PAT. Unit tests run in CI.
    
    ## Evidence
    
    Visual smoke evidence will be attached here.
  • [codex] expose Bedrock credential source in account/read (#27751)
    ## Why
    
    `account/read` currently reports only `type: "amazonBedrock"`, so
    clients cannot distinguish a Codex-managed Bedrock API key from
    credentials supplied by AWS. The app UI needs that distinction to render
    the appropriate account state without duplicating provider-auth logic.
    
    Credential-source selection belongs to the Bedrock model provider
    because it already owns the precedence between managed Bedrock auth and
    the external AWS credential path. This builds on #27443 and #27689.
    
    ## What changed
    
    - Added `AmazonBedrockCredentialSource` with `codexManaged` and
    `awsManaged` values.
    - Included the selected credential source in
    `ProviderAccount::AmazonBedrock` and the app-server `Account` response.
    - Made `AmazonBedrockModelProvider::account_state()` classify the source
    from its managed-auth state.
    - Regenerated the app-server JSON and TypeScript schemas.
    - Updated app-server account documentation and downstream TUI matches.
    
    `codexManaged` means the provider found a managed Bedrock API key.
    `awsManaged` identifies the provider's external AWS credential path; it
    does not assert that the AWS credential chain has been validated.
    
    ## Testing
    
    - Added model-provider coverage for Codex-managed precedence and
    AWS-managed fallback.
    - Added app-server protocol serialization coverage for both wire values.
    - Added app-server integration coverage for both `account/read`
    responses.
    - `just test -p codex-protocol -p codex-model-provider -p
    codex-app-server-protocol` (497 tests passed).
    
    After rebasing onto #27711, the `codex-app-server` test target compiled
    past the image-generation `PathUri` migration. Local linking was then
    interrupted by disk exhaustion (`No space left on device`).
  • feat: expose AWS account state from account/read (#19048)
    ## Why
    
    AWS/Bedrock mode currently reports `account: null` with
    `requiresOpenaiAuth: false` from `account/read`. That suppresses the
    OpenAI-auth requirement, but it does not let app clients distinguish AWS
    auth from any other non-OpenAI custom provider. For the prototype AWS
    provider UX, clients need a simple provider-derived signal so they can
    suppress ChatGPT/API-key login and token-refresh paths without
    hardcoding Bedrock checks.
    
    ## What changed
    
    - Adds an `aws` variant to the v2 `Account` protocol union.
    - Adds `ProviderAccountKind` to `codex-model-provider` so the runtime
    provider owns the app-visible account classification.
    - Makes Amazon Bedrock return `ProviderAccountKind::Aws` from the
    model-provider layer.
    - Updates app-server `account/read` to map `ProviderAccountKind` to the
    existing `GetAccountResponse` wire shape.
    - Preserves the existing `account: null, requiresOpenaiAuth: false`
    behavior for other non-OpenAI providers.
    - Regenerates the app-server protocol schema fixtures.
    - Adds coverage for provider account classification and for the Amazon
    Bedrock `account/read` response.
    
    ## Testing
    
    - `cargo test -p codex-model-provider`
    - `cargo test -p codex-app-server-protocol`
    - `cargo test -p codex-app-server get_account_with_aws_provider`
    
    ## Notes
    
    I attempted `just bazel-lock-update` and `just bazel-lock-check`, but
    both are blocked in my local environment because `bazel` is not
    installed.
  • Support prolite plan type (#17419)
    Addresses #17353
    
    Problem: Codex rate-limit fetching failed when the backend returned the
    new `prolite` subscription plan type.
    
    Solution: Add `prolite` to the backend/account/auth plan mappings, keep
    unknown WHAM plan values decodable, and regenerate app-server plan
    schemas.
  • Revert "Option to Notify Workspace Owner When Usage Limit is Reached" (#17391)
    Reverts openai/codex#16969
    
    #sev3-2026-04-10-accountscheckversion-500s-for-openai-workspace-7300
  • Option to Notify Workspace Owner When Usage Limit is Reached (#16969)
    ## Summary
    - Replace the manual `/notify-owner` flow with an inline confirmation
    prompt when a usage-based workspace member hits a credits-depleted
    limit.
    - Fetch the current workspace role from the live ChatGPT
    `accounts/check/v4-2023-04-27` endpoint so owner/member behavior matches
    the desktop and web clients.
    - Keep owner, member, and spend-cap messaging distinct so we only offer
    the owner nudge when the workspace is actually out of credits.
    
    ## What Changed
    - `backend-client`
    - Added a typed fetch for the current account role from
    `accounts/check`.
      - Mapped backend role values into a Rust workspace-role enum.
    - `app-server` and protocol
      - Added `workspaceRole` to `account/read` and `account/updated`.
    - Derived `isWorkspaceOwner` from the live role, with a fallback to the
    cached token claim when the role fetch is unavailable.
    - `tui`
      - Removed the explicit `/notify-owner` slash command.
    - When a member is blocked because the workspace is out of credits, the
    error now prompts:
    - `Your workspace is out of credits. Request more from your workspace
    owner? [y/N]`
      - Choosing `y` sends the existing owner-notification request.
    - Choosing `n`, pressing `Esc`, or accepting the default selection
    dismisses the prompt without sending anything.
    - Selection popups now honor explicit item shortcuts, which is how the
    `y` / `n` interaction is wired.
    
    ## Reviewer Notes
    - The main behavior change is scoped to usage-based workspace members
    whose workspace credits are depleted.
    - Spend-cap reached should not show the owner-notification prompt.
    - Owners and admins should continue to see `/usage` guidance instead of
    the member prompt.
    - The live role fetch is best-effort; if it fails, we fall back to the
    existing token-derived ownership signal.
    
    ## Testing
    - Manual verification
      - Workspace owner does not see the member prompt.
    - Workspace member with depleted credits sees the confirmation prompt
    and can send the nudge with `y`.
    - Workspace member with spend cap reached does not see the
    owner-notification prompt.
    
    ### Workspace member out of usage
    
    https://github.com/user-attachments/assets/341ac396-eff4-4a7f-bf0c-60660becbea1
    
    ### Workspace owner
    <img width="1728" height="1086" alt="Screenshot 2026-04-09 at 11 48
    22 AM"
    src="https://github.com/user-attachments/assets/06262a45-e3fc-4cc4-8326-1cbedad46ed6"
    />
  • Add usage-based business plan types (#15934)
    ## Summary
    - add `self_serve_business_usage_based` and `enterprise_cbp_usage_based`
    to the public/internal plan enums and regenerate the app-server + Python
    SDK artifacts
    - map both plans through JWT login and backend rate-limit payloads, then
    bucket them with the existing Team/Business entitlement behavior in
    cloud requirements, usage-limit copy, tooltips, and status display
    - keep the earlier display-label remap commit on this branch so the new
    Team-like and Business-like plans render consistently in the UI
    
    ## Testing
    - `just write-app-server-schema`
    - `uv run --project sdk/python python
    sdk/python/scripts/update_sdk_artifacts.py generate-types`
    - `just fix -p codex-protocol -p codex-login -p codex-core -p
    codex-backend-client -p codex-cloud-requirements -p codex-tui -p
    codex-tui-app-server -p codex-backend-openapi-models`
    - `just fmt`
    - `just argument-comment-lint`
    - `cargo test -p codex-protocol
    usage_based_plan_types_use_expected_wire_names`
    - `cargo test -p codex-login usage_based`
    - `cargo test -p codex-backend-client usage_based`
    - `cargo test -p codex-cloud-requirements usage_based`
    - `cargo test -p codex-core usage_limit_reached_error_formats_`
    - `cargo test -p codex-tui plan_type_display_name_remaps_display_labels`
    - `cargo test -p codex-tui remapped`
    - `cargo test -p codex-tui-app-server
    plan_type_display_name_remaps_display_labels`
    - `cargo test -p codex-tui-app-server remapped`
    - `cargo test -p codex-tui-app-server
    preserves_usage_based_plan_type_wire_name`
    
    ## Notes
    - a broader multi-crate `cargo test` run still hits unrelated existing
    guardian-approval config failures in
    `codex-rs/core/src/config/config_tests.rs`
  • feat: vendor app-server protocol schema fixtures (#10371)
    Similar to what @sayan-oai did in openai/codex#8956 for
    `config.schema.json`, this PR updates the repo so that it includes the
    output of `codex app-server generate-json-schema` and `codex app-server
    generate-ts` and adds a test to verify it is in sync with the current
    code.
    
    Motivation:
    - This makes any schema changes introduced by a PR transparent during
    code review.
    - In particular, this should help us catch PRs that would introduce a
    non-backwards-compatible change to the app schema (eventually, this
    should also be enforced by tooling).
    - Once https://github.com/openai/codex/pull/10231 is in to formalize the
    notion of "experimental" fields, we can work on ensuring the
    non-experimental bits are backwards-compatible.
    
    `codex-rs/app-server-protocol/tests/schema_fixtures.rs` was added as the
    test and `just write-app-server-schema` can be use to generate the
    vendored schema files.
    
    Incidentally, when I run:
    
    ```
    rg _ codex-rs/app-server-protocol/schema/typescript/v2
    ```
    
    I see a number of `snake_case` names that should be `camelCase`.