LiveView Authentication
Runtime authentication is the second identity realm: the operators who use LiveView screens. It is fully independent of Platform authentication — different user store, different token secret, different audience.
Why two realms
An operator on the plant floor and an engineer in the Platform need different things:
| Platform user | Runtime user | |
|---|---|---|
| Population | Tens | Hundreds, changing with shifts and contractors |
| Identity source | The QUBIQ configuration database | Your own directory or database |
| Authorises | Design and administration | Viewing screens, writing permitted tags |
| Token | JWT_SECRET | LIVE_JWT_SECRET, audience liveview |
Putting operators in the platform user table would mean every shift change touching the engineering system. Keeping them separate means a runtime token presented to a design-time endpoint fails on audience — the separation is structural, not a policy.
User Databases
A User Database is an external identity source holding runtime users. A project is bound to one.
| Project binding | LiveView behaviour |
|---|---|
| Unbound (default) | Public — anyone who can reach the URL sees the screens |
| Bound | /{project}/login required; runtime roles govern access and writes |
The binding is authoritative and written only through its dedicated endpoint — never through the project manifest — so an author cannot grant access by editing a resource.
Managing user databases requires Manage LiveView sign-in, a super-admin permission by default.
Runtime users
| Field | Meaning |
|---|---|
| Username, email | Identity |
| First / last name | Display |
| Approved | An administrator has admitted the account |
| Active | The account is not suspended |
| Phone, WhatsApp opt-in | Contact channels for notification |
| Roles | Runtime role names |
| Write level | Derived — the highest level across the user's roles |
| Last login | Diagnostics |
Approved and Active are orthogonal
Login requires both. The derived states are:
| Approved | Active | Status |
|---|---|---|
| false | — | pending — self-registered, awaiting admission |
| true | true | active |
| true | false | suspended |
An account is never "pending and active": approval sets both together. Self-registered users start unapproved; administrator-created users start approved.
The two gates mean "not yet admitted" and "admitted but currently suspended" are distinguishable — which matters when a contractor's access is paused rather than never granted.
Write-security levels
A small fixed hierarchy. A role maps to a level; a tag may require one; a write is allowed when the operator's level is at least the tag's.
| Level | Name | Meaning |
|---|---|---|
| 0 | Read | Cannot write at all |
| 1 | Operate | Baseline write capability |
| 2 | Supervise | Supervisor actions — recipes, mode changes |
| 3 | Admin | Calibration, safety-adjacent parameters |
The operator's level is the highest across their roles, and it is embedded in the runtime token so the write path checks it without a database round trip per write.
Tag Line1/Filler/SpeedSP writable, write level 2
Role "Operator" level 1 → write rejected
Role "Supervisor" level 2 → write allowed
Both gates are enforced server-side. Hiding a button is usability, not security.
Roles and rosters
| Concept | Purpose |
|---|---|
| Runtime role | Named group with a write level and view access |
| Role membership | Which users hold which roles |
| Roster | An on-call schedule of shifts and members |
| On-call now | Who is currently on shift — the target for notifications |
A shift counts as active when the current time falls within its window, or when it has no window (always-on).
Revocation
Runtime tokens have a TTL, but revocation must not wait for it — a suspended operator should lose access now, not in an hour.
QUBIQ keeps a short-TTL revocation cache of (user → active, roles). The runtime middleware consults it rather than querying the external database on every request. On a cache miss it runs one lightweight lookup.
The result: cost is roughly one query per active user per cache window, and a suspended or role-changed operator is reflected within about that window.
Self-registration
Where enabled, operators register themselves and land as pending. An administrator approves, which sets both approved and active, and assigns roles.
This suits sites with high turnover: the account exists and is attributable from the first day, but grants nothing until a human admits it.
Session behaviour
| Situation | Behaviour |
|---|---|
| Token expires | Re-authentication requested; screen state preserved where possible |
| Operator suspended | Access revoked within the revocation cache window |
| Roles changed | New level applies within the same window |
| Network drops | Session resumes on reconnect if the token is still valid |
Kiosk panels
For a permanent panel, decide deliberately:
- A shared panel account is acceptable where the panel is physically secured and every action is attributable to the panel. Set its write level to the minimum that lets the shift work.
- Individual logins where actions must be attributable to a person — anything regulated, or anything where the audit journal has to answer "who".
Do not give a shared kiosk account level 3.
Checklist
- Every production project is bound to a User Database — no accidental public LiveView
-
LIVE_JWT_SECRETis set explicitly, not derived - Writable tags have write levels reflecting real consequence
- Roles map to levels matching actual responsibility
- Self-registration, if enabled, has a named approver
- Leavers are suspended, not deleted, so history stays attributable
- Kiosk accounts hold the minimum level that lets the shift work