Local Repository
Repository::local(path).await opens the standard persistent profile. CLI
commands that open a local repository use the same profile. sync selects
its source and destination explicitly; archive inspection needs no
repository.
Opening a new profile creates its payload directory, lock files, and logical database. Opening an already-current profile performs no logical state write. Schema initialization or upgrade may write and is coordinated like any other state mutation.
Layout
Section titled “Layout”The main paths are:
<repository>/ blobs/ blobs/b3/<xx>/<hex> chunks/b3/<xx>/<hex> bao/b3/<xx>/<hex> casita.sqlite casita.sqlite.online-pins gc.lock spill/ runs/| Path | Purpose |
|---|---|
casita.sqlite |
Revisioned object records, ordered links, named roots, and current repository revision, plus two local accelerators: verified closures and the ingest cache |
blobs/blobs/b3/... |
Multi-chunk and empty-payload manifests |
blobs/chunks/b3/... |
Zstd-compressed FastCDC chunks |
blobs/bao/b3/... |
Optional derived Bao outboards for verified range reads |
casita.sqlite.online-pins |
Durable scoped pins and deletion claims |
gc.lock |
Cross-process single-collector mutex |
spill/ |
Temporary traversal state, present only while a traversal exceeds its memory budget |
runs/ |
Temporary checkouts for casita run; an interrupted run may leave files here |
Spill files are not repository state. A traversal that outgrows SpillLimits
moves its visited set and work queue into a temporary database here, deletes it
when the traversal ends however it ends, and holds a lock file meanwhile so a
repository open sweeps abandoned files without disturbing a live traversal in
another process.
Spill telemetry
Section titled “Spill telemetry”fsck() reports traversal temporary-state use in FsckReport::spill, and
collect() reports the same information in CollectionOutcome::spill. The
SpillMetrics summary has two fields:
files_opened: temporary spill databases opened during the operation.peak_bytes: the greatest aggregate footprint observed for active spill databases, including their SQLite WAL files.
Metrics are captured before cleanup. It is therefore normal for a completed
operation to report nonzero values while spill/ is empty afterwards. They are
performance diagnostics, not persistent repository state or a quota guarantee.
The sharding key is lowercase BLAKE3 hex; <xx> is its leading shard.
Single-chunk payloads omit a separate manifest because their chunk and payload
digests are identical.
Logical state
Section titled “Logical state”The SQLite-format database stores four generic concerns:
- one opaque current repository revision;
- immutable object keys, physical payload IDs, and verified sizes;
- canonical ordered forward links; and
- validated named roots selecting exact object keys.
Logical state is authoritative. Casita does not reconstruct records by scanning the payload directory. Physical data without a record is collectible residue; a record with no physical payload is an integrity failure.
Local accelerators
Section titled “Local accelerators”The same database holds two tables that are not logical state. Neither is consulted by a reader, neither participates in the repository revision, and either may be discarded: losing one costs work, never correctness.
- Verified closures record which object graphs have already been checked
whole. Records are immutable and only collection removes them, so a closure
that verified once stays verified; publication, checkout, and synchronization
stop their walk at a remembered one instead of re-reading everything beneath
it.
fsckignores the table, because reading the bytes back is exactly what an audit is for. - The ingest cache records which content each imported file held, keyed by the device, inode, size, and both timestamps the walk observed. See Imports.
Both are pruned by collection alongside the objects they refer to, and every digest either one produces is confirmed against committed state before it is used, so an entry that outlives its object costs a lookup rather than returning a stale answer.
The local state engine uses a multi-process WAL. Casita serializes logical
writes while independent readers may proceed concurrently. The current
pre-release database layout is schema version 6, including object creation
generations for online snapshot retention. Existing
databases with any other PRAGMA user_version are rejected without mutation;
development-only schemas from before the first release must be recreated or
re-imported. A future schema change will require an explicit offline migration
rather than modifying a repository during ordinary open.
Physical payload behavior
Section titled “Physical payload behavior”Payload identity is always BLAKE3 over complete plaintext bytes. The default chunk store uses content-defined FastCDC boundaries targeting 256 KiB, bounded at half and twice that average, then compresses chunks with Zstd.
These choices do not affect logical identity:
- equal plaintext payloads share the same
BlobId; - equal regions may share physical chunks across different payloads;
- changing chunking, compression, or backend does not change object keys; and
- every chunk is verified after decompression, while a complete sequential read verifies the whole payload at EOF.
Bao outboards are derived physical state. Their presence enables independent verified range reads but is not required to retain or transfer a logical object.
The default store admits at most 64 MiB of plaintext chunk work concurrently across its clones. Transfer independently defaults to a 64 MiB in-flight byte budget. Both are deployment controls rather than durable format parameters.
Process coordination
Section titled “Process coordination”Mutation sessions, retention holds, and transfers register durable scoped pins.
Readers and writers can continue during collection; their pins retain the
logical objects and physical data they use. Collectors take gc.lock so only
one collection or initialization operation runs across processes.
collect() waits for a competing collector, while try_collect() returns
Busy. Operating-system lock release handles collector crashes. Data pins,
prune fences, and deletion claims remain durable until their exact ownership is
resolved; elapsed time never makes an operation safe to forget.
Deleting or replacing gc.lock while Casita processes are running breaks
collector coordination.
Collection order
Section titled “Collection order”Collection marks named-root closures and active pin scopes in one immutable snapshot. It then:
- atomically commits a logical state containing only the marked records;
- deletes unreferenced payload manifests; and
- deletes unreferenced chunks.
Logical prune precedes physical deletion. A physical deletion failure may leak space for a later run but does not invalidate reachable logical state.
The standard local profile knows that state and payloads share one filesystem. If the logical prune fails specifically because storage is full, it may delete only the already-marked stale physical set to create emergency headroom, reopen the writer, and retry the prune. The pin ledger separately reserves bounded bookkeeping space for ownership transitions while capacity is available.
Before a local MutationSession registers its staging pin, Casita samples disk
usage. At the default 80% threshold it attempts nonblocking collection. If
usage remains at or above 75%, it releases least recently used evictable roots
and vacuums after each release. Permanent roots remain. Completed pressure
passes have a 60-second cooldown shared through a repository stamp file.
Busy admits the mutation and leaves the attempt pending for a later session.
Callers may still run gc, invoke collect() directly, or schedule
DiskPressurePolicy::probe_and_collect. On a filesystem with nonzero reported
capacity, zero free bytes always triggers an attempt when the cooldown permits.
Deterministic publication crash tests
Section titled “Deterministic publication crash tests”The library test suite kills a child process at recorded publication steps, then reopens the repository and checks committed roots, payload bytes, and subsequent collection. Run the matrix with:
devenv shell cargo test --all-features --lib blob::crash_tests -- --nocaptureThe matrix covers immutable object writes, catalog publication and rebase, SQL root changes, and process death before or after commit. It verifies that visible roots have complete graphs, acknowledged data survives, and a reopened repository can accept new work. It runs in the normal Linux, macOS, and Windows library suites without an external server.
These tests model process death while the operating system remains alive. They do not model power loss, torn sectors, or remote object-store durability. Unix also tests directory flush boundaries.
Backup and restore
Section titled “Backup and restore”There is currently no separate repository snapshot command. For a simple filesystem backup:
- stop or quiesce every process that can write, publish, retain, or collect;
- copy the complete repository root, including the database and payload tree;
- preserve filesystem metadata needed by the database and regular files; and
- open the restored copy with Casita and run
fsckbefore relying on it.
Copying only casita.sqlite loses payloads. Copying only blobs/ loses the
logical keys, links, roots, and revision that make those bytes meaningful.
Ordinary copy tools do not participate in Casita’s advisory locks, so do not
assume a live file-by-file copy is an atomic snapshot.
Treat an independently restored copy as a separate repository. Revisions are opaque local state tokens and must not be used to order or equate later states across the original and restored repositories.
Operational commands
Section titled “Operational commands”| Goal | Command |
|---|---|
| Inspect roots | casita --repository PATH root ls |
| Preview reclaimable data | casita --repository PATH gc --dry-run |
| Collect unreachable data | casita --repository PATH gc |
| Verify logical and physical integrity, and safely repair when possible | casita --repository PATH fsck [--source REPLICA] |
Do not use gc as a repair tool for reachable corruption. Preserve the
affected repository, inspect the fsck findings, and restore or re-import the
authoritative data as appropriate.