calternal-fs
Safe, handle-relative access to a calternal data directory.
The server is the single writer. Content is never modified in place: an
immutable blob may therefore be hardlinked by many homes without one user’s
replace changing another user’s file. One server process owns the data
directory; multi-node use requires a distributed lock. The hardlink safety
invariant depends on that exclusive writer, OS ownership of the data
directory, and replacement by rename. Path confinement cannot detect a
hardlink planted by an unrelated process with write access to the tree.
The reserved .system tree is repaired to private directory and file
modes before the server opens the Index or creates snapshots (#728).
Paths are UTF-8. URL percent decoding happens at the API boundary. Unicode control characters are rejected, including newline in Trash metadata. Symlinks are neither created nor followed, including while traversing a parent directory. Non-Linux targets get a compile error rather than an unsafe fallback.
Source: crates/calternal-fs/src/lib.rs
Re-exports
Section titled “Re-exports”pub use calternal_path::is_hidden_namepub use calternal_path::is_hidden_pathpub use calternal_path::is_internal_pathpub use calternal_path::is_internal_temppub use calternal_path::is_not_user_activity
Structs
Section titled “Structs”BlobScrubCorruption
Section titled “BlobScrubCorruption”pub struct BlobScrubCorruptionOne corrupt CAS entry found or repaired by a scrub page.
Fields
pub expected_hash: String: The BLAKE3 digest in the CAS file name.pub actual_hash: String: The BLAKE3 digest of the bytes that were found.pub quarantine_name: String: The quarantine entry used for the bad inode.pub affected_paths: Vec<String>: Home paths that were hardlinks to the bad inode.pub repaired_paths: Vec<String>: Home paths that now link to a verified CAS entry.pub unrepaired_paths: Vec<String>: Home paths that still need recovery.
Implements: Clone, Debug, Eq, PartialEq
Source: crates/calternal-fs/src/blob.rs:19
BlobScrubPage
Section titled “BlobScrubPage”pub struct BlobScrubPageA bounded part of a CAS scan. The cursor is opaque and can be saved between pages, including across server restarts.
Fields
pub checked_blobs: u64: Number of digest-named CAS entries checked on this page.pub bytes_checked: u64: Bytes read while checking and repairing this page.pub cursor: Option<String>: Cursor for the next page, orNonewhen the scrub is complete.pub corruptions: Vec<BlobScrubCorruption>: Corrupt entries found or recovered on this page.
Implements: Clone, Debug, Default, Eq, PartialEq
Source: crates/calternal-fs/src/blob.rs:37
DirectoryWriteProof
Section titled “DirectoryWriteProof”pub struct DirectoryWriteProofA parent directory held across an atomic server write (#1034, DESIGN §54). The handle prevents inode reuse until subscribers finish. Matching the full pre-write token to the Index proves continuity even when another namespace write changes its parent before the asynchronous Index bridge runs.
Implements: Debug, Clone
DirectoryWriteProof::before
Section titled “DirectoryWriteProof::before”pub fn before(&self) -> (&RelPath, FileFingerprint)The confined parent and its token before the server write.
DirectoryWriteProof::still_names_same_directory
Section titled “DirectoryWriteProof::still_names_same_directory”pub fn still_names_same_directory(&self, root: &Root) -> boolA replaced directory never inherits the proof, even with inode reuse. The pinned handle keeps the original inode alive during this comparison.
Source: crates/calternal-fs/src/root.rs:338
DirEntry
Section titled “DirEntry”pub struct DirEntryNo doc comment.
Fields
pub name: Stringpub stat: FileStat
Implements: Debug, Clone
Source: crates/calternal-fs/src/root.rs:379
DirPage
Section titled “DirPage”pub struct DirPageDirectory entries in filesystem order; the opaque cursor can resume a scan. Callers must restart if the directory changes between pages.
Fields
pub entries: Vec<DirEntry>pub next: Option<i64>
Implements: Debug, Clone
Source: crates/calternal-fs/src/root.rs:386
FileFingerprint
Section titled “FileFingerprint”pub struct FileFingerprintKernel identity and change token for an opened item. The Index uses this token to reject stale paths without reading file content on every request.
Fields
pub device: u64pub inode: u64pub size: u64pub modified_seconds: i64pub modified_nanoseconds: i64
Implements: Debug, Clone, Copy, Eq, PartialEq
Source: crates/calternal-fs/src/root.rs:316
FileStat
Section titled “FileStat”pub struct FileStatNo doc comment.
Fields
pub size: u64pub is_dir: boolpub is_file: bool: True only for regular files. Symlinks and special files are false.pub modified_seconds: i64: Last modification time fromstat, in Unix seconds and nanoseconds.pub modified_nanos: u32pub changed_seconds: i64: Last inode change time, used only when the filesystem has no birth time.pub changed_nanos: u32pub links: u64pub created_seconds: Option<i64>: Inode creation time from Linuxstatx, when the filesystem provides it.pub modified: i64: Last modification time in Unix seconds, from the opened inode.
Implements: Debug, Clone
Source: crates/calternal-fs/src/root.rs:251
FsChange
Section titled “FsChange”pub struct FsChangeA durable filesystem change; previous identifies an atomic replacement
so subscribers can preserve an existing item’s identity safely.
Fields
pub path: RelPathpub previous: Option<FileFingerprint>pub directory_write: Option<DirectoryWriteProof>: Only atomic server file writes carry a pinned parent continuity proof (#1034).
Implements: Debug, Clone
Source: crates/calternal-fs/src/root.rs:326
HistoryFile
Section titled “HistoryFile”pub struct HistoryFileHeld history directory and writer lock. All operations use fixed file names.
HistoryFile::len
Section titled “HistoryFile::len”pub fn len(&self) -> Result<u64>Segment length; a history with no committed records has length zero.
HistoryFile::is_empty
Section titled “HistoryFile::is_empty”pub fn is_empty(&self) -> Result<bool>True for an absent or zero-byte segment (#975).
HistoryFile::read_range
Section titled “HistoryFile::read_range”pub fn read_range(&self, offset: u64, len: usize) -> Result<Vec<u8>>Read one bounded range, without allocating from on-disk length fields.
HistoryFile::append
Section titled “HistoryFile::append”pub fn append(&self, bytes: &[u8]) -> Result<u64>Append a complete framed record and sync before acknowledgement. A failed append rolls back its own bytes so later writes cannot hide a torn tail.
HistoryFile::append_reserved
Section titled “HistoryFile::append_reserved”pub fn append_reserved(&self, bytes: &[u8], reservations: &[String]) -> Result<u64>Convert the caller’s queued allowance to real bytes under the shared write lock. Other uploads retain their quota and space claims (#975).
HistoryFile::materialized_etag
Section titled “HistoryFile::materialized_etag”pub fn materialized_etag(&self) -> Result<Option<String>>Read the saved Note hash or old:new save intent. The bounded marker lets recovery tell an unfinished save from a true external edit (§61, #975).
HistoryFile::mark_materialized
Section titled “HistoryFile::mark_materialized”pub fn mark_materialized(&self, etag: &str) -> Result<()>Publish a saved hash, or old:new save intent before file replacement. Both hashes are accepted during crash recovery; successful save reduces the intent to one hash. Quota includes staging (DESIGN §61, #975 review).
HistoryFile::truncate
Section titled “HistoryFile::truncate”pub fn truncate(&self, len: u64) -> Result<()>Drop a verified incomplete final record during recovery (#975).
HistoryFile::replace
Section titled “HistoryFile::replace”pub fn replace(&self, write: impl FnOnce(&mut File) -> std::io::Result<()>) -> Result<()>Atomically replace history after retention. A streaming writer bounds memory for long histories. A crash leaves either the old or new segment.
Source: crates/calternal-fs/src/history.rs:9
HlsDirectory
Section titled “HlsDirectory”pub struct HlsDirectoryA held HLS rendition directory for one content hash and approved profile.
Fields
pub path: PathBuf: Procfs path for trusted callers that already run beside the server.
Source: crates/calternal-fs/src/hls.rs:11
HlsWork
Section titled “HlsWork”pub struct HlsWorkA server-owned sink for one bounded HLS rendition (#779). Progressive playlists follow synced ranges. Until completion, Drop removes every output inode, including any published partial playlist.
Implements: Drop
HlsWork::enable_progressive
Section titled “HlsWork::enable_progressive”pub fn enable_progressive(&mut self, metadata_headroom: u64) -> Result<()>Reserve room for replacing a progressive playlist while a stream grows. Current and new playlist inodes can coexist until atomic rename (#779).
HlsWork::write_stream
Section titled “HlsWork::write_stream”pub fn write_stream(&mut self, bytes: &[u8]) -> Result<()>Consume pipe bytes only while rendition, playlist and disk budgets permit it.
HlsWork::stream_bytes
Section titled “HlsWork::stream_bytes”pub fn stream_bytes(&self) -> u64Number of admitted stream bytes, used to validate playlist byte ranges.
HlsWork::publish_progress
Section titled “HlsWork::publish_progress”pub fn publish_progress(&mut self, playlist: &[u8]) -> Result<()>Atomically publish ranges that the caller validated against written bytes. Each update retains only one current playlist; its replacement temporary also fits inside admission. Duplicate frames do no disk work (#779).
HlsWork::publish
Section titled “HlsWork::publish”pub fn publish(&mut self, playlist: &[u8]) -> Result<()>Publish a complete playlist while retaining cleanup ownership (#779). A failed Index commit must still remove these otherwise uncounted bytes.
HlsWork::retain_indexed
Section titled “HlsWork::retain_indexed”pub fn retain_indexed(&mut self)Transfer cleanup ownership after the completed cache entry is durable. The caller holds its cache admission lock until this work is dropped.
Source: crates/calternal-fs/src/hls.rs:20
PrivatePermissionRepairCounts
Section titled “PrivatePermissionRepairCounts”pub struct PrivatePermissionRepairCountsCount private system-tree permission repairs without exposing paths (#728).
Fields
pub directories: u64: Number of directories changed to mode 0700.pub files: u64: Number of regular files changed to mode 0600.
Implements: Clone, Copy, Debug, Default, Eq, PartialEq
Source: crates/calternal-fs/src/root.rs:27
RelPath
Section titled “RelPath”pub struct RelPath(pub(crate) String);A validated UTF-8 path below a Root; every component is nonempty and safe.
Implements: Clone, Debug, Eq, PartialEq, Hash
RelPath::new
Section titled “RelPath::new”pub fn new(path: impl AsRef<str>) -> Result<Self>No doc comment.
RelPath::as_str
Section titled “RelPath::as_str”pub fn as_str(&self) -> &strNo doc comment.
RelPath::join
Section titled “RelPath::join”pub fn join(&self, child: &str) -> Result<Self>Append a validated relative path without exposing path construction to callers.
RelPath::user_home
Section titled “RelPath::user_home”pub fn user_home(id: &str) -> Result<Self>Resolve the immutable user ID as one component below users.
RelPath::split
Section titled “RelPath::split”pub fn split(&self) -> (&str, &str)Split a validated relative path into its directory and final component.
This lets sibling scanners inspect a component without rebuilding a path.
RelPath validation guarantees the final component is nonempty and that
the directory contains no unsafe components (#420).
Source: crates/calternal-fs/src/path.rs:235
pub struct RootNo doc comment.
Implements: Clone
Root::stat_appledouble
Section titled “Root::stat_appledouble”pub fn stat_appledouble(&self, owner: &str, relative: &str) -> Result<FileStat>Return one Finder companion’s metadata through the confined Home root.
Root::read_appledouble
Section titled “Root::read_appledouble”pub fn read_appledouble(&self, owner: &str, relative: &str) -> Result<File>Open an existing Finder companion only while its visible item exists.
Root::write_appledouble
Section titled “Root::write_appledouble”pub async fn write_appledouble( &self, owner: &str, relative: &str, bytes: &[u8], ) -> Result<WriteResult>Atomically replace one bounded Finder companion in the User’s hidden store. Normal Files Index and Versions do not include this metadata.
Root::delete_appledouble
Section titled “Root::delete_appledouble”pub fn delete_appledouble(&self, owner: &str, relative: &str) -> Result<()>Remove one companion while preserving the visible file or directory.
Root::list_appledouble
Section titled “Root::list_appledouble”pub fn list_appledouble(&self, owner: &str, parent: &str) -> Result<Vec<DirEntry>>List Finder metadata that belongs to the visible files and directory in one Home-relative folder. Hidden names and detached metadata stay out.
Root::copy_directory_appledouble
Section titled “Root::copy_directory_appledouble”pub fn copy_directory_appledouble(&self, from: &RelPath, to: &RelPath) -> Result<()>Copy a folder’s own AppleDouble attributes and Finder view data. The visible destination exists before these confined journal steps. Child files use Root::copy; each resource is capped before publication under the operation lock (#648, review F4).
Root::scrub_blobs_page
Section titled “Root::scrub_blobs_page”pub async fn scrub_blobs_page( &self, cursor: Option<&str>, limit: usize, ) -> Result<BlobScrubPage>Check a bounded number of CAS entries. Call again with the returned
cursor until it is None; a saved cursor can resume after a restart.
The writer lock stops server writes while this page checks and repairs entries. A directory offset keeps each page bounded without loading a whole shard into memory. New CAS entries made while a scrub runs are checked on the next scheduled scrub.
Root::collect_blobs
Section titled “Root::collect_blobs”pub async fn collect_blobs(&self) -> Result<u64>Remove blob entries with no Home path or Version hardlink. Quarantine is excluded because its entries hold damaged inodes while the scrub repairs their Home links or waits for an intact source.
Root::destination_within
Section titled “Root::destination_within”pub fn destination_within(&self, source: &RelPath, target: &RelPath) -> Result<bool>Reject a directory destination beneath the source inode before any write. Comparing ancestor fingerprints also covers paths that have been renamed.
Root::move_path
Section titled “Root::move_path”pub fn move_path(&self, from: &RelPath, to: &RelPath, overwrite: bool) -> Result<()>Move a Home entry and journal its versions and AppleDouble companions with the visible namespace change (#648). Move content and its mirrored Version tree in a journaled operation (#909). Equal paths are a no-op. Reject name collisions, type changes, and a directory target inside the source. Cross-Home moves check quota growth. With overwrite, keep displaced Home content as a Version (DESIGN §2, §11).
Root::copy
Section titled “Root::copy”pub fn copy(&self, from: &RelPath, to: &RelPath, overwrite: bool) -> Result<()>Copy content and its Finder companion under the same operation lock and publication journal, clearing stale destination metadata (#648). Copy one file through a synced temporary entry, then journal its rename (#909; DESIGN §2, §5). Check quota and free space for Home targets. Prefer a reflink when enabled; a verified Blob store inode can instead share a hardlink. The result is read-only. With overwrite, keep displaced Home content as a Version; source history is not copied.
Root::delete
Section titled “Root::delete”pub fn delete(&self, path: &RelPath) -> Result<()>Permanently remove one entry and its hidden Finder metadata in one journal so a deleted file cannot leave a detached companion (#648). Permanently remove an item and its Home Version tree (#909; DESIGN §11). Validate directory depth before deletion and journal both removals. This does not create a Trash entry; use the Trash operation for recovery.
Root::history_file
Section titled “Root::history_file”pub fn history_file(&self, owner: &str, item_id: &str) -> Result<HistoryFile>Resolve a stable item into its owner’s private history directory. The owner ID is one component; only the item’s digest becomes a directory name.
Root::history_exists
Section titled “Root::history_exists”pub fn history_exists(&self, owner: &str, item_id: &str) -> Result<bool>Check a stable history identity without creating a directory. Read-only API requests must not grow the Home with arbitrary IDs (§26, #975 review).
Root::history_usage
Section titled “Root::history_usage”pub fn history_usage(&self, owner: &str) -> Result<u64>Sum persisted history bytes, including fold staging files. This does not create a Home. The collaboration event path adds per-author budgets.
Root::hls_work
Section titled “Root::hls_work”pub fn hls_work(&self, hash: &str, height: u16, limit: u64) -> Result<HlsWork>Admit a fresh rendition before starting its decoder (#779). Incomplete work restarts from the immutable input. Existing completed entries must be checked by the caller before using this constructor.
Root::hls_directory
Section titled “Root::hls_directory”pub fn hls_directory(&self, hash: &str, height: u16) -> Result<HlsDirectory>Create or open a confined HLS rendition directory.
Root::hls_failed
Section titled “Root::hls_failed”pub fn hls_failed(&self, hash: &str, height: u16) -> Result<bool>Return whether a media decoder already failed for this immutable source and rendition profile.
Root::mark_hls_failed
Section titled “Root::mark_hls_failed”pub fn mark_hls_failed(&self, hash: &str, height: u16) -> Result<()>Record a terminal decoder failure in the rendition’s confined cache.
Root::read_hls_file
Section titled “Root::read_hls_file”pub fn read_hls_file(&self, hash: &str, height: u16, name: &str) -> Result<File>Open one validated playlist or segment without following symlinks.
Root::list_hls_files
Section titled “Root::list_hls_files”pub fn list_hls_files(&self, hash: &str, height: u16) -> Result<Vec<DirEntry>>List regular HLS output files in one rendition directory.
Root::remove_hls_directory
Section titled “Root::remove_hls_directory”pub fn remove_hls_directory(&self, hash: &str, height: u16) -> Result<()>Remove one rendition and its files. This only accepts a content hash and one of the two supported profiles, so a cache key cannot select a path in a Home or elsewhere in the data directory.
Root::hls_directory_size
Section titled “Root::hls_directory_size”pub fn hls_directory_size(&self, hash: &str, height: u16) -> Result<u64>Return the bytes held by regular files in one rendition directory.
Root::recover
Section titled “Root::recover”pub fn recover(&self) -> Result<()>Replay unfinished namespace operations before serving requests.
Root::case_insensitive_children
Section titled “Root::case_insensitive_children”pub fn case_insensitive_children(&self, parent: &RelPath, name: &str) -> Result<Vec<RelPath>>Return sibling paths whose NFC Unicode case-folded name matches name.
Files uses this before creating a routed attachment folder so an old
spelling cannot be recreated beside its renamed form (#621).
Root::ensure_name_available
Section titled “Root::ensure_name_available”pub fn ensure_name_available(&self, target: &RelPath, source: Option<&RelPath>) -> Result<()>Check a new sibling name with Unicode full case folding after NFC. Validated internal targets keep their reserved parent (#648); public callers still obtain targets through the public RelPath validator. The optional source is the same inode during a case-only rename.
Every upload and write of a new name runs this check, so its cost is
one raw directory read: no stat per entry, no sort and no fold of
an ASCII name beyond a byte compare. Only an entry whose folded name
matches is looked at further. A list here made each upload into a
large folder cost one stat per sibling (#122).
Root::active_hls_bytes
Section titled “Root::active_hls_bytes”pub fn active_hls_bytes(&self) -> u64Full active rendition budgets, including bytes already written (#779). Admission uses this with completed cache entries under Video’s cache lock.
Root::available_disk_bytes
Section titled “Root::available_disk_bytes”pub fn available_disk_bytes(&self) -> Result<u64>Bytes the filesystem currently reports as available to this process.
Root::quota_limit
Section titled “Root::quota_limit”pub fn quota_limit(&self, home: &RelPath) -> Result<Option<u64>>Return the current server-configured limit for a Home, if any.
Root::recompute_quota
Section titled “Root::recompute_quota”pub fn recompute_quota(&self, home: &RelPath) -> Result<u64>Recompute Home usage, including Versions and Trash but excluding the separately capped AppleDouble store, without collapsing hardlinks.
Root::set_quota
Section titled “Root::set_quota”pub fn set_quota(&self, home: &RelPath, limit: u64) -> Result<()>Configure a home’s logical limit for writes, copies, and moves.
Root::clear_quota
Section titled “Root::clear_quota”pub fn clear_quota(&self, home: &RelPath) -> Result<()>Remove a server-managed home limit when the instance default is unlimited.
Root::reserve_upload
Section titled “Root::reserve_upload”pub fn reserve_upload(&self, id: &str, home: &RelPath, bytes: u64) -> Result<()>Reserve a Tus upload’s declared size before its first chunk is written. The reservation protects quota for the full upload and disk space for its not-yet-received bytes. The operation lock makes it atomic with every quota-aware Home write.
Root::restore_upload_reservation
Section titled “Root::restore_upload_reservation”pub fn restore_upload_reservation( &self, id: &str, home: &RelPath, length: u64, offset: u64, ) -> Result<()>Restore an active upload reservation from its durable Files row. Existing uploads remain resumable even when their Home is now over its limit or the host has consumed part of the protected free space.
Root::update_upload_progress
Section titled “Root::update_upload_progress”pub fn update_upload_progress(&self, id: &str, offset: u64) -> Result<()>Move received chunk bytes from future disk use into actual filesystem use. Quota stays reserved until finalization removes the upload row.
Root::release_upload_reservation
Section titled “Root::release_upload_reservation”pub fn release_upload_reservation(&self, id: &str)Release an upload reservation after its durable row is removed.
Root::open
Section titled “Root::open”pub fn open(path: &Path, prefer_reflink: bool) -> Result<Self>Open one directory for both user data and instance state.
This preserves the original single-directory layout. Use
Root::open_split when Homes and the Blob store need a separate
filesystem from .system/.
Root::open_split
Section titled “Root::open_split”pub fn open_split( instance_data: &Path, user_data: &Path, prefer_reflink: bool, ) -> Result<Self>Open the user-data root and the instance-state root separately.
Public paths, Homes, Groups and .cas/ resolve below user_data.
Only the fixed internal .system/ path resolves below
instance_data. Both roots must already exist and are held with
directory handles for the lifetime of this value.
Root::prepare_user_data
Section titled “Root::prepare_user_data”pub fn prepare_user_data(&self) -> Result<()>Create the fixed user-data roots, confirm CAS link compatibility, and verify that the server can make and sync an atomic write under Homes.
Root::subscribe_changes
Section titled “Root::subscribe_changes”pub fn subscribe_changes(&self) -> tokio::sync::broadcast::Receiver<FsChange>Subscribe to durable path changes made through any handle for this data directory.
Root::lock_mutation
Section titled “Root::lock_mutation”pub async fn lock_mutation(&self) -> tokio::sync::MutexGuard<'_, ()>Serialize a caller’s Index intent, namespace mutation, and Index completion across all handles for this data directory.
Root::lock_user_settings
Section titled “Root::lock_user_settings”pub async fn lock_user_settings(&self, user: &str) -> tokio::sync::OwnedMutexGuard<()>Lock the in-memory merge step for one User’s settings file.
Callers must drop this guard before writing to disk. The settings
helper uses write_checked after the merge, so a concurrent write can be
retried without holding a per-User lock across fsync or other I/O.
Root::system_directory
Section titled “Root::system_directory”pub fn system_directory(&self, child: Option<&str>) -> Result<File>Open the reserved system directory for the server’s Index and snapshots. New and existing directories in this namespace use mode 0700 (#728). The caller must keep the returned handle alive while using its procfs path.
Root::repair_private_system_storage
Section titled “Root::repair_private_system_storage”pub fn repair_private_system_storage(&self) -> Result<PrivatePermissionRepairCounts>Repair writable server data below .system at process startup.
The Index, snapshots and derived caches contain private User or
Instance data. Walk from the held system root, reject links and special
files, and set directories to 0700 and regular files to 0600. Exclude
the external secrets directory: deployment mounts it read-only, and
read_system_secret_file plus the signing loader validate its files.
The private .system boundary still encloses that mount. Return
counts only so the caller can log the repair without a path (#728,
DESIGN §2).
Root::ensure_private_system_file
Section titled “Root::ensure_private_system_file”pub fn ensure_private_system_file(&self, name: &str) -> Result<bool>Create or repair one fixed-name SQLite file under .system.
Precreating SQLite’s Index with mode 0600 makes SQLite’s WAL and
rollback journal inherit a private mode. fchmod removes any umask or
SQLite default-mode dependence. The name must be one path component
(#728, DESIGN §2).
Root::harden_private_backup_file
Section titled “Root::harden_private_backup_file”pub fn harden_private_backup_file(&self, name: &str) -> Result<bool>Set one completed snapshot file to mode 0600 below .system/backups.
SQLite creates the file used by VACUUM INTO; the containing directory
is already private, so this handle-relative repair closes the final
permission gap before the snapshot is exposed to backup readers (#728).
Root::search_index_directory
Section titled “Root::search_index_directory”pub fn search_index_directory(&self) -> Result<File>Open the private directory for the rebuildable Tantivy index.
The returned handle stays open while Tantivy uses its procfs path. The fixed internal path keeps index files out of every Home and prevents a caller from selecting a path with user input.
Root::lock_search_index_startup
Section titled “Root::lock_search_index_startup”pub fn lock_search_index_startup(&self) -> Result<SearchIndexStartupLock>Lock Search Index startup and hold its directory through writer open.
Each server takes this gate before probing Tantivy’s active writer lock. This makes stale-lock recovery safe when two servers start together. Issue #505 adds the gate around the lock probe and writer claim.
Root::lock_user_search_index_startup
Section titled “Root::lock_user_search_index_startup”pub fn lock_user_search_index_startup(&self, user_id: &str) -> Result<SearchIndexStartupLock>Lock startup for one private User Index. Its gate shares the validated User directory with the Index, so recovery cannot cross User boundaries. Issue #505 applies the same recovery rule to per-User writers.
Root::user_search_index_directory
Section titled “Root::user_search_index_directory”pub fn user_search_index_directory(&self, user_id: &str) -> Result<File>Open one User’s private derived Search directory below the server-owned
Index area. The validated User component is joined through InternalPath;
callers cannot select another User’s directory with a path fragment.
Root::user_vector_index_directory
Section titled “Root::user_vector_index_directory”pub fn user_vector_index_directory(&self, user_id: &str) -> Result<File>Open one User’s derived SQLite directory beside their Search Index.
Issue #435 keeps vector files physically separate. A validated single
User component and a fixed leaf confine all access below .system.
Root::user_search_index_staging_directory
Section titled “Root::user_search_index_staging_directory”pub fn user_search_index_staging_directory(&self, user_id: &str) -> Result<File>Open the private staging generation for one User’s Search rebuild.
Root::clear_user_search_index_directory
Section titled “Root::clear_user_search_index_directory”pub fn clear_user_search_index_directory(&self, user_id: &str) -> Result<()>Clear only this User’s active derived Search generation.
Root::clear_user_search_index_staging_directory
Section titled “Root::clear_user_search_index_staging_directory”pub fn clear_user_search_index_staging_directory(&self, user_id: &str) -> Result<()>Clear only this User’s staging generation before a rebuild.
Root::publish_user_search_index_staging
Section titled “Root::publish_user_search_index_staging”pub fn publish_user_search_index_staging(&self, user_id: &str) -> Result<()>Exchange complete per-User generations without exposing a partial Index.
Root::user_search_index_ready
Section titled “Root::user_search_index_ready”pub fn user_search_index_ready(&self, user_id: &str) -> Result<bool>A User reads a private generation only after its complete rebuild was published. The versioned one-byte marker survives a server restart (#1044).
Root::mark_user_search_index_ready
Section titled “Root::mark_user_search_index_ready”pub fn mark_user_search_index_ready(&self, user_id: &str) -> Result<()>Publish the current analyzer version after the active Search generation exists (#1044).
Root::clear_user_search_index_ready
Section titled “Root::clear_user_search_index_ready”pub fn clear_user_search_index_ready(&self, user_id: &str) -> Result<()>Stop private reads after a failed update. The shared migration Index remains available until the next complete per-User rebuild.
Root::search_index_staging_directory
Section titled “Root::search_index_staging_directory”pub fn search_index_staging_directory(&self) -> Result<File>Open the fixed staging directory for an atomic Tantivy rebuild.
This directory is a sibling of the active Index. Its name is constant and never comes from a request or a filesystem event.
Root::photos_clip_index_directory
Section titled “Root::photos_clip_index_directory”pub fn photos_clip_index_directory(&self) -> Result<File>Open the private rebuildable photo CLIP index directory.
Callers keep this handle open while SQLite uses a fixed file beneath its procfs descriptor path. The directory is never visible in a Home.
Root::clear_search_index_directory
Section titled “Root::clear_search_index_directory”pub fn clear_search_index_directory(&self) -> Result<()>Remove files from the server-owned Tantivy directory before a schema rebuild. Tantivy indexes are derived data; clearing this fixed private directory lets a schema change trigger a rebuild from the Data tree.
Root::clear_search_index_staging_directory
Section titled “Root::clear_search_index_staging_directory”pub fn clear_search_index_staging_directory(&self) -> Result<()>Remove the old generation from the staging directory before a rebuild.
Root::publish_search_index_staging
Section titled “Root::publish_search_index_staging”pub fn publish_search_index_staging(&self) -> Result<()>Atomically publish the completed staged Index and keep the prior generation at the fixed staging name until the next rebuild.
Root::read_system_config
Section titled “Root::read_system_config”pub fn read_system_config(&self) -> Result<Vec<u8>>Read the server-owned instance configuration without exposing .system
through user-facing relative paths.
Root::read_system_secret_file
Section titled “Root::read_system_secret_file”pub fn read_system_secret_file(&self, path: &RelPath) -> Result<SystemSecretFile>Read one bounded regular file below .system/secrets/ without leaving
the held instance directory. The returned mode lets callers reject a
key that other Users on the host could read.
Root::write_system_config
Section titled “Root::write_system_config”pub fn write_system_config(&self, bytes: &[u8]) -> Result<()>Atomically replace the instance configuration with private permissions.
Root::read_system_dedup_scrub_state
Section titled “Root::read_system_dedup_scrub_state”pub fn read_system_dedup_scrub_state(&self) -> Result<Vec<u8>>Read the server-owned, resumable CAS scrub checkpoint. The caller owns its serialization format; Root only provides confined, bounded I/O.
Root::write_system_dedup_scrub_state
Section titled “Root::write_system_dedup_scrub_state”pub fn write_system_dedup_scrub_state(&self, bytes: &[u8]) -> Result<()>Atomically persist a scrub checkpoint with private permissions. A checkpoint is replaced only after its complete contents reach disk.
Root::read_system_secret_key
Section titled “Root::read_system_secret_key”pub fn read_system_secret_key(&self) -> Result<Option<[u8; 32]>>Read the instance secret key from the reserved system directory.
The key is a fixed-size binary value. A missing file is distinct from an unreadable or malformed file so startup can create it only once.
Root::write_system_secret_key
Section titled “Root::write_system_secret_key”pub fn write_system_secret_key(&self, key: &[u8; 32]) -> Result<()>Atomically install an instance secret key without replacing an existing key.
A no-replace rename lets concurrent first starts race safely. The
caller reads the winning key after Exists; it must never overwrite a
key that may already protect Security state.
Root::open_search_model_assets
Section titled “Root::open_search_model_assets”pub fn open_search_model_assets(&self) -> Result<Option<(File, File)>>Open the pinned semantic model and tokenizer from the private system tree.
The returned files stay anchored below this Root. Callers must keep both handles alive while they read them or load the model.
Root::write_search_model_assets
Section titled “Root::write_search_model_assets”pub fn write_search_model_assets(&self, model: &[u8], tokenizer: &[u8]) -> Result<()>Install the verified semantic model and tokenizer with atomic file replaces.
The model manifest pins both hashes. This method accepts bytes only after the caller verifies them, and it never accepts a caller-selected path.
Root::open_photo_clip_model_assets
Section titled “Root::open_photo_clip_model_assets”pub fn open_photo_clip_model_assets(&self) -> Result<Option<(File, File, File)>>Open the fixed CLIP model files beneath the held data-directory handle.
Root::write_photo_clip_model_assets
Section titled “Root::write_photo_clip_model_assets”pub fn write_photo_clip_model_assets( &self, text_model: &[u8], vision_model: &[u8], tokenizer: &[u8], ) -> Result<()>Atomically install verified CLIP files under their fixed private names.
Root::open_voice_model_download
Section titled “Root::open_voice_model_download”pub fn open_voice_model_download(&self, asset: VoiceModelAsset) -> Result<File>Open a fixed voice-model staging file for a resumable download.
The .part file is intentionally private and is not returned by the
final-asset API. The downloader seeks to its current length before
appending the next verified range.
Root::open_voice_model_asset
Section titled “Root::open_voice_model_asset”pub fn open_voice_model_asset(&self, asset: VoiceModelAsset) -> Result<Option<File>>Open one installed voice-model asset, if it has been published.
Root::publish_voice_model_download
Section titled “Root::publish_voice_model_download”pub fn publish_voice_model_download(&self, asset: VoiceModelAsset) -> Result<()>Publish a completed voice asset with an atomic rename and directory sync.
The caller verifies size and digest before publishing. The final name can never refer to a partially downloaded file.
Root::write_voice_recording
Section titled “Root::write_voice_recording”pub fn write_voice_recording( &self, user_id: [u8; 16], id: [u8; 16], format: VoiceAudioFormat, bytes: &[u8], ) -> Result<()>Store one bounded recording in its User’s private derived Voice store.
Audio does not enter the visible Home. Both path components are fixed
size IDs generated by the server, then resolved below .system (#619).
Root::open_voice_recording
Section titled “Root::open_voice_recording”pub fn open_voice_recording( &self, user_id: [u8; 16], id: [u8; 16], format: VoiceAudioFormat, ) -> Result<File>Open one User’s stored recording by opaque ID and fixed media format.
Root::remove_voice_recording
Section titled “Root::remove_voice_recording”pub fn remove_voice_recording( &self, user_id: [u8; 16], id: [u8; 16], format: VoiceAudioFormat, ) -> Result<()>Remove one User’s temporary recording after its Job finishes.
Root::write_voice_transcript
Section titled “Root::write_voice_transcript”pub fn write_voice_transcript( &self, user_id: [u8; 16], id: [u8; 16], text: &str, ) -> Result<()>Save a bounded result in its User’s private store beneath the Job ID.
Root::read_voice_transcript
Section titled “Root::read_voice_transcript”pub fn read_voice_transcript(&self, user_id: [u8; 16], id: [u8; 16]) -> Result<Option<String>>Read one User’s result by its opaque queue Job ID.
Root::remove_voice_transcript
Section titled “Root::remove_voice_transcript”pub fn remove_voice_transcript(&self, user_id: [u8; 16], id: [u8; 16]) -> Result<()>Remove one User’s result after it expires or the User is deleted.
Root::prune_voice_transcripts
Section titled “Root::prune_voice_transcripts”pub fn prune_voice_transcripts( &self, user_id: [u8; 16], max_age_seconds: u64, ) -> Result<usize>Remove one User’s results older than a bounded retention window. Only server-generated Job filenames are considered; cache files use a separate directory and survive until the User is deleted (#619).
Root::read_voice_transcript_cache
Section titled “Root::read_voice_transcript_cache”pub fn read_voice_transcript_cache( &self, user_id: [u8; 16], audio_hash: [u8; 32], ) -> Result<Option<String>>Read the exact-audio transcript cache from the owning User’s derived store.
Root::write_voice_transcript_cache
Section titled “Root::write_voice_transcript_cache”pub fn write_voice_transcript_cache( &self, user_id: [u8; 16], audio_hash: [u8; 32], text: &str, ) -> Result<()>Atomically persist one transcript cache in its User’s derived store.
Root::prune_orphan_voice_recordings
Section titled “Root::prune_orphan_voice_recordings”pub fn prune_orphan_voice_recordings( &self, user_id: [u8; 16], live_ids: &[[u8; 16]], ) -> Result<usize>Remove staged recordings that have no pending or leased Job.
Callers hold the User mutation lock while they collect live_ids and
run the sweep, so a new file cannot race its queue insert (#619).
Root::purge_user_voice_data
Section titled “Root::purge_user_voice_data”pub fn purge_user_voice_data(&self, user_id: [u8; 16]) -> Result<()>Delete all private Voice results, recordings and hash cache for a User. DESIGN §48 requires derived speech text to leave with its owning User.
Root::list_system_backups
Section titled “Root::list_system_backups”pub fn list_system_backups(&self) -> Result<Vec<String>>Return snapshot filenames from the private backup directory.
Root::probe_system_writable
Section titled “Root::probe_system_writable”pub fn probe_system_writable(&self) -> Result<()>Check that the data directory can accept an atomic server write.
Root::stat
Section titled “Root::stat”pub fn stat(&self, path: &RelPath) -> Result<FileStat>No doc comment.
Root::fingerprint
Section titled “Root::fingerprint”pub fn fingerprint(&self, path: &RelPath) -> Result<FileFingerprint>No doc comment.
Root::read
Section titled “Root::read”pub fn read(&self, path: &RelPath) -> Result<File>No doc comment.
Root::read_all
Section titled “Root::read_all”pub fn read_all(&self, path: &RelPath) -> Result<Vec<u8>>No doc comment.
Root::list
Section titled “Root::list”pub fn list(&self, path: Option<&RelPath>) -> Result<impl Iterator<Item = Result<DirEntry>>>No doc comment.
Root::list_utf8
Section titled “Root::list_utf8”pub fn list_utf8( &self, path: Option<&RelPath>, ) -> Result<impl Iterator<Item = Result<DirEntry>>>List entries with UTF-8 names and skip names that are not UTF-8.
Whole-Home rebuilds use this so one unaddressable name cannot hide
valid sibling Notes; ordinary listings keep the strict list contract (#724).
Root::list_page
Section titled “Root::list_page”pub fn list_page( &self, path: Option<&RelPath>, after: Option<i64>, limit: usize, ) -> Result<DirPage>Read a directory page in filesystem order through its handle (#909).
The positive limit counts visible entries; reserved paths are skipped.
after is an opaque directory offset, not a sorted-name cursor. A full
page returns its last offset even if no more entries remain. Changes
between calls can affect pagination; this is not a snapshot (DESIGN §2).
Root::mkdir_p
Section titled “Root::mkdir_p”pub fn mkdir_p(&self, path: &RelPath) -> Result<()>No doc comment.
Root::remove_empty_user_dir
Section titled “Root::remove_empty_user_dir”pub fn remove_empty_user_dir(&self, owner: &str, path: &RelPath) -> Result<()>Remove one empty directory under the named User’s Home using its held
parent directory. Issue #422 uses this after moving legacy backgrounds;
the owner check blocks cross-Home deletion and REMOVEDIR rejects races.
Root::sidecars_for
Section titled “Root::sidecars_for”pub fn sidecars_for(&self, parent: &RelPath) -> Result<Vec<SidecarFile>>Find sidecar files for a regular file using names in its own directory.
The directory scan runs through this Root’s held handle. A sidecar is returned only when one regular sibling matches; links, directories, special files and ambiguous names remain independent entries.
Root::scratch_file
Section titled “Root::scratch_file”pub fn scratch_file(&self) -> Result<ScratchFile>Create a private 0600 file below the held instance-state root.
openat2 creates a random name below a held directory handle. Drop
unlinks it by name relative to that same handle. The native consumer
receives only the descriptor-relative proc-fd path (#462, DESIGN §48).
Root::thumbnail_temp
Section titled “Root::thumbnail_temp”pub fn thumbnail_temp(&self) -> Result<ThumbnailTemp>Create a registered cache temporary with a held parent and WebP suffix.
Recovery must not unlink a renderer result before it is published (#802).
Create a private thumbnail cache file under .system (#728).
Root::write_thumbnail
Section titled “Root::write_thumbnail”pub fn write_thumbnail(&self, temp: &mut ThumbnailTemp, bytes: &[u8]) -> Result<()>Write one bounded WebP returned by the isolated decoder to a held file.
Root::publish_thumbnail
Section titled “Root::publish_thumbnail”pub fn publish_thumbnail(&self, temp: ThumbnailTemp, hash: &str, size: u32) -> Result<()>Publish a media thumbnail under the historical cache name.
Root::publish_thumbnail_for
Section titled “Root::publish_thumbnail_for”pub fn publish_thumbnail_for( &self, temp: ThumbnailTemp, hash: &str, size: u32, kind: ThumbnailKind, ) -> Result<()>Publish a bounded WebP to its renderer-specific cache family. Sync and atomically publish one WebP while its guard owns failure cleanup (#802).
Root::discard_thumbnail
Section titled “Root::discard_thumbnail”pub fn discard_thumbnail(&self, temp: ThumbnailTemp) -> Result<()>Unlink an unused thumbnail; its guard retries cleanup if this call fails (#802).
Root::thumbnail_failed
Section titled “Root::thumbnail_failed”pub fn thumbnail_failed(&self, hash: &str) -> Result<bool>Return whether media bytes have a current terminal decoder failure.
Root::thumbnail_failed_for
Section titled “Root::thumbnail_failed_for”pub fn thumbnail_failed_for(&self, hash: &str, kind: ThumbnailKind) -> Result<bool>Return whether this renderer family has a terminal decoder failure.
Root::clear_thumbnail_failed_for
Section titled “Root::clear_thumbnail_failed_for”pub fn clear_thumbnail_failed_for(&self, hash: &str, kind: ThumbnailKind) -> Result<()>Remove one renderer’s terminal marker when the Index selects a new renderer for the same bytes. Markers are derived state and must not survive a corrected MIME projection (#851).
Root::mark_thumbnail_failed
Section titled “Root::mark_thumbnail_failed”pub fn mark_thumbnail_failed(&self, hash: &str) -> Result<()>Cache a versioned terminal media failure so page views do not restart a decoder for the same immutable hostile or unsupported bytes.
Root::mark_thumbnail_failed_for
Section titled “Root::mark_thumbnail_failed_for”pub fn mark_thumbnail_failed_for(&self, hash: &str, kind: ThumbnailKind) -> Result<()>Cache a terminal failure only for the renderer family that failed.
Root::read_thumbnail
Section titled “Root::read_thumbnail”pub fn read_thumbnail(&self, hash: &str, size: u32) -> Result<File>Read a media thumbnail from its backwards-compatible cache name.
Root::read_thumbnail_for
Section titled “Root::read_thumbnail_for”pub fn read_thumbnail_for(&self, hash: &str, size: u32, kind: ThumbnailKind) -> Result<File>Read a thumbnail from the selected renderer-specific cache family.
Root::media_snapshot_input
Section titled “Root::media_snapshot_input”pub fn media_snapshot_input(&self, source: &File, maximum_bytes: u64) -> Result<File>Make one bounded decoder snapshot (#501 / DESIGN §39). Inputs up to
MEDIA_MEMFD_LIMIT_BYTES stay in a sealed memfd. Larger inputs use an
anonymous on-disk file in the Home filesystem, with a read-only descriptor
passed to the decoder. The source inode never reaches a native tool.
Root::list_trash
Section titled “Root::list_trash”pub fn list_trash(&self, home: &RelPath) -> Result<Vec<DirEntry>>List the names needed to restore entries in one Home’s Trash.
Root::trash
Section titled “Root::trash”pub fn trash(&self, path: &RelPath) -> Result<String>Move a Home item and its Finder companion into freedesktop Trash, returning the unique name used by restore (#648).
Root::trash_original
Section titled “Root::trash_original”pub fn trash_original(&self, home: &RelPath, name: &str) -> Result<RelPath>Read the original path from a freedesktop Trash info file.
Root::trash_fingerprint
Section titled “Root::trash_fingerprint”pub fn trash_fingerprint(&self, home: &RelPath, name: &str) -> Result<FileFingerprint>Identify the item still held in Trash for Index recovery.
Root::read_trash
Section titled “Root::read_trash”pub fn read_trash(&self, home: &RelPath, name: &str) -> Result<File>Open one Trash entry’s bytes for a caller that must verify its content
before restore (saved-search Undo, issue #758). The name is checked
by trash_original, so only a journaled entry of this Home can open.
Callers bound the read themselves; this returns the open file only.
Root::restore
Section titled “Root::restore”pub fn restore(&self, home: &RelPath, name: &str) -> Result<RelPath>Restore a Trash item and its hidden Finder metadata to the original path.
Restore the Trash item to the path recorded in its .trashinfo (#909).
Reject occupied content or Version destinations. Journal the content
and archived Version-tree moves with removal of the info file, then
return the restored path. Destination parents must exist (DESIGN §11).
Root::empty_trash
Section titled “Root::empty_trash”pub fn empty_trash(&self, home: &RelPath) -> Result<()>Empty Trash and its mirrored Finder metadata without following symlinks.
Root::upload_ids
Section titled “Root::upload_ids”pub fn upload_ids(&self) -> Result<Vec<String>>List on-disk staging IDs so the Index can remove uploads with no row.
Root::write_upload_chunk
Section titled “Root::write_upload_chunk”pub fn write_upload_chunk(&self, id: &str, offset: u64, bytes: &[u8]) -> Result<()>Write one immutable tus chunk at an offset. Repeating an offset safely replaces a chunk left by a crash before the Index offset advanced.
Root::read_upload_chunk
Section titled “Root::read_upload_chunk”pub fn read_upload_chunk(&self, id: &str, offset: u64) -> Result<File>No doc comment.
Root::remove_upload
Section titled “Root::remove_upload”pub fn remove_upload(&self, id: &str) -> Result<()>No doc comment.
Root::stage_user_home
Section titled “Root::stage_user_home”pub fn stage_user_home(&self, user_id: [u8; 16]) -> Result<()>Move one Home out of the live tree with one journalled rename.
The caller first records the deletion intent in Security state. This move then makes the Home unavailable to normal requests while keeping every byte in the same filesystem for the background policy action. The source and destination checks make retries safe after a crash.
Root::archive_user_home
Section titled “Root::archive_user_home”pub fn archive_user_home(&self, user_id: [u8; 16], expires_at: i64) -> Result<UserHomeArchive>Move one Home into the admin archive and return its fixed expiry. Repeating this call for the same user returns the existing archive so a server restart cannot extend the retention period.
Root::archive_staged_user_home
Section titled “Root::archive_staged_user_home”pub fn archive_staged_user_home( &self, user_id: [u8; 16], expires_at: i64, ) -> Result<UserHomeArchive>Move one staged Home into the archive, or create its empty marker when the user had no Home. Repeating this after a crash does not create a second archive or extend the retention period.
Root::transfer_user_home
Section titled “Root::transfer_user_home”pub fn transfer_user_home( &self, source_user_id: [u8; 16], target_user_id: [u8; 16], transfer_id: [u8; 16], ) -> Result<RelPath>Put the complete source Home in one collision-free folder in the target Home. This preserves every filename and hierarchy without overwriting the recipient’s existing files.
Root::transfer_staged_user_home
Section titled “Root::transfer_staged_user_home”pub fn transfer_staged_user_home( &self, source_user_id: [u8; 16], target_user_id: [u8; 16], transfer_id: [u8; 16], ) -> Result<RelPath>Move one staged Home into a collision-resistant folder in the target Home. The destination is unique to this durable deletion intent. This is an admin transfer, so it preserves the source even if its logical size puts the target over quota; normal writes enforce the target quota.
Root::purge_user_home
Section titled “Root::purge_user_home”pub fn purge_user_home(&self, user_id: [u8; 16]) -> Result<()>Permanently remove one Home. Missing Homes are already purged.
Root::purge_staged_user_home
Section titled “Root::purge_staged_user_home”pub fn purge_staged_user_home(&self, user_id: [u8; 16]) -> Result<()>Permanently remove one staged Home. The journal records the recursive removal, so recovery can resume after any unlink without touching any live Home.
Root::purge_user_search_index
Section titled “Root::purge_user_search_index”pub fn purge_user_search_index(&self, user_id: [u8; 16]) -> Result<()>Remove Derived Search data after any account deletion policy. Archives retain the Home, but do not retain a queryable Index for a deleted User.
Root::list_user_archives
Section titled “Root::list_user_archives”pub fn list_user_archives(&self) -> Result<Vec<UserHomeArchive>>List valid archive markers without exposing the reserved system path.
Root::purge_expired_user_archives
Section titled “Root::purge_expired_user_archives”pub fn purge_expired_user_archives(&self, now: i64) -> Result<usize>Purge expired archive folders. Their expiry is encoded in the folder name, so this sweep resumes safely after any server restart.
Root::list_versions
Section titled “Root::list_versions”pub fn list_versions(&self, path: &RelPath) -> Result<Vec<DirEntry>>List previous content by version name for a file in a Home.
Root::read_version
Section titled “Root::read_version”pub fn read_version(&self, path: &RelPath, name: &str) -> Result<File>Open immutable previous content using the same handle-relative checks.
Root::restore_version
Section titled “Root::restore_version”pub async fn restore_version(&self, path: &RelPath, name: &str) -> Result<WriteResult>Restore previous content through the normal atomic Replace path.
Root::thin_versions
Section titled “Root::thin_versions”pub fn thin_versions(&self, path: &RelPath, now: i64) -> Result<u64>Apply the pure retention policy to a file’s versions and return the number removed. The caller schedules this outside interactive writes.
Root::retain_web_asset_generation
Section titled “Root::retain_web_asset_generation”pub fn retain_web_asset_generation( &self, version_json: &[u8], assets: &[(&str, &[u8])], now: SystemTime, ) -> Result<WebAssetStoreStats>Retain one generated frontend build under the persistent instance data.
version_json gives the deployment a stable identity. Asset routes
must be SvelteKit immutable routes. The method keeps the last ten builds
and every build no more than seven days old, and fails before commit if
the bounded store would exceed one GiB (#423).
Root::read_retained_web_asset
Section titled “Root::read_retained_web_asset”pub fn read_retained_web_asset(&self, url_path: &str) -> Result<File>Open one retained immutable route using a validated URL path.
URL text is never joined to a filesystem path. Its checked route digest
selects a flat name below .system/web-assets/assets/; invalid and
missing routes both return NotFound so the HTTP layer can answer 404
without exposing the store layout (#423).
Root::web_asset_store_stats
Section titled “Root::web_asset_store_stats”pub fn web_asset_store_stats(&self) -> Result<WebAssetStoreStats>Return bounded counts and physical bytes for the retained store (#423).
Root::write_new_file_at_root
Section titled “Root::write_new_file_at_root”pub fn write_new_file_at_root(&self, name: &RelPath, bytes: &[u8]) -> Result<()>Create one private file directly under this held directory handle.
This is for explicit exports such as a CLI attachment download. It
does not add the file to a Home or the content-addressed store. A
single component keeps the destination anchored to this handle, and
openat2 rejects symlinks and traversal before creating the file.
Root::replace_if
Section titled “Root::replace_if”pub async fn replace_if<R: AsyncRead + Unpin>( &self, path: &RelPath, expected_blake3: &str, input: R, quota: Option<u64>, ) -> Result<WriteResult>Replace only when the current bytes still match the expected BLAKE3 digest. The comparison and versioned installation share the writer lock.
Root::replace_live_if
Section titled “Root::replace_live_if”pub async fn replace_live_if<R: AsyncRead + Unpin>( &self, path: &RelPath, expected_blake3: &str, input: R, quota: Option<u64>, ) -> Result<WriteResult>Checked replace for a live document whose prior edits are already durable in collaboration history. All atomic-write and quota rules still apply (§61).
Root::replace_if_preserving_mtime
Section titled “Root::replace_if_preserving_mtime”pub async fn replace_if_preserving_mtime<R: AsyncRead + Unpin>( &self, path: &RelPath, expected_blake3: &str, input: R, source_identity: FileFingerprint, ) -> Result<WriteResult>Preserve the verified source mtime while adding migration metadata. Digest and inode checks share the writer lock. Set the time on the private staged fd before publication; never reopen the destination for metadata changes (DESIGN §2, #1148). External writers remain outside the server’s exclusive-writer contract.
Root::write
Section titled “Root::write”pub async fn write<R: AsyncRead + Unpin>( &self, path: &RelPath, input: R, mode: WriteMode, quota: Option<u64>, ) -> Result<WriteResult>No doc comment.
Root::write_with_mtime
Section titled “Root::write_with_mtime”pub async fn write_with_mtime<R: AsyncRead + Unpin>( &self, path: &RelPath, input: R, mode: WriteMode, quota: Option<u64>, modified: SystemTime, ) -> Result<WriteResult>Write a file with a caller-provided source mtime before it is visible.
This uses a private inode instead of the shared content-addressed blob: two files with equal bytes can have different source mtimes, and changing a shared inode’s timestamp would change both files.
Root::write_checked
Section titled “Root::write_checked”pub async fn write_checked<R: AsyncRead + Unpin>( &self, path: &RelPath, input: R, mode: WriteMode, quota: Option<u64>, expected_blake3: Option<&str>, modified: Option<SystemTime>, ) -> Result<WriteResult>The general form of Root::write, Root::replace_if and
current bytes (checked under the writer lock, like replace_if) and an
optional source mtime. A Files upload that replaces a known revision
uses it, so a write that lands after the upload’s check is never
overwritten (#98).
Root::write_checked_reserved
Section titled “Root::write_checked_reserved”pub async fn write_checked_reserved<R: AsyncRead + Unpin>( &self, path: &RelPath, input: R, mode: WriteMode, quota: Option<u64>, conditions: WriteConditions<'_>, ) -> Result<WriteResult>Install an upload while exchanging its durable quota reservation for the new Home bytes. Other writers continue to count that reservation until the upload row and its staging files are removed.
Source: crates/calternal-fs/src/root.rs:392
ScratchFile
Section titled “ScratchFile”pub struct ScratchFileA private file for a native reader that needs a seekable path.
The file has a random internal name and mode 0600. Drop consumers before
this value so the native reader closes before cleanup. The proc-fd path is
process-local and must not escape the operation that created it.
Implements: Drop
ScratchFile::path
Section titled “ScratchFile::path”pub fn path(&self) -> &PathReturn the process-local path for a native library that only accepts a filename. It refers to this already-open unnamed inode.
ScratchFile::file_mut
Section titled “ScratchFile::file_mut”pub fn file_mut(&mut self) -> &mut FileReturn the opened file for bounded streaming writes or reads.
Source: crates/calternal-fs/src/temp_file.rs:14
SearchIndexStartupLock
Section titled “SearchIndexStartupLock”pub struct SearchIndexStartupLockStartup gate for opening one Tantivy Search Index.
Keep this value alive while checking the writer lock and creating the writer. The gate serializes server starts, so a stale lock entry cannot be removed while another calternal process is opening the same Index. Issue #505 adds this gate because Tantivy’s lock file can remain after a crash.
SearchIndexStartupLock::clear_unlocked_writer_lock
Section titled “SearchIndexStartupLock::clear_unlocked_writer_lock”pub fn clear_unlocked_writer_lock(&self) -> Result<bool>Remove the fixed writer-lock entry only when its OS lock is not held.
Tantivy uses an advisory lock on this file. Its name can remain after a process exits, so the name alone cannot prove that a writer is stale. The caller must keep this startup gate alive until writer creation. Issue #505 requires recovery to preserve a live writer’s lock.
Source: crates/calternal-fs/src/root.rs:48
SidecarFile
Section titled “SidecarFile”pub struct SidecarFileA validated sidecar path and its standard naming form.
Fields
pub path: RelPath: Path relative to the held data directory.pub kind: SidecarKind: Filename form used by this sidecar.
Implements: Clone, Debug, Eq, PartialEq
Source: crates/calternal-fs/src/sidecar.rs:60
SidecarPair
Section titled “SidecarPair”pub struct SidecarPair<'a>A sidecar and the one regular sibling that it matches.
Fields
pub parent: &'a str: Parent file name in the same directory.pub sidecar: &'a str: Sidecar file name in the same directory.pub kind: SidecarKind: Filename form used by this sidecar.
Implements: Clone, Copy, Debug, Eq, PartialEq
Source: crates/calternal-fs/src/sidecar.rs:49
SystemSecretFile
Section titled “SystemSecretFile”pub struct SystemSecretFileA bounded file read from .system/secrets/ through the held system root.
The bytes are cleared when this value is dropped because it may contain a
private key. mode is the permission mode from the opened inode.
Implements: Drop
SystemSecretFile::as_bytes
Section titled “SystemSecretFile::as_bytes”pub fn as_bytes(&self) -> &[u8]No doc comment.
SystemSecretFile::mode
Section titled “SystemSecretFile::mode”pub fn mode(&self) -> u32Unix permission and special bits from the opened file.
Source: crates/calternal-fs/src/root.rs:37
ThumbnailTemp
Section titled “ThumbnailTemp”pub struct ThumbnailTempKeep one private thumbnail inode registered until publication or discard (#802).
Fields
pub path: PathBuf
Source: crates/calternal-fs/src/thumbnails.rs:95
UserHomeArchive
Section titled “UserHomeArchive”pub struct UserHomeArchiveOne archived Home and the time when the server may purge it.
Fields
pub user_id: Stringpub expires_at: i64
Implements: Clone, Debug, Eq, PartialEq
Source: crates/calternal-fs/src/user_homes.rs:14
WebAssetStoreStats
Section titled “WebAssetStoreStats”pub struct WebAssetStoreStatsThe size and item counts of the retained immutable asset store.
Fields
pub bytes: u64: Bytes used by digest-named assets and deployment manifests.pub asset_files: usize: Number of retained asset files.pub deployment_manifests: usize: Number of retained deployment manifests.
Implements: Clone, Copy, Debug, Default, Eq, PartialEq
Source: crates/calternal-fs/src/web_assets.rs:36
WriteConditions
Section titled “WriteConditions”pub struct WriteConditions<'a>Preconditions and metadata that affect one atomic write.
Grouping these related values keeps the checked write API small and makes the upload-reservation exception explicit at each call site.
Fields
pub expected_blake3: Option<&'a str>: Require the current bytes to match this BLAKE3 digest before replacing.pub modified: Option<std::time::SystemTime>: Set a source modification time before the new file becomes visible.pub reservation_id: Option<&'a str>: Exchange this upload’s reservation for its installed Home bytes.
Implements: Clone, Copy, Debug, Default
Source: crates/calternal-fs/src/root.rs:137
WriteResult
Section titled “WriteResult”pub struct WriteResultNo doc comment.
Fields
pub size: u64pub hash: Stringpub first_bytes: Vec<u8>: At most the first 64 KiB already read from the incoming write stream. Files uses this bounded prefix to set its MIME projection without reopening the newly written file (#851; DESIGN §2 and §4).pub version_name: Option<String>: Name of the previous-content Version created by this write, if any.
Implements: Debug, Clone
Source: crates/calternal-fs/src/root.rs:368
pub enum ErrorNo doc comment.
Variants
InvalidPathNameTooLongExistsNameConflictCasePreconditionFailedNotFoundInvalidSystemSecretDifferentDeviceQuotaExceeded { limit: u64, projected: u64 }FreeSpaceReserve { reserve: u64, available: u64 }Io(#[source] std::io::Error)Unsupported
Implements: Debug, Error
Source: crates/calternal-fs/src/error.rs:4
SidecarKind
Section titled “SidecarKind”pub enum SidecarKindThe supported standard filename forms for one sidecar.
Variants
FullXmp:<full filename>.xmp, for exampleIMG_1234.CR3.xmp.LightroomXmp:<stem>.xmp, for exampleIMG_1234.xmpforIMG_1234.CR3.AppleAaeUpper:<stem>.AAE, the iOS and macOS spelling.AppleAaeLower:<stem>.aae, the lowercase iOS and macOS spelling.
Implements: Clone, Copy, Debug, Eq, Hash, PartialEq
SidecarKind::key
Section titled “SidecarKind::key”pub fn key(self) -> &'static strStable value stored by the Files Index.
SidecarKind::from_key
Section titled “SidecarKind::from_key”pub fn from_key(value: &str) -> Option<Self>Read a stable value stored by the Files Index.
Source: crates/calternal-fs/src/sidecar.rs:13
ThumbnailKind
Section titled “ThumbnailKind”pub enum ThumbnailKindSelect the stable thumbnail cache family for one renderer output. PDF pages and text cards need separate identities because equal file bytes can select either renderer from their indexed MIME and suffix (#510/#547).
Variants
Media: Existing image and video thumbnails keep their established cache names.Pdf: First-page PDF renders use a separate cache family.TextCard: Escaped text previews use a separate cache family.
Implements: Clone, Copy, Debug, Default, Eq, Hash, PartialEq
ThumbnailKind::for_indexed_file
Section titled “ThumbnailKind::for_indexed_file”pub fn for_indexed_file(path: &str, mime: Option<&str>) -> SelfSelect the renderer family from the trusted indexed MIME value. Keep this decision beside the cache key so every API surface requests the same entry that the worker publishes (#510/#547/#851, DESIGN §39).
The MIME comes from the shared content detector, so a PDF or Markdown
file without a suffix still gets its card. text/plain is also what
the detector stores for source code, HTML and scripts (kept inert), so
only plain-text names (no suffix, .txt, .log, …) get a text card;
the suffix chooses among text formats only, never over the bytes.
ThumbnailKind::parse
Section titled “ThumbnailKind::parse”pub fn parse(value: &str) -> Option<Self>Parse the public, fixed set of variant labels accepted by the API.
ThumbnailKind::as_str
Section titled “ThumbnailKind::as_str”pub const fn as_str(self) -> &'static strReturn the stable label used in query strings and cache identities.
Source: crates/calternal-fs/src/thumbnails.rs:17
VoiceAudioFormat
Section titled “VoiceAudioFormat”pub enum VoiceAudioFormatA recording container accepted by the local Voice pipeline.
Variants
WebmOggMp4WavMp3FlacAac
Implements: Clone, Copy, Debug, Eq, PartialEq
Source: crates/calternal-fs/src/root.rs:161
VoiceModelAsset
Section titled “VoiceModelAsset”pub enum VoiceModelAssetA fixed, server-owned file in the local voice model set.
The variants map to filenames here so a model downloader never builds a filesystem path from a remote manifest or user input.
Variants
ParakeetEncoderParakeetDecoderParakeetJoinerParakeetTokensS1Mini
Implements: Clone, Copy, Debug, Eq, PartialEq
Source: crates/calternal-fs/src/root.rs:151
WriteMode
Section titled “WriteMode”pub enum WriteModeNo doc comment.
Variants
CreateNewReplaceReplaceLive: Live content already has durable collaboration history (DESIGN §61, #975).
Implements: Clone, Copy, Debug, Eq, PartialEq
Source: crates/calternal-fs/src/root.rs:126
Type aliases
Section titled “Type aliases”Result
Section titled “Result”pub type Result<T> = std::result::Result<T, Error>;No doc comment.
Source: crates/calternal-fs/src/error.rs:32
Functions
Section titled “Functions”fold_name
Section titled “fold_name”pub fn fold_name(name: &str) -> StringReturn the NFC and full Unicode case-folded name key (DESIGN §26). Sibling lookup and repair must use this same key to preserve identities when imported spellings collide (#618). Validate names before path access.
Source: crates/calternal-fs/src/path.rs:214
is_hls_segment_name
Section titled “is_hls_segment_name”pub fn is_hls_segment_name(name: &str) -> boolCheck the one HLS segment filename form accepted by the confined cache.
Source: crates/calternal-fs/src/hls.rs:144
is_sidecar_filename
Section titled “is_sidecar_filename”pub fn is_sidecar_filename(name: &str) -> boolReturn whether a name uses a supported sidecar suffix.
This is useful for preserving a relation after a parent rename, when the former parent name is no longer available for lexical matching.
Source: crates/calternal-fs/src/sidecar.rs:121
is_sidecar_name
Section titled “is_sidecar_name”pub fn is_sidecar_name(parent_name: &str, candidate_name: &str) -> boolTest whether two sibling names use one of the supported sidecar forms.
Source: crates/calternal-fs/src/sidecar.rs:113
normalize_new_name
Section titled “normalize_new_name”pub fn normalize_new_name(name: &str) -> Result<String>Normalize a newly created directory entry. Existing entries are resolved
through RelPath without applying this policy so old data stays accessible.
Source: crates/calternal-fs/src/path.rs:24
open_runtime_codecs
Section titled “open_runtime_codecs”pub fn open_runtime_codecs() -> Result<File>Open the runtime’s generated native-codec manifest through a held root directory handle. The constant relative name cannot select a user path.
Source: crates/calternal-fs/src/lib.rs:114
pair_sidecars
Section titled “pair_sidecars”pub fn pair_sidecars<'a>( entries: impl IntoIterator<Item = (&'a str, bool)>,) -> Vec<SidecarPair<'a>>Pair sidecar files with regular siblings when exactly one parent matches.
The input carries only file names and a regular-file flag. Directories, symlinks and special files cannot become either side of a pair. The two name maps avoid comparing every sibling with every other sibling in a large folder. Ambiguous matches stay independent files.
Source: crates/calternal-fs/src/sidecar.rs:131
sealed_media_bytes
Section titled “sealed_media_bytes”pub fn sealed_media_bytes(bytes: &[u8], maximum_bytes: u64) -> Result<File>Make a bounded immutable decoder input from server-owned bytes (#988, DESIGN §39). Startup diagnostics use this rather than a Home file or a writable temporary file.
Source: crates/calternal-fs/src/thumbnails.rs:690
sealed_media_input
Section titled “sealed_media_input”pub fn sealed_media_input(source: &File, maximum_bytes: u64) -> Result<File>Copy a held source into a bounded, kernel-sealed decoder input (#410/#501, DESIGN §39). Native tools must never receive the original Home inode: a read-only descriptor alone does not prevent owner metadata changes. All four seals remain in force even if the decoder reopens this memory file. This operation has no path argument and never writes to the data directory.
Source: crates/calternal-fs/src/thumbnails.rs:665
sidecar_name
Section titled “sidecar_name”pub fn sidecar_name(parent_name: &str, kind: SidecarKind) -> Option<String>Return the standard sidecar name for parent_name and kind.
Source: crates/calternal-fs/src/sidecar.rs:93
sidecar_path
Section titled “sidecar_path”pub fn sidecar_path(parent: &RelPath, kind: SidecarKind) -> Result<RelPath>Return a sidecar path beside parent, using a validated relative name.
Source: crates/calternal-fs/src/sidecar.rs:187
versions_to_keep
Section titled “versions_to_keep”pub fn versions_to_keep(times: &[i64], now: i64) -> Vec<bool>Time-based Version thinning. Keep all for a day, then one per hour until age seven days, one per day until age 28 days, one per week until age 84 days, and one per 30-day bucket thereafter. Input is newest first, in Unix seconds; the first entry in each tier and timestamp bucket wins. Each file’s versions live below its mirrored relative path.
Source: crates/calternal-fs/src/versions.rs:10
Constants
Section titled “Constants”MAX_APPLEDOUBLE_FILE_BYTES
Section titled “MAX_APPLEDOUBLE_FILE_BYTES”pub const MAX_APPLEDOUBLE_FILE_BYTES: u64Keep a single AppleDouble resource bounded even if a client declares a huge upload. The DAV layer checks the declared length too; this is the filesystem boundary for every caller.
Source: crates/calternal-fs/src/appledouble.rs:17
MAX_APPLEDOUBLE_USER_BYTES
Section titled “MAX_APPLEDOUBLE_USER_BYTES”pub const MAX_APPLEDOUBLE_USER_BYTES: u64Cap the complete hidden store independently from a User’s normal Home quota.
Source: crates/calternal-fs/src/appledouble.rs:19
MEDIA_MEMFD_LIMIT_BYTES
Section titled “MEDIA_MEMFD_LIMIT_BYTES”pub const MEDIA_MEMFD_LIMIT_BYTES: u64Keep snapshots through 64 MiB in a sealed memfd; larger media snapshots use an anonymous file to avoid pinning a full transcode input in RAM (#501).