Fund Accounting & Fund Economics
This section covers the heart of OpsDNA: the machinery that turns a fundβs legal terms (an LPA, side letters) and its economic events (capital calls, wires, marks, distributions) into an audit-grade general ledger, per-LP capital accounts (PCAP), and Carta-shaped financial statements. Everything here is deterministic because the numbers face auditors and LPs: every figure on a statement must be re-derivable from pinned inputs and provable, not merely stored.
The one-paragraph mental model
Economic policy lives as typed IR payloads in vehicle_terms_versions
(ADR-0019 β βthe payload IS the IRβ). At close time, evaluators in
packages/fund-economics/src/runtime/ decode those payloads and apply them to
snapshotted facts, emitting canonical <Domain>Application records wrapped
in <Domain>ApplicationTrace bundles (ADR-0001). Persistence narrows the
canonical records into <Domain>ApplicationRow projections through adapter
pairs (ADR-0002) and writes them alongside dimensioned GL journal entries
produced by the ledger kernel (packages/ledger/src/kernel.ts). Per-LP
PCAP is a rebuildable projection of that canonical state (ADR-0010), and
statements are built from the GL + projections by
packages/fund-statements-builder. The Acceptance Lab
(apps/acceptance-lab) runs whole synthetic funds through this pipeline and
asserts the statements tie out.
Flow: runtime β trace β persistence β statements
Why the separation exists
Three properties drive nearly every boundary in this domain:
- Determinism. Every evaluator is pure over its inputs; every money
operation goes through exact-decimal
biginthelpers (no IEEE floats); and every material output carries a canonical-JSON hash (application_hash,payload_hash,input_hash/output_hashoncalculation_runs). Two runs over the same bytes produce the same bytes. - Re-derivation. Projections (PCAP component balances,
fund_terms_index) are never systems of record β they can always be rebuilt from canonical GL lines, subledger entries, or terms payloads, and they carry source hashes so staleness is detectable, never silent. - Audit. A statement line traces back through
journal_line β source_event β calculation_run β terms-version link set, and the runtime trace bundles explain why each decision was made (branch selection, carry-rate lookup chains, per-tier arithmetic steps).
The boundaries have teeth. Runtime code under
packages/fund-economics/src/runtime/ may not import persistence row types;
non-adapter persistence code may not import *Application/*Trace types
(ADR-0002); and engines are banned from reading the fund_terms_index
projection (ADR-0019 Β§2). These rules are enforced by
scripts/check-package-boundaries.ts and boundary tests β a violation fails
bun run verify, not just review.
Pages in this section
Key ADRs
| ADR | What it pins |
|---|---|
docs/adrs/0001-canonical-record-contract.md | The <Domain>Application / <Domain>ApplicationTrace contract |
docs/adrs/0002-runtime-persistence-trace-separation.md | The package boundary + row-adapter identities |
docs/adrs/0005-asc-946-820-fair-value-accounting.md | Fair-value marks as first-class GL entries |
docs/adrs/0010-pcap-component-balance-projection-layer.md | Per-LP PCAP as a projection, never a second ledger |
docs/adrs/0011-venture-waterfall-fee-and-carry-economics.md | Venture economics invariants and levers |
docs/adrs/0019-economic-terms-payload-as-ir.md | The payload IS the IR; fail-closed profiles |
Related sections: Entity Model (which vehicle owns which economics), Persistence (repositories, RLS, migrations), Source Pipeline (how bank events become ledger source events).