Commit Graph
4 Commits
Author SHA1 Message Date
Felipe Coury 40e7dda4d2 perf(config): defer remote sandbox hostname lookup (#28542)
## Why

[#18763](https://github.com/openai/codex/pull/18763) added canonical
hostname resolution for `remote_sandbox_config`. Requirements
composition currently performs that synchronous DNS lookup on every
fresh process, even when none of the loaded requirements layers contains
`[[remote_sandbox_config]]`. On hosts with slow local DNS resolution,
this can add several seconds to Codex startup.

## What

- defer hostname resolution until a parsed requirements layer actually
contains `remote_sandbox_config`
- cache the resolver result once per requirements composition,
preserving the existing single-lookup behavior across multiple layers
- keep the existing FQDN resolution and per-layer requirements
precedence unchanged
- cover both the ordinary no-lookup path and the multi-layer
single-lookup path

## How to Test

On a host where local canonical-name resolution is slow:

1. Start Codex without `[[remote_sandbox_config]]` in any managed
requirements layer and confirm startup no longer waits for hostname
resolution.
2. Add a matching `[[remote_sandbox_config]]` entry and confirm its
`allowed_sandbox_modes` still overrides the layer's top-level value.
3. Add remote sandbox entries to multiple requirements layers and
confirm precedence remains unchanged while the hostname is resolved only
once.

Targeted tests:

- `just test -p codex-config hostname_resolver`
- `just test -p codex-config` (181 passed)
2026-06-16 11:17:41 -04:00
Anton Panasenko b9dc3b7a8b feat(app-server): enforce managed remote control disable (#27961)
## Why

Managed deployments need a reliable deny gate for remote control.
Persisted enablement and explicit startup requests currently remain able
to start the transport, while the removed `features.remote_control` key
is intentionally only a compatibility no-op.

This adds a dedicated requirement that administrators can use to force
remote control off without deleting the user's persisted preference.
Removing the requirement and restarting restores the prior choice.

## What Changed

- Added top-level `allow_remote_control` requirements parsing, sourced
layer precedence, debug output, and `configRequirements/read` exposure
as `allowRemoteControl`.
- Added a typed transport policy captured from the startup requirements
snapshot. Managed disable forces the initial state to disabled and
prevents enrollment, refresh, connection, and persisted-preference
mutation.
- Rejected every `remoteControl/*` RPC before parameter deserialization
with JSON-RPC `-32600` and `remote control is disabled by managed
requirements`.
- Preserved the existing disabled status notification and the previous
behavior when the requirement is `true` or omitted.
- Regenerated app-server protocol schemas and documented the new
requirement.

## Verification

- Confirmed all remote-control RPCs, including a malformed request,
return the managed-policy error while the initial status notification
remains `disabled`.
- Confirmed explicit ephemeral startup and persisted enablement make no
backend connection and leave the SQLite preference unchanged.
- Confirmed `allow_remote_control = true` does not enable or block
remote control and `configRequirements/read` returns
`allowRemoteControl: false` for the deny policy.

Related issue: N/A (managed-policy hardening).
2026-06-12 20:10:12 -07:00
viyatb-oaiandCodex 2f108f9fd9 permissions: enforce managed permission profile allowlists (#24852)
## Why

Permission profile allowlists are an enterprise security boundary, but
they also need to compose across the managed requirements layers added
in #24620.

A map representation lets each requirements layer add, allow, or revoke
individual profiles without replacing an entire array.

## Managed Contract

Administrators configure the mergeable allow map with
`allowed_permission_profiles`. A recommended enterprise configuration
explicitly lists every built-in and custom profile users should be able
to select:

```toml
default_permissions = "review_only"

[allowed_permission_profiles]
":read-only" = true
":workspace" = true
review_only = true
# ":danger-full-access" is intentionally omitted, so it is denied.

[permissions.review_only]
extends = ":read-only"
```

- Profiles whose effective merged value is `true` are allowed.
- Missing profiles and profiles set to `false` are denied.
- This is a closed allowlist: built-in profiles and profiles introduced
in future versions are denied unless explicitly allowed.
- Explicitly list each built-in profile the enterprise wants to make
available. Omit built-ins such as `:danger-full-access` when they should
remain unavailable.
- Set `default_permissions` explicitly to the allowed profile users
should receive when they have no local selection.
- Higher-precedence layers override only the profile keys they define.
- `false` is only needed when a higher-precedence layer must revoke a
`true` inherited from a lower layer.
- Explicit keys must refer to known built-in or managed profiles.

A custom or narrowed allowlist requires an allowed
`default_permissions`. For compatibility, if both `:workspace` and
`:read-only` are explicitly allowed, an omitted default resolves to
`:workspace`; customer configurations should still set the intended
default explicitly.

When `allowed_permission_profiles` is absent, existing implicit
permission and legacy `sandbox_mode` behavior is unchanged.

## What Changed

- Add `allowed_permission_profiles` as a `BTreeMap<String, bool>` that
merges per profile across requirements layers.
- Enforce managed defaults, strict denial of omitted profiles, and the
explicitly allowed standard-pair fallback.
- Expose `allowedPermissionProfiles` through `configRequirements/read`
and regenerate its schemas.
- Add regression coverage for map composition and revocation, managed
defaults, strict denial of omitted built-ins, and API output.

## Verification

- Focused `codex-config` coverage for layered map composition and
revocation
- Focused `codex-core` coverage for managed defaults, invalid defaults,
strict denial of omitted built-ins, and the standard built-in pair
- Focused `codex-app-server` coverage for requirements API output
- Scoped Clippy for `codex-config`, `codex-core`,
`codex-app-server-protocol`, and `codex-app-server`

## Documentation

The managed `requirements.toml` documentation should introduce
`allowed_permission_profiles` as a closed permission-profile allowlist
before this setting is published on developers.openai.com.

---------

Co-authored-by: Codex <noreply@openai.com>
2026-06-05 18:06:29 -07:00
joeflorencio-openai 20debf746b Compose requirements layers (#24619)
## Summary

PR 2 of 5 in the cloud-managed config client stack.

Adds a shared requirements-layer composition engine. The composer
defines how ordered requirements layers combine, with focused tests for
the merge semantics and provenance behavior. The final PR in the stack
wires runtime requirements sources into this path.

## Details

- Mental model: requirements layers are ordered lowest priority first,
matching `ConfigLayerStack`; lower-priority layers provide defaults
while higher-priority layers win scalar/list conflicts.
- Regular fields use config-style TOML merging, including recursive
table merging, so requirements layering follows the same broad model as
`config.toml` layering.
- Domain-specific fields keep explicit semantics: `rules.prefix_rules`
and hooks preserve high-priority-first output, hooks fail closed on
active managed-dir conflicts, and `permissions.filesystem.deny_read`
dedupes as a stable high-priority-first union.
- `remote_sandbox_config` is evaluated within each layer before the
regular TOML merge, so host-specific sandbox constraints do not leak
across layers.
- Provenance points at the exact source when one layer owns a value and
uses composite provenance when a table field is assembled from multiple
layers.

## Validation

Local validation:

- `just fmt`
- `cargo check -p codex-config`
- `just test -p codex-config requirements_composition`
- `git diff --check`

CI will run the broader test matrix.
2026-05-31 15:14:06 -07:00