Resolve conflicts and complete the profile display-name -> ID migration
across the daemon, CLI, UI services, tray, and React frontend.
- Regenerate client/proto daemon.pb.go from the merged proto so it carries
both branches' RPCs (ui-refactor: SubscribeStatus/RegisterUILog/ExtendAuthSession,
main: RenameProfile + id fields); keep the v6.33.1 generator header
- server.go: combine ui-refactor's profile-list-changed events with main's
id-bearing responses; publish profile-list-changed on rename
- Drop the deleted Fyne client_ui.go/profile.go and port main's profile-ID
changes into the refactored services/tray
- UI services, tray and React: send the profile ID as the daemon handle and
keep the display name for rendering only (activeProfileId vs activeProfile)
- Relax the profile-name input to match the daemon's sanitizeDisplayName
(spaces, emoji, any valid UTF-8); cap at 128
- Expose RenameProfile via a Profiles.Rename services wrapper (+ regenerated
bindings) for the frontend to wire up
- cmd/login.go: use the profile ID for GetProfileState
Add a no-op WailsUIReady RPC the UI probes once at startup. A reachable
daemon that returns Unimplemented predates this UI and is too old to
drive it; the probe distinguishes that from an unreachable daemon. On an
outdated daemon the UI fires a localized OS notification, since the main
window may not open to show an in-app error.
Proto regenerated with protoc 33.1 to keep the v6.33.1 header.
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.
Integrates main's MDM configuration-profile feature and adapts it to the
Wails UI (this branch had already replaced the Fyne UI).
Conflict resolution:
- go.mod/go.sum: take main's deps; howett.net/plist pinned to v1.0.2-... (tidy)
- client/proto/daemon.pb.go: regenerated from the merged daemon.proto
- client/internal/peer/status.go: union of ipToKey (main) + sessionExpiresAt (HEAD)
- client/server/server.go: main's intent/liveness model (connectionGoroutineRunning,
clientRunning no longer cleared by the goroutine) + empty-PSK guard
- client/ui/client_ui.go, client/ui/profile.go: removed (dead Fyne UI)
MDM port (backend + tray):
- services/settings.go: expose MDMManagedFields plus a managedFields map keyed
by Config field names so the settings form can gate a control without
translating mdm.Key* names
- tray: gate Profiles / Exit Node menus on DisableProfiles / DisableNetworks via
GetFeatures, refreshed on the config_changed system event (replaces the legacy
2s poll); localized MDM policy-applied toast in all shipped locales
- client/proto/metadata.go: shared constants for the config_changed /
policy_applied event markers
PreSharedKey: GetConfig now returns preSharedKeySet (bool) instead of the masked
value; the settings form provides its own placeholder and sends a new key only
when the user types one.
When the daemon is set to debug/trace, the GUI now automatically writes a
rotated gui-client.log in the user's config dir and the daemon's debug bundle
collects it. The UI learns the level both at startup (daemon already in debug)
and live, by piggybacking the existing SubscribeEvents stream: the daemon
publishes a marked log-level-changed SystemEvent (and a per-subscription
snapshot), which DaemonFeed routes to guilog.DebugLog instead of an OS toast.
The UI registers its log path via a new RegisterUILog RPC so the root daemon,
which can't resolve the user's config dir, knows where to find the file.
Manual --log-file (any value) disables the daemon-driven file logging.
Fix: client/ui SetLogLevel looked up proto.LogLevel_value with the lowercase
logrus name, which never matched the uppercase enum keys and silently fell back
to INFO — so trace/debug requests from the bundle flow had no effect.