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

# Approval rounds

> Create and manage sequential approval rounds on tickets with configurable policies, threshold rules, approver management, and admin controls.

Approval rounds are the building blocks of ticket approvals. Each round defines a set of approvers and a policy that determines when the round is complete. Add a single round for simple approvals or chain multiple rounds for multi-stage workflows.

## Mental model

Approval rounds are a linked list of approval stages on a ticket. Each round has a policy, a set of approvers, and a status. The system evaluates the policy after each approver action and advances through the chain automatically.

***

## Round data model

| Field              | Type                                                | Description                                    |
| ------------------ | --------------------------------------------------- | ---------------------------------------------- |
| `name`             | String (nullable)                                   | Display name for the round                     |
| `policy`           | ANY, ALL, MAJORITY, THRESHOLD                       | Determines completion criteria                 |
| `status`           | PENDING, ACTIVE, APPROVED, DECLINED, RESET, SKIPPED | Current round state                            |
| `threshold`        | Integer (nullable)                                  | Required approval count for THRESHOLD policy   |
| `nextRoundId`      | String (nullable)                                   | Links to the next round in sequence            |
| `resetFromRoundId` | String (nullable)                                   | Links to the round this replaced (after reset) |
| `openedAt`         | DateTime (nullable)                                 | When the round was activated                   |
| `closedAt`         | DateTime (nullable)                                 | When the round completed                       |

***

## Approver data model

| Field         | Type                        | Description                |
| ------------- | --------------------------- | -------------------------- |
| `userId`      | String                      | The approver's user ID     |
| `status`      | PENDING, APPROVED, DECLINED | Approver's decision status |
| `reason`      | String (nullable)           | Decline reason             |
| `completedAt` | DateTime (nullable)         | When the decision was made |
| `deletedAt`   | DateTime (nullable)         | Soft delete timestamp      |

***

## Policy evaluation logic

Policy evaluation happens after each approver action (approve, decline, or remove):

**ANY policy:**

* At least one APPROVED approver → round APPROVED
* Any DECLINED approver → round DECLINED

**ALL policy:**

* All approvers APPROVED → round APPROVED
* Any DECLINED approver → round DECLINED

**MAJORITY policy:**

* More than half of approvers APPROVED → round APPROVED
* Any DECLINED approver → round DECLINED

**THRESHOLD policy:**

* N or more APPROVED approvers → round APPROVED
* Impossible to reach N (remaining pending + already approved \< threshold) → round DECLINED

After round completion:

* If `nextRound` exists → activate it (set status to ACTIVE, set `openedAt`)
* If no next round → set ticket `approvalStatus` to APPROVED or DECLINED

***

## Sidebar focus logic

The sidebar shows the "focused" round, determined by priority:

1. Active round (status = ACTIVE)
2. Most recently declined round
3. Last round if all are approved
4. First pending round

When approvers are added via the sidebar with no existing rounds, the system auto-creates a round with ANY policy.

***

## Reset behavior

**Single round reset:**

1. Original round status set to RESET
2. New round created with `resetFromRoundId` pointing to the original
3. New round is inserted into the linked list at the same position
4. New round is set to ACTIVE
5. Carried-over approvers are re-notified

**Full approval reset:**

1. All non-reset rounds are archived (status = RESET)
2. New rounds created matching the original chain
3. First round activated, ticket status set to IN\_PROGRESS

***

## Workflow integration

The "Add Approvers" workflow action creates a round at the **head** of the linked list:

* If rounds already exist: new round becomes the first round, ticket status resets to IN\_PROGRESS
* If no rounds: creates round and kicks off approval
* Supports assignment strategies: All (all users), Round Robin (one user), Auto (system bot auto-approves)

The "Wait for Approval" action pauses until the ticket's approval status changes from IN\_PROGRESS or the configured timeout (default 3 days) expires. The action branches into three outcome paths — On Approved, On Declined, and On Timeout — so workflows can escalate or auto-close stalled approvals.

***

## Constraints and gotchas

* Only one round can be ACTIVE at a time.
* Rounds require at least one approver.
* Removing the last approver from a round deletes the round (via sidebar).
* Removing approvers triggers immediate policy re-evaluation, which can auto-complete the round.
* Reset preserves audit history. Reset rounds (status = RESET) are hidden from the UI but remain in the database.
* The linked-list structure means round ordering is stored via `nextRoundId` references, not an `order` column.
* `sourceTemplateRoundId` tracks which template round generated each ticket round (for lineage).
