From f7d5c241cd8c5a9f7d5e117940bff93299b6bb77 Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Mon, 27 Apr 2026 11:37:54 -0700 Subject: [PATCH] permissions: remove cwd special path --- .../schema/json/ClientRequest.json | 17 +-- ...CommandExecutionRequestApprovalParams.json | 15 --- .../PermissionsRequestApprovalParams.json | 15 --- .../PermissionsRequestApprovalResponse.json | 15 --- .../schema/json/ServerNotification.json | 15 --- .../schema/json/ServerRequest.json | 15 --- .../codex_app_server_protocol.schemas.json | 17 +-- .../codex_app_server_protocol.v2.schemas.json | 17 +-- .../schema/json/v2/CommandExecParams.json | 15 --- ...anApprovalReviewCompletedNotification.json | 15 --- ...dianApprovalReviewStartedNotification.json | 15 --- .../RawResponseItemCompletedNotification.json | 2 +- .../schema/json/v2/ThreadForkParams.json | 15 --- .../schema/json/v2/ThreadForkResponse.json | 15 --- .../schema/json/v2/ThreadResumeParams.json | 17 +-- .../schema/json/v2/ThreadResumeResponse.json | 15 --- .../schema/json/v2/ThreadStartParams.json | 15 --- .../schema/json/v2/ThreadStartResponse.json | 15 --- .../schema/json/v2/TurnStartParams.json | 15 --- .../typescript/v2/FileSystemSpecialPath.ts | 2 +- .../app-server-protocol/src/protocol/v2.rs | 24 ++++- codex-rs/app-server/README.md | 4 +- .../app-server/src/bespoke_event_handling.rs | 7 +- .../app-server/tests/suite/v2/command_exec.rs | 8 +- codex-rs/core/src/config/config_tests.rs | 2 +- codex-rs/core/src/exec_policy_tests.rs | 2 +- codex-rs/core/src/exec_tests.rs | 24 +++-- codex-rs/core/src/safety_tests.rs | 2 +- codex-rs/core/src/session/session.rs | 28 ++--- codex-rs/core/src/session/tests.rs | 6 +- codex-rs/core/src/tools/handlers/mod.rs | 2 +- codex-rs/exec-server/src/file_system.rs | 4 +- codex-rs/exec-server/src/fs_sandbox.rs | 8 +- .../exec-server/src/remote_file_system.rs | 2 +- codex-rs/linux-sandbox/src/bwrap.rs | 2 +- .../linux-sandbox/src/linux_run_main_tests.rs | 4 +- codex-rs/protocol/src/models.rs | 8 +- codex-rs/protocol/src/permissions.rs | 100 +++++++++++------- codex-rs/protocol/src/protocol.rs | 4 +- codex-rs/sandboxing/src/policy_transforms.rs | 7 +- .../sandboxing/src/policy_transforms_tests.rs | 16 +-- .../tui/src/bottom_pane/approval_overlay.rs | 1 - 42 files changed, 164 insertions(+), 383 deletions(-) diff --git a/codex-rs/app-server-protocol/schema/json/ClientRequest.json b/codex-rs/app-server-protocol/schema/json/ClientRequest.json index cf665f4a5c5c..f8e0c0b22401 100644 --- a/codex-rs/app-server-protocol/schema/json/ClientRequest.json +++ b/codex-rs/app-server-protocol/schema/json/ClientRequest.json @@ -1028,21 +1028,6 @@ "title": "MinimalFileSystemSpecialPath", "type": "object" }, - { - "properties": { - "kind": { - "enum": [ - "current_working_directory" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "CurrentWorkingDirectoryFileSystemSpecialPath", - "type": "object" - }, { "properties": { "kind": { @@ -6124,4 +6109,4 @@ } ], "title": "ClientRequest" -} +} \ No newline at end of file diff --git a/codex-rs/app-server-protocol/schema/json/CommandExecutionRequestApprovalParams.json b/codex-rs/app-server-protocol/schema/json/CommandExecutionRequestApprovalParams.json index 76d265c5913a..ce587a7f106b 100644 --- a/codex-rs/app-server-protocol/schema/json/CommandExecutionRequestApprovalParams.json +++ b/codex-rs/app-server-protocol/schema/json/CommandExecutionRequestApprovalParams.json @@ -392,21 +392,6 @@ "title": "MinimalFileSystemSpecialPath", "type": "object" }, - { - "properties": { - "kind": { - "enum": [ - "current_working_directory" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "CurrentWorkingDirectoryFileSystemSpecialPath", - "type": "object" - }, { "properties": { "kind": { diff --git a/codex-rs/app-server-protocol/schema/json/PermissionsRequestApprovalParams.json b/codex-rs/app-server-protocol/schema/json/PermissionsRequestApprovalParams.json index ef268908f946..adb50dee4351 100644 --- a/codex-rs/app-server-protocol/schema/json/PermissionsRequestApprovalParams.json +++ b/codex-rs/app-server-protocol/schema/json/PermissionsRequestApprovalParams.json @@ -177,21 +177,6 @@ "title": "MinimalFileSystemSpecialPath", "type": "object" }, - { - "properties": { - "kind": { - "enum": [ - "current_working_directory" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "CurrentWorkingDirectoryFileSystemSpecialPath", - "type": "object" - }, { "properties": { "kind": { diff --git a/codex-rs/app-server-protocol/schema/json/PermissionsRequestApprovalResponse.json b/codex-rs/app-server-protocol/schema/json/PermissionsRequestApprovalResponse.json index f49165296a3f..3e775a3da9f0 100644 --- a/codex-rs/app-server-protocol/schema/json/PermissionsRequestApprovalResponse.json +++ b/codex-rs/app-server-protocol/schema/json/PermissionsRequestApprovalResponse.json @@ -177,21 +177,6 @@ "title": "MinimalFileSystemSpecialPath", "type": "object" }, - { - "properties": { - "kind": { - "enum": [ - "current_working_directory" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "CurrentWorkingDirectoryFileSystemSpecialPath", - "type": "object" - }, { "properties": { "kind": { diff --git a/codex-rs/app-server-protocol/schema/json/ServerNotification.json b/codex-rs/app-server-protocol/schema/json/ServerNotification.json index 629c0b97fa50..aa5c944d9c45 100644 --- a/codex-rs/app-server-protocol/schema/json/ServerNotification.json +++ b/codex-rs/app-server-protocol/schema/json/ServerNotification.json @@ -1199,21 +1199,6 @@ "title": "MinimalFileSystemSpecialPath", "type": "object" }, - { - "properties": { - "kind": { - "enum": [ - "current_working_directory" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "CurrentWorkingDirectoryFileSystemSpecialPath", - "type": "object" - }, { "properties": { "kind": { diff --git a/codex-rs/app-server-protocol/schema/json/ServerRequest.json b/codex-rs/app-server-protocol/schema/json/ServerRequest.json index 50510adf9841..51cab50810fd 100644 --- a/codex-rs/app-server-protocol/schema/json/ServerRequest.json +++ b/codex-rs/app-server-protocol/schema/json/ServerRequest.json @@ -731,21 +731,6 @@ "title": "MinimalFileSystemSpecialPath", "type": "object" }, - { - "properties": { - "kind": { - "enum": [ - "current_working_directory" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "CurrentWorkingDirectoryFileSystemSpecialPath", - "type": "object" - }, { "properties": { "kind": { diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json index 47c6680ad06d..696a734d151f 100644 --- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json +++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json @@ -8573,21 +8573,6 @@ "title": "MinimalFileSystemSpecialPath", "type": "object" }, - { - "properties": { - "kind": { - "enum": [ - "current_working_directory" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "CurrentWorkingDirectoryFileSystemSpecialPath", - "type": "object" - }, { "properties": { "kind": { @@ -17752,4 +17737,4 @@ }, "title": "CodexAppServerProtocol", "type": "object" -} +} \ No newline at end of file diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json index 455d9f16f44c..cb2e86700685 100644 --- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json +++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json @@ -5092,21 +5092,6 @@ "title": "MinimalFileSystemSpecialPath", "type": "object" }, - { - "properties": { - "kind": { - "enum": [ - "current_working_directory" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "CurrentWorkingDirectoryFileSystemSpecialPath", - "type": "object" - }, { "properties": { "kind": { @@ -15637,4 +15622,4 @@ }, "title": "CodexAppServerProtocolV2", "type": "object" -} +} \ No newline at end of file diff --git a/codex-rs/app-server-protocol/schema/json/v2/CommandExecParams.json b/codex-rs/app-server-protocol/schema/json/v2/CommandExecParams.json index b85a0e79119c..7db4d635ee87 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/CommandExecParams.json +++ b/codex-rs/app-server-protocol/schema/json/v2/CommandExecParams.json @@ -146,21 +146,6 @@ "title": "MinimalFileSystemSpecialPath", "type": "object" }, - { - "properties": { - "kind": { - "enum": [ - "current_working_directory" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "CurrentWorkingDirectoryFileSystemSpecialPath", - "type": "object" - }, { "properties": { "kind": { diff --git a/codex-rs/app-server-protocol/schema/json/v2/ItemGuardianApprovalReviewCompletedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/ItemGuardianApprovalReviewCompletedNotification.json index e4a278330c71..98f44e50a2cf 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ItemGuardianApprovalReviewCompletedNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ItemGuardianApprovalReviewCompletedNotification.json @@ -184,21 +184,6 @@ "title": "MinimalFileSystemSpecialPath", "type": "object" }, - { - "properties": { - "kind": { - "enum": [ - "current_working_directory" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "CurrentWorkingDirectoryFileSystemSpecialPath", - "type": "object" - }, { "properties": { "kind": { diff --git a/codex-rs/app-server-protocol/schema/json/v2/ItemGuardianApprovalReviewStartedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/ItemGuardianApprovalReviewStartedNotification.json index b4ad6af44b74..16e47c2d726d 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ItemGuardianApprovalReviewStartedNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ItemGuardianApprovalReviewStartedNotification.json @@ -177,21 +177,6 @@ "title": "MinimalFileSystemSpecialPath", "type": "object" }, - { - "properties": { - "kind": { - "enum": [ - "current_working_directory" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "CurrentWorkingDirectoryFileSystemSpecialPath", - "type": "object" - }, { "properties": { "kind": { diff --git a/codex-rs/app-server-protocol/schema/json/v2/RawResponseItemCompletedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/RawResponseItemCompletedNotification.json index 34e4086c596e..d877286d8944 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/RawResponseItemCompletedNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v2/RawResponseItemCompletedNotification.json @@ -922,4 +922,4 @@ ], "title": "RawResponseItemCompletedNotification", "type": "object" -} +} \ No newline at end of file diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadForkParams.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadForkParams.json index d120fc8b5d53..504dbdc67eb4 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadForkParams.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadForkParams.json @@ -183,21 +183,6 @@ "title": "MinimalFileSystemSpecialPath", "type": "object" }, - { - "properties": { - "kind": { - "enum": [ - "current_working_directory" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "CurrentWorkingDirectoryFileSystemSpecialPath", - "type": "object" - }, { "properties": { "kind": { diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json index a2f2490a0b23..3ab0077d0ac3 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json @@ -569,21 +569,6 @@ "title": "MinimalFileSystemSpecialPath", "type": "object" }, - { - "properties": { - "kind": { - "enum": [ - "current_working_directory" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "CurrentWorkingDirectoryFileSystemSpecialPath", - "type": "object" - }, { "properties": { "kind": { diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeParams.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeParams.json index 872a3eb32418..aaa2a439cb76 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeParams.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeParams.json @@ -257,21 +257,6 @@ "title": "MinimalFileSystemSpecialPath", "type": "object" }, - { - "properties": { - "kind": { - "enum": [ - "current_working_directory" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "CurrentWorkingDirectoryFileSystemSpecialPath", - "type": "object" - }, { "properties": { "kind": { @@ -1452,4 +1437,4 @@ ], "title": "ThreadResumeParams", "type": "object" -} +} \ No newline at end of file diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json index 516627576ec9..12c38db5dc7a 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json @@ -569,21 +569,6 @@ "title": "MinimalFileSystemSpecialPath", "type": "object" }, - { - "properties": { - "kind": { - "enum": [ - "current_working_directory" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "CurrentWorkingDirectoryFileSystemSpecialPath", - "type": "object" - }, { "properties": { "kind": { diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartParams.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartParams.json index 5a59e280ea19..bc8d83d2bc33 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartParams.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartParams.json @@ -209,21 +209,6 @@ "title": "MinimalFileSystemSpecialPath", "type": "object" }, - { - "properties": { - "kind": { - "enum": [ - "current_working_directory" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "CurrentWorkingDirectoryFileSystemSpecialPath", - "type": "object" - }, { "properties": { "kind": { diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json index f773c0be69d3..6e1637ec8054 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json @@ -569,21 +569,6 @@ "title": "MinimalFileSystemSpecialPath", "type": "object" }, - { - "properties": { - "kind": { - "enum": [ - "current_working_directory" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "CurrentWorkingDirectoryFileSystemSpecialPath", - "type": "object" - }, { "properties": { "kind": { diff --git a/codex-rs/app-server-protocol/schema/json/v2/TurnStartParams.json b/codex-rs/app-server-protocol/schema/json/v2/TurnStartParams.json index 559698100f9c..d866c03152d1 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/TurnStartParams.json +++ b/codex-rs/app-server-protocol/schema/json/v2/TurnStartParams.json @@ -218,21 +218,6 @@ "title": "MinimalFileSystemSpecialPath", "type": "object" }, - { - "properties": { - "kind": { - "enum": [ - "current_working_directory" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "CurrentWorkingDirectoryFileSystemSpecialPath", - "type": "object" - }, { "properties": { "kind": { diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/FileSystemSpecialPath.ts b/codex-rs/app-server-protocol/schema/typescript/v2/FileSystemSpecialPath.ts index bf27547ee74e..f4dc2b01e619 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/FileSystemSpecialPath.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/FileSystemSpecialPath.ts @@ -2,4 +2,4 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -export type FileSystemSpecialPath = { "kind": "root" } | { "kind": "minimal" } | { "kind": "current_working_directory" } | { "kind": "project_roots", subpath: string | null, } | { "kind": "tmpdir" } | { "kind": "slash_tmp" } | { "kind": "unknown", path: string, subpath: string | null, }; +export type FileSystemSpecialPath = { "kind": "root" } | { "kind": "minimal" } | { "kind": "project_roots", subpath: string | null, } | { "kind": "tmpdir" } | { "kind": "slash_tmp" } | { "kind": "unknown", path: string, subpath: string | null, }; diff --git a/codex-rs/app-server-protocol/src/protocol/v2.rs b/codex-rs/app-server-protocol/src/protocol/v2.rs index b7dccc8613bd..e1c941019d13 100644 --- a/codex-rs/app-server-protocol/src/protocol/v2.rs +++ b/codex-rs/app-server-protocol/src/protocol/v2.rs @@ -1434,7 +1434,7 @@ v2_enum_from_core!( pub enum FileSystemSpecialPath { Root, Minimal, - CurrentWorkingDirectory, + #[serde(alias = "current_working_directory")] ProjectRoots { subpath: Option, }, @@ -1451,7 +1451,6 @@ impl From for FileSystemSpecialPath { match value { CoreFileSystemSpecialPath::Root => Self::Root, CoreFileSystemSpecialPath::Minimal => Self::Minimal, - CoreFileSystemSpecialPath::CurrentWorkingDirectory => Self::CurrentWorkingDirectory, CoreFileSystemSpecialPath::ProjectRoots { subpath } => Self::ProjectRoots { subpath }, CoreFileSystemSpecialPath::Tmpdir => Self::Tmpdir, CoreFileSystemSpecialPath::SlashTmp => Self::SlashTmp, @@ -1465,7 +1464,6 @@ impl From for CoreFileSystemSpecialPath { match value { FileSystemSpecialPath::Root => Self::Root, FileSystemSpecialPath::Minimal => Self::Minimal, - FileSystemSpecialPath::CurrentWorkingDirectory => Self::CurrentWorkingDirectory, FileSystemSpecialPath::ProjectRoots { subpath } => Self::ProjectRoots { subpath }, FileSystemSpecialPath::Tmpdir => Self::Tmpdir, FileSystemSpecialPath::SlashTmp => Self::SlashTmp, @@ -8111,6 +8109,26 @@ mod tests { .expect_err("zero glob scan depth should fail deserialization"); } + #[test] + fn legacy_current_working_directory_special_path_deserializes_as_project_roots() { + let special_path = serde_json::from_value::(json!({ + "kind": "current_working_directory", + })) + .expect("legacy cwd special path should deserialize"); + + assert_eq!( + special_path, + FileSystemSpecialPath::ProjectRoots { subpath: None } + ); + assert_eq!( + serde_json::to_value(&special_path).expect("serialize special path"), + json!({ + "kind": "project_roots", + "subpath": null, + }) + ); + } + #[test] fn permissions_request_approval_response_uses_granted_permission_profile_without_macos() { let read_only_path = if cfg!(windows) { diff --git a/codex-rs/app-server/README.md b/codex-rs/app-server/README.md index 35df7016c487..639bfce5c930 100644 --- a/codex-rs/app-server/README.md +++ b/codex-rs/app-server/README.md @@ -909,7 +909,7 @@ Run a standalone command (argv vector) in the server’s sandbox without creatin "type": "managed", "fileSystem": { "type": "restricted", "entries": [ { "path": { "type": "special", "value": { "kind": "root" } }, "access": "read" }, - { "path": { "type": "special", "value": { "kind": "current_working_directory" } }, "access": "write" } + { "path": { "type": "special", "value": { "kind": "project_roots", "subpath": null } }, "access": "write" } ] }, "network": { "enabled": false } }, @@ -1255,7 +1255,7 @@ the client can offer session-scoped and/or persistent approval choices. ### Permission requests -The built-in `request_permissions` tool sends an `item/permissions/requestApproval` JSON-RPC request to the client with the requested permission profile. This v2 payload mirrors the command-execution `additionalPermissions` shape: it can request network access and additional filesystem access. The `cwd` field identifies the directory used to resolve cwd-relative permissions such as `:cwd`, `:project_roots`, and relative deny globs. +The built-in `request_permissions` tool sends an `item/permissions/requestApproval` JSON-RPC request to the client with the requested permission profile. This v2 payload mirrors the command-execution `additionalPermissions` shape: it can request network access and additional filesystem access. The `cwd` field identifies the directory used to resolve project-root permissions and relative deny globs. ```json { diff --git a/codex-rs/app-server/src/bespoke_event_handling.rs b/codex-rs/app-server/src/bespoke_event_handling.rs index a1eba990c6dd..a398acc35cd2 100644 --- a/codex-rs/app-server/src/bespoke_event_handling.rs +++ b/codex-rs/app-server/src/bespoke_event_handling.rs @@ -4008,7 +4008,7 @@ mod tests { file_system: Some(CoreFileSystemPermissions { entries: vec![FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }], @@ -4054,7 +4054,7 @@ mod tests { file_system: Some(CoreFileSystemPermissions { entries: vec![FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }], @@ -4104,7 +4104,8 @@ mod tests { "path": { "type": "special", "value": { - "kind": "current_working_directory" + "kind": "project_roots", + "subpath": null } }, "access": "write" diff --git a/codex-rs/app-server/tests/suite/v2/command_exec.rs b/codex-rs/app-server/tests/suite/v2/command_exec.rs index 83718a8dc7e7..211cec935508 100644 --- a/codex-rs/app-server/tests/suite/v2/command_exec.rs +++ b/codex-rs/app-server/tests/suite/v2/command_exec.rs @@ -246,7 +246,7 @@ async fn command_exec_accepts_permission_profile() -> Result<()> { #[cfg(unix)] #[tokio::test] -async fn command_exec_permission_profile_cwd_uses_command_cwd() -> Result<()> { +async fn command_exec_permission_profile_project_roots_use_command_cwd() -> Result<()> { let server = create_mock_responses_server_sequence_unchecked(Vec::new()).await; let codex_home = TempDir::new()?; let command_dir = codex_home.path().join("command-cwd"); @@ -264,7 +264,7 @@ async fn command_exec_permission_profile_cwd_uses_command_cwd() -> Result<()> { }; entries.push(FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::ProjectRoots { subpath: None }, }, access: FileSystemAccessMode::Write, }); @@ -298,7 +298,7 @@ async fn command_exec_permission_profile_cwd_uses_command_cwd() -> Result<()> { let response: CommandExecResponse = to_response(response)?; assert_eq!( response.exit_code, 0, - "parent cwd write should fail under command-cwd-scoped profile: {response:?}" + "parent cwd write should fail under command project-root profile: {response:?}" ); assert_eq!( std::fs::read_to_string(command_dir.join("child.txt"))?, @@ -306,7 +306,7 @@ async fn command_exec_permission_profile_cwd_uses_command_cwd() -> Result<()> { ); assert!( !codex_home.path().join("parent.txt").exists(), - "permissionProfile :cwd write should not grant the server cwd when command cwd differs" + "permissionProfile :project_roots write should not grant the server cwd when command cwd differs" ); Ok(()) diff --git a/codex-rs/core/src/config/config_tests.rs b/codex-rs/core/src/config/config_tests.rs index 995e4299c641..e25c83e58d62 100644 --- a/codex-rs/core/src/config/config_tests.rs +++ b/codex-rs/core/src/config/config_tests.rs @@ -947,7 +947,7 @@ async fn permission_profile_override_applies_runtime_roots_to_legacy_projection( }, FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }, diff --git a/codex-rs/core/src/exec_policy_tests.rs b/codex-rs/core/src/exec_policy_tests.rs index fb90ef322f3e..3692e31ee709 100644 --- a/codex-rs/core/src/exec_policy_tests.rs +++ b/codex-rs/core/src/exec_policy_tests.rs @@ -1004,7 +1004,7 @@ fn managed_cwd_write_profile_is_not_read_only() { }, FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }, diff --git a/codex-rs/core/src/exec_tests.rs b/codex-rs/core/src/exec_tests.rs index 4e8ba10c2010..a9304e75eee1 100644 --- a/codex-rs/core/src/exec_tests.rs +++ b/codex-rs/core/src/exec_tests.rs @@ -535,7 +535,9 @@ fn windows_restricted_token_rejects_split_only_filesystem_policies() { let file_system_policy = FileSystemSandboxPolicy::restricted(vec![ codex_protocol::permissions::FileSystemSandboxEntry { path: codex_protocol::permissions::FileSystemPath::Special { - value: codex_protocol::permissions::FileSystemSpecialPath::CurrentWorkingDirectory, + value: codex_protocol::permissions::FileSystemSpecialPath::project_roots( + /*subpath*/ None, + ), }, access: codex_protocol::permissions::FileSystemAccessMode::Write, }, @@ -630,7 +632,9 @@ fn windows_restricted_token_supports_full_read_split_write_read_carveouts() { }, codex_protocol::permissions::FileSystemSandboxEntry { path: codex_protocol::permissions::FileSystemPath::Special { - value: codex_protocol::permissions::FileSystemSpecialPath::CurrentWorkingDirectory, + value: codex_protocol::permissions::FileSystemSpecialPath::project_roots( + /*subpath*/ None, + ), }, access: codex_protocol::permissions::FileSystemAccessMode::Write, }, @@ -720,7 +724,9 @@ fn windows_elevated_supports_split_write_read_carveouts() { }, codex_protocol::permissions::FileSystemSandboxEntry { path: codex_protocol::permissions::FileSystemPath::Special { - value: codex_protocol::permissions::FileSystemSpecialPath::CurrentWorkingDirectory, + value: codex_protocol::permissions::FileSystemSpecialPath::project_roots( + /*subpath*/ None, + ), }, access: codex_protocol::permissions::FileSystemAccessMode::Write, }, @@ -774,7 +780,9 @@ fn windows_elevated_rejects_unreadable_split_carveouts() { }, codex_protocol::permissions::FileSystemSandboxEntry { path: codex_protocol::permissions::FileSystemPath::Special { - value: codex_protocol::permissions::FileSystemSpecialPath::CurrentWorkingDirectory, + value: codex_protocol::permissions::FileSystemSpecialPath::project_roots( + /*subpath*/ None, + ), }, access: codex_protocol::permissions::FileSystemAccessMode::Write, }, @@ -821,7 +829,9 @@ fn windows_elevated_rejects_unreadable_globs() { }, codex_protocol::permissions::FileSystemSandboxEntry { path: codex_protocol::permissions::FileSystemPath::Special { - value: codex_protocol::permissions::FileSystemSpecialPath::CurrentWorkingDirectory, + value: codex_protocol::permissions::FileSystemSpecialPath::project_roots( + /*subpath*/ None, + ), }, access: codex_protocol::permissions::FileSystemAccessMode::Write, }, @@ -870,7 +880,9 @@ fn windows_elevated_rejects_reopened_writable_descendants() { }, codex_protocol::permissions::FileSystemSandboxEntry { path: codex_protocol::permissions::FileSystemPath::Special { - value: codex_protocol::permissions::FileSystemSpecialPath::CurrentWorkingDirectory, + value: codex_protocol::permissions::FileSystemSpecialPath::project_roots( + /*subpath*/ None, + ), }, access: codex_protocol::permissions::FileSystemAccessMode::Write, }, diff --git a/codex-rs/core/src/safety_tests.rs b/codex-rs/core/src/safety_tests.rs index 0ca10e66e6b0..d699172498f1 100644 --- a/codex-rs/core/src/safety_tests.rs +++ b/codex-rs/core/src/safety_tests.rs @@ -258,7 +258,7 @@ fn explicit_read_only_subpaths_prevent_auto_approval_for_external_sandbox() { let file_system_sandbox_policy = FileSystemSandboxPolicy::restricted(vec![ FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }, diff --git a/codex-rs/core/src/session/session.rs b/codex-rs/core/src/session/session.rs index dcadac70a8fa..d4c0d337cf68 100644 --- a/codex-rs/core/src/session/session.rs +++ b/codex-rs/core/src/session/session.rs @@ -149,19 +149,19 @@ impl SessionConfiguration { ); let file_system_policy_matches_legacy = current_file_system_sandbox_policy .is_semantically_equivalent_to(&legacy_file_system_projection, &self.cwd); - let file_system_policy_has_rebindable_cwd_write = current_file_system_sandbox_policy - .entries - .iter() - .any(|entry| { - entry.access.can_write() - && matches!( - &entry.path, - FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory - | FileSystemSpecialPath::ProjectRoots { subpath: None }, - } - ) - }); + let file_system_policy_has_rebindable_project_root_write = + current_file_system_sandbox_policy + .entries + .iter() + .any(|entry| { + entry.access.can_write() + && matches!( + &entry.path, + FileSystemPath::Special { + value: FileSystemSpecialPath::ProjectRoots { subpath: None }, + } + ) + }); if let Some(collaboration_mode) = updates.collaboration_mode.clone() { next_configuration.collaboration_mode = collaboration_mode; } @@ -228,7 +228,7 @@ impl SessionConfiguration { )?; } else if cwd_changed && file_system_policy_matches_legacy - && file_system_policy_has_rebindable_cwd_write + && file_system_policy_has_rebindable_project_root_write { // Preserve richer split policies across cwd-only updates; only // rederive when the session is already using a structurally diff --git a/codex-rs/core/src/session/tests.rs b/codex-rs/core/src/session/tests.rs index 951575532390..283220e8fa2c 100644 --- a/codex-rs/core/src/session/tests.rs +++ b/codex-rs/core/src/session/tests.rs @@ -2874,7 +2874,7 @@ async fn session_configuration_apply_preserves_profile_file_system_policy_on_cwd let file_system_sandbox_policy = FileSystemSandboxPolicy::restricted(vec![ FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }, @@ -3187,7 +3187,7 @@ async fn session_configuration_apply_preserves_absolute_cwd_write_root_on_cwd_up !updated .file_system_sandbox_policy() .can_write_path_with_cwd(next_cwd.as_path(), updated.cwd.as_path()), - "cwd-only update must not reinterpret an absolute old-cwd grant as :cwd" + "cwd-only update must not reinterpret an absolute old-cwd grant as :project_roots" ); } @@ -3850,7 +3850,7 @@ async fn request_permissions_response_materializes_session_cwd_grants_before_rec file_system: Some(FileSystemPermissions { entries: vec![FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }], diff --git a/codex-rs/core/src/tools/handlers/mod.rs b/codex-rs/core/src/tools/handlers/mod.rs index f96b49ad4288..0ddd1e5062d2 100644 --- a/codex-rs/core/src/tools/handlers/mod.rs +++ b/codex-rs/core/src/tools/handlers/mod.rs @@ -354,7 +354,7 @@ mod tests { entries: vec![ FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }, diff --git a/codex-rs/exec-server/src/file_system.rs b/codex-rs/exec-server/src/file_system.rs index cd31ae63c553..fde69d642136 100644 --- a/codex-rs/exec-server/src/file_system.rs +++ b/codex-rs/exec-server/src/file_system.rs @@ -117,9 +117,7 @@ pub(crate) fn file_system_policy_has_cwd_dependent_entries( .any(|entry| match &entry.path { FileSystemPath::GlobPattern { pattern } => !Path::new(pattern).is_absolute(), FileSystemPath::Special { - value: - FileSystemSpecialPath::CurrentWorkingDirectory - | FileSystemSpecialPath::ProjectRoots { .. }, + value: FileSystemSpecialPath::ProjectRoots { .. }, } => true, FileSystemPath::Path { .. } | FileSystemPath::Special { .. } => false, }) diff --git a/codex-rs/exec-server/src/fs_sandbox.rs b/codex-rs/exec-server/src/fs_sandbox.rs index be3ea457bcb8..32cbba9572d3 100644 --- a/codex-rs/exec-server/src/fs_sandbox.rs +++ b/codex-rs/exec-server/src/fs_sandbox.rs @@ -118,7 +118,7 @@ fn sandbox_cwd(sandbox: &FileSystemSandboxContext) -> Result Self { Self::Managed { file_system: ManagedFileSystemPermissions::Restricted { @@ -415,7 +419,7 @@ impl PermissionProfile { }, FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }, diff --git a/codex-rs/protocol/src/permissions.rs b/codex-rs/protocol/src/permissions.rs index 63c2e3c4f76e..7d389a951997 100644 --- a/codex-rs/protocol/src/permissions.rs +++ b/codex-rs/protocol/src/permissions.rs @@ -80,7 +80,7 @@ impl FileSystemAccessMode { pub enum FileSystemSpecialPath { Root, Minimal, - CurrentWorkingDirectory, + #[serde(alias = "current_working_directory")] ProjectRoots { #[serde(default, skip_serializing_if = "Option::is_none")] #[ts(optional)] @@ -414,9 +414,9 @@ impl FileSystemSandboxPolicy { /// Converts a legacy sandbox policy into a cwd-independent filesystem policy. /// - /// `WorkspaceWrite` uses symbolic entries for cwd-scoped access so callers - /// can preserve the active cwd binding until the policy is actually - /// resolved for a turn or command. + /// `WorkspaceWrite` uses symbolic project-root entries so callers can keep + /// the profile independent of the concrete root until it is resolved for a + /// turn or command. pub fn from_legacy_sandbox_policy(sandbox_policy: &SandboxPolicy) -> Self { let mut file_system_policy = Self::from(sandbox_policy); let SandboxPolicy::WorkspaceWrite { @@ -571,6 +571,28 @@ impl FileSystemSandboxPolicy { self.resolve_access_with_cwd(path, cwd).can_write() } + /// Replaces symbolic `:project_roots` entries with absolute paths resolved + /// against `cwd`. + /// + /// Use this when a durable permission profile must survive a cwd-only + /// update without rebinding its project-root authority to the new cwd. + pub fn materialize_project_roots_with_cwd(mut self, cwd: &Path) -> Self { + let cwd = AbsolutePathBuf::from_absolute_path(cwd).ok(); + for entry in &mut self.entries { + let FileSystemPath::Special { + value: FileSystemSpecialPath::ProjectRoots { .. }, + } = &entry.path + else { + continue; + }; + + if let Some(path) = resolve_file_system_path(&entry.path, cwd.as_ref()) { + entry.path = FileSystemPath::Path { path }; + } + } + self + } + pub fn with_additional_readable_roots( mut self, cwd: &Path, @@ -867,11 +889,6 @@ impl FileSystemSandboxPolicy { } }, FileSystemSpecialPath::Minimal => {} - FileSystemSpecialPath::CurrentWorkingDirectory => { - if entry.access.can_write() { - workspace_root_writable = true; - } - } FileSystemSpecialPath::ProjectRoots { subpath } => { if subpath.is_none() && entry.access.can_write() { workspace_root_writable = true; @@ -1001,7 +1018,7 @@ impl From<&SandboxPolicy> for FileSystemSandboxPolicy { entries.push(FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }); @@ -1099,20 +1116,8 @@ fn special_paths_share_target(left: &FileSystemSpecialPath, right: &FileSystemSp match (left, right) { (FileSystemSpecialPath::Root, FileSystemSpecialPath::Root) | (FileSystemSpecialPath::Minimal, FileSystemSpecialPath::Minimal) - | ( - FileSystemSpecialPath::CurrentWorkingDirectory, - FileSystemSpecialPath::CurrentWorkingDirectory, - ) | (FileSystemSpecialPath::Tmpdir, FileSystemSpecialPath::Tmpdir) | (FileSystemSpecialPath::SlashTmp, FileSystemSpecialPath::SlashTmp) => true, - ( - FileSystemSpecialPath::CurrentWorkingDirectory, - FileSystemSpecialPath::ProjectRoots { subpath: None }, - ) - | ( - FileSystemSpecialPath::ProjectRoots { subpath: None }, - FileSystemSpecialPath::CurrentWorkingDirectory, - ) => true, ( FileSystemSpecialPath::ProjectRoots { subpath: left }, FileSystemSpecialPath::ProjectRoots { subpath: right }, @@ -1210,10 +1215,6 @@ fn resolve_file_system_special_path( FileSystemSpecialPath::Root | FileSystemSpecialPath::Minimal | FileSystemSpecialPath::Unknown { .. } => None, - FileSystemSpecialPath::CurrentWorkingDirectory => { - let cwd = cwd?; - Some(cwd.clone()) - } FileSystemSpecialPath::ProjectRoots { subpath } => { let cwd = cwd?; match subpath.as_ref() { @@ -1550,7 +1551,7 @@ mod tests { let policy = FileSystemSandboxPolicy::restricted(vec![FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }]); @@ -1566,7 +1567,7 @@ mod tests { } #[test] - fn legacy_workspace_write_projection_preserves_symbolic_cwd() { + fn legacy_workspace_write_projection_preserves_symbolic_project_root() { let policy = SandboxPolicy::WorkspaceWrite { writable_roots: Vec::new(), network_access: false, @@ -1585,7 +1586,7 @@ mod tests { }, FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }, @@ -1611,6 +1612,27 @@ mod tests { ); } + #[test] + fn legacy_current_working_directory_special_path_deserializes_as_project_roots() + -> serde_json::Result<()> { + let value = serde_json::json!({ + "kind": "current_working_directory", + }); + + let special_path = serde_json::from_value::(value)?; + assert_eq!( + special_path, + FileSystemSpecialPath::project_roots(/*subpath*/ None) + ); + assert_eq!( + serde_json::to_value(&special_path)?, + serde_json::json!({ + "kind": "project_roots", + }) + ); + Ok(()) + } + #[cfg(unix)] #[test] fn writable_roots_skip_default_dot_codex_when_explicit_user_rule_exists() { @@ -1624,7 +1646,7 @@ mod tests { let policy = FileSystemSandboxPolicy::restricted(vec![ FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }, @@ -1703,7 +1725,7 @@ mod tests { }, FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }, @@ -1774,7 +1796,7 @@ mod tests { #[cfg(unix)] #[test] - fn current_working_directory_special_path_preserves_symlinked_cwd() { + fn project_roots_special_path_preserves_symlinked_root() { let cwd = TempDir::new().expect("tempdir"); let real_root = cwd.path().join("real"); let link_root = cwd.path().join("link"); @@ -1804,7 +1826,7 @@ mod tests { }, FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }, @@ -2094,7 +2116,7 @@ mod tests { let policy = FileSystemSandboxPolicy::restricted(vec![ FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }, @@ -2141,7 +2163,7 @@ mod tests { let policy = FileSystemSandboxPolicy::restricted(vec![ FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }, @@ -2318,7 +2340,7 @@ mod tests { let cwd_root = AbsolutePathBuf::from_absolute_path(cwd.path()).expect("absolute cwd"); let policy = FileSystemSandboxPolicy::restricted(vec![FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Read, }]); @@ -2336,7 +2358,7 @@ mod tests { let cwd_root = AbsolutePathBuf::from_absolute_path(cwd.path()).expect("absolute cwd"); let policy = FileSystemSandboxPolicy::restricted(vec![FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }]); @@ -2356,7 +2378,7 @@ mod tests { .expect("resolve extra root"); let policy = FileSystemSandboxPolicy::restricted(vec![FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }]); @@ -2368,7 +2390,7 @@ mod tests { FileSystemSandboxPolicy::restricted(vec![ FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }, diff --git a/codex-rs/protocol/src/protocol.rs b/codex-rs/protocol/src/protocol.rs index 1e84e1806c86..0e46b97b9f47 100644 --- a/codex-rs/protocol/src/protocol.rs +++ b/codex-rs/protocol/src/protocol.rs @@ -4397,7 +4397,7 @@ mod tests { }, FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }, @@ -4459,7 +4459,7 @@ mod tests { let policy = FileSystemSandboxPolicy::restricted(vec![ FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }, diff --git a/codex-rs/sandboxing/src/policy_transforms.rs b/codex-rs/sandboxing/src/policy_transforms.rs index fc352865a80e..3dad862bea6c 100644 --- a/codex-rs/sandboxing/src/policy_transforms.rs +++ b/codex-rs/sandboxing/src/policy_transforms.rs @@ -350,9 +350,7 @@ fn materialize_cwd_dependent_entry( ) -> FileSystemSandboxEntry { match &entry.path { FileSystemPath::Special { - value: - FileSystemSpecialPath::CurrentWorkingDirectory - | FileSystemSpecialPath::ProjectRoots { .. }, + value: FileSystemSpecialPath::ProjectRoots { .. }, } => resolve_permission_path(&entry.path, cwd) .map(|path| FileSystemSandboxEntry { path: FileSystemPath::Path { path }, @@ -380,9 +378,6 @@ fn resolve_permission_path(path: &FileSystemPath, cwd: &Path) -> Option { - AbsolutePathBuf::from_absolute_path(cwd).ok() - } FileSystemSpecialPath::ProjectRoots { subpath } => { let cwd = AbsolutePathBuf::from_absolute_path(cwd).ok()?; Some(match subpath { diff --git a/codex-rs/sandboxing/src/policy_transforms_tests.rs b/codex-rs/sandboxing/src/policy_transforms_tests.rs index 9b412057351a..3404eee3da85 100644 --- a/codex-rs/sandboxing/src/policy_transforms_tests.rs +++ b/codex-rs/sandboxing/src/policy_transforms_tests.rs @@ -299,7 +299,7 @@ fn intersect_permission_profiles_accepts_child_path_granted_for_requested_cwd() file_system: Some(FileSystemPermissions { entries: vec![FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }], @@ -332,7 +332,7 @@ fn intersect_permission_profiles_materializes_cwd_grant_for_reuse() { file_system: Some(FileSystemPermissions { entries: vec![FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }], @@ -383,7 +383,7 @@ fn intersect_permission_profiles_deduplicates_materialized_grants() { entries: vec![ FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }, @@ -425,7 +425,7 @@ fn intersect_permission_profiles_materializes_cwd_deny_entries() { }, FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::None, }, @@ -474,7 +474,7 @@ fn intersect_permission_profiles_drops_deny_entries_without_filesystem_grants() entries: vec![ FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }, @@ -512,7 +512,7 @@ fn intersect_permission_profiles_rejects_concrete_grants_matched_by_requested_de entries: vec![ FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }, @@ -550,7 +550,7 @@ fn intersect_permission_profiles_materializes_relative_deny_globs_for_reuse() { .expect("absolute later cwd"); let cwd_write = FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }; @@ -629,7 +629,7 @@ fn intersect_permission_profiles_drops_broader_cwd_grant_for_requested_child_pat file_system: Some(FileSystemPermissions { entries: vec![FileSystemSandboxEntry { path: FileSystemPath::Special { - value: FileSystemSpecialPath::CurrentWorkingDirectory, + value: FileSystemSpecialPath::project_roots(/*subpath*/ None), }, access: FileSystemAccessMode::Write, }], diff --git a/codex-rs/tui/src/bottom_pane/approval_overlay.rs b/codex-rs/tui/src/bottom_pane/approval_overlay.rs index ce3b04b33bd6..9cf25e8cf7f8 100644 --- a/codex-rs/tui/src/bottom_pane/approval_overlay.rs +++ b/codex-rs/tui/src/bottom_pane/approval_overlay.rs @@ -875,7 +875,6 @@ fn special_path_label(value: &FileSystemSpecialPath) -> String { match value { FileSystemSpecialPath::Root => ":root".to_string(), FileSystemSpecialPath::Minimal => ":minimal".to_string(), - FileSystemSpecialPath::CurrentWorkingDirectory => ":cwd".to_string(), FileSystemSpecialPath::ProjectRoots { subpath } => path_label(":project_roots", subpath), FileSystemSpecialPath::Tmpdir => ":tmpdir".to_string(), FileSystemSpecialPath::SlashTmp => "/tmp".to_string(),