HIPsHanzo Proposals
Back to HIPs
HIP-1122FinalStandards TrackInfrastructure

Deploy — The GitOps Plane

Hanzo AI
Created: 2026-08-20
Requires: HIP-0026, HIP-0106, HIP-0139

HIP-1122: Deploy — The GitOps Plane

Abstract

/v1/deploy is Hanzo CD: see what each app in the fleet is running, sync it, and roll back a bad release. It is implemented in hanzoai/cloud at apps/deploy, observing the operator-managed fleet — applications, resource tree, per-object health, live diff — and driving reconciliation. Each operator hanzo.ai/v1 App CR is a GitOps Application (apps/deploy/deploy.go:8-11). This HIP states that the cluster is the store, which reads are tenant-scoped, and why the writes are SuperAdmin-only.

Motivation

The operator reconciles declared state into workloads whether or not anyone is watching; what was missing was the watch. Without one plane that projects the fleet — declared version, health, sync, the owned-resource tree — the answer to "what is running" is a kubectl session, which neither the console nor a tenant can be handed. This plane is that projection, at the addresses the CD dashboard that consumes it already speaks (apps/deploy/deploy.go:13-15).

Specification

The key words MUST, MUST NOT, SHOULD, SHOULD NOT and MAY are to be interpreted as in RFC 2119.

§1 The cluster is the store

deploy owns no store. Its state is the cluster's: App CRs, their owned objects (Deployment, Service, Ingress, ReplicaSet, Pod), and the static-plane site CRDs projected as Application rows so the fleet list covers the whole delivery surface (apps/deploy/deploy.go:76-84). Nothing this plane serves survives the cluster it reads, and nothing needs to.

§2 The addresses

Every route is under /v1/deploy, enumerated as explicit prefixes in the manifest row (manifest/apps.go:175). The fleet reads — applications, detail, resource tree, revisions, clusters, projects, settings, gitops, version — are typed. The raw routes are raw because their answers cannot be values: stream/applications and the streamed resource tree are event streams; login, callback and logout are the console's OIDC redirect dance against IAM (apps/deploy/login.go:128-140); sync, rollback and reconcile are imperatives answering acknowledgement, not a resource; account/can-i/{...} is a wildcard permission probe the dashboard issues.

§3 Tenancy — two scopes, one predicate

Scope is derived from the validated identity in one place (resolveScope, apps/deploy/scope.go:66-84): a SuperAdmin — decided by the c.IsAdmin() predicate alone, which already implies a validated principal — sees and mutates the whole fleet; a validated org member sees only apps carrying its own hanzo.ai/org label, read-only. The writes (sync, rollback, reconcile) MUST remain SuperAdmin-only: they change what runs. Secret objects are never surfaced — no tree node, no manifest — so the projection cannot leak materialized env (apps/deploy/deploy.go:36-38). Console sign-in resolves SuperAdmins through the admin-console IAM application, whose organization is the reserved admin org (apps/deploy/login.go:101-106), and validates tokens with the same validator the identity boundary uses.

§4 Money, events, telemetry

deploy is free, in those words (plugin/deploy/main.go:21, cloud.Free; not in spend.go:275). It publishes no events on the bus — the stream routes are per-request server-sent events, not bus topics — and it emits nothing to observability beyond the request span every route gets.

§5 Stage

deploy is ga: it is the platform core's delivery lens, part of the self-service agentic OS rather than a vertical application.

§6 Upstream

deploy derives from no forked code. Two third-party facts stand: it reads the cluster through k8s.io/client-go (Apache-2.0), and it serves the CD dashboard's own address shapes so that console consumes it unchanged (apps/deploy/deploy.go:13-15) — a wire dialect implemented, not code inherited.

Rationale

The alternative to reading the cluster is keeping a deployment database and reconciling it against reality — a second copy of state whose one failure mode, drift, is exactly what a CD plane exists to expose. Reading the CRs directly means the plane can be wrong only by being stale, never by disagreeing.

Security Considerations

The wrong implementation is a cluster console handed to tenants. Three boundaries hold it: writes require the SuperAdmin predicate, org reads are filtered by the org label resolved from the validated principal (never a header), and Secrets are excluded from the tree at the GVR list, so no query shape can reach them. The OIDC flow fails closed — a missing verifier or public URL disables sign-in rather than weakening it (apps/deploy/login.go:119-121).

References

  • HIP-0026 — Identity and Access Management
  • HIP-0106 — Hanzo Plugin Contract
  • HIP-0139 — Capability

Copyright

Released under CC0 1.0 Universal Public Domain Dedication.