summaryrefslogtreecommitdiffstats
path: root/docs/desktop-client-v1.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/desktop-client-v1.md')
-rw-r--r--docs/desktop-client-v1.md4
1 files changed, 2 insertions, 2 deletions
diff --git a/docs/desktop-client-v1.md b/docs/desktop-client-v1.md
index fedfc8d..cde8453 100644
--- a/docs/desktop-client-v1.md
+++ b/docs/desktop-client-v1.md
@@ -1057,7 +1057,7 @@ build existing.
|---|---|---|
| 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 | ✅ **RUNS** (2026-08-18, Electron 42 / Chromium 148 under xvfb). The packaged interface mounts over `app://`, secure context, `crypto.subtle` present, Argon2 WASM loaded, zero console errors. Three things were learned by running it — see §3.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 |
+| D3 | ✅ **DONE, verified on a real desktop** (Ubuntu 24.04 GNOME, 2026-08-18). Settings reports `gnome-libsecret`, and `secrets.bin` is written 0600 with Chromium's **`v11`** prefix — the marker for keyring-backed encryption; the fixed-key fallback writes `v10`. The key name does not appear in clear. On a headless session the same code reports `unavailable` and **refuses to store**, which is the honest outcome and is now explained in Settings rather than left as a bare word |
| D4 | ✅ **DONE 2026-08-18, verified against a hub running this code** — first-run hub prompt (no default, on purpose), passphrase sign-in registers this device, later launches sign in with the device key and no passphrase. **The renderer never holds that key**: it is generated, stored and used entirely in the main process, which signs on request — the same rule as the save dialog, because the renderer is the part that parses hostile input. Measured: register 201 → passphrase login 200 → device register 201 → **device sign-in 200 with a real session** → a stranger's key 401. **Not verified:** safeStorage actually persisting the key, which needs a desktop with a keyring — this session has none, and the application correctly *refuses* rather than storing unprotected | 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 |
@@ -1088,7 +1088,7 @@ Deletions enabled once native is the recommended client are unchanged from
| O2 | LAN enrolment door | One endpoint, bounded window, one-time code, closes permanently on success. Small but it executes before any authentication |
| O3 | `device_policy {allow_bundle: false}` | The mechanism that actually closes C4 (§5.1). Needs to be signed by a pinned key, never settable by the hub |
| O4 | Node-admin panel isolation | Node-supplied strings (filenames, hub-originated usernames) rendered in a process holding the user's keys. H2 was exactly this. Separate window or partition at minimum |
-| O5 | `MESHBAY_UNLOCK_KEY` in `node.env` | Plaintext in the user's home. The client could move it to the OS keychain for the desktop persona |
+| O5 | `MESHBAY_UNLOCK_KEY` in `node.env` | Still open for the **node**. For the **client**, the OS keychain path is proven: `safeStorage` on a real GNOME desktop uses the keyring (`v11`), and refuses rather than downgrading where there is none |
| O6 | Electron version floor | X25519 and Ed25519 in WebCrypto must be verified on the pinned version, not assumed |
| ~~O7~~ | Several directories in one group | **Decided 2026-08-17** — named roots, unique names, union root. See §6.7 |
| O8 | Minimum client version in `GET /v1/hub/version` | Needed before the first public package (§2.6). Trivial now, awkward once clients are in the wild |