Download all docs
modifiers

Auth Policy

A near-universal access-control modifier you attach to the 47 element types the runtime's unified attach graph considers compatible (app, automation, board, circle, claude-code, codex, csharp, diagram, discord, document, email, external-agent, facebook, files, fortnox, github, go-fn, graph, hitl, http, instagram, javascript, lab, linkedin, matrix, mattermost, open-code, phone-number, planning-board, python, recruitment-board, rocketchat, ruby, rust-fn, sales-board, slack, spa, sql, ssr, teams, three-d, timeseries, triformer, twitter, vector, view, websocket) so one place declares who may call them — accepting the chosen authentication methods and the authorization rules, and rejecting a request with a 401 or 403 before it ever reaches your code. (On io elements it attaches mainly for cascade hygiene; the live 401/403 gate is on the actor, frontend, and API surfaces.)

Working with it

Selecting a Auth Policy reveals its settings in the properties panel; it has no dedicated full-screen workbench.

How it appears

The same element type rendered as a definition, a circle instance, and a live workspace card.

Ay
type

Auth Policy

Define authentication requirements and access rules

modifiersmodifierdefinition

When to use / not

When to use

  • Protecting a public-facing endpoint, app, or action so callers must present valid credentials before the request runs.
  • Centralising one set of auth rules and reusing it across many elements, instead of re-declaring authentication on each one.
  • Enforcing role- or scope-based access — denying authenticated callers who lack the required role or permission.
  • Adding a restrictive auth requirement to a scope where the strictest policy should win over anything inherited.

When not to use

  • Minting the bearer tokens or keys that callers authenticate *with* — that is the api-token element; auth-policy only checks credentials, it does not issue them.
  • Brokering a third-party login / OAuth grant flow to obtain access tokens — reach for the oauth modifier; auth-policy validates the credential a request already carries.
  • Tenant isolation itself — circles are the airtight boundary; auth-policy guards entry to elements inside a circle, it is not the boundary.

Topology

Attaches to another element as a modifier, shaping that element's behaviour rather than running on its own.

Properties

authenticationobject
Authentication configuration
scopeobject
Policy scope
sessionobject
Session configuration
tokenobject
Token lifecycle configuration. Declares WHEN a bearer/api_key token should be proactively refreshed and WHERE to refresh it. Distinct from `session.*`, which governs session-cookie lifetime only and does not apply to bearer or api_key tokens. Advisory: the `evaluate` operation is a simulation endpoint and reports the configured lifecycle back in its response, but performs no outbound refresh call. Live refresh-and-retry enforcement is tracked separately (IMPROVE-381); outbound OAuth credential refresh already has its own home and is not duplicated here.
rulesarray
Top-level authorization rules (allow/deny per action+resource). Same as authorization.rules.
groupsarray
Required groups for access. Same as authorization.groups.

Capabilities

Defined for this element
  • Auth
  • Evaluate
  • Observe

Operations

  • attachPOST
  • deleteDELETE
  • detachPOST
  • disablePOST
  • enablePOST
  • evaluatePOST
  • getGET
  • get_attached_modifiersGET
  • intentionGET
  • list_attachmentsGET
  • readmeGET
  • readme_updatePOST
  • schemaGET
  • updatePATCH

Ports

Inputs

  • authenticationconfig
  • authorizationconfig
  • scopeconfig

Errors / when it fails

Auth policy should define roles and/or permissions
Fails unless: len(authorization.roles) > 0 or len(authorization.permissions) > 0

Validation rules

  • Policy does not require authentication - ensure this is intentional
  • Policy grants admin role - ensure proper authorization checks

Auth Policy (auth-policy)

Category: modifiers | Form: | Symbol: Ay

Define authentication requirements and access rules

Defines authentication and authorization requirements for attached elements. Cascade strategy: restrictive — when inherited and local policies conflict, the stricter policy wins. Evaluation order 50 (early in the middleware chain, after CORS at 5). Attaches to the near-universal set of action, agent, app, automation, board, frontend, integration, and integration-connector element types whose target contracts opt in (47 element types in the runtime’s unified attach graph: app, automation, board, circle, claude-code, codex, csharp, diagram, discord, document, email, external-agent, facebook, files, fortnox, github, go-fn, graph, hitl, http, instagram, javascript, lab, linkedin, matrix, mattermost, open-code, phone-number, planning-board, python, recruitment-board, rocketchat, ruby, rust-fn, sales-board, slack, spa, sql, ssr, teams, three-d, timeseries, triformer, twitter, vector, view, websocket). Fails with HTTP 401 when auth is required but not provided, or 403 when credentials are present but insufficient. Spec supports authentication.methods array (first entry is the required method, default “bearer”) and authorization.type (default “rbac”). The evaluate operation checks credentials against the policy and returns allowed/denied. Use auth-policy for access control; use api-token for creating bearer tokens to authenticate with. Common mistake: not attaching auth-policy to public-facing elements. For io elements (inbound HTTP, etc.), the policy attaches for cascade hygiene; credential validation runs through the io element’s native spec.auth configuration (bearer/api_key/ hmac/basic). The full machine-token authorization mode is tracked in IMPROVE-381.

Guide

Overview

An auth-policy is a modifier you attach to an element to tighten who may reach it: require authentication, require MFA, restrict to particular roles, or narrow the policy to certain paths and methods.

What it can and cannot do

It can only TIGHTEN access. It can never widen it.

check_auth_policy (physics/src/runtime/modifier_evaluator.rs) runs after the platform’s own check_authorization, and is structurally additive: every arm returns either Ok(()) or an error. There is no path through it that grants access. So attaching an auth-policy:

  • cannot make an element public,
  • cannot turn a 401 into a 200,
  • cannot fix a 422 VISIBILITY_NOT_ALLOWED.

If you are trying to let anonymous visitors reach an element, auth-policy is the wrong tool — put an io/http gateway in front of it instead. See Public pages that show live data.

Cascade is restrictive: when an inherited policy and a local one disagree, the stricter one wins, so tightening a parent can never be silently loosened by a child. Evaluation order is 50.

Where it is enforced, and where it is not

Enforced on the operation-dispatch and element-execution rails — /ops/* invocations and WebSocket open. It is not the credential check for io inbound (receive ops authenticate against the io element’s own spec.auth), and it does not gate frontend /live serving, where visible_to is the only gate. Attaching a policy to a visible_to: everyone SPA changes nothing about who can load that page.

Configuration

The schema is properties.yaml. The examples below are lifted from its examples: block, so they are schema-valid by construction.

Require authentication, allow one role

authentication:
  required: true
  methods: [bearer]
authorization:
  type: rbac
  rules:
    - effect: allow
      role: admin
      action: "*"
      resource: "*"

Top-level rules alias

rules and groups may be written at the top level instead of nested under authorization. Pick one shape, don’t mix them — mixing is the most common first-attempt 422.

rules:
  - effect: allow
    role: admin
    action: "*"
    resource: "*"

With token refresh

authentication:
  required: true
  methods: [bearer]
token:
  refresh_endpoint: "https://auth.example.com/oauth/token"
  refresh_before_seconds: 30
  refresh_skew_seconds: 10

Fields

Top-level: authentication, authorization, scope, session, token, plus the rules / groups aliases. Nothing is required.

authentication.required defaults to true — and an omitted authentication: block inherits that default rather than inverting it. (It used to invert: a policy written with only authorization.rules required no authentication and, because of an early return, skipped every role, group, scope and rule check below it. A deny-all rule on such a policy denied nothing.)

authentication.methods accepts api_key, bearer, oauth2, session, saml, oidc. The first entry is the required method; the default is bearer.

authorization carries two DISTINCT rule shapes — do not mix their fields. RBAC rules[] take {effect, action, resource, role}. ABAC conditions[] take {attribute, operator, value}. Putting ABAC keys inside a rules[] entry is the other common 422.

Related

  • api-token — mints the bearer credentials you authenticate with. auth-policy guards the door; api-token makes the key.
  • Failure statuses: 401 when authentication is required but absent, 403 when a credential is present but insufficient.

Error Recovery

ErrorRecovery guidanceNext actions
validationAuth-policy accepts two schema shapes: nested (authorization.rules) and a top-level rules alias. Pick one, don’t mix.

Capabilities

  • require-auth: Enforce authentication
  • roles: Role-based access
  • permissions: Permission-based access
  • scopes: OAuth scope requirements

Properties

PropertyTypeDefaultDescription
authenticationobjectAuthentication configuration
authorizationobjectAuthorization config. Two DISTINCT rule shapes live here — do NOT mix their fields. RBAC rules[] take {effect, action, resource, role} (e.g. {effect: ‘allow’, action: ‘read’, resource: ‘/api/docs/*’, role: ‘editor’}). ABAC conditions[] take {attribute, operator, value} (e.g. {attribute: ‘department’, operator: ‘eq’, value: ‘finance’}). Putting ABAC attribute/operator/value keys inside a rules[] entry is the #1 first-attempt 422 (a rule’s allowed properties are only action/effect/resource/role). Set type (rbac | abac | acl) to signal intent.
scopeobjectPolicy scope
sessionobjectSession configuration
tokenobjectToken lifecycle configuration. Declares WHEN a bearer/api_key token should be proactively refreshed and WHERE to refresh it. Distinct from session.*, which governs session-cookie lifetime only and does not apply to bearer or api_key tokens. Advisory: the evaluate operation is a simulation endpoint and reports the configured lifecycle back in its response, but performs no outbound refresh call. Live refresh-and-retry enforcement is tracked separately (IMPROVE-381); outbound OAuth credential refresh already has its own home and is not duplicated here.
rulesarrayTop-level authorization rules (allow/deny per action+resource). Same as authorization.rules.
groupsarrayRequired groups for access. Same as authorization.groups.

Operations

attach

Post /ops/attach | Auth: Read

Attach this modifier to a target element

Attaches this modifier to a target element. The target_id must be a UUID of an existing element that supports this modifier type (check applies_to in definition.yaml). Priority controls evaluation order when multiple modifiers of the same type are attached — lower priority runs first. The attachment is stored in element_modifiers table. Cascade resolution runs at bond-time to merge this modifier into the target’s resolved config. Common mistake: attaching to an incompatible element type — check topology rules first.

delete

Delete /ops/delete | Auth: Admin

Delete element (soft delete)

Soft delete — sets state to ‘deleted’ but retains the record. Cannot delete elements that have children (has_no_bond precondition) or active runs. Requires admin auth and confirmation.

detach

Post /ops/detach | Auth: Read

Detach this modifier from a target element

Removes this modifier from a target element. Requires the target_id. Pervasive modifiers (audit, policy) can only be detached at the level they were originally attached — inherited pervasive modifiers cannot be detached by child elements. After detach, cascade resolution re-runs to remove this modifier’s effect from the resolved config.

disable

Post /ops/disable | Auth: Admin

Disable element (hides and prevents use)

Idempotent — safe to call on already-disabled elements. Optionally pass a reason string. Disabled elements cannot be invoked or executed. Inverse of enable.

enable

Post /ops/enable | Auth: Admin

Enable element (makes usable and visible)

Idempotent — safe to call on already-enabled elements. Transitions element to ready/enabled state. Cannot enable deleted elements. Inverse of disable.

evaluate

Post /ops/evaluate | Auth: Read

Evaluate authentication policy

Tests credentials against this policy. Accepts flat fields (role, action, token), nested objects (subject.role, request.action), or context paths (context.role, context.action). Reads spec.authentication.methods[0] (default “bearer”) and spec.authorization.type (default “rbac”). Returns allowed (bool), denied_reasons, and policy details. Configure spec.authorization.roles and spec.authorization.permissions to enforce access control.

get

Get /ops/get | Auth: Read

Get element details

Element is already resolved by the routing layer — this returns the cached element, not a fresh DB query. Use the path /api/{circle}/{slug} to address elements.

get_attached_modifiers

Get /ops/attached/{target_id} | Auth: Read

Get all modifiers attached to a target element

Lists all modifiers attached to a specific target element, including modifier_id, type, subcategory, and priority. Useful for debugging cascade resolution or understanding which policies apply to an element before invoking it. Each entry also exposes attachment_id (the element_modifiers row id; same value as modifier_id, which is kept as a deprecated alias) and modifier_uuid (the source modifier element’s own UUID, omitted when the named source element is absent or deleted). During triage, use modifier_uuid to identify the bound modifier element, not modifier_id.

intention

Get /ops/intention | Auth: Read

Get element intention with full inheritance chain

Returns three levels: direct (this element’s intention), inherited (from category and root), and resolved (final merged intention). Useful for understanding an element’s purpose in context of its hierarchy.

list_attachments

Get /ops/targets | Auth: Read

List all elements this modifier is attached to

Returns all target elements where this modifier is currently applied. Shows target_id, target_type, priority, and cascade_policy.

readme

Get /ops/readme | Auth: Read

Get element README.md content

Reads README.md from the element’s git repository. Returns empty content (not an error) if no README exists. Always returns markdown format.

readme_update

Post /ops/readme_update | Auth: Write

Update element README.md content

Creates or overwrites README.md in the element’s git repo. Commits to the draft branch. Content must be provided as a markdown string.

schema

Get /ops/schema | Auth: Read

Get element input/output schema (MCP tools/list compatible)

Returns type-level port schemas from the TypeRegistry — not instance-specific overrides. Includes direction (input/output), required flag, and JSON schema per port. Useful for understanding what data an element accepts and produces.

update

Patch /ops/update | Auth: Write

Update element

Partial update — send only the fields you want to change. spec, name, and intention are all independently optional. spec MUST be a JSON object when present; deep-merged into the existing spec by default. Empty {"spec":{}} preserves existing spec content but still records a new version (no-op for content, not for version state). To clear/replace the entire spec wholesale send {"spec":{...},"deep":false}. List-typed spec fields use replace semantics (the patch list replaces the existing list, no array merging). Coordinates Git + DB writes. Slug cannot be changed after creation.

Error Codes

CodeClassRetryableDescription
AUTH_REQUIREDauthnoAuthentication required
AUTH_INVALID_TOKENauthnoInvalid or expired token
AUTH_INSUFFICIENT_PERMISSIONSauthnoMissing required permissions
AUTH_INSUFFICIENT_ROLESauthnoMissing required roles

Lifecycle / runtime

Defined for this element

Execution model: sync

Observability

Defined for this element

Metrics

  • evaluation_count
  • rejection_count

Events

  • auth-policy.evaluated
  • auth-policy.rejected

Pricing / cost

Platform default

Operation costs

  • create: free
  • update: free
  • delete: free
  • get: free
  • list: free
  • invoke: 10000 micro-AU
  • tool_use: free

Set it up

Require Authenticationstring
Auth Methodsstring