summaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-04 09:28:14 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-04 09:28:14 +0200
commit3ce52774760b222d94d78bc0118e9da2662a809f (patch)
tree52a16c7e05080869fbb17b83665b2fb2048b21e2 /docs
parent220e6e701806213a576ce80fa655cd9cf4a51880 (diff)
downloadmeshbay-3ce52774760b222d94d78bc0118e9da2662a809f.tar.gz
feat: Windows installer (W4) — one per-user NSIS package, client + node
`npm run dist:win` produces MeshBay-Setup-<version>.exe: the Electron client and, beside it under resources/node-runtime/, the frozen meshbay-node daemon (meshbay-common inside it). No hub. Per-user, no elevation — matches the W3 constraint that a logon-triggered scheduled task needs admin. electron-builder / package.json build.win nsis, build/icon.ico, extraResources -> node-runtime/ build.nsis oneClick:false perMachine:false allowElevation:false allowToChangeInstallationDirectory:true dist:win -> packaging/win/build-win.ps1 (mirrors dist -> build-client.sh) packaging/win/ meshbay-node.spec + node-entry.py PyInstaller freeze of meshbay_node.daemon:main. The awkward deps (aiortc, av, aioquic, pydantic_core, uvicorn, watchdog, guessit, blake3, tzdata) are pulled in whole with collect_all — that list is expected to grow when a frozen run raises ModuleNotFoundError. build-node-runtime.ps1 throwaway venv -> pip install -> PyInstaller -> packages/meshbay-client/node-runtime/ (gitignored) build-win.ps1 Node>=22 check, npm ci, Electron bump, sync-ui, node runtime, electron-builder --win nsis bump-electron.mjs the Chromium-CVE "build against latest Electron" policy, out of the PS script (5.1 here-string terminator rules) README.md PyInstaller, not the python-embed zip: the frozen meshbay-node.exe is a genuine relocatable single binary, which is what src/main.js:findNodeBinary spawns (process.resourcesPath/node-runtime/meshbay-node.exe when packaged) and what the W3 autostart launcher points at. The embeddable zip needs pip to make that wrapper and the wrapper bakes in an absolute interpreter path. build/installer.nsh: on uninstall, taskkill meshbay-node.exe and delete the W3 Startup .vbs (it would point wscript at a deleted binary every sign-in). %LOCALAPPDATA%\meshbay\ — node.toml, keystore.enc — is never touched. ffmpeg is not bundled by default (node finds it on PATH); build-win.ps1 -FfmpegDir copies ffmpeg.exe/ffprobe.exe in for a self-contained installer. Verified on the Windows guest: PyInstaller freeze builds first try (node-runtime 147 MB), frozen `meshbay-node status` talks to the live daemon's loopback API; electron-builder --win nsis produces MeshBay-Setup-0.1.0.exe (155 MB), oneClick/perMachine flags applied, node-runtime bundled at the path findNodeBinary expects. test_packaging_win.py (14) pins the config invariants and the NSIS <-> platform.py autostart seam. Node suite 798 pass / 34 skip. Open: Authenticode signing (13.9 — unsigned => SmartScreen), Windows CI (18.3), electron-updater. First clean-machine install + DPAPI + autostart round-trip is a manual check. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Diffstat (limited to 'docs')
-rw-r--r--docs/PACKAGING-GUIDE.md45
-rw-r--r--docs/WINDOWS-PORT.md92
2 files changed, 97 insertions, 40 deletions
diff --git a/docs/PACKAGING-GUIDE.md b/docs/PACKAGING-GUIDE.md
index 0f9997d..5a5c388 100644
--- a/docs/PACKAGING-GUIDE.md
+++ b/docs/PACKAGING-GUIDE.md
@@ -59,6 +59,51 @@ sudo rpm -e meshbay-client meshbay-hub meshbay-node meshbay-common
---
+## Windows
+
+One installer, **`MeshBay-Setup-<version>.exe`**, carries the client **and** the
+node (with `meshbay-common` inside it). There is no Windows hub.
+
+### Install
+
+Run the installer. It is **per-user** — no administrator prompt — and lands in
+`%LOCALAPPDATA%\Programs\meshbay-client\`. The node daemon ships beside the app
+at `resources\node-runtime\meshbay-node.exe`; the client finds it automatically.
+
+**ffmpeg** is required for video streaming and is *not* in the installer unless
+it was built with `-FfmpegDir`. Otherwise install it separately
+(`winget install ffmpeg`) so the node finds it on `PATH`.
+
+### First run
+
+Open MeshBay and sign in. Use the **Node** page (or a terminal) to provision:
+
+```
+meshbay-node init
+meshbay-node autostart install # run the daemon at every sign-in (no admin)
+```
+
+Runtime data — `node.toml`, `keystore.enc`, `unlock.key`, `data\` — lives in
+`%LOCALAPPDATA%\meshbay\` and **survives uninstall/reinstall**.
+
+### Uninstall
+
+*Apps & features → MeshBay → Uninstall*, or the Start-menu *Uninstall MeshBay*
+entry. It stops a running daemon and removes the sign-in launcher; it does not
+touch `%LOCALAPPDATA%\meshbay\` (the keystore).
+
+### Build from source
+
+See [`packaging/win/README.md`](../packaging/win/README.md). On a machine with
+Node ≥ 22 and Python ≥ 3.12:
+
+```powershell
+cd packages\meshbay-client
+npm run dist:win
+```
+
+---
+
## Post-install: Node (desktop user)
### 1. Initialize
diff --git a/docs/WINDOWS-PORT.md b/docs/WINDOWS-PORT.md
index 9b3caee..239dbd1 100644
--- a/docs/WINDOWS-PORT.md
+++ b/docs/WINDOWS-PORT.md
@@ -1,10 +1,17 @@
# MeshBay — Windows Port
-> Status: **audit complete, work not started.**
-> Created 2026-09-03 from a full codebase scan.
+> Status: **W1–W3 + W5–W8 done; W4 packaging built, not yet run on a clean machine.**
+> Created 2026-09-03 from a full codebase scan; progress notes added 2026-09-04.
> This document is both the audit results and the implementation plan.
> It does not repeat the design decisions already in `desktop-client-v1.md`
> (§6.8, §7.5, decisions E8/E12) — read that first.
+>
+> **What shipped (branch `win-webrtc-stun`):** platform dirs / signals / perms /
+> ffmpeg discovery / CLI messages (W1-2-5-6-7-8, commits through `c2620a5`);
+> event loop stays Proactor (`5098e6c`); JWT clock-skew leeway (`dad2157`);
+> daemon lifecycle via a Startup-folder `.vbs` launcher, **not** Task Scheduler
+> (`220e6e7` — `schtasks /create /sc ONLOGON` needs elevation, see §5.3). W4 is
+> `packaging/win/` + `package.json` `build.win` — see §5.4.
---
@@ -298,37 +305,41 @@ of the Windows port — per-user mode ships first.
**Estimated scope:** ~200 lines Python + ~150 lines JS for per-user mode.
Service mode is a separate milestone.
-### 5.4 Packaging (W4)
+### 5.4 Packaging (W4) — **built 2026-09-04**
-**Scope:** `package.json` + `packaging/win/`
+**Scope:** `package.json` `build.win`/`build.nsis` + `packaging/win/` + one
+`src/main.js` line. **One installer**, `MeshBay-Setup-<version>.exe`, per-user,
+carrying the **client** and the **node** (with `meshbay-common` inside it). No
+hub.
-Add to `package.json`:
+`packaging/win/README.md` is the build guide. In brief:
-```json
-"win": {
- "target": "nsis",
- "icon": "build/icons/icon.ico"
-},
-"nsis": {
- "oneClick": false,
- "perMachine": false,
- "allowToChangeInstallationDirectory": true
-}
-```
-
-Add a `packaging/win/` directory with:
-- Icon in `.ico` format
-- Optional: Authenticode signing script (Phase 13.9)
+| File | |
+|---|---|
+| `package.json` `build.win` | `target: nsis`, `icon: build/icon.ico`, `extraResources` → `node-runtime/` |
+| `package.json` `build.nsis` | `oneClick:false`, `perMachine:false`, `allowElevation:false`, `allowToChangeInstallationDirectory:true` — no admin, ever |
+| `packages/meshbay-client/build/icon.ico` | multi-res, generated from `build/icon.png` |
+| `packages/meshbay-client/build/installer.nsh` | uninstall: `taskkill meshbay-node.exe` + delete the W3 Startup `.vbs` |
+| `packaging/win/meshbay-node.spec` + `node-entry.py` | PyInstaller freeze of `meshbay_node.daemon:main` |
+| `packaging/win/build-node-runtime.ps1` | runs PyInstaller → `packages/meshbay-client/node-runtime/` (gitignored) |
+| `packaging/win/build-win.ps1` | orchestrator: Node check → `npm ci` → Electron bump → `sync-ui` → node runtime → `electron-builder --win nsis` |
+| `packaging/win/bump-electron.mjs` | the Chromium-CVE "build against latest Electron" policy, factored out of the PS script |
+| `npm run dist:win` | → `build-win.ps1` (mirrors how `dist` → `build-client.sh`) |
-The `dist` script gets a platform flag:
-`"dist:win": "npm run sync-ui && electron-builder --win nsis"`
+**PyInstaller, not the python-embed zip.** The frozen `meshbay-node.exe` is a
+genuine relocatable single binary — which is what `findNodeBinary` in
+`src/main.js` spawns (`process.resourcesPath/node-runtime/meshbay-node.exe`) and
+what the W3 autostart launcher points at (`platform._node_exe`). The embeddable
+zip needs pip to produce that wrapper, and the wrapper bakes in an **absolute**
+interpreter path that breaks the moment the tree is installed elsewhere.
-Python node on Windows: **bundled with the Electron app** or installed
-separately. The simplest path is embedding Python via `python-embed` (the
-official embeddable zip from python.org) and installing meshbay-node into
-it. This avoids requiring a system Python install.
+**ffmpeg** is not bundled by default (the node finds it on `PATH`); pass
+`-FfmpegDir` to `build-win.ps1` to copy `ffmpeg.exe`/`ffprobe.exe` in beside the
+daemon for a self-contained installer.
-**Estimated scope:** config + build script, no code changes.
+**Still open:** Authenticode signing (Phase 13.9 — unsigned ⇒ SmartScreen),
+a Windows CI runner (Phase 18.3), `electron-updater`. First clean-machine
+install + `safeStorage`/DPAPI + autostart round-trip is a manual check.
### 5.5 File permissions (W5)
@@ -388,24 +399,25 @@ when `sys.platform == "win32"`.
## 6. Execution order
```
-W1 Platform directories ← unblocks everything; testable on Linux
-W2 Signal handling ← 10 lines; do it with W1
-W5 File permissions ← trivial guards; do it with W1
-W7 CLI messages ← cosmetic; do it with W1
-W6 ffmpeg discovery ← small; do it with W1
- ──── milestone: daemon runs on Windows ────
-W3 Daemon lifecycle ← largest item; per-user mode first
- ──── milestone: daemon starts/stops on Windows ────
-W4 Packaging ← electron-builder config + build script
- ──── milestone: installable on Windows ────
+W1 Platform directories ✅ done
+W2 Signal handling ✅ done (SIGINT/SIGTERM; CTRL_CLOSE still open — see below)
+W5 File permissions ✅ done
+W7 CLI messages ✅ done
+W6 ffmpeg discovery ✅ done
+W8 test suite green on win32 ✅ done (encoding sweep + skipif; 784 pass)
+ ──── milestone: daemon runs on Windows ✅ (verified end to end) ────
+W3 Daemon lifecycle ✅ done — Startup-folder .vbs (Task Scheduler needs admin)
+ ──── milestone: daemon starts/stops on Windows ✅ ────
+W4 Packaging ✅ built — one per-user NSIS installer, client + node
+ ──── milestone: installable on Windows — pending a clean-machine run ────
+ CTRL_CLOSE_EVENT handler ← open: window-close / bare taskkill skips _shutdown()
Service mode (W3b) ← Phase 2, optional
Authenticode signing ← Phase 13.9
CI Windows matrix ← Phase 18.3
```
-W1 through W7 (minus W3 and W4) can ship as a **single commit** — they are
-mechanical, self-contained, and testable on Linux. W3 and W4 are the real
-work and can be developed in parallel.
+W1–W2–W5–W6–W7–W8 shipped as a run of mechanical commits, testable on Linux.
+W3 and W4 were the real work.
---