Codex Handbook
app-server/src/config_manager_service_tests.rs 929 lines
use super::*;use anyhow::Result;use codex_app_server_protocol::AppConfig;use codex_app_server_protocol::AppToolApproval;use codex_app_server_protocol::AppsConfig;use codex_app_server_protocol::AskForApproval;use codex_config::CloudConfigBundleLoader;use codex_config::LoaderOverrides;use codex_config::test_support::CloudConfigBundleFixture;use codex_utils_absolute_path::AbsolutePathBuf;use pretty_assertions::assert_eq;use tempfile::tempdir;#[test]fn toml_value_to_item_handles_nested_config_tables() {    let config = r#"[mcp_servers.docs]command = "docs-server"[mcp_servers.docs.http_headers]X-Doc = "42""#;    let value: TomlValue = toml::from_str(config).expect("parse config example");    let item = toml_value_to_item(&value).expect("convert to toml_edit item");    let root = item.as_table().expect("root table");    assert!(!root.is_implicit(), "root table should be explicit");    let mcp_servers = root        .get("mcp_servers")        .and_then(TomlItem::as_table)        .expect("mcp_servers table");    assert!(        !mcp_servers.is_implicit(),        "mcp_servers table should be explicit"    );    let docs = mcp_servers        .get("docs")        .and_then(TomlItem::as_table)        .expect("docs table");    assert_eq!(        docs.get("command")            .and_then(TomlItem::as_value)            .and_then(toml_edit::Value::as_str),        Some("docs-server")    );    let http_headers = docs        .get("http_headers")        .and_then(TomlItem::as_table)        .expect("http_headers table");    assert_eq!(        http_headers            .get("X-Doc")            .and_then(TomlItem::as_value)            .and_then(toml_edit::Value::as_str),        Some("42")    );}#[tokio::test]async fn write_value_preserves_comments_and_order() -> Result<()> {    let tmp = tempdir().expect("tempdir");    let original = r#"# Codex user configurationmodel = "gpt-5.2"approval_policy = "on-request"[notice]# Preserve this commenthide_full_access_warning = true[features]unified_exec = true"#;    std::fs::write(tmp.path().join(CONFIG_TOML_FILE), original)?;    let service = ConfigManager::without_managed_config_for_tests(tmp.path().to_path_buf());    service        .write_value(ConfigValueWriteParams {            file_path: Some(tmp.path().join(CONFIG_TOML_FILE).display().to_string()),            key_path: "features.personality".to_string(),            value: serde_json::json!(true),            merge_strategy: MergeStrategy::Replace,            expected_version: None,        })        .await        .expect("write succeeds");    let updated = std::fs::read_to_string(tmp.path().join(CONFIG_TOML_FILE)).expect("read config");    let expected = r#"# Codex user configurationmodel = "gpt-5.2"approval_policy = "on-request"[notice]# Preserve this commenthide_full_access_warning = true[features]unified_exec = truepersonality = true"#;    assert_eq!(updated, expected);    Ok(())}#[tokio::test]async fn clear_missing_nested_config_is_noop() -> Result<()> {    let tmp = tempdir().expect("tempdir");    let path = tmp.path().join(CONFIG_TOML_FILE);    std::fs::write(&path, "")?;    let service = ConfigManager::without_managed_config_for_tests(tmp.path().to_path_buf());    let response = service        .write_value(ConfigValueWriteParams {            file_path: Some(path.display().to_string()),            key_path: "features.personality".to_string(),            value: serde_json::Value::Null,            merge_strategy: MergeStrategy::Replace,            expected_version: None,        })        .await        .expect("clear missing config succeeds");    assert_eq!(response.status, WriteStatus::Ok);    assert_eq!(response.overridden_metadata, None);    assert_eq!(std::fs::read_to_string(&path)?, "");    Ok(())}#[tokio::test]async fn write_value_rejects_legacy_profile_selector() -> Result<()> {    let tmp = tempdir().expect("tempdir");    let path = tmp.path().join(CONFIG_TOML_FILE);    std::fs::write(&path, "model = \"gpt-main\"\n")?;    let service = ConfigManager::without_managed_config_for_tests(tmp.path().to_path_buf());    let error = service        .write_value(ConfigValueWriteParams {            file_path: Some(path.display().to_string()),            key_path: "profile".to_string(),            value: serde_json::json!("work"),            merge_strategy: MergeStrategy::Replace,            expected_version: None,        })        .await        .expect_err("legacy profile selector write should fail");    assert_eq!(        error.write_error_code(),        Some(ConfigWriteErrorCode::ConfigValidationError)    );    assert!(        error            .to_string()            .contains("`profile` is a legacy config selector"),        "{error}"    );    assert_eq!(std::fs::read_to_string(&path)?, "model = \"gpt-main\"\n");    Ok(())}#[tokio::test]async fn write_value_rejects_legacy_profile_table() -> Result<()> {    let tmp = tempdir().expect("tempdir");    let path = tmp.path().join(CONFIG_TOML_FILE);    std::fs::write(&path, "")?;    let service = ConfigManager::without_managed_config_for_tests(tmp.path().to_path_buf());    let error = service        .write_value(ConfigValueWriteParams {            file_path: Some(path.display().to_string()),            key_path: "profiles.work.model".to_string(),            value: serde_json::json!("gpt-work"),            merge_strategy: MergeStrategy::Replace,            expected_version: None,        })        .await        .expect_err("legacy profile table write should fail");    assert_eq!(        error.write_error_code(),        Some(ConfigWriteErrorCode::ConfigValidationError)    );    assert!(        error            .to_string()            .contains("`profiles` contains legacy config profile tables"),        "{error}"    );    assert_eq!(std::fs::read_to_string(&path)?, "");    Ok(())}#[tokio::test]async fn batch_write_rejects_legacy_profile_selector() -> Result<()> {    let tmp = tempdir().expect("tempdir");    let path = tmp.path().join(CONFIG_TOML_FILE);    std::fs::write(&path, "model = \"gpt-main\"\n")?;    let service = ConfigManager::without_managed_config_for_tests(tmp.path().to_path_buf());    let error = service        .batch_write(ConfigBatchWriteParams {            edits: vec![                codex_app_server_protocol::ConfigEdit {                    key_path: "model".to_string(),                    value: serde_json::json!("gpt-work"),                    merge_strategy: MergeStrategy::Replace,                },                codex_app_server_protocol::ConfigEdit {                    key_path: "profile".to_string(),                    value: serde_json::json!("work"),                    merge_strategy: MergeStrategy::Replace,                },            ],            file_path: Some(path.display().to_string()),            expected_version: None,            reload_user_config: false,        })        .await        .expect_err("legacy profile selector batch write should fail");    assert_eq!(        error.write_error_code(),        Some(ConfigWriteErrorCode::ConfigValidationError)    );    assert!(        error            .to_string()            .contains("`profile` is a legacy config selector"),        "{error}"    );    assert_eq!(std::fs::read_to_string(&path)?, "model = \"gpt-main\"\n");    Ok(())}#[tokio::test]async fn write_value_supports_nested_app_paths() -> Result<()> {    let tmp = tempdir().expect("tempdir");    std::fs::write(tmp.path().join(CONFIG_TOML_FILE), "")?;    let service = ConfigManager::without_managed_config_for_tests(tmp.path().to_path_buf());    service        .write_value(ConfigValueWriteParams {            file_path: Some(tmp.path().join(CONFIG_TOML_FILE).display().to_string()),            key_path: "apps".to_string(),            value: serde_json::json!({                "app1": {                    "enabled": false,                },            }),            merge_strategy: MergeStrategy::Replace,            expected_version: None,        })        .await        .expect("write apps succeeds");    service        .write_value(ConfigValueWriteParams {            file_path: Some(tmp.path().join(CONFIG_TOML_FILE).display().to_string()),            key_path: "apps.app1.default_tools_approval_mode".to_string(),            value: serde_json::json!("prompt"),            merge_strategy: MergeStrategy::Replace,            expected_version: None,        })        .await        .expect("write apps.app1.default_tools_approval_mode succeeds");    let read = service        .read(ConfigReadParams {            include_layers: false,            cwd: None,        })        .await        .expect("config read succeeds");    assert_eq!(        read.config.apps,        Some(AppsConfig {            default: None,            apps: std::collections::HashMap::from([(                "app1".to_string(),                AppConfig {                    enabled: false,                    approvals_reviewer: None,                    destructive_enabled: None,                    open_world_enabled: None,                    default_tools_approval_mode: Some(AppToolApproval::Prompt),                    default_tools_enabled: None,                    tools: None,                },            )]),        })    );    Ok(())}#[tokio::test]async fn write_value_supports_custom_mcp_server_default_tool_approval_mode() -> Result<()> {    let tmp = tempdir().expect("tempdir");    std::fs::write(        tmp.path().join(CONFIG_TOML_FILE),        "[mcp_servers.docs]\ncommand = \"docs-server\"\n",    )?;    let service = ConfigManager::without_managed_config_for_tests(tmp.path().to_path_buf());    service        .write_value(ConfigValueWriteParams {            file_path: Some(tmp.path().join(CONFIG_TOML_FILE).display().to_string()),            key_path: "mcp_servers.docs.default_tools_approval_mode".to_string(),            value: serde_json::json!("approve"),            merge_strategy: MergeStrategy::Replace,            expected_version: None,        })        .await        .expect("write mcp server default_tools_approval_mode succeeds");    let contents = std::fs::read_to_string(tmp.path().join(CONFIG_TOML_FILE))?;    assert!(contents.contains("default_tools_approval_mode = \"approve\""));    let read = service        .read(ConfigReadParams {            include_layers: false,            cwd: None,        })        .await        .expect("config read succeeds");    assert_eq!(        read.config            .additional            .get("mcp_servers")            .and_then(|servers| servers.get("docs"))            .and_then(|docs| docs.get("default_tools_approval_mode")),        Some(&serde_json::json!("approve"))    );    Ok(())}#[tokio::test]async fn read_includes_origins_and_layers() {    let tmp = tempdir().expect("tempdir");    let user_path = tmp.path().join(CONFIG_TOML_FILE);    std::fs::write(&user_path, "model = \"user\"").unwrap();    let user_file = AbsolutePathBuf::try_from(user_path.clone()).expect("user file");    let managed_path = tmp.path().join("managed_config.toml");    std::fs::write(&managed_path, "approval_policy = \"never\"").unwrap();    let managed_file = AbsolutePathBuf::try_from(managed_path.clone()).expect("managed file");    let service = ConfigManager::new_for_tests(        tmp.path().to_path_buf(),        vec![],        LoaderOverrides::with_managed_config_path_for_tests(managed_path.clone()),        CloudConfigBundleLoader::default(),    );    let response = service        .read(ConfigReadParams {            include_layers: true,            cwd: None,        })        .await        .expect("response");    assert_eq!(response.config.approval_policy, Some(AskForApproval::Never));    assert_eq!(        response            .origins            .get("approval_policy")            .expect("origin")            .name,        ConfigLayerSource::LegacyManagedConfigTomlFromFile {            file: managed_file.clone()        },    );    let layers = response.layers.expect("layers present");    // Local macOS machines can surface an MDM-managed config layer at the    // top of the stack; ignore it so this test stays focused on file/user/system ordering.    let layers = if matches!(        layers.first().map(|layer| &layer.name),        Some(ConfigLayerSource::LegacyManagedConfigTomlFromMdm)    ) {        &layers[1..]    } else {        layers.as_slice()    };    assert_eq!(layers.len(), 3, "expected three layers");    assert_eq!(        layers.first().unwrap().name,        ConfigLayerSource::LegacyManagedConfigTomlFromFile {            file: managed_file.clone()        }    );    assert_eq!(        layers.get(1).unwrap().name,        ConfigLayerSource::User {            file: user_file.clone(),            profile: None,        }    );    assert!(matches!(        layers.get(2).unwrap().name,        ConfigLayerSource::System { .. }    ));}#[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 mut loader_overrides =        LoaderOverrides::with_managed_config_path_for_tests(tmp.path().join("managed_config.toml"));    loader_overrides.managed_preferences_base64 = Some(        base64::prelude::BASE64_STANDARD.encode(            r#"sandbox_mode = "workspace-write"[sandbox_workspace_write]writable_roots = ["~/code"]"#            .as_bytes(),        ),    );    let service = ConfigManager::new_for_tests(        tmp.path().to_path_buf(),        vec![],        loader_overrides,        CloudConfigBundleLoader::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");    std::fs::write(        tmp.path().join(CONFIG_TOML_FILE),        "approval_policy = \"on-request\"",    )    .unwrap();    let managed_path = tmp.path().join("managed_config.toml");    std::fs::write(&managed_path, "approval_policy = \"never\"").unwrap();    let managed_file = AbsolutePathBuf::try_from(managed_path.clone()).expect("managed file");    let service = ConfigManager::new_for_tests(        tmp.path().to_path_buf(),        vec![],        LoaderOverrides::with_managed_config_path_for_tests(managed_path.clone()),        CloudConfigBundleLoader::default(),    );    let result = service        .write_value(ConfigValueWriteParams {            file_path: Some(tmp.path().join(CONFIG_TOML_FILE).display().to_string()),            key_path: "approval_policy".to_string(),            value: serde_json::json!("never"),            merge_strategy: MergeStrategy::Replace,            expected_version: None,        })        .await        .expect("result");    let read_after = service        .read(ConfigReadParams {            include_layers: true,            cwd: None,        })        .await        .expect("read");    assert_eq!(        read_after.config.approval_policy,        Some(AskForApproval::Never)    );    assert_eq!(        read_after            .origins            .get("approval_policy")            .expect("origin")            .name,        ConfigLayerSource::LegacyManagedConfigTomlFromFile {            file: managed_file.clone()        }    );    assert_eq!(result.status, WriteStatus::Ok);    assert!(result.overridden_metadata.is_none());}#[tokio::test]async fn version_conflict_rejected() {    let tmp = tempdir().expect("tempdir");    let user_path = tmp.path().join(CONFIG_TOML_FILE);    std::fs::write(&user_path, "model = \"user\"").unwrap();    let service = ConfigManager::without_managed_config_for_tests(tmp.path().to_path_buf());    let error = 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!("gpt-5.2"),            merge_strategy: MergeStrategy::Replace,            expected_version: Some("sha256:bogus".to_string()),        })        .await        .expect_err("should fail");    assert_eq!(        error.write_error_code(),        Some(ConfigWriteErrorCode::ConfigVersionConflict)    );}#[tokio::test]async fn write_value_defaults_to_user_config_path() {    let tmp = tempdir().expect("tempdir");    std::fs::write(tmp.path().join(CONFIG_TOML_FILE), "").unwrap();    let service = ConfigManager::without_managed_config_for_tests(tmp.path().to_path_buf());    service        .write_value(ConfigValueWriteParams {            file_path: None,            key_path: "model".to_string(),            value: serde_json::json!("gpt-new"),            merge_strategy: MergeStrategy::Replace,            expected_version: None,        })        .await        .expect("write succeeds");    let contents = std::fs::read_to_string(tmp.path().join(CONFIG_TOML_FILE)).expect("read config");    assert!(        contents.contains("model = \"gpt-new\""),        "config.toml should be updated even when file_path is omitted"    );}#[tokio::test]async fn write_value_defaults_to_selected_user_config_path() {    let tmp = tempdir().expect("tempdir");    std::fs::write(tmp.path().join(CONFIG_TOML_FILE), "model = \"gpt-main\"").unwrap();    let selected_path = tmp.path().join("work.config.toml");    std::fs::write(&selected_path, "").unwrap();    let mut loader_overrides =        LoaderOverrides::with_managed_config_path_for_tests(tmp.path().join("managed_config.toml"));    loader_overrides.user_config_path =        Some(AbsolutePathBuf::from_absolute_path(&selected_path).expect("selected config path"));    loader_overrides.user_config_profile = Some("work".parse().expect("profile-v2 name"));    let service = ConfigManager::new_for_tests(        tmp.path().to_path_buf(),        vec![],        loader_overrides,        CloudConfigBundleLoader::default(),    );    service        .write_value(ConfigValueWriteParams {            file_path: None,            key_path: "model".to_string(),            value: serde_json::json!("gpt-work"),            merge_strategy: MergeStrategy::Replace,            expected_version: None,        })        .await        .expect("write succeeds");    assert_eq!(        std::fs::read_to_string(&selected_path).expect("read selected config"),        "model = \"gpt-work\"\n"    );    assert_eq!(        std::fs::read_to_string(tmp.path().join(CONFIG_TOML_FILE)).expect("read main config"),        "model = \"gpt-main\""    );}#[tokio::test]async fn load_default_config_preserves_selected_user_config_path_after_load_error() {    let tmp = tempdir().expect("tempdir");    std::fs::write(tmp.path().join(CONFIG_TOML_FILE), "model = \"gpt-main\"").unwrap();    let selected_path = tmp.path().join("work.config.toml");    std::fs::write(&selected_path, "not valid toml").unwrap();    let selected_file =        AbsolutePathBuf::from_absolute_path(&selected_path).expect("selected config path");    let mut loader_overrides =        LoaderOverrides::with_managed_config_path_for_tests(tmp.path().join("managed_config.toml"));    loader_overrides.user_config_path = Some(selected_file.clone());    loader_overrides.user_config_profile = Some("work".parse().expect("profile-v2 name"));    let service = ConfigManager::new_for_tests(        tmp.path().to_path_buf(),        vec![],        loader_overrides,        CloudConfigBundleLoader::default(),    );    service        .load_latest_config(/*fallback_cwd*/ None)        .await        .expect_err("selected config should fail to load");    let config = service        .load_default_config()        .await        .expect("default config loads after selected config error");    assert_eq!(        config.config_layer_stack.get_user_config_file(),        Some(&selected_file)    );}#[tokio::test]async fn invalid_user_value_rejected_even_if_overridden_by_managed() {    let tmp = tempdir().expect("tempdir");    std::fs::write(tmp.path().join(CONFIG_TOML_FILE), "model = \"user\"").unwrap();    let managed_path = tmp.path().join("managed_config.toml");    std::fs::write(&managed_path, "approval_policy = \"never\"").unwrap();    let service = ConfigManager::new_for_tests(        tmp.path().to_path_buf(),        vec![],        LoaderOverrides::with_managed_config_path_for_tests(managed_path.clone()),        CloudConfigBundleLoader::default(),    );    let error = service        .write_value(ConfigValueWriteParams {            file_path: Some(tmp.path().join(CONFIG_TOML_FILE).display().to_string()),            key_path: "approval_policy".to_string(),            value: serde_json::json!("bogus"),            merge_strategy: MergeStrategy::Replace,            expected_version: None,        })        .await        .expect_err("should fail validation");    assert_eq!(        error.write_error_code(),        Some(ConfigWriteErrorCode::ConfigValidationError)    );    let contents = std::fs::read_to_string(tmp.path().join(CONFIG_TOML_FILE)).expect("read config");    assert_eq!(contents.trim(), "model = \"user\"");}#[tokio::test]async fn reserved_builtin_provider_override_rejected() {    let tmp = tempdir().expect("tempdir");    std::fs::write(tmp.path().join(CONFIG_TOML_FILE), "model = \"user\"\n").unwrap();    let service = ConfigManager::without_managed_config_for_tests(tmp.path().to_path_buf());    let error = service        .write_value(ConfigValueWriteParams {            file_path: Some(tmp.path().join(CONFIG_TOML_FILE).display().to_string()),            key_path: "model_providers.openai.name".to_string(),            value: serde_json::json!("OpenAI Override"),            merge_strategy: MergeStrategy::Replace,            expected_version: None,        })        .await        .expect_err("should reject reserved provider override");    assert_eq!(        error.write_error_code(),        Some(ConfigWriteErrorCode::ConfigValidationError)    );    assert!(error.to_string().contains("reserved built-in provider IDs"));    assert!(error.to_string().contains("`openai`"));    let contents = std::fs::read_to_string(tmp.path().join(CONFIG_TOML_FILE)).expect("read config");    assert_eq!(contents, "model = \"user\"\n");}#[tokio::test]async fn write_value_rejects_feature_requirement_conflict() {    let tmp = tempdir().expect("tempdir");    std::fs::write(tmp.path().join(CONFIG_TOML_FILE), "").unwrap();    let service = ConfigManager::new_for_tests(        tmp.path().to_path_buf(),        vec![],        LoaderOverrides::without_managed_config_for_tests(),        CloudConfigBundleFixture::loader_with_enterprise_requirement(            r#"[features]personality = true"#,        ),    );    let error = service        .write_value(ConfigValueWriteParams {            file_path: Some(tmp.path().join(CONFIG_TOML_FILE).display().to_string()),            key_path: "features.personality".to_string(),            value: serde_json::json!(false),            merge_strategy: MergeStrategy::Replace,            expected_version: None,        })        .await        .expect_err("conflicting feature write should fail");    assert_eq!(        error.write_error_code(),        Some(ConfigWriteErrorCode::ConfigValidationError)    );    assert!(        error            .to_string()            .contains("invalid value for `features`: `features.personality=false`"),        "{error}"    );    assert_eq!(        std::fs::read_to_string(tmp.path().join(CONFIG_TOML_FILE)).unwrap(),        ""    );}#[tokio::test]async fn read_reports_managed_overrides_user_and_session_flags() {    let tmp = tempdir().expect("tempdir");    let user_path = tmp.path().join(CONFIG_TOML_FILE);    std::fs::write(&user_path, "model = \"user\"").unwrap();    let user_file = AbsolutePathBuf::try_from(user_path.clone()).expect("user file");    let managed_path = tmp.path().join("managed_config.toml");    std::fs::write(&managed_path, "model = \"system\"").unwrap();    let managed_file = AbsolutePathBuf::try_from(managed_path.clone()).expect("managed file");    let cli_overrides = vec![(        "model".to_string(),        TomlValue::String("session".to_string()),    )];    let service = ConfigManager::new_for_tests(        tmp.path().to_path_buf(),        cli_overrides,        LoaderOverrides::with_managed_config_path_for_tests(managed_path.clone()),        CloudConfigBundleLoader::default(),    );    let response = service        .read(ConfigReadParams {            include_layers: true,            cwd: None,        })        .await        .expect("response");    assert_eq!(response.config.model.as_deref(), Some("system"));    assert_eq!(        response.origins.get("model").expect("origin").name,        ConfigLayerSource::LegacyManagedConfigTomlFromFile {            file: managed_file.clone()        },    );    let layers = response.layers.expect("layers");    // Local macOS machines can surface an MDM-managed config layer at the    // top of the stack; ignore it so this test stays focused on file/session/user ordering.    let layers = if matches!(        layers.first().map(|layer| &layer.name),        Some(ConfigLayerSource::LegacyManagedConfigTomlFromMdm)    ) {        &layers[1..]    } else {        layers.as_slice()    };    assert_eq!(        layers.first().unwrap().name,        ConfigLayerSource::LegacyManagedConfigTomlFromFile { file: managed_file }    );    assert_eq!(layers.get(1).unwrap().name, ConfigLayerSource::SessionFlags);    assert_eq!(        layers.get(2).unwrap().name,        ConfigLayerSource::User {            file: user_file,            profile: None        }    );}#[tokio::test]async fn write_value_reports_managed_override() {    let tmp = tempdir().expect("tempdir");    std::fs::write(tmp.path().join(CONFIG_TOML_FILE), "").unwrap();    let managed_path = tmp.path().join("managed_config.toml");    std::fs::write(&managed_path, "approval_policy = \"never\"").unwrap();    let managed_file = AbsolutePathBuf::try_from(managed_path.clone()).expect("managed file");    let service = ConfigManager::new_for_tests(        tmp.path().to_path_buf(),        vec![],        LoaderOverrides::with_managed_config_path_for_tests(managed_path.clone()),        CloudConfigBundleLoader::default(),    );    let result = service        .write_value(ConfigValueWriteParams {            file_path: Some(tmp.path().join(CONFIG_TOML_FILE).display().to_string()),            key_path: "approval_policy".to_string(),            value: serde_json::json!("on-request"),            merge_strategy: MergeStrategy::Replace,            expected_version: None,        })        .await        .expect("result");    assert_eq!(result.status, WriteStatus::OkOverridden);    let overridden = result.overridden_metadata.expect("overridden metadata");    assert_eq!(        overridden.overriding_layer.name,        ConfigLayerSource::LegacyManagedConfigTomlFromFile { file: managed_file }    );    assert_eq!(overridden.effective_value, serde_json::json!("never"));}#[tokio::test]async fn upsert_merges_tables_replace_overwrites() -> Result<()> {    let tmp = tempdir().expect("tempdir");    let path = tmp.path().join(CONFIG_TOML_FILE);    let base = r#"[mcp_servers.linear]bearer_token_env_var = "TOKEN"name = "linear"url = "https://linear.example"[mcp_servers.linear.env_http_headers]existing = "keep"[mcp_servers.linear.http_headers]alpha = "a""#;    let overlay = serde_json::json!({        "bearer_token_env_var": "NEW_TOKEN",        "http_headers": {            "alpha": "updated",            "beta": "b"        },        "name": "linear",        "url": "https://linear.example"    });    std::fs::write(&path, base)?;    let service = ConfigManager::without_managed_config_for_tests(tmp.path().to_path_buf());    service        .write_value(ConfigValueWriteParams {            file_path: Some(path.display().to_string()),            key_path: "mcp_servers.linear".to_string(),            value: overlay.clone(),            merge_strategy: MergeStrategy::Upsert,            expected_version: None,        })        .await        .expect("upsert succeeds");    let upserted: TomlValue = toml::from_str(&std::fs::read_to_string(&path)?)?;    let expected_upsert: TomlValue = toml::from_str(        r#"[mcp_servers.linear]bearer_token_env_var = "NEW_TOKEN"name = "linear"url = "https://linear.example"[mcp_servers.linear.env_http_headers]existing = "keep"[mcp_servers.linear.http_headers]alpha = "updated"beta = "b""#,    )?;    assert_eq!(upserted, expected_upsert);    std::fs::write(&path, base)?;    service        .write_value(ConfigValueWriteParams {            file_path: Some(path.display().to_string()),            key_path: "mcp_servers.linear".to_string(),            value: overlay,            merge_strategy: MergeStrategy::Replace,            expected_version: None,        })        .await        .expect("replace succeeds");    let replaced: TomlValue = toml::from_str(&std::fs::read_to_string(&path)?)?;    let expected_replace: TomlValue = toml::from_str(        r#"[mcp_servers.linear]bearer_token_env_var = "NEW_TOKEN"name = "linear"url = "https://linear.example"[mcp_servers.linear.http_headers]alpha = "updated"beta = "b""#,    )?;    assert_eq!(replaced, expected_replace);    Ok(())}