Remove legacy sandbox-policy accessors from configuration (#61395)

## What changed

- Remove `Config::legacy_sandbox_policy` and `Permissions::legacy_sandbox_policy`.
- Update core and TUI tests to use permission profiles and filesystem/network policies directly, with explicit conversion where legacy wire formats are required.
- Report the active sandbox label in app-server resume override mismatch diagnostics.

GitOrigin-RevId: cbc5417944e23404523e69dc5516d66d6bfafefe
This commit is contained in:
ioanbudea-OAI
2026-11-13 23:03:49 +00:00
committed by copyberry
parent 5158e9780e
commit f626b8fde9
15 changed files with 170 additions and 277 deletions
@@ -1191,7 +1191,6 @@ flag = false
async fn managed_preferences_expand_home_directory_in_workspace_write_roots() -> anyhow::Result<()>
{
use base64::Engine;
use codex_protocol::protocol::SandboxPolicy;
let Some(home) = dirs::home_dir() else {
return Ok(());
@@ -1230,23 +1229,15 @@ writable_roots = ["~/code"]
.await?;
let expected_root = AbsolutePathBuf::from_absolute_path(home.join("code"))?;
match &config.legacy_sandbox_policy() {
SandboxPolicy::WorkspaceWrite {
writable_roots,
network_access: true,
exclude_tmpdir_env_var: true,
exclude_slash_tmp: false,
} => {
assert_eq!(
writable_roots
.iter()
.filter(|root| **root == expected_root)
.count(),
1,
);
}
other => panic!("expected workspace-write policy, got {other:?}"),
}
assert_eq!(
config.permissions.permission_profile(),
&codex_protocol::models::PermissionProfile::workspace_write_with(
&[expected_root],
codex_protocol::permissions::NetworkSandboxPolicy::Enabled,
/*exclude_tmpdir_env_var*/ true,
/*exclude_slash_tmp*/ false,
)
);
assert_eq!(config.permissions.active_permission_profile(), None);
Ok(())
+92 -151
View File
@@ -101,7 +101,6 @@ use codex_protocol::permissions::FileSystemSandboxPolicy;
use codex_protocol::permissions::FileSystemSpecialPath;
use codex_protocol::permissions::NetworkSandboxPolicy;
use codex_protocol::protocol::MultiAgentVersion;
use codex_protocol::protocol::NetworkAccess;
use codex_protocol::protocol::RealtimeVoice;
use codex_protocol::protocol::SandboxPolicy;
use codex_protocol_test_support::ContentItemTestExt;
@@ -2718,7 +2717,7 @@ async fn permissions_profiles_network_disabled_by_default_does_not_start_proxy()
}
#[tokio::test]
async fn default_permissions_profile_populates_runtime_sandbox_policy() -> std::io::Result<()> {
async fn default_permissions_profile_populates_runtime_permissions() -> std::io::Result<()> {
let codex_home = TempDir::new()?;
let cwd = TempDir::new()?;
std::fs::create_dir_all(cwd.path().join("docs"))?;
@@ -2793,15 +2792,6 @@ async fn default_permissions_profile_populates_runtime_sandbox_policy() -> std::
},
]),
);
assert_eq!(
&config.legacy_sandbox_policy(),
&SandboxPolicy::WorkspaceWrite {
writable_roots: vec![],
network_access: false,
exclude_tmpdir_env_var: true,
exclude_slash_tmp: true,
}
);
assert!(
!config
.permissions
@@ -2904,10 +2894,6 @@ async fn permission_profile_override_populates_runtime_permissions() -> std::io:
permission_profile
);
assert_eq!(config.permissions.active_permission_profile(), None);
assert_eq!(
&config.legacy_sandbox_policy(),
&SandboxPolicy::DangerFullAccess
);
Ok(())
}
@@ -3008,9 +2994,11 @@ extends = ":workspace"
extends: Some(BUILT_IN_PERMISSION_PROFILE_WORKSPACE.to_string()),
})
);
assert_eq!(
config.legacy_sandbox_policy(),
SandboxPolicy::new_workspace_write_policy()
assert!(
config
.permissions
.file_system_sandbox_policy()
.can_write_local_path_with_cwd(cwd.path(), cwd.path())
);
Ok(())
}
@@ -3215,12 +3203,6 @@ async fn permission_profile_override_preserves_managed_unrestricted_filesystem()
config.permissions.effective_permission_profile(),
permission_profile
);
assert_eq!(
&config.legacy_sandbox_policy(),
&SandboxPolicy::ExternalSandbox {
network_access: NetworkAccess::Restricted,
}
);
Ok(())
}
@@ -3238,16 +3220,16 @@ async fn managed_unrestricted_permission_profile_still_enables_network_requireme
ConfigToml::default(),
ConfigOverrides {
cwd: Some(cwd.path().to_path_buf()),
permission_profile: Some(permission_profile),
permission_profile: Some(permission_profile.clone()),
..Default::default()
},
codex_home.abs(),
)
.await?;
assert_eq!(
&config.legacy_sandbox_policy(),
&SandboxPolicy::DangerFullAccess,
"the legacy projection is intentionally lossy for managed unrestricted profiles"
config.permissions.effective_permission_profile(),
permission_profile
);
let layers = config
@@ -3276,8 +3258,7 @@ async fn managed_unrestricted_permission_profile_still_enables_network_requireme
}
#[tokio::test]
async fn permission_profile_override_keeps_memories_root_out_of_legacy_projection()
-> std::io::Result<()> {
async fn permission_profile_override_keeps_memories_root_read_only() -> std::io::Result<()> {
let codex_home = TempDir::new()?;
let cwd = TempDir::new()?;
let permission_profile = PermissionProfile::from_runtime_permissions(
@@ -3318,15 +3299,6 @@ async fn permission_profile_override_keeps_memories_root_out_of_legacy_projectio
.file_system_sandbox_policy()
.can_write_local_path_with_cwd(memories_root.as_path(), cwd.path())
);
assert_eq!(
&config.legacy_sandbox_policy(),
&SandboxPolicy::WorkspaceWrite {
writable_roots: vec![],
network_access: false,
exclude_tmpdir_env_var: true,
exclude_slash_tmp: true,
}
);
Ok(())
}
@@ -4072,20 +4044,24 @@ async fn implicit_builtin_workspace_profile_preserves_sandbox_workspace_write_se
"implicit :workspace cannot be faithfully re-selected when it includes \
legacy sandbox_workspace_write settings"
);
match config.legacy_sandbox_policy() {
SandboxPolicy::WorkspaceWrite {
writable_roots,
network_access,
exclude_tmpdir_env_var,
exclude_slash_tmp,
} => {
assert!(writable_roots.contains(&extra_root));
assert!(network_access);
assert!(exclude_tmpdir_env_var);
assert!(!exclude_slash_tmp);
}
sandbox_policy => panic!("expected workspace-write projection, got {sandbox_policy:?}"),
}
assert_eq!(
policy
.entries
.into_iter()
.filter(|entry| matches!(
&entry.path,
FileSystemPath::Special {
value: FileSystemSpecialPath::Tmpdir | FileSystemSpecialPath::SlashTmp
}
))
.collect::<Vec<_>>(),
vec![FileSystemSandboxEntry::new(
FileSystemPath::Special {
value: FileSystemSpecialPath::SlashTmp
},
FileSystemAccessMode::Write,
)]
);
Ok(())
}
@@ -4341,15 +4317,6 @@ async fn permissions_profiles_allow_direct_write_roots_outside_workspace_root()
.file_system_sandbox_policy()
.can_write_local_path_with_cwd(external_write_path.as_path(), cwd.path())
);
assert_eq!(
&config.legacy_sandbox_policy(),
&SandboxPolicy::WorkspaceWrite {
writable_roots: vec![external_write_path],
network_access: false,
exclude_tmpdir_env_var: true,
exclude_slash_tmp: true,
}
);
Ok(())
}
@@ -4457,12 +4424,6 @@ async fn permissions_profiles_allow_unknown_special_paths() -> std::io::Result<(
missing_path_behavior: None,
}]),
);
assert_eq!(
&config.legacy_sandbox_policy(),
&SandboxPolicy::ReadOnly {
network_access: false,
}
);
assert!(
config.startup_warnings.iter().any(|warning| warning.contains(
"Configured filesystem path `:future_special_path` is not recognized by this version of Codex and will be ignored."
@@ -4529,12 +4490,6 @@ async fn permissions_profiles_allow_missing_filesystem_with_warning() -> std::io
config.permissions.file_system_sandbox_policy(),
FileSystemSandboxPolicy::restricted(Vec::new())
);
assert_eq!(
&config.legacy_sandbox_policy(),
&SandboxPolicy::ReadOnly {
network_access: false,
}
);
assert!(
config.startup_warnings.iter().any(|warning| warning.contains(
"Permissions profile `dev` does not define any recognized filesystem entries for this version of Codex."
@@ -4666,7 +4621,6 @@ async fn permissions_profiles_allow_network_enablement() -> std::io::Result<()>
config.permissions.network_sandbox_policy().is_enabled(),
"expected network sandbox policy to be enabled",
);
assert!(config.legacy_sandbox_policy().has_full_network_access());
Ok(())
}
@@ -5241,7 +5195,10 @@ exclude_slash_tmp = true
)
.await?;
let sandbox_policy = config.legacy_sandbox_policy();
let sandbox_policy = config
.permissions
.effective_permission_profile()
.to_legacy_sandbox_policy(cwd.path())?;
let file_system_policy = config.permissions.file_system_sandbox_policy();
let network_policy = config.permissions.network_sandbox_policy();
@@ -6406,25 +6363,27 @@ async fn add_dir_override_extends_workspace_writable_roots() -> std::io::Result<
let expected_backend = backend.abs();
if cfg!(target_os = "windows") {
match &config.legacy_sandbox_policy() {
SandboxPolicy::ReadOnly { .. } => {}
other => panic!("expected read-only policy on Windows, got {other:?}"),
}
assert_eq!(
config.permissions.permission_profile(),
&PermissionProfile::read_only()
);
} else {
match &config.legacy_sandbox_policy() {
SandboxPolicy::WorkspaceWrite { writable_roots, .. } => {
assert_eq!(
writable_roots
.iter()
.filter(|root| **root == expected_backend)
.count(),
1,
"expected single writable root entry for {}",
expected_backend.display()
);
}
other => panic!("expected workspace-write policy, got {other:?}"),
}
assert!(
config
.permissions
.file_system_sandbox_policy()
.can_write_local_path_with_cwd(expected_backend.as_path(), config.cwd.as_path())
);
let writable_roots = config.permissions.user_visible_workspace_roots();
assert_eq!(
writable_roots
.iter()
.filter(|root| **root == expected_backend)
.count(),
1,
"expected single writable root entry for {}",
expected_backend.display()
);
}
Ok(())
@@ -6546,10 +6505,10 @@ async fn workspace_write_includes_configured_writable_root_once_without_memories
.await?;
if cfg!(target_os = "windows") {
match &config.legacy_sandbox_policy() {
SandboxPolicy::ReadOnly { .. } => {}
other => panic!("expected read-only policy on Windows, got {other:?}"),
}
assert_eq!(
config.permissions.permission_profile(),
&PermissionProfile::read_only()
);
} else {
assert!(
!memories_root.exists(),
@@ -6557,21 +6516,23 @@ async fn workspace_write_includes_configured_writable_root_once_without_memories
memories_root.display()
);
let expected_memories_root = memories_root.abs();
match &config.legacy_sandbox_policy() {
SandboxPolicy::WorkspaceWrite { writable_roots, .. } => {
assert!(!writable_roots.contains(&expected_memories_root));
assert_eq!(
writable_roots
.iter()
.filter(|root| **root == writable_root)
.count(),
1,
"expected single writable root entry for {}",
writable_root.display()
);
}
other => panic!("expected workspace-write policy, got {other:?}"),
}
assert!(
config
.permissions
.file_system_sandbox_policy()
.can_write_local_path_with_cwd(writable_root.as_path(), config.cwd.as_path())
);
let writable_roots = config.permissions.user_visible_workspace_roots();
assert!(!writable_roots.contains(&expected_memories_root));
assert_eq!(
writable_roots
.iter()
.filter(|root| **root == writable_root)
.count(),
1,
"expected single writable root entry for {}",
writable_root.display()
);
}
Ok(())
@@ -6621,17 +6582,13 @@ async fn memory_tool_makes_memories_root_readable_without_creating_or_widening_w
);
if cfg!(target_os = "windows") {
match &config.legacy_sandbox_policy() {
SandboxPolicy::ReadOnly { .. } => {}
other => panic!("expected read-only policy on Windows, got {other:?}"),
}
assert_eq!(
config.permissions.permission_profile(),
&PermissionProfile::read_only()
);
} else {
match &config.legacy_sandbox_policy() {
SandboxPolicy::WorkspaceWrite { writable_roots, .. } => {
assert!(!writable_roots.contains(&memories_root_abs));
}
other => panic!("expected workspace-write policy, got {other:?}"),
}
let writable_roots = config.permissions.user_visible_workspace_roots();
assert!(!writable_roots.contains(&memories_root_abs));
}
Ok(())
@@ -11601,24 +11558,14 @@ async fn test_untrusted_project_gets_unless_trusted_approval_policy() -> anyhow:
"Expected UnlessTrusted approval policy for untrusted project"
);
// Verify that untrusted projects still get WorkspaceWrite sandbox (or ReadOnly on Windows)
if cfg!(target_os = "windows") {
assert!(
matches!(
&config.legacy_sandbox_policy(),
SandboxPolicy::ReadOnly { .. }
),
"Expected ReadOnly on Windows"
);
} else {
assert!(
matches!(
&config.legacy_sandbox_policy(),
SandboxPolicy::WorkspaceWrite { .. }
),
"Expected WorkspaceWrite sandbox for untrusted project"
);
}
assert_eq!(
config.permissions.permission_profile(),
&if cfg!(target_os = "windows") {
PermissionProfile::read_only()
} else {
PermissionProfile::workspace_write()
}
);
Ok(())
}
@@ -11670,8 +11617,8 @@ async fn requirements_disallowing_default_sandbox_falls_back_to_required_default
.build()
.await?;
assert_eq!(
config.legacy_sandbox_policy(),
SandboxPolicy::new_read_only_policy()
config.permissions.effective_permission_profile(),
PermissionProfile::read_only()
);
Ok(())
}
@@ -11696,8 +11643,8 @@ async fn explicit_sandbox_mode_falls_back_when_disallowed_by_requirements() -> s
.build()
.await?;
assert_eq!(
config.legacy_sandbox_policy(),
SandboxPolicy::new_read_only_policy()
config.permissions.effective_permission_profile(),
PermissionProfile::read_only()
);
Ok(())
}
@@ -11974,8 +11921,6 @@ async fn permission_profile_override_falls_back_when_disallowed_by_requirements(
.build()
.await?;
let expected_sandbox_policy = SandboxPolicy::new_read_only_policy();
assert_eq!(config.legacy_sandbox_policy(), expected_sandbox_policy);
assert_eq!(
config.permissions.effective_permission_profile(),
PermissionProfile::read_only()
@@ -12110,10 +12055,6 @@ async fn permission_profile_override_preserves_split_write_roots() -> std::io::R
.file_system_sandbox_policy()
.can_write_local_path_with_cwd(outside_root.as_path(), config.cwd.as_path())
);
assert!(matches!(
&config.legacy_sandbox_policy(),
SandboxPolicy::WorkspaceWrite { .. }
));
assert_eq!(
config.permissions.network_sandbox_policy(),
NetworkSandboxPolicy::Restricted
-16
View File
@@ -204,7 +204,6 @@ pub use codex_config::ConstraintError;
pub use codex_config::ConstraintResult;
pub use codex_config::LoaderOverrides;
pub use codex_network_proxy::NetworkProxyAuditMetadata;
use codex_sandboxing::compatibility_sandbox_policy_for_permission_profile;
pub use codex_sandboxing::system_bwrap_warning;
pub use managed_features::ManagedFeatures;
pub(crate) use metrics::emit_session_start_metrics;
@@ -497,12 +496,6 @@ impl Permissions {
self.permission_profile().network_sandbox_policy()
}
/// Legacy compatibility projection derived from the canonical profile.
pub fn legacy_sandbox_policy(&self, cwd: &Path) -> SandboxPolicy {
let permission_profile = self.effective_permission_profile();
compatibility_sandbox_policy_for_permission_profile(&permission_profile, cwd)
}
/// Check whether a legacy sandbox policy can be applied to this permission
/// set after projecting it into the canonical permission profile.
pub fn can_set_legacy_sandbox_policy(
@@ -1794,10 +1787,6 @@ impl Config {
}
}
pub fn legacy_sandbox_policy(&self) -> SandboxPolicy {
self.permissions.legacy_sandbox_policy(self.cwd.as_path())
}
/// Combine runtime and profile roots without interpreting them on the current host.
pub fn effective_workspace_roots(&self) -> Vec<PathUri> {
let mut workspace_roots = self
@@ -3914,11 +3903,6 @@ impl Config {
)
} else {
let configured_network_proxy_config = NetworkProxyConfig::default();
// No named `[permissions]` profile is active, but permissions
// should still flow through the canonical profile representation.
// Derive the old `sandbox_mode` defaults as a profile first, then
// keep a legacy-compatible projection only for the remaining code
// paths that still speak `SandboxPolicy`.
let mut permission_profile = if let Some(PermissionConfig::Legacy { mode, workspace_write }) = permission_config {
translate_legacy_permissions(
mode,
@@ -185,7 +185,7 @@ async fn accepted_input_applies_thread_settings() {
environments: Some(local_selections(config.cwd.clone()).into_requests()),
approval_policy: Some(config.permissions.approval_policy.value()),
approvals_reviewer: Some(codex_config::types::ApprovalsReviewer::AutoReview),
sandbox_policy: Some(config.legacy_sandbox_policy()),
permission_profile: Some(config.permissions.effective_permission_profile()),
summary: config.model_reasoning_summary,
personality: config.personality,
collaboration_mode: Some(CollaborationMode {
@@ -57,7 +57,6 @@ use codex_protocol::models::FunctionCallOutputBody;
use codex_protocol::models::PermissionProfile;
use codex_protocol::models::ResponseInputItem;
use codex_protocol::models::ResponseItem;
use codex_protocol::models::SandboxEnforcement;
use codex_protocol::openai_models::ReasoningEffort;
use codex_protocol::protocol::AgentStatus;
use codex_protocol::protocol::AskForApproval;
@@ -65,12 +64,9 @@ use codex_protocol::protocol::EventMsg;
use codex_protocol::protocol::FileSystemAccessMode;
use codex_protocol::protocol::FileSystemPath;
use codex_protocol::protocol::FileSystemSandboxEntry;
use codex_protocol::protocol::FileSystemSandboxPolicy;
use codex_protocol::protocol::InterAgentCommunication;
use codex_protocol::protocol::ItemCompletedEvent;
use codex_protocol::protocol::NetworkSandboxPolicy;
use codex_protocol::protocol::Op;
use codex_protocol::protocol::SandboxPolicy;
use codex_protocol::protocol::SessionSource;
use codex_protocol::protocol::SubAgentSource;
use codex_protocol::protocol::TurnAbortReason;
@@ -2289,10 +2285,9 @@ async fn spawn_agent_reapplies_runtime_sandbox_after_role_config() {
Arc::clone(&environment_manager),
);
set_agent_control(&mut session, manager.agent_control());
let expected_sandbox = turn.config.legacy_sandbox_policy();
#[allow(deprecated)]
let mut expected_file_system_sandbox_policy =
FileSystemSandboxPolicy::from_legacy_sandbox_policy_for_cwd(&expected_sandbox, &turn.cwd);
let expected_profile = turn.config.permissions.effective_permission_profile();
let (mut expected_file_system_sandbox_policy, expected_network_sandbox_policy) =
expected_profile.to_runtime_permissions();
expected_file_system_sandbox_policy
.entries
.push(FileSystemSandboxEntry {
@@ -2308,9 +2303,8 @@ async fn spawn_agent_reapplies_runtime_sandbox_after_role_config() {
},
missing_path_behavior: None,
});
let expected_network_sandbox_policy = NetworkSandboxPolicy::from(&expected_sandbox);
let expected_permission_profile = PermissionProfile::from_runtime_permissions_with_enforcement(
SandboxEnforcement::from_legacy_sandbox_policy(&expected_sandbox),
expected_profile.enforcement(),
&expected_file_system_sandbox_policy,
expected_network_sandbox_policy,
);
@@ -2390,7 +2384,6 @@ async fn spawn_agent_reapplies_runtime_sandbox_after_role_config() {
.expect("spawned agent thread should exist")
.config_snapshot()
.await;
assert_eq!(snapshot.sandbox_policy(), expected_sandbox);
assert_eq!(snapshot.approval_policy, AskForApproval::OnRequest);
assert_eq!(snapshot.approvals_reviewer, ApprovalsReviewer::AutoReview);
assert_eq!(snapshot.permission_profile, expected_permission_profile);
@@ -4555,29 +4548,6 @@ async fn tool_handlers_cascade_close_and_resume_and_keep_explicitly_closed_subtr
async fn build_agent_spawn_config_uses_captured_step_settings_and_turn_context_values(
parent_enabled: bool,
) {
fn pick_allowed_sandbox_policy(
permissions: &crate::config::Permissions,
base: SandboxPolicy,
cwd: &std::path::Path,
) -> SandboxPolicy {
let candidates = [
SandboxPolicy::new_read_only_policy(),
SandboxPolicy::new_workspace_write_policy(),
SandboxPolicy::DangerFullAccess,
];
candidates
.into_iter()
.find(|candidate| {
if *candidate == base {
return false;
}
permissions
.can_set_legacy_sandbox_policy(candidate, cwd)
.is_ok()
})
.unwrap_or(base)
}
let (_session, mut turn) = make_session_and_context().await;
update_turn_settings_for_test(&mut turn, |settings| {
update_selected_settings_for_test(settings, |selected| {
@@ -4609,19 +4579,23 @@ async fn build_agent_spawn_config_uses_captured_step_settings_and_turn_context_v
}
#[allow(deprecated)]
let turn_cwd = turn.cwd.clone();
let sandbox_policy = pick_allowed_sandbox_policy(
&turn.config.permissions,
turn.config.legacy_sandbox_policy(),
turn_cwd.as_path(),
);
let file_system_sandbox_policy =
FileSystemSandboxPolicy::from_legacy_sandbox_policy_for_cwd(&sandbox_policy, &turn_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,
);
let base_profile = turn.config.permissions.effective_permission_profile();
let permission_profile = [
PermissionProfile::read_only(),
PermissionProfile::workspace_write()
.materialize_project_roots_with_workspace_roots(&[turn_cwd]),
PermissionProfile::Disabled,
]
.into_iter()
.find(|candidate| {
*candidate != base_profile
&& turn
.config
.permissions
.can_set_permission_profile(candidate)
.is_ok()
})
.unwrap_or(base_profile);
turn.initial_environments.environments.clear();
Arc::make_mut(&mut turn.config)
.permissions
+20 -8
View File
@@ -781,8 +781,11 @@ async fn websocket_test_codex_shell_chain() -> Result<()> {
let mut builder = test_codex().with_windows_cmd_shell();
let test = builder.build_with_websocket_server(&server).await?;
test.submit_turn_with_policy("run the echo command", test.config.legacy_sandbox_policy())
.await?;
test.submit_turn_with_permission_profile(
"run the echo command",
test.config.permissions.effective_permission_profile(),
)
.await?;
let connection = server.single_connection();
assert_eq!(connection.len(), 2);
@@ -847,8 +850,11 @@ async fn websocket_first_turn_uses_startup_prewarm_and_create(
});
}
let test = builder.build_with_websocket_server(&server).await?;
test.submit_turn_with_policy("hello", test.config.legacy_sandbox_policy())
.await?;
test.submit_turn_with_permission_profile(
"hello",
test.config.permissions.effective_permission_profile(),
)
.await?;
assert_eq!(server.handshakes().len(), 1);
let connection = server.single_connection();
@@ -942,8 +948,11 @@ async fn websocket_first_turn_handles_handshake_delay_with_startup_prewarm() ->
let mut builder = test_codex();
let test = builder.build_with_websocket_server(&server).await?;
test.submit_turn_with_policy("hello", test.config.legacy_sandbox_policy())
.await?;
test.submit_turn_with_permission_profile(
"hello",
test.config.permissions.effective_permission_profile(),
)
.await?;
assert_eq!(server.handshakes().len(), 1);
let connection = server.single_connection();
@@ -999,8 +1008,11 @@ async fn websocket_v2_test_codex_shell_chain() -> Result<()> {
});
let test = builder.build_with_websocket_server(&server).await?;
test.submit_turn_with_policy("run the echo command", test.config.legacy_sandbox_policy())
.await?;
test.submit_turn_with_permission_profile(
"run the echo command",
test.config.permissions.effective_permission_profile(),
)
.await?;
let connection = server.single_connection();
assert_eq!(connection.len(), 3);
+2 -2
View File
@@ -2843,7 +2843,7 @@ async fn user_turn_collaboration_mode_overrides_model_and_effort() -> anyhow::Re
.with_thread_settings(ThreadSettingsOverrides {
environments: Some(local_requests(config.cwd.clone())),
approval_policy: Some(config.permissions.approval_policy.value()),
sandbox_policy: Some(config.legacy_sandbox_policy()),
permission_profile: Some(config.permissions.effective_permission_profile()),
summary: Some(
config
.model_reasoning_summary
@@ -3101,7 +3101,7 @@ async fn user_turn_explicit_reasoning_summary_overrides_model_catalog_default()
.with_thread_settings(ThreadSettingsOverrides {
environments: Some(local_requests(config.cwd.clone())),
approval_policy: Some(config.permissions.approval_policy.value()),
sandbox_policy: Some(config.legacy_sandbox_policy()),
permission_profile: Some(config.permissions.effective_permission_profile()),
summary: Some(ReasoningSummary::Concise),
collaboration_mode: Some(CollaborationMode {
mode: ModeKind::Default,
@@ -546,7 +546,7 @@ async fn collaboration_instructions_added_on_user_turn() -> Result<()> {
.with_thread_settings(ThreadSettingsOverrides {
environments: Some(local_requests(test.config.cwd.clone())),
approval_policy: Some(test.config.permissions.approval_policy.value()),
sandbox_policy: Some(test.config.legacy_sandbox_policy()),
permission_profile: Some(test.config.permissions.effective_permission_profile()),
summary: Some(
test.config
.model_reasoning_summary
@@ -593,7 +593,7 @@ async fn collaboration_instructions_omitted_when_disabled() -> Result<()> {
.with_thread_settings(ThreadSettingsOverrides {
environments: Some(local_requests(test.config.cwd.clone())),
approval_policy: Some(test.config.permissions.approval_policy.value()),
sandbox_policy: Some(test.config.legacy_sandbox_policy()),
permission_profile: Some(test.config.permissions.effective_permission_profile()),
summary: Some(
test.config
.model_reasoning_summary
@@ -651,7 +651,7 @@ async fn user_turn_overrides_collaboration_instructions_after_override() -> Resu
.with_thread_settings(ThreadSettingsOverrides {
environments: Some(local_requests(test.config.cwd.clone())),
approval_policy: Some(test.config.permissions.approval_policy.value()),
sandbox_policy: Some(test.config.legacy_sandbox_policy()),
permission_profile: Some(test.config.permissions.effective_permission_profile()),
summary: Some(
test.config
.model_reasoning_summary
@@ -260,7 +260,7 @@ approvals_reviewer = "user"
"model": session.model, "modelProvider": session.model_provider_id, "cwd": session.cwd,
"approvalPolicy": app::AskForApproval::from(session.approval_policy),
"approvalsReviewer": app::ApprovalsReviewer::from(session.approvals_reviewer),
"sandbox": app::SandboxPolicy::from(test.config.legacy_sandbox_policy()),
"sandbox": app::SandboxPolicy::from(test.config.permissions.effective_permission_profile().to_legacy_sandbox_policy(test.config.cwd.as_path())?),
}))?;
client.track_response(
/*connection_id*/ 1,
+5 -5
View File
@@ -916,7 +916,7 @@ async fn send_user_turn_with_no_changes_does_not_send_environment_context() -> a
let default_cwd = config.cwd.clone();
let default_approval_policy = config.permissions.approval_policy.value();
let default_sandbox_policy = &config.legacy_sandbox_policy();
let default_permission_profile = config.permissions.effective_permission_profile();
let default_model = session_configured.model;
let default_effort = config.model_reasoning_effort.clone();
let default_summary = config.model_reasoning_summary;
@@ -930,7 +930,7 @@ async fn send_user_turn_with_no_changes_does_not_send_environment_context() -> a
.with_thread_settings(ThreadSettingsOverrides {
environments: Some(local_requests(default_cwd.clone())),
approval_policy: Some(default_approval_policy),
sandbox_policy: Some(default_sandbox_policy.clone()),
permission_profile: Some(default_permission_profile.clone()),
summary: Some(default_summary.unwrap_or(ReasoningSummary::Auto)),
collaboration_mode: Some(CollaborationMode {
mode: ModeKind::Default,
@@ -955,7 +955,7 @@ async fn send_user_turn_with_no_changes_does_not_send_environment_context() -> a
.with_thread_settings(ThreadSettingsOverrides {
environments: Some(local_requests(default_cwd.clone())),
approval_policy: Some(default_approval_policy),
sandbox_policy: Some(default_sandbox_policy.clone()),
permission_profile: Some(default_permission_profile.clone()),
summary: Some(default_summary.unwrap_or(ReasoningSummary::Auto)),
collaboration_mode: Some(CollaborationMode {
mode: ModeKind::Default,
@@ -1053,7 +1053,7 @@ async fn send_user_turn_with_changes_sends_environment_context() -> anyhow::Resu
let default_cwd = config.cwd.clone();
let default_approval_policy = config.permissions.approval_policy.value();
let default_sandbox_policy = &config.legacy_sandbox_policy();
let default_permission_profile = config.permissions.effective_permission_profile();
let default_model = session_configured.model;
let default_effort = config.model_reasoning_effort.clone();
let default_summary = config.model_reasoning_summary;
@@ -1067,7 +1067,7 @@ async fn send_user_turn_with_changes_sends_environment_context() -> anyhow::Resu
.with_thread_settings(ThreadSettingsOverrides {
environments: Some(local_requests(default_cwd.clone())),
approval_policy: Some(default_approval_policy),
sandbox_policy: Some(default_sandbox_policy.clone()),
permission_profile: Some(default_permission_profile.clone()),
summary: Some(default_summary.unwrap_or(ReasoningSummary::Auto)),
collaboration_mode: Some(CollaborationMode {
mode: ModeKind::Default,
+4 -6
View File
@@ -5,9 +5,9 @@ use anyhow::Result;
use codex_config::LoaderOverrides;
use codex_core::config::ConfigBuilder;
use codex_core::config::ConfigOverrides;
use codex_protocol::models::PermissionProfile;
use codex_protocol::protocol::AskForApproval;
use codex_protocol::protocol::EventMsg;
use codex_protocol::protocol::SandboxPolicy;
use codex_utils_cargo_bin::cargo_bin;
use core_test_support::responses;
use core_test_support::skip_if_remote;
@@ -107,13 +107,11 @@ async fn forged_worktree_project_config_cannot_start_host_mcp() -> Result<()> {
}
);
assert_eq!(
loaded.permissions.legacy_sandbox_policy(&checkout),
loaded.permissions.effective_permission_profile(),
if registered {
SandboxPolicy::DangerFullAccess
PermissionProfile::Disabled
} else {
SandboxPolicy::ReadOnly {
network_access: false,
}
PermissionProfile::read_only()
}
);