Specification · bankrec @ 0.1

bankrec — Bank Reconciliation · Area Specification

last conformance run: 4/4 scenarios pass · 7 acts mapped 2026-10-24 20:21 UTC

Spec

Status: 0.1. The bank statement against the books, per account and statement: every difference named, every deposit tied to the payment it is, and a reconciliation a person signs. The check an accountant makes first, on the statements these books already import.

1. Calibration: who this is for

A small business and its accountant. The owner records a customer's payment the day the remittance arrives; the bank shows it days later, sometimes as one deposit for three checks. The accountant wants to see, for the statement ending on a day: the bank's balance, the books' balance, and the short list of items that explain the gap, each one named. Then a person's sign-off that it was looked at.

2. Scope

In: matching a statement row to the payments and refunds recorded here (one row to one or more), the reconciliation of an account at a statement's end, suggestions for matches, a person's sign-off kept as it stood, and whether the record has changed since.

Out (§9): bank feeds, matching statement rows to bills or adjusting entries (bills already link their payment's row), cash on hand, foreign currency revaluation, undoing a sign-off.

3. Entities and lifecycles

4. The acts

Writes: match, unmatch, sign_off (a person's act).

Reads: accounts (each bank and card account with its latest statement and whether it is reconciled), reconciliation (an account through a statement's last day), candidates (suggested matches, with why), signoffs.

5. Invariants

6. Required read models

accounts, reconciliation (the three item lists with their totals, the difference, what blocks a sign-off), candidates (per unmatched row: the cash items that fit, by amount, date and name), signoffs (with whether the record has changed since each).

7. Contract vs freedom

Contract: exact matches, a named difference, the person's sign-off, kept as it stood. Freedom: how the agent finds matches, how often to reconcile.

8. Conformance (scenarios)

01 a deposit is matched to its payment and stops being left out · 02 a match that does not add up, or a row already booked, is refused · 03 a payment not yet on the statement is listed in transit and the reconciliation ties · 04 the agent cannot sign off. The person's sign-off and the changed-since check are contract gate 20, because scenarios run as an agent.

9. Out of scope, on purpose

Bank feeds (statements arrive as files the agent reads), matching rows to bills (a bill's payment already links its row), cash on hand, revaluing foreign currency, and withdrawing a sign-off: a sign-off is a record of what someone looked at, and a later change shows as one.

Acts

ActKindRequired
matchwritetransaction items reason
unmatchwritematch reason
sign_offwriteaccount through reason
accountsreadnone
reconciliationreadaccount
candidatesreadnone
signoffsreadnone

Invariants

IdInvariant
REC-1Money is integer cents; a match adds up to its row exactly, in the row's currency.
REC-2Statement = books - recorded here and not on the statement + on the statement and not in the books; a leftover difference is named.
REC-3A matched row posts nothing itself and cannot be reviewed again while matched; nothing is in two matches.
REC-4Only a row that posts nothing can be matched; a row already booked is refused, naming what it is.
REC-5Signing off is a person's act, refused to an agent, and refused while the difference is not zero or a row is unaccounted for.
REC-6A sign-off keeps the reconciliation as it stood; a later change shows as changed since.
REC-7Suggestions suggest, never match.
REC-8Every write is a logged command with an actor; refusals are logged too.

Scenarios

Each scenario is a file of acts with expected outcomes. ok means the act must succeed with the listed fields; refused means the act must be refused with a sentence containing the listed text. Refusals are contract.

a deposit is matched to the payment it is pass

REC-3, REC-7: the deposit is suggested as the payment, matched with a reason, and then posts nothing itself; the account ties.
Environment: create_customer, record_payment, import_statement
#ActExpectWhy
1candidatesok count=1REC-7: a suggestion, nothing matched yet
2reconciliationok ready=falsethe deposit is not in the books yet and the payment is not matched
3matchok state="matched"
4reconciliationok ready=true difference=0 books=600000 matched=1REC-2, REC-3: matched once, the books equal the statement

a match that does not add up, or a row already booked, is refused pass

REC-1, REC-4: matches are exact, and a row booked as income cannot also be a payment.
Environment: create_customer, record_payment, record_payment, import_statement
#ActExpectWhy
1matchrefused A match is exactREC-1
2review_transactionok
3matchrefused count the money twiceREC-4

a payment not on the statement yet is in transit, and the account ties pass

REC-2: the check recorded on the 28th is not on April's statement; it is named in transit and the rest ties to the cent.
Environment: create_customer, record_payment, import_statement
#ActExpectWhy
1reconciliationok ready=falsethe service charge is not reviewed
2review_transactionok
3reconciliationok ready=true difference=0 books=548500 printed=498500REC-2: statement 4,985.00 = books 5,485.00 - 500.00 in transit

the agent cannot sign off a reconciliation pass

REC-5: signing off is a person's act, whatever the agent's role; the refusal is logged.
Environment: import_statement, review_transaction
#ActExpectWhy
1reconciliationok ready=true
2sign_offrefused person's actREC-5
3signoffsok count=0

These pages are generated from the files in specs/ in the repository; scenarios are executed by src/conformance.js on every build. Written and maintained by Peter Varga, who also runs Portland AI Works. github.com/alviso/saybooks, AGPL-3.0.