Skip to content

Groups

Design

A group lets an operator gather entities that the structural trees keep apart, so you can configure or grant access to “all AV displays” or “everything in this pilot” by attribute or by hand. A group is a named set of entities that cuts across the structural trees. The structural tree handles config by position and kind; groups handle config by attribute or by a hand-picked set. One “set of entities” primitive serves two jobs: a cascade overlay and an access scope, which an anonymous predicate never could.

A group:

  • is component / system / location / principal kind (matching the structural levels, plus principals for access);
  • has static membership (an explicit list) or dynamic membership (a filter, re-evaluated live as attributes change, so a device leaves the moment it stops matching);
  • has a weight (its specificity on the shared scale, see Placement; the only weights in the system);
  • carries variable / tag / rule bindings, with the same per-kind combinators the cascade uses;
  • is also the unit of access control: a visibility / permission scope (see identity and access).
TableKey columnsNotes
groupid, kind (component/system/location/principal), membership (static list or dynamic filter), weightcascade band and access scope (cascade, identity and access)

Structural layers auto-derive a specificity from position, weight-free, and the operator never tunes it: global lowest, then the templates, then the location / system / component trees by depth, then the entity’s own instance at the ceiling. A group’s weight is its specificity on that same scale, so a group sits wherever its weight lands relative to the structural bands: a high weight beats deployment (a must-apply override), a low weight loses to it (a default that deployment overrides). The instance ceiling beats any group; equal specificity breaks by creation order. A typed group applies at its own level: a component-group to components directly; a system-group reaches a component through the system layer of its cascade.

An entity belongs to a flat set of groups. Collect all their bindings and fold by specificity (weight): highest wins for variables and tag-values; rules accumulate, with weight resolving any add-vs-suppress conflict; equal weights break by creation order. There is no second precedence axis. So however many groups an entity is in, the group band collapses to one weighted list on the shared scale, fully predictable, and the resolve view names the winner.

Groups do not contain groups. A dynamic filter already expresses a union (type in (codec, display)) and multiple membership covers the rest, so nesting would earn only a narrow “DRY union of static sets” case, not worth its transitive-membership and cycle-guard cost. Whether to add it is an open question, gated on that case actually biting.

A _type (device/app, AV-System, room) is a classification attribute, resolved by a group filter (type == X), never a tree position. The tree is structural; attributes are groups. This is the bridge from the structural cascade to type-based policy: instead of a type layer in the tree, you author a dynamic group filtered on type and place it by weight.

In operator terms, the same user stories the cascade serves, the group-specific ones:

  • A fleet-wide fix that auto-clears. Cisco firmware 11.2 has a memory leak, so I make a dynamic group model == "Room Kit Pro" && firmware < "11.5" at high weight, slow its poll and suppress the false high-memory alarm; the 23 affected codecs across 6 floors get it at once, and each drops out the moment it upgrades. (dynamic group above deployment, live membership, rule suppression)
  • A broad policy as a floor, not a ceiling. I put baseline stricter thresholds on a low-weight “PCI-scope” group, so a lab on Floor 3 that needs its own values still wins; the policy is a default the specific deployment overrides. (low-weight group below deployment, the shared specificity scale)
  • A hand-picked set no filter can name. I drop the 5 executive briefing rooms into a static “Exec Rooms” group for premium escalation, and grant the exec-support team visibility to that same group. (static membership; groups double as the access scope)