Replace plain TCP zap.Dial / zap.Listen with zwing.DialZAP /
zwing.ListenZAP. zapwire.Dial and zapwire.NewServer now require a
*zwing.Config carrying a LocalIdentity — there is no cleartext mode.
Every netrunner control connection is X-Wing-encapsulated,
ChaCha20-Poly1305-encrypted, and identity-pinned via Ed25519 +
ML-DSA-65 hybrid signatures.
Wire format and opcode set are unchanged; only the dial/listen
seams are upgraded. The 14 e2e tests are updated to mint ephemeral
identities per test (newTestRig) and pin the server side, which
also proves the handshake actually authenticates.
Pairs with luxfi/zwing v0.2.1 (DialZAP / ListenZAP) and luxfi/api
v1.0.10 (zap.NewListener).
100% native ZAP, no protobuf, no gRPC, no codegen. Hand-written Go
types in zapwire/types/ encode/decode against luxfi/api/zap.Buffer
and zap.Reader directly. Server dispatches via a single zap.Handler
that switches on opcode (and sub-opcode for fan-out via OpStart).
Opcodes 60..63 reserved for netrunner control. Sub-opcodes (under
OpStart) provide RPC fan-out without consuming the limited opcode
range. Default port: 9999.
Migration plan:
Phase 1 (this commit): Ping, RPCVersion, Health, URIs, Status — 5
of 26 control RPCs landed with full e2e test coverage
Phase 2: lifecycle (Start, Stop, AddNode, RemoveNode, RestartNode,
PauseNode, ResumeNode, AttachPeer, SendOutboundMessage)
Phase 3: chain ops (CreateBlockchains, CreateChains, etc.)
Phase 4: snapshots (Save/Load/Remove/GetSnapshotNames + Hot)
Phase 5: streaming (StreamStatus over persistent ZAP conn)
Phase 6: swap netrunner/client/client.go + cli callers, delete rpcpb
Tests: go test ./zapwire/... — 5 RPCs e2e, all green.