## 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
Auth routing represented the default proxy policy as an absent configuration,
leaving consumers to reconstruct the fallback HTTP client independently. Carry
the application's resolved policy explicitly so auth and related requests use
the same client configuration.
## What changed
- Build `AuthRouteConfig` from the resolved `HttpClientFactory` for both
`ReqwestDefault` and `RespectSystemProxy` policies.
- Pass that route configuration through login, auth, cloud task, and cloud
configuration flows, and reuse its factory when loading cloud configuration.
- Log cloud-task configuration load failures before falling back to the
transport-default proxy policy.
## Testing
Extended configuration tests to verify that effective and bootstrap auth routes
select the expected proxy policy when system-proxy support is enabled or
disabled by feature requirements.
GitOrigin-RevId: d03802e2660f5cf6d940e8e718ec5c82ede7eab1
## Why
Elevated Windows sandboxes need stable managed-proxy ports while preserving the network policy and environment attribution of each sandboxed process.
## What changed
- Keep shared HTTP and SOCKS5 loopback ingress listeners alive across managed-proxy instances.
- Add a per-route restricting SID to elevated sandbox tokens and dispatch incoming connections to the matching proxy policy after attributing the client process.
- Reject connections without exactly one registered route, remove routes when their proxy handle is dropped, and keep unsandboxed Windows launches off the managed ingress.
- Provision the elevated sandbox with the configured proxy ports and local-binding setting, honoring the selected profile and CLI overrides.
## Testing
- Add Windows unit tests for TCP ownership attribution, route selection, restricting-token propagation, and setup settings.
- Add an end-to-end Windows test covering stable ports, isolated environment policies, HTTP and SOCKS5 routing, and route teardown.
GitOrigin-RevId: 783fac6e0f904dc9bb1955b75d4a5895e8bb9690
## Why
Default read-only protections for project metadata should apply when paths such
as `.git`, `.agents`, and `.codex` exist, without causing sandbox setup to
materialize missing paths as ACL targets.
## What changed
- Add an optional `missing_path_behavior` to filesystem sandbox entries and
mark default project-metadata protections with `skip`.
- Preserve the behavior through permission transforms and exec/MCP protocol
serialization while keeping existing path wire variants stable.
- Ignore skip-missing entries when projecting configuration or Windows sandbox
overrides, while retaining explicit metadata carveouts.
## Testing
- Cover protocol round trips for path and special-path entries.
- Verify default metadata protections and Windows explicit carveout handling.
GitOrigin-RevId: 6df13dadacdd131c44aab9f15a967c81051355c1
## What changed
- Apply managed values for `sqlite_home`, `log_dir`, `model_catalog_json`,
`check_for_update_on_startup`, `allow_login_shell`, the report-submission
opt-in, and `windows.sandbox_private_desktop` to the runtime configuration,
with source-aware warnings when they override configured values.
- Expose these values through `configRequirements/read`, return them from
`config/read`, include them in session config locks, and show their sources in
the TUI config debug view.
- Reject app-server writes that overlap an exact managed requirement with
`configRequirementReadonly` while leaving unrelated sibling keys writable.
## Testing
- Cover runtime overrides, requirement API mapping, config reads and writes,
session lock serialization, cross-platform path URIs, and debug output.
GitOrigin-RevId: d4e23b6fd7775c1a6dfe2eab313cdcee50b07081
## What changed
- Add `shell_environment_policy.filters`, mapping environment-variable patterns to `include` or `exclude`, while continuing to accept the legacy `exclude` and `include_only` arrays.
- Merge filter keys case-insensitively across config layers so higher-precedence entries can override individual patterns. Switching representations replaces the other representation instead of combining them.
- Reject mixed, duplicate, or malformed filter definitions in enabled layers, config writes, and reloads, while retaining the previous session configuration when a reload is invalid.
- Make config-manager reads and writes representation-aware and preserve existing formatting when updating individual policy values.
## Testing
Add coverage for parsing, schema constraints, layered merging, validation and diagnostics, config writes, override metadata, and invalid session reloads.
GitOrigin-RevId: e15464bca53e6e7ef31fcc97537fda60ed5d670a
## Why
Remote plugin requests did not use Codex's effective outbound proxy policy, so
they could bypass configured system proxy and PAC routing.
## What changed
- Route remote plugin catalog, mutation, sharing, upload, and bundle download
requests through the configured route-aware HTTP client.
- Select routes using the complete request URL, including encoded query
parameters and backend-provided signed upload or download URLs.
- Preserve standard Codex headers and suppress diagnostics for URLs or headers
that may contain credentials.
## Testing
Add coverage for route selection of catalog queries, workspace plugin uploads,
and backend-provided bundle download URLs.
GitOrigin-RevId: 106936659e21decf145b6ab4d4be84992e386861
## Why
The curated plugin startup sync can fall back from Git to HTTP, but those
requests did not use Codex's effective outbound proxy policy.
## What changed
- Thread the configured HTTP client factory into curated plugin sync.
- Route GitHub API, zipball, backup metadata, and returned download URLs
through the route-aware client when system proxy support is enabled.
- Preserve the existing default HTTP client behavior, including its custom CA
fallback, when system proxy support is disabled.
- Apply the standard Codex headers to startup-sync HTTP requests.
## Testing
Add coverage that records route selection for repository, archive, metadata,
and backend-supplied download URLs, and verifies standard headers are sent.
GitOrigin-RevId: e1ea13bdab58a84c9948a2c8b82a5ec5c964ea99
## Why
Permission profiles defined by `requirements.toml` can be selected as active,
but their network configuration was not included when resolving the network
proxy specification for that selection.
## What changed
Merge managed permission profiles from `requirements.toml` with configured
profiles before looking up the active profile's network proxy settings.
## Testing
- Verify config loading retains the proxy settings of an active managed
profile.
- Verify `turn/start` accepts a managed profile with network settings.
GitOrigin-RevId: 3374f82a8fb0ce8f338fa2cea77c28ea2eb89636
## What changed
- Remove the `spawn_agents_on_csv` and `report_agent_job_result` tools and their agent-job runtime and state models.
- Drop the legacy `agent_jobs` and `agent_job_items` tables during state database migration.
- Keep `features.enable_fanout` and `agents.job_max_runtime_seconds` accepted as no-op compatibility settings while omitting them from the generated configuration schema.
## Testing
- Verify upgrades remove both legacy agent-job tables.
- Verify the removed feature and configuration keys still parse without taking effect.
GitOrigin-RevId: 8cc3337da78c67162229f02f40a747f503542646
## What changed
- Remove unused APIs and test helpers across the Rust workspace.
- Route Linux sandbox test setup through the shared exec request path.
- Drop dependencies that became unnecessary after the cleanup.
GitOrigin-RevId: 48fd9b2b1575bad7add0819786b4d8ec88d8486f
## What changed
- Add `tui.resume_cwd` with `current` and `session` modes for resume and fork flows.
- Let users persist either mode directly from the working-directory prompt, while preserving one-time choices when no preference is configured.
- Apply the preference consistently during startup and in-app resume, honor explicit `--cd` overrides, and reject unsupported or unavailable directory choices with a clear error.
## Testing
- Cover configuration parsing and persistence, prompt behavior, startup and in-app flows, session metadata fallback, and remote workspace constraints.
GitOrigin-RevId: 7bf144c4b8c55bdb868cc8a71caf397c7740451a
## 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
- Represent built-in filesystem policy entries with the same `Path` and
`Special` variants used by other entries.
- Remove generated-default filtering from Windows sandbox policy resolution and
simplify elevated deny-write handling to rely on direct-runtime enforcement
and the legacy policy projection.
- Update protocol conversions, policy transforms, and profile expectations for
the reduced filesystem path model.
GitOrigin-RevId: a65793e6855a03d52a575e82cb3d4b9b2e32db5c
## What changed
- Apply `agents.default_subagent_model` and
`agents.default_subagent_reasoning_effort` when a spawn request does not
provide explicit values, including agent job workers.
- Allow full-history forks to use configured defaults or explicit model and
reasoning-effort overrides while retaining the parent conversation context.
- Preserve the selected model and reasoning effort when an agent role does not
override them.
## Testing
- Cover configured defaults, explicit override precedence, full-history forks,
role application, and agent job workers.
GitOrigin-RevId: b1efa8c9abeee82355088fceef57560433144595
## Why
The `agent_type` argument is only useful when agent roles are configured. Avoid
advertising an inapplicable override in the model-visible `spawn_agent` schema.
## What changed
- Include `agent_type` in the V1 and V2 spawn tools only when configured roles
are available.
- Clarify that `agent_type` is an explicit override and document its interaction
with context forking.
- Remove the unused `agents.support_agent_type` configuration field.
## Testing
- Add coverage for hiding `agent_type` without roles and exposing it when a role
is configured.
GitOrigin-RevId: 32e0f123b15f317e9cdb71774029375bc073d9ad
## What changed
- Add `agents.enabled` as a user override for multi-agent tools while keeping an enabled `features.multi_agent_v2` authoritative.
- Rename the shared spawned-thread limit to `agents.max_concurrent_threads_per_session`, retain `agents.max_threads` as an alias, and apply the setting to both multi-agent backends.
- Add reserved subagent model, reasoning effort, and agent-type settings to the config surface and persist all resolved agent settings in config locks.
- Show the resolved `[agents]` values in TUI debug-config output.
## Testing
- Cover config loading, legacy alias normalization across merged layers, backend-selection precedence, V2 concurrency, and debug output.
GitOrigin-RevId: 2957c954a2e1aef51592768dbbccd56c4bf8f118
## What changed
- Remove the standalone network proxy config loader, its mtime-based reloader, and their tests.
- Remove the helper exports and MITM action-reference validator used only by that loader.
GitOrigin-RevId: 60895fb4e3461e8c3f19db70869050410a4f5f07
## Why
Windows firewall enforcement is tied to the logon-user sandbox identities. Proxy-enforced commands therefore need the elevated backend even when the configured sandbox mode is the default restricted-token mode.
## What changed
- Select the elevated Windows sandbox backend whenever a command uses the managed network proxy.
- Remove configuration and startup checks that required users or managed requirements to select the elevated sandbox explicitly.
- Start and expose managed network proxy state consistently on Windows.
## Testing
- Verify that proxy enforcement selects the elevated backend for the restricted-token sandbox mode.
GitOrigin-RevId: e01ac052587721c468a8fbcf4e2c7c5a185a3e05
## Why
Elevated Windows sandbox setup could turn the built-in read-only protections
for workspace metadata into deny-write paths, creating metadata directories
that did not already exist.
## What changed
- Track whether filesystem permission entries come from a built-in profile or
were explicitly configured.
- Exclude generated metadata defaults from direct Windows deny-write overrides
while continuing to enforce explicit read-only carveouts for the same paths.
- Preserve the distinction while materializing and normalizing permission
paths, without exposing generated defaults as user configuration.
## Testing
Added Windows coverage confirming that elevated sandbox setup leaves missing
workspace metadata absent and still produces overrides for explicit metadata
carveouts.
GitOrigin-RevId: 701bcb229f631b18ab5ced22f3edf6f303d932f3
## Why
Token-budget sessions need a final opportunity to preserve important state before the current context is compacted.
## What changed
- When `auto_compact_fallback_prompt` is configured, reserve `auto_compact_fallback_buffer_tokens` beyond the base auto-compaction limit.
- At the base limit, inject the fallback prompt once as a developer message while keeping the normal tool surface available. Continue reporting zero base-window tokens during this reserve.
- Roll over when the reserve or full model context is exhausted, and skip the fallback when a new context was already requested.
## Testing
Added coverage for using the fallback reserve, rolling over after it is exhausted, and bypassing the fallback for an explicit `new_context` request.
GitOrigin-RevId: 32983ecadc5cb4927e15ecd7b1e896cb52a9ad3b
## What changed
- Add `auto_compact_fallback_prompt` and
`auto_compact_fallback_buffer_tokens` to `features.token_budget` and the
generated configuration schema.
- Trim empty fallback prompts, limit prompts to 2,000 bytes, require a buffer
when a prompt is configured, and reject non-positive buffer values.
- Preserve the new settings when locking resolved session configuration.
## Testing
- Cover config resolution and validation for overlong prompts, missing
buffers, and non-positive buffers.
- Extend the configuration-lock test to cover both settings.
GitOrigin-RevId: 6463f963ba1dbd633d76601b8344360a8c85cf8b
## Why
Special filesystem subpaths can contain relative or foreign-platform path
spellings. Treating this wire text as a host-native path can reinterpret it.
## What changed
- Store special filesystem subpaths as strings in the core permissions model.
- Represent app-server subpaths as `LegacyAppPathString` and convert them at
the protocol boundary without changing their spelling.
- Add `LegacyAppPathString::from_string` for callers that already own legacy
app-server path text.
GitOrigin-RevId: 2214f03aa997fd0e6eb2ab60d425304bb4bd6132
## Why
Network proxy enforcement on Windows requires the elevated sandbox backend. Silently selecting that backend for an unelevated configuration makes the effective sandbox differ from the configured mode.
## What changed
- Reject enabled network proxy configurations on Windows unless managed requirements allow only the elevated sandbox and `windows.sandbox` resolves to `"elevated"`.
- Preserve the configured sandbox backend during execution and validate proxy compatibility at config loading, sandbox setup, and process launch boundaries.
- Defer this validation during cloud-config bootstrap so authoritative managed requirements can be loaded first.
- Do not start or expose disabled Windows proxies, and render transitions to disabled networking as `<network enabled="false"></network>`.
## Testing
- Cover Windows requirement and sandbox compatibility matrices, bootstrap behavior, backend selection, disabled proxy handling, and environment-context updates.
GitOrigin-RevId: bfa1dda98594e0db61883f8e7f65bd560e3453e6
## What changed
- Add the `features.multi_agent_v2.expose_spawn_agent_model_overrides` setting, enabled by default, to expose `model` and `reasoning_effort` on the v2 `spawn_agent` tool.
- Keep these controls available when other spawn metadata is hidden, while allowing them to be disabled independently.
- Add root-agent and subagent guidance that overrides require a partial or context-free fork and should only be used when explicitly authorized.
## Testing
- Cover configuration parsing and defaults, usage-hint preservation, and tool-schema behavior with override exposure enabled and disabled.
GitOrigin-RevId: 92370498108c96fbd51f32965624ce531e991d9a
## 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
## Why
`NetworkProxyConfig` only wrapped `NetworkProxySettings` in a single
`network` field. That extra level made runtime callers repeat `.network`
everywhere without representing a real boundary.
## What changed
- move the managed-network fields directly onto `NetworkProxyConfig`
- collapse the matching partial-config wrapper
- update runtime callers and tests to use the direct fields
- keep the user-facing permissions/profile TOML layout unchanged
The internal serialized shape now matches the runtime type itself. This
does not change managed-network behavior or the `config.toml` shape.
## Summary
- enable `auth_elicitation` by default
- promote the feature to `Stable`, as default-enabled features must be
stable
- update the feature regression test to cover the new lifecycle state
and default
## Impact
Auth elicitation is now available without requiring users or clients to
opt in through configuration.
## Testing
- `just test -p codex-features` (52 passed)
## Summary
- Adds `writes` to `AppToolApproval` and exposes it through config and
app-server schemas, including
`[apps._default].default_tools_approval_mode`.
- In `writes`, tools with `readOnlyHint = true` skip approval; all other
tools prompt, including non-destructive writes and tools without
annotations.
- Prevents session or persistent approval choices in this mode so later
writes still prompt.
## Why
`auto` only prompts for risk-hinted actions, while `prompt` also
interrupts reads. Apps need a middle mode that gates writes without
prompting for declared read-only actions.
## Validation
- `just write-config-schema`
- `just write-app-server-schema`
- `just fmt`
- `just test -p codex-core mcp_turn_metadata` (4 passed)
- `just test -p codex-core writes_mode` (2 passed)
- `just test -p codex-app-server config_read_includes_apps` (1 passed)
- `just test -p codex-app-server-protocol` (251 passed)
- `just test -p codex-config` (200 passed)
- `just test -p codex-cli` (300 passed)
- `just fix -p codex-core -p codex-config -p codex-app-server-protocol
-p codex-app-server -p codex-cli`
## Why
`features.respect_system_proxy` already routes authentication traffic
through the OS proxy APIs, but it does not affect the primary inference
path. That leaves users behind OS-managed proxies unable to send normal
Responses API requests even after login succeeds.
This PR is the first product-path migration onto the route-aware
transport introduced in #31323 and refined in #31331. It also
establishes the construction pattern for later migrations: the effective
feature state is resolved once into a required HTTP client factory
rather than represented by an optional per-call setting.
The scope remains limited to the two HTTP Responses endpoints;
WebSockets, model discovery, memories, realtime, and file uploads remain
follow-up migrations.
## What changed
- Replace the optional proxy marker with an explicit
`OutboundProxyPolicy::{ReqwestDefault, RespectSystemProxy}` and a
required `HttpClientFactory`. The policy has no default, and the
lower-level route-aware reqwest builder is now private.
- Have `Config` construct the factory from the effective feature state
and require every `ModelClient` constructor to receive it. There is no
optional setter or implicit `None` fallback.
- Build HTTP clients for `/responses` and `/responses/compact` with
`ClientRouteClass::Api`, using the complete destination URL so PAC rules
can make URL-specific decisions.
- Layer route-aware selection onto Codex's existing default headers,
Cloudflare cookie store, custom CA handling, and sandbox no-proxy
behavior.
- Add an integration test that loads `features.respect_system_proxy`
through `config.toml`, creates a real Codex session, and verifies that
both a normal Responses turn and remote compaction reach an isolated
local proxy.
## Review guide
1. `http-client/src/outbound_proxy.rs` defines the mandatory
policy/factory boundary and keeps route resolution private.
2. `core/src/config/mod.rs`, `core/src/session/session.rs`, and
`core/src/client.rs` show the compile-time invariant: effective config
creates the factory, and `ModelClient` cannot be constructed without
one.
3. `login/src/auth/default_client.rs` preserves existing default-client
behavior while accepting the required factory for migrated routes.
4. `core/src/client.rs` switches only streaming Responses and remote
compaction HTTP transports to the API route class.
5. `core/tests/suite/responses_api_system_proxy.rs` is the behavioral
regression boundary. Its Linux subprocess deliberately sets the CGI
marker that disables reqwest's implicit environment-proxy handling, so
the test fails if session wiring or either Responses call site falls
back to the default client.
## Test plan
- `cargo check --tests -p codex-http-client -p codex-login -p
codex-core`
- `just test -p codex-login`
- `just test -p codex-core
respect_system_proxy_feature_resolves_enabled`
- Existing `compact_uses_bearer_after_agent_identity_session_fallback`
coverage passes with the new transport construction.
- New Linux integration coverage:
`responses_and_compact_use_enabled_system_proxy`
- `just bazel-lock-check`
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/31335).
* #31342
* __->__ #31335
## Why
Generic plugin guidance is currently emitted only with initial context
from host plugin state. An executor-selected plugin can become available
later in the same turn, making its skills and tools usable without ever
telling the model how plugin capabilities should be used.
## What
- project every ready selected plugin package, including skill-only
plugins
- carry plugin availability with the exact MCP runtime projection while
preserving MCP manager reuse when servers and connectors are unchanged
- move generic plugin guidance from the static initial-context path into
persisted World State
- recognize legacy and retained plugin fragments so resume and
compaction do not duplicate guidance
## Testing
- `just test -p codex-mcp-extension`
- `just test -p codex-core plugins_instructions`
- `just test -p codex-core
plugin_availability_change_reuses_the_mcp_manager`
- `just test -p codex-app-server --test all selected_capabilit`
## Why
Multi-agent V2 normally derives its mode instructions from reasoning
effort: Ultra enables proactive delegation, while other efforts require
an explicit request. Some deployments need to provide one configured
delegation policy that replaces those built-ins and remains stable when
reasoning effort changes.
## What changed
- Add `features.multi_agent_v2.multi_agent_mode_hint_text` alongside the
existing root and subagent hint settings.
- Treat any configured value, including an empty string, as
`MultiAgentMode::Custom(hint_text)`, so the configured text replaces the
built-in explicit-only and proactive policies.
- Persist the full custom variant and hint text in the turn-context
snapshot, so the durable comparison baseline detects both
reasoning-effort changes and configured policy-text changes.
- Preserve the existing explicit-only/proactive behavior when the
setting is absent.
- Replace the ambiguous `MultiAgentMode::None` variant with
`MultiAgentMode::Custom(String)` in new rollouts and API schemas. A
compatibility wire type maps legacy serialized `none` values to
`Custom("")` when resuming existing rollouts.
- Regenerate the config and app-server schemas.
## Configuration examples
The distinction is whether `multi_agent_mode_hint_text` is present. An
empty string is still a configured value and intentionally suppresses
the built-in mode instructions.
### Unset: preserve existing effort-derived behavior
```toml
[features.multi_agent_v2]
enabled = true
# multi_agent_mode_hint_text is omitted
```
- Ultra reasoning uses the built-in proactive delegation instructions.
- Other reasoning efforts use the built-in explicit-request-only
instructions.
### Empty: suppress all mode hint text
```toml
[features.multi_agent_v2]
enabled = true
multi_agent_mode_hint_text = ""
```
This selects effective mode `custom` at every reasoning effort and
injects an empty mode body, suppressing both built-in policies.
### Set: always use the configured text
```toml
[features.multi_agent_v2]
enabled = true
multi_agent_mode_hint_text = "Delegate to subagents when it will materially improve the result."
```
This selects effective mode `custom` at every reasoning effort and
injects the configured text verbatim instead of either built-in policy.
## Verification
- `just test -p codex-core multi_agent_mode`
- Covers a configured hint across High and Ultra reasoning efforts and
verifies the full custom hint is recorded for both turns.
- Covers an empty-string override suppressing both built-in instruction
bodies.
- `just test -p codex-protocol -p codex-app-server-protocol`
- Covers legacy `none` turn-context deserialization as `Custom("")` and
verifies the regenerated schemas.
## Why
Admins need persistent defaults for the model, reasoning effort, and
service tier shown when the Desktop App creates a new thread. These are
initialization defaults rather than runtime constraints: the App should
use them to initialize its draft while still allowing a user to make an
explicit selection.
The app-server therefore needs to expose the managed values before
thread creation without changing `thread/start` behavior for other
clients.
## What changed
- Parse `model`, `model_reasoning_effort`, and `service_tier` from
`[models.new_thread]` in `requirements.toml`.
- Compose the `models` requirements through the existing
requirements-layer precedence rules.
- Expose the resolved values through `configRequirements/read` as
`requirements.models.newThread`.
- Add the corresponding app-server protocol types and regenerate the
JSON and TypeScript schema fixtures.
- Document the new `configRequirements/read` fields in the app-server
README.
## Scope
This PR is data plumbing only. It does not apply these values during
`thread/start` and does not change thread creation for existing
app-server clients, resumed or forked sessions, internal or subagent
sessions, `codex exec`, or the TUI. A companion Desktop App change owns
draft initialization, sends the effective settings for ordinary and
prewarmed starts, and preserves explicit user changes.
## Validation
- Requirements deserialization coverage for `[models.new_thread]`
- Requirements-layer precedence coverage
- App-server API mapping coverage
- `configRequirements/read` integration coverage
- Regenerated app-server JSON and TypeScript schema fixtures
## Summary
This PR extends the existing managed `mcp_servers` identity requirement
so that one name-qualified rule can use either:
- the released exact command or URL identity;
- an exact stdio executable with an exact-length, ordered argument
matcher list; or
- a direct MCP URL matcher.
Matcher-based rules stay under the released `identity` key and use the
same `McpServerRequirement` abstraction and `mcp_servers.<server_name>`
namespace.
## Behavior
Policy activation and name qualification are unchanged:
- If `mcp_servers` is absent, ordinary configured MCP servers remain
unrestricted.
- If `mcp_servers` is present, a server needs a matching same-name
requirement.
- `mcp_servers = {}` continues to deny every configured MCP server.
- Existing exact identity requirements keep their released semantics.
Plugin-bundled MCP servers use the same requirement shapes under
`plugins.<plugin_name>.mcp_servers.<server_name>`. Top-level non-empty
rules continue to govern only ordinary configured servers; plugin rules
remain explicitly plugin-scoped. The existing globally empty
`mcp_servers = {}` plugin kill switch is preserved.
Requirements layers continue to use the existing regular TOML merge
behavior. Atomic replacement of named MCP requirements is intentionally
out of scope here and is tracked independently in #30118.
## Requirement contract
The released exact identity contract remains valid:
```toml
[mcp_servers.docs.identity]
command = "codex-mcp"
[mcp_servers.remote.identity]
url = "https://example.com/mcp"
```
Command identities continue to check only `command`; they do not inspect
arguments, `cwd`, `env`, or `env_vars`.
A command matcher uses an exact executable plus an exact-length, ordered
argument list. Each argument position supports `exact`, `prefix`, or
full-value `regex` matching:
```toml
[mcp_servers.internal_mcp_proxy.identity]
command = { executable = "company-cli", args = [
{ match = "exact", value = "mcp" },
{ match = "exact", value = "proxy" },
{ match = "exact", value = "--server" },
{ match = "regex", expression = '^https://[A-Za-z0-9-]+\.mcp\.internal\.example\.com(?::443)?(?:/.*)?$' },
] }
```
Direct streamable HTTP MCP definitions can use the same value matcher
types through `identity.url`:
```toml
[mcp_servers.internal_http.identity]
url = {
match = "regex",
expression = '^https://[A-Za-z0-9-]+\.mcp\.internal\.example\.com(?:/.*)?$',
}
```
Plugin-bundled MCP matchers use the same contract inside the
plugin-qualified allowlist:
```toml
[plugins."sample@test".mcp_servers.internal_mcp_proxy.identity]
command = { executable = "company-cli", args = [
{ match = "exact", value = "mcp" },
{ match = "exact", value = "proxy" },
] }
```
Regexes are validated while managed requirements are loaded, and regex
matching must cover the complete value. Command matchers constrain only
the executable and arguments.
## Why
Enterprise administrators need to allow MCP servers by executable and
positional-argument shape, including fixed arguments plus constrained
values such as internal MCP URLs passed to a proxy.
## Validation
- `just fmt`
- `git diff --check`
- `just test -p codex-config` (198 passed)
- `just test -p codex-core mcp_servers_by_matchers --lib` (2 passed)
A zero interval lets callers request a reminder at every
otherwise-eligible inference boundary.
## Validation
- just test -p codex-core load_config_resolves_current_time_reminder
## Why
Token-budget reminder and guidance messages can require more than 1,000
bytes to provide useful model-facing instructions. At the same time,
these strings are injected into model-visible context, so their size
must remain tightly bounded in response to the P0 context-growth
concern. A 2,000-byte runtime cap provides additional room without
allowing the substantially larger context growth of a 4 KiB limit.
## What changed
- raises the runtime byte limits for token-budget reminder templates and
guidance messages from 1,000 to 2,000
- raises the corresponding JSON Schema `maxLength` values to 2,000
- regenerates `codex-rs/core/config.schema.json`
## Testing
- `just test -p codex-features`
- `just test -p codex-core load_config_resolves_token_budget_config
load_config_rejects_invalid_token_budget_reminder_template`
The full `codex-core` test run completed 2,858 tests successfully and
encountered seven unrelated environment-sensitive failures involving
Seatbelt/network environment assertions, MCP capability setup, and abort
timing.
## 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
ChatGPT session authentication was inferred from the reserved Codex Apps
server name. That couples credential routing to Codex Apps-specific
behavior and prevents other MCP endpoints hosted by ChatGPT from
explicitly using the current session.
The opt-in also needs a clear security boundary: an arbitrary MCP
configuration must not be able to redirect ChatGPT credentials to
another origin.
## What changed
- Add `use_chatgpt_auth` to HTTP MCP server configuration, defaulting to
`false`.
- Honor the setting only when the parsed server URL has the same HTTP(S)
origin as the configured `chatgpt_base_url`; otherwise remove the
capability before startup.
- Resolve bearer tokens and static or environment-backed authorization
headers before selecting authentication, with configured authorization
taking precedence over ChatGPT session auth.
- Enable the setting for the built-in Codex Apps and hosted plugin
runtime endpoints while keeping Codex Apps caching and tool
normalization scoped to the reserved server.
- Persist the setting through MCP config rewrite paths and expose it in
the generated config schema.
- Load the current login state for `codex mcp list` so reported auth
status matches runtime behavior.
## Verification
Core integration coverage exercises the complete streamable HTTP MCP
startup path and verifies that:
- a same-origin opted-in server receives the current ChatGPT access
token;
- an explicitly configured authorization header takes precedence;
- a different-origin server completes MCP initialization and tool
listing without receiving any ChatGPT authorization header.
## Why
This PR adds a configurable `<context_window_guidance>` developer
section immediately after `<context_window>`. Harness integrations need
this section to give the model deployment-specific instructions for
preparing for context-window transitions.
## What changed
- Add an optional `features.token_budget.guidance_message` config with a
1,000-byte runtime cap and generated schema support.
- Render configured guidance as a developer `ContextualUserFragment`
wrapped in `<context_window_guidance>` immediately after
`<context_window>`.
- Omit the section when guidance is unset, empty, or whitespace-only.
- Preserve the resolved value in config locks and classify persisted
guidance as contextual developer content.
- Add integration coverage for rendered content and ordering.
## Summary
- move sleep tool enablement from top-level `[features].sleep_tool` to
`[features.current_time_reminder].sleep_tool`
- remove the standalone `Feature::SleepTool` flag and gate `clock.sleep`
from resolved current-time configuration
- update config schema, config-lock materialization, and existing sleep
coverage
Stacked on #29907.
## Why
Connector declarations currently enter Codex through broad plugin
capability summaries, then MCP setup, turn tooling, and `app/list` each
reconstruct the same information. That makes executor-selected
connectors difficult to add without coupling connector behavior to the
host plugin loader.
This PR introduces a small connector-owned value that later stack layers
can populate before thread startup.
## What changed
- Move the pure app-declaration parser into `codex-connectors`,
preserving declaration order and category cleanup while leaving
host-side validation and deduplication unchanged.
- Add an immutable `ConnectorSnapshot` with ordered connector IDs and
plugin display-name provenance.
- Adapt the existing local-plugin capability summaries into that
snapshot at current consumer boundaries.
- Use the snapshot for MCP tool provenance, turn connector inventory,
and `app/list`.
- Keep the crate API narrow: no test-only snapshot accessors are
exposed.
The externally visible behavior is unchanged. Connector tools still come
from the orchestrator-owned `/ps/mcp` server, and local plugin
enablement remains owned by the existing plugin loader.
## Stack scope
This is the foundation only. It does not read selected executor packages
or change thread startup. #29852 adds the executor-backed declaration
reader, and #29856 composes selected declarations into a thread
snapshot.
## Why
Config layer provenance describes how effective configuration was
assembled, so it belongs with the config loader rather than in
app-server's serialized API types.
## What changed
- Moved `ConfigLayerSource`, `ConfigLayerMetadata`, and `ConfigLayer`
ownership into `codex-config`.
- Kept app-server's wire payloads unchanged and added explicit
conversions at the app boundary.
- Removed lower-level app-server-protocol dependencies from config
consumers.
## Stack
This is PR 3 of 6, stacked on [PR
#29721](https://github.com/openai/codex/pull/29721). Review only the
delta from `codex/split-auth-domain-types`. Next: [PR
#29723](https://github.com/openai/codex/pull/29723).
## Validation
- `codex-config` coverage passed.
- App-server config-manager and config RPC coverage passed.
## Why
Managed deployments need a mergeable way to declare which marketplace
sources Codex may use. An enterprise-keyed TOML table avoids array merge
ambiguity and lets every requirements layer use the existing config
precedence rules without a marketplace-specific merger.
## Requirements shape
```toml
[marketplaces]
restrict_to_allowed_sources = true
[marketplaces.allowed_sources.company_plugins]
source = "git"
url = "https://github.com/example/company-plugins.git"
ref = "main"
[marketplaces.allowed_sources.internal_git]
source = "host_pattern"
host_pattern = "^git\\.example\\.com$"
[marketplaces.allowed_sources.local_plugins]
source = "local"
path = "/opt/company/codex-plugins"
```
`restrict_to_allowed_sources` follows normal scalar precedence.
`allowed_sources` follows normal recursive TOML table merge behavior:
distinct keys accumulate and fields under the same key use normal layer
precedence. The final `source` value later selects which fields the
marketplace admission policy interprets.
The raw rule fields remain optional while requirements layers are
composed, so a higher-priority layer can override only `ref`, `url`, or
another individual field. Source-specific validation and normalization
intentionally belong to the marketplace admission layer, not
requirements merging.
This initial shape includes `git`, `host_pattern`, and `local` sources.
It does not add npm or path-pattern rules.
## What changed
- Add the marketplace requirements TOML shape to
`ConfigRequirementsToml`, `ConfigRequirementsWithSources`, and
`ConfigRequirements`.
- Carry marketplace requirements through the existing regular
requirements merge path.
- Keep allowed-source entries as raw partial tables for downstream
policy interpretation.
- Cover partial same-key overlays, source changes, unknown fields, and
unmodified local paths.
This PR defines and composes the requirements only. Source admission is
implemented by the next PR in the stack.
## Stack
This is PR 1 of 3. #29753 adds source admission on top of this PR; draft
#29691 will add runtime enforcement after it is rebased later.
## Test plan
- `just test -p codex-config marketplace_`
## Summary
- rename `reminder_interval_model_requests` to
`reminder_interval_seconds`
- read the configured time provider before every model request and
inject a reminder only after the configured number of seconds has
elapsed
- preserve immediate first delivery and forced delivery after compaction
changes the context window
## Tests
- `just test -p codex-core current_time_reminder`
## Summary
Multi-agent v2 tools now use the fixed `collaboration` namespace when
namespace tools are available. This keeps the model-visible hint and the
actual tool surface aligned around `functions.collaboration.*`, without
exposing an unshipped namespace knob to users.
The PR also removes the old `features.multi_agent_v2.tool_namespace`
config/schema surface, updates the MAv2 test fixtures for namespaced
calls, and fixes stale `TurnContext.features` references that were
breaking `codex-core` builds.
## Changes
- Expose MAv2 tools under `collaboration` instead of relying on a
configurable namespace.
- Remove `tool_namespace` from MAv2 TOML config, resolved config,
validation, schema, and tests.
- Update tool-planning and integration fixtures to assert or emit
namespaced MAv2 tool calls.
- Read feature state through `TurnContext.config.features` in the
multi-agent mode context paths.
## Testing
- `just write-config-schema`
- `just test -p codex-features`
## Why
Remote stdio MCP servers can run in an environment whose path convention
differs from the Codex host. A Windows cwd such as
`C:\Users\openai\share` is absolute for the executor but was rejected by
a POSIX orchestrator.
Built on #29501, now merged, which only clarifies the host-native
`PathUri` constructor name.
## What changed
- Deserialize MCP cwd values as `LegacyAppPathString` so config does not
apply host path rules.
- Interpret that spelling as host-native for local launches and convert
it to `PathUri` at executor launch.
- Skip host filesystem and command resolution checks for remote stdio in
`codex doctor`.
- Add host-independent config and executor-boundary coverage using the
foreign path convention for each test platform.
## Validation
- `just test -p codex-utils-path-uri -p codex-config -p codex-mcp -p
codex-rmcp-client` (408 passed)
- `just test -p codex-cli -p codex-rmcp-client` (372 passed)
- `cargo check --workspace --tests`
- `just test` (11,311 passed; 43 unrelated environment/timing failures)
- `just fix -p codex-cli -p codex-config -p codex-core -p codex-mcp -p
codex-mcp-extension -p codex-rmcp-client -p codex-tui`