feat: Add additional macOS Sandbox Permissions for Launch Services, Contacts, Reminders (#14155)

Add additional macOS Sandbox Permissions levers for the following:

- Launch Services
- Contacts
- Reminders
This commit is contained in:
Leo Shimonaka
2026-03-10 16:34:47 -07:00
committed by Michael Bolin
parent 8ac27b2a16
commit 889b4796fc
25 changed files with 779 additions and 25 deletions

View File

@@ -110,6 +110,28 @@ pub enum MacOsPreferencesPermission {
ReadWrite,
}
#[derive(
Debug,
Clone,
PartialEq,
Eq,
PartialOrd,
Ord,
Default,
Hash,
Serialize,
Deserialize,
JsonSchema,
TS,
)]
#[serde(rename_all = "snake_case")]
pub enum MacOsContactsPermission {
#[default]
None,
ReadOnly,
ReadWrite,
}
#[derive(Debug, Clone, PartialEq, Eq, Default, Hash, Serialize, Deserialize, JsonSchema, TS)]
#[serde(rename_all = "snake_case", try_from = "MacOsAutomationPermissionDe")]
pub enum MacOsAutomationPermission {
@@ -174,10 +196,16 @@ pub struct MacOsSeatbeltProfileExtensions {
pub macos_preferences: MacOsPreferencesPermission,
#[serde(alias = "automations")]
pub macos_automation: MacOsAutomationPermission,
#[serde(alias = "launch_services")]
pub macos_launch_services: bool,
#[serde(alias = "accessibility")]
pub macos_accessibility: bool,
#[serde(alias = "calendar")]
pub macos_calendar: bool,
#[serde(alias = "reminders")]
pub macos_reminders: bool,
#[serde(alias = "contacts")]
pub macos_contacts: MacOsContactsPermission,
}
#[derive(Debug, Clone, Default, Eq, Hash, PartialEq, Serialize, Deserialize, JsonSchema, TS)]
@@ -1456,6 +1484,12 @@ mod tests {
assert!(MacOsPreferencesPermission::ReadOnly < MacOsPreferencesPermission::ReadWrite);
}
#[test]
fn macos_contacts_permission_order_matches_permissiveness() {
assert!(MacOsContactsPermission::None < MacOsContactsPermission::ReadOnly);
assert!(MacOsContactsPermission::ReadOnly < MacOsContactsPermission::ReadWrite);
}
#[test]
fn permission_profile_deserializes_macos_seatbelt_profile_extensions() {
let permission_profile = serde_json::from_value::<PermissionProfile>(serde_json::json!({
@@ -1464,6 +1498,7 @@ mod tests {
"macos": {
"macos_preferences": "read_write",
"macos_automation": ["com.apple.Notes"],
"macos_launch_services": true,
"macos_accessibility": true,
"macos_calendar": true
}
@@ -1480,8 +1515,38 @@ mod tests {
macos_automation: MacOsAutomationPermission::BundleIds(vec![
"com.apple.Notes".to_string(),
]),
macos_launch_services: true,
macos_accessibility: true,
macos_calendar: true,
macos_reminders: false,
macos_contacts: MacOsContactsPermission::None,
}),
}
);
}
#[test]
fn permission_profile_deserializes_macos_reminders_permission() {
let permission_profile = serde_json::from_value::<PermissionProfile>(serde_json::json!({
"macos": {
"macos_reminders": true
}
}))
.expect("deserialize reminders permission profile");
assert_eq!(
permission_profile,
PermissionProfile {
network: None,
file_system: None,
macos: Some(MacOsSeatbeltProfileExtensions {
macos_preferences: MacOsPreferencesPermission::ReadOnly,
macos_automation: MacOsAutomationPermission::None,
macos_launch_services: false,
macos_accessibility: false,
macos_calendar: false,
macos_reminders: true,
macos_contacts: MacOsContactsPermission::None,
}),
}
);
@@ -1502,8 +1567,11 @@ mod tests {
macos_automation: MacOsAutomationPermission::BundleIds(vec![
"com.apple.Notes".to_string(),
]),
macos_launch_services: false,
macos_accessibility: false,
macos_calendar: false,
macos_reminders: false,
macos_contacts: MacOsContactsPermission::None,
}
);
}
@@ -1514,8 +1582,11 @@ mod tests {
serde_json::from_value::<MacOsSeatbeltProfileExtensions>(serde_json::json!({
"preferences": "read_write",
"automations": ["com.apple.Notes"],
"launch_services": true,
"accessibility": true,
"calendar": true
"calendar": true,
"reminders": true,
"contacts": "read_only"
}))
.expect("deserialize macos permissions");
@@ -1526,8 +1597,11 @@ mod tests {
macos_automation: MacOsAutomationPermission::BundleIds(vec![
"com.apple.Notes".to_string(),
]),
macos_launch_services: true,
macos_accessibility: true,
macos_calendar: true,
macos_reminders: true,
macos_contacts: MacOsContactsPermission::ReadOnly,
}
);
}