Endpoint Registry Service - Version 1.0-rc3 πŸ”—

Abstract πŸ”—

This specification defines an endpoint registry extension to the xRegistry document format and API specification. An endpoint registry allows for publishing and discovery of asynchronous event sources, sinks, and subscription points in the scope of a system, along with important configuration parameters.

Table of Contents πŸ”—

Overview πŸ”—

This specification defines a registry of metadata definitions for abstract and concrete network endpoints to which messages can be produced, from which messages can be consumed, or which make messages available for subscriptions.

The metadata model defined in this specification is specifically focused on describing unidirectional endpoints for asynchronous information flows like discrete events, event streams, queueing, and publish/subscribe patterns.

Endpoint information is provided through the registry for discovery of endpoints, dynamic configuration of clients, and code generation.

The model allows for a loose correlation of endpoints through a channel concept, to designate, for instance, the input and output ends of a queue, but it intentionally avoids being specific about the shape of messaging and eventing entities. The correlation of endpoints for the purposes of realizing specific message exchange patterns like request/response or scatter/gather is also intentionally out of scope for this metadata model, because modeling such correlation contracts with sufficient depth is a whole additional definition layer above what this model aims to achieve.

The goal of this endpoint metadata model is to provide metadata structure to asynchronous topics and streams and queues in a way that is similar to how table and column definitions provide structure to databases. Database schemas structure data that you have. Endpoint definitions with their referenced or embedded message definitions with referenced or embedded schema definitions structure data that you will yet receive.

Continuing that analogy, the endpoint scope corresponds to the database, the message groups are schema scopes, and the message definitions correspond to tables. The schema associated with a message definition determines the column layout of the table. As event streams often end up landing in databases for long-term archival and analysis, this structural alignment is very helpful.

Endpoints πŸ”—

In a distributed system, the networked input sinks and output sources of an application, or an application infrastructure component like an event broker, are commonly called β€œendpoints”. Those endpoints serve as communication conduits to make information available to the application, or for the application to make information available to others.

In this specification we distinguish three distinct usage roles for endpoints:

Each endpoint definition defines a protocol selector by which the specific network application protocol is chosen to communicate with the endpoint. If a networked entity supports multiple protocols, each protocol endpoint MUST be declared separately, even if those are multiplexed over the same port. For instance, if you have an MQTT broker that can dynamically select between MQTT 3.1.1 and MQTT 5.0, those endpoints are to be declared separately as the capabilities differ substantially.

The protocol selector value determines which protocoloptions become available to define for the endpoint. The protocol-specific options are enumerated and explained in protocol options.

Each endpoint MAY also define an envelope selector which allows for defining particular envelopeoptions at the endpoint level. For CloudEvents, this permits the definition of the serialization mode (binary or structured) and the event format for structured mode.

Message Groups πŸ”—

The Endpoint is an xRegistry group-level construct that is conceptually an extension of the message definition group, meaning there are no β€œgroups of endpoints”. An endpoint MAY contain directly embedded message definitions. In the simplest case, an endpoint MAY embed its message definitions locally which in turn MAY embed their data schema definitions locally, all in one compact construct.

More commonly, Endpoints will reference one or more message definition groups that are defined externally in a message registry, and which have the advantage of being shareable across multiple Endpoints.

For describing a message broker queue, the best approach is to define a message group that defines the messages that are be allowed to flow on the queue and for that message group to then be referenced from the producer and the consumer endpoints of the queue, whereby both of those endpoints share the same channel identifier.

In the endpoint context, message groups have a function similar to interfaces in programming languages. They define related sets of messages that can be associated with an endpoint all at once.

Scenarios πŸ”—

Endpoint definitions can be abstract or concrete, distinguished by the deployed flag. If the deployed flag is set to true, one can expect the endpoint to be reachable on the network with the given parameters, assuming the client is within the same network scope. If the flag is set to false, the endpoint definition is to be treated like a template where configuration elements like the endpoint URI will have to be supplied by external configuration for the client to become functional.

A possible application of the latter are Endpoint definitions that define endpoint patterns as they are common for applications of the MQTT protocol. For instance, the Eclipse Sparkplug protocol is a convention that defines endpoint roles and messages and schemas for MQTT, and the SparkPlugB example that illustrates how Registry Endpoints can model the convention in formal terms.

Notations and Terminology πŸ”—

Notational Conventions πŸ”—

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.

For clarity, OPTIONAL attributes (specification-defined and extensions) are OPTIONAL for clients to use, but the servers' responsibility will vary. Server-unknown extension attributes MUST be silently stored in the backing datastore. Specification-defined, and server-known extension, attributes MUST generate an error if the corresponding feature is not supported or enabled. However, as with all attributes, if accepting the attribute would result in a bad state (such as exceeding a size limit, or results in a security issue), then the server MAY choose to reject the request.

In the pseudo JSON format snippets ? means the preceding attribute is OPTIONAL, * means the preceding attribute MAY appear zero or more times, and + means the preceding attribute MUST appear at least once. The presence of the # character means the remaining portion of the line is a comment. Whitespace characters in the JSON snippets are used for readability and are not normative.

Terminology πŸ”—

This specification defines the following terms:

Endpoint πŸ”—

An "endpoint" is a logical or physical network location to which messages can be produced, from which messages can be consumed, or which makes messages available via subscription for delivery to a consumer-designated endpoint.

Endpoint Registry Model πŸ”—

The Endpoint Registry is a registry of metadata definitions for abstract and concrete network endpoints to which messages can be produced, from which messages can be consumed, or which makes messages available via subscription and delivery to a consumer-designated endpoint.

As discussed in the CloudEvents Registry overview, endpoints are supersets of message definition groups and MAY contain inlined messages. Therefore, the Resources in the meta-model for the Endpoint Registry are likewise messages as defined in the message catalog specification.

The formal xRegistry extension model of the Endpoints Registry resides in the model.json file.

For easy reference, the JSON serialization of an Endpoint Registry adheres to this form:

{
  "specversion": "<STRING>",
  "registryid": "<STRING>",
  "self": "<URL>",
  "xid": "<XID>",
  "epoch": <UINTEGER>,
  "name": "<STRING>", ?
  "description": "<STRING>", ?
  "documentation": "<URL>", ?
  "labels": {
    "<STRING>": "<STRING>" *
  }, ?
  "createdat": "<TIMESTAMP>",
  "modifiedat": "<TIMESTAMP>",

  "model": { ... }, ?

  "endpointsurl": "<URL>",
  "endpointscount": <UINTEGER>,
  "endpoints": {
    "<KEY>": {
      "endpointid": "<STRING>",                   # xRegistry core attributes
      "self": "<URL>",
      "xid": "<XID>",
      "epoch": <UINTEGER>,
      "name": "<STRING>", ?
      "description": "<STRING>", ?
      "documentation": "<URL>", ?
      "labels": { "<STRING>": "<STRING>" * }, ?
      "createdat": "<TIMESTAMP>",
      "modifiedat": "<TIMESTAMP>",
      "deprecated": { ... }, ?

      "usage": [ "<STRING>" + ] ,                 # subscriber, consumer, producer
      "channel": "<STRING>", ?

      # Start of Endpoint extension attributes
      "envelope": "<STRING>", ?                   # e.g. CloudEvents/1.0
      "envelopeoptions": {
        "<STRING>": <JSON-VALUE> *

        # CloudEvents/1.0 options
        "mode": "<STRING>", ?                     # binary, structured
        "format": "<STRING>" ?                    # e.g. application/json
      },

      "protocol": "<STRING>", ?                   # e.g. HTTP/1.1
      "protocoloptions": {
        "<STRING>": <JSON-VALUE> *

        # Common protocol options
        "endpoints": [
          {                                     # entry shape is protocol
            "uri": "<URI>", ?                   #   specific: "uri" for all
            "bootstrap.servers":                #   protocols except "KAFKA",
              [ "<STRING>" * ], ?               #   which has no "uri" and
            "<STRING>": <JSON-VALUE> *          #   uses "bootstrap.servers"
          } *
        ], ?
        "authorization": [
          {
            "type": "<STRING>", ?
            "mechanism": "<STRING>", ?
            "resourceuri": "<URI>", ?
            "authorityuri": "<URI>" ?
          } *
        ], ?
        "deployed": <BOOLEAN>, ?

        # "HTTP" protocol options
        "method": "<STRING>", ?                          # Default: POST
        "headers": [ { "name": "<STRING>", "value": "<STRING>" } * ], ?
        "query": { "<STRING>": "<STRING>" * }, ?
        "apikeyname": "<STRING>", ?
        "apikeyin": "header" | "query" ?,              # Default: header
        "plainscheme": "basic" | "form" | "query" ?, # Default: basic
        "plainusernamefield": "<STRING>", ?
        "plainpasswordfield": "<STRING>" ?

        # "AMQP/1.0" protocol options
        "node": "<STRING>", ?
        "durable": <BOOLEAN>, ?                          # Default: false
        "link-properties": { "<STRING>": "<STRING>" * }, ?
        "connection-properties": { "<STRING>": "<STRING>" * }, ?
        "distribution-mode": "move" | "copy" ?,         # Default: move
        "connection-capabilities": [ "<STRING>" * ], ?
        "node-capabilities": [ "<STRING>" * ], ?
        "source-filters": { "<STRING>": <JSON-VALUE> * }, ?
        "dynamic": <BOOLEAN>, ?
        "terminus-durability": "none" | "configuration" | "unsettled-state" ?,
        "expiry-policy": "link-detach" | "session-end" | "connection-close" | "never" ?,
        "timeout": <UINTEGER>, ?
        "sender-settle-mode": "unsettled" | "settled" | "mixed" ?,
        "receiver-settle-mode": "first" | "second" ?

        # "MQTT/3.1.1" protocol options
        "topic": "<STRING>", ?
        "qos": <UINTEGER>, ?                             # Default: 0
        "retain": <BOOLEAN>, ?                           # Default: false
        "cleansession": <BOOLEAN>, ?                     # Default: true
        "topicfilter": "<STRING>", ?
        "willtopic": "<STRING>", ?
        "willmessage": "<XID>" ?

        # "MQTT/5.0" protocol options
        "topic": "<STRING>", ?
        "qos": <UINTEGER>, ?                             # Default: 0
        "retain": <BOOLEAN>, ?                           # Default: false
        "topicfilter": "<STRING>", ?
        "cleanstart": <BOOLEAN>, ?
        "sessionexpiryinterval": <UINTEGER>, ?
        "sharedsubscriptiongroup": "<STRING>", ?
        "nolocal": <BOOLEAN>, ?
        "retainaspublished": <BOOLEAN>, ?
        "retainhandling": 0 | 1 | 2 ?,
        "willtopic": "<STRING>", ?
        "willmessage": "<XID>" ?

        # "KAFKA" protocol options
        "topic": "<STRING>", ?
        "acks": <INTEGER>, ?                             # Default: 1
        "key": "<STRING>", ?
        "partition": <INTEGER>, ?
        "consumergroup": "<STRING>", ?
        "headers": { "<STRING>": "<STRING>" * }, ?
        "keyserializer": "<STRING>", ?
        "valueserializer": "<STRING>", ?
        "autooffsetreset": "earliest" | "latest" | "none" ?,
        "enableautocommit": <BOOLEAN> ?

        # "NATS" protocol options
        "subject": "<STRING>", ?
        "subjectfilter": "<STRING>", ?
        "queuegroup": "<STRING>" ?
      }, ?

      "messagegroups": [ "<URI>" * ], ?
      # End of Endpoint extensions

      "messagesurl": "<URL>", ?
      "messagescount": <UINTEGER>, ?
      "messages": {
        "<KEY>": {                                # messageid
          # See Message Definition spec for details
        } *
      } ?
    } *
  } ?
}

Endpoints Groups πŸ”—

The Group plural name (<GROUPS>) is endpoints, and the Group singular name (<GROUP>) is endpoint.

The following attributes are defined for the endpoint object in addition to the xRegistry-defined core attributes:

usage πŸ”—

channel πŸ”—

envelope πŸ”—

envelopeoptions πŸ”—

This specification defines the following envelope options for the indicated envelope values:

CloudEvents/1.0 πŸ”—

protocol πŸ”—

protocoloptions πŸ”—

protocoloptions.endpoints πŸ”—
protocoloptions.authorization πŸ”—
protocoloptions.authorization.type πŸ”—
protocoloptions.authorization.mechanism πŸ”—
protocoloptions.authorization.resourceuri πŸ”—
protocoloptions.authorization.authorityuri πŸ”—
protocoloptions.deployed πŸ”—

messagegroups πŸ”—

The messagegroups attribute is an array of URI to message definition groups. Relative references (beginning with /) are XIDs within the same registry. Absolute URIs reference message definition groups in external registries. The server stores absolute URIs as-is without resolving them.

The messagegroups attribute is used to reference message definition groups that are not inlined in the endpoint definition.

Example:

{
  "protocol": "HTTP/1.1",
  "protocoloptions": {
    "method": "POST"
  },
  "messagegroups": [
    "/messagegroups/mygroup",
    "https://other-catalog.example.com/messagegroups/external-group"
  ]
}

messages πŸ”—

Endpoints are supersets of message definition groups and MAY contain inlined messages. See Message Definitions.

Example:

{
  "protocol": "HTTP/1.1",
  "protocoloptions": {
    "method": "POST"
  },

  "messagesurl": "...",
  "messagescount": 1,
  "messages": {
    "myevent": {
      "envelope": "CloudEvents/1.0",
      "envelopemetadata": {
        "attributes": {
          "type": {
            "value": "myevent"
          }
        }
      }
    }
  }
}

When this specification, and the message specification, are used with specifications such as CloudEvents, where a semantically unique identifier is used in a runtime message (e.g. CloudEvent's type attribute), it is STRONGLY RECOMMENDED that the messageid values of the message definitions for an Endpoint match that unique identifier and therefore be unique across all messages within the messages collection and the messages referenced by the messagegroups attribute. This will allow for an easy "lookup" from an incoming runtime message to its related message definition.

However, there are times when this is not possible. For example, take the case where an Endpoint might have the same semantic message defined twice, once for a JSON serialization and once for an XML serialization. Using the same messageid value is not possible (even though the CloudEvent type attribute would be the same for both runtime messages), so one (or both) message definition's messageid values might not match the runtime message's type value. In those cases, finding the appropriate message definition will need to be done via examination of some other metadata - such as the message's envelopemetadata.type value along with its envelopeoptions.format value. These details are out of scope for this specification to define and are left as an implementation detail.

Implementations MAY choose to generate an error if it detects duplicate messageid values across the messages collection message definitions and the messagegroups referenced message definitions, if that is the desired constraint for their users.

Protocol Options πŸ”—

For each protocol specified in the following sections there is a table that describes the set of protocol-specific options and the roles (Producer, Consumer, Subscriber) to which each option applies. All protocol options are OPTIONAL.

The role applicability is descriptive: it guides clients on how to interpret metadata. Where a rule below is stated with MUST, MUST NOT, or REQUIRED, it is a conformance requirement of this specification, and a client evaluating the metadata MUST treat a violation as an error. A Registry server is not obligated to check these rules.

In each table below, role applicability is shown as:

Any string value of any protocol option MAY contain placeholders expressed with the RFC6570 Level 1 URI Template expression syntax, for example orders/{tenantid}/events. This applies to plain string values, to the string items of arrays, and to the keys and values of maps, and it also applies to the uri values of protocoloptions.endpoints. Placeholders are resolved out-of-band by the client; this specification does not define how the values are supplied. When the same placeholder name occurs in more than one value of the same endpoint, all of its occurrences MUST resolve to the same value.

HTTP options πŸ”—

The endpoint URIs for "HTTP" endpoints MUST be valid HTTP URIs using the "http" or "https" scheme as defined in HTTP Message Format.

HTTP has no single connection that serves several roles, so each HTTP role is a distinct interface with its own request contract. This specification distinguishes three HTTP roles:

An "HTTP" Endpoint describes a profile for message and event transfer over HTTP, not a general-purpose HTTP API surface. Declaring exactly one role per Endpoint keeps the request contract of each interface unambiguous, so that a client knows what it can send and what it can expect without inspecting individual messages. Describing a general HTTP API is out of scope for this specification and is served by an API description language such as OpenAPI.

Constraints:

Name Type P C S Description
method string (HTTP method), default POST βœ“ βœ“ βœ“ HTTP method for the concrete operation represented by the endpoint.
headers array of {name: string, value: string} βœ“ βœ“ βœ“ HTTP request headers. Duplicate names are allowed.
query map of string to string βœ“ βœ“ βœ“ HTTP query parameters for the operation.
apikeyname string βœ“ βœ“ βœ“ Name of the API key carrier when authorization.type is APIKey (for example x-api-key).
apikeyin enum: header, query, default header βœ“ βœ“ βœ“ Placement of API key metadata when authorization.type is APIKey. header SHOULD be used; query SHOULD only be used when header placement is not possible.
plainscheme enum: basic, form, query, default basic βœ“ βœ“ βœ“ Transport pattern for authorization.type = Plain. basic refers to HTTP Basic authentication (RFC7617).
plainusernamefield string βœ“ βœ“ βœ“ Parameter or header field name carrying the username when plainscheme is form or query.
plainpasswordfield string βœ“ βœ“ βœ“ Parameter or header field name carrying the password when plainscheme is form or query.

These options only define protocol-level placement and naming metadata. Credential values (API keys, usernames, passwords) MUST NOT be stored in endpoint metadata and MUST be supplied out-of-band.

AMQP options πŸ”—

The endpoint URIs for "AMQP" endpoints MUST be valid AMQP URIs using the "amqp" or "amqps" scheme. If the path portion of the URI is present, it MUST be a valid AMQP node name according to AMQP Addressing Version 1.0.

The following options are defined for AMQP endpoints.

Name Type P C S Description
node string βœ“ βœ“ βœ“ AMQP node (address). When set, it overrides the URI path.
durable boolean, default false βœ“ - - Whether the node identified by node is a durable node rather than a transient one. This is a property of the node. It is not the AMQP message header field of the same name and it is not terminus durability, which is expressed by terminus-durability. It does not by itself imply a delivery guarantee.
link-properties map of string to string βœ“ βœ“ βœ“ AMQP link properties.
connection-properties map of string to string βœ“ βœ“ βœ“ AMQP connection properties.
distribution-mode enum: move, copy, default move - βœ“ βœ“ AMQP source distribution mode. move means a transferred message is removed from the node and is therefore transferred to at most one receiver. copy means the message remains at the node after transfer and can also be transferred to other receivers. This describes distribution between the node and its receivers; it does not describe message locking.
connection-capabilities array of string βœ“ βœ“ βœ“ AMQP connection capabilities.
node-capabilities array of string βœ“ βœ“ βœ“ AMQP node capabilities.
source-filters map of string to any - βœ“ βœ“ AMQP source filter expressions/descriptor keys for receive setup.
dynamic boolean βœ“ βœ“ βœ“ Dynamic node creation for source/target setup, depending on role.
terminus-durability enum: none, configuration, unsettled-state βœ“ βœ“ βœ“ Durability mode for the applicable source or target terminus. For a producer endpoint this is the target terminus; for a consumer or subscriber endpoint it is the source terminus.
expiry-policy enum: link-detach, session-end, connection-close, never βœ“ βœ“ βœ“ Expiry policy for the applicable terminus, selected as for terminus-durability.
timeout uinteger βœ“ βœ“ βœ“ Timeout value used with terminus expiry policy.
sender-settle-mode enum: unsettled, settled, mixed βœ“ βœ“ βœ“ AMQP sender settle mode requested for the link. It constrains the party that sends transfers over the link: the local client for a producer endpoint, the remote node for a consumer or subscriber endpoint.
receiver-settle-mode enum: first, second βœ“ βœ“ βœ“ AMQP receiver settle mode requested for the link. It constrains the party that receives transfers over the link: the remote node for a producer endpoint, the local client for a consumer or subscriber endpoint.

An AMQP Endpoint MAY declare ["subscriber", "consumer"], because a single AMQP receiving link both establishes interest in the source node and carries the resulting transfers. When it does, the subscriber role refers to the establishment of the link with the node as source and the consumer role refers to the transfers over that link.

MQTT options πŸ”—

The endpoint URIs for "MQTT" endpoints MUST be valid MQTT URIs using the (informal) "mqtt" or "mqtts" scheme. If the path portion of the URI is present, it MUST be a valid MQTT topic name as described by MQTT 3.1.1 and MQTT 5.0. The informal schemes "tcp" (plain TCP/1883), "ssl" (TLS TCP/8883), and "wss" (Websockets/443) MAY also be used, but MUST NOT have a path.

The following options are defined for MQTT 3.1.1 and MQTT 5.0 endpoints.

Name Type P C S Description
topic string βœ“ - - Concrete publish topic name.
topicfilter string - - βœ“ Subscribe topic filter.
qos enum: 0, 1, 2, default 0 βœ“ βœ“ βœ“ Role-relative QoS intent: publish QoS for producer, requested max QoS for subscriber, effective delivery QoS for consumer context.
retain boolean, default false βœ“ - - MQTT retain flag for publish behavior.
willtopic string βœ“ βœ“ βœ“ CONNECT Will topic configuration.
willmessage xid (message reference) βœ“ βœ“ βœ“ CONNECT Will message definition reference.

Addressing constraints:

MQTT 3.1.1 specific options:

Name Type P C S Description
cleansession boolean, default true βœ“ βœ“ βœ“ MQTT 3.1.1 clean-session behavior for the connection.

MQTT 5.0 specific options:

Name Type P C S Description
cleanstart boolean βœ“ βœ“ βœ“ MQTT 5 clean-start behavior for the connection.
sessionexpiryinterval uinteger (0..4294967295) βœ“ βœ“ βœ“ MQTT 5 session expiry interval in seconds.
sharedsubscriptiongroup string - - βœ“ Shared subscription group name.
nolocal boolean - - βœ“ MQTT 5 subscribe no-local flag.
retainaspublished boolean - - βœ“ MQTT 5 subscribe retain-as-published flag.
retainhandling enum: 0, 1, 2 - - βœ“ MQTT 5 retain-handling mode.

Shared subscription constraints:

MQTT 5 Subscription Identifiers are runtime subscription state established by the subscribing client. They are not endpoint metadata and are therefore not defined as protocol options by this specification.

KAFKA options πŸ”—

The endpoint URIs for "Kafka" endpoints MUST be valid Kafka bootstrap server addresses. The scheme follows Kafka configuration usage as described in Apache Kafka, e.g. SSL://<HOST>:<PORT> or PLAINTEXT://<HOST>:<PORT>.

The following options are defined for Kafka endpoints.

Name Type P C S Description
topic string βœ“ βœ“ βœ“ Kafka topic name.
acks integer (-1..1), default 1 βœ“ - - Producer acknowledgement setting.
key string βœ“ - - Producer record key.
partition integer βœ“ βœ“ - Fixed producer partition target or explicit consumer partition selection.
consumergroup string - βœ“ - Consumer group identifier for group-based consumption.
headers map of string to string βœ“ - - Producer record headers.
keyserializer string βœ“ - - Producer key serializer class/name.
valueserializer string βœ“ - - Producer value serializer class/name.
autooffsetreset enum: earliest, latest, none - βœ“ - Consumer offset reset behavior when no valid committed offset exists.
enableautocommit boolean - βœ“ - Consumer automatic commit behavior.

Kafka does not have a subscription primitive that is separate from consumption; the group is the durable interest. This specification therefore discriminates the two roles by the presence of consumergroup:

NATS options πŸ”—

The endpoint URIs for "NATS" endpoints MUST be valid NATS URIs as described by NATS. The scheme MUST be "nats" or "tls" or "ws" and the URI MUST include a port number, e.g. nats://<HOST>:<PORT> or tls://<HOST>:<PORT>.

The options below describe Core NATS publish and subscribe.

The following options are defined for NATS endpoints.

Name Type P C S Description
subject string βœ“ - - Concrete publish subject.
subjectfilter string - - βœ“ Subscription subject filter.
queuegroup string - - βœ“ Queue subscription group associated with a subject filter.

Addressing constraints: