pub struct BlobStore { /* private fields */ }Expand description
A content-addressed blob store backed by a directory on disk and a
blobs table in SQLite for refcounting.
When constructed via BlobStore::with_redactor, UTF-8 content is passed
through the redaction engine before hashing and compression — the
record-time enforcement point of docs/redaction-design.md. Because the
content is redacted before hashing, the returned hash is the hash of what
is actually stored and content-addressing stays internally consistent.
Implementations§
Source§impl BlobStore
impl BlobStore
Sourcepub fn new(blobs_dir: PathBuf) -> Self
pub fn new(blobs_dir: PathBuf) -> Self
Create a new BlobStore rooted at blobs_dir. The directory itself
is created lazily on first write with 0700 permissions.
Sourcepub fn with_redactor(blobs_dir: PathBuf, redactor: Arc<Detectors>) -> Self
pub fn with_redactor(blobs_dir: PathBuf, redactor: Arc<Detectors>) -> Self
Sourcepub fn hash(content: &[u8]) -> String
pub fn hash(content: &[u8]) -> String
Compute the BLAKE3 hex hash of content without storing it (FR-1.4:
binary files record hashes even when content storage is skipped).
Centralized here so the recorder does not depend on blake3 directly.
Sourcepub fn put(&self, content: &[u8]) -> Result<PutOutcome>
pub fn put(&self, content: &[u8]) -> Result<PutOutcome>
Store content, compressed with zstd, keyed by its BLAKE3 hash. Returns
the hash of what was stored. If the blob already exists on disk,
content is not rewritten (content-addressing makes it identical). The
blobs table refcount is bumped by the store’s writer when an event
references this hash.
With a redactor attached (Self::with_redactor), UTF-8 content is
redacted first; the returned hash/size then describe the redacted
content, so callers must reference the outcome’s hash, never a hash
they computed over the original bytes.
Sourcepub fn get(&self, hash: &str) -> Result<Vec<u8>>
pub fn get(&self, hash: &str) -> Result<Vec<u8>>
Read a blob by hash, decompress it, and return the bytes.
Sourcepub fn remove_if_unreferenced(&self, hash: &str, refcount: i64) -> Result<bool>
pub fn remove_if_unreferenced(&self, hash: &str, refcount: i64) -> Result<bool>
Delete a blob from disk if its refcount has dropped to zero. Returns
true if a file was removed. The caller must have already decremented
the refcount in the DB; this is the GC step.
Sourcepub fn shred(&self, hash: &str) -> Result<bool>
pub fn shred(&self, hash: &str) -> Result<bool>
Securely delete a blob file: best-effort overwrite with zeros + fsync,
then unlink (docs/redaction-design.md I2). Returns true if a file
was removed. The overwrite raises the bar against recovery of the
plaintext from the filesystem; it is not a forensic guarantee on
journaling/copy-on-write filesystems or wear-leveled SSDs (documented
in docs/redaction.md). The caller must have already removed the
blob’s row / confirmed the refcount is zero.
Sourcepub fn iter_hashes(&self) -> Result<Vec<String>>
pub fn iter_hashes(&self) -> Result<Vec<String>>
Enumerate the BLAKE3 hex hashes of every blob file currently on disk,
by walking blobs/<2-char shard>/<64-hex>.zst. Used by
crate::store::Store::prune_orphan_blobs and
crate::store::Store::store_stats for orphan detection and footprint
accounting (Area 3). Returns hashes in arbitrary directory order;
defensively skips entries whose names are not a well-formed
<hash>.zst, so a stray file in the blobs dir never panics.