Files
codex/codex-rs/network-proxy/src/request_cancellation.rs
jif 8e85265c39 Handle pending network reviews after process completion (#42746)
## Why

A remote process can finish while a network policy review is still pending. Normal process cleanup should withdraw that review without turning the completed command into a review failure or losing its output.

## What changed

- Record whether a network policy request was withdrawn because the process finished, was cancelled, lost its executor connection, or timed out.
- Treat normal process completion as cleanup while retaining fail-closed behavior for other cancellation causes.
- Preserve explicit network denials before policy persistence so cleanup cannot replace the reported call outcome.

## Testing

Add an integration test that completes a remote process during a pending network review and verifies that the command reports its successful exit and output without approving the withdrawn request.

GitOrigin-RevId: 7f42d75631ee29eba43bf04cc953eea490f553fc
2026-09-04 12:08:02 +00:00

33 lines
1.1 KiB
Rust

//! Records why a policy request was withdrawn before its decision future is dropped.
use std::sync::Arc;
use std::sync::OnceLock;
/// The controller's first known reason for withdrawing a policy request.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum NetworkRequestCancellationReason {
/// The process exited and its output streams closed normally.
ProcessFinished,
/// The process was explicitly terminated or its handle was abandoned.
ProcessCancelled,
/// The connection to the executor was lost.
ConnectionClosed,
/// The policy decision deadline expired.
TimedOut,
}
/// Shared, in-process metadata; recording a reason does not authorize network access.
#[derive(Clone, Debug, Default)]
pub struct NetworkRequestCancellation(Arc<OnceLock<NetworkRequestCancellationReason>>);
impl NetworkRequestCancellation {
pub fn reason(&self) -> Option<NetworkRequestCancellationReason> {
self.0.get().copied()
}
/// Publish before dropping the decision future. Cleanup cannot replace an earlier cause.
pub fn record(&self, reason: NetworkRequestCancellationReason) {
let _ = self.0.set(reason);
}
}