Tags and Groups
Purpose
Tags and groups provide flexible classification and collection mechanisms.
They are intentionally separate concepts.
Tags
Tags are labels assigned to entities.
Examples:
Critical
Commissioned
Blocked
Trend
Production
Remote Access ReadyTags are good for:
- filtering,
- visual labels,
- simple classification,
- workflow state where a full workflow engine is unnecessary,
- reporting facets.
Tag Groups
Tag groups organize tags into sets.
Examples:
Criticality
├── Low
├── Medium
└── HighCommissioning Status
├── Not Started
├── In Progress
├── Blocked
└── CompleteVendor
├── Trend
├── Siemens
├── Schneider
└── TridiumSingle-Select vs Multi-Select
Tag groups should support a selection mode.
single
multiSingle-select example:
Criticality = HighMulti-select example:
Asset Capabilities = BACnet, Modbus, Remote Access ReadyFor single-select groups, the service layer must ensure only one active tag assignment exists per entity for that group.
Tags Are Entities
A tag should own an entity.
This enables:
- audit,
- permissions,
- hierarchy placement if needed,
- group membership if needed,
- relationships if needed.
Tag-specific fields live in the tags table.
Entity Tags
Use entity_tags for tag assignment.
Recommended fields:
id
entity_id
tag_entity_id
created_at
deleted_atUnique active assignment:
CREATE UNIQUE INDEX uq_entity_tags_active
ON entity_tags(entity_id, tag_entity_id)
WHERE deleted_at IS NULL;Entity Groups
An entity group is a named collection of entities.
Groups are useful when the user wants to manage a set of objects that are not necessarily in the same hierarchy branch.
Examples:
Commissioning Batch - July 2026
Critical BMS Controllers
Sites Requiring VPN Upgrade
Assets For Firmware UpdateA group is itself an entity, with group-specific metadata in entity_groups.
Group Membership
Use entity_group_members to store membership.
Recommended fields:
id
group_entity_id
member_entity_id
created_at
deleted_atUnique active membership:
CREATE UNIQUE INDEX uq_entity_group_members_active
ON entity_group_members(group_entity_id, member_entity_id)
WHERE deleted_at IS NULL;Groups Are Not Hierarchy
Do not model group membership with parent_entity_id.
Bad:
Commissioning Batch
└── Asset Aif Asset A is physically located under:
Customer -> Site -> BuildingAn entity should have one structural parent. Groups are many-to-many collections.
Tag Groups vs Entity Groups
| Concept | Purpose | Example |
|---|---|---|
| Tag Group | Organizes labels | Criticality: Low, Medium, High |
| Tag | Label assigned to entity | High |
| Entity Group | Collection of entities | July Commissioning Batch |
| Group Member | Entity in a collection | Asset A in July Commissioning Batch |
User Experience
Tags should feel lightweight.
Groups should feel like user-manageable collections.
Examples:
- user filters assets by tags,
- user creates a group for a commissioning batch,
- user bulk assigns assets to a group,
- user opens group detail page to see members,
- user applies batch actions to group members.
Backend Rules
Tag assignment must enforce:
- root entity scope,
- tag visibility,
- selection mode rules,
- soft-delete rules,
- audit where needed.
Group membership must enforce:
- root entity scope for group,
- root entity scope for member,
- whether mixed types are allowed,
- whether member type is allowed,
- duplicate prevention.
Example: Commissioning Batch
Entity type:
groupGroup metadata:
{
"name": "July 2026 Commissioning Batch",
"allowsMixedTypes": false
}Members:
Asset A
Asset B
Asset CActions:
- assign commissioning status,
- export list,
- bulk update property,
- create report,
- review blockers.