Data Contracts

This article assumes you've completed the Getting Started guide and understand the data modeling concepts.

Data contracts are the enforcement mechanism that makes data models mandatory. Without a contract, models are just documentation - contracts make validation happen.

Overview

In the component chain, contracts sit between models and execution:

Payload Shapes → Data Models → Data Contracts → Data Flows

                              Enforcement happens here

When you specify a data contract in a bridge, the UNS output plugin validates every message against the associated model.

UI Capabilities

The Management Console provides read-only access to contracts:

Feature
Available
Notes

View contract list

Shows all contracts with their models

Filter/search

Filter by name, instance, or model

View associations

See which model version each contract enforces

View usage

Shows count of stream processors using contract

Create contracts

Auto-created when creating models in UI

Edit contracts

Immutable once created

Delete contracts

Must be done via config.yaml

Contracts List

What you see in the UI:

  • Name: Contract identifier (e.g., _cnc_v1, _pump_v2)

  • Instance: Which UMH Core instance owns the contract

  • Model: The model and version being enforced (e.g., cnc (v1))

  • Stream Processors: Count of processors using this contract

Auto-Creation via UI

When you create a model in the UI, it automatically generates a matching contract:

  1. Create model pump version v1 in UI

  2. System auto-creates contract _pump_v1

  3. Contract immediately available for use in bridges

Configuration

Access configuration via: Instances → Select instance → ... → Config File

Basic Structure

Naming Convention

Contracts follow the pattern _modelname_version:

  • Always start with underscore

  • Include model name

  • End with version number

  • Examples: _pump_v1, _temperature_sensor_v2, _workorder_v1

Enforcement Mechanism

Where Validation Happens

The UNS output plugin (output: uns: {}) performs validation:

  1. Reads metadata: Extracts data_contract from message

  2. Looks up contract: Finds the associated model

  3. Validates structure: Checks topic path matches model

  4. Validates payload: Ensures data types match shapes

  5. Result:

    • ✅ Valid → Message published to topic

    • ❌ Invalid → Message rejected, bridge degraded

Validation Failures

When validation fails:

Result:

  • Message rejected (not published)

  • Bridge enters degraded state

  • Error logged with details

  • Bridge retries with backoff

Contract Types

The Special _raw Contract

  • Accepts any structure

  • No validation performed

  • Use for exploration and development

  • Bridge never goes degraded from data issues

Model-Based Contracts

  • Enforces exact model structure

  • Validates data types via payload shapes

  • Rejects non-conforming messages

  • Use for production systems

Relationship to Data Types

Data Type
Common Contracts
Validation

Raw/Exploration

_raw

No validation

Device Models

_pump_v1, _sensor_v1, _cnc_v1

Model-based validation

Business Models

_workorder_v1, _maintenance_v1

Always strict

Examples

Simple Device Contract

Relationship to Stream Processors

Stream processors don't use contracts directly - they reference models:

However, if a matching contract exists (_pump_v1), the stream processor's output will be validated against it automatically.

Last updated