feat(w7 p6): opt-in n0 DNS discovery for Discoverable presence

Wire the Discoverable presence posture to n0 DNS publish/lookup, the last
core piece of W7 (friends-first contacts). When a friend moves networks and
their saved address goes stale, they flip Discoverable to publish their
current address; everyone else resolves it by node id. Asymmetric: only the
mover publishes.

- src/discovery.rs (pure seam, +3 tests): lookup_plan(network_mode, want_publish)
  -> LookupPlan { resolver, publisher }. Relay-capable modes always resolve and
  publish only when Discoverable; DirectOnly (the explicit no-server posture)
  gets neither, overriding the toggle. DISCOVERY_TIMEBOX = 30 min.
- apply_discovery (core edge): clears + reinstalls the bound endpoint's
  address-lookup services at runtime (no endpoint rebuild). memory-lookup always;
  n0 PkarrResolver + DnsAddressLookup when resolver; PkarrPublisher when publisher.
  Toggling publish off drops the publisher (republish task ends; TTL-30s record
  expires). build_net_stack now binds uniformly with Minimal + per-mode relay and
  installs discovery via apply_discovery (drops the per-mode presets::N0 build).
- Toggle + time-box: SetPresenceMode re-applies discovery and arms/cancels a
  discovery_deadline; a select! branch fires at the deadline -> revert to Normal,
  stop publishing, and emit UiEvent::PresenceModeReverted so the GUI mirrors and
  persists it. Re-selecting Discoverable restarts the clock.

Decisions (user, 2026-06-16): 30-min auto-revert (not sticky); resolver always
on in relay-capable modes so a stationary friend in Normal can look up a mover.

266 lib tests green, clippy clean (--all-targets). Runtime smoke-tested: the new
Minimal+apply_discovery path binds and runs with no error/panic for both Normal
and Discoverable startup postures. Cross-network publish->lookup and the live
30-min revert still want a 2-machine field test (P7).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-16 16:24:46 -04:00
co-authored by Claude Opus 4.8
parent 3b02c2be0a
commit 22f0eed94d
6 changed files with 244 additions and 38 deletions
+25 -3
View File
@@ -193,9 +193,31 @@ Rejoin is best-effort (works only while the room is still live + reachable throu
stored ticket — reliability is P6/the member-ticket floor, not this list).
**Screenshot-verified** (seeded config → 3 recents render with correct ages + fallback).
### P6 — Opt-in discovery — Small
Wire the *discoverable* state to n0 DNS publish (default off, time-boxed). Lookup
path for finding a discoverable friend whose saved address went stale.
### P6 — Opt-in discovery — ✅ DONE 2026-06-16
Wires the *Discoverable* presence state to n0 DNS publish (default off, 30-min
time-boxed) plus an always-on lookup path. **Decisions (user, 2026-06-16):** 30-min
auto-revert (not sticky); resolver always on in relay-capable modes (the stationary
"looker" is usually in Normal, so lookups must work there).
- **Pure seam (`src/discovery.rs`, +3 tests):** `lookup_plan(network_mode, want_publish)
→ LookupPlan { resolver, publisher }` — relay modes always resolve + publish only when
Discoverable; **`DirectOnly` gets neither** (the explicit no-server posture overrides
the toggle). `DISCOVERY_TIMEBOX = 30 min`.
- **iroh edge (`apply_discovery` in `core/mod.rs`):** at runtime, on the bound endpoint,
`clear()` + reinstall the address-lookup services — memory-lookup always, n0 `PkarrResolver`
+ `DnsAddressLookup` when `resolver`, `PkarrPublisher` when `publisher`. **No endpoint
rebuild** — toggling publish off drops the publisher (its republish task ends; the
TTL-30s record expires). `build_net_stack` now binds uniformly with `Minimal` + per-mode
relay and calls `apply_discovery` (the old per-mode `presets::N0` build is gone), seeded
by the startup presence mode.
- **Toggle + time-box (core loop):** `SetPresenceMode` re-applies discovery and arms/cancels
a `discovery_deadline`; a `tokio::select!` branch fires at the deadline → revert to Normal +
stop publishing + `UiEvent::PresenceModeReverted` so the GUI mirrors/persists it (status:
"Discoverable timed out — back to Normal"). Re-selecting Discoverable restarts the clock.
- **Verified:** 266 lib tests green, clippy clean (`--all-targets`); runtime smoke-tested —
app binds + runs the new `Minimal`+`apply_discovery` path with no error/panic, both Normal
and Discoverable startup postures (the `PkarrPublisher` build path). ⚠️ **The actual cross-
network publish→lookup (a friend whose saved addr went stale resolving via n0 DNS) and the
live 30-min auto-revert need a 2-machine field test (P7).**
### P7 — Security review + 2-machine field test — SmallMedium
Surface: the friends-only listener (confirm non-friends are truly dropped pre-any