From 37f9c6d53a8295ba13df73222ec2ae8955b9b6be Mon Sep 17 00:00:00 2001 From: Aaron Levine Date: Wed, 3 Jun 2026 20:33:18 -0700 Subject: [PATCH] app-server: reload config for Windows thread forks git-stack-id: aaron/app-server-in-memory-config---4ivokd7wtu-snl git-stack-title: app-server: add in-memory config layer --- .../request_processors/thread_processor.rs | 18 +------ .../app-server/tests/suite/v2/thread_fork.rs | 50 +++++++++++++++++++ 2 files changed, 51 insertions(+), 17 deletions(-) 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 265832f9b7..ba40f0e8a0 100644 --- a/codex-rs/app-server/src/request_processors/thread_processor.rs +++ b/codex-rs/app-server/src/request_processors/thread_processor.rs @@ -3188,23 +3188,7 @@ impl ThreadRequestProcessor { })?; let history_cwd = Some(source_thread.cwd.clone()); - // Persist Windows sandbox mode. - let mut cli_overrides = cli_overrides.unwrap_or_default(); - if cfg!(windows) { - match WindowsSandboxLevel::from_config(&self.config) { - WindowsSandboxLevel::Elevated => { - cli_overrides - .insert("windows.sandbox".to_string(), serde_json::json!("elevated")); - } - WindowsSandboxLevel::RestrictedToken => { - cli_overrides.insert( - "windows.sandbox".to_string(), - serde_json::json!("unelevated"), - ); - } - WindowsSandboxLevel::Disabled => {} - } - } + let cli_overrides = cli_overrides.unwrap_or_default(); let request_overrides = if cli_overrides.is_empty() { None } else { diff --git a/codex-rs/app-server/tests/suite/v2/thread_fork.rs b/codex-rs/app-server/tests/suite/v2/thread_fork.rs index ff9f655630..9390ef3cf1 100644 --- a/codex-rs/app-server/tests/suite/v2/thread_fork.rs +++ b/codex-rs/app-server/tests/suite/v2/thread_fork.rs @@ -10,6 +10,8 @@ use codex_app_server_protocol::JSONRPCError; use codex_app_server_protocol::JSONRPCMessage; use codex_app_server_protocol::JSONRPCResponse; use codex_app_server_protocol::RequestId; +#[cfg(windows)] +use codex_app_server_protocol::SandboxPolicy; use codex_app_server_protocol::ServerNotification; use codex_app_server_protocol::SessionSource; use codex_app_server_protocol::ThreadForkParams; @@ -674,6 +676,54 @@ async fn thread_fork_surfaces_cloud_config_bundle_load_errors() -> Result<()> { Ok(()) } +#[cfg(windows)] +#[tokio::test] +async fn thread_fork_reloads_windows_sandbox_config_instead_of_startup_snapshot() -> Result<()> { + let codex_home = TempDir::new()?; + std::fs::write( + codex_home.path().join("config.toml"), + "[windows]\nsandbox = \"elevated\"\n", + )?; + + let mut mcp = TestAppServer::new(codex_home.path()).await?; + timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??; + + let start_id = mcp + .send_thread_start_request(ThreadStartParams::default()) + .await?; + let start_response: JSONRPCResponse = timeout( + DEFAULT_READ_TIMEOUT, + mcp.read_stream_until_response_message(RequestId::Integer(start_id)), + ) + .await??; + let start_response: ThreadStartResponse = to_response(start_response)?; + assert!( + matches!(start_response.sandbox, SandboxPolicy::WorkspaceWrite { .. }), + "elevated Windows sandbox config should select workspace-write defaults" + ); + + std::fs::write(codex_home.path().join("config.toml"), "")?; + + let fork_id = mcp + .send_thread_fork_request(ThreadForkParams { + thread_id: start_response.thread.id, + ..Default::default() + }) + .await?; + let fork_response: JSONRPCResponse = timeout( + DEFAULT_READ_TIMEOUT, + mcp.read_stream_until_response_message(RequestId::Integer(fork_id)), + ) + .await??; + let fork_response: ThreadForkResponse = to_response(fork_response)?; + assert!( + matches!(fork_response.sandbox, SandboxPolicy::ReadOnly { .. }), + "fork should resolve the updated config.toml instead of pinning startup Windows sandbox state" + ); + + Ok(()) +} + #[tokio::test] async fn thread_fork_ephemeral_remains_pathless_and_omits_listing() -> Result<()> { let server = create_mock_responses_server_repeating_assistant("Done").await;