Files
zeekayandHanzo Dev b37599e7be zap: the gate was blind to doctests; record who crates.io still credits
`cargo test --all-targets` does NOT imply `--doc` — it selects lib/bins/
tests/benches/examples and skips doctests entirely. Injecting
`compile_error!` into a lib.rs doc example passes the old gate with exit
0 and fails `cargo test --doc` immediately, so a doc example that does
not compile could ship green. Added the `--doc` line; the same injection
now takes `make test` to exit 2. `.github/workflows/test.yml` runs
`make test`, so CI picks this up with no second edit — the gate is one
thing, not a CI-only copy of one.

LLM.md: `zapwire` 1.0.0 and `zapc` 1.0.0 are published, so the collision
table no longer says "never published", and the crosswire entry names
`go run ./interop/golden` as the way to regenerate its hex.

Also recorded the part of the collision this repo CANNOT fix. crates.io
takes a crate's `repository` link from the most recently PUBLISHED
version, not the highest: `hanzo-zap` 0.2.1 (2026-06-23, from a
zap-proto/spec checkout) declares `repository = hanzoai/zap`, while
max_version 0.6.75 (2026-05-13) declares hanzonet/network. So
crates.io/crates/hanzo-zap still sends readers HERE for a crate whose
source is hanzo/net. Having vacated the name, this repo can no longer
correct it; hanzo/net publishing 0.6.76 would. Yanking 0.2.1 would not —
~25 engine forks pin it exactly and would fail to resolve.

make test: 27 lib + 10 crosswire + 2 live-Go interop + 1 doctest, exit 0.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-28 23:25:06 -07:00

5.8 KiB

LLM.md — hanzoai/zap

What this repo IS

The Rust runtime for the ZAP protocol, published to crates.io as zapwire 1.0.0 (depends on zapc 1.0.0). Two crates ship as a unit:

  • rust/ — the runtime: wire (header) · codec (data segment) · rpc (call envelope + promise pipelining) · transport (Conn/Server).
  • zapc-rs/ — zapc, the schema compiler rust/build.rs calls.

interop/main.go is a live Go ZAP peer used only by the Rust test suite; it is not shipped.

What this repo IS NOT

  • Not the sidecar. cmd/zap-sidecar was removed (Apr 2026); ZAP is embedded natively in every backend service (sql, kv, docdb, …), each exposing it on TCP 9999 from its own process. No sidecar container, image, or CRD field. ghcr.io/hanzoai/zap is no longer published.
  • Not hanzo-zap. See below.

The crate-name collision, resolved

hanzo-zap on crates.io has TWO source lineages and never had one home:

crate source state
hanzo-zap 0.6.75 (max) ~/work/hanzo/net/hanzo-zap (repo hanzonet/network) published; pinned by hanzo-node + hanzo/net
hanzo-zap 0.2.1 ~/work/zap/spec (repo zap-proto/spec) published; Client::connect / call_tool were TODO stubs
hanzo-zap 1.0.1 THIS repo, rust/ never published — declared the name without owning it; now shipped as zapwire 1.0.0
hanzo-zap (no version) ~/work/hanzo/evm/crates/hanzo-zap private path crate, never published

Resolution:

  1. This repo renamed to zapwire — a free name, and the accurate one: this crate is the wire runtime. NOT zap-proto: that is a reservation zap-proto/spec owns and publishes from reserve/zap-proto via its release.yml, pointing at zap-schema. Taking it would have recreated the very bug being fixed. Lib name is zapwire too, so it can share a dependency graph with zap-schema (whose lib is zap).
  2. zap-proto/spec already fixed itself. Its crate is now zap-schema 1.0.0; it no longer publishes hanzo-zap. The local ~/work/zap/spec checkout is 26 commits behind on a stale master branch — reading it instead of the remote would have "retired" 26 commits of live work, including a Rust cap capability runtime. Nothing to do there: git fetch before you judge a repo.
  3. hanzo-zap stays with hanzo/net/hanzo-zap — it published the max version and has the real consumers. 0.2.1 is NOT yanked: ~25 engine forks pin it exactly, and yanking would break their resolve.

Still open (hand-offs — both OUTSIDE this repo):

  • crates.io still credits hanzo-zap to THIS repo. The crate-level repository link is taken from the most recently PUBLISHED version, not the highest one: 0.2.1 shipped 2026-06-23 declaring repository = hanzoai/zap, while max_version 0.6.75 shipped 2026-05-13 declaring hanzonet/network. So anyone reading crates.io/crates/hanzo-zap is sent to this repo for a crate whose real source is hanzo/net. This repo can no longer fix that — it has vacated the name. The repair is for hanzo/net to publish hanzo-zap 0.6.76 (patch, latest+1), which re-points the link to hanzonet/network. Yanking 0.2.1 is NOT the fix: ~25 engine forks pin it exactly and would fail to resolve.
  • hanzo/evm/crates/hanzo-zap is a fourth crate with the same name. It is path-only, so nothing resolves it from the registry — but two crates with one name still cannot coexist in one cargo graph, so the evm one should be renamed before either is published.

Wire agreement with Go — how it is proved

  • rust/tests/crosswire.rs — golden hex generated FROM github.com/zap-proto/[email protected]'s rpc.BuildRequest / rpc.BuildResponse. Rust must both parse those bytes and emit them. Regenerate with go run ./interop/golden, which prints the finished Rust const lines — never hand-edit the hex.
  • rust/tests/interop.rs — builds and runs interop/main.go (a real transport.Listen server) on a Unix socket and drives it from zapwire::transport::Conn. This is what pins BEHAVIOUR: framing, direction tag, PromiseID correlation, connection lifecycle.

The gap that made this necessary: the Rust reader accepted wire version 1 only, and every Go RPC envelope is version 2 (NewBuilderV2). Rust could not read — or even re-parse its own — RPC envelope. Reverting that one condition turns both interop tests red with InvalidVersion(2).

Session crypto — the honest state

Rust ZAP is PLAINTEXT. Local over a Unix socket is correct; remote must stay on HTTPS. The Go plane already pins X25519MLKEM768 in transport.DialTLS/ListenTLS; Rust has no TLS sibling yet. The four concrete steps to close it are in README.md § Session crypto.

zap-proto/ws (multi-stream pubsub) is still a README + schema. Multi-message streams (dir 3/4/5) exist in the Go transport only; Rust ignores those frames so they cannot break unary traffic. Unary server PUSH does work, via the symmetric connection.

Test gate

make test → cargo fmt --check + cargo test --all-targets + cargo test --doc + go vet ./.... Currently 27 lib + 10 crosswire + 2 live-Go interop + 1 doctest. .github/workflows/test.yml runs make test itself — one gate, not a CI-only copy of one — with Go installed so the interop test can never silently skip.

--doc is a SEPARATE line because --all-targets does not imply it: with only --all-targets a doctest that fails to compile ships green. cargo clippy currently fails on this machine with multiple input filenames provided from the rustup clippy shim — an environment fault, not a code fault; it is not part of the gate until that is fixed.

See also

  • ~/work/zap/go — github.com/zap-proto/go, the reference runtime.
  • ~/work/hanzo/sql, ~/work/hanzo/kv, ~/work/hanzo/docdb — services that bake ZAP into their primary container.