finance

package
v1.801.307 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 28, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package finance is the ZAP-native money subsystem: a per-CUSTOMER, double-entry PREPAID WALLET on the native ledger core. It is the in-process implementation of cloud's types.FinanceClient (package alias finance.Client, mirroring commerce.Client) — the ONE money seam the ai prepaid gate, the admin grant, and the edge meter all bill through.

ONE LIGHTWEIGHT FILE PER ORG. Each org's books are an isolated Hanzo Base (SQLite) file at <dataDir>/orgs/<org>/finance.db (a separate <...>/finance-test.db for sandbox money, so test and live never mix). There is NO shared or relational database — the file IS the tenant boundary, so one org's wallet writes can never appear in another org's read. A file opens on first use and is cached; opens are serialized so a concurrent first touch opens exactly once.

MONEY-SAFETY. Every write is a BALANCED double-entry posting inside the org's own file: a deposit is funding:platform → wallet (credit the customer, debit the platform float); a usage debit is wallet → revenue:platform (debit the customer, credit platform revenue) — so every customer debit IS a platform-revenue credit in one atomic entry, and a file's postings always sum to zero. Both writes are idempotent on their ref (the ledger's (kind,program,ref) idempotency): a usage debit on RequestID and a deposit on DepositInput.Ref, so a retried debit or a fixed-ref backfill posts AT MOST ONCE; a deposit with an empty Ref takes a fresh ref and stays additive (grants stack). Amounts are int64 minor units (USD cents) — no float ever touches a balance. A balance read is the settled ledger balance, clamped at zero; transient holds are the caller's in-pod concern, never persisted here.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func MigrateOrg

func MigrateOrg(ctx context.Context, org string, balanceCents int64) (string, error)

MigrateOrg carries an org's existing prepaid balance into its native finance wallet, EXACTLY ONCE — the cutover primitive that moves each tenant's money from the legacy commerce ledger onto the ONE finance ledger. It deposits balanceCents into org's pooled wallet (subject == the org slug) under the FIXED idempotency ref "backfill:<org>", so a re-run (a retried operator call, a replayed job) finds the existing entry and credits the wallet at most once — returning the original entry id, moving no money. A non-positive balance is skipped ("" , nil): there is nothing to carry. It resolves the process-wide finance client published at boot; a nil client (finance not co-resident on this deployment) is an error, since there is no wallet to migrate into.

func New

func New(dataDir string) *ledgerFinance

New returns a finance client rooting each org's prepaid wallet file under dataDir (<dataDir>/orgs/<org>/finance.db, or finance-test.db in sandbox mode). Files open lazily on first use.

func Publish

func Publish(c Client)

Publish records the process-wide finance client. Called once at boot; nil clears.

func SetUsageHook

func SetUsageHook(h func(org string, test bool, project, service string))

SetUsageHook installs the post-debit hook (the cap alert-fire). Pass nil to clear.

Types

type Client

type Client = types.FinanceClient

Client is the in-process inter-subsystem seam cloud's money paths call. It IS cloud's types.FinanceClient — one narrow interface (BalanceCents + Deposit + RecordUsage), kept as an alias so a value satisfies both names with no adapter (mirrors commerce.Client).

func Current

func Current() Client

Current returns the published finance client, or nil before Publish (a consumer treats nil as "money layer not co-resident" and fails closed).

type UsageRow

type UsageRow struct {
	ID        string `json:"id"`
	Cents     int64  `json:"cents"`
	Model     string `json:"model"`
	CreatedAt int64  `json:"createdAt"`
}

UsageRow is one recorded usage debit — the READ twin of RecordUsage. The SAME wallet→revenue posting a metered call wrote is read back here, so the usage a customer SEES is exactly what drained their wallet. Cents is the debit magnitude (USD minor units); Model is the metered-unit label the debit carried (Entry.Memo); CreatedAt is unix seconds.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL