feat(core): plumb distinct approval ids for command approvals (#12051)

zsh fork PR stack:
- https://github.com/openai/codex/pull/12051 👈 
- https://github.com/openai/codex/pull/12052

With upcoming support for a fork of zsh that allows us to intercept
`execve` and run execpolicy checks for each subcommand as part of a
`CommandExecution`, it will be possible for there to be multiple
approval requests for a shell command like `/path/to/zsh -lc 'git status
&& rg \"TODO\" src && make test'`.

To support that, this PR introduces a new `approval_id` field across
core, protocol, and app-server so that we can associate approvals
properly for subcommands.
This commit is contained in:
Owen Lin
2026-02-17 17:55:57 -08:00
committed by GitHub
parent b3a8571219
commit db4d2599b5
33 changed files with 331 additions and 114 deletions

View File

@@ -2472,6 +2472,7 @@ async fn exec_approval_emits_proposed_command_and_decision_history() {
// Trigger an exec approval request with a short, single-line command
let ev = ExecApprovalRequestEvent {
call_id: "call-short".into(),
approval_id: Some("call-short".into()),
turn_id: "turn-short".into(),
command: vec!["bash".into(), "-lc".into(), "echo hello world".into()],
cwd: std::env::current_dir().unwrap_or_else(|_| PathBuf::from(".")),
@@ -2517,6 +2518,7 @@ async fn exec_approval_decision_truncates_multiline_and_long_commands() {
// Multiline command: modal should show full command, history records decision only
let ev_multi = ExecApprovalRequestEvent {
call_id: "call-multi".into(),
approval_id: Some("call-multi".into()),
turn_id: "turn-multi".into(),
command: vec!["bash".into(), "-lc".into(), "echo line1\necho line2".into()],
cwd: std::env::current_dir().unwrap_or_else(|_| PathBuf::from(".")),
@@ -2570,6 +2572,7 @@ async fn exec_approval_decision_truncates_multiline_and_long_commands() {
let long = format!("echo {}", "a".repeat(200));
let ev_long = ExecApprovalRequestEvent {
call_id: "call-long".into(),
approval_id: Some("call-long".into()),
turn_id: "turn-long".into(),
command: vec!["bash".into(), "-lc".into(), long],
cwd: std::env::current_dir().unwrap_or_else(|_| PathBuf::from(".")),
@@ -5684,6 +5687,7 @@ async fn approval_modal_exec_snapshot() -> anyhow::Result<()> {
// Inject an exec approval request to display the approval modal.
let ev = ExecApprovalRequestEvent {
call_id: "call-approve-cmd".into(),
approval_id: Some("call-approve-cmd".into()),
turn_id: "turn-approve-cmd".into(),
command: vec!["bash".into(), "-lc".into(), "echo hello world".into()],
cwd: std::env::current_dir().unwrap_or_else(|_| PathBuf::from(".")),
@@ -5743,6 +5747,7 @@ async fn approval_modal_exec_without_reason_snapshot() -> anyhow::Result<()> {
let ev = ExecApprovalRequestEvent {
call_id: "call-approve-cmd-noreason".into(),
approval_id: Some("call-approve-cmd-noreason".into()),
turn_id: "turn-approve-cmd-noreason".into(),
command: vec!["bash".into(), "-lc".into(), "echo hello world".into()],
cwd: std::env::current_dir().unwrap_or_else(|_| PathBuf::from(".")),
@@ -5791,6 +5796,7 @@ async fn approval_modal_exec_multiline_prefix_hides_execpolicy_option_snapshot()
let command = vec!["bash".into(), "-lc".into(), script];
let ev = ExecApprovalRequestEvent {
call_id: "call-approve-cmd-multiline-trunc".into(),
approval_id: Some("call-approve-cmd-multiline-trunc".into()),
turn_id: "turn-approve-cmd-multiline-trunc".into(),
command: command.clone(),
cwd: std::env::current_dir().unwrap_or_else(|_| PathBuf::from(".")),
@@ -6149,6 +6155,7 @@ async fn status_widget_and_approval_modal_snapshot() {
// Now show an approval modal (e.g. exec approval).
let ev = ExecApprovalRequestEvent {
call_id: "call-approve-exec".into(),
approval_id: Some("call-approve-exec".into()),
turn_id: "turn-approve-exec".into(),
command: vec!["echo".into(), "hello world".into()],
cwd: PathBuf::from("/tmp"),