Serialize manual network approval prompts per endpoint (#58351)

## Why

Concurrent executions accessing the same endpoint can produce duplicate network approval prompts before a session decision is recorded.

## What changed

- Queue manual prompts by environment, host, protocol, and port while keeping execution decisions separate.
- After a one-time approval or denial, let the next execution prompt. Reuse committed session grants and deny rules without another prompt.
- Keep tool results paused while requests are queued and attribute the wait to the triggering tool call.

## Testing

Extend coverage for concurrent requests, one-time and session decisions, independent ports, queued cancellation and timing, and isolation between local and remote environments.

GitOrigin-RevId: ebf580dddc39a9a9dc3b0d1acfa21438fbc6e100
This commit is contained in:
Charlie Marsh
2026-10-30 14:40:59 +00:00
committed by copyberry
parent 4969675f01
commit 80f469ce8a
7 changed files with 587 additions and 262 deletions
+16
View File
@@ -3070,6 +3070,22 @@ impl Session {
timing
}
/// Keep tool results paused and attribute a queued network prompt to its triggering call.
pub(crate) fn hold_queued_network_approval(
&self,
turn: &TurnContext,
call_id: Option<&str>,
) -> (
crate::elicitation::ElicitationRegistration,
Option<codex_direct_tool_timing::ToolBlockingTimingGuard>,
) {
let owner = self.user_wait_timing_owner(turn, call_id);
(
self.services.elicitations.register(),
self.start_user_wait_timing(turn, owner.as_deref()),
)
}
/// Emit an exec approval request event and await the user's decision.
///
/// The request is keyed by `call_id` + `approval_id` so matching responses