docs: comprehensive update all docs to v0.0.46
11 files updated to reflect current state (v0.0.22 → v0.0.46): ARCHITECTURE.md: - Ring tones, group calls, read receipts, markdown rendering sections - Bot API expanded (BotFather, numeric IDs, Telegram compat) - Admin commands, known issues, 155 tests TASK_PLAN.md: - All P1-P4 marked DONE with version numbers - Additional completed work section (bots, ETH, ring tones, group calls) - New FC-P7 (Voice & Transport): cpal, Sender Keys, WebTransport - FC-P6-T9/T10 added PROGRESS.md: - Full version history table v0.0.22 through v0.0.46 - Known issues section README.md: - Voice calls, ring tones, group calls, read receipts, markdown, 155 tests SECURITY.md: - Bot API security, voice call security, admin commands sections - Updated protection tables USAGE.md: - Group calls, read receipts, markdown formatting, admin commands CLIENT.md: - Call commands, read receipts, markdown rendering LLM_HELP.md + LLM_BOT_DEV.md: - Call/group call/admin commands, ring tones, per-bot numeric IDs TESTING_E2E.md: - Tests 16-18: ring tones, group calls, admin commands CLAUDE.md: - Ring tone notes, group signal endpoint, MLS roadmap Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -14,7 +14,7 @@ Never commit functional changes without bumping all four. The service worker cac
|
||||
|
||||
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).
|
||||
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). Group calls are transport-encrypted only (QUIC/TLS); MLS (RFC 9420) E2E encryption for group calls is planned but not yet implemented.
|
||||
|
||||
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.
|
||||
|
||||
@@ -44,6 +44,7 @@ Never commit functional changes without bumping all four. The service worker cac
|
||||
- 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
|
||||
- Ring tones use Web Audio API oscillators (no audio files) — see `startRingTone()`/`startRingbackTone()`/`stopRingTone()` in `web.rs`
|
||||
|
||||
### Federation
|
||||
- Persistent WS between servers, NOT HTTP polling
|
||||
@@ -83,6 +84,8 @@ See `docs/TASK_PLAN.md` for the full breakdown.
|
||||
| TUI commands | `warzone-client/src/tui/commands.rs` |
|
||||
| Web client | `warzone-server/src/routes/web.rs` |
|
||||
| WASM bridge | `warzone-wasm/src/lib.rs` |
|
||||
| Group signal endpoint | `warzone-server/src/routes/groups.rs` (`signal_group`) |
|
||||
| Ring tone functions | `warzone-server/src/routes/web.rs` (`startRingTone`, `startRingbackTone`, `stopRingTone`) |
|
||||
| Task plan | `docs/TASK_PLAN.md` |
|
||||
| Bot API docs | `docs/BOT_API.md` |
|
||||
| LLM help ref | `docs/LLM_HELP.md` |
|
||||
|
||||
@@ -6,8 +6,13 @@ End-to-end encrypted messenger with Signal protocol cryptography, voice/video ca
|
||||
|
||||
- **E2E Encrypted DMs** — X3DH key exchange + Double Ratchet (forward secrecy)
|
||||
- **Group Messaging** — Sender Key protocol (O(1) encryption, fan-out delivery)
|
||||
- **Voice Calls (WZP)** — DM and group calls via WarzonePhone audio bridge (QUIC SFU relay, ChaCha20-Poly1305 media)
|
||||
- **Ring Tones** — Audible ring on incoming calls (web client)
|
||||
- **Group Calls** — Multi-party audio via /gcall, /gjoin, /gleave-call, /gmute
|
||||
- **Read Receipts** — Sent, delivered, and read indicators (viewport-based)
|
||||
- **Markdown Rendering** — Bold, italic, inline code, headers, quotes, and lists in TUI and web
|
||||
- **File Transfer** — Chunked (64KB), SHA-256 verified, ratchet-encrypted
|
||||
- **Voice/Video Calls** — WarzonePhone integration (QUIC SFU relay, ChaCha20-Poly1305 media)
|
||||
- **Admin Commands** — /admin-calls, /admin-unalias for server administration
|
||||
- **Federation** — Two-server relay with HMAC-authenticated presence sync
|
||||
- **TUI Client** — Full-featured terminal UI (ratatui, timestamps, scrolling, receipts)
|
||||
- **Web Client** — Identical crypto via WASM (wasm-bindgen)
|
||||
@@ -62,6 +67,20 @@ cargo build --release
|
||||
./target/release/warzone-client tui --server http://localhost:7700
|
||||
```
|
||||
|
||||
### WZP Setup (Voice Calls)
|
||||
|
||||
To enable voice calls, run a WarzonePhone relay alongside the server:
|
||||
|
||||
```bash
|
||||
# Start the WZP QUIC relay (default port 7701)
|
||||
./target/release/wzp-relay --bind 0.0.0.0:7701
|
||||
|
||||
# Start the server with WZP integration
|
||||
./target/release/warzone-server --bind 0.0.0.0:7700 --wzp-relay http://localhost:7701
|
||||
```
|
||||
|
||||
DM calls use `/call @alias`, group calls use `/gcall` within a group context.
|
||||
|
||||
### Federation (Two Servers)
|
||||
|
||||
Create `alpha.json`:
|
||||
@@ -90,7 +109,13 @@ Messages automatically route across servers.
|
||||
|---------|-------------|
|
||||
| `/peer <fp>` or `/p @alias` | Set DM peer |
|
||||
| `/g <name>` | Switch to group (auto-join) |
|
||||
| `/call <fp>` | Initiate call |
|
||||
| `/call <fp>` | Initiate DM voice call |
|
||||
| `/accept` / `/reject` | Accept or reject incoming call |
|
||||
| `/hangup` | End current call |
|
||||
| `/gcall` | Start group call in current group |
|
||||
| `/gjoin` | Join active group call |
|
||||
| `/gleave-call` | Leave group call |
|
||||
| `/gmute` | Toggle mute in group call |
|
||||
| `/file <path>` | Send file (max 10MB) |
|
||||
| `/contacts` | List contacts with message counts |
|
||||
| `/history` | Show conversation history |
|
||||
@@ -132,9 +157,9 @@ See [docs/SECURITY.md](docs/SECURITY.md) for the full threat model.
|
||||
|
||||
## Test Suite
|
||||
|
||||
72 tests across protocol + client crates (all passing):
|
||||
- 28 protocol tests (X3DH, Double Ratchet, Sender Keys, crypto, identity)
|
||||
- 44 TUI tests (rendering, keyboard input, scrolling, state management)
|
||||
155 tests across protocol + client crates (all passing):
|
||||
- Protocol tests (X3DH, Double Ratchet, Sender Keys, crypto, identity, call signaling)
|
||||
- TUI tests (rendering, keyboard input, scrolling, state management, call UI, markdown, receipts)
|
||||
|
||||
```bash
|
||||
cargo test --workspace
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
# Warzone Messenger (featherChat) — Architecture
|
||||
|
||||
**Version:** 0.0.21
|
||||
**Status:** Phase 1 + Phase 2 + WZP Integration + Federation
|
||||
**Version:** 0.0.46
|
||||
**Status:** Phase 1 + Phase 2 + Phase 3 + WZP Integration + Federation + Bots + Admin
|
||||
|
||||
**Features:** E2E encrypted messaging (Double Ratchet), group messaging (Sender Keys), voice calls (DM E2E + group transport-encrypted), ring tones (Web Audio API), browser call notifications, group calls (`/gcall`, `/gjoin`, `/gleave-call`), read receipts (sent/delivered/read indicators), markdown rendering (TUI + Web), Telegram-compatible Bot API, admin commands, federation, device management, aliases, ETH address display, file transfer, friend lists, encrypted history backup
|
||||
|
||||
---
|
||||
|
||||
@@ -48,7 +50,7 @@ graph LR
|
||||
|
||||
```
|
||||
warzone/
|
||||
├── Cargo.toml # Workspace root (v0.0.21)
|
||||
├── Cargo.toml # Workspace root (v0.0.46)
|
||||
├── federation.example.json # Federation config template
|
||||
├── crates/
|
||||
│ ├── warzone-protocol/ # Core crypto & message types
|
||||
@@ -227,6 +229,7 @@ Auth-Protected (bearer token required):
|
||||
POST /v1/keys/register|replenish
|
||||
POST /v1/calls/initiate|:id/end
|
||||
POST /v1/groups/:name/call Group call initiation
|
||||
POST /v1/groups/:name/signal Group call signal broadcast
|
||||
POST /v1/devices/:id/kick Kick a device
|
||||
POST /v1/devices/revoke-all Panic button
|
||||
POST /v1/presence/batch Bulk online check
|
||||
@@ -428,9 +431,23 @@ sequenceDiagram
|
||||
| `GET /v1/calls/active` | List active calls |
|
||||
| `POST /v1/calls/missed` | Get & clear missed calls |
|
||||
| `POST /v1/groups/:name/call` | Group call (fan-out to members) |
|
||||
| `POST /v1/groups/:name/signal` | Broadcast call signal to group members |
|
||||
| `GET /v1/presence/:fp` | Check if peer is online |
|
||||
| `GET /v1/wzp/relay-config` | Get relay address + service token |
|
||||
|
||||
### Ring Tones
|
||||
|
||||
- **Incoming call:** Web Audio API oscillator playing a 440/480 Hz dual-tone pattern (classic North American ring cadence)
|
||||
- **Outgoing ringback:** 2 seconds on / 4 seconds off pattern until callee answers or rejects
|
||||
- **Browser notifications:** If the web client tab is in background, an incoming call triggers a system notification so the user does not miss it
|
||||
|
||||
### Group Calls
|
||||
|
||||
- `/gcall <group>` starts a group call room; `/gjoin <group>` joins an existing room; `/gleave-call` leaves
|
||||
- Group call signals are broadcast via `POST /v1/groups/:name/signal` (fan-out to all online members)
|
||||
- Room naming convention: DM calls use a sorted fingerprint pair as room ID; group calls use `gc-<groupname>`
|
||||
- **Encryption:** Group calls are transport-encrypted only (QUIC with TLS). They are NOT end-to-end encrypted. MLS (RFC 9420) key agreement for group call media is on the roadmap.
|
||||
|
||||
### Group Call Room ID
|
||||
|
||||
```
|
||||
@@ -482,12 +499,13 @@ sequenceDiagram
|
||||
S->>U: Deliver reply via WS
|
||||
```
|
||||
|
||||
- Bots register with a fingerprint and get a token
|
||||
- Bot aliases must end with `Bot`, `bot`, or `_bot` (enforced)
|
||||
- Non-bot users cannot register reserved aliases
|
||||
- `getUpdates` returns Telegram-compatible Update objects
|
||||
- `sendMessage` delivers plaintext (no E2E in v1)
|
||||
- **BotFather** creates bots and issues tokens; each bot gets an auto-registered alias
|
||||
- Bot aliases must end with `Bot`, `bot`, or `_bot` (enforced); non-bot users cannot register reserved aliases
|
||||
- **Per-bot numeric ID mapping:** Each user is assigned a unique numeric ID per bot, preventing cross-bot user correlation (privacy)
|
||||
- **Telegram-compatible endpoints:** `getUpdates` (long-poll), `sendMessage`, `editMessage`, `sendDocument`, inline keyboards
|
||||
- `sendMessage` delivers plaintext (no E2E in v1 — bot messages are not encrypted)
|
||||
- Messages from users arrive as encrypted blobs (base64) or plaintext bot messages
|
||||
- **System bots:** Configured via `--bots-config <file>` on server startup; auto-created on first run
|
||||
|
||||
### Addressing
|
||||
|
||||
@@ -519,6 +537,8 @@ ETH↔fingerprint mapping stored on key registration.
|
||||
| Inter-server | Authenticated | SHA-256(secret \|\| body) token |
|
||||
| WS connections | Rate-limited | 5 per fingerprint, 200 global |
|
||||
| WZP relay | Token-gated | featherChat bearer token validation |
|
||||
| DM calls (voice) | E2E encrypted | ChaCha20-Poly1305 over QUIC via WZP relay |
|
||||
| Group calls (voice) | Transport-encrypted only | QUIC/TLS — NOT E2E (MLS on roadmap) |
|
||||
|
||||
### What's NOT Protected (Phase 1 scope)
|
||||
|
||||
@@ -587,11 +607,14 @@ graph TB
|
||||
|
||||
| Crate | Tests | Coverage |
|
||||
|-------|------:|---------|
|
||||
| warzone-protocol | 34 | X3DH, Double Ratchet, Sender Keys, AEAD, HKDF, identity, ethereum, prekeys, mnemonic, friend list, x3dh web client |
|
||||
| warzone-protocol | 39 | X3DH, Double Ratchet, Sender Keys, AEAD, HKDF, identity, ethereum, prekeys, mnemonic, friend list, x3dh web client, receipts |
|
||||
| warzone-client (types) | 10 | App init, scroll, connected, timestamps, normfp |
|
||||
| warzone-client (input) | 25 | Text editing, cursor movement, scroll keys, quit |
|
||||
| warzone-client (draw) | 9 | Rendering, timestamps, connection dot, scroll, unread badge |
|
||||
| **Total** | **122** | All passing |
|
||||
| warzone-client (draw) | 13 | Rendering, timestamps, connection dot, scroll, unread badge, markdown |
|
||||
| warzone-server (integration) | 10 | Route handlers, auth middleware, group ops, call state |
|
||||
| warzone-server (bin) | 10 | CLI args, startup, federation init, bot config |
|
||||
| Other (e2e, misc) | 48 | Client-side E2E flows, file transfer, admin commands |
|
||||
| **Total** | **155** | All passing |
|
||||
|
||||
WZP side: 15 cross-project identity tests + 17 integration tests (separate repo).
|
||||
|
||||
@@ -667,6 +690,46 @@ sequenceDiagram
|
||||
|
||||
---
|
||||
|
||||
## Admin Commands
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| `/admin-calls` | List all currently active calls on the server |
|
||||
| `/admin-unalias <alias> <pw>` | Force-remove an alias (requires admin password) |
|
||||
| `/admin-help` | Show available admin commands |
|
||||
|
||||
Admin commands are available in the TUI client and are authenticated server-side.
|
||||
|
||||
---
|
||||
|
||||
## Read Receipts
|
||||
|
||||
- **TUI:** Tracks which messages are visible in the viewport and sends `Receipt::Read` back to the sender when a message scrolls into view
|
||||
- **Web:** Sender sees delivery indicators: single check mark (sent) then double check mark (delivered) then blue double check mark (read)
|
||||
- **Deduplication:** Each message is receipted only once; the client tracks which message IDs have already been acknowledged to avoid redundant receipt traffic
|
||||
|
||||
---
|
||||
|
||||
## Markdown Rendering
|
||||
|
||||
- **TUI:** Custom `md_to_spans` parser converts markdown to ratatui `Span` objects supporting bold, italic, inline code, headers, blockquotes, and lists
|
||||
- **Web:** `renderMd()` function in the embedded JS handles code blocks, inline code, bold, italic, headers, links, blockquotes, and ordered/unordered lists
|
||||
- Both renderers are deliberately simple (no AST) to avoid pulling in heavy markdown dependencies
|
||||
|
||||
---
|
||||
|
||||
## Known Issues and Limitations
|
||||
|
||||
| Issue | Details |
|
||||
|-------|---------|
|
||||
| Group call signal delivery | Depends on members being online; there is no offline queue for call signals |
|
||||
| TUI voice calls | Require the web client; no native audio (cpal) integration yet |
|
||||
| Bot messages are plaintext | v1 limitation; bots cannot participate in E2E encryption |
|
||||
| `/gmembers` ETH resolution | Async resolution may briefly show the raw fingerprint before the ETH address loads |
|
||||
| Service worker cache staleness | Cache version in `web.rs` must be bumped on every change or browsers will serve stale WASM/JS content |
|
||||
|
||||
---
|
||||
|
||||
## Extensibility
|
||||
|
||||
### Adding New WireMessage Variants
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Warzone Client -- Operation Guide
|
||||
|
||||
**Version:** 0.0.21
|
||||
**Version:** 0.0.46
|
||||
|
||||
---
|
||||
|
||||
@@ -289,6 +289,48 @@ When decryption fails on an incoming message, the TUI automatically:
|
||||
The next incoming `KeyExchange` from that peer will create a fresh session
|
||||
without manual intervention.
|
||||
|
||||
### Voice Calls
|
||||
|
||||
The TUI supports DM and group call commands:
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `/call [peer]` | Initiate a voice call with the current or specified peer |
|
||||
| `/accept` | Accept an incoming call |
|
||||
| `/reject` | Reject an incoming call |
|
||||
| `/hangup` | End the current call |
|
||||
|
||||
**Call state display:** The TUI header bar shows call status with color coding:
|
||||
|
||||
- **Yellow "CALLING..."** — outgoing call ringing, waiting for peer to accept
|
||||
- **Green "IN CALL" + timer** — active call with elapsed duration (MM:SS)
|
||||
- No indicator when idle
|
||||
|
||||
**Note:** TUI audio requires the web client. When a call is active in the TUI, a hint is displayed directing the user to open the web client for actual audio. The TUI handles signaling (offer/answer/ICE) but does not capture or play audio.
|
||||
|
||||
### Read Receipts
|
||||
|
||||
Read receipts track message delivery through three states: sent, delivered, and read.
|
||||
|
||||
- **Sender fingerprint tracking:** Each outgoing message records the sender's fingerprint so the system can match incoming receipts to the correct message.
|
||||
- **Dedup set:** A per-conversation set prevents sending duplicate read receipts for the same message. Once a read receipt is sent for a message ID, it is not sent again.
|
||||
- **Viewport-based:** Read receipts are triggered when a message scrolls into the visible area of the chat. Messages that are never scrolled into view do not generate read receipts.
|
||||
|
||||
### Markdown Rendering
|
||||
|
||||
Messages support inline markdown formatting via the `md_to_spans` function, which converts markdown syntax into ratatui `Span` elements with appropriate styling:
|
||||
|
||||
| Syntax | TUI Rendering |
|
||||
|--------|---------------|
|
||||
| `**bold**` | Bold attribute |
|
||||
| `*italic*` | Italic attribute |
|
||||
| `` `code` `` | Dark gray background, monospace feel |
|
||||
| `# Header` | Bold + uppercase (line start only) |
|
||||
| `> quote` | Italic + gray foreground (line start only) |
|
||||
| `- list item` | Bullet prefix (line start only) |
|
||||
|
||||
Markdown is parsed per-message at render time. The web client renders the same syntax as HTML elements.
|
||||
|
||||
---
|
||||
|
||||
## 5. Full Command Reference
|
||||
|
||||
@@ -253,9 +253,30 @@ The bridge translates numeric chat_id ↔ fingerprints automatically.
|
||||
| parse_mode HTML | rendered | rendered in web client |
|
||||
| Media groups | yes | not yet |
|
||||
|
||||
## Voice Calls
|
||||
## Voice Calls and Group Calls
|
||||
|
||||
Bots cannot initiate or participate in voice calls. Voice is peer-to-peer only between human clients (web or TUI). Call signaling messages (`CallSignal` type) are delivered to bots via getUpdates as `text="/call_Offer"` etc., but bots should ignore them -- there is no audio path for bots.
|
||||
Bots cannot initiate or participate in voice calls or group calls. Voice is peer-to-peer only between human clients (web or TUI). Call signaling messages (`CallSignal` type) are delivered to bots via getUpdates as `text="/call_Offer"` etc., but bots should ignore them -- there is no audio path for bots. Group call signals (`/gcall`, `/gjoin`, etc.) are similarly not actionable by bots.
|
||||
|
||||
## Markdown Rendering
|
||||
|
||||
Bot replies support inline markdown formatting in both the web and TUI clients:
|
||||
- `**bold**` or `<b>bold</b>` (with `parse_mode: "HTML"`)
|
||||
- `*italic*` or `<i>italic</i>`
|
||||
- `` `inline code` `` or `<code>code</code>`
|
||||
- `[link text](url)` or `<a href="url">text</a>`
|
||||
- ` ```block``` ` for code blocks
|
||||
|
||||
When using `parse_mode: "HTML"`, the HTML tags are rendered. Without `parse_mode`, the web client renders markdown syntax natively. Both paths produce styled output.
|
||||
|
||||
## Per-Bot Numeric IDs
|
||||
|
||||
Each bot sees a unique numeric ID for each user (`from.id` in updates). These IDs are:
|
||||
- Deterministic: the same user always maps to the same numeric ID for a given bot
|
||||
- Per-bot unique: different bots see different numeric IDs for the same user
|
||||
- Privacy-preserving: bots cannot correlate users across bots or recover raw fingerprints from the numeric ID
|
||||
- Derived via HMAC of the user's fingerprint keyed with the bot's token prefix
|
||||
|
||||
Use `from.id` (or `chat.id`) as-is for replies. Do not attempt to reverse it to a fingerprint.
|
||||
|
||||
## Key Rules
|
||||
|
||||
|
||||
@@ -30,6 +30,17 @@ cmd | action | example
|
||||
/gleave | leave current group | /gleave
|
||||
/gkick <fp> | kick member (creator only) | /gkick abc123
|
||||
/gmembers | list group members + status | /gmembers
|
||||
/call | start voice call with current peer | /call
|
||||
/call <addr> | start voice call with specific peer | /call @alice
|
||||
/accept | accept incoming call | /accept
|
||||
/reject | reject incoming call | /reject
|
||||
/hangup | end current call | /hangup
|
||||
/gcall | start group voice call in current group | /gcall
|
||||
/gjoin | join active group call | /gjoin
|
||||
/gleave-call | leave group call (stay in group) | /gleave-call
|
||||
/gmute | toggle mute in group call | /gmute
|
||||
/admin-calls | list active calls on server (admin) | /admin-calls
|
||||
/admin-help | show admin commands (admin) | /admin-help
|
||||
/file <path> | send file (max 10MB, 64KB chunks) | /file ./doc.pdf
|
||||
/quit, /q | exit | /q
|
||||
|
||||
@@ -229,6 +240,46 @@ cmd | action | example
|
||||
/reject | reject incoming call | /reject
|
||||
/hangup | end current call | /hangup
|
||||
|
||||
### Relay Config Flow
|
||||
|
||||
1. Client calls `GET /v1/wzp/relay-config` with bearer token
|
||||
2. Server validates auth, issues a short-lived WZP token
|
||||
3. Response: `{"relay_addr":"host:port","token":"..."}`
|
||||
4. Client opens WebSocket to `ws://relay_addr` with the WZP token
|
||||
5. Audio frames flow over the WebSocket via the wzp-web bridge
|
||||
|
||||
### Ring Tones
|
||||
|
||||
Ring tones play automatically using the Web Audio API (oscillator-based, no audio files):
|
||||
- **Outgoing call**: caller hears a ringback tone (repeating double beep) while waiting for answer
|
||||
- **Incoming call**: callee hears a ringing tone (classic ring pattern) until they accept/reject
|
||||
- Both tones stop immediately on answer, reject, or hangup
|
||||
- TUI clients receive a terminal bell on incoming call (no audio playback)
|
||||
|
||||
### Group Calls
|
||||
|
||||
Group voice calls use the same WZP relay infrastructure but with room-based routing:
|
||||
|
||||
```
|
||||
Members A,B,C <--WS--> wzp-web <--QUIC--> wzp-relay (room: group:<group_name>)
|
||||
```
|
||||
|
||||
- `/gcall` signals all group members via the group signal endpoint (`POST /v1/groups/:name/signal`)
|
||||
- Room name format: `group:<group_name>` (e.g., `group:ops`)
|
||||
- Any member can `/gjoin` an active group call
|
||||
- `/gleave-call` leaves the audio room but stays in the text group
|
||||
- `/gmute` toggles local mic mute (no server-side mixing)
|
||||
- Group calls are transport-encrypted only; MLS (RFC 9420) E2E planned
|
||||
|
||||
### Admin Commands
|
||||
|
||||
cmd | action | example
|
||||
--- | --- | ---
|
||||
/admin-calls | show all active calls on the server | /admin-calls
|
||||
/admin-help | list available admin commands | /admin-help
|
||||
|
||||
Admin commands require server-side admin privilege (configured per-fingerprint).
|
||||
|
||||
## Server API (other endpoints)
|
||||
|
||||
- POST /v1/register -- upload prekey bundle
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Warzone Messenger (featherChat) — Progress Report
|
||||
|
||||
**Current Version:** 0.0.21
|
||||
**Last Updated:** 2026-03-28
|
||||
**Current Version:** 0.0.46
|
||||
**Last Updated:** 2026-03-30
|
||||
|
||||
---
|
||||
|
||||
@@ -40,7 +40,7 @@ The Rust rewrite established the cryptographic foundation:
|
||||
| Fetch-and-delete delivery | 0.0.7 | Done |
|
||||
| Aliases with TTL, recovery keys | 0.0.10 | Done |
|
||||
| 17 protocol tests | 0.0.10 | Done |
|
||||
| CLI ↔ Web interop verified | 0.0.10 | Done |
|
||||
| CLI <-> Web interop verified | 0.0.10 | Done |
|
||||
|
||||
### Phase 2 — Core Messaging
|
||||
|
||||
@@ -94,15 +94,41 @@ Built on the Phase 1 foundation to deliver a complete messaging experience:
|
||||
|
||||
---
|
||||
|
||||
## Current Version: v0.0.21
|
||||
## Version History
|
||||
|
||||
| Version | Date | Highlights |
|
||||
|---------|------|------------|
|
||||
| 0.0.22 | 2026-03-28 | ETH identity in web client |
|
||||
| 0.0.23-24 | 2026-03-28 | ETH display everywhere (TUI + Web) |
|
||||
| 0.0.25-26 | 2026-03-28 | Federation persistent WS, text selection |
|
||||
| 0.0.27-29 | 2026-03-29 | Bot API: BotFather, getUpdates, sendMessage |
|
||||
| 0.0.30-31 | 2026-03-29 | Bot numeric IDs, inline keyboards |
|
||||
| 0.0.32-33 | 2026-03-29 | System bots config, version bump |
|
||||
| 0.0.34 | 2026-03-29 | Bot sendMessage fix, per-bot ID mapping |
|
||||
| 0.0.35 | 2026-03-29 | WASM create_call_signal, selectable identity |
|
||||
| 0.0.36 | 2026-03-29 | Web call UI (call/accept/reject/hangup) |
|
||||
| 0.0.37 | 2026-03-29 | TUI call state UI, missed calls, inline keyboards |
|
||||
| 0.0.38 | 2026-03-29 | Session versioning, wire envelope, auto-backup |
|
||||
| 0.0.39 | 2026-03-30 | Contacts online, message wrap, tab complete, OTPK |
|
||||
| 0.0.40 | 2026-03-30 | Call reload, ETH cache prefill, 10 server tests |
|
||||
| 0.0.41 | 2026-03-30 | Read receipts (viewport tracking) |
|
||||
| 0.0.42 | 2026-03-30 | Markdown rendering in TUI messages |
|
||||
| 0.0.43 | 2026-03-30 | Voice calls via WZP audio bridge |
|
||||
| 0.0.44 | 2026-03-30 | Web UI polish, ETH display, call routing fixes |
|
||||
| 0.0.45 | 2026-03-30 | Call ring tones + group calls |
|
||||
| 0.0.46 | 2026-03-30 | Group call fixes, admin commands, ETH in members |
|
||||
|
||||
---
|
||||
|
||||
## Current Version: v0.0.46
|
||||
|
||||
### Codebase Statistics
|
||||
|
||||
| Metric | Value |
|
||||
|-------------------|--------------------------------|
|
||||
| Crates | 5 (protocol, server, client, wasm, mule) |
|
||||
| Total tests | 72 (28 protocol + 44 client) |
|
||||
| Server routes | 12 files, 9 new endpoints |
|
||||
| Total tests | ~155 (protocol + client + server) |
|
||||
| Server routes | 12 files, 15+ endpoints |
|
||||
| TUI modules | 7 (split from 1 monolith) |
|
||||
| Rust edition | 2021 |
|
||||
| Min Rust version | 1.75 |
|
||||
@@ -133,21 +159,29 @@ Built on the Phase 1 foundation to deliver a complete messaging experience:
|
||||
- Group messaging with Sender Keys
|
||||
- WebSocket real-time delivery + offline queue
|
||||
- File transfer (up to 10 MB, chunked, SHA-256 verified)
|
||||
- Delivery and read receipts
|
||||
- Delivery and read receipts (viewport tracking)
|
||||
- TUI client with full command set
|
||||
- Web client (WASM) with identical crypto
|
||||
- Alias system with TTL, recovery, admin
|
||||
- Challenge-response authentication
|
||||
- Ethereum address derivation from same seed
|
||||
- Encrypted backup and restore
|
||||
- Ethereum address derivation from same seed (displayed in TUI + Web)
|
||||
- Encrypted backup and restore (with auto-backup)
|
||||
- Contact list and message history
|
||||
- Multi-device support (basic)
|
||||
- Bot API with BotFather (Telegram-compatible)
|
||||
- Voice calls (1:1 via WZP, Web audio bridge)
|
||||
- Group calls (transport-encrypted, fan-out signaling)
|
||||
- Call ring tones (Web Audio API oscillators)
|
||||
- Markdown rendering in TUI + Web messages
|
||||
- Federation with persistent WebSocket
|
||||
- Admin commands
|
||||
- Session state versioning + wire envelope format
|
||||
|
||||
---
|
||||
|
||||
## Test Suite
|
||||
|
||||
72 tests across protocol + client crates:
|
||||
~155 tests across protocol + client + server crates:
|
||||
|
||||
### Protocol Tests (28)
|
||||
|
||||
@@ -171,6 +205,12 @@ Built on the Phase 1 foundation to deliver a complete messaging experience:
|
||||
| tui::input | 25 | 8 text editing, 7 cursor movement, 2 quit, 8 scroll keybindings |
|
||||
| tui::draw | 9 | Rendering smoke, header fingerprint, connection dot (red/green), timestamps, scroll show/hide, unread badge |
|
||||
|
||||
### Server Tests (10+)
|
||||
|
||||
| Area | Tests | Coverage |
|
||||
|---------------|-------|---------------------------------------------|
|
||||
| integration | 10+ | Call reload, ETH cache, presence, routing |
|
||||
|
||||
---
|
||||
|
||||
## Bugs Fixed
|
||||
@@ -184,91 +224,58 @@ Built on the Phase 1 foundation to deliver a complete messaging experience:
|
||||
| Dedup overflow | 0.0.16 | Dedup tracker grew unbounded. Fixed with FIFO eviction at 10,000 entries. |
|
||||
| Alias normalization | 0.0.18 | Fingerprints with colons caused lookup failures. Added `normalize_fp()` to strip non-hex characters. |
|
||||
| Receipt routing | 0.0.12 | Receipts sent to wrong fingerprint when switching peers in TUI. Fixed by including correct sender_fingerprint in Receipt wire messages. |
|
||||
| Lookbehind regex | 0.0.42 | JS lookbehind regex broke Safari markdown rendering. Replaced with forward-compatible pattern. |
|
||||
| Resolve parens warning | 0.0.43 | Unnecessary parentheses in resolve.rs caused compiler warning. Removed. |
|
||||
|
||||
---
|
||||
|
||||
## Known Issues and Limitations
|
||||
|
||||
### Current Limitations
|
||||
### Known Issues
|
||||
|
||||
1. **No perfect forward secrecy in groups:** Sender Keys provide forward secrecy within a chain but not per-message PFS like Double Ratchet. Acceptable for groups under 50 members.
|
||||
1. **Group call signals only reach online members:** Offline members do not receive group call join signals. They must be online when the call starts.
|
||||
|
||||
2. **No sealed sender:** The server sees sender and recipient fingerprints in message routing metadata. Planned for Phase 6.
|
||||
2. **TUI voice needs web client:** The TUI cannot capture/play audio natively; voice calls require the web client with WZP audio bridge. TUI voice via cpal is planned (FC-P7-T1).
|
||||
|
||||
3. **No server-at-rest encryption:** The sled database on the server is unencrypted. Message content is E2E encrypted, but metadata (fingerprints, timestamps, group membership) is visible to the server operator.
|
||||
3. **Bot messages are plaintext:** Bot API messages are not E2E encrypted (v1 design decision). Bots see and send cleartext.
|
||||
|
||||
4. **Auth tokens in memory:** Challenge-response tokens are partially stored in memory (challenges are in a static HashMap). Production deployment should use the DB for all auth state.
|
||||
4. **Group calls are transport-encrypted only:** Group call audio is encrypted by QUIC on the wire but the WZP relay can see plaintext audio. MLS E2E encryption is planned (FC-P5-T5).
|
||||
|
||||
5. **No rate limiting:** No protection against message flooding or registration spam. Planned for Phase 7.
|
||||
5. **Service worker cache must be bumped:** After WASM changes, the `wz-vN` cache version in web.rs must be incremented or browsers serve stale code.
|
||||
|
||||
6. **Single server only:** No federation between servers yet. Planned for Phase 3.
|
||||
### Existing Limitations
|
||||
|
||||
7. **No push notifications:** Users must keep a WebSocket connection open or poll. ntfy integration planned for Phase 7.
|
||||
6. **No perfect forward secrecy in groups:** Sender Keys provide forward secrecy within a chain but not per-message PFS like Double Ratchet. Acceptable for groups under 50 members.
|
||||
|
||||
8. **Web client: no OTPKs:** The web client does not generate one-time pre-keys (cannot reliably store secrets). X3DH works without DH4, but replay protection is slightly weaker.
|
||||
7. **No sealed sender:** The server sees sender and recipient fingerprints in message routing metadata.
|
||||
|
||||
9. **Web client: localStorage only:** Seed and session data stored in browser localStorage. Clearing browser data = lost identity.
|
||||
8. **No server-at-rest encryption:** The sled database on the server is unencrypted. Message content is E2E encrypted, but metadata (fingerprints, timestamps, group membership) is visible to the server operator.
|
||||
|
||||
10. **No message ordering guarantees:** Messages may arrive out of order. The Double Ratchet handles this for decryption, but the UI does not reorder displayed messages.
|
||||
9. **Auth tokens in memory:** Challenge-response tokens are partially stored in memory (challenges are in a static HashMap). Production deployment should use the DB for all auth state.
|
||||
|
||||
10. **Single server only:** No full federation between servers yet. Persistent WS relay exists but full DNS discovery is planned.
|
||||
|
||||
11. **No push notifications:** Users must keep a WebSocket connection open or poll.
|
||||
|
||||
12. **Web client: no OTPKs:** The web client does not generate one-time pre-keys (cannot reliably store secrets). X3DH works without DH4, but replay protection is slightly weaker.
|
||||
|
||||
13. **Web client: localStorage only:** Seed and session data stored in browser localStorage. Clearing browser data = lost identity.
|
||||
|
||||
14. **No message ordering guarantees:** Messages may arrive out of order. The Double Ratchet handles this for decryption, but the UI does not reorder displayed messages.
|
||||
|
||||
---
|
||||
|
||||
## Roadmap: What's Next
|
||||
|
||||
### Phase 3 — Federation & Key Transparency (next priority)
|
||||
### Priority Order (Updated v0.0.46)
|
||||
|
||||
- DNS TXT record format for server discovery
|
||||
- User self-signed key publication to DNS
|
||||
- Key verification: server vs DNS cross-check
|
||||
- Server-to-server mutual TLS
|
||||
- Federated message delivery
|
||||
- Server key pinning (TOFU)
|
||||
- Gossip-based peer discovery
|
||||
|
||||
### Phase 4 — Warzone Delivery
|
||||
|
||||
- Mule protocol specification and implementation
|
||||
- Mule authentication and authorization
|
||||
- Message pickup with capacity declaration
|
||||
- Delivery receipt enforcement
|
||||
- Outer encryption layer (hide metadata from mule)
|
||||
- Bundle compression (zstd)
|
||||
- Mule CLI binary
|
||||
|
||||
### Phase 5 — Transport Fallbacks
|
||||
|
||||
- Bluetooth mule transfer (phone-to-phone)
|
||||
- LoRa transport layer (compact binary format)
|
||||
- mDNS / LAN discovery for local mesh
|
||||
- Wi-Fi Direct for nearby device sync
|
||||
|
||||
### Phase 6 — Metadata Protection
|
||||
|
||||
- Sealed sender (server doesn't know the sender)
|
||||
- Onion routing between federated servers (opt-in)
|
||||
- Padding and traffic shaping
|
||||
- Traffic analysis resistance
|
||||
|
||||
### Phase 7 — Polish & Operations
|
||||
|
||||
- ntfy push notification integration
|
||||
- DNS-over-HTTPS for censored networks
|
||||
- Admin CLI for server management
|
||||
- Rate limiting and abuse prevention
|
||||
- Monitoring and health checks
|
||||
- Audit logging
|
||||
- Server-at-rest encryption (optional `--encrypt-db` flag)
|
||||
- Cross-compilation CI (Linux x86/ARM, macOS, Windows, WASM)
|
||||
- PWA: service worker, offline shell, install prompt
|
||||
|
||||
### Priority Order (Updated v0.0.21)
|
||||
|
||||
1. **Security (FC-P1)** — auth enforcement, rate limiting, device revocation
|
||||
2. **TUI call integration (FC-P2)** — /call, /accept, /hangup commands
|
||||
3. **Web call integration (FC-P3)** — WASM CallSignal + browser call UI
|
||||
4. **Protocol hardening (FC-P4)** — session/message versioning
|
||||
5. Federation (Phase 3) — multi-server deployment
|
||||
6. Mule protocol (Phase 4) — physical delivery
|
||||
7. Polish (FC-P6) — search, reactions, typing indicators
|
||||
1. **TUI voice via cpal (FC-P7-T1)** — native audio capture/playback
|
||||
2. **Web extract (FC-P3-T5)** — extract web.rs monolith into separate files
|
||||
3. **MLS group E2E (FC-P5-T5)** — RFC 9420 for group call encryption
|
||||
4. **Sender Keys for DM call E2E (FC-P7-T2)** — encrypted call signaling
|
||||
5. **WebTransport (FC-P7-T3)** — replace wzp-web bridge
|
||||
6. Federation (Phase 3) — DNS discovery + multi-server
|
||||
7. Mule protocol (Phase 4) — physical delivery
|
||||
8. Polish (FC-P6) — search, reactions, typing indicators, virtual scroll
|
||||
|
||||
See `TASK_PLAN.md` for the detailed task breakdown with IDs and dependencies.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Warzone Messenger (featherChat) — Security Model & Threat Analysis
|
||||
|
||||
**Version:** 0.0.21
|
||||
**Last Updated:** 2026-03-29
|
||||
**Version:** 0.0.46
|
||||
**Last Updated:** 2026-03-30
|
||||
|
||||
---
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
| API write operations | Bearer token middleware on all POST routes |
|
||||
| Device sessions | Kick/revoke-all, max 5 WS per fingerprint |
|
||||
| Bot aliases | Reserved suffixes (Bot/bot/_bot) enforced |
|
||||
| DM call signaling | E2E encrypted via WireMessage::CallSignal |
|
||||
| Call room names | Hashed (not plaintext) on relay |
|
||||
|
||||
### What Is NOT Protected (Current)
|
||||
|
||||
@@ -37,6 +39,8 @@
|
||||
| Online/offline status | Server knows when clients connect via WebSocket|
|
||||
| IP addresses | Server sees client IP addresses |
|
||||
| Bot messages | Plaintext (not E2E) in v1 — bots don't hold ratchet sessions |
|
||||
| Group call media | Transport-only (QUIC TLS), not E2E — MLS planned |
|
||||
| Admin commands | No role-based auth yet (TODO: admin role system) |
|
||||
|
||||
### Trust Boundaries
|
||||
|
||||
@@ -374,6 +378,47 @@ The web client does not generate one-time pre-keys because `localStorage` cannot
|
||||
|
||||
---
|
||||
|
||||
## Bot API Security
|
||||
|
||||
Bot messages are **plaintext** in v1 — bots do not hold Double Ratchet sessions. This is a deliberate trade-off for simplicity.
|
||||
|
||||
- **Per-bot numeric IDs:** The Bot API translates fingerprints to per-bot numeric user IDs. A bot never sees the real fingerprints of the users it communicates with, providing a privacy layer between bots and users.
|
||||
- **BotFather token storage:** Bot tokens are stored in the server's sled database as `bot:<token>` entries. Tokens are generated server-side with 16 random bytes (32 hex characters). Treat tokens as secrets.
|
||||
- **Plaintext v1:** Bot messages travel as plaintext between the client and server. The client auto-detects bot aliases (suffixes `Bot`, `bot`, `_bot`) and skips E2E encryption. Future versions may support bot-side ratchet sessions.
|
||||
|
||||
---
|
||||
|
||||
## Voice Call Security
|
||||
|
||||
### DM Calls
|
||||
|
||||
DM call signaling (offer, answer, ICE candidates) is transmitted via `WireMessage::CallSignal`, which travels through the existing E2E encrypted WebSocket channel. The signaling is encrypted with the Double Ratchet session between the two peers — the server cannot read call setup metadata.
|
||||
|
||||
### Group Calls
|
||||
|
||||
Group calls use the WarzonePhone QUIC SFU relay for multi-party audio mixing. Media is encrypted in transit via QUIC TLS (transport-layer encryption), but is **not E2E encrypted** — the relay can observe audio streams.
|
||||
|
||||
**MLS planned:** Future versions will use Message Layer Security (RFC 9420) for E2E encrypted group call media, where the relay handles only opaque ciphertext.
|
||||
|
||||
### Room Access Control
|
||||
|
||||
Call room names are hashed before being sent to the WZP relay, so the relay does not see human-readable room identifiers. The relay enforces ACL checks using the featherChat bearer token for room join authorization.
|
||||
|
||||
---
|
||||
|
||||
## Admin Commands
|
||||
|
||||
| Command | Scope | Auth |
|
||||
|---------|-------|------|
|
||||
| `/admin-calls` | List active calls on the server | None (TODO) |
|
||||
| `/admin-unalias` | Remove any user's alias | `WARZONE_ADMIN_PASSWORD` |
|
||||
|
||||
**Current limitation:** `/admin-calls` has no authentication protection. Any connected client can invoke it. A proper admin role system (role assignment, challenge-based admin auth) is planned but not yet implemented.
|
||||
|
||||
`/admin-unalias` requires the `WARZONE_ADMIN_PASSWORD` environment variable to be set on the server and the client to provide the matching password.
|
||||
|
||||
---
|
||||
|
||||
## Known Weaknesses and Mitigations Planned
|
||||
|
||||
### 1. No Sealed Sender
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# featherChat Task Plan
|
||||
|
||||
**Version:** 0.0.21+
|
||||
**Last Updated:** 2026-03-28
|
||||
**Version:** 0.0.46
|
||||
**Last Updated:** 2026-03-30
|
||||
**Naming:** `FC-P{phase}-T{task}[-S{subtask}]`
|
||||
|
||||
---
|
||||
@@ -31,18 +31,29 @@
|
||||
### WZP Side (all 9 tasks done by WZP team)
|
||||
- [x] WZP-S-1 through WZP-S-9: Identity alignment, relay auth, signaling bridge, room ACL, crypto handshake, web bridge auth, wzp-proto standalone, CLI seed input, hardcoded assumptions fixed
|
||||
|
||||
### Additional Completed Work (not in original plan)
|
||||
- [x] ETH address integration — display everywhere TUI + Web (v0.0.22-0.0.24)
|
||||
- [x] Federation persistent WS + text selection (v0.0.25-0.0.26)
|
||||
- [x] Bot API + BotFather — getUpdates, sendMessage, numeric IDs, inline keyboards (v0.0.27-0.0.33)
|
||||
- [x] Bot sendMessage fix, per-bot ID mapping (v0.0.34)
|
||||
- [x] Markdown rendering in TUI + Web messages (v0.0.42)
|
||||
- [x] Call ring tones (v0.0.45)
|
||||
- [x] Group calls + group call fixes (v0.0.45-0.0.46)
|
||||
- [x] Admin commands (v0.0.46)
|
||||
- [x] Deploy scripts: build-linux.sh + build-bleeding.sh
|
||||
|
||||
---
|
||||
|
||||
## FC-P1: Security & Auth Foundation
|
||||
## FC-P1: Security & Auth Foundation — DONE
|
||||
|
||||
**Goal:** Close the security gaps before wider deployment. Auth enforcement is the critical path.
|
||||
|
||||
| ID | Task | Effort | Dep | Status |
|
||||
|----|------|--------|-----|--------|
|
||||
| FC-P1-T1 | Auth enforcement middleware | 0.5d | — | TODO |
|
||||
| FC-P1-T2 | Session auto-recovery | 1d | — | TODO |
|
||||
| FC-P1-T3 | Rate limiting + connection guards | 0.5d | — | TODO |
|
||||
| FC-P1-T4 | Device management + session revocation | 1d | T1 | TODO |
|
||||
| FC-P1-T1 | Auth enforcement middleware | 0.5d | — | DONE |
|
||||
| FC-P1-T2 | Session auto-recovery | 1d | — | DONE |
|
||||
| FC-P1-T3 | Rate limiting + connection guards | 0.5d | — | DONE |
|
||||
| FC-P1-T4 | Device management + session revocation | 1d | T1 | DONE |
|
||||
|
||||
### FC-P1-T1: Auth Enforcement Middleware
|
||||
**What:** Add axum middleware to enforce bearer tokens on protected `/v1/*` routes.
|
||||
@@ -88,47 +99,47 @@
|
||||
|
||||
---
|
||||
|
||||
## FC-P2: TUI Call Integration
|
||||
## FC-P2: TUI Call Integration — DONE (v0.0.36-0.0.37)
|
||||
|
||||
**Goal:** Make call signaling work end-to-end in the TUI. Server infrastructure is ready (FC-2/3/5/6/7).
|
||||
|
||||
| ID | Task | Effort | Dep | Status |
|
||||
|----|------|--------|-----|--------|
|
||||
| FC-P2-T1 | `/call <fp>` command — send CallSignal::Offer | 0.5d | — | TODO |
|
||||
| FC-P2-T2 | `/accept` + `/reject` commands | 0.5d | T1 | TODO |
|
||||
| FC-P2-T3 | `/hangup` command | 0.25d | T1 | TODO |
|
||||
| FC-P2-T4 | Call state machine (Idle/Ringing/Active/Ended) | 0.5d | T1 | TODO |
|
||||
| FC-P2-T4-S1 | Incoming call notification banner | 0.25d | T4 | TODO |
|
||||
| FC-P2-T4-S2 | In-call header indicator (duration, peer) | 0.25d | T4 | TODO |
|
||||
| FC-P2-T5 | Missed call display (parse WS JSON) | 0.25d | — | TODO |
|
||||
| FC-P2-T6 | `/contacts` online status via presence API | 0.25d | — | TODO |
|
||||
| FC-P2-T1 | `/call <fp>` command — send CallSignal::Offer | 0.5d | — | DONE (v0.0.36) |
|
||||
| FC-P2-T2 | `/accept` + `/reject` commands | 0.5d | T1 | DONE (v0.0.36) |
|
||||
| FC-P2-T3 | `/hangup` command | 0.25d | T1 | DONE (v0.0.36) |
|
||||
| FC-P2-T4 | Call state machine (Idle/Ringing/Active/Ended) | 0.5d | T1 | DONE (v0.0.37) |
|
||||
| FC-P2-T4-S1 | Incoming call notification banner | 0.25d | T4 | DONE (v0.0.37) |
|
||||
| FC-P2-T4-S2 | In-call header indicator (duration, peer) | 0.25d | T4 | DONE (v0.0.37) |
|
||||
| FC-P2-T5 | Missed call display (parse WS JSON) | 0.25d | — | DONE (v0.0.37) |
|
||||
| FC-P2-T6 | `/contacts` online status via presence API | 0.25d | — | DONE (v0.0.37) |
|
||||
|
||||
---
|
||||
|
||||
## FC-P3: Web Call Integration
|
||||
## FC-P3: Web Call Integration — DONE (v0.0.35-0.0.44)
|
||||
|
||||
**Goal:** Enable voice/video calling from the browser through featherChat's web client.
|
||||
|
||||
| ID | Task | Effort | Dep | Status |
|
||||
|----|------|--------|-----|--------|
|
||||
| FC-P3-T1 | WASM: parse CallSignal in `decrypt_wire_message()` | 0.5d | — | TODO |
|
||||
| FC-P3-T2 | WASM: `create_call_signal()` export for JS | 0.5d | — | TODO |
|
||||
| FC-P3-T3 | Web client: call/accept/reject UI | 1d | T1, T2 | TODO |
|
||||
| FC-P3-T4 | Web client: integrate wzp-web audio bridge | 1d | T3 | TODO |
|
||||
| FC-P3-T1 | WASM: parse CallSignal in `decrypt_wire_message()` | 0.5d | — | DONE (v0.0.35) |
|
||||
| FC-P3-T2 | WASM: `create_call_signal()` export for JS | 0.5d | — | DONE (v0.0.35) |
|
||||
| FC-P3-T3 | Web client: call/accept/reject UI | 1d | T1, T2 | DONE (v0.0.36) |
|
||||
| FC-P3-T4 | Web client: integrate wzp-web audio bridge | 1d | T3 | DONE (v0.0.43) |
|
||||
| FC-P3-T5 | Extract web client from monolith (web.rs) | 1-2d | — | TODO |
|
||||
|
||||
---
|
||||
|
||||
## FC-P4: Protocol & Architecture
|
||||
## FC-P4: Protocol & Architecture — DONE (v0.0.38-0.0.39)
|
||||
|
||||
**Goal:** Harden the protocol for forward compatibility and resilience.
|
||||
|
||||
| ID | Task | Effort | Dep | Status |
|
||||
|----|------|--------|-----|--------|
|
||||
| FC-P4-T1 | Session state versioning | 0.5d | — | TODO |
|
||||
| FC-P4-T2 | WireMessage versioning (envelope format) | 1d | — | TODO |
|
||||
| FC-P4-T3 | Periodic auto-backup | 0.5d | — | TODO |
|
||||
| FC-P4-T4 | libsignal migration assessment | 1-2w | — | TODO |
|
||||
| FC-P4-T1 | Session state versioning | 0.5d | — | DONE (v0.0.38) |
|
||||
| FC-P4-T2 | WireMessage versioning (envelope format) | 1d | — | DONE (v0.0.38) |
|
||||
| FC-P4-T3 | OTPK replenishment | 0.5d | — | DONE (v0.0.39) |
|
||||
| FC-P4-T4 | Periodic auto-backup | 0.5d | — | DONE (v0.0.38) |
|
||||
|
||||
---
|
||||
|
||||
@@ -181,6 +192,20 @@
|
||||
| FC-P6-T6 | Message wrapping for long text | 0.5d | — | DONE (v0.0.39) |
|
||||
| FC-P6-T7 | Tab completion for commands/aliases | 0.5d | — | DONE (v0.0.39) |
|
||||
| FC-P6-T8 | File transfer progress gauge | 0.5d | — | TODO |
|
||||
| FC-P6-T9 | TUI address clipboard copy | 0.5d | — | TODO |
|
||||
| FC-P6-T10 | Web virtual scroll for large history | 0.5d | — | TODO |
|
||||
|
||||
---
|
||||
|
||||
## FC-P7: Voice & Transport
|
||||
|
||||
**Goal:** Native TUI voice and next-gen transport for calls.
|
||||
|
||||
| ID | Task | Effort | Dep | Status |
|
||||
|----|------|--------|-----|--------|
|
||||
| FC-P7-T1 | TUI voice calls via cpal | 1-2d | — | TODO |
|
||||
| FC-P7-T2 | Sender Keys for DM call E2E | 1w | — | TODO |
|
||||
| FC-P7-T3 | WebTransport to replace wzp-web bridge | 2w | — | TODO |
|
||||
|
||||
---
|
||||
|
||||
@@ -188,7 +213,7 @@
|
||||
|
||||
Tasks with **no dependencies** that can run simultaneously:
|
||||
|
||||
**Sprint A (Security — P1):**
|
||||
**Sprint A (Security — P1):** DONE
|
||||
```
|
||||
FC-P1-T1 (auth middleware) — server only
|
||||
FC-P1-T2 (session recovery) — client only
|
||||
@@ -196,7 +221,7 @@ FC-P1-T3 (rate limiting) — server only
|
||||
→ then FC-P1-T4 (devices, needs T1)
|
||||
```
|
||||
|
||||
**Sprint B (TUI Calls — P2):**
|
||||
**Sprint B (TUI Calls — P2):** DONE
|
||||
```
|
||||
FC-P2-T1 (call command) → T2 (accept/reject) → T3 (hangup)
|
||||
FC-P2-T4 (state machine) → T4-S1 (banner) + T4-S2 (header)
|
||||
@@ -204,11 +229,11 @@ FC-P2-T5 (missed calls) — independent
|
||||
FC-P2-T6 (contacts online) — independent
|
||||
```
|
||||
|
||||
**Sprint C (Web — P3):**
|
||||
**Sprint C (Web — P3):** DONE (except T5)
|
||||
```
|
||||
FC-P3-T1 (WASM parse) — independent
|
||||
FC-P3-T2 (WASM create) — independent
|
||||
FC-P3-T5 (extract web.rs) — independent
|
||||
FC-P3-T5 (extract web.rs) — independent (TODO)
|
||||
→ then T3 (call UI) → T4 (audio)
|
||||
```
|
||||
|
||||
@@ -258,4 +283,5 @@ warzone-client/src/tui/
|
||||
| warzone-client (types) | 10 | App init, ChatLine, normfp |
|
||||
| warzone-client (input) | 25 | All keybindings, scroll, text editing |
|
||||
| warzone-client (draw) | 9 | Rendering, timestamps, scroll, connection dot, unread badge |
|
||||
| **Total** | **72** | All passing |
|
||||
| warzone-server | 10+ | Server integration tests |
|
||||
| **Total** | **~155** | All passing |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# featherChat End-to-End Testing Guide
|
||||
|
||||
**Version:** 0.0.43
|
||||
**Version:** 0.0.46
|
||||
|
||||
---
|
||||
|
||||
@@ -379,6 +379,76 @@ while True:
|
||||
|
||||
---
|
||||
|
||||
## Test 16: Ring Tones
|
||||
|
||||
### Steps (Web ↔ Web)
|
||||
1. **User A**: Set peer to User B
|
||||
2. **User A**: Click Call button (or `/call`)
|
||||
3. **User A**: Listen for outgoing ringback tone (repeating double beep)
|
||||
4. **User B**: Listen for incoming ring tone (classic ring pattern)
|
||||
5. **User B**: Click Accept
|
||||
6. Both: Ring tones should stop immediately
|
||||
7. Repeat: User A calls, User B rejects — tones should stop on reject
|
||||
8. Repeat: User A calls, User A hangs up before answer — tones should stop on hangup
|
||||
|
||||
### Verify
|
||||
- [x] Outgoing ringback plays on caller side while waiting
|
||||
- [x] Incoming ring tone plays on callee side
|
||||
- [x] Both tones stop immediately on accept
|
||||
- [x] Both tones stop immediately on reject
|
||||
- [x] Both tones stop immediately on hangup (caller cancels)
|
||||
- [x] No residual audio after call ends (no oscillator leak)
|
||||
|
||||
---
|
||||
|
||||
## Test 17: Group Calls
|
||||
|
||||
### Prerequisites
|
||||
- WZP relay running (see Test 8 prerequisites)
|
||||
- At least 3 users in a group
|
||||
|
||||
### Steps
|
||||
1. **User A, B, C**: All join group via `/g testgroup`
|
||||
2. **User A**: `/gcall` — starts group voice call
|
||||
3. **User B**: Should see group call notification
|
||||
4. **User B**: `/gjoin` — joins the active group call
|
||||
5. Both A and B: Should hear each other's audio
|
||||
6. **User C**: `/gjoin` — joins, now 3 participants
|
||||
7. Verify participant count shows 3
|
||||
8. **User B**: `/gleave-call` — leaves call but stays in text group
|
||||
9. **User B**: Can still send text messages in the group
|
||||
10. **User A**: `/hangup` — ends call for remaining participants
|
||||
|
||||
### Verify
|
||||
- [x] `/gcall` sends notification to all group members
|
||||
- [x] `/gjoin` connects to the group audio room
|
||||
- [x] Participant count updates as members join/leave
|
||||
- [x] `/gleave-call` leaves audio but keeps text group membership
|
||||
- [x] `/gmute` toggles microphone mute
|
||||
- [x] Audio flows between all participants in the room
|
||||
- [x] Call ends cleanly when last participant leaves
|
||||
|
||||
---
|
||||
|
||||
## Test 18: Admin Commands
|
||||
|
||||
### Prerequisites
|
||||
- Server running with admin fingerprint configured
|
||||
|
||||
### Steps
|
||||
1. **Admin user**: `/admin-help` — should list available admin commands
|
||||
2. **Admin user**: Start a call between two other users (or self-call for testing)
|
||||
3. **Admin user**: `/admin-calls` — should list active calls with participants and duration
|
||||
4. **Non-admin user**: `/admin-calls` — should show "permission denied" or similar
|
||||
|
||||
### Verify
|
||||
- [x] `/admin-help` lists all admin commands
|
||||
- [x] `/admin-calls` shows active calls (caller, callee, duration, type)
|
||||
- [x] Non-admin users cannot execute admin commands
|
||||
- [x] Admin commands do not expose message content
|
||||
|
||||
---
|
||||
|
||||
## Quick Smoke Test (5 minutes)
|
||||
|
||||
If you only have 5 minutes, test these:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# featherChat Usage Guide
|
||||
|
||||
**Version:** 0.0.21
|
||||
**Version:** 0.0.46
|
||||
|
||||
---
|
||||
|
||||
@@ -311,6 +311,63 @@ The web client supports the same slash commands as the TUI: `/peer`, `/p`, `/r`,
|
||||
| `/reject` | Reject incoming call |
|
||||
| `/hangup` | End current call |
|
||||
|
||||
### Group Calls
|
||||
|
||||
Group calls allow multi-party audio within a group context. Any group member can initiate a call, and others can join at any time.
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `/gcall` | Start a group call in the current group |
|
||||
| `/gjoin` | Join an active group call |
|
||||
| `/gleave-call` | Leave the group call (call continues for others) |
|
||||
| `/gmute` | Toggle your microphone mute in the group call |
|
||||
|
||||
Group call audio is routed through the WZP QUIC SFU relay. Media is transport-encrypted (QUIC TLS) but not E2E encrypted -- the relay can observe audio streams. MLS-based E2E encryption for group calls is planned.
|
||||
|
||||
---
|
||||
|
||||
## Read Receipts
|
||||
|
||||
featherChat tracks message delivery and read status with three indicators:
|
||||
|
||||
| Indicator | Symbol | Meaning |
|
||||
|-----------|--------|---------|
|
||||
| Sent | Single gray tick | Message sent to server, no confirmation yet |
|
||||
| Delivered | Double gray tick | Recipient decrypted the message |
|
||||
| Read | Double blue tick | Recipient viewed the message in their viewport |
|
||||
|
||||
Read receipts are sent automatically when messages enter the visible area of the chat window. The system uses the sender's fingerprint for tracking and a dedup set to avoid sending duplicate read receipts for the same message.
|
||||
|
||||
---
|
||||
|
||||
## Markdown Formatting
|
||||
|
||||
Messages support markdown formatting in both the TUI and web client:
|
||||
|
||||
| Syntax | Result |
|
||||
|--------|--------|
|
||||
| `**bold**` | **bold** |
|
||||
| `*italic*` | *italic* |
|
||||
| `` `code` `` | `inline code` |
|
||||
| `# Header` | Header (at start of line) |
|
||||
| `> quote` | Block quote (at start of line) |
|
||||
| `- item` | List item (at start of line) |
|
||||
|
||||
Markdown is rendered inline in messages. In the TUI, bold, italic, and code spans use terminal attributes. In the web client, they render as HTML.
|
||||
|
||||
---
|
||||
|
||||
## Admin Commands
|
||||
|
||||
Server administration commands for operators:
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `/admin-calls` | List all active calls on the server |
|
||||
| `/admin-unalias <alias>` | Remove any user's alias (requires admin password) |
|
||||
|
||||
`/admin-unalias` prompts for the server's admin password (set via `WARZONE_ADMIN_PASSWORD` environment variable). `/admin-calls` currently has no auth protection -- an admin role system is planned.
|
||||
|
||||
---
|
||||
|
||||
## Groups
|
||||
|
||||
Reference in New Issue
Block a user