diff --git a/VibeTunnel/version.xcconfig b/VibeTunnel/version.xcconfig
index 5a15e8c1..52bf9fb8 100644
--- a/VibeTunnel/version.xcconfig
+++ b/VibeTunnel/version.xcconfig
@@ -2,7 +2,7 @@
// This file contains the version and build number for the app
MARKETING_VERSION = 1.0.0-beta.2
-CURRENT_PROJECT_VERSION = 104
+CURRENT_PROJECT_VERSION = 105
// Domain and GitHub configuration
APP_DOMAIN = vibetunnel.sh
diff --git a/appcast-prerelease.xml b/appcast-prerelease.xml
index 91fc1876..8d95428a 100644
--- a/appcast-prerelease.xml
+++ b/appcast-prerelease.xml
@@ -5,39 +5,6 @@
https://github.com/amantus-ai/vibetunnel
VibeTunnel pre-release and beta updates feed
en
- -
- VibeTunnel 1.0.0-beta.2
- https://github.com/amantus-ai/vibetunnel/releases/download/v1.0.0-beta.2/VibeTunnel-1.0.0-beta.2.dmg
- 104
- 1.0.0-beta.2
- VibeTunnel 1.0.0-beta.2
Pre-release version
🎨 Improvements
-
-- Redesigned slick new web frontend
-- Faster terminal rendering in the web frontend
-- New Sessions spawn new Terminal windows. (This needs Applescript and Accessibility permissions)
-- Enhanced font handling with system font priority
-- Better async operations in PTY service for improved performance
-- Improved window activation when showing the welcome and settings windows
-- Preparations for Linux support
-
-
🐛 Bug Fixes
-
-- Fixed window front order when dock icon is hidden
-- Fixed PTY service enhancements with proper async operations
-- Fixed race condition in session creation that caused frontend to open previous session
-
-
View full changelog
- ]]>
- Thu, 19 Jun 2025 02:14:36 +0200
-
- 15.0
-
-
VibeTunnel 1.0-beta.1
https://github.com/amantus-ai/vibetunnel/releases/download/v1.0-beta.1/VibeTunnel-1.0-beta.1.dmg
diff --git a/scripts/codesign-app.sh b/scripts/codesign-app.sh
index cb6f61a7..a89e08a1 100755
--- a/scripts/codesign-app.sh
+++ b/scripts/codesign-app.sh
@@ -89,26 +89,26 @@ if [ -d "$APP_BUNDLE/Contents/Frameworks" ]; then
log "Signing embedded frameworks..."
find "$APP_BUNDLE/Contents/Frameworks" \( -type d -name "*.framework" -o -type f -name "*.dylib" \) 2>/dev/null | while read -r framework; do
log "Signing framework: $framework"
- codesign --force --options runtime --sign "$SIGN_IDENTITY" $KEYCHAIN_OPTS "$framework" || log "Warning: Failed to sign $framework"
+ codesign --force --options runtime --timestamp --sign "$SIGN_IDENTITY" $KEYCHAIN_OPTS "$framework" || log "Warning: Failed to sign $framework"
done
fi
# Sign embedded binaries (like tty-fwd)
if [ -f "$APP_BUNDLE/Contents/Resources/tty-fwd" ]; then
log "Signing tty-fwd binary..."
- codesign --force --options runtime --sign "$SIGN_IDENTITY" $KEYCHAIN_OPTS "$APP_BUNDLE/Contents/Resources/tty-fwd" || log "Warning: Failed to sign tty-fwd"
+ codesign --force --options runtime --timestamp --sign "$SIGN_IDENTITY" $KEYCHAIN_OPTS "$APP_BUNDLE/Contents/Resources/tty-fwd" || log "Warning: Failed to sign tty-fwd"
fi
# Sign the main executable
log "Signing main executable..."
-codesign --force --options runtime --entitlements "$TMP_ENTITLEMENTS" --sign "$SIGN_IDENTITY" $KEYCHAIN_OPTS "$APP_BUNDLE/Contents/MacOS/VibeTunnel" || true
+codesign --force --options runtime --timestamp --entitlements "$TMP_ENTITLEMENTS" --sign "$SIGN_IDENTITY" $KEYCHAIN_OPTS "$APP_BUNDLE/Contents/MacOS/VibeTunnel" || true
# Sign the app bundle WITHOUT deep signing (per Sparkle documentation)
# "Due to different code signing requirements, please do not add --deep to
# OTHER_CODE_SIGN_FLAGS or from custom build scripts when signing your application.
# This is a common source of Sandboxing errors."
log "Signing complete app bundle (without --deep per Sparkle requirements)..."
-codesign --force --options runtime --entitlements "$TMP_ENTITLEMENTS" --sign "$SIGN_IDENTITY" $KEYCHAIN_OPTS "$APP_BUNDLE"
+codesign --force --options runtime --timestamp --entitlements "$TMP_ENTITLEMENTS" --sign "$SIGN_IDENTITY" $KEYCHAIN_OPTS "$APP_BUNDLE"
# Verify the signature
log "Verifying code signature..."
diff --git a/scripts/notarize-app.sh b/scripts/notarize-app.sh
index 108ed8d2..b8345794 100755
--- a/scripts/notarize-app.sh
+++ b/scripts/notarize-app.sh
@@ -188,28 +188,29 @@ if [ -n "${KEYCHAIN_NAME:-}" ]; then
fi
# Sign XPC services (directories, not files)
+# IMPORTANT: Do NOT use --deep flag, sign each component individually
if [ -d "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Installer.xpc" ]; then
- codesign -f -s "$SIGN_IDENTITY" -o runtime $keychain_opts "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Installer.xpc"
+ codesign -f -s "$SIGN_IDENTITY" -o runtime --timestamp $keychain_opts "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Installer.xpc"
log "Signed Installer.xpc"
fi
if [ -d "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Downloader.xpc" ]; then
# For Sparkle versions >= 2.6, preserve entitlements
- codesign -f -s "$SIGN_IDENTITY" -o runtime --preserve-metadata=entitlements $keychain_opts "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Downloader.xpc"
+ codesign -f -s "$SIGN_IDENTITY" -o runtime --timestamp --preserve-metadata=entitlements $keychain_opts "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Downloader.xpc"
log "Signed Downloader.xpc"
fi
# Sign other Sparkle components
if [ -f "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework/Versions/B/Autoupdate" ]; then
- codesign -f -s "$SIGN_IDENTITY" -o runtime $keychain_opts "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework/Versions/B/Autoupdate"
+ codesign -f -s "$SIGN_IDENTITY" -o runtime --timestamp $keychain_opts "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework/Versions/B/Autoupdate"
log "Signed Autoupdate"
fi
if [ -d "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework/Versions/B/Updater.app" ]; then
- codesign -f -s "$SIGN_IDENTITY" -o runtime $keychain_opts "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework/Versions/B/Updater.app"
+ codesign -f -s "$SIGN_IDENTITY" -o runtime --timestamp $keychain_opts "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework/Versions/B/Updater.app"
log "Signed Updater.app"
fi
# Finally sign the framework itself
-codesign -f -s "$SIGN_IDENTITY" -o runtime $keychain_opts "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework"
+codesign -f -s "$SIGN_IDENTITY" -o runtime --timestamp $keychain_opts "$APP_BUNDLE/Contents/Frameworks/Sparkle.framework"
log "Signed Sparkle.framework"
# 2. Sparkle framework is already signed above per documentation
diff --git a/scripts/release.sh b/scripts/release.sh
index 1b66224b..00fc5fe5 100755
--- a/scripts/release.sh
+++ b/scripts/release.sh
@@ -331,6 +331,56 @@ echo ""
echo -e "${BLUE}📋 Step 5/8: Signing and notarizing...${NC}"
"$SCRIPT_DIR/sign-and-notarize.sh" --sign-and-notarize
+# Verify Sparkle component signing
+echo ""
+echo -e "${BLUE}🔍 Verifying Sparkle component signatures...${NC}"
+SPARKLE_OK=true
+
+# Check each Sparkle component for proper signing with timestamps
+if [ -d "$APP_PATH/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Installer.xpc" ]; then
+ if ! codesign -dv "$APP_PATH/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Installer.xpc" 2>&1 | grep -q "timestamp"; then
+ echo -e "${RED}❌ Installer.xpc missing timestamp signature${NC}"
+ SPARKLE_OK=false
+ else
+ echo "✅ Installer.xpc properly signed with timestamp"
+ fi
+fi
+
+if [ -d "$APP_PATH/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Downloader.xpc" ]; then
+ if ! codesign -dv "$APP_PATH/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Downloader.xpc" 2>&1 | grep -q "timestamp"; then
+ echo -e "${RED}❌ Downloader.xpc missing timestamp signature${NC}"
+ SPARKLE_OK=false
+ else
+ echo "✅ Downloader.xpc properly signed with timestamp"
+ fi
+fi
+
+if [ -f "$APP_PATH/Contents/Frameworks/Sparkle.framework/Versions/B/Autoupdate" ]; then
+ if ! codesign -dv "$APP_PATH/Contents/Frameworks/Sparkle.framework/Versions/B/Autoupdate" 2>&1 | grep -q "timestamp"; then
+ echo -e "${RED}❌ Autoupdate missing timestamp signature${NC}"
+ SPARKLE_OK=false
+ else
+ echo "✅ Autoupdate properly signed with timestamp"
+ fi
+fi
+
+if [ -d "$APP_PATH/Contents/Frameworks/Sparkle.framework/Versions/B/Updater.app" ]; then
+ if ! codesign -dv "$APP_PATH/Contents/Frameworks/Sparkle.framework/Versions/B/Updater.app" 2>&1 | grep -q "timestamp"; then
+ echo -e "${RED}❌ Updater.app missing timestamp signature${NC}"
+ SPARKLE_OK=false
+ else
+ echo "✅ Updater.app properly signed with timestamp"
+ fi
+fi
+
+if [ "$SPARKLE_OK" = false ]; then
+ echo -e "${RED}❌ Sparkle component signing verification failed!${NC}"
+ echo "This will cause 'update isn't properly signed' errors for users."
+ exit 1
+fi
+
+echo -e "${GREEN}✅ All Sparkle components properly signed${NC}"
+
# Step 5: Create DMG
echo ""
echo -e "${BLUE}📋 Step 6/8: Creating DMG...${NC}"
@@ -381,6 +431,47 @@ fi
echo -e "${GREEN}✅ DMG notarization complete and verified${NC}"
+# Verify app inside DMG is properly signed
+echo ""
+echo -e "${BLUE}🔍 Verifying app inside DMG...${NC}"
+
+# Mount the DMG temporarily
+DMG_MOUNT=$(mktemp -d)
+if hdiutil attach "$DMG_PATH" -mountpoint "$DMG_MOUNT" -nobrowse -quiet; then
+ DMG_APP="$DMG_MOUNT/VibeTunnel.app"
+
+ # Check if app is notarized
+ if spctl -a -t exec -vv "$DMG_APP" 2>&1 | grep -q "source=Notarized Developer ID"; then
+ echo "✅ App in DMG is properly notarized"
+ else
+ echo -e "${RED}❌ App in DMG is not properly notarized!${NC}"
+ hdiutil detach "$DMG_MOUNT" -quiet
+ exit 1
+ fi
+
+ # Check if notarization ticket is stapled
+ if xcrun stapler validate "$DMG_APP" 2>&1 | grep -q "The validate action worked"; then
+ echo "✅ App in DMG has stapled notarization ticket"
+ else
+ echo -e "${RED}❌ App in DMG missing stapled notarization ticket!${NC}"
+ hdiutil detach "$DMG_MOUNT" -quiet
+ exit 1
+ fi
+
+ # Check Sparkle components in DMG
+ if codesign -dv "$DMG_APP/Contents/Frameworks/Sparkle.framework/Versions/B/XPCServices/Installer.xpc" 2>&1 | grep -q "timestamp"; then
+ echo "✅ Sparkle components in DMG properly signed"
+ else
+ echo -e "${YELLOW}⚠️ Warning: Sparkle components in DMG may not have timestamp signatures${NC}"
+ fi
+
+ # Unmount DMG
+ hdiutil detach "$DMG_MOUNT" -quiet
+ echo -e "${GREEN}✅ App inside DMG verification complete${NC}"
+else
+ echo -e "${YELLOW}⚠️ Warning: Could not mount DMG for verification${NC}"
+fi
+
# Step 6: Create GitHub release
echo ""
echo -e "${BLUE}📋 Step 7/9: Creating GitHub release...${NC}"