Skip to content

ADR 0022: Application Update Delivery

  • Status: Accepted
  • Date: 2026-07-26
  • Deciders: PI-Desktop core
  • Related: D120, D126, D010, ADR 0021

Context

PI-Desktop needs a release-update path that preserves the renderer sandbox, does not expose feed configuration to untrusted UI code, and reflects each platform's actual installer capabilities. A single automatic-install policy is not appropriate: unsigned macOS packages cannot provide a qualified in-app upgrade lane, while Windows NSIS and Linux AppImage support electron-updater's download-and-install flow.

Decision

  1. Electron Main exclusively owns electron-updater, the fixed GitHub Releases feed, update polling, and install lifecycle. Renderer IPC exposes only allowlisted check, state, release-link, and install operations; callers cannot supply a feed URL.
  2. Development builds keep updates disabled. Packaged macOS and non-AppImage Linux use manual delivery: discovery stops at available and opens the fixed releases page. Windows NSIS and Linux AppImage use in-app download and quit-and-install delivery.
  3. The updater always sets allowPrerelease = false. electron-updater would otherwise pin prerelease installs (for example 0.2.0-rc.6) to the same custom channel (rc) and never offer a newer stable GitHub latest release. Prerelease-channel policy remains an operational follow-up if a dedicated RC feed is needed later.
  4. Automatic checks run after startup and periodically. Automatic failures remain ambient; explicit checks expose status and errors through the menu and Settings -> Info. A downloaded update remains actionable until install or normal shutdown.
  5. Feed manifests and artifact hashes are generated by electron-builder. The client ships no GitHub credential and fails closed when the feed or package cannot be validated.
  6. D126 later lifts D010's macOS-only publication scope and publishes all platform artifacts and update manifests produced by the release matrix. macOS remains notify-and-link until a signed in-app channel is separately qualified.
  7. Dual-locale product "what's new" text (D164) is maintained in packages/shared as EN + zh-CN catalogs. Main formats notes for the discovered version using the product UI locale and attaches them as optional UpdateState.releaseNotes on the existing updates path. GitHub auto-generated release bodies remain web-only; the renderer never supplies a notes URL.

Consequences

  • Update state is process-owned and consistent across the application menu, Settings, and the ambient banner.
  • The sandboxed renderer cannot redirect update traffic or install arbitrary packages.
  • Windows NSIS and Linux AppImage can update in-app from published tag feeds; macOS and Linux deb users install from the release page.
  • Prerelease installs graduate to newer stable releases through the same latest feed; a dedicated RC channel is not active.
  • In-app bilingual release highlights ship with the build and follow the product locale without a second network surface.
  • Signing, rollback, staged rollout, and optional prerelease-channel policy remain operational follow-ups rather than renderer capabilities.

Alternatives

  • Renderer-owned updater: rejected because it violates the process and sandbox boundary.
  • Caller-provided feed URLs: rejected because it creates an arbitrary package installation path.
  • Force one delivery mode on every platform: rejected because installer and signing guarantees differ by target.

Built for local-first development.