aboutsummaryrefslogtreecommitdiffstats
path: root/docs/MESHBAY_DESIGN.md
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-10-05 11:10:50 +0200
committerChristophe Besson <cbesson@gmail.com>2026-10-05 11:10:50 +0200
commit6cdc6016d72dcfb7530ac38a8fa92232418ac305 (patch)
treec14308cda27ebcb4edfb7096539b9773748b16fb /docs/MESHBAY_DESIGN.md
parent0b2634a20febbfe6d05e9b588093adcfbf13cab6 (diff)
downloadmeshbay-6cdc6016d72dcfb7530ac38a8fa92232418ac305.tar.gz
fix(node): plug an auto-ejected removable root back once its files return
A node started with the desktop session runs before the session has mounted its USB drives. The safety net then auto-ejected every removable root and persisted it exactly like an operator's eject, so after each reboot those roots stayed ejected until someone plugged them by hand (seen on a node whose /media drives were mounted a minute after it started). An auto-eject is now stored as such ("auto" in roster.db). At startup and at every reconcile, an auto-ejected root whose path is readable again is checked against a few files the hash cache knows under it, at the same path with the same size and mtime; one found and the root is plugged back and rescanned. An empty mount point or another drive in its place is not recognised and stays ejected. An operator's eject is never undone automatically. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'docs/MESHBAY_DESIGN.md')
-rw-r--r--docs/MESHBAY_DESIGN.md16
1 files changed, 13 insertions, 3 deletions
diff --git a/docs/MESHBAY_DESIGN.md b/docs/MESHBAY_DESIGN.md
index 2cfe7a4..9c87372 100644
--- a/docs/MESHBAY_DESIGN.md
+++ b/docs/MESHBAY_DESIGN.md
@@ -1565,7 +1565,8 @@ the whole tree or presents an empty directory to the next scan. Both propagate a
though the owner erased their library. So a root has two independent runtime
states:
-- **`ejected`** — operator-controlled, persisted in `roster.db`.
+- **`ejected`** — set by the operator, or by the safety net below; persisted in
+ `roster.db`, with which of the two set it.
- **`available`** — computed as `not ejected and is_live()`. This is what clients
and the indexer see.
@@ -1586,12 +1587,21 @@ let the following scan read the empty mount point as an erased library. It lives
hand-written config must not be rewritten because a USB drive was unplugged.
**Auto-eject is the safety net.** If a `removable` root's path disappears, the
-availability sweep sets `ejected` as though the operator had clicked it, and
-reports it so the daemon persists it. Nothing is deleted: index entries, cached
+availability sweep sets `ejected` and reports it so the daemon persists it, marked
+as the safety net's. Nothing is deleted: index entries, cached
metadata, thumbnails, chat history referencing those files and app directory
configurations all survive, the last flagged as temporarily invalid rather than
wrong.
+**The safety net's eject undoes itself; the operator's never does.** At startup
+and at every reconcile, an auto-ejected root whose path is readable again is
+checked against what the hash cache knows was under it: a few of those files,
+at the same path with the same size and mtime. One found, and the root is
+plugged back and rescanned, like a plug. None found, and it stays ejected: an
+empty mount point or another drive mounted in its place is exactly what the eject
+protects the index from. The case this serves is ordinary: a node started with
+the session, before the desktop has mounted its USB drives.
+
### 6.3 Indexing
The index is **content-addressed**: `GroupIndex` is keyed by blake3, so the same