S11: make presence/discovery state honest on apply failure
SetPresenceMode and the Discoverable time-box auto-revert both committed the new presence_mode to local state *before* apply_discovery and only log_msg'd on failure, so a failed off-transition could leave the n0 DNS PkarrPublisher running while the UI showed not-discoverable (privacy / reality mismatch — security-open-handoff S11, from the W7 P7 review). Fix (Codex, senior-reviewed): - discovery.rs: pure resolve_presence_transition(prev, requested, apply_ok) -> (mode, Option<error>) seam — on failure keep the previous (truthful) mode and surface a message. +4 unit tests. - apply_discovery now builds the replacement resolver/publisher services BEFORE clearing the service set, so a builder failure leaves the old posture fully intact (no partial state) — "keep previous mode" is then provably truthful. - Both SetPresenceMode and the time-box revert apply discovery first, route through the seam, commit only the truthful mode, and surface failures via the existing PresenceModeReverted (corrects the picker) + UiEvent::Error. No new wire/event variant. - A failed off-transition stays Discoverable and arms a 60s retry (DISCOVERY_REVERT_RETRY) so the beacon never stands stuck. - P3 notes documented: relay-resolve exposes n0 query metadata (by design); no explicit iroh unpublish API exists, so the bounded ~30s pkarr TTL linger is documented, not behavior-changed; DirectOnly stays no-n0. 306 lib tests / clippy --all-targets / release all green (re-run by senior). Runtime publish-stop behavior still wants a 2-machine / packet-capture check. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+7
-5
@@ -955,13 +955,15 @@ fn update(state: &mut AppState, message: AppMessage) -> Task<AppMessage> {
|
||||
state.friend_presence.insert(id, presence);
|
||||
}
|
||||
UiEvent::PresenceModeReverted { mode } => {
|
||||
// The Discoverable time-box elapsed; core dropped us back to
|
||||
// `mode` (Normal) and stopped publishing. Mirror + persist so the
|
||||
// presence picker reflects it, and tell the user why it changed.
|
||||
// Core corrected the committed presence mode. Mirror + persist so
|
||||
// the picker reflects the discovery state the endpoint actually has.
|
||||
state.config.presence_mode = mode;
|
||||
state.config.save();
|
||||
state.status_message =
|
||||
"Discoverable timed out — back to Normal".to_string();
|
||||
state.status_message = if mode == PresenceMode::Normal {
|
||||
"Discoverable timed out — back to Normal".to_string()
|
||||
} else {
|
||||
format!("Presence mode stayed {mode}")
|
||||
};
|
||||
}
|
||||
UiEvent::ShutdownComplete => {
|
||||
if state.closing {
|
||||
|
||||
Reference in New Issue
Block a user