Role-Based Access Control
GEM controls who can do what through roles. A user holds one or more roles; permissions are additive — the user gets the union of every role's grants. (The guide Create a Role covers the day-to-day mechanics; this page explains the model.)
Rules over three surfaces
A role is a list of allow / deny rules over three permission surfaces:
| Surface | Controls | Example rule |
|---|---|---|
ui | Which UIs / UI features are visible | allow ui * |
route | Which client routes are reachable | deny route /admin* |
api | Which server functions can be called | allow api * |
deny wins over an overlapping allow, so you carve exceptions out of a broad grant (e.g. allow route * + deny route /admin* = everything but the admin section).
Socket events are the API surface
This is the key idea: every WebSocket handler is automatically a permissionable api action. When a socket.on('my_function', …) handler is added in gem_client.js, GEM enumerates it (via socket.eventNames()) and it becomes a named action you can allow/deny in a role — no separate permission registry to maintain. The role editor lists these enumerated events.
The same api actions gate the REST API: a user granted query can call GET /api/data/..., a user granted command can call POST /api/control/command, and so on.
Role-level switches
Beyond rules, two toggles change how a role behaves:
- Allow Remote — when off, the role only works on the local network and is blocked from external IPs. Use it to keep installer/admin roles on-site only.
- Elevated — when on, the role bypasses admin-only API protection (an effective wildcard
apigrant) and can send commands to devices marked Elevated and run macros marked Elevated. Grant it sparingly.
The Elevated flag is what gates privileged macros — see how it's set per-macro in Build a Macro.
System role
The system role (ID 0) cannot be deleted. On a fresh system, first boot seeds an admin role (full access) and a ui role (everything except /admin*) — see First Boot.