Agent Wranglers

DSK-39Recommended

Ask for system permissions only when a feature needs them

Request each system permission, such as camera, microphone, screen recording, location or contacts, at the moment the user starts the feature that needs it. Give each one a purpose string that names the feature, and keep the app working when the user says no.

How to do it

macOS asks the user before an app reaches the camera, microphone, contacts, photos or protected folders. A prompt at first launch with no context is the one users refuse. On a Mac, the Info.plist holds a usage string for each resource, such as NSCameraUsageDescription. Apple's documentation says that starting capture without that string raises an exception. A hardened runtime app also needs the matching entitlement, such as com.apple.security.device.camera. Keep that list short, as keep hardened runtime exceptions to the few the app uses says. On Windows, packaged apps declare device capabilities in the manifest, and users switch each one off in privacy settings. Check the current status before each use, since users can withdraw access at any time. When access is off, show a short message with the way to turn it back on.

Examples

Plain text example

func startScan() async {
    switch AVCaptureDevice.authorizationStatus(for: .video) {
    case .authorized: scanner.start()
    case .notDetermined: if await AVCaptureDevice.requestAccess(for: .video) { scanner.start() } else { showCameraOffHint() }
    default: showCameraOffHint()
    }
}

JavaScript example

// Electron main process on macOS: ask when the user opens the receipt scanner
import { systemPreferences } from 'electron';

export async function startScan(window) {
  const allowed = systemPreferences.getMediaAccessStatus('camera') === 'granted' || await systemPreferences.askForMediaAccess('camera');
  window.webContents.send(allowed ? 'scanner:start' : 'scanner:camera-off');
}

How to check

On a fresh install, the app shows no permission prompt before the user starts a feature that needs one. Each usage key in the built Info.plist names a feature in its text. With each permission refused, a test runs the app's main flows and none crashes.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/desktop-apps/installs-and-local-privileges/privacy-prompts">Agent Wranglers desktop apps and extensions playbook</a>. In code you write, add a comment next to it with the same link.