> For the complete documentation index, see [llms.txt](https://docs.durohub.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.durohub.com/library-configuration/change-order-workflow-reference.md).

# Change Order Workflow Reference

## Overview

This document provides a complete reference for the Change Order Workflow Template YAML specification. The schema defines the structure and constraints for change order approval workflows in the Duro PLM system.

## Schema Information

* **Schema Version**: 1.0 (base) / 1.1 (adds change order types — see [Change Order Types](#change-order-types))
* **Schema URL**: [`https://phoenix-production.durohub.com/static/schemes/change-orders/schema.json`](https://phoenix-production.durohub.com/static/schemes/change-orders/schema.json)
* **Type**: Object

### JSON Schema Validation

The JSON Schema provides automated validation for your workflow templates. When editing YAML files, you can use this schema to:

* **Validate your templates** before deployment to catch errors early
* **Get auto-completion** in editors that support YAML Language Server
* **Ensure compliance** with all required fields and constraints

To use the schema in your YAML files, add this comment at the top:

```yaml
# yaml-language-server: $schema=https://phoenix-production.durohub.com/static/schemes/change-orders/schema.json
```

Many editors (VS Code, IntelliJ, etc.) will then provide real-time validation and helpful suggestions as you write your workflow templates.

## Root Level Properties

| Property          | Type   | Required  | Description                                                                                                                                         |
| ----------------- | ------ | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `version`         | string | Yes       | Schema version, quoted (e.g., `"1.0"` or `"1.1"`). Must be a string — an unquoted numeric version is rejected.                                      |
| `description`     | string | Yes       | Human-readable description (max 500 chars)                                                                                                          |
| `schema_type`     | string | Yes       | Must be `"change_order_scheme"`                                                                                                                     |
| `details`         | object | Yes       | Custom field definitions                                                                                                                            |
| `validations`     | array  | No        | Global validation rules                                                                                                                             |
| `stages`          | object | Yes       | Workflow stage configuration                                                                                                                        |
| `co_types`        | array  | v1.1 only | Change order types this template allows. Required when `version` is `"1.1"`. See [Change Order Types](#change-order-types).                         |
| `default_co_type` | string | No        | The type applied when a change order is created from this template without an explicit `coType`. Defaults to `ECO`; must be a member of `co_types`. |

### Example Root Structure

```yaml
version: "1.0"
description: "Engineering change order workflow with dual approval"
schema_type: "change_order_scheme"
details: { }
validations: [ ]
stages: { }
```

## Change Order Types

The `co_types` and `default_co_type` properties (schema version `1.1`) add two root-level fields that declare which [change order types](/core-concepts/change-orders.md#change-order-types) a template allows and which one it applies by default.

```yaml
version: "1.1"
description: "Engineering change workflow supporting ECO, ECR, and documentation updates"
schema_type: "change_order_scheme"

co_types: [ECO, ECR, DCO]
default_co_type: ECO

details: { }
stages:
  open: [ ]
```

| Property          | Type              | Required   | Description                                                                                                                  |
| ----------------- | ----------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `co_types`        | array of `CoType` | Yes (v1.1) | The types a user may choose from when creating a change order from this template. Must be non-empty. Duplicates are removed. |
| `default_co_type` | `CoType`          | No         | The type used when the creator does not pass an explicit `coType`. Defaults to `ECO`. Must be one of `co_types`.             |

### `CoType` values

| Value | Meaning                                                           |
| ----- | ----------------------------------------------------------------- |
| `ECO` | Engineering Change Order                                          |
| `MCO` | Manufacturing Change Order                                        |
| `DCO` | Documentation Change Order — **revision-frozen** (see note below) |
| `ECR` | Engineering Change Request                                        |
| `MCR` | Manufacturing Change Request                                      |
| `DCR` | Documentation Change Request                                      |
| `ECN` | Engineering Change Notice                                         |
| `MCN` | Manufacturing Change Notice                                       |
| `DCN` | Documentation Change Notice                                       |

{% hint style="info" %}
Only `DCO` alters behavior: change orders of type `DCO` never bump component revisions and cannot change a component's status or revision. All other types are classification metadata. See [Change Orders → Change Order Types](/core-concepts/change-orders.md#change-order-types).
{% endhint %}

### Rules and validation

* `co_types` and `default_co_type` are only recognized when `version` is `"1.1"`. Including them under `"1.0"` (or an unset version) is rejected (`CO_TYPES_UNSUPPORTED_IN_SCHEMA_VERSION`).
* When `version` is `"1.1"`, `co_types` is **required** and must contain at least one value (`CO_TYPES_REQUIRED_IN_SCHEMA_VERSION` / `CO_TYPES_EMPTY`).
* `default_co_type` must be a member of `co_types` (`DEFAULT_CO_TYPE_NOT_ALLOWED`). If omitted, it defaults to `ECO` — so a template that omits `default_co_type` must include `ECO` in `co_types`.
* Every entry in `co_types` and `default_co_type` must be a valid `CoType` value (`INVALID_CO_TYPE`).
* `version` must be authored as a **quoted string**. An unquoted `version: 1.1` parses as a number and is rejected (`SCHEMA_VERSION_MUST_BE_STRING`).

### Legacy (`1.0`) templates

A template without `co_types` (any `1.0` template) is treated as allowing only `ECO`, with `ECO` as the default. When queried through the GraphQL API, such a template returns `null` for both `coTypes` and `defaultCoType` — do not round-trip those nulls back into a `1.0` config on update. To offer additional types, migrate the template to `version: "1.1"` and add a `co_types` array.

{% hint style="info" %}
The built-in default templates shipped with every library ([`default.yaml`](https://phoenix-production.durohub.com/static/schemes/change-orders/default.yaml) and [`double.yaml`](https://phoenix-production.durohub.com/static/schemes/change-orders/double.yaml)) are authored at `version: "1.1"` with `co_types: [ECO]` and `default_co_type: ECO`. They are ECO-only out of the box; add other `CoType` values to `co_types` to allow them.

These templates do **not** define a `change_type` content field in `details.info.groups`. Change order type is set entirely through `co_types` / `default_co_type`; the legacy `change_type` enum that earlier templates used for this purpose has been removed. `default.yaml` now ships a *Reason for Change* field, and `double.yaml` an *Impact Analysis* group. Content fields named `change_type` remain valid as ordinary custom fields for backward compatibility, but are no longer part of the built-in defaults.
{% endhint %}

## Details Object

The `details` object contains custom field definitions organized in groups.

### Structure

```yaml
details:
  info:
    groups:
      - name: string
        icon: string (optional)
        description: string (optional)
        fields: [ ]
```

### Group Properties

| Property      | Type   | Required | Description                                    |
| ------------- | ------ | -------- | ---------------------------------------------- |
| `name`        | string | Yes      | Display name (max 100 chars)                   |
| `icon`        | string | No       | Material Design Icon (format: `mdi-icon-name`) |
| `description` | string | No       | Group description (max 500 chars)              |
| `fields`      | array  | Yes      | Array of field definitions                     |

## Field Definitions

Each field in a group has the following properties:

| Property      | Type    | Required    | Description                                             |
| ------------- | ------- | ----------- | ------------------------------------------------------- |
| `type`        | string  | Yes         | Field type (see Field Types section)                    |
| `name`        | string  | No          | Programmatic name (pattern: `^[a-zA-Z_][a-zA-Z0-9_]*$`) |
| `label`       | string  | Yes         | Display label (max 100 chars)                           |
| `description` | string  | No          | Help text (max 500 chars)                               |
| `placeholder` | string  | No          | Placeholder text (max 200 chars)                        |
| `required`    | boolean | No          | Deprecated - use `validations.required`                 |
| `validations` | object  | No          | Field validation rules                                  |
| `default`     | string  | No          | Default value (for enum fields)                         |
| `options`     | array   | Conditional | Required for list/enum types                            |
| `multiSelect` | boolean | No          | Enable multi-selection (list type only)                 |

### Field Types

| Type       | Description               | Additional Properties                |
| ---------- | ------------------------- | ------------------------------------ |
| `text`     | Single-line text input    | -                                    |
| `longtext` | Multi-line text area      | -                                    |
| `number`   | Numeric input             | `validations.min`, `validations.max` |
| `date`     | Date picker               | -                                    |
| `currency` | Currency amount           | `validations.min`, `validations.max` |
| `enum`     | Single selection dropdown | `options`, `default`                 |
| `list`     | Multiple selection        | `options`, `multiSelect`             |

### Field Validation Object

```yaml
validations:
  required: boolean
  min: integer
  max: integer
  pattern: string (regex)
```

| Property   | Type    | Applies To             | Description              |
| ---------- | ------- | ---------------------- | ------------------------ |
| `required` | boolean | All types              | Field is mandatory       |
| `min`      | integer | number, currency, text | Minimum value or length  |
| `max`      | integer | number, currency, text | Maximum value or length  |
| `pattern`  | string  | text                   | Regex validation pattern |

### Options for List/Enum Fields

```yaml
options:
  - label: string
    value: string
    description: string (optional)
```

| Property      | Type   | Required | Description                      |
| ------------- | ------ | -------- | -------------------------------- |
| `label`       | string | Yes      | Display text (max 100 chars)     |
| `value`       | string | Yes      | Stored value (max 100 chars)     |
| `description` | string | No       | Option help text (max 500 chars) |

## Validations Array

Global validation rules (currently reserved for future use).

```yaml
validations:
  - id: string
    severity: string
```

| Property   | Type   | Required | Description                           |
| ---------- | ------ | -------- | ------------------------------------- |
| `id`       | string | Yes      | Validation ID (pattern: `^\d+\.\d+$`) |
| `severity` | string | Yes      | One of: `error`, `warn`, `info`       |

## Stages Object

Defines the workflow stages and their behavior.

```yaml
stages:
  open: [ ]      # Required: Active review stages
  resolved: { }  # Optional: Resolution configuration
  closed: { }    # Optional: Closed state configuration
  onHold: { }    # Optional: On-hold state configuration
```

### Open Stages Array

Array of sequential review stages. Each stage has:

| Property       | Type    | Required | Description                                                          |
| -------------- | ------- | -------- | -------------------------------------------------------------------- |
| `name`         | string  | Yes      | Stage name (max 100 chars)                                           |
| `types`        | array   | Yes      | Available approval types                                             |
| `default`      | string  | Yes      | Default approval type                                                |
| `minReviewers` | integer | No       | Minimum reviewers required                                           |
| `reviewers`    | object  | No       | Pre-assigned reviewers (internal users)                              |
| `notifyList`   | object  | No       | Pre-assigned stage notifiers (internal users and/or external emails) |

#### Approval Types

Each stage must support one or more approval types:

| Type        | Description                          |
| ----------- | ------------------------------------ |
| `Unanimous` | All reviewers must approve           |
| `Majority`  | More than 50% must approve           |
| `Minimum`   | At least `minReviewers` must approve |

{% hint style="info" %}
The values shown here are the schema as stored and as accepted by the GraphQL API: `reviewers.users` and `notifyList.users` must be **UUID strings**. To resolve names to UUIDs, query your organization's members — see [RBAC → Get Organization Members with Roles](/advanced-topics/rbac.md#get-organization-members-with-roles). The web template editor accepts **email addresses** for internal users and resolves them to UUIDs on save, so manual lookup is only needed when authoring YAML by hand.
{% endhint %}

#### Reviewers Object

Pre-assign reviewers to a stage. Reviewers are internal users, specified as UUID strings.

```yaml
reviewers:
  users:
    - 123e4567-e89b-12d3-a456-426614174001
    - 123e4567-e89b-12d3-a456-426614174002
```

| Property | Type             | Required | Description                                                          |
| -------- | ---------------- | -------- | -------------------------------------------------------------------- |
| `users`  | array of strings | Yes      | Internal user UUIDs (format: `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`) |

**Note**: Each entry must be a UUID string referencing an existing user in the library's organization. External email addresses are not allowed here — use `notifyList.emails` instead. Duplicate IDs within a stage are automatically deduplicated.

#### NotifyList Object

Pre-assign notifiers to a stage. Notifiers are added to the stage's notify list when the change order is created but do not participate in the approval process. A notify list can include internal users, external email addresses, or both.

```yaml
notifyList:
  users:
    - 123e4567-e89b-12d3-a456-426614174003
  emails:
    - supplier@example.com
```

| Property | Type             | Required | Description                                                            |
| -------- | ---------------- | -------- | ---------------------------------------------------------------------- |
| `users`  | array of strings | No       | Internal user UUIDs (format: `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`)   |
| `emails` | array of strings | No       | External recipient email addresses (for people without a Duro account) |

**Note**: Provide `users`, `emails`, or both. `users` follows the same UUID and organization-membership rules as `reviewers.users`; `emails` accepts any well-formed address and is not checked against the organization.

### Stage Actions (resolved, closed, onHold)

```yaml
resolved:
  actions: [string]
  resolutions:
    onapproval: [string]
    onrejection: [string]
    onwithdrawal: [string]
```

#### Resolution Types

| Value          | Description                        |
| -------------- | ---------------------------------- |
| `AUTO_CLOSE`   | Automatically transition to closed |
| `MANUAL_CLOSE` | Require manual closure             |

## Complete Example

```yaml
version: "1.0"
description: "Medical device change control workflow"
schema_type: "change_order_scheme"

details:
  info:
    groups:
      - name: "Change Classification"
        icon: "mdi-medical-bag"
        fields:
          - name: "change_category"
            type: "enum"
            label: "Change Category"
            options:
              - label: "Design Change"
                value: "design"
                description: "Modifications to product design"
              - label: "Process Change"
                value: "process"
                description: "Manufacturing process updates"
            default: "design"
            validations:
              required: true
          
          - name: "risk_level"
            type: "list"
            label: "Risk Categories"
            multiSelect: true
            options:
              - label: "Patient Safety"
                value: "safety"
              - label: "Product Performance"
                value: "performance"
              - label: "Regulatory Compliance"
                value: "regulatory"

      - name: "Impact Assessment"
        icon: "mdi-chart-line"
        fields:
          - name: "validation_required"
            type: "enum"
            label: "Validation Required"
            options:
              - label: "Full Validation"
                value: "full"
              - label: "Partial Validation"
                value: "partial"
              - label: "No Validation"
                value: "none"
            validations:
              required: true

stages:
  open:
    - name: "Engineering Review"
      types: ["Unanimous"]
      default: "Unanimous"
      minReviewers: 2
      reviewers:
        users:
          - 123e4567-e89b-12d3-a456-426614174001
          - 123e4567-e89b-12d3-a456-426614174002
      notifyList:
        users:
          - 123e4567-e89b-12d3-a456-426614174003
        emails:
          - supplier@example.com

    - name: "Quality Review"
      types: ["Unanimous", "Majority"]
      default: "Unanimous"
      minReviewers: 1
      reviewers:
        users:
          - 123e4567-e89b-12d3-a456-426614174004

  resolved:
    resolutions:
      onapproval: ["AUTO_CLOSE"]
      onrejection: ["MANUAL_CLOSE"]

  closed: {}
```

## Validation Rules

The schema enforces these validation rules:

1. **Required Fields**: All fields marked as required must have values
2. **Pattern Matching**: Field names must match `^[a-zA-Z_][a-zA-Z0-9_]*$`
3. **Length Limits**:
   * Descriptions: 500 characters
   * Labels/Names: 100 characters
   * Placeholders: 200 characters
4. **Type Constraints**:
   * List/Enum fields must have at least one option
   * Only list fields can use `multiSelect`
5. **Stage Requirements**:
   * At least one open stage is required
   * Each stage must have a name, types array, and default type
   * Default type must be in the types array
6. **Participant Constraints**:
   * `reviewers.users` and `notifyList.users` must be arrays of UUID strings
   * Each user must exist in the system and belong to the library's organization
   * `notifyList.emails` accepts external email addresses and is not validated against the organization
   * Invalid participants are rejected at template upload

## Best Practices

1. **Use Semantic Names**: Choose descriptive names for fields and stages
2. **Provide Descriptions**: Help users understand field purposes
3. **Set Appropriate Validations**: Use min/max for numeric fields
4. **Configure Notifications**: Ensure stakeholders are informed
5. **Test Workflows**: Validate all paths through your workflow
6. **Version Control**: Track changes to workflow templates
7. **Document Decisions**: Use the description field to explain workflow design choices


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.durohub.com/library-configuration/change-order-workflow-reference.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
