Audit: - docs/AUDIT-2026-05-25.md: full protocol audit covering 8 findings (4 critical, 2 high, 5 medium, 4 low) with code references and fix effort estimates - vault/Audit/Tasks.md: Obsidian Tasks plugin file tracking all audit items with priorities, due dates, and per-step checklists Architecture docs updated for Wire format v2 and Wave 5/6 features: - ARCHITECTURE.md: adds wzp-video to dependency graph and project structure; wire format updated to v2 (16B header, 5B MiniHeader); relay concurrency section corrected (DashMap+RwLock is current, not a future optimization); test count 571→702; Android note - PROGRESS.md: Wave 5 and Wave 6 sections appended; test count 372→702; current status and open blockers as of 2026-05-25 - ROAD-TO-VIDEO.md: implementation status table inserted (✅/🟡/🔴/🔲 per phase); 6-step critical path to first video call - WZP-SPEC.md: MediaHeader updated to v2 (16B byte-aligned); MiniHeader updated to 5B with seq_delta; codec IDs 9-12 added (H.264/H.265/AV1); version negotiation section added Obsidian vault (vault/): - 114 files across Architecture/, PRDs/, Reports/, Android/, Reference/, Audit/ with YAML frontmatter - 00 - Home.md index note with wiki links - .obsidian/app.json config Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
3.4 KiB
3.4 KiB
tags, type
| tags | type | ||
|---|---|---|---|
|
prd |
PRD: Region-Based Relay Selection
Phase: Implemented (data model) Status: Done (2026-04-14) Crate: wzp-client, wzp-proto, wzp-relay
Problem
Clients are configured with a single relay address. With multiple relays in the federation mesh, the client should automatically discover all available relays and select the lowest-latency one. Currently there is no mechanism for the relay to advertise its mesh peers to clients, and no client-side data structure to track relay health over time.
Solution
- Relays advertise their region and mesh peers in
RegisterPresenceAck - Clients maintain a
RelayMapsorted by measured RTT preferred()returns the best relay for call setup
Implementation
New Module: crates/wzp-client/src/relay_map.rs
RelayEntry:
pub struct RelayEntry {
pub name: String,
pub addr: SocketAddr,
pub region: Option<String>,
pub rtt_ms: Option<u32>,
pub last_probed: Option<Instant>,
pub reachable: bool,
}
RelayMap API:
upsert(name, addr, region)— add or update a relay entryupdate_rtt(addr, rtt_ms)— record probe result, marks reachable, re-sortsmark_unreachable(addr)— sorts unreachable entries to endpreferred()->Option<&RelayEntry>— lowest RTT reachable relaypopulate_from_ack(relays, region)— parseRegisterPresenceAck.available_relays(format:"name|addr")needs_reprobe(max_age)— true if any entry has stale or missing probestale_entries(max_age)— list of entries needing fresh probes
Signal Protocol Extension
RegisterPresenceAck extended:
RegisterPresenceAck {
success: bool,
error: Option<String>,
relay_build: Option<String>,
relay_region: Option<String>, // NEW
available_relays: Vec<String>, // NEW — "name|addr" format
}
Relay Config Extension
RelayConfig extended:
pub region: Option<String>, // e.g., "us-east", "eu-west"
pub advertised_addr: Option<SocketAddr>, // for available_relays population
Relay Population
On RegisterPresenceAck, the relay populates:
relay_regionfromconfig.regionavailable_relaysfromconfig.peers(label|url format)
Deferred
- Automatic relay switching — using
preferred()to select relay during call setup instead of hardcoded config - Background reprobing — periodic RTT measurements to keep the relay map fresh
- Cross-relay RTT estimation — using mesh probe data to estimate combined caller-RTT + callee-RTT for optimal relay placement
Files
| File | Change |
|---|---|
crates/wzp-client/src/relay_map.rs |
New — RelayMap + RelayEntry |
crates/wzp-client/src/lib.rs |
Add pub mod relay_map |
crates/wzp-proto/src/packet.rs |
relay_region + available_relays on RegisterPresenceAck |
crates/wzp-relay/src/config.rs |
region + advertised_addr fields |
crates/wzp-relay/src/main.rs |
Populate RegisterPresenceAck from config + peers |
Testing
- 15 unit tests: preferred by RTT, unreachable not preferred, preferred empty/all-unreachable, populate_from_ack (valid + malformed entries), upsert updates/preserves region, needs_reprobe (empty/never/fresh), stale_entries, sort stability with equal RTT, mark_unreachable sorts to end, RelayEntry serialization
- 2 protocol tests: RegisterPresenceAck roundtrip with new fields, backward compat without new fields