Files
hips/HIPs/hip-0520-serving-topology.md
zeekayandHanzo Dev 7a9dcac628 What each runtime implements of the Hanzo corpus
An audit read the code and found the proposal that specifies it. Go reaches
all 122 capability proposals and 64 of the 121 other Standards Track ones;
Rust has 35, mostly the operator and the CLI; C++ has three, because the
complete original C++ in the estate is a ZAP handler, a bot nothing specifies,
and authored kernels inside forked CUDA and Metal crates.

    | | shipped | partial | none | not assessed |
    | Go   | 146 | 33 | 1 |  80 |
    | C++  |   1 |  2 | 0 | 257 |
    | Rust |  10 | 25 | 1 | 224 |

The large "not assessed" columns are the point rather than a gap. The model and
training specs are Python, the frontend and design-system proposals are
TypeScript, and recording `none` against those would read as a search that
came up empty when the honest statement is that the runtime was never the
question. Governance, Meta and Process are not graded at all.

Six proposals are Final with nothing found in Go and are left unwritten rather
than demoted: 0065, 0089, 0098, 0103, 0521 and 0902. HIP-0521 answers itself,
its own section reading "Not yet implemented". Three of the others name a
canonical Go file in consensus/protocol/auth that nobody wrote, in a package
where the four neighbouring proposals' files all exist with tests beside them.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-05 19:18:13 -07:00

5.8 KiB

hip, title, author, type, category, status, implementation-go, created, requires
hip title author type category status implementation-go created requires
0520 Serving Topology — Three Tiers, Horizontally Scalable, Pinned Per Entity Hanzo AI Team Standards Track Infrastructure Final partial 2026-07-29 HIP-0519

HIP-0520: Serving Topology — Three Tiers, Horizontally Scalable, Pinned Per Entity

Abstract

Three tiers, each holding one concern, each horizontally scalable:

  DO LB ──▶ ingress          TLS termination. Decides nothing.
        ──▶ gateway          THE EDGE: JWT verify, authz, rate limit.
        ──▶ cloud            Serves ANY request through the plugin framework.
                  └── ZAP over UDS ──▶ plugins (lazy, capabilities)

One transport family: ZAP over QUIC between tiers, ZAP over a unix socket on-host. Every tier scales by adding replicas.

Cloud is stateless but pinned: a replica owns no durable state, yet requests for one entity land on one replica, because a per-org store has exactly one writer.

Specification

The tiers

Ingress terminates TLS and forwards. It holds no identity, mints no header, makes no authorization decision. Any replica serves any request.

Gateway is the edge (HIP-0519): it strips client-supplied identity, verifies the credential against IAM, mints the identity headers, and applies the rate limit. Any replica serves any request, because the JWKS is cacheable and the decision is a pure function of the token.

Cloud serves any request through the plugin framework. It holds no state of its own; the state belongs to the plugins' stores, and a store has ONE OWNER.

Pinned per entity

A per-org store has one writer, so two replicas must never open one org's store. The request therefore goes to the replica that owns the entity:

  replica = rendezvous(entity, live replicas)

Highest-Random-Weight (rendezvous) hashing, not modulo: adding or removing a replica moves only the keys that must move, rather than reshuffling every key.

The entity is the owner of the store being written — the org for per-org data, the user or writer where the store is finer. It is read from the identity the edge already minted, so pinning costs no lookup and cannot disagree with the tenancy decision.

Pinning is a ROUTING property, never an authorization one. A request that reaches the wrong replica must be forwarded or refused, never served from a store the replica does not own. Reading a store you were not routed to is the single-writer violation this exists to prevent.

Lazy plugins

A plugin's process starts on FIRST USE, not at boot. A host composing dozens of plugins pays for the ones traffic reaches, not for the set. Dependency is a typed capability the plugin declares and is handed: the call boots the callee if it is registered, and the type — not a name string — is what says the dependency exists (HIP-0519 §capabilities).

Laziness is what makes many plugins affordable, and it is why a replica can serve ANY request: it need not hold every plugin resident to be able to answer for any of them.

Transport by locality, never by caller choice

The address SHAPE picks the transport, and one rule serves the listener and the dialer alike, so a node can never bind one transport and be dialled on another:

locality address transport
same process — no transport at all; call the consumer directly
same machine a socket PATH (/run/hanzo/x.sock) UDS — no kernel network stack, no port, no TLS to misconfigure
remote host host:port QUIC

A cross-machine hop on plain TCP is the case worth naming: an agent shipping every pod's telemetry across the cluster network carries other services' bodies, which is exactly the traffic that must not be readable in transit.

QUIC's TLS 1.3 negotiates X25519MLKEM768 (X-Wing) by default on Go 1.26, so the session key is quantum-secure with no per-caller crypto configuration. That is the whole reason locality picks the transport rather than a flag: the secure choice is the default one, and a caller cannot opt out by forgetting.

A PQ transport needs an identity, and an identity is a KMS concern. QUIC cannot start without server credentials, so "enable QUIC" is not a config flag — it is a key. Naming it in config and sourcing it anywhere but KMS is how a transport silently falls back to unencrypted or fails at start for a reason the operator cannot see.

KMS is the only source of identity and environment

Every credential and every piece of environment comes from KMS: the transport's TLS identity, a plugin's scoped material, a service's tokens. Never a plaintext file, never a baked image layer, never an env var an operator pasted.

This is what makes a lazily-started plugin safe to start: the host injects that child's own material, scoped to it, so a plugin holds exactly the secrets it was issued and no sibling's. A shared secret handed to every child proves nothing about any of them.

Deployment

Every change deploys natively through cd.hanzo.ai. No hand-applied manifests: a resource applied by hand is one git and the cluster can disagree about, with nothing to detect the drift. HIP-0519 records two network policies that are inert for exactly that reason.

Security Considerations

A pin is not a permission. Routing decides which replica answers; authorization decides whether the answer is owed. A replica must apply the same tenancy check whether or not it was the pinned one.

The edge must be unavoidable. Cloud replicas reachable without traversing the gateway accept whatever headers a caller sends — see HIP-0519, where a forged identity reads another tenant's secret.

References

  • HIP-0519 — One Identity Boundary (the edge, the header set, capabilities)
  • HIP-0106 — Wire protocol stack

Released under the MIT License.