Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog.
[Unreleased]
[0.11.0] - 2026-10-13
- Roadmap as forge issues (task-plus ADR 0004); release waits for the merge
Changed
ROADMAP.mdfollows task-plus ADR 0004: named epics of- #N textlines, each an open issue labelledroadmapon the Bytestone Forgejo; shipped items moved into this changelog under the versions that finished them.merge_wait: 10mintask-plus.yml, so a release's pull request is tagged and published in the same run once merged.CLAUDE.mdstates the code-flow level 1 practice: one branch per story, every change through a pull request.
[0.10.0] - 2026-10-13
[0.9.0] - 2026-10-13
- Policy as code: a parameter derived by code, the Policy contract, easyaccess/v2 tracking the bank's savings rate (gobank story 1.8.9)
Added
Declaration.Algorithm, a parameter derived by code: a function of the parameters it reads through the reader on a day, answering in the declaration's kind, for the bank's policy to express lag and take (gobank ADR-0006, ADR-0009).Declaration.IsDerivedis true of a formula or an algorithm.CheckDeclarationsrefuses a derived parameter that publishes a value, or one with both a formula and an algorithm.Policy, a bank's own rules as versioned code (gobank ADR-0007): its bank-scoped declarations and start-up check;CheckPolicy.SavingsRateKeyandLendingRateKeyname the bank's rates, which a policy declares and a tracking version reads.easyaccess/v2, Easy Access Tracker: the rate is the bank'ssavings_rate_bpsless 15 bps, floor 0, read from the bank's policy; its golden runs a cut mid-month.- testkit:
Reader, the parameter resolution alone over declarations and in-memory settings, which the Runner now reads through;SetMarket;CheckVersionWith, for a version whose start-up reads the bank.
Roadmap
PolicyandDeclaration.Algorithm, a parameter derived by code;easyaccess/v2tracking the bank's savings rate (gobank story 1.8.9)
[0.8.0] - 2026-10-12
- Posting.Step names a posting within its event (gobank ADR-0011); the day rule reads UTC days
Added
Posting.Stepnames a posting within the event the rule answered, so a runner records it against its cause, the account and the step and a replay finds the one already made (gobank ADR-0011).ApplyAccrued, the one posting the v1 rules make, names itapply.
Fixed
- The day rule read a day in the zone it was given, so a runner handing an
instant near midnight in another zone got positions keyed by a local
midnight no UTC-keyed ledger would find, and a value time at the local
day's end. A day is a UTC day (
Facts.Day, go-luca'sPosition.Day): the rule now reads the UTC day of any instant it is given (issue #2, go-luca's cross-timezone regression).
Added
- Tests ported from go-luca's retired interest suite (issue #2): a zero rate
accrues and applies nothing; the cross-timezone day;
BenchmarkInterestDay, the rule's cost per account-day with the facts in memory.
[0.7.0] - 2026-10-11
Fixed
overdraft/v1read overdrawn as a negative balance and refused past-limit. In the bank's view (gobank ADR-0008) an overdrawn current account is a debit balance, positive like a loan, so the limit is the most the balance may rise to. Its golden was the customer's way about: the withdrawal credited the account and the interest ran from the account toIncome:Interest. Regenerated (issue #1).
Changed
testkit.Runnerposts in the bank's view whatever the family:Depositcredits the account andWithdrawdebits it;DrawdownandRepayare the lending verbs. Lending tests that funded a loan withDepositnow draw it down, and their goldens say so.
Added
ScopeMarketandRiskFreeRateKey: a currency's official risk-free rate as a parameter at a scope of its own (gobank ADR-0009), declared by key alone and resolved by the runner for the currency of the product whose rules read it; written only by the market's feed.
[0.6.0] - 2026-10-10
[0.5.0] - 2026-10-10
[0.4.0] - 2026-10-10
- Products as versioned code (gobank ADR-0006, story 1.8.1): the version contract, six v1 packages, the feature framework retired
Added
- The product contract:
Version(identity, declared parameters, rules), nine events (StartUp,Open,PrePosting,PostPosting,Day,ParameterChange,Command,ChangeOfVersion,Close),Factsread through an interface,Intents(settings, postings, positions) returned,Refusalfor a rule's no. Rules are pure; the bank's runner carries the intents out. - Parameters as declarations with a scope (bank, version, account), a kind
(bps, money, int, cycle, day, text), a published value, or a derivation
from another parameter (spread, floor, cap).
CheckDeclarationsis the shared start-up check. gbp.Interest, the interest-bearing rules a version embeds: daily accrual on the closing balance, application when the cycle ends, theapply-interestcommand, close and change of version applying to date.- Six version packages, each with its own golden:
easyaccess/v1,fixedterm/v1(maturity fixed at open fromterm_months, withdrawals refused before it),isa/v1(deposits refused over the allowance),personalloan/v1,mortgage/v1,overdraft/v1(movements refused past the limit). The rates the bank held asfloat64are published basis points. The five 32-day goldens are byte-identical to the old framework's. testkit.Runner, the reference runner over an in-memory go-luca ledger: implementsFacts, resolves parameters by scope with effective-dated settings and derivations, carries out intents, surfaces refusals, logs reads.testkit.CheckVersion,testkit.RoundTrip.
Changed
AccrueandApplyAccruedare functions of the engine, not methods of a product;ApplyAccruedtakes the family and the description and always applies, the version deciding when.ApplicationCycle.Descriptionexported.- go-luca pinned at v0.5.0.
Removed
Product,Featureand the handler interfaces,SimContext,Simulation,ManagedAccount,ParameterStore,Clock, the catalogue constructors (EasyAccess()and the rest),RepaymentSchedule(monthly_repaymentwas never set by the bank),NextDay,ParamInterestApplication; testkit'sScenarioBuilder,GolucaScenarioand the FSMs. gobank stays on v0.3.0 until its story 1.8.2 adopts the contract.
Roadmap
- The product contract and six v1 version packages (gobank ADR-0006, story 1.8.1): rules pure over facts, intents carried out by the runner, parameters declared with scope, kind and derivation; the feature framework and simulation engine retired
- Golden
.golucatests per version, byte-identical to the framework's
[0.3.0] - 2026-10-05
- Product.Accrue and Product.Apply split the day rule for gobank stage 3 story (e); RateBps exported
Added
Product.AccrueandProduct.Apply, the two halves of the day rule (gobank ADR-0002 stage 3, story e).Accrueis the position at the end of a day with the day's interest accrued on the closing balance and nothing applied: pure and the same for any balance, so the daily pass writes it as the day's provisional projection and every event that moves the balance writes it again.Applybooks the cycle-end application from a position, and applying an applied position posts nothing, so the pass may revisit an account after a restart.NextDayis unchanged and isApplyofAccrue.RateBps, the conversion from a product's annual rate to the integer basis points the day rule accrues in, exported from the engine for callers that run the rules without it.
Roadmap
Accrue/ApplyAccrued: the day rule over go-luca positions, with the application cycle a parameter (gobank ADR-0002 stage 3)
[0.2.0] - 2026-10-05
-
Product.NextDay: the day rule as a pure function over go-luca positions; application cycle a product parameter; no separate month-end pass
-
Product.NextDay(gobank ADR-0002 stage 3, story c): the per-account day rule as a pure function — from the account's position at the end of the previous day (go-lucaPosition, balance and accrued interest as an exact fraction) and the day's closing balance to the position at the end of this day and the ledgerPostings it calls for. Interest accrues on the closing balance; when the product's cycle ends on the day the whole minor units are applied and the remainder carries forward. -
The application cycle is a product parameter,
interest_application:daily,monthly(the default, so the catalogue is unchanged) orannual.InterestAccrualrunsNextDayatEndOfDayand no longer handlesEndOfMonth; interest application is inside the daily pass.EndOfMonthremains for repayment schedules. -
AccountUpdateon an application day now hasClosingBalanceandAccruedNumeratorafter application,InterestAmountthe interest applied, andAccruedDeltathe day's accrual alone. Callers that derived the applied interest from the cached balance should useInterestAmount. -
Requires go-luca v0.3.0 (
Position,Fraction) and go-postgres v0.7.0. -
Simulation.AdoptAccount: put an account that already exists in the ledger under the engine's management (status, opened date, cached balance and parameters as the caller read them) without creating it or raising an AccountOpened event. A bank restarting over a stored ledger brings its accounts back this way. Rate resolution is shared withOpenAccount.
[0.1.10] - 2026-08-26
- Exact daily interest accrual in memory with monthly application; cached balances; PaceHook
[0.1.10] - 2026-08-26
- Rework InterestAccrual: exact integer daily accrual in memory (numerator over 10,000 x 365, remainder carried — sub-penny interest is no longer lost), applied to the account monthly as a single ledger movement. Previously interest posted daily to :Accrued sub-accounts and was never applied to balances.
- ManagedAccount gains CachedBalance (maintained by RecordMovement, removing per-day balance queries from end-of-day sweeps), RateBps, AccruedNumerator, and AccruedInterest().
- Simulation gains RefreshBalances (post-import cache priming) and PaceHook (lets single-threaded hosts yield during account sweeps).
- AccountUpdate gains AccruedDelta and AccruedNumerator.
[0.1.9] - 2026-08-24
- Bump go-luca to v0.2.31 (with go-postgres v0.5.5, gotreesitter v0.6.8); the previous go-luca v0.2.25 pin was unresolvable under the git.bytestone.uk module path
[0.1.6] - 2026-03-25
- Fix transaction directions and move interest logic to product layer
[0.1.5] - 2026-03-24
- Migrate dependencies from github.com/drummonds to codeberg.org/hum3
[0.1.4] - 2026-03-19
- working on interest feature
[0.1.3] - 2026-03-19
- updating checks after go-postgres update
[0.1.2] - 2026-03-17
- adding documentation
[0.1.1] - 2026-03-17
- Working on goluca integration
[0.1.0] - 2026-03-16
- fixing linter bug
Added
- Core types: EventType, Feature interface, Product, ManagedAccount, Clock, ParameterStore
- Simulation engine with event dispatch and time advancement
- Features: StatusLifecycle, InterestAccrual, DepositAcceptance, WithdrawalProcessing, TermLock, ISAWrapper, OverdraftFacility, RepaymentSchedule
- Product catalog: EasyAccess, FixedTerm, ISA, PersonalLoan, Mortgage, Overdraft
- Test infrastructure: testkit package with ScenarioBuilder, goluca assertions, golden file helpers