finance

package
v1.801.465 Latest Latest
Warning

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

Go to latest
Published: Aug 5, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

Documentation

Overview

Package finance is the SaaS business/finance dashboard (/v1/admin/finance) — the profitability panel: what we pay every vendor (COGS), what we earn, the gross margin, how fast we're burning the DigitalOcean promo credit, and the runway that credit + burn imply. SUPERADMIN ONLY (core.Admit).

It FABRICATES NOTHING and OWNS NO cost logic. COGS is the SINGLE source of truth in commerce (GET /v1/costs) — cloud CONSUMES it. Revenue + MRR come from commerce billing. The one direct vendor read that remains is the DigitalOcean promo-CREDIT balance + burn-down history — an ORTHOGONAL treasury view. The derived margin/runway math is a pure function (ComputeFinance) with a unit test proving the numbers.

Per-provider UPSTREAM credit ledger + usage funding split for admin.hanzo.ai.

TWO-LEDGER MODEL (do not conflate):

  • UPSTREAM (this file): what WE spend at each provider — provider promo credit (grant) burning down to paid. DigitalOcean's $26k GenAI credit is the first real row; DO's live remaining/burn/runway come from the DO billing API (reused from finance.go), every provider's burn from the ONE cloud_usage ledger. Grants are fixed contractual numbers seeded here (not a live vendor read); move to KMS/config when there is more than one.
  • DOWNSTREAM (clients/commerce): what we bill OUR customers (credit/prepaid/card). Orthogonal — never mixed with the upstream provider credits above.

Two SuperAdmin endpoints (the console renders them; this is the authoritative contract). Both reuse the admin gate + the cloud_usage warehouse — no new datastore, no duplicate reads.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AvgDailyBurnCents

func AvgDailyBurnCents(monthToDateSpendCents int64, now time.Time) int64

AvgDailyBurnCents derives the average daily DO burn from month-to-date usage: month-to-date spend divided by the number of elapsed days in the current month (at least 1, so day 1 doesn't divide by zero).

func Routes

func Routes(z *zip.App, s *cloud.Service[core.State])

Routes registers the finance dashboard (SuperAdmin only).

Types

type BackfillIn

type BackfillIn struct {
	// Org is the tenant to migrate. Required — there is no fleet-wide form of this
	// cutover, because each org must be reconciled on its own.
	Org string `json:"org"`
}

BackfillIn is the POST /v1/admin/finance/backfill input.

type BackfillOut

type BackfillOut struct {
	Status string      `json:"status"`
	Msg    string      `json:"msg"`
	Data   *Backfilled `json:"data"`
}

BackfillOut is the POST /v1/admin/finance/backfill envelope.

func Backfill

func Backfill(ctx context.Context, in *BackfillIn) (*BackfillOut, error)

Backfill carries ONE org's current commerce prepaid balance into the native finance wallet — the one-time cutover between the two ledgers.

It is IDEMPOTENT: the deposit uses the fixed ref "backfill:<org>", so re-running it credits the wallet at most once. Safe to retry.

The pre-migration balance is read from the CO-RESIDENT commerce ledger, not over HTTP: the admin HTTP client dials an unroutable in-process address and would read $0, and a phantom zero would silently carry nothing while reporting success. When commerce is not co-resident this fails rather than migrating nothing.

Example: {"org":"acme"} Response: {"status":"ok","msg":"","data":{"org":"acme","migratedCents":50000,"entryId":"fe_01J"}}

type Backfilled

type Backfilled struct {
	// Org is the tenant migrated.
	Org string `json:"org"`
	// MigratedCents is the balance carried across, read from commerce BEFORE the move.
	MigratedCents int64 `json:"migratedCents"`
	// EntryID is the finance ledger entry created, or "" when the balance was
	// non-positive and there was nothing to carry.
	EntryID string `json:"entryId"`
}

Backfilled is the cutover receipt.

type DoCost

type DoCost struct {
	Configured            bool             `json:"configured"`
	Error                 string           `json:"error,omitempty"`
	CreditRemainingCents  int64            `json:"creditRemainingCents"`
	MonthToDateSpendCents int64            `json:"monthToDateSpendCents"`
	AvgDailyBurnCents     int64            `json:"avgDailyBurnCents"`
	AccountBalanceCents   int64            `json:"accountBalanceCents"`
	GeneratedAt           string           `json:"generatedAt,omitempty"`
	History               []DoHistoryPoint `json:"history"`
}

DoCost is the DigitalOcean credit + spend view. When Configured is false every number is zero and the console renders the honest "connect DO_API_TOKEN" state.

type DoHistoryPoint

type DoHistoryPoint struct {
	Date        string `json:"date"`
	AmountCents int64  `json:"amountCents"`
	Type        string `json:"type"`
	Description string `json:"description"`
}

DoHistoryPoint is one credit burn-down series point (usage charge over time).

type FinanceCost

type FinanceCost struct {
	Configured bool              `json:"configured"`
	Error      string            `json:"error,omitempty"`
	Period     string            `json:"period"`
	TotalCents int64             `json:"totalCents"`
	Vendors    []commerce.Vendor `json:"vendors"`

	DigitalOcean DoCost `json:"digitalocean"`
}

FinanceCost is the platform COGS view — what WE pay our vendors. Its authority is commerce GET /v1/costs: TotalCents is the whole-platform COGS the margin math folds, and Vendors is the per-vendor breakdown. Configured is false (and every number 0) when commerce /v1/costs is unreachable.

DigitalOcean here is an ORTHOGONAL treasury view (promo-credit remaining + burn-down), NOT part of COGS: it feeds only the runway projection.

type FinanceData

type FinanceData struct {
	Cost        FinanceCost         `json:"cost"`
	Revenue     FinanceRevenue      `json:"revenue"`
	Derived     FinanceDerived      `json:"derived"`
	GeneratedAt string              `json:"generatedAt"`
	Sources     []core.SourceStatus `json:"sources"`
}

FinanceData is the full /v1/admin/finance aggregate.

func Compute

func Compute(s *cloud.Service[core.State], ctx context.Context, cr iam.Creds) FinanceData

Compute gathers the cost/revenue inputs and folds them through ComputeFinance. It is split out of the handler so the consolidated money board (/v1/admin/money) reports the SAME infrastructure cost and margin this endpoint serves — one aggregation, two views. (ComputeFinance stays the PURE fold; this is the I/O half in front of it.)

func ComputeFinance

func ComputeFinance(in FinanceInput) FinanceData

ComputeFinance is the PURE derivation: given the multi-vendor COGS view and the commerce revenue view, it computes gross margin, margin %, runway, and profitability. No I/O.

grossMarginCents = revenue - COGS(total, all vendors)
grossMarginPct   = grossMargin / revenue * 100          (0 when revenue is 0)
runwayDays       = DO creditRemaining / DO avgDailyBurn  (nil when burn 0 or DO off)
profitable       = revenue > COGS

type FinanceDerived

type FinanceDerived struct {
	GrossMarginCents int64    `json:"grossMarginCents"`
	GrossMarginPct   float64  `json:"grossMarginPct"`
	RunwayDays       *float64 `json:"runwayDays"`
	Profitable       bool     `json:"profitable"`
}

FinanceDerived is the pure profitability math. Runway is a pointer so it can be null (no honest runway when burn is zero or DO is unconfigured).

type FinanceInput

type FinanceInput struct {
	Cost        FinanceCost
	Revenue     FinanceRevenue
	GeneratedAt string
	Sources     []core.SourceStatus
}

FinanceInput is the raw material ComputeFinance folds into FinanceData. The handler fills Cost from the commerce COGS read (+ the DO-credit treasury view) and Revenue from commerce billing; the pure function does the math so the derivation is unit-testable in isolation.

type FinanceOut

type FinanceOut struct {
	Status string       `json:"status"`
	Msg    string       `json:"msg"`
	Data   *FinanceData `json:"data"`
}

FinanceOut is the GET /v1/admin/finance envelope.

type FinanceRevenue

type FinanceRevenue struct {
	Configured           bool  `json:"configured"`
	TotalRevenueCents    int64 `json:"totalRevenueCents"`
	MRRCents             int64 `json:"mrrCents"`
	CreditsConsumedCents int64 `json:"creditsConsumedCents"`
}

FinanceRevenue is the commerce revenue view (all money in USD cents).

type ProviderCredit

type ProviderCredit struct {
	Provider       string   `json:"provider"`
	GrantCents     int64    `json:"grant_cents"`
	BurnCents      int64    `json:"burn_cents"`
	RemainingCents int64    `json:"remaining_cents"`
	RunwayDays     *float64 `json:"runway_days"` // nil when burn is 0 / unknown (never a fabricated infinity)
	HasCredit      bool     `json:"has_credit"`
	IsPaidOnly     bool     `json:"is_paid_only"`
}

ProviderCredit is one provider's upstream credit ledger row.

type ProvidersCreditOut

type ProvidersCreditOut struct {
	Status string           `json:"status"`
	Msg    string           `json:"msg"`
	Data   []ProviderCredit `json:"data"`
}

ProvidersCreditOut is the GET /v1/admin/providers/credit envelope. This read carries no total: it is a fixed roster of providers, not a page.

type UsageFundingIn

type UsageFundingIn struct {
	// From is the inclusive start of the window. Unparseable or absent, together with
	// To, falls back to the last 30 days.
	From string `json:"from"`
	// To is the exclusive end of the window.
	To string `json:"to"`
}

UsageFundingIn is the GET /v1/admin/usage/funding window.

type UsageFundingOut

type UsageFundingOut struct {
	Status string            `json:"status"`
	Msg    string            `json:"msg"`
	Data   []UsageFundingRow `json:"data"`
}

UsageFundingOut is the GET /v1/admin/usage/funding envelope. No total: the split is one row per (provider, model) over the window, unpaginated.

type UsageFundingRow

type UsageFundingRow struct {
	Provider  string `json:"provider"`
	Model     string `json:"model"`
	Funding   string `json:"funding"` // credit | paid | paid_only | byo
	Tokens    int64  `json:"tokens"`
	CostCents int64  `json:"cost_cents"`
	Requests  int64  `json:"requests"`
}

UsageFundingRow is one (provider, model) usage roll-up tagged by funding class.

Jump to

Keyboard shortcuts

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