Files
mesh/agent/CLAUDE.md
Gilles Soulier 1d177e96a6 first
2026-01-05 13:20:54 +01:00

322 lines
7.7 KiB
Markdown

# CLAUDE.md — Mesh Agent
This file provides agent-specific guidance for the Mesh desktop agent (Rust).
## Agent Role
The Mesh Agent is a desktop application (Linux/Windows/macOS) that provides:
- **P2P data plane**: QUIC connections for file/folder/terminal transfer
- **Local capabilities**: Terminal/PTY management, file watching
- **Server integration**: WebSocket control plane, REST API
- **Gotify notifications**: Direct notification sending
**Critical**: The agent handles ONLY data plane via QUIC. Media (audio/video/screen) is handled by the web client via WebRTC.
## Technology Stack
- **Rust stable** (edition 2021)
- **tokio**: Async runtime
- **quinn**: QUIC implementation
- **tokio-tungstenite**: WebSocket client
- **reqwest**: HTTP client
- **portable-pty**: Cross-platform PTY
- **tracing**: Logging framework
- **thiserror**: Error types
## Project Structure
```
agent/
├── src/
│ ├── main.rs # Entry point
│ ├── config/
│ │ └── mod.rs # Configuration management
│ ├── mesh/
│ │ ├── mod.rs
│ │ ├── types.rs # Event type definitions
│ │ ├── ws.rs # WebSocket client
│ │ └── rest.rs # REST API client
│ ├── p2p/
│ │ ├── mod.rs
│ │ ├── endpoint.rs # QUIC endpoint
│ │ └── protocol.rs # P2P protocol messages
│ ├── share/
│ │ ├── mod.rs
│ │ ├── file_send.rs # File transfer
│ │ └── folder_zip.rs # Folder zipping
│ ├── terminal/
│ │ └── mod.rs # PTY management
│ └── notifications/
│ └── mod.rs # Gotify client
├── tests/
├── Cargo.toml
├── Cargo.lock
└── CLAUDE.md
```
## Development Commands
### Setup
```bash
cd agent
# Install Rust if needed: https://rustup.rs/
rustup update stable
```
### Build
```bash
cargo build
```
### Run
```bash
cargo run
```
### Build Release
```bash
cargo build --release
# Binary in target/release/mesh-agent
```
### Run Tests
```bash
cargo test
```
### Format & Lint
```bash
cargo fmt
cargo clippy -- -D warnings
```
## Configuration
The agent creates a config file at:
- **Linux**: `~/.config/mesh/agent.toml`
- **macOS**: `~/Library/Application Support/Mesh/agent.toml`
- **Windows**: `%APPDATA%\Mesh\agent.toml`
**Config structure**:
```toml
device_id = "uuid-v4"
server_url = "http://localhost:8000"
ws_url = "ws://localhost:8000/ws"
auth_token = "optional-jwt-token"
gotify_url = "optional-gotify-url"
gotify_token = "optional-gotify-token"
quic_port = 0 # 0 for random
log_level = "info"
```
## QUIC P2P Protocol
### Session Flow
1. **Request session** via WebSocket (`p2p.session.request`)
2. **Receive session info** (`p2p.session.created`) with endpoints and auth
3. **Establish QUIC connection** to peer
4. **Send P2P_HELLO** with session_token
5. **Receive P2P_OK** or P2P_DENY
6. **Transfer data** via QUIC streams
7. **Close session**
### First Message: P2P_HELLO
Every QUIC stream MUST start with:
```json
{
"t": "P2P_HELLO",
"session_id": "uuid",
"session_token": "jwt-from-server",
"from_device_id": "uuid"
}
```
The peer validates the token before accepting the stream.
### Message Types
**File transfer**:
- `FILE_META`: name, size, hash
- `FILE_CHUNK`: offset, data
- `FILE_ACK`: last_offset
- `FILE_DONE`: final hash
**Folder transfer**:
- `FOLDER_MODE`: zip or sync
- `ZIP_META`, `ZIP_CHUNK`, `ZIP_DONE` (for zip mode)
**Terminal**:
- `TERM_OUT`: output data (UTF-8)
- `TERM_RESIZE`: cols, rows
- `TERM_IN`: input data (requires `terminal:control` capability)
See [protocol_events_v_2.md](../protocol_events_v_2.md) for complete protocol.
## Error Handling Rules
**CRITICAL**: NO `unwrap()` or `expect()` in production code.
Use `Result<T, E>` everywhere:
```rust
use anyhow::Result;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum AgentError {
#[error("WebSocket error: {0}")]
WebSocket(String),
#[error("QUIC error: {0}")]
Quic(String),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
}
```
Handle errors gracefully:
```rust
match risky_operation().await {
Ok(result) => handle_success(result),
Err(e) => {
tracing::error!("Operation failed: {}", e);
// Attempt recovery or return error
}
}
```
## Logging
Use `tracing` crate:
```rust
use tracing::{info, warn, error, debug};
info!("Connection established");
warn!("Retrying connection: attempt {}", attempt);
error!("Failed to send file: {}", err);
debug!("Received chunk: offset={}, len={}", offset, len);
```
**Never log**:
- Passwords, tokens, secrets
- Full file contents
- Sensitive user data
## Security Checklist
- [ ] All QUIC sessions validated with server-issued tokens
- [ ] Tokens checked for expiration
- [ ] Terminal input ONLY accepted with `terminal:control` capability
- [ ] SSH secrets never transmitted (stay on local machine)
- [ ] File transfers use chunking with hash verification
- [ ] No secrets in logs
- [ ] TLS 1.3 for all QUIC connections
## Terminal/PTY Management
**Default mode**: Preview (read-only)
- Agent creates PTY locally
- Spawns shell (bash/zsh on Unix, pwsh on Windows)
- Streams output via `TERM_OUT` messages
- Ignores `TERM_IN` messages unless control granted
**Control mode**: (requires server-arbitrated capability)
- ONE controller at a time
- Server issues `terminal:control` capability token
- Agent validates token before accepting input
- Input sent via `TERM_IN` messages
**Important**: Can run `ssh user@host` in the PTY for SSH preview.
## File Transfer Strategy
**Chunking**:
- Default chunk size: 256 KB
- Adjustable based on network conditions
**Hashing**:
- Use `blake3` for speed
- Hash each chunk + final hash
- Receiver validates
**Resume**:
- Track `last_offset` with `FILE_ACK`
- Resume from last acknowledged offset on reconnect
**Backpressure**:
- Wait for `FILE_ACK` before sending next batch
- Limit in-flight chunks
## Cross-Platform Considerations
**PTY**:
- Unix: `portable-pty` with bash/zsh
- Windows: `portable-pty` with PowerShell or ConPTY
**File paths**:
- Use `std::path::PathBuf` (cross-platform)
- Handle path separators correctly
**Config directory**:
- Linux: `~/.config/mesh/`
- macOS: `~/Library/Application Support/Mesh/`
- Windows: `%APPDATA%\Mesh\`
## Build & Packaging
**Single binary per platform**:
- Linux: `mesh-agent` (ELF)
- macOS: `mesh-agent` (Mach-O)
- Windows: `mesh-agent.exe` (PE)
**Installers** (V1/V2):
- Linux: `.deb`, `.rpm`
- macOS: `.dmg`, `.pkg`
- Windows: `.msi`
**Release profile** (Cargo.toml):
```toml
[profile.release]
opt-level = 3
lto = true
codegen-units = 1
strip = true
```
## Testing Strategy
1. **Unit tests**: Individual functions, protocol parsing
2. **Integration tests**: QUIC handshake, file transfer end-to-end
3. **Manual tests**: Cross-platform PTY, real network conditions
## Performance Targets
- QUIC connection establishment: < 500ms
- File transfer: > 100 MB/s on LAN
- Terminal latency: < 50ms
- Memory usage: < 50 MB idle, < 200 MB active transfer
## Development Workflow
**Iterative approach** (CRITICAL):
1. Build compilable skeleton first
2. Add one module at a time
3. Test after each module
4. NO "big bang" implementations
**Module order** (recommended):
1. Config + logging
2. WebSocket client (basic connection)
3. REST client (health check, auth)
4. QUIC endpoint (skeleton)
5. File transfer (simple)
6. Terminal/PTY (preview only)
7. Gotify notifications
8. Advanced features (folder sync, terminal control)
---
**Remember**: The agent is data plane only (QUIC). WebRTC media is handled by the web client. Work in short iterations, and never use `unwrap()` in production code.