Skip to content

refactor(macos): thin runtime installer - #45

Merged
ssddOnTop merged 4 commits into
mainfrom
feat/thin-installer-v2
Aug 5, 2026
Merged

ssddOnTop merged 4 commits into
mainfrom
feat/thin-installer-v2

Conversation

@ssddOnTop

Copy link
Copy Markdown
Collaborator

Summary

Replaces the bespoke forge3 runtime installer (manifest parsing, SHA-256 checksums, Mach-O validation, archive extraction, versioned runtime store, launch-security scanning) with a thin wrapper around the cargo-dist shell installer served at https://install.forgecode.dev/server. Net −7,600 lines.

What the app does now

  1. First run: if ~/.cargo/bin/forge3 is missing, download the installer script and run it via /bin/sh with FORGE3_INSTALL_DIR=$CARGO_HOME (falling back to ~/.cargo — the script's own default target), FORGE3_NO_MODIFY_PATH=1, FORGE3_PRINT_QUIET=1. Managed mode: the axoupdater receipt is written so forge3's self-update keeps working.
  2. Supervise: spawn forge3 in its own process group; existing process management retained.
  3. Restart on exit: no app-side update checks. Whenever forge3 exits it is relaunched (exponential backoff 1s→60s; exit status 75 relaunches immediately as a self-update handoff).
  4. Quit: SIGTERM→SIGKILL the whole process group — no orphans.
  5. No verification: the installer script is fully trusted. The only Gatekeeper workaround left is a best-effort removexattr com.apple.quarantine on the installed binary.

Debug ergonomics

  • FORGE_ / FORGE3_ / RUST_LOG-prefixed env vars are forwarded to the forge3 child (FORGE_UPDATE_CURRENT_VERSION, FORGE_UPDATE_MANIFEST_URL, FORGE_UPDATE_INSTALLER_URL, FORGE3_API_KEY, FORGE_CONSOLE_ORIGIN, …).
  • FORGE_UPDATE_INSTALLER_URL also overrides the installer script source (e.g. http://127.0.0.1:9877/install.sh).
  • FORGE_RUNTIME_BINARY (debug builds only) points the app at a locally built forge3; the installer never touches a developer-supplied binary.

Deleted

MachOValidator, RuntimeArchive, RuntimeCrypto, RuntimeLaunchSecurity, RuntimeNetwork, RuntimeProcess, RuntimeStore, two test-helper executables, and their test suites.

Unchanged

  • UI: MenuRenderer, ForgeCodeLogo, Popover*, all visible strings/menu structure — byte-identical to main.
  • Sparkle 2 app-update integration — untouched and separate from forge3's self-update.

Testing

  • swift build clean; full suite (79 tests, 11 suites) green, including new ThinInstallerTests (env forwarding, /bin/sh invocation construction, cargo-home resolution, real script execution + de-quarantine, failure surfacing).
  • Live smoke test against a local fake installer on 127.0.0.1:9877: install → binary lands in <install-dir>/bin/forge3 → launch → env vars verified in child (non-allowlisted secrets dropped) → kill → relaunch with new pid → stop → no orphans.
  • Note: the final commit (cargo-home install dir) is build-verified; the test suite could not be re-run locally due to a broken toolchain mid-OS-update on the dev machine — CI should confirm.

Known follow-up

forge3's update.install stages the new binary but the process keeps running until restarted (Downloaded state, no self-exit — verified in svc-update). The app only restarts on exit, so an installed update currently applies on the next forge3 exit/app relaunch. Closing that loop cleanly is an SDK-side change: exit (e.g. status 75) after a successful install.

… script

The installer script's own default target is $CARGO_HOME (falling back to
~/.cargo), and forge3's self-update always writes back there. Pinning
FORGE3_INSTALL_DIR to Application Support made the app disagree with the
runtime about where the binary lives. Use the cargo home so the app, the
installer, and forge3's self-update all operate on ~/.cargo/bin/forge3.
@ssddOnTop ssddOnTop changed the title refactor(macos): thin runtime installer — trust the upstream shell installer refactor(macos): thin runtime installer Aug 5, 2026
@ssddOnTop
ssddOnTop merged commit 3fe1045 into main Aug 5, 2026
7 checks passed
@ssddOnTop
ssddOnTop deleted the feat/thin-installer-v2 branch August 5, 2026 07:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant