From 8adb6032cc931952ff7a329202b07932f070eadf Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Thu, 14 May 2026 23:10:45 -0700 Subject: [PATCH 1/5] tui/exec: show effective workspace roots in summaries (#22612) ## Why This PR builds on [#22611](https://github.com/openai/codex/pull/22611). After `runtimeWorkspaceRoots` moved onto thread state, the user-facing summaries were still inconsistent about which roots they showed. In particular, `/status` and the exec startup summary could under-report extra workspace roots from `--add-dir` or from profile-defined `workspace_roots`, which made the new model look incorrect even when the permissions themselves were right. ## What Changed - switched the TUI status surfaces to summarize against `Config::effective_workspace_roots()` - updated the exec human-output summary to render from the effective permission profile instead of the raw constrained profile - added focused regressions for both the TUI and exec code paths so extra workspace roots stay visible in user-facing summaries ## Verification Targeted coverage for this follow-up lives in: - `codex-rs/tui/src/status/tests.rs` - `codex-rs/exec/src/event_processor_with_human_output_tests.rs` The added regressions verify that: - status output includes profile-defined workspace roots in the effective permissions summary - exec startup output includes runtime workspace roots instead of collapsing back to `cwd` only --- .../src/event_processor_with_human_output.rs | 5 +- ...event_processor_with_human_output_tests.rs | 71 +++++++++++++++++++ .../tui/src/chatwidget/status_surfaces.rs | 8 +-- codex-rs/tui/src/status/card.rs | 13 ++-- codex-rs/tui/src/status/tests.rs | 34 +++++++++ 5 files changed, 120 insertions(+), 11 deletions(-) diff --git a/codex-rs/exec/src/event_processor_with_human_output.rs b/codex-rs/exec/src/event_processor_with_human_output.rs index 755d754f08..c3190b8740 100644 --- a/codex-rs/exec/src/event_processor_with_human_output.rs +++ b/codex-rs/exec/src/event_processor_with_human_output.rs @@ -420,6 +420,7 @@ fn config_summary_entries( config: &Config, session_configured_event: &SessionConfiguredEvent, ) -> Vec<(&'static str, String)> { + let permission_profile = config.permissions.effective_permission_profile(); let mut entries = vec![ ("workdir", config.cwd.display().to_string()), ("model", session_configured_event.model.clone()), @@ -434,9 +435,9 @@ fn config_summary_entries( ( "sandbox", summarize_permission_profile( - &config.permissions.effective_permission_profile(), + &permission_profile, &config.cwd, - config.permissions.user_visible_workspace_roots(), + config.effective_workspace_roots().as_slice(), ), ), ]; diff --git a/codex-rs/exec/src/event_processor_with_human_output_tests.rs b/codex-rs/exec/src/event_processor_with_human_output_tests.rs index 17cfda4550..1e900f2b61 100644 --- a/codex-rs/exec/src/event_processor_with_human_output_tests.rs +++ b/codex-rs/exec/src/event_processor_with_human_output_tests.rs @@ -2,12 +2,17 @@ use codex_app_server_protocol::ServerNotification; use codex_app_server_protocol::ThreadItem; use codex_app_server_protocol::Turn; use codex_app_server_protocol::TurnStatus; +use codex_core::config::ConfigBuilder; +use codex_protocol::SessionId; +use codex_protocol::ThreadId; use codex_protocol::models::PermissionProfile; use codex_protocol::permissions::FileSystemAccessMode; use codex_protocol::permissions::FileSystemPath; use codex_protocol::permissions::FileSystemSandboxEntry; use codex_protocol::permissions::FileSystemSandboxPolicy; use codex_protocol::permissions::NetworkSandboxPolicy; +use codex_protocol::protocol::AskForApproval; +use codex_protocol::protocol::SessionConfiguredEvent; use codex_utils_absolute_path::test_support::PathBufExt; use codex_utils_absolute_path::test_support::test_path_buf; use codex_utils_sandbox_summary::summarize_permission_profile; @@ -15,6 +20,7 @@ use owo_colors::Style; use pretty_assertions::assert_eq; use super::EventProcessorWithHumanOutput; +use super::config_summary_entries; use super::final_message_from_turn_items; use super::reasoning_text; use super::should_print_final_message_to_stdout; @@ -168,6 +174,71 @@ fn summarizes_managed_read_only_permission_profile() { ); } +#[tokio::test] +async fn config_summary_entries_include_runtime_workspace_roots() { + let codex_home = tempfile::tempdir().expect("create codex home"); + let cwd = tempfile::tempdir().expect("create cwd"); + let extra_root = tempfile::tempdir().expect("create extra root"); + let mut config = ConfigBuilder::default() + .codex_home(codex_home.path().to_path_buf()) + .fallback_cwd(Some(cwd.path().to_path_buf())) + .build() + .await + .expect("build default config"); + let cwd = cwd.path().to_path_buf().abs(); + let extra_root = extra_root.path().to_path_buf().abs(); + let expected_extra_root_name = extra_root + .file_name() + .expect("extra root should have file name") + .to_string_lossy() + .to_string(); + config.cwd = cwd.clone(); + config.workspace_roots = vec![cwd.clone(), extra_root]; + config + .permissions + .set_workspace_roots(config.workspace_roots.clone()); + config + .permissions + .set_permission_profile(PermissionProfile::workspace_write_with( + &[], + NetworkSandboxPolicy::Restricted, + /*exclude_tmpdir_env_var*/ true, + /*exclude_slash_tmp*/ true, + )) + .expect("set permission profile"); + + let session_configured_event = SessionConfiguredEvent { + session_id: SessionId::new(), + thread_id: ThreadId::new(), + forked_from_id: None, + thread_source: None, + thread_name: None, + model: "gpt-5.4".to_string(), + model_provider_id: config.model_provider_id.clone(), + service_tier: None, + approval_policy: AskForApproval::Never, + approvals_reviewer: config.approvals_reviewer, + permission_profile: config.permissions.effective_permission_profile(), + active_permission_profile: None, + cwd, + reasoning_effort: None, + initial_messages: None, + network_proxy: None, + rollout_path: None, + }; + + let summary_entries = config_summary_entries(&config, &session_configured_event); + let sandbox_summary = summary_entries + .iter() + .find_map(|(key, value)| (*key == "sandbox").then_some(value)) + .expect("sandbox summary entry"); + assert!( + sandbox_summary.starts_with("workspace-write [workdir, ") + && sandbox_summary.contains(&expected_extra_root_name), + "expected runtime workspace root in sandbox summary: {summary_entries:?}" + ); +} + #[test] fn final_message_from_turn_items_uses_latest_agent_message() { let message = final_message_from_turn_items(&[ diff --git a/codex-rs/tui/src/chatwidget/status_surfaces.rs b/codex-rs/tui/src/chatwidget/status_surfaces.rs index 8dd5f327d3..e34fe4688a 100644 --- a/codex-rs/tui/src/chatwidget/status_surfaces.rs +++ b/codex-rs/tui/src/chatwidget/status_surfaces.rs @@ -902,11 +902,9 @@ fn permissions_display(config: &Config) -> String { } let permission_profile = config.permissions.effective_permission_profile(); - let summary = summarize_permission_profile( - &permission_profile, - &config.cwd, - config.permissions.workspace_roots(), - ); + let workspace_roots = config.effective_workspace_roots(); + let summary = + summarize_permission_profile(&permission_profile, &config.cwd, workspace_roots.as_slice()); if let Some(details) = summary.strip_prefix("read-only") && !details.contains("(network access enabled)") { diff --git a/codex-rs/tui/src/status/card.rs b/codex-rs/tui/src/status/card.rs index 9a7c23606f..3d30f800b6 100644 --- a/codex-rs/tui/src/status/card.rs +++ b/codex-rs/tui/src/status/card.rs @@ -256,7 +256,7 @@ impl StatusHistoryCell { ) -> (Self, StatusHistoryHandle) { let approval_policy = AskForApproval::from(config.permissions.approval_policy.value()); let permission_profile = config.permissions.effective_permission_profile(); - let workspace_roots = config.permissions.user_visible_workspace_roots(); + let workspace_roots = config.effective_workspace_roots(); let mut config_entries = vec![ ("workdir", config.cwd.display().to_string()), ("model", model_name.to_string()), @@ -267,7 +267,11 @@ impl StatusHistoryCell { ), ( "sandbox", - summarize_permission_profile(&permission_profile, &config.cwd, workspace_roots), + summarize_permission_profile( + &permission_profile, + &config.cwd, + workspace_roots.as_slice(), + ), ), ]; if config.model_provider.wire_api == WireApi::Responses { @@ -291,8 +295,9 @@ impl StatusHistoryCell { .map(|(_, v)| v.clone()) .unwrap_or_else(|| "".to_string()); let active_permission_profile = config.permissions.active_permission_profile(); - let sandbox = status_permission_summary(&permission_profile, &config.cwd, workspace_roots); - let workspace_root_suffix = workspace_root_suffix(workspace_roots, &config.cwd); + let sandbox = + status_permission_summary(&permission_profile, &config.cwd, workspace_roots.as_slice()); + let workspace_root_suffix = workspace_root_suffix(workspace_roots.as_slice(), &config.cwd); let approval = status_approval_label(approval_policy, config.approvals_reviewer, &approval); let permissions = status_permissions_label( active_permission_profile.as_ref(), diff --git a/codex-rs/tui/src/status/tests.rs b/codex-rs/tui/src/status/tests.rs index 65a390a007..9380718196 100644 --- a/codex-rs/tui/src/status/tests.rs +++ b/codex-rs/tui/src/status/tests.rs @@ -463,6 +463,40 @@ async fn status_permissions_workspace_roots_show_additional_directories() { ); } +#[tokio::test] +async fn status_permissions_workspace_roots_include_profile_defined_directories() { + let temp_home = TempDir::new().expect("temp home"); + let mut config = test_config(&temp_home).await; + set_workspace_cwd(&mut config, test_path_buf("/workspace/tests").abs()); + config + .permissions + .approval_policy + .set(AskForApproval::OnRequest.to_core()) + .expect("set approval policy"); + let profile_root = test_path_buf("/workspace/shared").abs(); + config + .permissions + .set_permission_profile_from_session_snapshot_with_profile_workspace_roots( + PermissionProfile::workspace_write_with( + std::slice::from_ref(&profile_root), + NetworkSandboxPolicy::Restricted, + /*exclude_tmpdir_env_var*/ false, + /*exclude_slash_tmp*/ false, + ), + Some(ActivePermissionProfile::new(":workspace")), + vec![profile_root.clone()], + ) + .expect("set permission profile"); + + assert_eq!( + permissions_text_for(&config), + Some(format!( + "Workspace [{}] (on-request)", + profile_root.display() + )) + ); +} + #[tokio::test] async fn status_permissions_broadened_workspace_profile_shows_builtin_label() { let temp_home = TempDir::new().expect("temp home"); From 76f8e0136b8d55b564dfb350af4ec62e0ccfc772 Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Thu, 14 May 2026 23:30:05 -0700 Subject: [PATCH 2/5] guardian: use permission profile for review sandbox --- codex-rs/core/src/guardian/review_session.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/codex-rs/core/src/guardian/review_session.rs b/codex-rs/core/src/guardian/review_session.rs index 2f15548919..70fbe4ea12 100644 --- a/codex-rs/core/src/guardian/review_session.rs +++ b/codex-rs/core/src/guardian/review_session.rs @@ -9,6 +9,7 @@ use codex_analytics::GuardianReviewAnalyticsResult; use codex_analytics::GuardianReviewSessionKind; use codex_protocol::config_types::Personality; use codex_protocol::config_types::ReasoningSummary as ReasoningSummaryConfig; +use codex_protocol::models::PermissionProfile; use codex_protocol::models::ResponseItem; use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig; use codex_protocol::protocol::AskForApproval; @@ -698,6 +699,7 @@ async fn run_review_on_session( .total_token_usage() .await .unwrap_or_default(); + let guardian_permission_profile = PermissionProfile::read_only(); let submit_result = run_before_review_deadline( deadline, @@ -709,8 +711,10 @@ async fn run_review_on_session( cwd: params.parent_turn.cwd.to_path_buf(), approval_policy: AskForApproval::Never, approvals_reviewer: None, - sandbox_policy: SandboxPolicy::new_read_only_policy(), - permission_profile: None, + sandbox_policy: SandboxPolicy::ReadOnly { + network_access: false, + }, + permission_profile: Some(guardian_permission_profile), model: params.model.clone(), effort: params.reasoning_effort, summary: Some(params.reasoning_summary), @@ -892,12 +896,11 @@ pub(crate) fn build_guardian_review_session_config( ); guardian_config.developer_instructions = None; guardian_config.permissions.approval_policy = Constrained::allow_only(AskForApproval::Never); - let sandbox_policy = SandboxPolicy::new_read_only_policy(); guardian_config .permissions - .set_legacy_sandbox_policy(sandbox_policy, guardian_config.cwd.as_path()) + .set_permission_profile(PermissionProfile::read_only()) .map_err(|err| { - anyhow::anyhow!("guardian review session could not set sandbox policy: {err}") + anyhow::anyhow!("guardian review session could not set permission profile: {err}") })?; guardian_config.include_apps_instructions = false; guardian_config From 9c42aa0c6e4b2b1db49c968a5fb8d1126ee7484d Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Thu, 14 May 2026 23:31:16 -0700 Subject: [PATCH 3/5] context: remove legacy permissions instructions helper --- .../src/context/permissions_instructions.rs | 22 ------------------ .../context/permissions_instructions_tests.rs | 23 ------------------- 2 files changed, 45 deletions(-) diff --git a/codex-rs/core/src/context/permissions_instructions.rs b/codex-rs/core/src/context/permissions_instructions.rs index cd5a8ac338..e982ca17d2 100644 --- a/codex-rs/core/src/context/permissions_instructions.rs +++ b/codex-rs/core/src/context/permissions_instructions.rs @@ -8,7 +8,6 @@ use codex_protocol::permissions::NetworkSandboxPolicy; use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::GranularApprovalConfig; use codex_protocol::protocol::NetworkAccess; -use codex_protocol::protocol::SandboxPolicy; use codex_protocol::protocol::WritableRoot; use codex_utils_template::Template; use std::path::Path; @@ -85,27 +84,6 @@ impl PermissionsInstructions { ) } - /// Builds permissions instructions from a legacy sandbox policy. - pub fn from_policy( - sandbox_policy: &SandboxPolicy, - approval_policy: AskForApproval, - approvals_reviewer: ApprovalsReviewer, - exec_policy: &Policy, - cwd: &Path, - exec_permission_approvals_enabled: bool, - request_permissions_tool_enabled: bool, - ) -> Self { - Self::from_permission_profile( - &PermissionProfile::from_legacy_sandbox_policy(sandbox_policy), - approval_policy, - approvals_reviewer, - exec_policy, - cwd, - exec_permission_approvals_enabled, - request_permissions_tool_enabled, - ) - } - fn from_permissions_with_network( sandbox_mode: SandboxMode, network_access: NetworkAccess, diff --git a/codex-rs/core/src/context/permissions_instructions_tests.rs b/codex-rs/core/src/context/permissions_instructions_tests.rs index 16d5dc631a..6d1aa5d886 100644 --- a/codex-rs/core/src/context/permissions_instructions_tests.rs +++ b/codex-rs/core/src/context/permissions_instructions_tests.rs @@ -53,29 +53,6 @@ fn builds_permissions_with_network_access_override() { ); } -#[test] -fn builds_permissions_from_policy() { - let policy = SandboxPolicy::WorkspaceWrite { - writable_roots: vec![], - network_access: true, - exclude_tmpdir_env_var: false, - exclude_slash_tmp: false, - }; - - let instructions = PermissionsInstructions::from_policy( - &policy, - AskForApproval::UnlessTrusted, - ApprovalsReviewer::User, - &Policy::empty(), - &PathBuf::from("/tmp"), - /*exec_permission_approvals_enabled*/ false, - /*request_permissions_tool_enabled*/ false, - ); - let text = instructions.body(); - assert!(text.contains("Network access is enabled.")); - assert!(text.contains("`approval_policy` is `unless-trusted`")); -} - #[test] fn builds_permissions_from_profile() { let cwd = PathBuf::from("/tmp"); From 1ea78ab0b834577a9cac6a9e2a7f79dc5a2d801c Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Thu, 14 May 2026 23:32:47 -0700 Subject: [PATCH 4/5] telemetry: tag sandboxes from permission profiles --- codex-rs/core/src/sandbox_tags.rs | 14 -------------- codex-rs/core/src/sandbox_tags_tests.rs | 20 ++++++++++---------- codex-rs/core/src/turn_metadata_tests.rs | 10 ++++++---- 3 files changed, 16 insertions(+), 28 deletions(-) diff --git a/codex-rs/core/src/sandbox_tags.rs b/codex-rs/core/src/sandbox_tags.rs index f6db4da918..2973a5bf94 100644 --- a/codex-rs/core/src/sandbox_tags.rs +++ b/codex-rs/core/src/sandbox_tags.rs @@ -1,24 +1,10 @@ use codex_protocol::config_types::WindowsSandboxLevel; use codex_protocol::models::PermissionProfile; -#[cfg(test)] -use codex_protocol::protocol::SandboxPolicy; use codex_sandboxing::SandboxType; use codex_sandboxing::get_platform_sandbox; use codex_sandboxing::policy_transforms::should_require_platform_sandbox; use std::path::Path; -#[cfg(test)] -pub(crate) fn sandbox_tag( - policy: &SandboxPolicy, - windows_sandbox_level: WindowsSandboxLevel, -) -> &'static str { - permission_profile_sandbox_tag( - &PermissionProfile::from_legacy_sandbox_policy(policy), - windows_sandbox_level, - /*enforce_managed_network*/ false, - ) -} - pub(crate) fn permission_profile_sandbox_tag( profile: &PermissionProfile, windows_sandbox_level: WindowsSandboxLevel, diff --git a/codex-rs/core/src/sandbox_tags_tests.rs b/codex-rs/core/src/sandbox_tags_tests.rs index 8b00de9ccd..64dc50574f 100644 --- a/codex-rs/core/src/sandbox_tags_tests.rs +++ b/codex-rs/core/src/sandbox_tags_tests.rs @@ -1,6 +1,5 @@ use super::permission_profile_policy_tag; use super::permission_profile_sandbox_tag; -use super::sandbox_tag; use codex_protocol::config_types::WindowsSandboxLevel; use codex_protocol::models::ManagedFileSystemPermissions; use codex_protocol::models::PermissionProfile; @@ -10,8 +9,6 @@ use codex_protocol::permissions::FileSystemSandboxEntry; use codex_protocol::permissions::FileSystemSandboxKind; use codex_protocol::permissions::FileSystemSandboxPolicy; use codex_protocol::permissions::NetworkSandboxPolicy; -use codex_protocol::protocol::NetworkAccess; -use codex_protocol::protocol::SandboxPolicy; use codex_sandboxing::SandboxType; use codex_sandboxing::get_platform_sandbox; use codex_utils_absolute_path::AbsolutePathBuf; @@ -20,29 +17,32 @@ use std::path::Path; #[test] fn danger_full_access_is_untagged_even_when_linux_sandbox_defaults_apply() { - let actual = sandbox_tag( - &SandboxPolicy::DangerFullAccess, + let actual = permission_profile_sandbox_tag( + &PermissionProfile::Disabled, WindowsSandboxLevel::Disabled, + /*enforce_managed_network*/ false, ); assert_eq!(actual, "none"); } #[test] fn external_sandbox_keeps_external_tag_when_linux_sandbox_defaults_apply() { - let actual = sandbox_tag( - &SandboxPolicy::ExternalSandbox { - network_access: NetworkAccess::Enabled, + let actual = permission_profile_sandbox_tag( + &PermissionProfile::External { + network: NetworkSandboxPolicy::Enabled, }, WindowsSandboxLevel::Disabled, + /*enforce_managed_network*/ false, ); assert_eq!(actual, "external"); } #[test] fn default_linux_sandbox_uses_platform_sandbox_tag() { - let actual = sandbox_tag( - &SandboxPolicy::new_read_only_policy(), + let actual = permission_profile_sandbox_tag( + &PermissionProfile::read_only(), WindowsSandboxLevel::Disabled, + /*enforce_managed_network*/ false, ); let expected = get_platform_sandbox(/*windows_sandbox_enabled*/ false) .map(SandboxType::as_metric_tag) diff --git a/codex-rs/core/src/turn_metadata_tests.rs b/codex-rs/core/src/turn_metadata_tests.rs index a9c7a7b87d..2f79927103 100644 --- a/codex-rs/core/src/turn_metadata_tests.rs +++ b/codex-rs/core/src/turn_metadata_tests.rs @@ -1,9 +1,8 @@ use super::*; -use crate::sandbox_tags::sandbox_tag; +use crate::sandbox_tags::permission_profile_sandbox_tag; use codex_protocol::models::PermissionProfile; use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig; -use codex_protocol::protocol::SandboxPolicy; use codex_protocol::protocol::ThreadSource; use core_test_support::PathBufExt; use core_test_support::PathExt; @@ -89,7 +88,6 @@ async fn build_turn_metadata_header_includes_has_changes_for_clean_repo() { fn turn_metadata_state_uses_platform_sandbox_tag() { let temp_dir = TempDir::new().expect("temp dir"); let cwd = temp_dir.path().abs(); - let sandbox_policy = SandboxPolicy::new_read_only_policy(); let permission_profile = PermissionProfile::read_only(); let state = TurnMetadataState::new( @@ -110,7 +108,11 @@ fn turn_metadata_state_uses_platform_sandbox_tag() { let thread_id = json.get("thread_id").and_then(Value::as_str); let thread_source = json.get("thread_source").and_then(Value::as_str); - let expected_sandbox = sandbox_tag(&sandbox_policy, WindowsSandboxLevel::Disabled); + let expected_sandbox = permission_profile_sandbox_tag( + &permission_profile, + WindowsSandboxLevel::Disabled, + /*enforce_managed_network*/ false, + ); assert_eq!(sandbox_name, Some(expected_sandbox)); assert_eq!(session_id, Some("session-a")); assert_eq!(thread_id, Some("thread-a")); From 8e7e4c06bf0e9d3d3d593de944c995301677c2e9 Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Thu, 14 May 2026 23:50:19 -0700 Subject: [PATCH 5/5] app-server: stop returning thread permission profiles --- .../codex_app_server_protocol.schemas.json | 6 +- .../codex_app_server_protocol.v2.schemas.json | 6 +- .../schema/json/v2/ThreadForkResponse.json | 327 +----------------- .../schema/json/v2/ThreadResumeResponse.json | 327 +----------------- .../schema/json/v2/ThreadStartResponse.json | 327 +----------------- .../typescript/v2/ThreadForkResponse.ts | 3 +- .../typescript/v2/ThreadResumeResponse.ts | 3 +- .../typescript/v2/ThreadStartResponse.ts | 3 +- .../src/protocol/common.rs | 2 - .../src/protocol/v2/tests.rs | 3 - .../src/protocol/v2/thread.rs | 25 +- .../request_processors/thread_lifecycle.rs | 1 - .../request_processors/thread_processor.rs | 3 - codex-rs/exec/src/lib.rs | 12 +- codex-rs/exec/src/lib_tests.rs | 11 +- codex-rs/tui/src/app_server_session.rs | 54 +-- 16 files changed, 37 insertions(+), 1076 deletions(-) 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 e37c26881b..12cb9d83b8 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 @@ -15511,7 +15511,7 @@ "$ref": "#/definitions/v2/SandboxPolicy" } ], - "description": "Legacy sandbox policy retained for compatibility. Experimental clients should prefer `permissionProfile` when they need exact runtime permissions." + "description": "Legacy sandbox policy retained for compatibility. Experimental clients should prefer `activePermissionProfile` for profile provenance." }, "serviceTier": { "type": [ @@ -17003,7 +17003,7 @@ "$ref": "#/definitions/v2/SandboxPolicy" } ], - "description": "Legacy sandbox policy retained for compatibility. Experimental clients should prefer `permissionProfile` when they need exact runtime permissions." + "description": "Legacy sandbox policy retained for compatibility. Experimental clients should prefer `activePermissionProfile` for profile provenance." }, "serviceTier": { "type": [ @@ -17311,7 +17311,7 @@ "$ref": "#/definitions/v2/SandboxPolicy" } ], - "description": "Legacy sandbox policy retained for compatibility. Experimental clients should prefer `permissionProfile` when they need exact runtime permissions." + "description": "Legacy sandbox policy retained for compatibility. Experimental clients should prefer `activePermissionProfile` for profile provenance." }, "serviceTier": { "type": [ 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 653a1a5751..4a199057d8 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 @@ -13335,7 +13335,7 @@ "$ref": "#/definitions/SandboxPolicy" } ], - "description": "Legacy sandbox policy retained for compatibility. Experimental clients should prefer `permissionProfile` when they need exact runtime permissions." + "description": "Legacy sandbox policy retained for compatibility. Experimental clients should prefer `activePermissionProfile` for profile provenance." }, "serviceTier": { "type": [ @@ -14827,7 +14827,7 @@ "$ref": "#/definitions/SandboxPolicy" } ], - "description": "Legacy sandbox policy retained for compatibility. Experimental clients should prefer `permissionProfile` when they need exact runtime permissions." + "description": "Legacy sandbox policy retained for compatibility. Experimental clients should prefer `activePermissionProfile` for profile provenance." }, "serviceTier": { "type": [ @@ -15135,7 +15135,7 @@ "$ref": "#/definitions/SandboxPolicy" } ], - "description": "Legacy sandbox policy retained for compatibility. Experimental clients should prefer `permissionProfile` when they need exact runtime permissions." + "description": "Legacy sandbox policy retained for compatibility. Experimental clients should prefer `activePermissionProfile` for profile provenance." }, "serviceTier": { "type": [ 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 4eb85f4ed3..1608b2f48c 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json @@ -470,202 +470,6 @@ ], "type": "string" }, - "FileSystemAccessMode": { - "enum": [ - "read", - "write", - "none" - ], - "type": "string" - }, - "FileSystemPath": { - "oneOf": [ - { - "properties": { - "path": { - "$ref": "#/definitions/AbsolutePathBuf" - }, - "type": { - "enum": [ - "path" - ], - "title": "PathFileSystemPathType", - "type": "string" - } - }, - "required": [ - "path", - "type" - ], - "title": "PathFileSystemPath", - "type": "object" - }, - { - "properties": { - "pattern": { - "type": "string" - }, - "type": { - "enum": [ - "glob_pattern" - ], - "title": "GlobPatternFileSystemPathType", - "type": "string" - } - }, - "required": [ - "pattern", - "type" - ], - "title": "GlobPatternFileSystemPath", - "type": "object" - }, - { - "properties": { - "type": { - "enum": [ - "special" - ], - "title": "SpecialFileSystemPathType", - "type": "string" - }, - "value": { - "$ref": "#/definitions/FileSystemSpecialPath" - } - }, - "required": [ - "type", - "value" - ], - "title": "SpecialFileSystemPath", - "type": "object" - } - ] - }, - "FileSystemSandboxEntry": { - "properties": { - "access": { - "$ref": "#/definitions/FileSystemAccessMode" - }, - "path": { - "$ref": "#/definitions/FileSystemPath" - } - }, - "required": [ - "access", - "path" - ], - "type": "object" - }, - "FileSystemSpecialPath": { - "oneOf": [ - { - "properties": { - "kind": { - "enum": [ - "root" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "RootFileSystemSpecialPath", - "type": "object" - }, - { - "properties": { - "kind": { - "enum": [ - "minimal" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "MinimalFileSystemSpecialPath", - "type": "object" - }, - { - "properties": { - "kind": { - "enum": [ - "project_roots" - ], - "type": "string" - }, - "subpath": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "kind" - ], - "title": "KindFileSystemSpecialPath", - "type": "object" - }, - { - "properties": { - "kind": { - "enum": [ - "tmpdir" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "TmpdirFileSystemSpecialPath", - "type": "object" - }, - { - "properties": { - "kind": { - "enum": [ - "slash_tmp" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "SlashTmpFileSystemSpecialPath", - "type": "object" - }, - { - "properties": { - "kind": { - "enum": [ - "unknown" - ], - "type": "string" - }, - "path": { - "type": "string" - }, - "subpath": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "kind", - "path" - ], - "type": "object" - } - ] - }, "FileUpdateChange": { "properties": { "diff": { @@ -904,135 +708,6 @@ } ] }, - "PermissionProfile": { - "oneOf": [ - { - "description": "Codex owns sandbox construction for this profile.", - "properties": { - "fileSystem": { - "$ref": "#/definitions/PermissionProfileFileSystemPermissions" - }, - "network": { - "$ref": "#/definitions/PermissionProfileNetworkPermissions" - }, - "type": { - "enum": [ - "managed" - ], - "title": "ManagedPermissionProfileType", - "type": "string" - } - }, - "required": [ - "fileSystem", - "network", - "type" - ], - "title": "ManagedPermissionProfile", - "type": "object" - }, - { - "description": "Do not apply an outer sandbox.", - "properties": { - "type": { - "enum": [ - "disabled" - ], - "title": "DisabledPermissionProfileType", - "type": "string" - } - }, - "required": [ - "type" - ], - "title": "DisabledPermissionProfile", - "type": "object" - }, - { - "description": "Filesystem isolation is enforced by an external caller.", - "properties": { - "network": { - "$ref": "#/definitions/PermissionProfileNetworkPermissions" - }, - "type": { - "enum": [ - "external" - ], - "title": "ExternalPermissionProfileType", - "type": "string" - } - }, - "required": [ - "network", - "type" - ], - "title": "ExternalPermissionProfile", - "type": "object" - } - ] - }, - "PermissionProfileFileSystemPermissions": { - "oneOf": [ - { - "properties": { - "entries": { - "items": { - "$ref": "#/definitions/FileSystemSandboxEntry" - }, - "type": "array" - }, - "globScanMaxDepth": { - "format": "uint", - "minimum": 1.0, - "type": [ - "integer", - "null" - ] - }, - "type": { - "enum": [ - "restricted" - ], - "title": "RestrictedPermissionProfileFileSystemPermissionsType", - "type": "string" - } - }, - "required": [ - "entries", - "type" - ], - "title": "RestrictedPermissionProfileFileSystemPermissions", - "type": "object" - }, - { - "properties": { - "type": { - "enum": [ - "unrestricted" - ], - "title": "UnrestrictedPermissionProfileFileSystemPermissionsType", - "type": "string" - } - }, - "required": [ - "type" - ], - "title": "UnrestrictedPermissionProfileFileSystemPermissions", - "type": "object" - } - ] - }, - "PermissionProfileNetworkPermissions": { - "properties": { - "enabled": { - "type": "boolean" - } - }, - "required": [ - "enabled" - ], - "type": "object" - }, "ReasoningEffort": { "description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning", "enum": [ @@ -2572,7 +2247,7 @@ "$ref": "#/definitions/SandboxPolicy" } ], - "description": "Legacy sandbox policy retained for compatibility. Experimental clients should prefer `permissionProfile` when they need exact runtime permissions." + "description": "Legacy sandbox policy retained for compatibility. Experimental clients should prefer `activePermissionProfile` for profile provenance." }, "serviceTier": { "type": [ 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 312d289e41..302c2e1069 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json @@ -470,202 +470,6 @@ ], "type": "string" }, - "FileSystemAccessMode": { - "enum": [ - "read", - "write", - "none" - ], - "type": "string" - }, - "FileSystemPath": { - "oneOf": [ - { - "properties": { - "path": { - "$ref": "#/definitions/AbsolutePathBuf" - }, - "type": { - "enum": [ - "path" - ], - "title": "PathFileSystemPathType", - "type": "string" - } - }, - "required": [ - "path", - "type" - ], - "title": "PathFileSystemPath", - "type": "object" - }, - { - "properties": { - "pattern": { - "type": "string" - }, - "type": { - "enum": [ - "glob_pattern" - ], - "title": "GlobPatternFileSystemPathType", - "type": "string" - } - }, - "required": [ - "pattern", - "type" - ], - "title": "GlobPatternFileSystemPath", - "type": "object" - }, - { - "properties": { - "type": { - "enum": [ - "special" - ], - "title": "SpecialFileSystemPathType", - "type": "string" - }, - "value": { - "$ref": "#/definitions/FileSystemSpecialPath" - } - }, - "required": [ - "type", - "value" - ], - "title": "SpecialFileSystemPath", - "type": "object" - } - ] - }, - "FileSystemSandboxEntry": { - "properties": { - "access": { - "$ref": "#/definitions/FileSystemAccessMode" - }, - "path": { - "$ref": "#/definitions/FileSystemPath" - } - }, - "required": [ - "access", - "path" - ], - "type": "object" - }, - "FileSystemSpecialPath": { - "oneOf": [ - { - "properties": { - "kind": { - "enum": [ - "root" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "RootFileSystemSpecialPath", - "type": "object" - }, - { - "properties": { - "kind": { - "enum": [ - "minimal" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "MinimalFileSystemSpecialPath", - "type": "object" - }, - { - "properties": { - "kind": { - "enum": [ - "project_roots" - ], - "type": "string" - }, - "subpath": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "kind" - ], - "title": "KindFileSystemSpecialPath", - "type": "object" - }, - { - "properties": { - "kind": { - "enum": [ - "tmpdir" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "TmpdirFileSystemSpecialPath", - "type": "object" - }, - { - "properties": { - "kind": { - "enum": [ - "slash_tmp" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "SlashTmpFileSystemSpecialPath", - "type": "object" - }, - { - "properties": { - "kind": { - "enum": [ - "unknown" - ], - "type": "string" - }, - "path": { - "type": "string" - }, - "subpath": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "kind", - "path" - ], - "type": "object" - } - ] - }, "FileUpdateChange": { "properties": { "diff": { @@ -904,135 +708,6 @@ } ] }, - "PermissionProfile": { - "oneOf": [ - { - "description": "Codex owns sandbox construction for this profile.", - "properties": { - "fileSystem": { - "$ref": "#/definitions/PermissionProfileFileSystemPermissions" - }, - "network": { - "$ref": "#/definitions/PermissionProfileNetworkPermissions" - }, - "type": { - "enum": [ - "managed" - ], - "title": "ManagedPermissionProfileType", - "type": "string" - } - }, - "required": [ - "fileSystem", - "network", - "type" - ], - "title": "ManagedPermissionProfile", - "type": "object" - }, - { - "description": "Do not apply an outer sandbox.", - "properties": { - "type": { - "enum": [ - "disabled" - ], - "title": "DisabledPermissionProfileType", - "type": "string" - } - }, - "required": [ - "type" - ], - "title": "DisabledPermissionProfile", - "type": "object" - }, - { - "description": "Filesystem isolation is enforced by an external caller.", - "properties": { - "network": { - "$ref": "#/definitions/PermissionProfileNetworkPermissions" - }, - "type": { - "enum": [ - "external" - ], - "title": "ExternalPermissionProfileType", - "type": "string" - } - }, - "required": [ - "network", - "type" - ], - "title": "ExternalPermissionProfile", - "type": "object" - } - ] - }, - "PermissionProfileFileSystemPermissions": { - "oneOf": [ - { - "properties": { - "entries": { - "items": { - "$ref": "#/definitions/FileSystemSandboxEntry" - }, - "type": "array" - }, - "globScanMaxDepth": { - "format": "uint", - "minimum": 1.0, - "type": [ - "integer", - "null" - ] - }, - "type": { - "enum": [ - "restricted" - ], - "title": "RestrictedPermissionProfileFileSystemPermissionsType", - "type": "string" - } - }, - "required": [ - "entries", - "type" - ], - "title": "RestrictedPermissionProfileFileSystemPermissions", - "type": "object" - }, - { - "properties": { - "type": { - "enum": [ - "unrestricted" - ], - "title": "UnrestrictedPermissionProfileFileSystemPermissionsType", - "type": "string" - } - }, - "required": [ - "type" - ], - "title": "UnrestrictedPermissionProfileFileSystemPermissions", - "type": "object" - } - ] - }, - "PermissionProfileNetworkPermissions": { - "properties": { - "enabled": { - "type": "boolean" - } - }, - "required": [ - "enabled" - ], - "type": "object" - }, "ReasoningEffort": { "description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning", "enum": [ @@ -2572,7 +2247,7 @@ "$ref": "#/definitions/SandboxPolicy" } ], - "description": "Legacy sandbox policy retained for compatibility. Experimental clients should prefer `permissionProfile` when they need exact runtime permissions." + "description": "Legacy sandbox policy retained for compatibility. Experimental clients should prefer `activePermissionProfile` for profile provenance." }, "serviceTier": { "type": [ 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 c363f2e78d..9dc08614cf 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json @@ -470,202 +470,6 @@ ], "type": "string" }, - "FileSystemAccessMode": { - "enum": [ - "read", - "write", - "none" - ], - "type": "string" - }, - "FileSystemPath": { - "oneOf": [ - { - "properties": { - "path": { - "$ref": "#/definitions/AbsolutePathBuf" - }, - "type": { - "enum": [ - "path" - ], - "title": "PathFileSystemPathType", - "type": "string" - } - }, - "required": [ - "path", - "type" - ], - "title": "PathFileSystemPath", - "type": "object" - }, - { - "properties": { - "pattern": { - "type": "string" - }, - "type": { - "enum": [ - "glob_pattern" - ], - "title": "GlobPatternFileSystemPathType", - "type": "string" - } - }, - "required": [ - "pattern", - "type" - ], - "title": "GlobPatternFileSystemPath", - "type": "object" - }, - { - "properties": { - "type": { - "enum": [ - "special" - ], - "title": "SpecialFileSystemPathType", - "type": "string" - }, - "value": { - "$ref": "#/definitions/FileSystemSpecialPath" - } - }, - "required": [ - "type", - "value" - ], - "title": "SpecialFileSystemPath", - "type": "object" - } - ] - }, - "FileSystemSandboxEntry": { - "properties": { - "access": { - "$ref": "#/definitions/FileSystemAccessMode" - }, - "path": { - "$ref": "#/definitions/FileSystemPath" - } - }, - "required": [ - "access", - "path" - ], - "type": "object" - }, - "FileSystemSpecialPath": { - "oneOf": [ - { - "properties": { - "kind": { - "enum": [ - "root" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "RootFileSystemSpecialPath", - "type": "object" - }, - { - "properties": { - "kind": { - "enum": [ - "minimal" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "MinimalFileSystemSpecialPath", - "type": "object" - }, - { - "properties": { - "kind": { - "enum": [ - "project_roots" - ], - "type": "string" - }, - "subpath": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "kind" - ], - "title": "KindFileSystemSpecialPath", - "type": "object" - }, - { - "properties": { - "kind": { - "enum": [ - "tmpdir" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "TmpdirFileSystemSpecialPath", - "type": "object" - }, - { - "properties": { - "kind": { - "enum": [ - "slash_tmp" - ], - "type": "string" - } - }, - "required": [ - "kind" - ], - "title": "SlashTmpFileSystemSpecialPath", - "type": "object" - }, - { - "properties": { - "kind": { - "enum": [ - "unknown" - ], - "type": "string" - }, - "path": { - "type": "string" - }, - "subpath": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "kind", - "path" - ], - "type": "object" - } - ] - }, "FileUpdateChange": { "properties": { "diff": { @@ -904,135 +708,6 @@ } ] }, - "PermissionProfile": { - "oneOf": [ - { - "description": "Codex owns sandbox construction for this profile.", - "properties": { - "fileSystem": { - "$ref": "#/definitions/PermissionProfileFileSystemPermissions" - }, - "network": { - "$ref": "#/definitions/PermissionProfileNetworkPermissions" - }, - "type": { - "enum": [ - "managed" - ], - "title": "ManagedPermissionProfileType", - "type": "string" - } - }, - "required": [ - "fileSystem", - "network", - "type" - ], - "title": "ManagedPermissionProfile", - "type": "object" - }, - { - "description": "Do not apply an outer sandbox.", - "properties": { - "type": { - "enum": [ - "disabled" - ], - "title": "DisabledPermissionProfileType", - "type": "string" - } - }, - "required": [ - "type" - ], - "title": "DisabledPermissionProfile", - "type": "object" - }, - { - "description": "Filesystem isolation is enforced by an external caller.", - "properties": { - "network": { - "$ref": "#/definitions/PermissionProfileNetworkPermissions" - }, - "type": { - "enum": [ - "external" - ], - "title": "ExternalPermissionProfileType", - "type": "string" - } - }, - "required": [ - "network", - "type" - ], - "title": "ExternalPermissionProfile", - "type": "object" - } - ] - }, - "PermissionProfileFileSystemPermissions": { - "oneOf": [ - { - "properties": { - "entries": { - "items": { - "$ref": "#/definitions/FileSystemSandboxEntry" - }, - "type": "array" - }, - "globScanMaxDepth": { - "format": "uint", - "minimum": 1.0, - "type": [ - "integer", - "null" - ] - }, - "type": { - "enum": [ - "restricted" - ], - "title": "RestrictedPermissionProfileFileSystemPermissionsType", - "type": "string" - } - }, - "required": [ - "entries", - "type" - ], - "title": "RestrictedPermissionProfileFileSystemPermissions", - "type": "object" - }, - { - "properties": { - "type": { - "enum": [ - "unrestricted" - ], - "title": "UnrestrictedPermissionProfileFileSystemPermissionsType", - "type": "string" - } - }, - "required": [ - "type" - ], - "title": "UnrestrictedPermissionProfileFileSystemPermissions", - "type": "object" - } - ] - }, - "PermissionProfileNetworkPermissions": { - "properties": { - "enabled": { - "type": "boolean" - } - }, - "required": [ - "enabled" - ], - "type": "object" - }, "ReasoningEffort": { "description": "See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning", "enum": [ @@ -2572,7 +2247,7 @@ "$ref": "#/definitions/SandboxPolicy" } ], - "description": "Legacy sandbox policy retained for compatibility. Experimental clients should prefer `permissionProfile` when they need exact runtime permissions." + "description": "Legacy sandbox policy retained for compatibility. Experimental clients should prefer `activePermissionProfile` for profile provenance." }, "serviceTier": { "type": [ diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/ThreadForkResponse.ts b/codex-rs/app-server-protocol/schema/typescript/v2/ThreadForkResponse.ts index c44533ec1a..c5b1201c26 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/ThreadForkResponse.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/ThreadForkResponse.ts @@ -16,7 +16,6 @@ instructionSources: Array, approvalPolicy: AskForApproval, /** */ approvalsReviewer: ApprovalsReviewer, /** * Legacy sandbox policy retained for compatibility. Experimental clients - * should prefer `permissionProfile` when they need exact runtime - * permissions. + * should prefer `activePermissionProfile` for profile provenance. */ sandbox: SandboxPolicy, reasoningEffort: ReasoningEffort | null}; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/ThreadResumeResponse.ts b/codex-rs/app-server-protocol/schema/typescript/v2/ThreadResumeResponse.ts index f91756c7c6..7a4f90377c 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/ThreadResumeResponse.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/ThreadResumeResponse.ts @@ -16,7 +16,6 @@ instructionSources: Array, approvalPolicy: AskForApproval, /** */ approvalsReviewer: ApprovalsReviewer, /** * Legacy sandbox policy retained for compatibility. Experimental clients - * should prefer `permissionProfile` when they need exact runtime - * permissions. + * should prefer `activePermissionProfile` for profile provenance. */ sandbox: SandboxPolicy, reasoningEffort: ReasoningEffort | null}; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/ThreadStartResponse.ts b/codex-rs/app-server-protocol/schema/typescript/v2/ThreadStartResponse.ts index 9573bd7dee..38859a3805 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/ThreadStartResponse.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/ThreadStartResponse.ts @@ -16,7 +16,6 @@ instructionSources: Array, approvalPolicy: AskForApproval, /** */ approvalsReviewer: ApprovalsReviewer, /** * Legacy sandbox policy retained for compatibility. Experimental clients - * should prefer `permissionProfile` when they need exact runtime - * permissions. + * should prefer `activePermissionProfile` for profile provenance. */ sandbox: SandboxPolicy, reasoningEffort: ReasoningEffort | null}; diff --git a/codex-rs/app-server-protocol/src/protocol/common.rs b/codex-rs/app-server-protocol/src/protocol/common.rs index e0cd330fff..8e4a30db67 100644 --- a/codex-rs/app-server-protocol/src/protocol/common.rs +++ b/codex-rs/app-server-protocol/src/protocol/common.rs @@ -2301,7 +2301,6 @@ mod tests { approval_policy: v2::AskForApproval::OnFailure, approvals_reviewer: v2::ApprovalsReviewer::User, sandbox: v2::SandboxPolicy::DangerFullAccess, - permission_profile: None, active_permission_profile: None, reasoning_effort: None, }, @@ -2348,7 +2347,6 @@ mod tests { "sandbox": { "type": "dangerFullAccess" }, - "permissionProfile": null, "activePermissionProfile": null, "reasoningEffort": null } diff --git a/codex-rs/app-server-protocol/src/protocol/v2/tests.rs b/codex-rs/app-server-protocol/src/protocol/v2/tests.rs index 50058cb686..d17a3dd988 100644 --- a/codex-rs/app-server-protocol/src/protocol/v2/tests.rs +++ b/codex-rs/app-server-protocol/src/protocol/v2/tests.rs @@ -3498,9 +3498,6 @@ fn thread_lifecycle_responses_default_missing_optional_fields() { assert_eq!(start.instruction_sources, Vec::::new()); assert_eq!(resume.instruction_sources, Vec::::new()); assert_eq!(fork.instruction_sources, Vec::::new()); - assert_eq!(start.permission_profile, None); - assert_eq!(resume.permission_profile, None); - assert_eq!(fork.permission_profile, None); assert_eq!(start.active_permission_profile, None); assert_eq!(resume.active_permission_profile, None); assert_eq!(fork.active_permission_profile, None); diff --git a/codex-rs/app-server-protocol/src/protocol/v2/thread.rs b/codex-rs/app-server-protocol/src/protocol/v2/thread.rs index a3321436f6..ffe2c353d1 100644 --- a/codex-rs/app-server-protocol/src/protocol/v2/thread.rs +++ b/codex-rs/app-server-protocol/src/protocol/v2/thread.rs @@ -1,7 +1,6 @@ use super::ActivePermissionProfile; use super::ApprovalsReviewer; use super::AskForApproval; -use super::PermissionProfile; use super::PermissionProfileSelectionParams; use super::SandboxMode; use super::SandboxPolicy; @@ -213,14 +212,8 @@ pub struct ThreadStartResponse { /// Reviewer currently used for approval requests on this thread. pub approvals_reviewer: ApprovalsReviewer, /// Legacy sandbox policy retained for compatibility. Experimental clients - /// should prefer `permissionProfile` when they need exact runtime - /// permissions. + /// should prefer `activePermissionProfile` for profile provenance. pub sandbox: SandboxPolicy, - /// Full active permissions for this thread. `activePermissionProfile` - /// carries display/provenance metadata for this runtime profile. - #[experimental("thread/start.permissionProfile")] - #[serde(default)] - pub permission_profile: Option, /// Named or implicit built-in profile that produced the active /// permissions, when known. #[experimental("thread/start.activePermissionProfile")] @@ -339,14 +332,8 @@ pub struct ThreadResumeResponse { /// Reviewer currently used for approval requests on this thread. pub approvals_reviewer: ApprovalsReviewer, /// Legacy sandbox policy retained for compatibility. Experimental clients - /// should prefer `permissionProfile` when they need exact runtime - /// permissions. + /// should prefer `activePermissionProfile` for profile provenance. pub sandbox: SandboxPolicy, - /// Full active permissions for this thread. `activePermissionProfile` - /// carries display/provenance metadata for this runtime profile. - #[experimental("thread/resume.permissionProfile")] - #[serde(default)] - pub permission_profile: Option, /// Named or implicit built-in profile that produced the active /// permissions, when known. #[experimental("thread/resume.activePermissionProfile")] @@ -459,14 +446,8 @@ pub struct ThreadForkResponse { /// Reviewer currently used for approval requests on this thread. pub approvals_reviewer: ApprovalsReviewer, /// Legacy sandbox policy retained for compatibility. Experimental clients - /// should prefer `permissionProfile` when they need exact runtime - /// permissions. + /// should prefer `activePermissionProfile` for profile provenance. pub sandbox: SandboxPolicy, - /// Full active permissions for this thread. `activePermissionProfile` - /// carries display/provenance metadata for this runtime profile. - #[experimental("thread/fork.permissionProfile")] - #[serde(default)] - pub permission_profile: Option, /// Named or implicit built-in profile that produced the active /// permissions, when known. #[experimental("thread/fork.activePermissionProfile")] diff --git a/codex-rs/app-server/src/request_processors/thread_lifecycle.rs b/codex-rs/app-server/src/request_processors/thread_lifecycle.rs index c64066ee93..4781df8350 100644 --- a/codex-rs/app-server/src/request_processors/thread_lifecycle.rs +++ b/codex-rs/app-server/src/request_processors/thread_lifecycle.rs @@ -626,7 +626,6 @@ pub(super) async fn handle_pending_thread_resume_request( approval_policy: approval_policy.into(), approvals_reviewer: approvals_reviewer.into(), sandbox, - permission_profile: Some(permission_profile.into()), active_permission_profile, reasoning_effort, }; diff --git a/codex-rs/app-server/src/request_processors/thread_processor.rs b/codex-rs/app-server/src/request_processors/thread_processor.rs index 3038feeef1..21160950ab 100644 --- a/codex-rs/app-server/src/request_processors/thread_processor.rs +++ b/codex-rs/app-server/src/request_processors/thread_processor.rs @@ -1199,7 +1199,6 @@ impl ThreadRequestProcessor { approval_policy: config_snapshot.approval_policy.into(), approvals_reviewer: config_snapshot.approvals_reviewer.into(), sandbox, - permission_profile: Some(config_snapshot.permission_profile.into()), active_permission_profile, reasoning_effort: config_snapshot.reasoning_effort, }; @@ -2554,7 +2553,6 @@ impl ThreadRequestProcessor { approval_policy: session_configured.approval_policy.into(), approvals_reviewer: session_configured.approvals_reviewer.into(), sandbox, - permission_profile: Some(config_snapshot.permission_profile.into()), active_permission_profile, reasoning_effort: session_configured.reasoning_effort, }; @@ -3215,7 +3213,6 @@ impl ThreadRequestProcessor { approval_policy: session_configured.approval_policy.into(), approvals_reviewer: session_configured.approvals_reviewer.into(), sandbox, - permission_profile: Some(config_snapshot.permission_profile.into()), active_permission_profile, reasoning_effort: session_configured.reasoning_effort, }; diff --git a/codex-rs/exec/src/lib.rs b/codex-rs/exec/src/lib.rs index 9f7174ec68..1004124ba5 100644 --- a/codex-rs/exec/src/lib.rs +++ b/codex-rs/exec/src/lib.rs @@ -1089,11 +1089,7 @@ fn session_configured_from_thread_start_response( response.service_tier.clone(), response.approval_policy.to_core(), response.approvals_reviewer.to_core(), - response - .permission_profile - .clone() - .map(Into::into) - .unwrap_or_else(|| config.permissions.effective_permission_profile()), + config.permissions.effective_permission_profile(), response.active_permission_profile.clone().map(Into::into), response.cwd.clone(), response.reasoning_effort, @@ -1114,11 +1110,7 @@ fn session_configured_from_thread_resume_response( response.service_tier.clone(), response.approval_policy.to_core(), response.approvals_reviewer.to_core(), - response - .permission_profile - .clone() - .map(Into::into) - .unwrap_or_else(|| config.permissions.effective_permission_profile()), + config.permissions.effective_permission_profile(), response.active_permission_profile.clone().map(Into::into), response.cwd.clone(), response.reasoning_effort, diff --git a/codex-rs/exec/src/lib_tests.rs b/codex-rs/exec/src/lib_tests.rs index 367bba5d05..92dc0678e5 100644 --- a/codex-rs/exec/src/lib_tests.rs +++ b/codex-rs/exec/src/lib_tests.rs @@ -528,7 +528,7 @@ async fn session_configured_from_thread_response_uses_review_policy_from_respons } #[tokio::test] -async fn session_configured_from_thread_response_uses_permission_profile_from_response() { +async fn session_configured_from_thread_response_uses_permission_profile_from_config() { let codex_home = tempdir().expect("create temp codex home"); let cwd = tempdir().expect("create temp cwd"); let config = ConfigBuilder::default() @@ -537,13 +537,15 @@ async fn session_configured_from_thread_response_uses_permission_profile_from_re .build() .await .expect("build config"); - let mut response = sample_thread_start_response(); - response.permission_profile = Some(PermissionProfile::Disabled.into()); + let response = sample_thread_start_response(); let event = session_configured_from_thread_start_response(&response, &config) .expect("build bootstrap session configured event"); - assert_eq!(event.permission_profile, PermissionProfile::Disabled); + assert_eq!( + event.permission_profile, + config.permissions.effective_permission_profile() + ); } fn sample_thread_start_response() -> ThreadStartResponse { @@ -583,7 +585,6 @@ fn sample_thread_start_response() -> ThreadStartResponse { exclude_tmpdir_env_var: false, exclude_slash_tmp: false, }, - permission_profile: None, active_permission_profile: None, reasoning_effort: None, } diff --git a/codex-rs/tui/src/app_server_session.rs b/codex-rs/tui/src/app_server_session.rs index 0470d24db6..464b8052b4 100644 --- a/codex-rs/tui/src/app_server_session.rs +++ b/codex-rs/tui/src/app_server_session.rs @@ -1415,7 +1415,6 @@ async fn thread_session_state_from_thread_start_response( ) -> Result { let permission_profile = permission_profile_from_thread_response( &response.sandbox, - response.permission_profile.as_ref(), response.cwd.as_path(), config, thread_params_mode, @@ -1448,7 +1447,6 @@ async fn thread_session_state_from_thread_resume_response( ) -> Result { let permission_profile = permission_profile_from_thread_response( &response.sandbox, - response.permission_profile.as_ref(), response.cwd.as_path(), config, thread_params_mode, @@ -1481,7 +1479,6 @@ async fn thread_session_state_from_thread_fork_response( ) -> Result { let permission_profile = permission_profile_from_thread_response( &response.sandbox, - response.permission_profile.as_ref(), response.cwd.as_path(), config, thread_params_mode, @@ -1509,14 +1506,10 @@ async fn thread_session_state_from_thread_fork_response( fn permission_profile_from_thread_response( sandbox: &codex_app_server_protocol::SandboxPolicy, - permission_profile: Option<&codex_app_server_protocol::PermissionProfile>, cwd: &std::path::Path, config: &Config, thread_params_mode: ThreadParamsMode, ) -> PermissionProfile { - if let Some(permission_profile) = permission_profile { - return permission_profile.clone().into(); - } match thread_params_mode { ThreadParamsMode::Embedded => config.permissions.effective_permission_profile(), ThreadParamsMode::Remote => { @@ -2109,7 +2102,6 @@ mod tests { .to_legacy_sandbox_policy(test_path_buf("/tmp/project").as_path()) .expect("read-only profile must be legacy-compatible") .into(), - permission_profile: Some(read_only_profile.clone().into()), active_permission_profile: None, reasoning_effort: None, }; @@ -2147,61 +2139,43 @@ mod tests { } #[tokio::test] - async fn remote_thread_response_prefers_permission_profile_over_legacy_sandbox() { + async fn remote_thread_response_uses_legacy_sandbox_fallback() { let temp_dir = tempfile::tempdir().expect("tempdir"); let config = build_config(&temp_dir).await; let cwd = test_path_buf("/tmp/project").abs(); - let fallback_sandbox = PermissionProfile::read_only() + let sandbox = PermissionProfile::read_only() .to_legacy_sandbox_policy(cwd.as_path()) .expect("read-only profile must be legacy-compatible") .into(); - let response_profile = AppServerPermissionProfile::Managed { - file_system: PermissionProfileFileSystemPermissions::Restricted { - entries: vec![ - FileSystemSandboxEntry { - path: FileSystemPath::Special { - value: FileSystemSpecialPath::Root, - }, - access: FileSystemAccessMode::Read, - }, - FileSystemSandboxEntry { - path: FileSystemPath::Special { - value: FileSystemSpecialPath::ProjectRoots { - subpath: Some(".env".into()), - }, - }, - access: FileSystemAccessMode::None, - }, - ], - glob_scan_max_depth: None, - }, - network: PermissionProfileNetworkPermissions { enabled: false }, - }; - let split_profile: PermissionProfile = response_profile.clone().into(); assert_eq!( permission_profile_from_thread_response( - &fallback_sandbox, - Some(&response_profile), + &sandbox, cwd.as_path(), &config, ThreadParamsMode::Remote, ), - split_profile + PermissionProfile::read_only() ); } #[tokio::test] - async fn embedded_thread_response_prefers_permission_profile_when_present() { + async fn embedded_thread_response_uses_local_config_profile() { let temp_dir = tempfile::tempdir().expect("tempdir"); - let config = build_config(&temp_dir).await; + let config = ConfigBuilder::default() + .codex_home(temp_dir.path().to_path_buf()) + .harness_overrides(ConfigOverrides { + default_permissions: Some(BUILT_IN_PERMISSION_PROFILE_READ_ONLY.to_string()), + ..ConfigOverrides::default() + }) + .build() + .await + .expect("config should build"); let cwd = test_path_buf("/tmp/project").abs(); - let response_profile = PermissionProfile::read_only().into(); assert_eq!( permission_profile_from_thread_response( &codex_app_server_protocol::SandboxPolicy::DangerFullAccess, - Some(&response_profile), cwd.as_path(), &config, ThreadParamsMode::Embedded,