Commit Graph
2953 Commits
Author SHA1 Message Date
Viktor Liu d52cf1d376 Fix VNC lint, 386 atomic alignment, and Sonar code smells 2026-05-20 16:34:29 +02:00
Viktor Liu fd8a21d3a0 Resolve merge conflicts with main 2026-05-20 15:38:01 +02:00
Viktor Liu d705dac572 Collapse X11 DISPLAY/XAUTHORITY auto-detect logs into one line 2026-05-20 15:36:26 +02:00
Viktor Liu 9192b4f029 [client] Bump macOS sleep callback timeout to 20s (#6220) 2026-05-20 13:09:22 +02:00
Maycon Santos c784b02550 [misc] Update contribution guidelines (#6219)
Update contribution guidelines and PR template to require discussing impactful changes with the team
2026-05-20 12:21:03 +02:00
Viktor Liu cb3269df4c Add ExtendedMouseButtons for back/forward mouse buttons 2026-05-20 12:15:00 +02:00
Viktor Liu 2ce8ba1068 Enable IdP JWKS refresh in VNC JWT validator 2026-05-20 12:15:00 +02:00
Viktor Liu e56dca74ca Track macOS click count and pixel-scale wheel scroll 2026-05-20 12:14:53 +02:00
Viktor Liu 17b60b6c6b Use pixel-mode scroll on macOS for smoother wheel events 2026-05-20 12:14:45 +02:00
Viktor Liu 46e3cf8daf Drop unreliable Sequoia preflight from macOS Screen Recording check 2026-05-20 12:14:37 +02:00
Viktor Liu 88695f17cc Proxy macOS VNC connections from the LaunchDaemon to a per-user agent via launchctl asuser 2026-05-20 12:12:20 +02:00
Viktor Liu 8092fe2f93 Extract daemon-to-agent loopback proxy and token helpers into a platform-neutral file 2026-05-20 12:11:15 +02:00
Viktor Liu 6193ed5b17 Drop pbpaste trace log that fires whenever the macOS pasteboard is empty 2026-05-20 12:11:15 +02:00
Viktor Liu 025c6109a5 Composite remote cursor into the framebuffer when the dashboard toggles it on 2026-05-20 12:11:15 +02:00
Viktor Liu 0b9c902ed4 Emit Cursor pseudo-encoding on Linux, Windows, and macOS 2026-05-20 12:11:15 +02:00
Viktor Liu 254b8033af Treat ExtendedClipboard messages with the Caps bit as Caps regardless of co-set action bits 2026-05-20 12:11:15 +02:00
Viktor Liu e274bb81c5 Collapse dirty rects to their bounding box when the bbox is densely dirty 2026-05-20 12:11:15 +02:00
Viktor Liu f8ab072f3c Honour client JPEG quality fully now that backpressure caps it dynamically 2026-05-20 12:11:15 +02:00
Viktor Liu b1b3b6f12d Throttle VNC encoder JPEG quality and skip frames under write backpressure 2026-05-20 12:11:15 +02:00
Viktor Liu 7e7e8d8b32 Surface DXGI fallback to GDI at warn level on Windows 2026-05-20 12:11:15 +02:00
Viktor Liu 56598571c3 Accept any RGB shift permutation as Tight-compatible per RFB 7.7.6 2026-05-20 12:11:15 +02:00
Viktor Liu 1b2353f907 Restore Hextile SolidFill and Zlib encoding paths 2026-05-20 12:11:15 +02:00
Maycon Santos 4e2ed2a4d7 [management] Add metrics for peer status updates and ephemeral cleanup (#6196)
* [management] Add metrics for peer status updates and ephemeral cleanup

The session-fenced MarkPeerConnected / MarkPeerDisconnected path and
the ephemeral peer cleanup loop both run silently today: when fencing
rejects a stale stream, when a cleanup tick deletes peers, or when a
batch delete fails, we have no operational signal beyond log lines.

Add OpenTelemetry counters and a histogram so the same SLO-style
dashboards that already exist for the network-map controller can cover
peer connect/disconnect and ephemeral cleanup too.

All new attributes are bounded enums: operation in {connect,disconnect}
and outcome in {applied,stale,error,peer_not_found}. No account, peer,
or user ID is ever written as a metric label — total cardinality is
fixed at compile time (8 counter series, 2 histogram series, 4 unlabeled
ephemeral series).

Metric methods are nil-receiver safe so test composition that doesn't
wire telemetry (the bulk of the existing tests) works unchanged. The
ephemeral manager exposes a SetMetrics setter rather than taking the
collector through its constructor, keeping the constructor signature
stable across all test call sites.

* [management] Add OpenTelemetry metrics for ephemeral peer cleanup

Introduce counters for tracking ephemeral peer cleanup, including peers pending deletion, cleanup runs, successful deletions, and failed batches. Metrics are nil-receiver safe to ensure compatibility with test setups without telemetry.
2026-05-20 12:11:15 +02:00
Maycon Santos 1f45c6f772 [management] Fence peer status updates with a session token (#6193)
* [management] Fence peer status updates with a session token

The connect/disconnect path used a best-effort LastSeen-after-streamStart
comparison to decide whether a status update should land. Under contention
— a re-sync arriving while the previous stream's disconnect was still in
flight, or two management replicas seeing the same peer at once — the
check was a read-then-decide-then-write window: any UPDATE in between
caused the wrong row to be written. The Go-side time.Now() that fed the
comparison also drifted under lock contention, since it was captured
seconds before the write actually committed.

Replace it with an integer-nanosecond fencing token stored alongside the
status. Every gRPC sync stream uses its open time (UnixNano) as its token.
Connects only land when the incoming token is strictly greater than the
stored one; disconnects only land when the incoming token equals the
stored one (i.e. we're the stream that owns the current session). Both
are single optimistic-locked UPDATEs — no read-then-write, no transaction
wrapper.

LastSeen is now written by the database itself (CURRENT_TIMESTAMP). The
caller never supplies it, so the value always reflects the real moment
of the UPDATE rather than the moment the caller queued the work — which
was already off by minutes under heavy lock contention.

Side effects (geo lookup, peer-login-expiration scheduling, network-map
fan-out) are explicitly documented as running after the fence UPDATE
commits, never inside it. Geo also skips the update when realIP equals
the stored ConnectionIP, dropping a redundant SavePeerLocation call on
same-IP reconnects.

Tests cover the three semantic cases (matched disconnect lands, stale
disconnect dropped, stale connect dropped) plus a 16-goroutine race test
that asserts the highest token always wins.

* [management] Add SessionStartedAt to peer status updates

Stored `SessionStartedAt` for fencing token propagation across goroutines and updated database queries/functions to handle the new field. Removed outdated geolocation handling logic and adjusted tests for concurrency safety.

* Rename `peer_status_required_approval` to `peer_status_requires_approval` in SQL store fields
2026-05-20 12:11:15 +02:00
Nicolas Frati e6a05af1ba [management] fix: device redirect uri wasn't registered (#6191)
* fix: device redirect uri wasn't registered

* fix lint
2026-05-20 12:11:15 +02:00
Viktor Liu 757037b927 Clean up legacy 32-bit and HKCU registry entries on Windows install (#6176) 2026-05-20 12:11:15 +02:00
Maycon Santos 30330c1786 Avoid context cancellation in cancelPeerRoutines (#6175)
When closing go routines and handling peer disconnect, we should avoid canceling the flow due to parent gRPC context cancellation.

This change triggers disconnection handling with a context that is not bound to the parent gRPC cancellation.
2026-05-20 12:11:15 +02:00
Viktor Liu 7ef658d0f4 [management] Avoid peer IP reallocation when account settings update preserves the network range (#6173) 2026-05-20 12:11:15 +02:00
Maycon Santos d250f92c43 feat(reverse-proxy): clusters API surfaces type, online status, and capability flags (#6148)
The cluster listing now answers three questions in one round-trip
instead of forcing the dashboard to cross-reference the domains API:
which clusters can this account see, are they currently up, and what
do they support. The ProxyCluster wire type drops the boolean
self_hosted in favour of a `type` enum (`account` / `shared`) plus
explicit `online`, `supports_custom_ports`, `require_subdomain`, and
`supports_crowdsec` fields.

Store query reworked so offline clusters still appear (no last_seen
WHERE), with online and connected_proxies both derived from the
existing 2-min active window via portable CASE expressions; the
1-hour heartbeat reaper still removes long-stale rows. Service
manager enriches each cluster with the capability flags via the
existing per-cluster lookups (CapabilityProvider now also exposes
ClusterSupportsCrowdSec).

GetActiveClusterAddresses* keep their tight 2-min filter so service
routing and domain enumeration aren't pulled into the wider window.

The hard cut removes self_hosted from the response — the dashboard is
the only consumer and is updated in the matching PR; no transitional
field is shipped.

Adds a cross-engine regression test asserting offline clusters
surface, connected_proxies counts only fresh proxies, and
account-scoped BYOP clusters never leak across accounts.
2026-05-20 10:08:34 +02:00
Maycon Santos 80966ab1b0 [management] Ensure SessionStartedAt has a default value (#6211)
* [management] Ensure SessionStartedAt has a default value

Avoid null values for the new column

* [management] Add PeerStatus with LastSeen in peer_test

* [management] Add migration for PeerStatusSessionStartedAt default value

* [management] Add PeerStatus with LastSeen in migration tests
2026-05-20 08:25:30 +02:00
Maycon Santos af24fd7796 [management] Add metrics for peer status updates and ephemeral cleanup (#6196)
* [management] Add metrics for peer status updates and ephemeral cleanup

The session-fenced MarkPeerConnected / MarkPeerDisconnected path and
the ephemeral peer cleanup loop both run silently today: when fencing
rejects a stale stream, when a cleanup tick deletes peers, or when a
batch delete fails, we have no operational signal beyond log lines.

Add OpenTelemetry counters and a histogram so the same SLO-style
dashboards that already exist for the network-map controller can cover
peer connect/disconnect and ephemeral cleanup too.

All new attributes are bounded enums: operation in {connect,disconnect}
and outcome in {applied,stale,error,peer_not_found}. No account, peer,
or user ID is ever written as a metric label — total cardinality is
fixed at compile time (8 counter series, 2 histogram series, 4 unlabeled
ephemeral series).

Metric methods are nil-receiver safe so test composition that doesn't
wire telemetry (the bulk of the existing tests) works unchanged. The
ephemeral manager exposes a SetMetrics setter rather than taking the
collector through its constructor, keeping the constructor signature
stable across all test call sites.

* [management] Add OpenTelemetry metrics for ephemeral peer cleanup

Introduce counters for tracking ephemeral peer cleanup, including peers pending deletion, cleanup runs, successful deletions, and failed batches. Metrics are nil-receiver safe to ensure compatibility with test setups without telemetry.
2026-05-18 22:55:19 +02:00
Maycon Santos 13d32d274f [management] Fence peer status updates with a session token (#6193)
* [management] Fence peer status updates with a session token

The connect/disconnect path used a best-effort LastSeen-after-streamStart
comparison to decide whether a status update should land. Under contention
— a re-sync arriving while the previous stream's disconnect was still in
flight, or two management replicas seeing the same peer at once — the
check was a read-then-decide-then-write window: any UPDATE in between
caused the wrong row to be written. The Go-side time.Now() that fed the
comparison also drifted under lock contention, since it was captured
seconds before the write actually committed.

Replace it with an integer-nanosecond fencing token stored alongside the
status. Every gRPC sync stream uses its open time (UnixNano) as its token.
Connects only land when the incoming token is strictly greater than the
stored one; disconnects only land when the incoming token equals the
stored one (i.e. we're the stream that owns the current session). Both
are single optimistic-locked UPDATEs — no read-then-write, no transaction
wrapper.

LastSeen is now written by the database itself (CURRENT_TIMESTAMP). The
caller never supplies it, so the value always reflects the real moment
of the UPDATE rather than the moment the caller queued the work — which
was already off by minutes under heavy lock contention.

Side effects (geo lookup, peer-login-expiration scheduling, network-map
fan-out) are explicitly documented as running after the fence UPDATE
commits, never inside it. Geo also skips the update when realIP equals
the stored ConnectionIP, dropping a redundant SavePeerLocation call on
same-IP reconnects.

Tests cover the three semantic cases (matched disconnect lands, stale
disconnect dropped, stale connect dropped) plus a 16-goroutine race test
that asserts the highest token always wins.

* [management] Add SessionStartedAt to peer status updates

Stored `SessionStartedAt` for fencing token propagation across goroutines and updated database queries/functions to handle the new field. Removed outdated geolocation handling logic and adjusted tests for concurrency safety.

* Rename `peer_status_required_approval` to `peer_status_requires_approval` in SQL store fields
2026-05-18 20:25:12 +02:00
Viktor Liu bc407527f4 Register VNC netstack service only when netstack is active 2026-05-18 14:50:10 +02:00
Viktor Liu 5543404188 Cap honored VNC client JPEG quality at 50 2026-05-18 14:50:10 +02:00
Viktor Liu c2fdf62f1f Detect dead VNC peers on both ends and report session stats 2026-05-18 14:50:10 +02:00
Viktor Liu b9f5264e36 Restore createRDPProxy wasm entry point for dashboard RDP 2026-05-18 14:50:10 +02:00
Nicolas Frati 705f87fc20 [management] fix: device redirect uri wasn't registered (#6191)
* fix: device redirect uri wasn't registered

* fix lint
2026-05-18 12:57:59 +02:00
Viktor Liu 97d0a6776f Release sticky modifiers and mouse buttons on client disconnect 2026-05-18 08:55:27 +02:00
Viktor Liu 7e7e056f3a Reset Tight zlib stream when deflater is recreated mid-session
Also scrub brand-name references from comments.
2026-05-18 07:54:21 +02:00
Viktor Liu 785f94d13f Guard buildExtClipProvideText against oversized input 2026-05-18 07:42:24 +02:00
Viktor Liu bfb6750b13 Reset encoding capability flags on each SetEncodings 2026-05-18 07:41:42 +02:00
Viktor Liu f5e1057127 Latin-1 round-trip for legacy CutText and soft-fail ext clipboard errors 2026-05-18 07:41:12 +02:00
Viktor Liu ee393d0e62 Clamp Tight length to 22 bits and fall back to Raw on overflow 2026-05-17 21:27:13 +02:00
Viktor Liu 0b8fc5da59 Split session.go: encoder pipeline and clipboard handling into separate files 2026-05-17 17:32:01 +02:00
Viktor Liu 2d0a54f31a Fix golangci-lint and Sonar: drop newZlibState, extract applyEncoding, inline stub comment 2026-05-17 17:16:10 +02:00
Viktor Liu 61ec8d67de Honor QualityLevel and CompressLevel pseudo-encodings 2026-05-17 16:52:57 +02:00
Viktor Liu 76add0b9b2 Fix ExtendedClipboard auto-request by advertising all actions in Caps 2026-05-17 16:47:53 +02:00
Viktor Liu a11341f57a Add ExtendedClipboard pseudo-encoding for UTF-8 bidirectional clipboard 2026-05-17 16:34:14 +02:00
Viktor Liu b135d462d6 Drop unused zlibState.scratch field 2026-05-17 16:33:48 +02:00
Viktor Liu da37a28951 Exclude VNC server from js, ios, and android builds 2026-05-17 15:48:15 +02:00