billing

package
v1.801.455 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: 23 Imported by: 0

Documentation

Overview

Package billing is your org's balance, what it has spent, and the cards it pays with.

It is the customer's own money door, serving the org-scoped /v1/billing/{usage,usage/accounts,balance,gpu-eligibility,gpu-charge,payment-methods} reads plus the six /v1/finance/{balance,credits,usage,invoices,payment-methods,ledger} projections the finance UI renders (finance.go). It owns NEITHER prefix whole — commerce serves the merchant half of /v1/billing/* (invoices, subscriptions, alerts, webhooks) and treasury serves /v1/finance/{treasury,accounts}.

WHY THIS EXISTS. On the console host (console.hanzo.ai) the ingress routes /v1/* straight to cloud-api:8000 — the console's Next BFF is reached only at "/". So the console's /v1/billing/usage + /v1/billing/balance calls land HERE, on cloud-api, NOT on the console's per-tenant commerce proxy. cloud-api previously wired commerce billing ONLY under the admin-gated aggregate (apps/admin, /v1/admin/*), so a normal org owner (e.g. davelorenzini / maxpower) hitting /v1/billing/usage had NO customer route and was denied — the "Access required" wall on every product overview + o11y usage panel. This adds exactly the customer surface those calls need.

TENANT ISOLATION (the whole point). The org is the VALIDATED IAM owner claim (principal.Org — the trusted X-Org-Id the identity middleware minted from the caller's verified session/bearer, HIP-0026; NEVER a client-supplied header). A customer therefore reads ONLY their OWN org's ledger. The commerce billing subject is pinned server-side to that org and NO client-supplied subject/org query param is ever forwarded, so the browser cannot widen scope. This is the per-org READ twin of the admin god-view (apps/admin) — the SAME commerce S2S machinery, but scoped to the caller instead of all-orgs (which stays admin-only).

SUBJECT. Prepaid balance is per-ORG: commerce keys the wallet under the BARE org slug as the `user` subject + the trusted `X-Org-Id` (admin.orgSubject / metering identityFromCtx — verified live: user=<org> + X-Org-Id=<org> returns the real wallet, "org/user" reads an empty one). The gateway debits this SAME key, so a read here shows exactly what the org is charged.

TWO BACKENDS, ONE WIRE. Balance and usage read the co-resident native ledger DIRECTLY when finance is published (balance.go, usage_coresident.go) — which it always is in the unified binary — and fall back to the commerce S2S proxy only on a split deploy. Either way the wire is commerce's: the console's normalizeUsageRecords parses the RAW per-request ledger ({usage:[{transactionId,amount,metadata,createdAt}]}) and balance is the raw {balance,holds,available} cents object, so the proxy path forwards commerce's body + status VERBATIM and never rolls up (the rollup is the admin aggregate's job).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Mount

func Mount(app cloud.Router, deps cloud.Deps) error

Mount registers the customer-facing /v1/billing/* read surface on app.

Types

This section is empty.

Jump to

Keyboard shortcuts

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