Skip to main content
Murmur uses a catalog-based authorization model. Org admins get full access by default. For finer control, define roles, create groups, and bind them to users. This page explains the permission system end to end.

Default access

Out of the box, Murmur provides two levels of default access based on GitHub org membership: These defaults work for most teams. The authorization system described below lets you customize access when you need finer control.

Built-in grants

A few capabilities come from built-in platform bindings rather than your own configuration:
  • Change-request proposals. Every org member, every service profile, and every agent runtime VM can propose, discover, and endorse change-requests (change-request.create, change-request.list, change-request.read, change-request.endorse). Endorsing is an advisory thumbs-up only — it never approves a change, and approving still requires permission to write the target resource directly.
  • Agent persona reads. Agent runtime VMs can read and list their tenant’s agent-persona catalog (agent-persona.read, agent-persona.list) so a running agent can resolve the persona it operates under. They cannot create, edit, or delete personas.
  • Knowledge. Members, service profiles, and agent runtime VMs hold knowledge.*, so agents can read fleet lore and author corrections directly. The injection configuration (knowledge-config.*) stays admin-only.
  • Agent peers. An agent runtime VM can view and list the other agents its own owner owns in its own workspace (agent.read, agent.list), so a running agent can see the work happening alongside it. Agents owned by anyone else — another developer, a service profile — and agents in other workspaces stay invisible to it, and it gets no ability to change any of them. To open a read edge between two workspaces of the same owner, create a tenant-binding whose grant names the reading agents (users: ["agent-runtime:{provider}/{org}/w/{reader workspace}/{owner provider}/{account}/*"]) and whose name_pattern names the target workspace ({owner provider}/{account}/w/{target workspace}/*). Deleting that binding closes the edge immediately — running agents do not need to be restarted.

Permission model

Permissions are expressed as {kind}.{verb} strings. A permission grants the ability to perform a specific verb on a specific resource kind.

Kinds

Kinds correspond to catalog resource types and platform operations: agent, secret, user-secret, placement, environment, workspace, pool-config, machine-type, image, recipe, repo-config, agent-persona, flight, change-request, user, role, group, tenant-binding, alias, service-profile

Verbs

Examples

Wildcards

Wildcards let you grant broad permissions concisely: Wildcard permissions are resolved at authorization time. If a new kind or verb is added, existing wildcards automatically cover it.

Roles

Roles are catalog resources of kind role. A role defines a named set of permissions:

Example roles

Observer (read-only)

Grants read and list access on all resource kinds. Cannot spawn agents, modify resources, or access secret values.

Developer

Grants the ability to spawn and manage agents, read secrets, and manage personal user-secrets. Cannot modify infrastructure resources or authorization configuration.

Admin (full access)

Grants all permissions. Equivalent to org admin default access.

Groups

Groups organize users for bulk role assignment. Groups are catalog resources of kind group:

Group sources

Dynamic sources (github_admin, all_tenant_members) automatically update as org membership changes — no manual member management required.

Tenant bindings

Tenant bindings connect users or groups to roles. They are catalog resources of kind tenant-binding:

Binding a user directly

Binding a group

This gives every org member the observer role’s permissions in addition to their default access.

Per-resource grants

For fine-grained control, you can attach permissions directly to individual catalog resources. Per-resource grants restrict who can modify specific resources without affecting access to other resources of the same kind.
This means only members of platform-admins can modify the production-placement resource, even if other users have general placement.edit permission.

Name patterns

Grants can include a name_pattern that restricts the grant to resources whose name matches the pattern. This is how Murmur implements self-scoped access — a developer can manage their own secrets without accessing anyone else’s.

Variables

Matching

  • Exact match — the resolved pattern must equal the resource name
  • Prefix match — a trailing * matches any resource name starting with the prefix

Examples

When alice (authenticated via github_oauth) calls the API, the pattern resolves to github_oauth/alice/* — she can access github_oauth/alice/GH_TOKEN but not github_oauth/bob/GH_TOKEN.
This resolves to an exact match — alice can access github_oauth/alice and nothing else.

Checking permissions

Use the CLI to check what permissions you have:

Authorization flow

When an API request arrives, the authorization system evaluates permissions in this order:
  1. Identify the caller — extract identity from the token (user, agent, or service).
  2. Resolve memberships — determine which groups the caller belongs to.
  3. Collect grants — gather all role bindings (tenant-wide + per-resource) that apply to the caller.
  4. Flatten permissions — expand wildcards and merge all permission sets.
  5. Check — verify that the required {kind}.{verb} permission exists in the flattened set.
  6. Allow or deny — if the permission is present, allow; otherwise, deny with a descriptive error.
Default org admin and org member access is applied before custom roles. Custom roles add to (not replace) the defaults.