Commit Graph

9 Commits

Author SHA1 Message Date
Siavash Sameni
c37bd7934c v0.0.39: contacts online, message wrap, tab complete, multipart, OTPK
FC-P2-T6: /contacts shows online status (● online, ○ offline)
FC-P6-T6: Long messages word-wrap into multiple lines with aligned indent
FC-P6-T7: Tab completion for 33 slash commands (4 new tests)
FC-P8-T6: sendDocument accepts both JSON and multipart form data
OTPK: Auto-replenish on TUI startup when supply < 3 (generates 10 new)

135 tests passing (was 127)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 17:22:42 +04:00
Siavash Sameni
ea04405199 v0.0.23: ETH display everywhere, local build, web UX fixes
Version: 0.0.22 → 0.0.23, SW cache wz-v3 → wz-v4

TUI:
- Own messages show ETH address (0x...) instead of fingerprint
- Received messages: async ETH cache lookup (resolve on first sight)
- /info shows Identity + Fingerprint
- Welcome message shows ETH address

Web:
- Header shows only ETH address (single element, click to copy)
- Own messages show ETH format
- Received messages resolve sender ETH via /v1/resolve/
- /peer 0x... resolves via /v1/resolve/ endpoint
- Click messages area → focuses text input

Client:
- register_bundle sends eth_address to server
- ETH↔fingerprint mapping stored on registration

Build:
- --local: build on current machine (auto-detect apt/dnf/pacman/brew)
- --local-ship: build locally + deploy to all servers
- --local-clean: build + clean cargo cache

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 08:50:31 +04:00
Siavash Sameni
7fe6de0ba1 Alias TTL renews only on authenticated actions (sending messages)
- Sending a message includes `from` fingerprint
- Server renews alias TTL on send (proves identity: you encrypted it)
- Polling/receiving does NOT renew (anyone can spam messages to you)
- Key registration does NOT renew (separate concern)

This prevents alias keepalive attacks where someone spams a user
just to keep their alias from expiring.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 07:39:15 +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
8dd45b1bfe Normalize fingerprints everywhere: strip colons from URLs and DB keys
Client: strip colons before putting fingerprints in URL paths
(colons in URLs confuse axum path matching).

Server: normalize fingerprints in message routes too.

All fingerprint storage and lookup is now hex-only, case-insensitive.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 22:41:26 +04:00
Siavash Sameni
de118371de Fix bundle lookup: normalize fingerprints, handle 404 gracefully
Server: normalize fingerprints by stripping colons and lowercasing
before storing/looking up in sled. Adds tracing for register/lookup.

Client: check HTTP status before parsing JSON response body.
Shows clear error when user is not registered instead of parse error.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 22:37:41 +04:00
Siavash Sameni
94b845eb5b Fix all compiler warnings across server and client
- Remove unused ServerConfig struct (config via CLI args)
- Remove unused otpks field from Database (not yet needed)
- Wire AppError into message routes with proper error propagation
- Remove unused imports in send.rs (Seed, MessageContent, etc.)
- Suppress dead_code on BundleResponse.fingerprint (needed by serde)

Zero warnings, 17/17 tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 22:16:11 +04:00
Siavash Sameni
82f5061aa1 Wire E2E messaging: send, recv, session persistence, auto-registration
CLI client (warzone):
- `warzone init` now generates pre-key bundle (1 SPK + 10 OTPKs),
  stores secrets in local sled DB, saves bundle for server registration
- `warzone register -s <url>` registers bundle with server
- `warzone send <fp> <msg> -s <url>` full E2E flow:
  - Auto-registers bundle on first use
  - Fetches recipient's pre-key bundle
  - Performs X3DH key exchange (first message) or uses existing session
  - Encrypts with Double Ratchet
  - Sends WireMessage envelope to server
- `warzone recv -s <url>` polls and decrypts:
  - Handles KeyExchange messages (X3DH respond + ratchet init as Bob)
  - Handles Message (decrypt with existing ratchet session)
  - Saves session state after each decrypt

Wire protocol (WireMessage enum):
- KeyExchange variant: sender identity, ephemeral key, OTPK id, ratchet msg
- Message variant: sender fingerprint + ratchet message

Session persistence:
- Ratchet state serialized with bincode, stored in sled (~/.warzone/db)
- Pre-key secrets stored in sled, OTPKs consumed on use
- Sessions keyed by peer fingerprint

Networking (net.rs):
- register_bundle, fetch_bundle, send_message, poll_messages
- JSON API over HTTP, bundles serialized with bincode + base64

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:40:21 +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