Files
zip/hanzo.yml
zooqueenandHanzo Dev e570a16f6a telemetry: spans and the request record ship over native ZAP
The request boundary already holds everything a server span and a request
record contain, so both are structs filled from data it has: the trace, span
and parent ids it minted or joined, the route template as the name, start and
duration, an outcome-derived status, and the caller's org when a gateway
parked one. They are appended under one lock, drained once per tick and at
shutdown, and shipped as JSON in a ZAP envelope — internal/o11y declares the
batch shapes itself, no SDK, no protobuf, nothing a consumer inherits.

The keys are the collector's vocabulary, not ours. It reads a path out of
url.path / http.target / http.route / path in that order, so those are the
keys this fills; http.path, which an earlier draft shipped, fills nothing.
The contract/ module proves it the only way that stays true: it starts the
collector's real receivers, serves one real request, and asserts on the
structs those receivers produced. It is its own module because the collector
already requires zip — the proof would otherwise be a cycle.

The address is the switch, spelled O11Y_SPANS_ADDR / O11Y_LOGS_ADDR /
O11Y_METRICS_ADDR — three names because the collector binds one listener per
signal and promises no adjacency between them. The metrics name replaces
O11Y_METRICS_ZAP_ENDPOINT, which deployments had already stopped matching;
the socket preference is deleted because the collector only ever binds TCP,
so that branch could not run. Nothing stated means nothing starts: no
exporter, no node, no dial, no goroutine.

An app's own logging stays its own. Only zip's request line ships to the log
ear; teeing a program's every log line off the box is one decision for
luxfi/log to make once, for everything that logs.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-04 21:49:59 -07:00

35 lines
1.8 KiB
YAML

# Canonical CI config for zap-proto/zip — read by the hanzoai/ci reusable
# (.github/workflows/cicd.yml). zip is a LIBRARY: no images, no deploy — CI's
# whole job is proving the framework contract on every push, on OUR arc pool.
# The reference plugin, published per OS/arch on every tag. zip defines the
# install contract (zip.Plugin{URL, Sum}: fetch, verify the SHA-256 BEFORE the
# file is made executable, cache by digest), so zip is where a runnable proof of
# it belongs: any host can point at these bits and exercise its own install path
# without building anything. It is also what the pattern is for — the plugin is
# built ONCE here and every host picks up the same artifact.
#
# https://github.com/zap-proto/zip/releases/download/<tag>/example-billing-<os>-<arch>
# https://github.com/zap-proto/zip/releases/download/<tag>/binaries.json ← url + sha256
binaries:
- name: example-billing
main: ./examples/plugin/billing
platforms: [linux/amd64, linux/arm64, darwin/arm64]
test:
- name: go-vet
run: go vet ./...
- name: go-test
# The full suite includes the load-bearing contract pins: route-chain
# ORDER (middleware-first/handler-last — an inversion here silently breaks
# every auth gate in every app built on zip), the no-Next abort, empty-leaf
# group roots, static fallback, and the runtime/middleware packages.
run: go test -count=1 -timeout 10m ./...
- name: go-test-collector
# contract/ is a module of its own, so ./... above does not reach it and no
# consumer of zip inherits what it requires. It runs the collector's REAL
# receivers against a real zip app: the one thing proving that two
# deliberately separate declarations of the batch shapes still describe one
# thing. See contract/doc.go.
run: cd contract && go test -count=1 -timeout 5m ./...