Files
VoiceStudio/scripts/macos-dev-unquarantine.sh
T
Palash DebnathandClaude Opus 4.8 948bc76543 macOS: ad-hoc sign so users open without Terminal + signing/notarization verification (#290)
* chore(release): add macOS signing/Gatekeeper/notarization verification

Codify and enforce the macOS build-signing requirements. The release
pipeline built bundles and had opt-in Apple signing, but never verified
codesign/spctl/notarization — unsigned or broken bundles could ship silently.

- scripts/verify-macos-signing.sh: runs codesign --verify --deep --strict,
  spctl Gatekeeper assessment, per-nested-Mach-O signature check, stapler
  validate, and (opt-in) notarytool history. Report-only by default (unsigned
  dev/preview is expected); --require-signed fails on any unsigned/un-notarized
  component so a broken release stops instead of publishing an unsigned artifact.
- scripts/macos-dev-unquarantine.sh: local-dev-only quarantine stripper, with a
  loud "never a substitute for notarization" warning.
- release.yml: new "Verify macOS signing" step on the macOS leg — report-only on
  unsigned paths, STRICT on the opt-in signed stable path (same condition as
  "Configure Apple signing"), so signing/notarization failures fail the job.
- docs/macos-signing-verification.md: the canonical 10-point requirements +
  how-to-verify checklist, cross-linked to docs/install/macos.md and DESKTOP_RELEASE.md.

Verified locally: report-only PASS (exit 0) and --require-signed FAIL (exit 1)
against the real unsigned debug .app; release.yml parses as valid YAML.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(macos): ad-hoc sign bundle so users open it without Terminal (no Apple ID)

The "app is damaged and can't be opened" error is caused by a broken/incomplete
code-signature seal (codesign --verify failed: "code has no resources but
signature indicates they must be present") on the quarantined download — there
is no GUI bypass for that variant on modern macOS, forcing users to run `xattr`.

Give the bundle a VALID ad-hoc signature at build time (free, no Apple Developer
account) via tauri.conf.json bundle.macOS.signingIdentity = "-". Verified through
a real `tauri build`: the produced .app is now flags=adhoc,runtime and passes
codesign --verify --deep --strict. A valid seal flips the Gatekeeper prompt from
the un-bypassable "damaged" to the GUI-bypassable "unidentified developer", which
users clear with right-click → Open / Settings → "Open Anyway" — no Terminal.

Still not notarized (that needs the paid Apple ID), so there's a one-time
confirmation rather than a clean double-click. The opt-in Developer-ID path is
unchanged: APPLE_SIGNING_IDENTITY (env) overrides the "-" default on the signed
stable release.

- tauri.conf.json: signingIdentity "-" (ad-hoc default).
- verify-macos-signing.sh: detect ad-hoc tier; report the no-Terminal GUI path
  in report-only, still FAIL it under --require-signed (production must notarize).
- docs/install/macos.md: lead the Gatekeeper section with right-click → Open;
  keep xattr as fallback for the harsher "damaged"/corrupted-download case.
- docs/macos-signing-verification.md: signing-tiers table + ad-hoc default note.
- release.yml: comment the ad-hoc default + env override on the signed path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 13:26:04 +05:30

47 lines
2.4 KiB
Bash
Executable File

#!/usr/bin/env bash
# ──────────────────────────────────────────────────────────────────────────
# macos-dev-unquarantine.sh — strip com.apple.quarantine from a LOCAL TEST
# artifact so you can launch an unsigned dev/preview build without the
# right-click → Open dance.
#
# ⚠️ LOCAL DEVELOPMENT CONVENIENCE ONLY.
# This is NEVER a substitute for proper Developer ID signing + notarization
# of production releases. Real users must receive a signed, notarized build
# (see docs/macos-signing-verification.md) — do not ship artifacts and tell
# users to run this. Production signing is gated separately in release.yml.
#
# Usage:
# scripts/macos-dev-unquarantine.sh "path/to/OmniVoice Studio.app"
# scripts/macos-dev-unquarantine.sh ~/Downloads/OmniVoice*.dmg
# scripts/macos-dev-unquarantine.sh # auto-discover newest built .app
# ──────────────────────────────────────────────────────────────────────────
set -uo pipefail
if [ "$(uname -s)" != "Darwin" ]; then
echo "macos-dev-unquarantine: not macOS — nothing to do."
exit 0
fi
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
TARGET="${1:-}"
if [ -z "$TARGET" ]; then
TARGET="$(find "$REPO_ROOT/frontend/src-tauri/target" -type d -name '*.app' -path '*/bundle/macos/*' 2>/dev/null | grep -E '/release/' | head -1)"
[ -z "$TARGET" ] && TARGET="$(find "$REPO_ROOT/frontend/src-tauri/target" -type d -name '*.app' -path '*/bundle/macos/*' 2>/dev/null | head -1)"
[ -z "$TARGET" ] && { echo "ERROR: no built .app found — pass an explicit path." >&2; exit 2; }
fi
[ -e "$TARGET" ] || { echo "ERROR: path does not exist: $TARGET" >&2; exit 2; }
echo "⚠️ DEV-ONLY: stripping com.apple.quarantine from:"
echo " $TARGET"
echo " (not a substitute for signing + notarization — see docs/macos-signing-verification.md)"
xattr -dr com.apple.quarantine "$TARGET" 2>/dev/null || true
if xattr -pr com.apple.quarantine "$TARGET" >/dev/null 2>&1; then
echo "✗ quarantine attribute still present — try: sudo xattr -dr com.apple.quarantine \"$TARGET\""
exit 1
fi
echo "✓ quarantine cleared — the unsigned build will now launch locally."