mirror of
https://github.com/openai/codex.git
synced 2026-05-03 10:56:37 +00:00
permissions: make runtime config profile-backed (#19606)
## Why This supersedes #19391. During stack repair, GitHub marked #19391 as merged into a temporary stack branch rather than into `main`, so the runtime-config change needed a fresh PR. `PermissionProfile` is now the canonical permissions shape after #19231 because it can distinguish `Managed`, `Disabled`, and `External` enforcement while also carrying filesystem rules that legacy `SandboxPolicy` cannot represent cleanly. Core config and session state still needed to accept profile-backed permissions without forcing every profile through the strict legacy bridge, which rejected valid runtime profiles such as direct write roots. The unrelated CI/test hardening that previously rode along with this PR has been split into #19683 so this PR stays focused on the permissions model migration. ## What Changed - Adds `Permissions.permission_profile` and `SessionConfiguration.permission_profile` as constrained runtime state, while keeping `sandbox_policy` as a legacy compatibility projection. - Introduces profile setters that keep `PermissionProfile`, split filesystem/network policies, and legacy `SandboxPolicy` projections synchronized. - Uses a compatibility projection for requirement checks and legacy consumers instead of rejecting profiles that cannot round-trip through `SandboxPolicy` exactly. - Updates config loading, config overrides, session updates, turn context plumbing, prompt permission text, sandbox tags, and exec request construction to carry profile-backed runtime permissions. - Preserves configured deny-read entries and `glob_scan_max_depth` when command/session profiles are narrowed. - Adds `PermissionProfile::read_only()` and `PermissionProfile::workspace_write()` presets that match legacy defaults. ## 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/19606). * #19395 * #19394 * #19393 * #19392 * __->__ #19606
This commit is contained in:
@@ -2880,7 +2880,11 @@ allow_local_binding = true
|
||||
};
|
||||
let mut builder = test_codex().with_home(home).with_config(move |config| {
|
||||
config.permissions.approval_policy = Constrained::allow_any(approval_policy);
|
||||
config.permissions.sandbox_policy = Constrained::allow_any(SandboxPolicy::DangerFullAccess);
|
||||
let cwd = config.cwd.clone();
|
||||
config
|
||||
.permissions
|
||||
.set_legacy_sandbox_policy(SandboxPolicy::DangerFullAccess, cwd.as_path())
|
||||
.expect("test setup should allow sandbox policy");
|
||||
let layers = config
|
||||
.config_layer_stack
|
||||
.get_layers(
|
||||
|
||||
@@ -8,8 +8,7 @@ use codex_core::spawn::CODEX_SANDBOX_ENV_VAR;
|
||||
use codex_protocol::config_types::WindowsSandboxLevel;
|
||||
use codex_protocol::error::Result;
|
||||
use codex_protocol::exec_output::ExecToolCallOutput;
|
||||
use codex_protocol::permissions::FileSystemSandboxPolicy;
|
||||
use codex_protocol::permissions::NetworkSandboxPolicy;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_protocol::protocol::SandboxPolicy;
|
||||
use codex_sandboxing::SandboxType;
|
||||
use codex_sandboxing::get_platform_sandbox;
|
||||
@@ -52,12 +51,11 @@ where
|
||||
};
|
||||
|
||||
let policy = SandboxPolicy::new_read_only_policy();
|
||||
let permission_profile = PermissionProfile::from_legacy_sandbox_policy(&policy);
|
||||
|
||||
process_exec_tool_call(
|
||||
params,
|
||||
&policy,
|
||||
&FileSystemSandboxPolicy::from(&policy),
|
||||
NetworkSandboxPolicy::from(&policy),
|
||||
&permission_profile,
|
||||
&cwd,
|
||||
&None,
|
||||
/*use_legacy_landlock*/ false,
|
||||
|
||||
@@ -672,12 +672,24 @@ async fn steered_user_input_follows_compact_when_only_the_steer_needs_follow_up(
|
||||
async fn steered_user_input_waits_when_tool_output_triggers_compact_before_next_request() {
|
||||
let (gate_first_completed_tx, gate_first_completed_rx) = oneshot::channel();
|
||||
|
||||
let large_output_command = if cfg!(windows) {
|
||||
"[Console]::Out.Write([string]::new([char]'0', 4000))"
|
||||
} else {
|
||||
"printf '%04000d' 0"
|
||||
};
|
||||
let large_output_args = json!({
|
||||
"command": large_output_command,
|
||||
"login": false,
|
||||
"timeout_ms": 2000,
|
||||
})
|
||||
.to_string();
|
||||
|
||||
let first_chunks = vec![
|
||||
chunk(ev_response_created("resp-1")),
|
||||
chunk(ev_function_call(
|
||||
"call-1",
|
||||
"shell_command",
|
||||
r#"{"command":"printf '%04000d' 0","login":false,"timeout_ms":2000}"#,
|
||||
&large_output_args,
|
||||
)),
|
||||
gated_chunk(
|
||||
gate_first_completed_rx,
|
||||
|
||||
@@ -550,7 +550,10 @@ async fn permissions_message_includes_writable_roots() -> Result<()> {
|
||||
|
||||
let mut builder = test_codex().with_config(move |config| {
|
||||
config.permissions.approval_policy = Constrained::allow_any(AskForApproval::OnRequest);
|
||||
config.permissions.sandbox_policy = Constrained::allow_any(sandbox_policy_for_config);
|
||||
config
|
||||
.permissions
|
||||
.set_legacy_sandbox_policy(sandbox_policy_for_config, config.cwd.as_path())
|
||||
.expect("test sandbox policy should be allowed");
|
||||
config.config_layer_stack = ConfigLayerStack::default();
|
||||
});
|
||||
let test = builder.build(&server).await?;
|
||||
|
||||
Reference in New Issue
Block a user