Verify: remote desktop candidate f9f2e2c (UNACCEPTED) - #1
Draft
daoleno wants to merge 69 commits into
Draft
Conversation
Preserve the partial X11 and shared native client implementation, harden native terminal-state cleanup, and document remaining input and runtime acceptance gaps. This is a local source checkpoint, not release acceptance.
Replace React command props with a bounded generation-scoped imperative queue, fence helper input on revocation, and add focused behavior and race coverage. Native builds and device acceptance remain open.
Bind the configured portal grant to PipeWire/GStreamer, preserve X11 and ordered input, and cover private-bus lifecycle and source selection. Real compositor and native-client acceptance remain pending.
Probe presence with list-panes so quiet show-options on a gone session is idempotent absence, while live unowned windows stay protected. Co-authored-by: Cursor <cursoragent@cursor.com>
Unknown process probes no longer skip generation checks and empty list-panes no longer counts as presence, so leftover owned windows stay until identity or pane generation matches. Co-authored-by: Cursor <cursoragent@cursor.com>
Users run zen without a second helper path or startup compile. Linux desktop-capable builds cgo-link native capture into the same executable, doctor reports remaining GTK/GStreamer/X11 dynamic deps, and a root broker refuses user-writable DEV binaries. Co-authored-by: Cursor <cursoragent@cursor.com>
…d ELF cgo does not hash external #included native C, so size/mtime and go-file touches were not rebuild proof. Hash native inputs into CFLAGS, rename onto the previous binary, and require fixture-linked identity plus child retirement. Co-authored-by: Cursor <cursoragent@cursor.com>
Offline mermaid 11.6.0 runs in a sandboxed WebView so Chat, Brain, and Work show actual diagrams instead of source, with copy, fullscreen, and strict untrusted-diagram limits. Co-authored-by: Cursor <cursoragent@cursor.com>
Android Fabric aborted when dataDetectorTypes was the string none. Serialize engine jobs, cap preview WebViews, and run desktopLanStorage tests in a child process so uploads mocks cannot steal saveServer. Co-authored-by: Cursor <cursoragent@cursor.com>
…ery codes Pairing still grants terminal plus desktop, but Connect now pins zen-desktop.invalid on the existing port, fails closed on scope/TLS/host-setup separately, and uses the current logged-in session without a per-connect GTK prompt. Owned-Xvfb proof and native unit gates: worklog/2026-09-10-remote-desktop-recovery-checkpoint.md. Co-authored-by: Cursor <cursoragent@cursor.com>
Registry-backed user-systemd attribution merges into the session-services snapshot; minimal service control hook; sheet distinguishes persistent rows without terminal actions.
Serialize registry RMW; exact-cgroup+UID attribution; omit claimed duplicates; bound systemctl; validate registry version and entries.
One 6s deadline covers all units with 4s per-unit cap and 1s pipe drain; ctx-aware seams; hung-multiunit and WS error-row regressions.
The pan responder is rebuilt on every offset render, so its per-instance gestureState.dx restarted after each move and pan only tracked a fragment of the drag. Accumulate pan state in a persistent ref through small model helpers and add a deterministic regression covering cumulative deltas, sequential gestures, cancel/re-anchor and the shared drag/pinch mapping.
The ARM64 Metro debug APK must upgrade an installed code27 without uninstall, so bump app.base.json to versionCode 28 and keep the release identity verifier on the tracked code (the same constant the release automation rewrites). Document the owned-VM native acceptance session, the pan fix, the supported controls, and the remaining operator/iOS/portrait limits truthfully.
Add the reviewed config-plugin integration: manifest placeholders opposite the standalone launcher, debug-only Metro connection activity/manifest in src/debug, focused plugin tests, and Bun-based developer workflow docs. The debug APK keeps the normal launcher; standalone and release builds are unaffected.
zen and zen-dev now share one authority path. The desktop broker's ownerUnit is optional: by default it admits the configured owner UID over the owner-only socket with the existing one-use signed challenge, generation/session binding, device scope and revocation; configuring ownerUnit still adds root-enforced system-unit cgroup exclusivity. The installer and activation no longer require a unit, so foreground, tmux and service deployments are equivalent and no zen-tmux service or daemon-unit migration is implied. Add owner-policy and real peer-credential tests plus a runtime parity BDD that builds zen/zen-dev and proves the same identity, fail-closed duplicate owner and restart persistence for both entry points.
The test no longer runs zen-dev in the shared checkout: it copies the module to a temporary snapshot where the DEV runner's watched sources and tmp/zen-dev output are test-owned, and asserts the repository's shared build output is unchanged by hash and mtime. Also fix the reviewed defects: one reliable process-completion channel with immediate cleanup registration, bounded HTTP client, uid-derived tmux socket path and non-starting tmux cleanup, exact lifecycle-lock cause plus original-owner health for the duplicate check, and matching desktop build options for the direct and DEV binaries.
zen boot install renders and enables one standard systemd user unit for the reviewed binary with the same state/arguments as foreground use, reports status (unit, binary, linger, health) and uninstalls only its own managed unit. Linger is required for boot before an interactive login and the exact operator command is reported when it cannot be enabled in-process. No second identity, tmux service or custom supervisor is introduced.
Describe zen boot install/status/uninstall as the one shared boot-persistence entry for the same runtime, including linger for pre-login and the uninstall scope.
The generated user unit ordered itself After=default.target while being WantedBy=default.target; a target implicitly orders itself after the units it wants, so the real manager dropped the implicit edge (ordering cycle). Render the unit without that line and verify the rendered file with systemd-analyze. Store the explicit runtime contract in the unit and a small owned metadata sidecar: absolute binary, state directory, address, working directory and non-secret PATH, with systemd-correct quoting for ExecStart ($$, %%, \\, \"), WorkingDirectory (%% only), Environment (quoted, %% and C escapes) and control-character rejection. Resolve relative paths and ~ at install time. Refuse root installation and paths this user cannot execute. Preflight the state lifecycle lock and listen address before writing: a live manual owner is refused, never killed. After enable --now or restart, verify the active unit's main process is the installed binary, the state lock is held, and /health on the installed address serves the installed state's daemon_id before claiming success. Idempotent reinstall leaves a healthy daemon running; command changes restart explicitly, Environment-only edits do not. Status reads the installed metadata, hashes the installed binary and attributes health to the installed identity. Uninstall stops first and retains the unit and configuration on any stop/disable failure. KillMode=process is intentional: the daemon reuses the user's ordinary tmux server, so unit stop/restart must not kill the cgroup tree (Workers survive, the daemon still terminates and restarts).
An active unit running the same binary plus a manual daemon using another state could satisfy the previous checks: the unit's MainPID matched the binary, the manual daemon held its own state lock, and /health served that state's identity. Bind ownership to the unit's actual process tree instead: require the lifecycle-lock holder to live inside the unit's systemd cgroup (/proc/<pid>/cgroup vs the unit ControlGroup). Install preflight refuses a state locked outside that cgroup even while any zen.service is active, and uninstall detects an own leftover daemon in the captured unit cgroup and retains the configuration instead of deleting it. Unknown facts no longer default to success: a missing MainPID, unreadable ControlGroup, or missing/erroring FragmentPath fails install verification, and status reports unknown ownership instead of claiming the unit owns the state. Any changed runtime context (including HOME/PATH) now restarts the unit explicitly rather than leaving live state stale. KillMode=process still keeps the shared tmux server out of the unit's kill scope, but the DEV watcher/daemon child-lifetime dependency is documented as open and owned by the runtime worker, not claimed as solved.
The watcher now sets PR_SET_PDEATHSIG on the daemon child, so an abrupt watcher death (crash, SIGKILL or a process-scoped supervisor stop) stops the child and releases the single-owner state lock instead of leaving an orphan. Normal rebuild, graceful stop and failed-build last-good behavior are unchanged, and the external tmux server is never part of this binding. Add a real re-exec test proving the child dies after the watcher is SIGKILLed.
A single active sample could observe a transient process inside the unit cgroup (a leftover DEV daemon about to lose the state lock) together with matching health. Require two consecutive verified observations before reporting success; a failed confirmation keeps the precise cause and stops only the unit this command started.
The previous check only matched an open /proc/<pid>/fd path, so a process inside the unit cgroup that merely opened the state lock file could be reported as the holder next to a manual owner outside. Require the kernel's actual flock record instead: /proc/<pid>/fdinfo for the matching descriptor must carry a FLOCK record. Processes that only opened the file have no record; an inheritor of the locked open file description still does, so a DEV child whose watcher died remains detectable. Ownership scans now return explicit errors instead of folding unreadable /proc access into "no owner": install preflight and verification fail, and uninstall retains the unit and metadata. Uninstall also requires readable installed metadata and refuses to guess when the remaining owner cannot be attributed to an outside process. Add real-process regression tests (opener without flock is never the holder), unreadable-scan and metadata-failure tests, and correct the two-observation comment to claim only two valid samples, not persistent identical ownership.
A permission error no longer proves a process is foreign: same-UID non-dumpable processes hide their /proc/<pid>/fd from this UID. Once a process is matched to the requested unit cgroup, or when a same-UID process cannot be inspected, the ownership scan now returns an explicit unknown error instead of reporting no owner; only genuinely foreign processes (different UID, or exited PIDs) are skipped so normal non-root enumeration still works. Uninstall now consults the lifecycle flock probe first: if the lock is still held after stop but its holder cannot be attributed, the unit and metadata are retained with an explicit error, and destructive removal only happens when the lock is released or the holder is proven outside the unit. The fdinfo parser now requires an acquired exclusive whole-file flock record (FLOCK + WRITE + 0 EOF); blocked waiters carry no record and shared, POSIX or range locks are ignored. Add parser cases, a strict-permission scan test, and held-but-unattributable uninstall regressions; verified real same-UID non-dumpable EACCES behavior out of band.
bootProcessIsSameUID returned false when Lstat failed or the platform stat type was unavailable, so bootSkipInspectionError read an unknown UID as proven foreign and skipped it. Replace it with an explicit owner kind (unknown/same/foreign): only a positively known foreign UID may skip a permission-denied process, exited PIDs still skip, and unknown stays an error. Add focused regressions for the unknown-owner classifier and for an in-cgroup permission denial that must not be skipped.
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.
UNACCEPTED verification candidate at f9f2e2c (includes desktop9705e27, GitDiff800abf3/d6c8d41, continuity7085999, TLS9fca158/fb72c3d). Generic broker retry in f9f2e2c under correction by Worker186. Purpose: trigger CI platform/build results at exactly identified SHA only; NOT full functional acceptance. No release/tag. Brain owns acceptance/main publication.