summaryrefslogtreecommitdiffstats
path: root/docs/MESHBAY_NODE_PROTOCOL.md
Commit message (Collapse)AuthorAgeFilesLines
* feat: a group can be left out of Search, and Search tries every nodeChristophe Besson11 days1-0/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | `search_listed` is a per-group setting on the node, changed by a signed operator op and carried in the sealed handshake ack. Search reads it after the handshake and stops there: no index is fetched, cached or merged, in any of the four views, and the page says how many groups it left out. The switch is a "Search" section in the group's settings, shown to the operator. Absent means listed, at every layer: roster default, ack default, and the client only drops a group on an explicit `false` — so an upgrade or an older node removes nothing from anyone's Search. It is a listing preference and protects nothing: the node serves the same index to Search and to the group page and cannot tell them apart, every member lists the group by opening it, and a client that ignores the flag lists it in Search too. Design §9.11 says so, so it is never described as private. The cost is one handshake per unlisted group, because only the node knows the setting. Search also took `nodes[0]` twice — for the index and for the pooled connection — the defect 4cce50f fixed on the group page only. One `connectToGroup` now walks the list the same way: a refusal about this browser stops, `not_hosted` or a failed connection moves on. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XuNrwLf5EFWCMHzfoEvnpm
* fix: an empty group claim is a claim on nothingChristophe Besson13 days1-1/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A node that hosts no groups sends no `group_ids` on its hub socket, and the hub resolved the claim with `set(claimed_groups or authorized)` — so "I host nothing" arrived as "I host every group this account belongs to", other members' included. Such a node can serve none of them: it holds no GEK, and its own handshake refuses them with "Group not hosted on this node". `/v1/groups/{id}/nodes` answers in registration order and `_node_groups` is in-memory, so which node a client was sent to depended on who reconnected first after a hub restart. GroupPage took `nodes[0]` with no fallback. On 2026-09-11 a hub deploy at 20:14 reshuffled the registry, a second member's unconfigured node won the race, and a group stopped opening for everyone in it with its only real host online throughout. Any member could take one of their groups down, by accident, by leaving an empty node running. Four changes, because no one of them is sufficient: - the hub never widens an absent claim, and `update_groups` goes through the same ceiling as registration — it assigned its list verbatim, so the bound that makes C2 hold at authentication was one message wide - the node states the empty set rather than omitting the field - the refusal carries `not_hosted`, so a client can tell "try the next node" from "you, here, must do something first" - GroupPage walks the list instead of indexing into it The three lines involved date from 13, 20 and 23 August and each is defensible alone. The defect is in the seam, which is where the last two also were: a falsy empty collection must never mean "unspecified". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T4YmK41VsEURWFdop4EEeT
* docs(mnp): the protocol reference, brought to the cleanup pushChristophe Besson2026-09-101-0/+2197
MESHBAY_NODE_PROTOCOL.md and playlists.md move into the repository, where a reader can follow them. The protocol reference was written against the tree before the cleanup landed and described three things that no longer exist. Corrected here rather than left to be discovered: * member_upload is gone from the handshake ack and from the message catalogue. Whether a member may write is a property of each root, and a summary field beside the authoritative one is a second source for one question — whichever the reader consults first decides it. * video_root, audio_root and photo_roots are gone from the ack, the signed-op table and the message reference. app_directories is not "the general form" of three narrower ops any more; it is the only one. What survives is their storage key on the node, because that is a key on an operator's disk rather than on the wire, and a node upgraded into this has to find its own configuration. * The sender-key implementation the chat section pointed at has been deleted, along with the ratchet. The argument for deriving a key per device stands on its own now instead of pointing at a module to compare against. playlists.md is added as written — a design for a feature that is not built, and the first one to need per-account state spanning several groups on several nodes. Its decided shape is summarised in MESHBAY_DESIGN.md section 9.10. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YVoHVCcfBqud6ZjG4db3y7