mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
Enforce automatic review for managed models (#37511)
## What changed - Add the managed `auto_review.required_on_models` requirement, unioning model slugs across requirement layers and exposing the result through `configRequirements/read`. - Force listed models to use `on-request` approvals with the `auto_review` reviewer. Downgrade Full Access to workspace-write when starting a protected session, and reject incompatible runtime overrides or use when automatic review is disabled. - Preserve these protections across thread starts, resumes, forks, model changes, turn overrides, MCP approvals, and TUI session attachment. ## Testing - Add coverage for layered model requirements and exact provider-alias matching. - Add app-server tests for protected thread lifecycle operations, unsafe setting overrides, legacy thread upgrades, disabled automatic review, and requirements API output. GitOrigin-RevId: c4b1d52c3b5b75e86880725412b8f0812e0dfcd9
This commit is contained in:
1 parent
8073dbb20b
commit
208f05b233
37 files changed
+944
-36
No files matched your search
@@ -109,6 +109,8 @@ pub(crate) struct SessionConfiguration {
|
||||
pub(super) metrics_service_name: Option<String>,
|
||||
pub(super) app_server_client_name: Option<String>,
|
||||
pub(super) app_server_client_version: Option<String>,
|
||||
/// Guardian reviewer identity is trusted only when established during an in-memory spawn.
|
||||
pub(super) trusted_guardian_reviewer: bool,
|
||||
/// Source of the session (cli, vscode, exec, mcp, ...)
|
||||
pub(super) session_source: SessionSource,
|
||||
/// Persisted thread history contract selected when this thread was created.
|
||||
@@ -251,6 +253,38 @@ impl SessionConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn validate_auto_review_requirement(&self) -> ConstraintResult<()> {
|
||||
if self.trusted_guardian_reviewer {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let requirements = self
|
||||
.original_config_do_not_use
|
||||
.config_layer_stack
|
||||
.requirements();
|
||||
let model = self.collaboration_mode.model();
|
||||
if !requirements.auto_review_required_for_model(model) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if self.approval_policy.value() == AskForApproval::OnRequest
|
||||
&& self.approvals_reviewer == ApprovalsReviewer::AutoReview
|
||||
&& !self
|
||||
.file_system_sandbox_policy()
|
||||
.has_full_disk_write_access()
|
||||
&& self
|
||||
.original_config_do_not_use
|
||||
.features
|
||||
.enabled(Feature::GuardianApproval)
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
Err(ConstraintError::AutoReviewRequired {
|
||||
model: model.to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn apply(&self, updates: &SessionSettingsUpdate) -> ConstraintResult<Self> {
|
||||
let mut next_configuration = self.clone();
|
||||
let current_sandbox_policy = self.sandbox_policy();
|
||||
@@ -303,8 +337,37 @@ impl SessionConfiguration {
|
||||
next_configuration.approval_policy.set(approval_policy)?;
|
||||
}
|
||||
if let Some(approvals_reviewer) = updates.approvals_reviewer {
|
||||
next_configuration
|
||||
.original_config_do_not_use
|
||||
.config_layer_stack
|
||||
.requirements()
|
||||
.approvals_reviewer
|
||||
.can_set(&approvals_reviewer)?;
|
||||
next_configuration.approvals_reviewer = approvals_reviewer;
|
||||
}
|
||||
if !next_configuration.trusted_guardian_reviewer
|
||||
&& self.collaboration_mode.model() != next_configuration.collaboration_mode.model()
|
||||
&& next_configuration
|
||||
.original_config_do_not_use
|
||||
.config_layer_stack
|
||||
.requirements()
|
||||
.auto_review_required_for_model(next_configuration.collaboration_mode.model())
|
||||
{
|
||||
if updates.approval_policy.is_none() {
|
||||
next_configuration
|
||||
.approval_policy
|
||||
.set(AskForApproval::OnRequest)?;
|
||||
}
|
||||
if updates.approvals_reviewer.is_none() {
|
||||
next_configuration
|
||||
.original_config_do_not_use
|
||||
.config_layer_stack
|
||||
.requirements()
|
||||
.approvals_reviewer
|
||||
.can_set(&ApprovalsReviewer::AutoReview)?;
|
||||
next_configuration.approvals_reviewer = ApprovalsReviewer::AutoReview;
|
||||
}
|
||||
}
|
||||
if let Some(windows_sandbox_level) = updates.windows_sandbox_level {
|
||||
next_configuration.windows_sandbox_level = windows_sandbox_level;
|
||||
}
|
||||
@@ -405,6 +468,7 @@ impl SessionConfiguration {
|
||||
if let Some(app_server_client_version) = updates.app_server_client_version.clone() {
|
||||
next_configuration.app_server_client_version = Some(app_server_client_version);
|
||||
}
|
||||
next_configuration.validate_auto_review_requirement()?;
|
||||
Ok(next_configuration)
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user