## What changed
- Use `exec_command` and `write_stdin` as the shell tool surface.
- Treat legacy `default`, `local`, and `shell_command` model metadata as `unified_exec`.
- Remove obsolete shell-selection configuration and runtime paths while preserving the feature and policy gates for zsh fork execution.
GitOrigin-RevId: d743cbe598630d73052f1fecad680c4cde17977d
## What changed
- Add the hidden Daybreak Blue and Daybreak Red model definitions.
- Refresh model capabilities, instructions, plan availability, and service-tier metadata.
- Configure the auto-review model for Responses Lite and code-mode tools, and update Guardian request tests for the resulting `additional_tools` and developer-message layout.
## Testing
- Update Guardian request snapshots and assertions for initial and follow-up reviews.
- Verify MCP approval routing against the developer-message form of the Guardian prompt.
GitOrigin-RevId: 6680e9abebdcbc43224a81348591e26f8422f3ec
## What changed
- Remove the legacy `shell_command` handler and runtime, leaving `exec_command`
and `write_stdin` as the shell execution tools.
- Treat legacy `shell_command` model metadata as `unified_exec`, and normalize
legacy user opt-outs so they do not disable command execution. Managed feature
requirements and `shell_tool` can still disable it.
- Preserve shell approvals, sandboxing, zsh-fork support, and output truncation
through the unified execution path.
## Testing
- Cover legacy configuration and model-metadata compatibility.
- Exercise unified shell execution, approvals, truncation, and `apply_patch`
serialization across the app-server and core test suites.
GitOrigin-RevId: 5c2fd6164fc3519cdae4944cb9db276b8467311c
## What changed
- Add `rejection_instructions` and `timeout_instructions` to catalog-provided auto-review messages.
- Use the acting model's instructions for denied and timed-out reviews across tool approvals, shell escalation, and MCP elicitation responses.
- Fall back to the existing instructions only when a catalog value is absent, while preserving explicit empty-string overrides.
## Testing
- Cover catalog overrides, legacy fallbacks, empty values, and separation between acting-model and reviewer-model messages.
GitOrigin-RevId: c5b2c2dbdaefd45d1d658651dd1abaeb6d8c93da
## 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
- Add optional `guardian_v2` model-message defaults for classifier instructions,
review thresholds, reasoning effort, transcript selection and limits, and
action and compaction token limits.
- Apply those defaults when Guardian v2 samples a tool call, while preserving
explicit `[features.guardianv2]` settings over catalog values.
- Preserve the new catalog configuration when applying model overrides.
## Testing
- Cover model-catalog serialization and model override behavior.
- Verify that sampling uses catalog defaults while retaining local overrides.
GitOrigin-RevId: 4ae9ec235c647acbca05a20b7c4b87a4e1331161
## What changed
- Add model-catalog messages for root and subagent roles, explicit delegation, and delegation hints.
- Resolve role instructions in config, catalog, then bundled-default order, while preserving empty values as an explicit way to suppress fallback text.
- Refresh catalog-provided role and mode instructions when the model changes, and give full-history forks the selected child model's subagent role without retaining the parent's role guidance.
- Keep existing config overrides and reasoning-effort behavior, including proactive delegation for ultra reasoning effort.
## Testing
- Cover message deserialization and preservation through model overrides.
- Cover precedence, empty overrides, model switches, resumed sessions, and full-history subagent forks.
GitOrigin-RevId: 4625cf7c6a5490176adddfaa0fb99100707daea9
## 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
- Parse `node_repl_auto_review_required` and `node_repl_disabled` from model catalog entries and include their values in each turn's Responses API metadata.
- Treat both fields as reserved metadata so client-provided values cannot override the selected model's policy.
- Use the selected review model's catalog entry when building metadata for review turns.
## Testing
- Cover metadata propagation across model switches, review turns, Responses API requests, and MCP tool calls.
GitOrigin-RevId: c1f63426eeb8e559abff439fbc618716a4908aff
## What changed
- Add `include_apps_usage_instructions` to model metadata, defaulting to true for compatibility with existing metadata.
- Emit generic Apps guidance only when apps are available and the selected model enables it.
- Enable the capability for interactive model presets while leaving `codex-auto-review` and local models opted out.
## Testing
- Verify that missing metadata defaults to enabled and an explicit opt-out survives serialization.
GitOrigin-RevId: 6a20573cddfd3b80083d2b4b015829b49e6cc283
## What changed
- Propagate the optional `modelSpecialty` field through the model catalog and
app-server `model/list` response.
- When a newly selected model has the `cyber` specialty, default an active TUI
thread to workspace-write permissions with on-request approval. Use auto
review when available, otherwise keep the user as reviewer, while respecting
configured permission requirements.
- Show a notice when auto review is applied and strengthen the full-access
warning for cyber models.
- Preserve explicitly selected permissions when only reasoning settings change.
## Testing
- Cover auto-review defaults, requirement-aware fallback behavior, permission
preservation across reasoning changes, and the new warning notice.
GitOrigin-RevId: 8f25b0082d3051d9ff91f7355921236d0f82f758
## 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 `include_plugin_usage_instructions` to model metadata, defaulting to false.
- Emit generic plugin guidance only when plugins are available and the selected model enables it.
- Enable the capability for interactive model presets while leaving `codex-auto-review` opted out.
GitOrigin-RevId: 67f5a97e978033f5f1d533956c0b9deeae610283
## 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
- Add optional `default` and `plan` collaboration-mode messages to model catalog metadata.
- Prefer the active mode's catalog message, including an explicit empty value, while falling back to the existing developer instructions when the catalog variant is absent.
- Track the model in collaboration-mode world state so mode and model changes append the appropriate instructions, and clear prior instructions when no current message exists.
- Preserve catalog collaboration messages when instruction overrides remove other model instruction fields.
## Testing
- Cover catalog deserialization, variant selection, fallback and empty-message behavior, legacy snapshot migration, mode changes, and model changes.
GitOrigin-RevId: d4c6c0028423bc50b0e8175e55586f3e7bc1c3a8
## Why
Matching model ETags can arrive on every response, but a recent models cache does
not need to be rewritten each time.
## What changed
Renew the models cache timestamp only after more than half of its configured TTL
has elapsed. Matching ETags continue to avoid refetching `/models`.
## Testing
Added integration coverage that verifies a recent cache remains unchanged and an
older cache is renewed without another `/models` request.
GitOrigin-RevId: b45da3824674c6b41d982ba4a405b419b09b7715
## What changed
- Add token-budget settings to model catalog messages and apply them when the
feature is enabled without explicit token-budget configuration.
- Keep explicit user settings authoritative, reject invalid catalog defaults,
and preserve resolved defaults in exported config locks.
- Manage context-window guidance through world state so it updates once when
the active model changes while retaining prior conversation history.
## Testing
- Cover catalog defaults, explicit overrides, disabled features, invalid
values, config-lock replay, and model switching.
GitOrigin-RevId: 54544fefaa14b09f5ef5bad9967a13c52b87b0fe
## What changed
- Add the action-risk review prompt template and default generic security policy to the `codex-auto-review` catalog entry.
- Define its `never` approval and `danger_full_access`, `workspace_write`, and `read_only` permission messages.
GitOrigin-RevId: 025bb609c12ae9d5235054747267a1ee46d118ef
## 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
## What changed
- Add model-catalog approval message variants for `never` and `unless_trusted`.
- Select the catalog message that matches the active approval policy, while retaining the existing built-in text when that variant is absent.
- Treat an explicitly empty variant as an instruction to suppress the built-in approval text, consistent with `on_request` messages.
## Testing
- Cover variant selection, fallback and empty-message behavior, catalog deserialization, and the initial permissions message sent to the model.
GitOrigin-RevId: a0f8d41a08645f39b80093be53f200eeee18ca25
## What changed
- Add personality instruction variables for the GPT-5.6 model variants.
- Add the GPT-5.5 availability notice.
- Remove the `auto_review` and `permissions` message fields and the legacy `supports_reasoning_summary_parameter` flag from the bundled catalog.
GitOrigin-RevId: 426b0735a78232d2f658e0124db7c45889d08286
## What changed
- Set the bundled GPT-5.6 model variants' context windows to 272,000 tokens.
- Refresh model instructions and message configuration.
- Record reasoning-summary support and update skills, permissions, and auto-review metadata across the model catalog.
GitOrigin-RevId: 8be55124bf50af14756a174033a5cb362f4db714
## What changed
- Add an optional `policy_template` field to auto-review model messages.
- Build Guardian instructions from the catalog template when present, while
preserving the existing precedence for managed and catalog policy content.
- Fall back independently to the bundled template and bundled policy, and
preserve explicit empty catalog values.
## Testing
- Cover missing and empty template deserialization, policy precedence, bundled
fallbacks, and Guardian prewarm instructions.
GitOrigin-RevId: 93116dadbc9bf40527882844a428caed4159fff6
## 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
- Add per-sandbox-mode permission messages to `ModelMessages` and preserve them when applying model configuration overrides.
- Use the selected catalog message in permission instructions, substituting `{{ network_access }}` with the active network policy. Fall back to the existing sandbox text when no override is provided, and allow an empty override to omit only the sandbox section.
- Apply catalog permission messages when a session starts and when its model changes.
## Testing
- Cover catalog deserialization, mode selection, network substitution, fallback and empty-message behavior, remote model catalogs, and model changes.
GitOrigin-RevId: cd5ed3aee3155dca0e7b2358c0f09bae73236856
## 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
- Add an `auto_review.policy` field to model catalog messages.
- Use the selected Guardian model's catalog policy for review-session instructions, while preserving the precedence of `guardian_policy_config` and falling back to the built-in policy when neither is present.
- Preserve auto-review messages when model instruction overrides remove catalog instruction templates.
## Testing
- Cover configured-policy precedence, explicit empty catalog policies, catalog-message preservation, and propagation of the catalog policy into a prewarmed Guardian session.
GitOrigin-RevId: 26b61ae2958ea8325a64834dcf91f47e140d74b3
## What changed
- Add `supports_reasoning_summary_parameter` to model metadata, defaulting to
`true` for backward compatibility.
- Omit `reasoning.summary` and its summary-delivery stream option when the
selected model does not support the parameter.
- Apply the capability of the final selected model when a spawned agent uses a
different model.
## Testing
- Cover unsupported models in regular requests and spawned-agent model
overrides.
GitOrigin-RevId: 72b783799fc0685cef1501ef2dbf62d1308ceead
## Why
Model catalog instructions can include a baked-in `# Personality` section. An
explicit `none` setting should omit that section instead of sending it as part
of the model's base instructions.
## What changed
- Pass the configured personality into the models manager.
- When personality support is enabled and the setting is explicitly `none`,
remove the `# Personality` section through the next level-one heading from
catalog base instructions and instruction templates.
- Preserve explicit `base_instructions` overrides and avoid warning when no
personality was requested.
## Testing
Added unit and integration coverage for section removal, heading boundaries,
CRLF input, preserved configurations, and explicit base instructions.
GitOrigin-RevId: 452c88d3ac6001c2ac7d4fef269cd75dc239fa61
## 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
## Summary
External auth had two paths: provider-command credentials were resolved
through `ExternalAuth`, while app-provided ChatGPT credentials were
installed separately and only used the provider for refresh.
`ExternalAuth` also declared an auth mode independently from the
`CodexAuth` value it returned, so the declaration and credentials could
disagree.
This change makes the provider-owned `CodexAuth` authoritative for
initial resolution, credential kind, and refresh.
- remove `ExternalAuth::auth_mode` and require providers to return their
current auth from `resolve`
- route external auth registration, resolution, and unauthorized refresh
through `AuthManager::set_external_auth`
- keep the last resolved credential with its provider so synchronous
consumers and unauthorized recovery observe the credential's actual mode
- make the app-server bridge own both initial and refreshed ChatGPT
credentials, and detach it on logout
- keep model listing free of auth-refresh side effects, including in
offline mode
Provider-command auth still follows its configured cache interval.
App-provided ChatGPT auth still asks the parent app once after a `401`
and retries the request once.
Stacked on #31355.
## Testing
- `just test -p codex-login`
- `just test -p codex-models-manager`
- focused `codex-app-server` tests for external login/logout,
unauthorized refresh, and workspace mismatch
## Why
Approval guidance is currently assembled entirely by the client. Model
Messages V2 needs model catalogs to provide model-specific `on_request`
guidance for both user-reviewed and auto-reviewed approval flows while
retaining the existing generated prompt as a compatibility fallback.
## What changed
- add nullable `on_request` and `on_request_auto_review` catalog
messages
- select the message matching the active approvals reviewer for
`on_request` policies
- replace the complete legacy approval section when the selected catalog
value exists, including support for an empty string that suppresses the
section
- retain legacy rendering when the object or selected key is absent, and
for non-`on_request` policies
- preserve approval messages when base-instruction or personality
overrides clear instruction templates
- refresh permissions instructions when the active model changes
- pass catalog messages through initial and incremental permissions
construction
## Relationship to reviewer persistence
PR #31309 independently persists the approvals reviewer in turn context
and refreshes permissions when that reviewer changes. This PR is based
directly on `main` and does not duplicate that rollout migration; once
both land, reviewer switches will also select and append the new catalog
variant.
## Testing
- `just test -p codex-protocol`
- `just test -p codex-prompts`
- `just test -p codex-models-manager`
- `just test -p codex-core permissions_messages`
## Summary
- refactor `ExternalAuth` to return `CodexAuth` directly
- remove the parallel `ExternalAuthTokens` wrapper
- preserve existing external bearer and app-server refresh behavior
This is a mechanical precursor refactor; it does not add auth
capabilities or change recovery behavior.
## Testing
- `cargo fmt --all`
- `cargo test -q -p codex-login --lib`
- `cargo test -q -p codex-app-server --test all
external_auth_refreshes_on_unauthorized`
## Summary
- add a false-by-default `include_skills_usage_instructions` model
metadata field
- enable the field for the bundled `gpt-5.5` model metadata
- consume the metadata in both core and extension skill rendering
- remove hardcoded legacy-model matching and its marker plumbing
## Why
Helper threads such as task title generation can request a model ID that
is valid for the default OpenAI provider but unavailable from the active
provider. With Amazon Bedrock, `gpt-5.4-mini` is rejected while the
provider static catalog exposes Bedrock model IDs such as
`openai.gpt-5.5` and `openai.gpt-5.4`. This causes repeated background
404s and can surface a misleading turn error even when the main turn
succeeds.
Clients need an explicit way to ask app-server to resolve an unavailable
helper model to the active provider default. That fallback must remain
limited to providers with an authoritative static catalog so custom or
dynamically discovered model IDs are not rewritten based on an
incomplete catalog.
Fixes#28741.
## What changed
- Add the experimental `allowProviderModelFallback` option to
`thread/start`, defaulting to `false` to preserve existing behavior.
- Thread the option through thread creation and model selection.
- When enabled for a static model manager, preserve requested models
present in the catalog and replace unavailable models with the provider
default.
- Continue preserving explicit model IDs for dynamic model managers
without fetching a catalog solely to validate them.
- Document the new `thread/start` behavior in the app-server API
overview.
## Test
Temporary test-client harness:
```
ThreadStartParams {
model: Some("gpt-5.4-mini".to_string()),
allow_provider_model_fallback: true,
..Default::default()
}
```
Command:
```
CODEX_HOME=/tmp/codex-bedrock-thread-start-home \
CODEX_E2E_BEDROCK_THREAD_START_ONLY=1 \
./target/debug/codex-app-server-test-client \
--codex-bin ./target/debug/codex \
-c 'model_provider="amazon-bedrock"' \
send-message-v2 --experimental-api ignored
```
Relevant output:
```
> "method": "thread/start",
> "params": {
> "model": "gpt-5.4-mini",
> "modelProvider": null,
> "allowProviderModelFallback": true,
> ...
> }
< "result": {
< "model": "openai.gpt-5.5",
< "modelProvider": "amazon-bedrock",
< ...
< }
```
## Why
Authentication mode is a domain concept used by login, model selection,
telemetry, and transports. Keeping the canonical type in app-server
protocol forces those lower-level crates to depend on an unrelated wire
API.
## What changed
- Added canonical `codex_protocol::auth::AuthMode` domain values.
- Kept the app-server wire DTO unchanged and added an explicit app-side
conversion.
- Removed production app-server-protocol dependencies from login,
model-provider-info, models-manager, and otel call paths.
## Stack
This is PR 2 of 6, stacked on [PR
#29714](https://github.com/openai/codex/pull/29714). Review only the
delta from `codex/split-json-rpc-protocols`. Next: [PR
#29722](https://github.com/openai/codex/pull/29722).
## Validation
- Auth and login coverage passed in the focused protocol/domain test
run.
- App-server account and auth conversion coverage passed.
## Summary
Stacked on #26706.
Adds the shared auth/system-proxy contract that later platform resolver
PRs plug into. This PR moves Codex-owned auth and startup HTTP clients
through a common route-aware boundary, but does not yet add Windows or
macOS system proxy resolution.
The default path remains unchanged when `respect_system_proxy` is absent
or disabled.
## Implementation
- Adds `codex-client/src/outbound_proxy.rs` with the shared
route-selection model:
- `OutboundProxyConfig`;
- `ClientRouteClass`;
- `RouteFailureClass`;
- `build_reqwest_client_for_route`.
- Preserves the existing reqwest/default-client behavior when no route
config is supplied.
- Uses the fixed MVP routing policy when route config is supplied:
platform system/PAC/WPAD discovery, then explicit env proxy variables,
then direct connection.
- Keeps platform-specific system discovery behind the shared client
boundary. This PR provides the contract and fallback behavior; later
resolver PRs plug in Windows and macOS discovery.
- Adds `login::AuthRouteConfig` so auth call sites depend on a small
policy type instead of platform resolver details.
- Maps the resolved `Config.respect_system_proxy` boolean into
`AuthRouteConfig` for auth-owned clients.
- Wires the route config through browser login, device-code login,
access-token login, login status, logout/revoke, token refresh, API-key
exchange, app-server account login, TUI/app startup, cloud-config
bootstrap, cloud tasks, plugin auth, and exec startup config loading.
## End-user behavior
- No behavior changes by default.
- When `respect_system_proxy = true`, auth-owned clients opt into the
shared route-aware client path.
- On platforms without a resolver implementation in this PR, system
discovery is unavailable and the route-aware path falls back to explicit
env proxy handling, then direct connection.
- Custom CA handling remains separate from proxy route selection and
still runs through the shared client builder.
- No proxy URLs, PAC contents, or resolved platform details are exposed
through the public config surface introduced here.
## Tests
Adds or updates coverage for:
- preserving default auth-client fallback behavior when no route config
is provided;
- injected environment-proxy fallback without mutating process
environment;
- existing login-server E2E flows using explicit `auth_route_config:
None` to guard unchanged default behavior;
- updated auth manager, login, logout, cloud-config, startup, and
plugin-auth call sites passing route config explicitly.
## Intent
Keep Bazel and Starlark files consistently formatted without requiring
contributors to install or version buildifier themselves.
## Implementation
- Add a SHA-256-pinned, cross-platform DotSlash manifest for buildifier
v8.5.1.
- Run buildifier from the shared `just fmt` and `just fmt-check` driver,
with Windows-safe explicit DotSlash invocation.
- Provision DotSlash in formatting CI and contributor devcontainers, and
document the source-build prerequisite.
- Apply the initial mechanical buildifier formatting baseline.
## Why
Windows Credential Manager limits generic credential blobs to 2,560
bytes. Large serialized ChatGPT auth payloads can exceed that limit, so
keyring-mode CLI auth needs a backend that keeps only the encryption key
in the OS keyring and stores the payload in Codex's encrypted
local-secrets file.
This is the third PR in the encrypted-auth stack:
1. #27504 — feature and config selection
2. #27535 — auth-specific local-secrets namespaces
3. This PR — CLI auth implementation and activation
4. MCP OAuth implementation and activation
## What Changed
- Added encrypted CLI-auth storage using the `CliAuth` secrets
namespace.
- Preserved direct keyring storage for platforms/configurations where it
remains selected.
- Selected the backend consistently for login, logout, refresh,
device-code login, auth loading, and login restrictions.
- Threaded resolved bootstrap/full config through CLI, exec, TUI,
app-server account handling, cloud config, and cloud tasks.
- Removed stale `auth.json` fallback data after successful encrypted
saves and removed encrypted, direct-keyring, and fallback data during
logout.
- Added storage and integration coverage for both direct and encrypted
keyring modes.
MCP OAuth persistence is intentionally left to the next PR.
## Validation
- `just test -p codex-login` — 131 passed
- `just test -p codex-cli` — 280 passed
- `just test -p codex-app-server v2::account` — 25 passed
- `just test -p codex-cloud-config service` — 21 passed, 7 skipped
- `just fix -p codex-login`
- `just fix -p codex-cli`
- `just fmt`
## 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`
## Summary
- add optional `comp_hash` metadata to `ModelInfo`
- update `ModelInfo` fixtures for the shared schema change
- keep older model responses compatible by defaulting the field to
`None`
## Why
The models endpoint needs an opaque identifier for compaction-compatible
model configurations. This PR only exposes that value in model metadata;
it does not add it to turn context or change runtime behavior.
Follow-up #27520 carries the value through turn context and rollouts,
then uses it to trigger compaction.
## Stack
- based directly on `main`
- replaces #27519, which was accidentally merged into the wrong base
branch
- functionality follow-up: #27520
## Testing
- `just test -p codex-protocol
model_info_defaults_availability_nux_to_none_when_omitted`
- `just fix -p codex-core -p codex-protocol -p codex-analytics -p
codex-models-manager`
## 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.
## 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.
## Summary
- add a defaulted `ModelInfo.use_responses_lite` catalog field
- support serializing `reasoning.context` while preserving the existing
effort and summary path
- has not been turned on for any models yet
I've added an override to parallel tools if responses_lite is on. I've
also forced persistent reasoning when using responses_lite. It would be
ideal if we could centralize all the responses_lite plumbing, but I
think this is best for now to keep the plumbing & diffs small.
## Testing
- `cargo test -p codex-protocol
model_info_defaults_availability_nux_to_none_when_omitted`
- `RUST_MIN_STACK=8388608 cargo test -p codex-core
responses_lite_sets_all_turns_context_and_disables_parallel_tool_calls`
- `RUST_MIN_STACK=8388608 cargo test -p codex-core
configured_reasoning_summary_is_sent`
- `cargo check -p codex-core --tests`
- `RUST_MIN_STACK=8388608 cargo clippy -p codex-core --tests` (passes
with pre-existing warnings in `codex-code-mode` and
`codex-core-plugins`)
Stack split from #25708. Original PR intentionally left open. This first
PR adds the multi-agent runtime metadata types and catalog plumbing used
by the rest of the stack.
## Why
Guardian auto-review normally uses the provider-preferred review model
when one is available. Some parent models need model-catalog metadata to
select a different review model while keeping older `/models` payloads
compatible when that metadata is absent.
## What changed
- Added optional `ModelInfo::auto_review_model_override` metadata to the
public model payload as a review-model slug.
- Updated Guardian review model selection to prefer the catalog override
when present, while preserving the existing provider preferred-model
path and parent-model fallback when it is omitted.
- Added focused Guardian coverage for override and no-override model
selection.
- Added an `auto_review` core integration suite test that loads override
metadata from a remote model catalog path and asserts the strict
auto-review `/responses` request uses the catalog-selected review model.
- Updated existing `ModelInfo` fixtures and local catalog constructors
for the new optional field.
## Validation
- `cargo test -p codex-protocol
model_info_defaults_availability_nux_to_none_when_omitted`
- `cargo test -p codex-core guardian_review_uses_`
- `cargo test -p codex-core
remote_model_override_uses_catalog_model_for_strict_auto_review --test
all`
- `just fix -p codex-protocol`
- `just fix -p codex-core`
- `just fmt`
- `git diff --check`