Documentation Index
Fetch the complete documentation index at: https://prismeai-legacy.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
The access-manager module provides three groups of functions :
- Service account management — Create, rotate, delete service accounts and issue JWT tokens. Restricted to privileged workspaces defined via
PRIVILEGED_WORKSPACES.
- Product bindings — CRUD operations on the
product_bindings collection to link resources to users, orgs, or groups. Available to any workspace.
- Access checking — High-level
checkAccess function that combines permissions, scopes, and bindings to determine if a caller can access a resource. Available to any workspace.
Service account functions (getServiceAccountToken, createServiceAccount, rotateServiceAccountSecret, deleteServiceAccount) are only available to workspaces listed in the PRIVILEGED_WORKSPACES environment variable. Binding and access check functions are available to all workspaces.
Service Account Functions
getServiceAccountToken — Get a JWT token for a service account
- run:
module: access-manager
function: getServiceAccountToken
parameters:
orgSlug: "{{orgSlug}}"
serviceAccountSlug: "{{saSlug}}"
create: true
expiresIn: 3600
output: tokenResult
| Parameter | Type | Required | Description |
|---|
orgSlug | string | yes | Organization slug |
serviceAccountSlug | string | yes | Service account slug |
create | boolean | no | When true, creates the service account if it doesn’t exist and rotates the secret if needed. When false or omitted, only works with a cached secret. |
name | string | no | Display name for the service account (used on creation) |
roleSlug | string | no | Role to assign. Must be in the workspace’s allowedRoleSlugs. Defaults to the workspace’s defaultRoleSlug. |
expiresIn | number | no | Token TTL in seconds |
Returns the token response including accessToken, tokenType, expiresAt, permissions, and scopes.
createServiceAccount — Create a new service account
- run:
module: access-manager
function: createServiceAccount
parameters:
orgSlug: "{{orgSlug}}"
serviceAccountSlug: "{{saSlug}}"
name: "My Agent"
roleSlug: "agent-standard"
output: result
| Parameter | Type | Required | Description |
|---|
orgSlug | string | yes | Organization slug |
serviceAccountSlug | string | yes | Service account slug |
name | string | no | Display name |
roleSlug | string | no | Role to assign (validated against allowed roles) |
Returns the created service account including slug and clientSecret. If the service account already exists, returns { slug } without error.
rotateServiceAccountSecret — Rotate a service account’s client secret
- run:
module: access-manager
function: rotateServiceAccountSecret
parameters:
orgSlug: "{{orgSlug}}"
serviceAccountSlug: "{{saSlug}}"
output: result
| Parameter | Type | Required | Description |
|---|
orgSlug | string | yes | Organization slug |
serviceAccountSlug | string | yes | Service account slug |
Returns the new clientSecret.
deleteServiceAccount — Delete a service account
- run:
module: access-manager
function: deleteServiceAccount
parameters:
orgSlug: "{{orgSlug}}"
serviceAccountSlug: "{{saSlug}}"
output: result
| Parameter | Type | Required | Description |
|---|
orgSlug | string | yes | Organization slug |
serviceAccountSlug | string | yes | Service account slug |
Cache behavior
The module caches client secrets in memory after creation or rotation. This cache is automatically invalidated when:
- A service account is deleted (clears secret + permissions cache)
- A service account secret is rotated (clears secret cache)
- A service account is updated (clears permissions cache)
Cache invalidation is event-driven and applies to all runtime instances simultaneously.
Service Account Example
slug: get-agent-token
name: Get Agent Token
do:
# Create (or reuse) a service account and get a JWT token
- run:
module: access-manager
function: getServiceAccountToken
parameters:
orgSlug: "{{orgSlug}}"
serviceAccountSlug: "agent-{{agentId}}"
name: "Agent {{agentId}}"
create: true
expiresIn: 3600
output: tokenResult
# Use the token to call an API
- fetch:
url: "{{config.apiUrl}}/resources"
method: GET
headers:
Authorization: "Bearer {{tokenResult.accessToken}}"
output: resources
Product Bindings Functions
Product bindings associate resources (agents, workflows, etc.) to principals (users, orgs, groups) within a workspace. All binding functions automatically scope queries to the caller’s workspaceId — it cannot be overridden.
findBindings — Query bindings
- run:
module: access-manager
function: findBindings
parameters:
query:
resourceType: agents
principalType: user
principalId: "{{userId}}"
options:
pagination:
limit: 50
page: 0
sort:
createdAt: desc
output: bindings
| Parameter | Type | Required | Description |
|---|
query | object | yes | Filter fields matching ProductBinding (e.g. resourceType, resourceId, principalType, principalId, orgSlug) |
options.pagination | object | no | { page, skip, limit } |
options.sort | object | no | Sort fields (e.g. { createdAt: 'desc' }) |
options.fields | array | no | Fields to return |
Returns an array of binding documents.
findAndCountBindings — Query bindings with total count
- run:
module: access-manager
function: findAndCountBindings
parameters:
query:
resourceType: agents
options:
pagination:
limit: 20
page: 0
output: result
# result.items = [...], result.total = 42
Same parameters as findBindings. Returns { items: [...], total: number }.
countBindings — Count matching bindings
- run:
module: access-manager
function: countBindings
parameters:
query:
resourceType: agents
orgSlug: "{{orgSlug}}"
output: count
| Parameter | Type | Required | Description |
|---|
query | object | yes | Filter fields |
Returns a number.
insertBinding — Create a binding
- run:
module: access-manager
function: insertBinding
parameters:
data:
resourceType: agents
resourceId: "{{agentId}}"
principalType: user
principalId: "{{targetUserId}}"
orgSlug: "{{orgSlug}}"
grantedBy: "{{userId}}"
email: "{{targetEmail}}"
output: result
# result.acknowledged = true, result.insertedId = "..."
| Parameter | Type | Required | Description |
|---|
data.resourceType | string | yes | Resource type (e.g. agents, workflows) |
data.resourceId | string | yes | Resource identifier |
data.principalType | string | yes | user, org, or group |
data.principalId | string | yes | Principal identifier |
data.orgSlug | string | yes | Organization slug |
data.grantedBy | string | yes | User who granted the binding |
data.email | string | no | Email for user bindings |
data.roleSlug | string | null | no | Optional role slug controlling which actions this binding grants. See Role-based bindings. When null or omitted, the binding grants every action except delete. |
The workspaceId and workspaceSlug are set automatically from the caller’s context. Emits a runtime.bindings.created event.
A unique constraint prevents duplicate bindings for the same (workspaceId, resourceType, resourceId, principalType, principalId).
updateBinding — Update an existing binding
- run:
module: access-manager
function: updateBinding
parameters:
query:
resourceType: agents
resourceId: "{{agentId}}"
principalType: user
principalId: "{{targetUserId}}"
data:
roleSlug: editor
output: result
# result.matchedCount = 1, result.modifiedCount = 1
| Parameter | Type | Required | Description |
|---|
query | object | yes | Filter to match the binding(s) to update |
data.roleSlug | string | null | no | New role slug to apply. Pass null to clear the role (binding will then grant all actions except delete). |
Only roleSlug can be updated through this function — other fields are immutable. Emits a runtime.bindings.updated event when at least one binding is modified.
deleteOneBinding — Delete a single binding
- run:
module: access-manager
function: deleteOneBinding
parameters:
query:
resourceType: agents
resourceId: "{{agentId}}"
principalType: user
principalId: "{{targetUserId}}"
output: result
# result.deletedCount = 1
| Parameter | Type | Required | Description |
|---|
query | object | yes | Filter to match the binding to delete |
Emits a runtime.bindings.deleted event if a binding was deleted.
deleteManyBindings — Delete multiple bindings
- run:
module: access-manager
function: deleteManyBindings
parameters:
query:
resourceType: agents
resourceId: "{{agentId}}"
output: result
# result.deletedCount = 5
| Parameter | Type | Required | Description |
|---|
query | object | yes | Filter to match bindings to delete |
Emits a runtime.bindings.deleted.many event if any bindings were deleted.
Workspace cleanup
When a workspace is deleted, all its bindings are automatically removed.
Access Check Function
The checkAccess function provides a high-level access control check that combines three sources: permissions (from run.permissions), scopes (from run.scopes), and bindings (from the product_bindings collection). This replaces the need for complex DSUL-based permission checking.
checkAccess — Check resource access
- run:
module: access-manager
function: checkAccess
parameters:
resourceType: agents
resourceId: "{{agentId}}"
action: read
output: access
All parameters are optional. When called without resourceType/action, it only checks authentication and returns isWorkspaceAdmin.
| Parameter | Type | Required | Description |
|---|
resourceType | string | no | Resource type (e.g. agents, workflows). Must be set together with action. |
resourceId | string | no | Specific resource ID. Requires resourceType. |
action | string | no | Action to check (typically read, write, share, delete, manage, but any string is accepted — must match the keys in roles[*].permissions). Must be set together with resourceType. |
list | boolean | no | When true, returns the list of granted resource IDs instead of a single grant |
roles | object | no | Role definitions for binding role enforcement. Record<string, { name?: string, permissions: string[] }>. Required as soon as any matching binding has a roleSlug — otherwise checkAccess throws. See Role-based bindings. |
Return value
| Field | Type | Description |
|---|
granted | boolean | Whether access is granted |
reason | string | Why access was granted: permission, wildcard-scope, scope, or binding:{principalType} (e.g. binding:user, binding:org, binding:group). When the matching binding carries a roleSlug, the reason becomes binding:{principalType}:{roleSlug} (e.g. binding:user:editor). |
grantedIds | string[] | Only in list mode — merged set of IDs from scopes and bindings |
hasWildcardScope | boolean | true if the caller has wildcard scope (sees all resources of this type) |
isWorkspaceAdmin | boolean | true if the caller has * or {workspaceSlug} manage permission |
error | object | Only when granted is false — contains error (code) and message (human-readable) |
The error object follows the same shape as _auth automations:
error.error | error.message | When |
|---|
Unauthorized | Authentication required | No authenticated user (no userId and no org API key) |
Forbidden | Access denied: missing permission '{workspaceSlug}:{resourceType}:{action}' | User is authenticated but has no matching permission |
Resolution order
-
Authentication — The caller must have a
userId (user session) or an orgSlug (org API key). If neither is present, returns Unauthorized immediately.
-
Permissions — Checked from
run.permissions (set by the token’s role). The function checks in order:
* with manage → workspace admin
{workspaceSlug} with manage → workspace admin
{workspaceSlug}:{resourceType} with manage or {action} → access
- If no permission matches → returns
Forbidden immediately (scopes and bindings are not checked)
-
Scopes — Parsed from
run.scopes (only if permission was granted):
*, {workspaceSlug}:*, or {workspaceSlug}:{resourceType}:* → wildcard scope (all resources)
{workspaceSlug}:{resourceType}:{id} → adds id to scoped IDs
-
Bindings — Looked up in
product_bindings for the caller’s identity (userId, org, groups). Only checked for single resource mode when the scope doesn’t match. Each matching binding is then evaluated against the requested action through role-based bindings.
Role-based bindings
Bindings can carry a roleSlug to restrict which actions they grant. The role definitions themselves live outside the binding — they must be passed to checkAccess via the roles parameter (typically loaded from config.roles):
- run:
module: access-manager
function: checkAccess
parameters:
resourceType: agents
resourceId: "{{agentId}}"
action: write
roles:
owner:
name: Owner
permissions: [read, write, share, delete]
admin:
name: Admin
permissions: [read, write, share]
editor:
name: Editor
permissions: [read, write]
reader:
name: Reader
permissions: [read]
output: access
Resolution rules applied to each candidate binding:
Binding roleSlug | roles parameter | Behavior |
|---|
null / unset | (any) | Binding grants every action except delete. Used for legacy bindings or “full collaborator” semantics. |
set (e.g. editor) | provided, slug exists | Action must be in roles[slug].permissions — otherwise the binding is ignored and checkAccess continues to the next binding (or returns Forbidden). |
| set | not provided at all | checkAccess throws — passing roles is required as soon as any binding could be role-typed. |
| set | provided but slug missing | The binding is ignored (treated as having no permissions). |
checkAccess only stops at the first binding that grants the requested action. If a user has multiple bindings (e.g. reader and editor), the most permissive applicable one wins.
When the binding is granted, the reason field reflects the role: binding:user:editor, binding:org:admin, etc.
Keep your role catalog in config.roles so it can be referenced consistently from every endpoint that calls checkAccess (and from insertBinding / updateBinding for validation).
Modes
Auth-only (no resourceType, no action):
- Returns
{ granted: true, isWorkspaceAdmin } — just confirms the caller is authenticated
Unauthenticated caller:
- Returns
{ granted: false, error: { error: 'Unauthorized', message: 'Authentication required' } }
Single resource (resourceId provided):
- If wildcard scope →
{ granted: true, reason: 'wildcard-scope', hasWildcardScope: true, isWorkspaceAdmin }
- If scoped ID match →
{ granted: true, reason: 'scope', hasWildcardScope: false, isWorkspaceAdmin }
- If binding found and the binding’s
roleSlug allows the action → { granted: true, reason: 'binding:{principalType}' or 'binding:{principalType}:{roleSlug}', hasWildcardScope: false, isWorkspaceAdmin }
- Otherwise →
{ granted: false, hasWildcardScope: false, error: { error: 'Forbidden', message: '...' } }
List mode (list: true, no resourceId):
- If wildcard scope →
{ granted: true, grantedIds: [], hasWildcardScope: true } (caller sees everything)
- Otherwise →
{ granted: true, grantedIds: [...], hasWildcardScope: false } (merged+deduplicated scoped IDs + binding IDs)
Permission-only (resourceType + action, no resourceId, no list):
- Returns
{ granted: true, reason: 'permission', hasWildcardScope, isWorkspaceAdmin }
Access check examples
Guard a specific resource
- run:
module: access-manager
function: checkAccess
parameters:
resourceType: agents
resourceId: "{{agentId}}"
action: read
output: access
# access.error is set when granted=false (UNAUTHORIZED or FORBIDDEN)
- conditions:
"{{access.error}}":
- break:
automation: true
output:
error: "{{access.error.error}}"
message: "{{access.error.message}}"
Check auth + admin status only
- run:
module: access-manager
function: checkAccess
output: access
# access.granted = true if authenticated
# access.isWorkspaceAdmin = true if user has * or workspace-level manage
List all accessible resources
- run:
module: access-manager
function: checkAccess
parameters:
resourceType: agents
action: read
list: true
output: access
# If access.hasWildcardScope is true, query all agents without filter
# Otherwise, filter agents by access.grantedIds
- conditions:
"{{access.hasWildcardScope}}":
- fetch:
url: "{{config.apiUrl}}/agents"
output: agents
default:
- fetch:
url: "{{config.apiUrl}}/agents?ids={{access.grantedIds | join ','}}"
output: agents