HIPsHanzo Proposals
Back to HIPs
HIP-1201FinalStandards TrackPlatform

Admission — Launch Control

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

HIP-1201: Admission — Launch Control

Abstract

admission is the launch-control gate for the deployment's hosted services: it decides, per request host, whether the service answering that host is in waitlist mode, and, per user, whether the caller has been admitted. It is apps/admission in hanzoai/cloud, and it is the complete waitlist feature composed one-way over the one flag engine — admission imports apps/flags; flags never imports admission (apps/admission/waitlist.go:19-20).

Its wire surface is one operation: the public mode read a guard or client resolves before anything else, answering "is this host gated, and which service governs it".

Motivation

Launch gating used to be a mode column beside the thing it gated. Decomplected, it is two orthogonal axes with a single decision plane: per-service mode is the platform switch waitlist.<svc>, evaluated through the flag engine — there is no second mode store — and per-user approval is IAM's, reused (apps/admission/waitlist.go:1-17, apps/admission/middleware.go:16-36). The engine stays a pure predicate; this package is its first composed tenant.

Specification

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

§1 Address

The capability answers one typed operation:

GET /v1/admission/waitlist  →  { host, service, waitlistMode, known }

?host= defaults to the host the request itself was addressed to; an unregistered host answers known: false (apps/admission/waitlist.go:311-323). Today's router serves this route at /v1/flags/waitlist, under a root owned by the flags capability; that pair is carried by hanzoai/cloud openapi/misfiled.txt and closes by fold. The stores are distinct files, so this is a misfiled route, never a split question.

The waitlist join API (/v1/waitlist) is served by base (manifest/apps.go:75) and is not this capability's.

§2 Store

The capability owns the launch registry: waitlist.db, a cloud.OrgStore named waitlist opened in the reserved platform/platform tenant — one file for the deployment, riding the same per-(org, project) machinery as the flag definitions, encrypted at rest (apps/admission/waitlist.go:37-47, apps/admission/registry.go:10-12). The registry is deliberately mode-free: it answers only which service owns a host and its display metadata; the mode itself is the flag engine's switch.

§3 The rule, and who may read

The mode read is anonymous by design and MUST remain so: an unadmitted visitor cannot hold a flag, so HIP-0139 §8.2's flag-gated 404 cannot apply to the endpoint that implements launch gating. The read carries no tenant data.

Enforcement applies the rule at one native middleware (Enforce, apps/admission/middleware.go): on a governed host in waitlist mode, a caller with a Hanzo API key is allowed (possession-gated), an approved user is allowed, a pending user is bounced to the waitlist, an unauthenticated one to login. Approval is fail-open — only the exact IAM value pending gates; absent, approved and rejected all read admitted (apps/admission/approval.go:28-35) — and the literal lives with the gate that acts on it, so two places can never disagree about who is waitlisted. A registry failure degrades to the in-memory brand seed and the decide fail-opens (apps/admission/waitlist.go:329-333); health, auth and the join API are never gated (apps/admission/middleware.go:106,120-124).

§4 Metering, events, observability, stage

The capability is free (plugin/admission/main.go:26, cloud.Free). It publishes no events on the bus and delivers nothing to customer webhooks. Beyond the request span, it emits its readiness line and warn-level degradation logs (apps/admission/waitlist.go:244-248,354). Its stage is whatever its manifest row says, and this text does not restate it: per HIP-0139 §8 the stage is declared once, in manifest.App.Stage, and a second copy here can only drift from it. It did — this section read ga while the row had been staged alpha, which is this capability's own case for the rule.

That the stage is not ga is a fact about who is shown the capability, never about whether this specification is settled; status: above answers that. Admission is this deployment's own launch control, so an org that is not the operator has nothing to configure through it.

§5 Upstream

The capability derives from no forked, embedded or mirrored OSS project.

Rationale

The alternative is a mode column in the registry — one store answering both "who owns this host" and "is it gated". That braids configuration into decision: every mode edit becomes a registry migration, and the flag engine's existing evaluation, audit and admin plane get a parallel twin. Composing the engine one-way keeps exactly one switch store and makes the arrow of dependency a checkable fact.

Security Considerations

The wrong implementation is measured by which way it fails. Enforcement that fails closed on a registry error locks every user out of login and out of the waitlist itself — which is why the decide fail-opens and the exempt prefixes exist. Enforcement that reads approval from a request value instead of IAM lets a caller admit themselves; the predicate MUST resolve from the identity plane or the minted header, never client input. The anonymous mode read discloses only what the gated landing page already shows: that a host is gated. It MUST NOT grow tenant data, or its openness becomes a leak.

References

  • HIP-0063 — Feature Flags Standard
  • HIP-0106 — The Hanzo Plugin Contract
  • HIP-0139 — Capability

Copyright

Released under CC0 1.0 Universal Public Domain Dedication.