summaryrefslogtreecommitdiffstats
path: root/docs/MESHBAY_DESIGN.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/MESHBAY_DESIGN.md')
-rw-r--r--docs/MESHBAY_DESIGN.md29
1 files changed, 29 insertions, 0 deletions
diff --git a/docs/MESHBAY_DESIGN.md b/docs/MESHBAY_DESIGN.md
index f125825..bda33f1 100644
--- a/docs/MESHBAY_DESIGN.md
+++ b/docs/MESHBAY_DESIGN.md
@@ -2471,6 +2471,35 @@ Two structural recommendations from that review stand as rules:
| **T2** | The hub was the key directory. **Closed** by admission redesign, not by safety numbers: the invite path reads no directory at all (§3.4). Reclassified as **H3** |
| **T3** | **The hub serves the SPA. Accepted permanently for browser users.** It is the only remaining way an active hub reads content, it is an artifact-level attack rather than a silent lie, and it does not exist for a native client — whose value is realised by reproducible builds, not by packaging (§2.3, §8.2) |
+### 13.5b Availability between members (`AV`)
+
+**Added 2026-09-12, after the finding that produced it.** The first three
+reviews asked who can read what, who can impersonate whom, and what a hostile
+node can forge. None asked **what a legitimate but misconfigured or careless
+member costs everyone else** — and that is the question a group platform lives
+on, because every member was invited by someone who trusted them and none of
+them is an attacker. `C2` had asked "can a node claim a group its owner is not
+in?" and the answer was correctly no; nobody had asked what happens when a node
+claims one its owner *is* in but which it does not host, which is how a group
+went dark for all of its members on 2026-09-11 with its real host online
+throughout.
+
+The lens, for anything reviewed from here: **a participant supplies input; who
+else bears the cost?** Where the answer is "someone other than the sender",
+there must be a ceiling, and it must apply on every path that writes the state
+— not only the one where the ceiling was first thought of.
+
+| Label | The rule it names |
+|---|---|
+| **AV1** | **An empty claim is a claim on nothing.** A node's group set is `authorized ∩ claimed`, and an absent or empty `group_ids` registers it for no group rather than all of its owner's — on registration and on `update_groups` alike (§7.2) |
+| **AV2** | **A client treats the hub's node list as candidates, not a ranking**, and tries the next one on a `not_hosted` refusal (`MESHBAY_NODE_PROTOCOL.md` §6.3) |
+| **AV3** | **A node speaks only for the groups it is registered for.** `chat_notify` names a group and is checked against that node's set before a notification is written for anyone, and it is rate-limited per node — the fan-out is one write per member |
+| **AV4** | **Nobody names a third party's address.** A swarm source publishes a transport and a port, never a host; where a peer is comes from its node record, stamped with the address its announce arrived from. The number of hashes one account may claim is bounded |
+| **AV5** | **An answer is accepted only from the node the offer was sent to.** A `peer_id` is bound to its node, so no connected node can resolve another's pending offer |
+| **AV6** | **A relay proves possession of its approved key.** A public key is not a password, and the register call is unauthenticated by design — it is not a user — so the proof is the only thing standing between a stranger and where nodes send relayed traffic |
+| **AV7** | **A node bounds how many peers it holds and how long an unproven one lasts.** The hub's cap is per calling account, which is a limit on each member and not on the machine, so without this an operator's exposure grew with the size of their groups |
+| **AV8** | **One account cannot make the hub mail another at will.** The invitation email's subject comes from the group row, never from the request, and the endpoint is metered |
+
### 13.6 Chat design findings
| Label | The rule it names |