Files
featherChat/warzone/UAT/PHASE1.md
Siavash Sameni c8b51fa96b UAT test plans for all 7 phases
UAT/PHASE1.md — 20 test scenarios, 80+ checkboxes
  Identity, encryption, messaging, TUI, web, groups, aliases,
  auth, OTP replenishment, session persistence, cross-client

UAT/PHASE2.md — 7 scenarios (WASM, receipts, files, multi-device, HW wallet, groups, history)
UAT/PHASE3.md — 6 scenarios (DNS discovery, key transparency, federation, mutual TLS, gossip)
UAT/PHASE4.md — 10 scenarios (mule identity, pickup, delivery, receipts, dedup, expiry, compression)
UAT/PHASE5.md — 6 scenarios (Bluetooth, LoRa, mDNS, Wi-Fi Direct, USB export, fallback chain)
UAT/PHASE6.md — 3 scenarios (sealed sender, traffic analysis resistance, onion routing)
UAT/PHASE7.md — 8 scenarios (ntfy, DoH, DB encryption, admin CLI, rate limiting, audit, CI, monitoring)

Each test has exact commands to run and checkboxes for pass/fail.

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

12 KiB

Phase 1 — User Acceptance Testing

Prerequisites

cd warzone
cargo build
rm -rf warzone-data  # clean server DB

Open 3 terminals:

  • T1: Server
  • T2: Alice (default ~/.warzone)
  • T3: Bob (WARZONE_HOME=/tmp/bob)

1. Server Startup

T1:

cargo run --bin warzone-server
  • Server prints "Listening on 0.0.0.0:7700"
  • curl http://localhost:7700/v1/health returns {"status":"ok","version":"0.1.0"}
  • http://localhost:7700/ loads the web UI in a browser

2. Identity Generation

T2 (Alice):

cargo run --bin warzone-client -- init
  • Prompted "Set passphrase (empty for no encryption):"
  • Input is hidden (no echo)
  • Prompted "Confirm passphrase:"
  • Fingerprint displayed in format xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
  • 24-word BIP39 mnemonic displayed
  • Seed path shown (e.g. /Users/you/.warzone/identity.seed)
  • "Generated 1 signed pre-key + 10 one-time pre-keys" shown
  • File ~/.warzone/identity.seed exists
  • File ~/.warzone/bundle.bin exists
  • File permissions on identity.seed are 600 (Unix): ls -la ~/.warzone/identity.seed

T3 (Bob):

WARZONE_HOME=/tmp/bob cargo run --bin warzone-client -- init
  • Bob gets a different fingerprint than Alice
  • Seed saved to /tmp/bob/identity.seed
  • Bob's mnemonic is different from Alice's

3. Seed Encryption

T2 (Alice):

cargo run --bin warzone-client -- info
  • Prompted for passphrase (if one was set during init)
  • Fingerprint, signing key, and encryption key displayed
  • Same fingerprint as during init
  • Wrong passphrase shows "Wrong passphrase" error

Test plaintext seed (empty passphrase):

WARZONE_HOME=/tmp/test cargo run --bin warzone-client -- init
# press Enter twice for empty passphrase
xxd /tmp/test/identity.seed | head -1
  • File is exactly 32 bytes (raw seed, no encryption header)

Test encrypted seed:

xxd ~/.warzone/identity.seed | head -1
  • File starts with 575a 5331 (hex for "WZS1" magic bytes)
  • File is larger than 32 bytes (salt + nonce + ciphertext)

4. Mnemonic Recovery

WARZONE_HOME=/tmp/recovered cargo run --bin warzone-client -- recover <paste 24 words from Alice's init>
  • "Identity recovered!" shown
  • Fingerprint matches Alice's original fingerprint
  • WARZONE_HOME=/tmp/recovered cargo run --bin warzone-client -- info shows same keys

5. Key Registration

T2 (Alice):

cargo run --bin warzone-client -- register -s http://localhost:7700

T3 (Bob):

WARZONE_HOME=/tmp/bob cargo run --bin warzone-client -- register -s http://localhost:7700

Verify on server:

curl http://localhost:7700/v1/keys/list
  • JSON shows 2 keys with Alice's and Bob's fingerprints (hex, no colons)

Verify lookup works:

curl http://localhost:7700/v1/keys/<bob-fingerprint-no-colons>
  • Returns JSON with fingerprint and bundle (base64 string)
  • Does NOT return 404

6. 1:1 E2E Encrypted Messaging (CLI)

T2 (Alice sends to Bob):

cargo run --bin warzone-client -- send "<bob-fingerprint>" "Hello from Alice" -s http://localhost:7700
  • "No existing session. Fetching key bundle for ..."
  • "Message sent to "

T3 (Bob receives):

WARZONE_HOME=/tmp/bob cargo run --bin warzone-client -- recv -s http://localhost:7700
  • "Received 1 message(s):"
  • [new session] <alice-fingerprint>: Hello from Alice

Bob sends reply:

WARZONE_HOME=/tmp/bob cargo run --bin warzone-client -- send "<alice-fingerprint>" "Hi Alice, Bob here" -s http://localhost:7700
  • "Message sent to ..." (no "new session" — reuses existing ratchet)

Alice receives:

cargo run --bin warzone-client -- recv -s http://localhost:7700
  • [new session] <bob-fingerprint>: Hi Alice, Bob here

7. Fetch-and-Delete (No Duplicate Delivery)

T3 (Bob polls again):

WARZONE_HOME=/tmp/bob cargo run --bin warzone-client -- recv -s http://localhost:7700
  • "No new messages." (Alice's message was deleted on first poll)

8. TUI Chat (CLI)

T2 (Alice):

cargo run --bin warzone-client -- chat "<bob-fingerprint>" -s http://localhost:7700

T3 (Bob):

WARZONE_HOME=/tmp/bob cargo run --bin warzone-client -- chat "<alice-fingerprint>" -s http://localhost:7700
  • Both TUIs launch with header showing fingerprints
  • Alice types "hello from TUI" → Enter
  • Message appears in green on Alice's screen
  • Within 2 seconds, message appears in yellow on Bob's screen
  • Bob types "reply from Bob" → Enter
  • Message appears on both screens
  • /info shows fingerprint
  • /quit exits TUI cleanly (terminal restored)
  • Ctrl+C also exits cleanly
  • Esc also exits cleanly

9. Groups (CLI TUI)

T2 (Alice, in TUI):

/g ops
  • "Joined 'ops'" or "Group 'ops' auto-created"
  • "Switched to group #ops"

T3 (Bob, in TUI):

/g ops
  • "Joined 'ops'"
  • "Switched to group #ops"

Alice types a message:

hello team
  • Message appears on Alice's screen with [#ops] tag
  • Message appears on Bob's screen within 2 seconds

Bob replies:

hey alice!
  • Appears on both screens

Test group list:

/glist
  • Shows #ops (2 members)

Switch back to DM:

/dm
  • "Switched to DM mode"

10. Aliases (CLI TUI)

T2 (Alice, in TUI):

/alias alice
  • "Alias @alice registered"

T3 (Bob, in TUI):

/alias bob
  • "Alias @bob registered"

Alice sets peer by alias:

/peer @bob
  • "@bob → " resolved
  • "Peer set to "

List aliases:

/aliases
  • Shows @alice → <fp> and @bob → <fp>

11. Web UI — Identity

Open http://localhost:7700/ in a browser.

  • "WARZONE" title and "Generate Identity" button shown
  • Click "Generate Identity"
  • Fingerprint displayed in green
  • Hex seed displayed in orange
  • "Enter Chat" button shown
  • Click "Enter Chat"
  • Chat screen loads with header showing fingerprint
  • "Key registered with server" message appears
  • Refresh page → auto-loads identity (no setup screen)

12. Web UI — DM

Open TWO browser tabs/windows (or incognito for second identity).

Tab 1: Generate identity → Enter Chat Tab 2: Generate identity → Enter Chat

Tab 1: Paste Tab 2's fingerprint in peer input field. Type "hello from tab 1". Enter.

  • Message appears in green on Tab 1
  • Message appears with lock icon on Tab 2 within 2 seconds

Tab 2: Paste Tab 1's fingerprint. Type "hello back". Enter.

  • Message appears on both tabs

13. Web UI — Groups

Tab 1:

/g webteam
  • "Joined group" and "Switched to group" messages

Tab 2:

/g webteam
  • Also joined

Tab 1: Type "hello webteam" → Enter

  • Message appears on Tab 1 with [webteam] tag
  • Message appears on Tab 2 within 2 seconds

14. Web UI — Aliases

Tab 1:

/alias webuser1
  • "Alias @webuser1 registered"

Tab 1:

/info
  • Shows fingerprint with (@webuser1) suffix

Tab 2: Set peer input to @webuser1. Type message. Enter.

  • Message delivered (alias resolved to fingerprint)

15. Alias TTL & Recovery

Register alias via curl:

curl -X POST http://localhost:7700/v1/alias/register \
  -H 'Content-Type: application/json' \
  -d '{"alias":"testuser","fingerprint":"<alice-fp-no-colons>"}'
  • Response includes recovery_key (32-char hex)
  • Response includes expires_in_days: 365
  • SAVE THE RECOVERY KEY

Check alias:

curl http://localhost:7700/v1/alias/resolve/testuser
  • Returns fingerprint + expires_in_days

Recover alias to new fingerprint:

curl -X POST http://localhost:7700/v1/alias/recover \
  -H 'Content-Type: application/json' \
  -d '{"alias":"testuser","recovery_key":"<saved-key>","new_fingerprint":"<bob-fp-no-colons>"}'
  • "ok: true"
  • new_recovery_key returned (rotated)

Verify transfer:

curl http://localhost:7700/v1/alias/resolve/testuser
  • Now points to Bob's fingerprint

Wrong recovery key:

curl -X POST http://localhost:7700/v1/alias/recover \
  -H 'Content-Type: application/json' \
  -d '{"alias":"testuser","recovery_key":"wrong","new_fingerprint":"aaaa"}'
  • "error: invalid recovery key"

16. Server Auth (Challenge-Response)

Request challenge:

curl -X POST http://localhost:7700/v1/auth/challenge \
  -H 'Content-Type: application/json' \
  -d '{"fingerprint":"<alice-fp-no-colons>"}'
  • Returns challenge (64-char hex) and expires_at (unix timestamp)
  • Challenge expires in ~60 seconds

17. OTP Key Replenishment

Check count:

curl http://localhost:7700/v1/keys/<alice-fp-no-colons>/otpk-count
  • Returns otpk_count (number, may be 0 if not yet stored separately)

Replenish:

curl -X POST http://localhost:7700/v1/keys/replenish \
  -H 'Content-Type: application/json' \
  -d '{"fingerprint":"<alice-fp-no-colons>","otpks":[{"id":100,"public_key":"aa"},{"id":101,"public_key":"bb"}]}'
  • Returns stored: 2 and total count

Verify count increased:

curl http://localhost:7700/v1/keys/<alice-fp-no-colons>/otpk-count
  • otpk_count increased by 2

18. Protocol Unit Tests

cargo test -p warzone-protocol
  • identity::tests::deterministic_derivation — PASS
  • identity::tests::mnemonic_roundtrip — PASS
  • identity::tests::fingerprint_display — PASS
  • mnemonic::tests::roundtrip — PASS
  • crypto::tests::aead_roundtrip — PASS
  • crypto::tests::aead_wrong_key_fails — PASS
  • crypto::tests::aead_wrong_aad_fails — PASS
  • crypto::tests::hkdf_deterministic — PASS
  • prekey::tests::signed_pre_key_verify — PASS
  • prekey::tests::signed_pre_key_reject_tampered — PASS
  • prekey::tests::generate_otpks — PASS
  • x3dh::tests::x3dh_shared_secret_matches — PASS
  • ratchet::tests::basic_exchange — PASS
  • ratchet::tests::bidirectional — PASS
  • ratchet::tests::multiple_messages_same_direction — PASS
  • ratchet::tests::out_of_order — PASS
  • ratchet::tests::many_messages — PASS

Total: 17/17 PASS


19. Session Persistence

T2 (Alice, send then quit):

cargo run --bin warzone-client -- send "<bob-fp>" "message 1" -s http://localhost:7700
cargo run --bin warzone-client -- send "<bob-fp>" "message 2" -s http://localhost:7700
  • First send says "No existing session" (X3DH)
  • Second send does NOT say "No existing session" (reuses saved ratchet)
  • ls ~/.warzone/db/ shows sled database files

T3 (Bob receives both):

WARZONE_HOME=/tmp/bob cargo run --bin warzone-client -- recv -s http://localhost:7700
  • Both messages decrypted correctly
  • Messages in order

20. Cross-Client Compatibility

Web → CLI:

Web Tab sends message to CLI Alice's fingerprint.

  • CLI recv shows [encrypted message from CLI client — use CLI to read] OR fails gracefully
  • No crash on either side

CLI → Web:

CLI Alice sends to Web Tab's fingerprint.

  • Web shows graceful error (different crypto) or ignores silently
  • No crash on either side

Note: Web↔CLI interop requires WASM bridge (Phase 2). Currently incompatible crypto is expected.


Summary

# Feature Result
1 Server startup
2 Identity generation
3 Seed encryption
4 Mnemonic recovery
5 Key registration
6 1:1 E2E messaging
7 Fetch-and-delete
8 TUI chat
9 Groups (CLI)
10 Aliases (CLI)
11 Web UI identity
12 Web UI DM
13 Web UI groups
14 Web UI aliases
15 Alias TTL & recovery
16 Server auth
17 OTP replenishment
18 Protocol tests (17/17)
19 Session persistence
20 Cross-client compat

Tester: _______________ Date: _______________ Build: cargo build commit hash: _______________