v2.0.3 Release Changes (TBD)#988
Open
tvancott42 wants to merge 4 commits into
Open
Conversation
…te Agent connection alerts; Multi-Site Disable / Remove Site (#982) (#987) * Settings - Connection: API key auth recovers after the UniFi Network application restarts (#986) A transient 401/403 from /proxy/network while the Network application is upgrading, reprovisioning, or wedged permanently killed an API-key client: EnsureAuthenticatedAsync treated any auth failure as a revoked key and short-circuited every subsequent call without touching the network, until the container was restarted or the connection re-saved. Re-validate the key instead, throttled to one probe per minute so a genuinely revoked key stays cheap. * Alerts & Schedule - Rules: new UniFi Console event types alert when the console connection fails and recovers Two consecutive failed auth probes spanning at least 50s publish console.connection_failed (Warning); the next successful auth publishes console.connection_restored (Info). Armed only after a successful connection, suppressed while an agent tunnel is coming up, counters reset on intentional teardown, and default rules seed with a 30-minute failure cooldown so a flapping console upgrade produces one alert, not a stream. Per-site via the connection service's site slug. * Alerts & Schedule - Rules: On-Site Agent event types alert when a site agent goes offline and reconnects A periodic sweep checks IsAgentLive (open tunnel or fresh heartbeat) for every enrolled agent; 3 continuous minutes offline publishes agent.offline (Warning) once per outage, and the next live sweep pairs it with agent.reconnected (Info). Sweeping instead of hooking tunnel teardown keeps agent redeploys and tunnel bounces silent. Never-seen and disabled agents are excluded so in-progress setups don't alert. * Alerts & Schedule - Rules: On-Site Agent rules only seed on the main site when the default site has an agent Secondary sites keep them (agents are their normal connection mode, and site provisioning seeds them at creation). Single-site installs no longer get agent rules they can't use; enrolling a default-site agent seeds them at that moment. Skipped rules also mean a user deletion sticks instead of re-seeding every startup. * Multi-Site: site switcher keyboard support - Esc closes, arrows navigate, Enter/Space select Arrow keys move focus through the menu (Down from the trigger enters the list), Enter activates natively, Space activates per the ARIA menu pattern, and Escape closes the dropdown. Tab/Shift+Tab keep their native behavior - only fully-handled keys are intercepted. * Settings - Multi-Site: Disable / Remove Site (#982) New third section in a site's Configuration panel alongside Agent and Settings. Disable stops the site's monitoring collection and console connection immediately and hides it from the site switcher, Sites page, and overview card - data is kept and it can be re-enabled in place. Remove is permanent behind a double confirmation: it deletes the site's agents, registry row, and database directory (SQLite pools cleared first so the files aren't locked), then frees the license seat. Both are blocked for the default site and for the site currently being viewed. Disabled sites' agents are excluded from the offline alert sweep - taking a paused site's agent down is intentional. * Multi-Site: double-click guard on Create Site, no confirm on re-enable, form-help legibility Create Site already disabled while busy, but a fast double-click queues both click events before the disabled state renders and the circuit runs them back to back - the second created the duplicate name-2 site from #982. A re-entrancy guard on the created site swallows it. Re-enabling a disabled site no longer asks for confirmation (only disable does). Form help text bumped 0.75rem -> 0.8rem. * Multi-Site: site switcher rebuilds live when the site list changes New SiteRegistryChangeNotifier singleton broadcasts create, rename, enable/disable, remove, and the multi-site toggle from SiteManagementService; every open circuit's switcher subscribes, reloads its list on its own dispatcher, and closes the dropdown if it was open. Previously the switcher only loaded at circuit start, so registry changes needed a page reload to show up. * Multi-Site: Create Site spinner actually renders; Remove Site confirm notes InfluxDB buckets stay SQLite completes EF's async calls synchronously, so site provisioning never yielded and the queued disabled+spinner render only flushed after it finished - the button looked inert for the full few seconds. A Task.Yield after flagging busy pushes the spinner to the browser first. Bucket deletion needs the InfluxDB admin token, which is deliberately never persisted, so Remove Site leaves the site's buckets; the confirmation now says so (retention ages the data out regardless). * Sites: Add Site card scrolls to the add form and focuses the name field Rides the existing Settings anchor scroll-and-highlight: the card now navigates to the multisite tab with the #site-agent-setup anchor, which scrolls to the wizard and focuses its site name input.
…504, matching the 401/403 recovery A self-hosted UniFi OS Server / Network application behind a reverse proxy returns 502/503/504 while the backend restarts, upgrades, or reprovisions. The client only reset auth state (and thus re-authenticated, fed the connection alerting, and self-healed) on 401/403 - a gateway 5xx just failed the call and left the client wedged "connected" while every console read failed. Treat the gateway-unavailable family the same as a stale session via a shared IsRecoverableAuthFailure check across every re-auth path, and surface a "temporarily unavailable, retrying" message on connect instead of a raw "failed with status 502" or a JSON parse error.
…fter a transient outage The periodic device-fetch reconnect only covered agent-tunneled secondary sites (!_isDefault && console-via-agent). The default, directly-connected site relied solely on the one-shot startup connect, so a self-hosted console returning 502/503 during a restart or upgrade - especially right when the optimizer starts - failed that connect, disposed the client, and left the main site dark until a schedule ran or the process restarted. Reconnect any disconnected site that isn't waiting on an agent tunnel, still throttled to one attempt per 30s, so the default site recovers on its own once the console's backend is back.
…ped IPv6 (::ffff:) (#990) * Client Performance / speed tests: normalize IPv4-mapped client IPs (::ffff:) An IPv4 client accepted on Kestrel's dual-stack socket (the Docker/Proxmox default) arrives as the IPv4-mapped IPv6 form ::ffff:a.b.c.d. That prefix was carried through unmodified, so: - Client Performance showed "Device Not Found" (the detected ::ffff: address never equals the console's plain-IPv4 BestIp), and - Client / LAN / WAN Client Speed Test stored and displayed the mapped address and mislabeled LAN devices as WAN (the private-IP prefix check missed it), and the result never enriched a ClientMac, so it couldn't correlate to a client's Performance dashboard. Normalize IPv4-mapped addresses to plain IPv4 at every point a client address is captured - the client-dashboard HTTP capture and agent whoami probe, the speed-test endpoints/recording, the iperf3 client relay and connection parse, and the agent's result relay - via a shared NetworkUtilities.NormalizeToIPv4String helper. Going forward DeviceHost stores plain IPv4, enrichment matches the console list and sets ClientMac, and correlation works by MAC (the stable key). Also harden the consumers as defense in depth (IdentifyClientAsync, the speed test LAN/WAN badge, and IsPrivateIpAddress, which had a latent bug misreporting a mapped RFC1918 address as public), and add a data migration that collapses existing ::ffff: DeviceHost values so the three speed-test views show real IPs. The normalization only unwraps ::ffff: mapped addresses (IsIPv4MappedToIPv6); genuine IPv6 client identity - GUA, ULA, link-local - is never altered. The migration deliberately does not re-derive ClientMac: correlating a historical row by its point-in-time IP is unsound (DHCP/reservation churn), so old rows are cleaned for display but stay uncorrelated rather than risk mis-attribution. * Test: GetClientIp normalizes a mapped RemoteIpAddress and X-Forwarded-For Exercises the actual client-IP capture entry point with a synthetic DefaultHttpContext - the path an IPv4 client hits on Kestrel's dual-stack socket - so the ::ffff: unwrap is verified without needing that environment. Covers mapped connection address, mapped XFF (precedence), plain IPv4, a real IPv6 client (left untouched), and the no-address "unknown" fallback. * Test: use RFC 3849 documentation IPv6 range for the passthrough case
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rolling collection of dev changes for the v2.0.3 release. This description tracks what's on dev as PRs land; release notes are drafted from it at release time.
So far: #987 (fixes #986, #982) and #990 (fixes #989), plus 502/503/504 handling and default-site reconnect follow-ups on dev
Settings - Connection
Multi-Site
Client Performance
::ffff:a.b.c.d), which never matched the UniFi Console's plain-IPv4 client list - so the page showed "Device Not Found" with a::ffff:-prefixed address even though the device was right there. The address is normalized to plain IPv4 before lookup, on the default site and via the on-site agent whoami probe on managed sites (fixes Client Performance: device not found / Client Speed Test: showing LAN device as WAN (::ffff: IP prefix) #989). Genuine IPv6 clients are left untouched.Client Speed Test
::ffff:address, so the device column showed the prefix and a local device was mislabeled WAN. New results store and display plain IPv4 with the right label; Client WAN Test and LAN Speed Test share the results table and benefit too. A one-time migration collapses existing::ffff:addresses so past results also show real IPs, and normalizing before enrichment lets a result resolve its device MAC and correlate to that client's Client Performance history.Alerts & Schedule - Rules
console.connection_failed(Warning) after two consecutive failed authentication attempts spanning at least the revalidation interval;console.connection_restored(Info) on recovery. Per-site, armed only after a successful connection, suppressed while a site's agent tunnel is coming up, 30-minute failure cooldown so a flapping console upgrade produces one alert.agent.offline(Warning) when an enrolled agent is continuously offline for 3 minutes;agent.reconnected(Info) when it returns. Judged by the same live definition the UI uses (open tunnel or fresh heartbeat) via a periodic sweep, so agent redeploys and brief tunnel bounces stay silent. Agents never connected, disabled, or on a disabled site don't alert.Fixes