mirror of
https://github.com/openai/codex.git
synced 2026-11-13 21:30:47 +00:00
## Why Completed remote commands wait up to 100 ms for late network denials even when all execution-owned network decision callbacks and requests have finished. ## What changed Allow deferred network approval cleanup to finish as soon as an executor-owned remote proxy's decisions drain. Retain the grace period when a shared listener could still report an untagged denial, including when that listener starts during the command. Always register the blocked-request observer when starting the session proxy. ## Testing Extend the paused-time regression test to cover immediate completion after remote callbacks drain and propagation of a late denial from a newly registered shared listener. GitOrigin-RevId: 41bda6504f6d97d5626beba58cf30fb4a9a2dbdd
65 lines
2.4 KiB
Rust
65 lines
2.4 KiB
Rust
use super::*;
|
|
|
|
pub(super) struct ExecutionScope {
|
|
pub(super) environment_id: String,
|
|
pub(super) execution_id: String,
|
|
pub(super) attribution_token: String,
|
|
pub(super) environment_policy: Option<crate::EnvironmentNetworkPolicy>,
|
|
// Dropping the execution scope closes this channel and cancels remote reviews.
|
|
pub(super) lifetime_tx: tokio::sync::watch::Sender<()>,
|
|
state: Arc<NetworkProxyState>,
|
|
}
|
|
|
|
impl Drop for ExecutionScope {
|
|
fn drop(&mut self) {
|
|
self.state.unregister_execution(&self.attribution_token);
|
|
}
|
|
}
|
|
|
|
impl NetworkProxy {
|
|
/// Waits until every remote decision callback and in-flight request for this
|
|
/// execution has been dropped. Call after the executor has started, when no
|
|
/// further callbacks will be installed for this scope. An unscoped proxy
|
|
/// cannot establish this boundary, so its wait remains pending.
|
|
pub async fn wait_for_remote_policy_deciders(&self) {
|
|
match &self.execution_scope {
|
|
Some(scope) => scope.lifetime_tx.closed().await,
|
|
None => std::future::pending().await,
|
|
}
|
|
}
|
|
|
|
/// Returns a proxy with execution-specific attribution and attachment policy.
|
|
pub fn for_execution(
|
|
&self,
|
|
environment_id: &str,
|
|
execution_id: &str,
|
|
attribution_token: String,
|
|
environment_policy: Option<crate::EnvironmentNetworkPolicy>,
|
|
fallback_policy_decider: Option<Arc<dyn NetworkPolicyDecider>>,
|
|
) -> Result<Self> {
|
|
anyhow::ensure!(
|
|
self.execution_scope.is_none(),
|
|
"cannot scope an execution-scoped network proxy"
|
|
);
|
|
self.state
|
|
.register_execution(&attribution_token, environment_id, execution_id);
|
|
|
|
let (lifetime_tx, _) = tokio::sync::watch::channel(());
|
|
let mut proxy = self.clone();
|
|
proxy.policy_decider = proxy.policy_decider.or(fallback_policy_decider);
|
|
// Strict attachment allowlists cannot be expanded through approval callbacks.
|
|
if matches!(&environment_policy, Some(policy) if policy.managed_allowed_domains_only) {
|
|
proxy.policy_decider = None;
|
|
}
|
|
proxy.execution_scope = Some(Arc::new(ExecutionScope {
|
|
environment_id: environment_id.to_string(),
|
|
execution_id: execution_id.to_string(),
|
|
attribution_token,
|
|
environment_policy,
|
|
lifetime_tx,
|
|
state: Arc::clone(&self.state),
|
|
}));
|
|
Ok(proxy)
|
|
}
|
|
}
|