Enforce exact values from managed config requirements (#34597)

## What changed

- Apply managed values for `sqlite_home`, `log_dir`, `model_catalog_json`,
  `check_for_update_on_startup`, `allow_login_shell`, the report-submission
  opt-in, and `windows.sandbox_private_desktop` to the runtime configuration,
  with source-aware warnings when they override configured values.
- Expose these values through `configRequirements/read`, return them from
  `config/read`, include them in session config locks, and show their sources in
  the TUI config debug view.
- Reject app-server writes that overlap an exact managed requirement with
  `configRequirementReadonly` while leaving unrelated sibling keys writable.

## Testing

- Cover runtime overrides, requirement API mapping, config reads and writes,
  session lock serialization, cross-platform path URIs, and debug output.

GitOrigin-RevId: d4e23b6fd7775c1a6dfe2eab313cdcee50b07081
This commit is contained in:
Abhinav authored and copyberry committed 2026-07-21 19:08:58 +00:00
1 parent 7442f5f932
commit ee71c4a90f
34 files changed
+1566 -71

No files matched your search

+30 -9
View File
@@ -153,6 +153,7 @@ mod network_proxy_spec;
mod otel;
mod permission_profile_catalog;
mod permissions;
mod requirements;
mod resolved_permission_profile;
#[cfg(test)]
mod schema;
@@ -3037,7 +3038,7 @@ impl Config {
pub(crate) async fn load_config_with_layer_stack(
fs: &dyn ExecutorFileSystem,
cfg: ConfigToml,
mut cfg: ConfigToml,
overrides: ConfigOverrides,
codex_home: AbsolutePathBuf,
config_layer_stack: ConfigLayerStack,
@@ -3058,13 +3059,31 @@ impl Config {
resolve_orchestrator_feature_enabled(orchestrator.and_then(|value| value.skills.as_ref()));
let orchestrator_mcp_enabled =
resolve_orchestrator_feature_enabled(orchestrator.and_then(|value| value.mcp.as_ref()));
// Ensure that every field of ConfigRequirements is applied to the final
// Config.
let mut startup_warnings = config_layer_stack
.startup_warnings()
.unwrap_or_default()
.to_vec();
let configured_sqlite_home = cfg.sqlite_home.clone();
requirements::apply_to_config(
&mut cfg,
config_layer_stack.requirements(),
&mut startup_warnings,
);
// Destructure every field to ensure ConfigRequirements additions are
// either applied above or handled while constructing the final Config.
let ConfigRequirements {
sqlite_home: _,
log_dir: _,
model_catalog_json: _,
check_for_update_on_startup: _,
allow_login_shell: _,
feedback: _,
approval_policy: mut constrained_approval_policy,
approvals_reviewer: mut constrained_approvals_reviewer,
permission_profile: mut constrained_permission_profile,
windows_sandbox_mode: mut constrained_windows_sandbox_mode,
windows_sandbox_private_desktop: _,
web_search_mode: mut constrained_web_search_mode,
allow_managed_hooks_only: _,
allow_appshots: _,
@@ -3082,11 +3101,6 @@ impl Config {
guardian_policy_config_source: _,
} = config_layer_stack.requirements().clone();
let mut startup_warnings = config_layer_stack
.startup_warnings()
.unwrap_or_default()
.to_vec();
// Destructure ConfigOverrides fully to ensure all overrides are applied.
let ConfigOverrides {
model,
@@ -3754,11 +3768,18 @@ impl Config {
.as_ref()
.map(AbsolutePathBuf::to_path_buf)
.unwrap_or_else(|| codex_home.join("log").to_path_buf());
let sqlite_home_env = resolve_sqlite_home_env(&resolved_cwd);
requirements::push_sqlite_home_env_override_warning(
configured_sqlite_home.as_ref(),
sqlite_home_env.as_deref(),
config_layer_stack.requirements().sqlite_home.as_ref(),
&mut startup_warnings,
);
let sqlite_home = cfg
.sqlite_home
.as_ref()
.map(AbsolutePathBuf::to_path_buf)
.or_else(|| resolve_sqlite_home_env(&resolved_cwd))
.or(sqlite_home_env)
.unwrap_or_else(|| codex_home.to_path_buf());
let original_permission_profile = permission_profile.clone();
apply_requirement_constrained_value(