Commit Graph
7 Commits
Author SHA1 Message Date
cd727c6867 Make panic wipe deterministic and device-bound (#1431)
* Make panic wipe deterministic and device-bound

* Scope install markers to iOS

* Harden panic recovery and service shutdown

* Invalidate queued BLE ingress during panic

* Harden panic keychain and media cleanup

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
Co-authored-by: jack <jack@deck.local>
2026-07-26 10:28:50 +02:00
276cde44e7 Gate Tor/relay startup on network reachability (#1389)
On a mesh-only/offline device the app used to bootstrap Tor and spin
Nostr relay reconnects forever ("connecting to Tor…"), wasting battery
even when there was provably no network path at all.

Add an NWPathMonitor-backed reachability signal (NetworkReachabilityMonitor)
and fold it into NetworkActivationService's activation gate:

- Tor bootstrap and relay connect/reconnect are now gated on the network
  path being usable. When the path is fully unsatisfied (no interface at
  all) we set autoStart off, shut Tor down, and disconnect relays instead
  of looping. When a usable path returns we resume.
- Conservative policy: only NWPath.Status.unsatisfied counts as offline.
  A flaky-but-present link stays "reachable" (Tor tolerates intermittent
  connectivity); we never tear down on the first hiccup.
- Transitions are debounced (ReachabilityDebounce, ~2.5s) so path flapping
  cannot thrash Tor/relay startup. The debounce is a pure value type,
  unit-tested without the Network framework or real timers.
- Starts optimistic (reachable) so nothing is suppressed before the first
  path evaluation arrives.
- BLE mesh never consults this gate and works fully offline.
- NWPathMonitor's background callback hops to the main actor before
  touching any state.

Surfaces NetworkActivationService.isNetworkReachable for UI to distinguish
"offline" from "connecting to Tor".

Tests: pure debounce (satisfied → allowed, unsatisfied → suppressed after
interval, flap debounced, recover-after-outage) plus service wiring
(unreachable suppresses Tor+relays, recovery resumes, loss disconnects).

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 14:11:49 +02:00
fdf28aa5bb Fix launch crash: recursive dispatch_once between NostrRelayManager and NetworkActivationService (#1343)
* Fix launch crash: recursive dispatch_once between NostrRelayManager and NetworkActivationService

NostrRelayManager.init() runs applyDefaultRelayPolicy(force: true), which
calls dependencies.activationAllowed() when the user has location
permission or a mutual favorite. That closure resolves
NetworkActivationService.shared, whose init captured
NostrRelayManager.shared — re-entering the still-running dispatch_once on
the same thread. libdispatch traps on recursive dispatch_once
(EXC_BREAKPOINT in _dispatch_once_wait), killing the app ~50ms after
launch, before the first frame.

Fresh installs were unaffected (no permission, no favorites, so the
policy path never touched NetworkActivationService during init), which is
why this passed local testing but crashed established TestFlight users on
every launch. Two independent TestFlight crash reports on 1.5.2 (1)
show the identical stack.

Break the cycle by resolving the relay controller lazily: store a
provider closure in init and dereference NostrRelayManager.shared on
first use (start()/reevaluate()), after both singletons have finished
initializing. The injectable test initializer keeps its signature.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Bump version to 1.5.3

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 12:48:53 +02:00
a136b5b7e9 Expand coverage for relay, identity, and location flows (#1055)
* Expand coverage for relay, identity, and location flows

* Fix macOS SwiftPM CI failures

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2026-03-12 12:50:46 -10:00
3a35b3acc2 Modularization: Extract Tor into a separate module (#602)
* Extract Tor into a separate module

* Add Tor package as a dependency for iOS & macOS targets

* Move `tor-nolzma.xcframework` inside Tor

* Remove `libz` from Frameworks as its linked in Tor

* Remove stray `.gitkeep` from macOS target membership

* Fix missing import and access control for modularized Tor

- Add import Tor to NetworkActivationService
- Make TorManager.shutdownCompletely() public for external access

* Fix tor-nolzma.xcframework structure for Xcode builds

- Add missing Info.plist files to all framework slices
- Restructure macOS framework to use deep bundle format (Versions/)
- Keep iOS frameworks as shallow bundles (standard for iOS)

This fixes the Xcode build errors while maintaining SPM compatibility.

* Remove stale xcframework references from Xcode project

Xcode cleaned up old direct references to tor-nolzma.xcframework
since it's now managed internally by the Tor Swift package.

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-10-02 11:53:34 +02:00
54bb812469 Gate relays on mutual favorites and add Tor toggle (#631)
Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-09-16 08:12:51 -07:00
9cbdb0a764 Gate Tor/Nostr start behind permissions or mutual favorites; add clean shutdown + robust gating (#619)
- Add NetworkActivationService to permit Tor/Nostr only when location is authorized OR at least one mutual favorite exists.
- Gate TorManager.startIfNeeded/ensureRunningOnForeground behind a global allowAutoStart flag.
- Always stop Tor on background for deterministic restarts; rebuild sessions on foreground when allowed.
- NostrRelayManager respects the gate in connect/ensureConnections/subscribe/send/connectToRelay and skips reconnection when disallowed.
- Symmetric shutdown when conditions become disallowed: disconnect relays and stop Tor.
- Fix double-start by avoiding restart if Tor is already ready; prevent background thrash.
- Improve UX: post "starting tor…" via TorWillStart, and "tor started…" on initial ready; keep existing restart messages.

Rationale: Avoid starting Tor/relays when the user has no location permission and no mutual favorites, and ensure a clean, predictable lifecycle (no stale sockets, no double starts).

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-09-15 16:46:49 +02:00