permissions: make runtime config profile-backed

This commit is contained in:
Michael Bolin
2026-04-25 18:50:01 -07:00
parent 9881dc7306
commit b0de9cbd2d
60 changed files with 1440 additions and 665 deletions
+59
View File
@@ -37,6 +37,7 @@ use codex_protocol::exec_output::ExecToolCallOutput;
use codex_protocol::models::FileSystemPermissions;
use codex_protocol::models::FunctionCallOutputBody;
use codex_protocol::models::FunctionCallOutputPayload;
use codex_protocol::models::PermissionProfile;
use codex_protocol::permissions::FileSystemAccessMode;
use codex_protocol::permissions::FileSystemPath;
use codex_protocol::permissions::FileSystemSandboxEntry;
@@ -1493,6 +1494,11 @@ async fn session_configured_reports_permission_profile_for_external_sandbox() ->
config.permissions.sandbox_policy = codex_config::Constrained::allow_any(sandbox_policy);
config.permissions.file_system_sandbox_policy = FileSystemSandboxPolicy::external_sandbox();
config.permissions.network_sandbox_policy = NetworkSandboxPolicy::Restricted;
config.permissions.permission_profile =
codex_config::Constrained::allow_any(PermissionProfile::from_runtime_permissions(
&config.permissions.file_system_sandbox_policy,
config.permissions.network_sandbox_policy,
));
});
let test = builder.build(&server).await?;
@@ -2246,6 +2252,7 @@ async fn set_rate_limits_retains_previous_credits() {
compact_prompt: config.compact_prompt.clone(),
approval_policy: config.permissions.approval_policy.clone(),
approvals_reviewer: config.approvals_reviewer,
permission_profile: config.permissions.permission_profile.clone(),
sandbox_policy: config.permissions.sandbox_policy.clone(),
file_system_sandbox_policy: config.permissions.file_system_sandbox_policy.clone(),
network_sandbox_policy: config.permissions.network_sandbox_policy,
@@ -2350,6 +2357,7 @@ async fn set_rate_limits_updates_plan_type_when_present() {
compact_prompt: config.compact_prompt.clone(),
approval_policy: config.permissions.approval_policy.clone(),
approvals_reviewer: config.approvals_reviewer,
permission_profile: config.permissions.permission_profile.clone(),
sandbox_policy: config.permissions.sandbox_policy.clone(),
file_system_sandbox_policy: config.permissions.file_system_sandbox_policy.clone(),
network_sandbox_policy: config.permissions.network_sandbox_policy,
@@ -2799,6 +2807,7 @@ pub(crate) async fn make_session_configuration_for_tests() -> SessionConfigurati
compact_prompt: config.compact_prompt.clone(),
approval_policy: config.permissions.approval_policy.clone(),
approvals_reviewer: config.approvals_reviewer,
permission_profile: config.permissions.permission_profile.clone(),
sandbox_policy: config.permissions.sandbox_policy.clone(),
file_system_sandbox_policy: config.permissions.file_system_sandbox_policy.clone(),
network_sandbox_policy: config.permissions.network_sandbox_policy,
@@ -2922,6 +2931,52 @@ async fn session_configuration_apply_permission_profile_preserves_existing_deny_
);
}
#[tokio::test]
async fn session_configuration_apply_permission_profile_accepts_direct_write_roots() {
let mut session_configuration = make_session_configuration_for_tests().await;
let cwd = tempfile::tempdir().expect("create cwd");
session_configuration.cwd = cwd.path().abs();
let external_write_dir = tempfile::tempdir().expect("create external write root");
let external_write_path = AbsolutePathBuf::from_absolute_path(
codex_utils_absolute_path::canonicalize_preserving_symlinks(external_write_dir.path())
.expect("canonical temp dir"),
)
.expect("canonical temp dir should be absolute");
let file_system_sandbox_policy =
FileSystemSandboxPolicy::restricted(vec![FileSystemSandboxEntry {
path: FileSystemPath::Path {
path: external_write_path.clone(),
},
access: FileSystemAccessMode::Write,
}]);
let permission_profile = PermissionProfile::from_runtime_permissions(
&file_system_sandbox_policy,
NetworkSandboxPolicy::Restricted,
);
let updated = session_configuration
.apply(&SessionSettingsUpdate {
permission_profile: Some(permission_profile.clone()),
..Default::default()
})
.expect("permission profile update should accept direct runtime permissions");
assert_eq!(updated.permission_profile(), permission_profile);
assert_eq!(
updated.file_system_sandbox_policy(),
file_system_sandbox_policy
);
assert_eq!(
updated.sandbox_policy(),
SandboxPolicy::WorkspaceWrite {
writable_roots: vec![external_write_path],
network_access: false,
exclude_tmpdir_env_var: true,
exclude_slash_tmp: true,
}
);
}
#[cfg_attr(windows, ignore)]
#[tokio::test]
async fn new_default_turn_uses_config_aware_skills_for_role_overrides() {
@@ -3114,6 +3169,7 @@ async fn session_new_fails_when_zsh_fork_enabled_without_zsh_path() {
compact_prompt: config.compact_prompt.clone(),
approval_policy: config.permissions.approval_policy.clone(),
approvals_reviewer: config.approvals_reviewer,
permission_profile: config.permissions.permission_profile.clone(),
sandbox_policy: config.permissions.sandbox_policy.clone(),
file_system_sandbox_policy: config.permissions.file_system_sandbox_policy.clone(),
network_sandbox_policy: config.permissions.network_sandbox_policy,
@@ -3220,6 +3276,7 @@ pub(crate) async fn make_session_and_context() -> (Session, TurnContext) {
compact_prompt: config.compact_prompt.clone(),
approval_policy: config.permissions.approval_policy.clone(),
approvals_reviewer: config.approvals_reviewer,
permission_profile: config.permissions.permission_profile.clone(),
sandbox_policy: config.permissions.sandbox_policy.clone(),
file_system_sandbox_policy: config.permissions.file_system_sandbox_policy.clone(),
network_sandbox_policy: config.permissions.network_sandbox_policy,
@@ -3434,6 +3491,7 @@ async fn make_session_with_config_and_rx(
compact_prompt: config.compact_prompt.clone(),
approval_policy: config.permissions.approval_policy.clone(),
approvals_reviewer: config.approvals_reviewer,
permission_profile: config.permissions.permission_profile.clone(),
sandbox_policy: config.permissions.sandbox_policy.clone(),
file_system_sandbox_policy: config.permissions.file_system_sandbox_policy.clone(),
network_sandbox_policy: config.permissions.network_sandbox_policy,
@@ -4583,6 +4641,7 @@ where
compact_prompt: config.compact_prompt.clone(),
approval_policy: config.permissions.approval_policy.clone(),
approvals_reviewer: config.approvals_reviewer,
permission_profile: config.permissions.permission_profile.clone(),
sandbox_policy: config.permissions.sandbox_policy.clone(),
file_system_sandbox_policy: config.permissions.file_system_sandbox_policy.clone(),
network_sandbox_policy: config.permissions.network_sandbox_policy,