Skip to main content

JSON Structure: Semantic and Reference-System Annotations
draft-vasters-json-structure-sem-ann-00

Document Type Active Internet-Draft (individual)
Author Clemens Vasters
Last updated 2026-08-06
RFC stream (None)
Intended RFC status (None)
Formats
Stream Stream state (No stream defined)
Consensus boilerplate Unknown
RFC Editor Note (None)
IESG IESG state I-D Exists
Telechat date (None)
Responsible AD (None)
Send notices to (None)
draft-vasters-json-structure-sem-ann-00
Network Working Group                                         C. Vasters
Internet-Draft                                     Microsoft Corporation
Intended status: Standards Track                           6 August 2026
Expires: 7 February 2027

       JSON Structure: Semantic and Reference-System Annotations
                draft-vasters-json-structure-sem-ann-00

Abstract

   Data types describe representation, but they do not explain the
   semantic, temporal, spatial, and operational characteristics needed
   to interpret and compare data.  This document defines optional JSON
   Structure annotations that bind schema nodes to terms in external
   vocabularies; annotations for observation results, observed
   properties, features of interest, procedures, time semantics,
   quality, derivation, and cadence; annotations for spatial referencing
   by coordinates, by vector and tensor reference frames, by
   transformations between frames, and along linear elements; and
   annotations for color spaces, audio channel layouts, spectral bands,
   code lists, and measurement conditioning.

   The annotations make an incompatibility between two data sets
   detectable by machine; they do not resolve one.  They are optional,
   and their absence does not make a schema invalid.

About This Document

   This note is to be removed before publishing as an RFC.

   The latest revision of this draft can be found at https://json-
   structure.github.io/semantic-annotations/draft-vasters-json-
   structure-sem-ann.html.  Status information for this document may be
   found at https://datatracker.ietf.org/doc/draft-vasters-json-
   structure-sem-ann/.

   Source for this draft and an issue tracker can be found at
   https://github.com/json-structure/semantic-annotations.

Status of This Memo

   This Internet-Draft is submitted in full conformance with the
   provisions of BCP 78 and BCP 79.

Vasters                  Expires 7 February 2027                [Page 1]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   Internet-Drafts are working documents of the Internet Engineering
   Task Force (IETF).  Note that other groups may also distribute
   working documents as Internet-Drafts.  The list of current Internet-
   Drafts is at https://datatracker.ietf.org/drafts/current/.

   Internet-Drafts are draft documents valid for a maximum of six months
   and may be updated, replaced, or obsoleted by other documents at any
   time.  It is inappropriate to use Internet-Drafts as reference
   material or to cite them other than as "work in progress."

   This Internet-Draft will expire on 7 February 2027.

Copyright Notice

   Copyright (c) 2026 IETF Trust and the persons identified as the
   document authors.  All rights reserved.

   This document is subject to BCP 78 and the IETF Trust's Legal
   Provisions Relating to IETF Documents (https://trustee.ietf.org/
   license-info) in effect on the date of publication of this document.
   Please review these documents carefully, as they describe your rights
   and restrictions with respect to this document.  Code Components
   extracted from this document must include Revised BSD License text as
   described in Section 4.e of the Trust Legal Provisions and are
   provided without warranty as described in the Revised BSD License.

Table of Contents

   1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   5
     1.1.  Semantic Binding and External Definitions . . . . . . . .   7
     1.2.  Observable and Observed Property Concepts . . . . . . . .   8
   2.  Conventions . . . . . . . . . . . . . . . . . . . . . . . . .   8
   3.  Annotation Model  . . . . . . . . . . . . . . . . . . . . . .   9
   4.  Vocabulary Annotations  . . . . . . . . . . . . . . . . . . .  13
     4.1.  The concepts Keyword  . . . . . . . . . . . . . . . . . .  13
       4.1.1.  The reference Property  . . . . . . . . . . . . . . .  13
       4.1.2.  The kind Property . . . . . . . . . . . . . . . . . .  13
       4.1.3.  Type Compatibility  . . . . . . . . . . . . . . . . .  14
       4.1.4.  Relationship to the Annotation Model  . . . . . . . .  15
       4.1.5.  Relationship to observedProperty  . . . . . . . . . .  15
   5.  Observation Annotations . . . . . . . . . . . . . . . . . . .  17
     5.1.  The observedProperty Keyword  . . . . . . . . . . . . . .  17
       5.1.1.  The reference Property  . . . . . . . . . . . . . . .  17
       5.1.2.  The kind Property . . . . . . . . . . . . . . . . . .  17
       5.1.3.  Attachment and Scope  . . . . . . . . . . . . . . . .  18
     5.2.  Semantic Mappings and Result Hints  . . . . . . . . . . .  20
     5.3.  The semanticRole Keyword  . . . . . . . . . . . . . . . .  20
       5.3.1.  Observation Result Concern  . . . . . . . . . . . . .  21

Vasters                  Expires 7 February 2027                [Page 2]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

       5.3.2.  Feature and Procedure Concern . . . . . . . . . . . .  22
       5.3.3.  Temporal Concern (Observation Time) . . . . . . . . .  26
       5.3.4.  Temporal Concern (Flattened Period Boundaries)  . . .  28
       5.3.5.  Temporal Concern (Operational Event Time) . . . . . .  30
       5.3.6.  Status Concern  . . . . . . . . . . . . . . . . . . .  34
     5.4.  The derivation Keyword  . . . . . . . . . . . . . . . . .  35
     5.5.  The statistic Keyword . . . . . . . . . . . . . . . . . .  37
   6.  Coded Value Annotations . . . . . . . . . . . . . . . . . . .  43
     6.1.  The codedValues Keyword . . . . . . . . . . . . . . . . .  44
       6.1.1.  The reference and kind Properties . . . . . . . . . .  44
       6.1.2.  Example . . . . . . . . . . . . . . . . . . . . . . .  46
   7.  Measurement Conditioning Annotations  . . . . . . . . . . . .  46
     7.1.  The measurementConditioning Keyword . . . . . . . . . . .  46
       7.1.1.  The weighting Property  . . . . . . . . . . . . . . .  47
       7.1.2.  The timeWeighting Property  . . . . . . . . . . . . .  47
       7.1.3.  The levelReference Property . . . . . . . . . . . . .  48
       7.1.4.  Example . . . . . . . . . . . . . . . . . . . . . . .  48
   8.  Reference System Meta-Types . . . . . . . . . . . . . . . . .  49
     8.1.  The referenceRole Keyword . . . . . . . . . . . . . . . .  49
   9.  Temporal Reference Annotations  . . . . . . . . . . . . . . .  50
     9.1.  The phenomenonTimeRelation Keyword  . . . . . . . . . . .  51
     9.2.  The supportPeriod Keyword . . . . . . . . . . . . . . . .  53
       9.2.1.  The length Property . . . . . . . . . . . . . . . . .  53
       9.2.2.  The anchor Property . . . . . . . . . . . . . . . . .  53
     9.3.  The temporalReferenceSystem Keyword . . . . . . . . . . .  56
       9.3.1.  The reference Property  . . . . . . . . . . . . . . .  56
       9.3.2.  The kind Property . . . . . . . . . . . . . . . . . .  56
       9.3.3.  The position Property . . . . . . . . . . . . . . . .  57
       9.3.4.  The sortOrder Property  . . . . . . . . . . . . . . .  58
       9.3.5.  Type Compatibility  . . . . . . . . . . . . . . . . .  58
     9.4.  The cadence Keyword . . . . . . . . . . . . . . . . . . .  61
       9.4.1.  The kind Property . . . . . . . . . . . . . . . . . .  62
       9.4.2.  The period Property . . . . . . . . . . . . . . . . .  62
   10. Spatial Reference Annotations . . . . . . . . . . . . . . . .  66
     10.1.  The coordinateReferenceSystem Keyword  . . . . . . . . .  66
       10.1.1.  The reference Property . . . . . . . . . . . . . . .  66
       10.1.2.  The kind Property  . . . . . . . . . . . . . . . . .  67
       10.1.3.  The coordinates Property . . . . . . . . . . . . . .  67
       10.1.4.  Vertical and Compound Systems  . . . . . . . . . . .  70
     10.2.  The vectorReferenceFrames Keyword  . . . . . . . . . . .  72
       10.2.1.  The reference and kind Properties  . . . . . . . . .  73
       10.2.2.  The components Property  . . . . . . . . . . . . . .  73
       10.2.3.  The variance Property  . . . . . . . . . . . . . . .  74
       10.2.4.  Multiple Frames and Shared Components  . . . . . . .  75
     10.3.  The tensorReferenceFrames Keyword  . . . . . . . . . . .  78
       10.3.1.  The frames Property  . . . . . . . . . . . . . . . .  79
       10.3.2.  The components Property  . . . . . . . . . . . . . .  81
     10.4.  The frameTransforms Keyword  . . . . . . . . . . . . . .  84

Vasters                  Expires 7 February 2027                [Page 3]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

       10.4.1.  The Conventions This Document Fixes  . . . . . . . .  85
       10.4.2.  The from and to Properties . . . . . . . . . . . . .  86
       10.4.3.  The encoding Property  . . . . . . . . . . . . . . .  86
       10.4.4.  The components Property  . . . . . . . . . . . . . .  88
       10.4.5.  The rotationSequence Property  . . . . . . . . . . .  92
       10.4.6.  The translation Property . . . . . . . . . . . . . .  94
     10.5.  The linearReferenceSystem Keyword  . . . . . . . . . . .  97
       10.5.1.  The reference Property . . . . . . . . . . . . . . .  97
       10.5.2.  The kind Property  . . . . . . . . . . . . . . . . .  98
       10.5.3.  The linearElement Property . . . . . . . . . . . . .  99
       10.5.4.  The measure Property . . . . . . . . . . . . . . . .  99
       10.5.5.  The measureEnd Property  . . . . . . . . . . . . . .  99
       10.5.6.  The direction Property . . . . . . . . . . . . . . .  99
   11. Colorimetric Reference Annotations  . . . . . . . . . . . . . 101
     11.1.  The colorSpaces Keyword  . . . . . . . . . . . . . . . . 101
       11.1.1.  The reference and kind Properties  . . . . . . . . . 102
       11.1.2.  The codePoints Property  . . . . . . . . . . . . . . 104
       11.1.3.  The channels Property  . . . . . . . . . . . . . . . 105
       11.1.4.  The packing Property . . . . . . . . . . . . . . . . 105
       11.1.5.  The alpha and alphaMode Properties . . . . . . . . . 107
       11.1.6.  The transfer Property  . . . . . . . . . . . . . . . 108
       11.1.7.  The illuminant and observer Properties . . . . . . . 109
       11.1.8.  Example  . . . . . . . . . . . . . . . . . . . . . . 110
   12. Signal Channel Annotations  . . . . . . . . . . . . . . . . . 112
     12.1.  The audioChannels Keyword  . . . . . . . . . . . . . . . 112
       12.1.1.  The reference and kind Properties  . . . . . . . . . 113
       12.1.2.  The channels Property  . . . . . . . . . . . . . . . 113
       12.1.3.  The levelReference Property  . . . . . . . . . . . . 114
       12.1.4.  The encoding Property  . . . . . . . . . . . . . . . 114
       12.1.5.  Example  . . . . . . . . . . . . . . . . . . . . . . 116
     12.2.  The spectralBands Keyword  . . . . . . . . . . . . . . . 116
       12.2.1.  The reference and kind Properties  . . . . . . . . . 117
       12.2.2.  The bands Property . . . . . . . . . . . . . . . . . 118
       12.2.3.  The calibration Property . . . . . . . . . . . . . . 118
       12.2.4.  Example  . . . . . . . . . . . . . . . . . . . . . . 119
   13. Conformance . . . . . . . . . . . . . . . . . . . . . . . . . 120
     13.1.  Check Outcomes . . . . . . . . . . . . . . . . . . . . . 120
     13.2.  Schema Conformance . . . . . . . . . . . . . . . . . . . 120
     13.3.  Processing Conformance . . . . . . . . . . . . . . . . . 121
     13.4.  Inheritance and Imports  . . . . . . . . . . . . . . . . 123
   14. Extension Meta-Schema . . . . . . . . . . . . . . . . . . . . 123
   15. Security Considerations . . . . . . . . . . . . . . . . . . . 124
     15.1.  Privacy Considerations . . . . . . . . . . . . . . . . . 125
   16. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 125
   17. References  . . . . . . . . . . . . . . . . . . . . . . . . . 125
     17.1.  Normative References . . . . . . . . . . . . . . . . . . 125
     17.2.  Informative References . . . . . . . . . . . . . . . . . 127
   Appendix A.  Reference URIs (Informative) . . . . . . . . . . . . 133

Vasters                  Expires 7 February 2027                [Page 4]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

     A.1.  Vocabularies  . . . . . . . . . . . . . . . . . . . . . . 133
     A.2.  Temporal Reference Systems  . . . . . . . . . . . . . . . 133
     A.3.  Coordinate Reference Systems  . . . . . . . . . . . . . . 135
     A.4.  Vector Reference Frames . . . . . . . . . . . . . . . . . 135
     A.5.  Linear Reference Systems  . . . . . . . . . . . . . . . . 136
     A.6.  Code Lists  . . . . . . . . . . . . . . . . . . . . . . . 136
   Change Log  . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
   Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . 137
   Author's Address  . . . . . . . . . . . . . . . . . . . . . . . . 138

1.  Introduction

   A schema states how a value is written.  It gives a type, and with
   JSON Structure Units [JSTRUCT-UNITS] it gives a unit, so that a
   reader knows a member holds a number of metres.  It does not state
   what the number measures, what the metres are measured from, or when
   the measurement applies.  Two schemas can agree on double and on m
   and still describe water level above a tide-gauge datum and height
   above an ellipsoid, which are not the same quantity and must not be
   compared.  That difference is usually recorded in prose
   documentation, inferred from a member name, or known only to the
   people who built the system.

   This document is an extension to JSON Structure Core [JSTRUCT-CORE]
   that records it in the schema, by annotation, without changing what
   the schema validates.  Its keywords let a schema author:

   *  bind a type or member to a term in a published vocabulary, so that
      two systems naming a thing differently can establish that they
      mean the same thing;

   *  declare what a record observes and which member carries the
      result, as distinct from the property observed, the feature it
      belongs to, the procedure that produced it, and the time it
      applies to;

   *  name the reference system a value is expressed against, whether a
      temporal regime, a coordinate reference system, a vector or tensor
      reference frame, a transformation from one frame to another, or a
      linear reference system, so that a position, a direction, or an
      orientation can be interpreted and two of them compared; and

   *  resolve the members that together carry one compound value onto
      the axes, channels, or bands that give them meaning, whether those
      of a color space, an audio channel layout, or a set of spectral
      bands.

Vasters                  Expires 7 February 2027                [Page 5]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   The same concern applies to a value that stands alone.  One keyword
   binds a coded value to the register that assigns the code its
   meaning, so that a number or a short string can be resolved rather
   than guessed at from a member name.  Another records the frequency
   weighting, time weighting, and level reference that a conditioned
   measurement already carries, so that a sound level measured under one
   weighting is not silently compared with one measured under another.

   Most of these are bindings to a definition maintained elsewhere.
   This document defines no vocabulary, no reference system, no color
   space, no channel layout, and no code list of its own.  Established
   bodies publish them, and an annotation refers to one.  What is
   defined here is the form of that reference, the roles a schema may
   assign to its own members, and the rules by which a processor can
   check that the two agree.

   The roles are the one place where that account needs qualifying.
   semanticRole and derivation do carry a vocabulary of observation
   concepts, and this document does not pretend otherwise.  What it
   declines to be is a normative encoding of the observation model of
   [ISO19156].  It defines no observation as a type to instantiate, no
   classes for procedures or features, and no relationships among
   observation entities, and it requires no record to be shaped like an
   observation.  The roles describe what the members of a record already
   are, over a structure someone else fixed.  A record does not become
   an observation by carrying them, a schema that carries none is not
   deficient for that reason, and a processor does not reconstruct an
   observation entity from the roles it finds (Section 13.3).

   Nor does this document define analytical procedures.  Several
   keywords name an operation, and naming one is not specifying it.  A
   schema that declares a value an hourly mean records an operation that
   has already been performed; it does not state what a mean computes,
   how gaps in the set were treated, whether the window was inclusive of
   its bounds, or whether a consumer may recompute the value.  The
   annotations describe what was done, and a processor does not read an
   instruction out of them (Section 13.3).

   Nor does it define a lineage model, although several keywords carry
   lineage facts: derivation says how a value was produced,
   observingProcedure identifies what produced it, and ingestionTime
   says when a system received it.  [PROV-O] gives entities, activities,
   and agents identities and relates them by derivation and attribution.
   What is here is flat and confined to one record, with no identity for
   the act that produced a value and no way to chain a value to the
   value it came from.  The two do not conflict and a record can carry
   both; the concepts example maps a publication instant onto
   prov:generatedAtTime (Section 4.1).

Vasters                  Expires 7 February 2027                [Page 6]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   The keywords defined here are chosen by one test.  A quality of a
   value earns a keyword when a consumer must know it to decide whether
   two values may be combined or compared, and when it holds for the
   type rather than varying from one instance to the next.  Axis order,
   frequency weighting, and the register a code is drawn from meet that
   test: get one of them wrong and an arithmetic result is wrong while
   every value still validates.  Licensing, retention, and endpoint
   addressing do not meet it, because they do not change what may be
   computed from a value.  A per-observation calibration record does not
   meet it, because it varies from one record to the next and belongs in
   the payload rather than in the schema.  Geometry, provenance, and
   unit algebra do not meet it, because each is a model in its own right
   that another specification defines; this document cites those rather
   than restating them.

   The annotations are optional and additive.  A processor that does not
   implement them reads the schema exactly as JSON Structure Core
   defines it.  This document defines no conversion, and a processor
   that cannot resolve a referenced definition reports the check as
   indeterminate rather than assuming agreement.  Correctly declining to
   combine two values is the outcome these annotations enable;
   transforming them so that they can be combined remains the work of a
   tool that holds the authoritative definitions.

1.1.  Semantic Binding and External Definitions

   Most keywords defined here share one shape.  Each is an object
   carrying a reference property that identifies a definition and a kind
   property that names the model the definition belongs to.  This lets a
   reader know how to interpret it and a processor know what can be
   checked. concepts, observedProperty, temporalReferenceSystem,
   coordinateReferenceSystem, linearReferenceSystem, codedValues, the
   entries of vectorReferenceFrames, colorSpaces, audioChannels, and
   spectralBands, and the frames named by tensorReferenceFrames and
   frameTransforms all follow this shape.

   A definition is ordinarily maintained outside the schema, and
   reference is then an absolute URI [RFC3986].  Every one of these
   keywords except concepts and observedProperty also admits a
   definition held in the schema itself, carried by a shareable type
   that Section 8 calls a meta-type; kind is then type and reference is
   a type reference { "$ref": <JSON Pointer> } to that type.  The kind
   determines which form applies, and each keyword states the rule for
   its own values.

   A kind names a definition model and not the format of the resource
   that carries it.  The enumerations are open so that an author whose
   model is not already named can name it.

Vasters                  Expires 7 February 2027                [Page 7]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   The annotations bind terms; they do not express statements, node
   identity, or entailment, and this document defines no prefix
   mechanism and no compact URI form.

   A value is read against one temporal or coordinate reference system,
   quantifies one phenomenon, and draws its code from one register, so
   those keywords, observedProperty, and codedValues each take a single
   binding.  Vocabularies overlap by design, and the same notion is
   deliberately given a term in several of them, so concepts takes a
   list.  The keywords that resolve components onto axes, channels, or
   bands take a list for a different reason: one record can carry
   several such quantities at once, and one set of numbers can be
   published in more than one frame or more than one color space at
   once.

   measurementConditioning stands apart from this shape.  It identifies
   no external definition, because what it records is not a system a
   value is read against but a treatment the value has already
   undergone, and it states that treatment directly.

1.2.  Observable and Observed Property Concepts

   Observation is one application of the general model in Section 1.1.
   An _observable property definition_ is the externally governed
   concept, such as water level or bridge vibration, and this document
   defines no format for one.  An _observed property declaration_ is the
   observedProperty annotation that binds one record shape to one such
   definition.

   An observation act is one concrete execution of an observing
   procedure for one declared observed property and feature context,
   producing one result value and optionally its qualifiers.

2.  Conventions

   The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
   "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
   "OPTIONAL" in this document are to be interpreted as described in
   BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all
   capitals, as shown here.

   Some examples in this document contain lines that exceed the maximum
   line length permitted in an RFC.  Those examples use the single
   backslash line wrapping strategy of [RFC8792] and carry the header
   that strategy defines.  A line ending in a backslash is continued by
   the first non-space character of the following line; the backslash,
   the line break, and the leading whitespace are removed to recover the
   original text.

Vasters                  Expires 7 February 2027                [Page 8]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

3.  Annotation Model

   concepts MAY occur on a type definition and on a property, collection
   item, map value, or choice member schema, subject to Section 4.

   semanticRole, derivation, temporalReferenceSystem, and cadence MAY
   occur directly on a property, collection item, map value, or choice
   member schema, subject to Section 5. phenomenonTimeRelation and
   supportPeriod MAY occur on a direct property. statistic MAY occur
   wherever derivation occurs, subject to Section 5.5.
   temporalReferenceSystem MAY also occur on an object or tuple that
   defines a temporal type, and binds an existing member of it.

   observedProperty MAY occur on an object or tuple intended to describe
   an observation record, and on a member schema of one that carries a
   result, subject to Section 5.1. coordinateReferenceSystem,
   vectorReferenceFrames, tensorReferenceFrames, frameTransforms,
   linearReferenceSystem, colorSpaces, audioChannels, and spectralBands
   MAY occur on an object or tuple and bind existing properties.
   codedValues and measurementConditioning MAY occur on a property,
   collection item, map value, or choice member schema, subject to their
   sections. referenceRole MAY occur on a member of a meta-type, subject
   to Section 8.

   All keywords defined here are direct peer keywords, and no wrapper is
   implied.  Every annotation is OPTIONAL, and a schema can use any
   subset, including none.  Conformance constrains only annotations that
   are present; it never requires another annotation or an annotated
   property to exist.

   Several keywords bind members of the annotated type by name.  Such a
   name is the name of the property as declared in the schema, and it is
   resolved against the effective definition of the annotated type,
   which includes members contributed by $extends and members of an
   imported or shadowing definition [JSTRUCT-IMPORT].  A name that does
   not resolve to a direct member of that effective definition is
   invalid.  An alternate, localized, or otherwise serialization-facing
   name assigned to a member by another extension, such as JSON
   Structure Alternate Names [JSTRUCT-ALTNAMES], changes how the member
   appears in an instance document and does not change the identity the
   annotation binds; a processor MUST NOT resolve a member name stated
   in an annotation against such a name, and MUST NOT treat the presence
   of one as altering the mapping.

   Every reference value that is a URI SHOULD be resolvable, and
   dereferencing it SHOULD yield a definition of the identified term or
   system.  A processor is not required to dereference a reference, and
   an unresolved reference is indeterminate rather than incorrect.

Vasters                  Expires 7 February 2027                [Page 9]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   A reference identifies whatever its URI identifies, revision
   included, and this document defines no version, epoch, or as-of
   member to stand beside it.  A body that revises definitions and means
   them to stay citable puts the revision in the identifier, which is
   what the naming policy behind the identifiers used throughout this
   document provides for: a definition is named
   /def/{objectType}/{authority}/{version}/{code} [OGC-NAMES], so the 0
   in http://www.opengis.net/def/crs/EPSG/0/4326 occupies a version
   position that a schema needing one edition rather than another fills
   in.  A schema pins an edition by writing the identifier the publisher
   supplies for it.

   A separate member would state in a second place what the URI already
   carries, and no processor could reconcile the two without resolving
   the reference, which none is required to do.  Where a publisher
   revises without giving each revision an identifier, a schema SHOULD
   record that fact in description, which informs a reader without
   inviting a processor to act on it.

   The enumerations of this document are of two sorts, and one rule
   divides them.  An enumeration is closed where its values select a
   behavior that this document itself defines, so that a value outside
   it would establish nothing for any processor.  An enumeration is open
   where its values name a model, register, or definition that another
   body maintains, because this document cannot enumerate what others
   publish and a value it has not heard of may still be one that a
   reader knows.

   Closed are semanticRole, derivation, statistic in both of its forms,
   phenomenonTimeRelation, referenceRole, sortOrder, the kind of
   cadence, the anchor of supportPeriod, the variance of
   vectorReferenceFrames and tensorReferenceFrames, the symmetry of
   tensorReferenceFrames, the encoding and rotationSequence of
   frameTransforms, and the alphaMode and transfer of colorSpaces.  A
   value outside a closed enumeration is invalid.

   Open are the kind of every reference-style keyword, the weighting and
   timeWeighting of measurementConditioning, the levelReference of both
   measurementConditioning and audioChannels, the calibration of
   spectralBands, and the encoding of audioChannels.  A value outside an
   open enumeration is valid; a processor MUST preserve it and MUST NOT
   reject a schema for carrying it.

   Closure states where a value's meaning comes from, and is not a claim
   that a list is finished.  A later version of this document may add
   values to a closed enumeration, and the versioned meta-schema URI a
   schema names is what tells a processor which set is in force
   (Section 14).

Vasters                  Expires 7 February 2027               [Page 10]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   A value defined here is one a processor can act on, and this document
   states what each establishes.  A value not defined here establishes
   nothing, and a processor MUST NOT infer a constraint from it.  This
   document defines no registry of further values and no mechanism by
   which a private value acquires meaning for a processor that does not
   already know it.

   Because the open enumerations are open, two authors may choose one
   token for two unrelated things. kind classifies and reference
   identifies, and that division bounds the consequence.  A processor
   MUST NOT treat a kind value as establishing the identity of a
   definition, and MUST NOT conclude from two schemas carrying equal
   kind values that they draw on the same register, model, or
   definition.  Where kind agrees and reference does not, the references
   govern.  A processor meeting a kind it does not recognize reports the
   check indeterminate (Section 13.1).

   That bounds a collision rather than preventing one.  A registry of
   kind values is the remedy; a future revision of this document is
   expected to establish one, and none exists at the time of writing.
   Until one does, a kind value outside those defined here means what it
   means only to a processor that already knows it.  A schema SHOULD use
   a value defined here where one fits, and SHOULD NOT coin a broad
   token such as sensor or registry for a private arrangement, since the
   broadest tokens are the ones most likely to be coined twice.

    +===========================+=====================================+
    | Keyword                   | Meaning                             |
    +===========================+=====================================+
    | concepts                  | Terms in external vocabularies that |
    |                           | the annotated node corresponds to.  |
    +---------------------------+-------------------------------------+
    | semanticRole              | Function of a result, temporal,     |
    |                           | quality, status, or operational     |
    |                           | value.                              |
    +---------------------------+-------------------------------------+
    | observedProperty          | Reference to an observable-property |
    |                           | definition.                         |
    +---------------------------+-------------------------------------+
    | phenomenonTimeRelation    | Refinement of how a result relates  |
    |                           | to phenomenonTime.                  |
    +---------------------------+-------------------------------------+
    | supportPeriod             | Length of the phenomenon-time       |
    |                           | period a result characterizes, and  |
    |                           | the position anchoring it.          |
    +---------------------------+-------------------------------------+
    | derivation                | Category describing how a result    |
    |                           | value was produced.                 |

Vasters                  Expires 7 February 2027               [Page 11]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

    +---------------------------+-------------------------------------+
    | statistic                 | Summary function that produced a    |
    |                           | result from a set of values.        |
    +---------------------------+-------------------------------------+
    | temporalReferenceSystem   | Binding from a temporal-position    |
    |                           | encoding to its reference           |
    |                           | definition.                         |
    +---------------------------+-------------------------------------+
    | cadence                   | Expected pattern of successive      |
    |                           | temporal positions.                 |
    +---------------------------+-------------------------------------+
    | coordinateReferenceSystem | CRS and ordered properties forming  |
    |                           | a coordinate.                       |
    +---------------------------+-------------------------------------+
    | vectorReferenceFrames     | Frames and ordered properties       |
    |                           | forming the components of vector    |
    |                           | quantities.                         |
    +---------------------------+-------------------------------------+
    | tensorReferenceFrames     | Frames and indexed properties       |
    |                           | forming the components of tensor    |
    |                           | quantities.                         |
    +---------------------------+-------------------------------------+
    | frameTransforms           | Frames and properties forming a     |
    |                           | transformation from one frame to    |
    |                           | another.                            |
    +---------------------------+-------------------------------------+
    | linearReferenceSystem     | LRS and properties forming a        |
    |                           | location along a linear element.    |
    +---------------------------+-------------------------------------+
    | colorSpaces               | Color spaces and properties forming |
    |                           | the channels of color values.       |
    +---------------------------+-------------------------------------+
    | referenceRole             | Function of a member within a       |
    |                           | reference-system meta-type.         |
    +---------------------------+-------------------------------------+
    | audioChannels             | Audio channel layout, level         |
    |                           | reference, and encoding for channel |
    |                           | values.                             |
    +---------------------------+-------------------------------------+
    | spectralBands             | Spectral bands and ordered          |
    |                           | properties forming the bands of a   |
    |                           | multiband value.                    |
    +---------------------------+-------------------------------------+
    | codedValues               | Binding from a coded property to an |
    |                           | external code list.                 |
    +---------------------------+-------------------------------------+
    | measurementConditioning   | Frequency or time weighting and     |
    |                           | level reference a scalar            |

Vasters                  Expires 7 February 2027               [Page 12]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

    |                           | measurement carries.                |
    +---------------------------+-------------------------------------+

                                  Table 1

   Omission means undeclared unless stated otherwise.  It never implies
   compatible, successful, or acceptable data.

4.  Vocabulary Annotations

4.1.  The concepts Keyword

   The concepts keyword binds the annotated node to terms defined by
   external vocabularies, following the model in Section 1.1.  In this
   document a concept is any term that a vocabulary defines, including a
   class, a property, or a SKOS concept [SKOS].  The skos-concept kind
   names one such term type and places no constraint on the others.

   When present, concepts MUST be a non-empty array of objects.  Each
   object MUST have a REQUIRED reference string and a REQUIRED kind
   string.  No other properties are permitted.

   The array is unordered and no entry is primary.  Every entry holds
   simultaneously: the annotated node corresponds to all of the terms
   listed, and a reader does not select among them.  Two entries MUST
   NOT carry the same reference.

4.1.1.  The reference Property

   reference MUST be an absolute URI [RFC3986] that identifies one term.
   The URI is the identifier that the vocabulary assigns to the term.
   This document defines no prefix mechanism, no compact form, and no
   resolution protocol.

4.1.2.  The kind Property

   kind classifies which definition model the URI identifies.  It is an
   open enumeration.  The following values are defined:

Vasters                  Expires 7 February 2027               [Page 13]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

      +=======================+=====================================+
      | Value                 | Referenced definition               |
      +=======================+=====================================+
      | rdfs-class            | A class in RDF Schema [RDF-SCHEMA]. |
      +-----------------------+-------------------------------------+
      | rdf-property          | An RDF property [RDF-CONCEPTS].     |
      +-----------------------+-------------------------------------+
      | owl-class             | A class in OWL 2 [OWL2].            |
      +-----------------------+-------------------------------------+
      | owl-object-property   | An OWL 2 object property.           |
      +-----------------------+-------------------------------------+
      | owl-datatype-property | An OWL 2 datatype property.         |
      +-----------------------+-------------------------------------+
      | skos-concept          | A concept in a SKOS concept scheme  |
      |                       | [SKOS].                             |
      +-----------------------+-------------------------------------+
      | dcterms-property      | A property in DCMI Metadata Terms   |
      |                       | [DCTERMS].                          |
      +-----------------------+-------------------------------------+

                                  Table 2

   Other values MAY identify further definition models.  Appendix A.1
   lists namespace URIs for the vocabularies named above.

4.1.3.  Type Compatibility

   A kind denotes either a class or a property, and the two attach to
   different schema nodes:

   *  rdfs-class and owl-class denote a class, and the annotation MUST
      occur on a type definition.

   *  rdf-property, owl-object-property, owl-datatype-property, and
      dcterms-property denote a property, and the annotation MUST occur
      on a property, collection item, map value, or choice member
      schema.

   *  skos-concept denotes neither, and the annotation MAY occur on
      either.

   All entries of one concepts array MUST agree.  An array MUST NOT
   combine an entry whose kind denotes a class with an entry whose kind
   denotes a property.  A kind outside the values defined above
   establishes no constraint, and a processor MUST NOT infer one.

Vasters                  Expires 7 February 2027               [Page 14]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

4.1.4.  Relationship to the Annotation Model

   The keywords defined in this document already state the part a node
   plays.  A concepts entry that names a term whose meaning is that same
   part carries no information beyond the annotation it accompanies and
   SHOULD be omitted.

   A node that carries observedProperty is an observation record by
   Section 3, and SHOULD NOT also be bound to a general observation
   class.  A member that carries semanticRole SHOULD NOT also be bound
   to a vocabulary property whose meaning is that same role, such as a
   term for the result of an observation beside observationValue, or a
   term for the feature that an observation is about beside
   featureOfInterest.

   concepts is for meaning that the annotation model does not carry: the
   domain class of a record, the catalogue or taxonomic term that a
   member names, or a correspondence that a consumer needs in order to
   join the data to another vocabulary.  A redundant entry is not an
   error, and a processor MUST NOT reject a document for carrying one.

4.1.5.  Relationship to observedProperty

   concepts states which external terms the annotated node corresponds
   to. observedProperty states which phenomenon a record quantifies.
   Where the term is an observable-property definition, observedProperty
   carries it and concepts MUST NOT name it.  The same URI MUST NOT
   appear in both keywords on one node.

   Correspondences between one observable-property definition and terms
   in other vocabularies belong to the definition and are recorded once
   there, as described in Section 5.2.  They are not repeated as
   concepts entries in every schema that cites the definition.

   A binding is a statement about meaning and not about resolution.  A
   missing or unresolved term is indeterminate and MUST NOT be repaired
   from property names, descriptions, labels, or samples.

   Example:

Vasters                  Expires 7 February 2027               [Page 15]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   {
     "name": "TideGaugeReading",
     "type": "object",
     "description": "One water-level reading from a tide gauge.",
     "concepts": [
       {
         "reference": "http://www.w3.org/ns/sosa/Observation",
         "kind": "owl-class"
       }
     ],
     "observedProperty": {
       "reference":
         "https://vocab.nerc.ac.uk/collection/P01/current/ASLVZZ01/",
       "kind": "nerc-p01"
     },
     "properties": {
       "waterLevel": {
         "type": "double",
         "unit": "m",
         "description": "Height of the water surface above datum.",
         "examples": [2.41],
         "semanticRole": "observationValue",
         "concepts": [
           {
             "reference": "http://www.w3.org/ns/sosa/hasSimpleResult",
             "kind": "rdf-property"
           }
         ]
       },
       "issued": {
         "type": "datetime",
         "description": "Instant at which the reading was published.",
         "examples": ["2026-03-11T08:15:00Z"],
         "concepts": [
           {
             "reference": "http://purl.org/dc/terms/issued",
             "kind": "dcterms-property"
           },
           {
             "reference": "http://www.w3.org/ns/prov#generatedAtTime",
             "kind": "rdf-property"
           }
         ]
       }
     }
   }

Vasters                  Expires 7 February 2027               [Page 16]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

5.  Observation Annotations

5.1.  The observedProperty Keyword

   The observedProperty keyword identifies the observable-property
   definition associated with an observation record, or with one result
   within it, as introduced in Section 1.2.

   When present, observedProperty MUST be an object with a REQUIRED
   reference string and a REQUIRED kind string.  No other properties are
   permitted.

5.1.1.  The reference Property

   reference MUST be an absolute URI [RFC3986] that identifies one
   immutable observable-property definition.  Version identity, when
   used, is implied by the URI itself, and a materially different
   concept MUST be identified by a different URI.  The URI SHOULD deep-
   link to one concrete definition entry in the selected vocabulary.
   This document does not define a resolution protocol, URI layout,
   storage model, or catalog serialization.

5.1.2.  The kind Property

   kind classifies which definition model the URI identifies.  It is an
   open enumeration, and a value identifies the vocabulary or catalog
   type that publishes the definition.

   Examples of catalog types include:

   *  cf-standard-name for URIs identifying entries from the CF Standard
      Name Table, for example a URI identifying air_temperature;

   *  nerc-p01 for entries from the NERC Vocabulary Server Parameter
      Usage Vocabulary (P01) identified by dereferenceable concept URIs.

   An organization that publishes its own catalog names its own model.
   The examples in this document use example-catalog where the cited
   catalog is fictional.

   Example:

Vasters                  Expires 7 February 2027               [Page 17]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   {
     "observedProperty": {
       "reference":
         "https://vocab.nerc.ac.uk/collection/P01/current/CTMPZZ01/",
       "kind": "nerc-p01"
     }
   }

5.1.3.  Attachment and Scope

   observedProperty MAY occur on an object or tuple that describes an
   observation record, and on a member schema of that object or tuple
   that carries a result.

   On a record it identifies the observable property of every result in
   that record that does not carry one of its own.  On a result member
   it identifies the observable property of that result alone and takes
   precedence over the record's.

   Every annotation identifies exactly one observable property for the
   node it is attached to.  A missing or unresolved reference is
   indeterminate and MUST NOT be repaired from labels, mappings, result
   schemas, units, descriptions, property names, or samples.

   The feature, procedure, and temporal roles of a record are shared by
   every result in it.  Where a record carries more than one result, a
   resultQuality on the record qualifies all of them, and qualifying one
   result on its own requires modelling that result as a nested object.

   Example of a record with two results:

Vasters                  Expires 7 February 2027               [Page 18]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   {
     "name": "BuoySurfacePacket",
     "type": "object",
     "properties": {
       "buoy_id": {
         "type": "string",
         "semanticRole": "featureOfInterest"
       },
       "measured_at": {
         "type": "datetime",
         "description": "Time both results occurred",
         "examples": ["2026-07-27T12:00:00Z"],
         "semanticRole": "phenomenonTime"
       },
       "sea_surface_temperature": {
         "type": "double",
         "unit": "Cel",
         "examples": [18.4],
         "semanticRole": "observationValue",
         "observedProperty": {
           "reference":
           "https://vocab.nerc.ac.uk/collection/P01/current/CTMPZZ01/",
           "kind": "nerc-p01"
         }
       },
       "practical_salinity": {
         "type": "double",
         "unit": "1",
         "examples": [35.1],
         "semanticRole": "observationValue",
         "observedProperty": {
           "reference":
           "https://vocab.nerc.ac.uk/collection/P01/current/PSLTZZ01/",
           "kind": "nerc-p01"
         }
       }
     },
     "required": [
       "buoy_id", "measured_at", "sea_surface_temperature",
       "practical_salinity"
     ],
     "additionalProperties": false
   }

Vasters                  Expires 7 February 2027               [Page 19]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

5.2.  Semantic Mappings and Result Hints

   An authority MAY publish semantic mappings from an observable-
   property definition to other identified concepts, using relation
   kinds such as exactMatch, closeMatch, broader, narrower, related, and
   quantityKind.  Mapping targets MUST be absolute URIs, and a mapping
   SHOULD carry a review state such as proposed, reviewed, or rejected.

   Only a reviewed exactMatch can provide evidence that two distinct
   identifiers denote the same observable property. closeMatch,
   hierarchy, relatedness, label similarity, and quantity-kind
   classification do not establish equivalence, and no mapping alone
   authorizes execution.

   A quantityKind mapping can reference a QUDT QuantityKind [QUDT] as a
   classification and compatibility hint.  Other mappings can target CF
   Standard Names, SOSA/SSN concepts, or agency vocabularies
   [CF-STANDARD-NAMES] [SOSA-SSN].

   An authority MAY identify an expected result schema.  That schema and
   any quantity-kind mapping are hints; the actual result schema and
   JSON Structure Units annotations remain authoritative.  An
   observable-property definition MUST NOT override unit semantics or
   duplicate authoritative dimensions, unit lists, conversion factors,
   or conversion formulas.

5.3.  The semanticRole Keyword

   The semanticRole keyword identifies the observation or operational
   function of an annotated value.

   The value of semanticRole MUST be one of a closed set of permitted
   values defined in this section.  A semanticRole value is never a URI;
   terms drawn from external vocabularies are carried by concepts
   instead.

   semanticRole is scalar; therefore each annotated schema element can
   carry one semanticRole value.

   One containing type MUST NOT declare two direct members with the same
   value for any of phenomenonTime, resultTime, effectiveTime,
   phenomenonTimeStart, phenomenonTimeEnd, effectiveTimeStart,
   effectiveTimeEnd, ingestionTime, scheduledTime, actualTime, or
   forecastIssueTime.  Each of these roles identifies one position, and
   every rule in this document that resolves such a role to a member
   presumes one.  A type declaring two leaves those rules unresolvable
   rather than ambiguous.

Vasters                  Expires 7 February 2027               [Page 20]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   The observation-result and feature roles carry no such restriction.
   Repetition is meaningful for them, and the sections defining them
   state what it projects.

5.3.1.  Observation Result Concern

   A record using the roles of this concern, together with the feature
   and procedure roles defined below:

   {
     "name": "WaterLevelObservation",
     "type": "object",
     "observedProperty": {
       "reference": "https://example.org/props/water-level/v1",
       "kind": "example-catalog"
     },
     "properties": {
       "station": {
         "type": "string",
         "examples": ["USGS-12149000"],
         "semanticRole": "featureOfInterest"
       },
       "procedure": {
         "type": "string",
         "examples": ["Pressure transducer"],
         "semanticRole": "observingProcedure"
       },
       "result": {
         "type": "double",
         "description": "Water level above datum",
         "unit": "m",
         "examples": [2.47],
         "semanticRole": "observationValue"
       },
       "quality": {
         "type": "string",
         "description": "Quality classification for this result",
         "examples": ["validated", "estimated"],
         "semanticRole": "resultQuality"
       }
     },
     "required": ["station", "procedure", "result", "quality"],
     "additionalProperties": false
   }

Vasters                  Expires 7 February 2027               [Page 21]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

5.3.1.1.  observationValue

   A property carrying the result of an observation act.

   An observationValue is the outcome of one observation act, not the
   act itself.  Each act is represented by one complete value in one
   annotated property.  Structured or composite results can be
   represented with an object, tuple, or another compatible compound
   type.  Multiple observationValue properties in the same containing
   type represent multiple results, not one combined act.

5.3.1.2.  resultQuality

   One result-quality value associated with the observation,
   corresponding to ISO result semantics [ISO19156].

   resultQuality qualifies the observationValue; it is not the result
   value itself.

   A single observation act can carry multiple quality qualifiers, and
   each direct property with semanticRole: resultQuality projects one of
   them.

   The value schema or external vocabulary defines the quality scale.
   This specification defines no threshold, ordering, confidence model,
   or processing effect.  Omission does not imply acceptable quality.
   Procedure-level quality metadata describes the measuring process in
   general and is distinct from resultQuality, which describes one
   observation result.

5.3.2.  Feature and Procedure Concern

   A record using the roles of this concern:

Vasters                  Expires 7 February 2027               [Page 22]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   {
     "name": "RiverSampleObservation",
     "type": "object",
     "observedProperty": {
       "reference": "https://example.org/props/dissolved-oxygen/v1",
       "kind": "example-catalog"
     },
     "properties": {
       "observationId": { "type": "uuid" },
       "waterBody": {
         "type": "string",
         "description": "River water body ultimately of interest",
         "examples": ["Rhine", "Niers", "Schwalm"],
         "semanticRole": "ultimateFeatureOfInterest"
       },
       "sampleParcel": {
         "type": "string",
         "description": "Sampled water parcel directly observed",
         "examples": ["Surface sample at station 17"],
         "semanticRole": "proximateFeatureOfInterest"
       },
       "sampler": {
         "type": "uri",
         "description": "Instrument identifier from a device catalogue",
         "examples": [
           "https://vocab.nerc.ac.uk/collection/L22/current/TOOL1248/"
         ],
         "semanticRole": "observingProcedure"
       },
       "dissolvedOxygen": {
         "type": "double",
         "unit": "mg/L",
         "semanticRole": "observationValue"
       }
     },
     "required": [
       "observationId", "waterBody", "sampleParcel", "sampler",
       "dissolvedOxygen"
     ],
     "additionalProperties": false
   }

Vasters                  Expires 7 February 2027               [Page 23]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

5.3.2.1.  featureOfInterest

   Value identifying or describing the feature whose property is
   observed: the entity that is the subject of the observation.  It is
   distinct from observedProperty, which identifies which property is
   observed, from observingProcedure, which identifies how the value is
   produced, and from observationValue, which carries the result.

   The annotated property's value can be a scalar, object, tuple, or
   collection.  The property schema defines representation, cardinality,
   and requiredness.

   Where the feature is a member of a collection held elsewhere in the
   document, JSON Structure Relations [JSTRUCT-RELATIONS] states the
   reference:

   {
     "definitions": {
       "HydroGraph": {
         "type": "object",
         "name": "HydroGraph",
         "properties": {
           "riverReaches": {
             "type": "array",
             "items": { "$ref": "#/definitions/RiverReach" }
           },
           "observations": {
             "type": "array",
             "items": { "$ref": "#/definitions/RiverObservation" }
           }
         },
         "required": ["riverReaches", "observations"],
         "additionalProperties": false
       },
       "RiverReach": {
         "type": "object",
         "name": "RiverReach",
         "identity": ["reachId"],
         "properties": {
           "reachId": { "type": "string" },
           "riverName": { "type": "string" },
           "fromNodeId": { "type": "string" },
           "toNodeId": { "type": "string" },
           "lengthMeters": { "type": "double", "unit": "m" }
         },
         "required": ["reachId", "riverName", "fromNodeId", "toNodeId"],
         "additionalProperties": false
       },

Vasters                  Expires 7 February 2027               [Page 24]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

       "RiverObservation": {
         "type": "object",
         "name": "RiverObservation",
         "identity": ["observationId"],
         "properties": {
           "observationId": { "type": "uuid" },
           "reachIdRef": {
             "type": "string",
             "description": "River reach identifier",
             "semanticRole": "featureOfInterest"
           },
           "waterLevel": {
             "type": "double",
             "semanticRole": "observationValue",
             "unit": "m"
           }
         },
         "relations": {
           "featureReachRef": {
             "cardinality": "single",
             "targettype": { "$ref": "#/definitions/RiverReach" },
             "scope": "#/definitions/HydroGraph/properties/riverReaches"
           }
         },
         "required": ["observationId", "reachIdRef", "waterLevel"],
         "additionalProperties": false
       }
     }
   }

   In an instance, reachIdRef carries the same identifier value used by
   the relation target identity, for example "RR-1042".

5.3.2.2.  proximateFeatureOfInterest

   Value identifying or describing the feature directly involved in
   observing.

   This role identifies the immediate feature participating in
   measurement context (for example a sampled parcel).  Where the
   observation involves sampling, this is the feature that ISO 19156
   [ISO19156] calls a sampling feature.

5.3.2.3.  ultimateFeatureOfInterest

   Value identifying or describing the feature ultimately of interest.

Vasters                  Expires 7 February 2027               [Page 25]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   This role identifies the broader feature for which the observation is
   semantically interpreted.

   Neither proximate nor ultimate feature is inferred from the other.
   When featureOfInterest and specialized FoI roles coexist, processors
   MUST preserve them as separate declarations and MUST NOT assume
   equivalence.  Feature identity MUST NOT be inferred from observation
   identity, location, property names, or transport metadata.

5.3.2.4.  observingProcedure

   Value identifying or describing the procedure used for the
   observation act.

   Procedure identity is comparability-critical: different procedures
   can yield different biases or meanings for the same property and
   feature.  Equality is evidence for candidate grouping, not proof of
   statistical interchangeability.  When a shared catalog is available,
   procedure identifiers SHOULD be expressed as URIs; a device or
   instrument registry serves where the procedure is effectively defined
   by the instrument or sampler used.

5.3.3.  Temporal Concern (Observation Time)

   A record using the roles of this concern:

Vasters                  Expires 7 February 2027               [Page 26]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   {
     "name": "WaterLevelBulletin",
     "type": "object",
     "properties": {
       "station_id": {
         "type": "string",
         "semanticRole": "featureOfInterest"
       },
       "observed_at": {
         "type": "datetime",
         "description": "Time the water level applied at the station",
         "examples": ["2026-07-27T12:00:00Z"],
         "semanticRole": "phenomenonTime"
       },
       "published_at": {
         "type": "datetime",
         "description": "Time when the result became available",
         "examples": ["2026-07-27T12:00:04Z"],
         "semanticRole": "resultTime"
       },
       "in_force": {
         "type": "object",
         "description": "Period during which the bulletin is in force",
         "semanticRole": "effectiveTime",
         "properties": {
           "start": { "type": "datetime" },
           "end": { "type": "datetime" }
         },
         "required": ["start", "end"],
         "additionalProperties": false
       },
       "water_level": {
         "type": "double",
         "unit": "m",
         "semanticRole": "observationValue"
       }
     },
     "required": [
       "station_id", "observed_at", "published_at", "in_force",
       "water_level"
     ],
     "additionalProperties": false
   }

5.3.3.1.  phenomenonTime

   Time during which the result applies to the observed property.  It
   can be represented as an instant or period.

Vasters                  Expires 7 February 2027               [Page 27]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   When used for an instant, phenomenonTime MUST annotate a value whose
   Core type and reference binding together encode a temporal position.
   It MAY instead annotate a named object or tuple representing a
   period.

5.3.3.2.  resultTime

   Temporal position at which the result became available.

   resultTime MUST annotate a value whose Core type and reference
   binding together encode a temporal position.

5.3.3.3.  effectiveTime

   Period during which the record is in force and its use is intended.

   effectiveTime MAY annotate a named object or tuple representing a
   period.

   effectiveTime qualifies the record and not the phenomenon.  It states
   how long a warning, advisory, or other issued statement is meant to
   be acted on, and it gives no boundary to any observed property.  A
   record that describes a period of the world, including a forecast,
   states that period with phenomenonTime or with phenomenonTimeStart
   and phenomenonTimeEnd.  The two are independent: a warning in force
   for twelve hours may concern a phenomenon lasting minutes.

   This document defines no record-versioning axis.  The role is named
   effectiveTime rather than validTime because the latter names the
   bitemporal valid time of ISO 19108 [ISO19108]. effectiveTime is not
   that valid time, which pairs the period a fact is held true of the
   world with the period a system recorded it, and a processor MUST NOT
   read it as one.

   "Time" or "Duration" in any ISO, boundary, or operational role name
   defined by this document does not require a Gregorian, ISO 8601, or
   RFC 3339 encoding.  The semanticRole states semantics; the Core type
   and any temporalReferenceSystem state representation and reference
   semantics.

5.3.4.  Temporal Concern (Flattened Period Boundaries)

   A record using the roles of this concern.  The two pairs are
   independent axes: the phenomenon-time pair bounds what the result is
   about, and the effective-time pair bounds how long the record is in
   force.

Vasters                  Expires 7 February 2027               [Page 28]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   {
     "name": "AirQualityAdvisory",
     "type": "object",
     "properties": {
       "site_id": {
         "type": "string",
         "semanticRole": "featureOfInterest"
       },
       "averaging_window_opens": {
         "type": "datetime",
         "examples": ["2026-07-27T12:00:00Z"],
         "semanticRole": "phenomenonTimeStart"
       },
       "averaging_window_closes": {
         "type": "datetime",
         "examples": ["2026-07-27T13:00:00Z"],
         "semanticRole": "phenomenonTimeEnd"
       },
       "advisory_effective_at": {
         "type": "datetime",
         "examples": ["2026-07-27T15:00:00Z"],
         "semanticRole": "effectiveTimeStart"
       },
       "advisory_expires_at": {
         "type": "datetime",
         "examples": ["2026-07-28T03:00:00Z"],
         "semanticRole": "effectiveTimeEnd"
       },
       "mean_pm25": {
         "type": "double",
         "unit": "ug/m3",
         "semanticRole": "observationValue"
       }
     },
     "required": [
       "site_id",
       "averaging_window_opens",
       "averaging_window_closes",
       "advisory_effective_at",
       "advisory_expires_at",
       "mean_pm25"
     ],
     "additionalProperties": false
   }

Vasters                  Expires 7 February 2027               [Page 29]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

5.3.4.1.  phenomenonTimeStart

   Temporal position encoding the start of the phenomenonTime period.

   phenomenonTimeStart MUST annotate a value whose Core type and
   reference binding together encode a temporal position.

5.3.4.2.  phenomenonTimeEnd

   Temporal position encoding the end of the phenomenonTime period.

   phenomenonTimeEnd MUST annotate a value whose Core type and reference
   binding together encode a temporal position.

5.3.4.3.  effectiveTimeStart

   Temporal position encoding the start of the effectiveTime period.

   effectiveTimeStart MUST annotate a value whose Core type and
   reference binding together encode a temporal position.

5.3.4.4.  effectiveTimeEnd

   Temporal position encoding the end of the effectiveTime period.

   effectiveTimeEnd MUST annotate a value whose Core type and reference
   binding together encode a temporal position.

   A paired start and end projects one period, not two separate
   attributes.  Period closure is not supplied by these role names.
   This specification uses half-open [start,end) periods only for
   phenomenonTimeRelation; another convention requires a separate
   representation or profile.

5.3.5.  Temporal Concern (Operational Event Time)

   A planned activity, its execution, and its acceptance by a receiving
   system:

Vasters                  Expires 7 February 2027               [Page 30]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   {
     "name": "SamplingRun",
     "type": "object",
     "properties": {
       "run_id": { "type": "uuid" },
       "scheduled_sample_time": {
         "type": "datetime",
         "description": "Planned time for sample collection",
         "examples": ["2026-07-27T14:00:00Z"],
         "semanticRole": "scheduledTime"
       },
       "actual_sample_time": {
         "type": "datetime",
         "description": "Time when sample collection actually occurred",
         "examples": ["2026-07-27T14:07:12Z"],
         "semanticRole": "actualTime"
       },
       "ingested_at": {
         "type": "datetime",
         "description": "Time the receiving system accepted the record",
         "examples": ["2026-07-27T14:09:30Z"],
         "semanticRole": "ingestionTime"
       },
       "station_id": {
         "type": "string",
         "semanticRole": "featureOfInterest"
       }
     },
     "required": [
       "run_id",
       "scheduled_sample_time",
       "actual_sample_time",
       "ingested_at",
       "station_id"
     ],
     "additionalProperties": false
   }

5.3.5.1.  ingestionTime

   Temporal position when a declared system accepted the record.

   ingestionTime MUST annotate a value whose Core type and reference
   binding together encode a temporal position.

Vasters                  Expires 7 February 2027               [Page 31]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

5.3.5.2.  scheduledTime

   Planned temporal position for an activity.

   scheduledTime MUST annotate a value whose Core type and reference
   binding together encode a temporal position.

5.3.5.3.  actualTime

   Temporal position when the planned activity occurred.

   actualTime MUST annotate a value whose Core type and reference
   binding together encode a temporal position.

5.3.5.4.  forecastIssueTime

   Forecast-specific resultTime: the temporal position when a forecast
   product was issued.

   forecastIssueTime MUST annotate a value whose Core type and reference
   binding together encode a temporal position.

   A forecast record states the position or period it describes with
   phenomenonTime, or with phenomenonTimeStart and phenomenonTimeEnd.  A
   forecast is an observation whose result time precedes its phenomenon
   time, and it carries the same temporal roles as any other
   observation; nothing about the phenomenon-time roles restricts them
   to positions that have already elapsed.

5.3.5.5.  forecastLeadDuration

   Duration between the forecast issue position and the phenomenon-time
   position the forecast describes.

   forecastLeadDuration MUST annotate Core duration or a numeric value
   with a temporal unit [JSTRUCT-UNITS].

   Example:

Vasters                  Expires 7 February 2027               [Page 32]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   {
     "name": "RiverStageForecast",
     "type": "object",
     "properties": {
       "station_id": {
         "type": "string",
         "semanticRole": "featureOfInterest"
       },
       "issued_at": {
         "type": "datetime",
         "description": "Time when the forecast bulletin was issued",
         "examples": ["2026-07-27T09:00:00Z"],
         "semanticRole": "forecastIssueTime"
       },
       "forecast_window": {
         "type": "object",
         "description": "Phenomenon-time period the forecast describes",
         "semanticRole": "phenomenonTime",
         "properties": {
           "start": { "type": "datetime" },
           "end": { "type": "datetime" }
         },
         "required": ["start", "end"],
         "additionalProperties": false
       },
       "lead_time": {
         "type": "duration",
         "description": "Duration from issue to the phenomenon time",
         "examples": ["PT6H"],
         "semanticRole": "forecastLeadDuration"
       },
       "predicted_water_level": {
         "type": "double",
         "unit": "m",
         "semanticRole": "observationValue"
       }
     },
     "required": [
       "station_id", "issued_at", "forecast_window",
       "predicted_water_level"
     ],
     "additionalProperties": false
   }

   These operational values describe the handling of the record.  A
   processor MUST NOT read any of them as phenomenonTime, resultTime,
   observedProperty, featureOfInterest, or observingProcedure.

Vasters                  Expires 7 February 2027               [Page 33]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

5.3.6.  Status Concern

5.3.6.1.  status

   State of the record itself, or of the feature it describes, such as
   whether a value is provisional, verified, superseded, or withdrawn.

   status MUST annotate a value drawn from a fixed set of states, which
   is a Core string or an integer type.  The states are defined outside
   this document.  The annotated schema MUST either constrain them with
   enum [JSTRUCT-CORE] or identify the set that defines them, which MAY
   be a vocabulary referenced via concepts.

   status qualifies the record rather than the phenomenon.  A change of
   status does not change what was observed, and a record MAY be
   reissued with a new status and an unchanged result.

   status and resultQuality are distinct. resultQuality states how good
   a result is, on a scale the quality vocabulary defines; status states
   how the record carrying it is to be treated.  A provisional record
   and a low-quality result are independent conditions, and a processor
   MUST NOT read either annotation as the other.

   Example:

   {
     "name": "WaterLevelRecord",
     "type": "object",
     "properties": {
       "water_level": {
         "type": "double",
         "unit": "m",
         "semanticRole": "observationValue"
       },
       "record_status": {
         "type": "string",
         "description": "Standing of this record in the lifecycle",
         "enum": ["provisional", "verified", "superseded", "withdrawn"],
         "examples": ["provisional"],
         "semanticRole": "status"
       }
     },
     "required": ["water_level", "record_status"],
     "additionalProperties": false
   }

Vasters                  Expires 7 February 2027               [Page 34]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

5.4.  The derivation Keyword

   The derivation keyword classifies how a result value was produced.

   When present, derivation MUST be one of:

    +============+====================================================+
    | Derivation | Meaning                                            |
    +============+====================================================+
    | measured   | Produced directly by an observation procedure      |
    |            | performing measurement.                            |
    +------------+----------------------------------------------------+
    | statistic  | Produced by summarizing a set of values with one   |
    |            | of the functions named by statistic (Section 5.5). |
    +------------+----------------------------------------------------+
    | calculated | Produced by a deterministic calculation that       |
    |            | statistic does not name.                           |
    +------------+----------------------------------------------------+
    | estimated  | Inferred from incomplete, indirect, or uncertain   |
    |            | evidence.                                          |
    +------------+----------------------------------------------------+
    | modeled    | Produced by a model, simulation, or predictive     |
    |            | procedure.                                         |
    +------------+----------------------------------------------------+

                                  Table 3

   Routine conversion, rounding, or serialization does not by itself
   change measured to calculated.  The category identifies no source,
   formula, software, or detailed procedure, and it is not a lineage
   model: it does not identify the act that produced the value or relate
   that value to the values it was derived from ([PROV-O]).

   statistic and calculated divide the calculations between them.  Where
   the result is one of the summaries this document names, the
   derivation is statistic and the statistic keyword names which one, so
   a reader can tell an hourly mean from an hourly maximum without
   reading prose.  Every other calculation is calculated, and the schema
   SHOULD explain the method in the description of the annotated schema.
   This document defines no expression language, and a processor MUST
   NOT parse a description or reproduce a calculation from it.

   The names alone do not divide the categories, and the tests below do.
   They are stated so that two authors describing the same value reach
   the same category.

Vasters                  Expires 7 February 2027               [Page 35]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   The first division is between measured and the rest, and it is the
   one that carries the most weight for a consumer.  A value is measured
   where it is what an observation procedure read, and it is not
   measured where any function, fit, inference, or model stood between
   the procedure and the value.  Unit conversion, rounding, and
   serialization are not such functions, as stated above.

   Determinism divides calculated from estimated and modeled.  Where the
   same inputs must yield the same output, and the function could be
   written down, the value is calculated however elaborate the
   arithmetic and however many inputs it consumes.  A dew point obtained
   from a measured temperature and a measured humidity by a published
   formula is calculated.

   Dependence on unobserved state divides modeled from estimated.  An
   estimated value carries only what the observations carry, arranged
   under an assumption about their error: an interpolated fill for a
   failed sensor, or a strike position derived from arrival times at
   several detectors, is estimated, because something was observed and
   the value is an inference from evidence that does not determine it.
   A modeled value carries information the observations do not contain,
   supplied by the model's own representation of the system, and the
   procedure would produce a value for a place and time at which nothing
   was observed at all.  A forecast temperature is modeled.  A value
   that a model produced and that observations then corrected, as in a
   reanalysis or an assimilated field, is modeled, because the model
   supplies the state and the observations only constrain it.

   Where the choice among calculated, estimated, and modeled is
   genuinely unclear, the schema SHOULD state the method in description.
   An author MUST NOT resolve such a case by choosing measured, and a
   processor MUST NOT infer a formula, a model, an uncertainty, or a
   procedure from any of these values.

   Example:

Vasters                  Expires 7 February 2027               [Page 36]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   {
     "name": "SeaStateReport",
     "type": "object",
     "properties": {
       "sea_state_index": {
         "type": "double",
         "description": "Composite sea-state index",
         "semanticRole": "observationValue",
         "derivation": "modeled"
       }
     },
     "required": ["sea_state_index"],
     "additionalProperties": false
   }

5.5.  The statistic Keyword

   The statistic keyword names the summary function that produced a
   result value from a set of values.

   Most summary functions are fully identified by their name.  A few are
   not: a percentile is not one function but a family, and naming the
   family without the rank identifies nothing. statistic therefore takes
   two forms.  A function that takes no parameter is written as a
   string, and a function that takes one is written as an object that
   names the function and carries the parameter.

   When statistic is a string, it MUST be one of:

Vasters                  Expires 7 February 2027               [Page 37]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

         +===================+==================================+
         | Statistic         | Meaning                          |
         +===================+==================================+
         | mean              | Arithmetic mean of the set.      |
         +-------------------+----------------------------------+
         | median            | Middle value of the ordered set. |
         +-------------------+----------------------------------+
         | mode              | Most frequent value of the set.  |
         +-------------------+----------------------------------+
         | minimum           | Least value of the set.          |
         +-------------------+----------------------------------+
         | maximum           | Greatest value of the set.       |
         +-------------------+----------------------------------+
         | sum               | Total of the set.                |
         +-------------------+----------------------------------+
         | count             | Number of values in the set.     |
         +-------------------+----------------------------------+
         | standardDeviation | Standard deviation of the set.   |
         +-------------------+----------------------------------+
         | variance          | Variance of the set.             |
         +-------------------+----------------------------------+
         | range             | Difference between the greatest  |
         |                   | and least value.                 |
         +-------------------+----------------------------------+

                                 Table 4

   When statistic is an object, it MUST carry a function member and the
   parameter member that function requires, and no other members.
   function MUST be one of:

      +============+============+==================================+
      | Function   | Parameter  | Meaning                          |
      +============+============+==================================+
      | percentile | percentile | Value below which the stated     |
      |            |            | percentage of the set falls.     |
      +------------+------------+----------------------------------+
      | nthHighest | rank       | Value at the stated position     |
      |            |            | counting down from the greatest. |
      +------------+------------+----------------------------------+
      | nthLowest  | rank       | Value at the stated position     |
      |            |            | counting up from the least.      |
      +------------+------------+----------------------------------+

                                 Table 5

Vasters                  Expires 7 February 2027               [Page 38]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   percentile MUST be a number greater than zero and less than one
   hundred, and rank MUST be an integer of two or more. percentile MUST
   be present when function is percentile and MUST NOT be present
   otherwise; rank MUST be present when function is nthHighest or
   nthLowest and MUST NOT be present otherwise.

   Both enumerations are closed.  A statistic that is a string outside
   the first table, or an object whose function is outside the second,
   is invalid.

   One meaning has one spelling.  A function that takes no parameter
   MUST be written in the string form, so { "function": "mean" } is
   invalid.  A percentile of zero or one hundred MUST be written as
   minimum or maximum, and a rank of one MUST be written as maximum or
   minimum, which is why the ranges above exclude them.  A quantile is
   expressed as the equivalent percentile, so a quantile of 0.95 is
   written as a percentile of 95.  Without these rules two schemas could
   declare the same statistic in ways that no equality test would match.

   A rank is not a percentile.  The fourth-highest value of a set of
   three hundred and sixty-five is the 99.18th percentile and of a set
   of ninety is the 96.7th, so neither form can be rewritten as the
   other without knowing how many values the set held, and statistic
   does not state that.  Both forms are needed because both are what
   definitions in force actually specify: an air quality limit is
   commonly expressed as a rank, and a service level objective as a
   percentile.

   statistic and the statistic derivation are one declaration in two
   parts.  A schema whose derivation is statistic MUST carry a statistic
   keyword, and a schema carrying a statistic keyword MUST have a
   derivation of statistic.  The derivation says the value summarizes a
   set, and the keyword says how.  Where phenomenonTimeRelation is
   accumulation, statistic MUST be the string sum.

   A calculation that no value in either table names is calculated
   rather than statistic, and Section 5.4 states what a schema does
   instead.

   A vocabulary term names the phenomenon and frequently excludes the
   summary function, so an hourly mean and an hourly maximum of one
   phenomenon carry the same observedProperty and differ only here.  Two
   results that carry the same observable property and different
   statistics are not comparable as like quantities.  The parameter is
   part of the statistic: a 95th percentile and a 99th percentile are
   different statistics, as are a fourth-highest and a fifth-highest,
   and a processor MUST NOT treat two parameterized statistics as alike
   unless both the function and the parameter agree.

Vasters                  Expires 7 February 2027               [Page 39]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   The set that the statistic summarizes is the one the other
   annotations already establish: the temporal roles give its extent in
   time, and the feature and procedure roles give its subject.  This
   document defines no other scoping, and the only argument statistic
   takes is the one that identifies the function.  It does not state a
   window alignment, a weighting, a sample count, a treatment of missing
   values, an interpolation method by which a percentile is obtained
   from a finite set, or a computation, and a processor MUST NOT
   recompute a result from it.

   Example:

   {
     "name": "HourlyAirTemperatureSummary",
     "type": "object",
     "observedProperty": {
       "reference":
       "http://vocab.nerc.ac.uk/standard_name/air_temperature/",
       "kind": "cf-standard-name"
     },
     "properties": {
       "station": {
         "type": "string",
         "examples": ["DWD-10382"],
         "semanticRole": "featureOfInterest"
       },
       "hour_start": {
         "type": "datetime",
         "examples": ["2026-07-27T12:00:00Z"],
         "semanticRole": "phenomenonTimeStart"
       },
       "hour_end": {
         "type": "datetime",
         "examples": ["2026-07-27T13:00:00Z"],
         "semanticRole": "phenomenonTimeEnd"
       },
       "temperature_mean": {
         "type": "double",
         "unit": "Cel",
         "description": "Mean air temperature over the hour",
         "examples": [21.4],
         "semanticRole": "observationValue",
         "derivation": "statistic",
         "statistic": "mean"
       },
       "temperature_max": {
         "type": "double",
         "unit": "Cel",

Vasters                  Expires 7 February 2027               [Page 40]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

         "description": "Greatest air temperature over the hour",
         "examples": [24.9],
         "semanticRole": "observationValue",
         "derivation": "statistic",
         "statistic": "maximum"
       }
     },
     "required": [
       "station", "hour_start", "hour_end", "temperature_mean",
       "temperature_max"
     ],
     "additionalProperties": false
   }

   The record below carries two parameterized statistics of the same
   observable over the same interval.  They differ only in the
   parameter, and nothing but the parameter distinguishes them.

Vasters                  Expires 7 February 2027               [Page 41]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   {
     "name": "RequestLatencySummary",
     "type": "object",
     "properties": {
       "window_start": {
         "type": "datetime",
         "examples": ["2026-07-27T12:00:00Z"],
         "semanticRole": "phenomenonTimeStart"
       },
       "window_end": {
         "type": "datetime",
         "examples": ["2026-07-27T12:05:00Z"],
         "semanticRole": "phenomenonTimeEnd"
       },
       "latency_p95": {
         "type": "double",
         "unit": "ms",
         "description": "Latency below which 95 percent completed",
         "examples": [128.4],
         "semanticRole": "observationValue",
         "derivation": "statistic",
         "statistic": { "function": "percentile", "percentile": 95 }
       },
       "latency_p99": {
         "type": "double",
         "unit": "ms",
         "description": "Latency below which 99 percent completed",
         "examples": [512.7],
         "semanticRole": "observationValue",
         "derivation": "statistic",
         "statistic": { "function": "percentile", "percentile": 99 }
       }
     },
     "required": [
       "window_start", "window_end", "latency_p95", "latency_p99"
     ],
     "additionalProperties": false
   }

   The record below carries a rank.  The fourth-highest daily maximum is
   the form in which an ozone air quality standard is stated, and it is
   not the same statistic as any percentile unless the number of days in
   the year is known.

Vasters                  Expires 7 February 2027               [Page 42]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   ========== NOTE: '\' line wrapping per RFC 8792 ===========

   {
     "name": "AnnualOzoneSummary",
     "type": "object",
     "observedProperty": {
       "reference": "http://vocab.nerc.ac.uk/standard_name/\
           mole_fraction_of_ozone_in_air/",
       "kind": "cf-standard-name"
     },
     "properties": {
       "site": {
         "type": "string",
         "examples": ["US-060370016"],
         "semanticRole": "featureOfInterest"
       },
       "year_start": {
         "type": "datetime",
         "examples": ["2025-01-01T00:00:00Z"],
         "semanticRole": "phenomenonTimeStart"
       },
       "year_end": {
         "type": "datetime",
         "examples": ["2026-01-01T00:00:00Z"],
         "semanticRole": "phenomenonTimeEnd"
       },
       "fourth_highest_daily_max_8h": {
         "type": "double",
         "unit": "[ppb]",
         "description": "Fourth-highest daily maximum 8-hour mean",
         "examples": [68.0],
         "semanticRole": "observationValue",
         "derivation": "statistic",
         "statistic": { "function": "nthHighest", "rank": 4 },
         "phenomenonTimeRelation": "interval"
       }
     },
     "required": [
       "site", "year_start", "year_end", "fourth_highest_daily_max_8h"
     ],
     "additionalProperties": false
   }

6.  Coded Value Annotations

Vasters                  Expires 7 February 2027               [Page 43]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

6.1.  The codedValues Keyword

   The codedValues keyword binds the annotated property to a code list,
   so that the coded value it carries can be resolved to the meaning the
   list assigns it.

   A coded value is a number or a short string that stands for a state
   in a register maintained elsewhere: a present-weather code, an
   airport identifier, a diagnosis code.  The register gives each code a
   meaning, and the value alone does not.  This keyword differs from the
   reference-style keywords that bind components to the axes of a space
   in that it binds a single value to a list of meanings, and it differs
   from concepts in that concepts binds the node to one term while
   codedValues binds the property to a whole enumeration that its
   instance values draw from.

   When present, codedValues MUST be an object with a REQUIRED reference
   and a REQUIRED kind, and no other members.

6.1.1.  The reference and kind Properties

   reference identifies one specific code list.  It MUST be an absolute
   URI [RFC3986], or, where kind is type, a type reference { "$ref":
   <JSON Pointer> } [JSTRUCT-CORE] to a shareable type definition that
   enumerates the codes. kind does not name the list; it classifies the
   register model the list belongs to, so that a processor knows how the
   list is organized and how a value joins to an entry.  Several lists
   of one model are distinguished by reference, not by kind: the
   country, currency, and language tables are three iso lists, and the
   location indicators and aircraft type designators are two icao lists.
   kind is an open enumeration; the following values are defined here:

Vasters                  Expires 7 February 2027               [Page 44]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

    +===========+====================================================+
    | Kind      | Kind of list                                       |
    +===========+====================================================+
    | wmo-codes | A register in the WMO Codes Registry [WMO-CODES].  |
    +-----------+----------------------------------------------------+
    | iso       | An ISO code table, such as the ISO 3166 country    |
    |           | codes [ISO3166], the ISO 4217 currency codes       |
    |           | [ISO4217], or the ISO 639 language codes [ISO639]. |
    +-----------+----------------------------------------------------+
    | unlocode  | The UN/LOCODE location code list [UNLOCODE].       |
    +-----------+----------------------------------------------------+
    | icao      | An ICAO code list, such as the location indicators |
    |           | of [ICAO7910] or the aircraft type designators of  |
    |           | [ICAO8643].                                        |
    +-----------+----------------------------------------------------+
    | iata      | An IATA code directory [IATA-CODES].               |
    +-----------+----------------------------------------------------+
    | iana      | An IANA registry [IANA-PROTOCOLS], such as the     |
    |           | Language Subtag Registry [IANA-LANGTAGS].          |
    +-----------+----------------------------------------------------+
    | icd       | A linearization of the WHO International           |
    |           | Classification of Diseases [WHO-ICD].              |
    +-----------+----------------------------------------------------+
    | snomed-ct | A SNOMED CT edition or reference set [SNOMED-CT].  |
    +-----------+----------------------------------------------------+
    | loinc     | The LOINC database [LOINC].                        |
    +-----------+----------------------------------------------------+
    | atc       | The WHO Anatomical Therapeutic Chemical            |
    |           | classification [WHO-ATC].                          |
    +-----------+----------------------------------------------------+
    | unspsc    | The UNSPSC commodity code set [UNSPSC].            |
    +-----------+----------------------------------------------------+
    | type      | A meta-type in the annotated schema whose          |
    |           | enumeration lists the codes, as Section 8          |
    |           | describes.                                         |
    +-----------+----------------------------------------------------+

                                 Table 6

   The annotated value MUST be of a scalar type, a string or an integer,
   of the kind the identified list uses for its notations.  Where kind
   is type, the identified type enumerates the code notations, and a
   value denotes the entry whose notation it equals.

   A value in an instance denotes the entry the register publishes for
   that value.  How the value is joined to the entry, whether by
   appending it to the register URI or by another rule, is stated by the
   register and not by this document.  Some registers, including

Vasters                  Expires 7 February 2027               [Page 45]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   [WMO-CODES], publish each entry at a dereferenceable URI; a reference
   to such a register identifies more often than it resolves, which is
   true of the other reference-style keywords as well.

   A missing or unresolved register is indeterminate and MUST NOT be
   repaired from labels, property names, descriptions, or samples.  A
   value that the register does not define is not made meaningful by
   this annotation.

   A processor is not required to dereference the URI.  This document
   does not define a resolution protocol, URI layout, storage model, or
   definition serialization.

6.1.2.  Example

   The property below carries a present-weather code from the WMO
   register for present weather, whose entries are the integers zero
   through several hundred.

   {
     "name": "SurfaceObservation",
     "type": "object",
     "properties": {
       "stationId": { "type": "string" },
       "presentWeather": {
         "type": "int32",
         "codedValues": {
           "reference": "http://codes.wmo.int/bufr4/codeflag/0-20-003",
           "kind": "wmo-codes"
         }
       }
     },
     "required": ["stationId", "presentWeather"],
     "additionalProperties": false
   }

7.  Measurement Conditioning Annotations

7.1.  The measurementConditioning Keyword

   The measurementConditioning keyword states the frequency weighting,
   time weighting, and level reference that a scalar measurement
   carries, so that two values of the same unit that were conditioned
   differently are not compared as like quantities.

   A weighted level is a single number, not a bundle of channels, and
   its unit does not record how it was made.  An A-weighted sound level
   and a Z-weighted one are both in decibels, and comparing them is a

Vasters                  Expires 7 February 2027               [Page 46]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   mistake the numbers do not prevent.  The weighting, the time
   constant, and the reference the level stands against are the hidden
   convention this keyword carries.

   When present, measurementConditioning MUST be an object with an
   OPTIONAL weighting, an OPTIONAL timeWeighting, and an OPTIONAL
   levelReference, and no other members.  At least one of the three MUST
   be present.  The annotated value MUST be of numeric type.

7.1.1.  The weighting Property

   weighting, when present, names the frequency weighting the value
   carries.  It is an open enumeration; the values defined here are the
   frequency weightings of [IEC61672-1]:

              +=======+====================================+
              | Value | Meaning                            |
              +=======+====================================+
              | a     | A-weighting.                       |
              +-------+------------------------------------+
              | c     | C-weighting.                       |
              +-------+------------------------------------+
              | z     | Zero-weighting, the flat response. |
              +-------+------------------------------------+

                                 Table 7

7.1.2.  The timeWeighting Property

   timeWeighting, when present, names the time weighting the value
   carries.  It is an open enumeration; the values defined here are the
   time weightings of [IEC61672-1]:

                     +=======+======================+
                     | Value | Meaning              |
                     +=======+======================+
                     | fast  | Fast time weighting. |
                     +-------+----------------------+
                     | slow  | Slow time weighting. |
                     +-------+----------------------+

                                 Table 8

   The impulse time weighting of the superseded IEC 651 is not among
   these; where a legacy dataset needs it, it is carried as an open
   value.

Vasters                  Expires 7 February 2027               [Page 47]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

7.1.3.  The levelReference Property

   levelReference, when present, states what the level is relative to.
   This is one property appearing in two keywords: the levelReference of
   audioChannels (Section 12.1.3) takes the same values with the same
   meanings, since both answer the same question about a quantity
   expressed on a logarithmic scale.

    +===============+=================================================+
    | Value         | Meaning                                         |
    +===============+=================================================+
    | soundPressure | The reference is 20 micropascals [ISO1683], and |
    |               | a level in decibels is sound pressure level.    |
    +---------------+-------------------------------------------------+
    | fullScale     | The reference is digital full scale, the        |
    |               | greatest level the representation admits, and a |
    |               | level in decibels is dBFS.                      |
    +---------------+-------------------------------------------------+

                                  Table 9

   The enumeration is open.  A value outside it MUST be an absolute URI
   [RFC3986] identifying another reference, because a level may be
   referred to a voltage, a power, or a quantity that the standard
   governing an instrument fixes, and this document does not enumerate
   what other bodies define.  A processor that does not know a value
   MUST preserve it, MUST NOT reject the schema for carrying it, and
   MUST NOT compare a level against one carrying a different reference.

7.1.4.  Example

   The property below carries an A-weighted, fast, sound-pressure level.

Vasters                  Expires 7 February 2027               [Page 48]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   {
     "name": "NoiseReading",
     "type": "object",
     "properties": {
       "sensorId": { "type": "string" },
       "soundLevel": {
         "type": "double",
         "unit": "dB",
         "measurementConditioning": {
           "weighting": "a",
           "timeWeighting": "fast",
           "levelReference": "soundPressure"
         }
       }
     },
     "required": ["sensorId", "soundLevel"],
     "additionalProperties": false
   }

8.  Reference System Meta-Types

   A reference system need not be published by an authority.  Where the
   kind of a reference-system keyword is type, reference is a type
   reference { "$ref": <JSON Pointer> } [JSTRUCT-CORE] to a shareable
   type definition, and that type definition is the definition of the
   system.  Such a type is a meta-type.  It is ordinarily maintained in
   its own document and brought into definitions with $import
   [JSTRUCT-IMPORT], so that one definition serves every schema that
   cites it.

   A meta-type declares the members of the system, and the annotation
   maps the members of the annotated schema onto them.  The two need not
   agree in member names, member order, or member count.

   A meta-type is an ordinary type definition that a schema author
   writes, and it is unrelated to the extension meta-schema of
   Section 14, which is the schema of this specification.

8.1.  The referenceRole Keyword

   referenceRole states the function of a member within a meta-type.  It
   MAY occur on a property, collection item, map value, or choice member
   schema of a type that a reference identifies, and it establishes
   nothing elsewhere.

   When present, referenceRole MUST be one of:

Vasters                  Expires 7 February 2027               [Page 49]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

          +===============+=====================================+
          | Value         | Function of the member              |
          +===============+=====================================+
          | position      | Carries a temporal position, mapped |
          |               | by position (Section 9.3).          |
          +---------------+-------------------------------------+
          | linearElement | Identifies a linear element, mapped |
          |               | by linearElement (Section 10.5).    |
          +---------------+-------------------------------------+
          | measure       | Carries a distance along a linear   |
          |               | element, mapped by measure.         |
          +---------------+-------------------------------------+
          | direction     | Qualifies direction of travel or    |
          |               | orientation, mapped by direction.   |
          +---------------+-------------------------------------+

                                  Table 10

   One meta-type MUST NOT declare two members with the same
   referenceRole.  A member without referenceRole is a component of the
   system that no annotation maps, and an annotated schema MAY carry it,
   under any name, or omit it.

   A mapping is established by referenceRole and never by a member name.
   A processor MUST NOT infer a role from the name of a member, and a
   meta-type that declares no member for a role a keyword requires is
   unusable by that keyword.

   A coordinate reference system takes no roles, because its meta-type
   is a tuple and the order of its elements establishes the axes
   (Section 10.1).  A vector reference frame takes no roles for the same
   reason (Section 10.2).

9.  Temporal Reference Annotations

   The keywords in this section concern temporal positions, the values
   that place an observation or an operational event on a time line.
   phenomenonTimeRelation states how a result relates to the position it
   accompanies, supportPeriod gives the length of the period a result
   characterizes where the record bounds it at one end,
   temporalReferenceSystem states how a position value is to be read,
   and cadence states how successive positions are expected to recur.

Vasters                  Expires 7 February 2027               [Page 50]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

9.1.  The phenomenonTimeRelation Keyword

   The phenomenonTimeRelation keyword refines how a result value relates
   to phenomenonTime.  When semanticRole: observationValue is also
   present, it describes the observation result.  It is not a
   replacement for phenomenonTime.

   When present, it MUST be one of:

       +==============+============================================+
       | Value        | Meaning                                    |
       +==============+============================================+
       | instant      | Result applies at the sibling temporal     |
       |              | position having role phenomenonTime.       |
       +--------------+--------------------------------------------+
       | untilNext    | Result applies from that position until    |
       |              | the next actual compatible observation.    |
       +--------------+--------------------------------------------+
       | interval     | Result characterizes a half-open           |
       |              | phenomenon-time period the record encodes. |
       +--------------+--------------------------------------------+
       | accumulation | Result is accumulated over that half-open  |
       |              | phenomenon-time period.                    |
       +--------------+--------------------------------------------+

                                  Table 11

   instant and untilNext can be resolved only when a sibling
   phenomenonTime annotation identifies a temporal position. interval
   and accumulation can be resolved when sibling phenomenonTimeStart and
   phenomenonTimeEnd annotations identify boundaries in a common
   reference regime or through an authoritative conversion, and can be
   resolved when supportPeriod states the length of the period and a
   sibling position anchors it (Section 9.2).  Otherwise the support is
   declared but its temporal extent is indeterminate.  Effective-time
   and operational roles do not supply phenomenon-time boundaries.

   These values state how a result relates to a phenomenon time and not
   how it was produced; the summary function, where there is one, is
   carried by statistic (Section 5.5).  They do not authorize summation
   or prove complete coverage.  For untilNext, the successor is the next
   actual observation with compatible resolved feature of interest,
   observed property, declared procedure, value type, unit, temporal
   binding, and support.  Cadence does not prove a successor exists;
   without one the support end is unknown.  Omission is not instant.

Vasters                  Expires 7 February 2027               [Page 51]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   Example. air_temperature holds until the next compatible observation,
   so it reads against the sibling phenomenonTime; rainfall is
   accumulated over the period, so it reads against the sibling boundary
   pair:

   {
     "name": "WeatherReport",
     "type": "object",
     "properties": {
       "observed_at": {
         "type": "datetime",
         "semanticRole": "phenomenonTime"
       },
       "window_opens": {
         "type": "datetime",
         "semanticRole": "phenomenonTimeStart"
       },
       "window_closes": {
         "type": "datetime",
         "semanticRole": "phenomenonTimeEnd"
       },
       "air_temperature": {
         "type": "double",
         "unit": "Cel",
         "semanticRole": "observationValue",
         "phenomenonTimeRelation": "untilNext"
       },
       "rainfall": {
         "type": "double",
         "unit": "mm",
         "semanticRole": "observationValue",
         "phenomenonTimeRelation": "accumulation"
       }
     },
     "required": [
       "observed_at",
       "window_opens",
       "window_closes",
       "air_temperature",
       "rainfall"
     ],
     "additionalProperties": false
   }

Vasters                  Expires 7 February 2027               [Page 52]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

9.2.  The supportPeriod Keyword

   The supportPeriod keyword states the length of the phenomenon-time
   period a result characterizes, for a period the record bounds at one
   end rather than two.  A mean wind speed over the ten minutes ending
   at the observation time, a half-hourly settlement quantity stamped
   with the instant its period opens, and a pressure change over the
   preceding three hours are all of that shape: the length is fixed by
   the publishing arrangement, and one position in the record fixes
   where the period sits.  Such a feed carries no second boundary and
   gains nothing from a schema that invents a member for one.

   When present, supportPeriod MUST be an object with a REQUIRED length
   and a REQUIRED anchor.  No other properties are permitted.

9.2.1.  The length Property

   length states the extent of the period and MUST express a positive
   interval in the temporal reference system applicable to the anchoring
   position.  For a Core datetime, date, or time, it MUST be a positive
   Core duration.  Another temporal reference system MAY use a numeric,
   string, or structured interval representation defined by that system,
   on the terms Section 9.4 states for period.

9.2.2.  The anchor Property

   anchor states which boundary of the period the anchoring position
   occupies and MUST be one of:

              +=======+=====================================+
              | Value | Meaning                             |
              +=======+=====================================+
              | start | The anchoring position opens the    |
              |       | period, which runs forward from it. |
              +-------+-------------------------------------+
              | end   | The anchoring position closes the   |
              |       | period, which runs back to it.      |
              +-------+-------------------------------------+

                                  Table 12

   The anchoring position is the sibling annotated phenomenonTimeStart
   when anchor is start, and the sibling annotated phenomenonTimeEnd
   when anchor is end.  Where the record carries no member in that role,
   the anchoring position is the sibling annotated phenomenonTime.
   Where it carries neither, the period has a length and no location,
   and the extent remains indeterminate.

Vasters                  Expires 7 February 2027               [Page 53]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   The period is half-open on the terms Section 9.1 states.  For an
   anchoring position t, an anchor of end gives [t - length, t) and an
   anchor of start gives [t, t + length).

   supportPeriod MUST NOT be present unless phenomenonTimeRelation is
   interval or accumulation, and MUST NOT be present where sibling
   phenomenonTimeStart and phenomenonTimeEnd annotations both identify
   boundaries, because the record then encodes the period and a stated
   length would restate or contradict it.

   The boundary roles do not subsume this keyword. phenomenonTimeStart
   and phenomenonTimeEnd annotate members, so they state a period only
   where the record carries a value at each end of it, and the
   resolution rules of this document read one sibling in each role.
   Support is a property of a result rather than of a record, and one
   record may carry results of differing extent: a buoy report may close
   a twenty-minute wave summary and a three-hour pressure change at a
   single observation time, leaving one place to put a boundary and two
   periods to state. supportPeriod is carried by the result it
   describes, so each result states its own extent, and a length fixed
   by the publishing arrangement is stated once in the schema rather
   than transmitted in every record.

   A support period is a fact about one value and a cadence is a fact
   about a producer.  The two are often numerically equal and are never
   the same statement.  A station reporting hourly a mean taken over the
   last ten minutes of each hour has a cadence of one hour and a support
   period of ten minutes, and a schema declaring only the cadence would
   leave a reader free to treat fifty minutes of every hour as observed.
   cadence does not bound a phenomenon time (Section 9.4), and
   supportPeriod asserts nothing about whether a successor record exists
   or when it arrives.

   Where the length is not fixed by the schema, because it varies with
   the station, the instrument, or the message, there is no length to
   state and a schema MUST NOT state a nominal one.  The extent is then
   indeterminate, and a schema SHOULD record in description what governs
   the length, so that a reader learns where to obtain it rather than
   assuming a value.

   Example.  A surface report carries a mean wind speed over the ten
   minutes ending at the observation time and a rainfall total
   accumulated over the hour that opens at the stated instant.  The
   record has one boundary member and two periods:

Vasters                  Expires 7 February 2027               [Page 54]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   {
     "name": "SurfaceReport",
     "type": "object",
     "properties": {
       "observed_at": {
         "type": "datetime",
         "examples": ["2026-07-27T12:50:00Z"],
         "semanticRole": "phenomenonTime"
       },
       "accumulation_opens": {
         "type": "datetime",
         "examples": ["2026-07-27T12:00:00Z"],
         "semanticRole": "phenomenonTimeStart"
       },
       "wind_speed": {
         "type": "double",
         "unit": "m/s",
         "semanticRole": "observationValue",
         "derivation": "statistic",
         "statistic": "mean",
         "phenomenonTimeRelation": "interval",
         "supportPeriod": { "length": "PT10M", "anchor": "end" }
       },
       "rainfall": {
         "type": "double",
         "unit": "mm",
         "semanticRole": "observationValue",
         "derivation": "measured",
         "phenomenonTimeRelation": "accumulation",
         "supportPeriod": { "length": "PT1H", "anchor": "start" }
       }
     },
     "required": [
       "observed_at",
       "accumulation_opens",
       "wind_speed",
       "rainfall"
     ],
     "additionalProperties": false
   }

   The record carries no phenomenonTimeEnd, so wind_speed anchors on
   observed_at and covers [12:40Z, 12:50Z). rainfall anchors on
   accumulation_opens and covers [12:00Z, 13:00Z).  The two periods
   overlap and neither is the other, and a reader that took the
   observation instant for both would attribute the hour's rain to ten
   minutes of it.

Vasters                  Expires 7 February 2027               [Page 55]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

9.3.  The temporalReferenceSystem Keyword

   The temporalReferenceSystem keyword identifies the temporal reference
   definition needed to interpret an encoded temporal position or
   duration.

   It attaches to a temporally typed property or to a type definition
   that serves as one.  Where that type is an object or tuple, position
   names the member that carries the position value.

   When present, temporalReferenceSystem MUST be an object with a
   REQUIRED reference string, a REQUIRED kind string, an OPTIONAL
   position string, and an OPTIONAL sortOrder string.  No other
   properties are permitted.

   Core temporal types need no annotation when their Core semantics are
   fully intended.  A non-Core or ambiguous encoding is indeterminate
   without one.

9.3.1.  The reference Property

   reference MUST identify one temporal reference definition.  Where
   kind is type it MUST be a type reference { "$ref": <JSON Pointer> }
   [JSTRUCT-CORE] to a shareable type definition, and otherwise it MUST
   be an absolute URI [RFC3986]. kind states which definition model the
   reference identifies.  This document does not define a resolution
   protocol, URI layout, storage model, or definition serialization.

   Where the identified definition has a domain of validity, an
   annotated position MUST lie in that domain.

9.3.2.  The kind Property

   kind classifies which definition model the URI identifies.  It is an
   open enumeration.  The following values are defined here:

Vasters                  Expires 7 February 2027               [Page 56]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

       +==================+========================================+
       | Kind             | Referenced definition                  |
       +==================+========================================+
       | ogc-trs          | A concept in the OGC temporal          |
       |                  | reference system register, whose       |
       |                  | entries follow ISO 19108 [ISO19108].   |
       +------------------+----------------------------------------+
       | ogc-temporal-crs | A GML TemporalCRS served by the OGC    |
       |                  | definitions server, establishing a     |
       |                  | temporal datum, origin, and coordinate |
       |                  | system [ISO19111] [OGC-TOPIC2].        |
       +------------------+----------------------------------------+
       | type             | A meta-type declaring a member whose   |
       |                  | referenceRole is position, alongside   |
       |                  | the components of the regime           |
       |                  | (Section 8).                           |
       +------------------+----------------------------------------+

                                  Table 13

   Other values MAY name further definition models.  Appendix A lists
   resolvable URIs for the registered kinds.

   Whichever model a kind names, the identified definition MUST
   establish the components applicable to the encoding it governs.
   Where it defines a compound regime that locates a position by scoped
   components [OGC-TOPIC25], it MUST state component order, the scope
   and reset behavior of each component, and the rules for comparing
   positions from different scopes.

   A type reference carries a regime that no register holds.  The
   referenced meta-type MUST declare a member whose referenceRole is
   position, and the type and unit of that member establish the
   encoding.  The position property maps the annotated member onto it.
   The remaining members of the meta-type are components of the regime
   that the annotation does not map.  What a type definition cannot
   express, such as reset behavior and comparison across scopes, is
   stated in its description.

9.3.3.  The position Property

   position is REQUIRED when the annotation is attached to an object or
   tuple and is prohibited otherwise.  It MUST name a direct member of
   that object or tuple, and that member MUST be REQUIRED.

   The named member carries the temporal position.  Its values MUST sort
   in the direction given by sortOrder under the ordering defined for
   its own type, which for a string is lexical order.  A compound

Vasters                  Expires 7 February 2027               [Page 57]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   position achieves this by rendering its components most significant
   first at fixed width.  A processor can therefore order and compare
   positions without implementing the referenced definition.

   The remaining members MAY hold the individual components,
   identifiers, or other detail.  A processor is not required to
   interpret them.

9.3.4.  The sortOrder Property

   sortOrder states how the ordering of the encoded value runs relative
   to temporal order.  When present, it MUST be one of:

        +==========+=============================================+
        | Value    | Ordering                                    |
        +==========+=============================================+
        | forward  | An increasing value is a later position.    |
        +----------+---------------------------------------------+
        | backward | An increasing value is an earlier position. |
        +----------+---------------------------------------------+

                                 Table 14

   When sortOrder is absent, the value is forward.

   Most definitions count from an epoch toward the present and are
   therefore forward.  An annotation citing a definition whose values
   count away from a datum into the past, such as years before present
   or a geologic time scale, MUST declare sortOrder as backward.

   sortOrder applies to the annotated value, or to the member named by
   position where one is named.  It states the direction of the ordering
   and nothing else, and a definition whose values do not order under
   their own type at all is not made orderable by declaring either
   value.

9.3.5.  Type Compatibility

   The referenced definition establishes an encoding, and the annotated
   schema MUST be able to carry it:

Vasters                  Expires 7 February 2027               [Page 58]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   +========================================+=========================+
   | Encoding established by the definition | Compatible schema       |
   +========================================+=========================+
   | A date and time in a calendar,         | Core datetime, date,    |
   | following [RFC3339]                    | time, or string         |
   +----------------------------------------+-------------------------+
   | A count of units elapsed from an epoch | a Core integer or       |
   |                                        | number type             |
   +----------------------------------------+-------------------------+
   | Any other encoding                     | string, or an object or |
   |                                        | tuple carrying position |
   +----------------------------------------+-------------------------+

                                 Table 15

   Where the definition establishes a unit for its axis, a numeric
   position MUST carry a unit or ucumUnit annotation compatible with
   that unit.  Epoch definitions differ in unit, so a count of seconds
   and a count of milliseconds from the same origin are distinct
   definitions rather than one definition with two encodings.

   How much of this a reader can check depends on kind.  An ogc-
   temporal-crs definition determines the encoding, since its axis
   states either a unit of measure, which takes a numeric position, or a
   date and time, which takes a string.  A type definition declares the
   type of each component and likewise determines it.  An ogc-trs
   concept names a time scale and establishes no axis, unit, or
   encoding, so the compatibility check is indeterminate, as it is for a
   kind outside this enumeration.

   The annotation does not change the JSON base type, turn a data value
   into an identifiable temporal object, or supply a conversion.  A
   processor MUST compare, order, or combine positions only within the
   same binding or through an authoritative transformation.  A position
   whose definition establishes only order MUST NOT be treated as a
   metric coordinate without additional authority.  Property names alone
   establish none of these semantics.

   Example.  The clock is defined once as a meta-type and cited by
   reference, so a record of another shape can name the same definition.
   The record names the mapped member ordinal rather than clockPosition,
   and position establishes the mapping; the remaining components are
   carried under the record's own names and are not mapped. ordinal
   renders the components at fixed width, so a processor can order two
   positions without implementing the definition.

Vasters                  Expires 7 February 2027               [Page 59]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   {
     "$schema":
     "https://json-structure.org/meta/semantic-annotations/v0/#",
     "$id": "https://schemas.example.org/racing-speed-observation",
     "name": "RacingSpeedObservation",
     "type": "object",
     "identity": ["observation_id"],
     "observedProperty": {
       "reference": "https://example.org/props/vehicle-speed/v1",
       "kind": "example-catalog"
     },
     "properties": {
       "observation_id": { "type": "uuid" },
       "entry_id": {
         "type": "string",
         "semanticRole": "featureOfInterest"
       },
       "race_clock": {
         "type": "object",
         "semanticRole": "phenomenonTime",
         "temporalReferenceSystem": {
           "reference": { "$ref": "#/definitions/RaceClockPosition" },
           "kind": "type",
           "position": "ordinal"
         },
         "properties": {
           "ordinal": {
             "type": "string",
             "description": "Fixed-width position, ordered lexically",
             "examples": ["2026-07-26/R/S03/L014/01250.5"]
           },
           "session": { "type": "string" },
           "stint": { "type": "uint32" },
           "lap": { "type": "uint32" },
           "distance_driven": { "type": "double", "unit": "m" }
         },
         "required": [
           "ordinal", "session", "stint", "lap", "distance_driven"
         ],
         "additionalProperties": false
       },
       "speed": {
         "type": "double",
         "unit": "km/h",
         "semanticRole": "observationValue",
         "phenomenonTimeRelation": "instant",
         "derivation": "measured"
       }

Vasters                  Expires 7 February 2027               [Page 60]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

     },
     "required": ["observation_id", "entry_id", "race_clock", "speed"],
     "additionalProperties": false,
     "definitions": {
       "RaceClockPosition": {
         "name": "RaceClockPosition",
         "type": "object",
         "description": "Motor-racing clock.",
         "properties": {
           "clockPosition": {
             "type": "string",
             "description": "Fixed-width components, sorting lexically",
             "referenceRole": "position"
           },
           "session": { "type": "string" },
           "stint": { "type": "uint32" },
           "lap": { "type": "uint32" },
           "distanceDriven": { "type": "double", "unit": "m" }
         },
         "required": ["clockPosition"]
       }
     }
   }

   The clock locates a position by session, stint, lap, and distance
   driven within the lap, with the components rendered most significant
   first in clockPosition.  Stint numbering is entry-specific.

   The compound position is comparable only under the rules of the
   identified regime: equal stint, lap, and distance values do not imply
   equal positions across sessions or entries.  Mapping this clock to
   UTC or elapsed session time requires an authoritative synchronization
   relation or transformation.

9.4.  The cadence Keyword

   The cadence keyword describes expected producer behavior across
   successive values of an annotated temporal position.  A temporal role
   such as phenomenonTime, resultTime, ingestionTime, or
   forecastIssueTime, when also present, gives that sequence an
   observation or operational meaning.

   When present, cadence MUST be an object with a REQUIRED kind string
   and an OPTIONAL period.  No other properties are permitted.

Vasters                  Expires 7 February 2027               [Page 61]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

9.4.1.  The kind Property

   kind states the expected recurrence pattern and MUST be one of:

    +===========+====================================================+
    | Kind      | Meaning                                            |
    +===========+====================================================+
    | fixed     | Observations are expected at a regular period.     |
    +-----------+----------------------------------------------------+
    | irregular | Observations occur without a regular period.       |
    +-----------+----------------------------------------------------+
    | onChange  | Observations occur when represented state changes. |
    +-----------+----------------------------------------------------+

                                 Table 16

9.4.2.  The period Property

   period is REQUIRED when kind is fixed and is prohibited otherwise.
   It MUST express a positive interval in the temporal reference system
   applicable to the annotated temporal position.  For a Core datetime,
   date, or time, it MUST be a positive Core duration.  Another temporal
   reference system MAY use a numeric, string, or structured interval
   representation defined by that system.

   That latitude is what makes a rapid cadence expressible, and a schema
   for one SHOULD use it rather than force the period into civil time.
   A duration is written in seconds and their decimal fractions, and
   many rates that are exact on their own clock have no exact expression
   there: audio sampled at 48 kHz advances one frame every 1/48000 of a
   second, so any duration written for it is rounded, and a consumer
   that places positions by accumulating it drifts further from the
   truth with every frame.  Writing the period more exactly does not
   help, because civil time cannot express the instants either.  A
   stream whose positions are counted is not a stream whose positions
   are seconds.

   Where the values are counted on a clock of their own, the schema
   declares that clock as a meta-type, names it in
   temporalReferenceSystem (Section 9.3), and gives period as a count of
   that clock's own units, which for a value recorded once per tick is
   the integer 1.  The cadence is then exact, because it is stated in
   the system the values are expressed in.

Vasters                  Expires 7 February 2027               [Page 62]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   The conversion to seconds is data rather than annotation.  A rate
   varies from one delivery to the next while the schema stays the same,
   so a member of the record carries it, annotated with a unit
   [JSTRUCT-UNITS], and a consumer MUST NOT assume a conventional value
   for it.  Where a schema serves one rate and no other, const or enum
   [JSTRUCT-CORE] pins the value on that member.

   No keyword binds a clock to the member carrying its rate.  A
   processor MUST NOT take a member to be the rate of a clock because of
   the member's name or because its unit is one of frequency, and MUST
   NOT convert a position counted on such a clock to elapsed civil time
   unless a relation to civil time is established outside these
   annotations.  The meta-type declaring the clock states that relation,
   or its absence, in its description (Section 9.3).

   Cadence is not delivery time, a service-level objective, a
   completeness assertion, or a phenomenon-time boundary.  It does not
   assert that every position has a record, that records arrive in
   order, or that an untilNext successor exists.

   Cadence is an expectation and not a constraint, and the distinction
   is normative.  A schema that declares a cadence constrains no
   instance document.  An instance whose values do not follow the
   declared cadence is not invalid for that reason, because a stream
   that misses a beat is late rather than malformed, and a processor
   MUST NOT reject an instance, a value, or a schema on the ground that
   observed timing departs from a declared cadence.  A runtime service
   level belongs to an agreement between a producer and a consumer, not
   to a schema.

   A consumer may still act on a cadence.  A declared period sizes a
   window, sets a threshold beyond which a value is treated as stale,
   and makes an absent value detectable as a gap rather than absorbed
   silently.  Each of those is a decision the consumer makes about its
   own processing.  None of them changes the meaning of a value, and
   none licenses a value to be supplied where none was recorded
   (Section 15).

   Example:

Vasters                  Expires 7 February 2027               [Page 63]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   {
     "name": "WindSpeedObservation",
     "type": "object",
     "properties": {
       "measured_at": {
         "type": "datetime",
         "description": "Instant to which the wind speed applies",
         "examples": ["2026-07-27T12:10:00Z"],
         "semanticRole": "phenomenonTime",
         "cadence": {
           "kind": "fixed",
           "period": "PT10M"
         }
       },
       "wind_speed": {
         "type": "double",
         "unit": "m/s",
         "semanticRole": "observationValue"
       }
     },
     "required": ["measured_at", "wind_speed"],
     "additionalProperties": false
   }

   A cadence too rapid for civil time, stated on a clock of its own:

Vasters                  Expires 7 February 2027               [Page 64]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   {
     "name": "AudioSampleFrame",
     "type": "object",
     "properties": {
       "frame_index": {
         "type": "int64",
         "description": "Sample count from the start of delivery",
         "semanticRole": "phenomenonTime",
         "temporalReferenceSystem": {
           "reference": { "$ref": "#/definitions/AudioSampleClock" },
           "kind": "type",
           "sortOrder": "forward"
         },
         "cadence": {
           "kind": "fixed",
           "period": 1
         }
       },
       "sample_rate": {
         "type": "int32",
         "unit": "Hz",
         "description": "Sample frames per second for this delivery"
       },
       "amplitude": {
         "type": "double",
         "semanticRole": "observationValue"
       }
     },
     "required": ["frame_index", "sample_rate", "amplitude"],
     "additionalProperties": false,
     "definitions": {
       "AudioSampleClock": {
         "name": "AudioSampleClock",
         "type": "object",
         "description": "Sample-frame count clock for one delivery.",
         "properties": {
           "frame_count": {
             "type": "int64",
             "description": "Sample count from the start of delivery.",
             "referenceRole": "position"
           }
         },
         "required": ["frame_count"],
         "additionalProperties": false
       }
     }
   }

Vasters                  Expires 7 February 2027               [Page 65]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   The clock advances one unit per frame and does not reset within a
   delivery, so positions sort numerically and are comparable within one
   delivery and not across deliveries.  Elapsed seconds are the count
   divided by the frame rate of the delivery, which the meta-type does
   not supply.

   The cadence here is one sample-clock unit and is exact.  Written as a
   duration it could only have been approximated: PT0.0000208333S is
   short of a forty-eight-kilohertz frame by about thirty-three
   picoseconds, which is nothing in one frame and a full sample every
   thirteen seconds of programme, growing without bound for as long as
   the recording runs.

10.  Spatial Reference Annotations

   Each keyword in this section has two parts. reference and kind
   identify an external definition of a reference system.  The remaining
   properties bind the components of that system to named members of the
   object or tuple carrying the annotation.  A position or a vector is
   held across several members, so these keywords attach to a complex
   type and are not meaningful on a scalar.

10.1.  The coordinateReferenceSystem Keyword

   The coordinateReferenceSystem keyword identifies the coordinate
   reference system [ISO19111] under which coordinate values held in
   properties of an object or tuple are to be interpreted.

   When present, coordinateReferenceSystem MUST be an object with a
   REQUIRED reference string, a REQUIRED kind string, and a REQUIRED
   coordinates array.  No other properties are permitted.

10.1.1.  The reference Property

   reference MUST identify one coordinate reference system whose
   definition establishes an ordered set of axes, each with an axis
   direction and unit of measure.  Where kind is type it MUST be a type
   reference { "$ref": <JSON Pointer> } [JSTRUCT-CORE] to a shareable
   type definition, and otherwise it MUST be an absolute URI [RFC3986].
   kind states which definition model the reference identifies.

   A processor is not required to dereference the URI, and a returned
   representation need not expose the axes.  This document does not
   define a resolution protocol, URI layout, storage model, or
   definition serialization.

Vasters                  Expires 7 February 2027               [Page 66]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

10.1.2.  The kind Property

   kind classifies which definition model the URI identifies.  It is an
   open enumeration.  The following values are defined here:

          +=========+==========================================+
          | Kind    | Referenced definition                    |
          +=========+==========================================+
          | ogc-crs | A GML CRS served by the OGC definitions  |
          |         | server, named according to the OGC name  |
          |         | type specification [OGC-NAMES].          |
          +---------+------------------------------------------+
          | epsg    | A record in the EPSG Geodetic Parameter  |
          |         | Dataset [EPSG].                          |
          +---------+------------------------------------------+
          | type    | A meta-type that is a tuple whose        |
          |         | elements in order are the axes of an     |
          |         | engineering or local system (Section 8). |
          +---------+------------------------------------------+

                                 Table 17

   Other values MAY name further definition models.

   A type reference carries an engineering or local system that no
   register holds.  The referenced meta-type MUST be a tuple, and the
   order given by its tuple keyword is the axis order. coordinates maps
   the annotated properties onto those elements by position, so the
   number of names in coordinates MUST equal the number of elements and
   each element establishes the unit of its axis.  Axis direction,
   datum, and origin are stated in the description of the meta-type or
   of its elements.

   Schema authors SHOULD use a registered definition where one exists.
   Appendix A lists resolvable URIs for the registered kinds.

10.1.3.  The coordinates Property

   coordinates MUST be a non-empty ordered array of distinct property
   names.  Every name MUST resolve to a direct property of the annotated
   object or tuple.  The property at array index zero supplies axis 1 of
   the referenced coordinate system, the property at index one supplies
   axis 2, and so on.  The number of names MUST equal the dimension of
   that coordinate system.

   This ordering is an assertion by the schema author.  It is not
   inferred from property names or from a representation returned by
   dereferencing reference.

Vasters                  Expires 7 February 2027               [Page 67]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   A name in coordinates MAY resolve to a property whose type is array
   or tuple.  Where it does resolve to an array, that name MUST be the
   only entry in coordinates, and the elements of the array instances
   MUST supply the axes in order rather than the named property
   supplying one axis.

   For a tuple, the number of elements MUST equal the dimension of the
   referenced system.  A schema using an array SHOULD constrain its
   length.  The axes of a coordinate reference system may carry
   differing units, which a tuple can state per element and an array
   cannot.

   Coordinate properties MUST have numeric types.  When a coordinate
   property has a unit or ucumUnit annotation, that unit MUST be
   compatible with the corresponding axis.  A processor MAY verify the
   asserted ordering, units, and dimension using a trusted authority-
   specific CRS database.  Without such a definition source, it MUST
   preserve the declaration but treat those checks and coordinate
   transformations as indeterminate.

   Properties not named by coordinates are not part of the coordinate.
   The annotation therefore applies safely to an existing object that
   also contains identity, temporal, status, or other values.

   An object or tuple MUST NOT carry more than one
   coordinateReferenceSystem annotation.  An object containing multiple
   coordinates SHOULD model each coordinate as a nested object.  This
   document does not define coordinate epochs for dynamic coordinate
   reference systems.

   The coordinate order is significant.  OGC CRS84 uses longitude,
   latitude:

Vasters                  Expires 7 February 2027               [Page 68]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   {
     "name": "Crs84Position",
     "type": "object",
     "coordinateReferenceSystem": {
       "reference": "http://www.opengis.net/def/crs/OGC/1.3/CRS84",
       "kind": "ogc-crs",
       "coordinates": ["lon", "lat"]
     },
     "properties": {
       "lat": {
         "type": "double",
         "unit": "deg"
       },
       "lon": {
         "type": "double",
         "unit": "deg"
       }
     },
     "required": ["lat", "lon"],
     "additionalProperties": false
   }

   EPSG:4326 [EPSG] uses its authoritative latitude, longitude axis
   order:

   {
     "name": "Epsg4326Position",
     "type": "object",
     "coordinateReferenceSystem": {
       "reference": "http://www.opengis.net/def/crs/EPSG/0/4326",
       "kind": "ogc-crs",
       "coordinates": ["lat", "lon"]
     },
     "properties": {
       "lat": {
         "type": "double",
         "unit": "deg"
       },
       "lon": {
         "type": "double",
         "unit": "deg"
       }
     },
     "required": ["lat", "lon"],
     "additionalProperties": false
   }

Vasters                  Expires 7 February 2027               [Page 69]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

10.1.4.  Vertical and Compound Systems

   A vertical coordinate reference system has one axis, and coordinates
   then names one property.  This is the binding that makes a height or
   a depth interpretable, because the number and its unit do not state
   what the value is measured from.

   The axis direction comes from the referenced definition and not from
   the annotation, so whether the axis is positive up or positive down
   is a fact about the identified system.  Where kind is type, the
   description of the meta-type or of its elements states it.

   The following excerpt binds a gauge reading to NAVD88 height:

   {
     "name": "GaugeHeightObservation",
     "type": "object",
     "coordinateReferenceSystem": {
       "reference": "http://www.opengis.net/def/crs/EPSG/0/5703",
       "kind": "ogc-crs",
       "coordinates": ["water_level"]
     },
     "properties": {
       "station": {
         "type": "string",
         "description": "Observed gauging station",
         "examples": ["USGS-12149000"],
         "semanticRole": "featureOfInterest"
       },
       "measured_at": {
         "type": "datetime",
         "examples": ["2026-07-27T12:00:00Z"],
         "semanticRole": "phenomenonTime"
       },
       "water_level": {
         "type": "double",
         "unit": "m",
         "description": "Water surface elevation",
         "examples": [2.47],
         "semanticRole": "observationValue"
       }
     },
     "required": ["station", "measured_at", "water_level"],
     "additionalProperties": false
   }

Vasters                  Expires 7 February 2027               [Page 70]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   Where a horizontal position and a height belong to one compound
   system, that system has one definition and one set of axes, so a
   single annotation names all of them in order.  The annotation of such
   an object reads:

   {
     "coordinateReferenceSystem": {
       "reference": "http://www.opengis.net/def/crs/EPSG/0/6349",
       "kind": "ogc-crs",
       "coordinates": ["lat", "lon", "height"]
     }
   }

   Where the height belongs to a different system from the horizontal
   position, or where it is a result rather than part of a position, the
   two are separate bindings.  Since an object carries at most one
   coordinateReferenceSystem, the schema models one of them as a nested
   object:

Vasters                  Expires 7 February 2027               [Page 71]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   {
     "name": "StationWaterLevel",
     "type": "object",
     "coordinateReferenceSystem": {
       "reference": "http://www.opengis.net/def/crs/EPSG/0/5703",
       "kind": "ogc-crs",
       "coordinates": ["water_level"]
     },
     "properties": {
       "station_position": {
         "type": "object",
         "coordinateReferenceSystem": {
           "reference": "http://www.opengis.net/def/crs/OGC/1.3/CRS84",
           "kind": "ogc-crs",
           "coordinates": ["lon", "lat"]
         },
         "properties": {
           "lat": { "type": "double", "unit": "deg" },
           "lon": { "type": "double", "unit": "deg" }
         },
         "required": ["lat", "lon"],
         "additionalProperties": false
       },
       "water_level": {
         "type": "double",
         "unit": "m",
         "examples": [2.47],
         "semanticRole": "observationValue"
       }
     },
     "required": ["station_position", "water_level"],
     "additionalProperties": false
   }

   This specification does not define a CRS, datum, coordinate
   operation, or transformation.  Those definitions and semantics come
   from ISO 19111 and the referenced authority.

10.2.  The vectorReferenceFrames Keyword

   The vectorReferenceFrames keyword identifies the reference frames on
   whose axes the components of vector quantities held in properties of
   an object or tuple are resolved.

   A vector quantity has a magnitude and a direction, and its components
   are its projections onto the axes of a frame, meaningless apart from
   it.  A frame is an ordered set of axis directions and has no origin,
   because moving the origin does not change a vector, whereas a

Vasters                  Expires 7 February 2027               [Page 72]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   coordinate reference system has one, fixed by its datum.  A record
   may carry both kinds of quantity: coordinateReferenceSystem binds the
   members that give a position (Section 10.1), and
   vectorReferenceFrames binds the members that give the components of a
   vector.

   A frame contributes directions only, and so does not establish the
   units of the members it binds.  The axes of a coordinate reference
   system may carry differing units, as in a geographic system with two
   angles and a height, but the components of a vector all carry the
   unit of the quantity.  The units of the members named by one frame
   MUST be mutually convertible and SHOULD be identical.

   When present, vectorReferenceFrames MUST be a non-empty array.  Each
   element MUST be an object with REQUIRED reference, kind, and
   components, an OPTIONAL variance, and no other members.  The keyword
   is an array because a single record may carry more than one vector
   quantity, and each quantity is resolved in its own frame.

10.2.1.  The reference and kind Properties

   reference and kind have the same value space and the same meaning as
   in coordinateReferenceSystem (Section 10.1), under one added
   condition: the axes of the referenced system MUST be directions
   rather than angles, since a component is a projection onto a
   direction.

   A registered coordinate reference system establishes axis directions,
   so it may serve as a frame wherever that condition holds.  Registries
   exist to identify positions, so most frames in which vectors are
   reported are not registered anywhere.  Such a frame is written as a
   tuple meta-type whose members, in the order given by tuple, are the
   axes, and whose member description values state the direction each
   axis points in.  The meta-type establishes the axes and their order,
   not the units of the annotated members.

10.2.2.  The components Property

   components behaves as coordinates does.  It MUST be a non-empty array
   of names, and it takes one of two forms.  In the first, every name is
   that of a direct property of numeric type, and the names are mapped
   by position onto the axes of the frame.  In the second, the array
   holds exactly one name, that of a direct property whose type is array
   or tuple and whose elements are of numeric type, and the elements of
   that property MUST supply the axes in order rather than the named
   property supplying one axis.  Because the components of a vector all
   carry one unit, an array serves here where it would not serve for a
   coordinate.

Vasters                  Expires 7 February 2027               [Page 73]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   Every name in components MUST resolve to a direct property of the
   annotated object or tuple.  The names within one components array
   MUST be distinct, since one value cannot be the component along two
   axes of one frame.  The number of axes supplied, whether by the names
   of the first form or by the elements of the single property of the
   second, MUST equal the number of axes the frame declares.  The
   ordering is an assertion by the schema author and is never inferred.

10.2.3.  The variance Property

   variance states how the components respond to a change of frame.
   When present, it MUST be one of:

      +===============+============================================+
      | Value         | Response                                   |
      +===============+============================================+
      | contravariant | The components transform with the change   |
      |               | of frame, as those of a displacement or a  |
      |               | velocity do.                               |
      +---------------+--------------------------------------------+
      | covariant     | The components transform with the inverse  |
      |               | transpose of the change of frame, as those |
      |               | of a gradient or a surface normal do.      |
      +---------------+--------------------------------------------+

                                 Table 18

   Writing M for the matrix that carries coordinates in one frame into
   coordinates in another, in the sense Section 10.4.1 fixes, a
   contravariant triple v becomes M v and a covariant triple w becomes
   the inverse transpose of M applied to w.  The change of frame is the
   passive one: the quantity does not move, the frame does.

   When variance is absent, the value is contravariant.  That is the
   default because the quantities most often reported, among them
   displacements, velocities, accelerations, and forces, are
   contravariant, and the covariant ones, among them gradients and
   surface normals, are the ones a schema author is likelier to be
   conscious of having.

Vasters                  Expires 7 February 2027               [Page 74]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   The distinction is invisible where two frames differ by a rotation
   alone, because the inverse transpose of a rotation is that rotation.
   It becomes visible as soon as they differ by a scaling or a shear.  A
   surface normal carried through a non-uniform scaling by the rule that
   carries a displacement ceases to be perpendicular to the surface it
   describes, and a pressure gradient carried the same way reports the
   wrong rate of change.  A processor that re-expresses components
   without reading variance is right for rotations and wrong for
   everything else, which is what this member exists to prevent.

10.2.4.  Multiple Frames and Shared Components

   Two elements MAY cite the same reference, which is how a record
   reporting two distinct vector quantities in one frame is written.  A
   property MAY be named by more than one element, which asserts that
   the frames share that axis and that the value is the same component
   in both, and is how one quantity expressed in two frames is written.
   The assertion is the schema author's, and a processor MUST NOT infer
   a shared axis from a shared property, from the names of the frames,
   or from equal values in samples.

   Two elements that name one property MUST declare the same variance,
   or omit it in both.  Components of differing variance along one
   shared axis agree under a rotation and part company under any other
   change of frame, so one value cannot stand for both.

   A property MAY also be named both by vectorReferenceFrames and by the
   coordinateReferenceSystem of the same object or tuple, as a position
   vector is.  Where it is, the unit established by the coordinate axis
   and the unit borne by the components of the vector MUST be mutually
   convertible.

   vectorReferenceFrames binds vector quantities and nothing else.  A
   rotation, a stress, a strain, or any other quantity whose components
   take more than one axis index is bound by tensorReferenceFrames
   (Section 10.3), since the declared order of a single frame cannot
   state which axis each component belongs to.  A quaternion carrying a
   rotation is bound by neither keyword: three of its four members lie
   along the axes of a frame and the fourth does not, so no ordered list
   of components states its binding.

   A reference that does not resolve leaves the frame indeterminate.  It
   does not make the annotation incorrect.

   In the following example a satellite navigation receiver reports a
   position and a velocity.  EPSG:4979 fixes the position; two of its
   three axes are angles, so it cannot serve as a vector frame, and the
   velocity cites EPSG:4978, whose axes are geocentric X, Y, and Z.  Re-

Vasters                  Expires 7 February 2027               [Page 75]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   expressing the record in another system would move the position by
   the whole of the transformation and would turn the velocity by its
   rotation alone, which is the distinction the two keywords carry.

   {
     "name": "NavigationFix",
     "type": "object",
     "coordinateReferenceSystem": {
       "reference": "http://www.opengis.net/def/crs/EPSG/0/4979",
       "kind": "ogc-crs",
       "coordinates": ["lat", "lon", "height"]
     },
     "vectorReferenceFrames": [
       {
         "reference": "http://www.opengis.net/def/crs/EPSG/0/4978",
         "kind": "ogc-crs",
         "components": ["vel_x", "vel_y", "vel_z"]
       }
     ],
     "properties": {
       "lat": { "type": "double", "unit": "deg" },
       "lon": { "type": "double", "unit": "deg" },
       "height": { "type": "double", "unit": "m" },
       "vel_x": { "type": "double", "unit": "m/s" },
       "vel_y": { "type": "double", "unit": "m/s" },
       "vel_z": { "type": "double", "unit": "m/s" }
     },
     "required": ["lat", "lon", "height", "vel_x", "vel_y", "vel_z"],
     "additionalProperties": false
   }

   Most frames have no registered identifier.  In the next example a
   magnetic field is reported in two such frames, each written as a
   meta-type.  The frames share their first axis, so the schema reports
   that component once, under bx, and names it in both elements.  The
   remaining components differ between the frames and are carried
   separately.

   {
     "name": "SolarWindSample",
     "type": "object",
     "vectorReferenceFrames": [
       {
         "reference": { "$ref": "#/definitions/GseFrame" },
         "kind": "type",
         "components": ["bx", "by_gse", "bz_gse"]
       },
       {

Vasters                  Expires 7 February 2027               [Page 76]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

         "reference": { "$ref": "#/definitions/GsmFrame" },
         "kind": "type",
         "components": ["bx", "by_gsm", "bz_gsm"]
       }
     ],
     "properties": {
       "bx": { "type": "double", "unit": "nT" },
       "by_gse": { "type": "double", "unit": "nT" },
       "bz_gse": { "type": "double", "unit": "nT" },
       "by_gsm": { "type": "double", "unit": "nT" },
       "bz_gsm": { "type": "double", "unit": "nT" }
     },
     "required": ["bx", "by_gse", "bz_gse", "by_gsm", "bz_gsm"],
     "additionalProperties": false,
     "definitions": {
       "GseFrame": {
         "name": "GseFrame",
         "type": "tuple",
         "description": "Geocentric Solar Ecliptic frame.",
         "properties": {
           "x": {
             "type": "double",
             "description": "Earth towards the Sun."
           },
           "y": {
             "type": "double",
             "description":
             "In the ecliptic plane, towards dusk, right-handed."
           },
           "z": {
             "type": "double",
             "description":
             "Parallel to the ecliptic pole, positive north."
           }
         },
         "tuple": ["x", "y", "z"]
       },
       "GsmFrame": {
         "name": "GsmFrame",
         "type": "tuple",
         "description": "Geocentric Solar Magnetospheric frame.",
         "properties": {
           "x": {
             "type": "double",
             "description": "Earth towards the Sun."
           },
           "y": {
             "type": "double",

Vasters                  Expires 7 February 2027               [Page 77]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

             "description":
             "Perpendicular to the dipole axis, right-handed."
           },
           "z": {
             "type": "double",
             "description":
             "In the plane of x and the dipole axis, positive north."
           }
         },
         "tuple": ["x", "y", "z"]
       }
     }
   }

   The frames are written separately because they differ, and they share
   their first axis because both take x from the Earth towards the Sun.
   The axis directions are those the NASA Satellite Situation Center
   states for these two frames [SSC-COORDS].

   This specification does not define a frame, an epoch, or a
   transformation between frames.  Those definitions come from the
   referenced authority or from the meta-type the schema itself
   supplies.

10.3.  The tensorReferenceFrames Keyword

   The tensorReferenceFrames keyword identifies the reference frames on
   whose axes the components of tensor quantities held in properties of
   an object or tuple are resolved.  A tensor quantity is a grid of
   numbers that means nothing without a frame to read it against.  Its
   rank is how many axes it takes to pick out one number of the grid:
   one for a vector, two for a stress or a rotation.  An engineer
   checking whether a bridge beam will crack uses nine numbers because
   the beam can be squeezed along its length and sheared across it at
   the same time, and no single number says both.

   At rank 1 the frame's declared order states the binding, which is
   what vectorReferenceFrames (Section 10.2) does and why frames
   requires at least two entries.  Above rank 1 the vector model no
   longer suffices and member names are insufficient.
   vectorReferenceFrames and tensorReferenceFrames coexist, because
   vectors are common and should be easy to declare.

   When present, tensorReferenceFrames MUST be a non-empty array.  Each
   element MUST be an object with a REQUIRED frames array, a REQUIRED
   components member, and an OPTIONAL symmetry string.  No other members
   are permitted.  The keyword is an array because one record may carry
   more than one tensor quantity.

Vasters                  Expires 7 February 2027               [Page 78]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

10.3.1.  The frames Property

   frames MUST be an array of at least two objects, each with REQUIRED
   reference and kind members whose values are as defined for
   vectorReferenceFrames (Section 10.2).  The number of entries is the
   rank of the tensor, and the index in position k ranges over the axes
   of the frame given by entry k, in the order that frame declares.

   One frame MAY be named by more than one entry, and is so named for a
   stress, a strain, or a seismic moment tensor.  Where the two entries
   of a rank-2 tensor name different frames, the tensor carries a vector
   in the second frame to a vector in the first, as for a rotation
   matrix or a Jacobian.

   Each entry MAY carry variance as defined in Section 10.2.3, stating
   how the index in that position responds to a change of the frame it
   ranges over.  The entries of one tensor need not agree.  A stress
   tensor is contravariant in both indices, while a Jacobian is
   contravariant in the first and covariant in the second, which is what
   makes it a map between frames rather than a quantity in one.

   Three entries give a rank-3 tensor, and one frame may fill them all.
   The piezoelectric strain coefficients of a crystal are one such
   tensor: an electric field applied along one axis strains the crystal
   across every pair of axes, so each coefficient is picked out by three
   axes of the same crystal frame.

   {
     "name": "PiezoelectricCoefficients",
     "type": "object",
     "tensorReferenceFrames": [
       {
         "frames": [
           {
             "reference": { "$ref": "#/definitions/CrystalAxes" },
             "kind": "type"
           },
           {
             "reference": { "$ref": "#/definitions/CrystalAxes" },
             "kind": "type"
           },
           {
             "reference": { "$ref": "#/definitions/CrystalAxes" },
             "kind": "type"
           }
         ],
         "components": "d"
       }

Vasters                  Expires 7 February 2027               [Page 79]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

     ],
     "properties": {
       "d": {
         "type": "array",
         "minItems": 3,
         "maxItems": 3,
         "items": {
           "type": "array",
           "minItems": 3,
           "maxItems": 3,
           "items": {
             "type": "array",
             "minItems": 3,
             "maxItems": 3,
             "items": { "type": "double", "ucumUnit": "C/N" }
           }
         }
       }
     },
     "required": ["d"],
     "additionalProperties": false,
     "definitions": {
       "CrystalAxes": {
         "name": "CrystalAxes",
         "type": "tuple",
         "description": "Orthogonal frame fixed by crystal symmetry.",
         "properties": {
           "x1": {
             "type": "double",
             "description": "First axis of that frame."
           },
           "x2": {
             "type": "double",
             "description": "Second axis, at a right angle to x1."
           },
           "x3": {
             "type": "double",
             "description": "Third axis, right-handed."
           }
         },
         "tuple": ["x1", "x2", "x3"]
       }
     }
   }

   d is nested three deep because frames has three entries, and each
   level is indexed by the three axes of CrystalAxes, so it holds
   twenty-seven values.  The outermost index is the axis of the applied

Vasters                  Expires 7 February 2027               [Page 80]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   field and the two inner ones are the axes of the strain it produces.
   Each level constrains its length to three [JSTRUCT-VALIDATION], which
   is how the shape the frames require is stated in the schema rather
   than left to the instance.

   symmetry MUST NOT be present unless frames has exactly two entries
   naming the same frame and declaring the same variance, or omitting it
   in both, since it speaks of an exchange of two indices ranging over
   one set of axes and a pair of indices of differing variance does not
   survive the exchange under a change of frame.  It MUST be symmetric,
   skewSymmetric, or none, and it is none where absent.  Under symmetric
   the component at row i and column j equals the component at row j and
   column i; under skewSymmetric it is the negation of it and the
   diagonal is zero.  The symmetries of tensors of higher rank, such as
   the minor and major symmetries of an elastic stiffness tensor, are
   not expressible here, and every component of such a tensor that is
   carried MUST be named individually.

10.3.2.  The components Property

   components MUST take one of two forms, each of which states the
   pairing of index to value in the schema, and neither of which admits
   a layout, packing, or multiplication convention as a separate
   declaration.

   The first form is a string naming a direct property of the annotated
   object or tuple whose type is an array or a tuple nested to exactly
   the depth given by the number of entries in frames, the outermost
   level indexed by the axes of the first entry and each further level
   by the next in turn, and whose innermost items are of a numeric type.
   A nesting whose depth differs from the number of entries in frames
   makes the annotation invalid.  At every level, the number of elements
   an instance carries MUST equal the number of axes declared by the
   frame of the corresponding entry, so a tuple, or an array whose
   length is constrained [JSTRUCT-VALIDATION], states the shape in the
   schema where a bare array leaves it to the instance.  The nesting
   carries the layout, so the row-major and column-major question does
   not arise, and a tensor declared symmetric or skewSymmetric is
   written out in full in this form.  Every position of the tensor is
   carried, so the rule of the paragraph after the next does not apply
   to this form.

   The second form is a non-empty array of objects, each with a REQUIRED
   index and a REQUIRED property and no other members. index MUST be an
   array of non-negative integers whose length equals the number of
   entries in frames, and whose integer in position k MUST be less than
   the number of axes declared by the frame of entry k. property MUST
   name a direct property of the annotated object or tuple having a

Vasters                  Expires 7 February 2027               [Page 81]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   numeric type.  Every component carried states its own index, so no
   packing order is defined here and the Voigt-style orderings in
   circulation need not be distinguished.  Within one components array
   no two entries may carry equal index values, and no two entries may
   name the same property.

   In the second form, a position named by no entry is determined by
   symmetry where symmetry is symmetric or skewSymmetric, and is
   otherwise undeclared; under none every position MUST be named.  Where
   symmetry is symmetric or skewSymmetric, at least one of each mirrored
   pair of positions MUST be named, and where both are named the
   instance values MUST stand in the relation that symmetry declares.
   The units of the members named by one element MUST be mutually
   convertible and SHOULD be identical.

   The Global CMT catalogue publishes a source solution for every
   significant earthquake as a fixed-column text record, and states the
   frame those solutions are resolved on only in the document describing
   that format: six moment-tensor elements against a spherical frame in
   which r is up, t is south, and p is east [GCMT-NDK].  The tensor is
   symmetric, so those six determine all nine, and the second form of
   components states the index of each without appeal to a packing
   order.  What a reader of the text file must look up, the schema
   carries.

   {
     "name": "MomentTensor",
     "type": "object",
     "tensorReferenceFrames": [
       {
         "frames": [
           {
             "reference": { "$ref": "#/definitions/UseFrame" },
             "kind": "type"
           },
           {
             "reference": { "$ref": "#/definitions/UseFrame" },
             "kind": "type"
           }
         ],
         "symmetry": "symmetric",
         "components": [
           { "index": [0, 0], "property": "mrr" },
           { "index": [1, 1], "property": "mtt" },
           { "index": [2, 2], "property": "mpp" },
           { "index": [0, 1], "property": "mrt" },
           { "index": [0, 2], "property": "mrp" },
           { "index": [1, 2], "property": "mtp" }

Vasters                  Expires 7 February 2027               [Page 82]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

         ]
       }
     ],
     "coordinateReferenceSystem": {
       "reference": "http://www.opengis.net/def/crs/EPSG/0/4326",
       "kind": "ogc-crs",
       "coordinates": ["lat", "lon"]
     },
     "properties": {
       "eventName": { "type": "string" },
       "centroidTime": { "type": "datetime" },
       "lat": { "type": "double", "unit": "deg" },
       "lon": { "type": "double", "unit": "deg" },
       "depth": { "type": "double", "ucumUnit": "km" },
       "mrr": { "type": "double", "ucumUnit": "dyn.cm" },
       "mtt": { "type": "double", "ucumUnit": "dyn.cm" },
       "mpp": { "type": "double", "ucumUnit": "dyn.cm" },
       "mrt": { "type": "double", "ucumUnit": "dyn.cm" },
       "mrp": { "type": "double", "ucumUnit": "dyn.cm" },
       "mtp": { "type": "double", "ucumUnit": "dyn.cm" }
     },
     "required": [
       "eventName", "centroidTime", "lat", "lon", "depth",
       "mrr", "mtt", "mpp", "mrt", "mrp", "mtp"
     ],
     "additionalProperties": false,
     "definitions": {
       "UseFrame": {
         "name": "UseFrame",
         "type": "tuple",
         "description":
         "Spherical frame of the Global CMT catalogue, at lat/lon.",
         "properties": {
           "r": { "type": "double", "description": "Up." },
           "t": { "type": "double", "description": "South." },
           "p": { "type": "double", "description": "East." }
         },
         "tuple": ["r", "t", "p"]
       }
     }
   }

   The following is the sample record printed in that same document: an
   earthquake beneath El Salvador on 1 January 2005, whose six elements
   give the orientation and the size of the movement on the fault, in
   dyne-centimetres.  The catalogue prints them scaled by a power of ten
   carried on a line of its own, and the instance carries the values
   themselves, that is, with the exponent applied.

Vasters                  Expires 7 February 2027               [Page 83]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   {
     "eventName": "C200501010120A",
     "centroidTime": "2005-01-01T01:20:05.1Z",
     "lat": 13.76,
     "lon": -89.08,
     "depth": 162.8,
     "mrr": 0.838e23,
     "mtt": -0.005e23,
     "mpp": -0.833e23,
     "mrt": 1.050e23,
     "mrp": -0.369e23,
     "mtp": 0.044e23
   }

   The value under mtp sits at row 1 and column 2, and the declaration
   of symmetric puts the same value at row 2 and column 1.  Nothing in
   the instance says so: the six numbers alone determine nine components
   only once the schema has stated the frame, the index of each, and the
   symmetry.

   UseFrame is a local frame, and up, south, and east are directions
   only once a point on the Earth is given.  The point is the one the
   coordinateReferenceSystem of the same object binds, and the
   description of the meta-type is where a schema says so.  This
   document defines no member that binds a frame to the position that
   orients it, and a processor MUST NOT infer such a binding from the
   presence of both keywords on one type.

   A rank-2 quantity whose two entries name different frames is a map
   from one frame to the other, and an attitude matrix, a Jacobian, and
   a sensor alignment are all of that shape. tensorReferenceFrames
   describes such a quantity correctly, but it says only what the
   indices range over.  It does not say that the numbers are a
   transformation, and it cannot describe the quaternion, the axis and
   angle, or the three Euler angles that the same transformation is more
   often published as.  Where the annotated properties carry a
   transformation, frameTransforms (Section 10.4) SHOULD be used
   instead.

10.4.  The frameTransforms Keyword

   The frameTransforms keyword identifies properties of an object or
   tuple that carry a transformation from one reference frame to
   another.

   The keywords before it bind quantities. coordinateReferenceSystem
   binds a position, vectorReferenceFrames binds a direction, and
   tensorReferenceFrames binds a quantity whose components take more

Vasters                  Expires 7 February 2027               [Page 84]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   than one axis index.  A transformation is none of those.  It is the
   map between two frames, and the numbers carrying it mean nothing
   until the sense of the map, the handedness of its angles, and the
   arrangement of its components are all settled.

   Common practice settles none of them.  NASA's Navigation and
   Ancillary Information Facility, which maintains the toolkit most
   planetary missions navigate with, states the position plainly: "there
   are no standards defining construction of quaternions, the underlying
   associated mathematics, or the connection to rotations.  In the
   absence of such standards, different organizations adopt disparate
   definitions, which makes communication difficult" [NAIF-QUAT].  The
   same paper enumerates what a reader must resolve before a rotation
   can be applied: whether a positive angle turns in the right-hand
   sense, whether the rotation turns a vector or turns the frame,
   whether the matrix multiplies from the left or the right, whether the
   sense runs from the base frame or towards it, and, for a quaternion,
   where the scalar sits and what sign its multiplication rule carries.
   Six independent choices, of which, as that paper observes, "the
   composition of several misunderstandings can lead to correct results
   in one context, incorrect in another, and frustration in general".
   The Robot Operating System reaches the same conclusion about Euler
   angles, which it discourages "due to having 24 'valid' conventions
   with different domains using different conventions by default"
   [REP-103].

   When present, frameTransforms MUST be a non-empty array.  Each
   element MUST be an object with REQUIRED from, to, encoding, and
   components, OPTIONAL rotationSequence and translation, and no other
   members.  The keyword is an array because one record may carry more
   than one transformation, as an attitude message does when it gives
   the orientation of a single instrument against two different
   reference frames.

10.4.1.  The Conventions This Document Fixes

   Every frame named by from or to MUST be right-handed and MUST declare
   exactly three axes, and a positive angle MUST be read as a rotation
   in the right-hand sense about the axis it is stated against.  Every
   encoding this keyword defines presupposes three dimensions, so a
   frame of any other arity cannot be named by either member.

Vasters                  Expires 7 February 2027               [Page 85]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   A transformation carries coordinates expressed in the from frame into
   coordinates expressed in the to frame.  Writing x for the coordinates
   of a vector in the from frame and x' for the coordinates of the same
   vector in the to frame, the transformation is the M for which x' = M
   x, and translation, where present, adds to that as x' = M x + t.
   This is the frame-transformation sense rather than the vector-
   rotation sense: the quantity does not move, the frame does.

   The Consultative Committee for Space Data Systems states that same
   sense for its attitude messages.  The quaternion "from frame A to
   frame B" is "the quaternion of the rotation that transforms the basis
   vectors of frame A into the basis vectors of frame B", and the matrix
   it corresponds to is defined by XB = MBA * XA [CCSDS-ADM].

   This document fixes these choices rather than offering them as
   members to be declared, and that committee is the precedent.  Its
   first issue made both the direction and the placement of the
   quaternion scalar into fields a producer filled in, ATTITUDE_DIR
   taking A2B or B2A and QUATERNION_TYPE taking FIRST or LAST
   [CCSDS-ADM1].  Its second issue deleted both, recording the rationale
   as "Simplicity of the standard" and, for the wider set of changes
   that pinned the meanings down, "To avoid misuse of exchange data"
   [CCSDS-ADM].  Fixing them cost that standard the ability to carry
   records laid out the other way, because its records are positional.
   It costs this document nothing, because components names members
   rather than positions.  A schema whose quaternion is stored scalar-
   last and one whose quaternion is stored scalar-first carry the same
   annotation, with the names written in the order fixed here.

10.4.2.  The from and to Properties

   from and to MUST each be an object with a REQUIRED reference and a
   REQUIRED kind, whose value spaces and meanings are those they have in
   vectorReferenceFrames (Section 10.2).  The axes of both frames MUST
   be directions rather than angles. variance MUST NOT appear in either,
   since a frame named by a transformation is not an index position of a
   quantity.

   from and to MAY cite the same reference.  A transformation between
   two realizations of one frame, or between one frame at two epochs, is
   written that way.

10.4.3.  The encoding Property

   encoding states which arrangement of numbers carries the
   transformation.  It is a closed enumeration, and a value outside it
   is invalid, because each value carries an arithmetic meaning that
   this document defines.

Vasters                  Expires 7 February 2027               [Page 86]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

      +===================+========================================+
      | Encoding          | Carried by                             |
      +===================+========================================+
      | quaternion        | Four members: the scalar, then the     |
      |                   | three components of the vector part.   |
      +-------------------+----------------------------------------+
      | axisAngle         | Four members: the angle, then the      |
      |                   | three components of the rotation axis. |
      +-------------------+----------------------------------------+
      | eulerAngles       | Three members: the angles of three     |
      |                   | successive intrinsic rotations.        |
      +-------------------+----------------------------------------+
      | rotationMatrix    | Nine values arranged three by three.   |
      +-------------------+----------------------------------------+
      | homogeneousMatrix | Sixteen values arranged four by four,  |
      |                   | acting on augmented coordinates.       |
      +-------------------+----------------------------------------+

                                 Table 19

   Every encoding but the last carries a rotation and nothing else, and
   an offset between the origins of the two frames is then carried by
   translation (Section 10.4.6) or not at all. homogeneousMatrix carries
   the rotation and the offset together in one matrix M4, acting on
   augmented coordinates as [x', 1] = M4 [x, 1] written as column
   vectors.  Its first three rows and first three columns are the
   rotation M, its fourth column holds in its first three entries the
   same three values translation would carry and in its fourth entry a
   one, and its fourth row is three zeroes and a one.

   The nine values of a rotationMatrix, and the first three rows and
   columns of a homogeneousMatrix, SHOULD be orthonormal with
   determinant positive one, within a tolerance appropriate to the
   numeric type.  A processor is not required to verify this, and this
   document defines no tolerance.  The remaining entries of a
   homogeneousMatrix MUST be as the previous paragraph states, so a
   projective matrix, a matrix carrying a scaling or a shear, and a
   matrix whose fourth row is anything other than three zeroes and a one
   are all outside this encoding.

Vasters                  Expires 7 February 2027               [Page 87]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   The first three entries of the fourth column of a homogeneousMatrix
   carry a length and the rest of the matrix is dimensionless, so those
   three entries are subject to the same unit rule as translation
   (Section 10.4.6): their units MUST be mutually convertible and SHOULD
   be identical.  A single nested property cannot state a unit for one
   position and not another, so a schema carrying a homogeneousMatrix in
   that form MUST establish those units in the referenced definition or
   in the indexed form of components, which names a separate property
   for each position.

10.4.4.  The components Property

   components names the members that carry the transformation, and its
   form follows encoding.

   For quaternion, axisAngle, and eulerAngles, components MUST be an
   array of names of direct properties of the annotated object or tuple,
   all of numeric type and all distinct, of the length the encoding
   requires.  Order within that array is fixed by this document.  It is
   never inferred from the order in which the properties are declared,
   from their names, or from their position in a tuple.

   For rotationMatrix and homogeneousMatrix, components MUST be either
   the name of one property whose type is an array or a tuple nested
   twice, the outer index selecting the row, or an array of indexed
   components in the form tensorReferenceFrames uses (Section 10.3),
   each stating its own index of two non-negative integers, row first.
   Neither form leaves a row-major or column-major reading open, which a
   flat array of nine or sixteen values would.

   In the nested form, each instance level MUST carry three elements for
   rotationMatrix and four for homogeneousMatrix.  In the indexed form,
   every position MUST be named, nine of them for rotationMatrix and
   sixteen for homogeneousMatrix, and each integer of an index MUST be
   less than three, respectively four. symmetry has no counterpart here,
   so no position is determined by any other and none may be left
   undeclared.

10.4.4.1.  Quaternions

   The four names given for quaternion are, in order, the member
   carrying the scalar and the members carrying the three components of
   the vector part, in the axis order the frames declare.  Writing a for
   the angle of the rotation that carries the from frame into the to
   frame and e for its unit axis, the scalar is cos(a/2) and each of the
   other three is sin(a/2) times the corresponding component of e.  The
   axis is unchanged by its own rotation, so its components are the same
   in both frames and the question of which frame they are resolved in

Vasters                  Expires 7 February 2027               [Page 88]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   does not arise.  Which physical direction the second, third, and
   fourth names stand for therefore follows from the axis order the
   frames declare, not from any convention of this document.

   The four values taken together SHOULD have unit norm, and the scalar
   SHOULD be non-negative, which confines the rotation angle to a half
   turn either way [CCSDS-ADM1].

   A worked case fixes the sense.  Let the to frame be the from frame
   turned a quarter turn in the right-hand sense about the third axis,
   so that the first axis of the to frame has the coordinates 0, 1, 0 in
   the from frame.  The quaternion is then the scalar 0.7071 with axis
   components 0, 0, 0.7071, and a vector whose coordinates in the from
   frame are 1, 0, 0 has the coordinates 0, -1, 0 in the to frame.
   Those are the values [CCSDS-ADM] prints for the same case.

   One other convention is in wide enough use to name.  The SPICE
   toolkit places the scalar first, as this document does, and measures
   its angle as the rotation of the coordinate system from the base
   frame in the right-hand sense, as this document does.  It
   nevertheless carries the negation of the vector part this document
   carries, so for the case above it gives the scalar 0.7071 with vector
   components 0, 0, -0.7071.  The cause is not the parameterization but
   the multiplication rule: NAIF records that its own product takes the
   cross-product term positive where the other convention in circulation
   takes it negative, that this "has the effect of inverting the sense
   of the rotation", and that converting a quaternion of the other
   convention into a SPICE one is done by moving the scalar to the front
   and negating the remaining three [NAIF-QUAT].  The two therefore
   differ in the sign of the vector part while agreeing on everything a
   reader is likely to check, and nothing in the four numbers reveals
   which was meant.  That is the ambiguity this keyword removes.

   The example below annotates an attitude carried as four separate
   properties.  The record stores the scalar last, as the current
   attitude message standard requires of its own records, and components
   names it first, as this document requires of the annotation.

   {
     "name": "SpacecraftAttitude",
     "type": "object",
     "frameTransforms": [
       {
         "from": {
           "reference": { "$ref": "#/definitions/BodyFrame" },
           "kind": "type"
         },
         "to": {

Vasters                  Expires 7 February 2027               [Page 89]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

           "reference": "http://www.opengis.net/def/crs/EPSG/0/4978",
           "kind": "ogc-crs"
         },
         "encoding": "quaternion",
         "components": ["qc", "q1", "q2", "q3"]
       }
     ],
     "properties": {
       "epoch": { "type": "datetime" },
       "q1": { "type": "double" },
       "q2": { "type": "double" },
       "q3": { "type": "double" },
       "qc": { "type": "double" }
     },
     "required": ["epoch", "q1", "q2", "q3", "qc"],
     "additionalProperties": false,
     "definitions": {
       "BodyFrame": {
         "name": "BodyFrame",
         "type": "tuple",
         "description": "Spacecraft body frame.",
         "properties": {
           "x": {
             "type": "double",
             "description": "Along the instrument boresight."
           },
           "y": {
             "type": "double",
             "description": "Completes a right-handed set."
           },
           "z": {
             "type": "double",
             "description": "Towards the solar array hinge."
           }
         },
         "tuple": ["x", "y", "z"]
       }
     }
   }

   An instance carrying the quarter turn worked above is the following.

Vasters                  Expires 7 February 2027               [Page 90]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   {
     "epoch": "2003-09-30T14:28:15.1172Z",
     "q1": 0.0,
     "q2": 0.0,
     "q3": 0.7071068,
     "qc": 0.7071068
   }

10.4.4.2.  Axis and Angle

   The four names given for axisAngle are, in order, the member carrying
   the angle and the members carrying the three components of the axis.
   The angle is that of the rotation carrying the from frame into the to
   frame, measured in the right-hand sense about the axis, and the axis
   components SHOULD have unit norm.  This is the one rotation-only
   encoding whose members do not all carry one unit: the angle MUST
   carry a unit or ucumUnit annotation of angle through [JSTRUCT-UNITS],
   since radians and degrees are not distinguishable in the value, and
   the axis components carry none. homogeneousMatrix likewise mixes
   units, its rotation entries carrying none and its offset entries
   carrying a length.

10.4.4.3.  Euler Angles

   eulerAngles requires rotationSequence, and the three names in
   components are the angles of the first, second, and third rotation in
   the order that sequence gives.

   The rotations are intrinsic.  The first turns the from frame about
   the axis the first letter names, the second turns the frame the first
   produced about the axis the second letter names, and the third turns
   the frame the second produced, the result being the to frame.  Under
   the extrinsic reading, where every rotation is about an axis of the
   original frame, the same three angles against the same sequence
   describe a different transformation.  Nothing is lost by fixing the
   intrinsic reading, because every extrinsic sequence has an intrinsic
   equal that Section 10.4.5 gives; degenerate cases, such as all three
   angles being zero, agree under both readings and need no conversion.

   That this needs saying is shown by the standard that most needs it.
   The current attitude message standard states the composition is
   intrinsic exactly once, in an annex marked informative [CCSDS-ADM],
   and the issue that preceded it for sixteen years never stated it at
   all [CCSDS-ADM1].

Vasters                  Expires 7 February 2027               [Page 91]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

10.4.5.  The rotationSequence Property

   rotationSequence MUST be present when encoding is eulerAngles and
   MUST NOT be present otherwise.  Its value MUST be three characters
   drawn from X, Y, and Z, no two adjacent characters being equal, which
   admits twelve values: XYX, XYZ, XZX, XZY, YXY, YXZ, YZX, YZY, ZXY,
   ZXZ, ZYX, and ZYZ.  The value is case-sensitive, and only these
   twelve upper-case strings are valid.  The leftmost character names
   the axis of the first rotation.

   X names the first axis of the frame being turned, Y the second, and Z
   the third, in the order that frame declares its axes.  The letters
   are positional and carry no direction of their own, whatever the
   frame calls its axes: in a frame declaring north, east, and down, X
   is north, Y is east, and Z is down.

   Twelve values are enough for every rotation, including every rotation
   a source states extrinsically, and an annotator working from such a
   source converts rather than looks for a value that is not there.  A
   rotation stated extrinsically as a sequence of three axes with three
   angles is the same rotation as the intrinsic sequence whose axis
   letters are those three in reverse, taking the same three angle
   values in reverse order.  Both reverse.  Reversing the letters while
   leaving the angles in place, or the reverse of that, gives a
   different rotation, and is the error this paragraph exists to
   prevent.

   The twelve conversions are these.  In every row the angles reverse,
   so components names the member holding the source's third angle first
   and the member holding its first angle last.

Vasters                  Expires 7 February 2027               [Page 92]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

    +====================+========================+==================+
    | Extrinsic sequence | rotationSequence value | components order |
    +====================+========================+==================+
    | XYX                | XYX                    | third, second,   |
    |                    |                        | first            |
    +--------------------+------------------------+------------------+
    | XYZ                | ZYX                    | third, second,   |
    |                    |                        | first            |
    +--------------------+------------------------+------------------+
    | XZX                | XZX                    | third, second,   |
    |                    |                        | first            |
    +--------------------+------------------------+------------------+
    | XZY                | YZX                    | third, second,   |
    |                    |                        | first            |
    +--------------------+------------------------+------------------+
    | YXY                | YXY                    | third, second,   |
    |                    |                        | first            |
    +--------------------+------------------------+------------------+
    | YXZ                | ZXY                    | third, second,   |
    |                    |                        | first            |
    +--------------------+------------------------+------------------+
    | YZX                | XZY                    | third, second,   |
    |                    |                        | first            |
    +--------------------+------------------------+------------------+
    | YZY                | YZY                    | third, second,   |
    |                    |                        | first            |
    +--------------------+------------------------+------------------+
    | ZXY                | YXZ                    | third, second,   |
    |                    |                        | first            |
    +--------------------+------------------------+------------------+
    | ZXZ                | ZXZ                    | third, second,   |
    |                    |                        | first            |
    +--------------------+------------------------+------------------+
    | ZYX                | XYZ                    | third, second,   |
    |                    |                        | first            |
    +--------------------+------------------------+------------------+
    | ZYZ                | ZYZ                    | third, second,   |
    |                    |                        | first            |
    +--------------------+------------------------+------------------+

                                 Table 20

Vasters                  Expires 7 February 2027               [Page 93]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   The six sequences whose first and third letters are equal reverse to
   themselves, and those rows are the ones to read carefully: the value
   written is the same string the source gives, which makes it easy to
   conclude that nothing needs doing.  Something does.  The angles still
   reverse, and an extrinsic ZXZ recorded as an intrinsic ZXZ with the
   angles left in source order is a different rotation from the one the
   source states.

   A source giving an extrinsic X-then-Y-then-Z rotation of 10, 20, and
   30 degrees is therefore annotated with a rotationSequence of ZYX, and
   components naming the member holding 30 degrees first, then the
   member holding 20, then the member holding 10.  The members
   themselves do not move and their values are not rewritten; only the
   order in which components names them changes.  Because nothing in the
   annotation records that the source was extrinsic, a schema that
   converts SHOULD say so in description, so that a later reader
   comparing the schema against the source document does not read the
   reversal as a mistake.  An extrinsic reading MUST NOT be recorded by
   inventing a thirteenth value, a lower-case spelling, or any other
   marking.

   The six values whose first and third characters are equal are
   permitted, though the standard that first enumerated them discouraged
   them "as their use can cause confusion" [CCSDS-ADM1].

10.4.6.  The translation Property

   translation, when present, MUST be an array of exactly three names of
   direct properties of the annotated object or tuple, all of numeric
   type and all distinct, giving the coordinates of the origin of the
   from frame expressed in the to frame, on the axes of the to frame in
   the order that frame declares them.  That is the t of x' = M x + t
   (Section 10.4.1), and it is the offset from the origin of the to
   frame to the origin of the from frame, not the other way about.
   Their units MUST be mutually convertible and SHOULD be identical.

   translation MUST NOT be present when encoding is homogeneousMatrix,
   whose fourth column carries the same three values in the same sense.
   Where translation is absent and encoding is not homogeneousMatrix,
   the element declares a rotation and says nothing about the origins,
   which is the correct reading for an attitude and the wrong one for a
   sensor alignment.

   The KITTI dataset publishes the alignment between its laser scanner
   and its reference camera in a calibration file holding nine numbers
   on one line and three on another, and states in its paper that the
   rotation and the translation run from the laser to the camera
   [KITTI].  Neither the file nor the paper says whether the nine

Vasters                  Expires 7 February 2027               [Page 94]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   numbers are rows or columns; the developer kit for one of its
   benchmarks states that its matrices are stored row-major, and the raw
   calibration file carries no such statement.  The two readings are
   transposes of one another, and for a rotation matrix both are valid
   rotations, so nothing in the numbers rules either out.  Only the
   physical arrangement of the sensors does.  The schema below states
   the reading, and the axis directions the file leaves to the reader,
   as declarations.

   {
     "name": "SensorAlignment",
     "type": "object",
     "frameTransforms": [
       {
         "from": {
           "reference": { "$ref": "#/definitions/LaserFrame" },
           "kind": "type"
         },
         "to": {
           "reference": { "$ref": "#/definitions/CameraFrame" },
           "kind": "type"
         },
         "encoding": "rotationMatrix",
         "components": "rotation",
         "translation": ["tx", "ty", "tz"]
       }
     ],
     "properties": {
       "calibrationTime": { "type": "datetime" },
       "rotation": {
         "type": "array",
         "minItems": 3,
         "maxItems": 3,
         "items": {
           "type": "array",
           "minItems": 3,
           "maxItems": 3,
           "items": { "type": "double" }
         }
       },
       "tx": { "type": "double", "ucumUnit": "m" },
       "ty": { "type": "double", "ucumUnit": "m" },
       "tz": { "type": "double", "ucumUnit": "m" }
     },
     "required": ["calibrationTime", "rotation", "tx", "ty", "tz"],
     "additionalProperties": false,
     "definitions": {
       "LaserFrame": {

Vasters                  Expires 7 February 2027               [Page 95]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

         "name": "LaserFrame",
         "type": "tuple",
         "description": "Frame of the rotating laser scanner.",
         "properties": {
           "x": {
             "type": "double",
             "description": "Forward along the vehicle."
           },
           "y": {
             "type": "double",
             "description": "To the left of the vehicle."
           },
           "z": { "type": "double", "description": "Up." }
         },
         "tuple": ["x", "y", "z"]
       },
       "CameraFrame": {
         "name": "CameraFrame",
         "type": "tuple",
         "description": "Frame of the reference camera.",
         "properties": {
           "x": {
             "type": "double",
             "description": "To the right in the image."
           },
           "y": {
             "type": "double",
             "description": "Down in the image."
           },
           "z": {
             "type": "double",
             "description": "Along the optical axis, from the camera."
           }
         },
         "tuple": ["x", "y", "z"]
       }
     }
   }

   The instance below carries the values that dataset publishes for one
   recording day.

Vasters                  Expires 7 February 2027               [Page 96]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   {
     "calibrationTime": "2012-03-15T11:37:16Z",
     "rotation": [
       [0.007533745, -0.9999714, -0.000616602],
       [0.01480249, 0.0007280733, -0.9998902],
       [0.9998621, 0.00752379, 0.01480755]
     ],
     "tx": -0.004069766,
     "ty": -0.07631618,
     "tz": -0.2717806
   }

   Read as rows, the first inner array gives the first axis of the
   camera frame in the components of the laser frame, and the matrix
   maps the forward axis of the laser onto the optical axis of the
   camera, which is the arrangement the vehicle has.  Read as columns,
   it maps them the other way.  The file name carries the direction and
   nothing carries the layout, which is the division of labor this
   keyword ends.

10.5.  The linearReferenceSystem Keyword

   The linearReferenceSystem keyword identifies the linear reference
   system [ISO19148] under which a location held in properties of an
   object or tuple is to be interpreted.

   When present, linearReferenceSystem MUST be an object with REQUIRED
   reference, kind, linearElement, and measure strings and OPTIONAL
   measureEnd and direction strings.  No other properties are permitted.

10.5.1.  The reference Property

   reference MUST identify one linear reference system.  Where kind is
   type it MUST be a type reference { "$ref": <JSON Pointer> }
   [JSTRUCT-CORE] to a shareable type definition, and otherwise it MUST
   be an absolute URI [RFC3986].  The identified definition MUST
   establish the linear referencing method, the measure origin, the
   increasing-measure direction, the measure unit, and the linear-
   element namespace. kind states which definition model the reference
   identifies.

   A processor is not required to dereference the URI.  This document
   does not define a resolution protocol, URI layout, storage model, or
   definition serialization.

Vasters                  Expires 7 February 2027               [Page 97]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

10.5.2.  The kind Property

   kind classifies which definition model the URI identifies.  It is an
   open enumeration.  The following values are defined here:

    +=============+===================================================+
    | Kind        | Referenced definition                             |
    +=============+===================================================+
    | lrs-network | A network published by a geospatial feature       |
    |             | service whose layer and metadata resources        |
    |             | establish the linear elements and the measure,    |
    |             | such as the WSDOT State Route system [WSDOT-LRS]. |
    +-------------+---------------------------------------------------+
    | type        | A meta-type declaring members whose referenceRole |
    |             | is linearElement and measure, and optionally      |
    |             | direction (Section 8).                            |
    +-------------+---------------------------------------------------+

                                  Table 21

   Other values MAY name further definition models.  Appendix A
   discusses the availability of registered definitions.

   Since the identified definition MUST establish the measure unit, the
   increasing-measure direction, and the linear-element namespace, a
   feature service layer that carries measure values on its vertices and
   a route identifier field without stating those is a rendering of
   positions in a reference system rather than a definition of one, and
   it does not qualify as an lrs-network.

   A type reference carries a system that no authority publishes, such
   as one internal to a plant, a terminal, or a private network.  The
   referenced meta-type MUST declare a member whose referenceRole is
   linearElement and a member whose referenceRole is measure, and MAY
   declare one whose referenceRole is direction.  The linearElement,
   measure, and direction properties of the annotation map the annotated
   properties onto those members, so the type of the element identifier
   and the unit of the measure are checkable.  Where the annotation
   names a measureEnd, that property maps onto the same member of the
   meta-type as measure, because both carry a distance in the same
   system.  The referencing method, measure origin, increasing-measure
   direction, and linear-element namespace are stated in the description
   of the meta-type or of its members.

Vasters                  Expires 7 February 2027               [Page 98]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

10.5.3.  The linearElement Property

   linearElement MUST name a direct property of the annotated object or
   tuple.  The property value identifies the road, railway, waterway,
   route, or other linear element within the linear-element namespace
   established by the identified system.

10.5.4.  The measure Property

   measure MUST name a direct numeric property, distinct from
   linearElement.  The property gives the distance from the measure
   origin along the identified linear element.  It MUST have a unit or
   ucumUnit annotation compatible with the measure unit established by
   the identified system.

10.5.5.  The measureEnd Property

   measureEnd, when present, MUST name another distinct direct numeric
   property whose type and unit are those required of measure.

   Where measureEnd is absent, the annotation locates a point on the
   linear element at measure.  Where it is present, the annotation
   locates the span of that element between measure and measureEnd, and
   measure is the start of the span.  Both ends lie on the one element
   that linearElement identifies, and this document defines no span
   crossing two elements.

   The span is closed at both ends, which differs from the half-open
   convention this document uses for temporal intervals.  Two spans that
   share an end therefore share the point at that end, and a consumer
   counting over abutting sections MUST account for that shared point.
   A span whose ends are equal is the point at that measure.  This
   document does not require that measureEnd exceed measure, since a
   system whose increasing-measure direction opposes the direction of
   travel encodes a forward span with a decreasing pair.

10.5.6.  The direction Property

   direction, when present, MUST name another distinct direct property.
   Its value qualifies the direction of travel or orientation using the
   vocabulary established by the identified system.  It does not alter
   the increasing-measure direction.

   Properties not named by linearElement, measure, measureEnd, or
   direction are not part of the linearly referenced location.

Vasters                  Expires 7 February 2027               [Page 99]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   This binding describes a location along one identified linear
   element, either a point or a span.  This document does not define
   offsets, referent-relative addressing, interpolative methods,
   transformations between linear reference systems, or network
   topology.

   The following excerpt locates a point on a Washington State route,
   where arm is the accumulated route mile measured from the route
   origin.  The cited service qualifies as an lrs-network because the
   layer it names publishes the route identifier syntax and the
   increasing-measure direction in its own metadata rather than leaving
   them to a reader of the geometry: it decomposes the route identifier
   into its parts and states that "a directional indicator has been
   added to the RouteIdentifier to distinguish between the increasing
   and decreasing direction of mileposting" [WSDOT-LRS].  It does not
   state the unit of the measure values, which is why the measure rule
   requires the annotated property to carry one:

   ========== NOTE: '\' line wrapping per RFC 8792 ===========

   {
     "name": "WsdotStateRouteLocation",
     "type": "object",
     "linearReferenceSystem": {
       "reference": "https://data.wsdot.wa.gov/arcgis/rest/services/\
           Shared/LRSData/FeatureServer/9",
       "kind": "lrs-network",
       "linearElement": "route_identifier",
       "measure": "arm",
       "direction": "inventory_direction"
     },
     "properties": {
       "route_identifier": {
         "type": "string"
       },
       "arm": {
         "type": "double",
         "unit": "mi",
         "ucumUnit": "[mi_i]"
       },
       "inventory_direction": {
         "type": "string"
       }
     },
     "required": ["route_identifier", "arm", "inventory_direction"],
     "additionalProperties": false
   }

Vasters                  Expires 7 February 2027              [Page 100]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

11.  Colorimetric Reference Annotations

   Color is the worked instance of a larger family: components resolved
   onto the channels of a named space, where the space fixes the basis
   those numbers weigh, the reference they stand relative to, and the
   encoding they carry.  Section 10 gives that treatment to positions
   and directions, and this section gives it to color, because color is
   the perceptual signal most often carried in general-purpose JSON —
   design tokens, stylesheets, image metadata — and the one most often
   carried with all of that left silent.  The same family continues past
   color in Section 12, where audio channel layout and multiband imaging
   resolve channel numbers onto a named space as color does.  A coded
   value bound to an external list (Section 6) and the weighting a
   scalar measurement carries (Section 7) are relatives of a different
   shape, each treated in its own section.

11.1.  The colorSpaces Keyword

   The colorSpaces keyword identifies the color spaces in which channel
   values held in properties of an object or tuple are to be
   interpreted.

   A color value is a measurement.  Three numbers are not a color until
   something states which primaries they weigh, what white they are
   relative to, what range they run over, and whether they are
   proportional to light or to the signal that drives a display.  Most
   of those are almost never carried with the numbers, and the ones that
   are are carried by conventions that differ between formats.

   The keywords of Section 10 lean on registers.  A position has the
   EPSG dataset and the OGC definitions server behind it, and a schema
   names a system by a URI that resolves to a definition of it.  Color
   has no equivalent.  The International Color Consortium publishes
   registries of RGB color spaces and of print characterization data,
   but those are pages written for a reader rather than identifiers
   minted for a machine [ICC-REGISTRY].  What exists in place of a
   register is of two other sorts.  A standards document may assign a
   code point, as [ITU-H273] assigns combinations of primaries, transfer
   function, matrix coefficients, and signal range to four integers.  Or
   the definition travels with the data as a profile, identified by a
   checksum over its own contents [ICC-SPEC].  Neither is a URI and
   neither dereferences.  A reference in this keyword identifies more
   often than it resolves, which is true of the other reference-style
   keywords as well but is true of this one always.

   When present, colorSpaces MUST be a non-empty array.  Each element
   MUST be an object with REQUIRED reference, kind, and channels,
   OPTIONAL codePoints, packing, alpha, alphaMode, transfer, illuminant,

Vasters                  Expires 7 February 2027              [Page 101]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   and observer, and no other members.  The keyword is an array because
   one record may carry a color in more than one space, as a
   characterization dataset does when it gives the device values that
   were printed alongside the color that was measured off the result.

   These members can disagree, and one principle settles every case in
   which they do. reference identifies a definition that describes a
   class of data, while codePoints, transfer, illuminant, and observer
   state what is true of _this_ data.  The narrower statement prevails,
   because a schema author declaring one is recording a fact about the
   values in hand and a definition cannot be.  The specific rules follow
   from that and are stated where each member is defined
   (Section 11.1.2, Section 11.1.6, Section 11.1.7); no rule lets a
   definition override a member, and none of them makes a schema
   invalid, since a processor that cannot resolve the definition cannot
   detect the disagreement in the first place.

11.1.1.  The reference and kind Properties

   reference MUST identify one color space or one set of device control
   values.  Where kind is type it MUST be a type reference { "$ref":
   <JSON Pointer> } [JSTRUCT-CORE] to a shareable type definition.
   Where kind is icc-profile it MUST be a URI [RFC3986] identifying the
   profile; the profile identifier [ICC-SPEC] computes over the profile
   contents is not itself a URI, and a schema carrying only that
   identifier MUST express it as one, under a scheme of the schema
   author's choosing that states which digest the remainder is.
   Otherwise it MUST be an absolute URI [RFC3986].

   What the identified definition MUST establish follows from what is
   being identified.

Vasters                  Expires 7 February 2027              [Page 102]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   +========================+=========================================+
   | Identified             | What the definition establishes         |
   +========================+=========================================+
   | A space whose channels | The primaries, the white point, and the |
   | are additive primaries | transfer function.                      |
   +------------------------+-----------------------------------------+
   | A space whose channels | The reference white, and the illuminant |
   | are tristimulus        | and the standard colorimetric observer, |
   | quantities, or are     | or else the schema declares them under  |
   | computed from them     | illuminant and observer.                |
   +------------------------+-----------------------------------------+
   | A set of device        | The device, medium, and process the     |
   | control values         | values drive, and the measurement       |
   |                        | conditions under which the result was   |
   |                        | characterized.                          |
   +------------------------+-----------------------------------------+

                                 Table 22

   A set of device control values is not a color space in the
   colorimetric sense, and the third row exists because such values are
   carried alongside colors often enough that excluding them would push
   the commonest characterization record out of this keyword. channels,
   alpha, and alphaMode apply to it unchanged; codePoints, transfer,
   illuminant, and observer do not, and MUST NOT be present on an
   element identifying one.

   kind classifies which definition model the reference identifies.  It
   is an open enumeration.  The following values are defined here:

Vasters                  Expires 7 February 2027              [Page 103]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

       +==============+============================================+
       | Kind         | Referenced definition                      |
       +==============+============================================+
       | itu          | A Recommendation of the International      |
       |              | Telecommunication Union.                   |
       +--------------+--------------------------------------------+
       | iec          | A standard of the International            |
       |              | Electrotechnical Commission.               |
       +--------------+--------------------------------------------+
       | cie          | A publication of the International         |
       |              | Commission on Illumination [CIE015].       |
       +--------------+--------------------------------------------+
       | icc-profile  | An ICC profile, identified as [ICC-SPEC]   |
       |              | identifies one.                            |
       +--------------+--------------------------------------------+
       | icc-registry | An entry in a registry the International   |
       |              | Color Consortium publishes [ICC-REGISTRY]. |
       +--------------+--------------------------------------------+
       | type         | A meta-type in the annotated schema, as    |
       |              | Section 8 describes.                       |
       +--------------+--------------------------------------------+

                                  Table 23

   A processor is not required to dereference the URI.  This document
   does not define a resolution protocol, URI layout, storage model, or
   definition serialization.  Where an element carries codePoints,
   transfer, illuminant, or observer alongside reference, those members
   prevail over the identified definition where the two disagree
   (Section 11.1.2, Section 11.1.6, Section 11.1.7).

11.1.2.  The codePoints Property

   codePoints, when present, MUST be an array of exactly four non-
   negative integers, being the color primaries, transfer
   characteristics, matrix coefficients, and video full range flag that
   [ITU-H273] defines, in that order.

   These four integers are the only identifier of a color space that is
   both machine-readable and widely deployed.  The PNG specification
   carries the same four in a chunk of its own, gives that chunk
   precedence over every other color declaration a file may hold, and
   requires the chunk carrying mastering display metadata to be
   accompanied by it, on the ground that such metadata means nothing
   without the space it is relative to [PNG3].  Where the identified
   definition and the code points disagree, the code points are the
   narrower statement and a processor MUST prefer them, so that two
   processors reading one schema do not part company. transfer is

Vasters                  Expires 7 February 2027              [Page 104]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   narrower still: where transfer is linear, it overrides the transfer
   characteristics code point, and where transfer is asDefined or
   absent, that code point governs.

11.1.3.  The channels Property

   channels MUST be a non-empty array of names of direct properties of
   the annotated object or tuple, all distinct, mapped by position onto
   the channels of the space in the order the identified definition
   declares them.  Except where packing is present, the number of
   channels supplied MUST equal the number the identified space defines,
   and an opacity channel is not one of them.  As with coordinates and
   components, the ordering is an assertion by the schema author and is
   never inferred from property order, property names, or position in a
   tuple.

   Where packing is absent, either every name is that of a property of
   numeric type, or the array holds exactly one name, that of a property
   whose type is array or tuple and whose elements are of numeric type,
   in which case the elements of that property supply the channels in
   order.  Where packing is present, the array holds exactly one name,
   that of a property of type string, and the channels are read out of
   that one value as Section 11.1.4 states.

   This document does not fix the range or the unit of a channel value.
   Where the identified definition does not establish them, as it does
   not for a device control value, the schema SHOULD declare them, by a
   unit annotation, by a numeric range, or in the description of the
   property.  The channels of one element SHOULD share one range
   convention.  A packing establishes both, and a schema carrying one
   declares neither.

11.1.4.  The packing Property

   A color is often carried not as a set of numbers but as one string
   that has all of them inside it.  The hexadecimal notation is the
   commonest such string in the world, and it asserts four things at
   once that the numbers alone do not: that the order is red, green,
   blue; that each channel is eight bits; that the range runs from zero
   to two hundred and fifty-five; and, in the CSS reading, that the
   space is sRGB with its transfer function applied.  A reader who knows
   the convention supplies all four.  This keyword exists so that they
   need not be known.

   packing, when present, states that one string property carries every
   channel of the element.  Its value MUST be hexRgb or hexRgba.

Vasters                  Expires 7 February 2027              [Page 105]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

     +=========+====================================================+
     | Value   | Meaning                                            |
     +=========+====================================================+
     | hexRgb  | Three channels in three or six hexadecimal digits. |
     +---------+----------------------------------------------------+
     | hexRgba | Three channels and an opacity in four or eight     |
     |         | hexadecimal digits.                                |
     +---------+----------------------------------------------------+

                                 Table 24

   The value of the named property MUST consist of hexadecimal digits,
   optionally preceded by a single #, and MUST hold three or six digits
   under hexRgb and four or eight under hexRgba.  The letters are case-
   insensitive, as [CSS-COLOR-4] says in as many words: "the case of the
   letters doesn't matter - #00ff00 is identical to #00FF00".  The # is
   part of the CSS token rather than of the notation, and a schema
   requiring one form or forbidding the other states so by a pattern
   [JSTRUCT-VALIDATION]; CSS itself accepts the bare form under the
   quirks mode of [CSS-COLOR-4].

   In the six-digit and eight-digit forms each successive pair of digits
   is one channel, read as an integer from zero to two hundred and
   fifty-five, where zero is the minimum of that channel and two hundred
   and fifty-five is its maximum.  In the three-digit and four-digit
   forms each single digit stands for the pair obtained by writing it
   twice, so that #123 is #112233.  The order is fixed by this document
   and is red, green, blue, and, under hexRgba, opacity.  It is not
   taken from the order the identified definition declares, and an
   element whose identified space declares its channels in any other
   order MUST NOT use a packing.

   The identified space MUST define exactly three channels, and they
   MUST be additive primaries. alpha MUST NOT be present where packing
   is hexRgba, whose fourth channel is the opacity; alphaMode MAY be
   present there and applies to it. alpha MAY be present where packing
   is hexRgb, which carries none.

   A packing carries eight bits for each channel, which is not enough
   resolution for values proportional to light, so transfer SHOULD be
   asDefined or absent where packing is present.

Vasters                  Expires 7 February 2027              [Page 106]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   The space is still named by reference, and this document does not
   assume one.  A bare hexadecimal string in a document that says
   nothing further is sRGB only because CSS says so, and CSS says so of
   the CSS notation and not of the digits: hex colors are among those
   that "resolve to sRGB" [CSS-COLOR-4].  A record carrying the same six
   digits for a wide-gamut display means a different color, and the
   difference is invisible in the value.

   The following excerpt is a design token whose color is written the
   way a stylesheet would write it.

   {
     "name": "BrandColorToken",
     "type": "object",
     "colorSpaces": [
       {
         "reference":
         "https://www.w3.org/TR/css-color-4/#predefined-sRGB",
         "kind": "iec",
         "channels": ["value"],
         "packing": "hexRgba"
       }
     ],
     "properties": {
       "token": {
         "type": "string"
       },
       "value": {
         "type": "string",
         "pattern": "^#[0-9a-fA-F]{8}$"
       }
     },
     "required": ["token", "value"],
     "additionalProperties": false
   }

11.1.5.  The alpha and alphaMode Properties

   alpha, when present, MUST name a direct property of numeric type
   carrying opacity, distinct from every name in channels.  Its value is
   a dimensionless fraction from zero to one unless the property
   declares otherwise by a unit annotation or a numeric range, and where
   it declares otherwise a processor MUST reduce it to that fraction
   before applying alphaMode. alphaMode MUST NOT be present when both
   alpha is absent and packing is not hexRgba, and states how the
   channel values stand to the opacity, wherever that opacity is
   carried.  When present, its value MUST be straight or premultiplied.

Vasters                  Expires 7 February 2027              [Page 107]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

         +===============+======================================+
         | Value         | Meaning                              |
         +===============+======================================+
         | straight      | The channel values are independent   |
         |               | of the opacity value.                |
         +---------------+--------------------------------------+
         | premultiplied | The channel values have already been |
         |               | multiplied by the opacity value.     |
         +---------------+--------------------------------------+

                                 Table 25

   Where an opacity is carried and alphaMode is absent, the value is
   straight.  That is also the reading a packed hexadecimal opacity
   carries on its own, since the notation of [CSS-COLOR-4] does not
   premultiply.

   The two are not distinguishable by inspection, except at an opacity
   of zero, where the premultiplied channels are all zero and the color
   is gone.  The PNG specification states its own choice in as many
   words: "The color values in a pixel are not premultiplied by the
   alpha value assigned to the pixel.  This rule is sometimes called
   'unassociated' or 'non-premultiplied' alpha", and, flatly, "PNG does
   not use premultiplied alpha" [PNG3].  Formats that do premultiply
   exist, and values carried from one to the other without the
   conversion are wrong everywhere the opacity is neither zero nor one.

11.1.6.  The transfer Property

   transfer, when present, states whether the channel values carry the
   transfer function of the identified space or are proportional to
   light.  Its value MUST be asDefined or linear.

    +===========+=====================================================+
    | Value     | Meaning                                             |
    +===========+=====================================================+
    | asDefined | The values carry the transfer function the          |
    |           | identified definition establishes.                  |
    +-----------+-----------------------------------------------------+
    | linear    | The values are proportional to radiometric          |
    |           | quantity, taking the primaries and white point of   |
    |           | the identified space but not its transfer function. |
    +-----------+-----------------------------------------------------+

                                  Table 26

   When absent, the value is asDefined.

Vasters                  Expires 7 February 2027              [Page 108]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   linear is what a renderer means when it calls a color energy-linear.
   A space and its linear counterpart are commonly given the same name,
   and the two are far apart: under the transfer function the ICC
   registry publishes for sRGB, a channel value of 0.5 stands for
   approximately 0.214 of the light that a channel value of 1.0 stands
   for [ICC-REGISTRY].  Arithmetic on color is defined on the linear
   values, and the PNG specification requires compositing to be
   performed on "intensity samples (not gamma-encoded samples)" [PNG3].

11.1.7.  The illuminant and observer Properties

   illuminant and observer, when present, state the conditions the
   values are relative to. illuminant names a standard illuminant, and
   SHOULD use a designation of [CIE015]. observer names a standard
   colorimetric observer; it is an open enumeration, and the values
   defined here are cie-1931-2 for the 1931 standard colorimetric
   observer and cie-1964-10 for the 1964 supplementary standard
   colorimetric observer.

   A space whose values are tristimulus quantities, or are computed from
   them, does not by itself establish either.  The definition of the
   1976 L*a*b* space says as much: it "is applicable to tristimulus
   values calculated using colour-matching functions of the CIE 1931
   standard colorimetric system or the CIE 1964 standard colorimetric
   system" [ISO11664-4].  Values computed under the two observers from
   one sample differ, and nothing in the values records which was used.
   Where the identified definition does not establish the illuminant and
   the observer, a schema SHOULD declare illuminant and observer.  Where
   the definition does establish them and the declared members disagree
   with it, the declared members prevail and a processor MUST prefer
   them, for the reason that the schema author is stating the condition
   these values were computed under and the definition is stating the
   condition its class of values is customarily computed under.  A
   processor SHOULD report the disagreement, and MUST NOT treat it as
   making the schema invalid.

Vasters                  Expires 7 February 2027              [Page 109]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   Published measurement data shows both practices.  The
   characterization datasets of the International Color Consortium carry
   their conditions in the file itself.  One widely used print dataset
   opens by stating its instrument geometry as "D50, 2 degree, geometry
   45/0, no polarisation filter, white backing, according to ISO
   13655:2009 M1", then repeats the illuminant and the observer angle in
   fields of their own and records the national laboratory its
   measurements are traceable to [ICC-REGISTRY].  Reference data for a
   widely used color target, published by the maker of that target,
   states the measurement condition and the filter and names neither an
   illuminant nor an observer anywhere in the file.  The second is not
   usable as reference data without information from outside it, and a
   schema is a place to put that information.

   An identifier of a color space is also an identifier of an edition of
   it.  The reference values for that same color target were revised,
   and for the white patch alone the lightness moved by more than one
   unit and the yellow-blue coordinate by nearly two, under an unchanged
   product name.  A schema naming the space but not the edition
   describes two different sets of numbers.

11.1.8.  Example

   A characterization dataset pairs the device values that were sent to
   a press with the color that was measured off the printed result.  The
   two are in different spaces, which is why the keyword is an array,
   and only one of them is a color space in the colorimetric sense at
   all; the other is a set of device control values whose meaning is
   precisely the measurement it is paired with.

Vasters                  Expires 7 February 2027              [Page 110]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   ========== NOTE: '\' line wrapping per RFC 8792 ===========

   {
     "name": "CharacterizationPatch",
     "type": "object",
     "colorSpaces": [
       {
         "reference":
         "https://registry.color.org/cmyk-registry/fogra51",
         "kind": "icc-registry",
         "channels": ["c", "m", "y", "k"]
       },
       {
         "reference": "https://cie.co.at/publications/\
             colorimetry-part-4-cie-1976-lab-colour-space-1",
         "kind": "cie",
         "channels": ["lStar", "aStar", "bStar"],
         "illuminant": "D50",
         "observer": "cie-1931-2"
       }
     ],
     "properties": {
       "sampleId": { "type": "int32" },
       "c": { "type": "double", "unit": "%" },
       "m": { "type": "double", "unit": "%" },
       "y": { "type": "double", "unit": "%" },
       "k": { "type": "double", "unit": "%" },
       "lStar": { "type": "double" },
       "aStar": { "type": "double" },
       "bStar": { "type": "double" }
     },
     "required": [
       "sampleId", "c", "m", "y", "k", "lStar", "aStar", "bStar"
     ],
     "additionalProperties": false
   }

   The instance below is one patch of that dataset, the solid of the
   third ink.

Vasters                  Expires 7 February 2027              [Page 111]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   {
     "sampleId": 649,
     "c": 0.0,
     "m": 0.0,
     "y": 100.0,
     "k": 0.0,
     "lStar": 88.94,
     "aStar": -4.04,
     "bStar": 92.37
   }

   The three measured values are a position in a space that is undefined
   until the illuminant and the observer are known, and the file the
   numbers came from is one of the ones that says so.  The annotation
   carries what that file carries, in a place a processor can read.

12.  Signal Channel Annotations

   The keywords of this section resolve components onto the channels of
   a named space, as Section 11 does for color.  A signal is a bundle of
   channel numbers that means nothing until something states which
   channel is which, what the numbers stand relative to, and how they
   are encoded.  Color carries that in colorSpaces; audio and multiband
   imaging carry it here.

12.1.  The audioChannels Keyword

   The audioChannels keyword identifies the channel layout in which
   audio sample values held in properties of an object or tuple are to
   be interpreted, the level the samples are relative to, and the
   encoding they carry.

   An audio sample is a measurement of a signal, and a set of samples is
   not sound until something states which loudspeaker or which role each
   channel drives, what the numbers stand relative to, and whether they
   are amplitudes or a companded encoding of them.  A bare array carries
   none of that, and the conventions that carry it differ between
   formats.

   When present, audioChannels MUST be a non-empty array.  Each element
   MUST be an object with a REQUIRED reference, a REQUIRED kind, a
   REQUIRED channels, an OPTIONAL levelReference, and an OPTIONAL
   encoding, and no other members.  The keyword is an array because one
   record may carry more than one channel group, as a programme does
   when a commentary track accompanies a music-and-effects mix.

Vasters                  Expires 7 February 2027              [Page 112]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

12.1.1.  The reference and kind Properties

   reference MUST identify one channel layout whose definition
   establishes an ordered set of channels, each with a loudspeaker
   position or a role.  Where kind is type it MUST be a type reference {
   "$ref": <JSON Pointer> } [JSTRUCT-CORE] to a shareable type
   definition, and otherwise it MUST be an absolute URI [RFC3986]. kind
   classifies which definition model the reference identifies.  It is an
   open enumeration; the following values are defined here:

          +======+=============================================+
          | Kind | Referenced definition                       |
          +======+=============================================+
          | itu  | A Recommendation of the International       |
          |      | Telecommunication Union, such as the        |
          |      | loudspeaker configurations of [ITU-BS2051]. |
          +------+---------------------------------------------+
          | type | A meta-type in the annotated schema, as     |
          |      | Section 8 describes.                        |
          +------+---------------------------------------------+

                                 Table 27

   A layout recommendation such as [ITU-BS2051] defines several
   configurations, and a bare reference to it names the recommendation
   rather than one of them; a schema that must pin one configuration
   deep-links to it or carries it as a type.  Where the recommendation
   mints no per-configuration URI, the deep link is a fragment that
   names the configuration in the recommendation's own notation, as
   #0+5+0 names its five-loudspeaker system with a low-frequency-effects
   channel; the fragment identifies the configuration whether or not the
   recommendation serves it.  A processor is not required to dereference
   the URI.  This document does not define a resolution protocol, URI
   layout, storage model, or definition serialization.

12.1.2.  The channels Property

   channels MUST be a non-empty array of names of direct properties of
   the annotated object or tuple, all distinct, mapped by position onto
   the channels of the layout in the order the identified definition
   declares them.  The number of channels supplied MUST equal the number
   the identified layout defines.  As with coordinates and the channels
   of colorSpaces, the ordering is an assertion by the schema author and
   is never inferred from property order, property names, or position in
   a tuple.  A low-frequency-effects channel is one of the channels, in
   the position the layout assigns it, and is not inferred from a
   property name.  Either every name is that of a property of numeric
   type, or the array holds exactly one name, that of a property whose

Vasters                  Expires 7 February 2027              [Page 113]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   type is array or tuple and whose elements are of numeric type, in
   which case the elements of that property supply the channels in
   order.

12.1.3.  The levelReference Property

   levelReference, when present, states what the sample amplitudes are
   relative to.  Its values, their meanings, and its openness are those
   of the levelReference of measurementConditioning (Section 7.1.3),
   which defines them.  Under fullScale the numeric range of the samples
   is stated by the property carrying them and not by this value.

   The default differs from that of measurementConditioning.  Here,
   absence means fullScale, because digital audio samples are referred
   to full scale unless something says otherwise.  Under
   measurementConditioning, absence means that no level reference is
   stated, because a conditioned measurement has no comparable default.

   Programme loudness is not a per-sample reference: it is an
   integrated, gated, frequency-weighted measure of a whole programme,
   defined by [ITU-BS1770] and given a target by [EBU-R128], and a
   schema that carries it carries it as its own annotated value, not as
   the level reference of the channels.

12.1.4.  The encoding Property

   encoding, when present, states how the stored numbers stand to
   amplitude.  Its value MUST be one of the values below or an absolute
   URI identifying another encoding.

Vasters                  Expires 7 February 2027              [Page 114]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

       +========+=================================================+
       | Value  | Meaning                                         |
       +========+=================================================+
       | linear | The numbers are proportional to amplitude, and  |
       |        | full scale is the range the annotated member's  |
       |        | declared type permits.                          |
       +--------+-------------------------------------------------+
       | float  | The numbers are proportional to amplitude and   |
       |        | full scale is unit magnitude, so a sample of    |
       |        | 1.0 is at full scale.  A magnitude greater than |
       |        | one is legal and is a level above full scale.   |
       +--------+-------------------------------------------------+
       | aLaw   | Each channel value is the eight-bit A-law code  |
       |        | word that [ITU-G711] defines.                   |
       +--------+-------------------------------------------------+
       | muLaw  | Each channel value is the eight-bit mu-law code |
       |        | word that [ITU-G711] defines.                   |
       +--------+-------------------------------------------------+

                                 Table 28

   Where absent, the encoding is linear.

   The division between linear and float is the scale, not the storage
   type.  A member of floating-point type whose samples run to the range
   of an integer quantization is linear; a member whose samples are
   normalized to unit magnitude is float, whatever its declared type.
   The distinction matters because every value validates under either
   and only one of them makes a decibel level or a sum of channels come
   out right, and because a float member may legitimately carry a
   magnitude greater than one that a reader must not treat as an error.

   Under aLaw or muLaw each channel value is an integer from zero to two
   hundred and fifty-five, and a reader restores amplitude by the
   inverse companding before any arithmetic.

   The enumeration is open because a sample encoding is a definition
   maintained elsewhere, as G.711 companding is.  A value that is a URI
   SHOULD identify a definition of the encoding.  A processor that does
   not know a value MUST preserve it, MUST NOT reject the schema for
   carrying it, and MUST NOT assume that the numbers are proportional to
   amplitude; the check is indeterminate rather than incorrect.  A
   compressed bitstream is not a set of channel members and is outside
   this keyword whatever its encoding is called.

   Object-based and scene-based audio, in which a sample is not one
   loudspeaker, are not channel layouts in this sense; they are
   described by the Audio Definition Model [ITU-BS2076] and are outside

Vasters                  Expires 7 February 2027              [Page 115]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   this keyword.  The time axis of audio, the sample rate, is a regular
   temporal cadence and is carried by temporalReferenceSystem and
   cadence (Section 9.4), not here.

12.1.5.  Example

   The record below is one multichannel sample frame of a five-channel-
   with-LFE programme, whose layout is the 0+5+0 system of [ITU-BS2051].
   The six property names are the schema author's; the order of channels
   is what binds them to the layout.

   {
     "name": "SurroundSampleFrame",
     "type": "object",
     "audioChannels": [
       {
         "reference": "https://www.itu.int/rec/R-REC-BS.2051/en#0+5+0",
         "kind": "itu",
         "channels": ["l", "r", "c", "lfe", "ls", "rs"],
         "levelReference": "fullScale",
         "encoding": "linear"
       }
     ],
     "properties": {
       "frameIndex": { "type": "int64" },
       "l":   { "type": "double" },
       "r":   { "type": "double" },
       "c":   { "type": "double" },
       "lfe": { "type": "double" },
       "ls":  { "type": "double" },
       "rs":  { "type": "double" }
     },
     "required": ["frameIndex", "l", "r", "c", "lfe", "ls", "rs"],
     "additionalProperties": false
   }

12.2.  The spectralBands Keyword

   The spectralBands keyword identifies the spectral bands onto which
   the components of a multiband value held in properties of an object
   or tuple are resolved, in the order a named sensor or band set
   declares them.

Vasters                  Expires 7 February 2027              [Page 116]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   A multiband pixel is a row of numbers, one per band, and it means
   nothing until something states which wavelengths each band covers and
   what physical quantity the number is.  The bands of one sensor are
   not the bands of another even where they are given the same colour
   name, and a raw count is not a radiance until the sensor's
   calibration is applied.

   When present, spectralBands MUST be a non-empty array.  Each element
   MUST be an object with a REQUIRED reference, a REQUIRED kind, a
   REQUIRED bands, and an OPTIONAL calibration, and no other members.
   The keyword is an array because one record may resolve its components
   onto more than one band set, as a fused product does when it carries
   bands from two instruments.

12.2.1.  The reference and kind Properties

   reference MUST identify one band set whose definition establishes an
   ordered set of bands, each with a wavelength range.  Where kind is
   type it MUST be a type reference { "$ref": <JSON Pointer> }
   [JSTRUCT-CORE] to a shareable type definition, and otherwise it MUST
   be an absolute URI [RFC3986]. kind classifies which definition model
   the reference identifies.  It is an open enumeration; the following
   values are defined here:

           +========+=========================================+
           | Kind   | Referenced definition                   |
           +========+=========================================+
           | sensor | A band set published by the operator of |
           |        | an instrument, such as the Operational  |
           |        | Land Imager bands of [USGS-LANDSAT].    |
           +--------+-----------------------------------------+
           | type   | A meta-type in the annotated schema, as |
           |        | Section 8 describes.                    |
           +--------+-----------------------------------------+

                                 Table 29

   A publication that lists the band sets of several instruments names
   one of them by a deep link, a fragment naming the instrument where
   the publisher mints no per-instrument URI, as #landsat-8-9-oli names
   the Operational Land Imager; the fragment identifies the band set
   whether or not the publication serves it.  A processor is not
   required to dereference the URI.  This document does not define a
   resolution protocol, URI layout, storage model, or definition
   serialization.

Vasters                  Expires 7 February 2027              [Page 117]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

12.2.2.  The bands Property

   bands MUST be a non-empty array of names of direct properties of the
   annotated object or tuple, all distinct, mapped by position onto the
   bands of the set in the order the identified definition declares
   them.  The number of bands supplied MUST equal the number the
   identified set defines.  As with the channels of colorSpaces, the
   ordering is an assertion by the schema author and is never inferred
   from property order, property names, or position in a tuple.  Either
   every name is that of a property of numeric type, or the array holds
   exactly one name, that of a property whose type is array or tuple and
   whose elements are of numeric type, in which case the elements of
   that property supply the bands in order.

12.2.3.  The calibration Property

   calibration, when present, states what physical quantity each band
   value is.  It is an open enumeration; the values defined here are:

     +===============+==============================================+
     | Value         | Meaning                                      |
     +===============+==============================================+
     | digitalNumber | The values are quantized, calibrated, scaled |
     |               | digital numbers in the identified product    |
     |               | encoding, which become a physical quantity   |
     |               | only when the per-band coefficients of the   |
     |               | acquisition are applied.                     |
     +---------------+----------------------------------------------+
     | radiance      | The values are spectral radiance, and their  |
     |               | unit is stated by JSON Structure Units       |
     |               | [JSTRUCT-UNITS].                             |
     +---------------+----------------------------------------------+
     | reflectance   | The values are reflectance, a dimensionless  |
     |               | fraction, of the kind the identified product |
     |               | defines, such as top-of-atmosphere planetary |
     |               | reflectance with or without a solar-angle    |
     |               | correction; where they are stored scaled,    |
     |               | the property states the scale.               |
     +---------------+----------------------------------------------+

                                 Table 30

   Where absent, the calibration is not established by this annotation
   and the identified definition or the unit of the property governs.
   The rescaling from a digital number to radiance or reflectance is
   per-band; for the Landsat imagers it is a multiplicative and an
   additive coefficient for each band, delivered in the product metadata
   [USGS-LANDSAT-L1], and a schema that holds digital numbers holds

Vasters                  Expires 7 February 2027              [Page 118]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   those coefficients as their own values.  A quantity the values
   defined here do not name, such as brightness temperature, is carried
   as an open value.

12.2.4.  Example

   The record below is one pixel of a nine-band Operational Land Imager
   scene, whose bands are those of [USGS-LANDSAT], carried as
   reflectance.

   ========== NOTE: '\' line wrapping per RFC 8792 ===========

   {
     "name": "OliPixel",
     "type": "object",
     "spectralBands": [
       {
         "reference": "https://www.usgs.gov/faqs/\
             what-are-band-designations-landsat-satellites",
         "kind": "sensor",
         "bands": [
           "coastalAerosol", "blue", "green", "red",
           "nir", "swir1", "swir2", "pan", "cirrus"
         ],
         "calibration": "reflectance"
       }
     ],
     "properties": {
       "column": { "type": "int32" },
       "row": { "type": "int32" },
       "coastalAerosol": { "type": "double" },
       "blue": { "type": "double" },
       "green": { "type": "double" },
       "red": { "type": "double" },
       "nir": { "type": "double" },
       "swir1": { "type": "double" },
       "swir2": { "type": "double" },
       "pan": { "type": "double" },
       "cirrus": { "type": "double" }
     },
     "required": [
       "column", "row", "coastalAerosol", "blue", "green", "red",
       "nir", "swir1", "swir2", "pan", "cirrus"
     ],
     "additionalProperties": false
   }

Vasters                  Expires 7 February 2027              [Page 119]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

13.  Conformance

13.1.  Check Outcomes

   A check defined by this document has one of three outcomes.  It is
   valid when a processor evaluated it and it held, invalid when a
   processor evaluated it and it did not hold, and indeterminate when a
   processor did not evaluate it because a definition it depends on was
   not resolved.

   A processor MUST report the three outcomes distinctly.  It MUST NOT
   report an indeterminate check as valid, MUST NOT reject a schema
   solely because a check was indeterminate, and MUST NOT act on an
   annotation as though an indeterminate check had held.

   A rule whose subject lies within the schema is always evaluable, and
   a check of such a rule is never indeterminate.  A rule whose subject
   is an external definition is indeterminate for as long as that
   definition is unresolved.

   Which definitions a processor holds is a deployment matter, so two
   conforming processors MAY reach different outcomes for one schema.
   They MUST differ only in that one returns indeterminate where the
   other returns valid or invalid.  A processor MUST NOT return valid
   where a processor holding the definition would return invalid.

   A profile, a deployment, or an agreement between parties MAY require
   that named checks be evaluated rather than left indeterminate.  This
   document requires it of no check.

13.2.  Schema Conformance

   A conforming schema selects the versioned extension meta-schema URI.
   It MAY use any subset of the annotations defined by this document,
   including none, and it MUST NOT be rejected merely because an
   annotation or annotated property is absent.

   Every annotation that is present:

   *  MUST occur at an attachment point permitted by this document;

   *  MUST have the defined value shape and use an allowed kind,
      semanticRole, or referenceRole value;

   *  MUST NOT repeat, within one containing type, a semanticRole that
      Section 5.3 states identifies one position;

   *  MUST be compatible with the Core type of the annotated schema; and

Vasters                  Expires 7 February 2027              [Page 120]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   *  MUST satisfy the applicable rules of JSON Structure Units
      [JSTRUCT-UNITS].

   Validation MUST reject malformed annotations and invalid identifiers
   or values within annotations, and those checks are never
   indeterminate.  External resolution, domain-of-validity, mapping-
   review, and transformation checks are indeterminate while the
   definition they depend on is unresolved, and Section 13.1 states how
   a processor reports them.

13.3.  Processing Conformance

   A conforming processor MUST preserve declarations, externally
   resolved facts, and inferences separately.  It MUST preserve the
   differences among an observation act, its result, an observable-
   property identity, a definition URI, an identifiable temporal object,
   and a temporal-position value.

   A processor MUST NOT infer:

   *  any semanticRole, observed-property annotation, concept binding,
      derivation, statistic, or cadence from a name, label, description,
      type, unit, position, or sample;

   *  a referenceRole, or the member of a meta-type that a mapping
      property names, from a member name;

   *  graph structure, node identity, statements, or entailment from a
      concept binding, or a term of one vocabulary from a term of
      another;

   *  identity or semantic equivalence from labels, closeMatch,
      hierarchy, relatedness, or QuantityKind classification;

   *  a feature, procedure, or identity absent from the corresponding
      semanticRole, or a proximate feature from an ultimate feature or
      conversely;

   *  a temporal reference regime from a non-Core or ambiguous encoding;

   *  metric intervals from ordinal positions or an untilNext end from
      cadence;

   *  complete coverage from interval or accumulation;

   *  that absent quality means acceptable quality;

Vasters                  Expires 7 February 2027              [Page 121]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   *  a coordinate, vector-frame, or linear reference binding from names
      or samples;

   *  the direction, sense, or component order of a frame
      transformation, or the variance of a vector or tensor quantity,
      from member names, from the values themselves, or from the frames
      the transformation runs between;

   *  a color space, an illuminant, an observer, a transfer function, or
      an alpha mode from channel names, from the range the channel
      values fall in, or from the number of channels present;

   *  an audio channel layout, level reference, or encoding; a spectral
      band set or calibration; a code-list binding; or a measurement
      weighting, time weighting, or level reference, from names,
      samples, units, or the number of members present;

   *  that members sharing a name prefix, a unit, or an observed
      property are the components of one vector quantity;

   *  an observation entity, or any class, identity, or relationship of
      an observation model, from the roles a schema declares;

   *  an instruction to perform, repeat, or recompute an operation from
      a keyword that names one; or

   *  permission to aggregate, convert, transform, reject outliers, or
      infer causality.

   A processor that selects one temporal position as the event-time axis
   of a record, for windowing, ordering, or watermarking, SHOULD select
   the member annotated phenomenonTime, or, where the record bounds the
   period at both ends, the member annotated phenomenonTimeStart.  It
   SHOULD NOT select a member annotated resultTime, ingestionTime,
   scheduledTime, or actualTime for that purpose.  Those roles state the
   handling of the record and not the time of the phenomenon, and a
   window built on them reports the behaviour of the pipeline rather
   than of the world.

   Where a processor needs both axes and its execution model admits only
   one, the phenomenon-time member is the recommended axis, and the
   operational position is carried as an ordinary value.  A processor
   that departs from this SHOULD record the position it selected, so
   that a reader of the output is not left to infer which axis produced
   it.

Vasters                  Expires 7 February 2027              [Page 122]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   A record annotating no phenomenon-time role supplies no phenomenon-
   time axis.  A processor MUST NOT construct one from a member name,
   and MUST NOT read an operational position as one.  It MAY still
   window on an operational position, which states when the record was
   handled.

   A processor MAY ignore this extension.  A processor claiming support
   MUST treat unresolved identifiers, domains, mappings, or conversions
   as indeterminate rather than compatible.

13.4.  Inheritance and Imports

   An annotation on an inherited property or type remains part of the
   effective schema.  Core inheritance does not define a local override
   of an inherited property.  Cross-property rules MUST be checked
   against the effective inherited type.

   JSON Structure Import copies complete definitions, including
   annotations [JSTRUCT-IMPORT].  Shadowing replaces the complete
   imported definition; it does not merge individual annotations.

   Member names stated by an annotation are resolved as Section 3
   requires: against the effective definition of the annotated type, and
   against declared property names rather than serialized ones.

   An annotation belongs to the definition it is written on, so
   annotations are part of what a type means rather than of how one
   schema uses it.  A schema that needs different annotations for the
   same structure shadows the definition and restates them, or defines a
   distinct type.  This document defines no overlay by which a schema
   attaches annotations to a definition it does not own.

   Where a type would inherit the same keyword from more than one base,
   the derived definition MUST state that keyword itself, and the stated
   value is the effective one.  A definition that leaves two inherited
   values of one keyword in force is not conforming, and a processor
   MUST NOT select between them.

14.  Extension Meta-Schema

   The extension meta-schema is published at:

   https://json-structure.org/meta/semantic-annotations/v0/#

   It offers one feature, JSONStructureSemanticAnnotations, whose add-
   ins contribute the keywords defined here to the Core property,
   object, tuple, array, set, map, and choice definitions.  A schema
   activates this specification by selecting that URI and naming the

Vasters                  Expires 7 February 2027              [Page 123]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   feature in $uses.  The meta-schema enables JSON Structure Units,
   Import, Conditional Composition, and Validation.  The annotations
   carry no profile or version member; the versioned meta-schema URI is
   the version identifier.

   The meta-schema validates the shape of each annotation defined here:
   the presence and form of its members, the enumerations that Section 3
   states are closed, and the form required of a reference for the
   accompanying kind.  It does not express a rule whose subject lies
   outside the annotated node.  Such rules, including every rule about a
   property that an annotation names and every rule about a definition
   that a reference identifies, are checked against the effective schema
   rather than by the meta-schema alone.  No companion reference type or
   import is required.

15.  Security Considerations

   Incorrect or malicious catalog entries, labels, mappings, feature
   identities, or procedure identities can cause results from different
   subjects, acts, or concepts to be combined.  Implementations MUST
   preserve catalog-URI identity, MUST NOT infer equivalence from
   discovery labels, and MUST NOT treat an unreviewed or non-exact
   mapping as approval.  Catalog write access and mapping review
   therefore require authentication, authorization, audit, and
   provenance.  Deprecation alternatives are migration advice, not
   automatic substitutions.

   No annotation is checked against the data it describes.  Validation
   confirms that a named member exists, that a closed enumeration holds,
   and that components and units agree in number and kind; it cannot
   confirm that a reference still identifies the definition the values
   are actually expressed against.  An annotation is therefore a claim
   that can be true when written and false later without anything
   failing: an instrument is recalibrated, a station is resurveyed onto
   a new datum, a producer reorders channels or changes a rate, a code
   list is superseded.  The schema continues to validate and the
   annotation continues to read as authoritative.

   Stale annotation is for that reason more dangerous than absent
   annotation.  The prohibitions in Section 13.3 guard the absent case,
   where a processor is required to decline rather than guess; they do
   not guard the stale case, where a processor holds an explicit
   statement, has no ground to doubt it, and proceeds with a combination
   it would otherwise have refused.  A schema author MUST revise the
   annotations of a schema in the same change that alters what the
   schema describes, and a consumer MUST NOT treat an annotation as
   evidence more current than the schema revision carrying it.

Vasters                  Expires 7 February 2027              [Page 124]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   The same property makes annotations a target.  Modifying a schema
   changes what data means without touching the data, without failing
   validation, and without any signal to a consumer: a substituted CRS
   reference relocates every coordinate, an alphaMode moved between
   straight and premultiplied alters every composite, an altered
   levelReference shifts every level by an amount large enough to matter
   and plausible enough to pass review.  Schema distribution therefore
   needs the integrity protection the data needs, and a change to an
   annotation warrants the review a change to a type warrants.

   Incorrect temporal roles, boundaries, reference systems,
   transformations, or domains of validity can reorder positions or
   create false coverage.  Cadence MUST NOT synthesize a missing
   untilNext successor.  Incorrect CRS, axis order, LRS, measure origin,
   unit, or direction can place a feature incorrectly.  Processors MUST
   NOT perform temporal, coordinate, linear, or unit transformations
   without validating authoritative definitions.

   Remote registries, schemas, vocabularies, procedures, mapping
   targets, and reference systems are untrusted input.  Implementations
   SHOULD use HTTPS where available, bounded retrieval, caching with
   version awareness, allow-lists where appropriate, cycle detection,
   and explicit trust decisions.

15.1.  Privacy Considerations

   Catalog labels and mappings, procedure and feature identities,
   locations, times, statuses, and quality can reveal sensitive
   operations or subjects.  Hidden labels are not an access-control
   mechanism.  This specification grants no access and does not replace
   minimization, privacy review, retention, or export controls.

   Dereferencing a reference can disclose processor interest to the
   party that serves the definition.

16.  IANA Considerations

   This document has no IANA actions.

17.  References

17.1.  Normative References

   [ISO19108] International Organization for Standardization, "ISO
              19108:2002 Geographic information - Temporal schema",
              2002, <https://www.iso.org/standard/26013.html>.

Vasters                  Expires 7 February 2027              [Page 125]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   [ISO19111] International Organization for Standardization, "ISO
              19111:2019 Geographic information - Referencing by
              coordinates", 2019,
              <https://www.iso.org/standard/74039.html>.

   [ISO19148] International Organization for Standardization, "ISO
              19148:2021 Geographic information - Linear referencing",
              2021, <https://www.iso.org/standard/75147.html>.

   [JSTRUCT-CORE]
              Vasters, C., "JSON Structure: Core", Work in Progress,
              Internet-Draft, draft-vasters-json-structure-core-04, 8
              June 2026, <https://datatracker.ietf.org/doc/html/draft-
              vasters-json-structure-core-04>.

   [JSTRUCT-UNITS]
              Vasters, C., "JSON Structure: Symbols, Scientific Units,
              and Currencies", Work in Progress, Internet-Draft, draft-
              vasters-json-structure-units-03, 8 June 2026,
              <https://datatracker.ietf.org/doc/html/draft-vasters-json-
              structure-units-03>.

   [JSTRUCT-VALIDATION]
              Vasters, C., "JSON Structure: Validation Extensions", Work
              in Progress, Internet-Draft, draft-vasters-json-structure-
              validation-03, 8 June 2026,
              <https://datatracker.ietf.org/doc/html/draft-vasters-json-
              structure-validation-03>.

   [OGC-NAMES]
              Open Geospatial Consortium, "OGC Name Type Specification -
              definitions - part 1 - basic name", n.d.,
              <https://docs.ogc.org/pol/09-048r6.html>.

   [RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
              Requirement Levels", BCP 14, RFC 2119,
              DOI 10.17487/RFC2119, March 1997,
              <https://www.rfc-editor.org/rfc/rfc2119>.

   [RFC3339]  Klyne, G. and C. Newman, "Date and Time on the Internet:
              Timestamps", RFC 3339, DOI 10.17487/RFC3339, July 2002,
              <https://www.rfc-editor.org/rfc/rfc3339>.

   [RFC3986]  Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
              Resource Identifier (URI): Generic Syntax", STD 66,
              RFC 3986, DOI 10.17487/RFC3986, January 2005,
              <https://www.rfc-editor.org/rfc/rfc3986>.

Vasters                  Expires 7 February 2027              [Page 126]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   [RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
              2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
              May 2017, <https://www.rfc-editor.org/rfc/rfc8174>.

17.2.  Informative References

   [CCSDS-ADM]
              Consultative Committee for Space Data Systems, "Attitude
              Data Messages, Recommended Standard, CCSDS 504.0-B-2, Blue
              Book", January 2024,
              <https://public.ccsds.org/Pubs/504x0b2.pdf>.

   [CCSDS-ADM1]
              Consultative Committee for Space Data Systems, "Attitude
              Data Messages, Recommended Standard, CCSDS 504.0-B-1, Blue
              Book, including Technical Corrigendum 1 (July 2015)", May
              2008, <https://public.ccsds.org/Pubs/504x0b1c1s.pdf>.

   [CF-STANDARD-NAMES]
              CF Conventions, "CF Standard Name Table", n.d.,
              <https://cfconventions.org/Data/cf-standard-
              names/current/build/cf-standard-name-table.html>.

   [CIE015]   International Commission on Illumination, "CIE 015:2018
              Colorimetry, 4th Edition", 2018,
              <https://cie.co.at/publications/colorimetry-4th-edition>.

   [CSS-COLOR-4]
              World Wide Web Consortium, "CSS Color Module Level 4",
              n.d., <https://www.w3.org/TR/css-color-4/>.

   [DCTERMS]  Dublin Core Metadata Initiative, "DCMI Metadata Terms",
              n.d., <https://www.dublincore.org/specifications/dublin-
              core/dcmi-terms/>.

   [EBU-R128] European Broadcasting Union, "EBU R 128: Loudness
              normalisation and permitted maximum level of audio
              signals", November 2023,
              <https://tech.ebu.ch/publications/r128>.

   [EPSG]     International Association of Oil and Gas Producers, "EPSG
              Geodetic Parameter Dataset", n.d., <https://epsg.org/>.

   [FHWA-ARNOLD]
              Federal Highway Administration, "All Road Network of
              Linear Referenced Data", n.d.,
              <https://www.fhwa.dot.gov/policyinformation/hpms/
              arnold.cfm>.

Vasters                  Expires 7 February 2027              [Page 127]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   [FHWA-HPMS]
              Federal Highway Administration, "Highway Performance
              Monitoring System Field Manual", n.d.,
              <https://www.fhwa.dot.gov/policyinformation/hpms/
              fieldmanual/>.

   [GCMT-NDK] Global CMT Project, "Explanation of the ndk file format
              used for the Global Centroid-Moment-Tensor catalog", 2006,
              <https://www.ldeo.columbia.edu/~gcmt/projects/CMT/catalog/
              allorder.ndk_explained>.

   [IANA-LANGTAGS]
              Internet Assigned Numbers Authority, "Language Subtag
              Registry", n.d., <https://www.iana.org/assignments/
              language-subtag-registry>.

   [IANA-PROTOCOLS]
              Internet Assigned Numbers Authority, "Protocol
              Registries", n.d., <https://www.iana.org/protocols>.

   [IATA-CODES]
              International Air Transport Association, "Airline and
              Airport Code Search", n.d.,
              <https://www.iata.org/en/publications/directories/code-
              search/>.

   [ICAO7910] International Civil Aviation Organization, "Location
              Indicators (Doc 7910)", n.d.,
              <https://store.icao.int/en/location-indicators-doc-7910>.

   [ICAO8643] International Civil Aviation Organization, "Aircraft Type
              Designators (Doc 8643)", n.d., <https://www.icao.int/
              operational-safety/doc-8643-aircraft-type-designators>.

   [ICC-REGISTRY]
              International Color Consortium, "ICC Characterization Data
              Registry", n.d., <https://registry.color.org/>.

   [ICC-SPEC] International Color Consortium, "Image technology colour
              management - Architecture, profile format, and data
              structure (ISO 15076-1:2025, ICC.1:2022, profile version
              4.4)", 2022, <https://www.color.org/v4spec.xalter>.

   [IEC61672-1]
              International Electrotechnical Commission, "IEC
              61672-1:2013 Electroacoustics - Sound level meters - Part
              1: Specifications", 2013,
              <https://webstore.iec.ch/en/publication/5708>.

Vasters                  Expires 7 February 2027              [Page 128]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   [ISO639]   International Organization for Standardization, "ISO 639:
              Code for individual languages and language groups", n.d.,
              <https://www.iso.org/iso-639-language-codes.html>.

   [ISO1683]  International Organization for Standardization, "ISO
              1683:2015 Acoustics - Preferred reference values for
              acoustical and vibratory levels", 2015,
              <https://www.iso.org/standard/64648.html>.

   [ISO3166]  International Organization for Standardization, "ISO 3166:
              Codes for the representation of names of countries and
              their subdivisions", n.d.,
              <https://www.iso.org/iso-3166-country-codes.html>.

   [ISO4217]  International Organization for Standardization, "ISO 4217:
              Codes for the representation of currencies", n.d.,
              <https://www.iso.org/iso-4217-currency-codes.html>.

   [ISO11664-4]
              International Commission on Illumination, "Colorimetry -
              Part 4: CIE 1976 L*a*b* colour space (ISO/CIE
              11664-4:2019)", 2019, <https://cie.co.at/publications/
              colorimetry-part-4-cie-1976-lab-colour-space-1>.

   [ISO19156] International Organization for Standardization, "ISO
              19156:2023 Geographic information - Observations,
              measurements and samples", 2023,
              <https://www.iso.org/standard/82463.html>.

   [ITU-BS1770]
              International Telecommunication Union, "Recommendation
              ITU-R BS.1770-5: Algorithms to measure audio programme
              loudness and true-peak audio level", November 2023,
              <https://www.itu.int/rec/R-REC-BS.1770/en>.

   [ITU-BS2051]
              International Telecommunication Union, "Recommendation
              ITU-R BS.2051-3: Advanced sound system for programme
              production", May 2022,
              <https://www.itu.int/rec/R-REC-BS.2051/en>.

   [ITU-BS2076]
              International Telecommunication Union, "Recommendation
              ITU-R BS.2076: Audio Definition Model", n.d.,
              <https://www.itu.int/rec/R-REC-BS.2076/en>.

Vasters                  Expires 7 February 2027              [Page 129]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   [ITU-G711] International Telecommunication Union, "Recommendation
              ITU-T G.711: Pulse code modulation (PCM) of voice
              frequencies", November 1988,
              <https://www.itu.int/rec/T-REC-G.711>.

   [ITU-H273] International Telecommunication Union, "Recommendation
              ITU-T H.273: Coding-independent code points for video
              signal type identification", July 2024,
              <https://www.itu.int/rec/T-REC-H.273>.

   [JSTRUCT-ALTNAMES]
              Vasters, C., "JSON Structure: Alternate Names and
              Descriptions", Work in Progress, Internet-Draft, draft-
              vasters-json-structure-alternate-names-03, 8 June 2026,
              <https://datatracker.ietf.org/doc/html/draft-vasters-json-
              structure-alternate-names-03>.

   [JSTRUCT-IMPORT]
              Vasters, C., "JSON Structure: Import", Work in Progress,
              Internet-Draft, draft-vasters-json-structure-import-03, 8
              June 2026, <https://datatracker.ietf.org/doc/html/draft-
              vasters-json-structure-import-03>.

   [JSTRUCT-RELATIONS]
              Vasters, C., "JSON Structure: Relations", Work in
              Progress, Internet-Draft, draft-vasters-json-structure-
              relations-00, 8 June 2026,
              <https://datatracker.ietf.org/doc/html/draft-vasters-json-
              structure-relations-00>.

   [KITTI]    Geiger, A., Lenz, P., Stiller, C., and R. Urtasun, "Vision
              meets Robotics: The KITTI Dataset", 2013,
              <https://www.cvlibs.net/publications/Geiger2013IJRR.pdf>.

   [LOINC]    Regenstrief Institute, "LOINC", n.d.,
              <https://loinc.org/>.

   [NAIF-QUAT]
              NASA Jet Propulsion Laboratory, Navigation and Ancillary
              Information Facility, "Quaternions White Paper", 30
              November 2003, <https://naif.jpl.nasa.gov/pub/naif/misc/
              Quaternion_White_Paper/Quaternions_White_Paper.pdf>.

   [OGC-TOPIC2]
              Open Geospatial Consortium, "OGC Abstract Specification
              Topic 2: Referencing by coordinates", 2019,
              <https://docs.ogc.org/as/18-005r4/18-005r4.html>.

Vasters                  Expires 7 February 2027              [Page 130]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   [OGC-TOPIC25]
              Open Geospatial Consortium, "OGC Abstract Specification
              Topic 25: Abstract Conceptual Model for Time", n.d.,
              <https://docs.ogc.org/as/23-049/23-049.html>.

   [OWL2]     World Wide Web Consortium, "OWL 2 Web Ontology Language
              Document Overview", n.d.,
              <https://www.w3.org/TR/owl2-overview/>.

   [PNG3]     World Wide Web Consortium, "Portable Network Graphics
              (PNG) Specification (Third Edition)", 24 June 2025,
              <https://www.w3.org/TR/png-3/>.

   [PROV-O]   World Wide Web Consortium, "PROV-O: The PROV Ontology",
              n.d., <https://www.w3.org/TR/prov-o/>.

   [QUDT]     QUDT.org, "QUDT Ontologies", n.d.,
              <https://www.qudt.org/>.

   [RDF-CONCEPTS]
              World Wide Web Consortium, "RDF 1.1 Concepts and Abstract
              Syntax", n.d., <https://www.w3.org/TR/rdf11-concepts/>.

   [RDF-SCHEMA]
              World Wide Web Consortium, "RDF Schema 1.1", n.d.,
              <https://www.w3.org/TR/rdf-schema/>.

   [REP-103]  Foote, T. and M. Purvis, "REP 103: Standard Units of
              Measure and Coordinate Conventions", 7 October 2010,
              <https://www.ros.org/reps/rep-0103.html>.

   [RFC8792]  Watsen, K., Auerswald, E., Farrel, A., and Q. Wu,
              "Handling Long Lines in Content of Internet-Drafts and
              RFCs", RFC 8792, DOI 10.17487/RFC8792, June 2020,
              <https://www.rfc-editor.org/rfc/rfc8792>.

   [SKOS]     World Wide Web Consortium, "SKOS Simple Knowledge
              Organization System Reference", n.d.,
              <https://www.w3.org/TR/skos-reference/>.

   [SNOMED-CT]
              SNOMED International, "SNOMED CT", n.d.,
              <https://www.snomed.org/>.

   [SOSA-SSN] World Wide Web Consortium, "Semantic Sensor Network
              Ontology", n.d., <https://www.w3.org/TR/vocab-ssn/>.

Vasters                  Expires 7 February 2027              [Page 131]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   [SPASE]    SPASE Consortium, "Space Physics Archive Search and
              Extract (SPASE) Data Model, Version 2.7.2", 2026,
              <https://spase-group.org/data/model/spase-latest/
              index.html>.

   [SSC-COORDS]
              NASA Goddard Space Flight Center, "Satellite Situation
              Center Users Guide, Appendix C: Description of Selected
              Coordinate Systems", n.d.,
              <https://sscweb.gsfc.nasa.gov/users_guide/
              Appendix_C.html>.

   [UNLOCODE] United Nations Economic Commission for Europe, "UN/LOCODE:
              United Nations Code for Trade and Transport Locations",
              n.d., <https://unece.org/trade/cefact/unlocode-code-list-
              country-and-territory>.

   [UNSPSC]   United Nations Global Marketplace, "United Nations
              Standard Products and Services Code (UNSPSC)", n.d.,
              <https://www.ungm.org/Public/UNSPSC>.

   [USGS-LANDSAT]
              United States Geological Survey, "What are the band
              designations for the Landsat satellites?", n.d.,
              <https://www.usgs.gov/faqs/what-are-band-designations-
              landsat-satellites>.

   [USGS-LANDSAT-L1]
              United States Geological Survey, "Using the USGS Landsat
              Level-1 Data Product", n.d., <https://www.usgs.gov/
              landsat-missions/using-usgs-landsat-level-1-data-product>.

   [WHO-ATC]  WHO Collaborating Centre for Drug Statistics Methodology,
              "ATC/DDD Index", n.d.,
              <https://atcddd.fhi.no/atc_ddd_index/>.

   [WHO-ICD]  World Health Organization, "International Classification
              of Diseases (ICD)", n.d., <https://icd.who.int/>.

   [WMO-CODES]
              World Meteorological Organization, "WMO Codes Registry
              (WMO No. 306 Manual on Codes)", n.d.,
              <https://codes.wmo.int/>.

Vasters                  Expires 7 February 2027              [Page 132]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   [WSDOT-LRS]
              Washington State Department of Transportation, "State
              Route Linear Referencing System", n.d.,
              <https://data.wsdot.wa.gov/arcgis/rest/services/Shared/
              LRSData/FeatureServer/9>.

Appendix A.  Reference URIs (Informative)

   The URIs below illustrate the kind values defined in this document.
   None of these lists is exhaustive, and a publisher can supersede any
   definition.

A.1.  Vocabularies

   A reference identifies a term, not the namespace of the model that
   defines it; Section 4.1 names the model behind each kind.
   Vocabularies that define terms in those models and that are widely
   used with observation data include the Semantic Sensor Network
   ontology [SOSA-SSN], which publishes http://www.w3.org/ns/sosa/ and
   http://www.w3.org/ns/ssn/, and the Provenance Ontology [PROV-O],
   which publishes http://www.w3.org/ns/prov#.

A.2.  Temporal Reference Systems

   The URIs in this section resolve at the OGC definitions server.

   Time-scale concepts, for kind ogc-trs:

   *  http://www.opengis.net/def/trs/BIPM/0/UTC, Coordinated Universal
      Time;

   *  http://www.opengis.net/def/trs/BIPM/0/TAI, International Atomic
      Time;

   *  http://www.opengis.net/def/trs/IERS/0/UT1, Universal Time UT1; and

   *  http://www.opengis.net/def/trs/USNO/0/GPS, GPS Time.

   None of these constrains the type of the annotated value.  Each names
   a time scale and establishes no axis, unit, or encoding, so any of
   them can accompany a Core temporal type, a string, a numeric epoch
   count, or a compound position.

   Temporal coordinate reference systems, for kind ogc-temporal-crs.
   Each establishes an origin and an axis, and the axis constrains the
   annotated type:

Vasters                  Expires 7 February 2027              [Page 133]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   *  http://www.opengis.net/def/crs/OGC/0/GregorianDateTime, a date and
      time in the Gregorian calendar.  Its axis carries no unit, and it
      takes a Core datetime, date, or time, or a string in the same
      form.

   *  http://www.opengis.net/def/crs/OGC/0/UnixTime, seconds elapsed
      from 1970-01-01T00:00:00Z.  It takes an integer or number carrying
      UCUM s.

   *  http://www.opengis.net/def/crs/OGC/0/AnsiDate, days elapsed from
      1601-01-01T00:00:00Z.  It takes an integer or number carrying UCUM
      d.

   *  http://www.opengis.net/def/crs/OGC/0/JulianDate, days elapsed from
      the Julian period origin.  It takes a number carrying UCUM d,
      since its origin falls at noon and positions are ordinarily
      fractional.

   *  http://www.opengis.net/def/crs/OGC/0/TruncatedJulianDate, days
      elapsed from 1968-05-24T00:00:00Z.  It takes a number carrying
      UCUM d.

   *  http://www.opengis.net/def/crs/OGC/0/BeforePresentTime, years
      counted backwards from 1950.  It takes a number carrying UCUM a.

   *  http://www.opengis.net/def/crs/OGC/0/ChronometricGeologicTime,
      millions of years counted backwards from year zero.  It takes a
      number carrying UCUM Ma.

   None of the numeric definitions takes a string, and GregorianDateTime
   does not take a number.  The last two count backwards, so a larger
   value is an earlier position and sortOrder is backward.

   The register also serves a parameterized definition taking an origin
   and a unit, which covers epoch counts for which no named definition
   exists.  A count of milliseconds from the Unix origin is identified
   by:

   http://www.opengis.net/def/crs/OGC/0/Temporal
     ?epoch=%221970-01-01T00:00:00Z%22&uom=%22ms%22

   Parameter values are quoted, and the URI is one line.  The constraint
   follows the uom parameter: this URI takes an integer or number
   carrying UCUM ms.  A count of seconds from the same origin is a
   different definition, not the same definition read at a different
   scale.

Vasters                  Expires 7 February 2027              [Page 134]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

A.3.  Coordinate Reference Systems

   For kind ogc-crs:

   *  http://www.opengis.net/def/crs/OGC/1.3/CRS84, WGS 84 with axes
      longitude, latitude;

   *  http://www.opengis.net/def/crs/OGC/0/CRS84h, WGS 84 with axes
      longitude, latitude, ellipsoidal height;

   *  http://www.opengis.net/def/crs/EPSG/0/4326, WGS 84 with axes
      latitude, longitude;

   *  http://www.opengis.net/def/crs/EPSG/0/4979, WGS 84 with axes
      latitude, longitude, ellipsoidal height.

   Axis order differs among these definitions, and the definition
   establishes it.  The first two and the last two describe the same
   datum in opposite axis order.

   For kind epsg, the EPSG Geodetic Parameter Dataset serves its own
   records, for example https://apps.epsg.org/api/v1/CoordRefSystem/4326
   [EPSG].  A definition served at an OGC URI under an EPSG code, as in
   the list above, is ogc-crs rather than epsg.

A.4.  Vector Reference Frames

   No register of vector reference frames corresponds to the temporal
   and coordinate registers.  A registered coordinate reference system
   whose axes are directions may be cited with ogc-crs or epsg, and the
   URIs listed in Appendix A.3 apply unchanged.  Most frames in which
   vector quantities are reported are not registered at all.

   Some communities publish a closed list of frame _names_ without
   serving a URI per frame.  The SPASE data model [SPASE] is the case in
   point: its CoordinateSystemName enumeration fixes tokens such as GSE,
   GSM, GEI, SM, RTN, HEE, MFA, and SensorCoordinates, and defines what
   each one means, but the register itself carries no per-token
   reference URI.  A token from such a list is not a reference value.
   Where the community that publishes the list also serves a resolvable
   definition, that URI is the reference and the token is not; where it
   does not, the frame is written as a tuple meta-type in the schema
   document and cited with kind type, as in Section 10.2.

Vasters                  Expires 7 February 2027              [Page 135]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

A.5.  Linear Reference Systems

   No register of linear reference systems corresponds to the temporal
   and coordinate registers.  ISO 19148 [ISO19148] specifies the
   conceptual schema, in which a location is a measurement along a
   linear element and optionally an offset from it, so that overlapping
   attributes can be carried against one geometry without fragmenting
   it.  It defines no identifiers for individual systems.  A linear
   reference system is therefore published by the authority that
   maintains the network, which is why lrs-network is the value defined
   here for a published system, and why a system published in another
   form is identified by a value naming the model that publishes it.  A
   system that no authority publishes is defined as a meta-type in the
   schema and cited with type.

   In the United States, the FHWA ARNOLD directive [FHWA-ARNOLD]
   requires each state department of transportation to maintain one
   linear reference system covering all public roads, modelled as the
   HPMS Field Manual prescribes [FHWA-HPMS]: routes carrying measure
   values on their vertices, with attributes held in event tables that
   cite a route and a measure rather than segmenting the underlying
   geometry.  A service published under that directive is an lrs-
   network, and its layer and metadata resources establish the linear
   elements and the measure.  The Washington state route network used in
   Section 10.5 is served at
   https://data.wsdot.wa.gov/arcgis/rest/services/Shared/LRSData/
   FeatureServer/9 [WSDOT-LRS].

A.6.  Code Lists

   A reference identifies one specific code list, and kind classifies
   the register model that list belongs to (Section 6.1).  The registers
   fall into two tiers by how a reference behaves.

   Some publish a resolvable URI for the list, or for each entry, so
   that a reference both identifies and dereferences:

   *  wmo-codes: a register in the WMO Codes Registry, such as
      http://codes.wmo.int/bufr4/codeflag/0-20-003, the present-weather
      register, whose entries are served beneath it [WMO-CODES].

   *  iana: a registry served under https://www.iana.org/assignments/,
      such as https://www.iana.org/assignments/media-types/media-
      types.xhtml for media types, or https://www.iana.org/assignments/
      language-subtag-registry for the BCP 47 language subtags
      [IANA-PROTOCOLS] [IANA-LANGTAGS].

Vasters                  Expires 7 February 2027              [Page 136]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

   *  snomed-ct: an edition under the SNOMED CT URI scheme,
      http://snomed.info/sct for the International Edition, with a
      module or version appended for a specific release [SNOMED-CT].

   *  loinc: the LOINC code system, http://loinc.org [LOINC].

   *  icd: a WHO linearization, http://id.who.int/icd/release/11/mms for
      the ICD-11 mortality and morbidity statistics [WHO-ICD].

   The rest publish their lists in standards or directories that mint no
   per-list machine URI.  A reference to one identifies more often than
   it resolves, and names the standard's identifier or landing page:

   *  iso: an ISO code table, named by its catalogue page such as
      https://www.iso.org/iso-3166-country-codes.html, or by a standard
      URN such as urn:iso:std:iso:3166:-1 [ISO3166] [ISO4217] [ISO639].

   *  unlocode: https://unece.org/trade/cefact/unlocode-code-list-
      country-and-territory [UNLOCODE].

   *  icao: the location indicators of Doc 7910,
      https://store.icao.int/en/location-indicators-doc-7910, or the
      aircraft type designators of Doc 8643, https://www.icao.int/
      operational-safety/doc-8643-aircraft-type-designators [ICAO7910]
      [ICAO8643].

   *  iata: https://www.iata.org/en/publications/directories/code-
      search/ [IATA-CODES].

   *  atc: https://atcddd.fhi.no/atc_ddd_index/ [WHO-ATC].

   *  unspsc: https://www.ungm.org/Public/UNSPSC [UNSPSC].

   A processor is not required to dereference a reference of either
   tier, and an unresolved reference is indeterminate rather than
   incorrect.  Under kind type the list is a meta-type in the schema and
   reference is the type reference { "$ref": <JSON Pointer> }, not a
   URI.

Change Log

   *  Initial version.

Acknowledgments

   The author thanks the JSON Structure community for review and
   feedback.

Vasters                  Expires 7 February 2027              [Page 137]
Internet-Draft     JSON Structure Semantic Annotations       August 2026

Author's Address

   Clemens Vasters
   Microsoft Corporation
   Email: clemensv@microsoft.com

Vasters                  Expires 7 February 2027              [Page 138]