GCDeviceHaptics.createEngine returns a CHHapticEngine (the only controller-rumble
API on Apple platforms); starting it spins up CoreHaptics, which looks up the
system audio-analytics daemon over Mach. The App Sandbox denies that global-name
lookup and the framework's precondition turns the denial into a hard crash
("Process is sandboxed but com.apple.security.exception.mach-lookup.global-name
doesn't contain com.apple.audioanalyticsd") the moment a controller's rumble
engine starts.
Add the documented, App-Store-acceptable temporary-exception whitelisting exactly
that one service. Verified embedded into the signed binary (codesign -d
--entitlements) alongside the existing entitlements. macOS-only (iOS/tvOS reject
temporary-exception keys and don't need it). App Store: declare it in App Sandbox
Entitlement Usage Information.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Mac App Store requires App Sandbox, which the macOS app didn't declare.
App Sandbox is macOS-only (invalid on iOS/tvOS, fails upload validation), so
the macOS target now uses a dedicated Config/Punktfunk-macOS.entitlements while
iOS/tvOS keep the shared Config/Punktfunk.entitlements (unchanged). The single
macOS app is sandboxed for BOTH channels — the Developer ID DMG is codesigned
with the same file — so the local build equals what App Store users get.
Entitlement set (verified against the code + Apple docs):
- app-sandbox, network.client.
- network.server: NOT optional despite the client being outbound-only — the
sandbox gates the bind() syscall as network-bind, and quinn (quic.rs) + the
raw-UDP plane (transport/udp.rs) both bind explicitly, so host->client
datagrams never arrive without it (the classic QUIC-under-sandbox trap).
- device.audio-input (mic uplink), device.bluetooth + device.usb (Xbox/DualSense
controllers over BT/USB via GameController), keychain-access-groups (existing).
Omitted: device.hid (undocumented), files.user-selected.* (no pickers),
networking.multicast (Bonjour browse is exempt; requesting it breaks signing).
CI (release.yml): add a macOS App Store archive+upload-to-TestFlight step
mirroring the iOS lane (manual Apple Distribution signing + the 'Punktfunk macOS
App Store Distribution' profile, app-store-connect/upload, installer-signed pkg),
continue-on-error until the portal prereqs exist; point the Developer ID DMG
codesign at the sandboxed entitlements. Docs (ci.md) + clients/apple README
updated; the runner additionally needs the macOS platform on the App Store
Connect record + the '3rd Party Mac Developer Installer' cert.
Verified: signed Debug build embeds exactly the intended entitlements
(codesign -d --entitlements), swift build green against the rebuilt xcframework.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>