Skip to content

v0.1.11 — LustLess (screen accountability actually captures and scores)

Latest

Choose a tag to compare

@HenryGetz HenryGetz released this 14 Oct 20:25

Screen accountability actually captures and scores

v0.1.10 shipped with screen capture not working at all — on either backend, on any machine where the user logs in after the daemon starts (i.e. every normal boot). If you installed 0.1.10, upgrade.

v0.1.10 shipped the Wayland backend but screen capture did not work at all on
a real machine, on either backend. Three bugs, all found by running the daemon
on a real X11 desktop rather than a VM, plus one that made a working capture
score nothing:

  • Sessions discovered after startup were silently dropped. logind's User
    property is the struct (uo); the watcher read it as a bare u32, so the read
    always failed and watch_session returned early. Sessions present at daemon
    start come from ListSessions (which already carries the uid) and were fine —
    but every session created after that arrives via the SessionNew signal and
    needs the property. On a normal boot the daemon starts before anyone logs in,
    so every session was dropped and capture skipped every tick as "session
    inactive" forever. Fixed by reading the struct, with a regression test that
    reads the property off real logind and pins the old shape as failing.
  • An ssh session could shadow the desktop. Session selection ranked by
    liveness only, so on any machine the operator was also ssh'd into, the tty
    session won and the capture path then refused it as a text session. Selection
    now prefers a local graphical session (x11/wayland, not remote) first.
  • The gate and the backend could disagree. gate() allowed a tick if any
    session for the uid was active+unlocked, while the backend captured the
    session selection picked. Both now judge the same session.
  • A capture with no window list was never scored. When the X11 backend could
    not read _NET_CLIENT_LIST it wrote apps: [] and only logged a warning
    claiming a full-frame fallback that did not exist. The classifier scores the
    apps in the manifest, so every capture was analyzed as zero windows — the
    daemon looked perfectly healthy while doing nothing. It now synthesizes one
    full-frame entry per monitor, as the Wayland backend always has.
  • Capture failure is no longer silent: "no session tracked for a signed-in uid"
    is a warning naming the defect, not an indistinguishable "session inactive".

Verified on a real X11 session (Display=:0, Type=x11, alongside five ssh
sessions for the same uid): session env applied (uid 1000, type X11, display Some(":0")) → backend selected (X11) → a real 1280×800 capture with 3069
distinct colours, written as a complete spool transaction (PNG + manifest +
ready), consumed by the classifier, and scored:
{"analyzed_count":1,"top_score":0.06666}. The client_screenshot metric row
in the daemon's ledger corroborates the write.


How this was found and verified

Found by running the daemon on a real X11 desktop (this workstation:
Type=x11, Display=:0, active) which also has five ssh sessions for the same
uid — a configuration that exposed two of the three bugs at once.

Verified end to end on that machine, unprivileged, with a test config:

capture: session env applied (uid 1000, type X11, display Some(":0"))
capture: backend selected (X11)
im0.png  1280x800, 3069 distinct colours
manifest.json + ready            (complete transaction)
{"analyzed_count":1,"top_score":0.06666}   (classifier result)

plus the client_screenshot metric row in the daemon's ledger corroborating the
write. Workspace: 355 tests pass, clippy -D warnings clean.

Packages

lustless_0.1.11_amd64.deb, lustless-0.1.11-1.x86_64.rpm,
lustless-0.1.11-1-x86_64.pkg.tar.zst, lustless-0.1.11-r0.apk, plus
install.sh and lustless.rsa.pub.


Correction: Wayland capture does not work in 0.1.11

This release fixed screen capture for X11 sessions and says "captures and
scores", which is true there. On a Wayland session it does not: the daemon
makes the xdg-desktop-portal ScreenCast grant as root, and a stock D-Bus
session bus rejects uid 0 (portal request failed: session bus … I/O error: failed to read from socket), so nothing is captured. Reproduced on Debian 13.7
(GNOME/Wayland) with no host changes, and on Ubuntu 24.04 only after a
hand-written allow-root bus policy plus setcap cap_sys_ptrace+ep on the portal
binaries — which is why it looked fine during this release's verification.

v0.1.12 fixes this properly: the grant is made by a privilege-dropped helper
running as the session user, which hands the PipeWire fd to the daemon. No host
policy changes, no capabilities added to system binaries. Upgrade if you are on a
Wayland desktop (Zorin Core, Ubuntu, Fedora, Debian GNOME).