Work with the OpenMeter ledger package. Use when modifying ledger code, writing ledger tests, or debugging ledger issues.
Guidance for working with the OpenMeter ledger package (openmeter/ledger/).
openmeter/ledger/ — core interfaces and primitives: Ledger, Account, SubAccount, Querier, routing, validation, account type definitionsopenmeter/ledger/historical/ — current concrete ledger implementation; books immutable transactions and computes balances by summing entriesopenmeter/ledger/account/ — account and sub-account domain types, posting addresses, route-backed sub-account identityopenmeter/ledger/account/service/ — account service; New(repo, liveServices) self-wires SubAccountService into AccountLiveServicesopenmeter/ledger/account/adapter/ — ent repo adapteropenmeter/ledger/resolvers/ — AccountResolver implementation; provisions per-customer accounts and shared business accountsopenmeter/ledger/resolvers/adapter/ — ent repo for customer→account mappingopenmeter/ledger/transactions/ — transaction templates, resolution, and prioritized customer-credit collection helperscustomer_fbo currently means customer credit/stored value, not a literal regulated FBO bank account. It includes prepaid, promotional, externally purchased, and similar credit sources.customer_receivable tracks value the customer owes but has not yet paid.customer_accrued is a staging account for acknowledged usage/spend that is not yet recognized as earnings for reporting.wash represents the outside world / external cash boundary and is expected to run negativeearnings receives recognized revenue from accruedbrokerage is the business-side offset used in FX flowsledger.Route and encoded into a routing key.currency for all account typescredit_priority for customer credit (customer_fbo) routing and collection ordercost_basis for FX-related routingtax_code and features are wired through routing and query code but are deferred from the current business flows.Route values in higher-level domain code:
CustomerFBORouteParamsCustomerReceivableRouteParamsCustomerAccruedRouteParamsBusinessRouteParamsopenmeter/ledger/transactions/ encode posting mechanics, not settlement-mode orchestration.IssueCustomerReceivableTemplate: customer credit +, customer receivable -FundCustomerReceivableTemplate: wash -, customer receivable +CoverCustomerReceivableTemplate: customer credit -, customer receivable +TransferCustomerFBOToAccruedTemplate: collect from prioritized customer credit sub-accounts into accruedTransferCustomerReceivableToAccruedTemplate: receivable -, accrued +RecognizeEarningsFromAccruedTemplate: accrued -, earnings +ConvertCurrencyTemplate: customer credit and brokerage postings on both source and target legsTransferCustomerFBOToAccruedTemplate currently supports partial collection. If no value can be collected it returns nil.transactions/ into a dedicated package.account/service.New takes account.AccountLiveServices; Locker is required for customer-account locking and Querier is required for balance lookups.historical.NewLedger(repo, accountService, locker) is the concrete runtime ledger.historical.Ledger.CommitGroup validates balanced transactions, locks affected customer accounts, creates a transaction group, then books transactions.CommitGroup applies to customer FBO and customer receivable accounts. Balance-consistency validation is still largely TODO territory.resolvers.AccountResolver provisions:
customer_fbo, customer_receivable, customer_accrued)wash, earnings, brokerage)go test runs, set POSTGRES_HOST=127.0.0.1 so Postgres-backed tests are not skipped.openmeter/ledger/testutils/integration.go is the main integration fixture for the ledger domain. It sets up:
openmeter/ledger/transactions/ are a good source of business-domain examples and expected balances.openmeter/ledger/historical/adapter/ledger_test.go are the best reference for query/filter behavior and migration-backed setup patterns.Prefer direct command execution for ledger verification. Do not wrap commands in sh -lc, bash -lc, or similar helper shells when a direct invocation works. If a Nix shell is required, use nix develop --impure .#ci -c env POSTGRES_HOST=127.0.0.1 go test ... rather than an extra shell wrapper.
# Run all ledger tests
POSTGRES_HOST=127.0.0.1 go test -tags=dynamic -v ./openmeter/ledger/...
# Run specific sub-packages
POSTGRES_HOST=127.0.0.1 go test -tags=dynamic -v ./openmeter/ledger/historical/...
POSTGRES_HOST=127.0.0.1 go test -tags=dynamic -v ./openmeter/ledger/account/...
POSTGRES_HOST=127.0.0.1 go test -tags=dynamic -v ./openmeter/ledger/transactions/...