docs: add JSON Schema for process definition documents

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
0264408
2026-09-21 11:52:57 +08:00
co-authored by Cursor
parent 02557a9b86
commit 056ab7a806
3 changed files with 299 additions and 1 deletions
+1
View File
@@ -471,6 +471,7 @@ components:
label:
type: string
ProcessDefinitionDocument:
description: Closed document shape is docs/process-definition.schema.json. Graph rules are enforced by ProcessDefinitionParser.
type: object
required: [id, name, steps, transitions]
properties:
+297
View File
@@ -0,0 +1,297 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://jetlumen.com/ordo/schema/process-definition.json",
"title": "Ordo process definition document",
"$comment": "Document shape for ProcessDefinitionParser.fromJson. Graph connectivity, unique ids, PARALLEL membership, due.goto branch rules, and predicate depth/leaf limits are enforced only by the parser.",
"type": "object",
"additionalProperties": false,
"required": ["id", "name", "steps", "transitions"],
"properties": {
"id": { "$ref": "#/$defs/nonEmptyString" },
"name": { "$ref": "#/$defs/nonEmptyString" },
"version": {
"type": "integer",
"minimum": 0,
"$comment": "Ignored by fromJson; written by toJson after publish."
},
"startStep": { "$ref": "#/$defs/nonEmptyString" },
"steps": {
"type": "array",
"minItems": 1,
"items": { "$ref": "#/$defs/topStep" }
},
"transitions": {
"type": "array",
"minItems": 1,
"items": { "$ref": "#/$defs/transition" }
}
},
"$defs": {
"nonEmptyString": {
"type": "string",
"pattern": ".*\\S.*"
},
"literal": {
"type": ["string", "number", "boolean"]
},
"topStep": {
"oneOf": [
{ "$ref": "#/$defs/approvalStep" },
{ "$ref": "#/$defs/actionStep" },
{ "$ref": "#/$defs/parallelStep" }
]
},
"leafStep": {
"oneOf": [
{ "$ref": "#/$defs/approvalStep" },
{ "$ref": "#/$defs/actionStep" }
]
},
"approvalStep": {
"type": "object",
"additionalProperties": false,
"required": ["id", "name", "candidates"],
"properties": {
"id": { "$ref": "#/$defs/nonEmptyString" },
"name": { "$ref": "#/$defs/nonEmptyString" },
"kind": { "const": "APPROVAL" },
"candidates": {
"type": "array",
"minItems": 1,
"uniqueItems": true,
"items": { "$ref": "#/$defs/nonEmptyString" }
},
"policy": { "type": "string", "enum": ["ANY", "ALL"] },
"due": { "$ref": "#/$defs/due" }
}
},
"actionStep": {
"type": "object",
"additionalProperties": false,
"required": ["id", "name", "kind", "action"],
"properties": {
"id": { "$ref": "#/$defs/nonEmptyString" },
"name": { "$ref": "#/$defs/nonEmptyString" },
"kind": { "const": "ACTION" },
"action": { "$ref": "#/$defs/nonEmptyString" },
"policy": { "type": "string", "enum": ["ANY", "ALL"] }
}
},
"parallelStep": {
"type": "object",
"additionalProperties": false,
"required": ["id", "name", "kind", "branches"],
"properties": {
"id": { "$ref": "#/$defs/nonEmptyString" },
"name": { "$ref": "#/$defs/nonEmptyString" },
"kind": { "const": "PARALLEL" },
"policy": { "type": "string", "enum": ["ANY", "ALL"] },
"branches": {
"type": "array",
"minItems": 2,
"items": { "$ref": "#/$defs/branch" }
}
}
},
"branch": {
"type": "object",
"additionalProperties": false,
"required": ["id", "steps", "transitions"],
"properties": {
"id": { "$ref": "#/$defs/nonEmptyString" },
"steps": {
"type": "array",
"minItems": 1,
"items": { "$ref": "#/$defs/leafStep" }
},
"transitions": {
"type": "array",
"minItems": 1,
"items": { "$ref": "#/$defs/transition" }
}
}
},
"due": {
"oneOf": [
{
"type": "object",
"additionalProperties": false,
"required": ["after", "then", "to"],
"properties": {
"after": { "$ref": "#/$defs/isoDuration" },
"then": { "const": "reassign" },
"to": { "$ref": "#/$defs/nonEmptyString" }
}
},
{
"type": "object",
"additionalProperties": false,
"required": ["after", "then"],
"properties": {
"after": { "$ref": "#/$defs/isoDuration" },
"then": { "const": "notify" },
"action": { "$ref": "#/$defs/nonEmptyString" }
}
},
{
"type": "object",
"additionalProperties": false,
"required": ["after", "then", "to"],
"properties": {
"after": { "$ref": "#/$defs/isoDuration" },
"then": { "const": "goto" },
"to": { "$ref": "#/$defs/nonEmptyString" }
}
}
]
},
"isoDuration": {
"type": "string",
"minLength": 2,
"$comment": "java.time.Duration.parse; must be positive after parse."
},
"transition": {
"type": "object",
"additionalProperties": false,
"required": ["from"],
"properties": {
"from": { "$ref": "#/$defs/nonEmptyString" },
"to": {
"type": ["string", "null"],
"minLength": 1
},
"when": { "$ref": "#/$defs/when" },
"priority": { "type": "integer" }
}
},
"when": {
"oneOf": [
{ "$ref": "#/$defs/refWhen" },
{ "$ref": "#/$defs/predicate" }
]
},
"refWhen": {
"type": "object",
"additionalProperties": false,
"required": ["ref"],
"properties": {
"ref": { "$ref": "#/$defs/nonEmptyString" },
"args": {
"type": "object",
"additionalProperties": true
}
}
},
"predicate": {
"oneOf": [
{ "$ref": "#/$defs/compareEq" },
{ "$ref": "#/$defs/compareNe" },
{ "$ref": "#/$defs/compareGt" },
{ "$ref": "#/$defs/compareGte" },
{ "$ref": "#/$defs/compareLt" },
{ "$ref": "#/$defs/compareLte" },
{ "$ref": "#/$defs/inPredicate" },
{ "$ref": "#/$defs/andPredicate" },
{ "$ref": "#/$defs/orPredicate" },
{ "$ref": "#/$defs/notPredicate" }
]
},
"comparePair": {
"type": "array",
"minItems": 2,
"maxItems": 2,
"prefixItems": [
{ "$ref": "#/$defs/nonEmptyString" },
{ "$ref": "#/$defs/literal" }
]
},
"compareEq": {
"type": "object",
"additionalProperties": false,
"required": ["eq"],
"properties": { "eq": { "$ref": "#/$defs/comparePair" } }
},
"compareNe": {
"type": "object",
"additionalProperties": false,
"required": ["ne"],
"properties": { "ne": { "$ref": "#/$defs/comparePair" } }
},
"compareGt": {
"type": "object",
"additionalProperties": false,
"required": ["gt"],
"properties": { "gt": { "$ref": "#/$defs/comparePair" } }
},
"compareGte": {
"type": "object",
"additionalProperties": false,
"required": ["gte"],
"properties": { "gte": { "$ref": "#/$defs/comparePair" } }
},
"compareLt": {
"type": "object",
"additionalProperties": false,
"required": ["lt"],
"properties": { "lt": { "$ref": "#/$defs/comparePair" } }
},
"compareLte": {
"type": "object",
"additionalProperties": false,
"required": ["lte"],
"properties": { "lte": { "$ref": "#/$defs/comparePair" } }
},
"inPredicate": {
"type": "object",
"additionalProperties": false,
"required": ["in"],
"properties": {
"in": {
"type": "array",
"minItems": 2,
"maxItems": 2,
"prefixItems": [
{ "$ref": "#/$defs/nonEmptyString" },
{
"type": "array",
"minItems": 1,
"items": { "$ref": "#/$defs/literal" }
}
]
}
}
},
"andPredicate": {
"type": "object",
"additionalProperties": false,
"required": ["and"],
"properties": {
"and": {
"type": "array",
"minItems": 1,
"items": { "$ref": "#/$defs/predicate" }
}
}
},
"orPredicate": {
"type": "object",
"additionalProperties": false,
"required": ["or"],
"properties": {
"or": {
"type": "array",
"minItems": 1,
"items": { "$ref": "#/$defs/predicate" }
}
}
},
"notPredicate": {
"type": "object",
"additionalProperties": false,
"required": ["not"],
"properties": {
"not": { "$ref": "#/$defs/predicate" }
}
}
}
}
+1 -1
View File
@@ -174,7 +174,7 @@ new ProcessDefinition("leave-request-routed", "Leave request",
### 3.2 JSON
`ProcessDefinitionParser.fromJson(String|InputStream)` / `toJson(ProcessDefinition)`。Spring 默认扫 `classpath*:ordo/*.json`。`toJson` 写出 `version` 与 `startStep`(当前步骤列表首位);`fromJson` 仍忽略 JSON 里的 `version`。
`ProcessDefinitionParser.fromJson(String|InputStream)` / `toJson(ProcessDefinition)`。Spring 默认扫 `classpath*:ordo/*.json`。`toJson` 写出 `version` 与 `startStep`(当前步骤列表首位);`fromJson` 仍忽略 JSON 里的 `version`。文档外形:[process-definition.schema.json](process-definition.schema.json);图连通、PARALLEL 约束、谓词深度/叶子上限仍以解析器为准。
```json
{