cloud

package module
v1.786.32 Latest Latest
Warning

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

Go to latest
Published: Jul 3, 2026 License: Apache-2.0 Imports: 38 Imported by: 0

README

cloud

cloud

Unified Go control plane and binary for the Hanzo platform (HIP-0106).

Status License

Quick start

docker run -p 8080:8080 ghcr.io/hanzoai/cloud:latest

What this is

hanzoai/cloud is one Go binary that mounts every Hanzo subsystem (iam, kms, base, gateway, ai, commerce, vfs, mq, dns, amqp, mcp, o11y, ...) into a single multi-tenant process. Same artifact serves api.hanzo.ai, api.osage.cloud, api.lux.cloud, api.zoo.cloud, and every white-label reseller. Brand, enabled subsystems, and tenant scope are deployment configuration.

hanzo — cloud control CLI

The same binary is also a gcloud/doctl-class CLI. The first token selects the mode:

  • hanzo <subsystem>server mode: serve a subsystem (hanzo iam, hanzo cloud, …).
  • hanzo <verb>client mode: control the live estate. A thin client over Hanzo IAM (hanzo.id), the platform control plane (platform.hanzo.ai/v1), and the cloud /v1 API — it invents no parallel API.
hanzo login                       # IAM password grant against hanzo.id → token in ~/.hanzo (0600)
hanzo whoami                      # identity from the stored token (--verify hits IAM userinfo)
hanzo apps list                   # platform apps board: declared/running/latest tag + drift + health
hanzo apps get <org>/<app>/<env>  # one app row
hanzo deploy <container> --project <p> --env <e>   # rolling, zero-downtime redeploy
hanzo clusters list|get|create|select|target       # dedicated DOKS cluster lifecycle
hanzo build <repo> --sha <sha> --image <img>       # platform-native (arcd/Kaniko) build, no GitHub builders
hanzo k8s target                  # the org's resolved deploy target (kubeconfig never returned)
hanzo config set <k> <v>          # ~/.hanzo/config preferences

Global flags: --org, -o/--output table|json, --platform-url, --iam-issuer, --platform-token. Tokens resolve from flag → env → ~/.hanzo (never hardcoded): the IAM user token is the identity; the platform control plane is service-token authed (it cannot validate user tokens), so apps/deploy/clusters use --platform-token / HANZO_PLATFORM_TOKEN / PLATFORM_SERVICE_TOKEN, and build uses HANZO_BUILD_TOKEN / PLATFORM_BUILD_CALLBACK_TOKEN.

Install: go install github.com/hanzoai/cloud/cmd/hanzo@latest, or brew install hanzoai/tap/hanzo.

Specs

Implements:

  • HIP-0014 Application Deployment
  • HIP-0026 IAM
  • HIP-0027 KMS
  • HIP-0037 AI Cloud Platform
  • HIP-0105 In-Process Extension Runtime
  • HIP-0106 Unified Cloud Binary
  • HIP-0302 Encrypted SQLite + ZapDB Durability

Architecture

                 api.{tenant}.{brand}
                          |
                   hanzoai/cloud (one Go binary)
                          |
   +----------+----------+----------+----------+----------+
   |    iam   |   base   |   kms    |    ai    | gateway  | ...
   |  Mount() |  Mount() |  Mount() |  Mount() |  Mount() |
   +----------+----------+----------+----------+----------+
   per-tenant SQLite (HIP-0302)   |   Hanzo IAM JWKS (HIP-0026)
   replicate -> S3 (HIP-0107)     |   ZAP inter-subsystem RPC

Every subsystem exposes func Mount(app *zip.App, deps cloud.Deps) error. White-label fork pattern: customers fork this repo to launch their own ecosystem.


Hanzo Cloud

The unified Go binary that imports every Hanzo-native subsystem and dispatches requests per deployment configuration. One artifact, many subsystems.

Per HIP-0106.

Subsystems mounted

  • iam — identity & access
  • base — per-tenant SQLite + extension runtimes (per HIP-0105)
  • kms — secrets
  • commerce — checkout, billing, pricing, invoicing (light router; NOT in PCI-DSS scope)
  • ai — LLM control plane / RAG / model hub / MCP management (was hanzoai/cloud pre-rename)
  • gateway — HTTP routing + policy
  • o11y — metrics / traces / logs
  • vfs — virtual filesystem / object-store abstraction
  • mq — message queue
  • dns, amqp, mcp, auto, tasks, ... (full list per HIP-0106)

Deployment modes

Same binary; different startup configuration:

cloud --enable=iam,base,kms,commerce,ai,gateway,o11y --brand=hanzo  --domain=hanzo.ai
cloud --enable=iam,base,kms,commerce,ai,gateway,o11y --brand=osage  --domain=osage.cloud
cloud --enable=iam,base,kms,commerce,ai,gateway,o11y --brand=lux    --domain=lux.cloud
cloud --enable=iam,base,kms,commerce,ai,gateway,o11y --brand=zoo    --domain=zoo.cloud

White-label fork pattern

Customers fork hanzoai/cloud to launch their own ecosystem in one binary. Brand detection, enabled subsystems, ZAP endpoints (payments / vault backends) are all deployment configuration.

Web framework

hanzoai/zip — Sinatra-style Go web framework built on Fiber v3. The ONE Go web framework. No .Fast escape hatch.

Console UI — embedded in the ONE binary

The same hanzoai/cloud binary serves the console (@hanzo/gui) UI at the web root AND the /v1 API from one process — one artifact, one origin, no separate console Service. The UI is compiled in via //go:embed (see webui.go).

Pipeline (in the Dockerfile, before go build):

console stage  →  build console2 static bundle  →  /out
      COPY --from=console /out/ → src/webui/dist/     (overlays the fallback shell)
build stage    →  go build   →  //go:embed all:webui/dist bakes it into /cloud

Serving (webui.go, registered LAST in Serve so it never shadows the API):

  • GET / and any client-side route (/orgs, /models, …) → the SPA shell (index.html) with Cache-Control: no-cache; fingerprinted assets under assets//_next/ are served immutable for a year, with brotli/gzip precompressed negotiation when the build emits .br/.gz siblings.
  • GET /v1/* (and /zap, /healthz, …) → the API. Real subsystem routes are registered before the console catch-all, so they always win; an unmatched path under an API prefix returns a real 404 (JSON namespace), never HTML.
  • Same-origin: the embedded console calls /v1 on its own host, so the session cookie is first-party — no second origin, no CORS.

webui/dist/index.html is a committed fallback shell (a real same-origin /v1 bootstrap) so go build always compiles and the binary always serves a UI even without the Node toolchain. The image build overwrites webui/dist with the real console bundle. See webui_test.go for the boot-and-assert tests (/ → shell, deep link → shell 200, /v1/* → API, unmatched /v1 → 404).

Honest current state: console2 ships 15 Next server route handlers (app/**/route.ts) that hold KMS-sourced service tokens and mint short-lived user tokens, so it emits a Node server bundle, not a static export (output: export would fail). Until console2 exposes a build:embed static target — or those handlers land here as native /v1 endpoints — the image embeds the fallback shell, and the separate console2 Service stays up. The Go embed/serve plumbing is complete and needs no further change to light up the full console the moment the static bundle exists.

Status

Scaffold. The Mount(app, deps) integration for each subsystem lands per HIP-0106's migration phases.

Documentation

Overview

Package cloud is the unified Hanzo Cloud binary per HIP-0106.

One Go binary mounts every Hanzo-native subsystem (iam, base, kms, commerce, ai, gateway, o11y, vfs, mq, dns, amqp, mcp, ...) via the canonical Mount(app *zip.App, deps cloud.Deps) error contract. Brand, enabled subsystems, and tenant scope are deployment configuration; the binary is the same artifact across every white-label deployment.

Per HIP-0106 — github.com/hanzoai/HIPs/blob/main/HIPs/hip-0106-unified-hanzo-cloud-binary.md.

Index

Constants

View Source
const DefaultBrand = "hanzo"

DefaultBrand is the fallback brand when CLOUD_BRAND is unknown.

View Source
const DefaultResourceFeeCents int64 = 100

DefaultResourceFeeCents is the fallback flat provision/create fee (in cents) when no operator override is set — $1.00, so "every service costs money" holds out of the box. It is a configurable POLICY default, not a fabricated market price: ops sets the real number per deployment/kind via ResourceFeeCents's env knobs. Set a kind to 0 to make it free (and therefore un-gated, mirroring the edge gate's price==0 pass-through).

Variables

View Source
var Registry []MountSpec

Registry is the in-process subsystem registry. Subsystems register via init() functions in their respective packages OR cmd/cloud/main.go can explicitly enumerate them. Either pattern works.

Functions

func AuditTrail added in v1.786.1

func AuditTrail(rec *audit.Recorder) zip.Handler

AuditTrail returns the audit middleware bound to rec. A nil rec makes it a no-op passthrough so callers always Use() it unconditionally.

func BillingGate added in v1.786.1

func BillingGate(m *metering.Client, price func(c *zip.Ctx) int64) zip.Handler

BillingGate returns a zip middleware that gates every request on the caller's commerce balance and records usage for priced paths.

Order of operations:

  1. price(c) == 0 AND not gated → pass straight through (free path).
  2. Authorize(ctx, identity) BEFORE c.Next(): nil → allow. ErrInsufficientBalance → 402 insufficient_balance, c.Next() NOT called. other error → 503 balance_unavailable, c.Next() NOT called (fail-closed; the client returns nil here when built FailOpen, so this branch never fires in fail-open mode).
  3. c.Next() runs the handler chain.
  4. After a successful chain, if price(c) > 0, fire `go m.Record(...)` so the debit never blocks or corrupts the response the user already received.

When m is nil or not configured (no commerce URL) the gate is a no-op: it returns c.Next() directly so an unconfigured deployment is never blocked. price must not be nil; pass DefaultPrice.

func ClientIP added in v1.786.1

func ClientIP(c *zip.Ctx) string

ClientIP extracts the originating client IP from X-Forwarded-For (the gateway sets it); the left-most entry is the real client. Shared by the edge gate and the resource meter so usage records carry a consistent client_ip.

func DefaultPrice added in v1.786.1

func DefaultPrice(c *zip.Ctx) int64

DefaultPrice is cloud's per-request price (in cents) for the edge gate.

It returns 0 — meaning "do not gate, do not charge" — for:

  • health/liveness probes (every /v1/<svc>/health and bare /health),
  • /v1/ai/* : the ai subsystem self-meters its own LLM token costs to commerce; charging again here would DOUBLE-BILL,
  • /v1/agents/* : the canonical agents subsystem now gates + meters its OWN per-run fee to commerce (clients/agents runAgent); the edge must stay 0 or every agent run is billed twice,
  • other subsystems that already self-meter their units (commerce billing itself, o11y telemetry, mcp tool dispatch),

and a non-zero flat price only on the generic agent/compute edge that has no finer-grained meter of its own. Tune per path as cloud grows its own metered surfaces; keep self-metering subsystems at 0 to preserve single-charge accounting.

func DenyResource added in v1.786.1

func DenyResource(c *zip.Ctx, err error) error

DenyResource renders the Gate denial outcomes as the SAME JSON the edge gate returns (denyBilling), so every Hanzo surface emits one error contract: 402 insufficient_balance / 503 balance_unavailable.

func IssuerForBrand added in v1.786.1

func IssuerForBrand(id string) string

IssuerForBrand returns the canonical OIDC issuer for a brand id.

func MountAll

func MountAll(app any, cfg *Config, deps Deps) error

MountAll iterates the registry in order and calls Mount() on each enabled subsystem.

func OrgHasUnsafeRune added in v1.786.32

func OrgHasUnsafeRune(s string) bool

OrgHasUnsafeRune reports whether s carries any whitespace, control, or zero-width/format rune — the class that defeats the injectivity of the org→tenant map. strings.TrimSpace (and fasthttp's own header-value OWS trimming) silently drop such runes at the edges, so two DISTINCT IAM org names ("acme" vs "acme ", or an NBSP/ZWSP variant) would collapse onto ONE tenant-<slug> namespace / image ref — a cross-tenant fold. The identity trust boundary REFUSES to grant tenancy from an org bearing one of these (fail secure) instead of folding it, so distinct raw names never collide and no namespace is ever derived from an invisible-character identifier.

Case / '-' / '.' / other visible punctuation are deliberately NOT unsafe: those fold INJECTIVELY through the org-slug hash (provisioning.SanitizeOrg). Only the invisible / edge-trimmable class — which no injective fold can survive once transport strips it — is rejected here. A legitimate IAM org slug never contains such a rune, so no real caller is affected.

func Register

func Register(name string, order int, mount MountFunc)

Register adds a subsystem to the in-process registry.

func RegisterWithShutdown added in v1.786.32

func RegisterWithShutdown(name string, order int, mount MountFunc, shutdown ShutdownFunc)

RegisterWithShutdown adds a subsystem that owns process-lifetime resources: a background worker (e.g. the agents scheduler) or a DB handle that must be flushed. shutdown is invoked by ShutdownAll on graceful stop. This is the ONE way a subsystem gets a teardown — Register stays the zero-teardown default.

func ResourceFeeCents added in v1.786.1

func ResourceFeeCents(envPrefix, kind string) int64

ResourceFeeCents resolves the flat create fee (in cents) for kind from operator config, most specific first:

<envPrefix>_<KIND>   e.g. CLOUD_PROVISION_FEE_CENTS_SQL=500
<envPrefix>          e.g. CLOUD_PROVISION_FEE_CENTS=100  (all kinds)
DefaultResourceFeeCents                                   ($1.00)

A clearly-named, configurable policy knob — never a fabricated price. A value of 0 makes the kind free (and un-gated). Negative/invalid values are ignored (fall through), so a typo can never make a paid resource free by accident.

func SanitizeIdentity added in v1.786.1

func SanitizeIdentity(v *identityValidator, adminOrg string) zip.Handler

SanitizeIdentity returns the identity-trust-boundary middleware.

Per request:

  • ALWAYS delete every header in authorityHeaders (a client copy never survives — this alone kills X-User-IsAdmin forgery).
  • Validate a Bearer / Basic / session-cookie JWT, if present: global admin (claims.isAdmin && owner == adminOrg) → X-User-IsAdmin=true; X-Org-Id = the requested org when present (admin org-switch), else owner. any other principal (incl. org admins, normal users) → X-Org-Id pinned to owner; NO admin. A client org cannot widen scope.
  • No / invalid / opaque-API-key credential: → NO admin (forgery dead), and the client's X-Org-Id is restored for the Phase-1 data path (residual below).

PHASE-1 RESIDUAL (documented; not a regression vs. today): with no validatable bearer, the client X-Org-Id is passed through for DATA scoping. cloud's data plane has no session of its own yet ("Auth stays gateway-owned in Phase 1") and the console browser data path depends on this header. So a direct-to-pod caller can still SELECT a tenant for DATA reads. Closing that needs the data path to carry a bearer universally OR the NetworkPolicy locked to gateway-only (which would break console2's legitimate direct in-cluster BFF) — Phase-2. The ADMIN boundary (this fix's P0) is closed on every path regardless, because X-User-IsAdmin is NEVER restored from client input.

FAIL MODE. If the validator can't verify a token (JWKS unreachable on a cold cache, issuer/audience misconfigured), the request resolves anonymous and BOTH planes fail SECURE. Admin fails closed (X-User-IsAdmin is never restored from client input), and — since F1 — the DATA plane fails closed too: it gates on a validated principal (clients/principal.Validated) and the anonymous request carries no X-User-Id, so the restored X-Org-Id is refused, not served. Never fails OPEN. The availability cost is bounded to COLD caches: the jwksCache is stale-on-error (a warm cache keeps validating through a transient JWKS outage), so only a from-cold JWKS failure degrades to anonymous-403.

func Serve

func Serve(enable []string) error

Serve boots the canonical compose root and mounts the selected subsystems.

This is the ONE place the cloud-server body lives. cmd/cloud (the full fused surface) and every `hanzo <svc>` subcommand share it; no boot logic is duplicated per entrypoint.

enable==nil ⇒ honor cfg.Enable from flags/env (cloud mode; empty = all). enable!=nil ⇒ force exactly that set (single-service mode), overriding --enable so `hanzo kms` is unambiguous.

Serve registers the HIP-0106 liveness contract (GET /v1/<name>/health for every enabled subsystem) before MountAll, runs the canonical middleware pipeline (Recover → RequestID → Logger), and shuts down gracefully on SIGINT/SIGTERM.

func ShutdownAll added in v1.786.32

func ShutdownAll(ctx context.Context, cfg *Config) error

ShutdownAll tears down every ENABLED subsystem that registered a ShutdownFunc, in REVERSE mount order (a dependency is torn down after its dependents), best effort: a failure is collected and the rest still run, so one stuck subsystem can't strand another's flush. Serve calls this inside the shutdown deadline.

Types

type AIClient

type AIClient = types.AIClient

type BaseClient

type BaseClient = types.BaseClient

type BrandInfo added in v1.786.1

type BrandInfo struct {
	// ID is the canonical brand key.
	ID string
	// IAMIssuer is the OIDC issuer (JWKS source) for this brand — the value the
	// JWT `iss` claim must equal and whose /v1/iam/.well-known/jwks signs tokens.
	IAMIssuer string
	// Domain is the brand's primary marketing/site domain (for response scoping).
	Domain string
}

BrandInfo is the PUBLIC per-brand identity used for token validation + URL scoping. No secrets.

func BrandFor added in v1.786.1

func BrandFor(id string) BrandInfo

BrandFor returns the BrandInfo for id, falling back to the Hanzo brand for an unknown id. Lookup is case-insensitive.

type ChatRequest

type ChatRequest = types.ChatRequest

type ChatResponse

type ChatResponse = types.ChatResponse

type Claims

type Claims = types.Claims

type CommerceClient

type CommerceClient = types.CommerceClient

type Config

type Config struct {
	// Enable lists subsystems to mount this run. Empty = all enabled.
	// Example: --enable=iam,base,kms,commerce,ai,gateway,o11y
	Enable []string

	// Brand is the white-label brand identifier.
	Brand string

	// Env is the deployment environment (mainnet|testnet|devnet) per the 3-env
	// split. Billing fires in EVERY env — test/dev meter against their own
	// sandbox commerce/Square, never free — so Env is an attribution label, not
	// a gate. Empty when the operator has not set CLOUD_ENV.
	Env string

	// Domain is the deployment's primary public domain.
	Domain string

	// IAMIssuer is the JWKS issuer for JWT validation (usually iam.hanzo.ai).
	IAMIssuer string

	// AdminOrg is the IAM org slug whose members are GLOBAL admins (IAM's
	// IsGlobalAdmin: owner == AdminOrg). The in-binary identity sanitizer grants
	// admin authority — the c.IsAdmin() that gates /v1/admin/* writes, the
	// /v1/pricing/sync trigger, and the literal "admin" tenant bucket — ONLY to a
	// validated principal from this org, never to a raw header. Env IAM_ADMIN_ORG
	// (default "admin"), matching the gateway's admin-guard.
	AdminOrg string

	// JWKSURL is the JSON Web Key Set endpoint the identity sanitizer fetches IAM
	// signing keys from. Defaults to {IAMIssuer}/v1/iam/.well-known/jwks
	// (HIP-0111); override with CLOUD_JWKS_URL.
	JWKSURL string

	// JWTAudiences is the audience allowlist the sanitizer accepts (OR semantics).
	// Defaults to the known Hanzo IAM client_ids; override with CLOUD_JWT_AUDIENCES
	// (comma-separated) or GATEWAY_ALLOWED_AUDIENCES.
	JWTAudiences []string

	// KMSMasterKeyRef is the base64-encoded 32-byte KMS master key (KEK) the
	// embedded luxfi/kms store seals every secret's DEK under. The operator
	// injects it from a K8s Secret as CLOUD_KMS_MASTER_KEY_REF; cloud reads it
	// ONLY from env (never from the store it hosts — the bootstrap chicken-and-egg)
	// and never logs it. Empty ⇒ the KMS subsystem runs fail-closed (health-only).
	KMSMasterKeyRef string

	// KMSMPCAddr / KMSMPCVaultID configure the MPC threshold-signing backend for
	// KMS Sign. Both empty (the default) ⇒ Sign fails closed with a clear error;
	// signing is never fabricated. Set via CLOUD_KMS_MPC_ADDR / CLOUD_KMS_MPC_VAULT_ID.
	KMSMPCAddr    string
	KMSMPCVaultID string

	// DataDir is the on-disk data root.
	DataDir string

	// ListenAddr is the public HTTP listener (default :8080).
	ListenAddr string

	// ZAPListenAddr is the ZAP-RPC listener (default :9653).
	ZAPListenAddr string

	// ZAPWebOrigins is the WebSocket Origin allowlist for the browser-facing
	// /zap ZAP plane (the SPA hosts that may open a ZAP-over-WS connection).
	// Empty == same-origin only. Set via CLOUD_ZAP_WEB_ORIGINS (comma-sep).
	ZAPWebOrigins []string

	// HealthListenAddr is the health/metrics listener (default :9090).
	HealthListenAddr string

	// AdminListenAddr is the admin endpoint (default :8081, gated by IAM admin).
	AdminListenAddr string

	// SitesApex is the zone whose subdomains are PUBLIC published-site hosts
	// (`<slug>.<apex>`, default hanzo.app). The site host-router (clients/sites)
	// serves the root path space for these hosts from OUR S3, ahead of the API
	// pipeline, so a published site is a public artifact — never a tenant API call.
	// Env CLOUD_SITES_APEX.
	SitesApex string

	// SitesReserved lists subdomain labels under SitesApex that are NOT sites and
	// must fall through to the normal pipeline (real app/api hosts on the apex).
	// This is the reserved-host exclusion that stops a published site from
	// shadowing a real hanzo.app app. The empty label (apex) and "www" are always
	// reserved; these add to them. Env CLOUD_SITES_RESERVED (comma-separated).
	SitesReserved []string

	// Endpoints for out-of-process subsystems (payments, vault). Empty
	// means the subsystem is disabled OR the deployment expects a default
	// service-discovery resolution.
	PaymentsZAPAddr string
	VaultZAPAddr    string

	// Billing gate (commerce metering) — the request-edge balance gate.
	//
	// CommerceHTTPURL is the commerce service base over HTTP (the metering
	// client speaks net/http, not ZAP). Empty disables the gate entirely.
	//
	// CommerceServiceToken is the admin-scoped commerce S2S token. It is a
	// SECRET sourced from a KMS-backed secret the operator injects as
	// COMMERCE_SERVICE_TOKEN — never hard-coded or read from disk here.
	//
	// BillingFailOpen flips the gate to allow-on-error. Default is
	// fail-closed (deny when balance can't be determined), matching the
	// gateway. Set only where availability outranks billing.
	CommerceHTTPURL      string
	CommerceServiceToken string
	BillingFailOpen      bool

	// AI inference gateway — the /v1/agents run path. Agent runs execute a real
	// chat completion through an OpenAI-compatible endpoint (the Hanzo LLM
	// gateway). This is the ONE real inference wiring: with AIAPIKey set,
	// pickAIClient returns the HTTP gateway client; without it deps.AI is the
	// fail-closed stub and a run never fabricates output.
	//
	// AIBaseURL is the gateway /v1 root (CLOUD_AI_BASE_URL, default
	// https://api.hanzo.ai/v1); the client appends /chat/completions.
	//
	// AIAPIKey is a KMS-injected virtual key (CLOUD_AI_API_KEY). It is a SECRET —
	// never logged, never printed, never read from disk here.
	//
	// AIDefaultModel is the served model an agent with no explicit model falls
	// back to (CLOUD_AI_DEFAULT_MODEL, default deepseek-v4-flash). Model routing
	// is the gateway's job; this is the ONLY cloud-side model default.
	AIBaseURL      string
	AIAPIKey       string
	AIDefaultModel string

	// AIAuthClientID / AIAuthClientSecret are the binary's OWN IAM service
	// identity (IAM_CLIENT_ID / IAM_CLIENT_SECRET). When no static AIAPIKey is
	// set, the AI client authenticates to the gateway with a client-credentials
	// (M2M) token minted from this identity and auto-refreshed — the durable
	// no-static-key path. On the Hanzo deployment the identity resolves to
	// admin/hanzo-cloud (gateway-balance-exempt), so cloud's per-org
	// ResourceMeter remains the single debit. The token endpoint is derived from
	// IAMIssuer ({issuer}/v1/iam/oauth/token). The secret is KMS-injected and
	// never logged.
	AIAuthClientID     string
	AIAuthClientSecret string

	// ZAP RPC endpoints for subsystems that are NOT enabled in this
	// process but are still needed by an enabled subsystem. Empty
	// means "no remote endpoint" — the client falls back to the
	// disabled stub which fails closed with a clear error.
	//
	// Convention: <subsystem>.<env>.<deployment>.svc:9653 — the same
	// inter-subsystem listener port the unified binary exposes. The
	// transport is hanzoai/zap, never JSON.
	IAMZAPAddr      string
	KMSZAPAddr      string
	BaseZAPAddr     string
	CommerceZAPAddr string
	AIZAPAddr       string
	O11yZAPAddr     string
	VFSZAPAddr      string
	MQZAPAddr       string
}

Config is the cloud binary's startup configuration. Drives which subsystems mount, what brand surface to serve, and where data lives.

func LoadConfig

func LoadConfig() *Config

LoadConfig reads flags + env into a Config. Flags override env.

func (*Config) Enabled

func (c *Config) Enabled(name string) bool

Enabled reports whether subsystem `name` is enabled in this config. Empty Enable list = all subsystems enabled.

func (*Config) Validate

func (c *Config) Validate() error

Validate returns an error if the config is missing required values.

type Counter

type Counter = types.Counter

type DBHandle

type DBHandle = types.DBHandle

type Deps

type Deps struct {
	// Logger is the canonical Hanzo logger (luxfi/log). Subsystems derive
	// scoped child loggers from this.
	Logger luxlog.Logger

	// Brand is the white-label brand identifier for this deployment.
	// Values: "hanzo", "lux", "zoo", "osage", "pars", or any customer brand.
	Brand string

	// Env is the deployment environment (mainnet|testnet|devnet). Subsystems
	// that meter usage stamp it for per-env attribution; it never gates or
	// bypasses billing (every env bills against its own commerce ledger).
	Env string

	// Domain is the deployment's primary domain (e.g. "api.hanzo.ai",
	// "api.osage.cloud"). Subsystems use this to scope URLs in responses.
	Domain string

	// IAMIssuer is the canonical OIDC issuer (JWKS source) for this brand,
	// resolved from Brand via the white-label registry unless pinned by the
	// operator. Subsystems validate JWT `iss` + signatures against
	// {IAMIssuer}/v1/iam/.well-known/jwks (HIP-0111). One issuer per deployment.
	IAMIssuer string

	// DataDir is the per-deployment data root. Per-tenant SQLite files
	// land at {DataDir}/orgs/{orgSlug}/{service}.db per HIP-0302.
	DataDir string

	// Subsystem clients — populated by BuildDeps based on enabled subsystems.
	// Each is an interface with both in-process and ZAP-RPC implementations.
	IAM      IAMClient
	KMS      KMSClient
	Base     BaseClient
	Commerce CommerceClient
	AI       AIClient
	O11y     O11yClient
	VFS      VFSClient
	MQ       MQClient

	// Payments + Vault stay out-of-process (PCI scope isolation per
	// HIP-0106). These clients always resolve to ZAP-RPC implementations,
	// never in-process.
	Payments PaymentsClient
	Vault    VaultClient

	// Metering is the canonical commerce billing client used by the
	// request-edge BillingGate. It speaks net/http to commerce's billing API
	// (separate from the ZAP Commerce client above, which is for typed
	// inter-subsystem calls). Nil or not-Enabled() makes the gate a no-op.
	Metering *metering.Client

	// Audit is the tamper-evident, append-only audit trail Recorder (FedRAMP AU-*
	// / SOC 2 CC-*). Serve constructs it once, wires the AuditTrail middleware to
	// it, and hands it here so the /v1/admin/audit query + /v1/admin/audit/verify
	// endpoints read the SAME store the middleware writes. Nil makes the audit
	// middleware a no-op and the query endpoint fall back to the IAM proxy (an
	// unconfigured deployment is never blocked). See audit/ and audit_middleware.go.
	Audit *audit.Recorder
}

Deps is the shared dependency surface passed to every subsystem's Mount(app, deps) function. Subsystems consume only what they need.

In-process: each Client below resolves to a direct Go method-call implementation. Out-of-process (legacy split deploys): the same Client resolves to a ZAP-RPC implementation. Subsystem code does not branch on which mode; the interface is the contract.

func BuildDeps

func BuildDeps(cfg *Config) Deps

BuildDeps constructs the Deps used by every subsystem's Mount(app, deps).

Wiring rules per HIP-0106 inter-subsystem contract:

  1. If the subsystem is enabled in this process, the Client field is left nil here. The subsystem's own Mount() will install a typed in-process Client into Deps via the SetClient helpers exposed by this package. (Subsystem Mounts run after BuildDeps; they have full access to construct their concrete implementation, and the resulting object goes back into Deps for everyone else to call.)

  2. If the subsystem is disabled but cfg has a non-empty ZAP RPC endpoint for it, the Client field gets a ZAP-RPC stub targeting that endpoint. Subsystem code calls deps.X.Foo(...) without knowing the call goes over the wire.

  3. If the subsystem is disabled AND there is no endpoint, the Client field gets a "disabled" stub that fails closed with a clear error. Mount-time consumers detect this with clients.IsDisabled(err) and log a friendly "dep X needed by Y not configured" message.

JSON does not appear in any of these paths. Inter-subsystem calls are ZAP-typed Go values either via direct method dispatch (mode 1) or via ZAP RPC over the wire (mode 2). JSON happens only at the gateway/ingress edge, through the zip jsonenc helper.

Payments and Vault are special: they are NEVER in-process per HIP-0106 solo-vault CDE. Their clients always resolve via clients.PaymentsRPCAt / clients.VaultRPCAt; the disabled stub fires when no endpoint is configured.

type IAMClient

type IAMClient = types.IAMClient

type IntentRequest

type IntentRequest = types.IntentRequest

type IntentResponse

type IntentResponse = types.IntentResponse

type IntentStatus

type IntentStatus = types.IntentStatus

type KMSClient

type KMSClient = types.KMSClient

type LicenseEntitlement

type LicenseEntitlement = types.LicenseEntitlement

type MQClient

type MQClient = types.MQClient

type MountFunc

type MountFunc func(app any, deps Deps) error // app is *zip.App; using any here to avoid an import cycle in pkg/cloud

MountFunc is the canonical signature every subsystem exposes per HIP-0106. Each Hanzo Go service ships a top-level `Mount` symbol matching this signature; cmd/cloud/main.go imports the package and calls it.

type MountSpec

type MountSpec struct {
	Name     string
	Order    int
	Mount    MountFunc
	Shutdown ShutdownFunc // optional; nil means the subsystem has nothing to tear down.
}

MountSpec describes one subsystem registered for mounting. The Order is used when ordering matters for inter-subsystem deps (e.g. iam before authz before commerce).

type O11yClient

type O11yClient = types.O11yClient

type Org

type Org = types.Org

type PaymentsClient

type PaymentsClient = types.PaymentsClient

type ResourceMeter added in v1.786.1

type ResourceMeter struct {
	// contains filtered or unexported fields
}

ResourceMeter gates and meters per-org spend for non-LLM resource creation, reusing Deps.Metering (the single commerce billing client). Build it with NewResourceMeter. A nil meter, or one whose commerce URL is unset, makes Gate allow and Meter a no-op — so an unconfigured deployment is never blocked, exactly like BillingGate.

func NewResourceMeter added in v1.786.1

func NewResourceMeter(deps Deps, provider string) *ResourceMeter

NewResourceMeter builds a ResourceMeter from the shared deps. provider labels the recorded usage so spend is attributable to the surface that metered it.

func (*ResourceMeter) Enabled added in v1.786.1

func (rm *ResourceMeter) Enabled() bool

Enabled reports whether billing will actually enforce (a commerce URL is configured). When false, Gate allows and Meter is a no-op.

func (*ResourceMeter) Gate added in v1.786.1

func (rm *ResourceMeter) Gate(ctx context.Context, org, kind string, costCents int64) error

Gate is the pre-create balance gate. It returns:

nil                              -> allow (balance positive, OR not priced,
                                    OR billing not configured).
metering.ErrInsufficientBalance  -> deny, out of funds (render 402).
other error                      -> balance unknown; fail-closed denies
                                    (render 503). Fail-open returns nil.

costCents<=0 means the kind is free → no gate (mirrors BillingGate's price==0 short-circuit). org MUST be the caller's resolved slug; it is sent as the commerce user AND X-Org-Id so the CALLER's ledger is checked, overriding the client default org — the anti-cross-tenant property. The balance check honors ctx (a client disconnect/timeout cancels it).

costCents is forwarded as AuthInput.AmountCents so the gate enforces available >= costCents, not merely available > 0 — otherwise a 1-cent balance would authorize an arbitrarily expensive charge (the debit still lands, taking the ledger negative). This mirrors what a prepaid gate must do: refuse a request the balance cannot cover BEFORE the work runs.

func (*ResourceMeter) Meter added in v1.786.1

func (rm *ResourceMeter) Meter(org, kind string, amountCents int64, requestID, clientIP string)

Meter records a successful charge to the caller's org ledger. It is the ONE metering entry point for BOTH the one-time create fee AND any recurring footprint charge (storage GB-month, GPU-hour): the caller supplies the amount, so a future recurring meter reuses this same method with a usage-derived amount. No-op when billing is not configured or amountCents<=0.

The debit is fire-and-forget on a background context: the resource already exists, so the charge must never block or corrupt the response the caller received, and a request-context cancellation must not cancel the debit (mirror of BillingGate). A debit failure is logged for reconciliation, not swallowed.

func (*ResourceMeter) MeterUsage added in v1.786.32

func (rm *ResourceMeter) MeterUsage(org, kind string, u metering.Usage)

MeterUsage is the general-purpose per-org debit: it records the caller-built usage event after forcing the per-org billing invariants that make the debit land on the CALLER's ledger and never another tenant's:

  • u.User and u.Org are OVERWRITTEN to the caller's org slug (the per-org prepaid billing key + the X-Org-Id namespace) — a caller can never bill someone else, and a surface can't accidentally leave them unset (which would debit the client-default org).
  • Provider defaults to the meter's provider; Status defaults to "success"; Currency defaults to "usd".

Everything else the caller supplies (AmountCents, Model, Actor, RequestID, token counts, ClientIP) flows through so a metered surface can attribute spend richly. Like Meter it is fire-and-forget on a background context and a no-op when billing is unconfigured or AmountCents<=0. kind is for the failure log.

type ShutdownFunc added in v1.786.32

type ShutdownFunc func(ctx context.Context) error

ShutdownFunc releases a subsystem's process-lifetime resources (background goroutines, open DB handles) on graceful shutdown. It must be idempotent and bounded — Serve calls it within the shutdown deadline. ctx carries that deadline so a slow teardown is cut off rather than hanging SIGTERM.

type Span

type Span = types.Span

type TenantConfig

type TenantConfig = types.TenantConfig

type Timing

type Timing = types.Timing

type User

type User = types.User

type VFSClient

type VFSClient = types.VFSClient

type VaultChargeRequest

type VaultChargeRequest = types.VaultChargeRequest

type VaultChargeResponse

type VaultChargeResponse = types.VaultChargeResponse

type VaultClient

type VaultClient = types.VaultClient

Directories

Path Synopsis
Package audit is the unified cloud binary's compliance-grade audit trail — tamper-evident, append-only, and complete over the security-relevant request surface (FedRAMP AU-* / SOC 2 CC-* controls).
Package audit is the unified cloud binary's compliance-grade audit trail — tamper-evident, append-only, and complete over the security-relevant request surface (FedRAMP AU-* / SOC 2 CC-* controls).
Package cli is the Hanzo cloud-control CLI — the gcloud/doctl-class client half of the `hanzo` binary.
Package cli is the Hanzo cloud-control CLI — the gcloud/doctl-class client half of the `hanzo` binary.
Package clients holds the canonical ZAP-typed inter-subsystem clients used by cloud.Deps.
Package clients holds the canonical ZAP-typed inter-subsystem clients used by cloud.Deps.
admin
Package admin mounts the god-mode admin surface (/v1/admin/*) the Hanzo Admin Console (admin.hanzo.ai, apps/operator) calls, per the api.ts contract.
Package admin mounts the god-mode admin surface (/v1/admin/*) the Hanzo Admin Console (admin.hanzo.ai, apps/operator) calls, per the api.ts contract.
agents
Package agents mounts the Hanzo Cloud /v1/agents surface: per-org autonomous agent definitions and their runs.
Package agents mounts the Hanzo Cloud /v1/agents surface: per-org autonomous agent definitions and their runs.
analytics
Package analytics mounts the Hanzo Cloud /v1/analytics/* surface: a native-Go, per-org analytics read API over the `hanzo` ClickHouse warehouse (the `datastore` cluster).
Package analytics mounts the Hanzo Cloud /v1/analytics/* surface: a native-Go, per-org analytics read API over the `hanzo` ClickHouse warehouse (the `datastore` cluster).
bot
Package botsvc mounts /v1/bot/* — a reverse proxy to the in-cluster bot-gateway (the OpenAI-compatible agent gateway that owns channels, skills, and the agent API).
Package botsvc mounts /v1/bot/* — a reverse proxy to the in-cluster bot-gateway (the OpenAI-compatible agent gateway that owns channels, skills, and the agent API).
console
Package console mounts the console's OWN standalone server surface natively in the unified cloud binary at /v1/console/* (HIP-0106).
Package console mounts the console's OWN standalone server surface natively in the unified cloud binary at /v1/console/* (HIP-0106).
crm
Package crm mounts the Hanzo Cloud /v1/crm/* surface: a native-Go, per-org CRM (companies, contacts, opportunities) on Base/SQLite.
Package crm mounts the Hanzo Cloud /v1/crm/* surface: a native-Go, per-org CRM (companies, contacts, opportunities) on Base/SQLite.
do
Package do mounts the Hanzo Cloud DigitalOcean-native infra surface — /v1/vpcs and /v1/load-balancers — on the unified cloud binary (HIP-0106).
Package do mounts the Hanzo Cloud DigitalOcean-native infra surface — /v1/vpcs and /v1/load-balancers — on the unified cloud binary (HIP-0106).
eval
Package eval mounts the Hanzo Cloud /v1/evals/* surface: a NATIVE, org-scoped evaluation system that replaces the Langfuse v3 fork (the crash-looping console proxy this file used to be).
Package eval mounts the Hanzo Cloud /v1/evals/* surface: a NATIVE, org-scoped evaluation system that replaces the Langfuse v3 fork (the crash-looping console proxy this file used to be).
exec
Package execsvc exposes the Code Interpreter ("Run Code") surface on the unified cloud-api /v1 plane, per HIP-0106.
Package execsvc exposes the Code Interpreter ("Run Code") surface on the unified cloud-api /v1 plane, per HIP-0106.
functions
Package functions mounts the Hanzo Cloud /v1/functions surface: a per-org serverless function registry.
Package functions mounts the Hanzo Cloud /v1/functions surface: a per-org serverless function registry.
git
Package git mounts the Hanzo Cloud /v1/git surface: S3-backed Git hosting native in the unified cloud binary — the "internal Gitea" foundation agents push code into.
Package git mounts the Hanzo Cloud /v1/git surface: S3-backed Git hosting native in the unified cloud binary — the "internal Gitea" foundation agents push code into.
gojahost
Package gojahost runs a Hanzo Node service's goja bundle (a self-contained, ESM-free JS file exposing globalThis.handle(req)) inside the unified cloud binary, per HIP-0106.
Package gojahost runs a Hanzo Node service's goja bundle (a self-contained, ESM-free JS file exposing globalThis.handle(req)) inside the unified cloud binary, per HIP-0106.
graph
client.go is the ONE HTTP path from this subsystem to the Lux chain-data plane.
client.go is the ONE HTTP path from this subsystem to the Lux chain-data plane.
kms
Package kms embeds luxfi/kms in-process inside the unified Hanzo Cloud binary per HIP-0106 ("all Go embeds in cloud"), replacing the legacy Infisical fork.
Package kms embeds luxfi/kms in-process inside the unified Hanzo Cloud binary per HIP-0106 ("all Go embeds in cloud"), replacing the legacy Infisical fork.
kmssvc
Package kms is the Fiber-facing subsystem that exposes the embedded luxfi/kms secrets-manager as /v1/kms/* on the unified Hanzo Cloud binary (HIP-0106).
Package kms is the Fiber-facing subsystem that exposes the embedded luxfi/kms secrets-manager as /v1/kms/* on the unified Hanzo Cloud binary (HIP-0106).
ml
Package mlsvc mounts the Hanzo Cloud /v1/ml/* and /v1/train/* surfaces: a thin, tenant-scoped bridge that turns three Kubeflow-family CustomResources into a small REST API.
Package mlsvc mounts the Hanzo Cloud /v1/ml/* and /v1/train/* surfaces: a thin, tenant-scoped bridge that turns three Kubeflow-family CustomResources into a small REST API.
o11y
Package o11y initializes the o11y subsystem's runtime handler in the unified cloud binary.
Package o11y initializes the o11y subsystem's runtime handler in the unified cloud binary.
paassvc
Package paassvc mounts the native, in-process Hanzo PaaS control plane at /v1/paas/*: the "one and only one way to deploy" made native to the cloud binary.
Package paassvc mounts the native, in-process Hanzo PaaS control plane at /v1/paas/*: the "one and only one way to deploy" made native to the cloud binary.
plan
Package plansvc mounts the @hanzo/plans catalog into the unified cloud binary under /v1/plans/*, per HIP-0106.
Package plansvc mounts the @hanzo/plans catalog into the unified cloud binary under /v1/plans/*, per HIP-0106.
platform
applylive.go — the ONE version-monotonic deploy mechanic shared by the image-source path (deployImage) and the git build reconciler.
applylive.go — the ONE version-monotonic deploy mechanic shared by the image-source path (deployImage) and the git build reconciler.
plugin
Package pluginsvc is the runtime plugin loader for the unified cloud binary.
Package pluginsvc is the runtime plugin loader for the unified cloud binary.
pricing
Admin surface for the catalog enablement overlay (global-admin only).
Admin surface for the catalog enablement overlay (global-admin only).
principal
Package principal is the ONE place the cloud data plane turns a request into a tenant.
Package principal is the ONE place the cloud data plane turns a request into a tenant.
product
Package productsvc exposes the read-only Search and Vector product surfaces the Hanzo console panels call at api.cloud.hanzo.ai, per HIP-0106.
Package productsvc exposes the read-only Search and Vector product surfaces the Hanzo console panels call at api.cloud.hanzo.ai, per HIP-0106.
projectsvc
Package projectsvc is the Hanzo Cloud projects control plane: the ONE org-scoped store of buildable/deployable sites, shared by every surface that shows a user's projects.
Package projectsvc is the Hanzo Cloud projects control plane: the ONE org-scoped store of buildable/deployable sites, shared by every surface that shows a user's projects.
prompts
Package prompts mounts the Hanzo Cloud /v1/prompts surface: a per-org, versioned prompt library.
Package prompts mounts the Hanzo Cloud /v1/prompts surface: a per-org, versioned prompt library.
provisioning
Package provisioningsvc is the Hanzo Cloud provisioning control plane.
Package provisioningsvc is the Hanzo Cloud provisioning control plane.
s3
Package s3 is the Fiber-facing subsystem that exposes an org-scoped S3 object-storage file manager as /v1/s3/* on the unified Hanzo Cloud binary (HIP-0106).
Package s3 is the Fiber-facing subsystem that exposes an org-scoped S3 object-storage file manager as /v1/s3/* on the unified Hanzo Cloud binary (HIP-0106).
s3admin
Package s3admin is the ONE shared S3 access path for the unified cloud binary.
Package s3admin is the ONE shared S3 access path for the unified cloud binary.
sites
Package sites is the public site-server for published projects: the host-routed edge that turns `<slug>.hanzo.app` into the static site a user deployed to OUR S3.
Package sites is the public site-server for published projects: the host-routed edge that turns `<slug>.hanzo.app` into the static site a user deployed to OUR S3.
templates
Package templates mounts /v1/templates — the read-only Hanzo starter-kit gallery: deployable app/site scaffolds (source of truth: hanzoai/gallery), vendored so the unified `cloud` binary ships the catalog with no external dependency.
Package templates mounts /v1/templates — the read-only Hanzo starter-kit gallery: deployable app/site scaffolds (source of truth: hanzoai/gallery), vendored so the unified `cloud` binary ships the catalog with no external dependency.
visor
client.go is the ONE HTTP path from this subsystem to Visor (the cloud OS at visor.hanzo.svc:19000 that owns compute — machines and DOKS node pools).
client.go is the ONE HTTP path from this subsystem to Visor (the cloud OS at visor.hanzo.svc:19000 that owns compute — machines and DOKS node pools).
websearch
Package websearch exposes Hanzo-native Web Search + Scrape on the unified cloud-api /v1 plane, so hanzo.chat's web_search agent tool runs entirely on Hanzo infrastructure with NO external SaaS provider, per HIP-0106.
Package websearch exposes Hanzo-native Web Search + Scrape on the unified cloud-api /v1 plane, so hanzo.chat's web_search agent tool runs entirely on Hanzo infrastructure with NO external SaaS provider, per HIP-0106.
zt
client.go is the ONE HTTP path from this subsystem to Hanzo Zero Trust — the OpenZiti-based fabric controller (hanzoai/zt) at zt-controller.hanzo.svc.
client.go is the ONE HTTP path from this subsystem to Hanzo Zero Trust — the OpenZiti-based fabric controller (hanzoai/zt) at zt-controller.hanzo.svc.
cmd
cloud command
cloud is the unified Hanzo Cloud binary per HIP-0106.
cloud is the unified Hanzo Cloud binary per HIP-0106.
hanzo command
Command hanzo is the unified Hanzo Go binary, dispatched by subcommand.
Command hanzo is the unified Hanzo Go binary, dispatched by subcommand.
migrate-pg-to-sqlite command
Command migrate-pg-to-sqlite copies a legacy `hanzo_cloud` PostgreSQL database into per-(org, user) SQLite files served by the Hanzo cloud orchestrator (HIP-0106).
Command migrate-pg-to-sqlite copies a legacy `hanzo_cloud` PostgreSQL database into per-(org, user) SQLite files served by the Hanzo cloud orchestrator (HIP-0106).
internal
org
Package org places each organization's data on exactly one replica of the unified cloud binary, and replicates it, WITHOUT any coordinator.
Package org places each organization's data on exactly one replica of the unified cloud binary, and replicates it, WITHOUT any coordinator.
storagelock
Package storagelock refuses to boot the canonical Hanzo cloud orchestrator against Postgres.
Package storagelock refuses to boot the canonical Hanzo cloud orchestrator against Postgres.
Package migration ports a legacy `hanzo_cloud` PostgreSQL database into per-(org, user) SQLite files served by the Hanzo cloud orchestrator (HIP-0106).
Package migration ports a legacy `hanzo_cloud` PostgreSQL database into per-(org, user) SQLite files served by the Hanzo cloud orchestrator (HIP-0106).
Package subsystems is the single source of truth for which Hanzo cloud subsystems are linked into a binary.
Package subsystems is the single source of truth for which Hanzo cloud subsystems are linked into a binary.
Package types holds the placeholder transport types AND the inter-subsystem client interfaces shared between cloud (the orchestrator) and cloud/clients (the in-process and RPC client implementations).
Package types holds the placeholder transport types AND the inter-subsystem client interfaces shared between cloud (the orchestrator) and cloud/clients (the in-process and RPC client implementations).
Package zapface serves the browser-facing ZAP RPC plane over WebSocket.
Package zapface serves the browser-facing ZAP RPC plane over WebSocket.

Jump to

Keyboard shortcuts

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