summaryrefslogtreecommitdiffstats
path: root/second-review.md
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-08-14 01:28:12 +0200
committerChristophe Besson <cbesson@gmail.com>2026-08-14 01:28:12 +0200
commitd7120761fe8cf406f374ef769db6e1f9bf1fe287 (patch)
treecc73da554575c51d7ee3837085a4318e08c610aa /second-review.md
parent8f6e2f724fd24a077de11d4a3b3ae069d369324d (diff)
downloadmeshbay-d7120761fe8cf406f374ef769db6e1f9bf1fe287.tar.gz
docs: record the invite redesign — H3 and M3 closed
draft-v5 §2: against an active hub, reading content moves from "❌ H3" to "❌ T3 (browser) · ✅ native". The defensible sentence becomes "the hub cannot read your content unless it ships you malicious client code" — T3 is now the only path, it is an artifact rather than a silent directory lie, and it does not exist for a native client. New §5.5 describes admission and key delivery, with the four properties that carry it and the one exception (open-join groups, where the hub can walk in the front door — a property of open joining, and the setting is read from node.toml). Corrected while writing it: §5.1 said the C5b fix stopped a group admin who does not run the node from inviting, and that the redesign reverses this. It does not, because delegation was deferred. What changed is the timing — the operator issues a code and is then out of the loop. devel-phases-next: 12.1 is done and NOT as written. The plan was key transparency plus safety numbers; what shipped removes the directory read instead. Safety numbers make substitution detectable by a human who checks, at first contact, when there is nothing to check against. 12.2 (served-SPA integrity) is now the highest-value item in that phase. Phase 14 marked for what landed. second-review: H3 and M3 annotated closed at the finding, with what actually closed them. The §7 verdict table is left intact — it is the record of an audit on a date, and falsifying it would be worse than leaving it — with a note pointing at draft-v5 §2 for current state. CLAUDE.md matters most here, being loaded every session: NS4 read "admin_pk_ed25519 auto-pinned from keystore ✅ DONE", which is M3 described as a feature. Rewritten, with the two fixes that must never be attempted (auto-pin, hub lookup). QE/deploy/README.md: set-admin-pk retired from the walkthrough; the regression checklist now exercises pairing, joining by code, recognition without a code, and revocation. USERGUIDE.md is beyond the invite work but was actively wrong: it told users to POST GEK bundles to a hub endpoint deleted in Phase 12, and to re-wrap for every remaining member on revocation. Both replaced with what the code does. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'second-review.md')
-rw-r--r--second-review.md21
1 files changed, 20 insertions, 1 deletions
diff --git a/second-review.md b/second-review.md
index a2218ad..071e6ef 100644
--- a/second-review.md
+++ b/second-review.md
@@ -394,6 +394,16 @@ Consider a localhost token in the URL to blunt DNS-rebinding against the unauthe
### H3 — An active hub breaks confidentiality through key substitution (T2 is not a residual risk)
+> **CLOSED 2026-08-14.** Not by the fix proposed below. The invite path no longer reads
+> the directory at all: the node holds the GEK and wraps it for a key the recipient
+> proves possession of over the authenticated channel, and identities are bound to
+> accounts by one-time codes the hub never sees. Safety numbers would have made the
+> substitution *detectable by a human who checks*; removing the lookup makes it
+> impossible. See `docs/invite-pairing-v1.md` and draft-v5 §5.5.
+>
+> `gek-init` had the same flaw with the node as the victim — it fetched every member's
+> public key from the hub and wrapped for the answer. That is gone too.
+
**Location:** `app.js:1389-1415`, `users.py:340-358`, `users.py:310-337`
The invite flow is: fetch `pk_x25519` for the invitee **from the hub**, wrap the GEK for it,
@@ -535,7 +545,11 @@ minimum password, and the calibration command prints instructions to hand-edit a
`meshbay_common` rather than writing a per-node parameter — so the keystore parameters cannot
actually be tuned per hardware as §4.2.1 promises.
-**M3 — Node operator cannot delete files in the default configuration.** `_resolve_admin_pk`
+**M3 — Node operator cannot delete files in the default configuration.** *(CLOSED
+2026-08-14 — the auto-pin is deleted; authority comes from the node's roster, established
+locally by `meshbay-node operator pair`. Asking the hub for the operator's key, the
+obvious-looking fix, would have let the hub install itself as node administrator.)*
+`_resolve_admin_pk`
(`daemon.py:451-465`) auto-pins the **node keystore's** Ed25519 key, while the browser signs
challenges with the **user identity** key from the keypair bundle (`app.js:983`). These are
different keys, so verification fails unless the operator manually sets `admin_pk_ed25519` to
@@ -619,6 +633,11 @@ client path.
## 7. Does the system do what it claims?
+> This table is the verdict **on the code as it stood on 2026-08-13**, and is left as the
+> record of what the review found. It is not the current state: Phase 11.5 closed C1–C6
+> and H1–H7 except H3, and the invite redesign closed H3 and M3 on 2026-08-14. For what
+> holds today, and against which adversary, read draft-v5 §2 — never this table.
+
| Claim (draft-v4) | Verdict | Why |
|---|---|---|
| Data never transits a central server | **Yes** | WebRTC DataChannel is genuinely P2P; hub relays SDP only. Well executed. |