Key request-permission grants by environment (#25850)

## Stack

1. This PR (#25850) - Key request-permission grants by environment:
stores and applies sticky permission grants per environment id.
2. #25858 - Add `environmentId` to `request_permissions`: lets the model
target a selected environment and resolves relative permission paths
against it.
3. #25862 - Propagate permission approval environment id: carries the
selected environment id through approval events, app-server requests,
TUI prompts, and delegate forwarding.
4. #25867 - Add remote request permissions integration coverage:
verifies the selected remote environment across request, approval, grant
reuse, and exec.

#25858, #25862, and #25867 are stacked on this PR and should be reviewed
after it.

## Why

Multi-environment CCA turns can attach both local and remote executors,
but request-permission grants were still effectively cwd-only. Pending
permission requests tracked a cwd, while stored turn/session grants had
no environment identity, so sticky grants could be reused through the
wrong executor context.

This makes the first permission-grant step environment-aware without
changing the external `request_permissions` payload shape: omitted
environment targeting remains bound to the primary turn environment.

## What Changed

- Store turn- and session-scoped request-permission grants by
`environment_id`.
- Keep the selected `TurnEnvironmentSelection` with pending
`request_permissions` calls so approval responses normalize and record
grants against the same environment.
- Resolve relative `request_permissions` file paths against the primary
turn environment cwd instead of deprecated `turn.cwd`.
- Apply sticky grants in `shell`, `exec_command`, and `apply_patch` by
selected environment id while still using the actual tool cwd for
cwd-relative permission materialization.
- Update Guardian and request-permissions coverage for the
environment-keyed grant behavior.

## Testing

Not run locally. Added or updated focused coverage for:

- `request_permission_grants_are_environment_keyed`
-
`request_permissions_tool_resolves_relative_paths_against_primary_environment`
- related Guardian/request-permissions sticky grant tests
This commit is contained in:
jif
2026-06-02 20:16:57 +02:00
committed by GitHub
Unverified
parent 9e3d5f29e2
commit 503ec190a8
10 changed files with 356 additions and 57 deletions
@@ -148,7 +148,9 @@ async fn request_permissions_routes_to_guardian_when_reviewer_is_enabled() {
})
);
assert_eq!(
session.granted_turn_permissions().await,
session
.granted_turn_permissions(codex_exec_server::LOCAL_ENVIRONMENT_ID)
.await,
Some(requested_permissions.into())
);
@@ -246,7 +248,12 @@ async fn request_permissions_guardian_review_stops_when_cancelled() {
.expect("request_permissions should stop when cancelled")
.expect("request_permissions task should not panic");
assert_eq!(response, None);
assert_eq!(session.granted_turn_permissions().await, None);
assert_eq!(
session
.granted_turn_permissions(codex_exec_server::LOCAL_ENVIRONMENT_ID)
.await,
None
);
}
#[tokio::test]
@@ -380,6 +387,7 @@ async fn strict_auto_review_turn_grant_forces_guardian_for_shell_command_policy_
scope: PermissionGrantScope::Turn,
strict_auto_review: true,
},
codex_exec_server::LOCAL_ENVIRONMENT_ID,
Some(&originating_turn_state),
)
.await;
@@ -564,12 +572,15 @@ async fn shell_command_allows_sticky_turn_permissions_without_inline_request_per
let mut active_turn = session.active_turn.lock().await;
let active_turn = active_turn.as_mut().expect("active turn");
let mut turn_state = active_turn.turn_state.lock().await;
turn_state.record_granted_permissions(PermissionProfile {
network: Some(NetworkPermissions {
enabled: Some(true),
}),
..Default::default()
});
turn_state.record_granted_permissions(
codex_exec_server::LOCAL_ENVIRONMENT_ID,
PermissionProfile {
network: Some(NetworkPermissions {
enabled: Some(true),
}),
..Default::default()
},
);
}
let session = Arc::new(session);