Problem
The macOS Workshop DMG is not codesigned. Tauri never runs codesign because no signingIdentity is configured, so the bundle carries only the linker's default ad hoc signature with no sealed resources:
$ codesign -dv PromptForge.app
Signature=adhoc
flags=0x20002(adhoc,linker-signed)
Sealed Resources=none
$ spctl --assess --type execute PromptForge.app
code has no resources but signature indicates they must be present
Gatekeeper treats that as a corrupt app rather than an unsigned one. A Safari-downloaded copy opened from Finder shows "PromptForge is damaged and can't be opened. You should move it to the Trash." with only Move to Trash / Cancel. There is no Open Anyway path in this state. The only way past it is xattr -d com.apple.quarantine, which no doc mentions.

Verified 2026-09-17 on Apple Silicon, macOS 26, with both the published PromptForge-arm64.dmg (0.2.0) and a DMG built from master (3121cdd). Both are in the same state.
Step 1: ad hoc sign the bundle (no certificate needed)
Set bundle.macOS.signingIdentity to "-" in crates/workshop/tauri.macos.conf.json. Tauri then ad hoc signs the whole bundle, including the externalBin gateway sidecar, with the hardened runtime and the existing Entitlements.plist.
Verified locally with the equivalent codesign --force --deep --sign - --options runtime --entitlements Entitlements.plist PromptForge.app:
-
The dialog becomes "PromptForge Not Opened. Apple could not verify..." with a Done button, and System Settings > Privacy & Security offers Open Anyway. This is the standard path for unsigned open source apps.

-
The signed bundle boots, spawns the sidecar gateway, and loads the whisper speech engine normally, so the hardened runtime and the mic entitlement are safe for this build.
Pair it with a README Downloads paragraph describing the Open Anyway step.
Step 2: Developer ID signing plus notarization in CI
- Enroll in the Apple Developer Program and create a Developer ID Application certificate. Export it as a base64
.p12.
- Add the secrets to the two macOS matrix entries in
.github/workflows/release-workshop.yml, where the # SIGNING (macOS) placeholder already sits. Tauri and tauri-action read these and sign, notarize, and staple the app and DMG:
APPLE_CERTIFICATE
APPLE_CERTIFICATE_PASSWORD
APPLE_SIGNING_IDENTITY
APPLE_ID + APPLE_PASSWORD + APPLE_TEAM_ID
(or APPLE_API_ISSUER + APPLE_API_KEY + APPLE_API_KEY_PATH)
- Set
bundle.macOS.minimumSystemVersion while there; the bundle currently claims the Tauri default 10.13.
Library validation risk. The gateway downloads whisper.cpp and llama.cpp dylibs at runtime. Under a real Team ID, hardened runtime library validation may refuse that third-party code. If speech or local inference fails to load on the signed build, add com.apple.security.cs.disable-library-validation to Entitlements.plist. Ad hoc signing skips team matching, so this cannot be tested before the certificate exists.
Step 3: make the release test catch this
The macOS "Install and check" step copies the app out of the DMG with cp and runs the binary directly, so it never touches Gatekeeper, LaunchServices, or quarantine. It passes today's broken state. Add:
codesign --verify --deep --strict PromptForge.app
spctl --assess --type execute PromptForge.app (expected to pass once Step 2 lands)
- an
open of a copy stamped with xattr -w com.apple.quarantine, checking that the process comes up
- a speech-load check on the signed build, for the library validation risk above
Note for anyone reproducing
A bundle that Finder has already refused once stays wedged on macOS 26: any binary inside it hangs at _dyld_start when executed directly, even after clearing quarantine, while a fresh copy of the same bytes runs. Diagnose from a fresh copy, not from a bundle that has been through the dialog.
Problem
The macOS Workshop DMG is not codesigned. Tauri never runs
codesignbecause nosigningIdentityis configured, so the bundle carries only the linker's default ad hoc signature with no sealed resources:Gatekeeper treats that as a corrupt app rather than an unsigned one. A Safari-downloaded copy opened from Finder shows "PromptForge is damaged and can't be opened. You should move it to the Trash." with only Move to Trash / Cancel. There is no Open Anyway path in this state. The only way past it is
xattr -d com.apple.quarantine, which no doc mentions.Verified 2026-09-17 on Apple Silicon, macOS 26, with both the published
PromptForge-arm64.dmg(0.2.0) and a DMG built frommaster(3121cdd). Both are in the same state.Step 1: ad hoc sign the bundle (no certificate needed)
Set
bundle.macOS.signingIdentityto"-"incrates/workshop/tauri.macos.conf.json. Tauri then ad hoc signs the whole bundle, including theexternalBingateway sidecar, with the hardened runtime and the existingEntitlements.plist.Verified locally with the equivalent
codesign --force --deep --sign - --options runtime --entitlements Entitlements.plist PromptForge.app:The dialog becomes "PromptForge Not Opened. Apple could not verify..." with a Done button, and System Settings > Privacy & Security offers Open Anyway. This is the standard path for unsigned open source apps.
The signed bundle boots, spawns the sidecar gateway, and loads the whisper speech engine normally, so the hardened runtime and the mic entitlement are safe for this build.
Pair it with a README Downloads paragraph describing the Open Anyway step.
Step 2: Developer ID signing plus notarization in CI
.p12..github/workflows/release-workshop.yml, where the# SIGNING (macOS)placeholder already sits. Tauri and tauri-action read these and sign, notarize, and staple the app and DMG:bundle.macOS.minimumSystemVersionwhile there; the bundle currently claims the Tauri default 10.13.Library validation risk. The gateway downloads whisper.cpp and llama.cpp dylibs at runtime. Under a real Team ID, hardened runtime library validation may refuse that third-party code. If speech or local inference fails to load on the signed build, add
com.apple.security.cs.disable-library-validationtoEntitlements.plist. Ad hoc signing skips team matching, so this cannot be tested before the certificate exists.Step 3: make the release test catch this
The macOS "Install and check" step copies the app out of the DMG with
cpand runs the binary directly, so it never touches Gatekeeper, LaunchServices, or quarantine. It passes today's broken state. Add:codesign --verify --deep --strict PromptForge.appspctl --assess --type execute PromptForge.app(expected to pass once Step 2 lands)openof a copy stamped withxattr -w com.apple.quarantine, checking that the process comes upNote for anyone reproducing
A bundle that Finder has already refused once stays wedged on macOS 26: any binary inside it hangs at
_dyld_startwhen executed directly, even after clearing quarantine, while a fresh copy of the same bytes runs. Diagnose from a fresh copy, not from a bundle that has been through the dialog.