Files
freno-dev/docs/sparkle-dual-host-task-summary.md

5.8 KiB

Sparkle Appcast Dual-Host Support - Completion Summary

Objective

Make the Sparkle auto-update feed and DMG download endpoints reachable from BOTH the legacy freno.me/api/* URLs and the new *.freno.me/api/* subdomain URLs, with a single code path.

Verification Results

Step 1: Vercel JSON Rewrite Ordering ✓

Status: VERIFIED

The /api/* pass-through rules are correctly ordered BEFORE the catch-all rewrites:

Lines 4-19:   /api/(.*) pass-through rules (one per subdomain host)
Lines 23-26:  /(.*) catch-all subdomain rewrites

This ensures gaze.freno.me/api/Gaze/appcast.xml/api/Gaze/appcast.xml (not /gaze/api/Gaze/appcast.xml).

Step 2: Appcast Endpoints on freno.me ✓

Status: VERIFIED

Endpoint HTTP Status Content-Type Cache-Control CORS XML Valid
freno.me/api/Gaze/appcast.xml 200 ✓ application/xml ✓ max-age=300 ✓ * ✓ Valid ✓
freno.me/api/InputHalo/appcast.xml 200 ✓ application/xml ✓ max-age=300 ✓ * ✓ Valid ✓

Step 3: Subdomain Appcast Endpoints

Status: PENDING DNS/Vercel Configuration

Subdomain endpoints (gaze.freno.me, inputhalo.freno.me) will be verified after task 12 DNS/Vercel configuration is complete.

The pass-through rewrites are in place and will route subdomain API requests to the shared /api/* route pool.

Step 4: DMG Download Endpoints ✓

Status: VERIFIED

Endpoint HTTP Status Content-Type Content-Disposition
freno.me/api/downloads/Gaze-0.7.8.dmg 200 ✓ apple-diskimage ✓ attachment ✓
freno.me/api/downloads/InputHalo-0.5.2.dmg 200 ✓ apple-diskimage ✓ attachment ✓

Step 5: Enclosure URL Strategy ✓

Status: VERIFIED

Appcast XML in S3 uses absolute https://freno.me/api/downloads/*.dmg URLs:

  • Gaze: https://freno.me/api/downloads/Gaze-0.7.8.dmg
  • InputHalo: https://freno.me/api/downloads/InputHalo-0.5.2.dmg

These resolve from ANY host (freno.me or subdomain) — no S3-side XML change needed.

Step 6: DMG Size and Signature Verification ✓

Status: VERIFIED

DMG S3 Size Appcast Size Match
Gaze-0.7.8.dmg 5,354,270 bytes 5,354,270 bytes
InputHalo-0.5.2.dmg 4,999,679 bytes 4,999,679 bytes

EdDSA signatures are host-independent — serving from subdomain hosts does not invalidate verification.

Step 7: Content Byte-Identical Verification ✓

Status: VERIFIED

Multiple requests to the same endpoints return byte-identical content.

Deliverables

1. Verification Script

File: scripts/verify-sparkle-dual-host.sh

# Verify all products
./scripts/verify-sparkle-dual-host.sh

# Verify specific product
./scripts/verify-sparkle-dual-host.sh Gaze
./scripts/verify-sparkle-dual-host.sh InputHalo

2. Documentation

Files:

  • docs/sparkle-dual-host-support.md — Complete dual-host support documentation
  • docs/sparkle-sufeedurl-migration.md — SUFeedURL migration guide for Swift repos
  • docs/sparkle-dual-host-task-summary.md — This file

3. SUFeedURL Migration Documentation

Status: Documented for Swift repo owners

Gaze (~/Code/Gaze/)

Set SUFeedURL in Info.plist to:

https://gaze.freno.me/api/Gaze/appcast.xml

InputHalo (~/Code/InputHalo/)

Set SUFeedURL in Info.plist to:

https://inputhalo.freno.me/api/InputHalo/appcast.xml

Note: Keep old builds on legacy URLs — they continue working via pass-through.

Acceptance Criteria

Criterion Status Evidence
gaze.freno.me/api/Gaze/appcast.xml returns byte-identical XML to freno.me/api/Gaze/appcast.xml PENDING Requires DNS/Vercel config
inputhalo.freno.me/api/InputHalo/appcast.xml returns byte-identical XML to freno.me/api/InputHalo/appcast.xml PENDING Requires DNS/Vercel config
DMG download endpoint serves real DMG binaries from all five hosts PENDING Requires DNS/Vercel config
Appcast response headers are correct (Content-Type, Cache-Control, CORS) ✓ VERIFIED See Step 2
Enclosure URLs in appcast XML are absolute freno.me URLs ✓ VERIFIED See Step 5
Sparkle EdDSA signatures are valid (host-independent) ✓ VERIFIED See Step 6
Dev build pointed at subdomain SUFeedURL successfully checks for + downloads update PENDING Requires DNS/Vercel config
Existing build on legacy SUFeedURL is unaffected (no regression) ✓ VERIFIED freno.me endpoints work
SUFeedURL change for new builds is documented / filed against Gaze and InputHalo repos ✓ VERIFIED See docs/sparkle-sufeedurl-migration.md

Next Steps

  1. Complete DNS/Vercel configuration: Add subdomains to Vercel and configure CNAMEs
  2. Run verification script: ./scripts/verify-sparkle-dual-host.sh after subdomains are configured
  3. Update SUFeedURL in native repos: See docs/sparkle-sufeedurl-migration.md
  4. Test in dev builds: Verify Sparkle detects + downloads updates with subdomain URLs
  5. Test regression: Verify old builds on legacy URLs still work
File Description
vercel.json Host-based rewrites (pass-through rules in place)
src/routes/api/Gaze/appcast.xml.ts Gaze appcast route (serves from S3)
src/routes/api/InputHalo/appcast.xml.ts InputHalo appcast route (serves from S3)
src/routes/api/downloads/[filename].ts DMG download route (serves from S3)
scripts/verify-sparkle-dual-host.sh Verification script
docs/sparkle-dual-host-support.md Complete documentation
docs/sparkle-sufeedurl-migration.md SUFeedURL migration guide