feat(scheduler): consistent action targeting in Scheduled Operations (#1431)

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.
This commit is contained in:
Anso
2026-06-24 21:02:15 -04:00
committed by GitHub
parent 0af7ad1df2
commit bc8c051962
14 changed files with 542 additions and 106 deletions
@@ -38,6 +38,11 @@ describe('scheduledActions registry', () => {
}
});
it('marks scan and prune as local-node actions', () => {
expect(getActionById('scan')).toMatchObject({ requiresNode: true, nodeScope: 'local' });
expect(getActionById('prune')).toMatchObject({ requiresNode: true, nodeScope: 'local' });
});
it('getActionById resolves a known id and returns undefined otherwise', () => {
expect(getActionById('restart')?.label).toBe('Restart Stack');
expect(getActionById('nope')).toBeUndefined();