The handbook
TenantsUsers and rolesApplicationsScopesAgentsContext (graphium)CultivatorsChatsTracingAudit log
Concepts

Concepts: Scopes

A scope is the unit of authorization throughout AcasoOS — a colon-delimited string such as users:read or agents:team-finder:run. Every privileged endpoint, RLS policy, and tool call resolves yes/no against the caller's effective scope set using one segment-wise matching rule.

Anatomy

namespace : resource ( : action )?

Examples:

  • users:readlist and view users.
  • agents:team-finder:runrun the agent named team-finder.
  • team:engineeringa tenant-specific scope.
  • acaso_os:adminthe super-scope.

The full canonical catalog is served by GET /v1/scopes/catalog and rendered in the Role editor's picker. See Reference: Scope catalog for the v1 list.

Segment-wise matching

A holder scope matches a required scope when each segment matches. A * segment is a single-segment wildcard.

RequiredHolderResult
context:readcontext:readmatch
team:engineeringteam:*match
team:engineering:seniorteam:*no match (segment count differs)
anythingacaso_os:adminmatch (short-circuit)
context:read*no match (bare * is rejected at write time)

acaso_os:admin short-circuits to true against any required scope. Bare * is rejected at write time so nobody can grant unbounded access by accident.

The same algorithm runs in Postgres (acaso_scope_matches_one, acaso_scopes_match) for RLS policies and in Python (acaso_shared.auth.scope_matching) for tool and agent listing filters. A parity test keeps the two in sync. The same matching also bounds an application's scope_ceiling — see Concepts: Applications.

Where scopes are checked

Scopes gate four surfaces, each independently:

Sidebar visibility

Nav items declare requiredScopes and are hidden when the active connection's effective_scopes does not satisfy them.

Page direct access

Routes render an "Insufficient permissions" empty state rather than issue a request that would 403.

RLS policies

Tenant-scoped tables have tenant_and_scope_isolation. A row gated by required_scopes is invisible to a caller whose session scopes do not match.

Tool invocation

Agent.required_scopes and @tool(required_scopes=...) both gate the LLM's tool list AND re-check at call time. Double lock.

Custom scopes

Tenant-specific scopes such as team:engineering or project:atlas live outside the canonical catalog. Add them to roles via the Role editor's free-form chips input. The matching rules apply identically; the catalog is just reference metadata for the picker.

Note: Custom scopes are syntax-validated as lowercase segment-wise strings. Bare * is rejected at every write surface.

PreviousConceptsApplicationsNext ConceptsAgents