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:
553
warzone/UAT/PHASE1.md
Normal file
553
warzone/UAT/PHASE1.md
Normal 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
163
warzone/UAT/PHASE2.md
Normal 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
128
warzone/UAT/PHASE3.md
Normal 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
157
warzone/UAT/PHASE4.md
Normal 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
148
warzone/UAT/PHASE5.md
Normal 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
73
warzone/UAT/PHASE6.md
Normal 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
174
warzone/UAT/PHASE7.md
Normal 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:** _______________
|
||||
Reference in New Issue
Block a user