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)"