spb/zyquo-agent Public MIT
The autonomous agent that actually operates your Mac — plans, runs real commands, verifies its own work.
Swift 94.7%
Shell 4.1%
Python 0.7%
Makefile 0.5%
1#!/bin/bash2#3# notarize.sh4# Zyquo Agent5#6# Author: Simon-Pierre Boucher7# Mail: contact@spboucher.ai8#9# Developer ID signing, notarization, stapling, and verification for10# Zyquo Agent. Identity, Team ID, and the notarytool keychain profile are the11# same ones the Zyquo family already uses (see ~/Desktop/other/OTHER/zyquo-term).12#13# Usage: notarize.sh <app-dir> <identity> <keychain-profile> <entitlements>14# notarize.sh <app-dir> <identity> <keychain-profile> <entitlements> dmg15#16# Signs nested code first, then the bundle, with the Hardened Runtime and a17# secure timestamp; submits a ditto zip to Apple, waits, staples the ticket,18# and fails loudly unless `spctl` reports "Notarized Developer ID".19#20# Entitlements posture (Resources/ZyquoAgent.entitlements): Hardened Runtime21# ON, App Sandbox deliberately OFF (Zyquo Agent must spawn /bin/bash and22# /usr/bin/osascript to do its job, like Terminal.app or the sibling Zyquo23# Term); the only declared entitlement is24# com.apple.security.automation.apple-events, paired with25# NSAppleEventsUsageDescription in Info.plist, for AppleScript automation.26# Keep that file pure ASCII with no XML comments: the AMFI parser codesign27# uses rejects both.28#29set -euo pipefail3031APP_DIR="${1:?app bundle path required}"32IDENTITY="${2:?signing identity required}"33KEYCHAIN_PROFILE="${3:?notarytool keychain profile required}"34ENTITLEMENTS="${4:?entitlements plist required}"35MAKE_DMG="${5:-}"3637APP_NAME="$(basename "$APP_DIR" .app)"38DIST="$(dirname "$APP_DIR")"39EXEC_NAME="ZyquoAgent"40ZIP_PATH="$DIST/${EXEC_NAME}.zip"41DMG_PATH="$DIST/${EXEC_NAME}.dmg"4243[ -d "$APP_DIR" ] || { echo "ERROR: $APP_DIR missing — run make release/bundle first" >&2; exit 1; }44[ -f "$ENTITLEMENTS" ] || { echo "ERROR: $ENTITLEMENTS missing" >&2; exit 1; }4546# ---------------------------------------------------------------- signing --47echo "=== Signing (Developer ID, hardened runtime) ==="48# Nested code first (frameworks/bundles/helpers), then the main executable,49# then the bundle itself — codesign requires inside-out order.50while IFS= read -r -d '' nested; do51 echo " nested: $nested"52 codesign --force --options runtime --timestamp \53 --entitlements "$ENTITLEMENTS" --sign "$IDENTITY" "$nested"54done < <(find "$APP_DIR/Contents" \55 \( -name '*.framework' -o -name '*.dylib' -o -name '*.bundle' \) -print0 2>/dev/null)5657codesign --force --options runtime --timestamp \58 --entitlements "$ENTITLEMENTS" --sign "$IDENTITY" \59 "$APP_DIR/Contents/MacOS/$EXEC_NAME"60codesign --force --options runtime --timestamp \61 --entitlements "$ENTITLEMENTS" --sign "$IDENTITY" "$APP_DIR"6263echo "=== Verifying signature ==="64codesign --verify --deep --strict --verbose=2 "$APP_DIR"65codesign --display --entitlements - --verbose=2 "$APP_DIR" 2>&1 | sed -n '1,12p'6667# ------------------------------------------------------------ notarizing --68echo "=== Submitting to Apple notary service (profile: $KEYCHAIN_PROFILE) ==="69rm -f "$ZIP_PATH"70ditto -c -k --keepParent "$APP_DIR" "$ZIP_PATH"71xcrun notarytool submit "$ZIP_PATH" --keychain-profile "$KEYCHAIN_PROFILE" --wait7273echo "=== Stapling ==="74xcrun stapler staple "$APP_DIR"75xcrun stapler validate "$APP_DIR"7677echo "=== Gatekeeper assessment ==="78assessment="$(spctl -a -vv "$APP_DIR" 2>&1)"79echo "$assessment"80case "$assessment" in81 *"source=Notarized Developer ID"*)82 echo "✅ spctl: accepted, source=Notarized Developer ID" ;;83 *)84 echo "❌ spctl did not report a notarized Developer ID signature" >&285 exit 1 ;;86esac8788# Re-zip the stapled bundle so the distributed archive carries the ticket.89rm -f "$ZIP_PATH"90ditto -c -k --keepParent "$APP_DIR" "$ZIP_PATH"91echo "Archive: $ZIP_PATH"9293# ------------------------------------------------------------- optional dmg --94if [ "$MAKE_DMG" = "dmg" ]; then95 echo "=== Building signed + notarized DMG ==="96 rm -f "$DMG_PATH"97 hdiutil create -volname "$APP_NAME" -srcfolder "$APP_DIR" \98 -ov -format UDZO "$DMG_PATH"99 codesign --force --timestamp --sign "$IDENTITY" "$DMG_PATH"100 xcrun notarytool submit "$DMG_PATH" --keychain-profile "$KEYCHAIN_PROFILE" --wait101 xcrun stapler staple "$DMG_PATH"102 spctl -a -vv -t open --context context:primary-signature "$DMG_PATH" 2>&1 | tail -3103 echo "DMG: $DMG_PATH"104fi105106echo "=== Done: $APP_DIR is signed, notarized, and stapled ==="107