โ† All docs  ยท  Home

ADR 0016 โ€” Storage durability: SQLite mock + persistent collection state

Context

Two pieces of durability were deferred:

  1. M2 shipped the in-memory and Oxigraph FeedbackStore backends and noted a SQLite mock as pending. The roadmap and CLAUDE.md both call for a SQLite mock as a durable, dependency-light store.
  2. M6 / ADR 0012 made the collection server polite (per-(server, uri) cache, freshness, validators) but its derived state โ€” registered servers, the cache, and the URI equivalence union-find โ€” was purely in-memory and lost on restart. A cold aggregator re-fans-out to every upstream and forgets every asserted equivalence.

Decision

1. SQLite FeedbackStore (freedback-storage, feature sqlite)

SqliteStore (rusqlite, bundled so no system SQLite) stores each annotation as one row keyed by its dedup id, with target / issuer / iat denormalized for SQL filtering/ordering and the raw JSON-LD kept verbatim. INSERT OR IGNORE on the dedup-id primary key gives idempotent put. It passes the shared conformance::run suite identically to the memory/Oxigraph backends, plus the conformance::persistence snapshot suite and a file-reopen durability test.

It is gated behind the sqlite feature (off by default) and pulls rusqlite only as an optional dependency. rusqlite is a native-only C dep, so the gate keeps it out of any wasm consumer (INVARIANT 5/6). Storage already depends on Oxigraph and is native-only, but the feature gate is the contract.

2. Persistent collection-server state (redb)

A new persist module backs AppState's servers / cache / equivalence with a single embedded redb database (pure Rust, the same KV the advanced client uses โ€” no Clang/RocksDB, wasm-capable though used native-only here), write-through on every mutation:

Persistence is opt-in: AppState::with_persistence(base, rate, path) (wired to FREEDBACK_STATE_PATH in the binary). Unset โ‡’ the original ephemeral in-memory behavior; no behavior change for existing callers/tests.

Why redb (not SQLite) for the collection server

Consequences