diff --git a/docs/contacts-plan.md b/docs/contacts-plan.md index 916cebb..326ee29 100644 --- a/docs/contacts-plan.md +++ b/docs/contacts-plan.md @@ -102,12 +102,18 @@ write — pattern from pixelpass `friends.rs`). Add-from-room (you met them in a gathering), local rename. No handshake required for the basic list (it's a local address book), though a lightweight mutual-add is optional polish. -### P3 — Member-issued / multi-bootstrap tickets — Small (the ticket mechanism) -Let any current member mint a ticket from `{ their live addr, the session topic }` -(both already in hand). Pre-exists: the type `PeerSpeakTicket` and `RoomState::join` -already takes `extra_bootstrap: Vec` (A8). Optionally bundle several -present members for redundancy. Also tighten ticket encoding (drop JSON/base64 fat, -index the relay URL — lossless, ~halves the string). +### P3 — Member-issued / multi-bootstrap tickets — ✅ core DONE 2026-06-15 (`c90dcf7`) +- **Member-issued ticket (DONE, non-breaking):** the ticket the UI shows/copies is + now stamped with the local member's own live address + the room's topic (pure + seam `PeerSpeakTicket::restamp`, +3 tests), so every member hands out a working + door pointing at themselves → rooms outlive their creator. Only the *display* + copy is re-stamped; the join/bootstrap `ticket_str` + A8 retain logic are + untouched. 248 lib tests green. ⚠️ **2-machine field test pending** (creator + leaves → a joiner's ticket still admits a newcomer). +- **Deferred (both BREAKING wire changes — want daylight + 2-machine):** + multi-bootstrap ticket (bundle several present members as `extra_bootstrap`, + needs a ticket struct change) and tighter ticket encoding (drop JSON/base64 fat, + index the relay URL; lossless ~halving). ### P4 — Friends-only idle listener + presence — Medium (the new primitive) A long-lived endpoint while the app is open (own ALPN, e.g. `peerspeak/friends/0`),