summaryrefslogtreecommitdiffstats
path: root/docs/MESHBAY_NODE_PROTOCOL.md
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-10-14 22:20:15 +0200
committerChristophe Besson <cbesson@gmail.com>2026-10-14 22:20:15 +0200
commit28c88908b88c58cba4de08710f6bb268ede02d57 (patch)
tree7e55f276ee0a8a25f6175f9ef81ebb845d1c218d /docs/MESHBAY_NODE_PROTOCOL.md
parent51705056a578d2649a989bf14a056fbcfae58a6b (diff)
downloadmeshbay-28c88908b88c58cba4de08710f6bb268ede02d57.tar.gz
feat(node): accept a device link request before the proof (MNP 6.3)
A new device of a known account holds no identity the node pinned, so it cannot complete a handshake until a pinned device approves it: it now files device_add_request in the pre-proof window, as the desktop app's case already required. The request stays inert until countersigned; at most 10 are pending per account, the oldest dropped. A 6.2 node answers it "Handshake required", which a client reads as "cannot link here". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'docs/MESHBAY_NODE_PROTOCOL.md')
-rw-r--r--docs/MESHBAY_NODE_PROTOCOL.md26
1 files changed, 17 insertions, 9 deletions
diff --git a/docs/MESHBAY_NODE_PROTOCOL.md b/docs/MESHBAY_NODE_PROTOCOL.md
index 207d640..8372ee7 100644
--- a/docs/MESHBAY_NODE_PROTOCOL.md
+++ b/docs/MESHBAY_NODE_PROTOCOL.md
@@ -625,20 +625,21 @@ operator's real choice (I8).
## 7. The pre-proof window
Between `handshake_challenge` and a valid `handshake_response` the peer is
-*authorized* but not *authenticated*. Three message families are served there, each
+*authorized* but not *authenticated*. Four message families are served there, each
because the peer provably cannot compute a proof without it. **Everything else is
answered `Handshake required`**: the dispatcher's authenticated branch begins
-immediately after these three, so the table below is the window, exhaustively.
+immediately after these four, so the table below is the window, exhaustively.
| Message | Why it must precede the proof | Bound |
|---|---|---|
| `keypair_bundle_fetch` | the client's own identity keys for this node live in an encrypted bundle stored on it | counts against `MAX_PRE_PROOF_FETCHES` = 4; audited |
| `gek_bundle_fetch` | the wrapped group key is what the proof is computed with | same counter |
| `join_request` | a first-time member holds no group key at all. Accepted after the proof as well — an operator pairing a browser is already connected — because its authority comes from the pairing code and the signature, never from the session state | 5 attempts per connection; wrong codes: 5 per account and 20 node-wide per 600 s, consulted only when a code is tried |
+| `device_add_request` | a new device of a known account holds no identity this node pinned, so the node wraps it no group key (§9). Inert: it admits nothing until a pinned device countersigns. Filed for the account the token names. Accepted after the proof as well | the device budget, 5 attempts per connection; 10 pending requests per account, the oldest dropped; audited |
-Device linking (§9) is **not** in this window. `device_add_request` and every message
-after it are answered only on an authenticated session, and the device budget of 5
-attempts per connection applies there.
+The rest of device linking (§9) is **not** in this window: `device_lookup`,
+`device_add`, `device_list`, `device_revoke` and `device_hello` are answered only on
+an authenticated session, by the device budget of 5 attempts per connection.
Exceeding the fetch budget is audited as `pre-proof fetch flood` and answered
`Too many requests`. Every fetch in this window is written to the audit log with the
@@ -960,9 +961,12 @@ two keys on the same node. A second device is admitted by **a key the node alrea
pinned** — never by the hub, which stores no user keys and therefore cannot countersign
anything.
-Every message in this section is answered on an **authenticated** session only (§7):
-both the device filing a request and the device approving it have completed a handshake
-on their own connection.
+The new device files its request in the **pre-proof window** (§7): it holds no
+identity the node pinned, so it cannot complete a handshake until the request is
+approved. Every other message in this section is answered on an **authenticated**
+session only — the approving device has completed a handshake on its own connection.
+Once approved, the new device's next `join_request`, with no code, is recognised and
+answered with the group key, like any pinned device's.
### 9.1 Exchange
@@ -2187,7 +2191,7 @@ message:
## 13. Versioning and compatibility
-MNP versions independently of the package version. Current: **`6.2`**; oldest peer
+MNP versions independently of the package version. Current: **`6.3`**; oldest peer
accepted: **`4.0`**.
4.0 is the floor: a member presents a short-lived node-audience token bound to one node
@@ -2217,6 +2221,10 @@ answer, as for any unknown type, and nothing else changes.
the roots table, additively: a 6.1 node gives no answer to either message, and a client
that ignores `paused` shows a paused root as an ordinary one.
+6.3 serves `device_add_request` in the pre-proof window (§7, §9), additively: a 6.2
+node answers it `Handshake required` there, which a client reads as "this node cannot
+link a new device", and nothing else changes.
+
The two numbers are separate on purpose. `MNP_VERSION` says what this build speaks;
`MNP_MIN_SUPPORTED` says what it will talk to, and moving the second is a decision about
whether an older peer can still do anything useful: