Comprehensive documentation: architecture, usage, integration, progress, security
docs/ARCHITECTURE.md (531 lines): System design, ASCII diagrams, crypto stack, dual-curve identity, wire protocol (7 WireMessage variants), server/client architecture, data flow diagrams, storage model, extensibility points docs/USAGE.md (550 lines): Complete user guide: installation, all CLI commands (10), all TUI commands (20+), all web commands, file transfer, identity management, aliases, groups, multi-device, backup, keyboard shortcuts docs/INTEGRATION.md (542 lines): WarzonePhone concept, Ethereum/Web3, OIDC, DNS federation, transport abstraction, multi-server mode, custom clients, ntfy, how-to guides for extending message types/commands/storage docs/PROGRESS.md (234 lines): Timeline, Phase 1 (16 features), Phase 2 (16 features), v0.0.20, 28 tests, bugs fixed, known limitations, Phase 3-7 roadmap docs/SECURITY.md (438 lines): Threat model, 8 crypto primitives, key derivation paths, forward secrecy, Sender Keys trade-offs, seed security, server trust, WASM security, known weaknesses, comparison with Signal/Matrix/SimpleX Total: 3,751 lines across 8 doc files. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
531
warzone/docs/ARCHITECTURE.md
Normal file
531
warzone/docs/ARCHITECTURE.md
Normal file
@@ -0,0 +1,531 @@
|
||||
# Warzone Messenger (featherChat) — Architecture
|
||||
|
||||
**Version:** 0.0.20
|
||||
**Status:** Phase 1 complete, Phase 2 complete
|
||||
|
||||
---
|
||||
|
||||
## High-Level Architecture
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────────┐
|
||||
│ Clients │
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌───────────────────────┐ │
|
||||
│ │ CLI Client │ │ TUI Client │ │ Web Client (WASM) │ │
|
||||
│ │ (warzone) │ │ (ratatui) │ │ (wasm-bindgen) │ │
|
||||
│ └──────┬───────┘ └──────┬───────┘ └───────────┬───────────┘ │
|
||||
│ │ │ │ │
|
||||
│ ┌──────┴─────────────────┴───────────────────────┴──────────┐ │
|
||||
│ │ warzone-protocol │ │
|
||||
│ │ Identity · X3DH · Double Ratchet · Sender Keys · History │ │
|
||||
│ └───────────────────────────┬───────────────────────────────┘ │
|
||||
└──────────────────────────────┼──────────────────────────────────┘
|
||||
│ HTTP / WebSocket
|
||||
▼
|
||||
┌──────────────────────────────────────────────────────────────────┐
|
||||
│ warzone-server │
|
||||
│ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────────────┐ │
|
||||
│ │ HTTP API │ │ WebSocket│ │ Auth │ │ Message Router │ │
|
||||
│ │ (axum) │ │ Relay │ │Challenge │ │ + Dedup │ │
|
||||
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────────┬────────┘ │
|
||||
│ │ │ │ │ │
|
||||
│ ┌────┴─────────────┴─────────────┴──────────────────┴────────┐ │
|
||||
│ │ sled Database │ │
|
||||
│ │ keys · messages · groups · aliases · tokens │ │
|
||||
│ └─────────────────────────────────────────────────────────────┘ │
|
||||
└──────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Crate Structure
|
||||
|
||||
The project is a Cargo workspace with five crates:
|
||||
|
||||
```
|
||||
warzone/
|
||||
├── Cargo.toml # Workspace root (v0.0.20)
|
||||
├── crates/
|
||||
│ ├── warzone-protocol/ # Core crypto & message types (library)
|
||||
│ ├── warzone-server/ # Server binary (axum + sled)
|
||||
│ ├── warzone-client/ # CLI/TUI client binary
|
||||
│ ├── warzone-wasm/ # WASM bridge for web client
|
||||
│ └── warzone-mule/ # Mule binary (future)
|
||||
└── docs/
|
||||
```
|
||||
|
||||
### warzone-protocol
|
||||
|
||||
The protocol crate is the heart of the system. It is a pure library with zero I/O dependencies, used by all other crates (including WASM).
|
||||
|
||||
| Module | Purpose |
|
||||
|---------------|------------------------------------------------------|
|
||||
| `identity` | Seed, IdentityKeyPair, PublicIdentity, Fingerprint |
|
||||
| `mnemonic` | BIP39 mnemonic encode/decode |
|
||||
| `crypto` | HKDF-SHA256, ChaCha20-Poly1305 AEAD |
|
||||
| `prekey` | SignedPreKey, OneTimePreKey, PreKeyBundle |
|
||||
| `x3dh` | X3DH key agreement (initiate + respond) |
|
||||
| `ratchet` | Double Ratchet state machine |
|
||||
| `message` | WireMessage enum, MessageContent, ReceiptType |
|
||||
| `session` | Session management types |
|
||||
| `store` | Storage trait definitions |
|
||||
| `sender_keys` | Sender Key protocol for groups |
|
||||
| `history` | Encrypted backup/restore (HKDF → ChaCha20) |
|
||||
| `ethereum` | secp256k1 identity, Ethereum address derivation |
|
||||
| `types` | Fingerprint, DeviceId, SessionId, MessageId |
|
||||
| `errors` | ProtocolError enum |
|
||||
|
||||
### warzone-server
|
||||
|
||||
An axum HTTP + WebSocket server with sled embedded database.
|
||||
|
||||
| Module | Purpose |
|
||||
|------------------|--------------------------------------------|
|
||||
| `main` | CLI args, server startup (default :7700) |
|
||||
| `state` | AppState, Connections map, DedupTracker |
|
||||
| `db` | Database struct (5 sled trees) |
|
||||
| `routes/keys` | Pre-key bundle registration & retrieval |
|
||||
| `routes/messages`| Send, poll (fetch-and-delete), ack |
|
||||
| `routes/groups` | Create, join, leave, kick, members, list |
|
||||
| `routes/aliases` | Register, resolve, recover, renew, admin |
|
||||
| `routes/auth` | Challenge-response authentication |
|
||||
| `routes/ws` | WebSocket real-time message delivery |
|
||||
| `routes/web` | Static file serving for web client |
|
||||
| `routes/health` | Health check endpoint |
|
||||
|
||||
### warzone-client
|
||||
|
||||
CLI and TUI client with local sled database for sessions, contacts, and history.
|
||||
|
||||
| Module | Purpose |
|
||||
|-------------|------------------------------------------------|
|
||||
| `main` | CLI parser (clap): init, recover, info, etc. |
|
||||
| `keystore` | Seed encryption at rest (Argon2id + ChaCha20) |
|
||||
| `storage` | LocalDb: sessions, pre_keys, contacts, history |
|
||||
| `net` | HTTP + WebSocket client |
|
||||
| `tui/app` | TUI application (ratatui + crossterm) |
|
||||
| `cli/*` | CLI subcommand handlers |
|
||||
|
||||
### warzone-wasm
|
||||
|
||||
WASM bridge exposing protocol functions to JavaScript via `wasm-bindgen`.
|
||||
|
||||
| Export | Purpose |
|
||||
|-------------------------|--------------------------------------------|
|
||||
| `WasmIdentity` | Seed generation, fingerprint, bundle |
|
||||
| `WasmSession` | Encrypt/decrypt with Double Ratchet |
|
||||
| `create_receipt` | Build receipt WireMessages |
|
||||
| `decrypt_wire_message` | Full message decryption pipeline |
|
||||
| `self_test` | End-to-end crypto verification in WASM |
|
||||
| `debug_bundle_info` | Bundle introspection for debugging |
|
||||
|
||||
### warzone-mule (future)
|
||||
|
||||
Placeholder for the mule binary — physical message relay for disconnected networks.
|
||||
|
||||
---
|
||||
|
||||
## Cryptographic Stack
|
||||
|
||||
### Primitives
|
||||
|
||||
| Primitive | Crate | Purpose |
|
||||
|-----------------------|----------------------|------------------------------------------|
|
||||
| Ed25519 | `ed25519-dalek` | Signing, identity verification |
|
||||
| X25519 | `x25519-dalek` | Diffie-Hellman key exchange |
|
||||
| ChaCha20-Poly1305 | `chacha20poly1305` | Authenticated encryption (AEAD) |
|
||||
| HKDF-SHA256 | `hkdf` + `sha2` | Key derivation |
|
||||
| SHA-256 | `sha2` | Fingerprint computation |
|
||||
| Argon2id | `argon2` | Passphrase-based key derivation |
|
||||
| secp256k1 ECDSA | `k256` | Ethereum-compatible signing |
|
||||
| Keccak-256 | `tiny-keccak` | Ethereum address derivation |
|
||||
|
||||
### Protocol Stack
|
||||
|
||||
```
|
||||
Application (plaintext)
|
||||
│
|
||||
▼
|
||||
Double Ratchet (per-message keys, forward secrecy)
|
||||
│
|
||||
▼
|
||||
X3DH (session establishment, 3-4 DH operations)
|
||||
│
|
||||
▼
|
||||
ChaCha20-Poly1305 (authenticated encryption)
|
||||
│
|
||||
▼
|
||||
Ed25519 (message signing + pre-key signing)
|
||||
│
|
||||
▼
|
||||
WireMessage (bincode serialization)
|
||||
│
|
||||
▼
|
||||
Transport (HTTP POST / WebSocket binary frame)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Dual-Curve Identity Model
|
||||
|
||||
Warzone derives two separate cryptographic identities from a single BIP39 seed:
|
||||
|
||||
```
|
||||
BIP39 Seed (32 bytes, 24 words)
|
||||
│
|
||||
├─── HKDF(info="warzone-ed25519") ──→ Ed25519 signing keypair
|
||||
│ │
|
||||
│ └─→ SHA-256[:16] = Fingerprint
|
||||
│
|
||||
├─── HKDF(info="warzone-x25519") ──→ X25519 encryption keypair
|
||||
│ (used in X3DH + Double Ratchet)
|
||||
│
|
||||
└─── HKDF(info="warzone-secp256k1") ──→ secp256k1 keypair
|
||||
│
|
||||
└─→ Keccak-256[-20:] = Ethereum Address
|
||||
```
|
||||
|
||||
**Messaging identity:** Ed25519 (signing) + X25519 (encryption). The fingerprint is `SHA-256(Ed25519_pubkey)[:16]`, displayed as `xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx`.
|
||||
|
||||
**Ethereum identity:** secp256k1 keypair derived from the same seed with domain-separated HKDF. The Ethereum address is derived using standard `Keccak-256(uncompressed_pubkey[1:])[-20:]`. EIP-55 checksummed display is supported.
|
||||
|
||||
This allows a single mnemonic to control both a Warzone messaging identity and an Ethereum wallet address.
|
||||
|
||||
---
|
||||
|
||||
## Wire Protocol
|
||||
|
||||
All messages between clients use the `WireMessage` enum, serialized with bincode:
|
||||
|
||||
```rust
|
||||
enum WireMessage {
|
||||
// Session establishment (X3DH + first ratchet message)
|
||||
KeyExchange {
|
||||
id, sender_fingerprint, sender_identity_encryption_key,
|
||||
ephemeral_public, used_one_time_pre_key_id, ratchet_message,
|
||||
},
|
||||
|
||||
// Subsequent DM messages (Double Ratchet encrypted)
|
||||
Message { id, sender_fingerprint, ratchet_message },
|
||||
|
||||
// Delivery / read receipts (plaintext metadata)
|
||||
Receipt { sender_fingerprint, message_id, receipt_type },
|
||||
|
||||
// File transfer: header announces the file
|
||||
FileHeader { id, sender_fingerprint, filename, file_size, total_chunks, sha256 },
|
||||
|
||||
// File transfer: individual chunk (encrypted data)
|
||||
FileChunk { id, sender_fingerprint, filename, chunk_index, total_chunks, data },
|
||||
|
||||
// Group message encrypted with Sender Key (O(1) encryption)
|
||||
GroupSenderKey { id, sender_fingerprint, group_name, generation, counter, ciphertext },
|
||||
|
||||
// Sender Key distribution (sent via 1:1 encrypted channel)
|
||||
SenderKeyDistribution { sender_fingerprint, group_name, chain_key, generation },
|
||||
}
|
||||
```
|
||||
|
||||
### Transport Encoding
|
||||
|
||||
- **CLI ↔ Server (HTTP):** JSON envelope with bincode message as byte array
|
||||
- **CLI ↔ Server (WebSocket binary):** 64 hex chars (recipient fingerprint) + raw bincode bytes
|
||||
- **Web ↔ Server (WebSocket JSON):** `{"to": "fingerprint", "message": [byte_array]}`
|
||||
|
||||
---
|
||||
|
||||
## Server Architecture
|
||||
|
||||
### Framework
|
||||
|
||||
- **axum 0.7** with tokio async runtime
|
||||
- **sled 0.34** embedded database (zero-config, no external DB)
|
||||
- **tower-http** for CORS and tracing middleware
|
||||
|
||||
### Route Structure
|
||||
|
||||
All API endpoints live under `/v1`:
|
||||
|
||||
```
|
||||
POST /v1/keys/register Register pre-key bundle
|
||||
GET /v1/keys/:fingerprint Fetch pre-key bundle
|
||||
POST /v1/keys/replenish Upload additional OTPKs
|
||||
GET /v1/keys/:fp/otpk-count Check remaining OTPKs
|
||||
GET /v1/keys/:fp/devices List registered devices
|
||||
GET /v1/keys/list List all registered fingerprints
|
||||
|
||||
POST /v1/messages/send Send encrypted message
|
||||
GET /v1/messages/poll/:fp Fetch-and-delete queued messages
|
||||
DELETE /v1/messages/:id/ack Explicit message acknowledgment
|
||||
|
||||
POST /v1/groups/create Create a group
|
||||
GET /v1/groups List all groups
|
||||
GET /v1/groups/:name Get group info
|
||||
POST /v1/groups/:name/join Join a group
|
||||
POST /v1/groups/:name/send Fan-out group message
|
||||
POST /v1/groups/:name/leave Leave a group
|
||||
POST /v1/groups/:name/kick Kick a member (creator only)
|
||||
GET /v1/groups/:name/members List members with aliases
|
||||
|
||||
POST /v1/alias/register Register an alias
|
||||
POST /v1/alias/recover Recover alias with recovery key
|
||||
POST /v1/alias/renew Heartbeat / renew TTL
|
||||
GET /v1/alias/resolve/:name Resolve alias → fingerprint
|
||||
GET /v1/alias/whois/:fp Reverse lookup fingerprint → alias
|
||||
GET /v1/alias/list List all aliases
|
||||
POST /v1/alias/unregister Remove your own alias
|
||||
POST /v1/alias/admin-remove Admin: remove any alias
|
||||
|
||||
POST /v1/auth/challenge Request a challenge
|
||||
POST /v1/auth/verify Verify signature, get bearer token
|
||||
|
||||
GET /v1/ws/:fingerprint WebSocket upgrade for real-time push
|
||||
|
||||
GET / Web client static files
|
||||
GET /health Health check
|
||||
```
|
||||
|
||||
### Message Routing
|
||||
|
||||
```
|
||||
Incoming message
|
||||
│
|
||||
├─→ Dedup check (bounded FIFO, 10,000 IDs)
|
||||
│ │
|
||||
│ ├─→ Duplicate? → silently drop
|
||||
│ └─→ New? → continue
|
||||
│
|
||||
├─→ Try WebSocket push to recipient
|
||||
│ │
|
||||
│ ├─→ Connected? → instant delivery
|
||||
│ └─→ Offline? → queue in sled DB
|
||||
│
|
||||
└─→ Renew sender's alias TTL
|
||||
```
|
||||
|
||||
### WebSocket Protocol
|
||||
|
||||
1. Client connects to `/v1/ws/:fingerprint`
|
||||
2. Server flushes any queued messages from DB
|
||||
3. Server registers a push channel for this connection
|
||||
4. Incoming WS messages are routed to recipient's WS or queued
|
||||
5. Multiple devices per fingerprint are supported (all receive a copy)
|
||||
6. On disconnect, stale senders are cleaned up
|
||||
|
||||
### Dedup Tracker
|
||||
|
||||
The `DedupTracker` prevents message duplication across HTTP and WebSocket delivery paths:
|
||||
|
||||
- Bounded to 10,000 message IDs
|
||||
- FIFO eviction when capacity is exceeded
|
||||
- Uses `HashSet` for O(1) lookup + `VecDeque` for ordering
|
||||
- Thread-safe via `std::sync::Mutex`
|
||||
|
||||
---
|
||||
|
||||
## Web Client Architecture (WASM)
|
||||
|
||||
The web client runs the **exact same crypto** as the CLI through the `warzone-wasm` crate:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ Browser │
|
||||
│ │
|
||||
│ ┌──────────────────┐ ┌──────────────────────────┐ │
|
||||
│ │ JavaScript UI │ │ warzone-wasm (WASM) │ │
|
||||
│ │ (chat.html) │──│ WasmIdentity │ │
|
||||
│ │ │ │ WasmSession │ │
|
||||
│ │ WebSocket ◄─────┤ │ decrypt_wire_message() │ │
|
||||
│ │ localStorage │ │ create_receipt() │ │
|
||||
│ │ │ │ self_test() │ │
|
||||
│ └──────────────────┘ └──────────────────────────┘ │
|
||||
│ │
|
||||
│ Storage: │
|
||||
│ localStorage: seed_hex, spk_secret_hex │
|
||||
│ localStorage: session:<fp> (base64 ratchet state) │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
Key design decisions:
|
||||
- **Web Crypto** provides cryptographic randomness (`OsRng` in WASM maps to `crypto.getRandomValues`)
|
||||
- **No OTPKs** in the web client — cannot reliably store secrets. X3DH works without DH4 (OTPKs are an anti-replay optimization, not a security requirement)
|
||||
- **SPK secret** stored in localStorage as hex, restored on page load
|
||||
- **Session state** serialized as base64 bincode, stored per-peer in localStorage
|
||||
- **bincode** wire format ensures CLI ↔ Web interoperability
|
||||
|
||||
---
|
||||
|
||||
## Data Flow Diagrams
|
||||
|
||||
### 1:1 Direct Message (First Message)
|
||||
|
||||
```
|
||||
Alice Server Bob
|
||||
│ │ │
|
||||
│ GET /v1/keys/:bob_fp │ │
|
||||
│─────────────────────────────→│ │
|
||||
│ ← PreKeyBundle (bincode) │ │
|
||||
│ │ │
|
||||
│ X3DH initiate(bundle) │ │
|
||||
│ → shared_secret │ │
|
||||
│ Double Ratchet init_alice() │ │
|
||||
│ ratchet.encrypt("hello") │ │
|
||||
│ │ │
|
||||
│ WireMessage::KeyExchange │ │
|
||||
│ POST /v1/messages/send │ │
|
||||
│─────────────────────────────→│ push via WS (or queue) │
|
||||
│ │─────────────────────────────→│
|
||||
│ │ │
|
||||
│ │ X3DH respond(spk_secret) │
|
||||
│ │ → shared_secret │
|
||||
│ │ init_bob() │
|
||||
│ │ ratchet.decrypt() │
|
||||
│ │ → "hello" │
|
||||
```
|
||||
|
||||
### 1:1 Direct Message (Subsequent)
|
||||
|
||||
```
|
||||
Alice Server Bob
|
||||
│ │ │
|
||||
│ ratchet.encrypt("hi again") │ │
|
||||
│ WireMessage::Message │ │
|
||||
│ ─── WS binary ─────────────→│ ─── WS push ───────────────→│
|
||||
│ │ │
|
||||
│ │ ratchet.decrypt()│
|
||||
│ │ → "hi again" │
|
||||
│ │ │
|
||||
│ │ WireMessage::Receipt │
|
||||
│ │←──────────────────────────── │
|
||||
│←─────────────────────────────│ │
|
||||
│ ✓✓ delivered │ │
|
||||
```
|
||||
|
||||
### Group Message (Sender Keys)
|
||||
|
||||
```
|
||||
Alice Server Bob, Carol
|
||||
│ │ │
|
||||
│ SenderKey::generate("ops") │ │
|
||||
│ Distribute via 1:1 channels: │ │
|
||||
│ encrypt(SK_dist, Bob) │ │
|
||||
│ encrypt(SK_dist, Carol) │ │
|
||||
│ ─────────────────────────────→│──── push to Bob,Carol ──→│
|
||||
│ │ │
|
||||
│ sender_key.encrypt("attack") │ │
|
||||
│ WireMessage::GroupSenderKey │ │
|
||||
│ POST /groups/ops/send │ │
|
||||
│ ─────────────────────────────→│──── fan-out ────────────→│
|
||||
│ │ │
|
||||
│ │ bob_copy.decrypt() │
|
||||
│ │ carol_copy.decrypt() │
|
||||
│ │ → "attack" │
|
||||
```
|
||||
|
||||
### File Transfer
|
||||
|
||||
```
|
||||
Sender Server Recipient
|
||||
│ │ │
|
||||
│ Read file, compute SHA-256 │ │
|
||||
│ Split into 64KB chunks │ │
|
||||
│ │ │
|
||||
│ WireMessage::FileHeader │ │
|
||||
│ ─────────────────────────────→│──── push ────────────────→│
|
||||
│ │ │
|
||||
│ WireMessage::FileChunk[0] │ │
|
||||
│ ─────────────────────────────→│──── push ────────────────→│
|
||||
│ WireMessage::FileChunk[1] │ │
|
||||
│ ─────────────────────────────→│──── push ────────────────→│
|
||||
│ ... │ │
|
||||
│ WireMessage::FileChunk[N-1] │ │
|
||||
│ ─────────────────────────────→│──── push ────────────────→│
|
||||
│ │ │
|
||||
│ │ Reassemble chunks │
|
||||
│ │ Verify SHA-256 │
|
||||
│ │ Save to downloads/ │
|
||||
```
|
||||
|
||||
File constraints: max 10 MB, 64 KB chunks.
|
||||
|
||||
---
|
||||
|
||||
## Storage Model
|
||||
|
||||
### Server sled Trees
|
||||
|
||||
| Tree | Key Format | Value | Purpose |
|
||||
|------------|-------------------------------|--------------------------|------------------------------|
|
||||
| `keys` | `<fingerprint>` | bincode PreKeyBundle | Identity + pre-key storage |
|
||||
| `keys` | `device:<fp>:<device_id>` | bincode PreKeyBundle | Per-device bundles |
|
||||
| `keys` | `otpk:<fp>:<id>` | hex pubkey | One-time pre-keys |
|
||||
| `messages` | `queue:<fp>:<uuid>` | raw bincode WireMessage | Offline message queue |
|
||||
| `groups` | `<group_name>` | JSON GroupInfo | Group membership |
|
||||
| `aliases` | `a:<alias>` | fingerprint string | Forward lookup |
|
||||
| `aliases` | `fp:<fingerprint>` | alias string | Reverse lookup |
|
||||
| `aliases` | `rec:<alias>` | JSON AliasRecord | Full record (TTL, recovery) |
|
||||
| `tokens` | `<token_hex>` | JSON {fp, expires_at} | Auth bearer tokens |
|
||||
|
||||
### Client sled Trees
|
||||
|
||||
| Tree | Key Format | Value | Purpose |
|
||||
|-------------|-------------------------------|--------------------------|----------------------------|
|
||||
| `sessions` | `<peer_fp_hex>` | bincode RatchetState | Double Ratchet sessions |
|
||||
| `pre_keys` | `spk:<id>` | 32-byte StaticSecret | Signed pre-key secrets |
|
||||
| `pre_keys` | `otpk:<id>` | 32-byte StaticSecret | One-time pre-key secrets |
|
||||
| `contacts` | `<fingerprint>` | JSON contact record | Contact list |
|
||||
| `history` | `hist:<fp>:<ts>:<uuid>` | JSON message record | Message history |
|
||||
|
||||
### Client Filesystem
|
||||
|
||||
```
|
||||
~/.warzone/
|
||||
├── identity.seed # WZS1 magic + salt(16) + nonce(12) + ciphertext(48)
|
||||
│ # or plain 32 bytes (legacy/testing)
|
||||
└── db/ # sled database directory
|
||||
├── conf
|
||||
├── db
|
||||
└── ...
|
||||
```
|
||||
|
||||
The `WARZONE_HOME` environment variable overrides `~/.warzone`.
|
||||
|
||||
---
|
||||
|
||||
## Extensibility Points
|
||||
|
||||
### Adding New WireMessage Variants
|
||||
|
||||
1. Add a new variant to `WireMessage` in `warzone-protocol/src/message.rs`
|
||||
2. Update `extract_message_id()` in both `routes/messages.rs` and `routes/ws.rs`
|
||||
3. Handle in the TUI poll loop (`tui/app.rs`)
|
||||
4. Handle in `decrypt_wire_message()` in `warzone-wasm/src/lib.rs`
|
||||
5. bincode serialization is automatic (enum tag + fields)
|
||||
|
||||
### Adding New Transport Traits (future)
|
||||
|
||||
The design document specifies a `Transport` trait:
|
||||
|
||||
```rust
|
||||
trait Transport {
|
||||
async fn send(&self, endpoint: &str, blob: &[u8]) -> Result<()>;
|
||||
async fn recv(&self) -> Result<Vec<u8>>;
|
||||
}
|
||||
```
|
||||
|
||||
Current transports: HTTPS (reqwest) and WebSocket (axum/tungstenite). Planned: Bluetooth, LoRa, Wi-Fi Direct, USB/file.
|
||||
|
||||
### Adding New Storage Backends
|
||||
|
||||
Client storage currently uses sled directly. The pattern for abstraction:
|
||||
- `LocalDb` in `storage.rs` already provides a clean API
|
||||
- Replace sled calls with trait methods for alternative backends (SQLite, IndexedDB, etc.)
|
||||
- Server's `Database` in `db.rs` follows the same pattern
|
||||
|
||||
### Adding New Server Routes
|
||||
|
||||
1. Create a module in `routes/`
|
||||
2. Implement `pub fn routes() -> Router<AppState>`
|
||||
3. Merge into the router in `routes/mod.rs`
|
||||
4. Access shared state via `State(state): State<AppState>`
|
||||
Reference in New Issue
Block a user