Commit Graph

92 Commits

Author SHA1 Message Date
Siavash Sameni
3429f518b1 feat: TUI /call, /accept, /reject, /hangup commands (FC-P2-T1+T2+T3)
- /call [fp|@alias|0x...] — send CallSignal::Offer to peer
- /accept — answer incoming call (uses last_dm_peer)
- /reject — reject incoming call
- /hangup — end active call
- All four added to /help text

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 16:19:01 +04:00
Siavash Sameni
e9182fdb41 v0.0.36: web call UI — call/accept/reject/hangup with signaling
Web client:
- Call bar between header and messages (hidden when idle)
- Call button appears when peer is set (not group)
- Incoming call: pulsing notification + Accept/Reject buttons
- Call states: idle → calling → ringing → active
- /call, /accept, /reject, /hangup slash commands
- CallSignal sent via WS binary frames (same as messages)
- handleCallSignal processes Offer/Answer/Hangup/Reject/Ringing/Busy
- Vibration on incoming call (mobile)
- create_call_signal WASM import wired up

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 16:07:03 +04:00
Siavash Sameni
0b58ddcee5 v0.0.35: WASM create_call_signal, selectable identity, web sections
FC-P3-T2: WASM create_call_signal() export
- Accepts signal_type string (offer/answer/hangup/etc), payload, target
- Returns bincode WireMessage::CallSignal bytes for WS send

FC-P3-T9: Selectable identity display in web
- ETH address shown in code-style block, click to copy
- addSys() gains rawHtml parameter for rich content

FC-P3-T5: Section navigation comments in web.rs
- 5 section markers: State, Crypto, Network, UI, Commands

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 16:00:43 +04:00
Siavash Sameni
0e7277fb20 fix: visible scrollbar on web messages area
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 15:51:43 +04:00
Siavash Sameni
7628ff7a75 v0.0.34: fix bot sendMessage — store per-bot numeric ID reverse mapping
Per-bot numeric IDs (privacy feature) broke sendMessage because the
reverse lookup couldn't find the fingerprint from the per-bot hash.

Fix: store numid:<numeric_id> → fingerprint in tokens tree when
generating updates. resolve_chat_id checks this mapping first.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 15:35:52 +04:00
Siavash Sameni
3489a7cf74 fix: log full bot tokens + write to data_dir/bot-tokens.txt
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 15:05:11 +04:00
Siavash Sameni
1e47b888c8 v0.0.33: bump version
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 14:51:39 +04:00
Siavash Sameni
5415d1f5c8 fix: auto-join #ops creates group if missing, remove auth from create/join group
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 14:47:54 +04:00
Siavash Sameni
13f2227bf0 v0.0.32: system bots config — persist across data wipes, welcome screen
Server:
- --bots-config <path> loads JSON array of system bots on startup
- Bots auto-created if missing, aliases restored on every start
- Bot list stored in DB for welcome screen (system:bot_list key)
- GET /v1/bot/list returns system bots (public, no auth)

Welcome screen:
- Web + TUI show available bots on first login
- "Available bots: @helpbot — featherChat help, @codebot — Coding..."
- Clickable in web (via address detection)

Config: bots.example.json with 10 suggested bots
Usage: warzone-server --enable-bots --bots-config bots.json

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 14:07:34 +04:00
Siavash Sameni
f04c24187d feat: auto-join #ops on first login (web + TUI)
New users with no peer/group set automatically join #ops so they
have someone to talk to. Saved peer overrides this on subsequent visits.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:54:19 +04:00
Siavash Sameni
3e583bb04b v0.0.31: per-bot unique user IDs, remove raw fingerprint from bot API
Privacy: from.id is now Hash(bot_token + user_fp) → different bots see
different numeric IDs for the same user. Prevents cross-bot user correlation.

Removed id_str (raw hex fingerprint) from all bot API responses.
Updated LLM_BOT_DEV.md and LLM_HELP.md.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:49:10 +04:00
Siavash Sameni
6fee73fc4d v0.0.30: markdown rendering in web, fix scrolling
Web:
- Markdown renderer: **bold**, *italic*, `code`, ```code blocks```,
  # headers, [links](url), > blockquotes, - lists
- All message text rendered as markdown (bot messages look great now)
- Fixed scroll: overflow-y: scroll + min-height: 0 on messages container
- CSS for code blocks, pre, headers, blockquotes, lists
- Styled: code=cyan bg, pre=dark bg+border, bold=white, italic=amber

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 12:36:00 +04:00
Siavash Sameni
8b37bd4323 fix: getUpdates enforces min 1s delay when empty (prevents tight-loop spam)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 12:25:41 +04:00
Siavash Sameni
b0fa9f92bd fix: BotFather stores rec: AliasRecord so resolve_alias finds bot aliases
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 12:21:45 +04:00
Siavash Sameni
76fd8dd81a fix: web bot detection checks alias name first, then whois fallback
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 11:19:34 +04:00
Siavash Sameni
e0e747e005 fix: BotFather fingerprint uses all-hex (00000000000000000b0ffa00e000000f)
Old fp contained non-hex chars (o,r) which got stripped by normFP,
causing whois lookup failure and bot detection to miss.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 11:17:05 +04:00
Siavash Sameni
76ee2ab585 fix: BotFather alias record ensures resolve_alias works after data wipe
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 11:14:41 +04:00
Siavash Sameni
878847ce89 fix: recognize @botfather as bot peer (special case, not pattern change)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 11:11:28 +04:00
Siavash Sameni
362e7a765b v0.0.29: BotFather — create bots by messaging @botfather
Built-in BotFather (Rust, server-side):
- Intercepts messages to @botfather in deliver_or_queue
- Commands: /newbot <name>, /mybots, /deletebot <name>, /token <name>
- Creates bot with fingerprint, token, alias, tracks ownership
- Replies via push_to_client or queue (works offline)
- Only active when --enable-bots is set

Standalone BotFather (Python):
- tools/botfather.py: uses bot API (getUpdates/sendMessage)
- Delegates core ops to built-in handler
- Extensible for additional features
- Reads token from BOTFATHER_TOKEN env or .botfather_token file

Flow: User messages @botfather → "/newbot MyBot" → gets token back

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 11:08:35 +04:00
Siavash Sameni
76cac77259 v0.0.28: BotFather-only registration, per-instance bot toggle, docs update
Security:
- Bot registration restricted to BotFather (requires botfather_token)
- Direct POST /v1/bot/register without BotFather auth → rejected

Deploy:
- systemd service reads /home/warzone/server.env for EXTRA_ARGS
- deploy/warzone-server.env.mequ: no bots (default)
- deploy/warzone-server.env.kh3rad3ree: --enable-bots
- setup.sh copies per-hostname env file

Docs updated:
- LLM_HELP.md: BotFather flow, plaintext bot messaging, E2E option, bridge
- LLM_BOT_DEV.md: botfather_token requirement, E2E mode, bridge section
- BOT_API.md: full BotFather flow, ownership, numeric IDs, webhook delivery
- SERVER.md: --enable-bots flag, per-instance config, bot system section
- USAGE.md: bot messaging, BotFather, bridge tool

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 09:52:12 +04:00
Siavash Sameni
8603087afb v0.0.27: TG-compatible bots — plaintext send, numeric IDs, webhooks, BotFather
Bot compatibility:
- Clients send plaintext bot_message to bot aliases (no E2E encryption)
- Numeric chat_id: fp_to_numeric_id() deterministic hash, accept string/number
- Webhook delivery: POST updates to bot's webhook URL (async, fire-and-forget)
- getUpdates timeout raised to 50s (was 30, TG uses 50)
- parse_mode HTML rendered in web client
- E2E bot registration: optional seed + bundle for encrypted bot sessions

BotFather + instance control:
- --enable-bots CLI flag (default: disabled)
- BotFather auto-created on first start (@botfather alias)
- Bot ownership: owner fingerprint stored in bot_info
- All bot endpoints return 403 when disabled

Bot Bridge:
- tools/bot-bridge.py: TG-compatible proxy for unmodified TG bots
- Translates chat_id int↔string, proxies getUpdates/sendMessage
- README with python-telegram-bot and Telegraf examples

Test fixes:
- Updated tests for ETH address display in header/messages

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 09:45:45 +04:00
Siavash Sameni
067f1ea20b v0.0.25: fix text selection in web chat, don't steal focus when selecting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 09:15:40 +04:00
Siavash Sameni
deb220ff2c fix: SW uses network-first strategy, updates apply without clearing storage
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 09:11:15 +04:00
Siavash Sameni
1851728a09 v0.0.24: ETH display in TUI header/messages, web peer resolve, click-focus
TUI:
- Header shows peer ETH address (resolved on /peer set)
- Own messages show ETH format
- Resolve display shows full formatted fingerprint (xxxx:xxxx:...)
- peer_eth field stored on App for header display

Web:
- Pasting 0x address in peer input box now resolves via /v1/resolve/
- Send path resolves 0x/@ before encrypting
- Click messages area → focuses text input
- Own messages show ETH format

Version: 0.0.23 → 0.0.24, SW cache wz-v4 → wz-v5
Build script: --local, --local-ship, --local-clean commands

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 09:04:37 +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
2aa58a4319 fix: TUI shows ETH address, /peer 0x... resolves, Cmd+key on macOS
TUI header: shows ETH address (0x...) instead of fingerprint
/peer 0x...: resolves via GET /v1/resolve/:address endpoint
Cmd+A/E/U/K/W: macOS SUPER modifier now handled alongside CONTROL
Added resolve_address() method for ETH/any address resolution

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 08:20:38 +04:00
Siavash Sameni
3efce2ddf4 v0.0.22: version bump, ETH identity in web client, version bump rule
Version:
- Workspace + protocol: 0.0.21 → 0.0.22
- Web client VERSION: 0.0.17 → 0.0.22
- Service worker cache: wz-v2 → wz-v3

ETH identity:
- Added WasmIdentity::eth_address() export (derives from seed via secp256k1)
- Web client sends eth_address during key registration
- Identity display shows ETH address first, then fingerprint
- No more server-side resolve needed — computed client-side

CLAUDE.md:
- Added MANDATORY version bump rule (4 places to update)
- Must bump on every functional change, never skip SW cache

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 08:11:31 +04:00
Siavash Sameni
fcbf2d5859 feat: complete Telegram-compatible Bot API + bot dev guide
Bot API (routes/bot.rs — full rewrite):
- getUpdates: persistent update_id counter, offset acknowledgement,
  limit (max 100), long-poll up to 30s with 1s intervals
- sendMessage: parse_mode, reply_to_message_id, reply_markup (inline keyboards)
- answerCallbackQuery: acknowledge button clicks
- editMessageText: update sent messages
- setWebhook / deleteWebhook / getWebhookInfo: webhook configuration
- sendDocument: file reference with caption
- Bot queue: raw messages migrated to bot_queue:<fp>:<update_id> for ordering

Web client (routes/web.rs):
- Bot messages rendered properly (was showing "[message could not be decrypted]")
- Handles bot_message, bot_edit, bot_document as both Text and Binary WS frames
- Inline keyboard buttons rendered as bracketed text
- Missed call notifications handled in Text frame path

Docs:
- LLM_BOT_DEV.md: token-optimized bot dev reference for coding assistant LLM
  (Python + Node.js examples, all endpoints, TG compatibility table)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 07:50:14 +04:00
Siavash Sameni
210fbbb35b feat: bot alias reservation + BOT_API.md documentation
- Aliases ending with Bot/bot/_bot reserved for registered bots only
- Non-bot users get clear error directing to /v1/bot/register
- Bot registration auto-creates alias (@name_bot suffix)
- BOT_API.md: full developer guide with endpoints, examples, echo bot
- LLM_HELP.md: expanded bot section with update types + Python example

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 07:34:45 +04:00
Siavash Sameni
7b72f7cba5 feat: friend list, bot API, ETH addressing, deep links, docs overhaul
Tier 1 — New features:
- E2E encrypted friend list: server stores opaque blob (POST/GET /v1/friends),
  protocol-level encrypt/decrypt with HKDF-derived key, 4 tests
- Telegram Bot API compatibility: /bot/register, /bot/:token/getUpdates,
  sendMessage, getMe — TG-style Update objects with proper message mapping
- ETH address resolution: GET /v1/resolve/:address (0x.../alias/@.../fp),
  bidirectional ETH↔fp mapping stored on key registration
- Seed recovery: /seed command in TUI + web client
- URL deep links: /message/@alias, /message/0xABC, /group/#ops
- Group members with online status in GET /groups/:name/members

Tier 2 — UX polish:
- TUI: /friend, /friend <addr>, /unfriend <addr> with presence checking
- Web: friend commands, showGroupMembers() on group join
- Web: ETH address in header, clickable addresses (click→peer or copy)
- Bot: full WireMessage→TG Update mapping (encrypted base64, CallSignal,
  FileHeader, bot_message JSON)

Documentation:
- USAGE.md rewritten: complete user guide with all commands
- SERVER.md rewritten: full admin guide with all 50+ endpoints
- CLIENT.md rewritten: architecture, commands, keyboard, storage
- LLM_HELP.md created: 1083-word token-optimized reference for helper LLM

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 07:31:54 +04:00
Siavash Sameni
dbf5d136cf fix: WASM double-X3DH bug, federated aliases, deploy tooling
WASM fix (critical):
- encrypt_key_exchange_with_id was calling x3dh::initiate a second time,
  generating a new ephemeral key that didn't match the ratchet — receiver
  always failed to decrypt. Now stores X3DH result from initiate() and
  reuses it. Added 2 protocol tests confirming the fix + the bug.
- Bumped service worker cache to wz-v2 to force browsers to re-fetch.
- Disabled wasm-opt for Hetzner builds (libc compat issue).

Federation — alias support:
- resolve_alias falls back to federation peer if not found locally
- register_alias checks peer server before allowing — globally unique aliases
- Added resolve_remote_alias() and is_alias_taken_remote() to FederationHandle

Federation — key proxy fix:
- Remote bundles no longer cached locally (stale cache caused decrypt failures)
- Local vs remote determined by device: prefix in keys DB

Client fixes:
- Self-messaging blocked ("Cannot send messages to yourself")
- /peer <self> blocked
- last_dm_peer never set to self
- /r <message> sends reply inline (switches peer + sends in one command)

Deploy tooling:
- scripts/build-linux.sh with --ship (build + deploy + destroy)
- --update-all, --status, --logs commands
- WASM rebuilt on Hetzner VM before server binary
- deploy/ directory: systemd service, federation configs, setup script
- Journald log cap (50MB, 7-day retention)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 22:59:19 +04:00
Siavash Sameni
f8eaf30bb4 refactor: federation uses persistent WS instead of HTTP polling
- Server-to-server communication via WebSocket at /v1/federation/ws
- Auth as first WS frame (shared secret), presence + forwards over same connection
- Auto-reconnect every 3s on disconnect, instant presence push on connect
- Replaces HTTP REST polling (no more 5s intervals, lower latency)
- Removed dead HMAC helpers (auth is now direct secret comparison over WS)
- Simplified ARCHITECTURE.md mermaid diagrams for Gitea rendering

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 16:56:13 +04:00
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
4a4fa9fab4 v0.0.21: FC-CRATE-1 — make warzone-protocol importable standalone
Replaced workspace dep inheritance with explicit versions in
warzone-protocol/Cargo.toml. The crate now builds both as a
workspace member AND standalone.

WZP can now import warzone-protocol directly:
  warzone-protocol = { path = "../featherChat/warzone/crates/warzone-protocol" }

This means WZP can delete its mirrored identity/crypto code and use:
- warzone_protocol::identity::{Seed, IdentityKeyPair, PublicIdentity}
- warzone_protocol::crypto::{hkdf_derive, aead_encrypt, aead_decrypt}
- warzone_protocol::ethereum::{derive_eth_identity, EthAddress}
- warzone_protocol::message::{WireMessage, CallSignalType}
- warzone_protocol::types::Fingerprint

Single source of truth for identity derivation — no more HKDF mismatches.

28/28 tests pass. Zero warnings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 09:21:18 +04:00
Siavash Sameni
064a730b42 v0.0.21: WZP integration groundwork — CallSignal + token validation
WZP-FC-1: CallSignal WireMessage variant
- CallSignalType enum: Offer, Answer, IceCandidate, Hangup, Reject, Ringing, Busy
- Routed through existing E2E encrypted channels
- Server dedup handles new variant
- TUI shows "📞 Call signal: Offer" etc
- CLI recv prints call signals

WZP-FC-4: Token validation endpoint
- POST /v1/auth/validate { "token": "..." }
- Returns: { "valid": true, "fingerprint": "...", "alias": "..." }
- WZP relay calls this to verify featherChat bearer tokens
- Resolves alias alongside fingerprint

These two unblock WZP integration tasks WZP-S-2 (accept FC tokens)
and WZP-S-3 (signaling bridge mode).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 09:13:23 +04:00
Siavash Sameni
fb987da8ac v0.0.20: file transfer in groups
/file <path> now works in group mode (#group):
- Sends file header + chunks to each group member
- Same fan-out approach as group text messages
- Each member receives and reassembles independently
- Progress shown: "Sending 'file.pdf' to group #ops..."

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 20:23:19 +04:00
Siavash Sameni
1601decf33 v0.0.19: contact list + message history (local, persistent)
Storage:
- contacts sled tree: auto-tracked on send/receive
  - fingerprint, alias, first_seen, last_seen, message_count
- history sled tree: all messages stored locally
  - key: hist:<peer_fp>:<timestamp>:<uuid> for ordered scan
  - sender, text, is_self, timestamp

TUI commands:
- /contacts or /c — list all contacts (sorted by most recent)
  Shows alias, fingerprint, message count
- /history or /h — show last 50 messages with current peer
- /h <fingerprint> — show history with specific peer

Auto-tracking:
- On send: touch_contact + store_message (is_self=true)
- On receive: touch_contact + store_message (is_self=false)
- Both KeyExchange and Message variants tracked

Backup: contacts + history included in export_all (encrypted backup).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 20:16:22 +04:00
Siavash Sameni
741e6fbcfd v0.0.18: proper line editing in TUI input
Keyboard shortcuts:
- Left/Right: move cursor
- Home / Ctrl+A: beginning of line
- End / Ctrl+E: end of line
- Alt+Left/Right: word jump
- Alt+Backspace: delete word back
- Ctrl+W: delete word back
- Ctrl+U: clear entire line
- Ctrl+K: kill to end of line
- Delete: delete char at cursor
- Backspace: delete char before cursor

Cursor position tracked, chars insert at cursor (not just append).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 20:04:12 +04:00
Siavash Sameni
a4405b4976 v0.0.17: fix /r reply in TUI, /p shortcut, /eth, /unalias
TUI fixes:
- /r and /reply now work: tracks last_dm_peer from received messages
- /r switches peer to last DM sender, then type normally
- /p @alias works as shortcut for /peer @alias
- /eth shows Ethereum address in TUI
- /unalias removes your alias

Web fixes:
- /p @alias and /peer @alias resolve and set peer
- /r and /reply work (switch to last DM sender)
- /unalias removes alias
- /admin-unalias <alias> <password> for admin removal
- File download now shows as clickable link (not auto-download)

Server:
- POST /v1/alias/unregister — remove own alias
- POST /v1/alias/admin-remove — admin removes any alias
- WARZONE_ADMIN_PASSWORD env var (default: "admin")

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 19:50:00 +04:00
Siavash Sameni
f4eac7b2aa v0.0.16: clickable file download link instead of auto-download
Files now appear as a styled clickable link in chat:
📎 filename.pdf (1.6 KB) from sender
Click to download. No auto-save dialog.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 18:17:33 +04:00
Siavash Sameni
ebaf5df671 Web file transfer: send + receive with auto-download
Web client:
- Paperclip file upload button in chat bar
- Chunked upload: 64KB chunks, SHA-256 integrity
- Progress display during send/receive
- Auto-download on complete (browser save dialog)
- Max 10MB per file

WASM:
- decrypt_wire_message now returns file_header and file_chunk
  with type, id, filename, chunk data (hex encoded)

Receive flow:
- FileHeader: registers pending transfer
- FileChunk: stores chunk, shows progress
- All chunks received: assembles, triggers blob download

Send flow (web→web or web→CLI):
- File sent as JSON messages (not bincode, for simplicity)
- Receiver handles both JSON and bincode formats

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 16:07:17 +04:00
Siavash Sameni
c9f3e338a7 Add /p as alias for /peer (both TUI and web), web /p @alias support
TUI: /p @manwe works same as /peer @manwe
Web: /p @manwe and /peer @manwe resolve alias and set peer input

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 15:38:35 +04:00
Siavash Sameni
9c70e02eba v0.0.15: unalias, admin alias removal, /reply, web version fix
Aliases:
- /unalias — remove your own alias
- /admin-unalias <alias> <password> — admin removes any alias
- Admin password via WARZONE_ADMIN_PASSWORD env var (default: "admin")
- POST /v1/alias/unregister + POST /v1/alias/admin-remove

Reply:
- /r or /reply — switches peer to whoever last DM'd you
- lastDmPeer tracked on both web and TUI
- Then type normally to reply

Web:
- Version bumped to 0.0.15 (was stuck at 0.0.10)
- WASM rebuilt with latest protocol

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 14:12:33 +04:00
Siavash Sameni
608a160614 Fix warnings: remove unused import and variable
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 13:39:05 +04:00
Siavash Sameni
661de47552 v0.0.14: Ethereum-compatible identity (secp256k1 + Keccak-256)
Protocol (ethereum.rs):
- derive_eth_identity(): HKDF from seed (info="warzone-secp256k1")
- secp256k1 signing key (k256 crate)
- Ethereum address: Keccak-256(uncompressed_pubkey[1..])[-20:]
- EIP-55 checksum address formatting
- eth_sign() / eth_verify() for secp256k1 ECDSA
- EthAddress type with Display, hex parsing, checksum
- 5 tests: deterministic, format, checksum, sign/verify, uniqueness

CLI:
- `warzone eth` — show Ethereum address alongside Warzone fingerprint
- Same seed produces both identities (dual-curve)

Dual identity model:
- Ed25519 + X25519 for Warzone messaging (fast, small signatures)
- secp256k1 for Ethereum compatibility (MetaMask, ENS, Ledger/Trezor)
- Both derived from the same BIP39 seed via different HKDF paths

28/28 protocol tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 13:30:25 +04:00
Siavash Sameni
86da52acc4 v0.0.13: Sender Keys for efficient group encryption
Protocol (sender_keys.rs):
- SenderKey: symmetric key with chain ratchet (forward secrecy per chain)
- generate(), rotate(), encrypt(), decrypt()
- SenderKeyDistribution: share key via 1:1 encrypted channel
- SenderKeyMessage: encrypted group message (O(1) instead of O(N))
- Chain key ratchets forward on each message (HKDF)
- Generation counter for key rotation tracking
- 4 tests: basic, multi-message, rotation, old-key rejection

WireMessage:
- GroupSenderKey variant: encrypted group message
- SenderKeyDistribution variant: key sharing

Server: dedup handles new variants.
CLI TUI + recv: stub handlers for new message types.
23/23 protocol tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 13:23:10 +04:00
Siavash Sameni
653c6c050b v0.0.12: Encrypted backup/restore + history module
Protocol:
- history.rs: derive_history_key (HKDF from seed, info="warzone-history")
- encrypt_history / decrypt_history (ChaCha20-Poly1305, WZH1 magic)
- 2 new tests (roundtrip + wrong seed), total 19/19

CLI:
- `warzone backup [output.wzb]` — exports all sessions + pre-keys
  as encrypted blob (only your seed can decrypt)
- `warzone restore <input.wzb>` — imports backup, merges (no overwrite)
- Backup format: WZH1 magic + nonce + encrypted JSON

Storage:
- export_all() — dumps sessions + pre-keys as base64 JSON
- import_all() — merges backup data (skip existing entries)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 12:59:54 +04:00
Siavash Sameni
fff443bb6d v0.0.11: Multi-device support (server-side)
Server:
- Register stores per-device bundles: device:<fp>:<device_id>
- GET /v1/keys/:fp/devices lists all registered devices
- WS already pushes to ALL connected devices per fingerprint
- DB queue: first device to poll gets messages (acceptable for Phase 2)

Multi-device flow:
- Same seed on two devices → same fingerprint
- Both register with different device_ids
- Both connect via WS → both receive messages in real-time
- Each device maintains its own ratchet sessions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 12:52:22 +04:00
Siavash Sameni
9811248b7c v0.0.10: Progressive Web App (PWA)
- Web manifest (standalone mode, theme, icon)
- Service worker: caches shell (HTML, WASM, icon) for offline
- SVG app icon (chat bubble with encryption indicator)
- iOS meta tags: apple-mobile-web-app-capable, status bar style
- Android: beforeinstallprompt → /install command
- Offline fallback: loads cached shell, shows reconnecting state
- Cache versioning with automatic old cache cleanup

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 12:32:59 +04:00
Siavash Sameni
4fb3973403 v0.0.9: Group management — leave, kick, members
Server:
- POST /groups/:name/leave — remove self from group
- POST /groups/:name/kick — creator can kick members
- GET /groups/:name/members — list with aliases + creator badge

CLI TUI:
- /gleave — leave current group
- /gkick <fp_or_alias> — kick (creator only)
- /gmembers — show member list with aliases and ★ for creator

Web client:
- Same commands: /gleave, /gkick, /gmembers

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