115 Commits

Author SHA1 Message Date
Mariusz Klochowicz
470680cb1f chore(apple): Migrate to latest Xcode recommended settings (#10766)
Prompted by Xcode warning at project startup.

Most of the changes are simple migrations from entitlements files
to build settings, which is the recommended approach, and were done
automatically by Xcode.

new settings:
- REGISTER_APP_GROUPS - Automatically registers app groups with
provisioning
profile (I had to set this manually when setting up, so it's a welcome
change)
- STRING_CATALOG_GENERATE_SYMBOLS - type-safe localization (no
  regression, we're not doing any localization currently)
- ENABLE_USER_SCRIPT_SANDBOXING - sandboxing all the build scripts

Note: I had to turn off the recommended `ENABLE_USER_SCRIPT_SANDBOXING`
as it
would interfere with our building of connlib during the build.

Also: make Makefile more ergonomic to use (setup LSP config during first
build)
2025-11-06 22:45:56 +00:00
Mariusz Klochowicz
936b095391 chore(apple): Enable Swift 6.2 Approachable Concurrency features (#10799)
Enables SWIFT_APPROACHABLE_CONCURRENCY build setting which activates
a few key Swift 6.2 concurrency features, including:

1. NonisolatedNonsendingByDefault - Makes nonisolated async functions
run
   on the caller's executor instead of the global executor, providing
   more predictable performance and behaviour

2. InferIsolatedConformances - Protocol conformances automatically
   inherit global actor isolation, reducing annotation burden

Read more:
https://www.donnywals.com/what-is-approachable-concurrency-in-xcode-26/

Also bumps swift-tools-version from 6.0 to 6.2 in Package.swift to
enable newer Package Manager manifest APIs.

As a result of better type inference, removes 1 redundant @Sendable
annotation in Store.swift:
- vpnStatusChangeHandler: @MainActor closures are implicitly Sendable
2025-11-05 21:56:24 +00:00
Mariusz Klochowicz
bf95dc45a3 refactor(apple): Upgrade to Swift 6.2 with concurrency checks (#10682)
This PR upgrades the Swift client from Swift 5 to Swift 6.2, addressing
all
concurrency-related warnings and runtime crashes that come with Swift
6's
strict concurrency checking.

## Swift 6 Concurrency Primer

**`actor`** - A new reference type that provides thread-safe, serialised
access to mutable state. Unlike classes, actors ensure that only one
piece of
code can access their mutable properties at a time. Access to actor
methods/properties requires await and automatically hops to the actor's
isolated executor.

**`@MainActor`** - An attribute that marks code to run on the main
thread.
Essential for UI updates and anything that touches UIKit/AppKit. When a
class/function is marked @MainActor, all its methods and properties
inherit
this isolation.

**`@Sendable`** - A protocol indicating that a type can be safely passed
across concurrency domains (between actors, tasks, etc.). Value types
(structs, enums) with Sendable stored properties are automatically
Sendable.
Reference types (classes) need explicit @unchecked Sendable if they
manage
thread-safety manually.

**`nonisolated`** - Opts out of the containing type's actor isolation.
For
example, a nonisolated method in a @MainActor class can be called from
any
thread without await. Useful for static methods or thread-safe
operations.

**`@concurrent`** - Used on closure parameters in delegate methods.
Indicates
the closure may be called from any thread, preventing the closure from
inheriting the surrounding context's actor isolation. Critical for
callbacks
from system frameworks that call from background threads.

**Data Races** - Swift 6 enforces at compile-time (and optionally at
runtime)
that mutable state cannot be accessed concurrently from multiple
threads. This
eliminates entire classes of bugs that were previously only caught
through
testing or production crashes.

## Swift Language Upgrade

- **Bump Swift 5 → 6.2**: Enabled strict concurrency checking throughout
the
  codebase
- **Enable ExistentialAny (SE-0335)**: Adds compile-time safety by
making
  protocol type erasure explicit (e.g., any Protocol instead of implicit
  Protocol)
- **Runtime safety configuration**: Added environment variables to log
concurrency violations during development instead of crashing, allowing
  gradual migration

## Concurrency Fixes

### Actor Isolation

- **TelemetryState actor** (Telemetry.swift:10): Extracted mutable
telemetry
state into a dedicated actor to eliminate data races from concurrent
access
- **SessionNotification @MainActor isolation**
(SessionNotification.swift:25):
  Properly isolated the class to MainActor since it manages UI-related
  callbacks
- **IPCClient caching** (IPCClient.swift): Fixed actor re-entrance
issues and
resource hash-based optimisation by caching the client instance in Store

### Thread-Safe Callbacks

- **WebAuthSession @concurrent delegate** (WebAuthSession.swift:46): The
  authentication callback is invoked from a background thread by
ASWebAuthenticationSession. Marked the wrapper function as @concurrent
to
  prevent MainActor inference on the completion handler closure, then
  explicitly hopped back to MainActor for the session.start() call. This
  fixes EXC_BAD_INSTRUCTION crashes at _dispatch_assert_queue_fail.
- **SessionNotification @concurrent delegate**
(SessionNotification.swift:131): Similarly marked the notification
delegate
method as @concurrent and used Task { @MainActor in } to safely invoke
the
  MainActor-isolated signInHandler

### Sendable Conformances

- Added Sendable to Resource, Site, Token, Configuration, and other
model
  types that are passed between actors and tasks
- **LogWriter immutability** (Log.swift): Made jsonData immutable to
prevent
  capturing mutable variables in @Sendable closures

### Nonisolated Methods

- **Static notification display** (SessionNotification.swift:73): Marked
showSignedOutNotificationiOS() as nonisolated since it's called from the
  Network Extension (different process) and only uses thread-safe APIs

Fixes #10674
Fixes #10675
2025-11-05 04:24:49 +00:00
Jamil
39b2f61cfd fix(ci): ensure version markers are replaced across all files (#10752)
Upon moving the version string from PKG_VERSION and Cargo.toml, we lost
the bump version automation. To avoid more bugs here in the future, we
now check for the version marker across all Git-tracked files,
regardless of their extension.

Fixes #10748

---------

Co-authored-by: Thomas Eizinger <thomas@eizinger.io>
2025-10-29 02:10:50 +00:00
Firezone Bot
76d86545a6 chore: publish apple-client 1.5.9 (#10654) 2025-10-20 14:04:08 +00:00
Jamil
73576922ff fix(apple/macos): clean up utun on quit (#10603)
On macOS, because it uses the System Extension packaging type, the
lifecycle of the tunnel provider process is not tied directly to
connlib's session start and end, but rather managed by the system. The
process is likely running at all times, even when the GUI is not open or
signed in.

The system will start the provider process upon the first IPC call to
it, which allocates a `utun` interface. The tricky part is ensuring this
interface gets removed when the GUI app quits. Otherwise, it's likely
that upon the next launch of the GUI app, the system will allocate a
_new_ utun interface, and the old one will linger until the next system
reboot.

Here's where things get strange. The system will only remove the `utun`
interface when stopping the tunnel under the following conditions:

- The provider is currently not in a `disconnected` state (so it needs
to be in `reasserting`, `connecting`, or `connected`
- The GUI side has called `stopTunnel`, thereby invoking the provider's
`stopTunnel` override function, or
- The provider side has called `cancelTunnelWithError`, or
- The `startTunnel`'s completionHandler is called with an `Error`

The problem we had is that we make various IPC calls throughout the
lifecycle of the GUI app, for example, to gather logs, set tunnel
configuration, and the like. If the GUI app was _not_ in a connected
state when the user quit, the `utun` would linger, even though we were
issuing a final `stopTunnel` upon quit in all circumstances.

To fix the issue, we update the dry run `startTunnel` code path we added
previously in two ways:

1. We add a `dryRun` error type to the `startTunnel`'s completionHandler
2. We implement the GUI app `applicationShouldTerminate` handler in
order to trigger one final dryRun which briefly moves the provider to a
connected state so the system will clean us up when its
completionHandler is invoked.


Tested under the following conditions:

- Launch app in a signed-out state -> quit
- Launch app in a signed-out state -> sign in -> quit
- Launch app in a signed-out state -> sign in -> sign out -> quit
- Launch app in a signed-in state -> quit
- Launch app in a signed-in state -> sign out -> quit

Notably, if the GUI app is killed with `SIGKILL`, our terminate hook is
_not_ called, and the utun lingers. We'll have to accept this edge case
for now.

Along with the above, the janky `consumeStopReason` mechanism has been
removed in favor of NE's `cancelTunnelWithError` to pass the error back
to the GUI we can then use to show the signed out alert.


Fixes #10580
2025-10-17 15:12:29 +00:00
Mariusz Klochowicz
97f3979fa6 fix(apple): Explicitly hide network extension from the UI (#10581)
Apparently if we set the CFBundleDisplayName we hint by default that
we *do* want to show it on newer macOS versions.

This seems to have been uncovered by Xcode 26 build recently.

Fixes #10579
2025-10-16 03:42:10 +00:00
Mariusz Klochowicz
cb50800d52 refactor(apple): Migrate iOS/macOS clients to UniFFI (#10368)
Replace callback-based Adapter with event polling-based AdapterUniFfi

This change improves reliability by eliminating callback lifetime
issues.
2025-10-13 23:13:52 +00:00
Mariusz Klochowicz
4d2b592d65 chore: Clean up Xcode config (#10461)
- declary sentry as FirezoneKit dependency
- add config for non-Xcode LSP config 
- add some more info in README
2025-10-01 02:08:18 +00:00
Mariusz Klochowicz
b1ed2f8a5e chore: improve macos dev experience (#10363)
Quality of life improvements for macOS devs, mostly relevant when not
using Xcode as daily driver - although some convenience functions &
explicit sentry dependency should make it better there too.
2025-09-17 02:17:36 +00:00
Firezone Bot
d8079c869f chore: publish apple-client 1.5.8 (#10323) 2025-09-10 17:06:40 +00:00
Firezone Bot
95ee111e62 chore: publish apple-client 1.5.7 (#10159) 2025-08-07 04:38:03 +00:00
Firezone Bot
acf52ccf1e chore: publish apple-client 1.5.6 (#10106) 2025-08-02 19:43:35 +00:00
Firezone Bot
e6fc7e62da chore: publish apple-client 1.5.5 (#10035) 2025-07-28 20:14:12 +00:00
Jamil
12351e5985 ci: publish apple 1.5.4 clients (#9842) 2025-07-11 16:35:25 +00:00
Jamil
081b075f2c chore: bump gui, apple, gateway (#9586)
The new publish automation still [has some
kinks](https://github.com/firezone/firezone/actions/runs/15764891111) so
publishing this manually.
2025-06-19 12:29:46 -07:00
Thomas Eizinger
01ad87b1c0 chore(apple): format swift code with formatter (#9535)
When working on the Swift codebase, I noticed that running the formatter
produced a massive diff. This PR re-formats the Swift code with `swift
format . --recursive --in-place` and adds a CI check to enforce it going
forward.

Resolves: #9534

---------

Co-authored-by: Jamil Bou Kheir <jamilbk@users.noreply.github.com>
2025-06-15 20:28:18 +00:00
Jamil
221ffc7e58 chore: publish Apple 1.5.2 (#9385) 2025-06-03 19:49:06 +00:00
Jamil
0c0ab13b90 ci: Bump apple version to 1.5.1 (#9343) 2025-06-01 16:43:31 +00:00
Jamil
b7ec92e3aa chore(ci): Bump apple clients to 1.5.0 (#9239) 2025-05-26 08:20:05 -07:00
Jamil
b5c18db5e8 chore(ci): Bump next clients version to 1.5.0 (#9229)
We've decided we'll be bumping the minor with shipping managed
configurations support.
2025-05-26 04:24:35 +00:00
Jamil
a7054b8f40 ci: Bump apple to 1.4.15 (#9217) 2025-05-24 12:51:27 +00:00
Jamil
6fd3493ed0 refactor(apple): Consolidate configuration to host app (#9196)
On Apple platforms, `UserDefaults` provides a convenient way to store
and fetch simple plist-compatible data for your app. Unbeknownst to the
author at the time of original implementation was the fact this these
keys are already designed for managed configurations to "mask" any
user-configured equivalents.

This means we no longer need to juggle two dicts in UserDefaults, and we
can instead check which keys are forced via a simple method call.

Additionally, the implementation was simplified in the following ways:

- The host app is the "source of truth" for app configuration now. The
tunnel service receives `setConfiguration` which applies the current
configuration, and saves it in order to start up again without the GUI
connected. The obvious caveat here is that if the GUI isn't running,
configuration such as `internetResourceEnabled` applied by the
administrator won't take effect. This is considered an edge case for the
time being since no customers have asked for this. Additionally, admins
can be advised to ensure the Firezone GUI is running on the system at
all times to prevent this.
- Settings and ConfigurationManager are now able to be removed - these
became redundant after consolidating configuration to the containing
app.
2025-05-22 16:18:00 +00:00
Jamil
1ceccc0da0 refactor(apple): Consolidate app configuration to UserDefaults (#9056)
We are currently storing app configuration across three places:

- UserDefaults (favorite resources)
- VPN configuration (Settings)
- Disk (firezone id)

These can be consolidated to UserDefaults, which is the standard way to
store app configuration like this.

UserDefaults is the umbrella persistence store for regular app
configuration (`plist` files which are just XML dictionaries),
iCloud-synced app configuration across a user's devices, and managed app
configuration (MDM). They provide a cached, thread-safe, and
interprocess-supported mechanism for handling app configuration. We can
also subscribe to changes on this app configuration to react to changes.

Unfortunately, the System Extension ruins some of our fun because it
runs as root, and is confined to a different group container, meaning we
cannot share configuration directly between GUI and tunnel procs.

To address this, we use the tunnel process to store all vital
configuration and introduce IPC calls to set and fetch these.

Commit-by-commit review recommended, but things got a little crazy
towards the end when I realized that we can't share a single
UserDefaults between both procs.
2025-05-12 05:27:49 +00:00
Thomas Eizinger
5566f1847f refactor(rust): move crates into a more sensical hierarchy (#9066)
The current `rust/` directory is a bit of a wild-west in terms of how
the crates are organised. Most of them are simply at the top-level when
in reality, they are all `connlib`-related. The Apple and Android FFI
crates - which are entrypoints in the Rust code are defined several
layers deep.

To improve the situation, we move around and rename several crates. The
end result is that all top-level crates / directories are:

- Either entrypoints into the Rust code, i.e. applications such as
Gateway, Relay or a Client
- Or crates shared across all those entrypoints, such as `telemetry` or
`logging`
2025-05-12 01:04:17 +00:00
Jamil
4e61ba9582 fix(apple): set new project version on each build (#9072)
When developing the macOS app, we always build the exact same version
and build code for each build. ~~This _may_ be one reason why we
constantly have to deactivate the extension before the new one will
launch.~~ Edit: Just tested, and I can verify that this does fix the
issue on dev builds, so no more having to uninstall the sysex between
builds.

Even if that's not the reason, this is a cleaner approach than building
it in our prod-only scripts.

---------

Signed-off-by: Jamil <jamilbk@users.noreply.github.com>
2025-05-12 00:55:14 +00:00
Jamil
07fa91f713 chore(apple): Add file header template for xcode (#9068)
When creating new files in Xcode, it's helpful if the file header is
already formatted properly.
2025-05-10 12:26:37 +00:00
Jamil
6e0e7343ba chore: release Apple & Gateway with ECN fix (#9013) 2025-05-02 00:16:40 -07:00
Jamil
2650d81444 chore: release clients with GSO fix (#8936) 2025-04-29 23:52:43 -07:00
Jamil
5db8e20f3b chore: release Apple and GUI clients (#8882)
- Apple clients 1.4.12
- GUI clients 1.4.11
2025-04-21 21:45:16 +00:00
Jamil
5669c83835 ci: Bump Apple clients to 1.4.11 (#8848)
Includes a fix for auto-starting on launch when other VPN clients have
been connected previously.
2025-04-19 11:45:42 +00:00
Jamil
22113f5940 chore(apple): Bump Swift dependencies (#8815)
Dependabot still fails to update these...
2025-04-18 18:07:42 +00:00
Jamil
a2e32a4918 ci: Bump apple to 1.4.10 to ship PKG (#8797)
This publishes the 1.4.10 permalinks for the PKG download.
2025-04-17 15:13:44 +00:00
Jamil
aab691a67f ci: Release Apple clients 1.4.9 (#8793)
These contain the recent UDP thread enhancements.
2025-04-15 20:14:43 +00:00
Jamil
effe169414 chore: release apple 1.4.8 (#8499)
Introduces the autoconnect and session end fixes.
2025-03-21 11:43:00 +00:00
Jamil
e642eefb35 chore: Cut all clients to ship search domains (#8442)
Waiting on app reviews to be approved, then this PR will be ready to
merge.
2025-03-17 17:25:11 +00:00
Jamil
25c708fb43 ci: Bump apple clients to 1.4.6 (#8418) 2025-03-12 04:09:49 +00:00
Jamil
48030f68d7 ci: Bump Apple clients to 1.4.5 (#8252)
These have been published. This fixes a critical bug preventing the
client from launching on macOS.
2025-02-24 23:41:38 -08:00
Jamil
0bc3895c3e ci: Bump Apple clients to 1.4.4 (#8245)
These have been released / published. Need to merge this to get website
links and changelog updated.
2025-02-24 09:01:45 -08:00
Jamil
e487272a1b chore(apple): Release Apple clients 1.4.3 (#8144) 2025-02-16 12:59:38 -08:00
Jamil
39cbf60ec8 ci: Bump Apple clients to 1.4.2 (#8109)
Fixes a slew of memory leaks, crashes, and other papercuts.
2025-02-13 22:08:45 +00:00
Jamil
62876028c8 chore(apple): Update Xcode project settings (#8114)
Xcode keeps pestering about these on each launch. Seems to be
maintainence-related project configuration updates.
2025-02-13 02:40:23 +00:00
Jamil
ace4d52346 style(apple): Add SwiftLint (#7909)
Adds SwiftLint using (mostly) default rules to our build pipeline.
Unfortunately, this results in quite a lot of errors / warnings.

All fixes included in this PR are simply refactoring. No functionality
has been changed.


Fixes: #4302
2025-01-30 15:09:56 +00:00
Jamil
6a73406194 chore: Bump Apple version to 1.4.1 (#7946) 2025-01-30 00:04:54 +00:00
Jamil
9155a46394 chore(apple): Treat apple compile warnings as errors (#7896)
Enables warnings-as-errors for the clang and swift compilers.
2025-01-28 19:23:30 +00:00
Jamil
6670741dee chore: Bump apple clients to 1.4.0 (#7785)
Bumps Apple clients to the 1.4.0 release. They're already live.
2025-01-17 00:07:25 +00:00
Jamil
216ca9b8bc chore(apple/macOS): Add boilerplate Info.plist parameters (#7717)
Some reports online indicate Gatekeeper relies on some of these to be
set for standalone apps and missing them can result in apps failing to
be marked "verified".

https://developer.apple.com/forums/thread/129024?page=2
2025-01-09 22:14:03 +00:00
Jamil
6476109b73 fix(apple): Simplify Xcode rust build steps (#7709)
Xcode doesn't allow wildcards in input file lists, so the rules I set up
in #7488 never took effect.

Upon further investigation, it appears that the `strip` command executed
unconditionally at the end of every Rust build was the culprit. Since
Xcode already does this for us, it's a useless step that adds about 30s
to the build time.

Unfortunately there isn't a good way to tell Xcode not to build rust.
But now we don't need to -- `cargo`'s build cache is smart enough to
skip builds and we are back to the ~1-2s range for repeated builds when
only Swift code has changed.

We also add the swift bridge generated code to version control. These
doesn't change regularly, and Xcode sometimes complains that the files
don't exist _before_ it lets you run the `cargo build` to generate them
🙃 .
2025-01-09 07:54:37 +00:00
Jamil
358ae1f92a fix(apple): Copy PrivacyInfo.xcprivacy for both platforms (#7681)
This needs to be at the root of the app bundle for both platforms.
Somehow it got moved to just the iOS network extension.
2025-01-07 09:49:54 +00:00
Jamil
55c4f576c4 chore(apple): Bump sentry-cocoa to 8.43.0 (#7675) 2025-01-06 07:26:36 +00:00