@verist/storage
v0.1.1
Published
Storage interface for workflow state with three-layer model (computed, overlay, effective)
Maintainers
Readme
@verist/storage
Storage interfaces and state-layer helpers for Verist.
Install
bun add @verist/storage veristWhat This Package Provides
RunStorecontract for durable workflow statecreateMemoryStore()— in-memoryRunStorefor examples and testsRunStateand commit/overlay typeseffectiveState()helper for computed + overlay mergetypedStore<T>()— bind a state type to aRunStore, removing repeated<T>at each call site- Typed storage conflict reasons for retry/fatal handling
Layered State Model
Verist uses three logical layers:
computed- values produced by stepsoverlay- human corrections (never overwritten by automation)effective- shallow merge where overlay wins
import { effectiveState } from "@verist/storage";
const state = {
computed: { verdict: "reject", confidence: 0.61 },
overlay: { verdict: "accept" },
};
const effective = effectiveState(state);
// { verdict: "accept", confidence: 0.61 }RunStore Contract
interface RunStore {
load<T = unknown>(
workflowId,
runId,
): Promise<Result<RunState<T>, StorageError>>;
commit<T>(
params: CommitParams<T>,
): Promise<Result<RunState<T>, StorageError>>;
setOverlay<T>(
workflowId,
runId,
overlay: Partial<T>,
): Promise<Result<RunState<T>, StorageError>>;
}Key invariants:
commit()is atomic for state + events (+ optional commands in adapter implementations)- Optimistic concurrency via
expectedVersion - First commit to a run must use
expectedVersion: 0 - Conflict results include
reasonfor typed retry/fatal decisions
For a production implementation, see @verist/storage-pg.
In-Memory Store
For examples and tests, use the built-in in-memory store:
import { createMemoryStore } from "@verist/storage";
const store = createMemoryStore();
// Create a new run
await store.commit({
workflowId: "verify-doc",
runId: "run-1",
stepId: "extract",
expectedVersion: 0,
output: { score: 0.8, risk: "high" },
events: [{ type: "scored" }],
});
// Load and apply overlay
await store.setOverlay("verify-doc", "run-1", { risk: "low" });No persistence, no outbox — events and commands are accepted but not stored.
Typed Store
When all calls share the same state type, use typedStore<T>() to avoid repeating the type parameter:
import { createMemoryStore, typedStore } from "@verist/storage";
interface AppState {
score: number;
risk: string;
}
const store = typedStore<AppState>(createMemoryStore());
// T is AppState at every call site — no <AppState> needed
await store.commit({
workflowId: "verify-doc",
runId: "run-1",
stepId: "extract",
expectedVersion: 0,
output: { score: 0.8, risk: "high" },
events: [{ type: "scored" }],
});