Commit Graph

3246 Commits

Author SHA1 Message Date
Zoltán Papp
bbba18fc96 Merge remote-tracking branch 'origin/ui-refactor' into ui-refactor 2026-06-09 19:07:45 +02:00
Eduard Gert
d70b3a3fa4 update debug bundle text 2026-06-09 18:23:07 +02:00
Eduard Gert
dac2ca4088 fix dropdown animation 2026-06-09 18:08:47 +02:00
Eduard Gert
4e1e7f9518 add common languages 2026-06-09 18:04:59 +02:00
Eduard Gert
9049974f26 lint 2026-06-09 16:33:30 +02:00
Eduard Gert
f8e3ac6d92 refactor, lint, cleanup 2026-06-09 16:31:52 +02:00
Zoltán Papp
96d31c3a5a Align Linux UI packaging deps with Wails v3 GTK4 stack
The Wails v3 tray is a pure DBus StatusNotifierItem implementation and no
longer links libappindicator (a Fyne-era dependency). Drop the
libayatana-appindicator runtime and build deps, and move the rpm package
and dev-dependency docs onto the GTK4 / WebKitGTK 6.0 stack that the
default (non-gtk3) build actually links against.
2026-06-09 12:52:46 +02:00
Eduard Gert
bada2b5b78 Merge remote-tracking branch 'origin/ui-refactor' into ui-refactor 2026-06-09 11:34:01 +02:00
Eduard Gert
32be58cb24 add description to translations 2026-06-09 11:33:54 +02:00
Eduard Gert
aaa5dbb606 forward ui browser logs to go 2026-06-09 10:55:56 +02:00
Zoltán Papp
4fc125dd38 Remove frontend from sonar exclusion 2026-06-09 10:32:19 +02:00
Eduard Gert
727e6d3004 update position of not connected text 2026-06-08 18:13:37 +02:00
Eduard Gert
4a79c24792 Merge remote-tracking branch 'origin/ui-refactor' into ui-refactor 2026-06-08 18:09:29 +02:00
Eduard Gert
6b2ae1c34c update session expiration dialog texts, add monitor aware position 2026-06-08 18:09:22 +02:00
Zoltán Papp
43175e0730 Move no-op rationale into empty function bodies
Replace the doc comments above the empty no-op stubs (bindTrayClick,
startTrayTheme, noopSessionWatcher.Dismiss/Close) with short in-body
comments explaining why each is empty.
2026-06-08 17:34:18 +02:00
Zoltán Papp
b598274424 [client/ui] Refresh profile list on CLI profile select
SwitchProfile now publishes the same profile-list-changed event that
AddProfile/RemoveProfile already emit. The daemon emits no dedicated
profile RPC event, and the React ProfileContext only refreshes on
EventProfileChanged (unlike the tray, which also re-fetches on every
status-string transition via loadProfiles). So a CLI-driven
"netbird down; profile select X; netbird up" refreshed the tray (the
down/up status flips trigger loadProfiles) but left the React profile
dropdown stale, since the select path never surfaced an event.

Publishing the marked INFO/SYSTEM event from SwitchProfile closes that
gap: dispatchSystemEvent re-emits EventProfileChanged, which
ProfileContext.refresh already subscribes to. No proto change.
2026-06-08 17:26:54 +02:00
Zoltán Papp
ee912e176a ci: skip translated locales in codespell with version-stable globs
The recursive ** skip pattern did not take effect with the codespell
shipped by the action, so de/common.json still tripped on real German
words. Use single-star globs (matched per path segment across versions)
and skip every translated locale, keeping only en as source of truth.
2026-06-08 17:14:38 +02:00
Zoltan Papp
6e23ed4da7 [client] Add error event publishing for rejected session deadlines (#6358)
* [client] Surface session deadline rejections via SystemEvent and add timer arm debug logs

When sessionwatch.Watcher.Update rejects a deadline (pre-epoch, too far
in the future, or past the clock-skew tolerance) it silently zeroes the
status recorder, leaving the UI with no "expires in" row and no
indication of why. Publish a SystemEvent_ERROR on the AUTHENTICATION
channel so the rejection appears in the UI event feed and the user
knows re-login may be required.

Also add Debugf log lines in armTimerLocked so that warning and
final-warning timer fire-times are visible in logs without having to
add instrumentation after the fact.

https://claude.ai/code/session_01Y3bQoNgcVjTD4zDTvv7a8u

* [client] Remove verbose arm-timer debug logs from sessionwatch

The per-arm Debugf lines added noise on every deadline update.
Rejection logging already happens at the call site in engine_authsession.go;
the watcher itself needs no extra instrumentation.

https://claude.ai/code/session_01Y3bQoNgcVjTD4zDTvv7a8u

* [client] Leave userMessage empty on deadline-rejected event; use metadata key

Daemon-layer PublishEvent userMessage strings are not localized — the UI
reads metadata keys and builds its own locale-aware copy (same pattern
as the session-warning events in event.go). Drop the hardcoded English
sentence from the deadline-rejected event and instead surface the
rejection reason via a new MetaSessionDeadlineRejected metadata key so
the UI can detect and localize it.

https://claude.ai/code/session_01Y3bQoNgcVjTD4zDTvv7a8u

* [client] Revert silent deadline-rejected event; restore userMessage

MetaSessionDeadlineRejected had no UI consumer: the tray only does
metadata-driven localisation for MetaSessionWarning events; all other
SystemEvents display userMessage directly (tray_events.go). Leaving
userMessage empty made the rejection invisible to the user.

Restore the English userMessage so the generic event path shows
something, and remove the unused MetaSessionDeadlineRejected constant.

https://claude.ai/code/session_01Y3bQoNgcVjTD4zDTvv7a8u

* [client] Localize session deadline rejected notification via metadata key

Follow the same pattern as session-warning events: the daemon emits an
empty userMessage and puts the signal in a typed metadata key
(MetaSessionDeadlineRejected); the UI tray detects the key and builds a
locale-aware OS notification from i18n strings.

Changes:
- sessionwatch/event.go: add MetaSessionDeadlineRejected constant
- engine_authsession.go: empty userMessage, use the new metadata key
- ui/authsession/warning.go: re-export MetaDeadlineRejected for UI consumers
- ui/tray_events.go: gate on isDeadlineRejected alongside isSessionWarning;
  new branch calls t.notify with localized title/body
- i18n locales (en/de/hu): add notify.sessionDeadlineRejected.{title,body}

https://claude.ai/code/session_01Y3bQoNgcVjTD4zDTvv7a8u

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-08 17:10:15 +02:00
Eduard Gert
b067544c8a update padding and text 2026-06-08 16:02:42 +02:00
Eduard Gert
10d84b758f add ipv6 2026-06-08 15:22:35 +02:00
Eduard Gert
0e4d0128b6 add custom error dialog 2026-06-08 12:44:33 +02:00
Zoltán Papp
21f1142355 Merge branch 'main' into ui-refactor
# Conflicts:
#	client/ui/debug.go
#	go.mod
#	go.sum
2026-06-05 17:50:18 +02:00
Eduard Gert
9ecc083139 update missing translations 2026-06-05 14:57:32 +02:00
Eduard Gert
efd874efac add cloud / selfhosted segment in profile creation 2026-06-05 14:38:00 +02:00
Eduard Gert
5877880789 replace native confirm dialog with modals in settings 2026-06-05 13:16:39 +02:00
Eduard Gert
4427aaa31f update advanced port margin, update settings bottom bar height 2026-06-05 12:29:18 +02:00
Zoltán Papp
0ce3fbf5af [client] Tolerate already-deleted peer on profile logout, clear stale email
logoutFromProfile failed hard when the management server returned NotFound
(peer already deleted from the dashboard), blocking both profile logout and
profile removal. Treat NotFound as success — the peer is already gone, so
deregistering it is already satisfied.

Also drop the user-side per-profile state file on logout. The account email is
sourced from <profile>.state.json (written by the CLI after SSO login), which
the root daemon can't reach, so logout left a stale email showing in the UI.
Connection.Logout now removes it from the UI process after a successful logout;
the next SSO login recreates it.
2026-06-05 12:05:41 +02:00
Zoltán Papp
3967864172 [client/ui] Center windows on show under minimal WMs (XEmbed tray)
On minimal window managers (fluxbox et al, the in-process XEmbed-tray
path) the WM neither centers small windows nor restores their position
across a hide -> show round-trip, so the main, Settings, and dialog
windows opened in the top-left corner instead of centered.

These windows are created Hidden, so Wails' Linux/GTK4 backend skips its
post-Show centering pass (gated on !Hidden) and InitialPosition has no
effect on an unrealized window. Re-center from Go after Show, gated on
the minimal-WM environment via a recenterOnShow predicate (set to
xembedTrayAvailable on Linux, nil on macOS/Windows where the WM handles
placement). centerWhenReady polls from a background goroutine until the
move actually lands -- Center() moves via raw X11, which no-ops while the
GdkSurface is still nil and GTK4 realizes it asynchronously after Show().

Also reorder xembed_host_linux.go so the static helpers (xembedTrayAvailable,
goMenuItemClicked) sit at the end, after the constructor and methods.
2026-06-05 11:42:03 +02:00
Eduard Gert
296d3f124b truncate dns in main screen 2026-06-05 09:55:50 +02:00
Eduard Gert
adf1fe1858 add ready prop to autosize hook 2026-06-05 09:48:17 +02:00
Zoltán Papp
1108808ab1 [client] Persist sync response only after network map is applied
Previously the SyncResponse was persisted to syncStore before
updateNetworkMap() ran. If applying the network map failed, the engine
persisted state it never applied, so GetLatestSyncResponse() could return
stale/unapplied state. Move the persistence into the post-apply success
path so the persisted response always reflects what the engine applied.
2026-06-04 18:31:37 +02:00
Zoltán Papp
db371a0263 [client/ui] Fix tray submenu not updating on KDE/Plasma
The Profiles and Exit Node submenus (and the About version/Update rows)
stopped reflecting changes on KDE/Plasma: after the first profile switch
the menu froze on its initial snapshot, and "Manage Profiles" — plus the
profile rows themselves — stopped responding to clicks entirely.

Root cause (confirmed via dbus-monitor): Plasma's StatusNotifierItem host
caches a submenu's layout the first time it is opened (GetLayout for that
submenu id) and never re-fetches it on a LayoutUpdated(parent=0) signal.
The old submenu.Clear()+Add() repaint allocated fresh monotonic item ids
each time but reused the same submenu container id, so Plasma kept showing
the stale snapshot and, on click, sent the stale ids back — which the
rebuilt itemMap no longer knew, silently no-op'ing the click.

Fix: route every dynamic tray-menu change through a new relayoutMenu that
rebuilds the whole tree (buildMenu + repaint cached state + a single
SetMenu), allocating brand-new submenu container ids. Plasma treats those
as unseen and re-queries them on next open, fixing both the stale paint
and the dead clicks. loadProfiles/refreshExitNodes now cache their rows
and drive relayoutMenu; the update row goes through a new onMenuChange
hook; the daemon-version row relayouts too. relayoutMenu is serialised by
menuMu and the fill*Submenu helpers are pure UI (no fetch, no SetMenu) so
it never recurses. The whole-tree SetMenu also subsumes the prior darwin
detached-NSMenu workaround.
2026-06-04 18:28:30 +02:00
Theodor Midtlien
512899d82d [client] Prevent corruption from competing log rotation and improve debug bundle (#6214)
* Adds heuristic to detect an edge case on Linux where a system has configured logrotate as a separate service to rotate log files which would mangle our client log files. If we detect logrotate being configured for netbird, we disable our rotation.

* Adds new env var to disable log rotation: NB_LOG_DISABLE_ROTATION

* Adds compressed and plain logrotate files to debug bundle.

* Replaces lumberjack with timberjack (maintained fork with bug fixes and extra features).

* Clarifies which daemon version is running in the bundle stats.

* Change logging for client service status to console
v0.72.0
2026-06-04 17:36:45 +02:00
Zoltán Papp
1412b06999 Add rabbit ai config 2026-06-04 17:27:56 +02:00
Zoltán Papp
ca6f6d88cb Merge branch 'main' into ui-refactor 2026-06-04 17:06:11 +02:00
Zoltán Papp
e298747203 [client/ui] Refresh profile list in tray + UI on CLI profile add/remove
The daemon emits no dedicated profile-changed RPC event, and a profile
add/remove doesn't move the connection status, so the UI's SubscribeStatus
path never fired for CLI-driven `netbird profile add|remove` (and the tray's
iconChanged guard would swallow it anyway). The tray menu and the React
profile list stayed stale until the next status-string transition.

AddProfile/RemoveProfile now publish a marked INFO/SYSTEM event over
SubscribeEvents (metadata kind=profile-list-changed, empty userMessage so it
stays silent). The UI's dispatchSystemEvent recognises the marker and
re-emits the existing EventProfileChanged, which the tray's loadProfiles and
React's ProfileContext.refresh already subscribe to — so both surfaces
refresh from a single signal that originates in the shared daemon handler
(covering both CLI and UI-initiated removals). No proto change.

Also drop a stray, build-breaking `app.Updater` line in main.go.
2026-06-04 16:03:22 +02:00
Theodor Midtlien
5993ec6e43 [client] Allow wireguard port to be zero in UI and show port in status command (#6158)
* Allow wireguard port to be set to 0 in UI

* Add wireguard port to cmd status

* Correct protoc version
2026-06-04 15:04:11 +02:00
Zoltán Papp
cba4a8a63b [client/ui] Fix login wedging until restart after a failed SSO attempt
startLogin held both guards (the module-level loginInFlight and the
caller's React-level loginGuard) across the post-failure errorDialog
await. The native Windows MessageBox disables its parent for its whole
lifetime while the main window's WindowClosing hook hides instead of
closing, so the dialog promise can outlive the click — and even a clean
dismissal kept the guards held until the promise settled. Until then
every later Connect click and tray trigger-login was silently dropped at
the guard check, so the only way back was a client restart.

Release both guards the instant the flow itself settles, before the
dialog: startLogin now takes an onSettled callback fired in its finally
(driveLogin releases loginGuard through it), and the errorDialog await
moved out of the try/finally so no guard is ever gated on the dialog.
2026-06-04 13:42:29 +02:00
Zoltán Papp
93e068f753 [client/ui] Honour DEV=true in windows:build:console for DevTools
windows:build:console fixed -tags production, which disables the
WebKit/WebView2 DevTools inspector — so there was no way to get a
console-attached Windows binary with the frontend JS console reachable.
Mirror build:native's DEV handling: DEV=true drops the production tag
while keeping the console subsystem (no -H windowsgui).
2026-06-04 13:21:41 +02:00
Zoltán Papp
94065a8058 [client/ui] Enable tray status row on Linux to avoid greyed-out indicator
The informational status row at the top of the tray menu was disabled on
Linux, which painted the connection-status indicator greyed-out. Enable
it on Linux so the row renders at full opacity; it has no OnClick handler
so clicking it remains a no-op.
2026-06-04 11:42:22 +02:00
Maycon Santos
eac6d501c3 [infrastructure] allow docker image overrides for getting started (#6335)
* [infrastructure] allow docker image overrides for getting started

Make dashboard and server image configurations overrideable via environment variables

* [infrastructure] update Traefik gRPC rule to include ProxyService PathPrefix

* make Traefik and CrowdSec images configurable via environment variables
2026-06-04 11:24:47 +02:00
Maycon Santos
deeae30612 [misc] Add Codecov integration and coverage reporting across workflows (#6333) 2026-06-03 19:08:45 +02:00
Bethuel Mmbaga
f3cdf163e1 [management] Export ResolveDomain (#6334) 2026-06-03 19:53:57 +03:00
Eduard Gert
d7263a6be9 Merge remote-tracking branch 'origin/ui-refactor' into ui-refactor 2026-06-03 17:33:20 +02:00
Eduard Gert
64199209cf add onboarding 2026-06-03 17:33:13 +02:00
Zoltán Papp
166c6118e2 [client] Fix Up failing with NeedsLogin after SSO login
After a successful WaitSSOLogin the daemon deliberately stays in
StatusNeedsLogin, and after a mid-session expiry (peer kicked out by the
management server) the engine tears down with clientRunning == false. In
both cases the caller's Up takes the fresh-start branch, which only
accepted StatusIdle and rejected NeedsLogin with
"up already in progress: current status NeedsLogin".

This forced a second Up to actually connect (CLI: re-run `netbird up`;
GUI: click Connect again). Treat NeedsLogin as a legitimate fresh-start
entry state and reset it to Idle before starting the engine, so the
first Up after login drives Connecting -> Connected directly.
2026-06-03 17:19:52 +02:00
Zoltan Papp
3e61ccb162 [client] Persist sync response via pluggable store (disk on iOS) (#6331)
* Persist sync response via pluggable store (disk on iOS)

The latest Management sync response (which carries the network map) was
kept in memory for debug bundle generation. On memory-constrained
platforms like iOS the network map can be large enough to matter.

Introduce a syncstore package with a Store interface and two backends:
a memory backend (the previous behavior) and a disk backend that
serializes the response to a file in the state directory. The backend
is selected per-platform at build time: disk on iOS, memory elsewhere.

The disk store clears any leftover file on construction so a fresh
store never reads stale data from an earlier run (e.g. another
profile's network map).

In the engine, drop the separate persistSyncResponse bool: the store is
only instantiated while persistence is enabled, and its presence is
what marks persistence as active. The store is also cleared on engine
close so the file does not linger on disk.

* syncstore: silence nilnil linter on "nothing stored" returns

Get returns (nil, nil) to signal that nothing is stored, which is part
of the Store contract and preserves the original behaviour. Annotate
both backends with //nolint:nilnil so golangci-lint does not flag it.

* syncstore: hold syncRespMux for the whole store Set/Get

Both handleSync and GetLatestSyncResponse snapshotted e.syncStore under
the read lock and then released it before calling Set/Get. That allowed
SetSyncResponsePersistence(false) or engine close to clear the store
mid-call. In particular a concurrent Clear()+nil followed by a late
Set could re-create the file that was just removed, defeating the
leak/lingering protection.

Hold syncRespMux for the duration of the store operation in both spots
so the store cannot be cleared while a Set/Get is in flight.

* syncstore: avoid StateDir "." when state path is empty

On mobile the state path may be empty (the engine tolerates a missing
state file). filepath.Dir("") returns ".", which would make a
disk-backed syncstore write into the working directory instead of
letting NewDiskStore fall back to os.TempDir().

Only set engineConfig.StateDir when path is non-empty.
2026-06-03 14:18:50 +02:00
Viktor Liu
a48c20d8d8 [client] Gate DNS forwarder on BlockInbound (#6257) 2026-06-03 11:33:29 +02:00
Riccardo Manfrin
2b57a7d43b [client, management, misc] expose VCS revision in dev build version output (#6263)
* Refactor to use a common checker for development version

* Adds commit sha to development version for cobra command only

Leave dashboard unaffected

* Adjust for "v0.31.1-dev" test case

which must be considered pre-release

* Drop synthetic "dev"/"0.50.0-dev" firewall feature-gate fixtures

These test cases encoded the loose strings.Contains(v, "dev")
semantics inherited from peerSupportedFirewallFeatures, but
NetbirdVersion() never produces those values — only the literal
"development" (and now "development-<sha>[-dirty]") ever flows
through the wire. The agent owns the semantics of an ephemeral
development build, so the tests should exercise the strings we
actually emit.

Replaced with development, development-<sha> and
development-<sha>-dirty cases that match the HasPrefix("development")
predicate introduced upstream.

* Remove unexistent tests on wire format

The sha / dirty flag are added only when the CLI asks the version.
Account versions is unaffacted and can only strictly match "development"

* Adds tests for IsDevelopmentVersion
2026-06-03 08:56:50 +02:00
Eduard Gert
1710868a09 add exit node switcher 2026-06-02 17:23:56 +02:00