Approvals dashboard
When policy resolves an action to needs_approval, Suvra creates an approval record. Reviewers work through these from /dashboard/approvals. For how the approval lifecycle, Slack notifications, and reuse integrity work, see Human approvals & Slack — this page covers the dashboard UI only.
Requires the approvals.read permission to view; approvals.decide to act.
Tabs
| Tab | Filter | Counts |
|---|---|---|
| Pending | status=pending and not expired | live count |
| Approved | status=approved | live count |
| Denied | status=denied | live count |
| All | everything (includes expired) | live count |
Each tab supports a search box (actor / action / target) and a limit control (1-500, default 100). Additional query filters: agent, environment.
Approvals table
| Column | Description |
|---|---|
| Created | UTC timestamp |
| Actor | User or agent that triggered the request |
| Action | Human-readable action title |
| Target | Path / URL / target in code format |
| Risk | Badge: low / medium / high (inferred from action type + decision) |
| Status | Badge: pending / approved / denied / expired |
| Approval ID | Truncated ID in code format |
| Actions | For pending: Approve & Execute, Approve, Deny; else "Closed" |
| Detail | Opens the detail drawer |
Detail drawer
Opens a side drawer showing:
- Decision hero with the action's risk and decision
- Summary — buyer-friendly explanation of why approval was required
- Key fields — Approval ID, Action ID, Matched Policy, Starter Pack (if any), Identity fields, Decided By, Note
- Why approval was required — bullets derived from
result_summary - Action payload — full
type+params+ identity JSON block - Drawer actions — Approve / Deny buttons (if pending and
approvals.decide)
Actions available to reviewers
Three buttons post to these CSRF-protected dashboard endpoints:
| Button | Endpoint |
|---|---|
| Approve | POST /dashboard/approvals/{approval_id}/approve |
| Deny | POST /dashboard/approvals/{approval_id}/deny |
| Approve & Execute | POST /dashboard/approvals/{approval_id}/approve_execute |
Approve records decided_by + note and flips the status — the caller still has to replay the action with meta.approval_id attached. Approve & Execute approves and immediately replays the action server-side. Deny is terminal and fails closed.
RBAC
- View tabs / drawers:
approvals.read(Viewer and above) - Approve / Deny / Approve & Execute:
approvals.decide(Operator, Policy Admin, Admin) - Viewers see the tabs read-only
Related
- Human approvals & Slack — approval lifecycle, webhooks, reuse integrity, expiration
- Audit Explorer
- Policy Model