Files
codex/codex-rs/cloud-config/src/validation_tests.rs
T
viyatb-oai dfcb5b5994 Support managed network requirements under permissions.network (#58182)
## What changed

Allow shared network constraints in `[permissions.network]` in `requirements.toml`, alongside `[permissions.filesystem]`. Apply them throughout configuration loading, network approvals, Windows sandbox policy validation, and `configRequirements/read`, and show their source in `/debug-config`.

Retain `[network_proxy]` and `[experimental_network]`, but reject mixing either with `[permissions.network]`, even across requirements layers. Preserve independent network and filesystem precedence and source attribution, and report unknown nested network fields.

Reserve `network` as a managed requirements table name and reject empty or profile-shaped tables with migration guidance. Profiles named `network` remain valid in `config.toml`. Document that policy publishers must keep using `[experimental_network]` until all readers support the chosen replacement.

## Testing

Add coverage for layered constraints and source attribution, conflicting spellings, profile-name migration errors, unknown-field diagnostics, and cloud validation. Extend API, project discovery, network approval, and Windows policy tests to cover `[permissions.network]`, and verify managed proxy settings remain independent of disabled feature configuration.

GitOrigin-RevId: 994dfca9abf5a7aea914276c0ded8b40d7ed0372
2026-10-29 22:36:06 +00:00

79 lines
3.0 KiB
Rust

use super::*;
use codex_config::CloudRequirementsFragment;
use pretty_assertions::assert_eq;
use tempfile::tempdir;
#[test]
fn cloud_validation_rejects_mixed_network_requirements() {
let home = tempdir().expect("tempdir");
let base_dir = AbsolutePathBuf::from_absolute_path(home.path()).expect("absolute path");
let mut bundle = CloudConfigBundle::default();
for alias in ["experimental_network", "network_proxy"] {
let nested = "[permissions.network]\nenabled = false";
let top_level = format!("[{alias}]\nenabled = false");
for contents in [
vec![format!("{nested}\n{top_level}")],
vec![nested.to_owned(), top_level],
] {
bundle.requirements_toml.enterprise_managed = contents
.into_iter()
.enumerate()
.map(|(index, contents)| CloudRequirementsFragment {
id: index.to_string(),
name: index.to_string(),
contents,
})
.collect();
let err = validate_bundle(&bundle, &base_dir).expect_err("mixed policy spellings");
assert_eq!(err.code(), CloudConfigBundleLoadErrorCode::InvalidBundle);
}
}
}
#[test]
fn cloud_fragments_combine_before_provider_validation() {
let home = tempdir().expect("tempdir");
let base_dir = AbsolutePathBuf::from_absolute_path(home.path()).expect("absolute path");
let mut bundle = CloudConfigBundle::default();
// Cloud fragments arrive highest-priority first.
bundle.requirements_toml.enterprise_managed = vec![
CloudRequirementsFragment {
id: "high".to_string(),
name: "URL".to_string(),
contents: "[model_providers.gateway]\nbase_url = 'https://gateway.example/v1'\n[model_providers.gateway.auth]\ntimeout_ms = 10000\ncwd = 'auth'"
.to_string(),
},
CloudRequirementsFragment {
id: "low".to_string(),
name: "Name".to_string(),
contents: "[model_providers.gateway]\nname = 'Gateway'\n[model_providers.gateway.auth]\ncommand = 'get-token'".to_string(),
},
];
assert_eq!(validate_bundle(&bundle, &base_dir), Ok(()));
}
#[test]
fn cloud_bedrock_overrides_accept_supported_fields() {
let home = tempdir().expect("tempdir");
let base_dir = AbsolutePathBuf::from_absolute_path(home.path()).expect("absolute path");
for provider in ["amazon-bedrock", "amazon-bedrock-runtime"] {
let mut bundle = CloudConfigBundle::default();
bundle.requirements_toml.enterprise_managed = vec![CloudRequirementsFragment {
id: "bedrock".to_string(),
name: "Bedrock".to_string(),
contents: format!(
r#"
[model_providers.{provider}]
base_url = "https://bedrock.example"
[model_providers.{provider}.http_headers]
X-Managed = "required"
[model_providers.{provider}.aws]
profile = "managed"
region = "us-east-1"
"#
),
}];
assert_eq!(validate_bundle(&bundle, &base_dir), Ok(()));
}
}