Give every scheduled action an explicit, predictable target model
(Action then Node then Stack then Options then Schedule):
- System Prune now exposes a Node picker and requires a node, so it can
no longer run silently on the default node.
- Vulnerability Scan and System Prune list local nodes only; both run on
the hub-local Docker daemon and reject remote nodes on the backend.
- Restart Stack service discovery loads services from the selected node
via fetchForNode instead of the active or local node.
- Fleet Snapshot shows a read-only "Scope: Entire fleet" summary.
Backend gains a shared local-node guard and prune node validation on
create and update, plus an executor-level remote-node guard, so the
frontend and backend validation now agree for every action.
Scheduled-operation action metadata was duplicated across the backend route
validator, the DatabaseService action union, the desktop action picker, the
Timeline lanes, and the mobile labels/tones. Adding or renaming one action meant
editing all of them.
Introduce one registry per package as the single source within that package:
- backend/src/services/scheduledActionRegistry.ts owns the action list and
target-type validation; routes/scheduledTasks.ts and DatabaseService import
from it (BackendScheduledAction type, VALID_ACTIONS, validateActionTarget).
- frontend/src/lib/scheduledActions.ts owns the UI metadata (labels, short
labels, categories, tones, target/node/stack/service flags, helper text) and
drives the create-flow picker, the All Tasks label, the Timeline lanes, and
the mobile schedule view.
Timeline lanes now group by semantic category (Lifecycle, Updates, Security,
Maintenance, Backups) sourced from the registry. The update-fleet UI alias is
made explicit via a backendAction field. Backend validation stays authoritative;
parity tests on each side keep the action sets in lockstep.