diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-08-18 09:42:34 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-08-18 09:42:34 +0200 |
| commit | 30e855f55f1d920b25da0bdd8e538c249d3c0c26 (patch) | |
| tree | 587dcad0beb8a120352613be8aa751a97040015c /docs | |
| parent | 768e07046368819b8a8f15c8b21e5a8bbfcdf282 (diff) | |
| download | meshbay-30e855f55f1d920b25da0bdd8e538c249d3c0c26.tar.gz | |
feat(client): the platform seam, and an Electron shell that has never been run
Stage D, and the honest half of it.
D1 — the seam (done, and verified)
----------------------------------
`static/platform.js`. `HUB` becomes `platform.hubBase()` and the transport is
built with the same base, so one address has one source. In a browser it returns
'' and every path stays relative to the origin that served the page — the
acceptance criterion for this split was "the browser SPA behaves identically",
and it does. `platform.js` joins `_ASSETS`, or a change to it would not move the
content hash and a cached browser would never ask for it.
D2 — the shell (written, never launched)
-----------------------------------------
**There is no npm on this machine. Electron was never installed and
`packages/meshbay-client/` has not been run once.** That is stated here rather
than discovered later.
What is there: a main process serving the packaged interface over a privileged
`app://` scheme (`secure` and `standard` are not cosmetic — without them the
service worker refuses to register and streamed downloads break silently), a
preload exposing an enumerated bridge that never passes a filesystem path, a
window with `sandbox`, `contextIsolation` and no node integration, navigation
away from the package refused, and a CSP where the hub is reachable over
connect-src and is not a script source. The hub address arrives as a process
argument because `platform.hubBase()` runs before anything can await.
`test_desktop_shell.py` pins each of those by reading the source — the treatment
`test_downloads.py` already gives the three browser save paths. It catches a
property being removed and proves nothing about the application running. Two
were checked by breaking them.
The interface is *copied* into the package by `build/sync-ui.js` from the hub's
static directory, and `ui/` is gitignored: a silent fork is the only real way to
end up maintaining the interface twice.
D3 — partial
------------
The bridge, and the part worth having now: safeStorage's backend is reported
rather than assumed. On Linux it falls back to a fixed key when no keyring is
running, silently — someone who believes the OS is holding their keys is told
when it is not. The native key lifecycle belongs with D4 and needs a running
application to mean anything.
D8 — partial, and a real defect found
--------------------------------------
`meshbay-node.spec` installed the SYSTEM template — the one carrying `User=%i` —
into `%{_userunitdir}`. A user unit already runs as its owner and cannot carry
`User=`; systemd refuses the file, so the packaged unit could never have
started. Nothing noticed because nobody had built and installed the RPM.
Two units now: the template to `%{_unitdir}`, and a new `meshbay-node-user.service`
that a person enables themselves without a password — which is what lets the
desktop client install a node without asking for one. It carries ExecReload, so
`meshbay-node reload` does not have to stop a service somebody is streaming from,
and documents the drop-in for a drive outside the home, RequiresMountsFor
included.
798 tests pass; e2e.py still passes end to end. Nothing here was built or
launched: no npm, no rpmbuild.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/desktop-client-v1.md | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/docs/desktop-client-v1.md b/docs/desktop-client-v1.md index 491af65..6b68bbd 100644 --- a/docs/desktop-client-v1.md +++ b/docs/desktop-client-v1.md @@ -1020,14 +1020,14 @@ build existing. | # | Component | Prio | |---|---|---| -| D1 | Configurable hub base URL + storage/save-file adapter (old 13.1) | 1 | -| D2 | Electron shell — `app://`, privileged scheme, CSP, preload, sandbox, single instance, tray, window state | 1 | -| D3 | Local key storage: `safeStorage`, explicit fallback where no keyring exists | 1 | +| D1 | ✅ **DONE 2026-08-18** — `static/platform.js`; `HUB` is `platform.hubBase()` and the transport is built with the same base. Browser behaviour identical, which was the acceptance criterion | 1 | +| D2 | ⚠️ **WRITTEN, NEVER RUN** — `packages/meshbay-client/`: main process, preload bridge, `app://` handler, CSP, single instance, window state. **There is no npm on the development machine, so Electron could not be installed and the application has never been launched.** Its security contract is pinned by `test_desktop_shell.py`, which reads the source the way `test_downloads.py` reads the save paths — weak evidence, and the only kind available without a packaged build | 1 | +| D3 | ◐ **PARTIAL** — the bridge (`secrets.get/set/clear/backend`) and the honest report of what the OS is actually doing: `unprotected_fallback` when safeStorage finds no keyring, surfaced in Settings rather than swallowed. The native key *lifecycle* belongs with D4 and needs a running application to mean anything | 1 | | D4 | Hybrid registration and first sign-in (§5) | 1 | | D5 | Node management panel over the Stage-B ops, root selection included | 2 | | D6 | First-run wizard — detect, enable the unit, link, group, `gek-init`, pair (§7.4) | 2 | | D7 | Native save dialog, streamed write from the main process | 2 | -| D8 | `.deb` + `.rpm` | 1 | +| D8 | ◐ **PARTIAL** — `electron-builder` configured for deb and rpm, and `meshbay-node-user.service` added. **Found doing it:** the spec installed the *system* template (`User=%i`) into the user unit directory, where systemd refuses the file — the packaged unit could never have started. Fixed, with `test_packaging_units.py`. Nothing has been built: no npm, no rpmbuild here | 1 | | D9 | Python sidecar — `group://` over QUIC | 2 | | D10 | Video thumbnails, own bounded pool (§6.10) | 2 | | D11 | Windows: MSI per-user, service mode offered, firewall and SmartScreen handled (§7.5) | 3 | |