> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nuon.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Operation Roles

> Assign different roles to different operations across sandbox, components, and actions.

Operation roles let you assign a specific role to each individual operation the Nuon runner performs,
such as provisioning your sandbox, deploying a component, or running an action, instead of relying on a
single all-purpose maintenance role. The result is granular, least-privilege access control with no changes
required to your customers' cloud accounts.

## Why Use Operation Roles?

Your deploy workflow might need `lambda:CreateFunction` and `lambda:UpdateFunctionCode`. Your teardown
workflow only needs `lambda:DeleteFunction`. With a shared maintenance role both permissions are always
present; with operation roles each workflow gets exactly what it needs.

Some concrete use cases:

* **Separate deploy vs teardown:** prevent accidental deletion by ensuring your deploy role cannot delete
  resources
* **Tighter sandbox permissions:** provision with a broad Terraform role and deprovision with a narrow
  destroy-only role
* **Emergency break-glass:** run a privileged action role for incident response without elevating all
  action runs
* **Audit-friendly access:** separate CloudTrail events per role make it easy to see which operation
  touched which resource

## Role Selection Precedence

When a run starts, the runner selects a role by walking this chain from highest to lowest priority:

| Priority    | Source                                                                                        | Scope         |
| ----------- | --------------------------------------------------------------------------------------------- | ------------- |
| 1 (highest) | Runtime override (`--role` flag / dashboard selection)                                        | Any operation |
| 2           | Break-glass role (`break_glass_role` field on action config, deprecated)                      | Actions only  |
| 3           | Entity role (inline `operation_roles` block or `role` field)                                  | Single entity |
| 4           | Matrix rule (`operation_roles.toml` principal + operation)                                    | App-wide      |
| 5 (lowest)  | Default role (`permissions.toml` `provision_role`, `deprovision_role`, or `maintenance_role`) | App-wide      |

The first match wins. If nothing matches the run fails.

## Defining Custom Roles

Any role used in an operation role assignment must be declared in `permissions.toml` with `type = "custom"`
so it is provisioned in the customer's CloudFormation stack:

```toml permissions.toml theme={null}
[[roles]]
type        = "custom"
name        = "{{.nuon.install.id}}-deploy-role"
description = "Role for Lambda deployments"

[[roles.policies]]
type     = "inline"
contents = """
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["lambda:CreateFunction", "lambda:UpdateFunctionCode"],
      "Resource": "*"
    }
  ]
}
"""
```

## Configuring Entity Roles

Entity roles are defined inline on the individual config file. They take precedence over matrix rules.

### Sandbox (`sandbox.toml`)

Use an `[[operation_roles]]` array to map sandbox operations to roles.

```toml sandbox.toml theme={null}
[[operation_roles]]
operation = "provision"
role      = "{{.nuon.install.id}}-sandbox-deploy-role"

[[operation_roles]]
operation = "reprovision"
role      = "{{.nuon.install.id}}-sandbox-update-role"

[[operation_roles]]
operation = "deprovision"
role      = "{{.nuon.install.id}}-sandbox-teardown-role"
```

Valid operations for sandbox: `provision`, `reprovision`, and `deprovision`.

### Components (`components/<name>.toml`)

Use the same `[[operation_roles]]` array on any component config file.

```toml components/my_lambda.toml theme={null}
[[operation_roles]]
operation = "provision"
role      = "{{.nuon.install.id}}-deploy-role"

[[operation_roles]]
operation = "reprovision"
role      = "{{.nuon.install.id}}-update-role"

[[operation_roles]]
operation = "deprovision"
role      = "{{.nuon.install.id}}-teardown-role"
```

Valid operations for components: `deploy` and `teardown`.

### Actions (`actions/<name>.toml`)

Actions use a single top-level `role` field (not an array). `break_glass_role` is deprecated and should no
longer be used.

```toml actions/db_migration.toml theme={null}
name    = "db_migration"
timeout = "10m"
role    = "{{.nuon.install.id}}-migration-role"

[[triggers]]
type = "manual"

[[steps]]
name    = "run-migration"
command = "./migrate.sh"
```

Valid operation for actions: `trigger`.

## Configuring Matrix Rules (`operation_roles.toml`)

The `operation_roles.toml` file defines app-level rules that apply across all installs. Rules are matched
by principal (which entity is performing the operation) and operation name.

Create a file named `operation_roles.toml` at the root of your app config:

```toml operation_roles.toml theme={null}
type = "matrix"

[[rules]]
principal = "nuon::component:my_lambda"
operation = "deploy"
role      = "{{.nuon.install.id}}-lambda-deploy-role"

[[rules]]
principal = "nuon::component:my_lambda"
operation = "teardown"
role      = "{{.nuon.install.id}}-lambda-teardown-role"

[[rules]]
principal = "nuon::sandbox"
operation = "provision"
role      = "{{.nuon.install.id}}-provision-role"

[[rules]]
principal = "nuon::sandbox"
operation = "deprovision"
role      = "{{.nuon.install.id}}-destroy-role"

[[rules]]
principal = "nuon::action:db_migration"
operation = "trigger"
role      = "{{.nuon.install.id}}-migration-role"
```

### Principal Format

| Entity             | Principal                |
| ------------------ | ------------------------ |
| Specific component | `nuon::component:<name>` |
| All components     | `nuon::component:*`      |
| Sandbox            | `nuon::sandbox`          |
| Specific action    | `nuon::action:<name>`    |
| All actions        | `nuon::action:*`         |

The wildcard `*` matches any entity of that type, making it easy to set a default role for all components
or all actions without listing each one.

## Role Name Templating

Role names support the same Go template syntax used elsewhere in Nuon config:

```toml theme={null}
role = "{{.nuon.install.id}}-deploy-role"
```

Common template variables:

| Variable                                       | Description                                        |
| ---------------------------------------------- | -------------------------------------------------- |
| `{{.nuon.install.id}}`                         | Install ID, ensures each install gets its own role |
| `{{.nuon.install.sandbox.outputs.<key>.name}}` | Sandbox stack output values                        |

The rendered role name must match a role defined in `permissions.toml` (either a standard role or a
`custom_roles` entry).

## Syncing with the CLI

After adding or changing operation role config, sync your app to push the updated config to Nuon:

```sh theme={null}
nuon apps sync
```

This syncs all the configs with the control plane, including `operation_roles.toml` and any inline `operation_roles` blocks.

## Runtime Role Override

You can override the role for a specific run without changing any config file.

### CLI

Pass `--role <role-name>` when triggering a sandbox or component operation:

```sh theme={null}
# Override role for a manual action run
nuon actions create-run -w <action-workflow-id> -i <install-id> --role my-custom-role
```

### Dashboard

On the install page, before triggering a run, use the role selector in the run options panel to choose an
alternative role from those available in the install's CloudFormation stack.

## Viewing Configured Roles

In the Nuon dashboard, navigate to your install and open the **Components** or **Actions** tab. Each entity
shows the currently configured role.

## Next Steps

* [Operation Roles Concepts](/concepts/operation-roles): understand the mental model and precedence chain
* [Permissions Config Reference](/config-ref/permissions): defining `provision_role`, `maintenance_role`,
  and `custom_roles`
