Switch runtime to cloud config bundle (#24622)

## Summary

- Adapts the moved `codex-cloud-config` crate from the legacy cloud
requirements endpoint to the new config bundle endpoint.
- Switches runtime consumers from `CloudRequirementsLoader` to
`CloudConfigBundleLoader` so one shared bundle supplies cloud-delivered
config and requirements.
- Removes the legacy cloud requirements domain loader path.

## Details

This intentionally keeps `codex-cloud-config` monolithic for review
lineage: the previous PR establishes the crate move, and this PR shows
the behavior change against that moved implementation. A follow-up PR
splits the module back into focused files.

The new bundle path preserves the important cloud requirements loader
semantics where intended: account-scoped signed cache, 30 minute TTL, 5
minute refresh cadence, retry/backoff, auth recovery, and fail-closed
startup loading. The cached payload changes from a single requirements
TOML string to the backend-delivered bundle, and validation rejects
malformed config or requirements fragments before cache write/use.
This commit is contained in:
joeflorencio-openai authored and GitHub committed 2026-06-02 13:18:59 -07:00
1 parent b794182ea7
commit d45cd26248
60 files changed
+2614 -2339

No files matched your search

@@ -586,7 +586,7 @@ impl AccountRequestProcessor {
)
.map_err(|err| internal_error(format!("failed to set external auth: {err}")))?;
self.auth_manager.reload().await;
self.config_manager.replace_cloud_requirements_loader(
self.config_manager.replace_cloud_config_bundle_loader(
self.auth_manager.clone(),
self.config.chatgpt_base_url.clone(),
);
@@ -645,7 +645,7 @@ impl AccountRequestProcessor {
let auth_manager = thread_manager.auth_manager();
auth_manager.reload().await;
config_manager
.replace_cloud_requirements_loader(auth_manager.clone(), chatgpt_base_url);
.replace_cloud_config_bundle_loader(auth_manager.clone(), chatgpt_base_url);
config_manager
.sync_default_client_residency_requirement()
.await;
@@ -1,11 +1,11 @@
use super::*;
fn cloud_requirements_load_error(err: &std::io::Error) -> Option<&CloudRequirementsLoadError> {
fn cloud_config_bundle_load_error(err: &std::io::Error) -> Option<&CloudConfigBundleLoadError> {
let mut current: Option<&(dyn std::error::Error + 'static)> = err
.get_ref()
.map(|source| source as &(dyn std::error::Error + 'static));
while let Some(source) = current {
if let Some(cloud_error) = source.downcast_ref::<CloudRequirementsLoadError>() {
if let Some(cloud_error) = source.downcast_ref::<CloudConfigBundleLoadError>() {
return Some(cloud_error);
}
current = source.source();
@@ -14,16 +14,16 @@ fn cloud_requirements_load_error(err: &std::io::Error) -> Option<&CloudRequireme
}
pub(super) fn config_load_error(err: &std::io::Error) -> JSONRPCErrorError {
let data = cloud_requirements_load_error(err).map(|cloud_error| {
let data = cloud_config_bundle_load_error(err).map(|cloud_error| {
let mut data = serde_json::json!({
"reason": "cloudRequirements",
"reason": "cloudConfigBundle",
"errorCode": format!("{:?}", cloud_error.code()),
"detail": cloud_error.to_string(),
});
if let Some(status_code) = cloud_error.status_code() {
data["statusCode"] = serde_json::json!(status_code);
}
if cloud_error.code() == CloudRequirementsLoadErrorCode::Auth {
if cloud_error.code() == CloudConfigBundleLoadErrorCode::Auth {
data["action"] = serde_json::json!("relogin");
}
data
@@ -54,7 +54,7 @@ mod thread_processor_behavior_tests {
use codex_app_server_protocol::ServerRequestPayload;
use codex_app_server_protocol::ThreadItem;
use codex_app_server_protocol::ToolRequestUserInputParams;
use codex_config::CloudRequirementsLoader;
use codex_config::CloudConfigBundleLoader;
use codex_config::LoaderOverrides;
use codex_config::SessionThreadConfig;
use codex_config::StaticThreadConfigLoader;
@@ -508,9 +508,9 @@ mod thread_processor_behavior_tests {
}
#[test]
fn config_load_error_marks_cloud_requirements_failures_for_relogin() {
let err = std::io::Error::other(CloudRequirementsLoadError::new(
CloudRequirementsLoadErrorCode::Auth,
fn config_load_error_marks_cloud_config_bundle_failures_for_relogin() {
let err = std::io::Error::other(CloudConfigBundleLoadError::new(
CloudConfigBundleLoadErrorCode::Auth,
Some(401),
"Your authentication session could not be refreshed automatically. Please log out and sign in again.",
));
@@ -520,7 +520,7 @@ mod thread_processor_behavior_tests {
assert_eq!(
error.data,
Some(json!({
"reason": "cloudRequirements",
"reason": "cloudConfigBundle",
"errorCode": "Auth",
"action": "relogin",
"statusCode": 401,
@@ -535,7 +535,7 @@ mod thread_processor_behavior_tests {
}
#[test]
fn config_load_error_leaves_non_cloud_requirements_failures_unmarked() {
fn config_load_error_leaves_non_cloud_config_bundle_failures_unmarked() {
let err = std::io::Error::other("required MCP servers failed to initialize");
let error = config_load_error(&err);
@@ -549,11 +549,11 @@ mod thread_processor_behavior_tests {
}
#[test]
fn config_load_error_marks_non_auth_cloud_requirements_failures_without_relogin() {
let err = std::io::Error::other(CloudRequirementsLoadError::new(
CloudRequirementsLoadErrorCode::RequestFailed,
fn config_load_error_marks_non_auth_cloud_config_bundle_failures_without_relogin() {
let err = std::io::Error::other(CloudConfigBundleLoadError::new(
CloudConfigBundleLoadErrorCode::RequestFailed,
/*status_code*/ None,
"Failed to load cloud requirements (workspace-managed policies).",
"Failed to load cloud config bundle (workspace-managed policies).",
));
let error = config_load_error(&err);
@@ -561,9 +561,29 @@ mod thread_processor_behavior_tests {
assert_eq!(
error.data,
Some(json!({
"reason": "cloudRequirements",
"reason": "cloudConfigBundle",
"errorCode": "RequestFailed",
"detail": "Failed to load cloud requirements (workspace-managed policies).",
"detail": "Failed to load cloud config bundle (workspace-managed policies).",
}))
);
}
#[test]
fn config_load_error_marks_invalid_cloud_config_bundle_failures_without_relogin() {
let err = std::io::Error::other(CloudConfigBundleLoadError::new(
CloudConfigBundleLoadErrorCode::InvalidBundle,
/*status_code*/ None,
"invalid cloud config bundle: invalid cloud config fragment Base policy (cfg_123)",
));
let error = config_load_error(&err);
assert_eq!(
error.data,
Some(json!({
"reason": "cloudConfigBundle",
"errorCode": "InvalidBundle",
"detail": "invalid cloud config bundle: invalid cloud config fragment Base policy (cfg_123)",
}))
);
}
@@ -595,7 +615,7 @@ mod thread_processor_behavior_tests {
Vec::new(),
LoaderOverrides::default(),
/*strict_config*/ false,
CloudRequirementsLoader::default(),
CloudConfigBundleLoader::default(),
Arg0DispatchPaths::default(),
Arc::new(StaticThreadConfigLoader::new(vec![
ThreadConfigSource::Session(SessionThreadConfig {