mac signing (debug builds)
This app is usually built fromscripts/package-mac-app.sh,
which now:
- sets a stable debug bundle identifier:
ai.fased.mac.debug - writes the Info.plist with that bundle id (override via
BUNDLE_ID=...) - calls
scripts/codesign-mac-app.shto sign the main binary and app bundle so macOS keeps TCC permissions stable. For stable permissions, use a real signing certificate. - uses
CODESIGN_TIMESTAMP=autoby default for Developer ID signatures. SetCODESIGN_TIMESTAMP=offto skip timestamping for offline debug builds. - injects build metadata into Info.plist:
FasedAgentBuildTimestamp(UTC) andFasedAgentGitCommit(short hash). - Packaging requires Node 24 recommended, or Node 22.14+ with
node:sqlite: the script runs TS builds and the Control UI build. - reads
SIGN_IDENTITYfrom the environment. Addexport SIGN_IDENTITY="Apple Development: Your Name (TEAMID)"to your shell rc to always sign with your cert. - requires explicit opt-in for ad-hoc signing via
ALLOW_ADHOC_SIGNING=1orSIGN_IDENTITY="-". This is not recommended for permission testing. - runs a Team ID audit after signing and fails if any Mach-O inside the app
bundle is signed by a different Team ID. Set
SKIP_TEAM_ID_CHECK=1to bypass.
Usage
Ad-hoc Signing Note
When signing withSIGN_IDENTITY="-" (ad-hoc), the script automatically
disables the Hardened Runtime (--options runtime). This prevents crashes
when the app loads embedded frameworks that do not share the same Team ID.
Ad-hoc signatures also break TCC permission persistence; see
macOS permissions for recovery steps.
Build metadata for About
package-mac-app.sh stamps the bundle with:
FasedAgentBuildTimestamp: ISO8601 UTC at package timeFasedAgentGitCommit: short git hash (orunknownif unavailable)
#if DEBUG. Run the packager to refresh these
values after code changes.
Why
TCC permissions are tied to the bundle identifier and code signature. Unsigned debug builds with changing UUIDs can cause macOS to forget grants after each rebuild. Signing the binaries and keeping a fixed bundle id/path (dist/FasedAgent.app) preserves grants between builds.