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>
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>
- 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>
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>
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>
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>