CPN Schema Reference
Overview
This document provides a complete reference for the CPN (Customer Part Number) Schema YAML specification. The schema defines the structure and constraints for CPN generation schemes in the Duro PLM system.
Schema Information
- Schema Version: 1.0 
- JSON Schema: - https://json-schema.org/draft-07/schema#
- Type: Object 
Root Level Properties
version
string
Yes
Version of the CPN schema. Must match pattern ^\d+\.\d+$
schema_type
string
Yes
Must be "id_generation_scheme"
settings
object
Yes
Global settings for CPN generation
elements
array
Yes
Array of element definitions
examples
array
Yes
Array of example CPNs that follow the scheme
Settings Object
The settings object contains global configuration options for CPN generation.
settings:
  allow_override: boolean      # Default: false
  allow_freeform: boolean      # Default: false
  override_elements: [string]  # Default: null (all elements)
  freeform_validation:         # Optional, only used when allow_freeform is true
    pattern: string            # Regex pattern for validation
    max_length: integer        # Maximum character length
    description: string        # Human-readable format descriptionallow_override
boolean
No
false
Whether manual CPN override is allowed. If false, the user must always accept the system-generated CPN. If true, the user may enter another CPN (see allow_freeform for rules).
allow_freeform
boolean
No
false
Defines how overrides behave. If false, overrides must still conform to the YAML scheme's format and validation rules. If true, overrides may be any unique valid string.
override_elements
array
No
null
Array of element names that can be overridden individually. Only applies when allow_override is true. See "Element-Level Override Control" section below for details.
freeform_validation
object
No
-
Custom validation rules for freeform overrides. Only applies when allow_freeform is true. If not provided, defaults to alphanumeric characters, hyphens, and underscores with 50 character limit.
Freeform Validation Object
When allow_freeform is true, you can optionally specify custom validation rules:
pattern
string
No
Regex pattern that freeform CPNs must match. If not specified, uses default pattern ^[a-zA-Z0-9\-_]+$
max_length
integer
No
Maximum length for freeform CPNs. If not specified or ≤ 0, defaults to 50 characters
description
string
No
Human-readable description of the format requirements shown to users
Freeform Validation Examples
Basic freeform with default validation:
settings:
  allow_override: true
  allow_freeform: true
  # Uses default pattern ^[a-zA-Z0-9\-_]+$ with 50 character limitCustom pattern for company naming convention:
settings:
  allow_override: true
  allow_freeform: true
  freeform_validation:
    pattern: "^[A-Z]{2,4}-\\d{4,6}$"
    max_length: 20
    description: "Format: 2-4 letters, hyphen, 4-6 digits"Flexible pattern with length limit:
settings:
  allow_override: true
  allow_freeform: true
  freeform_validation:
    pattern: "^[A-Z][A-Z0-9\\-_]*$"    # Must start with uppercase letter
    max_length: 25
    description: "Must start with uppercase letter, followed by letters, numbers, hyphens, or underscores"Element-Level Override Control
The override_elements setting provides granular control over which specific elements in your CPN scheme can be overridden by users. This is useful when you want to allow customization of only certain parts of the CPN while keeping others fixed.
Override Elements Behavior
null (default)
All elements are overrideable when allow_override is true
["element1", "element2"]
Only the specified elements can be overridden
Override Elements Examples
Allow override of specific elements only:
settings:
  allow_override: true
  allow_freeform: false
  override_elements: ["variant"]  # Only variant can be overridden
elements:
  - type: "list"
    name: "category"
    # ... category element (NOT overrideable)
  - type: "numeric_counter" 
    name: "sequence"
    # ... sequence element (NOT overrideable)
  - type: "list"
    name: "variant"
    values: ["A", "B", "C"]
    # This variant element CAN be overriddenAllow all elements to be overridden (default behavior):
settings:
  allow_override: true
  # override_elements not specified = all elements overrideableBehavior Matrix
false
false
ignored
User must accept the system-generated CPN. No manual input allowed.
false
true
ignored
Same as above — allow_freeform has no effect when allow_override is false.
true
false
null (default)
User may override entire CPN or individual elements, but values must conform to YAML scheme rules.
true
false
["element1"]
User may override only specified elements. Values must conform to each element's validation rules.
true
true
null (default)
User may override with freeform text OR override individual elements. Freeform validates against global freeform_validation.
true
true
["element1"]
User may override with freeform text OR override specified elements with their element-level rules.
Elements
The elements array contains definitions for each component of the CPN. Each element must be one of the following types:
- list— selects a value from a predefined list or reference
- constant— inserts a fixed value such as a delimiter or prefix
- numeric_counter— generates sequential numeric integer values within a range
- hex_counter— generates sequential hexadecimal values within a range
- free— allows user‑entered free‑form text validated by a regex and max length
- group— bundles multiple elements into a single logical unit
Common Element Properties
All elements include these base properties:
type
string
Yes
Element type identifier (e.g., list, constant, numeric_counter, etc.).
name
string
Yes
Unique name for the element.
required
boolean
No
Whether the element must appear in every generated CPN. Defaults to false.
allow_freeform
boolean
No
Whether this element accepts freeform values beyond its defined constraints when overridden. Defaults to false. Only applies when the element is listed in override_elements.
freeform_validation
object
No
Custom validation rules for element-level freeform overrides. Only applies when allow_freeform is true for this element.
attachedTo
array
No
Names of one or more elements that this element is scoped to. Ensures values are unique within the context of the attached element(s).
About type
typeSpecifies what kind of element is being defined. Must be one of: list, constant, numeric_counter, hex_counter, free, or group. This property determines how the element behaves in generation.
About name
nameA unique identifier for the element. This is used internally to reference the element (e.g., in attachedTo) and must be unique within the scheme. Names should be descriptive (e.g., prefix, sequence, variant) and not include spaces.
About required
requiredIndicates whether the element must be present in every generated CPN.
- If - true, the element is always included.
- If - false, the element may be omitted (e.g., optional group for free‑form suffixes).
Defaults to false if not specified.
About allow_freeform (Element-Level)
allow_freeform (Element-Level)When an element has allow_freeform: true and is listed in the override_elements array, users can provide custom values that go beyond the element's normal constraints. For example, a list element with values ["A", "B", "C"] could accept "Z" as an override if allow_freeform: true.
- If - true, the element accepts freeform values when overridden (validated against- freeform_validationif provided)
- If - falseor omitted, the element only accepts values that conform to its type-specific rules
- Only applies when the element is included in - settings.override_elements
About freeform_validation (Element-Level)
freeform_validation (Element-Level)Provides custom validation rules for individual element freeform overrides, following the same structure as global freeform_validation:
freeform_validation:
  pattern: "^[A-Z]{1,3}$"        # Regex pattern
  max_length: 10                 # Maximum character length  
  description: "1-3 uppercase letters"  # User-friendly descriptionIf not provided, defaults to the same pattern as global freeform validation (alphanumeric, hyphens, underscores, 50 character limit).
About attachedTo
attachedToThe attachedTo property is commonly used with counters and variants to ensure that their values remain unique within the context of one or more parent elements. For example, a sequence counter attached to a prefix will generate independent sequences for each prefix value. This prevents conflicts across different contexts without forcing a single global sequence. Multiple attachments are supported (e.g., ['prefix', 'sequence']), allowing values to be scoped by combinations of elements when needed.
Example
- type: "numeric_counter"
  name: "sequence"
  required: true
  attachedTo: ['prefix']
  format:
    min_value: 1
    max_value: 9999List Element
A list element allows selection from a predefined set of values. It’s typically used for intelligent schemes where the CPN prefix or another segment is determined by categories, part families, or other fixed options.
Values can be defined inline as strings, as objects with metadata, or pulled dynamically using template references. Optionally, a regex validation pattern can be applied for additional checks.
- type: "list"
  name: string
  required: boolean
  allow_freeform: boolean
  freeform_validation:
    pattern: string
    max_length: integer
    description: string
  use: string
  values: (string[] | object[] | template_string)
  validation:
    pattern: stringvalues
array|string
Yes
Array of values or template reference
allow_freeform
boolean
No
Whether to accept freeform values beyond the list when overridden
freeform_validation
object
No
Custom validation for element-level freeform values
validation.pattern
string
No
Regex pattern for additional validation of list values
Values need to be one of:
- Array of strings 
- Array of objects with - id,- name, and optional- description
- Template reference in format - ${{namespace.field}}
List Element Examples
- type: "list"
  name: "category"
  required: true
  values:
    # Simple string array
    - "410"
    - "591"
    - "423"
  # OR object array with metadata
  use: "id"  # Optional: use when values have id/name pairs
  values:
    - id: "410"
      name: "Screws"
      description: "Mechanical fasteners"
    - id: "591"
      name: "Resistors"
      description: "Electronic components"
  # OR reference to system values
  values: ${{ duro.categories }}
  validation:
    pattern: "^\\d{3}$"  # Optional regex pattern
# Element-level freeform override example
- type: "list"
  name: "variant"
  required: true
  values: ["A", "B", "C"]
  allow_freeform: true
  freeform_validation:
    pattern: "^[A-Z]{1,3}$"
    max_length: 3
    description: "1-3 uppercase letters"
  # Users can select A, B, C OR enter custom values like "Z", "XY", "ABC"Constant Element
Constants are fixed values that are injected into every generated CPN. They can be used for delimiters (such as - or .), prefixes, or any string that should always appear in the same position. A constant can be any string length.
- type: "constant"
  name: string
  required: boolean
  value: stringvalue
string
Yes
The constant value
Constant Element Example
- type: "constant"
  name: "separator"
  required: true
  value: "-"This inserts a dash (-) as a separator between other CPN elements.
- type: "constant"
  name: "prefix"
  required: true
  value: "TMP-"This ensures every CPN begins with the prefix TMP-, e.g., TMP-10001.
Numeric Counter
A numeric counter generates sequential numbers within the specified range. It is always fixed length, determined by the number of digits in format.max_value, and the system automatically prepends leading zeros to match that length.
- type: "numeric_counter"
  name: string
  required: boolean
  attachedTo: string[]
  format:
    min_value: integer
    max_value: integerattachedTo
array
No
Names of elements this counter is attached to
format.min_value
integer
Yes
Minimum value (must be ≥ 0)
format.max_value
integer
Yes
Maximum value
Numeric Counter Example
- type: "numeric_counter"
  name: "sequence"
  required: true
  attachedTo: [category]
  format:
    min_value: 1
    max_value: 99999This numeric counter generates a 5‑digit sequence ranging from 00001 to 99999. The length is determined by the number of digits in max_value (here, 5 digits). Leading zeros are automatically prepended so that every value is fixed length.
Because in this example the counter is attached to the prefix element, its sequence is tracked separately for each prefix value. This ensures uniqueness within the context of the prefix, rather than across all CPNs.
For example:
- First three CPNs for prefix - 100:- 100-00001
- 100-00002
- 100-00003
 
- Then the first CPN for prefix - 101:- 101-00001
 
- Returning to prefix - 100, the next generated CPN continues from its own sequence:- 100-00004
 
Hex Counter
A hex counter generates sequential values in hexadecimal within the specified range. It is always fixed length, determined by the number of digits in format.max_value, and the system automatically prepends leading zeros to match that length.
type: "hex_counter"
name: string
required: boolean
attachedTo: string[]
format:
  min_value: string
  max_value: stringattachedTo
array
No
Names of elements this counter is attached to
format.min_value
string
Yes
Minimum value in hex (pattern: ^[0-9A-F]+$)
format.max_value
string
Yes
Maximum value in hex (pattern: ^[0-9A-F]+$)
Hex Counter Example
2‑Digit Hex Sequence
- type: "hex_counter"
  name: "sequence"
  required: true
  attachedTo: [category]
  format:
    min_value: "0"
    max_value: "FF"Generates values like 00, 01, … FE, FF. Always fixed at 2 hex digits with zero padding.
Group Element
Groups allow you to combine multiple elements into a single logical unit. They are especially useful for creating more complex structures and, when used with attachedTo, can make the scoping of values clearer and less error‑prone.
A common pattern is grouping a prefix and a sequence into a base_cpn group, so that a variant can attach to the group instead of attaching separately to both prefix and sequence. This ensures that the variant’s values are tracked in the context of the complete base number, improving clarity and reducing ambiguity in the YAML configuration.
type: "group"
name: string
required: boolean
elements: arrayelements
array
Yes
Array of nested element definitions
Group elements can contain any other element type, including:
- List elements 
- Constant elements 
- Free text elements (only available within groups) 
- Numeric counters 
- Hex counters 
Group Element Examples
Example 1
- type: "group"
  name: "variant group"
  required: false
  elements:
    - type: "constant"
      name: "separator"
      value: "."
    - type: "free"
      name: "variant"
      validation:
        pattern: "^\\w{1,10}$"This group defines an optional variant section for the CPN. It always inserts a period (.) as a separator, followed by a free‑form variant field. The variant allows any word character (A–Z, a–z, 0–9, _) with a length between 1 and 10.
Example CPNs:
- 123-4567.A 
- 123-4567.TEST1 
Example 2
- type: "group"
  name: "base_cpn"
  required: true
  elements:
    - type: "list"
      name: "prefix"
      required: true
      values:
        - id: "Category100"
          value: "100"
      validation:
        pattern: "^[1-9][0-9]{2}$"
    - type: "constant"
      name: "delimiter_1"
      value: "-"
    - type: "numeric_counter"
      name: "sequence"
      required: true
      attachedTo: ['prefix']
      format:
        min_value: 1
        max_value: 99999
      validation:
        pattern: "^[1-9][0-9]{4}$"
- type: "constant"
  name: "delimiter_2"
  value: "-"
- type: "list"
  name: "variant"
  required: true
  attachedTo: ['base_cpn']
  values:
    - id: "A"
      value: "A"
    - id: "B"
      value: "B"
  validation:
    pattern: "^[A-Z]{1}$"In this example:
- The group - base_cpncombines- prefixand- sequenceinto a single logical unit.
- The - variantis attached to- base_cpn, so its values are tracked in the context of the complete base number rather than being tied individually to both- prefixand- sequence.
- This approach makes the YAML more readable and unambiguous compared to listing multiple - attachedToreferences separately.
Free Text Element
The free element allows users to provide custom input that isn’t generated automatically. Validations ensure that free‑form values follow defined rules, such as a regex pattern and maximum length. This is commonly used for suffixes, variant labels, or other optional identifiers that can be user‑entered.
Note: allow_override must be true for free to be available for user entry.
- type: "free"
  name: string
  validation:
    pattern: string
    max_length: integervalidation.pattern
string
Yes
Regex pattern for validation
validation.max_length
integer
Yes
Maximum length of the text
Examples Array
The examples array must contain at least one example CPN that follows the defined scheme.
examples:
  - "410-0001"
  - "ELEC-591-0042.variant"Template References
Template references allow dynamic value lists to be pulled from the system:
values: "${{ namespace.field }}"Template references must match the pattern: ^\$\{\{\s*[\w\.]+\s*\}\}$. Currently, the only supported namespace is duro. and the only supported fields are categories and families.
Complete Schema Examples
Example 1: Basic Schema with Element-Level Overrides
$schema: "https://json-schema.org/draft-07/schema#"
version: "1.0"
schema_type: "id_generation_scheme"
settings:
  allow_override: true
  allow_freeform: true
  override_elements: ["variant"]  # Only variant can be overridden individually
  freeform_validation:
    pattern: "^[A-Z]{2,4}-\\d{4,6}$"
    max_length: 20
    description: "Format: 2-4 letters, hyphen, 4-6 digits"
elements:
  - type: list
    name: category
    required: true
    use: id
    values:
      - id: "410"
        name: Screws
        description: Mechanical fasteners
    validation:
      pattern: "^\\d{3}$"
  
  - type: constant
    name: separator
    required: true
    value: "-"
  
  - type: numeric_counter
    name: sequence
    required: true
    attachedTo: [category]
    format:
      min_value: 1
      max_value: 9999
  
  - type: list
    name: variant
    required: true
    attachedTo: [category, sequence]
    values: ["A", "B", "C"]
    allow_freeform: true
    freeform_validation:
      pattern: "^[A-Z]{1,3}$"
      max_length: 3
      description: "1-3 uppercase letters"
examples:
  - "410-0001-A"
  - "410-0001-Z"    # Custom variant overrideExample 2: Mixed Override Control
version: "1.0"
schema_type: "id_generation_scheme"
settings:
  allow_override: true
  allow_freeform: false
  override_elements: ["category", "variant"]  # Multiple elements can be overridden
elements:
  - type: list
    name: category
    required: true
    values: ["ELEC", "MECH", "SOFT"]
    # allow_freeform not specified = false (must pick from list)
  
  - type: constant
    name: delimiter1
    value: "-"
  
  - type: numeric_counter
    name: sequence
    required: true
    attachedTo: [category]
    format:
      min_value: 1
      max_value: 999
    # This element is NOT in override_elements, so cannot be overridden
  
  - type: constant
    name: delimiter2
    value: "-"
  
  - type: list
    name: variant
    required: true
    values: ["STD", "ALT"]
    allow_freeform: true
    freeform_validation:
      pattern: "^[A-Z]{2,5}$"
      max_length: 5
      description: "2-5 uppercase letters"
    # Users can pick STD/ALT OR enter custom variants like "PROTO"
examples:
  - "ELEC-001-STD"
  - "ELEC-001-PROTO"  # Custom variant
  - "CHEM-001-STD"    # Custom category overrideValidation Rules
- Version must match pattern - ^\d+\.\d+$
- Schema type must be exactly - "id_generation_scheme"
- All referenced element names must be unique within their scope 
- Counter ranges must be valid (min ≤ max) and min must be ≥ 0 
- Hex counter values must be valid hexadecimal strings 
- Template references must match the specified pattern 
- At least one example CPN must be provided 
- Group elements must contain at least one element 
- All elements must be valid and referenced correctly 
- Groups can be optional even if they contain required elements 
Best Practices
- Structure - Place required elements before optional ones 
- Group related elements together 
- Use consistent naming conventions 
 
- Validation - Always include regex patterns for list values 
- Set appropriate counter ranges for your volume 
- Consider case sensitivity implications 
 
- Documentation - Include descriptions for all list values 
- Provide diverse examples 
- Comment complex regex patterns 
 
- Maintenance - Use template references for shared value sets 
- Keep counter ranges generous for future growth 
- Consider versioning implications 
 
Last updated
Was this helpful?
