gateway

package module
v2.16.19 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 30, 2026 License: Apache-2.0 Imports: 30 Imported by: 0

README

gateway

gateway

HTTP gateway: routing, JWT validation, identity strip + mint, rate limit, circuit break, telemetry.

Status License

Quick start

docker run -p 8080:8080 ghcr.io/hanzoai/gateway:latest

Build dependency: GOEXPERIMENT=jsonv2

The HIP-0106 in-process gateway mount runs on hanzoai/zip, which routes every JSON path through stdlib encoding/json/v2 when the binary is compiled with GOEXPERIMENT=jsonv2. Shipped Dockerfile + CI workflow set the flag; manual builds should do the same:

GOEXPERIMENT=jsonv2 make build

Without the experiment the binary still builds and runs - zip falls back to encoding/json v1. v2 is preferred for production: ~10% faster on the edge, ~25% fewer allocations per request. The mount startup log line json_variant=encoding/json/v2 confirms it is active.

No third-party JSON library is allowed in the Hanzo Go stack - stdlib only (HIP-0106 canonical Hanzo Go stack).

What this is

gateway is the unified API entry point for the Hanzo platform. Behind hanzoai/ingress (L7 TLS), in front of every Hanzo backend service. Validates JWTs against Hanzo IAM JWKS, strips every client-supplied identity header (X-User-*, X-Org-Id, ...), mints the three canonical identity headers from the JWT, then forwards in-process (when co-resident under hanzoai/cloud) or over the wire to downstream services.

Specs

Implements:

  • HIP-0026 IAM (identity-header contract)
  • HIP-0106 Unified Cloud Binary (gateway subsystem — already exposes Mount())

Architecture

   Internet  ->  hanzoai/ingress (TLS, L7)  ->  hanzoai/gateway
                                                    |
                                          JWT validation (IAM JWKS)
                                                    |
                          strip client X-* identity headers (unconditional)
                                                    |
                          mint X-User-Id / X-Org-Id / X-Roles from JWT
                                                    |
                          rate-limit, circuit-break, telemetry
                                                    |
                          in-process route to cloud subsystems
                                          OR
                          over-the-wire to standalone services

Hanzo Gateway

High-performance API gateway for Hanzo AI services. Routes 147+ API endpoints across production clusters with rate limiting, authentication forwarding, CORS, circuit breakers, and telemetry -- all driven by declarative JSON configuration.

CI Go License Docker

Overview

Hanzo Gateway is the unified API entry point for all Hanzo platform traffic. It sits behind Hanzo Ingress (L7 reverse proxy) and routes requests to internal services with per-endpoint rate limiting, header forwarding, and circuit breaker protection.

Cluster Domain Endpoints Rate Limit (global) Rate Limit (per IP)
hanzo-k8s api.hanzo.ai 133 5,000 req/s 100 req/s

The gateway can also be deployed independently by other organizations with their own configuration.

For full documentation, see docs.hanzo.ai/docs/services/gateway.

Architecture

                    Internet
                       |
              +--------+--------+
              |  Cloudflare CDN |
              +--------+--------+
                       |
              +--------+---------+
              | Hanzo Ingress    |
              | (L7 TLS/routing) |
              +--------+---------+
                       |
              +--------+---------+
              | Hanzo Gateway    |
              | 133 endpoints    |
              +---+----+----+----+
                  |    |    |
               Cloud  IAM  Commerce
               API         API

API Endpoints

OpenAI-Compatible LLM Routes (api.hanzo.ai)

These endpoints are fully compatible with the OpenAI API format. Point any OpenAI SDK client at https://api.hanzo.ai and it works out of the box.

Method Path Backend Description
POST /v1/chat/completions cloud:8000 Chat completions (streaming and non-streaming)
POST /v1/completions cloud:8000 Text completions
POST /v1/messages cloud:8000 Anthropic Messages API compatibility
GET /v1/models cloud:8000 List available models
POST /v1/embeddings cloud:8000 Text embedding generation
POST /v1/images/generations cloud:8000 Image generation
POST /v1/audio/transcriptions cloud:8000 Audio transcription (Whisper)
POST /v1/audio/speech cloud:8000 Text-to-speech synthesis
POST /v1/zap cloud:8000 Hanzo Zap (structured extraction)
POST /v1/async-invoke cloud:8000 Async inference (long-running jobs)
GET /v1/async-invoke/{id}/status cloud:8000 Poll async job status
GET /v1/async-invoke/{id} cloud:8000 Retrieve async job result
Platform Service Routes (api.hanzo.ai)

All platform routes are available at both /{service}/* and /v1/{service}/*.

Path prefix Backend Description
/auth/* iam:8000 IAM, authentication, OAuth
/cloud/* cloud:8000 Cloud API (projects, deployments)
/commerce/* commerce:8001 Commerce (orders, payments, products)
/analytics/* analytics Unified analytics and events
/billing/* billing Usage metering and invoicing
/console/* console Admin console API
/agents/* agents Agent orchestration
/search/* search AI-powered search
/vector/* vector Vector database operations
/operative/* operative Computer-use automation
/bot/* bot Bot framework (REST + WebSocket)
/kms/* kms Key management service
/platform/* platform PaaS deployment API
/functions/* functions Serverless functions
/web3/* web3 Web3 and blockchain APIs
/pricing/* pricing Model pricing and rate cards
/pricing/model/{name} pricing Single model price lookup
Monitoring Endpoints
Path Description
/__health Gateway health check (port 8080)
/health Application health check
/pubsub/healthz PubSub health
/pubsub/varz PubSub variables / metrics
/pubsub/connz PubSub connections
/pubsub/subsz PubSub subscriptions
/pubsub/jsz PubSub JetStream

Model Routing

Hanzo Gateway proxies all LLM requests through the Hanzo Cloud API (cloud), which handles model routing, load balancing, and provider selection. The gateway itself is provider-agnostic -- it forwards authenticated requests and streams responses back to the client.

How It Works
Client                Gateway              Cloud API            Provider
  |                      |                     |                    |
  |-- POST /v1/chat ---->|                     |                    |
  |   model: "zen4"      |-- forward --------->|                    |
  |                      |                     |-- route to tier -->|
  |                      |                     |   (Fireworks)      |
  |<---- streaming ------|----- streaming -----|<--- streaming -----|
  1. The client sends a request to api.hanzo.ai/v1/chat/completions with a model field.
  2. The gateway forwards the request (with all auth headers) to the Cloud API backend.
  3. The Cloud API resolves the model name to a provider and endpoint based on the model's tier and availability.
  4. Responses stream back through the gateway to the client with no buffering.
Model Tiers
Tier Models (examples) Provider Notes
Free zen3-nano, zen4-mini Hanzo DO cluster Best-effort, rate-limited
Standard zen4-pro, zen3-vl, zen4-coder-flash Fireworks, Together Low latency, high availability
Premium zen4, zen4-max, zen4-ultra Fireworks Dedicated capacity, highest throughput
Third-party gpt-4o, claude-sonnet-4-20250514, gemini-2.5-pro OpenAI, Anthropic, Google Pass-through with unified billing

The gateway does not need to know about model tiers -- it passes all requests to the Cloud API, which handles routing logic, fallback, and retries. Model availability is returned by GET /v1/models.

Authentication

All requests to api.hanzo.ai require a valid API key. Keys are issued through the Hanzo Console and scoped to a project.

API Key Authentication

Pass your API key in the Authorization header using the Bearer scheme:

curl https://api.hanzo.ai/v1/chat/completions \
  -H "Authorization: Bearer hk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "zen4-pro",
    "messages": [{"role": "user", "content": "Hello"}]
  }'
Auth Flow
Client --> Gateway --> Cloud API --> IAM (hanzo.id)
                                        |
                                    Validate key
                                    Resolve org/project
                                    Check rate limits
                                    Return user context

The gateway validates bearer JWTs against IAM (hanzo.id) using JWKS and re-emits the canonical 3 identity headers. Opaque API keys (hk-, sk-, fw_, hz_, pk-) pass through to the backend services for validation.

Header Forwarding

After JWT validation, the gateway emits exactly three canonical identity headers to downstream services and strips every other vendor/legacy variant on ingress:

  • X-User-Id -- user ID from JWT sub claim
  • X-Org-Id -- org slug from JWT owner claim
  • X-Roles -- comma-joined role names from JWT roles claim

Auxiliary headers emitted by the gateway (derivatives of the JWT):

  • X-User-Email -- email from JWT email claim
  • X-Phone-Number -- phone from JWT phone_number/phone claim
  • X-User-IsAdmin -- "true" when the JWT asserts isAdmin

Standard passthrough headers:

  • Authorization -- Bearer token or API key
  • Content-Type -- Request body encoding
  • Accept -- Response format preference
  • X-Request-ID -- Client-provided request tracing ID

Headers stripped unconditionally on ingress (never trusted from clients): X-User-Id, X-Org-Id, X-Roles, X-User-Email, X-Phone-Number, X-User-IsAdmin, X-User-Role, X-User-Roles, X-User-Name, X-Tenant-Id, X-Org, and every X-IAM-* / X-HANZO-* variant.

Rate Limiting

The gateway enforces rate limits at two levels: global (across all clients) and per-client (by IP address).

Global Configuration
{
  "extra_config": {
    "qos/ratelimit/router": {
      "max_rate": 5000,
      "client_max_rate": 100,
      "strategy": "ip"
    }
  }
}
Parameter Description Default
max_rate Total requests/second across all clients 5,000
client_max_rate Requests/second per client IP 100
strategy Client identification method ip
Per-Endpoint Overrides

Individual endpoints can override the global limits. This is useful for high-traffic inference routes or sensitive administrative endpoints:

{
  "endpoint": "/v1/chat/completions",
  "method": "POST",
  "extra_config": {
    "qos/ratelimit/router": {
      "max_rate": 10000,
      "client_max_rate": 50,
      "strategy": "ip",
      "every": "1s"
    }
  }
}

The every field sets the time window for the rate counter. Default is "1s" (per second). Set to "1m" for per-minute limits.

Rate Limit Responses

When a client exceeds their rate limit, the gateway returns:

HTTP/1.1 429 Too Many Requests
Content-Type: application/json

{"message": "rate limit exceeded"}

Observability

Logging

Structured logging is enabled by default with the [GATEWAY] prefix:

{
  "extra_config": {
    "telemetry/logging": {
      "level": "INFO",
      "prefix": "[GATEWAY]",
      "syslog": false,
      "stdout": true
    }
  }
}

Log levels: DEBUG, INFO, WARNING, ERROR, CRITICAL.

Health Check
# Gateway health (always returns 200 when the process is up)
curl http://localhost:8080/__health

# Application health (checks backend connectivity)
curl https://api.hanzo.ai/health
Metrics

The gateway exposes Prometheus-compatible metrics for scraping. Key metrics include:

  • Request count by endpoint and status code
  • Response latency histograms
  • Backend connection pool utilization
  • Circuit breaker state transitions
  • Rate limiter rejection counts
Circuit Breakers

Backend failures are automatically isolated. When a backend exceeds the error threshold, the circuit opens and requests are rejected immediately until the backend recovers. This prevents cascade failures across services.

Quick Start

Build from Source
# Build gateway binary
make build

# Build ingress sidecar binary
make build-ingress

# Run tests
make test

# Validate all configs
make validate
Run Locally
# Run with default config
./gateway run -c configs/hanzo/gateway.json
Docker
# Pull and run the latest image
docker run -p 8080:8080 ghcr.io/hanzoai/gateway:latest

# Build from source
make docker
Docker Compose
services:
  gateway:
    image: ghcr.io/hanzoai/gateway:latest
    ports:
      - "8080:8080"
    volumes:
      - ./configs/hanzo/gateway.json:/etc/gateway/gateway.json:ro
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:8080/__health"]
      interval: 10s
      timeout: 3s
      retries: 3
    restart: unless-stopped

Save as compose.yml and run:

docker compose up -d

Production Deployment

Hanzo Gateway runs on the hanzo-k8s DOKS cluster (do-sfo3-hanzo-k8s) in the hanzo namespace. Continuous deployment is handled by GitHub Actions -- every push to main builds a new image, applies the ConfigMap, and performs a rolling restart.

Deploy
# Apply config and restart pods
make deploy-hanzo

# Check status
make status

# Tail logs
make logs-hanzo
Infrastructure Details
Property Value
Image ghcr.io/hanzoai/gateway:latest
Replicas 2
Service type ClusterIP (behind Ingress)
Namespace hanzo
K8s context do-sfo3-hanzo-k8s
Health check GET /__health :8080
CI/CD GitHub Actions (deploy.yml)
K8s Manifests
k8s/
  hanzo/
    deployment.yaml     # Gateway deployment (2 replicas)
    service.yaml        # ClusterIP service
    ingress.yaml        # Ingress resource for api.hanzo.ai

Configuration

All routing is defined in JSON configuration files. Each cluster has its own config.

Editing Routes
  1. Edit the config file:

    $EDITOR configs/hanzo/gateway.json
    
  2. Validate the config:

    make validate
    
  3. Deploy:

    make deploy-hanzo
    

The Makefile creates a ConfigMap from the JSON file and triggers a rolling restart.

Config Structure
{
  "version": 3,
  "name": "Hanzo API Gateway",
  "port": 8080,
  "timeout": "120s",
  "extra_config": {
    "router": {
      "return_error_msg": true
    },
    "qos/ratelimit/router": {
      "max_rate": 5000,
      "client_max_rate": 100,
      "strategy": "ip"
    },
    "telemetry/logging": {
      "level": "INFO",
      "prefix": "[GATEWAY]",
      "stdout": true
    }
  },
  "endpoints": [
    {
      "endpoint": "/v1/chat/completions",
      "method": "POST",
      "input_headers": ["*"],
      "output_encoding": "no-op",
      "backend": [{
        "url_pattern": "/api/chat/completions",
        "host": ["http://cloud.hanzo.svc.cluster.local:8000"],
        "encoding": "no-op"
      }]
    }
  ]
}

Repository Structure

configs/
  hanzo/
    gateway.json        # Hanzo API Gateway config (133 endpoints)
    ingress.json        # Hanzo Ingress sidecar config
k8s/
  hanzo/                # K8s manifests for hanzo-k8s cluster
cmd/
  gateway/              # Gateway binary entry point
  ingress/              # Ingress sidecar binary entry point
tests/                  # Integration tests
Dockerfile              # Multi-stage build (Go 1.25 + Alpine 3.23)
Makefile                # Build, test, validate, deploy commands

DNS

Domain Path Target
*.hanzo.ai Cloudflare hanzo-k8s LB -> Ingress -> Gateway

Hanzo Gateway is one of four products in the Hanzo AI infrastructure stack:

Product Role Repository
Hanzo Ingress L7 reverse proxy, TLS termination, load balancing hanzoai/ingress
Hanzo Gateway API gateway, rate limiting, endpoint routing hanzoai/gateway
Hanzo Engine GPU inference engine, model serving hanzoai/engine
Hanzo Edge On-device inference runtime (mobile, web, embedded) hanzoai/edge
Internet -> Ingress (TLS/L7) -> Gateway (API routing) -> Engine (inference) / Cloud API / Services
                                                          Edge (on-device, client-side)

See also:

License

Apache-2.0 -- see LICENSE and NOTICE.

The service-assembly layer is derived from upstream Apache-2.0 projects and built on the Lura framework. The full upstream attributions -- which are the authoritative ones -- are preserved verbatim in NOTICE.

Documentation

Overview

build_app.go wires the gateway edge per HIP-0110.

The gateway is a pure ZAP→ZAP relay: ingress terminates TLS+HTTP and speaks ZAP to the gateway; the gateway authenticates on the Forward ENVELOPE, injects identity, and forwards to cloud/base over ZAP. The relay therefore lives on the ZAP node (RegisterRelay), not on an HTTP router — there is no per-request HTTP handling at the gateway anymore.

BuildApp still returns a tiny *zip.App so cmd/gateway/main can keep its :8080 listener as a process/liveness surface (ingress owns real client HTTP). It carries no forwarder and no auth middleware — those moved onto the node. RegisterRelay is the real entrypoint.

Package gateway is the Hanzo Gateway edge: the JWT trust boundary (identity strip + mint), the host/path routing table, and the HIP-0106 in-process mount surface consumed by the unified cloud binary.

Mount

The canonical entrypoint is Mount, in mount.go at the module root:

func Mount(app *zip.App, deps cloud.Deps) error

It carries NO build tag — it compiles in the default build. Consequently github.com/hanzoai/cloud is an unconditional dependency of this package and of the standalone cmd/gateway binary. Mount installs the auth middleware, serves GET /_/gateway/healthz, and best-effort loads the routes table; it is called explicitly by cloud's composition root (cloud/apps.Wire), not by an init() and not via a global registry.

Build tags

Two builds exist, and the one that SHIPS is `legacy`:

go build ./...               // default: no Lura; ZAP relay edge
go build -tags legacy ./...  // legacy: full Lura gin engine

Makefile sets BUILD_TAGS ?= legacy and the Dockerfile runs `make build`, so ghcr.io/hanzoai/gateway is the legacy engine. The default build serves only /healthz until the HIP-0110 ZAP relay backends are live; see the rationale comment above BUILD_TAGS in the Makefile.

Forwards-only: never add a lura import to a non-`legacy` file.

gate.go is the gateway relay's authn policy, run on every inbound Forward ENVELOPE per HIP-0110. It is the edge trust boundary: the gate validates the IAM JWT carried in the Forward's headers and stamps the resolved identity (TenantID/UserID/IsAdmin/Permissions) onto the envelope so the backend trusts the edge. forward.Relay then re-emits the Forward with that identity and ships it to the chosen backend.

One auth implementation: the gate reuses hanzoai/authz/edge (the same JWKS cache + JWT validation + token extraction shared with cmd/ingress and the gin/Lura middleware) and gateway's own permission bit-field math (computePermissionsBitField / permissionBits). No second copy.

Billing is NOT enforced here. The gateway is authn + identity injection only; cloud's own prepaid balance gate bills the bridged request. This split is deliberate (HIP-0110): the relay must not read f.Body and must not block on a per-request Commerce round-trip — it stamps identity and forwards. The gate therefore touches f.Path and f.Headers only.

Package gateway exposes the HIP-0106 unified-binary mount surface for the Hanzo Gateway. In the unified cloud binary the gateway acts as the trust boundary: it validates JWTs, strips client-supplied identity headers, and mints the gateway-authorized X-Org-Id / X-User-Id / X-User-Email / X-Roles / X-User-Permissions / X-User-IsAdmin / X-Phone-Number set documented in HIP-0026.

In split-deploy mode (legacy ghcr.io/hanzoai/gateway image) the gateway runs as its own legacy-engine process — the standalone cmd/gateway binary keeps that path. The Mount path below is the SAME logic, reused inside the cloud binary so we do not maintain two trust boundaries.

peer_resolver.go decouples "where a backend lives" (its ZAP address) from "which connected NodeID forward.Relay must Call" (the handshake- learned peerID). HIP-0110's relay needs a peerID per request path, but a peerID is only knowable AFTER a successful ConnectDirectID handshake.

The original boot path braided three concerns into dialBackends: start the node, eagerly dial both backends, and treat any dial failure as a fatal os.Exit. That made the gateway un-bootable whenever cloud:9090 / base:9091 were absent — which is the steady state in environments where the ZAP backends aren't deployed yet, while HTTP serving (the part prod actually needs) would work fine.

peerResolver separates those concerns. The node is started once and unconditionally; dialing a backend is deferred to first use and retried on every Call until it succeeds. A backend being down degrades only the requests routed to it (they get a "peer not found" error that forward.Relay returns to the caller as a normal per-request failure), never the process. ConnectDirectID is idempotent — once a backend is reachable the first resolve caches its peerID and every subsequent resolve is a lock-free map read — so a healthy backend is dialed exactly once and ZAP behaves identically to the old eager path.

routes.go is the gateway's pure host/path reverse-proxy routing table and CORS preflight — stdlib + gin + yaml, with ZERO dependency on the upstream Lura SDK. It is the default-build routing surface: the HIP-0110 trust-boundary mount (mount.go) loads this table via LoadRoutesFromFile so any path not owned by a co-resident subsystem is proxied to its configured backend, and the standalone binary shares the same table.

The legacy Lura gin-engine builder (NewEngine) that also consumed this table used to live alongside it in router_engine.go; it now sits behind the `legacy` build tag in legacy_engine.go so the upstream Lura graph stays out of the default build and the shipping image (see that file's header for the full rationale).

Index

Constants

View Source
const NeutralServerBrand = "gateway"

NeutralServerBrand is the Server value when a request Host matches no brand (internal k8s probes, direct-IP hits). Brand-neutral and honest about the role without ever naming the framework (fasthttp / fiber / zip / the legacy engine).

Variables

This section is empty.

Functions

func AssertGatewayMinted

func AssertGatewayMinted(c *zip.Ctx) bool

AssertGatewayMinted returns true iff the request flowed through gateway's auth middleware (i.e. X-Org-Id was minted by gateway, not supplied by the client).

Implementation: gateway middleware sets a per-request Locals key after JWT validation. AssertGatewayMinted reads that key.

In production, every cloud-mounted subsystem should reject any request where AssertGatewayMinted returns false (HTTP 502 with a clear message — it indicates a deployment misconfiguration, not a client problem).

func BuildApp

func BuildApp(deps RouterDeps) (*zip.App, error)

BuildApp returns the gateway's tiny HTTP surface for cmd/gateway/main's :8080 listener. Real client traffic arrives over ZAP via RegisterRelay; this app exists only so the process exposes a liveness/readiness HTTP endpoint on the public port. It carries no forwarder.

func InitZapListenerFromEnv

func InitZapListenerFromEnv()

InitZapListenerFromEnv initializes the ZAP listener from environment variables. Set ZAP_LISTENER_ENABLED=true to enable.

func LoadRoutes

func LoadRoutes(cfg *RoutesConfig) error

LoadRoutes loads routing config from YAML. Called at startup and on hot-reload.

func LoadRoutesFromFile

func LoadRoutesFromFile(path string) error

LoadRoutesFromFile loads routes from a YAML file.

func Mount

func Mount(app *zip.App, deps cloud.Deps) error

Mount registers the gateway subsystem on app per HIP-0106. The mount does three things:

  1. Installs the canonical zip middleware chain (strip client-supplied identity headers, validate JWT, mint X-* headers) so every downstream subsystem on the same zip.App sees a clean trust boundary.

  2. Loads the gateway routes table (KMS or local file) so any path not handled by a co-resident subsystem is proxied to the configured backend.

  3. Exposes /_/gateway/healthz on the native zip surface so liveness probes work even with auth fully enabled.

Mount is idempotent — calling it twice on the same App will install the middleware twice; the cloud composition root (apps.Wire) lists the gateway MountSpec once, so it is mounted exactly once per process.

func NewAuthMiddleware

func NewAuthMiddleware(cfg AuthConfig) gin.HandlerFunc

Public endpoints (configurable allowlist) bypass all auth checks.

func NewLazyPicker

func NewLazyPicker(node *zaplib.Node, logger luxlog.Logger, baseAddr, cloudAddr string) forward.PeerPicker

NewLazyPicker is the production seam: it builds a lazy resolver over an already-started node, best-effort warms the base and cloud backends (a failed warm is logged at WARN and ignored — the picker will retry on first use), and returns the forward.PeerPicker for RegisterRelay. The gateway boots regardless of backend reachability; healthy backends are dialed once here and served from cache thereafter.

func NewWidgetSecurityMiddleware

func NewWidgetSecurityMiddleware(cfg WidgetSecurityConfig) gin.HandlerFunc

NewWidgetSecurityMiddleware creates a gin middleware that enforces:

  1. Per-IP rate limiting for widget keys (hz_*): prevents any single IP from abusing the free widget endpoint.

  2. Global rate limiting across all widget requests: prevents distributed attacks from exhausting model API budget.

  3. Origin validation: widget keys are only accepted from approved Hanzo domains (Origin or Referer header). Non-browser clients (curl, scripts) that omit Origin headers are rejected for widget keys.

This middleware MUST run after NewAuthMiddleware. It only acts on requests with hz_ bearer tokens; all other requests pass through untouched.

func RegisterRelay

func RegisterRelay(deps RelayDeps) error

RegisterRelay installs the canonical HIP-0110 relay on deps.Node:

  • forward.Relay(node, gate, pick): decodes each inbound Forward envelope, runs the auth gate on it (JWT validate + identity inject, NO body read, NO billing — cloud bills the bridged request), re-emits the Forward with identity, and forwards to the picked peer, streaming the backend's Response back verbatim.
  • forward.RegisterReversePushHandler(node): routes backend→gateway Push frames (SSE / WebSocket) back to the originating client conn.

The gate reuses hanzoai/authz/edge + this gateway's money bit-field math; there is exactly one auth implementation. pick routes /v1/base/* to the base peer, everything else to cloud.

func SetGatewayMinted

func SetGatewayMinted(c *zip.Ctx)

SetGatewayMinted marks the current request as gateway-minted. Called by gateway's auth middleware after successful JWT validation (or trusted-headers pass-through). Subsystems must NEVER call this — it is the trust boundary itself.

func StartZapListener

func StartZapListener(cfg ZapListenerConfig) error

StartZapListener starts a TLS 1.3+PQ listener on the given port. External clients (e.g. dev CLI) connect here with TLS-wrapped ZAP binary. Each accepted TLS connection is transparently proxied to the internal ZAP node (started by the ZapBackendFactory pool on the internal port), which handles the ZAP handshake, message dispatch, and forwarding to cloud.

func StopZapListener

func StopZapListener()

StopZapListener gracefully shuts down the ZAP TLS listener.

Types

type AuthConfig

type AuthConfig struct {
	// Enabled controls whether the auth middleware is active.
	// Default: true. Set to false via AUTH_ENABLED=false to disable
	// all auth checks (useful for integration tests and development).
	Enabled bool

	// JWKS URL to fetch signing keys (default: https://hanzo.id/v1/iam/.well-known/jwks)
	JWKSURL string

	// Expected JWT issuer (default: https://hanzo.id)
	Issuer string

	// Audiences is the allowlist of acceptable JWT `aud` values. A token
	// passes when its audience matches ANY entry. IAM stamps user tokens with
	// aud=<client_id>, so a single fixed audience rejects every user JWT; the
	// allowlist (token.AudiencesFromEnv) is the fix. Override entirely with
	// GATEWAY_ALLOWED_AUDIENCES.
	Audiences []string

	// Billing check endpoint (default: http://commerce.hanzo.svc.cluster.local:8001)
	BillingURL string

	// BillingToken is the COMMERCE_SERVICE_TOKEN for authenticating with Commerce.
	BillingToken string

	// BillingEnabled controls whether billing checks are performed.
	// Default: true (checks enabled). Set to false to disable.
	BillingEnabled bool

	// BillingPaths scopes balance enforcement to request paths matching one
	// of these prefixes. This is the one knob that keeps billing OFF for the
	// AI/validated (per-token billed downstream) and public routes while
	// ON for the metered must-gate platform surface (cloud/tasks/insights/
	// o11y/mpc/evals/licensing/product/provisioning/…). The /v1/commerce
	// funding surface is hard-excluded in code (billingPathMatch) regardless
	// of this list. Empty list enforces on every non-funding, non-public
	// route. Set BILLING_PATHS to the must-gate prefixes. One scope.
	BillingPaths []string

	// Paths that bypass auth entirely (exact prefix match)
	PublicPaths []string

	// Hosts that bypass auth entirely (e.g. hanzo.id for login)
	PublicHosts []string

	// If true, requests without a token are rejected (402/401).
	// If false (default), requests without a token pass through without headers.
	RequireAuth bool
}

AuthConfig holds configuration for the auth middleware.

func DefaultAuthConfig

func DefaultAuthConfig() AuthConfig

DefaultAuthConfig returns the default auth configuration from environment variables.

func (AuthConfig) Validate added in v2.15.0

func (c AuthConfig) Validate() error

Validate reports a fatal misconfiguration: billing enabled without the Commerce endpoint and service token it depends on. Enforced so enabling billing can never silently fail open (empty URL → checkBalance allows) nor 503-storm the whole metered surface (empty token → Commerce 401). The one caller that can return an error — gateway.Mount — refuses to start in this state; NewAuthMiddleware additionally fails the balance gate closed.

type KMSResolver

type KMSResolver interface {
	// FetchRoutes returns the raw YAML payload at the given KMS path.
	// An empty path is a programmer error; resolvers should return an error.
	FetchRoutes(path string) ([]byte, error)
}

KMSResolver fetches a routing-config secret payload from a Hanzo KMS path. The default implementation is a noop; activated implementations are wired in by setting GATEWAY_ROUTES_KMS_PATH (and the resolver-specific env vars documented on each implementation).

Implementations MUST return the raw YAML bytes for the routes config; the caller (loadRoutesFromEnv) is responsible for parsing them via yaml.Unmarshal.

func SetKMSResolver

func SetKMSResolver(r KMSResolver) KMSResolver

SetKMSResolver swaps the package-level KMS resolver. Intended for tests and for embedders that want to plug in a non-HTTP secret backend. Returns the previous resolver so callers can restore it.

type RelayDeps

type RelayDeps struct {
	Logger luxlog.Logger
	Node   *zaplib.Node
	// Pick chooses the backend peer for a request path. Production passes a
	// lazy resolver-backed picker (peerResolver.picker) that dials backends
	// on first use, so the gateway boots even when the backends are absent.
	// When nil, RegisterRelay falls back to the static pickPeer over the
	// pre-resolved BasePeerID / CloudPeerID below.
	Pick forward.PeerPicker
	// BasePeerID / CloudPeerID are the handshake-learned NodeIDs of the
	// already-connected base and cloud peers (from ConnectDirectID at dial
	// time). Used only when Pick is nil (e.g. tests that dial up front).
	BasePeerID  string
	CloudPeerID string
	// Auth is the IAM JWT validation config for the relay gate. Use
	// DefaultAuthConfig() to read it from the environment.
	Auth AuthConfig
}

RelayDeps is what RegisterRelay needs to stand up the ZAP relay on a node.

type RouteEntry

type RouteEntry struct {
	Prefix  string `yaml:"prefix" json:"prefix"`
	Backend string `yaml:"backend" json:"backend"`
	Rewrite string `yaml:"rewrite,omitempty" json:"rewrite,omitempty"` // optional: rewrite prefix
}

RouteEntry maps a path prefix to a backend URL.

type RouterDeps

type RouterDeps struct {
	Logger    luxlog.Logger
	ZAPNode   *zaplib.Node
	CloudAddr string
	BaseAddr  string
}

RouterDeps is the set of dependencies BuildApp needs.

type RoutesConfig

type RoutesConfig struct {
	Redirects  map[string]string       `yaml:"redirects" json:"redirects"`
	Routes     map[string][]RouteEntry `yaml:"routes" json:"routes"`
	Subdomains map[string]string       `yaml:"subdomains" json:"subdomains"`
}

RoutesConfig is the YAML structure for gateway routing. Loaded from KMS (GATEWAY_ROUTES_KMS_PATH) or local file (GATEWAY_ROUTES_FILE).

type WidgetSecurityConfig

type WidgetSecurityConfig struct {
	// MaxRequestsPerIP is the maximum number of widget requests per IP
	// within the rate limit window. Default: 10.
	MaxRequestsPerIP int

	// Window is the sliding window duration for per-IP rate limiting.
	// Default: 1 minute.
	Window time.Duration

	// GlobalMaxRequests is the maximum total widget requests across all
	// IPs within the window. Protects against distributed abuse.
	// Default: 600.
	GlobalMaxRequests int

	// AllowedOrigins is the set of origin domains allowed for widget
	// requests. If empty, origin checking is disabled.
	AllowedOrigins []string

	// CleanupInterval controls how often stale entries are evicted
	// from the per-IP rate limit map. Default: 5 minutes.
	CleanupInterval time.Duration
}

WidgetSecurityConfig holds configuration for widget key rate limiting and origin validation.

func DefaultWidgetSecurityConfig

func DefaultWidgetSecurityConfig() WidgetSecurityConfig

DefaultWidgetSecurityConfig returns safe defaults.

AllowedOrigins can be overridden via WIDGET_ALLOWED_ORIGINS env var (comma-separated list of bare hostnames, no scheme/port). Subdomain matches are automatic: "hanzo.ai" also allows "*.hanzo.ai".

type ZapListenerConfig

type ZapListenerConfig struct {
	Port     int
	CertFile string
	KeyFile  string
	// InternalAddr is the local ZAP node's address to proxy to (e.g. "127.0.0.1:9652").
	InternalAddr string
}

ZapListenerConfig configures the inbound ZAP listener for external clients.

Directories

Path Synopsis
cmd
admin-api command
admin-api is the god-mode backend for the Hanzo Operator console (admin.hanzo.ai).
admin-api is the god-mode backend for the Hanzo Operator console (admin.hanzo.ai).
admin-guard command
admin-guard is the single forward-auth gate for Hanzo's admin surfaces.
admin-guard is the single forward-auth gate for Hanzo's admin surfaces.
gateway command
cmd/gateway is the standalone Hanzo Gateway edge process per HIP-0110.
cmd/gateway is the standalone Hanzo Gateway edge process per HIP-0110.
ingress command
Hanzo Ingress — lightweight host-based reverse proxy Replaces nginx-ingress with a minimal, config-driven proxy.
Hanzo Ingress — lightweight host-based reverse proxy Replaces nginx-ingress with a minimal, config-driven proxy.
waitlist-guard command
admin-guard is the single forward-auth gate that restricts Hanzo's RAW global-admin surfaces (platform.hanzo.ai, studio, commerce-admin, the raw KMS admin UI, the IAM management UI) to GLOBAL ADMINS ONLY — an IAM user whose org (`owner`) is the admin org (IAM `IsGlobalAdmin`: owner == AdminOrg).
admin-guard is the single forward-auth gate that restricts Hanzo's RAW global-admin surfaces (platform.hanzo.ai, studio, commerce-admin, the raw KMS admin UI, the IAM management UI) to GLOBAL ADMINS ONLY — an IAM user whose org (`owner`) is the admin org (IAM `IsGlobalAdmin`: owner == AdminOrg).
internal
hanzolog
Package hanzolog backs the engine's logging.Logger with hanzoai/log, the one logging library every Hanzo Go service uses.
Package hanzolog backs the engine's logging.Logger with hanzoai/log, the one logging library every Hanzo Go service uses.
lura/backoff
Package backoff contains some basic implementations and a selector by strategy name
Package backoff contains some basic implementations and a selector by strategy name
lura/config
Package config defines the config structs and some config parser interfaces and implementations
Package config defines the config structs and some config parser interfaces and implementations
lura/core
Package core contains some basic constants and variables
Package core contains some basic constants and variables
lura/encoding
Package encoding provides basic decoding implementations.
Package encoding provides basic decoding implementations.
lura/logging
Package logging provides a simple logger interface and implementations
Package logging provides a simple logger interface and implementations
lura/plugin
Package plugin provides tools for loading and registering plugins
Package plugin provides tools for loading and registering plugins
lura/proxy
Package proxy provides proxy and proxy middleware interfaces and implementations.
Package proxy provides proxy and proxy middleware interfaces and implementations.
lura/proxy/plugin
Package plugin provides tools for loading and registering proxy plugins
Package plugin provides tools for loading and registering proxy plugins
lura/register
Package register offers tools for creating and managing registers.
Package register offers tools for creating and managing registers.
lura/router
Package router defines some interfaces and common helpers for router adapters
Package router defines some interfaces and common helpers for router adapters
lura/router/gin
Package gin provides some basic implementations for building routers based on gin-gonic/gin
Package gin provides some basic implementations for building routers based on gin-gonic/gin
lura/router/mux
Package mux provides some basic implementations for building routers based on net/http mux
Package mux provides some basic implementations for building routers based on net/http mux
lura/sd
Package sd defines some interfaces and implementations for service discovery
Package sd defines some interfaces and implementations for service discovery
lura/sd/dnssrv
Package dnssrv defines some implementations for a dns based service discovery
Package dnssrv defines some implementations for a dns based service discovery
lura/transport/http/client
Package client provides some http helpers to create http clients and executors
Package client provides some http helpers to create http clients and executors
lura/transport/http/client/graphql
Package graphql offers a param extractor and basic types for building GraphQL requests
Package graphql offers a param extractor and basic types for building GraphQL requests
lura/transport/http/client/plugin
Package plugin provides plugin register interfaces for building http client plugins.
Package plugin provides plugin register interfaces for building http client plugins.
lura/transport/http/server
Package server provides tools to create http servers and handlers wrapping the lura router
Package server provides tools to create http servers and handlers wrapping the lura router
lura/transport/http/server/plugin
Package plugin provides plugin register interfaces for building http handler plugins.
Package plugin provides plugin register interfaces for building http handler plugins.
pkg/binder
Package binder allows to easily bind to Lua.
Package binder allows to easily bind to Lua.
pkg/bloomfilter
Package bloomfilter contains common data and interfaces needed to implement bloomfilters.
Package bloomfilter contains common data and interfaces needed to implement bloomfilters.
pkg/bloomfilter/bloomfilter
Package bbloomfilter implements a bloomfilter based on an m-bit bit array, k hashfilters and configuration.
Package bbloomfilter implements a bloomfilter based on an m-bit bit array, k hashfilters and configuration.
pkg/bloomfilter/register
Package register wires a rotating bloomfilter into the gateway from its extra_config block, exposing it over the internal RPC service.
Package register wires a rotating bloomfilter into the gateway from its extra_config block, exposing it over the internal RPC service.
pkg/bloomfilter/rotate
Package rotate implemennts a sliding set of three bloomfilters: `previous`, `current` and `next` and the bloomfilter interface.
Package rotate implemennts a sliding set of three bloomfilters: `previous`, `current` and `next` and the bloomfilter interface.
pkg/bloomfilter/rpc
Package rpc implements the rpc layer for the bloomfilter, following the principles from https://golang.org/pkg/net/rpc
Package rpc implements the rpc layer for the bloomfilter, following the principles from https://golang.org/pkg/net/rpc
pkg/bloomfilter/rpc/server
Package server implements an rpc server for the bloomfilter, registering a bloomfilter and accepting a tcp listener.
Package server implements an rpc server for the bloomfilter, registering a bloomfilter and accepting a tcp listener.
pkg/httpcache
Package httpcache provides a http.RoundTripper implementation that works as a mostly RFC-compliant cache for http responses.
Package httpcache provides a http.RoundTripper implementation that works as a mostly RFC-compliant cache for http responses.
plugin/audit
Package audit contains types and functions to summarize the features used in a configuration and to emit recommendations and comments when executing a check
Package audit contains types and functions to summarize the features used in a configuration and to emit recommendations and comments when executing a check
plugin/circuitbreaker/gobreaker
Package gobreaker provides a circuit breaker adapter using the sony/gobreaker lib.
Package gobreaker provides a circuit breaker adapter using the sony/gobreaker lib.
plugin/circuitbreaker/gobreaker/proxy
Package gobreaker provides a circuit breaker proxy middleware using the sony/gobreaker lib.
Package gobreaker provides a circuit breaker proxy middleware using the sony/gobreaker lib.
plugin/cobra
Package cmd defines the cobra command structs and an execution method for adding an improved CLI to KrakenD based api gateways
Package cmd defines the cobra command structs and an execution method for adding an improved CLI to KrakenD based api gateways
plugin/httpcache
Package httpcache introduces an in-memory-cached http client into the KrakenD stack
Package httpcache introduces an in-memory-cached http client into the KrakenD stack
plugin/koanf
Package koanf defines a config parser implementation based on the koanf pkg
Package koanf defines a config parser implementation based on the koanf pkg
plugin/metrics
Package metrics defines a set of basic building blocks for instrumenting the gateway.
Package metrics defines a set of basic building blocks for instrumenting the gateway.
plugin/metrics/gin
Package gin defines a set of basic building blocks for instrumenting KrakenD gateways built using the gin router
Package gin defines a set of basic building blocks for instrumenting KrakenD gateways built using the gin router
plugin/metrics/mux
Package mux defines a set of basic building blocks for instrumenting KrakenD gateways built using the mux router
Package mux defines a set of basic building blocks for instrumenting KrakenD gateways built using the mux router
plugin/ratelimit
krakendrate contains a collection of curated rate limit adaptors for the KrakenD framework
krakendrate contains a collection of curated rate limit adaptors for the KrakenD framework
plugin/ratelimit/proxy
Package proxy provides a rate-limit proxy middleware.
Package proxy provides a rate-limit proxy middleware.
plugin/ratelimit/router
Package router provides several rate-limit routers.
Package router provides several rate-limit routers.
loadgen
conn_holder command
Package main holds N idle keep-alive HTTP/1.1 connections against a target URL.
Package main holds N idle keep-alive HTTP/1.1 connections against a target URL.
Package middleware ships gateway-owned middleware for the zip web framework.
Package middleware ships gateway-owned middleware for the zip web framework.
Package token is the gateway's credential check: which issuer it trusts, which audiences it accepts, and the keys it verifies against.
Package token is the gateway's credential check: which issuer it trusts, which audiences it accepts, and the keys it verifies against.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL