permissions: migrate approval and sandbox consumers to profiles (#19393)

## Why

Runtime decisions should not infer permissions from the lossy legacy
sandbox projection once `PermissionProfile` is available. In particular,
`Disabled` and `External` need to remain distinct, and managed profiles
with split filesystem or deny-read rules should not be collapsed before
approval, network, safety, or analytics code makes decisions.

## What Changed

- Changes managed network proxy setup and network approval logic to use
`PermissionProfile` when deciding whether a managed sandbox is active.
- Migrates patch safety, Guardian/user-shell approval paths, Landlock
helper setup, analytics sandbox classification, and selected
turn/session code to profile-backed permissions.
- Validates command-level profile overrides against the constrained
`PermissionProfile` rather than a strict `SandboxPolicy` round trip.
- Preserves configured deny-read restrictions when command profiles are
narrowed.
- Adds coverage for profile-backed trust, network proxy/approval
behavior, patch safety, analytics classification, and command-profile
narrowing.

## Verification

- `cargo test -p codex-core direct_write_roots`
- `cargo test -p codex-core runtime_roots_to_legacy_projection`
- `cargo test -p codex-app-server
requested_permissions_trust_project_uses_permission_profile_intent`




































































---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/19393).
* #19395
* #19394
* __->__ #19393
This commit is contained in:
Michael Bolin authored and GitHub committed 2026-04-26 15:30:40 -07:00
1 parent 9c3abcd46c
commit dda8199b73
24 files changed
+367 -164

No files matched your search

+1 -1
View File
@@ -874,7 +874,7 @@ pub(crate) fn build_guardian_review_session_config(
guardian_config.permissions.network = Some(NetworkProxySpec::from_config_and_constraints(
live_network_config,
network_constraints,
&SandboxPolicy::new_read_only_policy(),
guardian_config.permissions.permission_profile.get(),
)?);
}
for feature in [
+6 -3
View File
@@ -27,6 +27,7 @@ use codex_protocol::ThreadId;
use codex_protocol::approvals::NetworkApprovalProtocol;
use codex_protocol::config_types::ApprovalsReviewer;
use codex_protocol::models::ContentItem;
use codex_protocol::models::PermissionProfile;
use codex_protocol::models::ResponseItem;
use codex_protocol::protocol::AskForApproval;
use codex_protocol::protocol::EventMsg;
@@ -1942,7 +1943,7 @@ async fn guardian_review_session_config_preserves_parent_network_proxy() {
}),
..Default::default()
}),
parent_config.permissions.sandbox_policy.get(),
parent_config.permissions.permission_profile.get(),
)
.expect("network proxy spec");
parent_config.permissions.network = Some(network.clone());
@@ -2007,7 +2008,7 @@ async fn guardian_review_session_config_uses_live_network_proxy_state() {
NetworkProxySpec::from_config_and_constraints(
parent_network,
/*requirements*/ None,
parent_config.permissions.sandbox_policy.get(),
parent_config.permissions.permission_profile.get(),
)
.expect("parent network proxy spec"),
);
@@ -2032,7 +2033,9 @@ async fn guardian_review_session_config_uses_live_network_proxy_state() {
NetworkProxySpec::from_config_and_constraints(
live_network,
/*requirements*/ None,
&SandboxPolicy::new_read_only_policy(),
&PermissionProfile::from_legacy_sandbox_policy(
&SandboxPolicy::new_read_only_policy(),
),
)
.expect("live network proxy spec")
)