feat(cua-driver-rs)(windows): register autostart task at RunLevel=Highest (unblocks UWP automation, #1602) - #1630
Conversation
…hest (#1602) The autostart Scheduled Task was registered with `RunLevel=Limited`, so on typical Windows installs (regular admin user with a UAC-split token) the daemon started at Medium IL. That's fine for Win32 + Chromium targets, but cross-AppContainer UIA RPCs truncate at Medium IL — Calculator returns ~1 element instead of the full ~30-40 element tree (issue #1601 / #1602). This switches the task registration to `RunLevel=Highest` so the daemon runs at the user's elevated token, which crosses the AppContainer boundary cleanly. Registering a `Highest`-level task itself requires the caller to be at High IL, so the install path now self-elevates only for the autostart-registration step. ## Why this and not UIAccess + EV cert We isolated the variable in a 4-cell matrix on a Windows 11 VM: 1. DevMode OFF + High IL → 41 Calculator elements ✅ 2. DevMode ON + High IL → 41 Calculator elements ✅ 3. DevMode ON + Medium IL (cuatest standard user, Win32 token IL inspected directly, IL=0x2000 confirmed) → daemon ran but UWP activation blocked by Session 0 (orthogonal limitation; a real user-session Medium IL daemon historically returned ~1 element per #1602). DevMode is not the variable. Token integrity is. RunLevel=Highest gets us to the High IL daemon without needing UIAccess (which would require an EV-cert signed `cua-driver-uia.exe`). One UAC prompt at install time in exchange for full UWP automation post-install. EV cert remains the long-term answer for users who can't or won't grant admin even once, but RunLevel=Highest unblocks the common case today. ## Changes ### `crates/cua-driver/src/autostart.rs` - `New-ScheduledTaskPrincipal ... -RunLevel Limited` → `-RunLevel Highest` - Detect access-denied / 0x80070005 / "requires elevation" in the PowerShell stderr and emit an actionable error pointing at #1602 instead of the raw stack trace. - Doc comment expanded to explain the WHY of `-RunLevel Highest` (the AppContainer / UIPI boundary, links to #1602 / #1601). ### `libs/cua-driver/scripts/install.ps1` - New `Test-IsElevated` helper. - `Register-CuaDriverAutostart` now self-elevates via `Start-Process -Verb RunAs` when called from a non-elevated install, with a clear pre-prompt explaining the UAC ceremony. The rest of the install (file extraction, junction creation, User PATH update) still runs unelevated as today — only the autostart step elevates. - Post-install hint block (both `-AutoStart` and non-`-AutoStart` branches) updated to mention RunLevel=Highest and the UWP/AppContainer trade-off ("without auto-start, Win32 + Chromium work fine; UWP needs the elevated autostart task"). ## Compat - Existing users with a `cua-driver-serve` task at `RunLevel=Limited` will get it re-registered as `Highest` next time they run `cua-driver autostart enable` or the installer with `-AutoStart` (the registration script unconditionally `Unregister-ScheduledTask` before `Register-ScheduledTask`). - Users who never call `autostart enable` see no behavior change. - macOS + Linux paths untouched. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughThis PR implements elevated Windows scheduled task registration with ChangesElevated Autostart Task Registration
Sequence DiagramssequenceDiagram
participant User as User
participant Installer as install.ps1
participant ElevCheck as Test-IsElevated
participant Register as Register-CuaDriverAutostart
participant ElevPS as Elevated PowerShell
participant CuaDriver as cua-driver autostart enable
User->>Installer: Run install.ps1 -AutoStart
Installer->>ElevCheck: Check elevation status
alt Already elevated
ElevCheck-->>Register: IsElevated=true
Register->>CuaDriver: Run directly
CuaDriver-->>Register: Task registered with RunLevel=Highest
else Not elevated
ElevCheck-->>Register: IsElevated=false
Register->>ElevPS: Spawn with -Verb RunAs
ElevPS->>CuaDriver: Run in elevated context
CuaDriver-->>ElevPS: Task registered with RunLevel=Highest
ElevPS-->>Register: Propagate exit code
end
Register-->>Installer: Registration complete
Installer-->>User: Display confirmation
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…Mode Latest (#1631) irm | iex of install.ps1 on a fresh user account (Windows 11 24H2 PS 5.1) fails immediately after the install-dir log lines with: iex : The property 'OSArchitecture' cannot be found on this object. Verify that the property exists. The source is Get-TargetTriple's call to [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture. Under Set-StrictMode -Version Latest (set at install.ps1:78), PowerShell 5.1 reports the static property access as a missing-property error in certain session contexts — specifically a freshly-created admin user with no profile, no prior loaded modules. The same script works fine under the RID-500 built-in Administrator account on the same VM, which is why this went undetected through the v0.2.9 install verification. ## Fix Use $env:PROCESSOR_ARCHITECTURE as the primary source for the architecture lookup. It's always set on Windows, never trips StrictMode introspection, and has no .NET version dependency. RuntimeInformation.OSArchitecture is kept as a try-catch fallback so we still handle exotic configurations where PROCESSOR_ARCHITECTURE is unset. Mapping: AMD64 -> x86_64-pc-windows-msvc (PROCESSOR_ARCHITECTURE on x64) ARM64 -> aarch64-pc-windows-msvc (PROCESSOR_ARCHITECTURE on arm64) X64 -> x86_64-pc-windows-msvc (fallback: RuntimeInformation.Architecture.ToString()) Arm64 -> aarch64-pc-windows-msvc (fallback) ## Verification - cargo check on the unrelated install path: clean (no code-side change) - install.ps1 parses cleanly on PS 5.1.26100.8457 - Smoke test: invoke Get-TargetTriple under `Set-StrictMode -Version Latest` -> returns 'x86_64-pc-windows-msvc' (no PropertyNotFoundStrict error) ## Repro / how it surfaced Reported by the cuademo test account (BUILTIN\Administrators, NOT RID 500, UAC-split-token) on the Windows VM during the post-#1630 fresh-install dogfood walkthrough. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
…s for RunLevel=Highest task (#1632) #1630 switched the autostart Scheduled Task to RunLevel=Highest, with install.ps1's Register-CuaDriverAutostart self-elevating via Start-Process -Verb RunAs when called from a non-elevated install. But the standalone `cua-driver autostart enable` CLI subcommand did NOT self-elevate — it just called Register-ScheduledTask directly from whatever IL the user's shell was at. From a typical Medium-IL PowerShell, that fails with 0x80070005 (Access is denied) and the user is told to "re-run from an elevated PowerShell", which is friction for what should be a one-command setup. This patch wires the same self-elevation into the Rust CLI: 1. First attempt: register directly. Works for callers already at High IL (install.ps1's elevated child shell, or someone running `cua-driver autostart enable` from an Administrator shell). 2. On access-denied (HRESULT 0x80070005 / "Access is denied" / "requires elevation"), the CLI itself triggers a UAC prompt via PowerShell's Start-Process -Verb RunAs, then runs `cua-driver autostart enable` inside the elevated child. The elevated child hits the first-attempt branch and registers the task cleanly. 3. If the UAC prompt is dismissed, surface a clear actionable error message ("re-run and accept the prompt"). Net UX: `cua-driver autostart enable` from any non-elevated PowerShell triggers a UAC prompt once, registers the Highest task, exits. No manual elevation required. Fixes a regression surfaced during the cuademo fresh-install dogfood. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
…on is at High IL (#1602) (#1634) Since PR #1630 the autostart task runs the main daemon at RunLevel=Highest, which puts cua-driver.exe at High IL with full UWP / AppContainer UIA access. The sibling cua-driver-uia.exe worker is therefore redundant for the common case — and worse, attempting to ShellExecute the (currently unsigned) uiAccess'd worker from a High-IL parent pops a Windows AIS error dialog ("A referral was returned from the server" = AIS refusing to elevate an unsigned uiAccess binary). The dialog blocks daemon startup and visibly confuses users. Repro: run `cua-driver autostart enable` from a standard admin user (non-RID-500), accept the UAC prompt, then `cua-driver autostart kick`. The main daemon starts at High IL, tries to spawn the uia worker via ShellExecute, AIS refuses, error dialog pops up over the desktop. ## Fix maybe_spawn_uia_worker() now gates on three conditions: 1. Main daemon is NOT at High IL (checked via PowerShell WindowsPrincipal.IsInRole(Administrator)). At High IL the worker is redundant. 2. CUA_DRIVER_RS_SPAWN_UIA_WORKER=1 env var is set. Default-off until the worker is actually EV-signed (#1602) and the spawn doesn't trip AIS. 3. The worker binary actually exists on disk next to cua-driver.exe. All three must be true for the spawn to fire. Common case (RunLevel=Highest install via the canonical install.ps1 + cua-driver autostart enable flow): condition (1) trips first — no spawn, no dialog, no UWP regression because the High-IL main daemon already does what the worker would have done. ## Future EV-cert path When we ship a signed cua-driver-uia.exe (the long-term #1602 answer), users running the daemon at Medium IL can opt into the worker by setting CUA_DRIVER_RS_SPAWN_UIA_WORKER=1. Default-off gives a no-surprises upgrade path: existing users on Medium IL stay on whatever path they're already on, and the explicit env var keeps us honest about which path is being exercised during the signed-binary rollout. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Summary
Switches the Windows autostart Scheduled Task from
RunLevel=LimitedtoRunLevel=Highestso the daemon runs at the user's elevated token. This is what unblocks cross-AppContainer UIA RPCs (Calculator, modern Settings, Photos, Microsoft Store apps) without requiring UIAccess + EV cert. The installer's-AutoStartpath now self-elevates only for the registration step; the rest of the install stays admin-free.Why now
We isolated the variable on a Windows 11 VM in a 4-cell matrix (DevMode × token IL):
GetTokenInformation)check_permissions.elevated=false; UWP activation blocked by Session 0 (an orthogonal Windows boundary, not the IL boundary)DevMode toggle does nothing to UIA tree depth. Token integrity is the variable. A real user-session Medium-IL daemon historically returned ~1 Calculator element per #1602 / #1601.
RunLevel=Highestis the cheapest path to the High-IL daemon — one UAC prompt at install time, then silent autostart at every logon. EV cert + UIAccess (full #1602 solution) is still cleaner UX long-term but costs $300/yr + a signing pipeline; this PR removes the Calculator gap today.Changes
crates/cua-driver/src/autostart.rs-RunLevel Limited→-RunLevel Highestin the inline PowerShellRegister-ScheduledTaskblock.libs/cua-driver/scripts/install.ps1Test-IsElevatedhelper usingWindowsPrincipal::IsInRole(Administrator).Register-CuaDriverAutostartnow self-elevates viaStart-Process -Verb RunAswhen invoked from a non-elevated install, with a clear pre-prompt. The rest of the install (file extraction, junction creation, User PATH update) still runs unelevated.-AutoStartand non--AutoStartbranches — explains RunLevel=Highest, mentions the "Win32 + Chromium fine without; UWP needs autostart" trade-off.Compat
cua-driver-servetask atRunLevel=Limitedget it re-registered asHighestnext time they runcua-driver autostart enable(the registration script unconditionallyUnregister-ScheduledTaskfirst).autostart enablesee zero behavior change.Test plan
cargo check -p cua-driverclean on the VM (14.56s)install.ps1parses cleanly on PowerShell 5.1 (3,167 tokens, 0 errors)irm install.ps1 | iexthencua-driver autostart enabletriggers UAC prompt, registers task atRunLevel=Highest, Calculator drives end-to-end after logoff/logonRelated
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes