mirror of
https://github.com/zap-proto/zapd.git
synced 2026-10-30 15:06:58 +00:00
3.2 KiB
3.2 KiB
zapd — the ZAP router (zap-proto/zapd)
Full docs: README.md. Design: HIP-0069 (hanzoai/hips).
- What: a library, not a daemon. Every process that speaks ZAP calls
zapd::embed()(router candidacy) andzapd::Node::join()(its own seat). Anfcntllock on<runtime>/zapd.lockelects one router per user login; its exit hands the seat to the next candidate. Doors:<runtime>/zapd.sock(0600) and the browser WebSocket on the port the pairing names (picked free at mint, 20000–29999). The runtime dir is validated (private_runtime) before anything locks, binds or connects in it. - Modules:
frame(envelope, +AUTH=8),id(<kind>/<host>/<name>, host stamped by the router),router(registry + route + presence; transport-free),elect(lock, doors, the one runtime thread),door(Origin/Host check, pairing proof, browser-only HELLO, no id take-over, browsers never originate, eight admissions at a time),pair(the code file<state>/zap/pair, 0600, lstat-checked),node(a process's seat; reconnects 50 ms→1 s; one call at a time, matched by responderfrom; talks only to a socket whose peer pid is the lock holder). - Unix and Windows: everything that differs is
src/os/{unix,windows}.rs. Windows: the door is the named pipe\\.\pipe\zapd-<user SID>-<hash of the runtime dir>with a DACL for the user and SYSTEM; the election isLockFileExon the same lock file; the winner writeszapd.pidbeside it (LockFileEx names no holder) and a node checksGetNamedPipeServerProcessIdagainst it, as a Unix node checkspeer_credagainstF_GETLK; private directories get a protected DACL (the0700counterpart) and a file is private when its owner is the token's user or owner SID.tests/windows.rsruns the election on real Windows in CI (windows-latest, x86_64-pc-windows-msvc); a localcargo check --target x86_64-pc-windows-gnucompiles it. Never Wine. - POSIX record locks drop when ANY fd of the file closes. The lock file is
opened once per process (
elect::lock_fd) and never closed; never open it anywhere else, or the router in this process loses its seat. - Binary:
zapd pair [--reset],zapd ls. It never serves. - Release: tag
v*→ binaries + npm@zap-proto/zapd, abi3 wheels to PyPIzapd(twine; the token is KMSpython-sdk-publish/PYPI_TOKEN, read with the repo's KMS_CLIENT_ID/SECRET, identity hanzo-ci), crate to crates.iozapd. Versions follow the tags (v1.1.1 was the last before the library). - Python:
python/— PyO3 binding of the same crate (import zapd), abi3-py310, built with maturin. The one router implementation; do not port it. - Test:
cargo testruns the election end to end with real processes (the test binary re-runs itself as the ignoredcandidatetest, each with its ownXDG_RUNTIME_DIR/XDG_STATE_HOME).cd python && pytestaftermaturin developdoes the same through Python. - Build here:
~/.cargo/config.tomlsetsrustc-wrapper = zccache, which breakscargo clippy; run clippy withRUSTC_WRAPPER=. - Do NOT add a schema, capnp or JSON to the router, or a second transport for the browser. Payloads are opaque; MCP traffic rides them as MCP's own JSON-RPC bytes.