Modules declare go 1.27.1 and the build images follow. go fix applied the
modernizers; omitzero is not applied, since it changes what the JSON says.
Co-authored-by: Hanzo Dev <[email protected]>
These types are published through the composed cloud document, whose
schema namespace is FLAT and global: `Service` appears in fifty-three
other app documents, `Run` and `Head` in ten each, and two names that
differ only in case are worse still — every generator PascalCases, so an
SDK binds whichever it read last or refuses to compile.
Three of the five are better names besides:
Version -> Artifact a tag and a digest identifying built bytes is
not a version; nothing here is semver.
Head -> Tip its own comment already said "the tip of the
default branch".
Service -> Pipeline the row is not a workload, it is the chain
behind one: head, built, declared, running.
Run -> Execution } free names for the two that only collided
Build -> Check }
The wire does not move: JSON comes from the tags and those are
untouched, which the shape test asserts. What changes is the name a
generated client gives the class.
Co-authored-by: Hanzo Dev <[email protected]>
It was package main, so nothing could import it — and that is why this
surface is the one a valid hanzo.id token cannot read. api.hanzo.ai
already carries /v1/deploy, the CD half of this same delivery plane,
behind the gateway's IAM identity; the CI half sits behind admin-guard
instead, which trusts an X-Org-Id header and answers a bearer with a
bare 401. A capability can be mounted; a package main can only be
deployed beside things.
Serve builds the handler and starts the pollers, taking a context so the
caller owns their lifetime. Both caches answer "no snapshot yet" rather
than blocking, so a mount never waits on an upstream fetch. Main keeps
the standalone server — listener and shutdown — and cmd/ci is four lines
over it, so the image is unchanged apart from the path it builds.
Main, not Run: a Run in this package is a CI run, the domain object, and
the binary's body is not one.
Co-authored-by: Hanzo Dev <[email protected]>
"Forge" was a borrowed word for the thing that hosts the repos, schedules the
builds and issues the tokens. That thing is Hanzo Git. The word named nothing a
reader could go look at, and it had already drifted: the same paragraph could
say "the forge" and "git.hanzo.ai" and leave you to work out they were one
thing.
forge.go becomes git.go for the same reason — the file reads what Hanzo Git
knows that the run list does not.
Where a second mention would just repeat the name, it says "the server"
instead. Left alone: "unforgeable" and "cannot be forged", which are the other
word entirely and mean what they say.
Co-authored-by: Hanzo Dev <[email protected]>
The table is wider than a phone and had no box to scroll in, so the page itself
scrolled sideways and carried the header and nav with it: a reader could see
that something was wrong but not what, which is the one thing the four columns
exist to say.
And two containers can share a repository at different versions on purpose — a
sidecar held back while the app moves on. Reading whichever came last reported
the pin unapplied on a service whose app container was carrying it, so the board
named drift where there was none. A workload runs the declared version if any of
its containers does.
The board showed build runs and nothing about deployment, so a service could
serve last week's code with every row on the page looking ordinary.
Four values per service, read from the systems that own them:
head ──build──▶ built ──pin──▶ declared ──reconcile──▶ running
Every arrow is a job of the pipeline this repo publishes — `image` produces the
artifact, `rollout` writes the pin cd.hanzo.ai reconciles — so a service is
current exactly when all four agree, and each way they disagree names the arrow
that did not happen: unbuilt, unshipped, unsynced, untested.
Head is read because the other three are not enough. built, declared and running
can name the same release while main has moved on and nothing since has produced
an image; comparing them to each other cannot see that at all.
Two readings the page depends on, both taken from a run's JOBS rather than its
single conclusion. A run that fails at `gate` built nothing and a run that fails
at `receipt` has already built, pinned and proved the release live — both report
`failure`. And a commit the forge never constructed a run for is absent rather
than failed: there is no log to open, so it is drawn as a different shape.
A service is its namespace and name, not its image: ghcr.io/hanzoai/static runs
as cdn, tabs and zen-landing on three versions at once, and keying rows by image
compares one service's pin against another's running version. The image is what
joins to the forge, where several services legitimately share one repo.
Comparisons refuse to guess. An unread source is never drawn as a difference, a
tag that cannot be ordered orders against nothing, and a commit still building
has not failed to produce an image.
Reads only — no deploy, retry or promotion. The cluster is read through the pod's
own ServiceAccount (get and list on workloads, nothing else, no stored
credential) and universe through the forge token this service already holds.
scope_test.go now covers /v1/fleet and the fleet page, and drives the real
router so the assertion cannot be made against a copy of a handler.