mirror of
https://github.com/openai/codex.git
synced 2026-11-10 08:43:33 +00:00
Expand browser and computer use requirements (#39995)
## What changed - Add a top-level `allow_browser_and_computer_use` requirement. - Support browser requirements for history access, automatic review, persistent approvals, and default or per-origin access policies. - Support computer-use requirements for persistent approvals, default app access, macOS bundle IDs, Windows AUMIDs, and Windows executables. - Preserve these settings and their sources when composing layered requirements. ## Testing - Cover deserialization, empty-value detection, source propagation, and layered TOML merging for the new requirements. GitOrigin-RevId: d14a10b64465f1c54e9bcc3795dc93031e6b029b
This commit is contained in:
1 parent
56012fafb8
commit
950dd184a1
8 files changed
+464
-27
No files matched your search
@@ -790,6 +790,7 @@ mod tests {
|
|||||||
let mapped = map_requirements_toml_to_api(ConfigRequirementsToml {
|
let mapped = map_requirements_toml_to_api(ConfigRequirementsToml {
|
||||||
computer_use: Some(ComputerUseRequirementsToml {
|
computer_use: Some(ComputerUseRequirementsToml {
|
||||||
allow_locked_computer_use: Some(false),
|
allow_locked_computer_use: Some(false),
|
||||||
|
..ComputerUseRequirementsToml::default()
|
||||||
}),
|
}),
|
||||||
..ConfigRequirementsToml::default()
|
..ConfigRequirementsToml::default()
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
use serde::Deserialize;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum AllowDenyRequirementToml {
|
||||||
|
Allow,
|
||||||
|
Deny,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug, Clone, Default, PartialEq, Eq)]
|
||||||
|
pub struct BrowserUseOriginPolicyToml {
|
||||||
|
pub access: Option<AllowDenyRequirementToml>,
|
||||||
|
pub downloads: Option<AllowDenyRequirementToml>,
|
||||||
|
pub uploads: Option<AllowDenyRequirementToml>,
|
||||||
|
pub full_cdp_access: Option<AllowDenyRequirementToml>,
|
||||||
|
pub auto_review: Option<AllowDenyRequirementToml>,
|
||||||
|
pub persistent_approval: Option<bool>,
|
||||||
|
pub access_approval_lifetime: Option<BrowserUseAccessApprovalLifetimeToml>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BrowserUseOriginPolicyToml {
|
||||||
|
fn is_empty(&self) -> bool {
|
||||||
|
self.access.is_none()
|
||||||
|
&& self.downloads.is_none()
|
||||||
|
&& self.uploads.is_none()
|
||||||
|
&& self.full_cdp_access.is_none()
|
||||||
|
&& self.auto_review.is_none()
|
||||||
|
&& self.persistent_approval.is_none()
|
||||||
|
&& self.access_approval_lifetime.is_none()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum BrowserUseAccessApprovalLifetimeToml {
|
||||||
|
Turn,
|
||||||
|
Thread,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug, Clone, Default, PartialEq, Eq)]
|
||||||
|
pub struct BrowserUseRequirementsToml {
|
||||||
|
pub allow_history_access: Option<bool>,
|
||||||
|
pub disable_auto_review: Option<bool>,
|
||||||
|
pub allow_global_persistent_approval: Option<bool>,
|
||||||
|
pub default_origin_policy: Option<BrowserUseOriginPolicyToml>,
|
||||||
|
pub origins: Option<BTreeMap<String, BrowserUseOriginPolicyToml>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BrowserUseRequirementsToml {
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.allow_history_access.is_none()
|
||||||
|
&& self.disable_auto_review.is_none()
|
||||||
|
&& self.allow_global_persistent_approval.is_none()
|
||||||
|
&& self
|
||||||
|
.default_origin_policy
|
||||||
|
.as_ref()
|
||||||
|
.is_none_or(BrowserUseOriginPolicyToml::is_empty)
|
||||||
|
&& self
|
||||||
|
.origins
|
||||||
|
.as_ref()
|
||||||
|
.is_none_or(|origins| origins.values().all(BrowserUseOriginPolicyToml::is_empty))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug, Clone, Default, PartialEq, Eq)]
|
||||||
|
pub struct ComputerUseMacosRequirementsToml {
|
||||||
|
pub bundle_ids: Option<BTreeMap<String, AllowDenyRequirementToml>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug, Clone, Default, PartialEq, Eq)]
|
||||||
|
pub struct ComputerUseWindowsRequirementsToml {
|
||||||
|
pub aumids: Option<BTreeMap<String, AllowDenyRequirementToml>>,
|
||||||
|
pub exes: Option<Vec<ComputerUseWindowsExeRequirementToml>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct ComputerUseWindowsExeRequirementToml {
|
||||||
|
pub publisher_name: String,
|
||||||
|
pub product_name: String,
|
||||||
|
pub binary_name: Option<String>,
|
||||||
|
pub access: AllowDenyRequirementToml,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug, Clone, Default, PartialEq, Eq)]
|
||||||
|
pub struct ComputerUseRequirementsToml {
|
||||||
|
pub allow_locked_computer_use: Option<bool>,
|
||||||
|
pub allow_persistent_approval: Option<bool>,
|
||||||
|
pub default_app_access: Option<AllowDenyRequirementToml>,
|
||||||
|
pub macos: Option<ComputerUseMacosRequirementsToml>,
|
||||||
|
pub windows: Option<ComputerUseWindowsRequirementsToml>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ComputerUseRequirementsToml {
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.allow_locked_computer_use.is_none()
|
||||||
|
&& self.allow_persistent_approval.is_none()
|
||||||
|
&& self.default_app_access.is_none()
|
||||||
|
&& self
|
||||||
|
.macos
|
||||||
|
.as_ref()
|
||||||
|
.is_none_or(|macos| macos.bundle_ids.as_ref().is_none_or(BTreeMap::is_empty))
|
||||||
|
&& self.windows.as_ref().is_none_or(|windows| {
|
||||||
|
windows.aumids.as_ref().is_none_or(BTreeMap::is_empty)
|
||||||
|
&& windows.exes.as_ref().is_none_or(Vec::is_empty)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,6 +27,8 @@ use crate::ManagedHooksRequirementsToml;
|
|||||||
use crate::McpServerRequirement;
|
use crate::McpServerRequirement;
|
||||||
use crate::PluginRequirementsToml;
|
use crate::PluginRequirementsToml;
|
||||||
use crate::RequirementsExecPolicy;
|
use crate::RequirementsExecPolicy;
|
||||||
|
use crate::browser_computer_use_requirements::BrowserUseRequirementsToml;
|
||||||
|
use crate::browser_computer_use_requirements::ComputerUseRequirementsToml;
|
||||||
use crate::config_toml::ConfigToml;
|
use crate::config_toml::ConfigToml;
|
||||||
use crate::mcp_requirements::validate_mcp_server_requirement;
|
use crate::mcp_requirements::validate_mcp_server_requirement;
|
||||||
use crate::mcp_types::AppToolApproval;
|
use crate::mcp_types::AppToolApproval;
|
||||||
@@ -793,28 +795,6 @@ impl fmt::Display for WebSearchModeRequirement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, Clone, Default, PartialEq, Eq)]
|
|
||||||
pub struct ComputerUseRequirementsToml {
|
|
||||||
pub allow_locked_computer_use: Option<bool>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ComputerUseRequirementsToml {
|
|
||||||
pub fn is_empty(&self) -> bool {
|
|
||||||
self.allow_locked_computer_use.is_none()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, Clone, Default, PartialEq, Eq)]
|
|
||||||
pub struct BrowserUseRequirementsToml {
|
|
||||||
pub disable_auto_review: Option<bool>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BrowserUseRequirementsToml {
|
|
||||||
pub fn is_empty(&self) -> bool {
|
|
||||||
self.disable_auto_review.is_none()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, Clone, Default, PartialEq, Eq)]
|
#[derive(Deserialize, Debug, Clone, Default, PartialEq, Eq)]
|
||||||
pub struct WindowsRequirementsToml {
|
pub struct WindowsRequirementsToml {
|
||||||
pub allowed_sandbox_implementations: Option<Vec<WindowsSandboxModeToml>>,
|
pub allowed_sandbox_implementations: Option<Vec<WindowsSandboxModeToml>>,
|
||||||
@@ -942,6 +922,7 @@ pub struct ConfigRequirementsToml {
|
|||||||
pub remote_sandbox_config: Option<Vec<RemoteSandboxConfigToml>>,
|
pub remote_sandbox_config: Option<Vec<RemoteSandboxConfigToml>>,
|
||||||
pub allowed_web_search_modes: Option<Vec<WebSearchModeRequirement>>,
|
pub allowed_web_search_modes: Option<Vec<WebSearchModeRequirement>>,
|
||||||
pub allow_managed_hooks_only: Option<bool>,
|
pub allow_managed_hooks_only: Option<bool>,
|
||||||
|
pub allow_browser_and_computer_use: Option<bool>,
|
||||||
pub allow_appshots: Option<bool>,
|
pub allow_appshots: Option<bool>,
|
||||||
pub allow_remote_control: Option<bool>,
|
pub allow_remote_control: Option<bool>,
|
||||||
pub computer_use: Option<ComputerUseRequirementsToml>,
|
pub computer_use: Option<ComputerUseRequirementsToml>,
|
||||||
@@ -1045,6 +1026,7 @@ pub struct ConfigRequirementsWithSources {
|
|||||||
pub default_permissions: Option<Sourced<String>>,
|
pub default_permissions: Option<Sourced<String>>,
|
||||||
pub allowed_web_search_modes: Option<Sourced<Vec<WebSearchModeRequirement>>>,
|
pub allowed_web_search_modes: Option<Sourced<Vec<WebSearchModeRequirement>>>,
|
||||||
pub allow_managed_hooks_only: Option<Sourced<bool>>,
|
pub allow_managed_hooks_only: Option<Sourced<bool>>,
|
||||||
|
pub allow_browser_and_computer_use: Option<Sourced<bool>>,
|
||||||
pub allow_appshots: Option<Sourced<bool>>,
|
pub allow_appshots: Option<Sourced<bool>>,
|
||||||
pub allow_remote_control: Option<Sourced<bool>>,
|
pub allow_remote_control: Option<Sourced<bool>>,
|
||||||
pub computer_use: Option<Sourced<ComputerUseRequirementsToml>>,
|
pub computer_use: Option<Sourced<ComputerUseRequirementsToml>>,
|
||||||
@@ -1104,6 +1086,7 @@ impl ConfigRequirementsWithSources {
|
|||||||
remote_sandbox_config: _,
|
remote_sandbox_config: _,
|
||||||
allowed_web_search_modes: _,
|
allowed_web_search_modes: _,
|
||||||
allow_managed_hooks_only: _,
|
allow_managed_hooks_only: _,
|
||||||
|
allow_browser_and_computer_use: _,
|
||||||
allow_appshots: _,
|
allow_appshots: _,
|
||||||
allow_remote_control: _,
|
allow_remote_control: _,
|
||||||
computer_use: _,
|
computer_use: _,
|
||||||
@@ -1156,6 +1139,7 @@ impl ConfigRequirementsWithSources {
|
|||||||
default_permissions,
|
default_permissions,
|
||||||
allowed_web_search_modes,
|
allowed_web_search_modes,
|
||||||
allow_managed_hooks_only,
|
allow_managed_hooks_only,
|
||||||
|
allow_browser_and_computer_use,
|
||||||
allow_appshots,
|
allow_appshots,
|
||||||
allow_remote_control,
|
allow_remote_control,
|
||||||
computer_use,
|
computer_use,
|
||||||
@@ -1237,6 +1221,7 @@ impl ConfigRequirementsWithSources {
|
|||||||
default_permissions,
|
default_permissions,
|
||||||
allowed_web_search_modes,
|
allowed_web_search_modes,
|
||||||
allow_managed_hooks_only,
|
allow_managed_hooks_only,
|
||||||
|
allow_browser_and_computer_use,
|
||||||
allow_appshots,
|
allow_appshots,
|
||||||
allow_remote_control,
|
allow_remote_control,
|
||||||
computer_use,
|
computer_use,
|
||||||
@@ -1277,6 +1262,8 @@ impl ConfigRequirementsWithSources {
|
|||||||
remote_sandbox_config: None,
|
remote_sandbox_config: None,
|
||||||
allowed_web_search_modes: allowed_web_search_modes.map(|sourced| sourced.value),
|
allowed_web_search_modes: allowed_web_search_modes.map(|sourced| sourced.value),
|
||||||
allow_managed_hooks_only: allow_managed_hooks_only.map(|sourced| sourced.value),
|
allow_managed_hooks_only: allow_managed_hooks_only.map(|sourced| sourced.value),
|
||||||
|
allow_browser_and_computer_use: allow_browser_and_computer_use
|
||||||
|
.map(|sourced| sourced.value),
|
||||||
allow_appshots: allow_appshots.map(|sourced| sourced.value),
|
allow_appshots: allow_appshots.map(|sourced| sourced.value),
|
||||||
allow_remote_control: allow_remote_control.map(|sourced| sourced.value),
|
allow_remote_control: allow_remote_control.map(|sourced| sourced.value),
|
||||||
computer_use: computer_use.map(|sourced| sourced.value),
|
computer_use: computer_use.map(|sourced| sourced.value),
|
||||||
@@ -1387,6 +1374,7 @@ impl ConfigRequirementsToml {
|
|||||||
&& self.remote_sandbox_config.is_none()
|
&& self.remote_sandbox_config.is_none()
|
||||||
&& self.allowed_web_search_modes.is_none()
|
&& self.allowed_web_search_modes.is_none()
|
||||||
&& self.allow_managed_hooks_only.is_none()
|
&& self.allow_managed_hooks_only.is_none()
|
||||||
|
&& self.allow_browser_and_computer_use.is_none()
|
||||||
&& self.allow_appshots.is_none()
|
&& self.allow_appshots.is_none()
|
||||||
&& self.allow_remote_control.is_none()
|
&& self.allow_remote_control.is_none()
|
||||||
&& self
|
&& self
|
||||||
@@ -1599,6 +1587,7 @@ impl TryFrom<ConfigRequirementsWithSources> for ConfigRequirements {
|
|||||||
default_permissions: _,
|
default_permissions: _,
|
||||||
allowed_web_search_modes,
|
allowed_web_search_modes,
|
||||||
allow_managed_hooks_only,
|
allow_managed_hooks_only,
|
||||||
|
allow_browser_and_computer_use: _,
|
||||||
allow_appshots,
|
allow_appshots,
|
||||||
allow_remote_control,
|
allow_remote_control,
|
||||||
computer_use,
|
computer_use,
|
||||||
@@ -2006,6 +1995,12 @@ pub fn sandbox_mode_requirement_for_permission_profile(
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::AllowDenyRequirementToml;
|
||||||
|
use crate::BrowserUseAccessApprovalLifetimeToml;
|
||||||
|
use crate::BrowserUseOriginPolicyToml;
|
||||||
|
use crate::ComputerUseMacosRequirementsToml;
|
||||||
|
use crate::ComputerUseWindowsExeRequirementToml;
|
||||||
|
use crate::ComputerUseWindowsRequirementsToml;
|
||||||
use crate::HookEventsToml;
|
use crate::HookEventsToml;
|
||||||
use crate::McpServerCommandMatcher;
|
use crate::McpServerCommandMatcher;
|
||||||
use crate::McpServerIdentity;
|
use crate::McpServerIdentity;
|
||||||
@@ -2129,6 +2124,7 @@ mod tests {
|
|||||||
remote_sandbox_config: _,
|
remote_sandbox_config: _,
|
||||||
allowed_web_search_modes,
|
allowed_web_search_modes,
|
||||||
allow_managed_hooks_only,
|
allow_managed_hooks_only,
|
||||||
|
allow_browser_and_computer_use,
|
||||||
allow_appshots,
|
allow_appshots,
|
||||||
allow_remote_control,
|
allow_remote_control,
|
||||||
computer_use,
|
computer_use,
|
||||||
@@ -2182,6 +2178,8 @@ mod tests {
|
|||||||
.map(|value| Sourced::new(value, RequirementSource::Unknown)),
|
.map(|value| Sourced::new(value, RequirementSource::Unknown)),
|
||||||
allow_managed_hooks_only: allow_managed_hooks_only
|
allow_managed_hooks_only: allow_managed_hooks_only
|
||||||
.map(|value| Sourced::new(value, RequirementSource::Unknown)),
|
.map(|value| Sourced::new(value, RequirementSource::Unknown)),
|
||||||
|
allow_browser_and_computer_use: allow_browser_and_computer_use
|
||||||
|
.map(|value| Sourced::new(value, RequirementSource::Unknown)),
|
||||||
allow_appshots: allow_appshots
|
allow_appshots: allow_appshots
|
||||||
.map(|value| Sourced::new(value, RequirementSource::Unknown)),
|
.map(|value| Sourced::new(value, RequirementSource::Unknown)),
|
||||||
allow_remote_control: allow_remote_control
|
allow_remote_control: allow_remote_control
|
||||||
@@ -2341,24 +2339,216 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn deserialize_computer_use_requirements() -> Result<()> {
|
fn deserialize_browser_and_computer_use_requirements() -> Result<()> {
|
||||||
let requirements: ConfigRequirementsToml = from_str(
|
let requirements: ConfigRequirementsToml = from_str(
|
||||||
r#"
|
r#"
|
||||||
|
allow_browser_and_computer_use = false
|
||||||
|
|
||||||
|
[browser_use]
|
||||||
|
allow_history_access = false
|
||||||
|
disable_auto_review = true
|
||||||
|
allow_global_persistent_approval = false
|
||||||
|
|
||||||
|
[browser_use.default_origin_policy]
|
||||||
|
access = "deny"
|
||||||
|
downloads = "allow"
|
||||||
|
uploads = "deny"
|
||||||
|
full_cdp_access = "allow"
|
||||||
|
auto_review = "deny"
|
||||||
|
persistent_approval = false
|
||||||
|
access_approval_lifetime = "turn"
|
||||||
|
|
||||||
|
[browser_use.origins."https://example.com"]
|
||||||
|
access = "allow"
|
||||||
|
downloads = "deny"
|
||||||
|
uploads = "allow"
|
||||||
|
full_cdp_access = "deny"
|
||||||
|
auto_review = "deny"
|
||||||
|
persistent_approval = true
|
||||||
|
access_approval_lifetime = "thread"
|
||||||
|
|
||||||
[computer_use]
|
[computer_use]
|
||||||
allow_locked_computer_use = false
|
allow_locked_computer_use = false
|
||||||
|
allow_persistent_approval = false
|
||||||
|
default_app_access = "deny"
|
||||||
|
|
||||||
|
[computer_use.macos.bundle_ids]
|
||||||
|
"com.apple.Safari" = "allow"
|
||||||
|
|
||||||
|
[computer_use.windows.aumids]
|
||||||
|
"Microsoft.Paint_8wekyb3d8bbwe!App" = "allow"
|
||||||
|
|
||||||
|
[[computer_use.windows.exes]]
|
||||||
|
publisher_name = "CN=Google LLC, O=Google LLC, L=Mountain View, S=California, C=US"
|
||||||
|
product_name = "Google Chrome"
|
||||||
|
binary_name = "chrome.exe"
|
||||||
|
access = "deny"
|
||||||
"#,
|
"#,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
assert_eq!(requirements.allow_browser_and_computer_use, Some(false));
|
||||||
|
assert_eq!(
|
||||||
|
requirements.browser_use,
|
||||||
|
Some(BrowserUseRequirementsToml {
|
||||||
|
allow_history_access: Some(false),
|
||||||
|
disable_auto_review: Some(true),
|
||||||
|
allow_global_persistent_approval: Some(false),
|
||||||
|
default_origin_policy: Some(BrowserUseOriginPolicyToml {
|
||||||
|
access: Some(AllowDenyRequirementToml::Deny),
|
||||||
|
downloads: Some(AllowDenyRequirementToml::Allow),
|
||||||
|
uploads: Some(AllowDenyRequirementToml::Deny),
|
||||||
|
full_cdp_access: Some(AllowDenyRequirementToml::Allow),
|
||||||
|
auto_review: Some(AllowDenyRequirementToml::Deny),
|
||||||
|
persistent_approval: Some(false),
|
||||||
|
access_approval_lifetime: Some(BrowserUseAccessApprovalLifetimeToml::Turn),
|
||||||
|
}),
|
||||||
|
origins: Some(BTreeMap::from([(
|
||||||
|
"https://example.com".to_string(),
|
||||||
|
BrowserUseOriginPolicyToml {
|
||||||
|
access: Some(AllowDenyRequirementToml::Allow),
|
||||||
|
downloads: Some(AllowDenyRequirementToml::Deny),
|
||||||
|
uploads: Some(AllowDenyRequirementToml::Allow),
|
||||||
|
full_cdp_access: Some(AllowDenyRequirementToml::Deny),
|
||||||
|
auto_review: Some(AllowDenyRequirementToml::Deny),
|
||||||
|
persistent_approval: Some(true),
|
||||||
|
access_approval_lifetime: Some(
|
||||||
|
BrowserUseAccessApprovalLifetimeToml::Thread,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
)])),
|
||||||
|
})
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
requirements.computer_use,
|
requirements.computer_use,
|
||||||
Some(ComputerUseRequirementsToml {
|
Some(ComputerUseRequirementsToml {
|
||||||
allow_locked_computer_use: Some(false),
|
allow_locked_computer_use: Some(false),
|
||||||
|
allow_persistent_approval: Some(false),
|
||||||
|
default_app_access: Some(AllowDenyRequirementToml::Deny),
|
||||||
|
macos: Some(ComputerUseMacosRequirementsToml {
|
||||||
|
bundle_ids: Some(BTreeMap::from([(
|
||||||
|
"com.apple.Safari".to_string(),
|
||||||
|
AllowDenyRequirementToml::Allow,
|
||||||
|
)])),
|
||||||
|
}),
|
||||||
|
windows: Some(ComputerUseWindowsRequirementsToml {
|
||||||
|
aumids: Some(BTreeMap::from([(
|
||||||
|
"Microsoft.Paint_8wekyb3d8bbwe!App".to_string(),
|
||||||
|
AllowDenyRequirementToml::Allow,
|
||||||
|
)])),
|
||||||
|
exes: Some(vec![ComputerUseWindowsExeRequirementToml {
|
||||||
|
publisher_name:
|
||||||
|
"CN=Google LLC, O=Google LLC, L=Mountain View, S=California, C=US"
|
||||||
|
.to_string(),
|
||||||
|
product_name: "Google Chrome".to_string(),
|
||||||
|
binary_name: Some("chrome.exe".to_string()),
|
||||||
|
access: AllowDenyRequirementToml::Deny,
|
||||||
|
}]),
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
assert!(!requirements.is_empty());
|
assert!(!requirements.is_empty());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn browser_and_computer_use_leaf_requirements_are_not_empty() -> Result<()> {
|
||||||
|
for (name, requirements_toml) in [
|
||||||
|
(
|
||||||
|
"browser history",
|
||||||
|
"[browser_use]\nallow_history_access = false",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"browser auto-review",
|
||||||
|
"[browser_use]\ndisable_auto_review = true",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"global persistent approval",
|
||||||
|
"[browser_use]\nallow_global_persistent_approval = false",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"default origin access",
|
||||||
|
"[browser_use.default_origin_policy]\naccess = \"deny\"",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"default origin downloads",
|
||||||
|
"[browser_use.default_origin_policy]\ndownloads = \"deny\"",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"default origin uploads",
|
||||||
|
"[browser_use.default_origin_policy]\nuploads = \"deny\"",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"default origin full CDP access",
|
||||||
|
"[browser_use.default_origin_policy]\nfull_cdp_access = \"deny\"",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"default origin auto-review",
|
||||||
|
"[browser_use.default_origin_policy]\nauto_review = \"deny\"",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"default origin persistent approval",
|
||||||
|
"[browser_use.default_origin_policy]\npersistent_approval = false",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"default origin access approval lifetime",
|
||||||
|
"[browser_use.default_origin_policy]\naccess_approval_lifetime = \"turn\"",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"origin access",
|
||||||
|
"[browser_use.origins.\"https://example.com\"]\naccess = \"deny\"",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"origin downloads",
|
||||||
|
"[browser_use.origins.\"https://example.com\"]\ndownloads = \"deny\"",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"origin uploads",
|
||||||
|
"[browser_use.origins.\"https://example.com\"]\nuploads = \"deny\"",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"origin full CDP access",
|
||||||
|
"[browser_use.origins.\"https://example.com\"]\nfull_cdp_access = \"deny\"",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"origin auto-review",
|
||||||
|
"[browser_use.origins.\"https://example.com\"]\nauto_review = \"deny\"",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"origin persistent approval",
|
||||||
|
"[browser_use.origins.\"https://example.com\"]\npersistent_approval = false",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"origin access approval lifetime",
|
||||||
|
"[browser_use.origins.\"https://example.com\"]\naccess_approval_lifetime = \"turn\"",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"computer persistent approval",
|
||||||
|
"[computer_use]\nallow_persistent_approval = false",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"default app access",
|
||||||
|
"[computer_use]\ndefault_app_access = \"deny\"",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"macOS bundle identifier",
|
||||||
|
"[computer_use.macos.bundle_ids]\n\"com.example.App\" = \"deny\"",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Windows AUMID",
|
||||||
|
"[computer_use.windows.aumids]\n\"Example.App_123!Main\" = \"deny\"",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Windows executable",
|
||||||
|
"[[computer_use.windows.exes]]\npublisher_name = \"CN=Example Corp\"\nproduct_name = \"Example App\"\naccess = \"deny\"",
|
||||||
|
),
|
||||||
|
] {
|
||||||
|
let requirements: ConfigRequirementsToml = from_str(requirements_toml)?;
|
||||||
|
assert!(!requirements.is_empty(), "{name} requirement was dropped");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn deserialize_new_thread_model_defaults() -> Result<()> {
|
fn deserialize_new_thread_model_defaults() -> Result<()> {
|
||||||
let requirements: ConfigRequirementsToml = from_str(
|
let requirements: ConfigRequirementsToml = from_str(
|
||||||
@@ -2431,8 +2621,19 @@ mod tests {
|
|||||||
let feature_requirements = FeatureRequirementsToml {
|
let feature_requirements = FeatureRequirementsToml {
|
||||||
entries: BTreeMap::from([("personality".to_string(), true)]),
|
entries: BTreeMap::from([("personality".to_string(), true)]),
|
||||||
};
|
};
|
||||||
|
let browser_use = BrowserUseRequirementsToml {
|
||||||
|
allow_history_access: Some(false),
|
||||||
|
disable_auto_review: Some(true),
|
||||||
|
allow_global_persistent_approval: None,
|
||||||
|
default_origin_policy: None,
|
||||||
|
origins: None,
|
||||||
|
};
|
||||||
let computer_use = ComputerUseRequirementsToml {
|
let computer_use = ComputerUseRequirementsToml {
|
||||||
allow_locked_computer_use: Some(false),
|
allow_locked_computer_use: Some(false),
|
||||||
|
allow_persistent_approval: Some(false),
|
||||||
|
default_app_access: None,
|
||||||
|
macos: None,
|
||||||
|
windows: None,
|
||||||
};
|
};
|
||||||
let auto_review = AutoReviewRequirementsToml {
|
let auto_review = AutoReviewRequirementsToml {
|
||||||
required_on_models: Some(vec!["managed-model".to_string()]),
|
required_on_models: Some(vec!["managed-model".to_string()]),
|
||||||
@@ -2485,10 +2686,11 @@ mod tests {
|
|||||||
remote_sandbox_config: None,
|
remote_sandbox_config: None,
|
||||||
allowed_web_search_modes: Some(allowed_web_search_modes.clone()),
|
allowed_web_search_modes: Some(allowed_web_search_modes.clone()),
|
||||||
allow_managed_hooks_only: Some(true),
|
allow_managed_hooks_only: Some(true),
|
||||||
|
allow_browser_and_computer_use: Some(false),
|
||||||
allow_appshots: Some(false),
|
allow_appshots: Some(false),
|
||||||
allow_remote_control: Some(false),
|
allow_remote_control: Some(false),
|
||||||
computer_use: Some(computer_use.clone()),
|
computer_use: Some(computer_use.clone()),
|
||||||
browser_use: None,
|
browser_use: Some(browser_use.clone()),
|
||||||
in_app_browser: None,
|
in_app_browser: None,
|
||||||
windows: Some(windows.clone()),
|
windows: Some(windows.clone()),
|
||||||
feature_requirements: Some(feature_requirements.clone()),
|
feature_requirements: Some(feature_requirements.clone()),
|
||||||
@@ -2559,13 +2761,17 @@ mod tests {
|
|||||||
/*value*/ true,
|
/*value*/ true,
|
||||||
enforce_source.clone(),
|
enforce_source.clone(),
|
||||||
)),
|
)),
|
||||||
|
allow_browser_and_computer_use: Some(Sourced::new(
|
||||||
|
/*value*/ false,
|
||||||
|
enforce_source.clone(),
|
||||||
|
)),
|
||||||
allow_appshots: Some(Sourced::new(/*value*/ false, enforce_source.clone(),)),
|
allow_appshots: Some(Sourced::new(/*value*/ false, enforce_source.clone(),)),
|
||||||
allow_remote_control: Some(Sourced::new(
|
allow_remote_control: Some(Sourced::new(
|
||||||
/*value*/ false,
|
/*value*/ false,
|
||||||
enforce_source.clone(),
|
enforce_source.clone(),
|
||||||
)),
|
)),
|
||||||
computer_use: Some(Sourced::new(computer_use, enforce_source.clone())),
|
computer_use: Some(Sourced::new(computer_use, enforce_source.clone())),
|
||||||
browser_use: None,
|
browser_use: Some(Sourced::new(browser_use, enforce_source.clone())),
|
||||||
in_app_browser: None,
|
in_app_browser: None,
|
||||||
windows: Some(Sourced::new(windows, enforce_source.clone())),
|
windows: Some(Sourced::new(windows, enforce_source.clone())),
|
||||||
feature_requirements: Some(Sourced::new(
|
feature_requirements: Some(Sourced::new(
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
mod auth_policy;
|
mod auth_policy;
|
||||||
|
mod browser_computer_use_requirements;
|
||||||
mod cloud_config_bundle;
|
mod cloud_config_bundle;
|
||||||
mod cloud_config_layers;
|
mod cloud_config_layers;
|
||||||
mod config_layer_source;
|
mod config_layer_source;
|
||||||
@@ -37,6 +38,14 @@ pub mod types;
|
|||||||
pub const CONFIG_TOML_FILE: &str = "config.toml";
|
pub const CONFIG_TOML_FILE: &str = "config.toml";
|
||||||
|
|
||||||
pub use auth_policy::ManagedAuthPolicy;
|
pub use auth_policy::ManagedAuthPolicy;
|
||||||
|
pub use browser_computer_use_requirements::AllowDenyRequirementToml;
|
||||||
|
pub use browser_computer_use_requirements::BrowserUseAccessApprovalLifetimeToml;
|
||||||
|
pub use browser_computer_use_requirements::BrowserUseOriginPolicyToml;
|
||||||
|
pub use browser_computer_use_requirements::BrowserUseRequirementsToml;
|
||||||
|
pub use browser_computer_use_requirements::ComputerUseMacosRequirementsToml;
|
||||||
|
pub use browser_computer_use_requirements::ComputerUseRequirementsToml;
|
||||||
|
pub use browser_computer_use_requirements::ComputerUseWindowsExeRequirementToml;
|
||||||
|
pub use browser_computer_use_requirements::ComputerUseWindowsRequirementsToml;
|
||||||
pub use cloud_config_bundle::CloudConfigBundle;
|
pub use cloud_config_bundle::CloudConfigBundle;
|
||||||
pub use cloud_config_bundle::CloudConfigBundleLayers;
|
pub use cloud_config_bundle::CloudConfigBundleLayers;
|
||||||
pub use cloud_config_bundle::CloudConfigBundleLoadError;
|
pub use cloud_config_bundle::CloudConfigBundleLoadError;
|
||||||
@@ -69,8 +78,6 @@ pub use config_requirements::AppToolRequirementToml;
|
|||||||
pub use config_requirements::AppToolsRequirementsToml;
|
pub use config_requirements::AppToolsRequirementsToml;
|
||||||
pub use config_requirements::AppsRequirementsToml;
|
pub use config_requirements::AppsRequirementsToml;
|
||||||
pub use config_requirements::AutoReviewRequirementsToml;
|
pub use config_requirements::AutoReviewRequirementsToml;
|
||||||
pub use config_requirements::BrowserUseRequirementsToml;
|
|
||||||
pub use config_requirements::ComputerUseRequirementsToml;
|
|
||||||
pub use config_requirements::ConfigRequirements;
|
pub use config_requirements::ConfigRequirements;
|
||||||
pub use config_requirements::ConfigRequirementsToml;
|
pub use config_requirements::ConfigRequirementsToml;
|
||||||
pub use config_requirements::ConfigRequirementsWithSources;
|
pub use config_requirements::ConfigRequirementsWithSources;
|
||||||
|
|||||||
@@ -229,6 +229,7 @@ fn populate_merged_regular_fields_with_sources(
|
|||||||
remote_sandbox_config: _,
|
remote_sandbox_config: _,
|
||||||
allowed_web_search_modes,
|
allowed_web_search_modes,
|
||||||
allow_managed_hooks_only,
|
allow_managed_hooks_only,
|
||||||
|
allow_browser_and_computer_use,
|
||||||
allow_appshots,
|
allow_appshots,
|
||||||
allow_remote_control,
|
allow_remote_control,
|
||||||
computer_use,
|
computer_use,
|
||||||
@@ -277,6 +278,10 @@ fn populate_merged_regular_fields_with_sources(
|
|||||||
set_sourced!(default_permissions, &["default_permissions"]);
|
set_sourced!(default_permissions, &["default_permissions"]);
|
||||||
set_sourced!(allowed_web_search_modes, &["allowed_web_search_modes"]);
|
set_sourced!(allowed_web_search_modes, &["allowed_web_search_modes"]);
|
||||||
set_sourced!(allow_managed_hooks_only, &["allow_managed_hooks_only"]);
|
set_sourced!(allow_managed_hooks_only, &["allow_managed_hooks_only"]);
|
||||||
|
set_sourced!(
|
||||||
|
allow_browser_and_computer_use,
|
||||||
|
&["allow_browser_and_computer_use"]
|
||||||
|
);
|
||||||
set_sourced!(allow_appshots, &["allow_appshots"]);
|
set_sourced!(allow_appshots, &["allow_appshots"]);
|
||||||
set_sourced!(allow_remote_control, &["allow_remote_control"]);
|
set_sourced!(allow_remote_control, &["allow_remote_control"]);
|
||||||
set_sourced!(auto_review, &["auto_review"]);
|
set_sourced!(auto_review, &["auto_review"]);
|
||||||
|
|||||||
@@ -609,6 +609,114 @@ fn network_maps_use_regular_toml_merge() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn browser_and_computer_use_requirements_use_regular_toml_merge() {
|
||||||
|
let composed = compose(vec![
|
||||||
|
layer(
|
||||||
|
"req_low",
|
||||||
|
"Low",
|
||||||
|
r#"
|
||||||
|
allow_browser_and_computer_use = true
|
||||||
|
|
||||||
|
[browser_use]
|
||||||
|
allow_history_access = true
|
||||||
|
allow_global_persistent_approval = true
|
||||||
|
|
||||||
|
[browser_use.default_origin_policy]
|
||||||
|
access = "allow"
|
||||||
|
access_approval_lifetime = "thread"
|
||||||
|
|
||||||
|
[browser_use.origins."https://example.com"]
|
||||||
|
access = "deny"
|
||||||
|
downloads = "allow"
|
||||||
|
|
||||||
|
[computer_use]
|
||||||
|
allow_locked_computer_use = true
|
||||||
|
default_app_access = "allow"
|
||||||
|
|
||||||
|
[computer_use.macos.bundle_ids]
|
||||||
|
"com.apple.Safari" = "deny"
|
||||||
|
|
||||||
|
[computer_use.windows.aumids]
|
||||||
|
"Microsoft.Paint_8wekyb3d8bbwe!App" = "allow"
|
||||||
|
"#,
|
||||||
|
),
|
||||||
|
layer(
|
||||||
|
"req_high",
|
||||||
|
"High",
|
||||||
|
r#"
|
||||||
|
allow_browser_and_computer_use = false
|
||||||
|
|
||||||
|
[browser_use]
|
||||||
|
allow_history_access = false
|
||||||
|
allow_global_persistent_approval = false
|
||||||
|
|
||||||
|
[browser_use.default_origin_policy]
|
||||||
|
persistent_approval = false
|
||||||
|
access_approval_lifetime = "turn"
|
||||||
|
|
||||||
|
[browser_use.origins."https://example.com"]
|
||||||
|
downloads = "deny"
|
||||||
|
uploads = "deny"
|
||||||
|
|
||||||
|
[computer_use]
|
||||||
|
allow_persistent_approval = false
|
||||||
|
|
||||||
|
[computer_use.macos.bundle_ids]
|
||||||
|
"com.apple.Safari" = "allow"
|
||||||
|
|
||||||
|
[[computer_use.windows.exes]]
|
||||||
|
publisher_name = "CN=Google LLC"
|
||||||
|
product_name = "Google Chrome"
|
||||||
|
binary_name = "chrome.exe"
|
||||||
|
access = "deny"
|
||||||
|
"#,
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.expect("compose requirements")
|
||||||
|
.expect("requirements present");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
composed,
|
||||||
|
expected_requirements(
|
||||||
|
r#"
|
||||||
|
allow_browser_and_computer_use = false
|
||||||
|
|
||||||
|
[browser_use]
|
||||||
|
allow_history_access = false
|
||||||
|
allow_global_persistent_approval = false
|
||||||
|
|
||||||
|
[browser_use.default_origin_policy]
|
||||||
|
access = "allow"
|
||||||
|
persistent_approval = false
|
||||||
|
access_approval_lifetime = "turn"
|
||||||
|
|
||||||
|
[browser_use.origins."https://example.com"]
|
||||||
|
access = "deny"
|
||||||
|
downloads = "deny"
|
||||||
|
uploads = "deny"
|
||||||
|
|
||||||
|
[computer_use]
|
||||||
|
allow_locked_computer_use = true
|
||||||
|
allow_persistent_approval = false
|
||||||
|
default_app_access = "allow"
|
||||||
|
|
||||||
|
[computer_use.macos.bundle_ids]
|
||||||
|
"com.apple.Safari" = "allow"
|
||||||
|
|
||||||
|
[computer_use.windows.aumids]
|
||||||
|
"Microsoft.Paint_8wekyb3d8bbwe!App" = "allow"
|
||||||
|
|
||||||
|
[[computer_use.windows.exes]]
|
||||||
|
publisher_name = "CN=Google LLC"
|
||||||
|
product_name = "Google Chrome"
|
||||||
|
binary_name = "chrome.exe"
|
||||||
|
access = "deny"
|
||||||
|
"#
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn windows_requirements_use_regular_toml_merge() {
|
fn windows_requirements_use_regular_toml_merge() {
|
||||||
let composed = compose(vec![
|
let composed = compose(vec![
|
||||||
|
|||||||
@@ -9886,6 +9886,7 @@ async fn test_requirements_web_search_mode_allowlist_does_not_warn_when_unset()
|
|||||||
allow_managed_hooks_only: None,
|
allow_managed_hooks_only: None,
|
||||||
allow_appshots: None,
|
allow_appshots: None,
|
||||||
allow_remote_control: None,
|
allow_remote_control: None,
|
||||||
|
allow_browser_and_computer_use: None,
|
||||||
computer_use: None,
|
computer_use: None,
|
||||||
browser_use: None,
|
browser_use: None,
|
||||||
in_app_browser: None,
|
in_app_browser: None,
|
||||||
|
|||||||
@@ -953,6 +953,7 @@ interrupt_message = false
|
|||||||
allow_managed_hooks_only: Some(true),
|
allow_managed_hooks_only: Some(true),
|
||||||
allow_appshots: Some(false),
|
allow_appshots: Some(false),
|
||||||
allow_remote_control: Some(false),
|
allow_remote_control: Some(false),
|
||||||
|
allow_browser_and_computer_use: None,
|
||||||
computer_use: None,
|
computer_use: None,
|
||||||
browser_use: None,
|
browser_use: None,
|
||||||
in_app_browser: None,
|
in_app_browser: None,
|
||||||
|
|||||||
Reference in new issue
Block a user