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 ¶
- func AvgDailyBurnCents(monthToDateSpendCents int64, now time.Time) int64
- func Routes(z *zip.App, s *cloud.Service[core.State])
- type BackfillIn
- type BackfillOut
- type Backfilled
- type DoCost
- type DoHistoryPoint
- type FinanceCost
- type FinanceData
- type FinanceDerived
- type FinanceInput
- type FinanceOut
- type FinanceRevenue
- type ProviderCredit
- type ProvidersCreditOut
- type UsageFundingIn
- type UsageFundingOut
- type UsageFundingRow
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AvgDailyBurnCents ¶
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).
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 ¶
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 data2: 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 data2: 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.