--- 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