Skip to content

Permissions

Mate uses an IAM-style permission model. Every agent declares a set of authorities it is allowed to use. At dispatch time, Mate computes the effective authority set by applying any deny rules from the trigger and from the tenant-wide configuration. The effective set determines both what the agent can do and the access level of the short-lived GitLab token minted for the job.

The effective authority set for a job is computed as:

effective = agent.permissions − trigger.deny − tenant.deny

Explicit deny at any layer always wins. If an authority is listed in trigger.deny or in the top-level tenant.deny, it is removed from the effective set regardless of what agent.permissions says. An empty effective set causes the job to be refused — an agent with no granted authorities cannot do anything meaningful.

LayerWhere it is setScope
agent.permissionsAgent definition in tenant config or .mate.ymlDefines the maximum possible set for this agent.
trigger.denyIndividual trigger entrySubtracts authorities for this trigger only. The agent’s full permissions are still used when the agent is invoked from other triggers.
tenant.denyTop-level deny: list in tenant configSubtracts authorities from every agent, for every trigger, across the entire tenant. Cannot be overridden by .mate.yml.
# tenant config
deny:
- merge # no agent may merge, tenant-wide
agents:
contributor:
permissions: [read, comment, push_branch, open_mr, merge]
triggers:
- on: issue_assigned
agent: contributor
deny: [push_branch] # this trigger: comment only, no push
- on: mr_opened
agent: contributor
# no trigger deny; effective = {read, comment, push_branch, open_mr}
# (merge was removed by tenant.deny)

For the issue_assigned trigger:

{read, comment, push_branch, open_mr, merge}
− {push_branch} # trigger.deny
− {merge} # tenant.deny
= {read, comment, open_mr}
AuthorityStatusWhat it allows
readAvailable nowRead repository content, file trees, issues, MRs, pipelines, and all other project data.
commentAvailable nowPost comments on issues and MRs.
push_branchReserved — tools not yet enabledPush commits to any branch (new or existing).
push_mr_branchReserved — tools not yet enabledPush commits to a branch. (A narrowing to the current MR’s source branch is intended but not yet enforced.)
open_mrReserved — tools not yet enabledOpen a new merge request, or update an existing MR’s title, description, or labels.
mergeReserved — tools not yet enabledMerge an open MR. Requires the MR to pass all required approvals — Mate cannot bypass them.
close_issueReserved — tools not yet enabledClose an issue.
update_issueReserved — tools not yet enabledUpdate issue fields: title, description, labels, and state.
touch_ciReserved — tools not yet enabledRetry or cancel pipeline jobs.

Any unknown authority string in permissions: or deny: is a validation error and causes the entire config to be rejected.

There is no approve_mr authority and it is not grantable. This is by design: an agent can never approve a merge request. Approvals require a human reviewer in GitLab. This is a separation-of-duties constraint — an agent that opens an MR and then also approves it would eliminate the human checkpoint that approvals are designed to enforce.

When Mate dispatches a job, it mints a short-lived GitLab project access token scoped to the minimum permissions required by the effective authority set. The access level and token scopes are derived automatically from the effective authorities:

Effective authorities includeToken scopesGitLab access level
Only readread_api, read_repositoryReporter
comment, close_issue, or update_issueapi, read_repositoryReporter
push_branch, push_mr_branch, or open_mrapi, read_repository, write_repositoryDeveloper
merge or touch_ciapi, read_repository, write_repositoryMaintainer

The highest applicable tier wins. If the effective set includes both comment and push_branch, the token is minted at Developer level.

The per-job token is the only GitLab credential the agent ever holds. It is scoped to a single project and expires when the job ends. The master GitLab token (configured in the tenant) never enters the agent container.

A per-repository .mate.yml can narrow an agent’s permissions but never expand them. The effective permissions of any repo-defined agent must be a subset of the base (tenant) agent’s permissions. Attempting to add an authority the base agent does not have is a merge-time error.

.mate.yml
agents:
reviewer:
permissions: [read, comment] # OK: subset of tenant reviewer's [read, comment, push_branch, open_mr]
# .mate.yml — this will fail
agents:
reviewer:
permissions: [read, comment, merge] # Error: merge is not in the base agent's permissions

Start with the minimum authority set your agent needs and expand only when required.

For a read-only reviewer that posts comments:

permissions: [read, comment]

For an agent that implements issues by pushing a branch and opening an MR:

permissions: [read, comment, push_branch, open_mr]

For an agent that fixes CI failures on the current MR branch:

permissions: [read, comment, push_mr_branch, touch_ci]

For an agent that manages issues (comments, updates labels, closes when done):

permissions: [read, comment, close_issue, update_issue]