Headscale's RegisterNodeRequest.user proto field is a string that the
RegisterNode handler resolves with GetUserByName (a strict WHERE name=?
SQL match) — there is no numeric-id fallback. The Owner select in the
Register Machine Key dialog was sending user.id, so registration failed
with ErrUserNotFound whenever the display name and the numeric id
disagreed (which is always for unlinked Headscale users).
Send user.name instead.
Closes#532
Amp-Thread-ID: https://ampcode.com/threads/T-019e7ae4-6862-760c-a3e7-239350eab71d
Co-authored-by: Amp <amp@ampcode.com>
Apparently I didn't use my brain cells and rely on the /version
endpoint that Headscale has exposed since 0.26 (our lowest supported
version). Switching to that significantly simplifies the API surface.
The 'Key expiry' attribute only checked node.expiry !== null, showing a
garbled date for the '0001-01-01T00:00:00Z' zero-time that headscale
may return for tagged nodes (juanfont/headscale#3170).
uiTagsForNode() only checked node.expiry === null, missing Go
zero-time that headscale returns for tagged nodes after a
restart (juanfont/headscale#3170).
The !node.expired guard is technically redundant with isNoExpiry but
documents intent: "No expiry" is only shown for nodes that never
had an expiry set
Previously we would use naive revalidators which would invalidate EVERY
SINGLE action loader every 3 seconds, resulting in several fetches. It
would also bubble fetches across the layout actions into the individual
pages.
This new approach selectively has live stores of resources which then
poll for changes on the server side and then dispatches updates to the
client via a new /events/live SSE endpoint.
In Headscale 0.28+, nodes can be registered with tag-only preauth keys
which have no associated user. This change updates the Machine type to
make user optional and adds null checks throughout the codebase where
node.user is accessed.
Fixes tag node operations (rename, add tags) that previously failed
with 'Unexpected Server Error' when accessing node.user.providerId
on nodes without a user association.
Refs: #432
Adds conditional rendering for the "Change owner" menu item in machine management, hiding it for versions 0.28.0-beta.1 and above. This prevents users from attempting to change node ownership on newer versions where this functionality is not supported. The change involves passing a new `supportsNodeOwnerChange` prop through the component hierarchy and updating the menu rendering logic accordingly.
- Add search input to filter machines by name or IP address
- Add sortable column headers for Name, IP, Version, and Last Seen
- Sort IP addresses numerically by octets (not alphabetically)
- Sort versions numerically by segments (1.10.0 > 1.9.0)
- Sort Last Seen with online machines treated as most recent
- Add time delta display for offline machines (e.g., "2 days ago")
- Add machine count display showing filtered/total counts
- Add clear button (X) to search input
Closes#351