bucket

package
v1.49.21 Latest Latest
Warning

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

Go to latest
Published: Jul 26, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package bucket is the ONE place that classifies commerce ledger transactions into the three money buckets the console + GPU policy read, and derives the per-bucket balances from the REAL tagged ledger — never a fabricated split.

The buckets (see the spend policy in Split):

  • Credit (granted) — promotional/starter grants, DO-backed, NON-cash. A Deposit tagged "starter-credit" (billing/credit) or "included-credit:YYYY-MM" (billing/allotment) or a "credit:"/"grant:" prefix. Usable for non-GPU compute; NEVER usable for GPUs.
  • Prepaid (real money) — funds the customer deposited via card top-up (deposit.go/topup.go: a Deposit tagged "topup", "husd", or a bare/other deposit). Real money. Usable for metered usage AND the ONLY bucket GPUs may draw from.
  • Card — a payment method on file (square_cardonfile). Not a ledger balance; surfaced separately (bucket only reports whether GPU spend is card-gated).

DECOMPLECTED (Hickey): this file is PURE money math over a slice of transactions — no datastore, no gin, no I/O. WHO reads the ledger (models/transaction/util) and WHO displays it (api/billing, the console) are separate concerns. The split is a projection of the same transactions the balance the gateway debits is computed from, so it reconciles to the cent:

CreditsRemaining + PrepaidRemaining == Balance   (always)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsGPUWithdrawal

func IsGPUWithdrawal(tags string) bool

IsGPUWithdrawal reports whether a Withdraw draws GPU compute — the spend that is barred from credits and must come ONLY from prepaid real money. GPU debits are tagged "gpu" / "gpu-<...>" / "gpu:<...>" by the GPU charge path.

Types

type Kind

type Kind int

Kind is the bucket a DEPOSIT funds: non-cash Credit or real-money Prepaid.

const (
	// Prepaid is the default for any deposit not explicitly a grant — real money
	// (card top-up, HUSD, settlement, manual). Defaulting UNKNOWN→Prepaid is the
	// fail-closed choice: an un-tagged deposit is treated as real money the
	// customer can spend on GPUs, never as free credit — so a tagging gap can
	// never silently mint spendable-on-GPU value out of a grant.
	Prepaid Kind = iota
	// Credit is a non-cash grant (starter/welcome, plan-included allotment,
	// promo). Spendable on non-GPU usage only.
	Credit
)

func DepositKind

func DepositKind(tags string) Kind

DepositKind classifies a Deposit transaction by its Tags into Credit vs Prepaid. Only the grant tags map to Credit; everything else (topup, husd, bare deposit, settlement) is real-money Prepaid.

type Split

type Split struct {
	// CreditsGranted is the total non-cash credit EVER granted (incl. expired) —
	// the "granted" figure. Display: "Credits: $X granted".
	CreditsGranted currency.Cents `json:"creditsGranted"`
	// CreditsRemaining is the non-cash credit still spendable now (active grants
	// minus non-GPU spend, credits-first). Display: "$Y left". Also surfaced under
	// the alias `trialBalance` (see bucketFields) — "trial" and "credit" name the
	// SAME non-cash bucket (starter/welcome/comp grants); the alias is the
	// consumer-facing name so a UI reads trial-vs-prepaid without ambiguity.
	CreditsRemaining currency.Cents `json:"creditsRemaining"`
	// PrepaidBalance is the real-money balance still on the ledger (deposits minus
	// the spend charged against prepaid). GPUs draw ONLY from this.
	PrepaidBalance currency.Cents `json:"prepaidBalance"`
	// PrepaidAvailable is PrepaidBalance minus holds — the amount a new prepaid
	// (GPU or metered) charge may actually draw. The GPU gate reads this.
	PrepaidAvailable currency.Cents `json:"prepaidAvailable"`

	// Balance/Holds/Available mirror the existing ledger fields so a bucketed read
	// is a superset of GetBalance's shape (backward compatible).
	Balance   currency.Cents `json:"balance"`
	Holds     currency.Cents `json:"holds"`
	Available currency.Cents `json:"available"`
}

Split is the per-currency bucket projection derived from the real ledger. All amounts in cents. It reconciles to the ledger balance exactly:

CreditsRemaining + PrepaidRemaining == Balance
Available                          == CreditsRemaining + PrepaidAvailable

func Compute

func Compute(transs []*transaction.Transaction, id string, now time.Time) Split

Compute derives the bucket split for ONE currency from the RAW transactions (source- and destination-side, NOT pre-filtered for expiry). now is the instant expiry is evaluated against (injected for testability).

Spend policy (documented, enforced consistently with the GPU charge path):

  • Non-GPU usage draws CREDITS FIRST, then prepaid — so free grants are spent before the customer's real money, exactly what a customer expects.
  • GPU usage draws ONLY prepaid real money — never credits. GPU debits are tagged so they reduce prepaid directly and can never consume a grant.

Because both classes reduce the same ledger, the arithmetic is:

creditsRemaining = max(0, creditsActive - nonGpuSpend)
prepaidBalance   = prepaidActive - gpuSpend - max(0, nonGpuSpend - creditsActive)

which sums to (creditsActive + prepaidActive - nonGpuSpend - gpuSpend) = the ledger balance — no value invented or lost.

Jump to

Keyboard shortcuts

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