Book of Record (BoR) & Double-Entry Ledger
This document organizes the core concepts, architectural decisions, and design rules around Books of Record, double-entry accounting, and how bank feed providers fit (and do not fit) into a General Ledger architecture.
1. What is a Book of Record (BoR)?
A Book of Record is the authoritative financial ledger that legally defines:
- Account balances
- Transaction history
- Ownership of funds
- Financial position for audit, tax, and regulatory purposes
If there is ever a dispute, reconciliation issue, or audit, the BoR is the final source of truth.
What a BoR does
- Records finalized, posted transactions
- Enforces double-entry accounting
- Maintains immutable history
- Supports audits, reversals, and period close
What a BoR is not
- A UI balance
- A payments processor
- A data warehouse
- A bank feed or aggregator
2. Double-Entry Ledger (Definition)
A double-entry ledger records every economic event with at least two equal and opposite entries:
Invariant: Σ(debits) = Σ(credits) (per currency)
Core elements
- Accounts (Chart of Accounts)
- Assets, Liabilities, Equity, Revenue, Expenses
- Journal Entries
- One logical economic event
- Journal Lines
- Debit or Credit to a single account
- Posting Rules
- Balanced entries only
- Immutable once posted
Simple example
Pay $500 rent from cash:
| Account | Debit | Credit |
|---|---|---|
| Rent Expense | 500 | |
| Cash | 500 |
3. Bank Feed Providers — Role and Limits
Bank feed providers (OFX/QBO/QFX file imports, or API-based providers such as Plaid) are not a Book of Record.
What a bank feed provider is
- Bank connectivity
- Transaction ingestion
- Data normalization
- Metadata enrichment
What a bank feed provider is not
- A ledger
- A posting engine
- An audit system
- A double-entry system
- A legal source of truth
4. Where Bank Feeds Fit in a BoR / GL Architecture
Bank Accounts
↓
Bank Feed Import (OFX / QBO / QFX file, or API provider)
↓
Ingestion & Matching Layer
↓
Your Double-Entry Ledger ← Book of Record
↓
Reporting, Tax, APIs
Key principle:
Your ledger must remain correct even if the bank feed provider is unavailable, delayed, or revised.
5. Do You Need Your Own Book of Record?
If your system allows users to:
- Categorize or reclassify transactions
- Split transactions
- Create invoices or bills
- Record accruals or adjustments
- Close accounting periods
- Produce a P&L or Balance Sheet
Then you are operating a Book of Record, whether you intended to or not.
6. Audit-Safe Mutation Rules
- Append-only: no updates or deletes on posted entries
- Draft → Posted lifecycle
- Corrections via reversal or delta adjustments
- Closed periods are immutable
- Idempotent external references
- Full audit trail for all actions
7. Core BoR Data Model (Conceptual)
Accounts
- account_id
- type (ASSET, LIABILITY, EQUITY, REVENUE, EXPENSE)
- currency
Journal Entry
- journal_entry_id
- source
- effective_date
- posted_at
- status
Journal Line
- journal_line_id
- journal_entry_id
- account_id
- debit | credit
- amount
Balances are derived, never authoritative.
8. Ledger Service Boundaries
Current implementation: the ledger is a module within the Node.js service — not a separate microservice. This is the right call for MVP: it avoids distributed-system complexity while keeping domain boundaries clean.
Future path: extract into a standalone microservice as load and team size warrant.
Benefits of a standalone ledger service when the time comes:
- Single source of accounting truth
- Centralized invariant enforcement
- Clear audit boundary
- Clean integration with domain services
9. Mermaid Diagrams
High-level flow
Audit-safe correction
10. Key Takeaways
- A Book of Record defines money
- Double-entry is mandatory
- Bank feed imports are input-only — they are never the source of truth
- If users can correct data, you own the BoR
- A modular ledger with clean boundaries scales into a standalone service when needed