diff --git a/codex-rs/app-server/src/codex_message_processor.rs b/codex-rs/app-server/src/codex_message_processor.rs index 0216a2a52..c86d41435 100644 --- a/codex-rs/app-server/src/codex_message_processor.rs +++ b/codex-rs/app-server/src/codex_message_processor.rs @@ -2307,7 +2307,11 @@ impl CodexMessageProcessor { } } } else if let Some(policy) = sandbox_policy.map(|policy| policy.to_core()) { - match self.config.permissions.sandbox_policy.can_set(&policy) { + match self + .config + .permissions + .can_set_legacy_sandbox_policy(&policy, &sandbox_cwd) + { Ok(()) => { let file_system_sandbox_policy = codex_protocol::permissions::FileSystemSandboxPolicy::from_legacy_sandbox_policy_for_cwd(&policy, &sandbox_cwd); @@ -8705,7 +8709,9 @@ impl CodexMessageProcessor { Ok(config) => { let setup_request = WindowsSandboxSetupRequest { mode, - policy: config.permissions.sandbox_policy.get().clone(), + policy: config + .permissions + .legacy_sandbox_policy(config.cwd.as_path()), policy_cwd: config.cwd.to_path_buf(), command_cwd, env_map: std::env::vars().collect(), diff --git a/codex-rs/cli/src/debug_sandbox.rs b/codex-rs/cli/src/debug_sandbox.rs index a6cd07699..c85da0f5f 100644 --- a/codex-rs/cli/src/debug_sandbox.rs +++ b/codex-rs/cli/src/debug_sandbox.rs @@ -227,7 +227,9 @@ async fn run_command_under_sandbox( let args = create_linux_sandbox_command_args_for_policies( command, cwd.as_path(), - config.permissions.sandbox_policy.get(), + &config + .permissions + .legacy_sandbox_policy(sandbox_policy_cwd.as_path()), &file_system_sandbox_policy, network_sandbox_policy, sandbox_policy_cwd.as_path(), @@ -290,7 +292,10 @@ async fn run_command_under_windows_session( use codex_windows_sandbox::spawn_windows_sandbox_session_elevated; use codex_windows_sandbox::spawn_windows_sandbox_session_legacy; - let policy_str = match serde_json::to_string(config.permissions.sandbox_policy.get()) { + let sandbox_policy = config + .permissions + .legacy_sandbox_policy(sandbox_policy_cwd.as_path()); + let policy_str = match serde_json::to_string(&sandbox_policy) { Ok(policy_str) => policy_str, Err(err) => { eprintln!("windows sandbox failed to serialize policy: {err}"); diff --git a/codex-rs/core/src/config/mod.rs b/codex-rs/core/src/config/mod.rs index 3d0089da8..eb6d10f84 100644 --- a/codex-rs/core/src/config/mod.rs +++ b/codex-rs/core/src/config/mod.rs @@ -237,6 +237,37 @@ impl Permissions { self.permission_profile.get().network_sandbox_policy() } + /// Legacy compatibility projection derived from the canonical profile. + pub fn legacy_sandbox_policy(&self, cwd: &Path) -> SandboxPolicy { + let permission_profile = self.permission_profile.get(); + let file_system_sandbox_policy = permission_profile.file_system_sandbox_policy(); + compatibility_sandbox_policy_for_permission_profile( + permission_profile, + &file_system_sandbox_policy, + permission_profile.network_sandbox_policy(), + cwd, + ) + } + + /// Check whether a legacy sandbox policy can be applied to this permission + /// set under both legacy and canonical profile constraints. + pub fn can_set_legacy_sandbox_policy( + &self, + sandbox_policy: &SandboxPolicy, + cwd: &Path, + ) -> ConstraintResult<()> { + self.sandbox_policy.can_set(sandbox_policy)?; + let file_system_sandbox_policy = + FileSystemSandboxPolicy::from_legacy_sandbox_policy_for_cwd(sandbox_policy, cwd); + let network_sandbox_policy = NetworkSandboxPolicy::from(sandbox_policy); + let permission_profile = PermissionProfile::from_runtime_permissions_with_enforcement( + SandboxEnforcement::from_legacy_sandbox_policy(sandbox_policy), + &file_system_sandbox_policy, + network_sandbox_policy, + ); + self.permission_profile.can_set(&permission_profile) + } + /// Replace permissions from a legacy sandbox policy and keep every /// permission projection in sync. pub fn set_legacy_sandbox_policy( @@ -244,7 +275,7 @@ impl Permissions { sandbox_policy: SandboxPolicy, cwd: &Path, ) -> ConstraintResult<()> { - self.sandbox_policy.can_set(&sandbox_policy)?; + self.can_set_legacy_sandbox_policy(&sandbox_policy, cwd)?; let file_system_sandbox_policy = FileSystemSandboxPolicy::from_legacy_sandbox_policy_for_cwd(&sandbox_policy, cwd); let network_sandbox_policy = NetworkSandboxPolicy::from(&sandbox_policy); @@ -253,7 +284,6 @@ impl Permissions { &file_system_sandbox_policy, network_sandbox_policy, ); - self.permission_profile.can_set(&permission_profile)?; self.sandbox_policy.set(sandbox_policy)?; self.permission_profile.set(permission_profile)?; diff --git a/codex-rs/core/src/session/session.rs b/codex-rs/core/src/session/session.rs index bf2e36a27..dcadac70a 100644 --- a/codex-rs/core/src/session/session.rs +++ b/codex-rs/core/src/session/session.rs @@ -634,7 +634,9 @@ impl Session { config.model_context_window, config.model_auto_compact_token_limit, config.permissions.approval_policy.value(), - config.permissions.sandbox_policy.get().clone(), + config + .permissions + .legacy_sandbox_policy(session_configuration.cwd.as_path()), mcp_servers.keys().map(String::as_str).collect(), config.active_profile.clone(), ); diff --git a/codex-rs/tui/src/app.rs b/codex-rs/tui/src/app.rs index 77c1f5277..bffa46e47 100644 --- a/codex-rs/tui/src/app.rs +++ b/codex-rs/tui/src/app.rs @@ -939,10 +939,14 @@ impl App { // On startup, if Agent mode (workspace-write) or ReadOnly is active, warn about world-writable dirs on Windows. #[cfg(target_os = "windows")] { + let startup_sandbox_policy = app + .config + .permissions + .legacy_sandbox_policy(app.config.cwd.as_path()); let should_check = WindowsSandboxLevel::from_config(&app.config) != WindowsSandboxLevel::Disabled && matches!( - app.config.permissions.sandbox_policy.get(), + &startup_sandbox_policy, codex_protocol::protocol::SandboxPolicy::WorkspaceWrite { .. } | codex_protocol::protocol::SandboxPolicy::ReadOnly { .. } ) @@ -956,7 +960,7 @@ impl App { let env_map: std::collections::HashMap = std::env::vars().collect(); let tx = app.app_event_tx.clone(); let logs_base_dir = app.config.codex_home.clone(); - let sandbox_policy = app.config.permissions.sandbox_policy.get().clone(); + let sandbox_policy = startup_sandbox_policy; Self::spawn_world_writable_scan(cwd, env_map, logs_base_dir, sandbox_policy, tx); } } diff --git a/codex-rs/tui/src/app/config_persistence.rs b/codex-rs/tui/src/app/config_persistence.rs index 44ef5f664..9f6b63122 100644 --- a/codex-rs/tui/src/app/config_persistence.rs +++ b/codex-rs/tui/src/app/config_persistence.rs @@ -300,9 +300,11 @@ impl App { .set_approval_policy(self.config.permissions.approval_policy.value()); } if sandbox_policy_override.is_some() - && let Err(err) = self - .chat_widget - .set_sandbox_policy(self.config.permissions.sandbox_policy.get().clone()) + && let Err(err) = self.chat_widget.set_sandbox_policy( + self.config + .permissions + .legacy_sandbox_policy(self.config.cwd.as_path()), + ) { tracing::error!( error = %err, @@ -312,8 +314,11 @@ impl App { .add_error_message(format!("Failed to enable Auto-review: {err}")); } if sandbox_policy_override.is_some() { - self.runtime_sandbox_policy_override = - Some(self.config.permissions.sandbox_policy.get().clone()); + self.runtime_sandbox_policy_override = Some( + self.config + .permissions + .legacy_sandbox_policy(self.config.cwd.as_path()), + ); } if approval_policy_override.is_some() diff --git a/codex-rs/tui/src/app/event_dispatch.rs b/codex-rs/tui/src/app/event_dispatch.rs index 7e096c6b9..4c3b03842 100644 --- a/codex-rs/tui/src/app/event_dispatch.rs +++ b/codex-rs/tui/src/app/event_dispatch.rs @@ -834,7 +834,10 @@ impl App { /*hint*/ None, )); - let policy = self.config.permissions.sandbox_policy.get().clone(); + let policy = self + .config + .permissions + .legacy_sandbox_policy(self.config.cwd.as_path()); let policy_cwd = self.config.cwd.clone(); let command_cwd = self.config.cwd.clone(); let env_map: std::collections::HashMap = @@ -1245,8 +1248,11 @@ impl App { .add_error_message(format!("Failed to set sandbox policy: {err}")); return Ok(AppRunControl::Continue); } - self.runtime_sandbox_policy_override = - Some(self.config.permissions.sandbox_policy.get().clone()); + self.runtime_sandbox_policy_override = Some( + self.config + .permissions + .legacy_sandbox_policy(self.config.cwd.as_path()), + ); self.sync_active_thread_permission_settings_to_cached_session() .await; @@ -1269,7 +1275,10 @@ impl App { std::env::vars().collect(); let tx = self.app_event_tx.clone(); let logs_base_dir = self.config.codex_home.clone(); - let sandbox_policy = self.config.permissions.sandbox_policy.get().clone(); + let sandbox_policy = self + .config + .permissions + .legacy_sandbox_policy(self.config.cwd.as_path()); Self::spawn_world_writable_scan( cwd, env_map, diff --git a/codex-rs/tui/src/app/thread_session_state.rs b/codex-rs/tui/src/app/thread_session_state.rs index 374307344..2b242890d 100644 --- a/codex-rs/tui/src/app/thread_session_state.rs +++ b/codex-rs/tui/src/app/thread_session_state.rs @@ -12,7 +12,10 @@ impl App { let approval_policy = self.config.permissions.approval_policy.value(); let approvals_reviewer = self.config.approvals_reviewer; - let sandbox_policy = self.config.permissions.sandbox_policy.get().clone(); + let sandbox_policy = self + .config + .permissions + .legacy_sandbox_policy(self.config.cwd.as_path()); let permission_profile = Some( self.chat_widget .config_ref() @@ -45,7 +48,10 @@ impl App { thread_id: ThreadId, thread: &Thread, ) -> ThreadSessionState { - let sandbox_policy = self.config.permissions.sandbox_policy.get().clone(); + let sandbox_policy = self + .config + .permissions + .legacy_sandbox_policy(self.config.cwd.as_path()); let mut session = self .primary_session_configured .clone() @@ -185,8 +191,10 @@ mod tests { app.chat_widget .set_sandbox_policy(expected_sandbox_policy.clone()) .expect("set widget sandbox policy"); - app.config.permissions.sandbox_policy = - codex_config::Constrained::allow_any(expected_sandbox_policy.clone()); + app.config + .permissions + .set_legacy_sandbox_policy(expected_sandbox_policy.clone(), app.config.cwd.as_path()) + .expect("set app sandbox policy"); app.sync_active_thread_permission_settings_to_cached_session() .await; diff --git a/codex-rs/tui/src/app_server_session.rs b/codex-rs/tui/src/app_server_session.rs index 8fa763021..366e8912a 100644 --- a/codex-rs/tui/src/app_server_session.rs +++ b/codex-rs/tui/src/app_server_session.rs @@ -1143,7 +1143,13 @@ fn thread_start_params_from_config( let permission_profile = permission_profile_override_from_config(config, thread_params_mode); let sandbox = permission_profile .is_none() - .then(|| sandbox_mode_from_policy(config.permissions.sandbox_policy.get().clone())) + .then(|| { + sandbox_mode_from_policy( + config + .permissions + .legacy_sandbox_policy(config.cwd.as_path()), + ) + }) .flatten(); ThreadStartParams { model: config.model.clone(), @@ -1170,7 +1176,13 @@ fn thread_resume_params_from_config( let permission_profile = permission_profile_override_from_config(&config, thread_params_mode); let sandbox = permission_profile .is_none() - .then(|| sandbox_mode_from_policy(config.permissions.sandbox_policy.get().clone())) + .then(|| { + sandbox_mode_from_policy( + config + .permissions + .legacy_sandbox_policy(config.cwd.as_path()), + ) + }) .flatten(); ThreadResumeParams { thread_id: thread_id.to_string(), @@ -1196,7 +1208,13 @@ fn thread_fork_params_from_config( let permission_profile = permission_profile_override_from_config(&config, thread_params_mode); let sandbox = permission_profile .is_none() - .then(|| sandbox_mode_from_policy(config.permissions.sandbox_policy.get().clone())) + .then(|| { + sandbox_mode_from_policy( + config + .permissions + .legacy_sandbox_policy(config.cwd.as_path()), + ) + }) .flatten(); ThreadForkParams { thread_id: thread_id.to_string(), @@ -1522,8 +1540,11 @@ mod tests { let temp_dir = tempfile::tempdir().expect("tempdir"); let config = build_config(&temp_dir).await; let thread_id = ThreadId::new(); - let expected_sandbox = - sandbox_mode_from_policy(config.permissions.sandbox_policy.get().clone()); + let expected_sandbox = sandbox_mode_from_policy( + config + .permissions + .legacy_sandbox_policy(config.cwd.as_path()), + ); let start = thread_start_params_from_config( &config, @@ -1564,8 +1585,11 @@ mod tests { let config = build_config(&temp_dir).await; let thread_id = ThreadId::new(); let remote_cwd = PathBuf::from("repo/on/server"); - let expected_sandbox = - sandbox_mode_from_policy(config.permissions.sandbox_policy.get().clone()); + let expected_sandbox = sandbox_mode_from_policy( + config + .permissions + .legacy_sandbox_policy(config.cwd.as_path()), + ); let start = thread_start_params_from_config( &config, diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs index 1fbe122b6..dd48f030c 100644 --- a/codex-rs/tui/src/chatwidget.rs +++ b/codex-rs/tui/src/chatwidget.rs @@ -6415,7 +6415,9 @@ impl ChatWidget { items, self.config.cwd.to_path_buf(), self.config.permissions.approval_policy.value(), - self.config.permissions.sandbox_policy.get().clone(), + self.config + .permissions + .legacy_sandbox_policy(self.config.cwd.as_path()), permission_profile, effective_mode.model().to_string(), effective_mode.reasoning_effort(), @@ -9466,7 +9468,10 @@ impl ChatWidget { pub(crate) fn open_permissions_popup(&mut self) { let include_read_only = cfg!(target_os = "windows"); let current_approval = self.config.permissions.approval_policy.value(); - let current_sandbox = self.config.permissions.sandbox_policy.get(); + let current_sandbox = self + .config + .permissions + .legacy_sandbox_policy(self.config.cwd.as_path()); let guardian_approval_enabled = self.config.features.enabled(Feature::GuardianApproval); let current_review_policy = self.config.approvals_reviewer; let mut items: Vec = Vec::new(); @@ -9600,7 +9605,11 @@ impl ChatWidget { name: base_name.clone(), description: base_description.clone(), is_current: current_review_policy == ApprovalsReviewer::User - && Self::preset_matches_current(current_approval, current_sandbox, &preset), + && Self::preset_matches_current( + current_approval, + ¤t_sandbox, + &preset, + ), actions: default_actions, dismiss_on_select: true, disabled_reason: default_disabled_reason, @@ -9617,7 +9626,7 @@ impl ChatWidget { is_current: current_review_policy == ApprovalsReviewer::AutoReview && Self::preset_matches_current( current_approval, - current_sandbox, + ¤t_sandbox, &preset, ), actions: Self::approval_preset_actions( @@ -9638,7 +9647,7 @@ impl ChatWidget { description: base_description, is_current: Self::preset_matches_current( current_approval, - current_sandbox, + ¤t_sandbox, &preset, ), actions: default_actions, @@ -9774,7 +9783,10 @@ impl ChatWidget { self.config.codex_home.as_path(), cwd.as_path(), &env_map, - self.config.permissions.sandbox_policy.get(), + &self + .config + .permissions + .legacy_sandbox_policy(self.config.cwd.as_path()), Some(self.config.codex_home.as_path()), ) { Ok(_) => None, @@ -9892,7 +9904,14 @@ impl ChatWidget { let mode_label = preset .as_ref() .map(|p| describe_policy(&p.sandbox)) - .unwrap_or_else(|| describe_policy(self.config.permissions.sandbox_policy.get())); + .unwrap_or_else(|| { + describe_policy( + &self + .config + .permissions + .legacy_sandbox_policy(self.config.cwd.as_path()), + ) + }); let info_line = if failed_scan { Line::from(vec![ "We couldn't complete the world-writable scan, so protections cannot be verified. " diff --git a/codex-rs/tui/src/chatwidget/tests/permissions.rs b/codex-rs/tui/src/chatwidget/tests/permissions.rs index 73263c687..ccab18bfc 100644 --- a/codex-rs/tui/src/chatwidget/tests/permissions.rs +++ b/codex-rs/tui/src/chatwidget/tests/permissions.rs @@ -1,6 +1,13 @@ use super::*; use pretty_assertions::assert_eq; +fn set_legacy_sandbox_policy(chat: &mut ChatWidget, sandbox_policy: SandboxPolicy) { + chat.config + .permissions + .set_legacy_sandbox_policy(sandbox_policy, chat.config.cwd.as_path()) + .expect("set sandbox policy"); +} + #[tokio::test] async fn approvals_selection_popup_snapshot() { let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await; @@ -347,8 +354,7 @@ async fn permissions_selection_history_snapshot_full_access_to_default() { .approval_policy .set(AskForApproval::Never) .expect("set approval policy"); - chat.config.permissions.sandbox_policy = - Constrained::allow_any(SandboxPolicy::DangerFullAccess); + set_legacy_sandbox_policy(&mut chat, SandboxPolicy::DangerFullAccess); chat.open_permissions_popup(); let popup = render_bottom_popup(&chat, /*width*/ 120); @@ -387,11 +393,7 @@ async fn permissions_selection_emits_history_cell_when_current_is_selected() { .approval_policy .set(AskForApproval::OnRequest) .expect("set approval policy"); - chat.config - .permissions - .sandbox_policy - .set(SandboxPolicy::new_workspace_write_policy()) - .expect("set sandbox policy"); + set_legacy_sandbox_policy(&mut chat, SandboxPolicy::new_workspace_write_policy()); chat.open_permissions_popup(); chat.handle_key_event(KeyEvent::from(KeyCode::Enter)); @@ -446,11 +448,7 @@ async fn permissions_selection_hides_auto_review_when_feature_disabled_even_if_a .approval_policy .set(AskForApproval::OnRequest) .expect("set approval policy"); - chat.config - .permissions - .sandbox_policy - .set(SandboxPolicy::new_workspace_write_policy()) - .expect("set sandbox policy"); + set_legacy_sandbox_policy(&mut chat, SandboxPolicy::new_workspace_write_policy()); chat.open_permissions_popup(); let popup = render_bottom_popup(&chat, /*width*/ 120); @@ -575,11 +573,7 @@ async fn permissions_selection_can_disable_auto_review() { .approval_policy .set(AskForApproval::OnRequest) .expect("set approval policy"); - chat.config - .permissions - .sandbox_policy - .set(SandboxPolicy::new_workspace_write_policy()) - .expect("set sandbox policy"); + set_legacy_sandbox_policy(&mut chat, SandboxPolicy::new_workspace_write_policy()); chat.open_permissions_popup(); chat.handle_key_event(KeyEvent::from(KeyCode::Up)); @@ -616,11 +610,7 @@ async fn permissions_selection_sends_approvals_reviewer_in_override_turn_context .approval_policy .set(AskForApproval::OnRequest) .expect("set approval policy"); - chat.config - .permissions - .sandbox_policy - .set(SandboxPolicy::new_workspace_write_policy()) - .expect("set sandbox policy"); + set_legacy_sandbox_policy(&mut chat, SandboxPolicy::new_workspace_write_policy()); chat.set_approvals_reviewer(ApprovalsReviewer::User); chat.open_permissions_popup(); diff --git a/codex-rs/tui/src/history_cell.rs b/codex-rs/tui/src/history_cell.rs index 16c2440de..33e2f25c6 100644 --- a/codex-rs/tui/src/history_cell.rs +++ b/codex-rs/tui/src/history_cell.rs @@ -1313,7 +1313,9 @@ pub(crate) fn new_session_info( pub(crate) fn is_yolo_mode(config: &Config) -> bool { has_yolo_permissions( config.permissions.approval_policy.value(), - config.permissions.sandbox_policy.get(), + &config + .permissions + .legacy_sandbox_policy(config.cwd.as_path()), ) } diff --git a/codex-rs/tui/src/lib.rs b/codex-rs/tui/src/lib.rs index 7f65e3b04..ef4dd6276 100644 --- a/codex-rs/tui/src/lib.rs +++ b/codex-rs/tui/src/lib.rs @@ -874,9 +874,12 @@ pub async fn run_main( set_default_client_residency_requirement(config.enforce_residency.value()); - if let Some(warning) = - add_dir_warning_message(&cli.add_dir, config.permissions.sandbox_policy.get()) - { + if let Some(warning) = add_dir_warning_message( + &cli.add_dir, + &config + .permissions + .legacy_sandbox_policy(config.cwd.as_path()), + ) { #[allow(clippy::print_stderr)] { eprintln!("Error adding directories: {warning}"); @@ -2205,7 +2208,9 @@ mod tests { current_date: None, timezone: None, approval_policy: config.permissions.approval_policy.value(), - sandbox_policy: config.permissions.sandbox_policy.get().clone(), + sandbox_policy: config + .permissions + .legacy_sandbox_policy(config.cwd.as_path()), permission_profile: None, network: None, file_system_sandbox_policy: None, @@ -2328,6 +2333,7 @@ trust_level = "untrusted" ..Default::default() }; let trusted_config = ConfigBuilder::default() + .loader_overrides(LoaderOverrides::without_managed_config_for_tests()) .codex_home(codex_home.clone()) .harness_overrides(trusted_overrides.clone()) .build() @@ -2342,6 +2348,7 @@ trust_level = "untrusted" ..trusted_overrides }; let untrusted_config = ConfigBuilder::default() + .loader_overrides(LoaderOverrides::without_managed_config_for_tests()) .codex_home(codex_home) .harness_overrides(untrusted_overrides) .build() diff --git a/codex-rs/tui/src/status/card.rs b/codex-rs/tui/src/status/card.rs index 2a05bb888..06594587b 100644 --- a/codex-rs/tui/src/status/card.rs +++ b/codex-rs/tui/src/status/card.rs @@ -254,7 +254,11 @@ impl StatusHistoryCell { ), ( "sandbox", - summarize_sandbox_policy(config.permissions.sandbox_policy.get()), + summarize_sandbox_policy( + &config + .permissions + .legacy_sandbox_policy(config.cwd.as_path()), + ), ), ]; if config.model_provider.wire_api == WireApi::Responses { @@ -277,7 +281,10 @@ impl StatusHistoryCell { .find(|(k, _)| *k == "approval") .map(|(_, v)| v.clone()) .unwrap_or_else(|| "".to_string()); - let sandbox = match config.permissions.sandbox_policy.get() { + let sandbox_policy = config + .permissions + .legacy_sandbox_policy(config.cwd.as_path()); + let sandbox = match &sandbox_policy { SandboxPolicy::DangerFullAccess => "danger-full-access".to_string(), SandboxPolicy::ReadOnly { .. } => "read-only".to_string(), SandboxPolicy::WorkspaceWrite { @@ -294,12 +301,11 @@ impl StatusHistoryCell { } }; let permissions = if config.permissions.approval_policy.value() == AskForApproval::OnRequest - && *config.permissions.sandbox_policy.get() - == SandboxPolicy::new_workspace_write_policy() + && sandbox_policy == SandboxPolicy::new_workspace_write_policy() { "Default".to_string() } else if config.permissions.approval_policy.value() == AskForApproval::Never - && *config.permissions.sandbox_policy.get() == SandboxPolicy::DangerFullAccess + && sandbox_policy == SandboxPolicy::DangerFullAccess { "Full Access".to_string() } else { diff --git a/codex-rs/tui/src/status/tests.rs b/codex-rs/tui/src/status/tests.rs index 44611deee..569f093a1 100644 --- a/codex-rs/tui/src/status/tests.rs +++ b/codex-rs/tui/src/status/tests.rs @@ -97,19 +97,20 @@ async fn status_snapshot_includes_reasoning_details() { config.model = Some("gpt-5.1-codex-max".to_string()); config.model_provider_id = "openai".to_string(); config.model_reasoning_summary = Some(ReasoningSummary::Detailed); + config.cwd = test_path_buf("/workspace/tests").abs(); config .permissions - .sandbox_policy - .set(SandboxPolicy::WorkspaceWrite { - writable_roots: Vec::new(), - network_access: false, - exclude_tmpdir_env_var: false, - exclude_slash_tmp: false, - }) + .set_legacy_sandbox_policy( + SandboxPolicy::WorkspaceWrite { + writable_roots: Vec::new(), + network_access: false, + exclude_tmpdir_env_var: false, + exclude_slash_tmp: false, + }, + config.cwd.as_path(), + ) .expect("set sandbox policy"); - config.cwd = test_path_buf("/workspace/tests").abs(); - let account_display = test_status_account_display(); let usage = TokenUsage { input_tokens: 1_200, @@ -182,17 +183,19 @@ async fn status_permissions_non_default_workspace_write_is_custom() { .approval_policy .set(AskForApproval::OnRequest) .expect("set approval policy"); + config.cwd = test_path_buf("/workspace/tests").abs(); config .permissions - .sandbox_policy - .set(SandboxPolicy::WorkspaceWrite { - writable_roots: Vec::new(), - network_access: true, - exclude_tmpdir_env_var: false, - exclude_slash_tmp: false, - }) + .set_legacy_sandbox_policy( + SandboxPolicy::WorkspaceWrite { + writable_roots: Vec::new(), + network_access: true, + exclude_tmpdir_env_var: false, + exclude_slash_tmp: false, + }, + config.cwd.as_path(), + ) .expect("set sandbox policy"); - config.cwd = test_path_buf("/workspace/tests").abs(); let account_display = test_status_account_display(); let usage = TokenUsage::default(); diff --git a/codex-rs/utils/sandbox-summary/src/config_summary.rs b/codex-rs/utils/sandbox-summary/src/config_summary.rs index 47f4ca770..b3de5b638 100644 --- a/codex-rs/utils/sandbox-summary/src/config_summary.rs +++ b/codex-rs/utils/sandbox-summary/src/config_summary.rs @@ -15,7 +15,11 @@ pub fn create_config_summary_entries(config: &Config, model: &str) -> Vec<(&'sta ), ( "sandbox", - summarize_sandbox_policy(config.permissions.sandbox_policy.get()), + summarize_sandbox_policy( + &config + .permissions + .legacy_sandbox_policy(config.cwd.as_path()), + ), ), ]; if config.model_provider.wire_api == WireApi::Responses {