Commit Graph

7 Commits

Author SHA1 Message Date
Siavash Sameni
3e0889e5dc v0.0.21: TUI overhaul, WZP call infrastructure, security hardening, federation
TUI:
- Split 1,756-line app.rs monolith into 7 modules (types, draw, commands, input, file_transfer, network, mod)
- Message timestamps [HH:MM], scrolling (PageUp/Down/arrows), connection status dot, unread badge
- /help command, terminal bell on incoming DM, /devices + /kick commands
- 44 unit tests (types, input, draw with TestBackend)

Server — WZP Call Infrastructure (FC-2/3/5/6/7/10):
- Call state management (CallState, CallStatus, active_calls, calls + missed_calls sled trees)
- WS call signal awareness (Offer/Answer/Hangup update state, missed call on offline)
- Group call endpoint (POST /groups/:name/call with SHA-256 room ID, fan-out)
- Presence API (GET /presence/:fp, POST /presence/batch)
- Missed call flush on WS reconnect
- WZP relay config + CORS

Server — Security (FC-P1):
- Auth enforcement middleware (AuthFingerprint extractor on 13 write handlers)
- Session auto-recovery (delete corrupted ratchet, show [session reset])
- WS connection cap (5/fingerprint) + global concurrency limit (200)
- Device management (GET /devices, POST /devices/:id/kick, POST /devices/revoke-all)

Server — Federation:
- Two-server federation via JSON config (--federation flag)
- Periodic presence sync (every 5s, full-state, self-healing)
- Message forwarding via HTTP POST with SHA-256(secret||body) auth
- Graceful degradation (peer down = queue locally)
- deliver_or_queue() replaces push-or-queue in ws.rs + messages.rs

Client — Group Messaging:
- SenderKeyDistribution storage + GroupSenderKey decryption in TUI
- sender_keys sled tree in LocalDb

WASM:
- All 8 WireMessage variants handled (no more "unsupported")
- decrypt_group_message() + create_sender_key_from_distribution() exports
- CallSignal parsing with signal_type mapping

Docs:
- ARCHITECTURE.md rewritten with Mermaid diagrams
- README.md created
- TASK_PLAN.md with FC-P{phase}-T{task} naming
- PROGRESS.md updated to v0.0.21

WZP submodule updated to 6f4e8eb (IAX2 trunking, adaptive quality, metrics, all S-tasks done)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:45:58 +04:00
Siavash Sameni
2ca25fd2bf v0.0.5: WebSocket real-time messaging
Server:
- WS endpoint: /v1/ws/:fingerprint
- Connection registry in AppState (fingerprint → WS senders)
- On connect: flushes queued DB messages, then pushes in real-time
- send_message: pushes to WS if connected, falls back to DB queue
- Auto-cleanup on disconnect
- WS accepts both binary and JSON text frames for sending

Web client:
- Replaces 2-second HTTP polling with persistent WebSocket
- Auto-reconnects on disconnect (3-second backoff)
- Sends via WS when connected, HTTP fallback
- Messages arrive instantly (no polling delay)
- "Real-time connection established" shown on connect

HTTP polling still works:
- CLI recv command uses HTTP (unchanged)
- Web falls back to HTTP if WS fails
- Mules/scripts can still use HTTP API

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 09:41:50 +04:00
Siavash Sameni
cfb227a93d Server auth (challenge-response) + OTP key replenishment
Authentication:
- POST /v1/auth/challenge {fingerprint} → {challenge, expires_at}
- POST /v1/auth/verify {fingerprint, challenge, signature} → {token}
- Client signs challenge with Ed25519 identity key
- Server verifies against stored public key
- Returns bearer token valid for 7 days
- Web clients get token without sig verify (Phase 2: WASM)
- validate_token() helper for protecting endpoints

OTP Key Replenishment:
- GET /v1/keys/:fp/otpk-count → {otpk_count}
- POST /v1/keys/replenish {fingerprint, otpks: [{id, public_key}]}
- OTPKs stored individually: otpk:<fp>:<id> → public_key
- Returns total count after replenishment

Phase 1 complete:
- [x] Seed-based identity + BIP39
- [x] X3DH + Double Ratchet (forward secrecy)
- [x] Pre-key bundles
- [x] Server (keys, messages, groups, aliases, auth)
- [x] CLI TUI + Web client
- [x] Aliases with TTL + recovery
- [x] Seed encryption (Argon2id + ChaCha20)
- [x] Server auth (challenge-response + tokens)
- [x] OTP key replenishment

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 07:55:02 +04:00
Siavash Sameni
29c059cebf Aliases: human-readable names mapped to fingerprints
Server:
- POST /v1/alias/register — claim an alias (one per fingerprint)
- GET /v1/alias/resolve/:name — alias → fingerprint
- GET /v1/alias/whois/:fingerprint — fingerprint → alias (reverse)
- GET /v1/alias/list — list all aliases
- Bidirectional mapping in sled (a:name→fp, fp:fp→name)
- One alias per person, re-registering replaces old alias

Web client:
- /alias <name> — register your alias
- /aliases — list all registered aliases
- /info — now shows alias alongside fingerprint
- Peer input accepts @alias (resolved before sending)
- Received messages show @alias instead of fingerprint
- DM: paste @alias or fingerprint in peer input

CLI TUI:
- /alias <name> — register alias
- /aliases — list all aliases
- /peer @alias — resolves alias to fingerprint
- Alias resolution displayed in system messages

Addressing model:
- @manwe (local) → server resolves → fingerprint
- @manwe.b1.example.com (federated) → DNS resolve (Phase 3)
- Raw fingerprint → always works, no resolution

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 07:01:35 +04:00
Siavash Sameni
f3e78c6cff Group chat with E2E encryption for both web and CLI clients
Server:
- POST /v1/groups/create — create named group
- POST /v1/groups/:name/join — join group
- GET /v1/groups/:name — get group info + member list
- GET /v1/groups — list all groups
- POST /v1/groups/:name/send — fan-out encrypted messages to members
- Groups stored in sled, members tracked by fingerprint

Web client:
- /gcreate <name> — create group
- /gjoin <name> — join group
- /g <name> — switch to group chat mode
- /glist — list all groups
- /dm — switch back to DM mode
- Group messages encrypted per-member (ECDH + AES-GCM for each)
- Group tag shown on received messages: "sender [groupname]"

CLI TUI client:
- Same commands: /gcreate, /gjoin, /g, /glist, /dm
- Group messages encrypted per-member (X3DH + Double Ratchet for each)
- Automatic X3DH key exchange with new group members on first message
- Sessions established and persisted per-member

Architecture:
- Client-side fan-out encryption: message encrypted N times (once per member)
- Server stores one copy per recipient in their message queue
- Reuses existing 1:1 encryption — no new crypto primitives needed
- Works for groups ≤ 50 members (per DESIGN.md)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 23:13:16 +04:00
Siavash Sameni
7451ad69bc Fix X3DH + add web client served by warzone-server
X3DH fix:
- Added identity_encryption_key (X25519) to PreKeyBundle
- initiate() and respond() now use correct DH operations per Signal spec:
  DH1=IK_a*SPK_b, DH2=EK_a*IK_b, DH3=EK_a*SPK_b, DH4=EK_a*OPK_b
- All 17 tests pass including x3dh_shared_secret_matches

Web client (served at /):
- Identity generation with seed (stored in localStorage)
- Recovery from hex-encoded seed
- Auto-load saved identity on page load
- Fingerprint display (same format as CLI: xxxx:xxxx:xxxx:xxxx)
- Key registration with server via /v1/keys/register
- Chat UI with message polling (5s interval)
- Commands: /help, /info, /seed
- Dark theme matching warzone aesthetic

Both clients (CLI + Web) now exist:
- CLI: warzone init, warzone info, warzone recover
- Web: http://localhost:7700/ (served by warzone-server)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:32:46 +04:00
Siavash Sameni
651396fa13 Scaffold Rust workspace: warzone-protocol, server, client, mule
4 crates, all compile. 16/17 tests pass.

warzone-protocol (core crypto):
- Seed-based identity (Ed25519 + X25519 from 32-byte seed via HKDF)
- BIP39 mnemonic encode/decode (24 words)
- Fingerprint type (SHA-256 truncated, displayed as xxxx:xxxx:xxxx:xxxx)
- ChaCha20-Poly1305 AEAD encrypt/decrypt with random nonce
- HKDF-SHA256 key derivation
- Pre-key bundle generation with Ed25519 signatures
- X3DH key exchange (simplified, needs X25519 identity key in bundle)
- Double Ratchet: full implementation with DH ratchet, chain ratchet,
  out-of-order message handling via skipped keys cache
- Message format (WarzoneMessage envelope + RatchetHeader)
- Session type with ratchet state
- Storage trait definitions (PreKeyStore, SessionStore, MessageQueue)

warzone-server (axum):
- sled database (keys, messages, one-time pre-keys)
- Routes: /v1/health, /v1/keys/register, /v1/keys/{fp},
  /v1/messages/send, /v1/messages/poll/{fp}, /v1/messages/{id}/ack

warzone-client (CLI):
- `warzone init` — generate seed, show mnemonic, save to ~/.warzone/
- `warzone recover <words>` — restore from mnemonic
- `warzone info` — show fingerprint and keys
- Seed storage at ~/.warzone/identity.seed (600 perms)
- Stubs for send, recv, chat commands

warzone-mule: Phase 4 placeholder

Known issue: X3DH test fails (initiate/respond use different DH ops
due to missing X25519 identity key in bundle). Fix in next step.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:27:48 +04:00