diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-10-01 13:06:32 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-10-01 13:06:32 +0200 |
| commit | e0905bd447f6214dc34e360554826ace45bde676 (patch) | |
| tree | 64c371d7675861f4af6ade210c46652bd610707a /docs/MESHBAY_DESIGN.md | |
| parent | 0d9d91eeea9001ea3838272416e3d526b6a2a1fc (diff) | |
| download | meshbay-e0905bd447f6214dc34e360554826ace45bde676.tar.gz | |
fix: an MBK2 bundle is opened once and stored again as MBK3
Transitional. The Argon2 run that makes M makes A, the key MBK2 bundles were
sealed under; a session keeps it as a decrypt-only key (IndexedDB in a browser,
the key storage in the desktop app). A client meeting an MBK2 bundle opens it —
or its recovery copy — and stores the same identity as MBK3 once connected; the
desktop app reseals or withdraws it as browser access says. A session without
A asks for the passphrase once. Older formats stay refused by name. Replaces
the unpin-and-reinvite step the 0.17 flag day required on every node.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'docs/MESHBAY_DESIGN.md')
| -rw-r--r-- | docs/MESHBAY_DESIGN.md | 47 |
1 files changed, 29 insertions, 18 deletions
diff --git a/docs/MESHBAY_DESIGN.md b/docs/MESHBAY_DESIGN.md index e721cb2..c443955 100644 --- a/docs/MESHBAY_DESIGN.md +++ b/docs/MESHBAY_DESIGN.md @@ -651,15 +651,27 @@ which were a second oracle when their key came from the passphrase alone. A bundle copied to another node, or served for another account, does not open. The recovery copy (§3.6) has the same format under the recovery key, with pepper -version 0. **Nothing else is read**: a bundle in an earlier format — sealed under -the passphrase alone — is refused by name, never opened and never replaced by a -new identity behind the member's back, which would leave the node pinning a key -nobody holds. The client says so, and the way out is the operator's: `member -unpin` (which drops the bundle) and a fresh code. That was the flag day of 0.17.0 -(§5.6). +version 0. **Nothing else is written.** One earlier format is still read, once, +to be replaced (*transitional*): `MBK2` — `"MBK2" ‖ nonce ‖ AES-GCM(A, {skEd, skX})`, +no associated data — sealed under the passphrase's Argon2 key alone. The Argon2 +run that makes `M` makes `A` anyway, so a session keeps `A` too, as a +decrypt-only key (in IndexedDB beside `M`; in the desktop application beside `M` +in its key storage, until sign-out). A client that meets an `MBK2` bundle opens +it with that key — or its recovery copy with the recovery key — and stores the +same identity as `MBK3` once the connection is made; the desktop application +stores it, or withdraws it, as the account's browser access says. Keeping `A` +for a session adds nothing a node does not already hold: the `MBK2` bundle on its +disk is the same oracle, until it is replaced. A session that has no `A` — one +opened before it was kept, a device sign-in — asks for the passphrase once. A +legacy key that does not open it means a bundle sealed under an older passphrase, +treated like a current bundle that does not open. Anything older than `MBK2` is +refused by name, never opened and never replaced by a new identity behind the +member's back, which would leave the node pinning a key nobody holds; the way +out is the operator's, `member unpin` and a fresh code. The `MBK2` reader goes +once no node holds one. **What a session keeps is `M`**, non-extractable, in IndexedDB until sign-out. -Not the pepper and not `A`. So the hub is asked for the pepper once per sign-in, +Not the pepper, and `A` only as the transitional decrypt-only key above. So the hub is asked for the pepper once per sign-in, inside the sign-in response, and never again while the session lasts: reloads, reconnections and new nodes derive nothing. @@ -1411,17 +1423,16 @@ reachable on every node, which is exactly what "no compatibility switch" forbids So the floor moved to 4.0, `client.minimum` moved to the release that carries the new client, and the hub, node and SPA deploy together. -**0.17.0 is a flag day with no protocol change at all**, and it follows the same -rule. The keypair bundle is opaque to the node, so MNP did not move; what changed -is what a client writes into it and reads out of it (`MBK3`, §3.7). A client that -still read the older format would keep it reachable, and an older client would -still write it — the passphrase-only seal that the pepper exists to replace. So -the client refuses the old format by name, and `client.minimum` moved to 0.17.0 -so that no desktop client can go on writing it; the browser takes the new client -from the hub on reload. What it costs is stated rather than migrated: each -identity sealed in the old format is re-created on its node after `member unpin` -and a fresh code, and a playlist the node alone held is lost — any copy a browser -or the application still has is sealed again over it. +**0.17.0 is a flag day**, and it follows the same rule. What a client writes into +the keypair bundle is `MBK3` (§3.7); an older client would go on writing the +passphrase-only seal the pepper exists to replace, so `client.minimum` is 0.17.0 +and the browser takes the new client from the hub on reload. An `MBK2` bundle is +read once and replaced (§3.7), so no identity has to be re-created; a playlist the +node alone held under the old key is lost — any copy a browser or the application +still has is sealed again over it. And retiring a device is signed under a +transcript of its own (`meshbay:device_revoke:v1`, §3.3), so a 0.17 client and a +0.16 node, or the reverse, cannot retire devices with each other: hub, nodes and +clients move together. **Every *requirement* is true of every peer the client can reach.** The floor moves with each MAJOR, so `check_version` refuses at the handshake any peer that cannot |