The daemon runs as SYSTEM and writes the bundle into C:\Windows\SystemTemp,
whose ACL denies the logged-in user, so a plain 'explorer /select' could not
open it. The Windows reveal now elevates via ShellExecuteW with the runas verb,
falling back to an unelevated reveal of the parent dir on decline.
The UI client migrated from Fyne to Wails v3 + React. Update the
Requirements and Build sections accordingly, fix the Windows installer
UI build command to use the task runner, bump the Go version to 1.25,
and drop the now-redundant client/ui/README.md.
The critical-event gate compared against a bare "critical" literal while
the matching string is produced from the proto SystemEvent_CRITICAL enum in
systemEventFromProto. Add services.SeverityCritical next to the Status*
constants so the two sides share one definition.
The critical-event gate used a case-sensitive == "critical" where every
other status/severity compare in the UI uses strings.EqualFold, so a
daemon-side reword to a different case would silently drop the bypass.
newXembedHost failure left the private session bus open, leaking an fd
per RegisterStatusNotifierItem on systems without an XEmbed tray. Add a
closeBus helper that logs on close failure and use it at every back-off
path instead of discarding the error.
Xlib's default protocol-error handler calls exit() on any async X error,
so a tray race (tray manager window dying between find and dock, XMoveWindow
on a popup the WM already destroyed) would take the whole UI process down.
Install process-global logging no-op handlers via XSetErrorHandler/
XSetIOErrorHandler after every XOpenDisplay. Since the handler slot is
process-global and GDK init can clobber it, additionally wrap the popup
code's raw Xlib calls on GDK's Display in gdk_x11_display_error_trap_push/
pop_ignored, which is independent of the global handler.
GetRestrictions called the daemon GetConfig with an empty
GetConfigRequest, which the daemon has rejected since multi-profile
support landed ("active profile name is empty") because it reads the
profile name from the request. Resolve the active profile via
GetActiveProfile first and pass its name/username, mirroring the
working Settings.GetConfig path. GetActiveProfile self-heals to the
default profile, so a valid name is always supplied; the
profile-switch-disabled MDM flag is orthogonal and unaffected.
WebKit (macOS WKWebView) omits the "Name: message" header from
Error.stack, so forwarding only the stack hid the real cause of
failures. Prepend the error name, message and optional cause before
the stack so daemon RPC errors surface in gui-client.log.
When JWT group sync is enabled with a restrictive JWTAllowGroups list, the local owner of an embedded-IdP (Dex) deployment can get locked out. The allow-groups check runs account-wide but local password users do not receive
external IdP group claims, so they can't satisfy the allowed list.
This skips JWT group evaluation for local Dex users so the restriction and JWT group sync continue to apply to external-IdP users as intended.
Non-English UI translations and the foreign-language examples in
TRANSLATING.md trip codespell on real foreign words. Extend the skip
list to cover es, fr, it, pt, ru, zh-CN locale dirs and the
TRANSLATING.md doc, keeping en/common.json as the source of truth.
IsDeselectAllActive was identical to IsDeselectAll (both return the
deselectAll flag under a read lock). The two were introduced in parallel
on separate branches for the same fix - guarding against management route
sync overriding a user's explicit deselect-all - and ended up coexisting
after the branches merged.
Drop IsDeselectAllActive, keep the canonical IsDeselectAll from main, and
move its richer doc comment over. Update callers accordingly.
Commit 8841b950a made connectWithRetryRuns stop after a single login
attempt on PermissionDenied, but TestConnectWithRetryRuns still asserted
the loop retries 3+ times, so it failed with counter=1.
Repurpose the test (now TestConnectStopsRetryOnPermissionDenied) to
verify the loop stops after exactly one login on PermissionDenied,
keeping the fast retry env config that would otherwise drive several
attempts. Also redirect profile paths to a temp dir so it runs without
root.
Group all type declarations at the top, keep each type's methods with it,
move package-level helpers and static functions to the end of the file.
- connection.go: ClientError methods sit directly under the struct; the
classifyDaemonError / translateShort helpers move to the file end.
- windowmanager.go: the title / retitleAll / hideOtherWindowsLocked /
restoreHiddenWindowsLocked / getScreenBasedOnCursorPosition helpers and the
errorDialogURL / u32ptr static functions move to the file end; u32ptr no
longer splits the const/var block.
Shorten over-long godoc/inline comments across the client/ui tray and
services code: drop narrative restatement, legacy-Fyne tangents, and text
already evident from signatures and names. Keep only the non-obvious why
(concurrency/lock ordering, platform quirks, ordering constraints, the
profile-switch state table). No code changes.