Files
zip/middleware
zooqueenandHanzo Dev 6cc782199b an app reports because it serves: telemetry is the framework's
Every program built on zip now emits one log line per request through its own
luxfi/log logger — method, path, status, duration, trace and span, plus the
caller when the environment parked one — and RED metrics through luxfi/metric,
with W3C trace context joined when a request carries it, minted when it does
not, and propagated on Call with no handler code. /metrics renders the one
registry, and export speaks the shipped ZAP exporter, which is what o11y
ingests. Config.Telemetry{Addr, Off} is the only switch; the default is on.

The boundary is installed outermost by materialise, so requests that match
nothing — 404s, preflights — are still counted; per-route composition cannot
see them. Two defects the tests forced out: the status is derived from the
handler's error, because at the boundary the response still reads 200 (fiber
writes the real status after unwinding, so every refusal would have recorded
as success); and the route label reads the not-found sentinel, because an
unmatched request leaves the middleware's own registration in place and would
otherwise be indistinguishable from a real root leaf.

middleware.Logger and middleware.Telemetry are deleted, not deprecated:
telemetry an app can lack is the defect this closes.

luxfi/metric moves to v1.9.1 — v1.9.0 is the published build whose registry
constructors sit behind a build tag nothing sets, so counters accepted Inc()
into a registry nothing gathers and /metrics served empty.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-04 14:36:48 -07:00
..

zip middleware

Generic middleware for the zip framework. Auth-specific middleware (JWT validation, identity-header stripping) lives in github.com/hanzoai/gateway/middleware — see "Why auth lives in gateway" below.

Available middleware

Name Purpose
Recover() panic → JSON 500
Logger(luxlog.Logger) request log via luxfi/log
RequestID() X-Request-Id propagation
Timeout(d) per-request ctx deadline
MaxBody(n) request size limit
CORS(opts) standard CORS
RateLimit(opts) per-key token bucket
Telemetry(o11yClient) OTel span + request metrics

Why auth lives in gateway

JWT validation + identity-header minting are the responsibility of the gateway subsystem (per HIP-0106). Other subsystems mounted inside the unified cloud binary trust the gateway-minted X-Org-Id header and do NOT re-validate JWTs themselves — re-running JWT validation per-subsystem is wasteful and risks divergent validation rules.

Subsystems that need to ASSERT the request was gateway-minted import github.com/hanzoai/gateway and call gateway.AssertGatewayMinted(c).

Pipeline order

Recommended order for a service that mounts zip behind hanzoai/gateway:

app.Use(
    middleware.Recover(),                // 1. always first
    middleware.RequestID(),              // 2. mint request id
    middleware.Logger(app.Logger()),     // 3. log with request id
    middleware.Telemetry(o11y),          // 4. metrics
    middleware.RateLimit(rlCfg),         // 5. limit
    middleware.CORS(corsCfg),            // 6. last — close to response
)

JWT validation + identity-header stripping/minting is owned by the gateway subsystem; see github.com/hanzoai/gateway/middleware.