"Every rebuild, macOS looked at the app and saw a stranger. Because technically, it was one."
The Symptom
You grant Accessibility. You grant Microphone. You rebuild the app to fix a typo — and macOS asks for both permissions again. And again, every single build. It feels like a broken OS or a broken app. It's neither: it's a completely logical consequence of how macOS decides whether two binaries are the "same app."
The Cause: Designated Requirement
macOS keys TCC grants (Accessibility, Microphone, and friends) to an app's designated requirement — the code-signing rule that says "this is that app." A plain swift build produces an ad-hoc signature, whose designated requirement is pinned to the binary's cdhash. Change one character of source, and the cdhash changes, so the DR changes, so the app you just built does not match the app the user granted. macOS isn't forgetting — it's correctly concluding this is a different app that happens to share a name.
swift build -> ad-hoc signature -> DR pinned to cdhash
|
v edit one line, rebuild
cdhash changes -> DR changes -> TCC: "who are you?" -> re-prompt forever
Fix: sign with ONE stable identity -> DR is stable -> grants persist
The Fix, and the Trap Inside the Fix
The fix is a single, stable, self-signed identity shared by all your apps — not a per-app certificate, which just multiplies the problem. Import it once per machine, have the build script sign with it, and the DR stops changing. Then there's a trap inside the fix worth knowing: security find-identity -v filters to Gatekeeper-valid identities, and a self-signed cert isn't (it reports as not trusted), so your identity appears to not exist. Detect it with security find-identity -p codesigning — no -v. One flag stands between "working as designed" and an hour of confusion. Finally, after the first properly-signed build, clear the stale ad-hoc-pinned grants once with tccutil reset and re-grant; from then on they persist.