Skip to Content
Fund AccountingOverview

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:

  1. Determinism. Every evaluator is pure over its inputs; every money operation goes through exact-decimal bigint helpers (no IEEE floats); and every material output carries a canonical-JSON hash (application_hash, payload_hash, input_hash/output_hash on calculation_runs). Two runs over the same bytes produce the same bytes.
  2. 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.
  3. 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

ADRWhat it pins
docs/adrs/0001-canonical-record-contract.mdThe <Domain>Application / <Domain>ApplicationTrace contract
docs/adrs/0002-runtime-persistence-trace-separation.mdThe package boundary + row-adapter identities
docs/adrs/0005-asc-946-820-fair-value-accounting.mdFair-value marks as first-class GL entries
docs/adrs/0010-pcap-component-balance-projection-layer.mdPer-LP PCAP as a projection, never a second ledger
docs/adrs/0011-venture-waterfall-fee-and-carry-economics.mdVenture economics invariants and levers
docs/adrs/0019-economic-terms-payload-as-ir.mdThe 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).

Last updated on