Files
3yearplan/schemas/README.md
Joseph Doherty 5953685ffb Seed the canonical OT schemas content under 3yearplan/schemas/ as a temporary location until a dedicated schemas repo is created (Gitea push-to-create is disabled, the dedicated repo needs a manual UI step). Initial seed contributed by the OtOpcUa team to unblock the EquipmentClassRef integration timeline (lmxopcua decision #112) and to provide the future cross-team owner with a concrete starting point rather than a blank slate. Marked DRAFT throughout with prominent "ownership TBD" framing in README and CONTRIBUTING — the future owner team should treat this seed as a starting point and revise format / structure / naming as the open questions in README "Open Questions" get resolved.
Includes: README explaining purpose / scope / temporary-location framing / format decision, CONTRIBUTING.md with proposed workflow + per-class semver versioning policy + validation commands, format/equipment-class.schema.json defining the shape of a class template (classId, version, displayName, applicability, signals, alarms, optional stateModel), format/tag-definition.schema.json defining the shape of a single canonical signal (name, dataType, category, unit, isArray, accessLevel, writeIdempotent, isHistorized, scaling), format/uns-subtree.schema.json defining the shape of a per-site UNS subtree (enterprise + site + areas + lines), classes/fanuc-cnc.json as the worked pilot class with 16 signals + 3 alarms + suggested state-derivation notes (per OtOpcUa corrections doc D1), uns/example-warsaw-west.json as a worked UNS subtree example, docs/overview.md (what / why / lifecycle / what's NOT in this repo), docs/format-decisions.md (8 numbered decisions covering JSON Schema choice per corrections D2, per-class semver, additive-only minor bumps, _default placeholder reservation, signal-name vs UNS-segment regex distinction, stateModel-as-informational, no per-equipment overrides at this layer, applicability.drivers as OtOpcUa driver enumeration), docs/consumer-integration.md (how OtOpcUa / Redpanda / dbt each integrate). $id URLs in the JSON schemas resolve at the actual current path so validators don't 404.

Top-level README adds a row to the Component Detail Files table pointing to schemas/. Corrections doc B2 (schemas-repo dependencies) marked partially RESOLVED with the seed location and a list of what still needs the plan team or cross-team owner to decide (owner team naming, dedicated repo migration, format-decision ratification, FANUC CNC pilot confirmation, CI gate setup, Redpanda + dbt consumer integration plumbing).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 12:35:27 -04:00

6.6 KiB
Raw Permalink Blame History

schemas — Canonical OT Equipment Definitions

Status: DRAFT — initial seed contributed by the OtOpcUa team (lmxopcua/docs/v2/acl-design.md, lmxopcua/docs/v2/plan.md decisions #112, #115, corrections doc D1+D2). Ownership of this content is TBD — should be assigned to a cross-team authority since it's consumed by OT and IT systems alike. The future owner team should treat this seed as a starting point, not a finished spec.

Temporary location: this seed lives at 3yearplan/schemas/ as a sub-tree of the 3-year-plan repo because Gitea's push-to-create is disabled and creating the dedicated schemas repo requires a manual UI step. Once the dedicated repo is created (proposed: gitea.dohertylan.com/dohertj2/schemas) and an owner team is named, this content should migrate over and references update accordingly. Until then, treat this directory as the canonical location for the seed.

Purpose

Single source of truth for the org's canonical OT equipment definitions:

  1. UNS hierarchy — the per-site Unified Namespace subtree (Enterprise / Site / Area / Line / Equipment) per the 3-year-plan handoff §UNS Naming Hierarchy
  2. Equipment-class templates — per-class declarations of which raw signals each equipment type exposes (FANUC CNCs surface these; Modbus PLCs surface those; etc.)
  3. Type vocabulary — the canonical machine-state values (Running / Idle / Faulted / Starved / Blocked) and any other shared enumerations consumers need

Who consumes this

Three surfaces per the 3-year-plan handoff §"Canonical Model Integration":

Consumer How
OtOpcUa equipment namespace At deploy/config time, OtOpcUa nodes fetch the equipment-class template referenced by Equipment.EquipmentClassRef and use it to validate the operator-configured tag set. Drift = config validation error
Redpanda topics + Protobuf schemas Equipment-class templates derive Protobuf message definitions for canonical events (equipment.state.transitioned, etc.)
dbt curated layer in Snowflake Same templates derive column definitions and dimension tables for the curated analytics model

OtOpcUa is one consumer of three. Decisions about format, structure, and naming live with the schemas-repo owner team (TBD), not with any one consumer.

Format

JSON Schema (Draft 2020-12) authored in this repo; Protobuf code-generated for wire serialization where needed (per OtOpcUa corrections doc D2 recommendation, blessed by the OtOpcUa team but pending schemas-repo team review).

Why JSON Schema as the authoring format:

  • Idiomatic for .NET (System.Text.Json + JsonSchema.Net) — OtOpcUa reads templates with no extra dependencies
  • Idiomatic for CI tooling (every CI runner can jq / validate JSON Schema without extra toolchain)
  • Supports validation at multiple layers: operator-visible Admin UI errors in OtOpcUa, schemas-repo CI gates, downstream consumer runtime validation
  • Better authoring experience than Protobuf (binary format, .proto compiler, poor merge story)
  • Where wire-format efficiency matters (Redpanda events), code-generate Protobuf from the JSON Schema source. One-way derivation is simpler than bidirectional sync.

Structure

schemas/
├── README.md                                    This file
├── CONTRIBUTING.md                              How to add a new class, validate, PR process
├── format/                                      JSON Schemas defining the format of everything below
│   ├── equipment-class.schema.json              Shape of an equipment-class template
│   ├── uns-subtree.schema.json                  Shape of a per-site UNS subtree definition
│   └── tag-definition.schema.json               Shape of an individual tag declaration inside a template
├── classes/                                     Equipment-class templates
│   └── fanuc-cnc.json                           Pilot class per OtOpcUa corrections D1
├── uns/                                         Per-site UNS subtree definitions
│   └── example-warsaw-west.json                 Worked example
└── docs/
    ├── overview.md                              What this repo is, who uses it, lifecycle
    ├── format-decisions.md                      Why JSON Schema, structure rationale, Protobuf derivation
    └── consumer-integration.md                  How each of the 3 consumers integrates

Lifecycle

  1. Author — humans edit JSON files in this repo, validated against the schemas in format/ by the CI gate
  2. Publish — merging to main makes the new content the authoritative version; semver tag on each release
  3. Consume — each consumer pulls a specific tagged version (or main for staging environments) and integrates per docs/consumer-integration.md

The current state has no consumers actively reading from this repo — content is seed-only. First wiring happens in OtOpcUa Phase 1+ when Equipment.EquipmentClassRef validation lands (see lmxopcua/docs/v2/plan.md decision #112).

Open Questions

Owner-team-decisions (not for OtOpcUa or any single consumer to make alone):

  • Repo ownership and review process: who owns this repo? PR review SLA? Format changes need who to sign off?
  • Versioning policy: semver per release? Per-class versioning vs whole-repo versioning? How do consumers pin versions?
  • Backward-compatibility policy: when a class adds a new required signal, do all existing equipment in OtOpcUa's central config DB need to be updated atomically? Or graceful degradation?
  • Cross-class shared types: how does a Position measurement (used by both FANUC CNC and a Beckhoff axis) avoid duplicate definitions?
  • Pilot class scope: FANUC CNC chosen per OtOpcUa corrections D1 because FOCAS already has a fixed pre-defined hierarchy. Confirm with the schemas-repo team that this is the right starting class.
  • Enterprise shortname (currently ent placeholder) — the UNS subtree definitions reference an Enterprise segment; the canonical value comes from organizational naming authority.

References

  • 3-year-plan handoff: gitea.dohertylan.com/dohertj2/3yearplanhandoffs/otopcua-handoff.md §"UNS Naming Hierarchy" + §"Canonical Model Integration" + §"Digital Twin Touchpoints"
  • OtOpcUa corrections doc: gitea.dohertylan.com/dohertj2/3yearplanhandoffs/otopcua-corrections-2026-04-17.md §B2 (schemas-repo dependencies) + §D1 (pilot class) + §D2 (format)
  • OtOpcUa v2 plan: gitea.dohertylan.com/dohertj2/lmxopcuadocs/v2/plan.md decisions #108115 + §"UNS naming hierarchy"