Runtime Persona Resolution
The Access Management models you define in Studio (privileges, roles, personas, swimlanes) are only definitions. They take effect when they are bound to a logged-in user at runtime — this binding is called persona resolution.
This page explains, at a high level, how a real user ends up carrying their roles and privileges while a workflow runs.
How a User Is Linked to a Persona
A persona is connected to a user outside the editors. In your user /
identity system, each user record carries a reference to a persona — a
personaRefId (also seen as personaId) that points to the id of a persona
defined in the Persona Editor.
So the design-time model and the real user meet through this one field: the user
record says "this person is the MakerUser persona", and Access Management
takes it from there.
The Resolution Chain
When a user logs in and a workflow starts, the system walks this chain:
User record (personaRefId)
│ login
▼
getUser function ──▶ getPersona(personaId)
│
▼
Runtime user
└─ persona
├─ roles (fully resolved, incl. parent roles)
├─ privileges (flattened from all roles)
└─ swimlanes (computed from the roles)
The result is a runtime user object whose privileges and swimlanes are then used by every authorization layer — starting the process, picking up a task, opening a form, and pressing a button.
The getUser Function
The piece that performs this binding is a workflow named function, by convention called getUser. It does two things:
- Fetch the user — a REST step retrieves the user's details (including their persona reference) from the authentication backend.
- Resolve the persona — a code step turns that into the runtime user and resolves the persona:
// inside the getUser function's code step
runtimeUser.persona = await flow.accessmanager.getPersona(dashboardUser.personaId);
flow.output.response = runtimeUser;
flow.accessmanager is injected into the workflow runtime automatically.
getPersona() loads the persona, resolves all of its roles (including inherited
parent roles), flattens their privileges, and computes the user's swimlanes.
What You Get
After resolution, the runtime user holds:
- the union of privileges from every role in their persona (parent roles included), and
- the swimlanes their roles belong to.
These are exactly the values the authorization checks compare against
workflow.privileges, swimlane.roles, qjson.security.privileges and
action.privileges.
Things to Watch Out For
If a user record has no personaRefId, the user resolves with no roles —
they hold no privileges and belong to no swimlane. Protected resources will deny
them, while resources with no privileges defined stay open (permissive default).
Make sure every user is assigned a persona.
In the current design a user carries a single persona. If a person needs more than one role, add those roles to their persona rather than expecting multiple personas.
Persona resolution is cached for performance. After you change a privilege, role, persona or swimlane model, take a Major Version and allow a short delay (about 1–2 minutes) for the cache to refresh. Also re-version the workflow so it picks up the new references — otherwise the runtime keeps using the old, stale permissions.