Documentation
¶
Overview ¶
Package blueprint mounts the Hanzo Cloud /v1/blueprint/* surface: the compute-cost basis for the OSS-template economy. Each deployable blueprint is a docker-compose stack (templates.hanzo.ai/blueprints/<id>/docker-compose.yml); this subsystem turns one into two things a deploying org and the console need:
- its SBOM — the bill of container images/services the stack runs, and
- a COMPUTE COST estimate — a per-hour rate derived from the services' summed CPU/memory footprint through a documented rate card (estimate.go).
That rate is what the platform SHOWS as "~$X/mo to run" per template, AND the basis the deploy path meters the deploying org on. It is therefore the cost the 20% author royalty (clients/authors, defaultShareBps=2000) is taken from: the author-royalty sweep already accrues 20% of a deploying org's metered platform spend; this package defines, from a real rate card rather than a fabricated number, the compute component of that spend.
DISTINCT FROM clients/sbom. That package stores a CycloneDX dependency SBOM keyed by image DIGEST — the packages INSIDE one image. This one derives the bill of IMAGES a compose stack runs and prices the stack's footprint. Different granularity, different concern; kept orthogonal.
Reference content, no store. The blueprints are embedded and validated once at mount (a malformed fixture fails the mount closed); there is no per-tenant state.
Surface (/v1 only):
GET /v1/blueprint list blueprint ids + a cost summary -> {data:[…]}
GET /v1/blueprint/sbom?template=<id> one blueprint's SBOM + cost -> Estimate
GET /v1/blueprint/sbom batch: every blueprint's SBOM + cost -> {data:[Estimate]}
GET /v1/blueprint/health liveness + the active rate card (not JWT-gated)
Registered as id "blueprint" with cloud.HealthOwner: it serves its own /v1/blueprint/health, so serve.go skips the generic liveness route.
Pure core of the blueprint estimator: the compose parser, the SBOM extractor (service→image bill of materials), the per-service sizing (declared reservations or a default footprint per service type), and the compute cost model (a documented rate card → cost per hour). Everything here is I/O-free and deterministic, so estimate_test.go drives it with inline compose documents — no registry, no network — exactly as clients/sbom/parse.go proves out its assemblers. blueprint.go is the thin orchestration that resolves a template id to a compose and serves these values.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type ClassFootprint ¶
type ClassFootprint struct {
Type string `json:"type"`
VCPU float64 `json:"vcpu"`
GB float64 `json:"gb"`
}
ClassFootprint is one published row of the sizing table: the per-replica footprint applied to a service of that class when its compose declares none.
func Sizing ¶
func Sizing() []ClassFootprint
Sizing publishes defaultSize, sorted by class so the disclosure is byte-stable across processes (Go map order is not).
type Estimate ¶
type Estimate struct {
TemplateID string `json:"templateId"`
SBOM []Service `json:"sbom"`
VCPUHours float64 `json:"vcpuHr"` // total vCPU per hour
GBHours float64 `json:"gbHr"` // total GB per hour
MicroUSDPerHour int64 `json:"microUsdPerHour"` // exact integer metering unit
CentsPerHour float64 `json:"estCentsPerHour"`
CentsPerMonth int64 `json:"estCentsPerMonth"` // for the "~$X/mo to run" label
RateCard RateCard `json:"rateCard"`
Estimate bool `json:"estimate"`
}
Estimate is the per-template result: the SBOM (bill of container images), the summed resource footprint, and the compute cost the deploying org is metered on. It is explicitly an ESTIMATE (Estimate: true) — the honest label the UI shows.
func EstimateCompose ¶
EstimateCompose parses a compose document and prices it with the process rate card. id labels the result (the template id); pass "" for an ad-hoc compose. This is the ONE entrypoint the HTTP handlers and the in-process deploy/metering seam call.
func EstimateService ¶
EstimateService prices ONE running service — a single container image at N replicas — with the process rate card. It is the single-container analogue of EstimateTemplate: a platform app (clients/platform) is one image at N replicas, not a compose stack, so the deploy-compute meter prices a running deployment through THIS seam while a multi-service blueprint prices through EstimateTemplate. Same kernel — class inferred from the image, class-default footprint × replicas, priced by the SAME RateCard via priceFootprint — so a bare deployment and a one-service template of the same image cost identically. est.MicroUSDPerHour is the exact per-hour figure the deploy path meters the deploying org on (the cost basis the 20% author royalty is then taken from). replicas < 1 is treated as 1.
func EstimateTemplate ¶
EstimateTemplate prices an embedded blueprint by id, returning ok=false for an unknown id. This is the ONE in-process entrypoint the deploy path calls to learn a template's compute rate: est.MicroUSDPerHour is the exact per-hour figure to meter the deploying org on (via the same commerce metering spine resource_billing uses), and est.CentsPerMonth is the "~$X/mo to run" the console renders. The author-royalty sweep (clients/authors) then accrues its 20% off that metered spend — so this function is the cost basis the royalty is taken from.
type RateCard ¶
type RateCard struct {
MicroUSDPerVCPUHour int64 `json:"microUsdPerVcpuHour"`
MicroUSDPerGBHour int64 `json:"microUsdPerGbHour"`
Basis string `json:"basis"`
}
RateCard is the two-knob compute price the estimator applies, carried on every Estimate so the response is self-documenting and the metering path reads the SAME numbers it displays. Values are microdollars per resource-hour.
func DefaultRateCard ¶
func DefaultRateCard() RateCard
DefaultRateCard is the shipped rate card (the constants above). rateCardFromEnv overlays operator overrides at Mount; the pure core defaults to this so tests are hermetic.
func Rates ¶
func Rates() RateCard
Rates publishes the LIVE card (post env overlay) so a client that must EXPLAIN a cost it did not itself compute — clients/authors disclosing the royalty basis — reads the one the estimator actually applied, not the shipped default. Returned by value: blueprint stays the only owner of the price.
type Service ¶
type Service struct {
Name string `json:"service"`
Image string `json:"image"`
Type string `json:"type"` // db | cache | web | worker | other
VCPU float64 `json:"vcpu"` // vCPU applied (× replicas)
GB float64 `json:"gb"` // GB memory applied (× replicas)
Replicas int `json:"replicas"` // deploy.replicas, default 1
Sized string `json:"sized"` // "declared" | "default"
}
Service is one row of the bill of materials: the compose service, its container image (the SBOM entry), the inferred class, the per-hour footprint applied, and whether that footprint was DECLARED in the compose or a class DEFAULT.