Documentation
How Moss works, end to end — and how to build on it. Every heading is linkable; copy the anchor from your address bar to deep-link a section.
Overview
Moss is a zero-infrastructure peer-to-peer mesh runtime written in Go and compiled to a C-shared library (.dll/.so/.dylib) or to WebAssembly. It gives an application a decentralized data-exchange mesh: peers discover each other without dedicated servers, authenticate and encrypt every link, and route messages over topic-based pub/sub.
The defining constraint is the absence of central infrastructure. There is no bootstrap server, no STUN/TURN you operate, and no account system — connectivity is produced by the peers themselves.
Quick start
Build the shared runtime and embed it through the FFI, or build a service binary:
# shared library (Linux / Windows / macOS)
CGO_ENABLED=1 go build -buildmode=c-shared -o moss.dll ./cmd/moss-ffi
# a telemetry gateway (node + read-only HTTP API)
go build -o moss-gateway ./cmd/moss-gateway
./moss-gateway -mesh global -http 127.0.0.1:8787
Two nodes on one host with telemetry on will discover each other (LAN beacons) and converge to the same network snapshot.
The standard public mesh is global — maintained by the Moss developers and the id every product should use to join the shared network. Pick a unique mesh id only when you want a private, isolated mesh (optionally gated further with a PSK).
Architecture
The core is layered so lower packages never depend on the orchestrator:
internal/crypto— identities and key derivation (Ed25519, X25519, HKDF, BLAKE2s).internal/transport— Noise handshake and encrypted sessions over a byte-oriented carrier.internal/gossip— pub/sub envelopes, message cache, peer scoring.internal/bootstrap— tracker clients and infohash derivation.internal/nat— NAT profiling, mapping, relay primitives.internal/stat— the privacy-preserving telemetry CRDT and hash chain.internal/mesh— theNodethat composes them all.
Discovery & bootstrapping
A node derives a private infohash from HKDF(mesh_id, psk) and uses it as a rendezvous key. It announces and queries through several independent channels:
- BitTorrent trackers — BEP 15 (UDP) and BEP 3 (HTTP) announces.
- Mainline DHT — periodic announce/lookup on a dedicated socket.
- LAN beacons — UDP multicast for same-network peers.
- WebRTC signaling — for browser peers (no UDP/DHT available there).
The PSK gates discovery: meshes can't be enumerated without it.
Transport & cryptography
Every session is a Noise XX handshake, suite 25519_ChaChaPoly_BLAKE2s, with the peer's Ed25519 identity bound to its Noise static key and the mesh id. Traffic is sealed with ChaCha20-Poly1305. On UDP, datagrams are wrapped by a keyed scramble codec so they look like random noise on the wire, resisting DPI fingerprinting — this is obfuscation, not the security boundary (Noise is).
Routing (pub/sub)
Messages flow over a GossipSub v1.1-inspired mesh: topic subscriptions form a peer mesh (degree D=6), publishes flood to eligible peers, and lazy IHAVE/IWANT gossip plus IDONTWANT suppression amortize duplicates. Peer scoring resists Sybil/eclipse behavior; a BLAKE2s message id deduplicates via a TTL cache.
NAT traversal
Moss profiles the local NAT (public, full-cone, restricted, port-restricted, symmetric, CGNAT) from STUN observations and binding behavior. It attempts UDP hole-punching, and falls back to relaying through peer-promoted supernodes when a direct path is impossible. Reachability is only ever asserted after a real inbound probe — a public reflexive address alone never marks a node "open", so CGNAT nodes are classified correctly and never promoted to supernodes.
Telemetry (privacy-preserving)
Opt-in (telemetry.enabled). Nodes gossip a per-epoch CRDT that yields a self-verifying snapshot of the whole network without naming any peer:
- Node count — a HyperLogLog sketch; cardinality only, members can't be enumerated.
- Bandwidth & distributions — each node contributes under an unlinkable per-epoch id
eid = BLAKE2s(epoch ‖ pubkey), with values clamped and perturbed by differential-privacy noise. - Merge — an LWW-map CRDT: order-independent, idempotent, so every node converges to identical state.
- Hash chain —
digest = BLAKE2s(epoch ‖ snapshot ‖ prev_digest). Because the CRDT converges, honest nodes compute the same digest; integrity is reproducibility, not a signature. - k-anonymity — detailed metrics stay hidden until enough nodes contribute in an epoch.
Read it via Moss_GetNetworkStats or a gateway's /api/stats and /api/chain.
Explorer
The explorer is a static client that reads telemetry from one or more gateways and verifies it in your browser via the wasm verifier: it checks hash-chain continuity and cross-checks that independent gateways agree. The topology view is a simulation seeded by the epoch digest — it reflects aggregate shape (counts, NAT/degree distributions), never real edges or addresses, so it discloses nothing.
A gateway is any node with telemetry on serving the read-only API: moss-gateway -http 127.0.0.1:8787. http://localhost works even from the https site; remote gateways must be https.
Switch which mesh you're viewing with the explorer's mesh selector (it appends ?meshid=… to each request, or open a deep link like ?meshid=global). The mesh list lives on the client; a gateway joins a requested mesh on demand, so you can point the explorer at any mesh the gateway can reach. The API also takes ?meshid= on /api/stats, /api/chain, and /api/events.
Browser runtime (WebAssembly)
Compiled to GOOS=js GOARCH=wasm, Moss runs as a full peer in the browser. JavaScript owns the WebRTC RTCPeerConnection, ICE, and signaling; the wasm module wraps each DataChannel as a connection and runs the same Noise transport and gossip over it. A small moss-signal relay brokers SDP/ICE between browser peers and never sees mesh traffic, which stays end-to-end encrypted.
FFI / API
The C ABI is intentionally small. Host applications call into mesh.Node through it:
Moss_Init(mesh_id, psk, config) -> handle
Moss_Start / Moss_Stop
Moss_Subscribe / Moss_Unsubscribe / Moss_Publish
Moss_SetCallback / Moss_SetEventCallback / Moss_SetScoringCallback
Moss_SetKeyStore
Moss_GetMeshInfo / Moss_GetNetworkStats
Moss_GetPublicKey / Moss_GetNATType
Moss_Free
Strings and buffers returned by the getters are owned by Moss; release them with Moss_Free. See docs/API.md for signatures, event ids, and error codes.
Configuration
Configuration is JSON passed to Moss_Init (or flags on the service binaries). Notable blocks:
{
"trackers": ["udp://tracker.opentrackr.org:1337/announce"],
"listen_port": 0,
"max_peers": 200,
"gossipsub": { "D": 6, "D_lo": 4, "D_high": 12 },
"nat": { "relay_max_sessions": 50, "relay_max_bandwidth_kbps": 256 },
"telemetry": { "enabled": false, "epoch_sec": 300, "dp_epsilon": 1.0, "k_anon": 5 }
}
Omit trackers for the built-in set; pass [] to disable tracker bootstrap. Partial nested objects fall back to defaults.
Running services
# telemetry gateway (read-only HTTP/SSE for the explorer)
go build -o moss-gateway ./cmd/moss-gateway
./moss-gateway -mesh global -http 127.0.0.1:8787
# offline two-node demo (no trackers, static peer)
./moss-gateway -mesh local -http :8810 -listen-port 41001 -trackers=false
./moss-gateway -mesh local -http :8811 -listen-port 41002 -static 127.0.0.1:41001 -trackers=false
# WebRTC signaling relay (for browser peers)
go build -o moss-signal ./cmd/moss-signal
./moss-signal -addr 127.0.0.1:8788
Source, full spec, and issues: github.com/redstone-md/moss.