Expand description
FathomDB — a local-first retrieval and graph-oriented data system for application and agent workloads.
This is the crate to depend on from Rust. It is a thin facade that
re-exports the public surface of the fathomdb-engine runtime, so you get
the supported API without depending on engine internals.
FathomDB embeds SQLite (FTS5 + sqlite-vec) in your process — there is no
server and no sidecar. One Engine owns the writer thread, a reader pool,
the projection scheduler and (optionally) an in-process embedder.
§Do you want this crate?
- Yes, if you want hybrid retrieval — a vector branch and an FTS5 branch fused by Reciprocal Rank Fusion — over data you also want to address by a stable identity, traverse as a graph, and be able to delete on request.
- No, if you want a client for a remote database, or an approximate nearest-neighbour index at very large scale: vector retrieval here is a full scan, so latency grows with corpus size.
Related crates: fathomdb-cli (the operator binary — doctor / recover),
fathomdb-embedder-api (the semver-stable embedder trait, versioned
independently), and fathomdb-engine (the runtime this crate re-exports;
prefer this facade).
§Example
use fathomdb::{Engine, PreparedWrite, SourceId};
let opened = Engine::open("./example.fdb")?;
let engine = opened.engine;
engine.write(&[PreparedWrite::Node {
kind: "note".into(),
body: "the sky is blue".into(),
// Provenance is MANDATORY — see below.
source_id: SourceId::new("doc-42")?,
logical_id: Some("note:sky".into()),
state: Default::default(),
reason: None,
valid_from: None,
valid_until: None,
}])?;
for hit in engine.search("sky")?.results {
// `hit.id` is a typed id-space carrier, not a row number.
println!("{:?} {} {}", hit.id.space, hit.id.value, hit.body);
}
engine.close()?;§Provenance is mandatory
Every canonical node and edge carries a SourceId. This is a type
rather than a validation check on purpose: Engine::erase_source addresses
rows by their source_id, so a row written without one could never be
erased on request. SourceId::new is the only public constructor and
refuses an empty id and the engine’s reserved _-prefixed namespace, which
makes an un-provenanced write a compile error rather than a runtime
surprise.
Treat a source_id as a public identifier: it is echoed on every search hit
and recorded in a retention-exempt erasure-audit row, so keep personal data
out of it.
§Deletion on request
Three verbs, differing in what they address, all on the default surface:
Engine::transition— move a governed node between existence states (promote, soft-delete, undelete).Engine::purge— irreversibly hard-erase one governed node, addressed by itslogical_id. Deleted-first and idempotent. There is no restore.Engine::erase_source— erase every row carrying onesource_id, including anonymous rows that have nological_idand thatEngine::purgetherefore cannot reach.
§Feature flags
- default — the governed application surface
(
dev/interfaces/rust.md§ Governed-surface contract): recovery-name-free and raw-SQL-free at the method level. No method namedrecover,restore,repair,fixorrebuildresolves. operator— un-gates the operator/recovery seam (rebuild_*,excise_source,dump_*,trace_source_ref,truncate_wal,verify_embedder,check_integrity,safe_export,recompute_meanand their report types).fathomdb-clienables it. Gating, not deletion: engine behaviour is identical with the feature on. See AC-074 (dev/acceptance.md) anddev/design/slice-27-fix1-operator-gate-design.md.
§Stability
Pre-1.0, so beta: the surface may change between micro releases. The
governed surface is pinned by
src/conformance/governed-surface-allowlist.json and any change to it is a
reviewed delta, but that is a change-control promise, not a semver one.
PreparedWrite and SearchFilter are #[non_exhaustive].
Structs§
- Boundary
Crossing - 0.8.20 Slice 10b (R-20-NV) — one node that crossed a validity boundary
inside the interrogated interval, as reported by
Engine::crossed_boundary_since. - Corruption
Detail - Stable corruption-on-open detail carried by
EngineOpenError::Corruption. - Counter
Snapshot - Snapshot of engine-internal counters returned by
Engine::counters. - Engine
- Excise
Report - Phase 9 Pack B excise report (AC-028a/b/c). Counts are post-excise
totals;
projections_invalidatedreports the shadow-row invalidation total (FTS5 + vec0 + projection terminal) for the excised source. - Explanation
- 0.8.8 EXP-OBS (Slice 5) — the opt-in retrieval explanation payload returned
behind
search_explained(theexplain=truesurface). Built from the engine’s OWN fusion/rerank machinery (fuse_three_armsper-arm ranks,ce_rerankblend components) — no parallel machinery (R-OBS-3). Carries a query-levelQueryTraceplus a per-hit breakdown parallel to (and in the same order as)SearchResult.results. - Extract
Document - G11 (Slice 15) — a document sent to a BYO-LLM extraction harness via
Engine::ingest_with_extractor. - Ingest
With Extractor Receipt - G11 (Slice 15) — receipt returned by
Engine::ingest_with_extractor. - Node
Record - Slice 30 (G2) — an active canonical node row returned by
read.get/read.get_many. - Open
Report - Opened
Engine - PerHit
Explain - 0.8.8 EXP-OBS (Slice 5) — per-hit provenance + score breakdown. One entry per
returned
SearchHit, same order.*_rankis the 0-based rank the hit’s body held in that arm’s pre-fusion list (None= absent from that arm). - Projection
Delta - 0.8.20 Slice 15d (R-20-PR) — the diff
Engine::configure_projectionsapplied. Idempotent re-registration yieldsunchanged == truewith all vecs empty (the “re-registration is a no-op” acceptance signal). A destructive change without an explicitdropis anErr, not a delta. - Projection
Fts - 0.8.20 Slice 15d (R-20-PR) — the
searchable→FTSsub-target selector. - Projection
Runtime Status - A pure, current view of projection-runtime facts for one open engine session.
- Projection
Runtime Status Entry - One declaration’s current dense status in
ProjectionRuntimeStatus. - Projection
Spec - 0.8.20 Slice 15d (R-20-PR / C-1) — a single declarative projection
declaration. HITL-ratified shape (
api-surface.md:85-89):{ name, roles: Set<ProjectionRole>, fts?, vector? }.rolescarries SET semantics (dedup + membership; an attribute can beFilterableANDSearchable) — encoded here as a sorted, de-duplicatedBTreeSet. Namedroles, notkind(kindis the node/edge type discriminator). - Projection
Vector - 0.8.20 Slice 15d (R-20-PR) — the
searchable→vectorsub-target selector. - Query
Trace - 0.8.8 EXP-OBS (Slice 5) — query-level retrieval trace. Reuses the existing
search_rerankedknobs + the active embedder identity; timings are coarse per-stage wall-clock (monotonic) captured only on the explain path. - Read
View - 0.8.20 Slice 10b (R-20-RV / R-20-NV) — the read view: the single knob
that decides which
canonical_nodesrows a read verb may see. - Recovery
Hint - Recovery dispatch surface attached to a corruption detail.
- Search
Expand Result - Slice 20 (G6) — result of
Engine::search_expand: initial search hits plus nodes reached by bounded BFS expansion that are not already in the search hit set. - Search
Filter - G10 — closed metadata filter for
Engine::search_filtered(Slice 10). - Search
Result - Hybrid
searchresult.resultscarries structuredSearchHits in vector-first, dedup-on-body order. DerivesClone, Debug, PartialEqbut notEq— each hit carries ascore: f64. - Soft
Fallback - Soft-fallback signal carried on hybrid
searchresults. - Source
Id - 0.8.20 Slice 5c (R-20-E3) — the provenance of a canonical row: which source
document it is attributable to, and therefore what
excise_sourcemust erase when that source is withdrawn. - Subscription
- Handle returned by
Engine::subscribe. - Write
Receipt
Enums§
- Comparison
Op - G4 (Slice 35) — comparison operator for
Predicate::JsonPathCompare. - Corruption
Kind - Open-path corruption category.
- Corruption
Locator - Locator pointing at the corrupted region of the database file.
- Dense
Readiness - 0.8.20 Slice 20 (R-20-DR) — the ENGINE-SET readiness of the
searchable→vectorprojection, perdev/design/record-lifecycle-protocol/projection-registry-and-async-embed.md§3. - Engine
Error - Engine
Open Error - Initial
State - OPP-12 Phase-1 (0.8.19 Slice 5) — the CREATE-TIME subset of
LifecycleState. - Lifecycle
State - OPP-12 record-lifecycle Phase-1 (0.8.19 Slice 5) — the existence axis.
- Open
Stage Engine.openstage at which corruption was detected.- Predicate
- G4 (Slice 35) — closed typed predicate for
Engine::read_listfilter. - Prepared
Write - Batch input shape for
Engine::write. - Projection
Role - 0.8.20 Slice 15d (R-20-PR, C-1) — one member of a
ProjectionSpec’s role set. Exactly three members (HITL-ratified S8,api-surface.md:87):searchable→FTSandsearchable→vectorare NOT roles — they are tier labels carried by thefts/vectorsub-objects of the spec, so an attribute isSearchableonce and the sub-objects select FTS-only / vector-only / both. - Projection
Runtime Unavailability Reason - The reason
ProjectionRuntimeStatus::runtime_embedder_availableis false. - Projection
Status Dense Readiness - The dense-readiness projection of
ProjectionRuntimeStatusEntry. - Scalar
Value - G4 (Slice 35) — scalar value for
Predicatecomparisons. - Soft
Fallback Branch - Which retrieval branch produced a hit (or could not contribute).
- Traversal
Direction - Slice 20 (G5) — direction of graph traversal for
Engine::graph_neighbors/Engine::search_expand.