v0.6.9 — systematic netmap null-tolerance
Fixed
Netmap decode now tolerates null for every sequence/map field (Go omitempty ↔ Rust).
Go marshals empty slices/maps as JSON null, so a control plane (notably an IPv6-off Headscale) sends null for array fields the client modeled as required sequences — failing the netmap decode with invalid type: null, expected a sequence/expected a map and looping the map-poll stream forever.
v0.6.8 fixed only Node.addresses. v0.6.9 is the systematic pass: rather than annotate each field (the per-field approach is what let the gap recur), null tolerance is applied at the struct level via #[serde_with::apply] on every type on the deserialized netmap path — Node, MapResponse, DNSConfig/Resolver, DerpMap/Region/HomeParams, SSHPolicy and its nested rules, ControlDialPlan, and the ts_packetfilter_serde filter/cap-grant types — so any Vec/map field added later is covered automatically.
null, []/{}, and a populated container are accepted interchangeably. Option<…> fields (whose null/absence means unchanged from the prior poll — e.g. peers, packet_filter singular) are deliberately left untouched, preserving delta-poll semantics.
Regression tests decode a full MapResponse + peer Node + DNSConfig, a DERP map, an SSH policy, a packet filter, and a dial plan with null everywhere a sequence/map is expected.
This project is not associated with Tailscale Inc.