# featherChat — Design Principles & Conventions ## Architecture Principles 1. **Single seed, multiple identities** — Ed25519 (messaging), X25519 (encryption), secp256k1 (ETH address) all derived from one BIP39 seed via HKDF with domain-separated info strings. 2. **E2E by default** — All user messages are Double Ratchet encrypted. The server NEVER sees plaintext. Friend lists are client-side encrypted. Only bot messages are plaintext (v1). 3. **Server is semi-trusted** — Server sees metadata (who talks to whom, timing, groups) but cannot read message content. Design all features with this trust boundary in mind. 4. **Federation is transparent** — Users don't need to know which server their peer is on. Key lookup, alias resolution, and message delivery automatically proxy through federation. 5. **Telegram Bot API compatibility** — Bot API follows Telegram conventions (getUpdates, sendMessage, token-in-URL). Bot aliases must end with Bot/bot/_bot. 6. **Auth on writes, open reads** — All POST/write endpoints require bearer tokens. GET/read endpoints are public (needed for key exchange before auth is possible). ## Coding Conventions ### Rust - Workspace crates: protocol (no I/O), server (axum), client (ratatui), wasm (wasm-bindgen), mule (future) - Error handling: `AppResult` in server, `anyhow::Result` in client, `ProtocolError` in protocol - State: `AppState` with `Arc>` for shared state, `Arc` for sled - Auth: `AuthFingerprint` extractor as first handler param for protected routes - Fingerprints: always normalize with `normfp()` (strip non-hex, lowercase) - New routes: create `routes/.rs`, add `pub fn routes() -> Router`, merge in `routes/mod.rs` ### TUI - 7 modules in `tui/`: types, draw, commands, input, file_transfer, network, mod - All ChatLine must include `timestamp: Local::now()` - Add new commands to both the handler chain AND `/help` text - Self-messaging prevention: check `normfp(&peer) != normfp(&self.our_fp)` ### Web (WASM) - JS embedded in `routes/web.rs` as Rust raw string — careful with escaping - Service worker cache version must be bumped on WASM changes (`wz-vN`) - `WasmSession::initiate()` stores X3DH result — `encrypt_key_exchange` must NOT re-initiate ### Federation - Persistent WS between servers, NOT HTTP polling - Presence re-pushed every 10s + on connect - Key lookup: proxy to peer for non-local fingerprints (never cache remote bundles) - Alias resolution: fall back to peer if not found locally - Registration: check peer to enforce global uniqueness ### Bot API - Token stored as `bot:` in tokens tree - Reverse lookup: `bot_fp:` → token - Alias auto-registered on bot creation with `_bot` suffix - Reserved aliases: `*Bot`, `*bot`, `*_bot` blocked for non-bots ## Task Naming `FC-P{phase}-T{task}[-S{subtask}]` See `docs/TASK_PLAN.md` for the full breakdown. ## Testing - Protocol: unit tests in each module's `#[cfg(test)]` - TUI: unit tests for types, input, draw (using ratatui TestBackend) - WASM: can't test natively (js-sys dependency) — test equivalent logic in protocol crate - Server: no integration tests yet (planned) ## Key Files | What | Where | |------|-------| | Wire format | `warzone-protocol/src/message.rs` | | Crypto primitives | `warzone-protocol/src/crypto.rs` | | Server state | `warzone-server/src/state.rs` | | All routes | `warzone-server/src/routes/mod.rs` | | Federation | `warzone-server/src/federation.rs` | | TUI commands | `warzone-client/src/tui/commands.rs` | | Web client | `warzone-server/src/routes/web.rs` | | WASM bridge | `warzone-wasm/src/lib.rs` | | Task plan | `docs/TASK_PLAN.md` | | Bot API docs | `docs/BOT_API.md` | | LLM help ref | `docs/LLM_HELP.md` |