mirror of
https://github.com/openai/codex.git
synced 2026-11-05 20:10:33 +00:00
Add runtime assertion authentication modes and an auth provider (#55636)
## What changed Add `RuntimeAuthProvider` to resolve request authentication through the runtime auth manager. Support `dual_header` mode, which sends a bearer credential alongside `x-openai-agent-assertion`, and `assertion_only` mode, which uses `Authorization: AgentAssertion …`. Replace stale authentication headers and sign a fresh assertion for each request attempt. Propagate registration failures without falling back to credential-only authentication, preserving policy errors and classifying transport failures, rate limits, and server errors as transient. Add the disabled-by-default `features.runtime_agent_instances` configuration with independent `enabled` and `mode` settings, schema support, and structured override merging. Selecting a mode alone does not enable the feature. ## Testing Add coverage for both modes with API key and ChatGPT credentials, stale header replacement, fresh assertions, credential refresh without runtime replacement, registration failures, and configuration parsing and merging. GitOrigin-RevId: 9e93d25762600f0ff592c5248fe4c8c2c8182c8d
This commit is contained in:
@@ -70,7 +70,11 @@ pub fn is_structured_feature_path<S: AsRef<str>>(path: &[S]) -> bool {
|
||||
features.as_ref() == "features"
|
||||
&& matches!(
|
||||
feature.as_ref(),
|
||||
"code_mode" | "multi_agent_v2" | "network_proxy" | "sleep_tool"
|
||||
"code_mode"
|
||||
| "multi_agent_v2"
|
||||
| "network_proxy"
|
||||
| "sleep_tool"
|
||||
| "runtime_agent_instances"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -295,33 +295,38 @@ fn code_mode_overrides_preserve_enabled_state_and_cell_overhead() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sleep_tool_overrides_preserve_disabled_state_and_mode() {
|
||||
for feature_path in ["features", "profiles.work.features"] {
|
||||
let disabled = (
|
||||
format!("{feature_path}.sleep_tool"),
|
||||
TomlValue::Boolean(false),
|
||||
);
|
||||
let mode = (
|
||||
format!("{feature_path}.sleep_tool.mode"),
|
||||
TomlValue::String("always_on".to_string()),
|
||||
);
|
||||
let expected = parse_toml(&format!(
|
||||
"[{feature_path}.sleep_tool]\nenabled = false\nmode = \"always_on\"\n",
|
||||
));
|
||||
for overrides in [vec![disabled.clone(), mode.clone()], vec![mode, disabled]] {
|
||||
assert_eq!(crate::build_cli_overrides_layer(&overrides), expected);
|
||||
}
|
||||
fn structured_mode_overrides_preserve_disabled_state_and_mode() {
|
||||
for (feature, selected_mode) in [
|
||||
("sleep_tool", "always_on"),
|
||||
("runtime_agent_instances", "assertion_only"),
|
||||
] {
|
||||
for feature_path in ["features", "profiles.work.features"] {
|
||||
let disabled = (
|
||||
format!("{feature_path}.{feature}"),
|
||||
TomlValue::Boolean(false),
|
||||
);
|
||||
let mode = (
|
||||
format!("{feature_path}.{feature}.mode"),
|
||||
TomlValue::String(selected_mode.to_string()),
|
||||
);
|
||||
let expected = parse_toml(&format!(
|
||||
"[{feature_path}.{feature}]\nenabled = false\nmode = \"{selected_mode}\"\n",
|
||||
));
|
||||
for overrides in [vec![disabled.clone(), mode.clone()], vec![mode, disabled]] {
|
||||
assert_eq!(crate::build_cli_overrides_layer(&overrides), expected);
|
||||
}
|
||||
|
||||
let boolean_layer = parse_toml(&format!("[{feature_path}]\nsleep_tool = false\n"));
|
||||
let table_layer = parse_toml(&format!(
|
||||
"[{feature_path}.sleep_tool]\nmode = \"always_on\"\n",
|
||||
));
|
||||
for (mut base, overlay) in [
|
||||
(boolean_layer.clone(), table_layer.clone()),
|
||||
(table_layer, boolean_layer),
|
||||
] {
|
||||
merge_toml_values(&mut base, &overlay);
|
||||
assert_eq!(base, expected);
|
||||
let boolean_layer = parse_toml(&format!("[{feature_path}]\n{feature} = false\n"));
|
||||
let table_layer = parse_toml(&format!(
|
||||
"[{feature_path}.{feature}]\nmode = \"{selected_mode}\"\n",
|
||||
));
|
||||
for (mut base, overlay) in [
|
||||
(boolean_layer.clone(), table_layer.clone()),
|
||||
(table_layer, boolean_layer),
|
||||
] {
|
||||
merge_toml_values(&mut base, &overlay);
|
||||
assert_eq!(base, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,6 +153,15 @@ pub fn features_schema(schema_gen: &mut SchemaGenerator) -> Schema {
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if feature.id == codex_features::Feature::RuntimeAgentInstances {
|
||||
validation.properties.insert(
|
||||
feature.key.to_string(),
|
||||
schema_gen.subschema_for::<codex_features::FeatureToml<
|
||||
codex_features::RuntimeAgentInstancesConfigToml,
|
||||
>>(),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if feature.id == codex_features::Feature::AppsMcpPathOverride {
|
||||
validation.properties.insert(
|
||||
feature.key.to_string(),
|
||||
|
||||
Reference in New Issue
Block a user