mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
feat: add network proxy feature flag (#20147)
## Why The permissions migration is making `permissions.<profile>.network.enabled` the canonical sandbox network bit, while proxy startup is a separate concern. Enabling network access should not implicitly start the proxy, and users who are still on legacy sandbox modes need a separate place to opt into proxy startup and provide proxy-specific settings. This follow-up to #19900 gives the network proxy its own feature surface instead of overloading permission-profile network semantics. ## What changed - Add an experimental `network_proxy` feature with a configurable `[features.network_proxy]` table. - Overlay `features.network_proxy` settings onto the configured proxy state after permission-profile selection, so the proxy only starts when the active `NetworkSandboxPolicy` already allows network access. - Preserve `[experimental_network]` startup behavior independently of the new feature flag. ## Behavior and examples There are now three related knobs: - `permissions.<profile>.network.enabled` controls whether the active permission profile has network access at all. - `features.network_proxy` enables proxy restrictions for an already-network-enabled profile. - Legacy `sandbox_mode` plus `[sandbox_workspace_write].network_access` still control whether legacy `workspace-write` has network access at all. The rule is: - network off + proxy flag on -> network stays off, proxy is a no-op - network on + proxy flag off -> unrestricted direct network - network on + proxy flag on -> network stays on, with proxy restrictions applied For permission profiles, the feature toggle adds proxy restrictions only when network access is already enabled: ```toml default_permissions = "workspace" [permissions.workspace.filesystem] ":minimal" = "read" [permissions.workspace.network] enabled = true [features] network_proxy = true ``` If `network.enabled = false`, the same feature flag is a no-op: network remains off and the proxy does not start. For legacy sandbox config, `network_access` remains the master switch: ```toml sandbox_mode = "workspace-write" [sandbox_workspace_write] network_access = true [features] network_proxy = true ``` That keeps legacy `workspace-write` network access on, but routes it through the proxy policy. If `network_access = false`, the proxy feature is a no-op and legacy `workspace-write` remains offline. The same proxy opt-in can be supplied from the CLI: ```bash codex -c 'features.network_proxy=true' ``` Additional proxy settings can be supplied when a table is needed: ```bash codex \ -c 'features.network_proxy.enabled=true' \ -c 'features.network_proxy.enable_socks5=false' ``` The intended behavior matrix is: | Config surface | Network setting | `features.network_proxy` | Direct sandbox network | Proxy | | --- | --- | --- | --- | --- | | Permission profile | `network.enabled = false` | off | restricted | off | | Permission profile | `network.enabled = false` | on | restricted | off | | Permission profile | `network.enabled = true` | off | enabled | off | | Permission profile | `network.enabled = true` | on | enabled | on | | Legacy `workspace-write` | `network_access = false` | off | restricted | off | | Legacy `workspace-write` | `network_access = false` | on | restricted | off | | Legacy `workspace-write` | `network_access = true` | off | enabled | off | | Legacy `workspace-write` | `network_access = true` | on | enabled | on | `[experimental_network]` requirements remain separate from the user feature toggle and still start the proxy on their own. Relevant code: - [`features/src/feature_configs.rs`](https://github.com/openai/codex/blob/43785aff47/codex-rs/features/src/feature_configs.rs#L58-L117) defines the feature-specific proxy config. - [`core/src/config/mod.rs`](https://github.com/openai/codex/blob/43785aff47/codex-rs/core/src/config/mod.rs#L1959-L1964) reads the feature table, and [later applies it only when network access is already enabled](https://github.com/openai/codex/blob/43785aff47/codex-rs/core/src/config/mod.rs#L2448-L2458). ## Verification Added focused coverage for: - keeping the proxy off when `features.network_proxy` is enabled but sandbox network access is disabled - the full permission-profile and legacy `workspace-write` matrix above - preserving `[experimental_network]` startup without the feature - reusing profile-supplied proxy settings when the feature is enabled Ran: - `cargo test -p codex-features` - `cargo test -p codex-core network_proxy_feature` - `cargo test -p codex-core experimental_network_requirements_enable_proxy_without_feature`
This commit is contained in:
1 parent
54ec99cb54
commit
c7b55cdc46
10 files changed
+718
-124
No files matched your search
@@ -164,6 +164,19 @@ fn tool_suggest_is_stable_and_enabled_by_default() {
|
||||
assert_eq!(Feature::ToolSuggest.default_enabled(), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn network_proxy_is_experimental_and_disabled_by_default() {
|
||||
assert_eq!(
|
||||
feature_for_key("network_proxy"),
|
||||
Some(Feature::NetworkProxy)
|
||||
);
|
||||
assert!(matches!(
|
||||
Feature::NetworkProxy.stage(),
|
||||
Stage::Experimental { .. }
|
||||
));
|
||||
assert_eq!(Feature::NetworkProxy.default_enabled(), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tool_search_is_stable_and_enabled_by_default() {
|
||||
assert_eq!(Feature::ToolSearch.stage(), Stage::Stable);
|
||||
@@ -531,6 +544,7 @@ fn materialize_resolved_enabled_writes_all_features_and_preserves_custom_config(
|
||||
let mut features = Features::with_defaults();
|
||||
features.enable(Feature::CodeMode);
|
||||
features.enable(Feature::MultiAgentV2);
|
||||
features.enable(Feature::NetworkProxy);
|
||||
features.disable(Feature::ToolSearch);
|
||||
|
||||
let mut features_toml = FeaturesToml {
|
||||
@@ -539,6 +553,11 @@ fn materialize_resolved_enabled_writes_all_features_and_preserves_custom_config(
|
||||
min_wait_timeout_ms: Some(2500),
|
||||
..Default::default()
|
||||
})),
|
||||
network_proxy: Some(FeatureToml::Config(crate::NetworkProxyConfigToml {
|
||||
enabled: Some(false),
|
||||
proxy_url: Some("http://127.0.0.1:43128".to_string()),
|
||||
..Default::default()
|
||||
})),
|
||||
entries: BTreeMap::from([("include_apply_patch_tool".to_string(), true)]),
|
||||
..Default::default()
|
||||
};
|
||||
@@ -563,6 +582,14 @@ fn materialize_resolved_enabled_writes_all_features_and_preserves_custom_config(
|
||||
..Default::default()
|
||||
}))
|
||||
);
|
||||
assert_eq!(
|
||||
features_toml.network_proxy,
|
||||
Some(FeatureToml::Config(crate::NetworkProxyConfigToml {
|
||||
enabled: Some(true),
|
||||
proxy_url: Some("http://127.0.0.1:43128".to_string()),
|
||||
..Default::default()
|
||||
}))
|
||||
);
|
||||
let replayed = Features::from_sources(
|
||||
FeatureConfigSource {
|
||||
features: Some(&features_toml),
|
||||
|
||||
Reference in new issue
Block a user