Permissions
Permission strings are the atomic unit of access control in BizFirstGO — dot-notation identifiers in resource.action format that are evaluated at every security boundary in the system.
Permission String Format
All permissions follow the pattern resource.action (using dot notation). The resource identifies the capability domain; the action identifies what operation is being authorized.
// Format: resource.action
"workflow.design" // can create/edit workflow definitions
"workflow.initiate" // can start a workflow instance
"workflow.view" // can read workflow status and history
"workflow.cancel" // can cancel a running workflow instance
"form.create" // can create new form definitions
"form.edit" // can modify existing form definitions
"form.publish" // can publish a form to users
"form.submit" // can submit a form
"form.view" // can read form definitions and submissions
"iam.user.manage" // can create/edit/delete users
"iam.role.assign" // can assign roles to users
"iam.policy.manage" // can create/edit security policies
"audit.read" // can read audit logs
"audit.export" // can export audit data
"report.finance.read" // custom domain permission — finance reports
"report.payroll.read" // custom domain permission — payroll reports
Wildcard Permissions
A trailing .* wildcard grants all actions on a resource. Wildcards are only available to system roles — tenant custom roles must enumerate specific permissions.
"workflow.*" // all workflow operations (admin only)
"form.*" // all form operations (admin only)
"iam.*" // all IAM operations (admin only)
"tenant.*" // all tenant management operations (admin only)
IPermissionProvider
public interface IPermissionProvider
{
/// <summary>
/// Returns the list of permission keys for a user.
/// Returns null if HttpContext is unavailable (background jobs) — treat as "no permissions".
/// Returns empty list if user has no explicit permissions.
/// </summary>
Task<IReadOnlyList<string>?> GetUserPermissionsAsync(
string userId,
string tenantId,
CancellationToken ct);
}
// BizFirst Passport implementation — reads from JWT "permissions" claim
// or falls back to SQL IAM_UserPermissions table for explicit grants
Full Permission Reference
| Permission | Resource | Description |
|---|---|---|
workflow.design | Flow Studio | Create and edit workflow definitions in Flow Studio |
workflow.initiate | Flow Studio | Start a new workflow instance |
workflow.view | Flow Studio | Read workflow status, history, and logs |
workflow.cancel | Flow Studio | Cancel a running workflow instance |
workflow.admin | Flow Studio | Administrative workflow operations (replay, force-complete) |
form.create | Atlas Forms | Create new form definitions |
form.edit | Atlas Forms | Modify existing form definitions |
form.publish | Atlas Forms | Publish forms to make them available to users |
form.submit | Atlas Forms | Submit a form instance |
form.view | Atlas Forms | Read form definitions and submission data |
iam.user.manage | Passport IAM | Create, update, and disable user accounts |
iam.role.assign | Passport IAM | Assign and revoke roles from users |
iam.policy.manage | Passport IAM | Create and manage security policies |
audit.read | Audit | Read security and activity audit logs |
audit.export | Audit | Export audit data to external systems |
managed-identity.manage | Passport | Create and manage managed identities |
task.complete | WorkDesk | Complete HIL tasks assigned to the user |
Defining Custom Permissions
POST /passport/admin/permissions
Authorization: Bearer {admin-token}
Content-Type: application/json
{
"permissionKey": "report.finance.read",
"displayName": "Read Finance Reports",
"description": "Allows access to financial reporting dashboards",
"resourceDomain": "report",
"tenantId": "tenant-abc"
}
// Custom permissions can then be assigned to tenant roles
// or checked at runtime using IPassportClient.CheckPermissionAsync()
Prefer checking permissions over checking roles in application code. Permission checks are more resilient to role restructuring — if you refactor which roles have which permissions, code that checks workflow.design continues to work correctly, while code that checks role == "manager" may break.