ADR 23: Personal Unified Installer and Cross-Platform Kit
Status: Accepted
Date: 2026-05-15
Context
Substratum is not only a hosted SaaS surface: operators need a personal distribution that installs the full local kit (mesh identity provisioning, sidecar-oriented runtime, companion mobile nodes) on macOS, Windows, and Android, with iOS following. Today the Tauri installer in apps/installer-gui focuses on Personal Device Triangle provisioning (keys, shared secrets, platform config). Users still expect a single coherent installer story: discover devices, apply policy (including how much disk space a node may use), install or update binaries, register autostart, and launch the stack—without treating “wizard” and “runtime” as unrelated products.
Constraints:
- Desktop can ship a rich orchestration UI (Tauri + web stack already in the repo).
- Android and iOS require native packaging (APK/AAB; App Store / TestFlight / enterprise distribution)—there is no portable “one binary” across all five targets.
- Storage limits must be enforceable in the long-running node, not only captured at install time.
Decision
Unified product story, not one universal binary. We standardize on one configuration contract and one ordered onboarding semantics (steps, validation, error vocabulary) across platforms. Packaging may differ per OS (Tauri bundle on desktop; APK/AAB on Android; Xcode-produced app and extensions on iOS), but the same logical phases and same persisted config shape apply wherever technically feasible.
Orchestrator pattern for desktop. The Tauri-based installer in
apps/installer-guiis the primary orchestrator on macOS and Windows: it runs elevated or guided steps to lay down artifacts, write configuration, invoke platform hooks (LaunchAgents, Windows services or equivalent, shortcuts), and optionally start or verify the kit. It may embed or download versioned components rather than requiring the user to run separate shell scripts as the default happy path.Mobile: same contract, native shell. Android ships as a native application that consumes the same triangle and storage fields (e.g. assets or secure storage generated from desktop export or in-device onboarding). iOS uses first-run onboarding inside the app (and store distribution); there is no general-purpose “installer.exe” model—onboarding UI and config schema align with desktop, not the Tauri binary.
Kit manifest. We treat the installable set as a versioned manifest (components, minimum OS versions, artifact locations or download URLs, verification expectations). The orchestrator reads the manifest and executes declared phases (provision identity → allocate storage policy → install binaries → register autostart → health check). Exact manifest format (JSON, TOML, or embedded in the Tauri app) is an implementation detail owned by the installer and release pipeline.
Storage allocation policy. The installer collects and persists a per-node storage budget (for example: data root path,
max_bytes, optional warning threshold). Enforcement (refusing writes, compaction, or eviction) is the responsibility of the long-running node (ADR 04: Sidecar Design and related storage adapters), which must treat installer-written caps as authoritative configuration. The installer does not pretend to enforce quotas after exit unless it also ships a supervising runtime.Security and updates. Personal distribution still requires artifact integrity (signatures or checksums), least-privilege install paths, and a documented path to updates (in-app updater, store updates, or replacement bundles). Proposed mechanics: ADR 31: Personal kit updates and in-app update checks.
Consequences
- Positive: Clear separation between orchestration UX (installer) and runtime behavior (sidecar / mobile node); one mental model for users; iOS/Android can join without rewriting desktop semantics; storage policy is explicit and testable.
- Negative: Higher engineering cost than a scripts-only MVP; CI must build per-platform artifacts; iOS timeline and capability set are constrained by App Store and background execution rules.
- Neutral: Existing triangle-only flows remain valid as an early phase of the manifest; they should evolve toward the unified phases rather than fork a second installer product.
Beyond the structured-triangle MVP
Structured substratum-triangle.json v1 and the Tauri wizard are the MVP slice of this ADR. The next phase adds installer Step 0 (hosting_topology: self-hosted home server vs Substratum Cloud), cross-platform self-hosted orchestration (install_self_hosted on macOS, Windows, Linux), three-node invariant, explicit “this device” / export targets (no hostname heuristics), and a separate substratum-installer-profile.json for mesh_mode (private_hardware vs cloud_relay) — captured in ADR 24: Installer post-MVP — mesh modes, explicit roles, and cloud relay.
Related
- ADR 03: Network Behavior — private swarm and libp2p module boundaries.
- ADR 04: Sidecar Design — local agent and daemon responsibilities.
- ADR 08: Hosting and Frontend Stack — Mithril / desktop UI stack.
- ADR 10: Repository Structure — monorepo placement of
apps/installer-guiand related crates. - ADR 14: Frontend Internationalization — Lingui in installer and explorer.
- ADR 22: Drive Lexicon and Persistence — drive and persistence vocabulary where storage UI touches product language.
- ADR 24: Installer post-MVP — mesh modes, explicit roles, and cloud relay — post-MVP installer and kit profile direction.