Skip to main content

Schema

The Schema component is a JSON schema definition for transition, flow, and master-data. Requests are validated on both the front-end and back-end, ensuring instance data consistency.

Schema source: vnext-schema/schema-definition.schema.json

Usage Types

TypeAttached AtPurpose
Master SchemaWorkflow root (attributes.schema)Main structure of instance data; consistency check on every change
Transition SchemaTransition definitionTransition request body validation
Flow SchemaWorkflow definitionWorkflow-level validation

Master Schema Behavior

The master schema is defined on the flow itself and determines the template structure of instance data. It also enables vNext features such as x-roles (field-level authorization), x-encryption, x-lookup and instance filtering. When an instance data merge is applied, the runtime validates it against the master schema and rejects the request if it does not conform.

Do not use required, set additionalProperties: true

Instance data grows via merge at each state. Therefore the master schema must not use required and must set additionalProperties: true so the data can expand. Strict requirements belong in transition schemas (request body validation), not the master schema.

The master schema also plays an active role in the Data Function: during instance filtering it resolves the types of dynamic fields from the schema, enabling advanced filtering.

Field-Level Authorization: x-roles

x-roles is the vocabulary keyword that authorizes a JSON Schema property (an instance data field) via role evaluation. It matters most in the master schema: it decides which fields are visible to whom — i.e. it provides column-level security. The Data Function and data-returning endpoints run the authorize layer and return only the fields the caller may see.

{
"x-roles": [
{ "role": "morph-idm.initiator", "grant": "allow" },
{ "role": "$userBehalfOf.$.context.Instance.Data.initial.customer.ownerUserId", "grant": "deny" }
]
}
FieldRequiredDescription
x-rolesRole grant list for the property (minItems: 1). If absent, the field is visible to all authorized callers
roleYesDomain-qualified role name (e.g. morph-idm.initiator) or a dynamic JSONPath expression
grantYesallow or deny. DENY always overrides ALLOW

The same system roles and JSONPath grant prefixes ($user. / $userBehalfOf. / $role.) apply; see Authorization. x-encryption is in the same field-governance scope (persisted / transport).

Filter & Sort Vocabulary

Whether a JSON (attributes.*) field is filterable and sortable is declared in the master schema via three keywords. The Data Function and instance-listing endpoints (.../instances?filter=, .../functions/data) honor this vocabulary:

KeywordTypeRequiredDescription
x-filterOperatorsstring[]NoAllowed filter operators. Empty or absent means the field is not filterable
x-sortablebooleanNoWhen true, the field is sortable. Absent means not sortable
x-displayFormatstringNoUI-facing format hint (e.g. yyyy-MM-dd'T'HH:mm:ssXXX)

x-filterOperators values: eq, ne, gt, ge, lt, le, between, match, like, startswith, endswith, in, nin (uniqueItems).

"startDateTime": {
"type": "string",
"format": "date-time",
"x-filterOperators": ["eq", "gt", "ge", "lt", "le", "between"],
"x-sortable": true,
"x-displayFormat": "yyyy-MM-dd'T'HH:mm:ssXXX"
}

A non-filterable field, or a disallowed operator, raises SchemaFilterValidationException. For per-type (numeric / date / text / boolean / array) operator behavior, the includes operator for JSON arrays, and the rules, see Instance Filtering → Schema-Driven Filterability.

For a read-only view (no input), the master schema can be supplied directly as the view's dataSchema; for input sections, a transition-specific schema should be used instead.

Data Context Vocabulary (data-vocab)

Vocabulary: vnext-schema/vocabularies/data-vocab.json

Two backwards-compatible annotations for schema-driven client context-store binding — a generic client wires a flow's inputs from, and persists its reusable outputs to, the client context-store purely from backend schemas, with zero per-flow client code:

AnnotationLives onDirectionApplied when
x-context-sourceA property of a transition input schemacontext-store → inputBuilding a start/transition payload
x-context-targetThe workflow master schemainstance data → context-storeOn every instance read (start result, after each transition)

x-context-source marks a property as client-resolved (no form field rendered), from one of: a literal ({ "const": <any> }), a context-store slot ({ "context": { "boundary": "device|user|subject", "key": "<template>", "storage"?: "memory|local|secure" } }), or the client identity ({ "identity": "subject" | "user" } — e.g. the logged-in userId / JWT sub).

"properties": {
"oldPassword": { "type": "string" },
"channel": { "type": "string", "x-context-source": { "const": "web" } },
"deviceId": { "type": "string", "x-context-source": { "context": { "boundary": "device", "key": "device.id" } } },
"userId": { "type": "string", "x-context-source": { "identity": "subject" } }
}

x-context-target (on the master schema) maps instance-data field paths (dot-notation) to context-store slots, applied on every instance read — so values that appear only after a transition (tokens, device ids, certificates) propagate automatically and become available to later flows via x-context-source. Slot keys support {instance} / {subject} templating; omit {instance} for cross-flow singletons.

"x-context-target": {
"deviceData.instanceId": { "context": { "boundary": "device", "key": "device.registration.{instance}" } },
"certificate": { "context": { "boundary": "device", "key": "device.cert.{instance}", "storage": "secure" } }
}

Standard JSON Schema validators ignore unknown x-* keywords, so unannotated schemas behave exactly as before — adoption is per-schema and incremental.

Required Fields

FieldTypeDescription
keystringUnique schema identifier
versionstringSchema version (SemVer)
domainstringOwning domain
flowstringAssociated flow
flowVersionstringFlow version
tagsstring[]Tags
attributesobjectJSON Schema (Draft) definition

Validation

Schemas are validated with Ajv2019. The front-end can use annotations for form validation; the back-end validates transition/start requests automatically.

  • Frontend: form annotations, real-time validation
  • Backend: request body validation, instance data merge validation
  • CI/CD: the schema itself is centrally validated in the vnext-schema repo

Typical Use Cases

  • Master schema to keep instance data immutable and versionable
  • Transition schema for distinct request body validation per transition
  • Form schema for automatic form generation on the UI side