CHANGELOG.md 5.3 KB

Changelog

All notable changes to this project are documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[Unreleased]

Added

  • Subaccounts: AccountId gains a subaccount leg ({ id, sub }), so several independent balances live under one owner, each individually addressable, drained, and closed. Aggregate reads take a base id plus an optional subaccount filter; exact operations take the full AccountId; balances are never summed across subaccounts. (ADR-0012)
  • Inflight holds: authorize, confirm, and void value through per-destination holding subaccounts, so an authorization reserves funds without committing them and a void returns them. (ADR-0014)
  • IBAN-style account identifiers: AccountId has a fixed 20-character Display/FromStr form (a base-36 body plus two mod-97 check digits) for presentation and routing, while storage keeps the two integer legs. (ADR-0015)
  • Cached balance projection: an append-only balance snapshot, refreshed lazily off the read path once enough activity accrues, shortens the everyday balance read; the authoritative live-posting sum stays the source of truth. (ADR-0019)
  • SagaStore::get_saga, a keyed read for a single write-ahead record, so recovery no longer scans every pending record.
  • Continuous integration now runs the storage conformance suite against PostgreSQL (exercising the Postgres-only FOR UPDATE and ON CONFLICT paths) and runs the test suite with the i128 Cent backing.

Changed

  • Storage write contract: every Store write method returns the number of affected rows and makes no domain decision. The saga interprets counts and owns idempotency and compensation, with a phase-tracked write-ahead record and roll-forward crash recovery in place of a monolithic commit transaction. (ADR-0003) (breaking for Store implementors)
  • Account balance constraint collapsed to the single DEBIT_MUST_NOT_EXCEED_CREDIT flag; overdraft is allowed by default. (ADR-0018)
  • The SQL schema separates append-only value tables from disposable active/reserved index tables. (ADR-0016, ADR-0017)
  • Intent resolution is pure and preserves typed errors across the saga.
  • Internal structure: the Ledger was split into concern-named submodules; the commit-safety invariant is documented and its double-spend guard named (ADR-0021); the write-ahead recovery record was concentrated into one pending module; balance computation was consolidated into one module.

Removed

  • The vestigial UserData type and the orphaned withdraw saga step. (breaking)

Documentation

  • Document that the ledger supports journaling: a committed transfer is a journal entry, a transfer with multiple movements is a compound journal entry, and the transfer log is the accounting journal. Adds doc/journaling.md and ADR-0013, and notes it in the README overview.

0.2.0 - 2026-07-01

Added

  • kuatia-dashboard: a server-rendered dashboard and REST API for observing a Kuatia ledger over HTTP. Browse accounts, postings, transfers, and the event log; inspect per-account balances computed in Rust.

Changed

  • The SQL backend stores binary identifiers as hex text and structured columns as JSON text instead of opaque blobs, so a ledger can be audited directly with SQL tooling. The SQLite and PostgreSQL schemas were unified into a single 001_init.sql.

0.1.0 - 2026-06-30

Initial release.

Added

  • Append-only, multi-asset, UTXO-style ledger. Value is tracked as signed postings with no mutable balance fields. Transfers atomically consume and create postings, enforcing per-asset conservation (sum(consumed) == sum(created)).
  • Intent API: movements (pay, deposit, withdraw) resolved into concrete postings by the core, committed through a single reserve → finalize saga with automatic retry and LIFO compensation.
  • Content-addressed transfers (double-SHA-256 of canonical bytes) for idempotency and tamper evidence.
  • Account policies: NoOverdraft, CappedOverdraft, UncappedOverdraft, SystemAccount, ExternalAccount, with append-only versioned accounts and snapshot pinning to guard against TOCTOU races.
  • Durable crash recovery via a phase-tracked write-ahead saga record and Ledger::recover() (roll-forward, not rollback).
  • Dumb-storage Store trait split into focused sub-traits, with an in-memory backend and a SQLite/PostgreSQL backend (kuatia-storage-sql).
  • A conformance test suite (store_tests!) applied to every storage backend.
  • Snowflake-style i64 IDs generated in Rust; the database never assigns IDs.
  • Compile-time swappable monetary backing (i64 default, i128 via the i128 feature).

Crates

  • kuatia-money — monetary Cent type with swappable integer backing.
  • kuatia-types — domain types: accounts, postings, transfers, books.
  • kuatia-core — pure, sans-IO logic: validation, hashing, posting selection.
  • kuatia-storage — storage abstraction and conformance suite.
  • kuatia-storage-sql — SQLite/PostgreSQL backend.
  • kuatia — async Ledger resource and saga commit pipeline.