Skip to content
This page was generated and translated with the assistance of AI. If you spot any inaccuracies, feel free to help improve it. Edit on GitHub

Workflow States ​

Every issue in OpenPR has a state that represents its position in the workflow. The kanban board columns map directly to these states.

OpenPR ships with four default states, but supports fully custom workflow states through a 3-tier resolution system. You can define different workflows per project, per workspace, or rely on the system defaults.

Default States ​

mermaid
graph LR
    BL["Backlog"] --> TD["To Do"]
    TD --> IP["In Progress"]
    IP --> DN["Done"]

    IP -.->|"blocked"| TD
    DN -.->|"reopened"| IP
    BL -.->|"prioritized"| IP
StateValueDescription
BacklogbacklogIdeas, future work, and unplanned items. Not yet scheduled.
To DotodoPlanned and prioritized. Ready to be picked up.
In Progressin_progressActively being worked on by an assignee.
DonedoneCompleted and verified.

These are the built-in states that every new workspace starts with. You can customize them or add additional states as described in Custom Workflows below.

State Transitions ​

OpenPR allows flexible state transitions. There are no enforced constraints -- any state can transition to any other state. Common patterns include:

TransitionTriggerExample
Backlog -> To DoSprint planning, prioritizationIssue pulled into upcoming sprint
To Do -> In ProgressDeveloper picks up workAssignee starts implementation
In Progress -> DoneWork completedPull request merged
In Progress -> To DoWork blocked or pausedWaiting on external dependency
Done -> In ProgressIssue reopenedBug regression discovered
Backlog -> In ProgressUrgent hotfixCritical production issue

Custom Workflows ​

OpenPR supports custom workflow states through a 3-tier resolution system. When the API validates a state for a work item, it resolves the effective workflow by checking three levels in order:

Project workflow  >  Workspace workflow  >  System defaults

If a project defines its own workflow, that takes precedence. Otherwise the workspace-level workflow is used. If neither exists, the four system default states apply.

Database Schema ​

Custom workflows are stored in two tables (introduced in migration 0024_workflow_config.sql):

  • workflows -- Defines a named workflow attached to a project or workspace.
  • workflow_states -- The individual states within a workflow.

Each state has the following properties:

FieldTypeDescription
keystringMachine-readable identifier (e.g. in_review)
display_namestringHuman-readable name (e.g. "In Review")
categorystringGrouping category for the state
positionintegerDisplay order on the kanban board
colorstringHex color code for the state badge
is_initialbooleanWhether this is the default state for new issues
is_terminalbooleanWhether this state represents completion

Creating a Custom Workflow via API ​

Step 1 -- Create a workflow for a project:

bash
curl -X POST http://localhost:8080/api/workflows \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "name": "Engineering Flow",
    "project_id": "<project_uuid>"
  }'

Step 2 -- Add states to the workflow:

bash
curl -X POST http://localhost:8080/api/workflows/<workflow_id>/states \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "key": "in_review",
    "display_name": "In Review",
    "category": "active",
    "position": 3,
    "color": "#f59e0b",
    "is_initial": false,
    "is_terminal": false
  }'

Example: 6-State Engineering Workflow ​

mermaid
graph LR
    BL["Backlog"] --> TD["To Do"]
    TD --> IP["In Progress"]
    IP --> IR["In Review"]
    IR --> QA["QA"]
    QA --> DN["Done"]

    IR -.->|"changes requested"| IP
    QA -.->|"failed"| IP
StateKeyCategoryInitialTerminal
Backlogbacklogbacklogyesno
To Dotodoplannednono
In Progressin_progressactivenono
In Reviewin_reviewactivenono
QAqaactivenono
Donedonecompletednoyes

Dynamic Validation ​

When a work item's state is updated, the API validates the new state against the effective workflow for that project. If you set a state key that does not exist in the resolved workflow, the API returns a 422 Unprocessable Entity error. States are not hardcoded -- they are looked up dynamically at request time.

Kanban Board ​

The board view displays issues as cards in columns corresponding to the workflow states. Drag and drop a card between columns to change its state. When custom workflows are active, the board automatically reflects the custom states and their configured order.

Each card shows:

  • Issue identifier (e.g., API-42)
  • Title
  • Priority indicator
  • Assignee avatar
  • Label badges

Updating State via API ​

bash
# Move issue to "in_progress"
curl -X PATCH http://localhost:8080/api/issues/<issue_id> \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{"state": "in_progress"}'

Updating State via MCP ​

json
{
  "method": "tools/call",
  "params": {
    "name": "work_items.update",
    "arguments": {
      "work_item_id": "<issue_uuid>",
      "state": "in_progress"
    }
  }
}

Priority Levels ​

In addition to states, each issue can have a priority level:

PriorityValueDescription
LowlowNice to have, no time pressure
MediummediumStandard priority, planned work
HighhighImportant, should be addressed soon
UrgenturgentCritical, needs immediate attention

Activity Tracking ​

Every state change is recorded in the issue's activity feed with the actor, timestamp, and old/new values. This provides a complete audit trail.

Next Steps ​

Released under the Apache-2.0 License.