Distribution architecture · stable channel

Stable release automatic updates

OpenProgram considers only complete, stable GitHub Releases verified against the manifest to be installable updates. Desktop automatically discovers and verifies platform installers: DMG on macOS and Authenticode-signed EXE on Windows; managed CLI/server verifies the complete runtime before switching atomically. New repository commits do not constitute user updates.

Design
Established
One stable channel, one Release contract
Implementation
Merged into main
Desktop, managed CLI, Release gate
Source baseline
v0.8.1
Current source and runtime/package version baseline; remote latest has not been reverified on this page
Dependency
0 new updater packages
Native Electron/Node, Python, and shell capabilities

Question

How can a production installation discover and apply new versions without tracking main, reducing product functionality, or losing a working version on failure?

Audience

Developers and release maintainers responsible for Release, Desktop, CLI/server, Settings, and installation documentation.

Scope

macOS/Windows Desktop, macOS/Linux/Windows managed CLI/server, and explicit routing for source checkouts.

Exclusions

Windows sandboxing, macOS signing, Linux Desktop, PyPI product installation, and background replacement of a running application.

01

Product contracts to preserve

Platform actions differ, but version sources, complete-product definitions, and verification results must agree.

Release unit

The update unit is the complete product

Do not update the wheel, Web, Program, OCR, Browser, or models separately. Every supported artifact satisfies the unified capability manifest and includes a pinned CPython.

Desktop

Automatic checks; open the installer after verification

The main process selects the DMG or EXE for the current platform and architecture and verifies bytes and SHA-256; Windows also verifies Authenticode. The renderer cannot provide URLs, hashes, or filenames.

CLI / server

Explicit command, atomic runtime switch

openprogram upgrade verifies the Release, runtime, capabilities, and cold start, then finally replaces current; it does not automatically restart the existing worker.

Development

Source installations retain the Git workflow

Source checkouts continue to use explicit refs, preflight, build, and probe, without presenting a development branch as a stable Release.

02

From GitHub Release to platform action

The two user paths separate after strict verification. Any missing, duplicate, or inconsistent data stops processing before download or installation.

Automatic update architecture GitHub latest Release passes stable-version, manifest, asset, and architecture validation, then enters either Desktop platform-installer verification and download or the managed CLI complete-runtime atomic-switch path. GitHub latest non-draft · non-prerelease Release gate vX.Y.Z · unique assets Manifest gate version · bytes · sha256 Platform route install type + arch Desktop · macOS arm64/x64 · Windows x64 managed CLI · macOS/Linux/Windows Desktop main process 1 · select exact platform/architecture installer 2 · stream to exclusive random .part file 3 · verify exact bytes + SHA-256 4 · Windows Authenticode, then open installer User confirms the visible platform installation Managed CLI installer 1 · fetch installer from immutable tag 2 · verify archive + capability manifest 3 · version probe + isolated worker cold start 4 · os.replace current symlink User explicitly restarts running worker remote metadata becomes trusted only after validation
1 · GitHub latest
Accept only non-draft, non-prerelease, vX.Y.Z.
2 · Release + manifest gate
Verify unique assets, version, bytes, SHA-256, and platform architecture.
3A · Desktop
Verify the platform installer; Windows additionally verifies Authenticode; the user then confirms installation.
3B · managed CLI
Verify the complete runtime and cold start, then atomically switch current.
metadata / DesktopComplete runtime installationTrust boundaries

The renderer never receives asset URLs, filenames, or hashes; CLI subprocesses inherit only the minimum environment required for installation.

03

Desktop and CLI completion boundaries

“Check,” “download,” and “install” each correspond to verifiable actions. The two platforms use different replacement mechanisms.

macOS Desktop

Automatic discovery + complete download + explicit installation handoff

  1. Startup schedulingA packaged app first checks 30 seconds after startup; development mode does not check automatically.
  2. Strict selectionMatch only the complete unsigned DMG for the current process.arch.
  3. Safe savingUser-selected destination; random exclusive temporary file; streaming size/hash verification.
  4. Open installation mediaOpen the DMG after successful verification. The app does not replace the running .app.

Windows Desktop

Automatic discovery + complete download + signature verification + explicit installation handoff

  1. Startup schedulingA packaged app checks automatically after startup; development mode does not check automatically.
  2. Strict selectionAccept only the exactly named OpenProgram-<version>-win-x64.exe.
  3. Dual verificationVerify size/SHA-256 while streaming; after saving, require Authenticode status Valid.
  4. Open the installerAfter verification, open the per-user NSIS wizard without silently replacing the running application.

macOS / Linux CLI & server

Explicit execution + complete runtime verification + atomic activation

  1. Checkopenprogram upgrade --check reports current and latest versions read-only.
  2. Versioned installerRead the script from the verified immutable tag and pin repository/version.
  3. Isolated acceptanceChecksum, capability manifest, version probe, and worker cold start must all succeed.
  4. ActivateAfter preparing the launcher, use os.replace to switch current; the user explicitly restarts the worker.
04

Settings → General → Application

The following are actual information states in the same Settings section, not separate product versions. Use the buttons or left/right arrow keys to switch.

Application

OpenProgram

Current version0.7.0
Automatically check for updates
Not checked yet
Check now

The cache is absent or expired. Automatic checks are enabled by default.

Application

OpenProgram

Current version0.7.0
Automatically check for updates
Checking GitHub Releases…
Check now · disabled

All windows reuse one in-flight Promise, preventing concurrent metadata requests.

Application

OpenProgram

Current version0.7.1
Latest stable release0.7.1
OpenProgram is up to date
Check nowView release notes

The same or a lower version is shown as up to date; stable downgrades are disallowed.

Application

OpenProgram

Current version0.7.0
Available version0.7.1 · stable
PublishedGitHub Release date
A complete update for this platform is available.
Download and open installerView release notes

Release Notes appear as plain-text summaries inside the app; the full body opens only the fixed GitHub Release page.

Application

OpenProgram

Downloading1.52 GB / 2.45 GB · 62%
Downloading and verifying the complete installer
Download in progress · disabled

The main process publishes progress at most every 250ms and guarantees a final state on completion.

Application

OpenProgram

Available version0.7.1
Download checksum mismatch. The temporary file was removed.
Retry downloadCheck nowView release notes

An error state retains verified release metadata, so users can retry directly without checking again.

05

Scheduling, persistence, and recovery

Automatic checks affect discovery only; they do not trigger unattended installation. Manual checks always force a refresh.

Startup + 30sFirst packaged-app schedule; calculate the due time first if a cache exists.
Successful check + 24hlastSuccessAt determines the next automatic check.
Failed check + 6hlastAttemptAt provides failure backoff, avoiding continuous GitHub requests.
Resume / settings changeClear the old timer, check immediately at most once, then reschedule.
Persisted schema 1

update-state.json

Save automaticChecks, lastAttemptAt, lastSuccessAt, and the latest verified release metadata using a temporary file plus rename. POSIX can specify file mode; Windows inherits the current user-directory ACL.

Repair

Corrupt state cannot control scheduling

Invalid JSON, unknown schemas, future timestamps, version/architecture mismatches, and missing releases are normalized and rewritten. A write failure must not commit hidden in-memory setting changes.

06

Trust boundaries

Verification occurs in the privileged process; the lower-privilege UI receives only projected display state.

Remote metadata

GitHub responses are untrusted by default

HTTPS, fixed host, at most 5 redirects, per-hop validation, size limit, and body idle timeout; also require draft === false and prerelease === false.

  • The tag must be vX.Y.Z
  • Asset names and manifest basenames are unique
  • GitHub size matches manifest bytes
Renderer IPC

The renderer cannot choose remote targets

Preload exposes only getState, check, boolean settings, download, openRelease, and state subscriptions.

  • Accept no URL, path, hash, repository, or command
  • Public state strips asset name/URL/SHA-256
  • Closing a window cannot abort a check or download
Downloaded files

Do not activate before verification finishes

Desktop uses random exclusive temporary files and handles short writes; Windows inherits directory ACLs and additionally verifies Authenticode. CLI verifies the complete runtime in a new version directory before replacing current.

  • Delete temporary files immediately on size/hash/signature mismatch
  • Reject archive path traversal
  • Launcher preparation failure preserves the old current
Child process

The versioned installer uses a minimal environment

Managed upgrade pins the repository and target version, passing only allowed entries such as PATH/HOME/temp/locale/proxy/XDG/OpenProgram state.

  • Do not inherit provider/API credentials
  • Do not inherit archive/checksum source overrides
  • --json always emits a single JSON document
07

Failure semantics

Every error states where processing stopped and what was preserved; vague “update failed” messages do not replace transaction boundaries.

Offline, timeout, GitHub rate limit
Automatic checks record the error and back off for 6 hours; manual checks show a retryable error.
The app and current version keep running
Invalid Release / manifest
Reject the response without downloading; do not fall back to a wheel, source archive, another architecture, or an older version.
The latest valid metadata may be retained
Installer body stall / size / hash / Windows signature error
Abort the response, close the file, delete the random temporary file, and restore the retry action.
Never open an unverified file
CLI archive / cold start / launcher failure
The installer exits nonzero without performing the final current replacement.
The old runtime remains current
Switch succeeded, but the worker still runs the old version
The command explicitly reports the active runtime update and prints an explicit restart instruction.
Running requests are not implicitly interrupted
08

Installation type determines the update path

Installation detection identifies only the current execution mode; it does not create product variants with different functionality.

managed_release
→
Official GitHub ReleaseDesktop bridge or complete runtime installer; immutable markers take precedence.
source_checkout
→
Explicit Git ref pipelinePreflight, checkout, dependencies/build, and probe; restart according to the development contract when needed.
unknown
→
Stable errorDo not guess PyPI, binary, or Git paths; direct the user to the official installer or a source checkout.

pip_wheel is not an official product installation type. Developer wheels may be build inputs, but do not provide an incomplete ordinary-user product.

09

Reference implementations and adoption

References establish platform constraints and state models; the final approach follows OpenProgram’s unsigned Desktop and complete-runtime contracts.

Adopt

GitHub Releases API

Latest stable metadata, Release Notes, and assets. Clients still independently validate stable fields, tags, unique assets, and manifests.

Adapt

Electron update lifecycle

Adopt the check / available / download / error state model; Desktop completes by opening the verified platform installer, without automatic replacement.

Not currently adopted

Electron autoUpdater

Native macOS automatic installation requires signing, and Electron provides no built-in Linux updater; these do not match current artifacts and platform contracts.

No new dependencies

electron-updater

The existing Release manifest, Node/Electron APIs, Python, and shell cover this phase; a new package cannot change the current Desktop installation boundary.

10

Implementation entry points

Links point to current main-branch public compatibility entry points and official implementations; design conclusions do not depend on copied code on this page.

11

Implementation status and acceptance evidence

Implemented facts and facts still requiring Release-environment verification are recorded separately. This page does not retain dated change logs or commit lists.

Implemented

Complete Desktop path

Stable metadata, platform/architecture selection, state cache, 24h/6h scheduling, minimal IPC, verified download, Windows Authenticode, Settings states, and Web fallback are implemented.

npm run check --workspace apps/desktop
Implemented

Complete managed CLI path

The Release manifest gate, immutable installer, environment isolation, dry-run/JSON, real old→new current switching, and old-version retention on launcher failure are covered.

uv run pytest -q tests/component/config/test_formal_release_updates.py tests/component/config/test_distribution_release.py
Verified

Security and failure paths

Per-hop host validation, metadata/download stall abort, short writes, random exclusive temporary files, checksum/size cleanup, concurrent Promises, and state repair are verified.

apps/desktop/scripts/check-update-service.js
Verified

Documentation and release gates

Bilingual installation/upgrade documentation, Release latest verification, documentation build, links, Desktop/Web/TypeScript, and workflow static gates are included in release checks.

python -m scripts.docs_site.checklinks
Repository release record

v0.8.1 acceptance record

The repository’s v0.8.1 acceptance records runtime, CLI, Desktop, manifest, and checksum artifact boundaries. The source version does not prove the current GitHub published release; this page does not revisit GitHub latest or treat historical remote-artifact checks as acceptance of a currently running client.

Installed-client acceptance

Real client update interactions

The current user window has not been operated to verify version discovery, opening the platform installer, long-running behavior, or sleep/resume scheduling; release-artifact smoke tests do not replace these interactions. Windows must additionally pass the Authenticode gate with a real certificate on an official release runner.

Historical compatibility acceptance

One-time transition from v0.6.6 and earlier

Historical records require Desktop to manually install the first updater-equipped v0.7.0 DMG, and CLI/server to rerun the public installer. This is v0.7.0 migration background, not the current v0.8.1 release state.

Current state and historical background

v0.7.0 was historically the first official release with the updater; the current source and installer version baseline is v0.8.1. Migration instructions for v0.6.6 and earlier Desktop remain as historical context; current evidence excludes foreground-client update interactions, so installed-client acceptance still requires separate verification.