Add an All PCs policy scope that excludes servers

The policy builder only offered "Matches everything" (the `true` scope node),
which also targets servers. Authoring an estate-wide policy almost always means
"every PC an operator sits at", and a reboot or script push against a server is
a materially different event.

Adds an `allpcs` scope node that matches every endpoint except those whose
computer type is server-designated. Server designation reads the computer type's
ICON slug, which is nominally a UI hint and is now load-bearing; it was chosen
over matching the type NAME (a site can rename "Server") and over a new isserver
column (needs a migration). It is isolated behind SERVER_ICON so promoting it to
a real flag later is a one-place change.

The `true` node is retained and still matches servers, so existing policies keep
their exact meaning rather than silently re-scoping. It stays visible in the
dropdown only when editing a policy that already uses it; new policies default
to `allpcs`.

Covered by tests/test_plugins/test_computers_policy_allpcs.py, verified against
a planted canary so the server-exclusion assertions are known to bite.
This commit is contained in:
benjamin.baker
2026-09-07 13:03:07 -04:00
parent 3626d7dd2e
commit 31dc9d49e1
5 changed files with 129 additions and 12 deletions

View File

@@ -140,7 +140,7 @@ const error = ref('')
const form = ref(emptyForm())
function emptyForm() {
return { name: '', description: '', scopejson: { type: 'true' }, actions: [] }
return { name: '', description: '', scopejson: { type: 'allpcs' }, actions: [] }
}
onMounted(() => loadData())
@@ -221,7 +221,7 @@ function openModal(item = null) {
form.value = {
name: item.name || '',
description: item.description || '',
scopejson: item.scopejson ? JSON.parse(JSON.stringify(item.scopejson)) : { type: 'true' },
scopejson: item.scopejson ? JSON.parse(JSON.stringify(item.scopejson)) : { type: 'allpcs' },
actions: (item.actions || []).map(a => ({
action: a.action, mode: a.mode || 'gate',
desiredstate: a.desiredstate, params: a.params, intervalminutes: a.intervalminutes