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:
rafael-oai authored and copyberry committed 2026-08-21 19:20:09 +00:00
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)
})
}
}
+231 -25
View File
@@ -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(
+9 -2
View File
@@ -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![
+1
View File
@@ -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,
+1
View File
@@ -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,