[ez][codex-rs] Support approvals reviewer in app defaults (#27075)

[from codex]

## Summary

- add `approvals_reviewer` support to `[apps._default]`
- resolve connected-app reviewers in per-app, app-default, then global
order
- expose the setting through the v2 config API and regenerate schema
fixtures

## Context

PR #25167 added `apps.<connector_id>.approvals_reviewer`, but the shared
app defaults table could not specify the reviewer. This extends the same
behavior to `[apps._default]` while preserving per-app overrides.

Managed `allowed_approvals_reviewers` requirements still constrain both
default and per-app values. A disallowed app value falls back to the
global reviewer, and non-app MCP servers continue using the global
reviewer.

## Testing

- `just write-config-schema`
- `just write-app-server-schema`
- `just fmt`
- `just test -p codex-config`
- `just test -p codex-core app_approvals_reviewer`
- `just test -p codex-app-server-protocol`
- `just test -p codex-app-server config_read_includes_apps`
This commit is contained in:
Alex Zamoshchin
2026-06-12 09:06:58 -07:00
committed by GitHub
parent 5b8e3c6d40
commit 3cac2e0d3f
12 changed files with 275 additions and 10 deletions
+7 -2
View File
@@ -1775,13 +1775,18 @@ The server also emits `app/list/updated` notifications whenever either source (a
```
Connected apps may override the thread's approval reviewer in `config.toml`.
When omitted, the app inherits the top-level `approvals_reviewer` value:
Use `apps._default.approvals_reviewer` to set the reviewer for all apps, and a
per-app value to override that default. When both are omitted, the app inherits
the top-level `approvals_reviewer` value:
```toml
approvals_reviewer = "auto_review"
[apps.demo-app]
[apps._default]
approvals_reviewer = "user"
[apps.demo-app]
approvals_reviewer = "auto_review"
```
Setting the app value to `"user"` routes its approval prompts to the user
@@ -7,6 +7,7 @@ use codex_app_server_protocol::AppConfig;
use codex_app_server_protocol::AppToolApproval;
use codex_app_server_protocol::ApprovalsReviewer;
use codex_app_server_protocol::AppsConfig;
use codex_app_server_protocol::AppsDefaultConfig;
use codex_app_server_protocol::AskForApproval;
use codex_app_server_protocol::ConfigBatchWriteParams;
use codex_app_server_protocol::ConfigEdit;
@@ -332,6 +333,9 @@ async fn config_read_includes_apps() -> Result<()> {
write_config(
&codex_home,
r#"
[apps._default]
approvals_reviewer = "auto_review"
[apps.app1]
enabled = false
approvals_reviewer = "user"
@@ -365,7 +369,12 @@ default_tools_approval_mode = "prompt"
assert_eq!(
config.apps,
Some(AppsConfig {
default: None,
default: Some(AppsDefaultConfig {
enabled: true,
approvals_reviewer: Some(ApprovalsReviewer::AutoReview),
destructive_enabled: true,
open_world_enabled: true,
}),
apps: std::collections::HashMap::from([(
"app1".to_string(),
AppConfig {
@@ -380,6 +389,16 @@ default_tools_approval_mode = "prompt"
)]),
})
);
assert_eq!(
origins
.get("apps._default.approvals_reviewer")
.expect("origin")
.name,
ConfigLayerSource::User {
file: user_file.clone(),
profile: None,
}
);
assert_eq!(
origins.get("apps.app1.enabled").expect("origin").name,
ConfigLayerSource::User {