Runbooks/Workflow Approvals

Workflow approvals

The Approval step stops a mesh workflow until a person decides. The run waits while the approvers are told by an inbox notice and an email. They approve or reject on the Approvals page of the portal. Approved continues the run. Rejected or timed out either ends the run, or continues into a branch that does something else.

Approvals are part of mesh workflows, so they need the Enterprise tier. This runbook covers the step’s fields, who can approve, what approvers see, what operators can do, and a worked example: manager approval before an account is enabled.

Add an Approval step

In the workflow designer (Configure → Workflows, then New workflow or Edit), drag Approval from the Control group of the palette onto the canvas. Select the card to fill in its fields.

FieldWhat it does
ApproversWho decides. Required. Pick them with the same Objects field as other steps: Related objects (for example the relationship manager, Objects this one points to), Objects matching a query (people, or a group), or Objects by id (expression). See Choosing the objects a step acts on. The object itself is refused: the object cannot approve its own workflow.
Escalate toOptional. A second set of approvers, asked as well when nobody has decided by Escalate after, or at once when none of the first set can act. Required when Escalate after is set.
Approvals neededHow many approvals settle the request. Default 1, minimum 1. Any single rejection rejects.
Escalate afterOptional. A duration such as 2.00:00:00. Must be shorter than Time out after.
Time out afterHow long to wait for a decision. Default 7.00:00:00, at least 1 minute, at most 400 days.
TitleOptional. The line approvers see in the list and the notice subject. It can contain tokens such as {{displayName}}. Default: the workflow name and the object’s name, such as New joiner approval: Ada Lovelace.
Message to approversOptional. Plain text shown to approvers, with tokens such as {{department}}. A sensitive attribute shows as <sensitive>.
When rejectedend (default) ends the run as Rejected. continue runs the next step, which can branch on the outcome.
When timed outend (default) ends the run as TimedOut. continue runs the next step.

Both durations are written as days.hours:minutes:seconds and count from the moment the request is opened. The 400-day limit is the Workflows:MaxDelayDays setting, shared with the Wait step; see Tuning.

Validate checks the step: approvers set, durations in range, Escalate after shorter than Time out after, and an escalation set present when Escalate after is.

Branch on the outcome

When When rejected or When timed out is continue, the properties panel shows Insert outcome fork. It adds two nested If/else branches right after the Approval step:

BranchConditionThenElse
Approved?EqualsIgnoreCase(attr("steps.<key>.outcome"), "approved")The request was approved.Goes to Rejected?.
Rejected?EqualsIgnoreCase(attr("steps.<key>.outcome"), "rejected")The request was rejected.The request timed out.

<key> is the Approval step’s key. The arms start empty; drag the steps you want into them. With When timed out left on end, a timed-out run ends before the fork, so the last Else arm is never reached.

Who can approve

Approvers are mesh objects, not typed user names. The portal links a signed-in person to their mesh object by matching the sign-in against the object’s userPrincipalName, mail or sAMAccountName.

Other object types found by the approver target are skipped with a note.

How approvers are told

Each approver who can act gets an inbox notice under the bell and, if email is set up and their object has an email address, an email. The messages are plain text.

WhenSubject
The request opensApproval: title (needs your approval)
The request escalates (to the escalation set)Approval: title (escalated to you)
Someone approves or rejects itApproval: title (approved), or Approval: title (rejected)
Nobody decided in timeApproval: title (timed out)
The run ended firstApproval: title (withdrawn)

The body starts with “Workflow:” and the workflow’s name, then “About:” with the object it is about and its type, the message, how many approvals there are so far (“Approvals so far: n of m”), and, for a new request, when it escalates and times out in UTC. Group join and vault requests use the same form with their own prefix; see Notifications. Only approvers are told. To tell anyone else, such as the person or HR, add a Send email step in the outcome branch.

The last line of the email is a link to the Approvals page when the Portal URL is set under Settings → Email, in the Links section. The link opens /#/identity/approvals. Without a Portal URL, the email ends with “Open the IdentityMesh portal and go to Approvals.” See Email.

The Approvals page

Approvals in the sidebar, its own entry directly below Mesh Objects, at /identity/approvals. It is the one shared page for every kind of approval: it lists workflow requests beside group join requests and vault check-out requests, with a kind filter. The old address /identity/workflows/approvals redirects to it with the Workflow kind preset. The page, its columns and the shared rules are described in Approvals. Deciding a workflow request needs the workflows.approve permission, which every built-in role except Viewer has. On a tier below Enterprise the page says “Approvals require the Enterprise tier”.

TabShows
To decideOpen requests you can decide now.
Decided by meRequests you have decided.
All openEvery open workflow request. Only for holders of workflows.execute.
Completion failedRequests whose follow-up action failed. A workflow request has no follow-up action of its own, so it never appears here.

A workflow row’s Title is the step’s Title, and its Subject is the object the run is for.

To decide, select Approve or Reject on the row. A dialog opens with a Reason (recorded in the audit trail) box. Confirm with Approve or Reject. The run picks the decision up within seconds.

A request that was already settled, a vote that crossed with someone else’s, or a subject that no longer exists is refused, with the reason. Reload the page to see where it stands.

What the run shows

While it waits, the run’s status is Delayed. It does not hold up other runs for the same object. The run detail shows a Waiting for approval panel with:

“Delayed until” on the run shows the next deadline. After the decision, the step’s outputs are on the run detail and the path the run took through the outcome fork is painted.

A run that ends because of the request shows Rejected or TimedOut, with the decision under Outcome, such as “Rejected by ada.lovelace@contoso.com” or “Timed out (timed out)”.

Outputs

OutputContains
outcomeapproved, rejected or timedOut.
approvedByThe sign-in names of the people who approved, joined with ;, in the order they decided. After an operator approval, the operator’s sign-in name.
decidedByWho settled the request. Empty when it timed out.
decidedUtcWhen it was settled or timed out, in UTC.
reasonThe reason given with the settling decision, or timed out.
approvalsHow many people approved.
escalatedtrue or false.
approvalIdThe request’s id.

A later step reads them as steps.<key>.<output>, for example {{steps.managerApproval.approvedBy}} in an email body.

Operator actions

Holders of workflows.execute can settle a request without being an approver. An operator decision settles it outright, whatever Approvals needed says, and the approvers are told it was decided by an administrator.

WhereActionEffect
Run detail of a run waiting for approvalApprove as operatorAsks for a reason, then approves. Replaces Skip step and Resume now for these runs.
Approvals page, All open tabApprove as operator / Reject as operatorOn rows you are not an approver on. On rows where you are an approver, Approve and Reject cast your own vote.
Run detailCancel runWithdraws the request. The approvers are told it was withdrawn.

Skipping the step through the API counts as an operator approval with the reason “skipped by operator”. The person the workflow runs for cannot settle their own request, even as an operator.

Withdrawn requests

A pending request is withdrawn, and its approvers are told, when:

A withdrawn request leaves To decide.

Permissions

PermissionAllows
workflows.approveOpen the Approvals page and decide the requests you are an approver on.
workflows.executeAlso see All open and decide any request as an operator.
workflows.writeAdd and edit Approval steps in workflows.
Roleworkflows.approve
Adminyes
Operatoryes
Viewerno
Useryes

The User role is the default role every signed-in person falls back to (see Authentication), so anyone can decide a request that names them. Holding the permission shows nothing by itself: the page lists only the requests the person is an approver on.

The installer’s database step adds what approvals need. A database updated outside the installer needs the database step run before the Admin API starts.

Every decision is recorded in the administrator audit trail with who made it, whether as an approver or as an operator, and the reason. For the permissions of the other kinds on the shared page, see Permissions.

Retention and erasure

Approval requests are removed with their runs by run-history retention (Retention.WorkflowRunDays, 90 days by default). Rejected and TimedOut runs age out like Completed ones. See Retention.

Erasing a person under DSAR and right to erasure blanks the text of the requests about them: the title reads [erased], and the subject name and message are removed. Who decided, and how, stays on the record.

How-to: manager approval before an account is enabled

This example holds a new joiner’s account disabled until their manager approves it. If the manager does not answer in two days, HR is asked as well. A rejection tells HR, and a request nobody answers in five days ends the run.

The example assumes:

1. Set the portal link. Open Settings → Email and, under Links, enter the Portal URL, the plain address of the portal such as https://identitymesh.example.com, then Save. See Email. Confirm with Send test that email is working.

2. Create the workflow. Open Configure → Workflows and select New workflow. Set the trigger Kind to Composer rule, pick “New joiners” and the direction In.

3. Add the Approval step. Drag Approval from Control onto the canvas. Name it “Manager approval” and set its key to managerApproval. Fill in:

FieldValue
ApproversRelated objects, relationship manager, Objects this one points to
Escalate toObjects matching a query, object type Group, criterion displayName equals HR approvers
Approvals needed1
Escalate after2.00:00:00
Time out after5.00:00:00
TitleEnable account for {{displayName}}
Message to approvers{{displayName}} joins {{department}}. Approve to enable their account.
When rejectedcontinue
When timed outend

4. Insert the outcome fork. Select Insert outcome fork. Two branches appear after the step, Approved? and Rejected?.

5. Validate and save. Select Validate. The status bar shows ✓ Valid. Save the workflow and enable it.

6. Start a test run. Use Run now against a test joiner whose manager can sign in, and choose In. Open the run from the Runs tab. Confirm that:

If the panel lists nobody, or the run ended at once as timed out with “no approver could act”, the test joiner has no manager the portal can recognise. See Troubleshooting.

7. Decide as the manager. Sign in as the manager. Confirm the bell shows “Approval: Enable account for … (needs your approval)” and the email arrived with its link. Open Approvals. The request is on To decide. Select Approve, enter a reason and confirm.

8. Check the outcome. Within seconds the run continues. On the run detail, confirm that:

Open the joiner’s mesh object. accountEnabled reads true, with the workflow as its source, and the object is queued for export. After the next export, the account is enabled in the target.

9. Test a rejection. Start a second test run and reject it with a reason. The run follows Rejected?, HR receives the email with the reason, and the account stays disabled.

Translated MIM approvals

The MIM migration analyzer translates MIM’s own approval activity and the MIM Workflow Activity Library’s Request Approval activity into an Approval step. Approvals from a policy rule’s authorization workflow are placed first in that rule’s workflow, before its other steps.

MIM approves a request before the change is made. A mesh workflow runs after the change is already in the mesh, so the Approval gates the steps that follow it, not the change itself. Every such proposal carries a note saying so. Review what the Approval gates before you enable a translated workflow.

Troubleshooting

What you seeCause and fix
An approver is marked no portal identityTheir mesh object has no userPrincipalName, mail or sAMAccountName that matches exactly one person. Give the object a value that matches their sign-in, then start a new run. A request that is already open keeps its approver list.
The run ended at once as TimedOut, reason “no approver could act”Nobody in Approvers or Escalate to could act, for example because the person has no manager. Fill the manager attribute, or add an escalation set.
The email ends with “Open the IdentityMesh portal and go to Approvals.”Portal URL is empty. Set it under Settings → Email, Links. The page is Approvals in the sidebar, its own entry directly below Mesh Objects.
The email link opens an error page instead of the Approvals pageThe Portal URL does not match the address the portal is opened at. Enter the plain address, such as https://identitymesh.example.com, with the right host name, port and path and no #. See Email.
The request is on the Approvals page, but no notice is in the bellThe bell matches notices on the sign-in name. Compare the approver’s sign-in with the userPrincipalName on their object. The Approvals page is the reliable list.
A decision is refusedIt was already settled, another decision landed first, or the object no longer exists. Reload the page.
The run stays Delayed after an approvalThe run picks a decision up within seconds, and at the latest within about a minute. If it still waits, check that workflows are not paused and that the Operations card shows a recent heartbeat.