Fixes
https://github.com/firezone/firezone/actions/runs/13293765777/job/37121384825
```
╷
│ Error: Failed to query available provider packages
│
│ Could not retrieve the list of available versions for provider
│ hashicorp/aws: locked provider registry.terraform.io/hashicorp/aws 5.64.0
│ does not match configured version constraint >= 3.29.0, >= 5.[79](https://github.com/firezone/firezone/actions/runs/13293765777/job/37121384825#step:8:80).0; must use
│ terraform init -upgrade to allow selection of new versions
│
│ To see which modules are currently depending on hashicorp/aws and what
│ versions are specified, run the following command:
│ terraform providers
╵
```
In the window of time between we check `AdapterState == .tunnelStarted`
and we call `setDns` in the Apple `pathUpdateHandler`, it's possible
that connlib disconnected. This window of time could potentially be
non-trivial since we read system resolvers in there, which hits the
disk.
As such, we should always check the `session` pointer is valid just
before use.
The `AdapterState` enum tracks two states: `tunnelStopped` and
`tunnelStarted`. In the `tunnelStarted` state, we populate a
`WrappedSession` object. This is redundant - connlib is either
`connected` and we have a `WrappedSession`, or it is not. Therefore we
can remove the `AdapterState` abstraction completely (which was leftover
from a previous developer) and directly use a `WrappedSession?` object
to issue calls to connlib with.
We set this to a valid `WrappedSession` upon connecting, and back to
`nil` as soon as connlib either `onDisconnect`s us, or the user
disconnects the tunnel.
Lastly, we avoid early-returning from queued workItems because we now
call connlib with `session?` which will no-op if there is no session,
allowing whatever IPC call running at the time (such as fetchResources)
to complete successfully, even though they'll see a "snapshotted" state
of the Adapter/PacketTunnelProvider. In other words, we no longer
enforce the session pointer to be valid for things that don't depend on
its state.
Fixes#7882
With the dependency bump in #7995, we introduced a visual regression
that made all windows lose their styling:

The changelog to the v4 bump actually mentions some breaking changes and
an automated upgrade tool but both the reviewer and the author of the PR
missed that.
This allows connections to the postgresql database via the standard
socket, which - opposed to TCP sockets - allows `peer` authentication
based on local unix users. This removes the need for a password and is
much simpler to deploy when running components locally.
In the current form, `DATABASE_SOCKET_DIR` takes precedence over
hostname, if the environment variable is present. I found that
`compile_config!` somehow enforces a value to be present which is
explicitly not what I want for some of these values (i think). I'd be
glad if anyone with more elixir experience can guide me as to how I can
make this more idiomatic.
---------
Supersedes: #8044
Signed-off-by: Jamil <jamilbk@users.noreply.github.com>
Co-authored-by: oddlama <oddlama@oddlama.org>
To my knowledge we don't rely on this particular functionality from
hackney. Unfortunately, we don't control the `hackney` version used by
deps, and there is no non-vulnerable version ready yet, so we ignore the
advisory for now.
A fuse has been set to fire one week from now.
Ok, the reason why we're still getting the error `One or more points
were written more frequently than the maximum sampling period configured
for the metric.` is because the metric points are identified by the
labels in the metric, and so are "aggregated" more frequently than our
API calls.
By adding the node name to the labels, we scope the metric by that node
and prevent inserting the points more often than our API calls.
After further investigation, it appears that the `NSImage` initializer
loads and decodes images *synchronously* from the disk. In the MenuBar,
we are "lazy-loading" these images, but since the menu is constructed as
part of app initialization, we are effectively loading these when the
app boots, in `FirezoneApp`.
After loading, these are cached, but the initial can hang the UI thread
on app launch for slow systems.
Unfortunately, `NSImage` does not _formally_ conform to `@Sendable`.
However, this may be a nuance that isn't true in most cases, such as
when treating `NSImage` instances as read-only from only a single
thread.
As such, we wrap `NSImage` with our own struct, and mark it `@unchecked
Sendable`. This allows us to load the images on a background thread and
assign them to their UI thread counterparts in an async manner.
See further discussion:
-
https://forums.swift.org/t/why-cant-i-send-an-nsimage-across-actor-boundaries/76199
-
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html#//apple_ref/doc/uid/10000057i-CH12-126728
Related: #7771
Currently, we are only logging the last error when we fail to connect to
any of the addresses from the portal. This is often not useful because
the last one is likely to be an IPv6 address which may not be supported
on the system so all we learn is "The requested address is not valid in
its context.".
The error code we see here means "There are no more endpoints available
from the endpoint mapper." This has something to do with Windows'
internal RPC communication between components. DNS deactivation is on a
best-effort basis and it appears that everything else is working just
fine, despite this error.
It appears to happen when we shut down our own service, so perhaps it is
just a race condition.
Whether we execute a task on the main thread or a background thread
doesn't affect whether the thread is "hung" as reported by Sentry.
Instead, our options for fixing these are:
- Try to use an async version of the underlying API (the [async
version](https://developer.apple.com/documentation/appkit/nsworkspace/open(_:configuration:completionhandler:))
of `open` for example)
- If there is none, and the call could potentially block (most likely to
do disk IO contention), at least schedule this on a new thread using
`Task.detached` but with `.background` priority so that it will avoid
blocking any other execution.
The main takeaway here is that unfortunately, under some conditions,
Sentry will _always_ report an "App Hanging" alert since it's constantly
monitoring all threads for paused execution longer than 2000ms.
We'll probably end up letting some of these slide (pausing a background
or worker thread isn't necessarily a UX issue), but pausing the UI
thread is.
Luckily, we're able to use async APIs for most things. The remaining
things (like working with log files over IPC) we use a `Task.detached`
for.
We currently have a bug in our changelog where the wrong download links
are being rendered for the Windows GUI client because we are incorrectly
matching on the title.
To fix this, we stop matching on the title and instead pass an `OS` enum
in the respective changelog components that need to differentiate
between OS-specific entries.
We've previously tried to handle the "No such process" error from
netlink when it tries to remove a route that no longer exists. What we
failed to do is use the correct sign for the error code as netlink
errors are always negative, yet when printed, the are positive numbers.
When an IP stack is programmatically disabled, such as with:
> reg add
"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters"
/v DisabledComponents /t REG_DWORD /d 255 /f
Attempting to interact with this IP stack will yield "NOT_FOUND" errors.
These aren't worth reporting to Sentry because there isn't much we can
do about it.
Whenever changing a URL we care about, we add an entry in
`website/redirects.js` to avoid breaking links to the old page. Most
search engines reindex these after 1 year, but other websites and places
won't, so we should generally keep them indefinitely since they don't
cost us much to keep around.
We have a bug in our Rust telemetry code where starting a new telemetry
session for an **unsupported** environment doesn't stop the previous one
if one already exists.
This results in very confusing Sentry issues that cannot be correlated
to our infrastructure.
The errors returned from Win32 API calls are currently duplicated in
several places. To makes it error-prone to handle them correctly. With
this PR, we de-duplicate this and add proper docs and links for further
reading to them.
We also fix a case where we would currently fail to set IP addresses for
our tunnel interface if the IP stack is not supported.
`fetchResources` is an IPC call, and we can use
`withCheckedThrowingContinuation` like the others to yield while we wait
for the provider to respond.
The particular sentry issue related to this isn't because we are
necessarily blocking the task thread, rather, I suspect it's when
applying the fetched Resources to the UI that we're slow. There isn't
much we can do about this, but this PR will only help.
Because we're using a timer that fires off a closure to do this, we
still use a `callback` inside the timer to actually set the Resources on
the main `Store`, which updates the UI.
Unfortunately refactoring these IPC calls lead to somewhat of a ball of
yarn, so the best way to summarize the spirit of this PR is:
- Ensure IPC calls use `withCheckedThrowingContinuation` where possible
- Thusly, marking these functions `async throws`
- Bubble these errors up the view where we can ultimately decide what to
do with them
- Keep VPN state management and conditional logic based on `NEVPNStatus`
in the vpnConfigurationManager
In order to test changes to the IPC service on Windows more easily, the
IPC service binary offers an `install` command that installs a new
"Debug" IPC service. Prior to that, the previous is uninstalled.
This doesn't work if one doesn't have a previous "Debug" IPC service so
the `install` command only works for devs that have at least run it once
with that part of the function commented out. To improve this Dev UX, we
don't abort if we can't uninstall the previous one.
This adds hardening to the relay example systemd service shown in the
admin portal. Instead of running the service as root to download the
relay binary, we can let systemd manage the state directory and run with
lower privileges at all times.
I've also removed a shell injection which would in theory allow a
malicious github api server to run commands as root in the pre start
phase.
That being said I have no idea how this script is intended to function,
since it downloads the relay binary from the latest release on GitHub
which currently is a `gui-client` release without any relay binaries
attached.
We are getting quite a few of these warnings on prod:
```
{400, "{\n \"error\": {\n \"code\": 400,\n \"message\": \"One or more TimeSeries could not be written: timeSeries[0-39]: write for resource=gce_instance{zone:us-east1-d,instance_id:2678918148122610092} failed with: One or more points were written more frequently than the maximum sampling period configured for the metric.\",\n \"status\": \"INVALID_ARGUMENT\",\n \"details\": [\n {\n \"@type\": \"type.googleapis.com/google.monitoring.v3.CreateTimeSeriesSummary\",\n \"totalPointCount\": 40,\n \"successPointCount\": 31,\n \"errors\": [\n {\n \"status\": {\n \"code\": 9\n },\n \"pointCount\": 9\n }\n ]\n }\n ]\n }\n}\n"}
```
Since the point count is _much_ less than our flush buffer size of 1000,
we can only surmise the limit we're hitting is the flush interval.
The telemetry metrics reporter is run on each node, so we run the risk
of violating Google's API limit regardless of what a single node's
`@flush_interval` is set to.
To solve this, we use a new table `telemetry_reporter_logs` that stores
the last time a particular `flush` occurred for a reporter module. This
tracks global state as to when the last flush occurred, and if too
recent, the timer-based flush is call is `no-op`ed until the next one.
**Note**: The buffer-based `flush` is left unchanged, this will always
be called when `buffer_size > max_buffer_size`.
We are quite a few versions behind.
The changelog lists a good amount of [Breaking API
changes](https://github.com/open-telemetry/opentelemetry-collector/releases),
but rather than enumerate all of those, or forever stay on the same
(ancient) version, I thought it would be a good idea to flex the upgrade
muscle here and see where it lands us on staging.
Bumps [sd-notify](https://github.com/lnicola/sd-notify) from 0.4.3 to
0.4.5.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/lnicola/sd-notify/blob/master/CHANGELOG.md">sd-notify's
changelog</a>.</em></p>
<blockquote>
<h2>[0.4.5] - 2025-01-18</h2>
<h3>Fixed</h3>
<ul>
<li>fixed a dubious transmute between different slice types</li>
</ul>
<h2>[0.4.4] - 2025-01-16</h2>
<h3>Added</h3>
<ul>
<li>added <code>NotifyState::MonotonicUsec</code>, for use with
<code>Type=notify-reload</code></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="70a941baf1"><code>70a941b</code></a>
Bump to 0.4.5</li>
<li><a
href="6958ce12e4"><code>6958ce1</code></a>
Merge pull request <a
href="https://redirect.github.com/lnicola/sd-notify/issues/15">#15</a>
from tbu-/pr_slice_transmute</li>
<li><a
href="1e938f2fd5"><code>1e938f2</code></a>
Use <code>slice::from_raw_parts</code> instead of
<code>mem::transmute</code></li>
<li><a
href="cb4459a4bb"><code>cb4459a</code></a>
Prepare for new release</li>
<li><a
href="8eb2c5cab3"><code>8eb2c5c</code></a>
Add NotifyState::MonotonicUsec and helper</li>
<li><a
href="5462699164"><code>5462699</code></a>
Add NotifyState::MonotonicUsec and helper</li>
<li><a
href="6990e3733f"><code>6990e37</code></a>
Fix clippy warnings</li>
<li>See full diff in <a
href="https://github.com/lnicola/sd-notify/compare/v0.4.3...v0.4.5">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.21 to 4.5.28.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/clap-rs/clap/releases">clap's
releases</a>.</em></p>
<blockquote>
<h2>v4.5.28</h2>
<h2>[4.5.28] - 2025-02-03</h2>
<h3>Features</h3>
<ul>
<li><em>(derive)</em> Unstable support for full markdown syntax for doc
comments, enabled with <code>unstable-markdown</code></li>
</ul>
<h2>v4.5.27</h2>
<h2>[4.5.27] - 2025-01-20</h2>
<h3>Documentation</h3>
<ul>
<li>Iterate on tutorials and reference based on feedback</li>
</ul>
<h2>v4.5.26</h2>
<h2>[4.5.26] - 2025-01-09</h2>
<h3>Fixes</h3>
<ul>
<li><em>(error)</em> Reduce binary size with the
<code>suggestions</code> feature</li>
</ul>
<h2>v4.5.25</h2>
<h2>[4.5.25] - 2025-01-09</h2>
<h3>Fixes</h3>
<ul>
<li><em>(help)</em> Reduce binary size</li>
</ul>
<h2>v4.5.24</h2>
<h2>[4.5.24] - 2025-01-07</h2>
<h3>Fixes</h3>
<ul>
<li><em>(parser)</em> Correctly handle defaults with
<code>ignore_errors(true)</code> and when a suggestion is provided for
an unknown argument</li>
</ul>
<h2>v4.5.23</h2>
<h2>[4.5.23] - 2024-12-05</h2>
<h3>Fixes</h3>
<ul>
<li><em>(parser)</em> When check <code>allow_negative_numbers</code>,
allow <code>E</code> again</li>
</ul>
<h2>v4.5.22</h2>
<h2>[4.5.22] - 2024-12-03</h2>
<h3>Fixes</h3>
<ul>
<li><em>(assert)</em> Catch bugs with arguments requiring themself</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/clap-rs/clap/blob/master/CHANGELOG.md">clap's
changelog</a>.</em></p>
<blockquote>
<h2>[4.5.28] - 2025-02-03</h2>
<h3>Features</h3>
<ul>
<li><em>(derive)</em> Unstable support for full markdown syntax for doc
comments, enabled with <code>unstable-markdown</code></li>
</ul>
<h2>[4.5.27] - 2025-01-20</h2>
<h3>Documentation</h3>
<ul>
<li>Iterate on tutorials and reference based on feedback</li>
</ul>
<h2>[4.5.26] - 2025-01-09</h2>
<h3>Fixes</h3>
<ul>
<li><em>(error)</em> Reduce binary size with the
<code>suggestions</code> feature</li>
</ul>
<h2>[4.5.25] - 2025-01-09</h2>
<h3>Fixes</h3>
<ul>
<li><em>(help)</em> Reduce binary size</li>
</ul>
<h2>[4.5.24] - 2025-01-07</h2>
<h3>Fixes</h3>
<ul>
<li><em>(parser)</em> Correctly handle defaults with
<code>ignore_errors(true)</code> and when a suggestion is provided for
an unknown argument</li>
</ul>
<h2>[4.5.23] - 2024-12-05</h2>
<h3>Fixes</h3>
<ul>
<li><em>(parser)</em> When check <code>allow_negative_numbers</code>,
allow <code>E</code> again</li>
</ul>
<h2>[4.5.22] - 2024-12-03</h2>
<h3>Fixes</h3>
<ul>
<li><em>(assert)</em> Catch bugs with arguments requiring themself</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="257d7812b9"><code>257d781</code></a>
chore: Release</li>
<li><a
href="06c5f5f329"><code>06c5f5f</code></a>
docs: Update changelog</li>
<li><a
href="6ac153557c"><code>6ac1535</code></a>
Merge pull request <a
href="https://redirect.github.com/clap-rs/clap/issues/5733">#5733</a>
from epage/bin</li>
<li><a
href="a7a8f93d6b"><code>a7a8f93</code></a>
fix(complete): Strip wrappers for running completer</li>
<li><a
href="b2c8e445aa"><code>b2c8e44</code></a>
feat(complete): Allow user to override bin/completer</li>
<li><a
href="21c9892efe"><code>21c9892</code></a>
chore: Release</li>
<li><a
href="0c8bceb3e9"><code>0c8bceb</code></a>
docs: Update changelog</li>
<li><a
href="d8f102a18c"><code>d8f102a</code></a>
Merge pull request <a
href="https://redirect.github.com/clap-rs/clap/issues/5732">#5732</a>
from epage/consistent</li>
<li><a
href="c92fca3a8f"><code>c92fca3</code></a>
docs(complete): Clarify CompleteEnv's Shell trait</li>
<li><a
href="5ca60e9079"><code>5ca60e9</code></a>
Merge pull request <a
href="https://redirect.github.com/clap-rs/clap/issues/5731">#5731</a>
from epage/bash</li>
<li>Additional commits viewable in <a
href="https://github.com/clap-rs/clap/compare/clap_complete-v4.5.21...clap_complete-v4.5.28">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Followup to the discussion on
https://github.com/firezone/firezone/pull/8064. By annotating the
callback that updates our Resources `@MainActor`, the compiler will
correctly warn us when we call it from a non-isolated context.
When the IPC service gets terminated gracefully, the user must have
initiated some kind of action, be it an upgrade or an explicit "Stop the
service". In that case, there is no point in displaying an alert with an
info / error message as the user already knows that they are stopping
Firezone. In order to not fatigue the user with alerts, we exit the GUI
with a toast notification when the IPC service shuts down gracefully.
Toast notifications do not grab the users attention, allowing them to
continue what they are doing while still being notified that their
Firezone client is now disconnected.
Fixes: #6232.
If we receive two `.connected` status change updates from the system in
a row, we'll incorrectly schedule an additional timer, and the handle to
the first one will be lost.
This causes a memory leak because we'll then never call the first
timer's `invalidate()` function in the `endUpdatingResources` call.
This fixes a bug introduced in db655dd171 that could lead to a crash or
undefined behavior because it potentially updates resources (a
`@Published` object) from a background thread.
UI updates must occur on the main thread only.