apomesh-substrate-state
The in-process state implementation plane. This crate holds the
non-Postgres adapters behind the substrate’s persistence ports: the
in-memory and SQLite StateStore adapters and the in-memory AssetStore.
These are the dev, test, and single-binary backends — the same ports the
durable Postgres family
implements, without a database server. It is a sibling implementation plane:
it binds only apomesh-substrate-types
(the ports + vocabulary) and the bundled SQLite library, so editing it
recompiles this plane and the runtime, never the heavier LLM or tool trees.
Reach for it when you run the in-memory or sqlite state-store backend, or
when a port grows a method and the in-process adapters must mirror it.
Position in the workspace
Section titled “Position in the workspace”- Layer: substrate implementation planes — the in-process side of the state-store layer. See The event log for the event-log and checkpoint model these adapters back.
- Depends on:
apomesh-substrate-types
(the
StateStore/AssetStoreports + the event / snapshot / memory / asset vocabulary), plusrusqlitewith thebundledfeature (the vendored SQLite C library — no external system dependency). - Consumed by:
apomesh-substrate — the runtime
constructs these adapters and injects them behind the ports, re-exporting
them through its own
state_store/asset_storefacades. The downstream durable adapters (apomesh-state-store-postgres and Redis) reuse this crate’scontractsuite transitively through that facade under thetest-utilfeature — they do not depend on it directly.
What it owns
Section titled “What it owns”InMemoryStateStore— aHashMap-backed adapter with no IO, for unit tests and dev paths that don’t want the SQLite dependency. Trivially auditable; the full port, exercised by the same contract suite the durable adapters run.SqliteStateStore— arusqliteadapter in WAL journal mode for single-binary deployments, edge nodes, and cloud-parity runs without a Postgres server. One writer at a time, made explicit through atokio::sync::Mutex<Connection>.InMemoryAssetStore— a content-addressed (SHA-256), per-tenant-keyed blob adapter that honours the streamingAssetReaderport even though it materialises the bytes.- The adapter-agnostic contract suite —
state_store::contract(behind thetest-utilfeature): the reusableStateStoreconformance tests every adapter, in-process or durable, runs against the same behaviour.
It does not own the ports (the StateStore / AssetStore traits live in
apomesh-substrate-types), state
reconstruction or event folds (the runtime rebuilds sessions — these adapters
carry opaque Vec<u8> snapshot bodies they never interpret), or the durable
adapters (Postgres in its own crate).
Capability envelope versus Postgres
Section titled “Capability envelope versus Postgres”Both in-process StateStore adapters implement the entire port — the
tenant-bound event log (append, read, prune, session enumeration; live
subscription is the event bus’s concept, layered over the read),
CheckpointSource-tagged snapshots, working memory, all three
memory tiers (episodic, semantic, procedural), named memory spaces, and the
side-effect log. Semantic search is supported, not stubbed: the in-memory
adapter blends linear-scan vector cosine with BM25; the SQLite adapter uses
FTS5 BM25 with cosine over stored embedding bytes. Both default to the
deterministic FakeEmbeddingProvider; a real provider installs via
with_embedding_provider. What differs from Postgres is the retrieval
mechanism — a brute-force / FTS5 scan versus pgvector’s halfvec + HNSW
approximate-nearest-neighbour index — not the capability. Absent here by
design (they live in the Postgres crate): the ANN vector index, the Redis
HybridStateStore write-through, at-rest sealing, and the sibling registry /
catalog / credential store family. The AssetStore in-process plane is
in-memory only; the durable PostgresAssetStore lives in the Postgres crate.
Public surface
Section titled “Public surface”| Entry point | Contract |
|---|---|
InMemoryStateStore | The full in-memory StateStore; new(), with_embedding_provider(provider). |
SqliteStateStore | The WAL SQLite StateStore; open(path), in_memory(), with_embedding_provider(provider). |
InMemoryAssetStore | The content-addressed in-memory AssetStore; new(). |
state_store | Re-exports the StateStore port + vocabulary from apomesh-substrate-types so adapters and the runtime facade reach crate::state_store::* unchanged. |
asset_store | The AssetStore counterpart re-export. |
state_store::contract | The adapter-agnostic conformance suite (feature test-util), reused by downstream adapter crates’ integration tests. |
The daemon selects the backend from the [statestore.backend] config section
(a closed StateStoreBackend enum). The two in-process backends are in-memory
(the default — volatile, dev + tests) and sqlite (durable single-file):
[statestore.backend]kind = "sqlite"path = "/var/lib/apomesh/state.db"The runtime constructs the matching adapter and injects it behind the port:
use std::sync::Arc;use apomesh_substrate_state::state_store::{SqliteStateStore, StateStore};
// WAL journal mode + schema are applied on open; re-opening is a no-op.let store: Arc<dyn StateStore> = Arc::new(SqliteStateStore::open("/var/lib/apomesh/state.db")?);Related
Section titled “Related”- Concepts: Sessions and events — the event log and checkpoint model these adapters implement.
- Reference: apomesh-state-store-postgres (the durable side of the same ports) and apomesh-substrate-types (where the ports are defined).
- Operate: Local stack — the Compose stack that runs the durable backend.