summaryrefslogtreecommitdiffstats
path: root/docs/meshbay-draft-v5.md
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-08-15 00:30:29 +0200
committerChristophe Besson <cbesson@gmail.com>2026-08-15 00:30:29 +0200
commit4156b5b8c3986278a887d1dce4db265746e9155f (patch)
treef98a5198015cbdfbf054549984cccc1a41bf499d /docs/meshbay-draft-v5.md
parented2e0640b48148b69eca00ad7dd06789506e12ac (diff)
downloadmeshbay-4156b5b8c3986278a887d1dce4db265746e9155f.tar.gz
docs: account deletion, notifications, and the APIs that no longer exist
Account deletion is the headline, in the user guide and in draft-v5 §6.1, and the important half is what deletion does *not* do. It releases the username, clears the email and password hash, drops memberships, notifications, refresh tokens and node registrations, and refuses any access token still inside its hour. It does not touch a node: files, the pinned identity and the keypair bundle stay on machines the hub does not command, which is the same sovereignty §5.5 relies on — so deleting a hub account is not an erasure request to the operators hosting you. The IP log survives too, attributable, for its legal retention period. The claims table in §2 gets a row saying exactly this, adversary by adversary. Notifications get a section: one entry per conversation rather than per message, never one for your own message, invitations that clear when you join, muting that lives on the hub so it works from any browser. Then the corrections, which is most of the diff. The guide still described a node HTTP API — `GET /index`, `GET /file/{id}`, an HLS playlist, and a `player.js` that does not exist — with curl examples inviting the reader to expose port 19001. That surface was removed in 0.2.0 as findings C1 and C6, precisely because it served files outside the handshake that decides what a peer may see. Sections 6, 7 and the API reference now describe MNP message pairs, and the quickstart says the same in French. Also corrected: the JWT table advertised a `pk_user` claim that no longer exists (it was what let the token issuer decide who could delete a file), `/pubkeys` no longer returns identity keys, and the GEK-distribution endpoints are gone entirely rather than merely unused. draft-v5 §5.2 had uploads landing in `.uploads/{user_id}/`; they land in `uploads/`, chat attachments included. §6.1 now says the hub learns the author's user_id from chat_notify — a stable identifier, and a metadata leak worth naming rather than leaving as "by whom". CLAUDE.md records why the deployed hub broke this week: create_all() creates missing tables, never missing columns, so a schema change passes every test (fresh DB per run) and never reaches production. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'docs/meshbay-draft-v5.md')
-rw-r--r--docs/meshbay-draft-v5.md40
1 files changed, 34 insertions, 6 deletions
diff --git a/docs/meshbay-draft-v5.md b/docs/meshbay-draft-v5.md
index 2a0f3b1..68f6843 100644
--- a/docs/meshbay-draft-v5.md
+++ b/docs/meshbay-draft-v5.md
@@ -65,6 +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 | — | — | ✅ |
+| Deleting your account erases you | ✅ hub-side | ✅ hub-side | ❌ **files, pinned identity and bundle stay on the node** — §6.1 | — | — |
| 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
@@ -237,10 +238,17 @@ of the loop, so nobody has to be online when the invitee actually joins.
### 5.2 Uploads
-Confined to `shared_root/.uploads/{user_id}/`, filename allowlist, no overwrite, chunk
-ordering enforced, size capped. Previously uploads landed in the shared root under a
-client-chosen name and overwrote anything there — which also defeated deletion
-authorization, since overwriting a file made the attacker its recorded uploader.
+Confined to `shared_root/uploads/`, filename allowlist, no overwrite (a colliding name
+gets a suffix), chunk ordering enforced, size capped. Chat attachments land there too, so
+there is one directory an operator can look at, empty, or back up. Nothing derived is
+written beside them: a chat thumbnail is the decrypted file scaled by the browser, so the
+node stores no second copy of an image it already holds.
+
+The destination has moved twice — `shared_root/` → `.uploads/{user_id}/` → `uploads/` —
+and the four protections above were carried across each move deliberately. The original
+version accepted a client-chosen path and overwrote whatever was there, which defeated
+deletion authorization as well: overwriting a file made the attacker its recorded
+uploader, and therefore the party allowed to delete it (C5a).
### 5.3 Operator interface
@@ -333,8 +341,28 @@ who could delete a file.
private keys, GEK bundles, keypair bundles, node IPs beyond ephemeral signaling.
**Knows, unavoidably:** who is a member of what, when nodes connect, when a chat message
-was posted and by whom (`chat_notify` — minimization was in the dropped phase), and
-content hashes for **public** groups only.
+was posted and by whom, and content hashes for **public** groups only.
+
+The "by whom" is a `user_id`, not a display name, since 2026-08-15. The node has to name
+the author for the hub to skip them when creating notifications — it used to name nobody,
+so the hub substituted the node's own account and told every author about their own
+message. The exchange is `chat_notify` over the node's hub socket and it carries no
+content, but it is a stable identifier: the hub can build who-talks-in-which-group-when
+without reading a word. Minimizing it was in the dropped phase, and it stays a known
+metadata leak rather than a solved problem.
+
+**Erases on request, and what survives.** A user can delete their own account from
+Settings (passphrase re-entered — a live token may be a borrowed laptop), and a hub admin
+can delete one. The row is tombstoned rather than dropped: username released, email and
+password hash cleared, node linking key dropped, memberships, notifications and refresh
+tokens removed, active access tokens refused at once by status check rather than left to
+expire. Two things survive on purpose. The IP log is kept for its legal retention period
+and stays attributable, since detaching it would keep the data and lose the only thing it
+is for. And **nothing on a node is touched**: files, the pinned identity and the keypair
+bundle live on machines the hub does not command, which is the same sovereignty that makes
+§5.5 work. Deleting the hub account is not an erasure request to the operators who host
+you — the operator interface (§5.3) is where that happens. Deletion is refused outright
+while the account still owns groups, rather than cascading into other people's data.
**No longer decides:** who holds the group key. The hub still publishes public keys, and
they are still used to look up an account by name — but nothing wraps a key for a key