mirror of
https://github.com/openai/codex.git
synced 2026-04-27 08:05:51 +00:00
Update guardian output schema (#17061)
## Summary - Update guardian output schema to separate risk, authorization, outcome, and rationale. - Feed guardian rationale into rejection messages. - Split the guardian policy into template and tenant-config sections. ## Validation - `cargo test -p codex-core mcp_tool_call` - `env -u CODEX_SANDBOX_NETWORK_DISABLED INSTA_UPDATE=always cargo test -p codex-core guardian::` --------- Co-authored-by: Owen Lin <owen@openai.com>
This commit is contained in:
@@ -514,7 +514,7 @@ pub struct ConfigRequirementsToml {
|
||||
pub enforce_residency: Option<ResidencyRequirement>,
|
||||
#[serde(rename = "experimental_network")]
|
||||
pub network: Option<NetworkRequirementsToml>,
|
||||
pub guardian_developer_instructions: Option<String>,
|
||||
pub guardian_policy_config: Option<String>,
|
||||
}
|
||||
|
||||
/// Value paired with the requirement source it came from, for better error
|
||||
@@ -551,7 +551,7 @@ pub struct ConfigRequirementsWithSources {
|
||||
pub rules: Option<Sourced<RequirementsExecPolicyToml>>,
|
||||
pub enforce_residency: Option<Sourced<ResidencyRequirement>>,
|
||||
pub network: Option<Sourced<NetworkRequirementsToml>>,
|
||||
pub guardian_developer_instructions: Option<Sourced<String>>,
|
||||
pub guardian_policy_config: Option<Sourced<String>>,
|
||||
}
|
||||
|
||||
impl ConfigRequirementsWithSources {
|
||||
@@ -583,16 +583,16 @@ impl ConfigRequirementsWithSources {
|
||||
rules: _,
|
||||
enforce_residency: _,
|
||||
network: _,
|
||||
guardian_developer_instructions: _,
|
||||
guardian_policy_config: _,
|
||||
} = &other;
|
||||
|
||||
let mut other = other;
|
||||
if other
|
||||
.guardian_developer_instructions
|
||||
.guardian_policy_config
|
||||
.as_deref()
|
||||
.is_some_and(|value| value.trim().is_empty())
|
||||
{
|
||||
other.guardian_developer_instructions = None;
|
||||
other.guardian_policy_config = None;
|
||||
}
|
||||
fill_missing_take!(
|
||||
self,
|
||||
@@ -608,7 +608,7 @@ impl ConfigRequirementsWithSources {
|
||||
rules,
|
||||
enforce_residency,
|
||||
network,
|
||||
guardian_developer_instructions,
|
||||
guardian_policy_config,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -633,7 +633,7 @@ impl ConfigRequirementsWithSources {
|
||||
rules,
|
||||
enforce_residency,
|
||||
network,
|
||||
guardian_developer_instructions,
|
||||
guardian_policy_config,
|
||||
} = self;
|
||||
ConfigRequirementsToml {
|
||||
allowed_approval_policies: allowed_approval_policies.map(|sourced| sourced.value),
|
||||
@@ -646,8 +646,7 @@ impl ConfigRequirementsWithSources {
|
||||
rules: rules.map(|sourced| sourced.value),
|
||||
enforce_residency: enforce_residency.map(|sourced| sourced.value),
|
||||
network: network.map(|sourced| sourced.value),
|
||||
guardian_developer_instructions: guardian_developer_instructions
|
||||
.map(|sourced| sourced.value),
|
||||
guardian_policy_config: guardian_policy_config.map(|sourced| sourced.value),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -704,7 +703,7 @@ impl ConfigRequirementsToml {
|
||||
&& self.enforce_residency.is_none()
|
||||
&& self.network.is_none()
|
||||
&& self
|
||||
.guardian_developer_instructions
|
||||
.guardian_policy_config
|
||||
.as_deref()
|
||||
.is_none_or(|value| value.trim().is_empty())
|
||||
}
|
||||
@@ -725,7 +724,7 @@ impl TryFrom<ConfigRequirementsWithSources> for ConfigRequirements {
|
||||
rules,
|
||||
enforce_residency,
|
||||
network,
|
||||
guardian_developer_instructions: _guardian_developer_instructions,
|
||||
guardian_policy_config: _guardian_policy_config,
|
||||
} = toml;
|
||||
|
||||
let approval_policy = match allowed_approval_policies {
|
||||
@@ -978,7 +977,7 @@ mod tests {
|
||||
rules,
|
||||
enforce_residency,
|
||||
network,
|
||||
guardian_developer_instructions,
|
||||
guardian_policy_config,
|
||||
} = toml;
|
||||
ConfigRequirementsWithSources {
|
||||
allowed_approval_policies: allowed_approval_policies
|
||||
@@ -997,7 +996,7 @@ mod tests {
|
||||
enforce_residency: enforce_residency
|
||||
.map(|value| Sourced::new(value, RequirementSource::Unknown)),
|
||||
network: network.map(|value| Sourced::new(value, RequirementSource::Unknown)),
|
||||
guardian_developer_instructions: guardian_developer_instructions
|
||||
guardian_policy_config: guardian_policy_config
|
||||
.map(|value| Sourced::new(value, RequirementSource::Unknown)),
|
||||
}
|
||||
}
|
||||
@@ -1023,8 +1022,7 @@ mod tests {
|
||||
};
|
||||
let enforce_residency = ResidencyRequirement::Us;
|
||||
let enforce_source = source.clone();
|
||||
let guardian_developer_instructions =
|
||||
"Use the company-managed guardian policy.".to_string();
|
||||
let guardian_policy_config = "Use the company-managed guardian policy.".to_string();
|
||||
|
||||
// Intentionally constructed without `..Default::default()` so adding a new field to
|
||||
// `ConfigRequirementsToml` forces this test to be updated.
|
||||
@@ -1039,7 +1037,7 @@ mod tests {
|
||||
rules: None,
|
||||
enforce_residency: Some(enforce_residency),
|
||||
network: None,
|
||||
guardian_developer_instructions: Some(guardian_developer_instructions.clone()),
|
||||
guardian_policy_config: Some(guardian_policy_config.clone()),
|
||||
};
|
||||
|
||||
target.merge_unset_fields(source.clone(), other);
|
||||
@@ -1069,10 +1067,7 @@ mod tests {
|
||||
rules: None,
|
||||
enforce_residency: Some(Sourced::new(enforce_residency, enforce_source)),
|
||||
network: None,
|
||||
guardian_developer_instructions: Some(Sourced::new(
|
||||
guardian_developer_instructions,
|
||||
source,
|
||||
)),
|
||||
guardian_policy_config: Some(Sourced::new(guardian_policy_config, source)),
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -1108,7 +1103,7 @@ mod tests {
|
||||
rules: None,
|
||||
enforce_residency: None,
|
||||
network: None,
|
||||
guardian_developer_instructions: None,
|
||||
guardian_policy_config: None,
|
||||
}
|
||||
);
|
||||
Ok(())
|
||||
@@ -1152,7 +1147,7 @@ mod tests {
|
||||
rules: None,
|
||||
enforce_residency: None,
|
||||
network: None,
|
||||
guardian_developer_instructions: None,
|
||||
guardian_policy_config: None,
|
||||
}
|
||||
);
|
||||
Ok(())
|
||||
@@ -1164,7 +1159,7 @@ mod tests {
|
||||
target.merge_unset_fields(
|
||||
RequirementSource::CloudRequirements,
|
||||
ConfigRequirementsToml {
|
||||
guardian_developer_instructions: Some(" \n\t".to_string()),
|
||||
guardian_policy_config: Some(" \n\t".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
@@ -1174,15 +1169,13 @@ mod tests {
|
||||
.expect("system requirements.toml path"),
|
||||
},
|
||||
ConfigRequirementsToml {
|
||||
guardian_developer_instructions: Some(
|
||||
"Use the system guardian policy.".to_string(),
|
||||
),
|
||||
guardian_policy_config: Some("Use the system guardian policy.".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
target.guardian_developer_instructions,
|
||||
target.guardian_policy_config,
|
||||
Some(Sourced::new(
|
||||
"Use the system guardian policy.".to_string(),
|
||||
RequirementSource::SystemRequirementsToml {
|
||||
@@ -1194,27 +1187,27 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_guardian_developer_instructions() -> Result<()> {
|
||||
fn deserialize_guardian_policy_config() -> Result<()> {
|
||||
let requirements: ConfigRequirementsToml = from_str(
|
||||
r#"
|
||||
guardian_developer_instructions = """
|
||||
guardian_policy_config = """
|
||||
Use the cloud-managed guardian policy.
|
||||
"""
|
||||
"#,
|
||||
)?;
|
||||
|
||||
assert_eq!(
|
||||
requirements.guardian_developer_instructions.as_deref(),
|
||||
requirements.guardian_policy_config.as_deref(),
|
||||
Some("Use the cloud-managed guardian policy.\n")
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn blank_guardian_developer_instructions_is_empty() -> Result<()> {
|
||||
fn blank_guardian_policy_config_is_empty() -> Result<()> {
|
||||
let requirements: ConfigRequirementsToml = from_str(
|
||||
r#"
|
||||
guardian_developer_instructions = """
|
||||
guardian_policy_config = """
|
||||
|
||||
"""
|
||||
"#,
|
||||
|
||||
Reference in New Issue
Block a user