Rust libraries
Entity Runtime is a workspace of narrow crates. Use only the boundary your application needs.
| Crate | Purpose |
|---|---|
entity-core | IO-free definitions, registry, runtime, decisions, events, and replay |
entity-yaml | YAML text to definition data; register it before execution |
entity-store | provider traits, memory/file stores, envelopes, projections, conformance suite |
entity-query | optional document containment queries and continuation cursors |
entity-sqlite | transactional embedded provider |
entity-postgres | transactional centralized provider |
entity-remote | versioned store protocol, transport trait, and hybrid policy |
entity-graph | deterministic lifecycle and reference renderings |
entity-surface | IO-free JSON Schema, OpenAPI, AsyncAPI, and entity documentation projection |
entity-shell | provider-backed create/get/list/events/execute shared by shells |
entity-mcp | synchronous schema-derived MCP tools over caller-provided stdio |
More columns: swipe horizontally, or focus the table and use the arrow keys.
The crates are currently consumed from the tagged repository:
[dependencies]
entity-core = { git = "https://github.com/beyond10x/entity-runtime", tag = "0.18.1" }
entity-yaml = { git = "https://github.com/beyond10x/entity-runtime", tag = "0.18.1" }
Keep all runtime crate dependencies on the same release tag. The system map explains which contracts are authored and which surfaces are generated.
Decide in memory
use entity_core::{CoreError, Registry, Runtime};
use serde_json::json;
let definition = entity_yaml::from_str(&yaml)?;
let mut registry = Registry::new();
registry.register(definition)?;
registry.validate_all()?;
let runtime = Runtime::new(®istry);
let drafted = runtime.create(
"refund",
1,
"refund-104",
json!({
"order_id": "order-88",
"amount_cents": 12_500,
"evidence_count": 2
}),
)?;
let submitted = runtime.execute(&drafted.instance, "submit", json!({}))?;
match runtime.execute(
&submitted.instance,
"approve",
json!({
"actor_role": "agent",
"reason": "customer supplied delivery evidence"
}),
) {
Err(CoreError::PreconditionFailed { rule, .. }) => {
assert_eq!(rule.as_deref(), Some("large_refunds_need_a_human"));
}
other => panic!("expected a policy refusal, got {other:?}"),
}
The caller-owned submitted.instance remains unchanged after the refusal.
Build a trusted shell
Your shell owns all ambient and privileged facts:
EntityInstance is serializable data with public fields because providers round-trip it. That is
not permission to trust any deserialized instance. Load canonical instances from a trusted provider
and let the kernel check definition identity and declared state.
Store atomically
Use RecordedCommit::new to bind a decision to Recording, then call
Store::commit_recorded. The provider checks Expect::Absent or Expect::Revision(n) before
writing state, history, and events.
For an ordered multi-subject command, use AtomicBatchStore::commit_batch on memory, SQLite, or
PostgreSQL providers. All expectations see earlier entries in the same batch; any conflict or
provider failure rolls the batch back.
Replay
entity_core::replay reruns complete decision records and compares normalized input, definition,
result, changes, and events. rehydrate folds legacy event-only histories against the current
definition, refusing any revision no operation could have produced, and is a migration tool rather
than equivalent proof: it has no definition snapshot and cannot see a decision that emitted nothing.
Match CoreError and StoreError variants in code. Display strings are for people and may be
reworded.
Optional document queries
DocumentQueryProvider is implemented by Memory Store and PostgreSQL. DocumentQuery selects one
entity type, applies recursive JSON containment to its fields, and returns an identity-ordered page.
The default limit is 100 and the maximum is 1,000. Reuse the returned cursor with the same entity and
filter; a cursor for another query is refused. Pagination alone does not hold a snapshot across calls.
PostgreSQL also offers command sessions for transactional reads, writes, queries, events, and
identity-range reservation. This is a provider-specific capability; the CLI list verb simply
enumerates stored IDs and exposes no query or transaction-session command.