From 862ab630714c792cba908e08d8286cec9e064ef5 Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Mon, 9 Feb 2026 19:26:39 -0800 Subject: [PATCH] chore: change ConfigState so it no longer depends on a single config.toml file for reloading (#11262) If anything, it should depend on `ConfigLayerStack`. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/11262). * #11207 * __->__ #11262 --- codex-rs/core/src/network_proxy_loader.rs | 7 +++- codex-rs/network-proxy/src/runtime.rs | 46 ++++++++++++----------- codex-rs/network-proxy/src/state.rs | 3 -- 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/codex-rs/core/src/network_proxy_loader.rs b/codex-rs/core/src/network_proxy_loader.rs index cafe05a0c..3e0645274 100644 --- a/codex-rs/core/src/network_proxy_loader.rs +++ b/codex-rs/core/src/network_proxy_loader.rs @@ -47,7 +47,6 @@ async fn build_config_state_with_mtimes() -> Result<(ConfigState, Vec Result<(ConfigState, Vec String { + "config layers".to_string() + } + async fn maybe_reload(&self) -> Result> { if !self.needs_reload().await { return Ok(None); diff --git a/codex-rs/network-proxy/src/runtime.rs b/codex-rs/network-proxy/src/runtime.rs index a1ab34757..029c7b5f6 100644 --- a/codex-rs/network-proxy/src/runtime.rs +++ b/codex-rs/network-proxy/src/runtime.rs @@ -22,7 +22,6 @@ use std::collections::HashSet; use std::collections::VecDeque; use std::net::IpAddr; use std::path::Path; -use std::path::PathBuf; use std::sync::Arc; use std::time::Duration; use time::OffsetDateTime; @@ -112,12 +111,14 @@ pub struct ConfigState { pub allow_set: GlobSet, pub deny_set: GlobSet, pub constraints: NetworkProxyConstraints, - pub cfg_path: PathBuf, pub blocked: VecDeque, } #[async_trait] pub trait ConfigReloader: Send + Sync { + /// Human-readable description of where config is loaded from, for logs. + fn source_label(&self) -> String; + /// Return a freshly loaded state if a reload is needed; otherwise, return `None`. async fn maybe_reload(&self) -> Result>; @@ -179,9 +180,9 @@ impl NetworkProxyState { } pub async fn force_reload(&self) -> Result<()> { - let (previous_cfg, cfg_path) = { + let previous_cfg = { let guard = self.state.read().await; - (guard.config.clone(), guard.cfg_path.clone()) + guard.config.clone() }; match self.reloader.reload_now().await { @@ -189,16 +190,18 @@ impl NetworkProxyState { // Policy changes are operationally sensitive; logging diffs makes changes traceable // without needing to dump full config blobs (which can include unrelated settings). log_policy_changes(&previous_cfg, &new_state.config); - let mut guard = self.state.write().await; - new_state.blocked = guard.blocked.clone(); - *guard = new_state; - let path = guard.cfg_path.display(); - info!("reloaded config from {path}"); + { + let mut guard = self.state.write().await; + new_state.blocked = guard.blocked.clone(); + *guard = new_state; + } + let source = self.reloader.source_label(); + info!("reloaded config from {source}"); Ok(()) } Err(err) => { - let path = cfg_path.display(); - warn!("failed to reload config from {path}: {err}; keeping previous config"); + let source = self.reloader.source_label(); + warn!("failed to reload config from {source}: {err}; keeping previous config"); Err(err) } } @@ -383,10 +386,12 @@ impl NetworkProxyState { }; log_policy_changes(&previous_cfg, &new_state.config); new_state.blocked = blocked; - let mut guard = self.state.write().await; - *guard = new_state; - let path = guard.cfg_path.display(); - info!("reloaded config from {path}"); + { + let mut guard = self.state.write().await; + *guard = new_state; + } + let source = self.reloader.source_label(); + info!("reloaded config from {source}"); Ok(()) } } @@ -493,12 +498,7 @@ pub(crate) fn network_proxy_state_for_policy( network.enabled = true; network.mode = NetworkMode::Full; let config = NetworkProxyConfig { network }; - let state = build_config_state( - config, - NetworkProxyConstraints::default(), - PathBuf::from("/nonexistent/config.toml"), - ) - .unwrap(); + let state = build_config_state(config, NetworkProxyConstraints::default()).unwrap(); NetworkProxyState::with_reloader(state, Arc::new(NoopReloader)) } @@ -509,6 +509,10 @@ struct NoopReloader; #[cfg(test)] #[async_trait] impl ConfigReloader for NoopReloader { + fn source_label(&self) -> String { + "test config state".to_string() + } + async fn maybe_reload(&self) -> Result> { Ok(None) } diff --git a/codex-rs/network-proxy/src/state.rs b/codex-rs/network-proxy/src/state.rs index 99009e76a..509ada760 100644 --- a/codex-rs/network-proxy/src/state.rs +++ b/codex-rs/network-proxy/src/state.rs @@ -5,7 +5,6 @@ use crate::policy::compile_globset; use crate::runtime::ConfigState; use serde::Deserialize; use std::collections::HashSet; -use std::path::PathBuf; pub use crate::runtime::BlockedRequest; pub use crate::runtime::BlockedRequestArgs; @@ -52,7 +51,6 @@ pub struct PartialNetworkConfig { pub fn build_config_state( config: NetworkProxyConfig, constraints: NetworkProxyConstraints, - cfg_path: PathBuf, ) -> anyhow::Result { let deny_set = compile_globset(&config.network.denied_domains)?; let allow_set = compile_globset(&config.network.allowed_domains)?; @@ -61,7 +59,6 @@ pub fn build_config_state( allow_set, deny_set, constraints, - cfg_path, blocked: std::collections::VecDeque::new(), }) }