Enforce managed residency for model providers (#39645)

## Why

Model provider configuration could override the residency header required by
`enforce_residency`, so provider-backed requests did not reliably honor the
managed setting.

## What changed

- Apply the managed residency header after building a provider, making it
  authoritative for model requests and model discovery.
- Warn when a provider configures the residency header through
  `http_headers` or `env_http_headers`, while preserving the original provider
  configuration and unrelated headers.
- Cover HTTP and WebSocket requests, model discovery, and case-insensitive
  header detection with targeted tests.

GitOrigin-RevId: 461ef8989d5bd06ffdea694aee4265e392e07590
This commit is contained in:
Anton Panasenko authored and copyberry committed 2026-08-20 07:33:27 +00:00
1 parent 663da53823
commit af0e82c562
7 files changed
+371 -3

No files matched your search

+83
View File
@@ -73,6 +73,7 @@ use codex_config::types::WindowsToml;
use codex_exec_server::LOCAL_FS;
use codex_features::Feature;
use codex_features::FeaturesToml;
use codex_login::default_client::RESIDENCY_HEADER_NAME;
use codex_login::test_support::auth_manager_from_optional_auth;
use codex_model_provider::ProviderCapabilities;
use codex_model_provider_info::LMSTUDIO_OSS_PROVIDER_ID;
@@ -947,6 +948,88 @@ profile = "codex-bedrock"
);
}
#[tokio::test]
async fn managed_residency_warns_about_provider_header_overrides_without_mutating_config()
-> std::io::Result<()> {
for enforce_residency in [None, Some(ResidencyRequirement::Us)] {
let cfg = toml::from_str::<ConfigToml>(
r#"
model_provider = "custom-openai"
[model_providers.custom-openai]
name = "OpenAI"
http_headers = { "X-OpenAI-Internal-Codex-Residency" = "request-override", "x-provider-header" = "preserved" }
env_http_headers = { "x-openai-internal-codex-residency" = "CODEX_TEST_UNSET_RESIDENCY_HEADER", "x-provider-env-header" = "CODEX_TEST_UNSET_PROVIDER_HEADER" }
"#,
)
.expect("existing provider configuration should remain loadable");
let requirements = ConfigRequirements {
enforce_residency: ConstrainedWithSource::new(
Constrained::allow_only(enforce_residency),
enforce_residency.map(|_| RequirementSource::Unknown),
),
..Default::default()
};
let requirements_toml = ConfigRequirementsToml {
enforce_residency,
..Default::default()
};
let config_layer_stack =
ConfigLayerStack::new(Vec::new(), requirements, requirements_toml)?;
let config = Config::load_config_with_layer_stack(
LOCAL_FS.as_ref(),
cfg,
ConfigOverrides::default(),
tempdir()?.abs(),
config_layer_stack,
)
.await?;
let static_headers = config
.model_provider
.http_headers
.as_ref()
.expect("static headers should remain configured");
let environment_headers = config
.model_provider
.env_http_headers
.as_ref()
.expect("environment-backed headers should remain configured");
assert_eq!(
static_headers
.get("X-OpenAI-Internal-Codex-Residency")
.map(String::as_str),
Some("request-override")
);
assert_eq!(
environment_headers
.get(RESIDENCY_HEADER_NAME)
.map(String::as_str),
Some("CODEX_TEST_UNSET_RESIDENCY_HEADER")
);
assert_eq!(
static_headers.get("x-provider-header").map(String::as_str),
Some("preserved")
);
assert_eq!(
environment_headers
.get("x-provider-env-header")
.map(String::as_str),
Some("CODEX_TEST_UNSET_PROVIDER_HEADER")
);
let expected_warning = format!(
"Ignoring `{RESIDENCY_HEADER_NAME}` in `model_providers.custom-openai` because managed residency is required."
);
assert_eq!(
config.startup_warnings.contains(&expected_warning),
enforce_residency.is_some()
);
}
Ok(())
}
#[test]
fn accepts_amazon_bedrock_aws_profile_override() {
let cfg = toml::from_str::<ConfigToml>(
+21
View File
@@ -5,6 +5,7 @@ use codex_config::config_toml::ConfigToml;
use codex_config::types::ApprovalsReviewer;
use codex_config::types::FeedbackConfigToml;
use codex_features::FeatureToml;
use codex_login::default_client::RESIDENCY_HEADER_NAME;
use codex_utils_absolute_path::AbsolutePathBuf;
use std::path::Path;
@@ -47,6 +48,26 @@ pub(super) fn apply_to_config(
requirements.feedback.as_ref(),
startup_warnings,
);
if requirements.enforce_residency.value().is_some() {
for (provider_name, provider) in &config.model_providers {
let has_residency_header = [&provider.http_headers, &provider.env_http_headers]
.into_iter()
.flatten()
.any(|headers| {
headers
.keys()
.any(|name| name.eq_ignore_ascii_case(RESIDENCY_HEADER_NAME))
});
if has_residency_header {
let warning = format!(
"Ignoring `{RESIDENCY_HEADER_NAME}` in `model_providers.{provider_name}` because managed residency is required."
);
tracing::warn!(provider = provider_name, "{warning}");
startup_warnings.push(warning);
}
}
}
if let Some(requirement) = requirements.windows_sandbox_private_desktop.as_ref() {
apply_exact_requirement(
"windows.sandbox_private_desktop",