diff --git a/warzone/UAT/PHASE1.md b/warzone/UAT/PHASE1.md new file mode 100644 index 0000000..626f2ba --- /dev/null +++ b/warzone/UAT/PHASE1.md @@ -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 +``` + +- [ ] "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/ +``` + +- [ ] 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 "" "Hello from Alice" -s http://localhost:7700 +``` + +- [ ] "No existing session. Fetching key bundle for ..." +- [ ] "Message sent to " + +**T3 (Bob receives):** +```bash +WARZONE_HOME=/tmp/bob cargo run --bin warzone-client -- recv -s http://localhost:7700 +``` + +- [ ] "Received 1 message(s):" +- [ ] `[new session] : Hello from Alice` + +**Bob sends reply:** +```bash +WARZONE_HOME=/tmp/bob cargo run --bin warzone-client -- send "" "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] : 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 "" -s http://localhost:7700 +``` + +**T3 (Bob):** +```bash +WARZONE_HOME=/tmp/bob cargo run --bin warzone-client -- chat "" -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 → ` and `@bob → ` + +--- + +## 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":""}' +``` + +- [ ] 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":"","new_fingerprint":""}' +``` + +- [ ] "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":""}' +``` + +- [ ] 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//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":"","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//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 "" "message 1" -s http://localhost:7700 +cargo run --bin warzone-client -- send "" "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: _______________ diff --git a/warzone/UAT/PHASE2.md b/warzone/UAT/PHASE2.md new file mode 100644 index 0000000..79ece14 --- /dev/null +++ b/warzone/UAT/PHASE2.md @@ -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 +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/` + +--- + +## 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:** _______________ diff --git a/warzone/UAT/PHASE3.md b/warzone/UAT/PHASE3.md new file mode 100644 index 0000000..f5c6ebb --- /dev/null +++ b/warzone/UAT/PHASE3.md @@ -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:** _______________ diff --git a/warzone/UAT/PHASE4.md b/warzone/UAT/PHASE4.md new file mode 100644 index 0000000..71ef051 --- /dev/null +++ b/warzone/UAT/PHASE4.md @@ -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 ` +- [ ] 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:** _______________ diff --git a/warzone/UAT/PHASE5.md b/warzone/UAT/PHASE5.md new file mode 100644 index 0000000..a83604f --- /dev/null +++ b/warzone/UAT/PHASE5.md @@ -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 +``` + +- [ ] 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:** _______________ diff --git a/warzone/UAT/PHASE6.md b/warzone/UAT/PHASE6.md new file mode 100644 index 0000000..2c90fdb --- /dev/null +++ b/warzone/UAT/PHASE6.md @@ -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 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:** _______________ diff --git a/warzone/UAT/PHASE7.md b/warzone/UAT/PHASE7.md new file mode 100644 index 0000000..f007ed7 --- /dev/null +++ b/warzone/UAT/PHASE7.md @@ -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 ` — blocks user from server +- [ ] `admin unban ` — unblocks user +- [ ] `admin list-mules` — shows authorized mules +- [ ] `admin authorize-mule ` — authorizes a mule +- [ ] `admin revoke-mule ` — 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:** _______________