Skip to content

Latest commit

 

History

History
98 lines (83 loc) · 4.76 KB

File metadata and controls

98 lines (83 loc) · 4.76 KB

Taskly Update Contract

Online updates are the release vehicle: every platform must be able to check, download, verify and install a new version without the user hunting for download pages. The behavior (triggers, UX, strings, failure handling) is identical on all platforms; the transport and install mechanism is native to each platform, like every other part of the Taskly architecture.

Behavior contract (all platforms)

  • Triggers: one silent check shortly after launch (throttled: at most once per 4 hours, persisted as config key last-update-check, unix epoch seconds), plus a manual Settings ▸ 检查更新… / Check for Updates… menu item that bypasses the throttle.
  • Silent mode: network failure / rate limit / not-installed → silently ignore (never nag). Manual mode reports every outcome.
  • Newer version found (semver compare, downgrades ignored) → dialog with the new version: 立即更新 / Update (install + relaunch) or 取消 / Cancel. Up-to-date → 当前已是最新版本 / Up to date.
  • Install failure → non-crashing error with the platform message; the running version keeps working (same rule as notifications).
  • CLI parity: --json output and exit codes are version-stable; an update must never change golden outputs within a major version.
  • i18n keys are shared (shared/i18n): menuCheckUpdates, updateUpToDate, updateAvailableTitle, updateAvailableBody, updateRestart, updateCheckFailed, updatePortable, plus macOS/ Linux-only keys below.

Platform mechanisms

The release pipeline signs and uploads update-manifest.json + manifest.sig for every release (see release.yml), so the feed exists on all platforms from day one. Host-side updaters land per platform:

Platform Feed Install Integrity Status
macOS update-manifest.json (this contract) zip → sha256 → ditto → atomic swap in place Ed25519 manifest signature (CryptoKit) + artifact sha256 shipped (macos-host/Sources/RivetHost/UpdateService.swift)
Windows update-manifest.json (this contract, windows entry) manual download until the host updater lands manifest sha256 host updater not built yet
Linux update-manifest.json (this contract, linux entry) manual download until the host updater lands manifest sha256 host updater not built yet

(The frozen v1 line used Velopack on Windows and a tarball replacer on Linux; those mechanisms died with that line — the Rivet hosts start from the manifest feed above.)

update-manifest.json

Generated by scripts/make-update-manifest.sh from the release artifacts and uploaded as a release asset. Exact bytes of the file are signed; the signature ships alongside as manifest.sig.

{
  "version": "1.1.0",
  "notesUrl": "https://github.com/turinglambdaai/taskly/releases/download/v1.1.0",
  "platforms": {
    "macos":   { "url": "https://…/taskly-1.1.0-macos-arm64.zip",
                 "sha256": "<hex of the zip>", "size": 12345678 },
    "windows": { "url": "https://…/taskly-1.1.0-windows-x64.zip",
                 "sha256": "<hex of the zip>", "size": 23456789 },
    "linux":   { "url": "https://…/taskly-1.1.0-linux-x64.tar.gz",
                 "sha256": "<hex of the tarball>", "size": 34567890 }
  }
}
  • version: the release version without the v prefix, must equal the root VERSION file.
  • Clients resolve the latest release via https://api.github.com/repos/turinglambdaai/taskly/releases/latest and download the update-manifest.json + manifest.sig assets from it (no separate metadata host).

Ed25519 signature (macOS)

  • Key type: Ed25519. Private key lives ONLY in the GitHub secret UPDATE_ED25519_PRIVATE_KEY (PEM) and in the release manager's local backup — never in the repository.
  • Generate / inspect: scripts/update-keys.sh (openssl, one-time).
  • Sign: `openssl pkeyutl -sign -inkey key.pem -rawin -in update-manifest.json

    manifest.sig (-rawin` is mandatory for Ed25519).

  • Public key: 32 raw bytes, base64, embedded as UpdateService.publicKeyBase64 in the macOS app. Rotate = ship a new public key one release before retiring the old private key.
  • Verification: exact manifest bytes → isValidSignature; any mismatch aborts the update silently in silent mode, with an error in manual mode.

Rollout rules

  • Downgrades are never auto-installed; semver compare is numeric per segment.
  • The updater must never delete or touch ~/.taskly/ (DB + config) — it swaps application bundles/prefixes only.
  • A failed swap must leave the previous install runnable (macOS keeps a .old copy until the next successful launch; future host updaters follow the same rule — replace only after a complete, checksummed extraction).