mirror of
https://github.com/openai/codex.git
synced 2026-04-24 14:45:27 +00:00
Expand ~ in MDM workspace write roots (#15351)
## Summary - Reuse the existing config path resolver for the macOS MDM managed preferences layer so `writable_roots = ["~/code"]` expands the same way as file-backed config - keep the change scoped to the MDM branch in `config_loader`; the current net diff is only `config_loader/mod.rs` plus focused regression tests in `config_loader/tests.rs` and `config/service_tests.rs` - research note: `resolve_relative_paths_in_config_toml(...)` is already used in several existing configuration paths, including [CLI overrides](74fda242d3/codex-rs/core/src/config_loader/mod.rs (L152-L163)), [file-backed managed config](74fda242d3/codex-rs/core/src/config_loader/mod.rs (L274-L285)), [normal config-file loading](74fda242d3/codex-rs/core/src/config_loader/mod.rs (L311-L331)), [project `.codex/config.toml` loading](74fda242d3/codex-rs/core/src/config_loader/mod.rs (L863-L865)), and [role config loading](74fda242d3/codex-rs/core/src/agent/role.rs (L105-L109)) ## Validation - `cargo fmt --all --check` - `cargo test -p codex-core managed_preferences_expand_home_directory_in_workspace_write_roots -- --nocapture` - `cargo test -p codex-core write_value_succeeds_when_managed_preferences_expand_home_directory_paths -- --nocapture` --------- Co-authored-by: Michael Bolin <mbolin@openai.com> Co-authored-by: Michael Bolin <bolinfest@gmail.com>
This commit is contained in:
@@ -237,6 +237,54 @@ async fn read_includes_origins_and_layers() {
|
||||
));
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[tokio::test]
|
||||
async fn write_value_succeeds_when_managed_preferences_expand_home_directory_paths() -> Result<()> {
|
||||
use base64::Engine;
|
||||
|
||||
let tmp = tempdir().expect("tempdir");
|
||||
std::fs::write(tmp.path().join(CONFIG_TOML_FILE), "model = \"user\"\n")?;
|
||||
|
||||
let service = ConfigService::new(
|
||||
tmp.path().to_path_buf(),
|
||||
vec![],
|
||||
LoaderOverrides {
|
||||
managed_config_path: Some(tmp.path().join("managed_config.toml")),
|
||||
managed_preferences_base64: Some(
|
||||
base64::prelude::BASE64_STANDARD.encode(
|
||||
r#"
|
||||
sandbox_mode = "workspace-write"
|
||||
[sandbox_workspace_write]
|
||||
writable_roots = ["~/code"]
|
||||
"#
|
||||
.as_bytes(),
|
||||
),
|
||||
),
|
||||
macos_managed_config_requirements_base64: None,
|
||||
},
|
||||
CloudRequirementsLoader::default(),
|
||||
);
|
||||
|
||||
let response = service
|
||||
.write_value(ConfigValueWriteParams {
|
||||
file_path: Some(tmp.path().join(CONFIG_TOML_FILE).display().to_string()),
|
||||
key_path: "model".to_string(),
|
||||
value: serde_json::json!("updated"),
|
||||
merge_strategy: MergeStrategy::Replace,
|
||||
expected_version: None,
|
||||
})
|
||||
.await
|
||||
.expect("write succeeds");
|
||||
|
||||
assert_eq!(response.status, WriteStatus::Ok);
|
||||
assert_eq!(
|
||||
std::fs::read_to_string(tmp.path().join(CONFIG_TOML_FILE)).expect("read config"),
|
||||
"model = \"updated\"\n"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn write_value_reports_override() {
|
||||
let tmp = tempdir().expect("tempdir");
|
||||
|
||||
@@ -285,9 +285,11 @@ pub async fn load_config_layers_state(
|
||||
));
|
||||
}
|
||||
if let Some(config) = managed_config_from_mdm {
|
||||
let managed_config =
|
||||
resolve_relative_paths_in_config_toml(config.managed_config, codex_home)?;
|
||||
layers.push(ConfigLayerEntry::new_with_raw_toml(
|
||||
ConfigLayerSource::LegacyManagedConfigTomlFromMdm,
|
||||
config.managed_config,
|
||||
managed_config,
|
||||
config.raw_toml,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -380,6 +380,54 @@ flag = false
|
||||
assert!(raw.contains("value = \"managed\""));
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[tokio::test]
|
||||
async fn managed_preferences_expand_home_directory_in_workspace_write_roots() -> anyhow::Result<()>
|
||||
{
|
||||
use base64::Engine;
|
||||
|
||||
let Some(home) = dirs::home_dir() else {
|
||||
return Ok(());
|
||||
};
|
||||
let tmp = tempdir()?;
|
||||
|
||||
let config = ConfigBuilder::default()
|
||||
.codex_home(tmp.path().to_path_buf())
|
||||
.fallback_cwd(Some(tmp.path().to_path_buf()))
|
||||
.loader_overrides(LoaderOverrides {
|
||||
managed_config_path: Some(tmp.path().join("managed_config.toml")),
|
||||
managed_preferences_base64: Some(
|
||||
base64::prelude::BASE64_STANDARD.encode(
|
||||
r#"
|
||||
sandbox_mode = "workspace-write"
|
||||
[sandbox_workspace_write]
|
||||
writable_roots = ["~/code"]
|
||||
"#
|
||||
.as_bytes(),
|
||||
),
|
||||
),
|
||||
macos_managed_config_requirements_base64: None,
|
||||
})
|
||||
.build()
|
||||
.await?;
|
||||
|
||||
let expected_root = AbsolutePathBuf::from_absolute_path(home.join("code"))?;
|
||||
match config.permissions.sandbox_policy.get() {
|
||||
SandboxPolicy::WorkspaceWrite { writable_roots, .. } => {
|
||||
assert_eq!(
|
||||
writable_roots
|
||||
.iter()
|
||||
.filter(|root| **root == expected_root)
|
||||
.count(),
|
||||
1,
|
||||
);
|
||||
}
|
||||
other => panic!("expected workspace-write policy, got {other:?}"),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[tokio::test]
|
||||
async fn managed_preferences_requirements_are_applied() -> anyhow::Result<()> {
|
||||
|
||||
Reference in New Issue
Block a user