diff --git a/codex-rs/tui/src/app_server_session.rs b/codex-rs/tui/src/app_server_session.rs index a21b4c099d..fb8f80267f 100644 --- a/codex-rs/tui/src/app_server_session.rs +++ b/codex-rs/tui/src/app_server_session.rs @@ -1118,7 +1118,10 @@ fn sandbox_mode_from_permission_profile( .network_sandbox_policy() .is_enabled() .then_some(codex_app_server_protocol::SandboxMode::DangerFullAccess) - } else if file_system_policy.can_write_path_with_cwd(cwd, cwd) { + } else if !file_system_policy + .get_writable_roots_with_cwd(cwd) + .is_empty() + { Some(codex_app_server_protocol::SandboxMode::WorkspaceWrite) } else { Some(codex_app_server_protocol::SandboxMode::ReadOnly) @@ -1508,6 +1511,12 @@ mod tests { use codex_app_server_protocol::ThreadStatus; use codex_app_server_protocol::Turn; use codex_app_server_protocol::TurnStatus; + use codex_protocol::models::ManagedFileSystemPermissions; + use codex_protocol::permissions::FileSystemAccessMode; + use codex_protocol::permissions::FileSystemPath; + use codex_protocol::permissions::FileSystemSandboxEntry; + use codex_protocol::permissions::FileSystemSpecialPath; + use codex_protocol::permissions::NetworkSandboxPolicy; use codex_utils_absolute_path::test_support::PathBufExt; use codex_utils_absolute_path::test_support::test_path_buf; use pretty_assertions::assert_eq; @@ -1600,6 +1609,35 @@ mod tests { assert_eq!(fork.permission_profile, None); } + #[test] + fn sandbox_mode_preserves_non_cwd_write_roots_for_remote_sessions() { + let cwd = test_path_buf("/workspace/project").abs(); + let extra_root = test_path_buf("/workspace/cache").abs(); + let permission_profile = PermissionProfile::Managed { + file_system: ManagedFileSystemPermissions::Restricted { + entries: vec![ + FileSystemSandboxEntry { + path: FileSystemPath::Special { + value: FileSystemSpecialPath::Root, + }, + access: FileSystemAccessMode::Read, + }, + FileSystemSandboxEntry { + path: FileSystemPath::Path { path: extra_root }, + access: FileSystemAccessMode::Write, + }, + ], + glob_scan_max_depth: None, + }, + network: NetworkSandboxPolicy::Restricted, + }; + + assert_eq!( + sandbox_mode_from_permission_profile(&permission_profile, cwd.as_path()), + Some(codex_app_server_protocol::SandboxMode::WorkspaceWrite) + ); + } + #[tokio::test] async fn thread_lifecycle_params_forward_explicit_remote_cwd_override_for_remote_sessions() { let temp_dir = tempfile::tempdir().expect("tempdir");