Skip to main content

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:

  1. Fetch the user — a REST step retrieves the user's details (including their persona reference) from the authentication backend.
  2. 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

Every user needs a persona reference

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.

One persona per user

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.

Re-version and wait after model changes

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.