Fetch Requirements from cloud (#10167)

Load requirements from Codex Backend. It only does this for enterprise
customers signed in with ChatGPT.

Todo in follow-up PRs:
* Add to app-server and exec too
* Switch from fail-open to fail-closed on failure
This commit is contained in:
gt-oai
2026-01-30 12:03:29 +00:00
committed by GitHub
parent 1ef5455eb6
commit e85d019daa
17 changed files with 673 additions and 17 deletions

View File

@@ -1,3 +1,4 @@
mod cloud_requirements;
mod config_requirements;
mod diagnostics;
mod fingerprint;
@@ -30,6 +31,7 @@ use std::io;
use std::path::Path;
use toml::Value as TomlValue;
pub use cloud_requirements::CloudRequirementsLoader;
pub use config_requirements::ConfigRequirements;
pub use config_requirements::ConfigRequirementsToml;
pub use config_requirements::McpServerIdentity;
@@ -69,6 +71,7 @@ const DEFAULT_PROJECT_ROOT_MARKERS: &[&str] = &[".git"];
/// earlier layer cannot be overridden by a later layer:
///
/// - admin: managed preferences (*)
/// - cloud: managed cloud requirements
/// - system `/etc/codex/requirements.toml`
///
/// For backwards compatibility, we also load from
@@ -98,6 +101,7 @@ pub async fn load_config_layers_state(
cwd: Option<AbsolutePathBuf>,
cli_overrides: &[(String, TomlValue)],
overrides: LoaderOverrides,
cloud_requirements: Option<CloudRequirementsLoader>, // TODO(gt): Once exec and app-server are wired up, we can remove the option.
) -> io::Result<ConfigLayerStack> {
let mut config_requirements_toml = ConfigRequirementsWithSources::default();
@@ -110,6 +114,13 @@ pub async fn load_config_layers_state(
)
.await?;
if let Some(loader) = cloud_requirements
&& let Some(requirements) = loader.get().await
{
config_requirements_toml
.merge_unset_fields(RequirementSource::CloudRequirements, requirements);
}
// Honor /etc/codex/requirements.toml.
if cfg!(unix) {
load_requirements_toml(