Skip to content

fix: gate Scheduled Maintenance commands on busy + pin explicit task principal#1160

Merged
laurentiu021 merged 1 commit into
mainfrom
fix/scheduled-maintenance-polish
Jun 29, 2026
Merged

fix: gate Scheduled Maintenance commands on busy + pin explicit task principal#1160
laurentiu021 merged 1 commit into
mainfrom
fix/scheduled-maintenance-polish

Conversation

@laurentiu021

Copy link
Copy Markdown
Owner

What

Two fixes for Scheduled Maintenance (#10), from the post-feature audit (Batch 5 of 6).

Fixes

  1. Commands not gated on busy (re-entrancy). Save / Remove / Refresh had no !IsBusy CanExecute gate, so a fast double-click (or Save-then-Remove) could start overlapping async operations and desync IsBusy. All three are now gated on !IsBusy, re-evaluated when IsBusy changes (observed via PropertyChanged, since IsBusy lives in ViewModelBase). Save/Remove refresh status via a new non-IsBusy-toggling LoadStatusAsync, so they no longer report not-busy mid-operation.
  2. Comment vs code drift on a privileged surface. The RegisterScript comment claimed a -User $env:USERNAME principal the Register-ScheduledTask call never passed (it relied on the cmdlet default). It now builds an explicit New-ScheduledTaskPrincipal (current user, Interactive logon, Limited run level) — making the "current user, no admin, only when logged on" posture deliberate and matching the docs.

Tests

MaintenanceSchedulerServiceTests (the service previously had zero): RegisterAsync passes only whitelisted args (the "no free-form text reaches the scheduler" security invariant), daily-flag mapping, null-exe → false + no run, empty results → false, PowerShell throws → false; GetStatusAsync no-rows / maps state+runs+result / throws → ExistsFalse.

Docs

CHANGELOG 1.51.5, version bump to 1.51.5.

Part of the post-feature audit remediation (Batch 5 of 6).

…principal

- Save / Remove / Refresh had no !IsBusy CanExecute gate, so a fast double-click
  (or Save-then-Remove) could start overlapping async operations and desync IsBusy.
  All three are now gated on !IsBusy and re-evaluated when IsBusy changes (observed
  via PropertyChanged, since IsBusy lives in ViewModelBase). Save/Remove now refresh
  status via a non-IsBusy-toggling LoadStatusAsync so they don't report not-busy
  mid-operation.
- The RegisterScript comment claimed a -User $env:USERNAME principal that the
  Register-ScheduledTask call never passed (it relied on the cmdlet default). Now it
  builds an explicit New-ScheduledTaskPrincipal (current user, Interactive logon,
  Limited run level) — making the 'current user, no admin, only when logged on'
  posture deliberate and matching the doc.

Tests: MaintenanceSchedulerService (previously 0) — RegisterAsync passes only
whitelisted args (security invariant), daily flag, null-exe -> false + no run,
empty results -> false, PS throws -> false; GetStatusAsync no-rows/maps/throws.
@laurentiu021 laurentiu021 merged commit b0b8d3d into main Jun 29, 2026
4 checks passed
@laurentiu021 laurentiu021 deleted the fix/scheduled-maintenance-polish branch June 29, 2026 12:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant