mirror of
https://github.com/openai/codex.git
synced 2026-06-01 19:02:59 +00:00
permissions: make legacy profile conversion cwd-free (#19414)
## Why The profile conversion path still required a `cwd` even when it was only translating a legacy `SandboxPolicy` into a `PermissionProfile`. That made profile producers invent an ambient `cwd`, which is exactly the anchoring we are trying to remove from permission-profile data. A legacy workspace-write policy can be represented symbolically instead: `:cwd = write` plus read-only `:project_roots` metadata subpaths. This PR creates that cwd-free base so the rest of the stack can stop threading cwd through profile construction. Callers that actually need a concrete runtime filesystem policy for a specific cwd still have an explicitly named cwd-bound conversion. ## What Changed - `PermissionProfile::from_legacy_sandbox_policy` now takes only `&SandboxPolicy`. - `FileSystemSandboxPolicy::from_legacy_sandbox_policy` is now the symbolic, cwd-free projection for profiles. - The old concrete projection is retained as `FileSystemSandboxPolicy::from_legacy_sandbox_policy_for_cwd` for runtime/boundary code that must materialize legacy cwd behavior. - Workspace-write profiles preserve `CurrentWorkingDirectory` and `ProjectRoots` special entries instead of materializing cwd into absolute paths. ## Verification - `cargo check -p codex-protocol -p codex-core -p codex-app-server-protocol -p codex-app-server -p codex-exec -p codex-exec-server -p codex-tui -p codex-sandboxing -p codex-linux-sandbox -p codex-analytics --tests` - `just fix -p codex-protocol -p codex-core -p codex-app-server-protocol -p codex-app-server -p codex-exec -p codex-exec-server -p codex-tui -p codex-sandboxing -p codex-linux-sandbox -p codex-analytics` --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/19414). * #19395 * #19394 * #19393 * #19392 * #19391 * __->__ #19414
This commit is contained in:
@@ -546,7 +546,7 @@ impl App {
|
||||
fn sync_runtime_permissions_from_legacy_sandbox_policy(config: &mut Config) {
|
||||
let sandbox_policy = config.permissions.sandbox_policy.get();
|
||||
config.permissions.file_system_sandbox_policy =
|
||||
codex_protocol::permissions::FileSystemSandboxPolicy::from_legacy_sandbox_policy(
|
||||
codex_protocol::permissions::FileSystemSandboxPolicy::from_legacy_sandbox_policy_for_cwd(
|
||||
sandbox_policy,
|
||||
&config.cwd,
|
||||
);
|
||||
|
||||
@@ -2218,7 +2218,6 @@ async fn inactive_thread_approval_bubbles_into_active_view() -> Result<()> {
|
||||
sandbox_policy: SandboxPolicy::new_workspace_write_policy(),
|
||||
permission_profile: Some(PermissionProfile::from_legacy_sandbox_policy(
|
||||
&SandboxPolicy::new_workspace_write_policy(),
|
||||
std::path::Path::new("/tmp/agent"),
|
||||
)),
|
||||
rollout_path: Some(test_path_buf("/tmp/agent-rollout.jsonl")),
|
||||
..test_thread_session(agent_thread_id, test_path_buf("/tmp/agent"))
|
||||
@@ -2381,7 +2380,6 @@ async fn side_defers_subagent_approval_overlay_until_side_exits() -> Result<()>
|
||||
sandbox_policy: SandboxPolicy::new_workspace_write_policy(),
|
||||
permission_profile: Some(PermissionProfile::from_legacy_sandbox_policy(
|
||||
&SandboxPolicy::new_workspace_write_policy(),
|
||||
std::path::Path::new("/tmp/agent"),
|
||||
)),
|
||||
rollout_path: Some(test_path_buf("/tmp/agent-rollout.jsonl")),
|
||||
..test_thread_session(agent_thread_id, test_path_buf("/tmp/agent"))
|
||||
@@ -2607,7 +2605,6 @@ async fn inactive_thread_approval_badge_clears_after_turn_completion_notificatio
|
||||
sandbox_policy: SandboxPolicy::new_workspace_write_policy(),
|
||||
permission_profile: Some(PermissionProfile::from_legacy_sandbox_policy(
|
||||
&SandboxPolicy::new_workspace_write_policy(),
|
||||
std::path::Path::new("/tmp/agent"),
|
||||
)),
|
||||
rollout_path: Some(test_path_buf("/tmp/agent-rollout.jsonl")),
|
||||
..test_thread_session(agent_thread_id, test_path_buf("/tmp/agent"))
|
||||
@@ -2664,7 +2661,6 @@ async fn inactive_thread_started_notification_initializes_replay_session() -> Re
|
||||
sandbox_policy: SandboxPolicy::new_workspace_write_policy(),
|
||||
permission_profile: Some(PermissionProfile::from_legacy_sandbox_policy(
|
||||
&SandboxPolicy::new_workspace_write_policy(),
|
||||
std::path::Path::new("/tmp/main"),
|
||||
)),
|
||||
..test_thread_session(main_thread_id, test_path_buf("/tmp/main"))
|
||||
};
|
||||
@@ -2780,7 +2776,6 @@ async fn inactive_thread_started_notification_preserves_primary_model_when_path_
|
||||
sandbox_policy: SandboxPolicy::new_workspace_write_policy(),
|
||||
permission_profile: Some(PermissionProfile::from_legacy_sandbox_policy(
|
||||
&SandboxPolicy::new_workspace_write_policy(),
|
||||
std::path::Path::new("/tmp/main"),
|
||||
)),
|
||||
..test_thread_session(main_thread_id, test_path_buf("/tmp/main"))
|
||||
};
|
||||
@@ -2852,7 +2847,6 @@ async fn thread_read_session_state_does_not_reuse_primary_permission_profile() {
|
||||
sandbox_policy: SandboxPolicy::new_workspace_write_policy(),
|
||||
permission_profile: Some(PermissionProfile::from_legacy_sandbox_policy(
|
||||
&SandboxPolicy::new_workspace_write_policy(),
|
||||
std::path::Path::new("/tmp/main"),
|
||||
)),
|
||||
..test_thread_session(main_thread_id, test_path_buf("/tmp/main"))
|
||||
};
|
||||
@@ -3754,7 +3748,6 @@ fn test_thread_session(thread_id: ThreadId, cwd: PathBuf) -> ThreadSessionState
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: Some(PermissionProfile::from_legacy_sandbox_policy(
|
||||
&SandboxPolicy::new_read_only_policy(),
|
||||
cwd.as_path(),
|
||||
)),
|
||||
cwd: cwd.abs(),
|
||||
instruction_source_paths: Vec::new(),
|
||||
|
||||
@@ -305,7 +305,6 @@ mod tests {
|
||||
sandbox_policy: SandboxPolicy::new_read_only_policy(),
|
||||
permission_profile: Some(PermissionProfile::from_legacy_sandbox_policy(
|
||||
&SandboxPolicy::new_read_only_policy(),
|
||||
cwd.as_path(),
|
||||
)),
|
||||
cwd: cwd.abs(),
|
||||
instruction_source_paths: Vec::new(),
|
||||
|
||||
@@ -172,9 +172,14 @@ mod tests {
|
||||
codex_config::Constrained::allow_any(AskForApproval::OnRequest);
|
||||
app.config.approvals_reviewer = ApprovalsReviewer::AutoReview;
|
||||
let expected_sandbox_policy = SandboxPolicy::new_workspace_write_policy();
|
||||
let expected_permission_profile = PermissionProfile::from_legacy_sandbox_policy(
|
||||
&expected_sandbox_policy,
|
||||
&main_session.cwd,
|
||||
let expected_file_system_policy =
|
||||
FileSystemSandboxPolicy::from_legacy_sandbox_policy_for_cwd(
|
||||
&expected_sandbox_policy,
|
||||
&main_session.cwd,
|
||||
);
|
||||
let expected_permission_profile = PermissionProfile::from_runtime_permissions(
|
||||
&expected_file_system_policy,
|
||||
NetworkSandboxPolicy::from(&expected_sandbox_policy),
|
||||
);
|
||||
app.chat_widget.handle_thread_session(main_session.clone());
|
||||
app.chat_widget
|
||||
|
||||
@@ -1541,10 +1541,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn turn_start_permission_overrides_send_profiles_only_for_embedded_runtime_overrides() {
|
||||
let cwd = test_path_buf("/tmp/project");
|
||||
let workspace_write = SandboxPolicy::new_workspace_write_policy();
|
||||
let workspace_write_profile =
|
||||
PermissionProfile::from_legacy_sandbox_policy(&workspace_write, &cwd);
|
||||
PermissionProfile::from_legacy_sandbox_policy(&workspace_write);
|
||||
|
||||
let (sandbox, profile) = turn_start_permission_overrides(
|
||||
ThreadParamsMode::Embedded,
|
||||
@@ -1567,7 +1566,6 @@ mod tests {
|
||||
workspace_write.clone(),
|
||||
Some(PermissionProfile::from_legacy_sandbox_policy(
|
||||
&workspace_write,
|
||||
&cwd,
|
||||
)),
|
||||
);
|
||||
assert_eq!(sandbox, Some(workspace_write.into()));
|
||||
@@ -1581,13 +1579,12 @@ mod tests {
|
||||
external_sandbox.clone(),
|
||||
Some(PermissionProfile::from_legacy_sandbox_policy(
|
||||
&external_sandbox,
|
||||
&cwd,
|
||||
)),
|
||||
);
|
||||
assert_eq!(sandbox, None);
|
||||
assert_eq!(
|
||||
profile,
|
||||
Some(PermissionProfile::from_legacy_sandbox_policy(&external_sandbox, &cwd).into())
|
||||
Some(PermissionProfile::from_legacy_sandbox_policy(&external_sandbox).into())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1672,7 +1669,6 @@ mod tests {
|
||||
permission_profile: Some(
|
||||
codex_protocol::models::PermissionProfile::from_legacy_sandbox_policy(
|
||||
&codex_protocol::protocol::SandboxPolicy::new_read_only_policy(),
|
||||
&test_path_buf("/tmp/project"),
|
||||
)
|
||||
.into(),
|
||||
),
|
||||
@@ -1721,7 +1717,6 @@ mod tests {
|
||||
SandboxPolicy::new_read_only_policy(),
|
||||
Some(PermissionProfile::from_legacy_sandbox_policy(
|
||||
&SandboxPolicy::new_read_only_policy(),
|
||||
std::path::Path::new("/tmp/project"),
|
||||
)),
|
||||
test_path_buf("/tmp/project").abs(),
|
||||
Vec::new(),
|
||||
@@ -1755,7 +1750,6 @@ mod tests {
|
||||
SandboxPolicy::new_read_only_policy(),
|
||||
Some(PermissionProfile::from_legacy_sandbox_policy(
|
||||
&SandboxPolicy::new_read_only_policy(),
|
||||
std::path::Path::new("/tmp/project"),
|
||||
)),
|
||||
test_path_buf("/tmp/project").abs(),
|
||||
Vec::new(),
|
||||
|
||||
@@ -2125,7 +2125,7 @@ impl ChatWidget {
|
||||
{
|
||||
Some(permission_profile) => permission_profile.to_runtime_permissions(),
|
||||
None => (
|
||||
codex_protocol::permissions::FileSystemSandboxPolicy::from_legacy_sandbox_policy(
|
||||
codex_protocol::permissions::FileSystemSandboxPolicy::from_legacy_sandbox_policy_for_cwd(
|
||||
&event.sandbox_policy,
|
||||
&event.cwd,
|
||||
),
|
||||
@@ -9791,7 +9791,7 @@ impl ChatWidget {
|
||||
self.config.permissions.sandbox_policy.set(policy)?;
|
||||
let sandbox_policy = self.config.permissions.sandbox_policy.get();
|
||||
self.config.permissions.file_system_sandbox_policy =
|
||||
codex_protocol::permissions::FileSystemSandboxPolicy::from_legacy_sandbox_policy(
|
||||
codex_protocol::permissions::FileSystemSandboxPolicy::from_legacy_sandbox_policy_for_cwd(
|
||||
sandbox_policy,
|
||||
&self.config.cwd,
|
||||
);
|
||||
|
||||
@@ -321,13 +321,20 @@ async fn session_configured_syncs_widget_config_permissions_and_cwd() {
|
||||
let updated_sandbox = SandboxPolicy::new_workspace_write_policy();
|
||||
chat.set_sandbox_policy(updated_sandbox.clone())
|
||||
.expect("set sandbox policy");
|
||||
let updated_file_system_policy = FileSystemSandboxPolicy::from_legacy_sandbox_policy_for_cwd(
|
||||
&updated_sandbox,
|
||||
&expected_cwd,
|
||||
);
|
||||
assert_eq!(
|
||||
chat.config_ref().permissions.permission_profile(),
|
||||
codex_protocol::models::PermissionProfile::from_legacy_sandbox_policy(
|
||||
&updated_sandbox,
|
||||
&expected_cwd
|
||||
codex_protocol::models::PermissionProfile::from_runtime_permissions_with_enforcement(
|
||||
codex_protocol::models::SandboxEnforcement::from_legacy_sandbox_policy(
|
||||
&updated_sandbox
|
||||
),
|
||||
&updated_file_system_policy,
|
||||
NetworkSandboxPolicy::from(&updated_sandbox),
|
||||
),
|
||||
"local sandbox changes should replace SessionConfigured profile-derived runtime permissions"
|
||||
"local sandbox changes should replace SessionConfigured profile-derived runtime permissions using the widget cwd"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user