Package
@flashylabs/rails
The settlement and authorisation layer of Flashy Finance: a thin service over @flashylabs/ledger that holds Flashy Gold, issues rule-bound rewards, enforces the draft → execute consent gate, and honours attenuated flashyID grants.
version 1.0.0 · measured 2026-10-19 from a checkout · source: flashy-rails
npm i @flashylabs/railsIt adds product rules on top of the ledger and nothing else — issuance must be rule-bound, value moves only with consent, delegated spend is capped by an attenuated grant. A ledger rule re-implemented here belongs in the ledger; the money invariants (no negative balance, opaque identity, idempotent replay) live in one place.
draftRedeem and draftTransfer are pure and write nothing, so an agent may call them; execute requires a consent token bound to that exact draft and holder and is the only method that moves a holder’s value out. There is no auto-approval at any tier. Tests run against the real ledger (InMemoryLedgerStore), never a mock — a mocked ledger would let a rule drift from the engine it runs on.
Edge cases — each one paid for once
A bigint literal is a bug, not a precision upgrade
Minor is a branded integer number. A 2000n literal throws "Cannot mix BigInt and other types" the moment it meets a ledger amount — caught by the suite on its first run. Convert at the edge with toMinor / toGold and use the ledger’s add / negate, never raw operators.
A dedup replay must not draw a grant down twice
The ledger de-duplicates an idempotent replay and settles once; if the rail charged the grant before reading result.deduplicated, a retried request would spend the delegated cap twice for one settlement. spendUnderGrant checks the flag first.