Ship ProdDash as one app: its own Node, its own copy, a .dmg

Installing is dragging ProdDash to Applications. The app carries the
dashboard and the Node that runs it, so nothing has to be installed first and
nothing can go missing underneath it.

  ProdDash.app/Contents/
    MacOS/ProdDash            the launcher
    Resources/node/bin/node   Node 24.21.0 LTS, fetched and checksum-verified
    Resources/app/            server.js, public/, modules/

Everything mutable stays where it already was, in ~/Library/Application
Support/ProdDash — and that now includes app/, the copy of ProdDash that
actually runs. The copy is not ceremony: ProdDash updates itself in place,
and nothing may write inside a signed .app. So the bundle holds a read-only
baseline and the data directory holds the running copy, which means both
routes to a new version keep working and don't fight — installing a newer
.app replaces the copy, while a copy that has already updated itself past the
bundle is left alone.

build.sh now assembles all of it: fetches Node against nodejs.org's published
checksums (cached in .cache/), embeds the server, compiles each module's
native helper so the Mac running ProdDash needs no compiler, signs nested
code before the bundle, and builds the disk image. --dev skips the payload
for launcher work, which still runs against a checkout.

Signing is set up for a Developer ID with the hardened runtime and
notarisation (--notarize), and falls back to ad-hoc when no such certificate
is installed. Entitlements are split by what each binary actually does: JIT
for node, audio input for the launcher and for module helpers that read one.

Built and run end to end: first-run install, bundled node, dashboard and
admin serving, re-seed in both directions (newer app replaces an older copy;
an updated copy survives), disk image mounts and its app verifies.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Waters Church
2026-09-11 12:38:46 -04:00
co-authored by Claude Opus 5
parent e1bceb3e60
commit adac3a4785
12 changed files with 435 additions and 123 deletions
+21 -11
View File
@@ -29,21 +29,28 @@ and a clear degraded state, then recover on their own.
## Run it
Requires [Node.js](https://nodejs.org) 18 or newer.
### macOS — the app
On a Mac, run it from the **menu-bar launcher** — see
[launcher/macos](launcher/macos). It starts and stops the server, can open at
login, owns the port, and holds the permissions the modules need: the
microphone the LTC listener reads, and local network access for ProdCom and
ProPresenter. macOS grants those to the app that owns the process, so a server
started any other way — over SSH, from a launchd job — simply doesn't have
them, and an LTC input goes silently to zeroes. Build it once:
Open the disk image and drag **ProdDash** to Applications. That's the whole
installation: the app carries the dashboard and its own Node runtime, so
nothing else has to be installed and nothing can be missing. It lives in the
menu bar, starts and stops the server, can open at login, and holds the
permissions the modules need — the microphone the LTC listener reads, and
local network access for ProdCom and ProPresenter. macOS grants those to the
app that owns the process, so a server started any other way (over SSH, from
a launchd job) simply doesn't have them, and an LTC input goes silently to
zeroes.
Build the disk image from a checkout with
[launcher/macos](launcher/macos)/`build.sh`:
```bash
cd launcher/macos && ./build.sh --install
cd launcher/macos && ./build.sh --dmg
```
Otherwise, from the app folder:
### Anywhere else, or from a checkout
Requires [Node.js](https://nodejs.org) 18 or newer.
```bash
node server.js
@@ -81,7 +88,10 @@ it at startup (`Settings : …`).
The directory holds `modules.json` (module config), `layouts/` (named
layouts) and `modules/` (modules installed from the admin page), all written
by the app itself. It may also hold a `proddash.json`
by the app itself. Installed from the macOS app, it also holds `app/` — the
copy of ProdDash that actually runs, laid down from inside the app bundle on
first launch and updated in place from then on (nothing may write inside a
signed .app, and ProdDash updates itself). It may also hold a `proddash.json`
with this machine's shell settings — the same keys as the checked-in
[config/proddash.json](config/proddash.json), which supplies the defaults: