aboutsummaryrefslogtreecommitdiffstats
path: root/docs/meshbay-draft-v5.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/meshbay-draft-v5.md')
-rw-r--r--docs/meshbay-draft-v5.md71
1 files changed, 44 insertions, 27 deletions
diff --git a/docs/meshbay-draft-v5.md b/docs/meshbay-draft-v5.md
index ffc30c2..2a0f3b1 100644
--- a/docs/meshbay-draft-v5.md
+++ b/docs/meshbay-draft-v5.md
@@ -65,7 +65,7 @@ This replaces the informal assurances scattered through v4 §4.2.x and §13.
| Client code integrity | ❌ **T3, accepted** | ❌ T3 | ✅ | ✅ | ✅ |
| Node content authority | ✅ | ✅ | ✅ sovereign | ✅ | ✅ |
| Hub cannot obtain the group key | ✅ | ✅ **since H3 closed** — except in `join_policy = "open"` groups, where it can join legitimately | — | — | ✅ |
-| Your identity keys stay yours | ✅ | ✅ | ⚠️ **offline attack on your keypair bundle** — see §7.1. Succeeds against a weak passphrase, and yields your content on *other* nodes plus the ability to sign as you | ✅ | ✅ |
+| Your identity keys stay yours | ✅ | ✅ | ⚠️ **offline attack on the bundle they hold** — see §7.1. Succeeds against a weak passphrase, and yields the identity used **on that node only**: nothing on anyone else's | ✅ | ✅ |
**The claim this project can make:** *the hub cannot read your content unless it ships you
malicious client code.* Since H3 closed (2026-08-14) that is the **only** remaining path,
@@ -92,11 +92,11 @@ even the hub."* Three reasons, all deliberate:
- **Members and the operator read everything.** Inherent: "end-to-end" here describes
*client ↔ node*, never *client ↔ client*.
-One boundary deserves naming, because the table above hid it until 2026-08-14: an operator
-hosts your content by design, but they should not be able to become *you*. They can try —
-your keypair bundle sits on their disk, and a weak passphrase gives it up (§7.1). That is
-the difference between a node operator reading what they host and a node operator reading
-what other operators host.
+One boundary deserves naming: an operator hosts your content by design, but they should not
+be able to become *you*. They can still try — a bundle sits on their disk and a weak
+passphrase gives it up — but since 2026-08-14 what it gives up is **the identity you use
+with them**, which unlocks nothing they did not already have. Reading what they host is by
+design; reading what *other* operators host is not, and no longer follows.
---
@@ -319,9 +319,15 @@ Hub minimization was considered and **deferred** (decision D4). The hub keeps se
the web UI and remains in the trusted path by choice. This section describes what it
*does*, not an aspiration.
-**Stores:** accounts (username, encrypted email, public keys, status, role), group
-registry and membership, IP logs (1 year, legal), node registrations, refresh tokens,
-notifications, moderation blocklist.
+**Stores:** accounts (username, encrypted email, status, role), group registry and
+membership, IP logs (1 year, legal), node registrations, refresh tokens, notifications,
+moderation blocklist.
+
+**No longer stores user identity keys** (2026-08-14). `users.pk_ed25519` and
+`users.pk_x25519` are dropped, `PUT /me/keys` is gone, and `/pubkeys` returns an account id
+and a node's linking key — nothing to wrap for. Tokens carry no `pk_user` claim either: the
+node used to record it as the uploader's identity, which let whoever issued tokens decide
+who could delete a file.
**Does not store:** file content, file names, private-group indexes, message content,
private keys, GEK bundles, keypair bundles, node IPs beyond ephemeral signaling.
@@ -371,19 +377,25 @@ separation, on-the-fly encryption.
### 7.1 The keypair bundle, and what it is worth to an attacker (C4)
-The bundle carries a user's identity keys, encrypted under their passphrase. It is stored
-on **every node whose group they join**, because that is what lets them open their account
-from a second browser — the ordinary expectation, and the only mechanism available to a
-browser that keeps nothing durable of its own.
+A bundle carries **one node's** identity keys, encrypted under the owner's passphrase, and
+is stored on that node. It is what lets a second browser open the same account there — the
+ordinary expectation, and the only mechanism available to a browser that keeps nothing
+durable of its own.
+
+The adversary is concrete: an operator holding their own node's disk, attacking offline at
+their leisure.
-So the adversary is concrete: an operator holding their own node's disk, attacking offline
-at their leisure.
+**What cracking one yields.** The identity that person uses **on that node** — where the
+operator already holds the content, the index and every byte they serve. It is not a key
+anywhere else: each node gets its own, generated the first time its owner joins it, and a
+key one node pinned is a stranger to the next (which asks for a code, like any first
+contact). Until 2026-08-14 a single identity was copied to every node joined, so one crack
+yielded content on *other* operators' nodes and the ability to sign as that user anywhere —
+that was the part worth attacking, and it is gone.
-**What cracking one yields.** The user's identity keys — and with them, content on
-**other** nodes and the ability to sign as that user. *Not* the content on the attacking
-operator's own node, which they host in the clear by design. This is the one place where a
-node operator can reach past the boundary the rest of the design gives them, and v5 did not
-say so before 2026-08-14.
+Two smaller consequences fall out. Two operators can no longer tell they host the same
+person by comparing keys. And the hub publishes no user keys at all now (§6.1), so there is
+no directory left to substitute from.
**Why Argon2id.** PBKDF2 is compute-only, which is exactly what a GPU is good at. Measured
on the development machine: PBKDF2-SHA512 600k costs 241 ms per guess on one core,
@@ -417,8 +429,10 @@ anything about one.
lives in IndexedDB for the session.
- The pre-proof window that serves bundles is still bounded (4 fetches) and audited.
-C4 closes properly when the native client stops storing bundles remotely (Phase 13.3):
-the material belongs on the user's own device, not on the hub *or* on other people's nodes.
+C4 is **reduced, not closed**: bundles still sit on disks their owner does not control, and
+a weak passphrase still gives up the key for that node. It closes when the native client
+stops storing them remotely (Phase 13.3) — the material belongs on the user's own device,
+not on the hub *or* on other people's nodes.
---
@@ -435,11 +449,14 @@ the material belongs on the user's own device, not on the hub *or* on other peop
| Transport | WebRTC | WebRTC **+ QUIC** |
| Positioning | **Convenience tier** — zero install | Recommended for sensitive use |
-**Several browsers, one identity.** A browser keeps nothing durable the user controls, so
-the account's keys are backed up — encrypted under the passphrase — to the nodes whose
-groups it joins. Any other browser then recovers them with the passphrase alone: same
-identity, same pin, no second pairing code. This is what makes the product behave the way
-people expect, and it is also finding C4 (§7.1). The native client removes the need for it
+**Several browsers, one identity per node.** A browser keeps nothing durable the user
+controls, so the identity it creates for a node is left with that node, encrypted under the
+passphrase. Any other browser recovers it there with the passphrase alone: same identity on
+that node, same pin, no second code. Joining a *different* node creates a different key and
+needs that operator's code, which is the first contact it has always needed.
+
+This is what makes the product behave the way people expect, and it is also finding C4
+(§7.1) — with a blast radius of one node. The native client removes the need for it
entirely, which is a large part of why it exists.
The SPA is not deprecated. It is the zero-install path and it stays. It must be labelled