Skip to content
Ledger by RODMENA
Menu

Product

What the ledger guarantees, and what enforces it

A guarantee is only worth what enforces it. Each of these is a rule inside the database, and a live check against the real service guards it.

Twelve guarantees

Each one names its enforcement and its check

  1. 01

    Every transaction balances

    For any kind of asset in the transaction, what leaves one account arrives in another. A transaction that does not balance is refused before anything is written.

    Enforced by
    the database, at the moment it commits
    Guarded by
    database certification probes
    The precise statement, for engineers

    Debits equal credits per (transaction, asset type), both sides present, 2–100 entries matching the declared count, verified at COMMIT by a deferred constraint trigger. Holds through any path, including direct SQL.

  2. 02

    History cannot be edited

    Entries are permanent, and nobody can change or delete them, including us. A mistake is corrected with a new, visible transaction that reverses it.

    Enforced by
    the database, which has no edit or delete path on the journal
    Guarded by
    database certification probes
    The precise statement, for engineers

    No UPDATE, DELETE or TRUNCATE on entries; transactions only move pending → committed | voided | expired. The API role holds no DELETE anywhere; guard triggers refuse the operation independently of privileges.

  3. 03

    Amounts are exact

    Money, credits and stock are counted in whole minor units. There is no fraction left to round away. Amounts travel as text and are never handled as approximate numbers.

    Enforced by
    the database column type and a build check that refuses approximate arithmetic on any amount path
    Guarded by
    probe_money_precision
    The precise statement, for engineers

    NUMERIC(38,0) minor units with a per-asset scale 0–12; the API carries amounts as decimal strings; a float on an amount path fails the lint gate.

  4. 04

    An account cannot go below its floor

    Every account declares its floor. A customer wallet is floored at zero, and an agreed overdraft is a negative limit. A movement that would breach the floor is refused, even when many requests race for the same balance.

    Enforced by
    the database, locking balances in a fixed order before it checks and backing that with a constraint
    Guarded by
    probe_account_floor, probe_floor_guard, probe_concurrency
    The precise statement, for engineers

    Balance rows locked SELECT … FOR UPDATE in ascending account id (deadlock structurally impossible), a half-second lock timeout → 409 with Retry-After, floor CHECK on account_balances.

  5. 05

    A retried request cannot move money twice

    Every write carries a key you choose. If your connection drops and you send the same request again, you get the original answer back and nothing moves a second time.

    Enforced by
    the ledger write and its receipt committing together, in one database transaction
    Guarded by
    probe_a38_idem_transient, probe_idem_operational_409, probe_idem_takeover_fp, probe_idem_storm_after_clear
    The precise statement, for engineers

    Idempotency-Key per (tenant, endpoint), remembered 7 days; claim → execute and complete in the same transaction → record business failures; lease takeover for crashed owners; UNIQUE(tenant_id, idempotency_key) on transactions.

  6. 06

    One customer can never see another

    Your credential is your boundary. As far as your requests are concerned, records that belong to someone else do not exist. A request that arrives without a valid boundary is refused.

    Enforced by
    two independent layers, the second inside the database, failing closed
    Guarded by
    probe_rls_parity, probe_control_plane_rls, probe_money_isolation, probe_sub_tenancy
    The precise statement, for engineers

    Tenant-bounded queries AND row-level security ENABLED + FORCED on every tenant table and partition, set per transaction; missing context errors rather than returning rows; the API role owns no tables and cannot bypass the policy.

  7. 07

    Reserve first, settle later

    A hold sets money or stock aside without moving it. You then complete it or release it. A hold you forget about is released when it expires.

    Enforced by
    the database state machine for transactions
    Guarded by
    probe_expiry_sweep, probe_hold_expiry_replay, probe_frozen_blocks_commit
    The precise statement, for engineers

    pending: true reduces available and leaves posted untouched; commit/void/expire move atomically; a sweeper expires unresolved holds on schedule; a frozen or closed account blocks settlement.

  8. 08

    A temporary failure never counts against you

    If the service itself has a momentary problem, your request key stays usable and the retry does the work. Only a real business refusal is remembered and replayed.

    Enforced by
    the retry protocol
    Guarded by
    probe_a38_idem_transient
    The precise statement, for engineers

    Transient conditions (lock timeout, deadlock retry, statement timeout, any unmapped 5xx) leave the key re-executable; deterministic business failures replay verbatim; anything carrying Retry-After honours a retry.

  9. 09

    A retry gets the original answer, even later

    Checks that depend on the clock run inside the write. A request you repeat an hour later is answered exactly as it was the first time.

    Enforced by
    the ordering of validation inside the write
    Guarded by
    probe_hold_expiry_replay
    The precise statement, for engineers

    Time-dependent validation runs inside the idempotency engine, never at the boundary; a completed key replays before any check runs.

  10. 10

    Every figure says what unit it is in

    Every response shows a balance in two forms, the way you would write it and as a whole number of minor units. A display value cannot be mistaken for a raw count.

    Enforced by
    the response contract
    Guarded by
    probe_read_contract_parity
    The precise statement, for engineers

    Every money field without a _minor suffix is a display-scale decimal string, on success responses as well as errors; the _minor companion is the integer.

  11. 11

    A bad request gets a clear answer

    A request with a wrong or oversized value is refused with a message naming the field. The service never answers a client mistake with an internal error.

    Enforced by
    validation at the boundary and a single error format across every layer
    Guarded by
    probe_input_bounds, probe_json_depth, probe_error_envelope_parity, probe_edge_error_envelope
    The precise statement, for engineers

    Malformed or out-of-domain input returns a 4xx naming the field; no 5xx and no SQLSTATE leaks; the same {"error":{"code"}} envelope from the application, the framework and the edge.

  12. 12

    Busy accounts catch up without skipping anything

    A shared account that every transaction touches is totalled in the background. The totalling cannot leave an entry out.

    Enforced by
    a visibility rule the background worker must respect
    Guarded by
    probe_rollup_visibility, probe_async_pending
    The precise statement, for engineers

    The rollup advances only to a horizon below which no future commit can land; if the horizon is unknowable it refuses to advance; the reconciler uses the same horizon.

The checks named above are part of the live probe suite that runs against the service. The database certification probes are the schema-level suite every migration must pass. How both are run, and what they found, is on the assurance pages.

Free today. Access is provisioned personally by RODMENA.

Tell us what you keep books of and we will set up a tenant, mint your first key and walk you through the tour.