# Mesh Networking

quicproquo includes a mesh networking layer for decentralised, peer-to-peer
messaging without central infrastructure. It is designed for community
networks (Freifunk, BATMAN-adv, Babel routing) and offline-capable
environments.

Mesh features are **feature-gated** — build the client with:

```bash
cargo build -p quicproquo-client --features mesh
```

## Architecture

```
Client A ── mDNS discovery ──► nearby qpq node (LAN / mesh)
                                      │
                             Cap'n Proto federation
                                      │
                             remote qpq node (across mesh)

Client B ── iroh P2P ──────► Client C (direct, NAT-traversed)
```

Three layers work together:

1. **Server federation** — servers relay messages across mesh via Cap'n Proto
   RPC over QUIC with mTLS
2. **mDNS discovery** — servers announce themselves, clients find nearby nodes
3. **iroh P2P** — direct peer-to-peer QUIC connections with NAT traversal

## Self-sovereign mesh identity

In mesh mode, identity is based on an Ed25519 keypair — independent of server
registration. No OPAQUE password auth or Authentication Service is required.

```
/mesh identity
```

Shows your mesh public key and known peers. The keypair and peer directory are
persisted in a local JSON file.

## mDNS discovery

Servers announce `_quicproquo._udp.local.` via mDNS on startup with TXT
records:

```
ver=1
server=<host:port>
domain=<local_domain>
```

Clients browse for nearby nodes:

```
/mesh peers
```

Note a discovered server for connection:

```
/mesh server 192.168.1.42:7000
```

## Direct P2P messaging

Send messages directly to a peer via iroh transport (QUIC with NAT
traversal):

```
/mesh send <peer_id> Hello from the mesh!
```

Messages are signed with your mesh identity key. The iroh relay server
is used as fallback when direct connections fail.

## Store-and-forward

Messages for offline peers are buffered with TTL-based expiry:

- **MeshEnvelope** — signed message with TTL, hop count, and max hops
- **Deduplication** — SHA-256 message ID prevents relay loops
- **MeshStore** — in-memory queue with per-recipient capacity limits
- **Garbage collection** — expired messages are automatically purged

Forward stored messages to a newly-discovered peer:

```
/mesh store       # show queue statistics
```

The routing table shows known paths:

```
/mesh route
```

## Broadcast channels

Lightweight pub/sub channels using symmetric ChaCha20-Poly1305 encryption
(no MLS overhead). Suitable for community bulletin boards, announcements,
and emergency broadcasts.

```
/mesh subscribe announcements        # join a channel
/mesh broadcast announcements Hello! # publish to a channel
```

Channels are created automatically on first subscription. The symmetric key is
derived from the topic name (for open channels) or distributed out-of-band
(for private channels).

## Federation

Servers relay messages for recipients on remote nodes:

- `handle_enqueue` and `handle_batch_enqueue` call
  `federation::routing::resolve_destination()`
- Remote recipients are forwarded via `FederationClient::relay_enqueue()`
- mTLS mutual authentication between federation peers

### Configuration

```bash
# Environment variables
QPQ_FEDERATION_LISTEN=0.0.0.0:7001
QPQ_LOCAL_DOMAIN=node1.mesh.local
QPQ_FEDERATION_CERT=/path/to/cert.der
QPQ_FEDERATION_KEY=/path/to/key.der
QPQ_FEDERATION_CA=/path/to/ca.der
```

Or in `qpq-server.toml`:

```toml
federation_enabled = true
federation_domain = "node1.mesh.local"
federation_listen = "0.0.0.0:7001"
```

### ALPN tokens

| Protocol | ALPN |
|---|---|
| Client ↔ Server | `b"capnp"` |
| P2P transport | `b"quicproquo/p2p/1"` |
| Federation | `b"quicproquo/federation/1"` |

## REPL command summary

| Command | Description |
|---|---|
| `/mesh peers` | Scan for nearby nodes via mDNS |
| `/mesh server <host:port>` | Note a discovered server |
| `/mesh send <peer_id> <msg>` | Direct P2P message |
| `/mesh broadcast <topic> <msg>` | Publish to broadcast channel |
| `/mesh subscribe <topic>` | Join a broadcast channel |
| `/mesh route` | Show routing table |
| `/mesh identity` | Show mesh identity info |
| `/mesh store` | Show store-and-forward stats |

## Implementation

- **P2P node:** `crates/quicproquo-p2p/src/lib.rs` — `P2pNode` with iroh
  transport
- **Mesh identity:** `crates/quicproquo-p2p/src/identity.rs`
- **Store-and-forward:** `crates/quicproquo-p2p/src/store.rs` +
  `envelope.rs`
- **Broadcast:** `crates/quicproquo-p2p/src/broadcast.rs`
- **mDNS discovery:** `crates/quicproquo-client/src/client/mesh_discovery.rs`
- **Federation routing:** `crates/quicproquo-server/src/node_service/delivery.rs`
- **REPL commands:** mesh handlers in `crates/quicproquo-client/src/client/repl.rs`
