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>
This commit is contained in:
Siavash Sameni
2026-03-27 08:01:36 +04:00
parent cfb227a93d
commit c8b51fa96b
7 changed files with 1396 additions and 0 deletions

553
warzone/UAT/PHASE1.md Normal file
View File

@@ -0,0 +1,553 @@
# Phase 1 — User Acceptance Testing
## Prerequisites
```bash
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:**
```bash
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):**
```bash
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):**
```bash
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):**
```bash
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):**
```bash
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:**
```bash
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
```bash
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):**
```bash
cargo run --bin warzone-client -- register -s http://localhost:7700
```
- [ ] "Bundle registered with http://localhost:7700"
**T3 (Bob):**
```bash
WARZONE_HOME=/tmp/bob cargo run --bin warzone-client -- register -s http://localhost:7700
```
- [ ] "Bundle registered with http://localhost:7700"
**Verify on server:**
```bash
curl http://localhost:7700/v1/keys/list
```
- [ ] JSON shows 2 keys with Alice's and Bob's fingerprints (hex, no colons)
**Verify lookup works:**
```bash
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):**
```bash
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 <bob-fingerprint>"
**T3 (Bob receives):**
```bash
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:**
```bash
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:**
```bash
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):**
```bash
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):**
```bash
cargo run --bin warzone-client -- chat "<bob-fingerprint>" -s http://localhost:7700
```
**T3 (Bob):**
```bash
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 → <bob-fingerprint>" resolved
- [ ] "Peer set to <bob-fingerprint>"
**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:**
```bash
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:**
```bash
curl http://localhost:7700/v1/alias/resolve/testuser
```
- [ ] Returns fingerprint + `expires_in_days`
**Recover alias to new fingerprint:**
```bash
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:**
```bash
curl http://localhost:7700/v1/alias/resolve/testuser
```
- [ ] Now points to Bob's fingerprint
**Wrong recovery key:**
```bash
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:**
```bash
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:**
```bash
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:**
```bash
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:**
```bash
curl http://localhost:7700/v1/keys/<alice-fp-no-colons>/otpk-count
```
- [ ] `otpk_count` increased by 2
---
## 18. Protocol Unit Tests
```bash
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):**
```bash
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):**
```bash
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: _______________

163
warzone/UAT/PHASE2.md Normal file
View File

@@ -0,0 +1,163 @@
# Phase 2 — User Acceptance Testing
> Phase 2 is NOT YET IMPLEMENTED. This is a pre-written test plan.
## Prerequisites
- Phase 1 UAT fully passing
- WASM toolchain installed (`wasm-pack`)
- Two devices or VMs for multi-device testing
---
## 1. WASM Build (Web-CLI Interop)
```bash
cd warzone/crates/warzone-protocol
wasm-pack build --target web
```
- [ ] WASM build succeeds
- [ ] Web client loads WASM module
- [ ] Web client uses X25519 + ChaCha20 (same as CLI)
- [ ] Web → CLI: message sent from browser, decrypted by CLI `recv`
- [ ] CLI → Web: message sent from CLI, decrypted in browser
- [ ] Bidirectional conversation works across web and CLI
---
## 2. Delivery Receipts
**Alice sends to Bob:**
- [ ] Alice's UI shows "sent" checkmark (✓) after server accepts
- [ ] When Bob's client polls and receives, server generates delivery receipt
- [ ] Alice's UI updates to "delivered" (✓✓)
- [ ] When Bob reads/decrypts, Bob's client sends read receipt
- [ ] Alice's UI updates to "read" (✓✓ blue/colored)
**Offline Bob:**
- [ ] Alice sends while Bob is offline
- [ ] "sent" (✓) shown immediately
- [ ] Bob comes online, polls → "delivered" (✓✓) on Alice's side
- [ ] Receipts themselves are E2E encrypted
---
## 3. File Transfer
**CLI:**
```
/file /path/to/document.pdf
```
- [ ] File is chunked, encrypted, and sent
- [ ] Recipient sees "[file: document.pdf (1.2 MB)]"
- [ ] `/save` or auto-download saves to disk
- [ ] File integrity check (hash matches)
- [ ] Files up to 10 MB work
- [ ] Progress shown during transfer
**Web:**
- [ ] File upload button in chat
- [ ] File encrypted and sent
- [ ] Recipient gets download link
- [ ] Downloaded file is correct
---
## 4. Multi-Device
**Setup: Alice on two devices (same seed):**
```bash
# Device 1
cargo run --bin warzone-client -- init
# Note mnemonic
# Device 2
WARZONE_HOME=/tmp/alice2 cargo run --bin warzone-client -- recover <mnemonic>
WARZONE_HOME=/tmp/alice2 cargo run --bin warzone-client -- register -s http://localhost:7700
```
- [ ] Both devices have same fingerprint
- [ ] Bob sends to Alice's fingerprint
- [ ] Device 1 receives and decrypts
- [ ] Device 2 receives and decrypts (separate session)
- [ ] Messages sent from Device 1 are visible on Device 2 (via sync)
- [ ] Device list shown on server: `GET /v1/devices/<fingerprint>`
---
## 5. Hardware Wallet Delegation
**Connect Ledger/Trezor:**
```bash
cargo run --bin warzone-client -- hw-delegate
```
- [ ] Detects hardware wallet via USB
- [ ] Shows "Sign delegation certificate on device"
- [ ] User confirms on hardware wallet
- [ ] Session key generated, delegation cert stored
- [ ] Subsequent operations use session key (no wallet needed)
- [ ] After 30 days, prompts for re-delegation
**Without hardware wallet (session key only):**
- [ ] All operations work using cached session key
- [ ] No USB prompts during normal chat
---
## 6. Group Management
**Kick member:**
```
/gkick @troublemaker
```
- [ ] Member removed from group
- [ ] Sender Keys rotated for remaining members
- [ ] Kicked member can no longer decrypt new messages
**Leave group:**
```
/gleave ops
```
- [ ] You are removed
- [ ] Remaining members rotate keys
**Group info:**
```
/ginfo ops
```
- [ ] Shows: name, creator, member list, creation date
---
## 7. Message History Persistence
- [ ] Close and reopen TUI → previous messages still shown
- [ ] History stored in local sled DB
- [ ] `/history 50` shows last 50 messages
- [ ] History is encrypted at rest (tied to seed)
---
## Summary
| # | Feature | Result |
|---|---------|--------|
| 1 | WASM web-CLI interop | ☐ |
| 2 | Delivery receipts | ☐ |
| 3 | File transfer | ☐ |
| 4 | Multi-device | ☐ |
| 5 | Hardware wallet delegation | ☐ |
| 6 | Group management | ☐ |
| 7 | Message history | ☐ |
**Tester:** _______________
**Date:** _______________

128
warzone/UAT/PHASE3.md Normal file
View File

@@ -0,0 +1,128 @@
# Phase 3 — User Acceptance Testing (Federation & Key Transparency)
> Phase 3 is NOT YET IMPLEMENTED. This is a pre-written test plan.
## Prerequisites
- Phase 2 UAT fully passing
- Two warzone-server instances on different domains
- DNS zone control for both domains
---
## 1. DNS Server Discovery
**Setup TXT record:**
```
_warzone._tcp.a1.example.com TXT "v=wz1; endpoint=https://wz.a1.example.com; pubkey=base64..."
```
**Test discovery:**
```bash
cargo run --bin warzone-client -- discover a1.example.com
```
- [ ] Resolves TXT record
- [ ] Shows endpoint URL and server public key
- [ ] Server pubkey pinned on first contact (TOFU)
---
## 2. DNS Key Transparency
**Publish key to DNS:**
```bash
cargo run --bin warzone-client -- publish-key --domain a1.example.com
```
- [ ] TXT record created: `manwe.a1.example.com TXT "v=wz1; fp=...; pubkey=...; sig=..."`
- [ ] Self-signature is valid
- [ ] Only server's delegated zone is modified
**Verify key via DNS:**
```bash
cargo run --bin warzone-client -- verify-key @manwe.a1.example.com
```
- [ ] Fetches TXT record
- [ ] Verifies self-signature
- [ ] Compares against server-provided key
- [ ] Match → "Key verified via DNS"
- [ ] Mismatch → "WARNING: server may be performing MITM"
- [ ] No DNS record → "Falling back to TOFU"
---
## 3. Federated Messaging
**Server A (a1.example.com) and Server B (b1.example.com):**
Alice is on Server A, Bob is on Server B.
**Alice sends to Bob:**
```
/dm @bob.b1.example.com hello from server A!
```
- [ ] Client resolves `b1.example.com` via DNS
- [ ] Fetches Bob's bundle from Server B
- [ ] X3DH + Ratchet encrypt
- [ ] Message sent via Server A → Server B relay
- [ ] Bob receives on Server B
- [ ] Bob decrypts successfully
**Bob replies:**
```
/dm @alice.a1.example.com hey alice!
```
- [ ] Reverse path works (B → A)
- [ ] Existing ratchet session reused
---
## 4. Server-to-Server Mutual TLS
- [ ] Server A connects to Server B with TLS
- [ ] Both servers verify each other's pubkey (from DNS TXT)
- [ ] Invalid server pubkey → connection refused
- [ ] Man-in-the-middle between servers → TLS fails
---
## 5. Gossip Peer Discovery
**Server A knows Server B. Server C joins:**
- [ ] Server C registers with Server A
- [ ] Server A gossips Server C's endpoint to Server B
- [ ] Server B can now route messages to Server C users
- [ ] No manual configuration needed on Server B
---
## 6. Hard-coded Peer List (DNS Fallback)
**DNS is down:**
```bash
cargo run --bin warzone-server -- --peers "https://wz.b1.example.com,https://wz.c1.example.com"
```
- [ ] Server connects to listed peers directly
- [ ] Federated messaging works without DNS
---
## Summary
| # | Feature | Result |
|---|---------|--------|
| 1 | DNS server discovery | ☐ |
| 2 | DNS key transparency | ☐ |
| 3 | Federated messaging | ☐ |
| 4 | Server mutual TLS | ☐ |
| 5 | Gossip peer discovery | ☐ |
| 6 | Hard-coded peer fallback | ☐ |
**Tester:** _______________
**Date:** _______________

157
warzone/UAT/PHASE4.md Normal file
View File

@@ -0,0 +1,157 @@
# Phase 4 — User Acceptance Testing (Warzone Delivery / Mule Protocol)
> Phase 4 is NOT YET IMPLEMENTED. This is a pre-written test plan.
## Prerequisites
- Phase 3 UAT fully passing
- Two isolated networks (can use VMs or Docker networks)
- A device that can move between networks (the mule)
---
## 1. Mule Identity & Authorization
```bash
cargo run --bin warzone-mule -- init
cargo run --bin warzone-mule -- register -s http://server-a:7700
```
- [ ] Mule generates its own identity
- [ ] Mule registered with Server A
- [ ] Server admin authorizes mule: `warzone-server admin authorize-mule <mule-fp>`
- [ ] Unauthorized mule rejected on pickup attempt
---
## 2. Message Pickup
**Server A has queued messages for users on Server B (which is offline):**
```bash
cargo run --bin warzone-mule -- pickup -s http://server-a:7700
```
- [ ] Mule connects to Server A
- [ ] Mule authenticates (challenge-response)
- [ ] Server returns queued outbound messages (encrypted blobs)
- [ ] Messages marked as "IN_TRANSIT by mule X" on Server A
- [ ] Mule stores messages locally
- [ ] Mule reports capacity: "Picked up 42 messages (1.2 MB / 50 MB capacity)"
---
## 3. Physical Transport & Delivery
**Mule moves to Server B's network:**
```bash
cargo run --bin warzone-mule -- deliver -s http://server-b:7700
```
- [ ] Mule connects to Server B
- [ ] Delivers encrypted blobs
- [ ] Server B queues messages for local recipients
- [ ] Server B returns delivery receipts (signed)
- [ ] Mule stores receipts locally
---
## 4. Receipt Delivery
**Mule returns to Server A's network:**
```bash
cargo run --bin warzone-mule -- receipts -s http://server-a:7700
```
- [ ] Mule delivers receipts to Server A
- [ ] Server A marks messages as DELIVERED
- [ ] Server A removes messages from outbound queue
---
## 5. Receipt Enforcement
**Mule tries to pick up again WITHOUT delivering previous receipts:**
```bash
cargo run --bin warzone-mule -- pickup -s http://server-a:7700
```
- [ ] Server A rejects: "outstanding receipts not delivered"
- [ ] Mule must deliver receipts first (or submit signed failure report)
---
## 6. Deduplication
**Two mules pick up the same messages:**
- [ ] Mule 1 picks up and delivers to Server B
- [ ] Mule 2 picks up same messages (still in transit)
- [ ] Mule 2 delivers to Server B
- [ ] Server B deduplicates: messages delivered once, no duplicates for recipients
---
## 7. Message Expiry
**Messages older than TTL:**
- [ ] Server queues message with 7-day TTL
- [ ] After 7 days without pickup → status changes to EXPIRED
- [ ] Expired messages not given to mules
- [ ] Expired messages cleaned up from DB
---
## 8. Outer Encryption (Metadata Hiding)
- [ ] Messages from Server A to Server B wrapped in outer encryption (Server B's pubkey)
- [ ] Mule sees only: "encrypted blob for Server B"
- [ ] Mule cannot see sender/recipient fingerprints
- [ ] Server B unwraps outer layer, routes inner messages to recipients
---
## 9. Partial Sync / Resume
**Mule connection interrupted during pickup:**
```bash
cargo run --bin warzone-mule -- pickup -s http://server-a:7700
# kill connection mid-transfer
cargo run --bin warzone-mule -- pickup -s http://server-a:7700
```
- [ ] Second pickup resumes from where it left off
- [ ] No duplicate messages in mule's local store
---
## 10. Compression
- [ ] Message bundles compressed with zstd before transfer
- [ ] Mule reports compressed size: "42 messages: 1.2 MB → 400 KB (67% compression)"
- [ ] Decompression on delivery
---
## Summary
| # | Feature | Result |
|---|---------|--------|
| 1 | Mule identity & auth | ☐ |
| 2 | Message pickup | ☐ |
| 3 | Physical delivery | ☐ |
| 4 | Receipt delivery | ☐ |
| 5 | Receipt enforcement | ☐ |
| 6 | Deduplication | ☐ |
| 7 | Message expiry | ☐ |
| 8 | Outer encryption | ☐ |
| 9 | Partial sync | ☐ |
| 10 | Compression | ☐ |
**Tester:** _______________
**Date:** _______________

148
warzone/UAT/PHASE5.md Normal file
View File

@@ -0,0 +1,148 @@
# Phase 5 — User Acceptance Testing (Transport Fallbacks)
> Phase 5 is NOT YET IMPLEMENTED. This is a pre-written test plan.
## Prerequisites
- Phase 4 UAT fully passing
- Bluetooth-capable devices
- LoRa hardware (e.g. Heltec ESP32 LoRa, RAK WisBlock)
- Two devices on same Wi-Fi for Wi-Fi Direct testing
---
## 1. Bluetooth Mule Transfer
**Mule device (phone/laptop) near Server A:**
```bash
cargo run --bin warzone-mule -- pickup --transport bluetooth
```
- [ ] Mule scans for nearby warzone-server via BLE advertisement
- [ ] Connects via Bluetooth Classic (RFCOMM)
- [ ] Picks up messages (same protocol as HTTP, different transport)
- [ ] Transfer speed reasonable (> 100 KB/s)
**Mule near Server B:**
```bash
cargo run --bin warzone-mule -- deliver --transport bluetooth
```
- [ ] Delivers messages via Bluetooth
- [ ] Receipts returned
---
## 2. LoRa Transport (Emergency)
**Setup two LoRa nodes with warzone-mule:**
```bash
cargo run --bin warzone-mule -- lora-beacon --freq 868.0
```
- [ ] Device broadcasts presence beacon (< 50 bytes)
- [ ] Nearby LoRa node detects beacon
**Send short text over LoRa:**
```bash
cargo run --bin warzone-mule -- lora-send "SOS need evac" --to <fingerprint>
```
- [ ] Message fits in single LoRa packet (< 250 bytes)
- [ ] Compact binary format used (not JSON)
- [ ] Recipient receives and decrypts
- [ ] Delivery receipt sent back over LoRa
**LoRa limitations:**
- [ ] Messages > 200 chars rejected with warning
- [ ] Files cannot be sent over LoRa
- [ ] Latency shown: "Sent via LoRa (estimated 2-5 seconds)"
---
## 3. mDNS / LAN Discovery
**Two devices on same LAN, no internet:**
```bash
cargo run --bin warzone-server -- --mdns
```
- [ ] Server advertises via mDNS: `_warzone._tcp.local`
- [ ] Client discovers server without typing IP/URL:
```bash
cargo run --bin warzone-client -- chat --discover
```
- [ ] Shows: "Found warzone server at 192.168.1.42:7700"
- [ ] Chat works normally over LAN
---
## 4. Wi-Fi Direct (Nearby Mesh)
**Two devices, no router needed:**
```bash
cargo run --bin warzone-client -- chat --wifi-direct
```
- [ ] Devices discover each other via Wi-Fi Direct
- [ ] Form ad-hoc connection
- [ ] Messages synced peer-to-peer (no server)
- [ ] Group sync: all messages replicated to all peers in range
- [ ] Bandwidth: > 10 MB/s
---
## 5. USB / Sneakernet Export
**Export messages:**
```bash
cargo run --bin warzone-client -- export --since 24h --to /mnt/usb/messages.wz
```
- [ ] Messages exported as encrypted file
- [ ] File is portable (copy to USB drive)
- [ ] Export size shown: "Exported 142 messages (2.3 MB)"
**Import on another machine:**
```bash
cargo run --bin warzone-client -- import /mnt/usb/messages.wz
```
- [ ] Messages imported and decrypted
- [ ] Deduplication: already-seen messages skipped
- [ ] "Imported 142 messages (38 new)"
---
## 6. Transport Fallback Priority
**Configure fallback chain:**
```
warzone-server --transport https,bluetooth,lora
```
- [ ] Server tries HTTPS first
- [ ] If HTTPS fails → falls back to Bluetooth
- [ ] If Bluetooth unavailable → falls back to LoRa
- [ ] Each fallback logged with reason
---
## Summary
| # | Feature | Result |
|---|---------|--------|
| 1 | Bluetooth mule | ☐ |
| 2 | LoRa transport | ☐ |
| 3 | mDNS discovery | ☐ |
| 4 | Wi-Fi Direct | ☐ |
| 5 | USB export/import | ☐ |
| 6 | Transport fallback | ☐ |
**Tester:** _______________
**Date:** _______________

73
warzone/UAT/PHASE6.md Normal file
View File

@@ -0,0 +1,73 @@
# Phase 6 — User Acceptance Testing (Metadata Protection)
> Phase 6 is NOT YET IMPLEMENTED. This is a pre-written test plan.
## Prerequisites
- Phase 5 UAT fully passing
- Network traffic analysis tools (Wireshark/tcpdump)
- At least 3 federated servers for onion routing
---
## 1. Sealed Sender
**Alice sends to Bob through server:**
- [ ] Server receives message with recipient fingerprint but NO sender fingerprint
- [ ] Server logs show: "Message for <bob-fp> from [sealed]"
- [ ] Bob decrypts and sees Alice's identity (embedded in ciphertext)
- [ ] Wireshark: server-bound traffic contains no sender metadata
**Server admin inspects DB:**
- [ ] Message queue shows `to` field only, no `from`
- [ ] Cannot determine who sent the message
---
## 2. Traffic Analysis Resistance
**Padding:**
- [ ] All messages padded to fixed sizes (256, 1024, 4096 bytes)
- [ ] Small "hi" and large paragraph produce same-size ciphertext on wire
- [ ] Wireshark confirms uniform packet sizes
**Timing:**
- [ ] Messages not sent immediately — random delay (0-2 seconds)
- [ ] Constant-rate dummy traffic when idle (configurable)
- [ ] Observer cannot distinguish real messages from dummy traffic
---
## 3. Onion Routing (Opt-in)
**Setup: 3 servers (A, B, C). Alice on A, Bob on C.**
```bash
cargo run --bin warzone-client -- chat @bob.c.example.com --onion
```
- [ ] Client builds onion route: A → B → C
- [ ] Message encrypted in 3 layers: encrypt(C, encrypt(B, encrypt(A, plaintext)))
- [ ] Server A sees: "message for Server B" (doesn't know final destination)
- [ ] Server B sees: "message for Server C" (doesn't know origin)
- [ ] Server C sees: "message for Bob" (doesn't know it went through A and B)
- [ ] Bob decrypts successfully
- [ ] Latency: shown as "onion: 3 hops, ~500ms"
**Onion routing disabled (default):**
- [ ] Direct routing: A → C (faster, less privacy)
- [ ] No onion overhead
---
## Summary
| # | Feature | Result |
|---|---------|--------|
| 1 | Sealed sender | ☐ |
| 2 | Traffic analysis resistance | ☐ |
| 3 | Onion routing | ☐ |
**Tester:** _______________
**Date:** _______________

174
warzone/UAT/PHASE7.md Normal file
View File

@@ -0,0 +1,174 @@
# Phase 7 — User Acceptance Testing (Operations & Polish)
> Phase 7 is NOT YET IMPLEMENTED. This is a pre-written test plan.
## Prerequisites
- Phase 6 UAT fully passing
- ntfy server (self-hosted or ntfy.sh)
- CI/CD pipeline configured
---
## 1. ntfy Push Notifications
**Setup:**
```bash
cargo run --bin warzone-server -- --ntfy-url https://ntfy.example.com
```
**Client subscribes:**
```bash
cargo run --bin warzone-client -- notifications --enable
```
- [ ] Client registers ntfy topic (fingerprint-derived)
- [ ] When offline and message arrives, ntfy push notification sent
- [ ] Notification shows: "New message" (NO message content — E2E)
- [ ] Android: ntfy app shows notification
- [ ] iOS: ntfy app shows notification
- [ ] Desktop: ntfy web shows notification
- [ ] Self-hosted ntfy: all above work against own instance
---
## 2. DNS-over-HTTPS (Censored Networks)
**DNS blocked but HTTPS available:**
```bash
cargo run --bin warzone-client -- chat --doh https://1.1.1.1/dns-query
```
- [ ] DNS resolution via HTTPS (bypasses local DNS censorship)
- [ ] Federation discovery works through DoH
- [ ] Key transparency verification works through DoH
- [ ] Fallback to system DNS if DoH fails
---
## 3. Server-at-Rest Encryption
```bash
cargo run --bin warzone-server -- --encrypt-db
# Prompted for passphrase on startup
```
- [ ] sled database encrypted at rest
- [ ] Server restart requires passphrase
- [ ] If server seized (power off), DB is unreadable without passphrase
- [ ] Performance impact: < 10% overhead
- [ ] Without `--encrypt-db`, DB is plaintext (default)
---
## 4. Admin CLI
```bash
cargo run --bin warzone-server -- admin
```
- [ ] `admin list-users` — shows all registered fingerprints + aliases
- [ ] `admin list-groups` — shows all groups + member counts
- [ ] `admin ban <fingerprint>` — blocks user from server
- [ ] `admin unban <fingerprint>` — unblocks user
- [ ] `admin list-mules` — shows authorized mules
- [ ] `admin authorize-mule <fp>` — authorizes a mule
- [ ] `admin revoke-mule <fp>` — revokes mule authorization
- [ ] `admin stats` — shows message counts, active users, queue depth
- [ ] `admin gc` — garbage collect expired messages, tokens, aliases
---
## 5. Rate Limiting
**Spam prevention:**
- [ ] More than 100 messages/minute from one fingerprint → rate limited
- [ ] Rate limit response: HTTP 429 with retry-after header
- [ ] Client shows: "Rate limited, retry in 30 seconds"
- [ ] Group sends: limit per-member, not per-group
**Registration abuse:**
- [ ] More than 5 identities from one IP per hour → blocked
- [ ] Alias registration: max 1 per hour per fingerprint
---
## 6. Audit Logging
```bash
cargo run --bin warzone-server -- --audit-log /var/log/warzone-audit.log
```
- [ ] All authentication events logged (success + failure)
- [ ] Key registrations logged
- [ ] Group create/join/leave logged
- [ ] Alias registrations logged
- [ ] Message metadata logged (from_fp, to_fp, timestamp, size — NO content)
- [ ] Mule pickups/deliveries logged
- [ ] Log format: structured JSON, one event per line
- [ ] Log rotation compatible (logrotate)
---
## 7. Cross-Compilation CI
```bash
cargo build --target x86_64-unknown-linux-gnu
cargo build --target aarch64-unknown-linux-gnu
cargo build --target x86_64-apple-darwin
cargo build --target aarch64-apple-darwin
cargo build --target x86_64-pc-windows-msvc
wasm-pack build --target web crates/warzone-protocol
```
- [ ] Linux x86_64: static binary, runs on Ubuntu/Debian/Alpine
- [ ] Linux aarch64 (ARM): runs on Raspberry Pi / ARM servers
- [ ] macOS x86_64: runs on Intel Macs
- [ ] macOS aarch64: runs on Apple Silicon
- [ ] Windows: runs on Windows 10+
- [ ] WASM: loads in Chrome, Firefox, Safari
- [ ] All binaries < 20 MB
- [ ] CI pipeline runs tests on all platforms
- [ ] Release artifacts uploaded to GitHub/Gitea
---
## 8. Monitoring & Health
**Health check:**
```bash
curl http://localhost:7700/v1/health
```
- [ ] Returns status, version, uptime
- [ ] Queue depth included
- [ ] Active connections count
- [ ] DB size on disk
**Prometheus metrics (optional):**
```bash
curl http://localhost:7700/metrics
```
- [ ] `warzone_messages_total` counter
- [ ] `warzone_active_users` gauge
- [ ] `warzone_queue_depth` gauge
- [ ] `warzone_auth_failures_total` counter
---
## Summary
| # | Feature | Result |
|---|---------|--------|
| 1 | ntfy notifications | ☐ |
| 2 | DNS-over-HTTPS | ☐ |
| 3 | Server-at-rest encryption | ☐ |
| 4 | Admin CLI | ☐ |
| 5 | Rate limiting | ☐ |
| 6 | Audit logging | ☐ |
| 7 | Cross-compilation CI | ☐ |
| 8 | Monitoring & health | ☐ |
**Tester:** _______________
**Date:** _______________