Red's re-review of the credit code, fixed. credit() read the row, then took the payer's hold, then marked the credit in a swap that only asked "is it credited". A reconciler on another replica (or the same one, on the next tick) could fail the payment in between: fail() released the hold, saw Credited false so reversed nothing, and closed the row for good. The request's swap then set Credited on that failed row and landed it — real money in the payer's balance for a payment Gateway refused, on a row no pass reads again, so nothing ever took it back. The swap now refuses a row that is Failed, and the pass that finds it not owed hands back the room it took and lands nothing. The Deferred flag is refused on a failed row too, so its view cannot promise a credit that will not come. TestACreditNeverLandsOnAFailedRow reproduces it: with the guard removed the row ends Failed+Credited+Landed with 700 cents posted; with it, the row stays failed, the ledger sees nothing and the hold is empty.
commerce
Checkout, billing, pricing, invoicing — the light commerce router for the Hanzo platform. NOT in PCI-DSS scope (PAN data lives in hanzoai/vault).
Quick start
docker run -p 8001:8001 ghcr.io/hanzoai/commerce:latest
What this is
commerce handles orders, products, subscriptions, invoices, and customer records for every Hanzo deployment. It is CDE-connected, not CDE-in-scope: card data is tokenized at hanzoai/vault and commerce only ever sees the token. The service is production multi-tenant (37+ X-Org-Id call sites), IAM-integrated, and already exposes func Mount(*zip.App, cloud.Deps) error — it is one of the three reference implementations of the HIP-0106 Mount contract.
Specs
Implements:
- HIP-0037 AI Cloud Platform (billing surface)
- HIP-0106 Unified Cloud Binary (commerce subsystem — already exposes
Mount())
Architecture
client -> gateway -> commerce (zip.App)
|
orders / products / subscriptions / invoices
|
+-----------+-----------+
| |
hanzoai/vault billing provider
(CDE — tokenizes PAN) (Stripe etc., webhook in)
|
per-tenant data via base (HIP-0302)
Development
sh scripts/fetch-plans.sh # vendor the @hanzo/plans catalog (go:embed)
go run ./cmd/commerce -dev # API on 127.0.0.1:8090
Data lives under COMMERCE_DIR (default ./commerce_data), one SQLite file per
org. The build needs cgo with the sqlite_math_functions tag, or
CGO_ENABLED=0 for the pure-Go SQLite backend.
Test
export GOWORK=off CGO_ENABLED=1 GOFLAGS=-tags=sqlite_math_functions
go vet ./...
go test ./billing/... ./payment/...
go run github.com/onsi/ginkgo/v2/ginkgo -r test/
The same gates run in CI from hanzo.yml.
License
MIT OR Apache-2.0 (LICENSE, LICENSE-MIT, LICENSE-APACHE) per HIP-0137 One License; vendored third-party terms are in NOTICE.