Skip to main content

Authorization Activities

Four activities let a workflow read and evaluate the platform's authorization policies, and act as another user.

Most workflows never call these: the platform already enforces policy around the activities that need it — http.request, shell.run, claude_agent.query and the deployment activities all check their own. Reach for these when a workflow has to make an authorization decision itself: gate a branch on whether the caller may do something, or carry out an action on another user's behalf.

Setup

No credentials. Identity comes from the calling context — the user the workflow is running as.

How a policy is shaped

A resource policy names a resource and lists, for each action on it, the grants that allow it. A grant is a pattern matched against evidence about the caller and the run.

resource: {resource_id: "sys.workflow", namespace: "system"}
items:
- privilege: {privilege_id, resource_id, action: "execute", description}
grants:
- content: ["user_email:jon@example.com", "group:user:moco_admins"]
relation: OR

Grant patterns come in two families:

User-basedContext-based
user_email:jon@example.comoauth_client_id:myapp
user_org_name:mocoland technologyweb_origin:https://example.com
group:user:moco_adminstarget_web_origin:https://*.prod.example.com
*wfspec_name:internal.example_workflow, parent_wfspec_name:ai.*
wfspec_tag:category:ai, tier:beta, debug_mode:true
env:DEVCONTAINER:true, group:http-allow-list.prod, *

relation is AND (default) or OR across the patterns in one grant.

Authorization fails open when no policy is deployed

If a resource has no policy, the check allows access and logs a warning. A deployment that wants http.request, shell.run or claude_agent.query restricted must actually deploy the policy — not deploying one is not a deny.

Defaults

All four: 60 s timeout, 3 attempts.

NotAuthorizedError is not retryable

A denial raised by raise_on_deny (or by any platform-side check) is a non-retryable error. Raising max_attempts will not help.


authz.list_resources

Lists the resources that have policies, optionally filtered.

Input

FieldTypeRequiredDefaultDescription
namespacestrnonullOnly resources in this namespace
resource_id_patternstrnonullOnly resource ids matching this pattern; * is the wildcard

Output

A list of resources, each {resource_id, namespace, description}.

Example

- activity:
name: list-system-resources
type: authz.list_resources
input_data:
namespace: "system"
resource_id_pattern: "sys.*"
output_name: resources # -> [{resource_id, namespace, description}, ...]

authz.get_resource_policy

Fetches the full policy for one resource — the input authz.check_privilege expects.

Input

FieldTypeRequiredDefaultDescription
resource_idstryesResource to fetch the policy for

Output

A ResourcePolicy: {resource, items, groups}, or null when the resource has no policy.

Example

- activity:
name: load-policy
type: authz.get_resource_policy
input_data:
resource_id: "sys.workflow"
output_name: resource_policy

authz.check_privilege

Evaluates whether the caller is granted an action on a resource, and returns a boolean — or raises, with raise_on_deny: true.

Evidence about the caller and the run is filled in automatically — user_id, requester_user_id, is_impersonated, tier, debug_mode, wfspec_name and caller_wfspec_name — on top of anything you add in extra_evidence.

Input

FieldTypeRequiredDefaultDescription
resource_policyobjectyesThe policy to evaluate, typically from authz.get_resource_policy
check_actionstryesThe action to check, e.g. execute
extra_evidencedictnonullAdditional evidence merged into the automatic set
raise_on_denyboolnofalseRaise NotAuthorizedError instead of returning false

Output

A boolean: true when the action is granted.

Example

Gate the rest of the workflow on the check:

- activity:
name: load-policy
type: authz.get_resource_policy
input_data:
resource_id: "sys.workflow"
output_name: resource_policy

- activity:
name: check-execute
type: authz.check_privilege
input_data:
resource_policy: "{{ resource_policy }}"
check_action: execute
raise_on_deny: true

Branching instead of failing:

- activity:
name: may-publish
type: authz.check_privilege
input_data:
resource_policy: "{{ resource_policy }}"
check_action: publish
extra_evidence:
target_env: "{{ target_env }}"
output_name: can_publish

- activity:
condition: "{{ can_publish }}"
type: http.request
input_data:
method: POST
url: "{{ publish_url }}"

authz.impersonate_user

Returns a user identity for another user, which later steps can run as. Use it for a workflow acting on someone's behalf — a scheduled job that must see what a particular user sees.

Input

FieldTypeRequiredDefaultDescription
run_as_user_idstryesThe user to act as

Output

A user identity:

FieldTypeDescription
user_idstrThe impersonated user
requester_user_idstrThe caller who asked for the impersonation
auth_modestrInherited from the caller's own credential type

Example

- activity:
name: act-as-owner
type: authz.impersonate_user
input_data:
run_as_user_id: "{{ dataset_owner_id }}"
output_name: run_as
Impersonating anyone but yourself is privileged

It requires the sys.workflow / impersonate_user privilege. The impersonated identity inherits the caller's auth_mode, so the credential class of the original request still applies.