Canonical CMMS schema
The normalized Asset + WorkOrder model every CMMS connector conforms to — one integration to the standard, not N raw pass-throughs.
Siphon's healthcare-CMMS connectors all map different source shapes (OData, an Azure-APIM
POST-query gateway, ServiceNow) onto one normalized model. That's the point: you
integrate once, to the standard — @siphon/canonical (CANONICAL_VERSION = "0.1").
The model is derived from real connectors, not invented — every field is populated by at least one shipped connector (AIMS3, FSI, Nuvolo).
Entities
Two entities today: Asset (medical-equipment / clinical device) and WorkOrder.
Each has a set of SCREAMING_SNAKE columns with a type (string | number | boolean | timestamp), a required flag, and aliases — the real per-connector variant names that
satisfy the field.
import { CANONICAL_SCHEMA, conformance } from "@siphon/canonical";
// e.g. ASSET_ID with aliases ["ASSET_NUMBER", "NAME", "ASSET_TAG"]
CANONICAL_SCHEMA.Asset; // CanonicalField[]Reconciliation is the value: ASSET_ID, ASSET_NUMBER, and NAME are the same concept
across three sources; the canonical field carries the aliases so every one maps home.
Conformance
conformance(entity, producedFieldNames) scores a connector's output columns against the
schema — matching by canonical name or a known alias:
conformance("Asset", ["ASSET_NUMBER", "DESCRIPTION", "SERIAL_NUMBER", "STATUS", "SEGMENT"]);
// → { coveragePct, requiredCoveragePct, covered, missingRequired, missingOptional, extra, version }- covered — canonical fields the connector populates.
- missingRequired / missingOptional — canonical fields it doesn't.
- extra — source-specific columns with no canonical home (kept in the warehouse
dataJSONB, just not part of the standard).
The report is honest about gaps by design — e.g. FSI exposes no source-updated timestamp,
so its Asset conformance shows a required miss on SOURCE_UPDATED_AT_UTC. Connectors
target the canonical fields (see the add-a-connector guide),
and a high conformance score is a sales artifact: this source is fully normalized.