Skip to main content
Docs navigation

Policies & approvals

Every run dispatch passes through your account's policy before it's sent to a runner. The policy makes one of three decisions: run it, pause it for approval, or deny the execution.

How a decision is made#

Each pack action declares its risk tier — neither the caller nor the control plane can change it. A policy then decides whether the run is dispatched, paused for approval, or denied.

The policy is selected by scope, most specific first: the runner's own ruleset, then its group's, then the account default.

A policy can define per-action overrides. It walks the ordered list of action ID patterns — for example, nomad.job_* requires approval, *.delete_* denies. The first match wins, so put the most specific patterns first.

If no override matches, the action's risk tier defaults (low / medium / high / critical) make the decision. In the policy these decisions are >allow, require_approval, and deny. When the policy cannot answer — a missing policy, an unknown tier — it denies.

The shipped default.
New accounts allow low and medium risk, require approval for high, and deny critical — no overrides.

A sensible first policy#

Keep the shipped defaults, then add overrides where real use shows you need them:

  1. Run a week with the defaults. Watch the Approvals queue — the requests that keep showing up are your override candidates.
  2. Deny anything you never want an agent to touch (*.purge_*deny) — a written rule beats everyone remembering.
  3. Turn repeated approvals into expiring standing grants instead of allow overrides — a grant stays tied to one key and expires on its own.

An override can also remove waiting. Some reads are high risk because their output can leak secrets — a full config dump may contain a credential — so the shipped policy holds them for a person. If your configs hold no secrets, or the exposure is acceptable, allow the action:

Policy → overrides
overrides:
  - name: allow-journal-reads
    action: linux.journalctl*
    decision: allow
  - name: allow-nginx-config-dump
    action: nginx.config_dump
    decision: allow

Redaction still masks credential patterns it recognizes, but it can miss — treat the output as sensitive when you allow a full dump.

Editing the policy#

Open Policies in the console sidebar. Owners and admins can edit; operators and viewers can read. The editor shows the four tier menus above the ordered override list. A higher tier can never be more permissive than a lower one — the editor and the API both refuse it.

emisar console · Policy
Risk-tier defaults, the per-action override list, and approval requirements in one editor.

The preview runs your edited rules against the scope's real catalog, so you see each action's decision before saving.

Saving a change bumps the policy version and applies from the next dispatch. Every save writes an audit event, and every run records the policy version that gated it — so you can always see which rules were in force.

Scope it to a runner or group#

The default policy governs the fleet. When one runner or group needs different rules — a locked-down database host, a permissive staging group — add a targeted ruleset for it in Policies.

A ruleset replaces the default policy for its runner or group — what you see for a scope is exactly what runs there. Remove it and the scope falls back to the next-broader policy.

Pattern: let an agent iterate on staging, hands-off

Give the staging group a ruleset that sets every tier to allow with no approvals. An agent can reproduce a bug, test a fix, and verify the result without waiting — and the production change it hands you is still held for approval by your stricter default.

Approvals#

When the decision is require_approval, the run is held and an approval request is created. Owners, admins, and operators get an email with a direct link, and the request appears under Approvals in the console with a live badge.

emisar console · Approval
The approver sees the action, risk, runner, exact command, and reason, then approves or denies, optionally with a reuse window.
  • One approval releases a run by default. For destructive work, require two approvers with self-approval off — the requester cannot approve their own request.
  • If an action or pack is unavailable, the decision panel explains the block. After restoring it, choose Recheck. Your note and reuse choices stay in place. Rechecking does not approve the request or switch it to a newer pack version.
  • If the required reviewers are unavailable, an owner or admin can use Approve with override. They must give a reason; it is recorded with the decision. The exception waives the missing reviews and, when necessary, the self-approval rule; it creates no standing grant and gets its own audit record. Scope, expiry, cancellation, pack trust, dispatch signatures, initiator access, and runner admission still apply.
  • Undecided requests expire after 24 hours and the held run is cancelled.
  • An LLM waiting on an approval long-polls wait_for_run and picks the result up the moment a human decides.
  • Each vote and final decision is audited with its approver, run ID, decision, and reason. Follow the run ID for the requester, action, arguments, and dispatch reason.

Standing grants#

Approving the same nomad job revert for each of 20 allocations helps nobody. Approval applies to This run only by default. When standing grants are enabled, choose Allow the agent to reuse this approval and a duration allowed by your account so matching future calls skip the queue:

  • Scoped tight. A grant is bound to one API key and action, and optionally one runner. When you approve, choose whether it covers only these exact arguments or any arguments.
  • Capped and revocable. A grant can carry a use limit, always expires, and is listed under Approvals where you can choose Revoke and confirm to end it early. Every use is still a fully audited run.

The reason requirement#

Every dispatch — console or MCP — must include a reason. Approvers see it, and the run and audit event keep it. For an agent, the reason says why it ran nomad job revert; the action name only says what.

An MCP caller can also send evidence — prior findings or run IDs that informed the call — and expected — the outcome that confirms success. Together with the reason, they preserve what the agent saw, why it acted, and what it expected. Operator and runbook dispatches leave both empty.

Last reviewed September 8, 2026