mirror of
https://github.com/openai/codex.git
synced 2026-11-14 21:40:39 +00:00
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:
@@ -212,9 +212,8 @@ fn collect_resume_override_mismatches(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if !sandbox_matches {
|
if !sandbox_matches {
|
||||||
let active_sandbox = config_snapshot.sandbox_policy();
|
|
||||||
mismatch_details.push(format!(
|
mismatch_details.push(format!(
|
||||||
"sandbox requested={requested_sandbox:?} active={active_sandbox:?}"
|
"sandbox requested={requested_sandbox:?} active={active_sandbox_label}"
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1191,7 +1191,6 @@ flag = false
|
|||||||
async fn managed_preferences_expand_home_directory_in_workspace_write_roots() -> anyhow::Result<()>
|
async fn managed_preferences_expand_home_directory_in_workspace_write_roots() -> anyhow::Result<()>
|
||||||
{
|
{
|
||||||
use base64::Engine;
|
use base64::Engine;
|
||||||
use codex_protocol::protocol::SandboxPolicy;
|
|
||||||
|
|
||||||
let Some(home) = dirs::home_dir() else {
|
let Some(home) = dirs::home_dir() else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@@ -1230,23 +1229,15 @@ writable_roots = ["~/code"]
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let expected_root = AbsolutePathBuf::from_absolute_path(home.join("code"))?;
|
let expected_root = AbsolutePathBuf::from_absolute_path(home.join("code"))?;
|
||||||
match &config.legacy_sandbox_policy() {
|
assert_eq!(
|
||||||
SandboxPolicy::WorkspaceWrite {
|
config.permissions.permission_profile(),
|
||||||
writable_roots,
|
&codex_protocol::models::PermissionProfile::workspace_write_with(
|
||||||
network_access: true,
|
&[expected_root],
|
||||||
exclude_tmpdir_env_var: true,
|
codex_protocol::permissions::NetworkSandboxPolicy::Enabled,
|
||||||
exclude_slash_tmp: false,
|
/*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.active_permission_profile(), None);
|
assert_eq!(config.permissions.active_permission_profile(), None);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -101,7 +101,6 @@ use codex_protocol::permissions::FileSystemSandboxPolicy;
|
|||||||
use codex_protocol::permissions::FileSystemSpecialPath;
|
use codex_protocol::permissions::FileSystemSpecialPath;
|
||||||
use codex_protocol::permissions::NetworkSandboxPolicy;
|
use codex_protocol::permissions::NetworkSandboxPolicy;
|
||||||
use codex_protocol::protocol::MultiAgentVersion;
|
use codex_protocol::protocol::MultiAgentVersion;
|
||||||
use codex_protocol::protocol::NetworkAccess;
|
|
||||||
use codex_protocol::protocol::RealtimeVoice;
|
use codex_protocol::protocol::RealtimeVoice;
|
||||||
use codex_protocol::protocol::SandboxPolicy;
|
use codex_protocol::protocol::SandboxPolicy;
|
||||||
use codex_protocol_test_support::ContentItemTestExt;
|
use codex_protocol_test_support::ContentItemTestExt;
|
||||||
@@ -2718,7 +2717,7 @@ async fn permissions_profiles_network_disabled_by_default_does_not_start_proxy()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[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 codex_home = TempDir::new()?;
|
||||||
let cwd = TempDir::new()?;
|
let cwd = TempDir::new()?;
|
||||||
std::fs::create_dir_all(cwd.path().join("docs"))?;
|
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!(
|
assert!(
|
||||||
!config
|
!config
|
||||||
.permissions
|
.permissions
|
||||||
@@ -2904,10 +2894,6 @@ async fn permission_profile_override_populates_runtime_permissions() -> std::io:
|
|||||||
permission_profile
|
permission_profile
|
||||||
);
|
);
|
||||||
assert_eq!(config.permissions.active_permission_profile(), None);
|
assert_eq!(config.permissions.active_permission_profile(), None);
|
||||||
assert_eq!(
|
|
||||||
&config.legacy_sandbox_policy(),
|
|
||||||
&SandboxPolicy::DangerFullAccess
|
|
||||||
);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3008,9 +2994,11 @@ extends = ":workspace"
|
|||||||
extends: Some(BUILT_IN_PERMISSION_PROFILE_WORKSPACE.to_string()),
|
extends: Some(BUILT_IN_PERMISSION_PROFILE_WORKSPACE.to_string()),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert!(
|
||||||
config.legacy_sandbox_policy(),
|
config
|
||||||
SandboxPolicy::new_workspace_write_policy()
|
.permissions
|
||||||
|
.file_system_sandbox_policy()
|
||||||
|
.can_write_local_path_with_cwd(cwd.path(), cwd.path())
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -3215,12 +3203,6 @@ async fn permission_profile_override_preserves_managed_unrestricted_filesystem()
|
|||||||
config.permissions.effective_permission_profile(),
|
config.permissions.effective_permission_profile(),
|
||||||
permission_profile
|
permission_profile
|
||||||
);
|
);
|
||||||
assert_eq!(
|
|
||||||
&config.legacy_sandbox_policy(),
|
|
||||||
&SandboxPolicy::ExternalSandbox {
|
|
||||||
network_access: NetworkAccess::Restricted,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3238,16 +3220,16 @@ async fn managed_unrestricted_permission_profile_still_enables_network_requireme
|
|||||||
ConfigToml::default(),
|
ConfigToml::default(),
|
||||||
ConfigOverrides {
|
ConfigOverrides {
|
||||||
cwd: Some(cwd.path().to_path_buf()),
|
cwd: Some(cwd.path().to_path_buf()),
|
||||||
permission_profile: Some(permission_profile),
|
permission_profile: Some(permission_profile.clone()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
codex_home.abs(),
|
codex_home.abs(),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&config.legacy_sandbox_policy(),
|
config.permissions.effective_permission_profile(),
|
||||||
&SandboxPolicy::DangerFullAccess,
|
permission_profile
|
||||||
"the legacy projection is intentionally lossy for managed unrestricted profiles"
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let layers = config
|
let layers = config
|
||||||
@@ -3276,8 +3258,7 @@ async fn managed_unrestricted_permission_profile_still_enables_network_requireme
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn permission_profile_override_keeps_memories_root_out_of_legacy_projection()
|
async fn permission_profile_override_keeps_memories_root_read_only() -> std::io::Result<()> {
|
||||||
-> std::io::Result<()> {
|
|
||||||
let codex_home = TempDir::new()?;
|
let codex_home = TempDir::new()?;
|
||||||
let cwd = TempDir::new()?;
|
let cwd = TempDir::new()?;
|
||||||
let permission_profile = PermissionProfile::from_runtime_permissions(
|
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()
|
.file_system_sandbox_policy()
|
||||||
.can_write_local_path_with_cwd(memories_root.as_path(), cwd.path())
|
.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(())
|
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 \
|
"implicit :workspace cannot be faithfully re-selected when it includes \
|
||||||
legacy sandbox_workspace_write settings"
|
legacy sandbox_workspace_write settings"
|
||||||
);
|
);
|
||||||
match config.legacy_sandbox_policy() {
|
assert_eq!(
|
||||||
SandboxPolicy::WorkspaceWrite {
|
policy
|
||||||
writable_roots,
|
.entries
|
||||||
network_access,
|
.into_iter()
|
||||||
exclude_tmpdir_env_var,
|
.filter(|entry| matches!(
|
||||||
exclude_slash_tmp,
|
&entry.path,
|
||||||
} => {
|
FileSystemPath::Special {
|
||||||
assert!(writable_roots.contains(&extra_root));
|
value: FileSystemSpecialPath::Tmpdir | FileSystemSpecialPath::SlashTmp
|
||||||
assert!(network_access);
|
}
|
||||||
assert!(exclude_tmpdir_env_var);
|
))
|
||||||
assert!(!exclude_slash_tmp);
|
.collect::<Vec<_>>(),
|
||||||
}
|
vec![FileSystemSandboxEntry::new(
|
||||||
sandbox_policy => panic!("expected workspace-write projection, got {sandbox_policy:?}"),
|
FileSystemPath::Special {
|
||||||
}
|
value: FileSystemSpecialPath::SlashTmp
|
||||||
|
},
|
||||||
|
FileSystemAccessMode::Write,
|
||||||
|
)]
|
||||||
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4341,15 +4317,6 @@ async fn permissions_profiles_allow_direct_write_roots_outside_workspace_root()
|
|||||||
.file_system_sandbox_policy()
|
.file_system_sandbox_policy()
|
||||||
.can_write_local_path_with_cwd(external_write_path.as_path(), cwd.path())
|
.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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4457,12 +4424,6 @@ async fn permissions_profiles_allow_unknown_special_paths() -> std::io::Result<(
|
|||||||
missing_path_behavior: None,
|
missing_path_behavior: None,
|
||||||
}]),
|
}]),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
|
||||||
&config.legacy_sandbox_policy(),
|
|
||||||
&SandboxPolicy::ReadOnly {
|
|
||||||
network_access: false,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert!(
|
assert!(
|
||||||
config.startup_warnings.iter().any(|warning| warning.contains(
|
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."
|
"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(),
|
config.permissions.file_system_sandbox_policy(),
|
||||||
FileSystemSandboxPolicy::restricted(Vec::new())
|
FileSystemSandboxPolicy::restricted(Vec::new())
|
||||||
);
|
);
|
||||||
assert_eq!(
|
|
||||||
&config.legacy_sandbox_policy(),
|
|
||||||
&SandboxPolicy::ReadOnly {
|
|
||||||
network_access: false,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert!(
|
assert!(
|
||||||
config.startup_warnings.iter().any(|warning| warning.contains(
|
config.startup_warnings.iter().any(|warning| warning.contains(
|
||||||
"Permissions profile `dev` does not define any recognized filesystem entries for this version of Codex."
|
"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(),
|
config.permissions.network_sandbox_policy().is_enabled(),
|
||||||
"expected network sandbox policy to be enabled",
|
"expected network sandbox policy to be enabled",
|
||||||
);
|
);
|
||||||
assert!(config.legacy_sandbox_policy().has_full_network_access());
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5241,7 +5195,10 @@ exclude_slash_tmp = true
|
|||||||
)
|
)
|
||||||
.await?;
|
.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 file_system_policy = config.permissions.file_system_sandbox_policy();
|
||||||
let network_policy = config.permissions.network_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();
|
let expected_backend = backend.abs();
|
||||||
if cfg!(target_os = "windows") {
|
if cfg!(target_os = "windows") {
|
||||||
match &config.legacy_sandbox_policy() {
|
assert_eq!(
|
||||||
SandboxPolicy::ReadOnly { .. } => {}
|
config.permissions.permission_profile(),
|
||||||
other => panic!("expected read-only policy on Windows, got {other:?}"),
|
&PermissionProfile::read_only()
|
||||||
}
|
);
|
||||||
} else {
|
} else {
|
||||||
match &config.legacy_sandbox_policy() {
|
assert!(
|
||||||
SandboxPolicy::WorkspaceWrite { writable_roots, .. } => {
|
config
|
||||||
assert_eq!(
|
.permissions
|
||||||
writable_roots
|
.file_system_sandbox_policy()
|
||||||
.iter()
|
.can_write_local_path_with_cwd(expected_backend.as_path(), config.cwd.as_path())
|
||||||
.filter(|root| **root == expected_backend)
|
);
|
||||||
.count(),
|
let writable_roots = config.permissions.user_visible_workspace_roots();
|
||||||
1,
|
assert_eq!(
|
||||||
"expected single writable root entry for {}",
|
writable_roots
|
||||||
expected_backend.display()
|
.iter()
|
||||||
);
|
.filter(|root| **root == expected_backend)
|
||||||
}
|
.count(),
|
||||||
other => panic!("expected workspace-write policy, got {other:?}"),
|
1,
|
||||||
}
|
"expected single writable root entry for {}",
|
||||||
|
expected_backend.display()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -6546,10 +6505,10 @@ async fn workspace_write_includes_configured_writable_root_once_without_memories
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if cfg!(target_os = "windows") {
|
if cfg!(target_os = "windows") {
|
||||||
match &config.legacy_sandbox_policy() {
|
assert_eq!(
|
||||||
SandboxPolicy::ReadOnly { .. } => {}
|
config.permissions.permission_profile(),
|
||||||
other => panic!("expected read-only policy on Windows, got {other:?}"),
|
&PermissionProfile::read_only()
|
||||||
}
|
);
|
||||||
} else {
|
} else {
|
||||||
assert!(
|
assert!(
|
||||||
!memories_root.exists(),
|
!memories_root.exists(),
|
||||||
@@ -6557,21 +6516,23 @@ async fn workspace_write_includes_configured_writable_root_once_without_memories
|
|||||||
memories_root.display()
|
memories_root.display()
|
||||||
);
|
);
|
||||||
let expected_memories_root = memories_root.abs();
|
let expected_memories_root = memories_root.abs();
|
||||||
match &config.legacy_sandbox_policy() {
|
assert!(
|
||||||
SandboxPolicy::WorkspaceWrite { writable_roots, .. } => {
|
config
|
||||||
assert!(!writable_roots.contains(&expected_memories_root));
|
.permissions
|
||||||
assert_eq!(
|
.file_system_sandbox_policy()
|
||||||
writable_roots
|
.can_write_local_path_with_cwd(writable_root.as_path(), config.cwd.as_path())
|
||||||
.iter()
|
);
|
||||||
.filter(|root| **root == writable_root)
|
let writable_roots = config.permissions.user_visible_workspace_roots();
|
||||||
.count(),
|
assert!(!writable_roots.contains(&expected_memories_root));
|
||||||
1,
|
assert_eq!(
|
||||||
"expected single writable root entry for {}",
|
writable_roots
|
||||||
writable_root.display()
|
.iter()
|
||||||
);
|
.filter(|root| **root == writable_root)
|
||||||
}
|
.count(),
|
||||||
other => panic!("expected workspace-write policy, got {other:?}"),
|
1,
|
||||||
}
|
"expected single writable root entry for {}",
|
||||||
|
writable_root.display()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -6621,17 +6582,13 @@ async fn memory_tool_makes_memories_root_readable_without_creating_or_widening_w
|
|||||||
);
|
);
|
||||||
|
|
||||||
if cfg!(target_os = "windows") {
|
if cfg!(target_os = "windows") {
|
||||||
match &config.legacy_sandbox_policy() {
|
assert_eq!(
|
||||||
SandboxPolicy::ReadOnly { .. } => {}
|
config.permissions.permission_profile(),
|
||||||
other => panic!("expected read-only policy on Windows, got {other:?}"),
|
&PermissionProfile::read_only()
|
||||||
}
|
);
|
||||||
} else {
|
} else {
|
||||||
match &config.legacy_sandbox_policy() {
|
let writable_roots = config.permissions.user_visible_workspace_roots();
|
||||||
SandboxPolicy::WorkspaceWrite { writable_roots, .. } => {
|
assert!(!writable_roots.contains(&memories_root_abs));
|
||||||
assert!(!writable_roots.contains(&memories_root_abs));
|
|
||||||
}
|
|
||||||
other => panic!("expected workspace-write policy, got {other:?}"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -11601,24 +11558,14 @@ async fn test_untrusted_project_gets_unless_trusted_approval_policy() -> anyhow:
|
|||||||
"Expected UnlessTrusted approval policy for untrusted project"
|
"Expected UnlessTrusted approval policy for untrusted project"
|
||||||
);
|
);
|
||||||
|
|
||||||
// Verify that untrusted projects still get WorkspaceWrite sandbox (or ReadOnly on Windows)
|
assert_eq!(
|
||||||
if cfg!(target_os = "windows") {
|
config.permissions.permission_profile(),
|
||||||
assert!(
|
&if cfg!(target_os = "windows") {
|
||||||
matches!(
|
PermissionProfile::read_only()
|
||||||
&config.legacy_sandbox_policy(),
|
} else {
|
||||||
SandboxPolicy::ReadOnly { .. }
|
PermissionProfile::workspace_write()
|
||||||
),
|
}
|
||||||
"Expected ReadOnly on Windows"
|
);
|
||||||
);
|
|
||||||
} else {
|
|
||||||
assert!(
|
|
||||||
matches!(
|
|
||||||
&config.legacy_sandbox_policy(),
|
|
||||||
SandboxPolicy::WorkspaceWrite { .. }
|
|
||||||
),
|
|
||||||
"Expected WorkspaceWrite sandbox for untrusted project"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -11670,8 +11617,8 @@ async fn requirements_disallowing_default_sandbox_falls_back_to_required_default
|
|||||||
.build()
|
.build()
|
||||||
.await?;
|
.await?;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
config.legacy_sandbox_policy(),
|
config.permissions.effective_permission_profile(),
|
||||||
SandboxPolicy::new_read_only_policy()
|
PermissionProfile::read_only()
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -11696,8 +11643,8 @@ async fn explicit_sandbox_mode_falls_back_when_disallowed_by_requirements() -> s
|
|||||||
.build()
|
.build()
|
||||||
.await?;
|
.await?;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
config.legacy_sandbox_policy(),
|
config.permissions.effective_permission_profile(),
|
||||||
SandboxPolicy::new_read_only_policy()
|
PermissionProfile::read_only()
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -11974,8 +11921,6 @@ async fn permission_profile_override_falls_back_when_disallowed_by_requirements(
|
|||||||
.build()
|
.build()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let expected_sandbox_policy = SandboxPolicy::new_read_only_policy();
|
|
||||||
assert_eq!(config.legacy_sandbox_policy(), expected_sandbox_policy);
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
config.permissions.effective_permission_profile(),
|
config.permissions.effective_permission_profile(),
|
||||||
PermissionProfile::read_only()
|
PermissionProfile::read_only()
|
||||||
@@ -12110,10 +12055,6 @@ async fn permission_profile_override_preserves_split_write_roots() -> std::io::R
|
|||||||
.file_system_sandbox_policy()
|
.file_system_sandbox_policy()
|
||||||
.can_write_local_path_with_cwd(outside_root.as_path(), config.cwd.as_path())
|
.can_write_local_path_with_cwd(outside_root.as_path(), config.cwd.as_path())
|
||||||
);
|
);
|
||||||
assert!(matches!(
|
|
||||||
&config.legacy_sandbox_policy(),
|
|
||||||
SandboxPolicy::WorkspaceWrite { .. }
|
|
||||||
));
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
config.permissions.network_sandbox_policy(),
|
config.permissions.network_sandbox_policy(),
|
||||||
NetworkSandboxPolicy::Restricted
|
NetworkSandboxPolicy::Restricted
|
||||||
|
|||||||
@@ -204,7 +204,6 @@ pub use codex_config::ConstraintError;
|
|||||||
pub use codex_config::ConstraintResult;
|
pub use codex_config::ConstraintResult;
|
||||||
pub use codex_config::LoaderOverrides;
|
pub use codex_config::LoaderOverrides;
|
||||||
pub use codex_network_proxy::NetworkProxyAuditMetadata;
|
pub use codex_network_proxy::NetworkProxyAuditMetadata;
|
||||||
use codex_sandboxing::compatibility_sandbox_policy_for_permission_profile;
|
|
||||||
pub use codex_sandboxing::system_bwrap_warning;
|
pub use codex_sandboxing::system_bwrap_warning;
|
||||||
pub use managed_features::ManagedFeatures;
|
pub use managed_features::ManagedFeatures;
|
||||||
pub(crate) use metrics::emit_session_start_metrics;
|
pub(crate) use metrics::emit_session_start_metrics;
|
||||||
@@ -497,12 +496,6 @@ impl Permissions {
|
|||||||
self.permission_profile().network_sandbox_policy()
|
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
|
/// Check whether a legacy sandbox policy can be applied to this permission
|
||||||
/// set after projecting it into the canonical permission profile.
|
/// set after projecting it into the canonical permission profile.
|
||||||
pub fn can_set_legacy_sandbox_policy(
|
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.
|
/// Combine runtime and profile roots without interpreting them on the current host.
|
||||||
pub fn effective_workspace_roots(&self) -> Vec<PathUri> {
|
pub fn effective_workspace_roots(&self) -> Vec<PathUri> {
|
||||||
let mut workspace_roots = self
|
let mut workspace_roots = self
|
||||||
@@ -3914,11 +3903,6 @@ impl Config {
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let configured_network_proxy_config = NetworkProxyConfig::default();
|
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 {
|
let mut permission_profile = if let Some(PermissionConfig::Legacy { mode, workspace_write }) = permission_config {
|
||||||
translate_legacy_permissions(
|
translate_legacy_permissions(
|
||||||
mode,
|
mode,
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ async fn accepted_input_applies_thread_settings() {
|
|||||||
environments: Some(local_selections(config.cwd.clone()).into_requests()),
|
environments: Some(local_selections(config.cwd.clone()).into_requests()),
|
||||||
approval_policy: Some(config.permissions.approval_policy.value()),
|
approval_policy: Some(config.permissions.approval_policy.value()),
|
||||||
approvals_reviewer: Some(codex_config::types::ApprovalsReviewer::AutoReview),
|
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,
|
summary: config.model_reasoning_summary,
|
||||||
personality: config.personality,
|
personality: config.personality,
|
||||||
collaboration_mode: Some(CollaborationMode {
|
collaboration_mode: Some(CollaborationMode {
|
||||||
|
|||||||
@@ -57,7 +57,6 @@ use codex_protocol::models::FunctionCallOutputBody;
|
|||||||
use codex_protocol::models::PermissionProfile;
|
use codex_protocol::models::PermissionProfile;
|
||||||
use codex_protocol::models::ResponseInputItem;
|
use codex_protocol::models::ResponseInputItem;
|
||||||
use codex_protocol::models::ResponseItem;
|
use codex_protocol::models::ResponseItem;
|
||||||
use codex_protocol::models::SandboxEnforcement;
|
|
||||||
use codex_protocol::openai_models::ReasoningEffort;
|
use codex_protocol::openai_models::ReasoningEffort;
|
||||||
use codex_protocol::protocol::AgentStatus;
|
use codex_protocol::protocol::AgentStatus;
|
||||||
use codex_protocol::protocol::AskForApproval;
|
use codex_protocol::protocol::AskForApproval;
|
||||||
@@ -65,12 +64,9 @@ use codex_protocol::protocol::EventMsg;
|
|||||||
use codex_protocol::protocol::FileSystemAccessMode;
|
use codex_protocol::protocol::FileSystemAccessMode;
|
||||||
use codex_protocol::protocol::FileSystemPath;
|
use codex_protocol::protocol::FileSystemPath;
|
||||||
use codex_protocol::protocol::FileSystemSandboxEntry;
|
use codex_protocol::protocol::FileSystemSandboxEntry;
|
||||||
use codex_protocol::protocol::FileSystemSandboxPolicy;
|
|
||||||
use codex_protocol::protocol::InterAgentCommunication;
|
use codex_protocol::protocol::InterAgentCommunication;
|
||||||
use codex_protocol::protocol::ItemCompletedEvent;
|
use codex_protocol::protocol::ItemCompletedEvent;
|
||||||
use codex_protocol::protocol::NetworkSandboxPolicy;
|
|
||||||
use codex_protocol::protocol::Op;
|
use codex_protocol::protocol::Op;
|
||||||
use codex_protocol::protocol::SandboxPolicy;
|
|
||||||
use codex_protocol::protocol::SessionSource;
|
use codex_protocol::protocol::SessionSource;
|
||||||
use codex_protocol::protocol::SubAgentSource;
|
use codex_protocol::protocol::SubAgentSource;
|
||||||
use codex_protocol::protocol::TurnAbortReason;
|
use codex_protocol::protocol::TurnAbortReason;
|
||||||
@@ -2289,10 +2285,9 @@ async fn spawn_agent_reapplies_runtime_sandbox_after_role_config() {
|
|||||||
Arc::clone(&environment_manager),
|
Arc::clone(&environment_manager),
|
||||||
);
|
);
|
||||||
set_agent_control(&mut session, manager.agent_control());
|
set_agent_control(&mut session, manager.agent_control());
|
||||||
let expected_sandbox = turn.config.legacy_sandbox_policy();
|
let expected_profile = turn.config.permissions.effective_permission_profile();
|
||||||
#[allow(deprecated)]
|
let (mut expected_file_system_sandbox_policy, expected_network_sandbox_policy) =
|
||||||
let mut expected_file_system_sandbox_policy =
|
expected_profile.to_runtime_permissions();
|
||||||
FileSystemSandboxPolicy::from_legacy_sandbox_policy_for_cwd(&expected_sandbox, &turn.cwd);
|
|
||||||
expected_file_system_sandbox_policy
|
expected_file_system_sandbox_policy
|
||||||
.entries
|
.entries
|
||||||
.push(FileSystemSandboxEntry {
|
.push(FileSystemSandboxEntry {
|
||||||
@@ -2308,9 +2303,8 @@ async fn spawn_agent_reapplies_runtime_sandbox_after_role_config() {
|
|||||||
},
|
},
|
||||||
missing_path_behavior: None,
|
missing_path_behavior: None,
|
||||||
});
|
});
|
||||||
let expected_network_sandbox_policy = NetworkSandboxPolicy::from(&expected_sandbox);
|
|
||||||
let expected_permission_profile = PermissionProfile::from_runtime_permissions_with_enforcement(
|
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_file_system_sandbox_policy,
|
||||||
expected_network_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")
|
.expect("spawned agent thread should exist")
|
||||||
.config_snapshot()
|
.config_snapshot()
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(snapshot.sandbox_policy(), expected_sandbox);
|
|
||||||
assert_eq!(snapshot.approval_policy, AskForApproval::OnRequest);
|
assert_eq!(snapshot.approval_policy, AskForApproval::OnRequest);
|
||||||
assert_eq!(snapshot.approvals_reviewer, ApprovalsReviewer::AutoReview);
|
assert_eq!(snapshot.approvals_reviewer, ApprovalsReviewer::AutoReview);
|
||||||
assert_eq!(snapshot.permission_profile, expected_permission_profile);
|
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(
|
async fn build_agent_spawn_config_uses_captured_step_settings_and_turn_context_values(
|
||||||
parent_enabled: bool,
|
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;
|
let (_session, mut turn) = make_session_and_context().await;
|
||||||
update_turn_settings_for_test(&mut turn, |settings| {
|
update_turn_settings_for_test(&mut turn, |settings| {
|
||||||
update_selected_settings_for_test(settings, |selected| {
|
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)]
|
#[allow(deprecated)]
|
||||||
let turn_cwd = turn.cwd.clone();
|
let turn_cwd = turn.cwd.clone();
|
||||||
let sandbox_policy = pick_allowed_sandbox_policy(
|
let base_profile = turn.config.permissions.effective_permission_profile();
|
||||||
&turn.config.permissions,
|
let permission_profile = [
|
||||||
turn.config.legacy_sandbox_policy(),
|
PermissionProfile::read_only(),
|
||||||
turn_cwd.as_path(),
|
PermissionProfile::workspace_write()
|
||||||
);
|
.materialize_project_roots_with_workspace_roots(&[turn_cwd]),
|
||||||
let file_system_sandbox_policy =
|
PermissionProfile::Disabled,
|
||||||
FileSystemSandboxPolicy::from_legacy_sandbox_policy_for_cwd(&sandbox_policy, &turn_cwd);
|
]
|
||||||
let network_sandbox_policy = NetworkSandboxPolicy::from(&sandbox_policy);
|
.into_iter()
|
||||||
let permission_profile = PermissionProfile::from_runtime_permissions_with_enforcement(
|
.find(|candidate| {
|
||||||
SandboxEnforcement::from_legacy_sandbox_policy(&sandbox_policy),
|
*candidate != base_profile
|
||||||
&file_system_sandbox_policy,
|
&& turn
|
||||||
network_sandbox_policy,
|
.config
|
||||||
);
|
.permissions
|
||||||
|
.can_set_permission_profile(candidate)
|
||||||
|
.is_ok()
|
||||||
|
})
|
||||||
|
.unwrap_or(base_profile);
|
||||||
turn.initial_environments.environments.clear();
|
turn.initial_environments.environments.clear();
|
||||||
Arc::make_mut(&mut turn.config)
|
Arc::make_mut(&mut turn.config)
|
||||||
.permissions
|
.permissions
|
||||||
|
|||||||
@@ -781,8 +781,11 @@ async fn websocket_test_codex_shell_chain() -> Result<()> {
|
|||||||
let mut builder = test_codex().with_windows_cmd_shell();
|
let mut builder = test_codex().with_windows_cmd_shell();
|
||||||
|
|
||||||
let test = builder.build_with_websocket_server(&server).await?;
|
let test = builder.build_with_websocket_server(&server).await?;
|
||||||
test.submit_turn_with_policy("run the echo command", test.config.legacy_sandbox_policy())
|
test.submit_turn_with_permission_profile(
|
||||||
.await?;
|
"run the echo command",
|
||||||
|
test.config.permissions.effective_permission_profile(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let connection = server.single_connection();
|
let connection = server.single_connection();
|
||||||
assert_eq!(connection.len(), 2);
|
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?;
|
let test = builder.build_with_websocket_server(&server).await?;
|
||||||
test.submit_turn_with_policy("hello", test.config.legacy_sandbox_policy())
|
test.submit_turn_with_permission_profile(
|
||||||
.await?;
|
"hello",
|
||||||
|
test.config.permissions.effective_permission_profile(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
assert_eq!(server.handshakes().len(), 1);
|
assert_eq!(server.handshakes().len(), 1);
|
||||||
let connection = server.single_connection();
|
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 mut builder = test_codex();
|
||||||
let test = builder.build_with_websocket_server(&server).await?;
|
let test = builder.build_with_websocket_server(&server).await?;
|
||||||
test.submit_turn_with_policy("hello", test.config.legacy_sandbox_policy())
|
test.submit_turn_with_permission_profile(
|
||||||
.await?;
|
"hello",
|
||||||
|
test.config.permissions.effective_permission_profile(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
assert_eq!(server.handshakes().len(), 1);
|
assert_eq!(server.handshakes().len(), 1);
|
||||||
let connection = server.single_connection();
|
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?;
|
let test = builder.build_with_websocket_server(&server).await?;
|
||||||
test.submit_turn_with_policy("run the echo command", test.config.legacy_sandbox_policy())
|
test.submit_turn_with_permission_profile(
|
||||||
.await?;
|
"run the echo command",
|
||||||
|
test.config.permissions.effective_permission_profile(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let connection = server.single_connection();
|
let connection = server.single_connection();
|
||||||
assert_eq!(connection.len(), 3);
|
assert_eq!(connection.len(), 3);
|
||||||
|
|||||||
@@ -2843,7 +2843,7 @@ async fn user_turn_collaboration_mode_overrides_model_and_effort() -> anyhow::Re
|
|||||||
.with_thread_settings(ThreadSettingsOverrides {
|
.with_thread_settings(ThreadSettingsOverrides {
|
||||||
environments: Some(local_requests(config.cwd.clone())),
|
environments: Some(local_requests(config.cwd.clone())),
|
||||||
approval_policy: Some(config.permissions.approval_policy.value()),
|
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(
|
summary: Some(
|
||||||
config
|
config
|
||||||
.model_reasoning_summary
|
.model_reasoning_summary
|
||||||
@@ -3101,7 +3101,7 @@ async fn user_turn_explicit_reasoning_summary_overrides_model_catalog_default()
|
|||||||
.with_thread_settings(ThreadSettingsOverrides {
|
.with_thread_settings(ThreadSettingsOverrides {
|
||||||
environments: Some(local_requests(config.cwd.clone())),
|
environments: Some(local_requests(config.cwd.clone())),
|
||||||
approval_policy: Some(config.permissions.approval_policy.value()),
|
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),
|
summary: Some(ReasoningSummary::Concise),
|
||||||
collaboration_mode: Some(CollaborationMode {
|
collaboration_mode: Some(CollaborationMode {
|
||||||
mode: ModeKind::Default,
|
mode: ModeKind::Default,
|
||||||
|
|||||||
@@ -546,7 +546,7 @@ async fn collaboration_instructions_added_on_user_turn() -> Result<()> {
|
|||||||
.with_thread_settings(ThreadSettingsOverrides {
|
.with_thread_settings(ThreadSettingsOverrides {
|
||||||
environments: Some(local_requests(test.config.cwd.clone())),
|
environments: Some(local_requests(test.config.cwd.clone())),
|
||||||
approval_policy: Some(test.config.permissions.approval_policy.value()),
|
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(
|
summary: Some(
|
||||||
test.config
|
test.config
|
||||||
.model_reasoning_summary
|
.model_reasoning_summary
|
||||||
@@ -593,7 +593,7 @@ async fn collaboration_instructions_omitted_when_disabled() -> Result<()> {
|
|||||||
.with_thread_settings(ThreadSettingsOverrides {
|
.with_thread_settings(ThreadSettingsOverrides {
|
||||||
environments: Some(local_requests(test.config.cwd.clone())),
|
environments: Some(local_requests(test.config.cwd.clone())),
|
||||||
approval_policy: Some(test.config.permissions.approval_policy.value()),
|
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(
|
summary: Some(
|
||||||
test.config
|
test.config
|
||||||
.model_reasoning_summary
|
.model_reasoning_summary
|
||||||
@@ -651,7 +651,7 @@ async fn user_turn_overrides_collaboration_instructions_after_override() -> Resu
|
|||||||
.with_thread_settings(ThreadSettingsOverrides {
|
.with_thread_settings(ThreadSettingsOverrides {
|
||||||
environments: Some(local_requests(test.config.cwd.clone())),
|
environments: Some(local_requests(test.config.cwd.clone())),
|
||||||
approval_policy: Some(test.config.permissions.approval_policy.value()),
|
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(
|
summary: Some(
|
||||||
test.config
|
test.config
|
||||||
.model_reasoning_summary
|
.model_reasoning_summary
|
||||||
|
|||||||
@@ -260,7 +260,7 @@ approvals_reviewer = "user"
|
|||||||
"model": session.model, "modelProvider": session.model_provider_id, "cwd": session.cwd,
|
"model": session.model, "modelProvider": session.model_provider_id, "cwd": session.cwd,
|
||||||
"approvalPolicy": app::AskForApproval::from(session.approval_policy),
|
"approvalPolicy": app::AskForApproval::from(session.approval_policy),
|
||||||
"approvalsReviewer": app::ApprovalsReviewer::from(session.approvals_reviewer),
|
"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(
|
client.track_response(
|
||||||
/*connection_id*/ 1,
|
/*connection_id*/ 1,
|
||||||
|
|||||||
@@ -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_cwd = config.cwd.clone();
|
||||||
let default_approval_policy = config.permissions.approval_policy.value();
|
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_model = session_configured.model;
|
||||||
let default_effort = config.model_reasoning_effort.clone();
|
let default_effort = config.model_reasoning_effort.clone();
|
||||||
let default_summary = config.model_reasoning_summary;
|
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 {
|
.with_thread_settings(ThreadSettingsOverrides {
|
||||||
environments: Some(local_requests(default_cwd.clone())),
|
environments: Some(local_requests(default_cwd.clone())),
|
||||||
approval_policy: Some(default_approval_policy),
|
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)),
|
summary: Some(default_summary.unwrap_or(ReasoningSummary::Auto)),
|
||||||
collaboration_mode: Some(CollaborationMode {
|
collaboration_mode: Some(CollaborationMode {
|
||||||
mode: ModeKind::Default,
|
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 {
|
.with_thread_settings(ThreadSettingsOverrides {
|
||||||
environments: Some(local_requests(default_cwd.clone())),
|
environments: Some(local_requests(default_cwd.clone())),
|
||||||
approval_policy: Some(default_approval_policy),
|
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)),
|
summary: Some(default_summary.unwrap_or(ReasoningSummary::Auto)),
|
||||||
collaboration_mode: Some(CollaborationMode {
|
collaboration_mode: Some(CollaborationMode {
|
||||||
mode: ModeKind::Default,
|
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_cwd = config.cwd.clone();
|
||||||
let default_approval_policy = config.permissions.approval_policy.value();
|
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_model = session_configured.model;
|
||||||
let default_effort = config.model_reasoning_effort.clone();
|
let default_effort = config.model_reasoning_effort.clone();
|
||||||
let default_summary = config.model_reasoning_summary;
|
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 {
|
.with_thread_settings(ThreadSettingsOverrides {
|
||||||
environments: Some(local_requests(default_cwd.clone())),
|
environments: Some(local_requests(default_cwd.clone())),
|
||||||
approval_policy: Some(default_approval_policy),
|
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)),
|
summary: Some(default_summary.unwrap_or(ReasoningSummary::Auto)),
|
||||||
collaboration_mode: Some(CollaborationMode {
|
collaboration_mode: Some(CollaborationMode {
|
||||||
mode: ModeKind::Default,
|
mode: ModeKind::Default,
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ use anyhow::Result;
|
|||||||
use codex_config::LoaderOverrides;
|
use codex_config::LoaderOverrides;
|
||||||
use codex_core::config::ConfigBuilder;
|
use codex_core::config::ConfigBuilder;
|
||||||
use codex_core::config::ConfigOverrides;
|
use codex_core::config::ConfigOverrides;
|
||||||
|
use codex_protocol::models::PermissionProfile;
|
||||||
use codex_protocol::protocol::AskForApproval;
|
use codex_protocol::protocol::AskForApproval;
|
||||||
use codex_protocol::protocol::EventMsg;
|
use codex_protocol::protocol::EventMsg;
|
||||||
use codex_protocol::protocol::SandboxPolicy;
|
|
||||||
use codex_utils_cargo_bin::cargo_bin;
|
use codex_utils_cargo_bin::cargo_bin;
|
||||||
use core_test_support::responses;
|
use core_test_support::responses;
|
||||||
use core_test_support::skip_if_remote;
|
use core_test_support::skip_if_remote;
|
||||||
@@ -107,13 +107,11 @@ async fn forged_worktree_project_config_cannot_start_host_mcp() -> Result<()> {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
loaded.permissions.legacy_sandbox_policy(&checkout),
|
loaded.permissions.effective_permission_profile(),
|
||||||
if registered {
|
if registered {
|
||||||
SandboxPolicy::DangerFullAccess
|
PermissionProfile::Disabled
|
||||||
} else {
|
} else {
|
||||||
SandboxPolicy::ReadOnly {
|
PermissionProfile::read_only()
|
||||||
network_access: false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -7809,7 +7809,7 @@ fn agent_picker_item_name_snapshot() {
|
|||||||
async fn side_fork_config_is_ephemeral_and_appends_developer_guardrails() {
|
async fn side_fork_config_is_ephemeral_and_appends_developer_guardrails() {
|
||||||
let app = make_test_app().await;
|
let app = make_test_app().await;
|
||||||
let original_approval_policy = app.config.permissions.approval_policy.value();
|
let original_approval_policy = app.config.permissions.approval_policy.value();
|
||||||
let original_sandbox_policy = app.config.legacy_sandbox_policy();
|
let original_permission_profile = app.config.permissions.effective_permission_profile();
|
||||||
|
|
||||||
let mut fork_config = app.side_fork_config();
|
let mut fork_config = app.side_fork_config();
|
||||||
crate::app_server_session::SideChatStorage::Temporary.configure_fork(&mut fork_config);
|
crate::app_server_session::SideChatStorage::Temporary.configure_fork(&mut fork_config);
|
||||||
@@ -7819,7 +7819,10 @@ async fn side_fork_config_is_ephemeral_and_appends_developer_guardrails() {
|
|||||||
fork_config.permissions.approval_policy.value(),
|
fork_config.permissions.approval_policy.value(),
|
||||||
original_approval_policy
|
original_approval_policy
|
||||||
);
|
);
|
||||||
assert_eq!(fork_config.legacy_sandbox_policy(), original_sandbox_policy);
|
assert_eq!(
|
||||||
|
fork_config.permissions.effective_permission_profile(),
|
||||||
|
original_permission_profile
|
||||||
|
);
|
||||||
let developer_instructions = fork_config
|
let developer_instructions = fork_config
|
||||||
.developer_instructions
|
.developer_instructions
|
||||||
.as_deref()
|
.as_deref()
|
||||||
|
|||||||
@@ -253,8 +253,12 @@ async fn misalignment_continuation_requires_current_review_and_submits_once() ->
|
|||||||
.then(|| config.permissions.user_visible_workspace_roots().to_vec()),
|
.then(|| config.permissions.user_visible_workspace_roots().to_vec()),
|
||||||
approval_policy: (!server_owned).then_some(AskForApproval::OnRequest),
|
approval_policy: (!server_owned).then_some(AskForApproval::OnRequest),
|
||||||
approvals_reviewer: None,
|
approvals_reviewer: None,
|
||||||
sandbox_policy: (!server_owned && !preserve)
|
sandbox_policy: (!server_owned && !preserve).then(|| config
|
||||||
.then(|| config.legacy_sandbox_policy().into()),
|
.permissions
|
||||||
|
.effective_permission_profile()
|
||||||
|
.to_legacy_sandbox_policy(config.cwd.as_path())
|
||||||
|
.expect("test permissions fit the legacy wire format")
|
||||||
|
.into()),
|
||||||
cyber_access_program: rollout_enabled.then_some(if daybreak {
|
cyber_access_program: rollout_enabled.then_some(if daybreak {
|
||||||
CyberAccessProgram::DaybreakBlue.into()
|
CyberAccessProgram::DaybreakBlue.into()
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ use super::helpers::drain_insert_history_transcript;
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::app_event::HistoryLookupResponse;
|
use crate::app_event::HistoryLookupResponse;
|
||||||
use codex_app_server_protocol::ImageReference;
|
use codex_app_server_protocol::ImageReference;
|
||||||
use codex_app_server_protocol::NetworkAccess;
|
|
||||||
use codex_app_server_protocol::SandboxPolicy;
|
|
||||||
use codex_app_server_protocol::ThreadItem;
|
use codex_app_server_protocol::ThreadItem;
|
||||||
use codex_protocol::models::FunctionCallOutputBody;
|
use codex_protocol::models::FunctionCallOutputBody;
|
||||||
use codex_protocol::models::ManagedFileSystemPermissions;
|
use codex_protocol::models::ManagedFileSystemPermissions;
|
||||||
@@ -686,10 +684,6 @@ async fn session_configured_syncs_widget_config_permissions_and_cwd() {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
let expected_permission_profile = expected_app_server_permission_profile.clone();
|
let expected_permission_profile = expected_app_server_permission_profile.clone();
|
||||||
let expected_core_sandbox = expected_permission_profile
|
|
||||||
.to_legacy_sandbox_policy(expected_cwd.as_path())
|
|
||||||
.expect("permission profile should project to legacy sandbox policy");
|
|
||||||
let expected_sandbox = SandboxPolicy::from(expected_core_sandbox);
|
|
||||||
let configured = crate::session_state::ThreadSessionState {
|
let configured = crate::session_state::ThreadSessionState {
|
||||||
read_only_history: false,
|
read_only_history: false,
|
||||||
daybreak_enabled: false,
|
daybreak_enabled: false,
|
||||||
@@ -721,8 +715,6 @@ async fn session_configured_syncs_widget_config_permissions_and_cwd() {
|
|||||||
AskForApproval::from(chat.config_ref().permissions.approval_policy.value()),
|
AskForApproval::from(chat.config_ref().permissions.approval_policy.value()),
|
||||||
AskForApproval::Never
|
AskForApproval::Never
|
||||||
);
|
);
|
||||||
let actual_sandbox = SandboxPolicy::from(chat.config_ref().legacy_sandbox_policy());
|
|
||||||
assert_eq!(&actual_sandbox, &expected_sandbox);
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
chat.config_ref().permissions.effective_permission_profile(),
|
chat.config_ref().permissions.effective_permission_profile(),
|
||||||
expected_app_server_permission_profile
|
expected_app_server_permission_profile
|
||||||
@@ -818,9 +810,6 @@ async fn session_configured_external_sandbox_keeps_external_runtime_policy() {
|
|||||||
network: NetworkSandboxPolicy::Restricted,
|
network: NetworkSandboxPolicy::Restricted,
|
||||||
};
|
};
|
||||||
let expected_permission_profile = expected_app_server_permission_profile.clone();
|
let expected_permission_profile = expected_app_server_permission_profile.clone();
|
||||||
let expected_sandbox = SandboxPolicy::ExternalSandbox {
|
|
||||||
network_access: NetworkAccess::Restricted,
|
|
||||||
};
|
|
||||||
let configured = crate::session_state::ThreadSessionState {
|
let configured = crate::session_state::ThreadSessionState {
|
||||||
read_only_history: false,
|
read_only_history: false,
|
||||||
daybreak_enabled: false,
|
daybreak_enabled: false,
|
||||||
@@ -848,8 +837,6 @@ async fn session_configured_external_sandbox_keeps_external_runtime_policy() {
|
|||||||
|
|
||||||
chat.handle_thread_session(configured);
|
chat.handle_thread_session(configured);
|
||||||
|
|
||||||
let actual_sandbox = SandboxPolicy::from(chat.config_ref().legacy_sandbox_policy());
|
|
||||||
assert_eq!(&actual_sandbox, &expected_sandbox);
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
chat.config_ref().permissions.effective_permission_profile(),
|
chat.config_ref().permissions.effective_permission_profile(),
|
||||||
expected_app_server_permission_profile
|
expected_app_server_permission_profile
|
||||||
|
|||||||
Reference in New Issue
Block a user