Skip to main content

Crate ousia

Crate ousia 

Source
Expand description

§Ousia

οὐσία — Ancient Greek for “essence” or “substance”.

Ousia is a Postgres-native ORM for Rust that ships with a built-in double-entry ledger as a first-class primitive. It is designed for applications where data, relationships, and money all need to move together — atomically, correctly, and without ceremony.

§What’s inside

§Graph-relational ORM

Model your domain as entities connected by typed edges. Relations are not just foreign keys — they are traversable, queryable graph connections backed by Postgres.

§Double-entry ledger

Every monetary operation — mint, burn, transfer, reserve — is a double-entry transaction. Nothing is deleted. Everything is auditable. The ledger is ACID-safe and lives in the same Postgres connection as your application data.

Money::atomic(&ctx, |tx| async move {
    // Lock $60 from user, mint $60 to merchant atomically.
    let money = tx.money("USD", user, 60_00).await?;
    let slice = money.slice(60_00)?;
    slice.transfer_to(merchant, "payment".to_string()).await?;
    Ok(())
})
.await?;

§Smart fragmentation

Balances are stored as value objects — discrete fragments of value. The fragmentation engine uses your asset’s natural denomination as a soft preferred chunk size, with a hard fragment cap (max_fragments) that automatically scales chunk size up when needed. Every spend is a consolidation opportunity: change is minted back into at most burned_count fragments, so active accounts stay lean over time without any background compaction job.

§FIFO aging

Value objects are selected oldest-first on every spend. Burned rows naturally age to the back of the live index and become eligible for cold-storage archival, keeping your hot dataset small.

§Atomic money operations

The Money API enforces correct usage at the type level:

  • Mint — create value out of thin air (deposits, issuance)
  • Burn — destroy value permanently (fees, redemptions)
  • Transfer — move value between owners atomically
  • Reserve — escrow value for a future authority
  • Slice — partition a money handle before spending

Unconsumed slices, over-slicing, and double-spend are all caught before hitting the database.

§Quick start

use ousia::{Engine, adapters::postgres::PostgresAdapter};

let adapter = PostgresAdapter::from_pool(pool);
adapter.init_schema().await?;

let engine = Engine::new(Box::new(adapter));
let ctx = engine.ledger_ctx();

§v2 highlights

  • MessagePack data column. Object/edge bodies are stored as BYTEA msgpack instead of JSONB. index_meta stays as JSONB so Postgres can GIN-index it.
  • Renamed tables. edges → object_edges, unique_constraints → object_constraints.
  • Partitioned schema. objects, object_edges, object_constraints, and object_geo are all partitioned BY LIST (type), one partition per derived type.
  • FK cascade. Each constraint/geo/edge partition foreign-keys into the matching objects_<type>(id) partition with ON DELETE CASCADE — no more orphaned children, no more round-trips to clean them up.
  • Edges declare their endpoints. #[ousia(from = User, to = Post)] now required on OusiaEdge derives; the trait exposes FROM_TYPE / TO_TYPE and init_schema uses them to wire the correct FKs.
  • Compile-time manifest. Every OusiaObject / OusiaEdge derive pushes into the MANIFEST distributed slice via linkme. init_schema() walks the slice — no more enumerating types by hand — and emits a target/ousia.json artifact for tooling.
  • Composed schema hash. One blake3 hash over every type’s indexed fields, stored as major.minor:hash in ousia_meta. Major bump → hard error; minor drift → warn and overwrite.
  • Explicit ledger asset list. init_ledger_schema(&["USD",…]) takes the asset codes from the caller; the library reads no env.

§Feature flags

FlagDefaultDescription
deriveRe-export OusiaObject / OusiaEdge derives
postgresPostgreSQL adapter via sqlx
ledgerBuilt-in double-entry ledger

§Ousia

Ousia (οὐσία) is Aristotle’s term for the fundamental substance of a thing — what it is at its core. The name reflects the library’s ambition: to be the essential data substrate of a Rust application, handling entities, relationships, and money in one coherent layer.

Re-exports§

pub use manifest::ManifestKind;
pub use manifest::TypeManifestEntry;
pub use manifest::MANIFEST;
pub use crate::adapters::Adapter;
pub use crate::adapters::EdgeRecord;
pub use crate::adapters::MultiEdgeContext;
pub use crate::adapters::MultiOwnedContext;
pub use crate::adapters::MultiPreloadContext;
pub use crate::adapters::ObjectRecord;
pub use crate::adapters::Query;
pub use crate::adapters::QueryContext;
pub use crate::edge::query::EdgeQuery;
pub use crate::error::Error;
pub use query::IndexQuery;
pub use ledger;
pub use crate::edge::meta::*;
pub use crate::edge::traits::*;
pub use crate::object::*;

Modules§

adapters
edge
error
manifest
Type manifest — compile-time registry of every Object and Edge linked into the binary.
object
query

Macros§

filter

Structs§

Engine
The Engine is the primary interface for interacting with domain objects and edges. It abstracts away storage details and provides a type-safe API.
Ousia
ReplicaConfig

Derive Macros§

OusiaDefault
OusiaEdge
OusiaObject