aboutsummaryrefslogtreecommitdiffstats
path: root/docs/MESHBAY_DESIGN.md
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-10-12 00:17:32 +0200
committerChristophe Besson <cbesson@gmail.com>2026-10-12 00:17:32 +0200
commit14911aae21ec4975f7a805b91e3c4867cb41974b (patch)
tree8c00230a88053905fd77938f3a9539efeb4c3094 /docs/MESHBAY_DESIGN.md
parentf6f107e02c7a4aa7326c9a82310a239327d81ed6 (diff)
downloadmeshbay-14911aae21ec4975f7a805b91e3c4867cb41974b.tar.gz
feat: let the operator pause and resume a root's indexing (MNP 6.2)
A whole-root walk now checks its root before every file: removed or ejected, it stops instead of reading the drive to the end; paused, it finishes from the hash cache alone. A paused root is not watched, not swept by reconcile and survives a restart (roster), its indexed files stay served. Resume runs the reconcile sweep over the root, so entries and their enrichment are kept. Signed root_pause / root_resume over MNP, loopback routes, CLI `root pause|resume`, a pause button on the indexing dock and pause/resume in the roots table of Group settings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'docs/MESHBAY_DESIGN.md')
-rw-r--r--docs/MESHBAY_DESIGN.md35
1 files changed, 30 insertions, 5 deletions
diff --git a/docs/MESHBAY_DESIGN.md b/docs/MESHBAY_DESIGN.md
index 9c63c52..d0b5475 100644
--- a/docs/MESHBAY_DESIGN.md
+++ b/docs/MESHBAY_DESIGN.md
@@ -16,7 +16,7 @@
> them — it names the invariant that holds today, not the incident that produced
> it. §13 is the register of those labels.
>
-> Wire versions at the time of writing: **MNP 6.1** (oldest peer accepted 4.0),
+> Wire versions at the time of writing: **MNP 6.2** (oldest peer accepted 4.0),
> **MHP 0.1**, packages **0.19.0**. The normative source for the wire format is
> `MESHBAY_NODE_PROTOCOL.md`; this document states the design the protocol
> serves, not its byte layout.
@@ -1231,7 +1231,7 @@ from anything in the response.
| `invite_link_create`, `invite_cancel` | the operator |
| group key init and rotation | **local admin API or CLI only**; the node generates the key itself |
| root add, root `writable`/`removable`, hosting a group, transfer limits | **local admin API or CLI only** (MNP 6.0) |
-| root remove/eject/plug, `apps_enabled`, app directories | operator-signed |
+| root remove/eject/plug/pause/resume, `apps_enabled`, app directories | operator-signed |
| ~~`gek_bundle_store`~~ | **the message does not exist.** No member ever hands the node key material |
`gek_bundle_store` was deleted rather than gated. The operator's X25519 public key
@@ -1641,8 +1641,9 @@ A signed op proves that the operator's key signed, not that they meant it: in a
browser that key is driven by code the hub serves (T3), and in the desktop
application by a renderer that parses content from nodes. Either could otherwise
have shared any folder on the machine, writable, from anywhere. The operator still
-sees every root and its flags from any browser; removing, ejecting and plugging stay
-signed ops, because they narrow what is shared or restore what already was.
+sees every root and its flags from any browser; removing, ejecting, plugging, pausing
+and resuming stay signed ops, because they narrow what is shared or restore what
+already was.
> **There is one answer to "may this member write", and it is the root.** A single
> flag over the group cannot express "this library is published read-only and that
@@ -1670,6 +1671,12 @@ states:
- **`available`** — computed as `not ejected and is_live()`. This is what clients
and the indexer see.
+A third, **`paused`**, is the operator's alone and independent of both: the root is
+readable and served, and its indexing is stopped (§6.3). Persisted in `roster.db`
+beside `ejected`, for the same reason: a pause that a restart undid would start the
+scan the operator stopped. Removing a root forgets its pause, so a directory added
+back under the same name starts indexed.
+
The distinction matters: between clicking eject and physically unplugging,
`is_live()` is still true, and without `ejected` the availability sweep would
immediately flip the root back.
@@ -1755,6 +1762,24 @@ reason to show progress.
`index_progress` is deliberately **not** sealed: counters only, every 2 s.
+**A walk looks at its root before every file.** A root removed from the set or
+ejected while it is walked is not read to the end: its entries are dropped, or
+frozen on a drive that is leaving. The walk reads the root from the current set,
+not the object it started with, because a reload replaces every root.
+
+**A pause outlasts the walk it stops.** Reconcile indexes every file the index
+lacks, so a walk that was merely cancelled is redone at the next tick. A paused
+root is therefore not watched, not swept by reconcile, and not hashed by any walk:
+
+- **A walk that meets a pause finishes from the hash cache alone.** What the node
+ already hashed stays listed; nothing new is read. Stopping dead is not enough,
+ because the index is rebuilt at every start and a rescan drops the root's
+ entries before it walks — either would leave a paused root half empty.
+- **Resuming runs the reconcile sweep over that root, never a scan.** A scan
+ replaces every entry it meets, and with them what the enrichment passes put
+ there; the sweep indexes only what the index lacks. The request returns once
+ the walk is queued, and the progress band shows it.
+
### 6.4 Uploads
Five protections, and they are the substance:
@@ -1989,7 +2014,7 @@ before its key is linked or a group exists.
```
meshbay-node status
meshbay-node group list|add|remove
-meshbay-node root list|add|remove|set|eject|plug
+meshbay-node root list|add|remove|set|eject|plug|pause|resume
meshbay-node gek init|rotate
meshbay-node operator pair
meshbay-node member list|invite [--link]|cancel|revoke|unpin