Files
spacedrive/docs
Jamie Pineandcapy-ai-staging[bot] cedc8d6f7e Locked volumes L1 and L2: vanished volumes go offline, attached means mounted (#3119)
* Locked volumes L1: a volume that disappears goes offline

The volume monitor marked a tracked volume offline only while detection
still returned it, so a drive that vanished while the daemon was down, or
a dataset whose key was not loaded, kept is_online = 1 and attach_library
resolved its sources against the stale flag. The monitor now reconciles
every tracked row against detection and marks a vanished volume offline,
telling the volume index so sources on it detach or reattach without a
restart. attach_library resolves against live detection when monitoring
is on, corrects a disagreeing row in place, and falls back to the stored
flag when it is off. Each mapped drive carries its mounted state, and a
source on a drive that is away comes up detached with its map restored
read-only, no watch armed and nothing dispatched at the directory left
behind. sources.list reads attachment from the index instead of the root
existing.

KeyManager::close used a file named :memory: as its placeholder, which
one process can only hold once; a second core closing in the same
process left its secrets file locked for the next open. It now uses
redb's in-memory backend.

Acceptance runs on a loop-mounted ext4 image unmounted with its mount
point left in place; the suite joins the acceptance group of
xtask test-core and skips with a reason without sudo or a loop device.

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* Locked volumes L2: attached means mounted

Attachment was Path::exists on the source root, and an unmounted drive
leaves its mount point behind as an empty directory that passes it. The
volume index now refuses to dispatch anything at a path whose drive is
detached or whose mount point is not a mount point (on Unix, its device
is the same as its parent directory's), whatever the stored state says:
the source walk, the whole-drive map, the coverage heal, the content
identification pass and the thumbnail job all check before running, and
the indexer and identification jobs check again at run so a job resumed
from a previous session cannot slip past. sources.track refuses the
mount point of a known volume that is not mounted instead of registering
a second source over the parent filesystem. The mount point check applies
to drives learned from a volume row or from detection; a directory a test
tracks as a drive keeps working.

The acceptance scenario unmounts a loop volume under a running daemon
with detection still saying mounted, drops the snapshot so a forced heal
wants a walk, and proves no walk or hash job runs, the store keeps every
record, tracking the directory refuses, and the listing reports the
source unmounted with its counts intact.

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* Release the library lock on every shutdown path

Library::shutdown returned early when the job manager could not pause a
running job in time, leaving the lock file behind; the next process in
the same hour then refused the library as in use. The acceptance run on
CI hit this when the hashing pass was still running at the fixture's
shutdown. The lock is now released after the inner shutdown whatever it
returned, and the fixture waits for its queued jobs before stopping.

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* Review fixes: scope volume rows to this device, keep away drives resolvable, check detected drives' mount points

attach_library_with and the monitor's reconcile now read and write only
this device's volume rows; the table holds every device's, and a peer's
row resolved against local detection was both corrected in place and
entered into the volume index at the peer's mount point. The reconcile
pass logs a row it cannot write and goes on to the next instead of
aborting the library's pass. locate keeps a drive that is away in its
fallback, so a mapped drive with no source over it still serves its map
read-only from its own partition rather than scratch, with the mounted
drive winning only at the same or a longer mount point. Drives detection
returned are mapped through track_detected_volume, which carries their
mount state and makes the mount point check apply to them; track_volume
stays for cloud prefixes and the directories tests stand in for drives.
The acceptance fixture waits for the hashing pass by its effect rather
than by the running job list.

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* Cloud volume roots are never refused as unmounted

A cloud volume mounts at a service prefix such as s3://bucket, which
detection never lists and Path::exists never answers for, so the mount
guards read it as away and volumes.index refused every cloud volume.
A cloud root is reachable as long as its row says so: attach maps it
mounted without correcting its row, root_attached and dispatch_refusal
pass it, and it never carries the mount point check.

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* Stop the library watcher before closing libraries at shutdown

The library directory watcher auto-opens a library whose lock file
changes, and close_library removes the lock file, so a core shutting
down reopened its own library from the watcher task and a core starting
in the same process then found it in use. The acceptance job on CI hit
this on every restart. The watcher now stops before the libraries close.

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* Acceptance tests: say what the library and index hold when a source is missing

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* Acceptance diagnostics carry a failed query instead of reading as empty

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* Acceptance diagnostics list the open libraries

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* Locked volumes acceptance fixture keeps the daemon's one library

The core's volume index serves the library opened last and library load
order follows the data directory listing, so a fixture with two libraries
came up with an empty index on some runners.

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

---------

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>
2026-10-07 12:25:06 +00:00
..

Spacedrive Documentation

The Spacedrive docs site, built with Fumadocs on Next.js. This directory is a standalone app with its own bun install, separate from the repo workspace.

bun install
bun run dev      # dev server on localhost:3000
bun run build    # production build

Or from the repo root: just dev-docs / just build-docs. Requires Node 20+.

Layout

  • overview/, core/, extensions/, cli/, react/, gpui/: published MDX content, one sidebar tab per folder. Navigation order lives in each folder's meta.json.
  • app/, lib/, components/: the Next.js app. Pages are served from the site root, so core/jobs.mdx renders at /core/jobs.
  • public/: images, logo, favicon.
  • plans/, core/design/, design/, archive/: internal working docs, not part of the site.
  • WRITING_GUIDE.mdx, CODE_COMMENTS.mdx: contributor guides, not published.

Writing pages

Frontmatter supports title, description, and sidebarTitle (a shorter name for the sidebar). Callouts, <Steps>, <Tabs>, <Cards>, and <Accordions> are registered globally, so no imports are needed in MDX. Every page is also served as raw markdown at <path>.md and indexed in /llms.txt.