Extract codex-config from codex-core (#11389)

`codex-core` had accumulated config loading, requirements parsing,
constraint logic, and config-layer state handling in a single crate.
This change extracts that subsystem into `codex-config` to reduce
`codex-core` rebuild/test surface area and isolate future config work.

## What Changed

### Added `codex-config`

- Added new workspace crate `codex-rs/config` (`codex-config`).
- Added workspace/build wiring in:
  - `codex-rs/Cargo.toml`
  - `codex-rs/config/Cargo.toml`
  - `codex-rs/config/BUILD.bazel`
- Updated lockfiles (`codex-rs/Cargo.lock`, `MODULE.bazel.lock`).
- Added `codex-core` -> `codex-config` dependency in
`codex-rs/core/Cargo.toml`.

### Moved config internals from `core` into `config`

Moved modules to `codex-rs/config/src/`:

- `core/src/config/constraint.rs` -> `config/src/constraint.rs`
- `core/src/config_loader/cloud_requirements.rs` ->
`config/src/cloud_requirements.rs`
- `core/src/config_loader/config_requirements.rs` ->
`config/src/config_requirements.rs`
- `core/src/config_loader/fingerprint.rs` -> `config/src/fingerprint.rs`
- `core/src/config_loader/merge.rs` -> `config/src/merge.rs`
- `core/src/config_loader/overrides.rs` -> `config/src/overrides.rs`
- `core/src/config_loader/requirements_exec_policy.rs` ->
`config/src/requirements_exec_policy.rs`
- `core/src/config_loader/state.rs` -> `config/src/state.rs`

`codex-config` now re-exports this surface from `config/src/lib.rs` at
the crate top level.

### Updated `core` to consume/re-export `codex-config`

- `core/src/config_loader/mod.rs` now imports/re-exports config-loader
types/functions from top-level `codex_config::*`.
- Local moved modules were removed from `core/src/config_loader/`.
- `core/src/config/mod.rs` now re-exports constraint types from
`codex_config`.
This commit is contained in:
Michael Bolin 2026-02-11 10:02:49 -08:00 committed by GitHub
parent 7e0178597e
commit 577a416f9a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 292 additions and 163 deletions

93
MODULE.bazel.lock generated

File diff suppressed because one or more lines are too long

22
codex-rs/Cargo.lock generated
View file

@ -1628,6 +1628,26 @@ dependencies = [
"thiserror 2.0.18",
]
[[package]]
name = "codex-config"
version = "0.0.0"
dependencies = [
"anyhow",
"codex-app-server-protocol",
"codex-execpolicy",
"codex-protocol",
"codex-utils-absolute-path",
"futures",
"multimap",
"pretty_assertions",
"serde",
"serde_json",
"sha2",
"thiserror 2.0.18",
"tokio",
"toml 0.9.12+spec-1.1.0",
]
[[package]]
name = "codex-core"
version = "0.0.0"
@ -1650,6 +1670,7 @@ dependencies = [
"codex-arg0",
"codex-async-utils",
"codex-client",
"codex-config",
"codex-execpolicy",
"codex-file-search",
"codex-git",
@ -1686,7 +1707,6 @@ dependencies = [
"landlock",
"libc",
"maplit",
"multimap",
"notify",
"once_cell",
"openssl-sys",

View file

@ -15,6 +15,7 @@ members = [
"cloud-tasks",
"cloud-tasks-client",
"cli",
"config",
"shell-command",
"core",
"hooks",
@ -83,20 +84,19 @@ codex-apply-patch = { path = "apply-patch" }
codex-arg0 = { path = "arg0" }
codex-async-utils = { path = "async-utils" }
codex-backend-client = { path = "backend-client" }
codex-cloud-requirements = { path = "cloud-requirements" }
codex-chatgpt = { path = "chatgpt" }
codex-cli = { path = "cli"}
codex-cli = { path = "cli" }
codex-client = { path = "codex-client" }
codex-shell-command = { path = "shell-command" }
codex-cloud-requirements = { path = "cloud-requirements" }
codex-config = { path = "config" }
codex-core = { path = "core" }
codex-hooks = { path = "hooks" }
codex-secrets = { path = "secrets" }
codex-exec = { path = "exec" }
codex-execpolicy = { path = "execpolicy" }
codex-experimental-api-macros = { path = "codex-experimental-api-macros" }
codex-feedback = { path = "feedback" }
codex-file-search = { path = "file-search" }
codex-git = { path = "utils/git" }
codex-hooks = { path = "hooks" }
codex-keyring-store = { path = "keyring-store" }
codex-linux-sandbox = { path = "linux-sandbox" }
codex-lmstudio = { path = "lmstudio" }
@ -109,25 +109,27 @@ codex-process-hardening = { path = "process-hardening" }
codex-protocol = { path = "protocol" }
codex-responses-api-proxy = { path = "responses-api-proxy" }
codex-rmcp-client = { path = "rmcp-client" }
codex-secrets = { path = "secrets" }
codex-shell-command = { path = "shell-command" }
codex-state = { path = "state" }
codex-stdio-to-uds = { path = "stdio-to-uds" }
codex-tui = { path = "tui" }
codex-utils-absolute-path = { path = "utils/absolute-path" }
codex-utils-approval-presets = { path = "utils/approval-presets" }
codex-utils-cache = { path = "utils/cache" }
codex-utils-cargo-bin = { path = "utils/cargo-bin" }
codex-utils-cli = { path = "utils/cli" }
codex-utils-elapsed = { path = "utils/elapsed" }
codex-utils-fuzzy-match = { path = "utils/fuzzy-match" }
codex-utils-home-dir = { path = "utils/home-dir" }
codex-utils-image = { path = "utils/image" }
codex-utils-json-to-toml = { path = "utils/json-to-toml" }
codex-utils-home-dir = { path = "utils/home-dir" }
codex-utils-oss = { path = "utils/oss" }
codex-utils-pty = { path = "utils/pty" }
codex-utils-readiness = { path = "utils/readiness" }
codex-utils-rustls-provider = { path = "utils/rustls-provider" }
codex-utils-string = { path = "utils/string" }
codex-utils-cli = { path = "utils/cli" }
codex-utils-elapsed = { path = "utils/elapsed" }
codex-utils-sandbox-summary = { path = "utils/sandbox-summary" }
codex-utils-approval-presets = { path = "utils/approval-presets" }
codex-utils-oss = { path = "utils/oss" }
codex-utils-fuzzy-match = { path = "utils/fuzzy-match" }
codex-utils-string = { path = "utils/string" }
codex-windows-sandbox = { path = "windows-sandbox-rs" }
core_test_support = { path = "core/tests/common" }
exec_server_test_support = { path = "exec-server/tests/common" }
@ -139,12 +141,12 @@ allocative = "0.3.3"
ansi-to-tui = "7.0.0"
anyhow = "1"
arboard = { version = "3", features = ["wayland-data-control"] }
askama = "0.15.4"
assert_cmd = "2"
assert_matches = "1.5.0"
async-channel = "2.3.1"
async-stream = "0.3.6"
async-trait = "0.1.89"
askama = "0.15.4"
axum = { version = "0.8", default-features = false }
base64 = "0.22.1"
bm25 = "2.3.2"
@ -154,8 +156,8 @@ chrono = "0.4.43"
clap = "4"
clap_complete = "4"
color-eyre = "0.6.3"
crossterm = "0.28.1"
crossbeam-channel = "0.5.15"
crossterm = "0.28.1"
ctor = "0.6.3"
derive_more = "2"
diffy = "0.4.2"
@ -173,10 +175,10 @@ icu_decimal = "2.1"
icu_locale_core = "2.1"
icu_provider = { version = "2.1", features = ["sync"] }
ignore = "0.4.23"
indoc = "2.0"
image = { version = "^0.25.9", default-features = false }
include_dir = "0.7.4"
indexmap = "2.12.0"
indoc = "2.0"
insta = "1.46.3"
inventory = "0.3.19"
itertools = "0.14.0"
@ -198,7 +200,6 @@ opentelemetry-appender-tracing = "0.31.0"
opentelemetry-otlp = "0.31.0"
opentelemetry-semantic-conventions = "0.31.0"
opentelemetry_sdk = "0.31.0"
tracing-opentelemetry = "0.32.0"
os_info = "3.12.0"
owo-colors = "4.2.0"
path-absolutize = "3.1.1"
@ -214,10 +215,14 @@ regex = "1.12.3"
regex-lite = "0.1.8"
reqwest = "0.12"
rmcp = { version = "0.14.0", default-features = false }
rustls = { version = "0.23", default-features = false, features = ["ring", "std"] }
runfiles = { git = "https://github.com/dzbarsky/rules_rust", rev = "b56cbaa8465e74127f1ea216f813cd377295ad81" }
rustls = { version = "0.23", default-features = false, features = [
"ring",
"std",
] }
schemars = "0.8.22"
seccompiler = "0.5.0"
semver = "1.0"
sentry = "0.46.0"
serde = "1"
serde_json = "1"
@ -227,11 +232,19 @@ serde_yaml = "0.9"
serial_test = "3.2.0"
sha1 = "0.10.6"
sha2 = "0.10"
semver = "1.0"
shlex = "1.3.0"
similar = "2.7.0"
socket2 = "0.6.1"
sqlx = { version = "0.8.6", default-features = false, features = ["chrono", "json", "macros", "migrate", "runtime-tokio-rustls", "sqlite", "time", "uuid"] }
sqlx = { version = "0.8.6", default-features = false, features = [
"chrono",
"json",
"macros",
"migrate",
"runtime-tokio-rustls",
"sqlite",
"time",
"uuid",
] }
starlark = "0.13.0"
strum = "0.27.2"
strum_macros = "0.27.2"
@ -246,20 +259,23 @@ tiny_http = "0.12"
tokio = "1"
tokio-stream = "0.1.18"
tokio-test = "0.4"
tokio-tungstenite = { version = "0.28.0", features = ["proxy", "rustls-tls-native-roots"] }
tungstenite = { version = "0.27.0", features = ["deflate", "proxy"] }
tokio-tungstenite = { version = "0.28.0", features = [
"proxy",
"rustls-tls-native-roots",
] }
tokio-util = "0.7.18"
toml = "0.9.5"
toml_edit = "0.24.0"
tracing = "0.1.44"
tracing-appender = "0.2.3"
tracing-opentelemetry = "0.32.0"
tracing-subscriber = "0.3.22"
tracing-test = "0.2.5"
tree-sitter = "0.25.10"
tree-sitter-bash = "0.25"
zstd = "0.13"
tree-sitter-highlight = "0.25.10"
ts-rs = "11"
tungstenite = { version = "0.27.0", features = ["deflate", "proxy"] }
uds_windows = "1.1.0"
unicode-segmentation = "1.12.0"
unicode-width = "0.2"
@ -272,6 +288,7 @@ webbrowser = "1.0"
which = "8"
wildmatch = "2.6.1"
zip = "2.4.2"
zstd = "0.13"
wiremock = "0.6"
zeroize = "1.8.2"
@ -317,7 +334,12 @@ unwrap_used = "deny"
# cargo-shear cannot see the platform-specific openssl-sys usage, so we
# silence the false positive here instead of deleting a real dependency.
[workspace.metadata.cargo-shear]
ignored = ["icu_provider", "openssl-sys", "codex-utils-readiness", "codex-secrets"]
ignored = [
"icu_provider",
"openssl-sys",
"codex-utils-readiness",
"codex-secrets",
]
[profile.release]
lto = "fat"

View file

@ -0,0 +1,6 @@
load("//:defs.bzl", "codex_rust_crate")
codex_rust_crate(
name = "config",
crate_name = "codex_config",
)

View file

@ -0,0 +1,26 @@
[package]
name = "codex-config"
version.workspace = true
edition.workspace = true
license.workspace = true
[lints]
workspace = true
[dependencies]
codex-app-server-protocol = { workspace = true }
codex-execpolicy = { workspace = true }
codex-protocol = { workspace = true }
codex-utils-absolute-path = { workspace = true }
futures = { workspace = true, features = ["alloc", "std"] }
multimap = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
sha2 = { workspace = true }
thiserror = { workspace = true }
toml = { workspace = true }
[dev-dependencies]
anyhow = { workspace = true }
pretty_assertions = { workspace = true }
tokio = { workspace = true, features = ["full"] }

View file

@ -1,4 +1,4 @@
use crate::config_loader::ConfigRequirementsToml;
use crate::config_requirements::ConfigRequirementsToml;
use futures::future::BoxFuture;
use futures::future::FutureExt;
use futures::future::Shared;

View file

@ -10,8 +10,8 @@ use std::fmt;
use super::requirements_exec_policy::RequirementsExecPolicy;
use super::requirements_exec_policy::RequirementsExecPolicyToml;
use crate::config::Constrained;
use crate::config::ConstraintError;
use crate::Constrained;
use crate::ConstraintError;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RequirementSource {
@ -80,7 +80,7 @@ pub struct ConfigRequirements {
pub sandbox_policy: ConstrainedWithSource<SandboxPolicy>,
pub web_search_mode: ConstrainedWithSource<WebSearchMode>,
pub mcp_servers: Option<Sourced<BTreeMap<String, McpServerRequirement>>>,
pub(crate) exec_policy: Option<Sourced<RequirementsExecPolicy>>,
pub exec_policy: Option<Sourced<RequirementsExecPolicy>>,
pub enforce_residency: ConstrainedWithSource<Option<ResidencyRequirement>>,
/// Managed network constraints derived from requirements.
pub network: Option<Sourced<NetworkConstraints>>,
@ -560,7 +560,6 @@ impl TryFrom<ConfigRequirementsWithSources> for ConfigRequirements {
#[cfg(test)]
mod tests {
use super::*;
use crate::config_loader::system_requirements_toml_file;
use anyhow::Result;
use codex_execpolicy::Decision;
use codex_execpolicy::Evaluation;
@ -574,6 +573,12 @@ mod tests {
cmd.iter().map(std::string::ToString::to_string).collect()
}
fn system_requirements_toml_file_for_test() -> Result<AbsolutePathBuf> {
Ok(AbsolutePathBuf::try_from(
std::env::temp_dir().join("requirements.toml"),
)?)
}
fn with_unknown_source(toml: ConfigRequirementsToml) -> ConfigRequirementsWithSources {
let ConfigRequirementsToml {
allowed_approval_policies,
@ -732,7 +737,7 @@ mod tests {
"#,
)?;
let requirements_toml_file = system_requirements_toml_file()?;
let requirements_toml_file = system_requirements_toml_file_for_test()?;
let source_location = RequirementSource::SystemRequirementsToml {
file: requirements_toml_file,
};
@ -1149,7 +1154,7 @@ mod tests {
]
"#;
let config: ConfigRequirementsToml = from_str(toml_str)?;
let requirements_toml_file = system_requirements_toml_file()?;
let requirements_toml_file = system_requirements_toml_file_for_test()?;
let source_location = RequirementSource::SystemRequirementsToml {
file: requirements_toml_file,
};

View file

@ -1,7 +1,7 @@
use std::fmt;
use std::sync::Arc;
use crate::config_loader::RequirementSource;
use crate::config_requirements::RequirementSource;
use thiserror::Error;
#[derive(Debug, Error, PartialEq, Eq)]

View file

@ -34,7 +34,7 @@ pub(super) fn record_origins(
}
}
pub(super) fn version_for_toml(value: &TomlValue) -> String {
pub fn version_for_toml(value: &TomlValue) -> String {
let json = serde_json::to_value(value).unwrap_or(JsonValue::Null);
let canonical = canonical_json(&json);
let serialized = serde_json::to_vec(&canonical).unwrap_or_default();

View file

@ -0,0 +1,39 @@
mod cloud_requirements;
mod config_requirements;
mod constraint;
mod fingerprint;
mod merge;
mod overrides;
mod requirements_exec_policy;
mod state;
pub use cloud_requirements::CloudRequirementsLoader;
pub use config_requirements::ConfigRequirements;
pub use config_requirements::ConfigRequirementsToml;
pub use config_requirements::ConfigRequirementsWithSources;
pub use config_requirements::ConstrainedWithSource;
pub use config_requirements::McpServerIdentity;
pub use config_requirements::McpServerRequirement;
pub use config_requirements::NetworkConstraints;
pub use config_requirements::NetworkRequirementsToml;
pub use config_requirements::RequirementSource;
pub use config_requirements::ResidencyRequirement;
pub use config_requirements::SandboxModeRequirement;
pub use config_requirements::Sourced;
pub use config_requirements::WebSearchModeRequirement;
pub use constraint::Constrained;
pub use constraint::ConstraintError;
pub use constraint::ConstraintResult;
pub use fingerprint::version_for_toml;
pub use merge::merge_toml_values;
pub use overrides::build_cli_overrides_layer;
pub use requirements_exec_policy::RequirementsExecPolicy;
pub use requirements_exec_policy::RequirementsExecPolicyDecisionToml;
pub use requirements_exec_policy::RequirementsExecPolicyParseError;
pub use requirements_exec_policy::RequirementsExecPolicyPatternTokenToml;
pub use requirements_exec_policy::RequirementsExecPolicyPrefixRuleToml;
pub use requirements_exec_policy::RequirementsExecPolicyToml;
pub use state::ConfigLayerEntry;
pub use state::ConfigLayerStack;
pub use state::ConfigLayerStackOrdering;
pub use state::LoaderOverrides;

View file

@ -4,7 +4,7 @@ pub(crate) fn default_empty_table() -> TomlValue {
TomlValue::Table(Default::default())
}
pub(crate) fn build_cli_overrides_layer(cli_overrides: &[(String, TomlValue)]) -> TomlValue {
pub fn build_cli_overrides_layer(cli_overrides: &[(String, TomlValue)]) -> TomlValue {
let mut root = default_empty_table();
for (path, value) in cli_overrides {
apply_toml_override(&mut root, path, value.clone());

View file

@ -10,7 +10,7 @@ use std::sync::Arc;
use thiserror::Error;
#[derive(Debug, Clone)]
pub(crate) struct RequirementsExecPolicy {
pub struct RequirementsExecPolicy {
policy: Policy,
}

View file

@ -1,5 +1,5 @@
use crate::config_loader::ConfigRequirements;
use crate::config_loader::ConfigRequirementsToml;
use crate::config_requirements::ConfigRequirements;
use crate::config_requirements::ConfigRequirementsToml;
use super::fingerprint::record_origins;
use super::fingerprint::version_for_toml;

View file

@ -33,6 +33,7 @@ codex-app-server-protocol = { workspace = true }
codex-apply-patch = { workspace = true }
codex-async-utils = { workspace = true }
codex-client = { workspace = true }
codex-config = { workspace = true }
codex-shell-command = { workspace = true }
codex-execpolicy = { workspace = true }
codex-file-search = { workspace = true }
@ -62,7 +63,6 @@ indexmap = { workspace = true }
indoc = { workspace = true }
keyring = { workspace = true, features = ["crypto-rust"] }
libc = { workspace = true }
multimap = { workspace = true }
notify = { workspace = true }
once_cell = { workspace = true }
os_info = { workspace = true }

View file

@ -77,16 +77,15 @@ use crate::config::profile::ConfigProfile;
use toml::Value as TomlValue;
use toml_edit::DocumentMut;
mod constraint;
pub mod edit;
mod network_proxy_spec;
pub mod profile;
pub mod schema;
pub mod service;
pub mod types;
pub use constraint::Constrained;
pub use constraint::ConstraintError;
pub use constraint::ConstraintResult;
pub use codex_config::Constrained;
pub use codex_config::ConstraintError;
pub use codex_config::ConstraintResult;
pub use network_proxy_spec::NetworkProxySpec;
pub use network_proxy_spec::StartedNetworkProxy;

View file

@ -1,6 +1,6 @@
use super::config_requirements::ConfigRequirementsToml;
use super::config_requirements::ConfigRequirementsWithSources;
use super::config_requirements::RequirementSource;
use super::ConfigRequirementsToml;
use super::ConfigRequirementsWithSources;
use super::RequirementSource;
use base64::Engine;
use base64::prelude::BASE64_STANDARD;
use core_foundation::base::TCFType;

View file

@ -1,14 +1,7 @@
mod cloud_requirements;
mod config_requirements;
mod diagnostics;
mod fingerprint;
mod layer_io;
#[cfg(target_os = "macos")]
mod macos;
mod merge;
mod overrides;
mod requirements_exec_policy;
mod state;
#[cfg(test)]
mod tests;
@ -16,10 +9,10 @@ mod tests;
use crate::config::CONFIG_TOML_FILE;
use crate::config::ConfigToml;
use crate::config::deserialize_config_toml_with_base;
use crate::config_loader::config_requirements::ConfigRequirementsWithSources;
use crate::config_loader::layer_io::LoadedConfigLayers;
use crate::git_info::resolve_root_git_project_for_trust;
use codex_app_server_protocol::ConfigLayerSource;
use codex_config::ConfigRequirementsWithSources;
use codex_protocol::config_types::SandboxMode;
use codex_protocol::config_types::TrustLevel;
use codex_protocol::protocol::AskForApproval;
@ -33,19 +26,27 @@ use std::path::Path;
use std::path::PathBuf;
use toml::Value as TomlValue;
pub use cloud_requirements::CloudRequirementsLoader;
pub use config_requirements::ConfigRequirements;
pub use config_requirements::ConfigRequirementsToml;
pub use config_requirements::ConstrainedWithSource;
pub use config_requirements::McpServerIdentity;
pub use config_requirements::McpServerRequirement;
pub use config_requirements::NetworkConstraints;
pub use config_requirements::NetworkRequirementsToml;
pub use config_requirements::RequirementSource;
pub use config_requirements::ResidencyRequirement;
pub use config_requirements::SandboxModeRequirement;
pub use config_requirements::Sourced;
pub use config_requirements::WebSearchModeRequirement;
pub use codex_config::CloudRequirementsLoader;
pub use codex_config::ConfigLayerEntry;
pub use codex_config::ConfigLayerStack;
pub use codex_config::ConfigLayerStackOrdering;
pub use codex_config::ConfigRequirements;
pub use codex_config::ConfigRequirementsToml;
pub use codex_config::ConstrainedWithSource;
pub use codex_config::LoaderOverrides;
pub use codex_config::McpServerIdentity;
pub use codex_config::McpServerRequirement;
pub use codex_config::NetworkConstraints;
pub use codex_config::NetworkRequirementsToml;
pub use codex_config::RequirementSource;
pub use codex_config::ResidencyRequirement;
pub use codex_config::SandboxModeRequirement;
pub use codex_config::Sourced;
pub use codex_config::WebSearchModeRequirement;
pub(crate) use codex_config::build_cli_overrides_layer;
pub use codex_config::merge_toml_values;
#[cfg(test)]
pub(crate) use codex_config::version_for_toml;
pub use diagnostics::ConfigError;
pub use diagnostics::ConfigLoadError;
pub use diagnostics::TextPosition;
@ -56,12 +57,6 @@ pub(crate) use diagnostics::first_layer_config_error_from_entries;
pub use diagnostics::format_config_error;
pub use diagnostics::format_config_error_with_source;
pub(crate) use diagnostics::io_error_from_config_error;
pub use merge::merge_toml_values;
pub(crate) use overrides::build_cli_overrides_layer;
pub use state::ConfigLayerEntry;
pub use state::ConfigLayerStack;
pub use state::ConfigLayerStackOrdering;
pub use state::LoaderOverrides;
/// On Unix systems, load default settings from this file path, if present.
/// Note that /etc/codex/ is treated as a "config folder," so subfolders such
@ -145,7 +140,7 @@ pub async fn load_config_layers_state(
let cli_overrides_layer = if cli_overrides.is_empty() {
None
} else {
let cli_overrides_layer = overrides::build_cli_overrides_layer(cli_overrides);
let cli_overrides_layer = build_cli_overrides_layer(cli_overrides);
let base_dir = cwd
.as_ref()
.map(AbsolutePathBuf::as_path)

View file

@ -11,10 +11,10 @@ use crate::config_loader::ConfigLayerEntry;
use crate::config_loader::ConfigLoadError;
use crate::config_loader::ConfigRequirements;
use crate::config_loader::ConfigRequirementsToml;
use crate::config_loader::config_requirements::ConfigRequirementsWithSources;
use crate::config_loader::config_requirements::RequirementSource;
use crate::config_loader::fingerprint::version_for_toml;
use crate::config_loader::ConfigRequirementsWithSources;
use crate::config_loader::RequirementSource;
use crate::config_loader::load_requirements_toml;
use crate::config_loader::version_for_toml;
use codex_protocol::config_types::TrustLevel;
use codex_protocol::config_types::WebSearchMode;
use codex_protocol::protocol::AskForApproval;
@ -1246,19 +1246,19 @@ async fn project_root_markers_supports_alternate_markers() -> std::io::Result<()
}
mod requirements_exec_policy_tests {
use super::super::config_requirements::ConfigRequirementsWithSources;
use super::super::requirements_exec_policy::RequirementsExecPolicyDecisionToml;
use super::super::requirements_exec_policy::RequirementsExecPolicyParseError;
use super::super::requirements_exec_policy::RequirementsExecPolicyPatternTokenToml;
use super::super::requirements_exec_policy::RequirementsExecPolicyPrefixRuleToml;
use super::super::requirements_exec_policy::RequirementsExecPolicyToml;
use crate::config_loader::ConfigLayerEntry;
use crate::config_loader::ConfigLayerStack;
use crate::config_loader::ConfigRequirements;
use crate::config_loader::ConfigRequirementsToml;
use crate::config_loader::ConfigRequirementsWithSources;
use crate::config_loader::RequirementSource;
use crate::exec_policy::load_exec_policy;
use codex_app_server_protocol::ConfigLayerSource;
use codex_config::RequirementsExecPolicyDecisionToml;
use codex_config::RequirementsExecPolicyParseError;
use codex_config::RequirementsExecPolicyPatternTokenToml;
use codex_config::RequirementsExecPolicyPrefixRuleToml;
use codex_config::RequirementsExecPolicyToml;
use codex_execpolicy::Decision;
use codex_execpolicy::Evaluation;
use codex_execpolicy::RuleMatch;

View file

@ -474,44 +474,46 @@ mod tests {
} else {
absolute_path("/etc/codex/requirements.toml")
};
let mut requirements = ConfigRequirements::default();
requirements.approval_policy = ConstrainedWithSource::new(
Constrained::allow_any(AskForApproval::OnRequest),
Some(RequirementSource::CloudRequirements),
);
requirements.sandbox_policy = ConstrainedWithSource::new(
Constrained::allow_any(SandboxPolicy::ReadOnly),
Some(RequirementSource::SystemRequirementsToml {
file: requirements_file.clone(),
}),
);
requirements.mcp_servers = Some(Sourced::new(
BTreeMap::from([(
"docs".to_string(),
McpServerRequirement {
identity: McpServerIdentity::Command {
command: "codex-mcp".to_string(),
let requirements = ConfigRequirements {
approval_policy: ConstrainedWithSource::new(
Constrained::allow_any(AskForApproval::OnRequest),
Some(RequirementSource::CloudRequirements),
),
sandbox_policy: ConstrainedWithSource::new(
Constrained::allow_any(SandboxPolicy::ReadOnly),
Some(RequirementSource::SystemRequirementsToml {
file: requirements_file.clone(),
}),
),
mcp_servers: Some(Sourced::new(
BTreeMap::from([(
"docs".to_string(),
McpServerRequirement {
identity: McpServerIdentity::Command {
command: "codex-mcp".to_string(),
},
},
)]),
RequirementSource::LegacyManagedConfigTomlFromMdm,
)),
enforce_residency: ConstrainedWithSource::new(
Constrained::allow_any(Some(ResidencyRequirement::Us)),
Some(RequirementSource::CloudRequirements),
),
web_search_mode: ConstrainedWithSource::new(
Constrained::allow_any(WebSearchMode::Cached),
Some(RequirementSource::CloudRequirements),
),
network: Some(Sourced::new(
NetworkConstraints {
enabled: Some(true),
allowed_domains: Some(vec!["example.com".to_string()]),
..Default::default()
},
)]),
RequirementSource::LegacyManagedConfigTomlFromMdm,
));
requirements.enforce_residency = ConstrainedWithSource::new(
Constrained::allow_any(Some(ResidencyRequirement::Us)),
Some(RequirementSource::CloudRequirements),
);
requirements.web_search_mode = ConstrainedWithSource::new(
Constrained::allow_any(WebSearchMode::Cached),
Some(RequirementSource::CloudRequirements),
);
requirements.network = Some(Sourced::new(
NetworkConstraints {
enabled: Some(true),
allowed_domains: Some(vec!["example.com".to_string()]),
..Default::default()
},
RequirementSource::CloudRequirements,
));
RequirementSource::CloudRequirements,
)),
..ConfigRequirements::default()
};
let requirements_toml = ConfigRequirementsToml {
allowed_approval_policies: Some(vec![AskForApproval::OnRequest]),
@ -631,11 +633,13 @@ approval_policy = "never"
#[test]
fn debug_config_output_normalizes_empty_web_search_mode_list() {
let mut requirements = ConfigRequirements::default();
requirements.web_search_mode = ConstrainedWithSource::new(
Constrained::allow_any(WebSearchMode::Disabled),
Some(RequirementSource::CloudRequirements),
);
let requirements = ConfigRequirements {
web_search_mode: ConstrainedWithSource::new(
Constrained::allow_any(WebSearchMode::Disabled),
Some(RequirementSource::CloudRequirements),
),
..ConfigRequirements::default()
};
let requirements_toml = ConfigRequirementsToml {
allowed_approval_policies: None,