Skip to main content

Control Who Can Do What

Role-based access control (RBAC) in Coreflux combines user groups, LoT Rules, permission flags, and optional Visu panel sharing so you can lock down topics, management operations, and dashboards without external ACL servers.
Like badge groups in a factory. Operators get a badge that opens production doors; supervisors get a badge that also opens the emergency-stop cabinet. Groups name the badges; Rules decide which doors each badge opens.

When to Use This Guide

Adding custom topic or management ACL rules (-addRule) requires a Growth or Enterprise license. Shipped default rules always apply. Group membership commands and permission flags are available on all tiers.

Write rules with correct layout and conditions in Rules Syntax, then return here for groups, precedence, and operator patterns.

User Groups

Each broker user can belong to one or more named groups. Group names are case-insensitive at evaluation time ("Operators" and "operators" match the same group). Prefer kebab-case or lowercase identifiers without spaces (zone1-staff, not Zone 1 Staff). Groups are created by naming them — assign a user to a group and reference that name in rules or Visu clauses.

Manage Groups via MQTT

Publish to $SYS/Coreflux/Command from a session authorized for user management (AllowedUserManagement, AllowedSystemConfiguration, or root). The requesting identity is the authenticated MQTT session — do not pass a requester in the payload.
Responses arrive on $SYS/Coreflux/Command/Output. See Broker Commands for the full command set.

Rule Precedence

Lower priority number wins. This is the same convention as BACnet write priority and ISA-18.2 alarm priority: the lower the number, the stronger the statement. The very strongest numbers are reserved for the broker’s own rules, so 100 is the strongest priority you can write. For a given operation (and topic, for topic operations), the broker considers only the rules with the lowest priority number among those that match. Within that winning band:
  • If any matching rule evaluates to DENY, the operation is denied (deny-wins)
  • Otherwise, if a rule allows, the operation is allowed
  • If no rule matches at all, the operation is denied (default-deny)
Weaker (higher-numbered) rules are consulted only where no stronger rule matches the topic. Because the catch-alls sit at the weakest priority 1 000 000, any rule you add in the user band overrides them for its topic (or, for Connect, for the whole connection). You do not need to remove or reprioritise a built-in to deny (or further allow) a topic.
Start broad rules high — you can only carve out downwards. An exception needs a lower number than the rule it overrides, and 100 is the floor of the user band. Give a namespace-wide rule a large number (1000, or higher if you expect several layers) and keep 100 for the most specific case. A broad rule placed at 100 leaves no room to carve out later without renumbering what is already deployed.
Prefer distinct priorities, or combine conditions with OR in one rule. Same-priority ties resolve deny-wins.

Layout requirements

The LoT lexer is indentation-sensitive (one level = 4 spaces):
  • Keep the full header on one line: DEFINE RULE Name WITH PRIORITY n FOR …
  • Put each IF / ELSE / ALLOW / DENY on its own line (a single-line THEN ALLOW ELSE DENY body is rejected)
  • Omitting ELSE is valid: THEN DENY allows everyone else, and THEN ALLOW denies everyone else. An explicit ELSE is still the clearer form.
  • Rule names are bare identifiers — no quotes around the rule name

Quick Start

Only members of operators may publish commands under machines/+/cmd:
Deploy with -addRule <definition> on $SYS/Coreflux/Command, or run the cell in a LoT Notebook. Remove with -removeRule <RuleName>.

Access-Control Cookbook

Deny a whole subtree

Beats the weakest-band publish catch-all (priority 1 000 000) for factory/raw/#; other topics still fall through to the default allow.

Restrict a topic to named users

Gate by permission flag

Switch a namespace toward default-deny

Blanket-deny at a coarse priority, then allow only what you intend at a stronger (lower) one:
Alternatively, remove the removable publish seed (-removeRule AllowPublishTopic) so unmatched publishes fall through to default-deny. Locked system rules and the root backstop still protect recovery. Restore the three shipped seeds later with -restoreRules. Do not expect -removeRule AllowConnect alone to lock CONNECT — see Connection admission.

Precedence walk-through

The table reads top-down in precedence order — the first band that matches decides:
  • Publish to office/x → only the catch-all matches → ALLOW
  • Publish to plant/motor → strongest match is DenyArea (1 000) → DENY
  • Publish to plant/sensors/t1 → strongest match is AllowSensors (100) → ALLOW

Permission Flags vs Groups

Set a flag via MQTT:
In Coreflux HUB User Management, Full Access maps to AllowedSystemConfiguration; User Management and Log Management map to the matching flags. Manage groups with the MQTT commands above (see also User Management). USER IN GROUP, USER IS / USER EQUALS, and USER HAS also work inside LoT Action bodies (for topic-triggered actions). Scheduled actions (ON EVERY / ON START) have no triggering user — group checks return false there.

Default Rules and System Access

Locked system rules

Management gates (CommandCall, user/rule/route/action management, and so on) and $SYS access rules are locked built-ins in the reserved band (0–99) — the strongest priorities on the number line. They cannot be removed, cannot be overridden by a same-named rule, and outrank every user rule (which are floored at 100), so no rule you write can revoke admin access and lock the broker. The band is split the same way user rules are — more specific means a lower number: base locked rules sit at 10, and more-specific $SYS carve-outs at 1. The flip side of that protection: a custom rule on a management scope, or on $SYS/# subscribe, never decides either — the locked rule always forms the winning band. Adjust those with permission flags instead. See Operation Scopes.

Seed catch-alls

Three permissive defaults sit at priority 1 000 000 — the weakest possible band — so MQTT clients keep working out of the box while losing to every rule an operator writes:
These are the only defaults an operator may remove or replace via MQTT. To change a seed catch-all’s body, -removeRule it and then -addRule your replacement — rule names must be unique. Project merges skip every built-in name — including these seeds — so redefine them with MQTT commands, not project files. To put the three seeds back (including resetting an override of those names to the shipped ALLOW body), run -restoreRules. That command requires root or AllowedSystemConfiguration and does not require an RBAC license. Locked built-ins and your other custom rules are left alone. Loading or unloading a project keeps locked built-ins and operator-authored rules. Only rules the broker attributes to the outgoing project are removed.

Connection admission

A rule written FOR Connect decides whether the broker accepts an MQTT CONNECT after authentication succeeds. Connect rules take no TO TOPIC clause. Any user-band Connect rule (100999 999) outranks AllowConnect.
A rule set with no Connect rule at all leaves CONNECT ungated — that is how upgrades from brokers that had no Connect operation keep accepting clients. -removeRule AllowConnect without adding a replacement therefore does not lock the door. To control who may connect, add an explicit FOR Connect policy. root remains admitted by the anti-lockout backstop.

Rejected priorities

-addRule and project rule merges reject both ends of the number line, and report the reason per rule:

Root anti-lockout

Independently of all rules, root can always connect, run commands, manage rules, and reach $SYS/Coreflux/Command and $SYS/Coreflux/Command/Output.

Upgrade note

Review any custom rule that used the 1–99 range. That band is now reserved for locked system rules, so such rules are clamped to 100 when the broker loads them (each clamp is logged with its old and new priority). Clamping keeps them in force and keeps them from outranking the locked safety rules, but several rules that used to be distinct can land on 100 together — where ties resolve deny-wins. Re-space them deliberately across the user band, putting the more specific rule at the lower number. Locked built-ins are rewritten to their canonical definitions and priorities on every start, and a seed catch-all you kept has its body preserved but its priority normalized to 1 000 000. A seed you deliberately removed stays removed. Fresh brokers also ship AllowConnect at 1 000 000; see Connection admission.

Visu Panel RBAC

LoTV panels can restrict who sees content and who can interact with controls.

Visibility

Published shared panels generate Layer 1 subscribe rules so only listed groups (or users via WITH SHARE TO USER) receive the panel. Others do not see it in $Visu/Catalog.

Interaction

Stack multiple FOR GROUP lines or multiple FOR USER lines. Do not mix FOR GROUP and FOR USER on the same component — only the last scope is enforced. Put named users into a group when both are needed. Denial modes: WITH INTERACT_DENY SILENT (default) or WITH INTERACT_DENY NOTIFY (publishes to $Visu/Session/<id>/Denied).

Two-layer enforcement


Best Practices

  • Start from the shipped defaults; every rule you add already overrides the catch-alls for its topic
  • Give namespace-wide rules a coarse number (1000 or higher) and reserve 100 for the most specific carve-outs
  • Prefer groups over hard-coded usernames for topic and panel access
  • Keep rule headers on one line; use consistent 4-space indentation
  • Keep custom priorities inside the user band (1001 000 000)
  • Document who owns each group name in your operations runbook
Never attempt to override locked system rules or rely on removing root protections. The reserved priority band and root backstop exist so the broker remains recoverable.

Next Steps

Rules Syntax

Conditions, operation scopes, and complete rule patterns.

Broker Commands

Group, user, and rule management command reference.
Last modified on August 28, 2026