diff --git a/codex-rs/core/tests/suite/request_permissions.rs b/codex-rs/core/tests/suite/request_permissions.rs index 455c1fabb9..1821094e1a 100644 --- a/codex-rs/core/tests/suite/request_permissions.rs +++ b/codex-rs/core/tests/suite/request_permissions.rs @@ -7,13 +7,14 @@ use codex_features::Feature; use codex_protocol::config_types::ApprovalsReviewer; use codex_protocol::models::AdditionalPermissionProfile as PermissionProfile; use codex_protocol::models::FileSystemPermissions; +use codex_protocol::models::PermissionProfile as RuntimePermissionProfile; +use codex_protocol::permissions::NetworkSandboxPolicy; use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::ExecApprovalRequestEvent; use codex_protocol::protocol::GranularApprovalConfig; use codex_protocol::protocol::Op; use codex_protocol::protocol::ReviewDecision; -use codex_protocol::protocol::SandboxPolicy; use codex_protocol::request_permissions::PermissionGrantScope; use codex_protocol::request_permissions::RequestPermissionProfile; use codex_protocol::request_permissions::RequestPermissionsResponse; @@ -31,6 +32,7 @@ use core_test_support::skip_if_no_network; use core_test_support::skip_if_sandbox; use core_test_support::test_codex::TestCodex; use core_test_support::test_codex::test_codex; +use core_test_support::test_codex::turn_permission_fields; use core_test_support::wait_for_event; use pretty_assertions::assert_eq; use regex_lite::Regex; @@ -182,9 +184,11 @@ async fn submit_turn( test: &TestCodex, prompt: &str, approval_policy: AskForApproval, - sandbox_policy: SandboxPolicy, + permission_profile: RuntimePermissionProfile, ) -> Result<()> { let session_model = test.session_configured.model.clone(); + let (sandbox_policy, permission_profile) = + turn_permission_fields(permission_profile, test.cwd.path()); test.codex .submit(Op::UserTurn { environments: None, @@ -197,7 +201,7 @@ async fn submit_turn( approval_policy, approvals_reviewer: Some(ApprovalsReviewer::User), sandbox_policy, - permission_profile: None, + permission_profile, model: session_model, effort: None, summary: None, @@ -283,13 +287,13 @@ async fn expect_request_permissions_event( } } -fn workspace_write_excluding_tmp() -> SandboxPolicy { - SandboxPolicy::WorkspaceWrite { - writable_roots: vec![], - network_access: false, - exclude_tmpdir_env_var: true, - exclude_slash_tmp: true, - } +fn workspace_write_excluding_tmp() -> RuntimePermissionProfile { + RuntimePermissionProfile::workspace_write_with( + &[], + NetworkSandboxPolicy::Restricted, + /*exclude_tmpdir_env_var*/ true, + /*exclude_slash_tmp*/ true, + ) } fn requested_directory_write_permissions(path: &Path) -> RequestPermissionProfile { @@ -319,14 +323,15 @@ async fn with_additional_permissions_requires_approval_under_on_request() -> Res let server = start_mock_server().await; let approval_policy = AskForApproval::OnRequest; - let sandbox_policy = SandboxPolicy::new_read_only_policy(); - let sandbox_policy_for_config = sandbox_policy.clone(); + let permission_profile = RuntimePermissionProfile::read_only(); + let permission_profile_for_config = permission_profile.clone(); let mut builder = test_codex().with_config(move |config| { config.permissions.approval_policy = Constrained::allow_any(approval_policy); config - .set_legacy_sandbox_policy(sandbox_policy_for_config) - .expect("set sandbox policy"); + .permissions + .set_permission_profile(permission_profile_for_config) + .expect("set permission profile"); config .features .enable(Feature::ExecPermissionApprovals) @@ -372,7 +377,7 @@ async fn with_additional_permissions_requires_approval_under_on_request() -> Res ) .await; - submit_turn(&test, call_id, approval_policy, sandbox_policy.clone()).await?; + submit_turn(&test, call_id, approval_policy, permission_profile.clone()).await?; let approval = expect_exec_approval(&test, command).await; assert_eq!( approval.additional_permissions, @@ -416,14 +421,15 @@ async fn request_permissions_tool_is_auto_denied_when_granular_request_permissio request_permissions: false, mcp_elicitations: true, }); - let sandbox_policy = SandboxPolicy::new_read_only_policy(); - let sandbox_policy_for_config = sandbox_policy.clone(); + let permission_profile = RuntimePermissionProfile::read_only(); + let permission_profile_for_config = permission_profile.clone(); let mut builder = test_codex().with_config(move |config| { config.permissions.approval_policy = Constrained::allow_any(approval_policy); config - .set_legacy_sandbox_policy(sandbox_policy_for_config) - .expect("set sandbox policy"); + .permissions + .set_permission_profile(permission_profile_for_config) + .expect("set permission profile"); config .features .enable(Feature::RequestPermissionsTool) @@ -463,7 +469,7 @@ async fn request_permissions_tool_is_auto_denied_when_granular_request_permissio &test, "request permissions under granular.request_permissions = false", approval_policy, - sandbox_policy, + permission_profile, ) .await?; @@ -501,14 +507,15 @@ async fn relative_additional_permissions_resolve_against_tool_workdir() -> Resul let server = start_mock_server().await; let approval_policy = AskForApproval::OnRequest; - let sandbox_policy = SandboxPolicy::new_read_only_policy(); - let sandbox_policy_for_config = sandbox_policy.clone(); + let permission_profile = RuntimePermissionProfile::read_only(); + let permission_profile_for_config = permission_profile.clone(); let mut builder = test_codex().with_config(move |config| { config.permissions.approval_policy = Constrained::allow_any(approval_policy); config - .set_legacy_sandbox_policy(sandbox_policy_for_config) - .expect("set sandbox policy"); + .permissions + .set_permission_profile(permission_profile_for_config) + .expect("set permission profile"); config .features .enable(Feature::ExecPermissionApprovals) @@ -564,7 +571,7 @@ async fn relative_additional_permissions_resolve_against_tool_workdir() -> Resul ) .await; - submit_turn(&test, call_id, approval_policy, sandbox_policy.clone()).await?; + submit_turn(&test, call_id, approval_policy, permission_profile.clone()).await?; let approval = expect_exec_approval(&test, command).await; assert_eq!( @@ -604,14 +611,15 @@ async fn read_only_with_additional_permissions_does_not_widen_to_unrequested_cwd let server = start_mock_server().await; let approval_policy = AskForApproval::OnRequest; - let sandbox_policy = SandboxPolicy::new_read_only_policy(); - let sandbox_policy_for_config = sandbox_policy.clone(); + let permission_profile = RuntimePermissionProfile::read_only(); + let permission_profile_for_config = permission_profile.clone(); let mut builder = test_codex().with_config(move |config| { config.permissions.approval_policy = Constrained::allow_any(approval_policy); config - .set_legacy_sandbox_policy(sandbox_policy_for_config) - .expect("set sandbox policy"); + .permissions + .set_permission_profile(permission_profile_for_config) + .expect("set permission profile"); config .features .enable(Feature::ExecPermissionApprovals) @@ -660,7 +668,7 @@ async fn read_only_with_additional_permissions_does_not_widen_to_unrequested_cwd ) .await; - submit_turn(&test, call_id, approval_policy, sandbox_policy.clone()).await?; + submit_turn(&test, call_id, approval_policy, permission_profile.clone()).await?; let approval = expect_exec_approval(&test, &command).await; assert_eq!( @@ -706,14 +714,15 @@ async fn read_only_with_additional_permissions_does_not_widen_to_unrequested_tmp let server = start_mock_server().await; let approval_policy = AskForApproval::OnRequest; - let sandbox_policy = SandboxPolicy::new_read_only_policy(); - let sandbox_policy_for_config = sandbox_policy.clone(); + let permission_profile = RuntimePermissionProfile::read_only(); + let permission_profile_for_config = permission_profile.clone(); let mut builder = test_codex().with_config(move |config| { config.permissions.approval_policy = Constrained::allow_any(approval_policy); config - .set_legacy_sandbox_policy(sandbox_policy_for_config) - .expect("set sandbox policy"); + .permissions + .set_permission_profile(permission_profile_for_config) + .expect("set permission profile"); config .features .enable(Feature::ExecPermissionApprovals) @@ -763,7 +772,7 @@ async fn read_only_with_additional_permissions_does_not_widen_to_unrequested_tmp ) .await; - submit_turn(&test, call_id, approval_policy, sandbox_policy.clone()).await?; + submit_turn(&test, call_id, approval_policy, permission_profile.clone()).await?; let approval = expect_exec_approval(&test, &command).await; assert_eq!( @@ -807,14 +816,15 @@ async fn workspace_write_with_additional_permissions_can_write_outside_cwd() -> let server = start_mock_server().await; let approval_policy = AskForApproval::OnRequest; - let sandbox_policy = workspace_write_excluding_tmp(); - let sandbox_policy_for_config = sandbox_policy.clone(); + let permission_profile = workspace_write_excluding_tmp(); + let permission_profile_for_config = permission_profile.clone(); let mut builder = test_codex().with_config(move |config| { config.permissions.approval_policy = Constrained::allow_any(approval_policy); config - .set_legacy_sandbox_policy(sandbox_policy_for_config) - .expect("set sandbox policy"); + .permissions + .set_permission_profile(permission_profile_for_config) + .expect("set permission profile"); config .features .enable(Feature::ExecPermissionApprovals) @@ -873,7 +883,7 @@ async fn workspace_write_with_additional_permissions_can_write_outside_cwd() -> ) .await; - submit_turn(&test, call_id, approval_policy, sandbox_policy.clone()).await?; + submit_turn(&test, call_id, approval_policy, permission_profile.clone()).await?; let approval = expect_exec_approval(&test, &command).await; assert_eq!( @@ -913,14 +923,15 @@ async fn with_additional_permissions_denied_approval_blocks_execution() -> Resul skip_if_no_network!(Ok(())); let server = start_mock_server().await; let approval_policy = AskForApproval::OnRequest; - let sandbox_policy = workspace_write_excluding_tmp(); - let sandbox_policy_for_config = sandbox_policy.clone(); + let permission_profile = workspace_write_excluding_tmp(); + let permission_profile_for_config = permission_profile.clone(); let mut builder = test_codex().with_config(move |config| { config.permissions.approval_policy = Constrained::allow_any(approval_policy); config - .set_legacy_sandbox_policy(sandbox_policy_for_config) - .expect("set sandbox policy"); + .permissions + .set_permission_profile(permission_profile_for_config) + .expect("set permission profile"); config .features .enable(Feature::ExecPermissionApprovals) @@ -977,7 +988,7 @@ async fn with_additional_permissions_denied_approval_blocks_execution() -> Resul ) .await; - submit_turn(&test, call_id, approval_policy, sandbox_policy.clone()).await?; + submit_turn(&test, call_id, approval_policy, permission_profile.clone()).await?; let approval = expect_exec_approval(&test, &command).await; assert_eq!( @@ -1020,14 +1031,15 @@ async fn request_permissions_grants_apply_to_later_exec_command_calls() -> Resul let server = start_mock_server().await; let approval_policy = AskForApproval::OnRequest; - let sandbox_policy = workspace_write_excluding_tmp(); - let sandbox_policy_for_config = sandbox_policy.clone(); + let permission_profile = workspace_write_excluding_tmp(); + let permission_profile_for_config = permission_profile.clone(); let mut builder = test_codex().with_config(move |config| { config.permissions.approval_policy = Constrained::allow_any(approval_policy); config - .set_legacy_sandbox_policy(sandbox_policy_for_config) - .expect("set sandbox policy"); + .permissions + .set_permission_profile(permission_profile_for_config) + .expect("set permission profile"); config .features .enable(Feature::ExecPermissionApprovals) @@ -1091,7 +1103,7 @@ async fn request_permissions_grants_apply_to_later_exec_command_calls() -> Resul &test, "write outside the workspace", approval_policy, - sandbox_policy, + permission_profile, ) .await?; @@ -1146,14 +1158,15 @@ async fn request_permissions_preapprove_explicit_exec_permissions_outside_on_req let server = start_mock_server().await; let approval_policy = AskForApproval::OnRequest; - let sandbox_policy = workspace_write_excluding_tmp(); - let sandbox_policy_for_config = sandbox_policy.clone(); + let permission_profile = workspace_write_excluding_tmp(); + let permission_profile_for_config = permission_profile.clone(); let mut builder = test_codex().with_config(move |config| { config.permissions.approval_policy = Constrained::allow_any(approval_policy); config - .set_legacy_sandbox_policy(sandbox_policy_for_config) - .expect("set sandbox policy"); + .permissions + .set_permission_profile(permission_profile_for_config) + .expect("set permission profile"); config .features .enable(Feature::ExecPermissionApprovals) @@ -1208,7 +1221,7 @@ async fn request_permissions_preapprove_explicit_exec_permissions_outside_on_req &test, "write outside the workspace", approval_policy, - sandbox_policy, + permission_profile, ) .await?; @@ -1266,14 +1279,15 @@ async fn request_permissions_grants_apply_to_later_shell_command_calls() -> Resu let server = start_mock_server().await; let approval_policy = AskForApproval::OnRequest; - let sandbox_policy = workspace_write_excluding_tmp(); - let sandbox_policy_for_config = sandbox_policy.clone(); + let permission_profile = workspace_write_excluding_tmp(); + let permission_profile_for_config = permission_profile.clone(); let mut builder = test_codex().with_config(move |config| { config.permissions.approval_policy = Constrained::allow_any(approval_policy); config - .set_legacy_sandbox_policy(sandbox_policy_for_config) - .expect("set sandbox policy"); + .permissions + .set_permission_profile(permission_profile_for_config) + .expect("set permission profile"); config .features .enable(Feature::ExecPermissionApprovals) @@ -1324,7 +1338,7 @@ async fn request_permissions_grants_apply_to_later_shell_command_calls() -> Resu &test, "write outside the workspace", approval_policy, - sandbox_policy, + permission_profile, ) .await?; @@ -1380,14 +1394,15 @@ async fn request_permissions_grants_apply_to_later_shell_command_calls_without_i let server = start_mock_server().await; let approval_policy = AskForApproval::OnRequest; - let sandbox_policy = workspace_write_excluding_tmp(); - let sandbox_policy_for_config = sandbox_policy.clone(); + let permission_profile = workspace_write_excluding_tmp(); + let permission_profile_for_config = permission_profile.clone(); let mut builder = test_codex().with_config(move |config| { config.permissions.approval_policy = Constrained::allow_any(approval_policy); config - .set_legacy_sandbox_policy(sandbox_policy_for_config) - .expect("set sandbox policy"); + .permissions + .set_permission_profile(permission_profile_for_config) + .expect("set permission profile"); config .features .enable(Feature::RequestPermissionsTool) @@ -1436,7 +1451,7 @@ async fn request_permissions_grants_apply_to_later_shell_command_calls_without_i &test, "write outside the workspace without inline permission feature", approval_policy, - sandbox_policy, + permission_profile, ) .await?; @@ -1494,14 +1509,15 @@ async fn partial_request_permissions_grants_do_not_preapprove_new_permissions() let server = start_mock_server().await; let approval_policy = AskForApproval::OnRequest; - let sandbox_policy = workspace_write_excluding_tmp(); - let sandbox_policy_for_config = sandbox_policy.clone(); + let permission_profile = workspace_write_excluding_tmp(); + let permission_profile_for_config = permission_profile.clone(); let mut builder = test_codex().with_config(move |config| { config.permissions.approval_policy = Constrained::allow_any(approval_policy); config - .set_legacy_sandbox_policy(sandbox_policy_for_config) - .expect("set sandbox policy"); + .permissions + .set_permission_profile(permission_profile_for_config) + .expect("set permission profile"); config .features .enable(Feature::ExecPermissionApprovals) @@ -1588,7 +1604,7 @@ async fn partial_request_permissions_grants_do_not_preapprove_new_permissions() &test, "write outside the workspace", approval_policy, - sandbox_policy, + permission_profile, ) .await?; @@ -1660,14 +1676,15 @@ async fn request_permissions_grants_do_not_carry_across_turns() -> Result<()> { let server = start_mock_server().await; let approval_policy = AskForApproval::OnRequest; - let sandbox_policy = workspace_write_excluding_tmp(); - let sandbox_policy_for_config = sandbox_policy.clone(); + let permission_profile = workspace_write_excluding_tmp(); + let permission_profile_for_config = permission_profile.clone(); let mut builder = test_codex().with_config(move |config| { config.permissions.approval_policy = Constrained::allow_any(approval_policy); config - .set_legacy_sandbox_policy(sandbox_policy_for_config) - .expect("set sandbox policy"); + .permissions + .set_permission_profile(permission_profile_for_config) + .expect("set permission profile"); config .features .enable(Feature::ExecPermissionApprovals) @@ -1709,7 +1726,7 @@ async fn request_permissions_grants_do_not_carry_across_turns() -> Result<()> { &test, "request permissions for later use", approval_policy, - sandbox_policy.clone(), + permission_profile.clone(), ) .await?; @@ -1754,7 +1771,7 @@ async fn request_permissions_grants_do_not_carry_across_turns() -> Result<()> { &test, "try to reuse permissions in a later turn", approval_policy, - sandbox_policy, + permission_profile, ) .await?; wait_for_completion(&test).await; @@ -1775,14 +1792,15 @@ async fn request_permissions_session_grants_carry_across_turns() -> Result<()> { let server = start_mock_server().await; let approval_policy = AskForApproval::OnRequest; - let sandbox_policy = workspace_write_excluding_tmp(); - let sandbox_policy_for_config = sandbox_policy.clone(); + let permission_profile = workspace_write_excluding_tmp(); + let permission_profile_for_config = permission_profile.clone(); let mut builder = test_codex().with_config(move |config| { config.permissions.approval_policy = Constrained::allow_any(approval_policy); config - .set_legacy_sandbox_policy(sandbox_policy_for_config) - .expect("set sandbox policy"); + .permissions + .set_permission_profile(permission_profile_for_config) + .expect("set permission profile"); config .features .enable(Feature::ExecPermissionApprovals) @@ -1829,7 +1847,7 @@ async fn request_permissions_session_grants_carry_across_turns() -> Result<()> { &test, "request session permissions for later use", approval_policy, - sandbox_policy.clone(), + permission_profile.clone(), ) .await?; @@ -1871,7 +1889,7 @@ async fn request_permissions_session_grants_carry_across_turns() -> Result<()> { &test, "reuse session permissions in a later turn", approval_policy, - sandbox_policy, + permission_profile, ) .await?;