- Who is requesting access: a user, group, agent, service account, or userset.
- What they are accessing: a project, room, repository, feed, secret, service account, or other project resource.
- Which role they have on that resource.
- Which room API scope a participant token carries after access is granted.
Principals
Anonymous website access
Grant a resource role toeveryone:all through its permissions dialog or the CLI:
thread_isolation: participant for anonymous connections; global thread sharing
cannot provide private visitor conversations.
On a website bound to a room or agent, send a POST to
/.well-known/meshagent/authorize. Requests are same-origin by default. To allow
cross-origin callers, include their exact origins (or * for all origins) in the
route’s existing paths[].targetContent.cors[].allowedOrigins lists. The
endpoint uses the combined origin lists across content paths; no separate
authorization origin setting is needed. Content allowedMethods do not restrict
the authorization POST. The response includes a short-lived jwt,
expires_in, and connect_path for the room or agent WebSocket. The server sets
an HttpOnly browser cookie to retain the anonymous identity across visits. Keep
the cookie when renewing credentials. Clearing it creates a new identity.
The TypeScript and Dart SDKs handle this exchange through
RoomClient.withAnonymous() and WebSocketChatClient.withAnonymous(). Call
start() as usual. They obtain fresh credentials before the initial connection
and every reconnect, using the same anonymous cookie. An open WebSocket is not
interrupted when its connection token expires. Outside a browser, pass an absolute
authorizationUrl; native clients retain the cookie for the provider’s lifetime.
For custom authentication, the existing WebSocket clients accept a tokenProvider
callback in TypeScript or an AccessTokenProvider in Dart.
Authorization and connection paths must reach the router without CDN caching.
The server checks the current Everyone permissions when issuing and validating
credentials. Browser sessions can be revoked, and credentials stop working if
the site is rebound to another resource. The visitor ID is not itself a credential.
Resources
Project Roles
Project roles apply at the project level. The user who creates a project becomes itsowner and automatically inherits admin access. Admins inherit user_profile_editor along with the other administrative project permissions. developer inherits a focused operational subset and does not include user_profile_editor. Direct, narrower roles can also be granted independently.
Project role guards enforce the requested effective role for both users and service accounts. A valid service-account credential alone does not authorize project operations: the caller needs the applicable creator, inventory, manager, member, billing, or other role, directly or through inheritance. OAuth credentials must also satisfy the endpoint’s scope requirement; native API keys do not carry OAuth scopes. Roles are checked on each request, including when the API-key identity is cached, so revoking a role removes the corresponding access.
This includes API-key listing and revocation (api_key_inventory and api_key_manager), service-account creation and management, custom-domain creation, and project feed inventory. Service-account feed listings require feed_inventory even when view is omitted or set to my. Default service-account grants are unchanged, but operations outside those grants now require explicit delegation.
Project IAM policy operations require the caller’s effective project admin role. Managing project groups and their membership requires group_manager, which admins inherit. These checks apply to service-account API keys as well as users; service-account OAuth tokens also require the admin scope. Default service accounts have neither administrative role and cannot assign themselves project roles or add themselves to privileged groups. An authorized administrator must delegate these permissions. Treat group_manager as privileged access: it permits changing membership in groups that may carry project admin or API-key roles.
Policy operations on a service_account resource require the caller’s effective project service_account_manager role and, for OAuth credentials, the developer scope. This prevents default service accounts from assigning themselves run_service_as on another account. A delegated policy manager can grant run-as access to any service account in the project, including an administrator, so this role also carries sensitive delegation authority.
Project membership APIs accept a
roles list. The server normalizes project membership to include member and expands inherited admin and developer roles. Older member records and Studio convenience settings map to roles like this:
User profile permissions
Users can edit their own global names and metadata withprofile:write. Project roles cannot edit global account defaults. Global annotations and editing other accounts require sysadmin endpoints, the OAuth sysadmin scope, and registered sysadmin membership.
Editing any project-local user profile, including your own, requires user_profile_editor, a token covering the project with projects:iam.write, and target membership. The legacy admin scope is accepted in place of projects:iam.write. Owners and admins inherit the editor permission; developers and ordinary members need an explicit grant.
Project profile reads and listings accept --view project|user|merged (default merged). All views require project access; project returns stored overrides, user returns global defaults, and merged applies overrides to defaults. Metadata and annotations merge by key.
MESHAGENT_PROJECT_ID or the active project. Use --global for personal account defaults. Without a project, ordinary profile commands address only your own global profile. Supplied maps replace the selected layer’s map; {} clears it. --inherit removes a project override and can be repeated. Annotations require string values. Global annotations can only be changed with sysadmin user update.
Sysadmin CLI commands require a login token containing sysadmin. For a dedicated administrator login, use MESHAGENT_OAUTH_SCOPES='profile:read profile:write sysadmin' meshagent auth login. Registered sysadmin membership is still required; adding the scope does not grant that membership.
See User profiles in the REST API for SDK examples, or Editing user profiles in Accounts for the app workflow.
Room, Agent, and Repository Roles
These roles apply to resource policies for rooms and repositories. They also describe the effective role set used for room and agent access decisions.
For rooms,
viewer, operator, developer, and admin map to room API scopes:
Group Roles
Feed Roles
Secret Roles
Service Account Roles
OAuth Scopes
OAuth scopes are token scopes, not OpenFGA resource roles. MeshAgent accepts the current scope names below for OAuth access tokens. Project and room wildcard scopes (project/*, room/*) still identify the project or room boundary for token checks.
Current tokens also accept compatibility aliases used by older clients, such as
profile, create_rooms, connect_room, managed_agents, llm_proxy, developer, and admin, when they map to the current scope names.
Effective Permissions
Effective permissions are the checks MeshAgent evaluates after combining direct resource roles with inherited project roles. You do not assign these directly; you grant the roles that satisfy them.Room API Scope Permissions
Room API scopes are embedded in participant tokens. They are not project roles. They control what a connected participant can call inside a room. If a grant object is absent, that API surface is denied. When a grant object exists,None in an allowlist generally means unrestricted access within that grant, and a boolean set to false disables that operation.
livekit
queues
messaging
dataset
If
dataset.tables is None, the participant may read, write, and alter every dataset table allowed by the grant.
sqlite
If
sqlite.databases is None, the participant may use all SQLite databases allowed by the grant. If a matching database grant has tables: None, table read, write, and alter access applies to all tables in that database.
memory
If
memory.memories is None, the participant may use all memories allowed by the grant.
sync
If
sync.paths is None, the participant may read and write all sync paths allowed by the grant.
storage
If
storage.paths is None, the participant may read and write all storage paths allowed by the grant.
containers
If
containers.registry is absent, registry list, pull, run, and write checks allow any repository covered by the container grant.