A Registry Service exposes resources, and their metadata, for the purposes of enabling discovery of those resources for either end-user consumption or automation and tooling.
A Registry Service is one that manages metadata about resources. At its core, the management of an individual resource is simply a REST-based interface for creating, modifying and deleting the resource. However, many resource models share a common pattern of grouping resources by their "type" and can optionally support versioning of the resources. This specification aims to provide a common interaction pattern for these types of services with the goal of providing an interoperable framework that will enable common tooling and automation to be created.
The first section of this specification, "Registry Formats and APIs", is meant to be a framework from which additional specifications can be defined that expose model specific resources and metadata.
The second section of this specification "CloudEvents Registry" defines a set of concrete resource types and metadata for the purpose of describing messaging and eventing endpoints, message and event metadata definitions, and the payload schemas they use. The name "CloudEvents Registry" reflects the specification coming from the CNCF CloudEvents project, but the specification is intended to be generic enough to be used with any messaging and eventing format and protocol and the registry section does thus define metadata formats for the native message formats of several other messaging and eventing protocols.
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, when a feature is marked as "OPTIONAL" this means that it is OPTIONAL for both the sender and receiver of a message message to support that feature. In other words, a sender can choose to include that feature in a message if it wants, and a receiver can choose to support that feature if it wants. A receiver that does not support that feature is free to take any action it wishes, including no action or generating an error, as long as doing so does not violate other requirements defined by this specification. However, the RECOMMENDED action is to ignore it. The sender SHOULD be prepared for the situation where a receiver ignores that feature. An Intermediary SHOULD forward OPTIONAL attributes.
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.
This specification defines the following terms:
An entity that acts as a collection of related Resources.
An implementation of this specification. Typically, the implementation would include model specific Groups, Resources and extension attributes.
A Resource is the main entity that is stored within a Registry Service. It MAY be versioned and grouped as needed by the Registry's model.
This section defines common Registry metadata elements and APIs. It is an explicit goal for this specification that metadata can be created and managed in files in a file system, for instance in a Git repository, and also managed in a Registry service that implement the API described here.
For instance, during development of a module, the metadata about the events raised by the modules will best be managed in a file that resides alongside the module's source code. When the module is ready to be deployed into a concrete system, the metadata about the events will be registered in a Registry service along with the endpoint where those events can be subscribed to or consumed from, and which allows discovery of the endpoint and all related metadata by other systems at runtime.
Therefore, the hierarchical structure of the Registry model is defined in such a way that is can be represented in a single file, including but not limited to JSON or YAML, or via the resource graph of a REST API.
The following attributes are used by one or more entities defined by this specification. They are defined here once rather than repeating them throughout the specification.
Attributes:
"id": "STRING"
"name": "STRING"
"description": "STRING"
"tags": { "STRING": "STRING" * }
"version": UINT
"epoch": UINT
"self": "URL"
"createdBy": "STRING"
"createdOn": "TIME"
"modifiedBy": "STRING"
"modifiedOn": "TIME"
"docs": "URI"
Implementations of this specification MAY define additional (extension) attributes, and they MAY appear at any level of the model. However they MUST adhere to the following rules:
- it is STRONGLY RECOMMENDED that they be named in such a way as to avoid potential conflicts with future Registry Service attributes. For example, use of a model specific prefix.
- they MUST differ from sibling attributes irrespective of case. This avoids potential conflicts if the attributes are serialized in a case-insensitive situation, such as HTTP headers.
In situations where an attribute is serialized in a case-sensitive situation, then the case specified by this specification, or the defining extension specification, MUST be adhere to.
- Type: String # SHOULD this be a URI-Reference?
- Description: An immutable unique identifier of the entity.
- Constraints:
- MUST be a non-empty string
- MUST be immutable
- MUST be unique within the scope of the entity's parent. In the case
of the
id
for the Registry itself, the uniqueness scope will be based on where the Registry is used. For example, a publicly accessible Registry might want to consider using a UUID, while a private Registry does not need to be so widely unique.
QUESTION: SHOULD Resource IDs be unique across the entire Registry too?
- Examples:
- A UUID
- Type: String
- Description: A human readable name of the entity.
Note that implementations MAY choose to enforce constraints on this value.
For example, they could mandate that
id
andname
be the same value. How any such requirement is shared with all parties is out of scope of this specification. - Constraints:
- MUST be a non-empty string
- Examples:
My Endpoints
- Type: String
- Description: A human readable summary of the purpose of the entity.
- Constraints:
- When this attributes has no value it MUST be serialized by either an empty string or by being excluded from the serialization of the owning entity
- Examples:
A queue of the sensor generated messages
- Type: Map of name/value string pairs
- Description: A mechanism in which additional metadata about the entity can be stored without changing the schema of the entity.
- Constraints:
- if present, MUST be a map of zero or more name/value string pairs
- each name MUST be a non-empty string consisting of only alphanumeric
characters,
-
,_
or a.
; be no longer than 63 characters; start with an alphanumeric character and be unique within the scope of this map. Values MAY be empty strings
- Examples:
{ "owner": "John", "verified": "" }
- Type: Unsigned Integer # SHOULD this be a String?
- Description: A numeric value representing a specific instance of an entity.
Note that versions of an entity can be modified without changing the
version
value. Often this value, or when a new version is created, is controlled by a user of the Registry. Also seeepoch
. - Constraints:
- MUST be an unsigned integer equal to or greater than zero
- older versions of the entity MUST have numerically smaller
version
values - MUST be unique across all versions of the entity
- Examples:
1
,2
,3
- Type: Unsigned Integer
- Description: A numeric value used to determine whether an entity has been
modified. Each time the associated entity is updated, this value MUST be
set to a new value that is greater than the current one.
Note that unlike
version
, this attribute is most often managed by the Registry itself. Additionally, if an entity is created that is based on another entity (e.g. a new version of an entity is created), then the new entity'sepoch
value can be reset (e.g. to zero) since the scope of its values is the entity. - Constraints:
- MUST be an unsigned integer equal to or greater than zero
- MUST be unique within the scope of a version of an entity. If the entity is not versioned then the scope is just the entity itself
- Examples:
1
,2
,3
- Type: URL
- Description: A unique URL for the entity. The URL MUST be a combination of
the base URL for the list of resources of this type of entity appended with
the
id
of the entity. - Constraints:
- MUST be a non-empty URL
- Examples:
https://example.com/registry/endpoints/123
- Type: String
- Description: A reference to the user or component that was responsible for the creation of this entity. This specification makes no requirement on the semantics or syntax of this value.
- Constraints:
- When this attributes has no value it MUST be serialized by either an empty string or by being excluded from the serialization of the owning entity
- Examples:
John Smith
john.smith@example.com
- Type: Timestamp
- Description: The date/time of when the entity was created.
- Constraints:
- MUST be a RFC3339 timestamp
- Examples:
- `2030-12-19T06:00:00Z"
- Type: String
- Description: A reference to the user or component that was responsible for the the latest update of this entity. This specification makes no requirement on the semantics or syntax of this value.
- Constraints:
- When this attributes has no value it MUST be serialized by either an empty string or by being excluded from the serialization of the owning entity
- Examples:
John Smith
john.smith@example.com
- Type: Timestamp
- Description: The date/time of when the entity was last updated.
- Constraints:
- MUST be a RFC3339 timestamp
- Examples:
- `2030-12-19T06:00:00Z"
- Type: URI-Reference
- Description: A URI-Reference to additional documentation about this entity. This specification does not place any constraints on the data returned from an HTTP GET to this value.
- Constraints:
- if present, MUST be a non-empty URI-Reference
- if present with a scheme, it MUST use either
http
orhttps
- MUST support an HTTP GET to this URI-Reference
- Examples:
https://example.com/docs/myQueue
This specification defines the following API patterns:
/?model # Manage the registry model
/ # Show all Groups
/GROUPs # Manage a Group Type
/GROUPs/gID # Manage a Group
/GROUPs/gID/RESOURCEs # Manage a Resource Type
/GROUPs/gID/RESOURCEs/rID # Manage the latest Resource version
/GROUPs/gID/RESOURCEs/rID?meta # Metadata about the latest Resource version
/GROUPs/gID/RESOURCEs/rID/versions # Show version strings for a Resource
/GROUPs/gID/RESOURCEs/rID/versions/VERSION # Manage a Resource version
/GROUPs/gID/RESOURCEs/rID/versions/VERSION?meta # Metadata about a Resource version
Where:
GROUPs
is a grouping name (plural). E.g.endpoints
gID
is the unique identifier of a single GroupRESOURCEs
is the type of resources (plural). E.g.definitions
rID
is the unique identifier of a single ResourceVERSION
is a version string referencing a versioned instead of a resource
While these APIs are shown to be at the root path of a Registry Service, implementation MAY choose to prefix them as necessary. However, the same prefix MUST be used consistently for all APIs in the same Registry Service.
The following sections define the APIs in more detail.
This returns the metadata describing the model of the Registry Service.
The request MUST be of the form:
GET /?model
A successful response MUST be of the form:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
{
"groups": [
{ "singular": "STRING", # eg. "endpoint"
"plural": "STRING", # eg. "endpoints"
"schema": "URI-Reference", ? # Schema doc for the group
"resources": [
{ "singular": "STRING", # eg. "definition"
"plural": "STRING", # eg. "definitions"
"versions": INT ? # Num old versions. Def=0, -1=unlimited
} +
] ?
} +
] ?
}
The following describes the attributes of Registry model:
groups
- REQUIRED if there are any Groups defined for the Registry
- The set of Groups supported by the Registry
groups.singular
- REQUIRED
- The singular name of a Group. E.g.
endpoint
- MUST be unique across all Groups in the Registry
groups.plural
- REQUIRED
- The plural name of a Group. E.g.
endpoints
- MUST be unique across all Groups in the Registry
groups.schema
- OPTIONAL
- A URI-Reference to a schema document for the Group
groups.resources
- REQUIRED if there are any Resources defined for the Group
- The set of Resource entities defined for the Group
groups.resources.singular
- REQUIRED
- The singular name of the Resource. E.g.
definition
groups.resources.plural
- REQUIRED
- The plural name of the Resource. E.g.
definitions
groups.resources.versions
- OPTIONAL
- Number of versions per Resource that will be stored in the Registry
- The default value is zero (
0
), meaning no old versions will be stored - A value of negative one (
-1
) indicates there is no stated limit, and implementation MAY prune old versions at any time. Implementation MUST NOT delete a version without also deleting all older versions.
Example:
Request:
GET /?model
Response:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
{ TODO }
This returns the Groups in the Registry along with metadata about the Registry itself.
The request MUST be of the form:
GET /
A successful response MUST be of the form:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
{
"id": "STRING",
"name": "STRING", ?
"description": "STRING", ? # Description of Registry
"specVersion": "STRING", # Registry spec version
"self": "URL",
"tags": { "STRING": "STRING" * }, ?
"docs": "URL", ?
# Repeat for each Group
"GROUPsURL": "URL", # eg. "endpointsURL" - repeated for each GROUP
"GROUPsCount": INT # eg. "endpointsCount"
}
Example:
Request:
GET /
Response:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
{
"specVersion": "0.1",
"endpointsURL": "https://example.com/endpoints",
"endpointsCount": 42,
"definitionGroupsURL": "https://example.com/groups",
"definitionGroupsCount": 3
}
This returns the Groups and all nested data in the Registry along with metadata about the Registry itself. This is designed for cases where the entire Registry's contents are to be represented as a single document.
The request MUST be of the form:
GET /?inline
A successful response MUST be of the form:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
{
"name": "STRING", ?
"description": "STRING", ? # Description of Registry
"specVersion": "STRING", # Registry spec version
"tags": { "STRING": "STRING" * }, ?
"docs": "URL", ?
"model": {
"groups": [
{ "singular": "STRING", # eg. "endpoint"
"plural": "STRING", # eg. "endpoints"
"schema": "URI-Reference", ? # Schema doc for the group
"resources": [
{ "singular": "STRING", # eg. "definition"
"plural": "STRING", # eg. "definitions"
"versions": INT ? # Num old versions. Def=0, -1=unlimited
} +
]
} +
]
}
# Repeat for each Group
"GROUPsURL": "URL", # eg. "endpointsURL"
"GROUPsCount": INT, # eg. "endpointsCount"
"GROUPs": { # eg. "endpoints"
"ID": { # The Group ID
"id": "STRING",
"name": "STRING",
"epoch": UINT, # What other common fields?
# type? createdBy/On? modifiedBy/On? docs? tags?
# description? self?
# Repeat for each RESOURCE in the Group
"RESOURCEsURL": "URL", # URL to retrieve all nested Resources
"RESOURCEsCount": INT # Total number resources
"RESOURCEs": { # eg. "definitions"
"ID": { # MUST match the "id" on the next line
"id": "STRING",
... remaining RESOURCE ?meta and RESOURCE itself ...
} *
} ? # OPTIONAL if RESOURCEsCount is zero
} *
} ? # OPTIONAL if GROUPsCount is zero
}
Note: If the Registry can not return all expected data in one response then it
MUST generate an error. In those cases, the client will need to query the
individual Groups via the /GROUPsURL
API so the Registry can leverage
pagination of the response.
TODO: define the error / add filtering / pagination
Example:
Request:
GET /?inline
Response:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
{ TODO }
This returns all entities that are in a Group.
The request MUST be of the form:
GET /GROUPs[?inline]
The OPTIONAL inline
query parameter indicates the nested Resources are to
be included in the response.
A successful response MUST be of the form:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
Link: <URL>;rel=next;count=INT # If pagination is needed
{
"ID": { # The Group ID
"id": "STRING", # Group attributes
"name": "STRING",
"epoch": UINT, # Server controlled
# Repeat for each RESOURCE in the Group
"RESOURCEsURL": "URL", # URL to retrieve all nested Resources
"RESOURCEsCount": INT, # Total number resources
"RESOURCEs": { # Only when ?inline is present
"ID": { # MUST match the "id" on the next line
"id": "STRING",
... remaining RESOURCE ?meta and RESOURCE itself ...
} *
} ? # OPTIONAL if RESOURCEsCount is zero
} *
}
Note: If the inline
query parameter is present and the presence of the
RESOURCEs
map results in even a single Group being too large to return in
one response then an error MUST be generated. In those cases the client will
need to query the individual Resources via the RESOURCEsURL
so the Registry
can leverage pagination of the response data.
Example:
Request:
GET /endpoints
Response:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
Link: <http://example.com/endpoints&page=2>;rel=next;count=100
{
"123": {
"id": "123",
"name": "A cool endpoint",
"epoch": 1,
"definitionsURL": "https://example.com/endpoints/123/definitions",
"definitionsCount": 5
},
"124": {
"id": "124",
"name": "Redis Queue",
"epoch": 3,
"definitionsURL": "https://example.com/endpoints/124/definitions",
"definitionsCount": 1
}
}
TODO: add filtering and define error
This will add a new Group to the Registry.
The request MUST be of the form:
POST /GROUPs
{
"id": "STRING", ? # If absent then it's server defined
"name": "STRING",
}
A successful response MUST be of the form:
HTTP/1.1 201 Created
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
Location: URL # .../GROUPs/ID
{ # MUST be full representation of new Group
"id": "STRING",
"name": "STRING",
"epoch": UINT,
# Repeat for each RESOURCE type in the Group
"RESOURCEsURL": "URL", # URL to retrieve all nested Resources
"RESOURCEsCount": INT # Total number resources
}
Example:
Request:
POST /endpoints
{ TODO }
Response:
HTTP/1.1 201 Created
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
Location: https://example.com/endpoints/ID
{ TODO }
This will return a single Group.
The request MUST be of the form:
GET /GROUPs/ID[?inline]
The OPTIONAL inline
query parameter indicates the nested Resources are to
be included in the response.
A successful response MUST be of the form:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
{
"id": "STRING", # Group attributes
"name": "STRING",
"epoch": UINT, # Server controlled
# Repeat for each RESOURCE type in the Group
"RESOURCEsURL": "URL", # URL to retrieve all nested Resources
"RESOURCEsCount": INT, # Total number resources
"RESOURCEs": { # Only when ?inline is present
"ID": {
"id": "STRING",
... remaining RESOURCE ?meta and RESOURCE itself ...
} *
} ? # OPTIONAL if RESOURCEsCount is zero
}
Example:
Request:
GET /endpoints/123
Response:
HTTP/1.1 ...
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
{
"id": "123",
"name": "A cool endpoint",
"epoch": 1,
"definitionsURL": "https://example.com/endpoints/123/definitions",
"definitionsCount": 5
}
This will update the attributes of a Group.
The request MUST be of the form:
PUT /GROUPs/ID[?epoch=EPOCH]
{
# Missing attributes are deleted from Group
"id": "STRING", # MUST match URL if present
"name": "STRING",
"epoch": UINT ? # OPTIONAL - MUST be current value if present
# Presence of the RESOURCEs attributes are OPTIONAL and MUST be ignored
}
A successful response MUST be of the form:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
{
"id": "STRING",
"name": "STRING",
"epoch": UINT, # MUST be greater than previous value
# Repeat for each RESOURCE type in the Group
"RESOURCEsURL": "URL",
"RESOURCEsCount": INT
}
Example:
Request:
PUT /endpoints/123
{
"id": "123",
"name": "A cooler endpoint",
"epoch": 1
}
Response:
HTTP/1.1 OK
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
{
"id": "123",
"name": "A cooler endpoint",
"epoch": 2,
"definitionsURL": "https://example.com/endpoints/123/definitions",
"definitionsCount": 5,
}
To delete a single Group the following API can be used.
The request MUST be of the form:
DELETE /GROUPs/ID[?epoch=EPOCH]
If epoch
is present then it MUST match the current value.
A successful response MUST be of the form:
HTTP/1.1 200 OK # 202 or 204 are ok
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
{ # RECOMMENDED, last known state of entity
"id": "STRING",
"name": "STRING",
"epoch": UINT,
...
} ?
To delete multiple Groups the following API can be used.
The request MUST be of the form:
DELETE /GROUPs
[
{
"id": "STRING",
"epoch": UINT ? # If present it MUST match current value
} *
]
A successful response MUST be of the form:
HTTP/1.1 200 OK # 202 or 204 are ok
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
{ "ID": { ... } * } ? # RECOMMENDED
If any of the individual deletes fails then the entire request MUST fail and none of the Groups are deleted.
A DELETE /GROUPs
without a body MUST delete all Groups.
This will retrieve the Resources from a Group.
The request MUST be of the form:
GET /GROUPs/ID/RESOURCEs[?inline]
The OPTIONAL inline
query parameter indicates the nested Resources are to
be included in the response.
A successful response MUST be of the form:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
Link: <URL>;rel=next;count=INT # If pagination is needed
{
"ID": {
"id": "STRING",
"name": "STRING",
"version": INT,
"epoch": UINT,
"self": "URL", # URL to specific version
"RESOURCEURI": "URI", ? # If not locally stored (singular)
"RESOURCE": {} ?, # If ?inline present & JSON (singular)
"RESOURCEBase64": "STRING" ? # If ?inline present & ~JSON (singular)
} *
}
Example:
Request:
GET /endpoints/123/definitions
Response:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
Link: <http://example.com/endpoints/123/definitions&page=2>;rel=next;count=100
{
"456": {
"id": "456",
"name": "Blob Created",
"format": "CloudEvents/1.0",
"version": 3,
"epoch": 1,
"self": "https://example.com/endpoints/123/definitions/456/version/3"
}
}
This will create a new Resources in a particular Group.
The request MUST be of the form:
POST /GROUPs/ID/RESOURCEs
Registry-name: STRING ? # If absent, default to the ID?
Registry-type: STRING ?
Registry-RESOURCEURI: URI ? # If present body MUST be empty (singular)
{ ...Resource entity... } ?
A successful response MUST be of the form:
HTTP/1.1 201 Created
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
Registry-id: STRING
Registry-name: STRING
Registry-type: STRING ?
Registry-version: STRING
Registry-epoch: UINT
Registry-self: STRING # URL to the specific version
Registry-RESOURCEURI: URI ? # If present body MUST be empty (singular)
Location: URL # Points to "latest" URL
Content-Location: URL # Same as Registry-self value
{ ...Resource entity... } ?
Example:
Request:
TODO
This will retrieve the latest version of a Resource. This can be considered an
alias for /GROUPs/ID/RESOURCEs/RESOURCEID/versions/VERSION
where
VERSION
is the latest version value.
The request MUST be of the form:
GET /GROUPs/ID/RESOURCEs/ID
A successful response MUST be of the form:
HTTP/1.1 200 OK or 307 Tempary Redirect # 307 if RESOURCEURI is present
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
Registry-id: STRING
Registry-name: STRING
Registry-type: STRING ?
Registry-version: STRING
Registry-epoch: UINT
Registry-self: STRING # URL to the specific version
Registry-RESOURCEURI: URI ? # If present body MUST be empty (singular)
Content-Location: URL # Same as Registry-self value
Location: URL # If 307. Same a Registry-RESOURCEURI
{ ...Resource entity... } ?
Example:
Request:
TODO
This will retrieve the metadata for the latest version of a Resource. This can
be considered an alias for
/GROUPs/ID/RESOURCEs/RESOURCEID/versions/VERSION?meta
where VERSION
is the
latest version value.
The request MUST be of the form:
GET /GROUPs/ID/RESOURCEs/ID?meta
A successful response MUST be of the form:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
{
"id": "STRING",
"name": "STRING",
"version": INT,
"epoch": UINT,
"self": "URL",
"RESOURCEURI": "URI" ? # singular
}
Example:
Request:
TODO
This will update the latest version of a Resource. Missing Registry HTTP headers MUST NOT be interpreted as deleting the attribute. However, a Registry HTTP headers with an empty string for its value MUST be interpreted as a request to delete the attribute.
The request MUST be of the form:
PUT /GROUPs/ID/RESOURCEs/ID[?epoch=EPOCH]
Registry-id: STRING ? # If present it MUST match URL
Registry-name: STRING ?
Registry-type: STRING ?
Registry-version: STRING ? # If present it MUST match current value
Registry-epoch: UINT ? # If present it MUST match current value & URL
Registry-self: STRING ? # If present it MUST be ignored?
Registry-RESOURCEURI: URI ? # If present body MUST be empty (singular)
{ ...Resource entity... } ? # If empty then content is erased
A successful response MUST be of the form:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
Registry-id: STRING
Registry-name: STRING
Registry-type: STRING ?
Registry-version: STRING
Registry-epoch: UINT # MUST be incremented
Registry-self: STRING
Registry-RESOURCEURI: URI ? # singular
Content-Location: URL
{ ...Resource entity... } ?
Note: if some of the Registry attributes are shared with the Resource itself then those values MUST appear in both the Registry HTTP headers as well as in the Resource itself when retrieving the Resource. However, in this "update" case, if the attribute only appears in the HTTP body and the corresponding Registry HTTP header is missing then the Registry attribute MUST be updated to match the Resource's attribute. If both are present on the request and do not have the same value then an error MUST be generated.
Example:
Request:
TODO
Response:
TODO
TODO: make a note that empty string and attribute missing are the same thing. Which error is to be returned?
This will update the metadata of the latest version of a Resource without creating a new version.
The request MUST be of the form:
PUT /GROUPs/ID/RESOURCEs/ID?meta[&epoch=EPOCH]
{
"id": "STRING",
"name": "STRING",
"version": INT, ? # If present it MUST match current value
"epoch": UINT, ? # If present it MUST match current value & URL
"self": "URL", ? # If present it MUST be ignored
"RESOURCEURI": "URI" ? # singular
}
A successful response MUST be of the form:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
{
"id": "STRING",
"name": "STRING",
"version": INT,
"epoch": UINT, # MUST be incremented
"self": "URL",
"RESOURCEURI": "URI" ? # singular
}
Example:
Request:
TODO
Response:
TODO
To delete a single Resource the following API can be used.
The request MUST be of the form:
DELETE /GROUPs/ID/RESOURCEs/ID[?epoch=EPOCH]
If epoch
is present then it MUST match the current value.
A successful response MUST be of the form:
HTTP/1.1 200 OK # 202 or 204 are ok
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
Registry-id: STRING
Registry-name: STRING
Registry-type: STRING ?
Registry-version: STRING
Registry-epoch: UINT
Registry-self: STRING
Registry-RESOURCEURI: URI ? # singular
Content-Location: URL # Does this make sense if it's been deleted?
{ ...Resource entity... } ?
Example:
Request:
TODO
To delete multiple Resources the following API can be used.
The request MUST be of the form:
DELETE /GROUPs/ID/RESOURCEs
[
{
"id": "STRING",
"epoch": UINT ? # If present it MUST match current value
} *
]
A successful response MUST be of the form:
HTTP/1.1 200 OK # 202 or 204 are ok
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
{ "ID": { ... } * } ? # RECOMMENDED
If any of the individual deletes fails then the entire request MUST fail and none of the Resources are deleted.
A DELETE /GROUPs/ID/RESOURCEs
without a body MUST delete all Resources in the
Group.
This will retrieve all versions of a Resource.
The request MUST be of the form:
GET /GROUPs/ID/RESOURCEs/ID/versions[?inline]
The OPTIONAL inline
query parameter indicates the nested Resources are to
be included in the response.
A successful response MUST be of the form:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
Link: <URL>;rel=next;count=INT # If pagination is needed
{
VERSION: {
"id": "STRING",
"name": "STRING",
"version": INT,
"epoch": UINT,
"self": "URL",
"RESOURCEURI": "URI", ? # If not locally stored (singular)
"RESOURCE": {} ?, # If ?inline present & JSON (singular)
"RESOURCEBase64": "STRING" ? # If ?inline present & ~JSON (singular)
} *
}
Example:
Request:
TODO
This will create a new version of a Resource. Any metadata not present will be inherited from latest version. To delete any metadata include its HTTP Header with an empty value.
The request MUST be of the form:
POST /GROUPs/ID/RESOURCEs/ID[?epoch=EPOCH]
Registry-id: STRING ? # If present it MUST match URL
Registry-name: STRING ?
Registry-type: STRING ?
Registry-version: STRING ? # MUST NOT be present
Registry-epoch: UINT ? # If present it MUST match current value & URL
Registry-self: STRING ? # If present it MUST be ignored?
Registry-RESOURCEURI: URI ? # If present body MUST be empty (singular)
{ ...Resource entity... } ? # If empty then content is erased
A successful response MUST be of the form:
HTTP/1.1 201 Created
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
Registry-id: STRING
Registry-name: STRING
Registry-type: STRING ?
Registry-version: STRING
Registry-epoch: UINT
Registry-self: STRING
Registry-RESOURCEURI: URI ? # singular
Content-Location: URL # Same as self
Location: .../GROUPs/ID/RESOURCEs/ID # or self?
{ ...Resource entity... } ?
Example:
Request:
TODO
Response:
TODO
This will retrieve a partiuclar version of a Resource.
The request MUST be of the form:
GET /GROUPs/ID/RESOURCEs/ID/versions/VERSION
A successful response MUST be of the form:
HTTP/1.1 200 OK or 307 Tempary Redirect # 307 if RESOURCEURI is present
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
Registry-id: STRING
Registry-name: STRING
Registry-type: STRING ?
Registry-version: STRING
Registry-epoch: UINT
Registry-self: STRING # URL to the specific version
Registry-RESOURCEURI: URI ? # If present body MUST be empty (singular)
Content-Location: URL # Same as Registry-self value
Location: URL # If 307. Same a Registry-RESOURCEURI
{ ...Resource entity... } ?
Example:
Request:
TODO
This will retrieve the metadata for a particular version of a Resource.
The request MUST be of the form:
GET /GROUPs/ID/RESOURCEs/ID/versions/VERSION?meta
A successful response MUST be of the form:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
{
"id": "STRING",
"name": "STRING",
"version": INT,
"epoch": UINT,
"self": "URL",
"RESOURCEURI": "URI" ? # singular
}
Example:
Request:
TODO
This will update a particular version of a Resource. Missing Registry HTTP headers MUST NOT be interpreted as deleting the attribute. However, a Registry HTTP headers with an empty string for its value MUST be interpreted as a request to delete the attribute.
The request MUST be of the form:
PUT /GROUPs/ID/RESOURCEs/ID/versions/VERSION[?epoch=EPOCH]
Registry-id: STRING ? # If present it MUST match URL
Registry-name: STRING ?
Registry-type: STRING ?
Registry-version: STRING ? # If present it MUST match current value & URL
Registry-epoch: UINT ? # If present it MUST match current value & URL
Registry-self: STRING ? # If present it MUST be ignored?
Registry-RESOURCEURI: URI ? # If present body MUST be empty (singular)
{ ...Resource entity... } ? # If empty then content is erased
A successful response MUST be of the form:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
Registry-id: STRING
Registry-name: STRING
Registry-type: STRING ?
Registry-version: STRING
Registry-epoch: UINT # MUST be incremented
Registry-self: STRING
Registry-RESOURCEURI: URI ? # singular
Content-Location: URL
{ ...Resource entity... } ?
Note: if some of the Registry attributes are shared with the Resource itself then those values MUST appear in both the Registry HTTP headers as well as in the Resource itself when retrieving the Resource. However, in this "update" case, if the attribute only appears in the HTTP body and the corresponding Registry HTTP header is missing then the Registry attribute MUST be updated to match the Resource's attribute. If both are present on the request and do not have the same value then an error MUST be generated.
Example:
Request:
TODO
This will update the metadata of a particular version of a Resource without creating a new version.
The request MUST be of the form:
PUT /GROUPs/ID/RESOURCEs/ID/versions/VERSION?meta[&epoch=EPOCH]
{
"id": "STRING",
"name": "STRING",
"version": INT, ? # If present it MUST match current value
"epoch": UINT, ? # If present it MUST match current value & URL
"self": "URL", ? # If present it MUST be ignored
"RESOURCEURI": "URI" ? # singular
}
A successful response MUST be of the form:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
{
"id": "STRING",
"name": "STRING",
"version": INT,
"epoch": UINT, # MUST be incremented
"self": "URL",
"RESOURCEURI": "URI" ? # singular
}
Example:
Request:
TODO
Response:
TODO
To delete a single version of a Resource the following API can be used.
The request MUST be of the form:
DELETE /GROUPs/ID/RESOURCEs/ID/versions/VERSION[?epoch=EPOCH]
If epoch
is present then it MUST match the current value.
A successful response MUST be of the form:
HTTP/1.1 200 OK # 202 or 204 are ok
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
Registry-id: STRING
Registry-name: STRING
Registry-type: STRING ?
Registry-version: STRING
Registry-epoch: UINT
Registry-self: STRING
Registry-RESOURCEURI: URI ? # singular
Content-Location: URL # Does this make sense if it's been deleted?
{ ...Resource entity... } ?
Example:
Request:
TODO
Response:
TODO
To delete multiple versions of a Resource the following API can be used.
The request MUST be of the form:
DELETE /GROUPs/ID/RESOURCEs/ID/versions
[
{
"id": "STRING",
"version": INT,
"epoch": UINT ? # If present it MUST match current value
} *
]
A successful response MUST be of the form:
HTTP/1.1 200 OK # 202 or 204 are ok
Content-Type: application/json; charset=utf-8
Content-Length: nnnn
{ "ID": { ... } * } ? # RECOMMENDED
If any of the individual deletes fails then the entire request MUST fail and none of the Resources are deleted.
If the latest version is deleted then the remaining version with the largest
version
value MUST become the latest.
An attempt to delete all versions MUST generate an error.
A DELETE /GROUPs/ID/RESOURCEs/ID/versions
without a body MUST delete all
versions (except the latest) of the Resource.
The CloudEvents Registry is a universal catalog and discovery metadata format as well as a metadata service API for messaging and eventing schemas, metaschemas, and messaging and eventing endpoints.
The CloudEvents registry model contains three separate registries that can be implemented separately or in combination.
- The Schema Registry section describes the metadata description of payload schemas for events and messages. The schema registry is universally applicable to any scenario where collaborating parties share structured data that is defined by formal schemas. For instance, when storing Protobuf encoded structured data in a cloud file store, you might place a schema registry in file form in the parent directory, which formally organizes and documents all versions of all Protobuf schemas that are used in the directory.
- The Message Definitions Registry section describes the metadata description of events and messages. The payload schemas for events and messages can be embedded in the definition, reference an external schema document, or can be referenced into the schema registry. The message definitions registry is universally applicable to any asynchronous messaging and eventing scenario. You might define a group of definitions that describe precisely which messages, with which metadata, are permitted to flow into a channel and can thus be expected by consumers of that channel and then associate that definition group with a topic or queue in your eventing or messaging infrastructure. That association might be a metadata attribute on the topic or queue in the messaging infrastructure that embeds the metadata or points to it.
- The Endpoint Registry section defines the metadata description of network endpoints that accept or emit events and messages. The endpoint registry is a formal description of associations of message definitions and network endpoints, which can be used to discover endpoints that consume or emit particular messages or events via a central registry. The message definitions can be embedded into the endpoint metadata or as a reference into the message definitions registry.
The metadata model is structured such that network endpoint information and message metadata and payload schemas can be described compactly in a single metadata object (and therefore as a single document) in the simplest case or can be spread out and managed across separate registry products in a sophisticated large-enterprise scenario.
The following is an exemplary, compact definition of an MQTT 5.0 consumer endpoint with a single, embedded message definition using an embedded Protobuf 3 schema for its payload.
{
"$schema": "https://cloudevents.io/schemas/registry",
"specversion": "0.5-wip",
"id": "urn:uuid:3978344f-8596-4c3a-a978-8fc9a6a469f7",
"endpoints" :
{
"com.example.telemetry" : {
"id" : "com.example.telemetry",
"usage": "consumer",
"config": {
"protocol": "MQTT/5.0",
"strict": false,
"endpoints": [
"mqtt://mqtt.example.com:1883"
],
"options" : {
"topic": "{deviceid}/telemetry"
}
},
"format" : "CloudEvents/1.0",
"definitions": {
"com.example.telemetry" : {
"id": "com.example.telemetry",
"description": "device telemetry event",
"format": "CloudEvents/1.0",
"metadata": {
"attributes": {
"id": {
"type": "string",
"required": true
},
"type": {
"type": "string",
"value": "com.example.telemetry",
"required": true
},
"time": {
"type": "datetime",
"required": true
},
"source": {
"type": "uritemplate",
"value": "{deploymentid}/{deviceid}",
"required": true
}
}
},
"schemaformat": "Protobuf/3.0",
"schema" : "syntax = \"proto3\"; message Metrics { float metric = 1; } }"
}
}
}
}
}
The same metadata can be expressed by spreading the metadata across the message definition and schema registries, which makes the definitions reusable for other scenarios:
{
"$schema": "https://cloudevents.io/schemas/registry",
"specversion": "0.4-wip",
"id": "urn:uuid:3978344f-8596-4c3a-a978-8fc9a6a469f7",
"endpoints" :
{
"com.example.telemetry" : {
"id" : "com.example.telemetry",
"usage": "consumer",
"config": {
"protocol": "MQTT/5.0",
"strict": false,
"endpoints": [
"mqtt://mqtt.example.com:1883"
],
"options" : {
"topic": "{deviceid}/telemetry"
}
},
"format" : "CloudEvents/1.0",
"definitionGroups" :[
"#/definitionGroups/com.example.telemetryEvents"
]
}
},
"definitionGroups" : {
"com.example.telemetryEvents" : {
"type" : "definitionGroup",
"id" : "com.example.telemetryEvents",
"definitions": {
"com.example.telemetry" : {
"id": "com.example.telemetry",
"description": "device telemetry event",
"format": "CloudEvents/1.0",
"metadata": {
"attributes": {
"id": {
"type": "string",
"required": true
},
"type": {
"type": "string",
"value": "com.example.telemetry",
"required": true
},
"time": {
"type": "datetime",
"required": true
},
"source": {
"type": "uritemplate",
"value": "{deploymentid}/{deviceid}",
"required": true
}
}
},
"schemaformat": "Protobuf/3.0",
"schemaurl" : "#/schemaGroups/com.example.telemetry/schema/com.example.telemetrydata/versions/1.0"
}
}
}
},
"schemaGroups" : {
"com.example.telemetry" : {
"type" : "schemagroup",
"id" : "com.example.telemetry",
"schemas": {
"com.example.telemetrydata" : {
"id": "com.example.telemetrydata",
"description": "device telemetry event data",
"format": "Protobuf/3.0",
"versions" : {
"1.0" : {
"type" : "schemaversion",
"id" : "1.0",
"schema" : "syntax = \"proto3\"; message Metrics { float metric = 1; }"
}
}
}
}
}
}
}
If we assume the message definitions and schemas to reside at an API endpoint, an endpoint definition might just reference the associated message definition group with a deep link to the respective object in the service:
If the message definitions and schemas are stored in a file-based registry, including files shared via public version control repositories, the reference link will first reference the file and then the object within the file, using JSON Pointer syntax:
{
"$schema": "https://cloudevents.io/schemas/registry",
"specversion": "0.4-wip",
"id": "urn:uuid:3978344f-8596-4c3a-a978-8fc9a6a469f7",
"endpoints" :
{
"com.example.telemetry" : {
"id" : "com.example.telemetry",
"usage": "consumer",
"config": {
// ... details ......
},
"format" : "CloudEvents/1.0",
"definitionGroups" :[
"https://rawdata.repos.example.com/myorg/myproject/main/example.telemetryEvents.cereg#/definitionGroups/com.example.telemetryEvents"
]
}
}
}
All other references to other objects in the registry can be expressed in the same way.
While the CloudEvents Registry is primarily motivated by enabling development of CloudEvents-based event flows, the registry is not limited to CloudEvents. It can be used to describe any asynchronous messaging or eventing endpoint and its messages, including endpoints that do not use CloudEvents at all. The Message Formats section therefore not only describes the attribute meta-schema for CloudEvents, but also meta-schemas for the native message envelopes of MQTT, AMQP, and other messaging protocols.
The registry is designed to be extensible to support any structured data encoding and related schemas for message or event payloads. The Schema Formats section describes the meta-schema for JSON Schema, XML Schema, Apache Avro schema, and Protobuf schema.
A CloudEvents Registry can be implemented using the Registry API or with plain text files.
When using the file-based model, files with the extension .cereg
use JSON
encoding. Files with the extension .cereg.yaml
or .cereg.yml
use YAML
encoding. The formal JSON schema for the file format is defined in the
CloudEvents Registry Document Schema,
which implements the Registry format and the CloudEvents Registry format.
The media-type for the file format is application/cloudevents-registry+json
for the
JSON encoding and application/cloudevents-registry+yaml
for the YAML encoding.
The JSON schema identifier is https://cloudevents.io/schemas/registry
and the
specversion
property indicates the version of this specification that the
elements of the file conform to.
A CloudEvents Registry file MUST contain a single JSON object or YAML document. The object declares the roots of the three sub-registries, which are either embedded or referenced. Any of the three sub-registries MAY be omitted.
{
"$schema": "https://cloudevents.io/schemas/registry",
"specversion": "0.4-wip",
"endpoints": { ... } | "endpointsUrl": "URL",
"definitionGroups": { ... } | "definitionGroupsUrl": "URL"
"schemaGroups" : { ... } | "schemaGroupsUrl": "URL",
}
While the file structure leads with endpoints followed by definition groups and then schema groups by convention, the order of the sub-registries is not significant.
The schema registry is a metadata store for organizing data schemas of any kind.
The Registry API extension model of the Schema Registry is:
{
"groups": [
{
"singular": "schemaGroup",
"plural": "schemaGroups",
"schema": "TBD",
"resources": [
{
"singular": "schema",
"plural": "schemas",
"versions": -1
}
]
}
]
}
The group (GROUP) name for the Schema Registry is schemaGroups
. The group does
not have any specific extension attributes.
A schema group is a collection of schemas that are related to each other in some application-defined way. A schema group does not impose any restrictions on the contained schemas, meaning that a schema group can contain schemas of different formats. Every schema MUST reside inside a schema group.
Example:
{
"schemaGroups": {
"com.example.schemas": {
"id": "com.example.schemas",
"schemas": {
...
}
}
}
}
The resources (RESOURCE) collection inside of schema groups is named schemas
.
The type of the resource is schema
. Any single schema
is a container for
one or more versions
, which hold the concrete schema documents or schema
document references.
Any new schema version that is added to a schema definition MUST be backwards compatible with all previous versions of the schema, meaning that a consumer using the new schema MUST be able to understand data encoded using a prior version of the schema. If a new version introduces a breaking change, it MUST be registered as a new schema with a new name.
When you retrieve a schema without qualifying the version, you will get the latest version of the schema, see retrieving a resource. The latest version is the lexically greatest version number, whereby all version ids MUST be left-padded with spaces to the same length before being compared.
The following extension is defined for the schema
object in addition to the
basic attributes:
- Type: String
- Description: Identifies the schema format. In absence of formal media-type
definitions for several important schema formats, we define a convention here
to reference schema formats by name and version as
{NAME}/{VERSION}
. This specification defines a set of common schema format names that MUST be used for the given formats, but applications MAY define extensions for other formats on their own. - Constraints:
- REQUIRED
- MUST be a non-empty string
- MUST follow the naming convention
{NAME}/{VERSION}
, whereby{NAME}
is the name of the schema format and{VERSION}
is the version of the schema format in the format defined by the schema format itself.
- Examples:
JsonSchema/draft-07
Protobuf/3
XSD/1.1
Avro/1.9
The VERSION
object of the schema
resource is of type schemaversion
. The
format
extension attribute of schema
MAY be repeated in schemaversion
for
clarity, but MUST be identical. schemaversion
has the following extension
attributes.
- Type: String | Object
- Description: Embedded schema string or object. The format and encoding of the
schema is defined by the
format
attribute. - Constraints:
- Mutually exclusive with
schemaurl
. One of the two MUST be present.
- Mutually exclusive with
- Type: URI
- Description: Reference to a schema document external to the registry.
- Constraints:
- Mutually exclusive with
schemaurl
. One of the two MUST be present. - Cross-references to a schema document within the same registry MUST NOT be used.
- Mutually exclusive with
The following example shows three embedded Protobuf/3
schema versions for a
schema named com.example.telemetrydata
:
{
"schemaGroups" : {
"com.example.telemetry" : {
"type" : "schemagroup",
"id" : "com.example.telemetry",
"schemas": {
"com.example.telemetrydata" : {
"id": "com.example.telemetrydata",
"description": "device telemetry event data",
"format": "Protobuf/3",
"versions" : {
"1.0" : {
"type" : "schemaversion",
"id" : "1.0",
"schema" : "syntax = \"proto3\"; message Metrics { float metric = 1; } }"
},
"2.0" : {
"type" : "schemaversion",
"id" : "2.0",
"schema" : "syntax = \"proto3\"; message Metrics { float metric = 1; string unit = 2; } }"
},
"3.0" : {
"type" : "schemaversion",
"id" : "3.0",
"schema" : "syntax = \"proto3\"; message Metrics { float metric = 1; string unit = 2; string description = 3; } }"
}
}
}
}
}
}
}
This section defines a set of common schema formats that MUST be used for the given formats, but applications MAY define extensions for other formats on their own.
The format
identifier for JSON Schema is
JsonSchema
.
When the format
attribute is set to JsonSchema
, the schema
attribute of
the schemaversion
is a JSON object representing a JSON Schema document
conformant with the declared version.
A URI-reference, like schemaurl
that points
to a JSON Schema document MAY use a JSON pointer expression to deep link into
the schema document to reference a particular type definition. Otherwise the
top-level object definition of the schema is used.
The version of the JSON Schema format is the version of the JSON
Schema specification that is used to define the schema. The version of the JSON
Schema specification is defined in the $schema
attribute of the schema
document.
The identifiers for the following JSON Schema versions
- Draft 07:
http://json-schema.org/draft-07/schema
- Draft 2019-09:
https://json-schema.org/draft/2019-09/schema
- Draft 2020-12:
https://json-schema.org/draft/2020-12/schema
are defined as follows:
JsonSchema/draft-07
JsonSchema/draft/2019-09
JsonSchema/draft/2020-12
which follows the exact convention as defined for JSON schema and expecting an eventually released version 1.0 of the JSON Schema specification using a plain version number.
The format
identifier for XML Schema is XSD
. The
version of the XML Schema format is the version of the W3C XML Schema specification
that is used to define the schema.
When the format
attribute is set to XSD
, the schema
attribute of
schemaversion
is a string containing an XML Schema document conformant with
the declared version.
A URI-reference, like schemaurl
that points
to a XSD Schema document MAY use an XPath expression to deep link into the
schema document to reference a particular type definition. Otherwise the root
element definition of the schema is used.
The identifiers for the following XML Schema versions
- 1.0:
https://www.w3.org/TR/xmlschema-1/
- 1.1:
https://www.w3.org/TR/xmlschema11-1/
are defined as follows:
XSD/1.0
XSD/1.1
The format
identifier for Apache Avro Schema is
Avro
. The version of the Apache Avro Schema format is the version of the Apache
Avro Schema release that is used to define the schema.
When the format
attribute is set to Avro
, the schema
attribute of the
schemaversion
is a JSON object representing an Avro schema document conformant
with the declared version.
Examples:
Avro/1.8.2
is the identifier for the Apache Avro release 1.8.2.Avro/1.11.0
is the identifier for the Apache Avro release 1.11.0
A URI-reference, like schemaurl
that points
to an Avro Schema document MUST reference an Avro record declaration contained
in the schema document using a URI fragment suffix [:]{record-name}
. The ':'
character is used as a separator when the URI already contains a fragment.
Examples:
- If the Avro schema document is referenced using the URI
https://example.com/avro/telemetry.avsc
, the URI fragment#TelemetryEvent
references the record declaration of theTelemetryEvent
record. - If the Avro schema document is a local schema registry reference like
#/schemaGroups/com.example.telemetry/schemas/com.example.telemetrydata
, in the which the reference is already in the form of a URI fragment, the suffix is appended separated with a colon, for instance.../com.example.telemetrydata:TelemetryEvent
.
The format
identifier for Protobuf Schema is
Protobuf
. The version of the Protobuf Schema format is the version of the
Protobuf syntax that is used to define the schema.
When the format
attribute is set to Protobuf
, the schema
attribute of the
schemaversion
is a string containing a Protobuf schema document conformant with
the declared version.
Protobuf/3
is the identifier for the Protobuf syntax version 3.Protobuf/2
is the identifier for the Protobuf syntax version 2.
A URI-reference, like schemaurl
that points
to an Protobuf Schema document MUST reference an Protobuf message
declaration
contained in the schema document using a URI fragment suffix [:]{message-name}
.
The ':' character is used as a separator when the URI already contains a
fragment.
Examples:
- If the Protobuf schema document is referenced using the URI
https://example.com/protobuf/telemetry.proto
, the URI fragment#TelemetryEvent
references the message declaration of theTelemetryEvent
message. - If the Protobuf schema document is a local schema registry reference like
#/schemaGroups/com.example.telemetry/schemas/com.example.telemetrydata
, in the which the reference is already in the form of a URI fragment, the suffix is appended separated with a colon, for instance.../com.example.telemetrydata:TelemetryEvent
.
The Message Definitions Registry (or "Message Catalog") is a registry of
metadata definitions for messages and events. The entries in the registry
describe constraints for the metadata of messages and events, for instance the
concrete values and patterns for the type
, source
, and subject
attributes
of a CloudEvent.
All message definitions (events are a from of messages and are therefore always implied to be included from here on forward) are defined inside definition groups.
A definition group is a collection of message definitions that are related to each other in some application-specific way. For instance, a definition group can be used to group all events raised by a particular application module or by a particular role of an application protocol exchange pattern.
The Registry API extension model of the Message Definitions Registry is
{
"groups": [
{
"singular": "definitionGroup",
"plural": "definitionGroups",
"schema": "TBD",
"resources": [
{
"singular": "definition",
"plural": "definitions",
"versions": 0,
}
]
}
]
}
The Group (GROUP) name is definitionGroups
. The type of a group is definitionGroup
.
The following attributes are defined for the definitionGroup
object in addition to the
basic attributes:
- Type: String
- Description: Identifies the message metadata format. Message metadata formats
are referenced by name and version as
{NAME}/{VERSION}
. This specification defines a set of common message format names that MUST be used for the given formats, but applications MAY define extensions for other formats on their own. All definitions inside a group MUST use this same format. - Constraints:
- REQUIRED
- MUST be a non-empty string
- MUST follow the naming convention
{NAME}/{VERSION}
, whereby{NAME}
is the name of the message format and{VERSION}
is the version of the schema format in the format defined by the schema format itself.
- Examples:
CloudEvents/1.0
MQTT/3.1.1
AMQP/1.0
Kafka/0.11
The resource (RESOURCE) collection name inside definitionGroup
is
definitions
. The resource name is definition
.
Different from schemas, message definitions do not contain a version history. If the metadata of two messages differs, they are considered different definitions.
The following extension is defined for the definition
object in addition to the
basic attributes:
Same as the format
attribute of the
definitionGroup
object.
Since definitions MAY be cross-referenced ("borrowed") across definition group
boundaries, this attribute is also REQUIRED and MUST be the same as the format
attribute of the definitionGroup
object into which the definition is embedded
or referenced.
Illustrating example:
"definitionGroups" : {
"com.example.abc" : {
"type" : "definitionGroup",
"id": "com.example.abc",
"format" : "CloudEvents/1.0",
"definitions" : {
"com.example.abc.event1" : {
"type" : "definition",
"id": "com.example.abc.event1",
"format" : "CloudEvents/1.0",
// ... details ...
}
},
"com.example.abc.event2" : {
"type" : "definition",
"id": "com.example.abc.event1",
"format" : "CloudEvents/1.0",
// ... details ...
}
},
"com.example.def" : {
"id": "com.example.def",
"format" : "CloudEvents/1.0",
"definitions" : {
"com.example.abc.event1" : {
"uri": "#/definitionGroups/com.example.abc/definitions/com.example.abc.event1",
// ... more ...
}
}
}
}
- Type: Object
- Description: Describes the metadata constraints for messages of this type. The content of the metadata property is defined by the message format, but all formats use a common schema for the constraints defined for their metadata headers, properties or attributes.
- Constraints:
- REQUIRED
- Examples:
- See Message Formats
- Type: String
- Description: Identifies the schema format applicable to the message payload, equivalent to the schema 'format' attribute.
- Constraints:
- OPTIONAL
- If present, MUST be a non-empty string
- If present, MUST follow the naming convention
{NAME}/{VERSION}
, whereby{NAME}
is the name of the schema format and{VERSION}
is the version of the schema format in the format defined by the schema format itself.
- Examples:
- 'JSONSchema/draft-07'
- 'Avro/1.9.0'
- 'Protobuf/3'
- Type: String | Object as defined by the schema format
- Description: Contains the inline schema for the message payload. The schema format
is identified by the
schemaformat
attribute. Equivalent to the schemaversion 'schema' attribute - Constraints:
- OPTIONAL.
- Mutually exclusive with the
schemaurl
attribute. - If present,
schemaformat
MUST be present.
- Examples:
- See Schema Formats
- Type: URI-reference
- Description: Contains a relative or absolute URI that points to the schema
object to use for the message payload. The schema format is identified by the
schemaformat
attribute. See Schema Formats for details on how to reference specific schema objects for the message payload. It is not sufficient for the URI-reference to point to a schema document; it MUST resolve to a concrete schema object. - Constraints:
- OPTIONAL.
- Mutually exclusive with the
schema
attribute. - If present,
schemaformat
MUST be present.
This section defines the message formats that are directly supported by this specification. Message formats lean on a protocol-neutral metadata definition like CloudEvents or on the message model definition of a specific protocol like AMQP or MQTT or Kafka. A message format defines constraints for the fixed and variable headers/properties/attributes of the event format or protocol message model.
Message format definitions might be specific to a particular client instance and used to configure that client. Therefore, the message format definitions allow for specifying very narrow constraints like the exact value of an Apache Kafka record
key
.
The following properties are common to all definitions of message headers/properties/attributes constraints:
- Type: Boolean
- Description: Indicates whether the property is REQUIRED to be present in a message of this type.
- Constraints:
- OPTIONAL. Defaults to
false
. - If present, MUST be a boolean value.
- OPTIONAL. Defaults to
- Type: String
- Description: A human-readable description of the property.
- Constraints:
- OPTIONAL.
- If present, MUST be a non-empty string.
- Type: Any
- Description: The value of the property. With a few exceptions, see below, this is the value that MUST be literally present in the message for the message to be considered conformant with this metaschema.
- Constraints:
- OPTIONAL.
- If present, MUST be a valid value for the property.
If the type
property has the value uritemplate
, value
MAY contain
placeholders. As defined in RFC6570 (Level 1), the placeholders MUST
be enclosed in curly braces ({
and }
) and MUST be a valid symbol
.
Placeholders that are used multiple times in the same message definition are
assumed to represent identical values.
When validating a message property against this value, the placeholders act as
wildcards. For example, the value {foo}/bar
would match the value abc/bar
or
xyz/bar
.
When creating a message based on a metaschema with such a value, the
placeholders MUST be replaced with valid values. For example, the value
{foo}/bar
would be replaced with abc/bar
or xyz/bar
when creating a
message.
If the type
property has the value timestamp
and the value
property is
set to a value of 01-01-0000T00:00:00Z
, the value MUST be replaced with the
current timestamp when creating a message.
- Type: String
- Description: The type of the property. This is used to constrain the value of the property.
- Constraints:
- OPTIONAL. Defaults to "string".
- The valid types are those defined in the CloudEvents
core specification, with some additions:
var
: Any type of value, includingnull
.boolean
: CloudEvents "Boolean" type.string
: CloudEvents "String" type.symbol
: Astring
that is restricted to alphanumerical characters and underscores.binary
: CloudEvents "Binary" type.timestamp
: CloudEvents "Timestamp" type (RFC3339 DateTime)duration
: RFC3339 Durationuritemplate
: RFC6570 Level 1 URI Templateuri
: CloudEvents "URI" type (RFC3986 URI)urireference
: CloudEvents "URI-reference" type (RFC3986 URI-reference)number
: IEEE754 Doubleinteger
: CloudEvents "Integer" type (RFC 7159, Section 6)
- Type: URI-reference
- Description: Contains a relative or absolute URI that points to the human-readable specification of the property.
- Constraints:
- OPTIONAL
For the "CloudEvents/1.0" format, the metadata
object contains a property attributes
, which is an object whose properties
correspond to the CloudEvents context attributes.
As with the CloudEvents specification, the attributes form a flat list and extension attributes are allowed. Attribute names are restricted to lower-case alphanumerical characters without separators.
The base attributes are defined as follows:
Attribute | Type |
---|---|
type |
string |
source |
uritemplate |
subject |
string |
id |
string |
time |
timestamp |
dataschema |
uritemplate |
datacontenttype |
string |
The following rules apply to the attribute declarations:
- All attribute declarations are OPTIONAL. Requirements for absent definitions are implied by the CloudEvents specification.
- The
specversion
attribute is implied by the message format and is NOT REQUIRED. If present, it MUST be declared with astring
type and set to the value "1.0". - The
type
,id
, andsource
attributes implicitly have therequired
flag set totrue
and MUST NOT be declared asrequired: false
. - The
id
attribute'svalue
SHOULD NOT be defined. - The
time
attribute'svalue
defaults to01-01-0000T00:00:00Z
("current time") and SHOULD NOT be declared with a different value. - The
datacontenttype
attribute'svalue
is inferred from theschemaformat
attribute of the message definition if absent. - The
dataschema
attribute'svalue
is inferred from theschemaurl
attribute orschema
attribute of the message definition if absent. - The
type
of the property definition defaults to the CloudEvents type definition for the attribute, if any. Thetype
of an attribute MAY be modified. For instance, thesource
typeurireference
MAY be changed touritemplate
or thesubject
typestring
MAY be constrained to aurireference
orinteger
. If no CloudEvents type definition exists, the type defaults tostring
.
The values of all string
and uritemplate
-typed attributes MAY contain
placeholders using the RFC6570 Level 1 URI Template syntax. When the
same placeholder is used in multiple properties, the value of the placeholder is
assumed to be identical.
The following example declares a CloudEvent with a JSON payload. The attribute
id
is REQUIRED in the declared event per the CloudEvents specification in
spite of such a declaration being absent here, the type
of the type
attribute is string
and the attribute is required
even though the
declarations are absent. The time
attribute is made required
contrary to the
CloudEvents base specification. The implied datacontenttype
is
application/json
and the implied dataschema
is
https://example.com/schemas/com.example.myevent.json
:
{
"format": "CloudEvents/1.0",
"metadata": {
"attributes": {
"type": {
"value": "com.example.myevent"
},
"source": {
"value": "https://{tenant}/{module}/myevent",
"type": "uritemplate"
},
"subject": {
"type": "urireference"
},
"time": {
"required": true
},
}
},
"schemaformat": "JsonSchema/draft-07",
"schemaurl": "https://example.com/schemas/com.example.myevent.json",
}
For clarity of the definition, you MAY always declare all implied attribute properties explicitly, but they MUST conform with the rules above.
The "HTTP" format is used to define messages that are sent over an HTTP connection. The format is based on the HTTP Message Format and is common across all version of HTTP.
The metadata
object MAY contain several
properties:
Property | Type | Description |
---|---|---|
headers |
Array | The HTTP headers. See below. |
query |
Map | The HTTP query parameters. |
path |
uritemplate |
The HTTP path. |
method |
string |
The http method |
status |
string |
The http status code |
HTTP allows for multiple headers with the same name. The headers
property is
therefore an array of objects with name
and value
properties. The name
property is a string that MUST be a valid HTTP header name.
The query
property is a map of string keys to string values.
The path
property is a URI template.
The method
property is a string that MUST be a valid HTTP method.
The status
property is a string that MUST be a valid HTTP response
code. The status
and method
properties are mutually exclusive and
MUST NOT be present at the same time.
The values of all string
and uritemplate
-typed properties and headers and
query elements MAY contain placeholders using the RFC6570 Level 1 URI
Template syntax. When the same placeholder is used in multiple properties, the
value of the placeholder is assumed to be identical.
The following example defines a message that is sent over HTTP/1.1:
{
"format": "HTTP/1.1",
"metadata": {
"headers": [
{
"name": "Content-Type",
"value": "application/json"
}
],
"query": {
"foo": "bar"
},
"path": "/foo/{bar}",
"method": "POST"
},
"schemaformat": "JsonSchema/draft-07",
"schemaurl": "https://example.com/schemas/com.example.myevent.json",
}
The "AMQP/1.0" format is used to define messages that are sent over an AMQP connection. The format is based on the default AMQP 1.0 Message Format.
The metadata
object MAY contain several
properties, each of which corresponds to a section of the AMQP 1.0 Message:
Property | Type | Description |
---|---|---|
properties |
Map | The AMQP 1.0 Message Properties section. |
application-properties |
Map | The AMQP 1.0 Application Properties section. |
message-annotations |
Map | The AMQP 1.0 Message Annotations section. |
delivery-annotations |
Map | The AMQP 1.0 Delivery Annotations section. |
header |
Map | The AMQP 1.0 Message Header section. |
footer |
Map | The AMQP 1.0 Message Footer section. |
As in AMQP, all sections and properties are OPTIONAL.
The values of all string
, symbol
, uri
, and uritemplate
-typed properties
MAY contain placeholders using the RFC6570 Level 1 URI Template
syntax. When the same placeholder is used in multiple properties, the value of
the placeholder is assumed to be identical.
Example for an AMQP 1.0 message type that declares a fixed subject
(analogous
to CloudEvents' type
), a custom property, and a content-type
of
application/json
without declaring a schema reference in the message
definition:
{
"format" : "AMQP/1.0",
"metadata": {
"properties": {
"message-id": {
"required" : true
},
"to": {
"value": "https://{host}/{queue}"
},
"subject": {
"value": "MyMessageType"
"required" : true
},
"content-type": {
"value": "application/json"
},
"content-encoding": {
"value": "utf-8"
}
},
"application-properties": {
"my-application-property": {
"value": "my-application-property-value"
}
}
}
}
The properties
property is an object that contains the properties of the
AMQP 1.0 Message Properties section. The
following properties are defined, with type constraints:
Property | Type | Description |
---|---|---|
message-id |
string |
uniquely identifies a message within the message system |
user-id |
binary |
identity of the user responsible for producing the message |
to |
uritemplate |
address of the node to send the message to |
subject |
string |
message subject |
reply-to |
uritemplate |
address of the node to which the receiver of this message ought to send replies |
correlation-id |
string |
client-specific id that can be used to mark or identify messages between clients |
content-type |
symbol |
MIME content type for the message |
content-encoding |
symbol |
MIME content encoding for the message |
absolute-expiry-time |
timestamp |
time when this message is considered expired |
group-id |
string |
group this message belongs to |
group-sequence |
integer |
position of this message within its group |
reply-to-group-id |
uritemplate |
group-id to which the receiver of this message ought to send replies to |
The application-properties
property is an object that contains the custom
properties of the AMQP 1.0 Application Properties section.
The names of the properties MUST be of type symbol
and MUST be unique.
The values of the properties MAY be of any permitted type.
The message-annotations
property is an object that contains the custom
properties of the AMQP 1.0 Message Annotations section.
The names of the properties MUST be of type symbol
and MUST be unique.
The values of the properties MAY be of any permitted type.
The delivery-annotations
property is an object that contains the custom
properties of the AMQP 1.0 Delivery Annotations section.
The names of the properties MUST be of type symbol
and MUST be unique.
The values of the properties MAY be of any permitted type.
The header
property is an object that contains the properties of the
AMQP 1.0 Message Header section. The
following properties are defined, with type constraints:
Property | Type | Description |
---|---|---|
durable |
boolean |
specify durability requirements |
priority |
integer |
relative message priority |
ttl |
integer |
message time-to-live in milliseconds |
first-acquirer |
boolean |
indicates whether the message has not been acquired previously |
delivery-count |
integer |
number of prior unsuccessful delivery attempts |
The footer
property is an object that contains the custom properties of the
AMQP 1.0 Message Footer section.
The names of the properties MUST be of type symbol
and MUST be unique.
The values of the properties MAY be of any permitted type.
The "MQTT/3.1.1" and "MQTT/5.0" formats are used to define messages that are sent over MQTT 3.1.1 or MQTT 5.0 connections. The format describes the MQTT PUBLISH packet content.
The metadata
object contains the elements of the
MQTT PUBLISH packet directly, with the user-properties
element corresponding
to the application properties collection of other protocols.
The following properties are defined. The MQTT 3.1.1 and MQTT 5.0 columns indicate whether the property is supported for the respective MQTT version.
Property | Type | MQTT 3.1.1 | MQTT 5.0 | Description |
---|---|---|---|---|
qos |
integer |
yes | yes | Quality of Service level |
retain |
boolean |
yes | yes | Retain flag |
topic-name |
string |
yes | yes | Topic name |
payload-format |
integer |
no | yes | Payload format indicator |
message-expiry-interval |
integer |
no | yes | Message expiry interval |
response-topic |
uritemplate |
no | yes | Response topic |
correlation-data |
binary |
no | yes | Correlation data |
content-type |
symbol |
no | yes | MIME content type of the payload |
user-properties |
Array | no | yes | User properties |
Like HTTP, the MQTT allows for multiple user properties with the same name,
so the user-properties
property is an array of objects, each of which
contains a single property name and value.
The values of all string
, symbol
, and uritemplate
-typed properties and
user-properties MAY contain placeholders using the RFC6570 Level 1
URI Template syntax. When the same placeholder is used in multiple properties,
the value of the placeholder is assumed to be identical.
The following example shows a message with the "MQTT/5.0" format, asking for QoS 1 delivery, with a topic name of "mytopic", and a user property of "my-application-property" with a value of "my-application-property-value":
{
"format" : "MQTT/5.0",
"metadata": {
"qos": {
"value": 1
},
"retain": {
"value": false
},
"topic-name": {
"value": "mytopic"
},
"user-properties": [
{ "my-application-property": {
"value": "my-application-property-value"
}
}
]
}
}
The "Kafka" format is used to define messages that are sent over Apache Kafka connections. The version number reflects the last version in which the record structure was changed in the Apache Kafka project, not the current version. If the version number is omitted, the latest version is assumed.
The metadata
object contains the common elements
of the Kafka producer and consumer records, with the headers
element corresponding to the application
properties collection of other protocols.
The following properties are defined:
Property | Type | Description |
---|---|---|
topic |
string |
The topic the record will be appended to |
partition |
integer |
The partition to which the record ought be sent |
key |
binary |
The key that will be included in the record |
headers |
Map | A map of headers to set on the record |
timestamp |
integer |
The timestamp of the record; if 0 (default), the producer will assign the timestamp |
The values of all string
, symbol
, uritemplate
-typed properties
and headers MAY contain placeholders using the RFC6570 Level 1 URI
Template syntax. When the same placeholder is used in multiple properties, the
value of the placeholder is assumed to be identical.
Example:
{
"format" : "Kafka/0.11",
"metadata" : {
"topic" : {
"value" : "mytopic"
},
"key" : {
"value" : "thisdevice"
}
}
}
The Endpoint Registry is a registry of metadata definitions for abstract and concrete network endpoint to which messages can be produced, from which messages can be consumed, or which makes messages available for subscription and delivery to a consumer-designated endpoint.
As discussed in CloudEvents Registry overview,
endpoints are supersets of message definition groups
and MAY contain inlined definitions. Therefore, the RESORCE level in the
meta-model for the Endpoint Registry are likewise definitions
:
{
"groups": [
{
"singular": "endpoint",
"plural": "endpoints",
"schema": "TBD",
"resources": [
{
"singular": "definition",
"plural": "definitions",
"versions": 0,
"mutable": true
}
]
}
]
}
A Group (GROUP) name is endpoints
. The type of a group is endpoint
.
The following attributes are defined for the endpoint
type:
-
Type: String (Enum:
subscriber
,consumer
,producer
) -
Description: The
usage
attribute is a string that indicates the intended usage of the endpoint by communicating parties.Each of these parties will have a different perspective on an endpoint. For instance, a
producer
endpoint is seen as a "target" by the originator of messages, and as a "source" by the party that accepts the messages. The nomenclature used for theusage
field is primarily oriented around the common scenario of network endpoints being provided by some sort of intermediary like a message broker. The termproducer
primarily describes the relationship of a client with that intermediary.In a direct-delivery scenario where the originator of messages connects directly to the target (e.g. a "WebHook" call), the target endpoint implements the accepting end of the
producer
relationship.Some of these perspectives are mentioned below for illustration, but not formally defined or reflected in the metadata model. Perspectives depend on the context in which the endpoint metadata is used and this metadata model is intentionally leaving perspectives open to users.
The following values are defined for
usage
-
subscriber
: The endpoint offers managing subscriptions for delivery of messages to another endpoint, using the CloudEvents Subscriptions API.Some perspectives that might exist on a subscriber endpoint:
- Application from which messages originate
- Application which accepts messages from the delivery agent
- Application which manages subscriptions for delivery of messages to the target application. This might be a message broker subscription manager.
-
consumer
: The endpoint offers messages being consumed from it.Some perspectives that might exist on a consumer endpoint:
- Message store or source which makes messages available for consumption; this might be a message broker topic or a queue.
- Proxy or other intermediary which solicits messages from the source and forwards them to the target endpoint.
- Application which consumes messages
-
producer
: The endpoint offers messages being produces (sent) to it.Some perspectives might exist on a producer endpoint:
- Application from which messages originate
- Reverse proxy or other intermediary which accepts messages from the originator and forwards them to the target endpoint.
- Application which accepts messages. This might be a message broker topic or a queue. This might be an HTTP endpoint that directly accepts and handles messages.
Any endpoint can be seen from different role perspectives:
There might also be further perspectives such as pipeline stages for pre-/post-processing, etc.
-
-
Constraints:
- REQUIRED.
- MUST be one of "subscriber", "consumer", or "producer".
- Type: URI
- Description: A URI reference to the original source of this Endpoint. This
can be used to locate the true authority owner of the Endpoint in cases of
distributed Endpoint Registries. If this property is absent its default value
is the value of the
self
property and in those cases its presence in the serialization of the Endpoint is OPTIONAL. - Constraints:
- OPTIONAL if this Endpoint Regsitry is the authority owner
- REQUIRED if this Ednpoint Regsitry is not the authority owner
- if present, MUST be a non-empty URI
- Examples:
https://example2.com/myregistry/endpoints/9876
-
Type: Object containing the following properties:
-
effective
An OPTIONAL property indicating the time when the Endpoint entered, or will enter, a deprecated state. The date MAY be in the past or future. If this property is not present the Endpoint is already in a deprecated state. If present, this MUST be an RFC3339 timestamp. -
removal
An OPTIONAL property indicating the time when the Endpoint MAY be removed. The Endpoint MUST NOT be removed before this time. If this property is not present then client can not make any assumption as to when the Endpoint might be removed. Note: as with most properties, this property is mutable. If present, this MUST be an RFC3339 timestamp and MUST NOT be sooner than theeffective
time if present. -
alternative
An OPTIONAL property specifying the URL to an alternative Endpoint the client can consider as a replacement for this Endpoint. There is no guarantee that the referenced Endpoint is an exact replacement, rather the client is expected to investigate the Endpoint to determine if it is appropriate. -
docs
An OPTIONAL property specifying the URL to additional information about the deprecation of the Endpoint. This specification does not mandate any particular format or information, however some possibilities include: reasons for the deprecation or additional information about likely alternative Endpoints. The URL MUST support an HTTP GET request.
-
-
Description: This specification makes no statement as to whether any existing secondary resources (such as subscriptions) will still be valid and usable after the Endpoint is removed. However, it is expected that new requests to create a secondary resource will likely be rejected.
Note that an implementation is not mandated to use this attribute in advance of removing an Endpoint, but is it RECOMMENDED that they do so.
-
Constraints:
- OPTIONAL
-
Examples:
"deprecated": {}
-
"deprecated": { "removal": "2030-12-19T00:00:00-00:00", "alternative": "https://example.com/endpoints/123" }
-
Type: String
-
Description: A string that can be used to correlate Endpoints. Any Endpoints within an instance of an Endpoint Registry that share the same non-empty
channel
value MUST have some relationship. This specification does not define that relationship or the specific values used in this property. However, it is expected that theusage
value in combination with thischannel
property will provide some information to help determine the relationship.For instance, a message broker queue "queue1" might be represented with a
producer
endpoint and aconsumer
endpoint, both with the samechannel
attribute value of "queue1".An event processing pipeline might have a sequence of stages, each with a
producer
endpoint and aconsumer
endpoint, all with the samechannel
attribute value of "pipeline1", or some further qualification like "pipeline1-stage1", etc.When this property has no value it MUST either be serialized as an empty string or excluded from the serialization entirely.
-
Constraints:
- OPTIONAL
- if present, MUST be a string
-
Examples:
queue1
Endpoints are supersets of message definition groups and MAY contain inlined definitions. See Message Definitions.
Example:
{
"protocol": "HTTP/1.1",
"options": {
"method": "POST"
},
"definitions" : {
"myevent": {
"format": "CloudEvents/1.0",
"metadata": {
"attributes": {
"type" : {
"value" : "myevent"
}
}}}}}
The definitionGroups
attribute is an array of URI-references to message
definition groups. The definitionGroups
attribute is used to reference
message definition groups that are not inlined in the endpoint definition.
Example:
{
"protocol": "HTTP/1.1",
"options": {
"method": "POST"
},
"definitionGroups" : [
"https://example.com/registry/definitiongroups/mygroup"
]
}
- Type: Map
- Description: Configuration details of the endpoint. An endpoint
MAY be defined without detail configuration. In this case, the endpoint is
considered to be "abstract".
Note: Authentication and authorization details are intentionally not included in the endpoint metadata. The supported authentication and authorization mechanisms are either part of the protocol, negotiated at runtime (e.g. SASL), made available through the specific endpoint's documentation, or separate metadata specific to security policies.
- Constraints:
- OPTIONAL
-
Type: String
-
Description: The transport or application protocol used by the endpoint. This specification defines a set of common protocol names that MUST be used for respective protocol endpoints, but implementations MAY define and use additional protocol names.
Predefined protocols are referred to by name and version as
{NAME}/{VERSION}
. If the version is not specified, the default version of the protocol is assumed. The version number format is determined by the protocol specification's usage of versions.The predefined protocol names are:
- "HTTP/1.1", "HTTP/2", "HTTP/3" - Use the lowest HTTP version that the endpoints supports; that is commonly "HTTP/1.1". The default version is "HTTP/1.1" and MAY be shortened to "HTTP".
- "AMQP/1.0" - Use the AMQP 1.0 protocol. MAY be shortened to "AMQP". AMQP draft versions before 1.0 (e.g. 0.9) are not AMQP.
- "MQTT/3.1.1", "MQTT/5.0" - Use the MQTT 3.1.1 or 5.0 protocol. The shorthand "MQTT" maps to "MQTT/5.0".
- "NATS/1.0.0" - Use the NATS protocol. MAY be shortened to "NATS",
- which assumes usage of the latest NATS clients.
- "KAFKA/3.5" - Use the Apache Kafka protocol. MAY be shortened to "KAFKA", which assumes usage of the latest Apache Kafka clients.
An example for an extension protocol identifier might be "BunnyMQ/0.9.1".
-
Constraints:
- REQUIRED
- MUST be a non-empty string.
- Type: Array of URI
- Description: The network addresses that are for communication with the endpoint. The endpoints are ordered by preference, with the first endpoint being the preferred endpoint. Some protocol implementations might not support multiple endpoints, in which case all but the first endpoint might be ignored. Whether the URI just identifies a network host or links directly to a resource managed by the network host is protocol specific.
- Constraints:
- OPTIONAL
- Each entry MUST be a valid, absolute URI (URL)
- Examples:
["tcp://example.com", "wss://example.com"]
["https://example.com"]
- Type: Map
- Description: Additional configuration options for the endpoint. The configuration options are protocol specific and described in the protocol options section below.
- Constraints:
- OPTIONAL
- When present, MUST be a map of non-empty strings to non-empty strings.
- If
config.protocol
is a well-known protocol, the options MUST be compliant with the protocol's options.
- Type: Boolean
- Description: If
true
, the endpoint metadata represents a public, live endpoint that is available for communication and a strict validator MAY test the liveness of the endpoint. - Constraints:
- OPTIONAL.
- Default value is
false
.
The following protocol options (config.options
) are defined for the respective
protocols. All of these are OPTIONAL.
The endpoint URIs for "HTTP" endpoints MUST be valid HTTP URIs using the "http" or "https" scheme.
The following options are defined for HTTP:
method
: The HTTP method to use for the endpoint. The default value isPOST
. The value MUST be a valid HTTP method name.headers
: An array of HTTP headers to use for the endpoint. HTTP allows for duplicate headers. The objects in the array have the following attributes:name
: The name of the HTTP header. The value MUST be a non-empty string.value
: The value of the HTTP header. The value MUST be a non-empty string.
query
: A map of HTTP query parameters to use for the endpoint. The value MUST be a map of non-empty strings to non-empty strings.
The values of all query
and headers
MAY contain placeholders using the
RFC6570 Level 1 URI Template syntax. When the same placeholder is
used in multiple properties, the value of the placeholder is assumed to be
identical.
Example:
{
"protocol": "HTTP/1.1",
"options": {
"method": "POST",
"headers": [
{
"name": "Content-Type",
"value": "application/json"
}
],
"query": {
"operation": "send"
}
}
}
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.
The following options are defined for AMQP endpoints.
node
: The name of the AMQP node (a queue or topic or some addressable entity) to use for the endpoint. If present, the value overrides the path portion of the Endpoint URI.durable
: Iftrue
, the AMQPdurable
flag is set on transfers. The default value isfalse
. This option only applies tousage:producer
endpoints.link-properties
: A map of AMQP link properties to use for the endpoint. The value MUST be a map of non-empty strings to non-empty strings.connection-properties
: A map of AMQP connection properties to use for the endpoint. The value MUST be a map of non-empty strings to non-empty strings.distribution-mode
: Eithermove
orcopy
. The default value ismove
. The distribution mode is AMQP's way of expressing whether a receiver operates on copies of messages (it's a topic subscriber) or whether it moves messages from the queue (it's a queue consumer). This option only applies tousage:consumer
endpoints.
The values of all link-properties
and connection-properties
MAY contain
placeholders using the RFC6570 Level 1 URI Template syntax. When the
same placeholder is used in multiple properties, the value of the placeholder is
assumed to be identical.
Example:
{
"usage" : "producer",
"protocol": "AMQP/1.0",
"options": {
"node": "myqueue",
"durable": true,
"link-properties": {
"my-link-property": "my-link-property-value"
},
"connection-properties": {
"my-connection-property": "my-connection-property-value"
},
"distribution-mode": "move"
}
}
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. 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 endpoints.
topic
: The MQTT topic to use for the endpoint. If present, the value overrides the path portion of the Endpoint URI. The value MAY contain placeholders using the RFC6570 Level 1 URI Template syntaxqos
: The MQTT Quality of Service (QoS) level to use for the endpoint. The value MUST be an integer between 0 and 2. The default value is 0. The value is overidden by theqos
property of the MQTT message format.retain
: Iftrue
, the MQTTretain
flag is set on transfers. The default value isfalse
. The value is overidden by theretain
property of the MQTT message format. This option only applies tousage:producer
endpoints.clean-session
: Iftrue
, the MQTTclean-session
flag is set on connections. The default value istrue
.will-topic
: The MQTTwill-topic
to use for the endpoint. The value MUST be a non-empty string. The value MAY contain placeholders using the RFC6570 Level 1 URI Template syntaxwill-message
: This is URI and/or JSON Pointer that refers to the MQTTwill-message
to use for the endpoint. The value MUST be a non-empty string. It MUST point to a valid ´definition´ that MUST either use the "CloudEvents/1.0" or "MQTT/3.1.1." or "MQTT/5.0"format
.
Example:
{
"usage" : "producer",
"protocol": "MQTT/5.0",
"options": {
"topic": "mytopic",
"qos": 1,
"retain": false,
"clean-session": false,
"will-topic": "mytopic",
"will-message": "#/definitionGroup/mygroup/definitions/my-will-message"
}
}
The endpoint URIs for "Kafka" endpoints MUST be valid Kafka
bootstrap server addresses. The scheme follows Kafka configuration usage, e.g.
SSL://{host}:{port}
or PLAINTEXT://{host}:{port}
.
The following options are defined for Kafka endpoints.
topic
: The Kafka topic to use for the endpoint. The value MUST be a non-empty string if present. The value MAY contain placeholders using the RFC6570 Level 1 URI Template syntaxacks
: The Kafkaacks
setting to use for the endpoint. The value MUST be an integer between -1 and 1. The default value is 1. This option only applies tousage:producer
endpoints.key
: The fixed Kafka key to use for this endpoint. The value MUST be a non-empty string if present. This option only applies tousage:producer
endpoints. The value MAY contain placeholders using the RFC6570 Level 1 URI Template syntaxpartition
: The fixed Kafka partition to use for this endpoint. The value MUST be an integer if present. This option only applies tousage:producer
endpoints.consumer-group
: The Kafka consumer group to use for this endpoint. The value MUST be a non-empty string if present. This option only applies tousage:consumer
endpoints. The value MAY contain placeholders using the RFC6570 Level 1 URI Template syntax
Example:
{
"usage" : "producer",
"protocol": "Kafka/2.0",
"options": {
"topic": "mytopic",
"acks": 1,
"key": "mykey",
}
}
The endpoint URIs for "NATS" endpoints MUST be valid NATS
URIs. 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 following options are defined for NATS endpoints.
subject
: The NATS subject to use. The value MAY contain placeholders using the RFC6570 Level 1 URI Template syntax
Example:
{
"usage" : "producer",
"protocol": "NATS/1.0.0",
"options": {
"subject": "mysubject"
}
}