From 2a840d40772d61978f74a415e125be8ff5e1b9cc Mon Sep 17 00:00:00 2001 From: David Wiesen Date: Wed, 6 May 2026 10:10:07 -0700 Subject: [PATCH] Accept legacy wsl2 Windows sandbox alias --- codex-rs/config/src/types.rs | 27 ++++++++++++++++++++++++++- codex-rs/config/src/types_tests.rs | 20 ++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/codex-rs/config/src/types.rs b/codex-rs/config/src/types.rs index 6cb9abc507..dbca12e9f9 100644 --- a/codex-rs/config/src/types.rs +++ b/codex-rs/config/src/types.rs @@ -27,6 +27,8 @@ use std::fmt; use schemars::JsonSchema; use serde::Deserialize; use serde::Serialize; +use serde::de::Error as _; +use std::str::FromStr; pub use crate::tui_keymap::KeybindingSpec; pub use crate::tui_keymap::KeybindingsSpec; @@ -111,13 +113,36 @@ pub enum OAuthCredentialsStoreMode { Keyring, } -#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema)] +#[derive(Serialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema)] #[serde(rename_all = "kebab-case")] pub enum WindowsSandboxModeToml { Elevated, Unelevated, } +impl FromStr for WindowsSandboxModeToml { + type Err = &'static str; + + fn from_str(value: &str) -> Result { + let normalized = value.trim().to_ascii_lowercase(); + match normalized.as_str() { + "elevated" => Ok(Self::Elevated), + "unelevated" | "wsl2" => Ok(Self::Unelevated), + _ => Err("expected `elevated`, `unelevated`, or legacy alias `wsl2`"), + } + } +} + +impl<'de> Deserialize<'de> for WindowsSandboxModeToml { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let value = String::deserialize(deserializer)?; + Self::from_str(&value).map_err(D::Error::custom) + } +} + #[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, JsonSchema)] #[schemars(deny_unknown_fields)] pub struct WindowsToml { diff --git a/codex-rs/config/src/types_tests.rs b/codex-rs/config/src/types_tests.rs index 2c3f69d986..442e36cdd7 100644 --- a/codex-rs/config/src/types_tests.rs +++ b/codex-rs/config/src/types_tests.rs @@ -1,6 +1,26 @@ use super::*; use pretty_assertions::assert_eq; +#[test] +fn windows_sandbox_mode_accepts_legacy_wsl2_alias_case_insensitively() { + let mode: WindowsSandboxModeToml = + toml::from_str("\"wsL2\"").expect("should deserialize legacy WSL2 alias"); + + assert_eq!(mode, WindowsSandboxModeToml::Unelevated); +} + +#[test] +fn windows_sandbox_mode_rejects_unknown_values() { + let err = toml::from_str::("\"sandboxie\"") + .expect_err("unknown sandbox values should be rejected"); + + assert!( + err.to_string() + .contains("expected `elevated`, `unelevated`, or legacy alias `wsl2`"), + "unexpected error: {err}" + ); +} + #[test] fn deserialize_skill_config_with_name_selector() { let cfg: SkillConfig = toml::from_str(