Skip to content

feat(network): sync only on known networks (#96) - #98

Merged
elementalvoid merged 3 commits into
mainfrom
ticket/96-known-networks
Nov 13, 2026
Merged

elementalvoid merged 3 commits into
mainfrom
ticket/96-known-networks

Conversation

@elementalvoid

Copy link
Copy Markdown
Owner

Closes #96.

Summary

Sync only on known networks is a Sync setting, off by default, with a list of names you type. On, uploads and scans wait unless the OS names the current wireless network in the list; a wired link always syncs, and an unprovable network holds.

 crates/sync-core/
 ├── network.rs        # decide() · NetworkSource · NetworkStatus
 ├── engine.rs         # second hold; check at start, OS event, 30s poll, upload network error
 ├── upload.rs         # is_held() = user pause OR network hold
 └── status.rs         # PauseReason · Status.network

 crates/app/
 ├── network.rs        # Linux D-Bus · Windows NLM + IP helper · macOS CoreWLAN/CaptiveNetwork
 ├── settings.rs       # sync_only_on_known_networks · known_networks
 ├── settings_view.rs  # switch · current network · add/remove rows · macOS Location row
 ├── status.rs         # reason on the card
 └── shell.rs          # reason in the tray tooltip
check_network
  if list off            → allowed
  if wired (no SSID)     → allowed
  if listed name         → allowed
  if unlisted name       → Paused — not on a known network
  if unknown / error / timeout / empty name / no link
                         → Paused — network unknown

The hold is separate from the user's pause, so Resume cannot override the list; Status.pause carries the reason to the dashboard and the tray.

Evidence

  • cargo nextest run --locked --workspace: 941 passed, 2 skipped. cargo clippy --workspace --all-targets -D warnings and cargo fmt --check clean.
  • The check's table and the fake-backend cases (crates/sync-core/tests/it/network.rs): listed, not listed, list off, wired, empty name, OS error and recovery, leaving a listed network (queue kept), returning (resumes without a click), the poll noticing a missed event, an upload network error re-checking, a hung OS call timing out and holding, a closed event channel not spinning.
  • Release workflow dispatched on this branch — all three platform jobs green (compiles the Windows COM sink and the macOS backends that only target-probe locally): https://github.com/elementalvoid/immich-sync/actions/runs/43332924214
  • Hand-checked on real hardware by the reporter: macOS (Location prompt, current network name, paused/resumed, wrapping row) and Windows (profile name, event pause/resume, wired syncs). Linux was built and tested in a dev container only — the NetworkManager name, wired type mapping and D-Bus events still need a desktop run (docs/network-hand-checks.md).

Merge Danger

Door: two-way. The setting defaults off (existing behaviour), the settings file gains two fields with defaults, and nothing is deleted or migrated.

Blast Radius: contained — one new setting; the only always-on paths are the engine's network check (platform syscall per 30s while the engine runs) and one startup read.

Docs: SPEC R8.8, GLOSSARY, ADR 0008 (Location prompt), README, docs/network-hand-checks.md.

The known-network list is a Sync setting, off by default. While it is on,
uploads and scans wait unless the OS names the current wireless network in
the list; a wired connection always syncs and the check fails closed on an
unknown name, a missing answer, an OS error, or no network at all.

The pure check, the hold and the poll live in sync-core behind one
NetworkSource trait; the shell answers it per platform: NetworkManager over
D-Bus on Linux, the Network List Manager plus the IP helper's adapter types on
Windows, and CoreWLAN, CaptiveNetwork and Location Services on macOS. Each
backend also reports OS change events, with a 30-second poll as the net under
them and a re-check after any upload network error.

The pause is a second hold beside the user's own: Status carries the reason,
so the dashboard and tray read 'Paused - not on a known network' or 'Paused -
network unknown', and Resume cannot override the list.
#96)

The Current network row was a side-by-side setting row, so a long reason
pushed the value past the page edge. It is now a stacked row whose value wraps
under the title, and the value no longer repeats the row's own words: it is the
name, 'wired', or 'unknown - <reason>'.

macOS never showed the Location prompt from a local build. The prompt needs an
app bundle, so a 'cargo run' binary has no usage string to show; the settings
page now asks at open when the list is already on (as well as on the switch),
carries NSLocationUsageDescription as well as the When-In-Use key, and offers
Open Location Settings when the grant is missing. The README and the hand-check
notes say the prompt only works from the installed app.
macOS CI runs clippy on the real arm64 target, where libc's ifa_flags is
already u32, so the try_from conversion was a no-op lint error. The probe
scripts now run clippy rather than check, so the same class cannot pass a
local probe again.
@elementalvoid
elementalvoid merged commit e6100aa into main Nov 13, 2026
4 checks passed
@elementalvoid
elementalvoid deleted the ticket/96-known-networks branch November 13, 2026 19:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sync only on known (listed) networks

1 participant