Honor per-environment login shell policy (#36811)

## What changed

- Store the effective `allow_login_shell` setting on each turn environment, including inherited environments whose child thread has a different policy.
- Expose the `login` argument for shell tools when any selected environment permits login shells.
- Validate each command against the policy of its selected environment instead of the turn-wide configuration.

## Testing

- Cover tool schema generation for single and multiple environments.
- Cover login-shell rejection by both the command handler and the unified exec integration.

GitOrigin-RevId: 5a93149a5c86f4087f2b92d663ebc33feff8a57c
This commit is contained in:
sayan-oai authored and copyberry committed 2026-08-03 23:33:05 +00:00
1 parent 61dc1d97f6
commit b258c028fe
18 files changed
+291 -28

No files matched your search

+10
View File
@@ -27,6 +27,12 @@ use tracing::instrument;
pub(crate) type ShellSnapshotTask = Shared<BoxFuture<'static, Option<Arc<ShellSnapshotFile>>>>;
/// Effective per-environment config; fields move here as executor config is migrated.
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct EnvironmentConfig {
pub(crate) allow_login_shell: bool,
}
#[derive(Clone)]
pub(crate) struct TurnEnvironment {
pub(crate) environment_id: String,
@@ -34,6 +40,7 @@ pub(crate) struct TurnEnvironment {
cwd: PathUri,
workspace_roots: Vec<PathUri>,
pub(crate) shell: Option<shell::Shell>,
pub(crate) config: EnvironmentConfig,
pub(crate) shell_snapshot: ShellSnapshotTask,
}
@@ -44,6 +51,7 @@ impl TurnEnvironment {
cwd: PathUri,
workspace_roots: Vec<PathUri>,
shell: Option<shell::Shell>,
config: EnvironmentConfig,
) -> Self {
Self {
environment_id,
@@ -51,6 +59,7 @@ impl TurnEnvironment {
cwd,
workspace_roots,
shell,
config,
shell_snapshot: futures::future::ready(None).boxed().shared(),
}
}
@@ -90,6 +99,7 @@ impl std::fmt::Debug for TurnEnvironment {
.field("cwd", &self.cwd)
.field("workspace_roots", &self.workspace_roots)
.field("shell", &self.shell)
.field("config", &self.config)
.finish_non_exhaustive()
}
}