StatusReply gains relay_connected/relay_error: a live hole-punched session keeps
every gauge healthy while the relay is unreachable, so no other field can show an
outage. PeerDiagnostic gains trace, the peer's recent punch steps (oldest first).
Both are what the p2p doctor report reads.
StatusReply gains a repeated PeerDiagnostic (path, reason, state, last punch
error, dialled endpoint, candidates, caps, session and silence ages, and the
punch counters), each keyed by the peer's base64 public key so the list is
attributable.
Add direct_peers/derp_peers gauges and punch_attempts/punch_success/
streams_direct/streams_derp counters, so an operator can tell whether hole
punching works for their peers or traffic is stuck on the relay.
OpenTunnel now only authorizes the tunnel and returns a random single-use
id (the stream credential); the reserved endpoint field and CloseTunnel
are removed. Tunnel is a bidi stream whose lifetime is the tunnel's
lifetime, bound to the OpenTunnel id via the "id" metadata key. Breaking
change; regenerated with the pinned toolchain.
Selects the endpoint's semantics: "tcp" (a byte stream, the default when
empty) or "udp" (a datagram endpoint, one datagram per write). A datagram
tunnel is what carries a tun link, since a byte-stream endpoint coalesces
and splits packets. Empty defaults to tcp, so existing clients and hosts
are unaffected.
Regenerate all protos from the module root with full relative paths so
descriptors register as e.g. auth/proto/auth.proto instead of bare
auth.proto. The protobuf file registry is process-global, so generic
filenames collided with other libraries and panicked at init
(proto: file "auth.proto" is already registered, #3).
Go API and wire format unchanged.
- .gitignore excludes .codegraph/.claude/.remember and test artifacts
- CLAUDE.md: service catalog now 13 types; p2p row plus its deliberate
deviations (opaque peer/endpoint, no example/, gRPC-only)
- README.md: p2p row and usage section with p2ps: config snippet
The two hop examples imported x/config only for the NodeConfig type to
build demo nodes, dragging x (and its viper dependency tree) under the
plugin SDK — inverting the x -> plugin layering and one pin-bump away
from a package import cycle. The node payload is plain JSON on the
wire, so the examples now use local struct types with the same JSON
shape. go.mod shrinks to grpc + protobuf.
P2P service with OpenTunnel/CloseTunnel/Status unary RPCs: the client
sends an opaque peer identifier, the plugin replies with an opaque
tunnel handle (v1: locally dialable TCP host:port). Error semantics:
transport/validation failures go through gRPC status; business
failures answer ok:false with a gRPC OK status — clients treat either
as failure. CloseTunnel is idempotent. Generated code checked in.