fix(agent): Desktop tab capture/WebRTC + cross-device self-update (VA-103) #105

Merged
David merged 2 commits from fix/VA-103-desktop-tab-session-fixes into main 2026-07-04 00:10:13 +02:00
Owner

Fixes surfaced while getting the Desktop tab working against a live deployment. Tracked in #VA-103. Two commits.

fix(agent): unblock Desktop tab capture and WebRTC data channel

  • Greeter Xauthority (active_session.rs): resolve XAUTHORITY from the running X server's -auth argument via /proc/<pid>/cmdline. An SDDM greeter (cookie under /run/sddm/xauth_*) previously resolved to None, so X11 capture could not authenticate to :0 and the tab was black. Also corrected docs that mislabeled a greeter as NoActiveSession (a root agent attaches to the greeter for unattended pre-login access).
  • WebRTC mDNS (vervain-agent-rtc): switch the answerer to MulticastDnsMode::QueryOnly so a browser's <uuid>.local host candidates are resolved rather than discarded. Disabled left zero remote candidates and ICE never paired on a LAN. Adds a regression test.
  • Switchover keyframe (tunnel.rs): call StreamState::invalidate() on both WebRTC transport transitions (WS to data channel, and failback) so a static screen still ships a full keyframe over the newly active transport instead of leaving the viewer black.
  • Log filter (main.rs): the default EnvFilter used vervain-agent=debug (hyphen) which never matched the crate target vervain_agent, silently suppressing the agent's own debug!. Corrected to vervain_agent.
  • Tooling (justfile): build-release copies the release binaries out of the dev-vervain-agent-target named volume to ./dist, which is otherwise invisible from the host.

fix(update): copy-fallback for cross-device binary swap

  • swap_in_place used a bare std::fs::rename, which fails EXDEV when the staged update and the target are on different filesystems (e.g. staged under /tmp, applied to /usr/local/bin). Adds an EXDEV fallback: copy into a temp in the target's own directory, then atomic-rename, preserving the atomic replace and the exec bit. Adds unit tests.

Verification

just pre-commit green (fmt, clippy --deny warnings, build, workspace tests, Windows check, TPM test). The capture and WebRTC fixes were confirmed on live hosts; the EXDEV fallback was exercised across a real filesystem boundary.

Not included (follow-up)

The greeter/X11 path here only covers the pre-login case. A logged-in user on these hosts is a KWin Wayland session, whose consent-free capture needs a root-level DRM/KMS scanout backend plus uinput injection. That is planned in #VA-104.

Fixes surfaced while getting the Desktop tab working against a live deployment. Tracked in #VA-103. Two commits. ## fix(agent): unblock Desktop tab capture and WebRTC data channel - **Greeter Xauthority** (`active_session.rs`): resolve `XAUTHORITY` from the running X server's `-auth` argument via `/proc/<pid>/cmdline`. An SDDM greeter (cookie under `/run/sddm/xauth_*`) previously resolved to `None`, so X11 capture could not authenticate to `:0` and the tab was black. Also corrected docs that mislabeled a greeter as `NoActiveSession` (a root agent attaches to the greeter for unattended pre-login access). - **WebRTC mDNS** (`vervain-agent-rtc`): switch the answerer to `MulticastDnsMode::QueryOnly` so a browser's `<uuid>.local` host candidates are resolved rather than discarded. `Disabled` left zero remote candidates and ICE never paired on a LAN. Adds a regression test. - **Switchover keyframe** (`tunnel.rs`): call `StreamState::invalidate()` on both WebRTC transport transitions (WS to data channel, and failback) so a static screen still ships a full keyframe over the newly active transport instead of leaving the viewer black. - **Log filter** (`main.rs`): the default `EnvFilter` used `vervain-agent=debug` (hyphen) which never matched the crate target `vervain_agent`, silently suppressing the agent's own `debug!`. Corrected to `vervain_agent`. - **Tooling** (`justfile`): `build-release` copies the release binaries out of the `dev-vervain-agent-target` named volume to `./dist`, which is otherwise invisible from the host. ## fix(update): copy-fallback for cross-device binary swap - `swap_in_place` used a bare `std::fs::rename`, which fails `EXDEV` when the staged update and the target are on different filesystems (e.g. staged under `/tmp`, applied to `/usr/local/bin`). Adds an EXDEV fallback: copy into a temp in the target's own directory, then atomic-rename, preserving the atomic replace and the exec bit. Adds unit tests. ## Verification `just pre-commit` green (fmt, clippy `--deny warnings`, build, workspace tests, Windows check, TPM test). The capture and WebRTC fixes were confirmed on live hosts; the EXDEV fallback was exercised across a real filesystem boundary. ## Not included (follow-up) The greeter/X11 path here only covers the pre-login case. A logged-in user on these hosts is a KWin Wayland session, whose consent-free capture needs a root-level DRM/KMS scanout backend plus `uinput` injection. That is planned in #VA-104.
Resolve XAUTHORITY for X11 display-manager / greeter sessions by reading the running X server's `-auth` file from /proc (active_session.rs); an SDDM greeter (cookie under /run/sddm/xauth_*) previously resolved to None, so X11 capture could not authenticate to :0 and the tab stayed black. Also correct the module docs that mislabeled a greeter as NoActiveSession: a root agent attaches to the greeter for unattended pre-login access.

Use MulticastDnsMode::QueryOnly in the RTC answerer so a browser's <uuid>.local mDNS host candidates are resolved instead of discarded; Disabled left zero remote candidates and ICE never formed a pair on a LAN. Adds a regression test.

Re-baseline a full keyframe on every WebRTC transport switch (tunnel.rs): call StreamState::invalidate() when the data channel opens and on failback to the WebSocket, so a static screen still ships a complete frame over the newly active transport instead of leaving the viewer black.

Fix the default log filter to target the crate as vervain_agent (underscore); the previous vervain-agent directive never matched the tracing target and silently suppressed the agent's own debug output.

build-release now copies the release binaries out of the dev-vervain-agent-target named volume to ./dist, which is otherwise invisible from the host.

#VA-103

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fix(update): copy-fallback for cross-device binary swap
All checks were successful
Check / fmt + clippy + tests (pull_request) Successful in 11m30s
Create release / Create release from merged PR (pull_request) Has been skipped
b6ec697ac3
swap_in_place used a bare std::fs::rename, which fails with EXDEV when the staged update and the target live on different filesystems (for example a binary staged under /tmp applied to /usr/local/bin). Add an EXDEV fallback that copies the staged bytes into a temp file in the target's own directory and then atomically renames it over the target, preserving the atomic replace and the executable mode bit. Adds unit tests for the cross-device path.

#VA-103

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
David merged commit 8bba40cff3 into main 2026-07-04 00:10:13 +02:00
David deleted branch fix/VA-103-desktop-tab-session-fixes 2026-07-04 00:10:13 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/vervain-agent!105
No description provided.