enigma-relay
Production-ready offline store-and-forward relay for Enigma nodes with durable queues, rate limiting, TTL/GC, idempotent acknowledgements, and optional TLS/mTLS.
Features
- HTTP/HTTPS API compatible with enigma-core outbox/pull/ack
- Durable sled backend (default) with atomic quotas; in-memory backend for testing
- Per-recipient quotas by count and bytes, per-endpoint/IP rate limiting, and structured JSON errors
- TTL with background GC, cursor-based paging, and idempotent push/ack flows
- Optional metrics endpoint and TLS/mTLS using rustls
Quickstart
- Run locally with defaults:
cargo run --features http(binds 127.0.0.1:0, sled at ./relay_db) - Embed from code:
let mut cfg = default; cfg.address = "127.0.0.1:3000".into; cfg.storage.kind = Sled; let running = start.await?; - Stop the server by sending on
running.shutdownand awaitingrunning.handle.
Configuration (TOML)
= "0.0.0.0:7000"
= "http" # or "tls"
[]
= "./cert.pem"
= "./key.pem"
# client_ca_pem_path = "./ca.pem" # enables mTLS when the mtls feature is on
[]
= "sled" # or "memory"
= "./relay_db"
[]
= 8_388_608
= 1_073_741_824
= 200_000
= 1_209_600
= 60
= 256
[]
= true
= 20
= 40
= 300
[]
= 10
= 5
= 10
HTTP API
POST /push— body{ recipient, message_id, ciphertext_b64, meta: { kind, total_len, chunk_index, chunk_count, sent_ms } }; enforces size, quotas, idempotency; response{ stored, duplicate?, queue_len?, queue_bytes? }.POST /pull— body{ recipient, cursor?, max? }; returns{ items: [...], next_cursor, remaining_estimate }ordered by arrival.POST /ack— body{ recipient, ack: [ { message_id, chunk_index } ] }; idempotent delete with{ deleted, missing, remaining }.GET /health— liveness.GET /stats— uptime and metrics (only when themetricsfeature is enabled; otherwise minimal JSON).- All errors are JSON
{ "error": { "code": "...", "message": "...", "details": ... } }.
Persistence and GC
- Sled backend keys:
msg:{recipient}:{arrival_seq}:{message_id}:{chunk_index},idx:{recipient}:{message_id}:{chunk_index},quota:{recipient},seq:{recipient}. - Push/ack updates are atomic and keep quotas consistent. GC runs on
gc_interval_secondsand removes expired items while updating quotas.
TLS and mTLS
- Enable the
tlsfeature and setmode = "tls"with PEM paths. Provideclient_ca_pem_pathand themtlsfeature to require client certificates.
Testing
- Default suite:
cargo test - TLS/persistence suite:
cargo test --features tls,persistence - Release build:
cargo build --release --features tls,persistence