How the openlogi-permissions Crate Checks macOS TCC and Linux Device Permissions
The openlogi-permissions crate provides a non-prompting abstraction layer that queries macOS TCC permissions via read-only system APIs and validates Linux device access by probing /dev/uinput and Logitech hidraw nodes, returning a unified PermissionStatus enum across both platforms.
The openlogi-permissions crate in the AprilNEA/OpenLogi repository standardizes privacy permission detection for the OpenLogi agent. It enables silent status checks without triggering system consent dialogs, while supporting deep-link navigation to macOS System Settings when users need to manually grant access.
macOS TCC Permission Handling
The macOS implementation in src/macos.rs focuses on Transparency, Consent, and Control (TCC) permissions, specifically covering Accessibility, Input Monitoring, CoreBluetooth, and Camera access. All query functions use read-only APIs—such as IOHIDCheckAccess—to ensure the crate never triggers a permission prompt; the owning process presents the prompt only when first accessing the resource.
Querying Input Monitoring and Accessibility
The input_monitoring() function determines authorization status by calling IOHIDCheckAccess(IOHIDRequestType::ListenEvent) and mapping the result to PermissionStatus::{Granted, Denied, Unknown}. As implemented in src/macos.rs lines 22-30, this approach reads the current TCC database state without modifying it or alerting the user.
Bluetooth Authorization Status
For Bluetooth permissions, the bluetooth() function instantiates the Objective-C class CBCentralManager via the objc2 crate to read the authorization property. According to src/macos.rs lines 32-48, the implementation translates the integer authorization codes into the crate's PermissionStatus enum, allowing the agent to detect whether the user has granted CoreBluetooth access.
Camera Access Detection
The camera() function delegates to the openlogi-camera crate's camera_authorization() function, then maps the returned enum to PermissionStatus. This integration, found in src/macos.rs lines 51-59, ensures consistent status reporting across the OpenLogi ecosystem while respecting the camera subsystem's specific implementation.
Deep-Linking to System Settings
When the application needs to direct users to grant permissions manually, the open_pane(permission) function constructs deep-link URLs such as x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility based on the Permission enum variant. As defined in src/macos.rs lines 62-75, this helper uses the opener crate to launch the specific privacy pane in System Settings.
Linux Device Permission Validation
Linux platforms lack consent dialogs; instead, access depends on udev rules granting read/write rights to device files. The implementation in src/linux.rs probes these filesystem permissions to determine if the user can access input devices.
Probing /dev/uinput and HID-Raw Devices
The input_device_access() function performs two distinct probes:
- Uinput check – Attempts to open
/dev/uinputfor writing; success indicates the user has permissions to create virtual input devices (src/linux.rslines 62-68). - Logitech HID-raw scan – Iterates through
/deventries matchinghidraw*, filters devices belonging to Logitech using the vendor ID defined inopenlogi_core, and attempts read/write access. The results populate the internalHidrawProbeenum (src/linux.rslines 70-88).
Permission Status Logic
The combined probe results convert to PermissionStatus via the From<Probes> implementation in src/linux.rs lines 54-58:
- Granted – Both uinput is writable and at least one Logitech hidraw device is accessible.
- Denied – Either uinput is not writable or hidraw access is denied.
- Unknown – Uinput is writable but no Logitech hidraw devices are present (hardware may be disconnected).
Because Linux lacks a settings pane equivalent, the open_pane function is a no-op on non-macOS platforms (src/lib.rs lines 72-76).
Cross-Platform API Usage
The crate exposes platform-specific functions conditionally compiled via #[cfg]. Applications can query permissions without handling platform differences manually:
use openlogi_permissions::{Permission, PermissionStatus, open_pane};
#[cfg(target_os = "macos")]
fn check_macos_permissions() {
// Query current status without prompting
let im = openlogi_permissions::input_monitoring();
println!("Input Monitoring: {:?}", im);
// Open System Settings if access is denied
if im != PermissionStatus::Granted {
open_pane(Permission::Accessibility);
}
}
#[cfg(target_os = "linux")]
fn check_linux_permissions() {
// Returns Granted, Denied, or Unknown based on device file probes
let dev = openlogi_permissions::input_device_access();
println!("Linux input-device access: {:?}", dev);
}
Summary
- The
openlogi-permissionscrate provides a unifiedPermissionStatusabstraction across macOS TCC and Linux udev permission models. - macOS checks use read-only APIs (
IOHIDCheckAccess,CBCentralManager) insrc/macos.rsto avoid triggering prompts, while supporting deep-links to System Settings. - Linux validation probes
/dev/uinputand Logitechhidrawdevice files insrc/linux.rsto determine access rights without requiring consent dialogs. - The
open_panehelper only functions on macOS, providing URLs likex-apple.systempreferences:com.apple.preference.security?Privacy_Accessibilityfor manual permission configuration.
Frequently Asked Questions
How does openlogi-permissions avoid triggering macOS permission prompts?
The crate exclusively uses read-only APIs such as IOHIDCheckAccess for Input Monitoring and property reads on CBCentralManager for Bluetooth. These functions query the TCC database without requesting access, ensuring input_monitoring() and bluetooth() calls remain silent. The owning process—typically the OpenLogi agent—triggers the actual prompt only when first attempting to use the protected resource.
What determines PermissionStatus::Unknown on Linux?
According to the From<Probes> implementation in src/linux.rs lines 57-58, the status returns Unknown when the user has write access to /dev/uinput but no Logitech hidraw devices are detected in /dev. This typically indicates that the user has sufficient permissions but the hardware is disconnected or not yet enumerated by the kernel.
Why is the open_pane function unavailable on Linux?
Linux lacks a centralized consent management interface equivalent to macOS System Settings TCC panes. As implemented in src/lib.rs lines 72-76, the open_pane function compiles to a no-op on non-macOS targets, allowing cross-platform code to call it unconditionally without runtime errors.
Which specific device files does the Linux implementation check?
The Linux module in src/linux.rs validates two resources: /dev/uinput for virtual input device creation, and /dev/hidraw* nodes specifically filtered for Logitech vendor IDs (defined in openlogi_core). The implementation attempts read/write opens on these files to determine effective permissions, returning Granted only when both resources are accessible.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →