## What changed
- Implement `account/bedrock/discover` to report AWS profiles and available environment credentials.
- Implement `account/bedrock/setup` for validated AWS profiles and environment credentials, persisting the selected region and profile in the Bedrock provider configuration.
- Resolve Bedrock authentication according to the selected credential source, and clear stale profile configuration when using a Codex-managed Bedrock API key.
## Testing
- Cover profile and environment discovery, setup validation and persistence, conflicting credentials, and authentication-source precedence.
GitOrigin-RevId: 16d700cb0843df768c2fdb6d0c8d26c3402e93df
## Why
App-server logs can be persisted or included in submitted diagnostics, so credentials used by model providers, authentication refreshes, and attestation requests must not appear in diagnostic output.
## What changed
- Add `RedactedString`, which preserves serialization and string access while replacing debug output with `<redacted>`.
- Use it for model-provider bearer tokens, header and query values, authentication command arguments, and attestation tokens.
- Avoid logging JSON-RPC error payloads and parser or authentication errors that may echo credentials; retain safe context such as error codes and categories.
## Testing
- Add an app-server regression test that exercises provider credentials, refreshed authentication tokens, and attestation tokens, then verifies none appear in persisted SQLite or submitted diagnostic logs.
GitOrigin-RevId: 8c50408adf94d93847658b1320682cf3b637d2cc
## What changed
- Switch Amazon Bedrock remote compaction to `compaction_trigger` items sent through `/v1/responses`.
- Remove the legacy dedicated compaction protocol from provider capabilities.
- Default remote compaction to unsupported and explicitly enable it for OpenAI, Azure Responses, and Amazon Bedrock providers.
## Testing
- Cover manual and automatic Amazon Bedrock compaction requests and their compacted history.
- Verify remote-compaction capabilities for configured and Amazon Bedrock providers.
GitOrigin-RevId: cf9ba314595367518b37a85f334f0c105ce47e45
## Why
Amazon Bedrock does not support the response items required by multi-agent V2.
## What changed
- Normalize Bedrock model catalogs to advertise `MultiAgentVersion::V1`.
- Cover both remote catalog normalization and the static Bedrock Runtime catalog in tests.
GitOrigin-RevId: 93832cd4b885daf4b87fb33a7be8502ae15c1b24
## Why
Model provider configuration could override the residency header required by
`enforce_residency`, so provider-backed requests did not reliably honor the
managed setting.
## What changed
- Apply the managed residency header after building a provider, making it
authoritative for model requests and model discovery.
- Warn when a provider configures the residency header through
`http_headers` or `env_http_headers`, while preserving the original provider
configuration and unrelated headers.
- Cover HTTP and WebSocket requests, model discovery, and case-insensitive
header detection with targeted tests.
GitOrigin-RevId: 461ef8989d5bd06ffdea694aee4265e392e07590
## Why
Bedrock sessions that use the AWS SDK credential chain need a way to recover when credentials expire during a request.
## What changed
- Add `aws.auth_refresh` provider configuration with an `aws` command, arguments, and a configurable timeout.
- Run the command for refreshable Bedrock authentication failures, reload the SDK credentials, re-sign the request, and retry it.
- Share refresh state across matching provider configurations so concurrent failures invoke the command only once. Bearer tokens, command auth, and static environment credentials do not use this recovery path.
## Testing
- Add coverage for configuration validation, refreshable error classification, concurrent refresh sharing, and an end-to-end retry signed with refreshed credentials.
GitOrigin-RevId: 0302fe3aabdbc1097e7bd62a74d407ba38a3cc57
## What changed
- Let model providers identify recoverable authentication errors and refresh their own authentication state before falling back to `AuthManager` recovery.
- Apply provider recovery to both HTTP and WebSocket response requests, with at most one provider-owned recovery attempt per request.
- Preserve existing `401 Unauthorized` handling as the default for providers that do not customize recovery.
## Testing
- Add coverage for successful and failed provider recovery, including the single-attempt bound and preservation of the original unauthorized error.
GitOrigin-RevId: 9a737e3be96354699586f97dd88e544a45082969
## Why
Custom model providers that do not require OpenAI authentication could inherit
ambient authentication headers, including the bearer token and
`ChatGPT-Account-ID`, and send them to the custom provider endpoint.
## What changed
- Resolve providers without `requires_openai_auth` or configured `auth` as
unauthenticated.
- Continue to honor an explicit `experimental_bearer_token` or command-resolved
provider authentication.
- Preserve ambient authentication for OpenAI providers.
## Testing
Added unit and request-level coverage for custom, explicitly authenticated, and
OpenAI provider authentication behavior.
GitOrigin-RevId: d89a79604338bc660a3edb2af0068cfa9b694fa2
## What changed
- Allow `gpt-5.6-sol`, `gpt-5.6-terra`, and `gpt-5.6-luna` context-window overrides up to 872,000 tokens.
- Build the corresponding Amazon Bedrock entries from each bundled model's metadata while preserving Bedrock-specific identifiers, availability, tool, reasoning, and service-tier settings.
## Testing
- Cover long-context override clamping for bundled and Amazon Bedrock GPT-5.6 models.
- Verify the normalized Amazon Bedrock catalog metadata and context limits.
GitOrigin-RevId: 9f530dee501222a4d280bb31bbcdc2dacbe35d7d
## What changed
Group Amazon Bedrock Runtime models by routing variant so every Global model
appears before the US cross-region models, while preserving the base model order
within each group. Update catalog priorities and tests to match the new order.
GitOrigin-RevId: e5a55d61163404172a418cb794b25f3b27f83618
## Why
Remote exec-server registry requests need to refresh managed credentials before sending a request. Static auth-header resolution cannot perform the asynchronous token exchange required by workload identity.
## What changed
- Add asynchronous auth-header resolution to `AuthProvider`, with the existing static-header behavior as the default.
- Resolve fresh managed credentials for each remote environment registry request while preserving the expected account and workspace identity.
- Load the cloud configuration bundle during remote exec-server startup when workload identity is selected.
## Testing
- Update the managed-auth and environment-registry auth tests to exercise asynchronous header resolution.
GitOrigin-RevId: 5d60f1127467aaacdb5d1a8f3d92278bc4bf2e29
## What changed
- Set `parallel_tool_calls` for regular and remote compaction prompts without consulting model metadata.
- Remove `supports_parallel_tool_calls` from `ModelInfo`, the bundled model catalog, and related fixtures.
- Preserve the existing Responses Lite behavior that disables parallel tool calls at request construction.
GitOrigin-RevId: 49552bdf97e71fa57325abb49f8adc0c88f1401a
## What changed
- Add the built-in `amazon-bedrock-runtime` provider for regional
`bedrock-runtime` OpenAI-compatible endpoints.
- Use endpoint-specific SigV4 service configuration while preserving bearer
token auth and per-provider AWS profile, region, and transport overrides.
- Provide global and US cross-region GPT-5.6 model variants, prefer global
routing for fallback and background tasks, and disable unsupported web search.
## Testing
- Cover provider configuration and capabilities, endpoint and auth selection,
runtime catalog ordering, model fallback, and web search omission.
GitOrigin-RevId: d158ab74a5768e1b4c61063365a0c06735313322
## What changed
- Select `gpt-5.6-luna` for Guardian approval reviews authenticated with an API key, while retaining `codex-auto-review` for ChatGPT authentication.
- Exercise API-key reviews through Responses Lite and fall back to the bundled Guardian policy when the selected model has no catalog-provided review policy.
- Refine the bundled policy's handling of trusted authorization, sensitive-data egress, credential probing, destructive command targets, and post-denial approval.
## Testing
- Cover provider model selection for API-key and ChatGPT authentication.
- Verify Guardian prewarming and review reuse with both Responses Lite and standard Responses requests.
GitOrigin-RevId: e35c43e1692fd643ab8faad1444c0d6a869b3e0c
## What changed
- Add the public asynchronous `ModelsCache` contract and cache entry/error types.
- Let model providers and `OpenAiModelsManager` accept caller-provided cache implementations while retaining the existing file-backed cache by default.
- Treat cache read failures as misses, keep cache write failures non-fatal, and support refreshing an entry's TTL after ETag revalidation.
- Continue to prefer an explicitly configured static model catalog over an injected cache.
## Testing
- Cover injected cache hits, read and write failures, TTL refreshes, and end-to-end model selection.
- Verify that the file-backed implementation satisfies the new cache contract and does not serve expired entries before revalidation.
GitOrigin-RevId: eef957a317910b8502a0c20f8fc112f689d5e389
## What changed
- Add provider-owned remote compaction capabilities for unsupported, v1, and v2 protocols.
- Mark Amazon Bedrock as v1-only so manual and automatic compaction use `/v1/responses/compact`, even when the v2 feature is enabled.
- Preserve v2 support for OpenAI and Azure Responses providers and local compaction for unsupported providers.
## Testing
- Cover Amazon Bedrock manual and automatic remote compaction, including endpoint selection, authentication headers, model selection, and reuse of the compacted summary.
GitOrigin-RevId: d58093178605d1f8155b93d9a161408177f6ac72
## Why
Amazon Bedrock supports hosted text web search, but it rejects the
`search_content_types` field used for multimodal search and does not support
external live or indexed web access.
## What changed
- Advertise hosted web search for Amazon Bedrock while marking external web
access as unsupported.
- Resolve unsupported live and indexed modes to cached search, or disable the
tool when cached search is prohibited by managed requirements.
- Normalize built-in and configured Bedrock model catalogs to text-only web
search, and retain the runtime provider in session configuration so turn
setup can apply its capabilities.
## Testing
- Cover cached fallback, managed-mode restrictions, text-only tool payloads,
provider capabilities, and catalog normalization.
GitOrigin-RevId: 310473849257401654388a4ebb42920e03aa3228
## What changed
- Allow multi-agent v2 parents to spawn any visible model that has not explicitly disabled multi-agent support.
- Expose collaboration tools to child agents only when their selected model supports multi-agent v2, keeping legacy models as leaf workers.
- Preserve a worker's selected model when reloading it into residency.
- Propagate multi-agent capability metadata to Amazon Bedrock model entries so delegation is gated consistently.
## Testing
- Cover model selection, leaf-worker tool visibility, Bedrock capability handling, and model preservation after reload.
GitOrigin-RevId: 1457adb1a09806d1f0621311d5a42a6815b9dd4e
## What changed
- Remove `ModelInfo.base_instructions` as an in-memory instruction source and use `model_messages.instructions_template` consistently for bundled, remote, fallback, and overridden model metadata.
- Preserve compatibility by promoting legacy `base_instructions` values when reading model responses and caches, and by including rendered legacy instructions when serializing `ModelsResponse` for older clients.
- Treat templates without instruction variables as literal text and retain the other model-message fields when applying instruction overrides.
This completes the consolidation proposed in https://github.com/openai/codex/pull/31302.
## Testing
- Cover legacy response and cache migration, canonical-template precedence, fallback instructions, personality rendering, overrides, and model switching.
GitOrigin-RevId: 089d986ca5e30da67db2c77a1b6a046d2cff52dc
## What changed
- Wrap `CodexErrorDetails` and an optional retry delay in `CodexErr`, allowing any mapped error to preserve server-provided retry timing.
- Generate the payload-free `CodexErrKind` classification alongside the error details and reuse it for analytics.
- Update error handling sites to inspect `CodexErr::details()` while preserving existing display, debug, protocol mapping, and retryability behavior.
## Testing
- Add coverage for legacy debug formatting, error-specific retryability, and retry-delay propagation through API error mapping.
GitOrigin-RevId: d3ab8a305f2a2ee21d0c0a8c8c388b06dda9c59a
## What changed
- Add the `supports_standalone_web_search` model-provider setting, defaulting to `false`, and preserve it in remote thread configuration.
- Enable the standalone `web.run` tool for opted-in custom Responses providers when web search is enabled and the runtime provider supports it.
- Send standalone search requests through the custom provider's endpoint and authentication.
## Testing
- Cover opt-in, default-off, disabled-search, and unsupported-provider behavior.
- Verify custom-provider search request routing and authorization through the app server.
GitOrigin-RevId: 7c5f96b0ce924ad2b9715c45bfc635e89fc39cff
## Why
ChatGPT token refresh requests need to follow the same configured routing policy as other authentication traffic, including environments that use the system proxy.
## What changed
- Require an `AuthRouteConfig` throughout login, logout, token refresh, personal access token, and agent identity flows.
- Build auth HTTP clients directly from that configuration instead of falling back to a default HTTP client when routing configuration is absent.
## Testing
- Add an integration test that refreshes a token through a cached system-proxy route and verifies the proxy receives the expected request.
GitOrigin-RevId: 7d54ab3219939a49921c51faf08cd4c2eabca51c
## Why
Auth managers should use the application's resolved HTTP client factory instead
of silently falling back to the transport's default proxy behavior.
## What changed
- Make `AuthRouteConfig` required when constructing an `AuthManager` or
`AuthConfig`.
- Pass each production caller's resolved routing configuration through without
wrapping it in an optional value.
- Add a test helper that explicitly selects the transport-default proxy policy
for callers that do not exercise custom routing.
GitOrigin-RevId: d89a3b1f8b5d4007650cdac0aae241c94d598580
## Why
`codex-http-client` is the intended owner of direct `reqwest` usage.
## What changed
- Build Codex's default and route-aware clients with `HttpClientBuilder`, and return `HttpClient` directly to API, model discovery, auth, remote control, skills, and extension callers.
- Preserve custom CA, proxy, Cloudflare cookie, sandbox, and request-logging policies while removing `codex-login`'s direct `reqwest` dependency.
- Use shared HTTP types for auth headers, status codes, transport errors, and login-server tests.
## Testing
- Add a Linux integration test verifying that a regular Responses API turn traverses the configured system proxy.
GitOrigin-RevId: 714695fb80762d2083e2f7a6414183e2b3b63854
## What changed
- Allow the built-in `amazon-bedrock` provider to override `base_url`, `auth`,
and `http_headers` in addition to its AWS profile and region.
- Use command-based bearer authentication and configured endpoints without
applying AWS request signing, while retaining regional endpoint resolution
for the default Bedrock configuration.
- Replace the Bedrock account `credentialSource` enum with the
`usesCodexManagedCredentials` boolean so command-authenticated and other
externally managed configurations are reported consistently.
## Testing
- Cover configuration merging and validation, command-authenticated proxy
requests with custom headers, and account reporting for managed and external
credentials.
GitOrigin-RevId: d1acbe602060470583b5e12f8d304bee5be46f4c
## What changed
- Hide `gpt-5.4` and `gpt-5.4-mini` from model selection and direct existing users to `gpt-5.6-terra` and `gpt-5.6-luna`, respectively.
- Use Terra for memory consolidation and Luna for memory extraction and rate-limit switch prompts.
- Keep Amazon Bedrock GPT-5 catalog entries visible when their bundled model metadata is hidden.
## Testing
- Add coverage that all Amazon Bedrock GPT-5 models remain visible and update TUI expectations for the new model choices.
GitOrigin-RevId: fd69c8d5fb6b510c77204df6b7ac3f07e67cded2
## What changed
- Handle experimental `account/login/start` requests with `type: "amazonBedrock"`.
- Validate the API key and Mantle region, persist the managed credential, select the `amazon-bedrock` model provider, and emit the standard login and account-update notifications.
- Reload configuration for account and authentication status reads so the newly selected provider is visible immediately, with the startup configuration as a fallback.
- Extend the app-server test client with an Amazon Bedrock login mode that redacts API keys from request logs.
## Testing
- Add app-server coverage for successful login, credential and provider persistence, notifications, refreshed account state, invalid inputs, conflicting configuration, forced ChatGPT login, external authentication, and configuration reload failure.
GitOrigin-RevId: bf3ae98375caee41e78d2cdc677127138184c17a
## Why
Embedding callers need to control whether model catalogs are persisted to disk.
## What changed
- Accept a shared models manager when constructing `ThreadManager` instead of always creating a cached manager internally.
- Add provider APIs for creating uncached model managers. OpenAI-compatible providers fetch on each `OnlineIfUncached` refresh without reading or writing `models_cache.json`.
- Keep existing app server, MCP server, sample, and test callers on the standard cached manager.
## Testing
- Verify an uncached manager fetches on every refresh.
- Verify an injected uncached manager controls thread refresh behavior and does not create `models_cache.json`.
GitOrigin-RevId: 8bb646054ecec4ccb865b2bf56249384916ea9db
## What changed
- Prioritize the GPT-5.6 Sol, Terra, and Luna variants ahead of GPT-5.5 and GPT-5.4 in the static Amazon Bedrock catalog, making Sol the default.
- Use each GPT-5.6 variant's bundled description and default reasoning level while retaining Bedrock's `max` reasoning support.
## Testing
- Update model-provider and app-server tests to cover catalog ordering, variant metadata, and provider-aware fallback to GPT-5.6 Sol.
GitOrigin-RevId: 1761390254deae47b62c043b1ba707c384cde5e9
## What changed
- Build a reasoning payload for every Responses request and always include `reasoning.encrypted_content`.
- Remove `supports_reasoning_summaries` from model metadata and retire the `model_supports_reasoning_summaries` configuration override.
- Use configured or model-default reasoning effort without a capability gate, including for guardian reviews and tracing.
GitOrigin-RevId: 2c9f194a5d2d4d688a2235299e6358f82ab8e1ea
[Codex Thread
019f2408-dc59-79f2-b245-4c11debd1a61](https://codex-thread-link.openai.chatgpt-team.site/thread/019f2408-dc59-79f2-b245-4c11debd1a61)
## Why
Long-lived Codex sessions can outlive the ChatGPT bearer token that was
present when the MCP runtime started.
The Responses path already recovers from token expiration by refreshing
or reloading the shared `AuthManager`. The reserved `codex_apps`
hosted-plugin client did not observe that update: `McpConnectionManager`
built its `/ps/mcp` HTTP auth once from a `CodexAuth` snapshot, and
`auth_provider_from_auth` copied that snapshot bearer into a static
`BearerAuthProvider`.
After the copied bearer expired, `/ps/mcp` kept sending it even though
Responses had a newer token in the same `AuthManager`. The failure
occurred before downstream connector execution, so unrelated apps such
as Gmail, Slack, and Google Calendar could all fail with the same
transport-level `401 token_expired`.
This replaces
[openai/codex#29474](https://github.com/openai/codex/pull/29474), which
was closed for inactivity without being merged. A new long-lived-session
report reproduced the same simultaneous `/ps/mcp` expiry pattern across
unrelated apps.
## What changed
- Add an `AuthManager`-backed request-header provider in
`codex-model-provider`. It keeps an `Arc<AuthManager>` and reads
`auth_cached()` for each outbound request, so the next `/ps/mcp` call
sees a token refreshed by the existing Responses/auth-recovery flow.
- Scope that provider to the startup account, ChatGPT user, and
workspace identity. Same-identity token reloads are followed; an account
switch emits no ambient auth until account-scoped MCP state is rebuilt.
- Have `McpConnectionManager` construct the dynamic provider only for
the reserved `codex_apps` registration used by the hosted-plugin
`/ps/mcp` path.
| MCP path | Auth behavior after this change |
| --- | --- |
| Reserved `codex_apps` hosted-plugin `/ps/mcp` | Read current
same-identity auth from the shared `AuthManager` per request |
| `codex_apps` with `CODEX_CONNECTORS_TOKEN` | Keep the environment
bearer-token override |
| User-configured/direct MCP registrations | Keep their existing
configured auth path |
## Non-goals
- No plugin-service changes.
- No downstream Slack, Gmail, Calendar, or other connector
OAuth/link-refresh changes.
- No auth UI changes.
- No behavior change for user-configured/direct MCP registrations.
- No new `/ps/mcp`-initiated token refresh; this makes `/ps/mcp` observe
refreshes already performed through the shared `AuthManager`.
## Tests
- `just test -p codex-model-provider`
- Covers same-identity token reloads and refuses a changed startup
identity.
- `just test -p codex-mcp`
- `just test -p codex-core mcp_auth_refresh`
- Creates the reserved hosted-plugin `codex_apps` `/ps/mcp` client
before the shared `AuthManager` changes, updates that same manager
through its public external-auth path, performs a real `tools/call`, and
asserts the request uses the current bearer.
## Why
Amazon Bedrock's GPT-5.6 variants currently appear as only `Sol`,
`Terra`, and `Luna`. Those labels omit the model family and version,
making them ambiguous in model lists and inconsistent with the naming of
other GPT models.
## What changed
- Rename the three Bedrock model display names to `GPT-5.6 Sol`,
`GPT-5.6 Terra`, and `GPT-5.6 Luna`.
- Strengthen the Bedrock model-manager test to verify both model IDs and
their propagated display names.
Model IDs, ordering, priorities, reasoning support, and default
selection are unchanged.
## Why
#31323 introduces `codex-http-client` and leaves compatibility
re-exports in `codex-client`. Low-level HTTP consumers should depend on
the crate that now owns those APIs rather than continuing through the
transitional compatibility layer.
This stacked follow-up makes that ownership explicit and moves the
repository toward enforcing the abstraction without mixing call-site
churn into the extraction itself.
## What changed
- Switched `codex-backend-client`, `codex-cloud-tasks`,
`codex-exec-server`, `codex-login`, and `codex-model-provider` from
`codex-client` to `codex-http-client` where they only use low-level HTTP
APIs.
- Added the direct dependency to `codex-api` for its custom-CA request
and websocket paths while retaining `codex-client` for higher-level
retry and transport policy.
- Updated imports and normalized login's internal client type name from
`CodexHttpClient` to `HttpClient`, while preserving its existing
`CodexRequestBuilder` re-export.
- Updated `Cargo.lock` to reflect the new direct dependency edges.
## Review guide
This PR is intentionally mechanical: 20 files and 92 changed lines, with
no runtime logic changes. The largest diff is
`codex-rs/login/src/auth/default_client.rs`, where the only
semantic-looking changes are type and import renames. The remaining
source changes replace `codex_client` import paths with
`codex_http_client`; the manifest and lockfile changes mirror those
imports.
## Test plan
- Compile-checked `codex-api`, `codex-backend-client`,
`codex-cloud-tasks`, `codex-exec-server`, `codex-login`, and
`codex-model-provider` together.
## Why
Amazon Bedrock's static catalog derives its GPT model definitions from
bundled OpenAI model metadata. The GPT-5.6 variants introduced in #30285
clone GPT-5.5, which carries an `availability_nux`; because app-server
forwards that metadata through `model/list`, clients can show GPT-5.5
launch copy for a GPT-5.6 Bedrock model.
`upgrade` is also model-catalog availability metadata and should not be
inherited by provider-specific Bedrock models.
## What changed
- Clear `availability_nux` and `upgrade` when constructing static
Bedrock GPT models.
- Add a regression test asserting that every static Bedrock model omits
both fields.
## Testing
- `just test -p codex-model-provider`
## Why
The Bedrock GPT-5.6 catalog advertises `max`, but Codex treated it as an
opaque custom effort. That made the reasoning picker render it as
lowercase `max` while known efforts use productized labels.
Making `max` a known effort aligns catalog data, parsing, and UI
presentation without changing the `max` wire value or persisted
representation.
## What changed
- Add first-class `ReasoningEffort::Max` parsing and serialization.
- Use the typed effort in the Bedrock catalog and render it as `Max` in
the TUI.
- Preserve forward-compatible custom-effort coverage with a genuinely
unknown `future` value.
### Before
<img width="559" height="124" alt="Screenshot 2026-06-28 at 12 08 47 PM"
src="https://github.com/user-attachments/assets/7c43cf4f-020b-4605-9239-0a9c97eb7364"
/>
### After
<img width="558" height="107" alt="Screenshot 2026-06-28 at 12 09 10 PM"
src="https://github.com/user-attachments/assets/b9cc5ded-c940-43b4-b024-bba25abe0a17"
/>
## Summary
- add Sol (`openai.gpt-5.6-sol`), Terra (`openai.gpt-5.6-terra`), and
Luna (`openai.gpt-5.6-luna`) to the Amazon Bedrock static model catalog
- derive all three entries from the bundled GPT-5.5 metadata and add the
Bedrock-only `max` reasoning effort
- keep the new entries below the current GPT-5.5 and GPT-5.4 models at
priorities 2, 3, and 4, preserving GPT-5.5 as the default
- add deep-equality coverage for inherited model configuration, catalog
ordering, context windows, and service-tier behavior
## Stack
This is PR 3 of the simplified HAI single-run-task stack:
- [#19047](https://github.com/openai/codex/pull/19047) Agent Identity
assertion and task-registration primitives, including the shared
run-task helper used by existing Agent Identity JWT auth.
- [#19049](https://github.com/openai/codex/pull/19049)
Disabled-by-default ChatGPT auth opt-in that provisions/reuses persisted
Agent Identity runtime auth and its single run task.
- [#19051](https://github.com/openai/codex/pull/19051) Run-scoped
provider auth that uses one backend-owned task id for first-party
inference and compaction requests.
[#19054](https://github.com/openai/codex/pull/19054) collapsed out of
the active stack because the simplified design no longer needs a
separate background/control-plane task helper.
## Summary
This PR moves Agent Identity usage into provider auth resolution. That
keeps `AgentAssertion` auth tied to first-party OpenAI provider requests
instead of applying a late session-wide override that could affect
local, custom, Bedrock, API-key, or external-bearer providers.
What changed:
- adds a small `ProviderAuthScope` struct carrying the run auth policy
and session source needed by provider-scoped auth resolution
- lets `Session` opt the existing `ModelClient` into `ChatGptAuth`
policy when `use_agent_identity` is enabled, without adding a second
model-client constructor
- resolves Agent Identity only for first-party OpenAI provider auth
paths
- uses the persisted run task id from the `AgentIdentityAuth` record to
build `AgentAssertion` auth for Responses requests
- routes shared request setup through scoped provider auth so unary
compact requests use the same run-task assertion path as inference turns
- keeps local/custom/Bedrock/env-key/external-bearer provider auth
unchanged
- lets missing run-task state surface through the existing model-request
error path instead of silently falling back to bearer auth
This PR intentionally does not create thread-scoped, target-scoped, or
background-scoped task identities. The run task is the only task Codex
registers in this POC shape.
## Testing
- `just test -p codex-model-provider`
- `just test -p codex-core client::tests::provider_auth_scope_uses`
- `just test -p codex-core remote_compact_uses_agent_identity_assertion`
## Why
MCP authentication has distinct OAuth and ChatGPT-session flows.
Representing that choice as `use_chatgpt_auth` makes one flow implicit
and allows the configuration model to express the distinction only
through a boolean.
ChatGPT credential forwarding also needs a first-party trust boundary. A
configurable `chatgpt_base_url` controls routing, but must not grant an
MCP server permission to receive session credentials.
This change builds on #29733, where the boolean was introduced.
## What changed
- Replace `use_chatgpt_auth` with an `auth` field backed by the
exhaustive `McpServerAuth` enum.
- Support `auth = "oauth"` and `auth = "chatgpt"`, with OAuth remaining
the default.
- Trust only the origin derived from the existing hardcoded
`CHATGPT_CODEX_BASE_URL` when granting ChatGPT auth to an MCP server.
- Keep configured bearer tokens and authorization headers ahead of the
selected authentication flow.
- Update config writers, schema output, fixtures, and integration-test
setup to use the enum.
## Verification
Integration coverage exercises the complete streamable HTTP startup path
in two independent configurations:
- A directly constructed MCP configuration verifies that matching an
overridden `chatgpt_base_url` does not grant ChatGPT auth.
- A persisted `config.toml` containing an attacker-controlled
`chatgpt_base_url` and `auth = "chatgpt"` verifies the same boundary
through normal config parsing.
Both tests complete MCP initialization and tool listing and assert that
the full captured request sequence contains no authorization headers.
Separate integration coverage verifies that configured authorization
takes precedence over ChatGPT auth.
## Why
Amazon Bedrock returns a `401 Unauthorized` response containing
`Signature expired:` when an AWS credential, including a short-lived
`AWS_BEARER_TOKEN_BEDROCK`, has expired. Codex currently surfaces that
response as a generic `unexpected status` error, which does not explain
how to recover.
Environment-provided bearer tokens cannot be refreshed automatically, so
the error should direct users to refresh their AWS credentials or
replace or remove the environment token and restart Codex. This
classification belongs to the Amazon Bedrock provider so similar
responses from other providers retain their existing behavior.
## What changed
- Add a synchronous `ModelProvider::map_api_error` hook that defaults to
the existing provider-neutral API error mapping, and route model
request, stream, WebSocket, and terminal unauthorized errors through the
active provider.
- Override the hook for Amazon Bedrock. After preserving the structured
status, body, URL, and request metadata, recognize `401` responses
containing `Signature expired:` and attach actionable credential
guidance.
- Keep `codex-protocol` provider-neutral by representing the guidance as
an optional `user_message`. Error rendering prefers this message while
continuing to append the URL, request ID, Cloudflare ray, and
authorization diagnostics.
- Add model-provider coverage for expired signatures and negative cases,
core coverage for provider dispatch after unauthorized recovery, and a
TUI snapshot for the rendered error.
## Testing
Tested with a real request with expired bedrock key:
<img width="962" height="126" alt="Screenshot 2026-06-22 at 3 56 51 PM"
src="https://github.com/user-attachments/assets/7e21cc7c-798e-4662-8467-7f304a2f2b59"
/>
# 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.
## Stack
This is PR 1 of the simplified HAI single-run-task stack:
- [#19047](https://github.com/openai/codex/pull/19047) Agent Identity
assertion and task-registration primitives, including the shared
run-task helper used by existing Agent Identity JWT auth.
- [#19049](https://github.com/openai/codex/pull/19049)
Disabled-by-default ChatGPT auth opt-in that provisions/reuses persisted
Agent Identity runtime auth and its single run task.
- [#19051](https://github.com/openai/codex/pull/19051) Run-scoped
provider auth that uses one backend-owned task id for first-party
inference and compaction requests.
[#19054](https://github.com/openai/codex/pull/19054) collapsed out of
the active stack because the simplified design no longer needs a
separate background/control-plane task helper.
## Summary
The simplified POC shape is one backend-owned task per Agent Identity
run. This PR makes the first layer match that final shape directly
instead of introducing task targets, caller-owned external task refs, or
intermediate wrappers that later PRs would need to undo.
What changed:
- keeps the `AgentAssertion` wire payload as `agent_runtime_id`,
`task_id`, `timestamp`, and `signature`
- exposes `register_agent_task` as the single task-registration helper
for both existing Agent Identity JWT auth and the ChatGPT-registration
path added later in the stack
- makes task registration send only the signed registration timestamp;
the backend owns the returned opaque task id
- removes the unused target/task-kind/external-task-ref surfaces from
`codex-agent-identity`
- keeps Agent Identity JWT JWKS lookup separate from agent/task
registration URL derivation
- updates Agent Identity JWT auth to register one run task during auth
construction and share that task across cloned auth handles
This PR intentionally does not enable ChatGPT-derived Agent Identity.
That opt-in and config gate are added in the next PR.
## Testing
- `just test -p codex-agent-identity`
## 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`).
## Why
First-party async traits should expose their `Send` contracts explicitly
without requiring `async_trait`. This completes the migration pattern
established in #27303 and #27304.
## What changed
- Replaced the remaining first-party `async_trait` traits with native
return-position `impl Future + Send` where statically dispatched and
explicit boxed `Send` futures where object safety is required.
- Kept implementations behavior-preserving, outlining existing async
bodies into inherent methods where that keeps the diff reviewable.
- Removed all direct first-party `async-trait` dependencies and the
workspace dependency declaration.
- Added a cargo-deny policy that permits `async-trait` only through the
remaining transitive wrapper crates.
- Updated `rand` from 0.8.5 to 0.8.6 to resolve RUSTSEC-2026-0097 and
keep the full cargo-deny check passing.
## Validation
- `just test -p codex-exec-server`: 216 passed, 2 skipped.
- `just test -p codex-model-provider`: 39 passed.
- `just test -p codex-core` and `just test`: changed tests passed;
remaining failures are environment-sensitive suites unrelated to this
migration.
- `cargo deny check`
- `just fix`
- `just fmt`
- `cargo shear`
- `just bazel-lock-check`
## Why
The Amazon Bedrock model provider currently discards the shared
`AuthManager`, so a Codex-managed Bedrock API key cannot reach
request-time provider auth. Bedrock instead falls through to AWS
environment or SDK credentials, and the request endpoint can be resolved
from a different region than the managed credential.
Managed Bedrock login should control both the bearer credential and
Mantle region. Unrelated OpenAI or ChatGPT credentials must remain
isolated from Bedrock.
## What changed
- Pass the shared `AuthManager` into `AmazonBedrockModelProvider`.
- Select `CodexAuth::BedrockApiKey` before the existing
`AWS_BEARER_TOKEN_BEDROCK` and AWS SDK/SigV4 paths.
- Use the managed Bedrock auth region when resolving the Mantle
endpoint.
- Filter other `CodexAuth` variants so OpenAI and ChatGPT auth are not
exposed to Bedrock request auth or unauthorized recovery.
- Add focused coverage for provider construction, managed-auth
precedence, bearer headers, endpoint selection, and OpenAI-auth
isolation.
## Why
Codex needs to manage Amazon Bedrock API key credentials through the
existing auth lifecycle instead of introducing a separate auth manager
or provider-specific credential file. Treating Bedrock API key login as
a primary auth mode gives it the same persistence, keyring, reload, and
logout behavior as the existing OpenAI API key and ChatGPT modes.
The credential is valid only for the `amazon-bedrock` model provider.
OpenAI-compatible providers must reject this auth mode rather than
treating the Bedrock key as an OpenAI bearer token.
## What changed
- Added `bedrockApiKey` as an app-server `AuthMode` and
`CodexAuth::BedrockApiKey` as a primary `AuthManager` mode.
- Added `BedrockApiKeyAuth`, containing the API key and AWS region, to
the existing `AuthDotJson` payload stored in `$CODEX_HOME/auth.json` or
the configured keyring backend.
- Added `login_with_bedrock_api_key(...)`, parallel to
`login_with_api_key(...)`, which replaces the current stored login with
Bedrock credentials.
- Reused generic auth reload and logout behavior instead of adding a
Bedrock-specific auth manager or logout path.
- Updated login restrictions, status reporting, diagnostics, telemetry
classification, generated app-server schemas, and auth fixtures for the
new mode.
- Added explicit errors when Bedrock API key auth is selected with an
OpenAI-compatible model provider.
This PR establishes managed storage and auth-mode behavior. Routing the
managed key and region into Amazon Bedrock requests will be in follow-up
PRs.
## Why
Memory startup used hardcoded OpenAI model slugs for extraction and
consolidation. That works for the default OpenAI-compatible path, but
provider-specific backends can require different model identifiers. In
particular, Amazon Bedrock should use its Bedrock model ID for these
background memory requests instead of the OpenAI `gpt-5.4-mini` /
`gpt-5.4` slugs.
## What Changed
- Added provider-owned preferred memory model methods alongside
`approval_review_preferred_model`.
- Updated memory extraction and consolidation to resolve their default
model through the active `ModelProvider`.
- Added Amazon Bedrock overrides so both memory stages use
`openai.gpt-5.4` through Bedrock’s provider-specific model ID.
- Kept explicit `memories.extract_model` and
`memories.consolidation_model` config overrides taking precedence.
- Added startup coverage for default OpenAI and Bedrock memory model
selection.
#closes #26288
## Summary
- add v2 personal access token support for `codex login
--with-access-token` and `CODEX_ACCESS_TOKEN`
- classify opaque `at-` tokens separately from legacy Agent Identity
JWTs
- hydrate required ChatGPT account metadata through AuthAPI
`/v1/user-auth-credential/whoami`
- use PATs directly as bearer tokens while preserving existing ChatGPT
account surfaces
- expose PAT-backed auth as the explicit `personalAccessToken`
app-server auth mode
## Implementation
PAT auth is intentionally small and stateless. Loading a PAT performs
one AuthAPI metadata request, stores the hydrated metadata in the
in-memory auth object, and redacts the secret from debug output. Legacy
Agent Identity JWT handling remains unchanged. The shared access-token
classifier lives in a private neutral module because it dispatches
between both credential types.
PAT hydration fails closed when AuthAPI omits any required metadata,
including email. Hydrated metadata is intentionally not persisted:
startup performs a live `whoami` preflight so revoked tokens or changed
account metadata are not accepted from a stale cache.
## Workspace restriction scope
This change intentionally does **not** apply
`forced_chatgpt_workspace_id` to PAT authentication. The setting is a
client-side config guardrail, not an authorization boundary, and PAT
does not currently require workspace-ID parity. The PAT login and
`CODEX_ACCESS_TOKEN` paths therefore validate through AuthAPI without
threading workspace-restriction state through access-token loading.
Existing workspace checks for non-PAT auth remain on their established
paths.
## App-server compatibility
The public app-server `AuthMode` is shared across v1 and v2, and
PAT-backed auth reports `personalAccessToken` through both APIs.
Following human review, this intentionally removes the temporary v1
compatibility mapping that reported PATs as `chatgpt`; the deprecated v1
API is kept in parity with v2 rather than maintaining a separate closed
enum. Clients with exhaustive auth-mode handling in either API version
must add the new case and should generally treat it as ChatGPT-backed
unless they need PAT-specific behavior.
The v1 auth-status response still omits the raw PAT when `includeToken`
is requested because that response cannot carry the account metadata
needed to reuse the credential safely. Persisted PAT auth also omits the
new enum value so older Codex builds can deserialize `auth.json` and
infer PAT auth from the credential field after a rollback.
## Validation
Latest review-fix validation:
- `CARGO_INCREMENTAL=0 just test -p codex-login` (126 passed)
- `CARGO_INCREMENTAL=0 just test -p codex-cli` (263 passed)
- `CARGO_INCREMENTAL=0 just test -p codex-cli
stored_auth_validation_handles_personal_access_token`
- `CARGO_INCREMENTAL=0 just test -p codex-app-server-protocol` (226
passed)
- `CARGO_INCREMENTAL=0 just test -p codex-models-manager
refresh_available_models_uses_remote_only_catalog_for_chatgpt_auth`
- `CARGO_INCREMENTAL=0 just test -p codex-tui
existing_non_oauth_chatgpt_login_counts_as_signed_in`
- `CARGO_INCREMENTAL=0 just fix -p codex-login -p
codex-app-server-protocol -p codex-models-manager -p codex-tui -p
codex-cli`
- `just fmt`
- `git diff --check`
The broader `codex-tui` suite previously compiled and ran 2,834 tests.
Three unrelated environment-sensitive guardian/IDE-socket tests failed
after retries; the PAT-relevant TUI coverage passed.
## Description
Bedrock currently only supports the implicit `default` service tier for
GPT models. This PR strips non-default service tier metadata from
Bedrock model catalogs so Codex does not advertise or send unsupported
tiers.
## What changed
- Normalize both built-in and configured Bedrock catalogs to
default-only service tier behavior.
- Add regression coverage for built-in and configured Bedrock catalogs.
## Validation
- `just fmt`
- `just test -p codex-model-provider`