Fix shell filter override reporting

This commit is contained in:
Abhinav Vedmala
2026-06-16 23:54:34 +00:00
parent 84f259737e
commit 8cec5f1a63
2 changed files with 87 additions and 3 deletions
@@ -616,6 +616,26 @@ fn value_at_path<'a>(root: &'a TomlValue, segments: &[String]) -> Option<&'a Tom
Some(current)
}
/// Looks up a path according to its config semantics.
///
/// Shell filter patterns compare case-insensitively and are normalized in the
/// merged effective config, while raw layers preserve their original spelling.
/// Match that path segment case-insensitively so equivalent raw and effective
/// paths compare without changing ordinary TOML path semantics.
fn value_at_semantic_path<'a>(root: &'a TomlValue, segments: &[String]) -> Option<&'a TomlValue> {
let [policy, filters, pattern] = segments else {
return value_at_path(root, segments);
};
if policy != "shell_environment_policy" || filters != "filters" {
return value_at_path(root, segments);
}
let filters = value_at_path(root, &segments[..2])?.as_table()?;
filters
.iter()
.find_map(|(candidate, value)| candidate.eq_ignore_ascii_case(pattern).then_some(value))
}
fn override_message(layer: &ConfigLayerSource) -> String {
match layer {
ConfigLayerSource::Mdm { domain, key: _ } => {
@@ -653,10 +673,10 @@ fn compute_override_metadata(
segments: &[String],
) -> Option<OverriddenMetadata> {
let user_value = match layers.get_active_user_layer() {
Some(user_layer) => value_at_path(&user_layer.config, segments),
Some(user_layer) => value_at_semantic_path(&user_layer.config, segments),
None => return None,
};
let effective_value = value_at_path(effective, segments);
let effective_value = value_at_semantic_path(effective, segments);
if user_value.is_some() && user_value == effective_value {
return None;
@@ -696,7 +716,9 @@ fn find_effective_layer(
segments: &[String],
) -> Option<ConfigLayerMetadata> {
for layer in layers.layers_high_to_low() {
if let Some(meta) = value_at_path(&layer.config, segments).map(|_| layer.metadata()) {
if let Some(meta) =
value_at_semantic_path(&layer.config, segments).map(|_| layer.metadata())
{
return Some(meta);
}
}
@@ -841,6 +841,68 @@ async fn write_value_reports_managed_override() {
assert_eq!(overridden.effective_value, serde_json::json!("never"));
}
#[tokio::test]
async fn write_value_matches_shell_filter_paths_case_insensitively() -> Result<()> {
let tmp = tempdir()?;
let config_path = tmp.path().join(CONFIG_TOML_FILE);
std::fs::write(&config_path, "")?;
let service = ConfigManager::without_managed_config_for_tests(tmp.path().to_path_buf());
let result = service
.write_value(ConfigValueWriteParams {
file_path: Some(config_path.display().to_string()),
key_path: "shell_environment_policy.filters.PATH".to_string(),
value: serde_json::json!("include"),
merge_strategy: MergeStrategy::Replace,
expected_version: None,
})
.await?;
assert_eq!(result.status, WriteStatus::Ok);
assert_eq!(result.overridden_metadata, None);
assert!(std::fs::read_to_string(config_path)?.contains("PATH = \"include\""));
Ok(())
}
#[tokio::test]
async fn write_value_reports_case_insensitive_shell_filter_override() -> Result<()> {
let tmp = tempdir()?;
let config_path = tmp.path().join(CONFIG_TOML_FILE);
std::fs::write(&config_path, "")?;
let managed_path = tmp.path().join("managed_config.toml");
std::fs::write(
&managed_path,
"[shell_environment_policy.filters]\npath = \"exclude\"\n",
)?;
let managed_file = AbsolutePathBuf::try_from(managed_path.clone())?;
let service = ConfigManager::new_for_tests(
tmp.path().to_path_buf(),
vec![],
LoaderOverrides::with_managed_config_path_for_tests(managed_path),
CloudConfigBundleLoader::default(),
);
let result = service
.write_value(ConfigValueWriteParams {
file_path: Some(config_path.display().to_string()),
key_path: "shell_environment_policy.filters.PATH".to_string(),
value: serde_json::json!("include"),
merge_strategy: MergeStrategy::Replace,
expected_version: None,
})
.await?;
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!("exclude"));
Ok(())
}
#[tokio::test]
async fn upsert_merges_tables_replace_overwrites() -> Result<()> {
let tmp = tempdir().expect("tempdir");