typeduck-codex-async-utils 0.59.0

Support package for the standalone Codex Web runtime (codex-network-proxy)
Documentation
use pretty_assertions::assert_eq;

use super::RemoteNetworkProxyConfig;
use super::RemoteNetworkProxyLaunchConfig;
use crate::MitmHookConfig;
use crate::NetworkMode;
use crate::NetworkProxyAuditMetadata;
use crate::NetworkProxyConfig;
use crate::NetworkProxyState;

#[test]
fn round_trip_preserves_supported_effective_settings() {
    let mut config = NetworkProxyConfig {
        enabled: true,
        enable_socks5: false,
        enable_socks5_udp: false,
        allow_upstream_proxy: false,
        dangerously_allow_all_unix_sockets: true,
        mode: NetworkMode::Limited,
        allow_local_binding: true,
        ..NetworkProxyConfig::default()
    };
    config.set_allowed_domains(vec!["example.com".into()]);
    config.set_denied_domains(vec!["blocked.example.com".into()]);
    config.set_allow_unix_sockets(vec!["/var/run/example.sock".into()]);

    let remote =
        RemoteNetworkProxyConfig::from_effective_config(&config).expect("supported remote config");
    let round_trip = remote.into_network_proxy_config();

    assert_eq!(round_trip, config);
}

#[test]
fn rejects_unsupported_configuration() {
    let cases = [
        (
            "MITM",
            NetworkProxyConfig {
                enabled: true,
                mitm: true,
                ..NetworkProxyConfig::default()
            },
        ),
        (
            "credential broker",
            NetworkProxyConfig {
                enabled: true,
                credential_broker: true,
                ..NetworkProxyConfig::default()
            },
        ),
        (
            "plaintext credential injection",
            NetworkProxyConfig {
                enabled: true,
                dangerously_allow_plaintext_credential_injection: true,
                ..NetworkProxyConfig::default()
            },
        ),
        (
            "MITM hooks",
            NetworkProxyConfig {
                enabled: true,
                mitm_hooks: vec![MitmHookConfig::default()],
                ..NetworkProxyConfig::default()
            },
        ),
    ];

    for (feature, config) in cases {
        assert!(
            RemoteNetworkProxyConfig::from_effective_config(&config).is_err(),
            "{feature} must not cross the remote executor boundary"
        );
    }
}

#[test]
fn accepts_unsupported_configuration_when_proxy_is_disabled() {
    let config = NetworkProxyConfig {
        mitm: true,
        credential_broker: true,
        dangerously_allow_plaintext_credential_injection: true,
        mitm_hooks: vec![MitmHookConfig::default()],
        ..NetworkProxyConfig::default()
    };

    let remote = RemoteNetworkProxyConfig::from_effective_config(&config)
        .expect("disabled proxy configuration does not cross the executor boundary");

    assert!(!remote.enabled);
}

#[test]
fn launch_config_materializes_audit_and_execution_attribution() {
    let proxy = RemoteNetworkProxyConfig::from_effective_config(&NetworkProxyConfig {
        enabled: true,
        ..NetworkProxyConfig::default()
    })
    .expect("supported remote config");
    let audit_metadata = NetworkProxyAuditMetadata {
        conversation_id: Some("conversation-1".to_string()),
        user_account_id: Some("account-1".to_string()),
        originator: Some("codex_cli_rs".to_string()),
        model: Some("model-1".to_string()),
        ..NetworkProxyAuditMetadata::default()
    };
    let state = NetworkProxyState::from_remote_launch_config(RemoteNetworkProxyLaunchConfig {
        proxy,
        audit_metadata: audit_metadata.clone(),
        environment_id: Some("remote".to_string()),
        execution_id: Some("execution-1".to_string()),
    })
    .expect("remote launch state");

    assert_eq!(state.audit_metadata(), &audit_metadata);
    assert_eq!(state.environment_id(), Some("remote"));
    assert_eq!(state.execution_id().as_deref(), Some("execution-1"));
}

#[test]
fn policy_decision_callback_opt_in_is_backward_compatible() {
    let mut config =
        RemoteNetworkProxyConfig::from_effective_config(&NetworkProxyConfig::default())
            .expect("supported remote config");
    let legacy = serde_json::to_value(&config).expect("serialize legacy config");
    assert_eq!(legacy.get("requestPolicyDecisions"), None);
    assert!(
        !serde_json::from_value::<RemoteNetworkProxyConfig>(legacy)
            .expect("deserialize legacy remote config")
            .request_policy_decisions
    );

    config.request_policy_decisions = true;
    let enabled = serde_json::to_value(&config).expect("serialize callback-enabled config");
    assert_eq!(enabled["requestPolicyDecisions"], true);
    assert_eq!(
        serde_json::from_value::<RemoteNetworkProxyConfig>(enabled)
            .expect("deserialize callback-enabled config"),
        config
    );
}