diff --git a/.github/workflows/auto-release.yml b/.github/workflows/auto-release.yml
index e651e75..d987cba 100644
--- a/.github/workflows/auto-release.yml
+++ b/.github/workflows/auto-release.yml
@@ -9,7 +9,9 @@ name: Auto-release
#
# Optional secrets (unsigned local-style build until these exist):
# MACOS_CERT_P12_BASE64, MACOS_CERT_PASSWORD Developer ID signing
-# NOTARY_APPLE_ID, NOTARY_TEAM_ID, NOTARY_PASSWORD notarization
+# NOTARY_KEY, NOTARY_KEY_ID, NOTARY_ISSUER_ID notarization (App Store
+# Connect API key — the team Apple ID is Microsoft-federated, so
+# app-specific passwords don't exist for it)
# TAP_DEPLOY_KEY SSH deploy key with write access to tutorintelligence/homebrew-tap
# SPARKLE_ED_PRIVATE_KEY signs update zips for the Sparkle appcast
on:
@@ -73,16 +75,18 @@ jobs:
fi
- name: Notarize and staple
- if: steps.ver.outputs.next != '' && env.NOTARY_APPLE_ID != ''
+ if: steps.ver.outputs.next != '' && env.NOTARY_KEY_ID != ''
env:
- NOTARY_APPLE_ID: ${{ secrets.NOTARY_APPLE_ID }}
- NOTARY_TEAM_ID: ${{ secrets.NOTARY_TEAM_ID }}
- NOTARY_PASSWORD: ${{ secrets.NOTARY_PASSWORD }}
+ NOTARY_KEY: ${{ secrets.NOTARY_KEY }}
+ NOTARY_KEY_ID: ${{ secrets.NOTARY_KEY_ID }}
+ NOTARY_ISSUER_ID: ${{ secrets.NOTARY_ISSUER_ID }}
run: |
+ echo "$NOTARY_KEY" > /tmp/notary_key.p8
ditto -c -k --keepParent dist/tingle.app dist/notarize.zip
- xcrun notarytool submit dist/notarize.zip --apple-id "$NOTARY_APPLE_ID" \
- --team-id "$NOTARY_TEAM_ID" --password "$NOTARY_PASSWORD" --wait
+ xcrun notarytool submit dist/notarize.zip --key /tmp/notary_key.p8 \
+ --key-id "$NOTARY_KEY_ID" --issuer "$NOTARY_ISSUER_ID" --wait
xcrun stapler staple dist/tingle.app
+ rm /tmp/notary_key.p8
- name: Package artifact
if: steps.ver.outputs.next != ''
diff --git a/CLAUDE.md b/CLAUDE.md
index da92c42..94e6e02 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -164,5 +164,7 @@ SPARKLE_ED_PRIVATE_KEY repo secret and Josh's login keychain, account
tutorintelligence/homebrew-tap. `tools/test_next_version.py` covers the
version math. Until the Apple Developer secrets land the build is unsigned
but releases still cut. Optional secrets: MACOS_CERT_P12_BASE64,
-MACOS_CERT_PASSWORD, NOTARY_APPLE_ID, NOTARY_TEAM_ID, NOTARY_PASSWORD,
-TAP_DEPLOY_KEY (SSH deploy key that pushes the cask bump to tutorintelligence/homebrew-tap).
+MACOS_CERT_PASSWORD, NOTARY_KEY / NOTARY_KEY_ID / NOTARY_ISSUER_ID (App
+Store Connect API key — the team Apple ID is Microsoft-federated, so
+app-specific passwords are unavailable), TAP_DEPLOY_KEY (SSH deploy key
+that pushes the cask bump to tutorintelligence/homebrew-tap).
diff --git a/packaging/entitlements.plist b/packaging/entitlements.plist
new file mode 100644
index 0000000..0be9796
--- /dev/null
+++ b/packaging/entitlements.plist
@@ -0,0 +1,14 @@
+
+
+
+
+
+ com.apple.security.device.audio-input
+
+ com.apple.security.automation.apple-events
+
+
+
diff --git a/scripts/bundle.sh b/scripts/bundle.sh
index 73c75fc..c902a66 100755
--- a/scripts/bundle.sh
+++ b/scripts/bundle.sh
@@ -72,6 +72,8 @@ cat > "$APP/Contents/Info.plist" <3BlTef+CpeHVRaFJfuvpqt1XGbVZe1HDPo3C127U70E=
SUEnableAutomaticChecks
+ NSAppleEventsUsageDescription
+ tingle's summon-agent button brings your coding app to the front.
NSMicrophoneUsageDescription
tingle listens to your line-in to detect the ting's ultrasonic signals and to transcribe dictation from its microphone.
NSHumanReadableCopyright
@@ -80,5 +82,19 @@ cat > "$APP/Contents/Info.plist" <
PLIST
-codesign --force --deep --sign "$IDENTITY" "$APP"
+# Hardened runtime is REQUIRED for notarization; the entitlements re-grant
+# mic capture and Apple Events under it. Sign Sparkle's nested code first
+# (its XPC services must each carry hardened runtime), then the app.
+if [ "$IDENTITY" != "-" ]; then
+ find "$APP/Contents/Frameworks/Sparkle.framework" \
+ \( -name "*.xpc" -o -name "*.app" \) -maxdepth 5 | while read -r NESTED; do
+ codesign --force --options runtime --sign "$IDENTITY" "$NESTED"
+ done
+ codesign --force --options runtime --sign "$IDENTITY" "$APP/Contents/Frameworks/Sparkle.framework"
+ codesign --force --options runtime \
+ --entitlements packaging/entitlements.plist \
+ --sign "$IDENTITY" "$APP"
+else
+ codesign --force --deep --sign "$IDENTITY" "$APP"
+fi
echo "built $APP (version $VERSION, signed: $IDENTITY)"