156 lines
6.3 KiB
Markdown
Raw Normal View History

2026-03-17 00:03:08 +00:00
---
name: mesh
description: Mesh networking development for Archipelago — protocol, crypto, serial driver, transport abstraction, and LoRa chat. Use when working on mesh radio, Meshcore protocol, LoRa messaging, transport layers, peer discovery, or off-grid communication features.
---
# Mesh Networking Skill
## Architecture
The mesh subsystem enables offline peer discovery and end-to-end encrypted messaging between Archipelago nodes via Meshcore LoRa radio devices (Heltec V3, T-Beam, RAK WisBlock).
```
USB Meshcore Device (115200 baud)
↕ serial2-tokio
core/archipelago/src/mesh/
├── mod.rs — MeshService: lifecycle, config, public API
├── types.rs — MeshPeer, MeshMessage, MeshStatus, MeshEvent
├── protocol.rs — Meshcore binary frame protocol (encode/decode)
├── serial.rs — MeshcoreDevice: async serial driver
├── crypto.rs — X25519 ECDH + ChaCha20-Poly1305 encryption
└── listener.rs — Background tokio task: serial reader + dispatcher
↕ RPC
core/archipelago/src/api/rpc/mesh.rs — 6 endpoints
↕ HTTP
neode-ui/src/stores/mesh.ts — Pinia store
neode-ui/src/views/Mesh.vue — Two-column chat UI
```
## Key Files
### Backend (Rust)
- `core/archipelago/src/mesh/mod.rs` — MeshService (start/stop/status/peers/messages/send/configure)
- `core/archipelago/src/mesh/types.rs` — All shared types
- `core/archipelago/src/mesh/protocol.rs` — Binary frame format, command builders, response parsers (12 unit tests)
- `core/archipelago/src/mesh/serial.rs` — USB serial driver, handshake, device detection
- `core/archipelago/src/mesh/crypto.rs` — X25519 key agreement + ChaCha20-Poly1305 (7 unit tests)
- `core/archipelago/src/mesh/listener.rs` — Background event loop, auto-reconnect, peer cache
- `core/archipelago/src/api/rpc/mesh.rs` — RPC handlers (mesh.status/peers/messages/send/broadcast/configure)
- `core/archipelago/src/server.rs` — MeshService initialization (non-blocking)
- `core/archipelago/src/identity.rs` — Ed25519 keypair, DID, X25519 derivation
### Frontend (Vue 3 + TypeScript)
- `neode-ui/src/stores/mesh.ts` — Pinia store with unread tracking
- `neode-ui/src/views/Mesh.vue` — Full chat UI (~1000 lines)
- `neode-ui/src/router/index.ts` — Route: `/dashboard/mesh`
### Mock Backend
- `neode-ui/mock-backend.js` — Dev mode mesh RPC responses (mesh.status/peers/messages/send/broadcast/configure)
## Protocol Reference
### Meshcore Frame Format
- Outbound: `<` (0x3C) + 2-byte LE length + data
- Inbound: `>` (0x3E) + 2-byte LE length + data
- Max LoRa payload: 160 bytes
- Baud: 115200, 8N1
### Key Commands
| Byte | Command | Description |
|------|---------|-------------|
| 0x01 | APP_START | Init session with version negotiation |
| 0x02 | SEND_TXT_MSG | Direct message (6-byte pubkey prefix) |
| 0x03 | SEND_CHANNEL_TXT_MSG | Broadcast on channel |
| 0x04 | GET_CONTACTS | Fetch contact list |
| 0x06 | SET_DEVICE_TIME | Sync device clock |
| 0x07 | SEND_SELF_ADVERT | Broadcast identity |
| 0x0A | SYNC_NEXT_MESSAGE | Retrieve queued messages |
### Identity Wire Format
`ARCHY:2:{ed25519_hex_64}:{x25519_hex_64}` (137 bytes, fits 160)
### Encryption
- X25519 Diffie-Hellman from Ed25519 keys (RFC 7748 clamping)
- ChaCha20-Poly1305 AEAD with random 12-byte nonce
- Wire: `[nonce 12B] + [ciphertext + tag 16B]` — max 132B plaintext
## RPC Endpoints
| Method | Params | Returns |
|--------|--------|---------|
| `mesh.status` | — | MeshStatus |
| `mesh.peers` | — | `{peers, count}` |
| `mesh.messages` | `{limit?}` | `{messages, count}` |
| `mesh.send` | `{contact_id, message}` | `{sent, message_id, encrypted}` |
| `mesh.broadcast` | — | `{broadcast}` |
| `mesh.configure` | `{enabled?, device_path?, channel_name?, broadcast_identity?, advert_name?}` | `{configured}` |
## Development Workflow
### Building & Testing (on dev server, NOT macOS)
```bash
# Deploy mesh changes
./scripts/deploy-to-target.sh --live
# Run mesh unit tests on server
ssh -i ~/.ssh/archipelago-deploy archipelago@192.168.1.228 \
'cd ~/archy/core && cargo test --all-features -- mesh'
# Check device is detected
ssh -i ~/.ssh/archipelago-deploy archipelago@192.168.1.228 \
'ls -la /dev/ttyUSB* /dev/ttyACM* 2>/dev/null'
# Watch mesh logs
ssh -i ~/.ssh/archipelago-deploy archipelago@192.168.1.228 \
'sudo journalctl -u archipelago -f | grep -i mesh'
```
### Frontend Dev (local, mock backend)
```bash
cd neode-ui && npm start
# Mesh mock data at http://localhost:8100/dashboard/mesh
```
## Roadmap Phases
### Phase 1: Core Implementation (COMPLETE)
- Meshcore binary protocol, serial driver, crypto, listener, RPC, Vue UI
### Phase 2: Mesh as Federation Transport
- NodeTransport trait abstraction (mesh/tor/lan backends)
- Transport priority: Mesh (1) > LAN/mDNS (2) > Tor (3)
- Chunked message protocol for >160B payloads (Reed-Solomon FEC)
- CBOR delta sync instead of full JSON state
- Transport indicator per peer in federation UI
- "Mesh only" off-grid mode
- Dependencies: `ciborium` (CBOR), `reed-solomon-erasure` (FEC), `mdns-sd` (LAN discovery)
### Phase 3: Encrypted Mesh Messaging
- Double Ratchet (Signal protocol) over LoRa
- X3DH key agreement using existing Ed25519/X25519
- Store-and-forward relay for offline peers (24h TTL)
- Message types: TEXT, ALERT, INVOICE (bolt11), PSBT_HASH, COORDINATE
- Per-peer chat threads, delivery status, offline indicators
### Phase 4: Off-Grid Bitcoin Operations
- Compact block headers over mesh (SPV verification)
- Transaction relay via internet-connected mesh peer
- Lightning payment coordination over mesh
- Emergency alert system (signed alerts, GPS, dead man's switch)
### Phase 5: Mesh Network Intelligence
- Adaptive routing, signal strength mapping, spreading factor adjustment
- Multi-path routing for reliability
- Steganographic modes
- Additional hardware: T-Beam, RAK WisBlock, WiFi mesh (802.11s), BLE, Blockstream Satellite
## Conventions
- All crypto uses existing identity infrastructure (Ed25519 signing key → X25519 derivation)
- Mesh init is non-blocking — errors logged but don't crash server
- Config persists to `{data_dir}/mesh-config.json`
- Message buffer: circular, max 100 messages
- Never build Rust on macOS — always deploy to server
- USB device paths: `/dev/ttyUSB*` and `/dev/ttyACM*`
- `archipelago` user must be in `dialout` group for serial access