Codex Handbook
core/src/config/network_proxy_spec_tests.rs 471 lines
use super::*;use codex_config::NetworkDomainPermissionToml;use codex_config::NetworkDomainPermissionsToml;use codex_network_proxy::NetworkDomainPermission;use codex_protocol::models::ManagedFileSystemPermissions;use codex_protocol::models::PermissionProfile;use codex_protocol::permissions::NetworkSandboxPolicy;use pretty_assertions::assert_eq;fn domain_permissions(    entries: impl IntoIterator<Item = (&'static str, NetworkDomainPermissionToml)>,) -> NetworkDomainPermissionsToml {    NetworkDomainPermissionsToml {        entries: entries            .into_iter()            .map(|(pattern, permission)| (pattern.to_string(), permission))            .collect(),    }}#[test]fn build_state_with_audit_metadata_threads_metadata_to_state() {    let spec = NetworkProxySpec {        base_config: NetworkProxyConfig::default(),        requirements: None,        config: NetworkProxyConfig::default(),        constraints: NetworkProxyConstraints::default(),        hard_deny_allowlist_misses: false,    };    let metadata = NetworkProxyAuditMetadata {        conversation_id: Some("conversation-1".to_string()),        app_version: Some("1.2.3".to_string()),        user_account_id: Some("acct-1".to_string()),        ..NetworkProxyAuditMetadata::default()    };    let state = spec        .build_state_with_audit_metadata(metadata.clone())        .expect("state should build");    assert_eq!(state.audit_metadata(), &metadata);}#[test]fn requirements_allowed_domains_are_a_baseline_for_user_allowlist() {    let mut config = NetworkProxyConfig::default();    config        .network        .set_allowed_domains(vec!["api.example.com".to_string()]);    let requirements = NetworkConstraints {        domains: Some(domain_permissions([(            "*.example.com",            NetworkDomainPermissionToml::Allow,        )])),        ..Default::default()    };    let spec = NetworkProxySpec::from_config_and_constraints(        config,        Some(requirements),        &PermissionProfile::read_only(),    )    .expect("config should stay within the managed allowlist");    assert_eq!(        spec.config.network.allowed_domains(),        Some(vec![            "*.example.com".to_string(),            "api.example.com".to_string()        ])    );    assert_eq!(        spec.constraints.allowed_domains,        Some(vec!["*.example.com".to_string()])    );    assert_eq!(spec.constraints.allowlist_expansion_enabled, Some(true));}#[test]fn requirements_allowed_domains_do_not_override_user_denies_for_same_pattern() {    let mut config = NetworkProxyConfig::default();    config        .network        .set_denied_domains(vec!["api.example.com".to_string()]);    let requirements = NetworkConstraints {        domains: Some(domain_permissions([(            "api.example.com",            NetworkDomainPermissionToml::Allow,        )])),        ..Default::default()    };    let spec = NetworkProxySpec::from_config_and_constraints(        config,        Some(requirements),        &PermissionProfile::workspace_write(),    )    .expect("managed allowlist should not erase a user deny");    assert_eq!(spec.config.network.allowed_domains(), None);    assert_eq!(        spec.config.network.denied_domains(),        Some(vec!["api.example.com".to_string()])    );    assert_eq!(        spec.constraints.allowed_domains,        Some(vec!["api.example.com".to_string()])    );}#[test]fn requirements_allowlist_expansion_keeps_user_entries_mutable() {    let mut config = NetworkProxyConfig::default();    config        .network        .set_allowed_domains(vec!["api.example.com".to_string()]);    let requirements = NetworkConstraints {        domains: Some(domain_permissions([(            "*.example.com",            NetworkDomainPermissionToml::Allow,        )])),        ..Default::default()    };    let spec = NetworkProxySpec::from_config_and_constraints(        config,        Some(requirements),        &PermissionProfile::workspace_write(),    )    .expect("managed baseline should still allow user edits");    let mut candidate = spec.config.clone();    candidate.network.upsert_domain_permission(        "api.example.com".to_string(),        NetworkDomainPermission::Deny,        normalize_host,    );    assert_eq!(        candidate.network.allowed_domains(),        Some(vec!["*.example.com".to_string()])    );    assert_eq!(        candidate.network.denied_domains(),        Some(vec!["api.example.com".to_string()])    );    validate_policy_against_constraints(&candidate, &spec.constraints)        .expect("user allowlist entries should not become managed constraints");}#[test]fn managed_unrestricted_profile_allows_domain_expansion() {    let mut config = NetworkProxyConfig::default();    config        .network        .set_allowed_domains(vec!["api.example.com".to_string()]);    let requirements = NetworkConstraints {        domains: Some(domain_permissions([(            "*.example.com",            NetworkDomainPermissionToml::Allow,        )])),        ..Default::default()    };    let permission_profile = PermissionProfile::Managed {        file_system: ManagedFileSystemPermissions::Unrestricted,        network: NetworkSandboxPolicy::Restricted,    };    let spec = NetworkProxySpec::from_config_and_constraints(        config,        Some(requirements),        &permission_profile,    )    .expect("managed unrestricted filesystem should still use managed network constraints");    assert_eq!(        spec.config.network.allowed_domains(),        Some(vec![            "*.example.com".to_string(),            "api.example.com".to_string()        ])    );    assert_eq!(spec.constraints.allowlist_expansion_enabled, Some(true));}#[test]fn danger_full_access_keeps_managed_allowlist_and_denylist_fixed() {    let mut config = NetworkProxyConfig::default();    config        .network        .set_allowed_domains(vec!["evil.com".to_string()]);    config        .network        .set_denied_domains(vec!["more-blocked.example.com".to_string()]);    let requirements = NetworkConstraints {        domains: Some(domain_permissions([            ("*.example.com", NetworkDomainPermissionToml::Allow),            ("blocked.example.com", NetworkDomainPermissionToml::Deny),        ])),        ..Default::default()    };    let spec = NetworkProxySpec::from_config_and_constraints(        config,        Some(requirements),        &PermissionProfile::Disabled,    )    .expect("yolo mode should pin the effective policy to the managed baseline");    assert_eq!(        spec.config.network.allowed_domains(),        Some(vec!["*.example.com".to_string()])    );    assert_eq!(        spec.config.network.denied_domains(),        Some(vec!["blocked.example.com".to_string()])    );    assert_eq!(spec.constraints.allowlist_expansion_enabled, Some(false));    assert_eq!(spec.constraints.denylist_expansion_enabled, Some(false));}#[test]fn managed_allowed_domains_only_disables_default_mode_allowlist_expansion() {    let mut config = NetworkProxyConfig::default();    config        .network        .set_allowed_domains(vec!["api.example.com".to_string()]);    let requirements = NetworkConstraints {        domains: Some(domain_permissions([(            "*.example.com",            NetworkDomainPermissionToml::Allow,        )])),        managed_allowed_domains_only: Some(true),        ..Default::default()    };    let spec = NetworkProxySpec::from_config_and_constraints(        config,        Some(requirements),        &PermissionProfile::workspace_write(),    )    .expect("managed baseline should still load");    assert_eq!(        spec.config.network.allowed_domains(),        Some(vec!["*.example.com".to_string()])    );    assert_eq!(spec.constraints.allowlist_expansion_enabled, Some(false));}#[test]fn managed_allowed_domains_only_ignores_user_allowlist_and_hard_denies_misses() {    let mut config = NetworkProxyConfig::default();    config        .network        .set_allowed_domains(vec!["api.example.com".to_string()]);    let requirements = NetworkConstraints {        domains: Some(domain_permissions([(            "managed.example.com",            NetworkDomainPermissionToml::Allow,        )])),        managed_allowed_domains_only: Some(true),        ..Default::default()    };    let spec = NetworkProxySpec::from_config_and_constraints(        config,        Some(requirements),        &PermissionProfile::workspace_write(),    )    .expect("managed-only allowlist should still load");    assert_eq!(        spec.config.network.allowed_domains(),        Some(vec!["managed.example.com".to_string()])    );    assert_eq!(        spec.constraints.allowed_domains,        Some(vec!["managed.example.com".to_string()])    );    assert_eq!(spec.constraints.allowlist_expansion_enabled, Some(false));    assert!(spec.hard_deny_allowlist_misses);}#[test]fn managed_allowed_domains_only_without_managed_allowlist_blocks_all_user_domains() {    let mut config = NetworkProxyConfig::default();    config        .network        .set_allowed_domains(vec!["api.example.com".to_string()]);    let requirements = NetworkConstraints {        managed_allowed_domains_only: Some(true),        ..Default::default()    };    let spec = NetworkProxySpec::from_config_and_constraints(        config,        Some(requirements),        &PermissionProfile::workspace_write(),    )    .expect("managed-only mode should treat missing managed allowlist as empty");    assert_eq!(spec.config.network.allowed_domains(), None);    assert_eq!(spec.constraints.allowed_domains, Some(Vec::new()));    assert_eq!(spec.constraints.allowlist_expansion_enabled, Some(false));    assert!(spec.hard_deny_allowlist_misses);}#[test]fn managed_allowed_domains_only_blocks_all_user_domains_in_full_access_without_managed_list() {    let mut config = NetworkProxyConfig::default();    config        .network        .set_allowed_domains(vec!["api.example.com".to_string()]);    let requirements = NetworkConstraints {        managed_allowed_domains_only: Some(true),        ..Default::default()    };    let spec = NetworkProxySpec::from_config_and_constraints(        config,        Some(requirements),        &PermissionProfile::Disabled,    )    .expect("managed-only mode should treat missing managed allowlist as empty");    assert_eq!(spec.config.network.allowed_domains(), None);    assert_eq!(spec.constraints.allowed_domains, Some(Vec::new()));    assert_eq!(spec.constraints.allowlist_expansion_enabled, Some(false));    assert!(spec.hard_deny_allowlist_misses);}#[test]fn deny_only_requirements_do_not_create_allow_constraints_in_full_access() {    let mut config = NetworkProxyConfig::default();    config        .network        .set_allowed_domains(vec!["api.example.com".to_string()]);    let requirements = NetworkConstraints {        domains: Some(domain_permissions([(            "managed-blocked.example.com",            NetworkDomainPermissionToml::Deny,        )])),        ..Default::default()    };    let spec = NetworkProxySpec::from_config_and_constraints(        config,        Some(requirements),        &PermissionProfile::Disabled,    )    .expect("deny-only requirements should not constrain the allowlist");    assert_eq!(        spec.config.network.allowed_domains(),        Some(vec!["api.example.com".to_string()])    );    assert_eq!(spec.constraints.allowed_domains, None);    assert_eq!(spec.constraints.allowlist_expansion_enabled, None);    assert_eq!(        spec.config.network.denied_domains(),        Some(vec!["managed-blocked.example.com".to_string()])    );}#[test]fn allow_only_requirements_do_not_create_deny_constraints_in_full_access() {    let mut config = NetworkProxyConfig::default();    config        .network        .set_denied_domains(vec!["blocked.example.com".to_string()]);    let requirements = NetworkConstraints {        domains: Some(domain_permissions([(            "managed.example.com",            NetworkDomainPermissionToml::Allow,        )])),        ..Default::default()    };    let spec = NetworkProxySpec::from_config_and_constraints(        config,        Some(requirements),        &PermissionProfile::Disabled,    )    .expect("allow-only requirements should not constrain the denylist");    assert_eq!(        spec.config.network.allowed_domains(),        Some(vec!["managed.example.com".to_string()])    );    assert_eq!(        spec.config.network.denied_domains(),        Some(vec!["blocked.example.com".to_string()])    );    assert_eq!(spec.constraints.denied_domains, None);    assert_eq!(spec.constraints.denylist_expansion_enabled, None);}#[test]fn requirements_denied_domains_are_a_baseline_for_default_mode() {    let mut config = NetworkProxyConfig::default();    config        .network        .set_denied_domains(vec!["blocked.example.com".to_string()]);    let requirements = NetworkConstraints {        domains: Some(domain_permissions([(            "managed-blocked.example.com",            NetworkDomainPermissionToml::Deny,        )])),        ..Default::default()    };    let spec = NetworkProxySpec::from_config_and_constraints(        config,        Some(requirements),        &PermissionProfile::workspace_write(),    )    .expect("default mode should merge managed and user deny entries");    assert_eq!(        spec.config.network.denied_domains(),        Some(vec![            "managed-blocked.example.com".to_string(),            "blocked.example.com".to_string()        ])    );    assert_eq!(        spec.constraints.denied_domains,        Some(vec!["managed-blocked.example.com".to_string()])    );    assert_eq!(spec.constraints.denylist_expansion_enabled, Some(true));}#[test]fn requirements_denylist_expansion_keeps_user_entries_mutable() {    let mut config = NetworkProxyConfig::default();    config        .network        .set_denied_domains(vec!["blocked.example.com".to_string()]);    let requirements = NetworkConstraints {        domains: Some(domain_permissions([(            "managed-blocked.example.com",            NetworkDomainPermissionToml::Deny,        )])),        ..Default::default()    };    let spec = NetworkProxySpec::from_config_and_constraints(        config,        Some(requirements),        &PermissionProfile::workspace_write(),    )    .expect("managed baseline should still allow user edits");    let mut candidate = spec.config.clone();    candidate.network.upsert_domain_permission(        "blocked.example.com".to_string(),        NetworkDomainPermission::Allow,        normalize_host,    );    assert_eq!(        candidate.network.allowed_domains(),        Some(vec!["blocked.example.com".to_string()])    );    assert_eq!(        candidate.network.denied_domains(),        Some(vec!["managed-blocked.example.com".to_string()])    );    validate_policy_against_constraints(&candidate, &spec.constraints)        .expect("user denylist entries should not become managed constraints");}