diff --git a/amqp-protocol-binding.md b/amqp-protocol-binding.md index 021afb69d..9e5db9650 100644 --- a/amqp-protocol-binding.md +++ b/amqp-protocol-binding.md @@ -5,10 +5,6 @@ The AMQP Protocol Binding for CloudEvents defines how events are mapped to OASIS AMQP 1.0 ([OASIS][oasis-amqp-1.0]; ISO/IEC 19464:2014) messages. -## Status of this document - -This document is a working draft. - ## Table of Contents 1. [Introduction](#1-introduction) diff --git a/avro-format.md b/avro-format.md index 62cf8d8ca..fcecbcfa1 100644 --- a/avro-format.md +++ b/avro-format.md @@ -5,10 +5,6 @@ The Avro Format for CloudEvents defines how events attributes are expressed in the [Avro 1.9.0 Specification][avro-spec]. -## Status of this document - -This document is a working draft. - ## Table of Contents 1. [Introduction](#1-introduction) diff --git a/ce_discovery.yaml b/ce_discovery.yaml deleted file mode 100644 index 2c534afaf..000000000 --- a/ce_discovery.yaml +++ /dev/null @@ -1,130 +0,0 @@ -openapi: '3.0.2' -info: - title: CloudEvents discovery API - description: CloudEvents discovery API specification according to [Discovery - Version 0.1-wip](https://github.com/cloudevents/spec/blob/master/discovery.md#service). - version: '0.1-WIP' -servers: - - url: https://api.cloudevents.io/test/v0.1 -paths: - /services: - get: - parameters: - - in: query - name: matching - description: The search term. - required: false - schema: - type: string - responses: - '200': - description: A list of services (optionally matching the query parameter). - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/service' - /services/{name}: - get: - parameters: - - in: path - name: name - description: The name of the service to be returned. - required: true - schema: - type: string - responses: - '200': - description: The corresponding service. - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/service' -components: - schemas: - service: - type: object - properties: - name: - type: string - description: A unique identifier for this Service. This value MUST be unique within the scope of this Discovery Endpoint. - example: storage, github - url: - type: string - description: A URL that references this Service. This value MUST be usable in subsequent requests, by authorized clients, to retrieve this Service entity. - example: http://example.com/services/storage, http://discovery.github.com/services/github - description: - type: string - description: Human readable description. - docsurl: - type: string - description: Absolute URL that provides a link to additional documentation about the service. This is intended for a developer to use in order to learn more about this service's events produced. - example: http://cloud.example.com/docs/blobstorage - specversions: - type: object - description: CloudEvents specversions that can be used for events published for this service. - subscriptionurl: - type: string - description: An absolute URL indicating where CloudSubscriptions subscribe API calls MUST be sent to. - subscriptionconfig: - type: object - description: "A map indicating supported options for the config parameter for the CloudSubscriptions subscribe() API call. Keys are the name of keys in the allowed config map, the values indicate the type of that parameter, confirming to the CloudEvents type system. TODO: Needs resolution with CloudSubscriptions API" - additionalProperties: - type: string - authscope: - type: string - description: Authorization scope needed for creating subscriptions. The actual meaning of this field is determined on a per-service basis. - example: storage.read - protocols: - type: array - description: This field describes the different values that might be passed in the protocol field of the CloudSubscriptions API. The protocols with existing CloudEvents bindings are identified as AMQP, MQTT3, MQTT5, HTTP, KAFKA, and NATS. An implementation MAY add support for further protocols. All services MUST support at least one delivery protocol, and MAY support additional protocols. - items: - type: string - description: protocol - example: '[ "HTTP", "AMQP", "KAFKA" ]' - events: - type: array - description: List of event types available in this service. - items: - $ref: '#/components/schemas/type' - type: - type: object - properties: - type: - type: string - description: CloudEvents type attribute. - example: com.github.pull.create, com.example.object.delete.v2 - description: - type: string - description: Human readable description. - dataschema: - type: string - description: CloudEvents datacontenttype attribute. Indicating how the data attribute of subscribed events will be encoded. - dataschematype: - type: string - description: If using dataschemacontent for inline schema storage, the dataschematype indicates the type of schema represented there. - dataschemacontent: - type: string - description: An inline representation of the schema of the data attribute encoding mechanism. This is an alternative to using the dataschema attribute. - sourcetemplate: - type: string - description: A URI Template according to RFC 6570 that defines how the source attribute will be generated. - example: "http://blob.store/{bucket}" - extensions: - type: array - description: An array or CloudEvents Extension Context Attributes that are used for this event type. - items: - type: object - properties: - name: - type: string - description: The CloudEvents context attribute name used by this extension. - type: - type: string - description: The data type of the extension attribute. - specurl: - type: string - description: An attribute pointing to the specification that defines the extension. - example: '{ "name": "dataref", "type": "URI-reference", "specurl": "https://github.com/cloudevents/spec/blob/master/extensions/dataref.md" }' diff --git a/discovery.md b/discovery.md deleted file mode 100644 index 7fa97a3f6..000000000 --- a/discovery.md +++ /dev/null @@ -1,875 +0,0 @@ -# CloudSubscriptions: Discovery - Version 0.1-wip - -## Abstract - -CloudSubscriptions Discovery API is a vendor-neutral API specification for -determining what events are available from a particular service, as well as how -to subscribe to those events. - -## Status of this document - -This is a working draft. Breaking changes could be made in the next minor -version. - -## Table of Contents - -- [Overview](#overview) -- [Notations and Terminology](#notations-and-terminology) -- [Resource Model](#resource-model) -- [API Specification](#api-specification) -- [Privacy & Security](#privacy-and-security) - -## Overview - -In order for consumers to receive events from services, they need to first -subscribe, or ask for, events from those services. To do so, there is often a -process necessary that involves steps such as discovering which service is of -interest, what events it generates and how to create the subscription for those -events. - -This specification defines a set of APIs to allow for consumers to perform these -queries against a "Discovery Endpoint". A Discovery Endpoint acts as a catalog -of [Services](#service) (event producers), that consumers can query to find the -ones of interest. Once found, additional metadata is provided in order to -consume and subscribe to events. The goal of this API is to be such that tooling -can be built where all possible services and event types aren't known in -advance. - -The deployment relationship of a Discovery Endpoint to the Services and Event -Producers that it advertises is out of scope of this specification. For example, -a Discovery Endpoint could choose to be implemented as part of a Service, or -Event Producer, or it could be acting as an independent aggregator of this -metadata. This implementation detail will be transparent to consumers. - -The main use-case to consider from the viewpoint of the event consumer is what -services are available, and what event types do they generate? - -The CloudEvent `source` attribute is a potential cause of high fan-out. For -example, consider a blob storage system where each directory constitutes a -distinct `source` attribute value. For this reason, the exact CloudEvents -`source` attribute value that might appear in a CloudEvent will not appear in -the Discovery API query result. Instead, a higher level classifier (`service`) -will be used to represent the abstract notion of the generic event producer of -those events - in the example case, the blob storage service itself. - -## 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](https://tools.ietf.org/html/rfc2119). - -### Terminology - -Note: some of the terms defined below are taken from the [CloudEvents](spec.md) -specification, and are marked with a reference to the original definition. Any -difference between the definitions is accidental and the CloudEvents version -takes precedence. - -This specification defines the following terms: - -#### Discovery Endpoint - -A compliant implementation of this specification that advertises the set of -Services, Event Types and other metadata to aid in the creation of an Event -Subscription. - -#### Service - -A "service" represents the entity which manages one or more event -[sources](#source-ce) and is associated with [producers](#producer-ce) that are -responsible for the generation of events. - -For example, an Object Store service might have a set of event sources where -each event source maps to a bucket. - -#### Source [[CE](./spec.md#source)] - -The "source" is the context in which the occurrence happened. In a distributed -system it might consist of multiple Producers. If a source is not aware of -CloudEvents, an external producer creates the CloudEvent on behalf of the -source. - -#### Producer [[CE](./spec.md#producer)] - -The "producer" is a specific instance, process or device that creates the data -structure describing the CloudEvent. - -#### Intermediary [[CE](./spec.md#intermediary)] - -An "intermediary" receives a message containing an event for the purpose of -forwarding it to the next receiver, which might be another intermediary or a -[Consumer](#consumer-ce). A typical task for an intermediary is to route the -event to receivers based on the information in the event -[Context](./spec.md#context). - -#### Consumer [[CE](./spec.md#consumer)] - -A "consumer" receives the event and acts upon it. It uses the context and data -to execute some logic, which might lead to the occurrence of new events. - -#### Subscription - -The request for events from a Service. - -## Resource Model - -This section defines the resource model of a Discovery Endpoint. - -### Services - -At the core of the data model is the concept of a [Service](#service). The API -then exposes multiple ways to query over a list of Services. To help explain the -Service resource, the following non-normative pseudo json shows its basic -structure: - -(`*` means zero or more, `+` means one or more, `?` means optional) - -Service: - -``` -{ - "id": "[a globally unique UUID]", - "epoch": "[discovery entry epoch value]", - "url": "[unique URL to this service]", - "name": "[unique name for this services]", - "description": "[human string]", ? - "docsurl": "[URL reference for human documentation]", ? - "specversions": [ "[ce-specversion value]" + ], - "subscriptionurl": "[URL to which the Subscribe request will be sent]", - "subscriptionconfig": { ? - "[key]": "[type]", * - }, - "subscrioptiondialects": [ "[dialect]" ], ? - "authscope": "[string]", ? - "protocols": [ "[string]" + ], - "events": [ ? - { * - "type": "[ce-type value]", - "description": "[human string]", ? - "datacontenttype": "[ce-datacontenttype value]", ? - "dataschema": "[ce-dataschema URI]", ? - "dataschematype": "[string per RFC 2046]", ? - "dataschemacontent": "[schema]", ? - "extensions": [ ? - { * - "name": "[CE context attribute name]", - "type": "[CE type string]", - "specurl": "[URL to specification defining the extension]" ? - } - ] - } - ] -} -``` - -An example: - -```json -{ - "id": "cbdd62e8-c095-11ea-b3de-0242ac130004", - "epoch": 1, - "url": "https://example.com/services/widgetService", - "name": "widgets", - "specversions": ["1.0"], - "subscriptionurl": "https://events.example.com", - "subscriptiondialects": [ "basic" ], - "protocols": ["HTTP"], - "events": [ - { - "type": "com.example.widget.create" - }, - { - "type": "com.example.widget.delete" - } - ] -} -``` - -Note: the above is just a sample and implementations are free to use any -internal model they wish to store the data as long as they are compliant with -the wire format/API defined by this specification. - -#### Service Attributes - -The following sections define the attributes that appear in a Service entity. - -##### id - -- Type: `String` -- Description: A unique identifier for this Service. This value MUST be globally - unique. While other metadata about this Service MAY change, this value MUST - NOT so that clients can use this attribute to know whether a Service returned - by a query is the same Service returned by a previous query. - - Whether a change to a Service would result in changing of the Service's - metadata (except `id`) and thus be just an update of an existing Service, or - whether the change would result in a brand new Service (with a new `id`) is - not defined by this specification. - - For example, if a Service's implementation is upgraded to a new version then - whether this would result in a new Service (and `id`) or is an update to the - existing Service's metadata, is an implementation choice. Likewise, this - specification makes no statement, or guarantees, as to the forwards or - backwards compatibility a Service as it changes over time. - - Note, unlike the `name` attribute which only needs to be unique within the - scope of a single Discovery Endpoint, the global uniqueness aspect of this - attribute allows for the discovery of the same Service across multiple - Discovery Endpoints. - - See the Primer for more information. - -- Constraints: - - REQUIRED in responses from the Discovery Endpoint. - - MUST be a valid UUID per RFC4122. -- Examples: - - `bf5ff5cc-d059-4c79-a89a-2513e45a1340` - -##### epoch - -- Type: `Integer` -- Description: The Discovery Endpoint's epoch value for this Service Entry. - This specification does not mandate any particular semantic meaning to - the value used. For example, implementations are free to use a value that - represents a timestamp or could choose to simply use a monotomically - increasing number. The only requirement is that the value MUST always - increase each time the Service Entry is updated. This allows for a quick - integer comparision to determine which version of this Service Entry is the - latest - meaning, the one with the larger integer value. - -- Constraints: - - REQUIRED in responses from the Discovery Endpoint. -- Examples: - - `42` - - `915148800` - -##### name - -- Type: `String` -- Description: A unique human readable identifier for this Service. This value - MUST be unique (case insensitive) within the scope of this Discovery Endpoint. - Note, this differs from the `id` attribute which is globally unique. -- Constraints: - - REQUIRED -- Examples: - - `my storage service` - - `cool git offering` - -##### url - -- Type: `URL` -- Description: An absolute URL that references this Service within this - Discovery Endpoint. This value MUST be usable in subsequent requests, by - authorized clients, to retrieve this Service - entity. -- Constraints: - - REQUIRED - - MUST be a non-empty URL - - MUST end with `fsegments` (per RFC1738) of: `/services/{id}` where `id` is - the Service's `id` attribute. -- Examples: - - `http://example.com/services/bf5ff5cc-d059-4c79-a89a-2513e45a1340` - - `http://discovery.github.com/services/892abefc-0293-9273-bead-92830efaefa0` - -##### description (Service) - -- Type: `String` -- Description: Human readable description. -- Constraints: - - OPTIONAL - - If present, MUST be a non-empty string - -##### docsurl - -- Type: `URL` -- Description: Absolute URL that provides a link to additional documentation - about the service. This is intended for a developer to use in order to learn - more about this service's events produced. -- Constraints: - - OPTIONAL - - If present, MUST be a non-empty absolute URI -- Examples: - - `http://cloud.example.com/docs/blobstorage` - -##### specversions - -- Type: Array of `Strings` per [RFC 2046](https://tools.ietf.org/html/rfc2046) -- Description: CloudEvents - [`specversions`](https://github.com/cloudevents/spec/blob/master/spec.md#specversion) - that can be used for events published for this service. -- Constraints: - - REQUIRED - - MUST be a non-empty array or non-empty strings - -##### subscriptionurl - -- Type: `URL` -- Description: An absolute URL indicating where CloudSubscriptions `subscribe` - API calls MUST be sent to. -- Constraints: - - REQUIRED - -##### subscriptionconfig - -- Type: `Map` of `String` to `String` -- Description: A map indicating supported options for the `config` parameter for - the CloudSubscriptions subscribe() API call. Keys are the name of keys in the - allowed config map, the values indicate the type of that parameter, conforming - to the CloudEvents - [type system](https://github.com/cloudevents/spec/blob/master/spec.md#type-system). - TODO: Needs resolution with CloudSubscriptions API -- Constraints: - - OPTIONAL -- Examples: - - ?? - -##### subscriptiondialects - -- Type: `Array` or `URI-reference` valuies -- Description: An array of filter dialects that MAY be used in the - Cloud Subscriptions subscribe() API call. -- Constraints: - - OPTIONAL -- Examples: - - `basic` - -##### authscope - -- Type: `String` -- Description: Authorization scope needed for creating subscriptions. The actual - meaning of this field is determined on a per-service basis. -- Constraints: - - OPTIONAL -- Example: - - `storage.read` - -##### protocols - -- Type: `List` of `String` -- Description: This field describes the different values that might be passed in - the `protocol` field of the CloudSubscriptions API. The protocols with - existing CloudEvents bindings are identified as AMQP, MQTT3, MQTT5, HTTP, - KAFKA, and NATS. An implementation MAY add support for further protocols. All - services MUST support at least one delivery protocol, and MAY support - additional protocols. -- Constraints: - - REQUIRED - - MUST be non-empty. -- Examples: - - `[ "HTTP" ]` - - `[ "HTTP", "AMQP", "KAFKA" ]` - -##### type - -- Type: `String` -- Description: CloudEvents - [`type`](https://github.com/cloudevents/spec/blob/master/spec.md#type) - attribute. -- Constraints: - - REQUIRED - - MUST be a non-empty string, following the constraints as defined in the - CloudEvents spec. -- Examples: - - `com.github.pull.create` - - `com.example.object.delete.v2` - -###### description (type) - -- Type: `String` -- Description: Human readable description. -- Constraints: - - OPTIONAL - - If present, MUST be a non-empty string - -###### datacontenttype - -- Type: `String` -- Description: CloudEvents - [`datacontenttype`](https://github.com/cloudevents/spec/blob/master/spec.md#datacontenttype) - attribute. Indicating how the `data` attribute of subscribed events will be - encoded. -- Constraints: - - OPTIONAL - - If present, MUST adhere to the format specified in - [RFC 2046](https://tools.ietf.org/html/rfc2046) - -###### dataschema - -- Type: `URI` -- Description: CloudEvents - [`dataschema`](https://github.com/cloudevents/spec/blob/master/spec.md#dataschema) - attribute. This identifies the canonical storage location of the schema of the - `data` attribute of subscribed events. -- Constraints: - - OPTIONAL - - If present, MUST be a non-empty URI - -###### dataschematype - -- Type: `String` per [RFC 2046](https://tools.ietf.org/html/rfc2046) -- Description: If using `dataschemacontent` for inline schema storage, the - `dataschematype` indicates the type of schema represented there. -- Constraints: - - OPTIONAL - - If present, MUST adhere to the format specified in - [RFC 2046](https://tools.ietf.org/html/rfc2046) -- Examples: - - `application/json` - -###### dataschemacontent - -- Type: `String` -- Description: An inline representation of the schema of the `data` attribute - encoding mechanism. This is an alternative to using the `dataschema` - attribute. -- Constraints: - - OPTIONAL - - If present, MUST be a non-empty string containing a schema compatible with - the `datacontenttype`. - - If `dataschama` is present, this field MUST NOT be present. - -###### sourcetemplate - -- Type: `URI Template` -- Description: A URI Template according to - [RFC 6570](https://tools.ietf.org/html/rfc6570) that defines how the source - attribute will be generated. -- Constraints: - - OPTIONAL - - If present, MUST be a Level 1 template compliant to - [RFC 6570](https://tools.ietf.org/html/rfc6570) -- Examples: - - "http://blob.store/{bucket}" - -###### extensions - -- Type: `Array` of structures -- Description: An array or CloudEvents - [Extension Context Attributes](https://github.com/cloudevents/spec/blob/master/spec.md#extension-context-attributes) - that are used for this event `type`. The structure contains the following - attributes: - - `name` - the CloudEvents context attribute name used by this extension. It - MUST adhere to the CloudEvents context attribute naming rules - - `type` - the data type of the extension attribute. It MUST adhere to the - CloudEvents [type system](./spec.md#type-system) - - `specurl` - an attribute pointing to the specification that defines the - extension -- Constraints: - - OPTIONAL - - if present, the `name` attribute in the structure is REQUIRED - - if present, the `type` attribute in the structure is REQUIRED - - if present, the `specurl` attribute in the structure is OPTIONAL -- Examples: - - `{ "name": "dataref", "type": "URI-reference", "specurl": "https://github.com/cloudevents/spec/blob/master/extensions/dataref.md" }` - -#### Service Examples - -```json -{ - "id": "3db60532-e839-417e-8644-e255f338776a", - "epoch": 1, - "url": "https://storage.example.com/service/storage", - "name": "storage", - "description": "Blob storage in the cloud", - "protocols": ["HTTP"], - "subscriptionurl": "https://cloud.example.com/docs/storage", - "events": [ - { - "type": "com.example.storage.object.create", - "specversions": ["1.x-wip"], - "datacontenttype": "application/json", - "dataschema": "http://schemas.example.com/download/com.example.storage.object.create.json", - "sourcetemplate": "https://storage.example.com/service/storage/{objectID}" - } - ] -} -``` - -## API Specification - -The endpoints defined by this specification are broken into two categories: -- Discovery APIs - used to find Services -- Management APIs - used to manage the Services within a Discovery Endpoint - -The relative paths specified below are NOT REQUIRED to be at the root of -the `fpath` (per RFC1738). However, they are REQUIRED to match the end of it. -For example, the follow are valid URLs/paths: - -``` -https://example.com/services -https://example.com/myAggregator/services -``` - -If a Discovery Endpoint can perform authorization checks to determine -which client can see which Service, and the requesting client is not allowed -access to a particular Service, then the Discovery Endpoint MUST respond -as if that Service does not exist. For example, it would be excluded from -any array of Services returned and it would result in a `404 Not Found` -error for a request to that Service directly. - -Unless there is some out-of-band agreement, all APIs MUST use JSON encoding, -which means when there is an HTTP Body the HTTP `Content-Type` Header MUST -be `application/json`. - -### Discovery APIs - -All of the API endpoints specified in this section MUST be supported by -compliant Discovery Endpoint implementations. - -#### `GET /services` - -This MUST return an array of zero or more Services. The array MUST contain all -Services available via this Discovery Enpoint. - -In the case of `200 OK`, the response format MUST adhere to the following: - -``` -200 OK -Content-Type: application/json - -[ - { - "id": "{id}", - "epoch": {int}, - "url": "{url}", - "name": "{name}", - ... remainder of Service attributes ... - } - ... -] -``` - -Implementations MAY use the [pagination](pagination.md) specification -if the number of Services returned is large. Clients SHOULD be -prepared to support paginated responses. - -#### `GET /services/{id}` - -If this refers to a valid Service, then this MUST return that single Service -entity. - -The following responses are defined by this specification: -- `200 OK` and the Service representation in the HTTP Response Body. -- `404 Not Found` if there is no Service with the specified `id`. - -Other responses are allowed, but not defined by this specification. - -In the case of `200 OK`, the response format MUST adhere to the following: - -``` -200 OK -Content-Type: application/json - -{ - "id": "{id}", - "epoch": {int}, - "url": "{url}", - "name": "{name}", - ... remainder of Service attributes ... -} -``` - -#### `GET /services?name={name}` - -This returns a single Service whose `name` attribute exactly matches the -`name` query parameter value specified (case insensitive). - -The following responses are defined by this specification: -- `200 OK` and the Service representation in the HTTP Response Body. -- `404 Not Found` if there is no Service with the specified `id`. - -In the case of `200 OK`, the response format MUST adhere to the following: - -``` -200 OK -Content-Type: application/json - -{ - "id": "{id}", - "epoch": {int}, - "url": "{url}", - "name": "{name}", - ... remainder of Service attributes ... -} -``` - -### Management APIs - -All of the API endpoints specified in this section MUST be supported by -compliant Discovery Endpoint implementations that support being managed. - -#### Asynchronous Processing - -For any of the following API endpoints, if the Discovery Endpoint chooses -to process the incoming request asynchronous then the following rules apply: -- A `202 Accepted` MUST be returned to the request. This indicates that the - request has been accepted but not processed yet. -- The `202 Accepted` response MUST include a `Location` HTTP Header that - points to a "status endpoint", which can be used to determine the status - of the original request. The HTTP Response body MAY be empty. -- The `202 Accepted` response MAY include a `Retry-After` HTTP Header - indicating the time, in seconds, that the sender SHOULD wait before - querying the status endpoint. - -A `GET` MAY be sent to the status endpoint to determine the status of the -original request. The following responses are defined: - -- `200 OK` indicates that the original request was successfully processed. - - Unless otherwise noted for a specific operation, the response MUST also - include the HTTP Headers and HTTP Response Body that is defined for the - original operation as if the response were sent synchronously. -- `202 Accepted` indicates that the original request is still being processed. - The response body MAY be empty. -- `406 Not Acceptable` to indicate that the original request failed to be - processed correctly. The HTTP response Body SHOULD include additional - information as to why it failed. - -Other responses are allowed, but not defined by this specification, however -they MUST be related to the `GET` itself and not the original request. - -How long a Discovery Endpoint supports requests to the status endpoint -is an implementation choice, however, it MUST be available immediately -upon return of the `202 Accepted` from the original request. - -#### `POST /services` - -This MUST add the specified Services to the list of Services available at this -Discovery Endpoint. The Body of the request message MUST contain an array of -zero or more Service Entries. For convenience to clients, each Service in the -array MAY include the `id` or `epoch` attributes but they MUST be ignored by -the Discovery Endpoint. Both of these attributes' values MUST be defined by -the Discovery Endpoint. - -If any Service specified in the request matches the `name` of any existing -Service, or the same `name` is used more than once within the request, then -an error MUST be generated. - -If the Discovery Endpoint is unable to successully add all of the Services -in the incoming request then an error MUST be generated and none of the -specified Services are to be added to the Discovery Endpoint. - -The follow responses are defined by this specification: -- `201 Created` if all the specified Services were processed successfully. - - If there was only one Service in the incoming request, then the response - MUST include an HTTP `Location` Header with a value that points to the - correspdonding Service. - - If the request contained more than one Service, then the HTTP `Location` - Header MUST NOT appear in the response. - - The HTTP Response Body MUST include an array of `id` values whose order - and values MUST match the list of Services in the request. - -Other responses are allowed, but not defined by this specification. - -The format of the HTTP Request MUST adhere to the following: -``` -Content-Type: application/json - -[ - { - "url": "{url}", - "name": "{name}", - ... remainder of Service attributes ... - } - ... -] -``` - -The format of the HTTP Response MUST adhere to the following: -``` -Content-Type: application/json - -[ - "id": "{id}" - ... -] -``` - -#### `POST /services?import` - -This MUST add, or update, the specified Services to the list of Services -available at this Discovery Endpoint. The Body of the request message MUST -contain an array of zero or more Service Entries. For convinience to clients, -the presence of the `id` and `epoch` attributes are OPTIONAL. If `id` is -present then it MUST be retained as a result of this operation and any existing -Service with that `id` MUST be replaced. If `epoch` is present then the -`epoch` value of the resulting Service MUST be larger than the maximum of -the incoming Service and any existing Service with that same `id`. If either -attribute is not present then the Discovery Endpoint MUST assign appropriate -value to the missing attribute. - -If the Discovery Endpoint is unable to successully add all of the Services -in the incoming request then an error MUST be generated and none of the -specified Services are to be added, or updated, in the Discovery Endpoint. - -The Services in the request message MUST be processed in the order in which -they appear. While any error in the overall process MUST rollback any changes -made due to the request, the processing of each Service in the request MUST be -applied as if all previous Services in the request were already completed. -This means that attribute uniqueness checking, such as on the `name` -attribute, MUST be done on the new state of all Services as if all previously -specified Services in the incoming request were already successfully processed. - -For example, if a Discovery Endpoint has a Service called `MyService`, it is -possible to rename that Service to `YourService` and then to add, or update, -another Service to use `MyService` as its `name`. But this is only true if -the rename of the first Service happens first the request message. - -Likewise, while it might be less than optimal, it is technically possible for -a request to update a Service multiple times if the same `id` is used more -than once within a request. - -The follow responses are defined by this specification: -- `201 Created` if all the specified Services were processed successfully. - - If there was only one Service in the incoming request, then the response - MUST include an HTTP `Location` Header with a value that points to the - correspoding Service. - - If the request contained more than one Service, then the HTTP `Location` - Header MUST NOT appear in the response. - - The HTTP Response Body MUST include an array of `id` values whose order - and values MUST match the list of Services in the request. - -Other responses are allowed, but not defined by this specification. - -The format of the HTTP Request MUST adhere to the following: -``` -Content-Type: application/json - -[ - { - "url": "{url}", - "name": "{name}", - ... remainder of Service attributes ... - } - ... -] -``` - -The format of the HTTP Response MUST adhere to the following: -``` -Content-Type: application/json - -[ - "id": "{id}" - ... -] -``` - -#### `PUT /services/{id}` - -This MUST update an existing Service in a Discovery Endpoint. The Body of the -request message MUST contain a single Service definition. The Service MUST -contain an `id` attribute that matches the `{id}` in the `PUT` URL. - -The request MAY include the `epoch` attribute. If present then the Discovery -Endpoint MUST ensure that the value on the incoming request matches the -current value on the Service. If they do not match then an error MUST be -generated and the Service MUST NOT be updated. However, if the incoming -request does not include this attribute then this verification MUST NOT -be done. - -Additionally, if the incoming request did contain the `epoch` attribute, then -its value MUST be updated by the Discovery Endpint to a larger value, -indicating that the Service has been updated. - -The follow responses are defined by this specification: -- `200 OK` if Service was updated. - The HTTP Response Body MUST include the JSON represenation of the updated - Service. -- `404 Not Found` if there is no Service with the specified `id`. - -Other responses are allowed, but not defined by this specification. - -The format of the HTTP Request MUST adhere to the following: -``` -Content-Type: application/json - -{ - "url": "{url}", - "epoch": "{id}", - "name": "{name}", - ... remainder of Service attributes ... -} -``` - -The format of the HTTP Response MUST adhere to the following: -``` -Content-Type: application/json - -{ - "url": "{url}", - "epoch": "{id}", - "name": "{name}", - ... remainder of Service attributes ... -} -``` -#### `PUT /services/{id}?import` - -This MUST create or update a Service in a Discovery Endpoint. The Body of the -request message MUST contain a single Service definition, however the presence -of the `epoch` attribute is OPTIONAL. The Service MUST contain an `id` -attribute that matches the `{id}` in the `PUT` URL. - -If `epoch` attribute is present then the resulting value of this attribute -MUST result in a value that is larger than both the incoming `epoch` value and -any existing Service's `epoch` value. If it is not present then the Discovery -Endpoint MUST assign a value that is larger than any existing Service's -`epoch` value. - -The follow responses are defined by this specification: -- `200 OK` if an existing Service was updated. - The HTTP Response Body MUST include the JSON represenation of the updated - Service. -- `201 Created` if a new Service was added. - The HTTP Response Body MUST include the JSON represenation of the - newly created Service. - -Other responses are allowed, but not defined by this specification. - -The format of the HTTP Request MUST adhere to the following: -``` -Content-Type: application/json - -{ - "url": "{url}", - "name": "{name}", - ... remainder of Service attributes ... -} -``` - -The format of the HTTP Response MUST adhere to the following: -``` -Content-Type: application/json - -{ - "url": "{url}", - "epoch": "{int}", - "name": "{name}", - ... remainder of Service attributes ... -} -``` -#### `DELETE /services/{id}` - -This MUST delete the Service at the referenced URL. - -The follow responses are defined by this specification: -- `200 OK` if the new Service was deleted. -- `404 Not Found` if there is no Service with the specified `id`. - -Other responses are allowed, but not defined by this specification. - -If the Service is successfully deleted any HTTP `GET` to the Service's -original URL MUST return an HTTP `404 Not Found` unless that URL happens to be -reused in the future (e.g. the Service was restored from a backup). - -### OpenAPI - -... - -## Privacy and Security - -The CloudDiscovery API does not place restrictions on implementation's choice of -an authentication and authorization mechanism. While the list of entities -returned from each query MAY differ, the format of the output MUST adhere to -this specification. diff --git a/ds-primer.md b/ds-primer.md deleted file mode 100644 index 93dba05dd..000000000 --- a/ds-primer.md +++ /dev/null @@ -1,201 +0,0 @@ -# Discovery and Subscription Primer - WIP - -## Abstract - -This non-normative document provides an overview of the Discovery and -Subscription API specifications. It is meant to complement those specifications -to provide additional background and insight into the history and design -decisions made during their development. This allows the specification itself -to focus on the normative technical details. - -## Status of this document - -This document is a working draft. - -## Table of Contents - -- History -- Design Goals -- Architecture -- Design Considerations -- Examples - -## History - -The CNCF working group created the CloudEvents specification to help with the -delivery of events from event producers to event consumers. The specification -defines some common eventing metadata (that were already part of most events -being generated), and where that data should appear based on how the event -is serialized and over which transport protocol it is being sent. - -By doing this, readers of those messages, whether they be the final recipient -of the event or an intermediary, can find and use this metadata without the -need to understand the business logic of the event itself. Often, this -is needed to help properly route the message to the next hop in the event's -journey to its final recipient. - -With that specification reaching verson 1.0 status, the project members then -considered what additional pain-points might need to be addressed in this -space. And, it seemed only natural that once there was some standardization -around the format of the events, that the group's attention should be to help -with consumers finding the event producers of interest, and programmatically -subscribing to receive events from those producers. - -Within that scope, two obvious items popped up: - -1 - Discovery: - This includes things such as: how does an event consumer know which events - a producer will generated? Which transport, and encoding, mechanisms do - they support? How should a consumer subscribe for events? - -2 - Subscriptions: - Once the consumer determines if a particular producer will generate events - that are of interest to them, how can they subscribe? Ideally, in an - interoperable way so as to not need to have custom logic for each producer. - -And with that, the 'Discovery' and 'Subscription API' specifications were born. - -## Design Goals - -- Re-use existing specifications and technology as much as possible -- Focus on the bare minimum, but have well defined extensibility points - -... - -## Use Cases - -The following list of use cases were driving considerations during the -development of these specifications. These are not meant to imply that other -use cases are not supported, rather they are enumerated here to help provide -insight into the team's focus during the development cycle. - -### Consumers - -- Consumer wants to programmatically determine the list of events (event types) - that a producer will generate so they can properly specify the list of events - they are interested in as part of the subscribe() operation. - -- Consumer wants to know which producers support certain event types so as to - allow for the consumer to subscribe only to those producers since those are - the only events that the consumer is interested in, or can support. - -- Consumer wants to know which event delivery mechansims a producer can support. - This will allow them to pick a transport that best suits their needs. For - example, a push vs pull delivery model. - -- Consumer wants to know if a producer can support filtering of events, and - which mechanisms, the producer supports. This can help consumers determine - which producer might be the best choice to reduce the amount of messages - sent, and whether filtering can be done by the producer or whether the - consumer will need to to it themselves. - -### Intermediaries - -- In order to route subscriptions to producers and to provide a combined - discovery endpoint to consumers, an intermediary aggregates the producers' - event catalogs. - -### Producers - -- Producer wants to register with an intermediary. As the intermediary also - provides a discovery endpoint, the producer transfers a catalog describing the - events it produces to the intermediary. - -## Architecture - -- picts -- flows - -... - -## Design Considerations - -- The Data Model -- Relationship to CE - CE required? ... -- REST vs ... -- REST Queries vs GraphQL -... - -### The `id` attribute - -Per the Discovery API specification, the Service's `id` is a globally -unique identifier for the Service. By ensuring that this value is immutable, -clients will be able to know when a Service is returned from the -Discovery Enpoints whether it is the same underlying Service as was returned -in a previous query despite any changes to its metadata - even if all of the -metadata has changed (except, of course, for the `id`). This includes the -cases where the same Service is returned from multiple Discovery Endpoints. - -Additionally, Discovery Endpoints may have multiple "views" over the set -of Services that they expose. Meaning, the same list of Services might -produce a different set of metadata based on these "views". In these cases, -the `id` attribute would be the same across those views if the Discovery -Endpoints wish for the underlying Service to be considered to be the same -Service. - -However, it is expected that given the same set of inputs (e.g. Discovery -Endpoint URL, user credentials, etc.), that the same `id` would be returned -each time for the same Service. - -## Examples -... - -### Simple Discovery and Subscribe - -``` -$ curl http://github.com/services -``` - -Response: -``` -- services: - - service: Github - subscriptionuri: https://api.github.com/subscribe - protocols: - - protocol: HTTP - types: - - type: com.github.pull_request.opened - datacontenttype: application/json - sourcetemplate: https://api.github.com/repos/{org}/{repo}/pulls/{id} - - type: com.github.pull_request.edited - datacontenttype: application/json - sourcetemplate: https://api.github.com/repos/{org}/{repo}/pulls/{id} - - type: com.github.pull_request.closed - datacontenttype: application/json - sourcetemplate: https://api.github.com/repos/{org}/{repo}/pulls/{id} - - type: com.github.issue.opened - datacontenttype: application/json - sourcetemplate: https://api.github.com/repos/{org}/{repo}/issues/{id} - - type: com.github.issue.edited - datacontenttype: application/json - sourcetemplate: https://api.github.com/repos/{org}/{repo}/issues/{id} - - type: com.github.issue.closed - datacontenttype: application/json - sourcetemplate: https://api.github.com/repos/{org}/{repo}/issues/{id} -``` - -Now subscribe: - -``` -$ curl https://api.github.com/subscribe/create -d @- << -{ -"id": "mysub1", -"protocol": "http", -"sink": "https://myfunc.example.com/processor" -} -``` - -Response: -``` -{ -"id": "mysub1", -"protocol": "http", -"sink": "https://myfunc.example.com/processor" -} -``` - -### Filtering - -### Pull - -### Using 'sourcetemplate' for routing diff --git a/http-protocol-binding.md b/http-protocol-binding.md index 91e55410c..3a084ea6b 100644 --- a/http-protocol-binding.md +++ b/http-protocol-binding.md @@ -5,10 +5,6 @@ The HTTP Protocol Binding for CloudEvents defines how events are mapped to HTTP 1.1 request and response messages. -## Status of this document - -This document is a working draft. - ## Table of Contents 1. [Introduction](#1-introduction) diff --git a/http-webhook.md b/http-webhook.md index 31f71f464..4b48d6db3 100644 --- a/http-webhook.md +++ b/http-webhook.md @@ -8,10 +8,6 @@ formal definition for Web Hooks. This specification aims to provide such a definition for use with [CNCF CloudEvents][ce], but is considered generally usable beyond the scope of CloudEvents. -## Status of this document - -This document is a working draft. - ## Table of Contents 1. [Introduction](#1-introduction) diff --git a/json-format.md b/json-format.md index d0e91a60e..de5418113 100644 --- a/json-format.md +++ b/json-format.md @@ -5,10 +5,6 @@ The JSON Format for CloudEvents defines how events are expressed in JavaScript Object Notation (JSON) Data Interchange Format ([RFC8259][rfc8259]). -## Status of this document - -This document is a working draft. - ## Table of Contents 1. [Introduction](#1-introduction) diff --git a/kafka-protocol-binding.md b/kafka-protocol-binding.md index f5b77a89d..3c5206e2e 100644 --- a/kafka-protocol-binding.md +++ b/kafka-protocol-binding.md @@ -5,10 +5,6 @@ The [Kafka][kafka] Protocol Binding for CloudEvents defines how events are mapped to [Kafka messages][kafka-message-format]. -## Status of this document - -This document is a working draft. - ## Table of Contents 1. [Introduction](#1-introduction) diff --git a/mqtt-protocol-binding.md b/mqtt-protocol-binding.md index a898bbf00..9e2962475 100644 --- a/mqtt-protocol-binding.md +++ b/mqtt-protocol-binding.md @@ -6,10 +6,6 @@ The MQTT Protocol Binding for CloudEvents defines how events are mapped to MQTT 3.1.1 ([OASIS][oasis-mqtt-3.1.1]; ISO/IEC 20922:2016) and MQTT 5.0 ([OASIS][oasis-mqtt-5]) messages. -## Status of this document - -This document is a working draft. - ## Table of Contents 1. [Introduction](#1-introduction) diff --git a/nats-protocol-binding.md b/nats-protocol-binding.md index d5e78f69e..e31bc28dd 100644 --- a/nats-protocol-binding.md +++ b/nats-protocol-binding.md @@ -5,10 +5,6 @@ The [NATS][nats] Protocol Binding for CloudEvents defines how events are mapped to [NATS messages][nats-msg-proto]. -## Status of this document - -This document is a working draft. - ## Table of Contents 1. [Introduction](#1-introduction) diff --git a/pagination.md b/pagination.md deleted file mode 100644 index ea2c928dc..000000000 --- a/pagination.md +++ /dev/null @@ -1,193 +0,0 @@ -# Pagination - -This document describes a mechanism by which a server can return a set of -records to a client in an incremental fashion. Often this will be used when -a client is doing a query for a set of records and the result set is too large -to return in one response. - -## 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](https://tools.ietf.org/html/rfc2119). - -## Client Request - -When a client sends a request to a server which is meant to result in a -set of records being returned, the client MAY include extra attributes -to control how those records are to be returned if the results can not -fit within one response message. - -### Client Attributes - -The follow list of attributes MAY be included in a client's request for -a set of records from a server. The client MUST only specify these on -the initial request for set. If the results can not fit within one -message then these attributes MUST NOT be added to subsequent requests -by the client. Note, the server MAY include these attributes within -the URI-reference returned in a response message, but the client MUST NOT -modify those values. - -#### limit - -- Type: unsigned 64-bit integer -- Description: Indicates the maximum number of records per message - that the cient is willing to accept. If the server is unable to - meet this criteria then it MUST generate an error. - There is no default value for this attribute. - If this attribute is not specified, then the server MAY choose to send back - as many, or as little, records per response message. -- Constraints: - - OPTIONAL - - MUST be an unsigned 64-bit integer with a value greater than 0 -- Examples: - - `100` - -## Server Response - -When a server returns a set of records, it MAY include additional attributes -to help the client retrieve the next set of records. - -### Server Attributes - -The following list of attributes MAY be included in a server's response to -a client's request for a set of records. - -Note: in the examples listed below, the use of certain query parameters -in the response messages from the server, such as `offset` and `limit`, -are an implementation detail of the server. How the server encodes the -information it needs to retrieve a certain set of records is not -mandated by this specification. - -#### link - -- Type: `URI-Reference` -- Description: A URI-Reference to another set of records. The relationship - of the next set, to the current set, MUST be specified by the `rel` - attribute. This value is meant to be treated as an opaque value by the - client. If a client uses this value in a subsequent request then it - MUST use it as it was provided by the server. Any attempt to modify its - value, or attributes (such as query parameters), is not defined by this - specification and the results from the server are undefined. -- Constraints: - - MUST NOT be present if there are no more records for the `rel` type of - relationship - - MUST be present if there are more records for the `rel` type of - relationship - - MUST be a URI-Reference as defined in RFC... -- Examples: - - `http://example.com/people?offset=3&limit=100` - - `http://example.com/people?id=1234` - - `http://example.com/people?resultset=7a835` - -#### rel - -- Type: `String` -- Description: A string representing the relationship between the records - available via the `link` URI-Reference and the current set of records. - This attribute adheres to the Relation Type as defined in section 5.3 - of RFC5988. - This specification uses the following values as defined by section 6.2.2 - in RFC598: - - `next` - indicates the next set of records in the sequence of records - being returned - - `prev` - indicates the previous set of records in the sequence of records - being returned - - `first` - indicates the first set of records in the sequence of records - being returned - - `last` - indicates the last set of records in the sequence of records - being returned - Unless otherwise constrained by a specification leveraging this - specification, additional values MAY be defined. -- Constraints: - - REQUIRED if the `link` attribute is present - - MUST be a string as defined by `relation-types` in RFC5988 - -#### expires - -- Type: `Timestamp` -- Description: Indicates when the set of records referenced by the - `link` will no longer be available. When not specified, the availability - of the data is undefined by this specification. However, it is RECOMMENDED - that this attribute only be excluded when the data being interated over - is not expected to change very often and therefore the server will - typically not need to save any state related to this client's requests. -- Constraints: - - OPTIONAL - -## HTTP Binding - -THe following describes how the attributes defined above would appear in a -flow of HTTP messages during the retrieval of a set of records. - -### Request for a record set - -To request a set of records from a server, a client will send an HTTP GET -request to the server. How this URL is determined is out of scope of this -specification. - -The client MAY include the `limit` attribute as part of this request. Unless -there is some out-of-bands negotiation to determine a different mechanism, -the server MUST accept the `limit` attribute as a query parameter (named -`limit`, case sensitive) in the URL. - -For example: -``` -http://example.com/people?limit=100 -``` - -### Response for a record set - -Each successful response from the server will adhere to the following: -- MUST respond with an HTTP 200 -- MUST include zero or more records -- if the response refers to the start of the set of records, then the `prev` - Link MUST NOT be included in the response -- if the response does not include the start of the set of records, then the - `prev` Link MAY be included in the response -- the response MAY include the `first` Link in any response -- if `limit` attribute was specified as part of the flow, the response MUST - NOT include more records than what the `limit` attribute has indicated -- if the response refers to the end of the set of records, then the `next` - Link MUST NOT be included in the response -- if the response does not refer to the end of the set of records, then the - `next` Link MUST be included in the response -- the response MAY include the `last` Link in any response -- the response MAY include the `expires` attribute in any response as an - HTTP "Expires" header. If present, it MUST adhere to the format specified in - [RFC 3339](https://tools.ietf.org/html/rfc7234#section-5.3) - -Additionally, Links MUST appear in the HTTP response as HTTP headers using -the format described in RFC5988. - -Example 1: -``` -Link: ;rel=next -Link: ;rel=prev -``` - -Example 2: -``` -Link: ;rel=next -Expires: Thu, 01 Dec 2021 16:00:00 GMT -``` - -Example 3: -``` -Link: ;rel=next -Link: ;rel=prev -``` - -### Iterating over the record set - -Once the record set retrieval has started, the client MAY use the Links -returned from the server to iterate through the full set of records. -Typically, the client will use the `next` Link from each response to retrieve -the next set of records until a response is returned without a `next` Link - -indicating that it has reached the end. - -However, if other Links are provided by the server, then the client MAY -use those Links instead to follow a different traversal path through the -records. diff --git a/primer.md b/primer.md index 91da0cac8..71509dfab 100644 --- a/primer.md +++ b/primer.md @@ -8,10 +8,6 @@ additional background and insight into the history and design decisions made during the development of the specification. This allows the specification itself to focus on the normative technical details. -## Status of this document - -This document is a working draft. - ## Table of Contents - [History](#history) diff --git a/protobuf-format.md b/protobuf-format.md index 36fd88a67..f25e9bf80 100644 --- a/protobuf-format.md +++ b/protobuf-format.md @@ -11,7 +11,7 @@ interchangeably. ## Status of this document -This document is a working draft. +This document is a release candidate. ## Table of Contents diff --git a/schemaregistry/schemaregistry.md b/schemaregistry/schemaregistry.md deleted file mode 100644 index b34a9e8f8..000000000 --- a/schemaregistry/schemaregistry.md +++ /dev/null @@ -1,407 +0,0 @@ -# CNCF Schema Registry API Version 0.1-wip - -## Abstract - -This specification defines a simple API for storing, organizing, and accessing -schema documents for use with serialization and data validation frameworks such -as Apache Avro and JSON Schema. - -## Status of this document - -This document is a working draft. - -## 1. Introduction - -Schema-dependent serialization formats and related frameworks such as Apache -Avro are popular in eventing and messaging scenarios. With most of the metadata -information such as names and types of fields being held externally in schema -documents, these frameworks are able to produce very compact on-wire -representations of structured data that is carried as the payload of events and -messages. While the wire-footprint savings are often very significant, the added -cost is that of schema handling. All communicating parties who need to -deserialize the event or message payload need access to the schema used to -publish it. - -For formats that do not depend on external schemas for serialization, schemas -might still be required in some scenarios to allow for consumers or inspecting -intermediaries to validate the data structure's compliance with a set of rules. - -This specification defines a very simple API focused on storing, organizing, and -accessing such documents. While there are very sophisticated metadata management -solutions available as open source and under neutral governance already, the focus -of this specification is not great sophistication but straightforward simplicity. - -This schema registry deals with only three top-level elements: - -- Schema Group: A named collection of schemas. Each group holds a logically - related set of schemas, typically managed by a single entity, belonging to a - particular application and/or having a shared access control management scope. -- Schema: A document describing the structure, names, and types of some - structured data payload. -- Version: A specific version of a schema document. Even though not prescribed - in this specification, an implementation might choose to impose compatibility - constraints on versions following the initial version of a schema. - -## 2. Schema Registry Elements - -This section further describes the elements enumerated in the introduction. All -data types used in this section are defined in the core CloudEvents -specification and MUST follow the respective formatting and syntax rules unless -specified otherwise. - -### 2.1. Schema Group - -A schema group is a named collection of schemas. Since a schema registry is -often a resource with a scope greater than a single application and might even -span multiple organizations, it is very useful to put a grouping construct -around sets of schemas that are related either by ownership or by a shared -subject matter context. - -Implementations of this specification MAY associate access control rules with -schema groups. For instance, a user or a group of users might be given write -access only to a particular schema group that their organization owns. If trade -secret protection is required for an application or parts of it and the schema -structure would give some of those away, read access to a group of schemas might -likewise be restricted. - -Access control rules at the schema group level MUST NOT limit visibility of the -schema groups themselves to users authorized to enumerate schema groups at the -registry level or to create new schema groups in order to create unambiguous -transparency about which `id` have already been taken. An implementation MAY -withhold all details other than the `id` attribute from a user not authorized -to access the schema group. - -This specification does not define management constructs for such access control -rules. - -### 2.1.1. Schema group attributes - -The data model for a schema group consists of these attributes: - -#### id - -- Type: `String` -- Description: Identifies the schema group. -- Constraints: - - REQUIRED - - MUST be a non-empty string - - MUST conform with RFC3986/3.3 `segment-nz-nc` syntax. This allows for "dot - notation", e.g. `org.example.myapp.module` for logical organization of - schema groups, even though the namespace is flat. - - MUST be unique within the scope of the schema registry -- Examples: - - mygroup - - my-group - - org.example.myapp.module - - events@example.com - -#### format - -- Type: `String` -- Description: Defines the schema format managed by this schema group. The - formats supported by an implementation are specific to the implementation. If - the format is omitted for the schema group, the format MUST be specified at - the schema-level. This specification does not mandate support for particular - formats. -- Constraints: - - OPTIONAL. - - MUST be a non-empty string, if present. - - MUST NOT be modified if at least one schema exists in the group. -- Examples: - - "avro" - - "json-schema" - - "xsd11" - -#### description - -- Type: `String` -- Description: Explains the purpose of the schema group. -- Constraints: - - OPTIONAL -- Examples: - - "This group holds schemas for the fabulous example app." - -#### createdtimeutc - -- Type: `Timestamp` -- Description: Instant when the schema group was added to the registry. -- Constraints: - - OPTIONAL - - Assigned by the server. - -#### updatedtimeutc - -- Type: `Timestamp` -- Description: Instant when the schema group was last updated -- Constraints: - - OPTIONAL - - Assigned by the server. - -## 2.2. Schema and Schema Version - -Conceptually, a schema is a description of a data structure. Since data -structures evolve over time, the schema describing them will also evolve over -time. Therefore, a schema often has multiple versions. - -For simple scenarios, the API allows for version management to be automatic and -transparent. Whenever a schema is updated, a new version number is assigned and -prior schema versions are retained. This specification does not mandate a -retention policy, but implementations MAY retire and remove outdated schema -versions. - -The latest available schema is always the default version that is retrieved when -the URL to the schema is given without the version specified. - -A newer schema version might introduce breaking changes or it might only -introduce careful changes that preserve compatibility. These strategies are not -subject of this specification, but the API provides a conflict handling -mechanism that allows an implementation to reject updates that do not comply -with a compatibility policy, if one has been implemented. - -### 2.2.1. Multi-format schema groups - -If the schema format has not been restricted at the schema group level, each -schema MAY have its own format. This choice is mutually exclusive. If a format -has been defined for the group, schemas in the group MUST use that format. - -### 2.2.2. Schema attributes - -As per the definition above, the schema object is a collection of versions -of schema documents. An implementation MAY add further attributes. - -#### id - -- Type: `String` -- Description: Identifies the schema. -- Constraints: - - REQUIRED - - MUST be a non-empty string - - MUST conform with RFC3986/3.3 `segment-nz-nc` syntax - - MUST be unique within the scope of the schema group -- Examples: - - myschema - - my-schema - -#### format - -- Type: `String` -- Description: Defines the format of this schema. The formats supported by an - implementation are specific to the implementation. If the format has been omitted - for the schema group, the format MUST be specified at the schema-level. This - specification does not mandate support for particular formats. -- Constraints: - - REQUIRED if not set at the schema group level. - - MUST be null (not present) if set at the schema group level. - - MUST be a non-empty string, if present. -- Examples: - - "avro" - - "json-schema" - - "xsd11" - -#### description - -- Type: `String` -- Description: Explains the purpose of the schema. -- Constraints: - - OPTIONAL -- Examples: - - "This schema describes the toppings for a Pizza." - -#### createdtimeutc - -- Type: `Timestamp` -- Description: Instant when the schema was added to the registry. -- Constraints: - - OPTIONAL - - Assigned by the server. - -#### updatedtimeutc - -- Type: `Timestamp` -- Description: Instant when the schema was last updated -- Constraints: - - OPTIONAL - - Assigned by the server. - -### 2.2.3 Schema version attributes - -A schema version is a document. The "body" of a schema version MAY be a text -document or binary stream. An implementation SHOULD validate whether a -schema version is valid according to the rules of its format, for instance -whether it is a valid Avro schema document when the format is Apache Avro. - -The schema version MAY also have an additional, optional unique identifier -within the scope of the registry. - -#### version - -- Type: `Integer` -- Description: The version of the schema. This is a simple counter and tracks - the version in the scope of this schema within the schema group. The schema - document content MAY indicate a different versioning scheme. -- Constraints: - - REQUIRED - - Assigned by server. -- Examples: - - 1 - - 2 - -#### id - -- Type: `String` -- Description: Identifies the schema document uniquely without requiring - other qualifiers. -- Constraints: - - OPTIONAL - - Assigned by the server. -- Examples: - - { ... guid ... } - -#### description - -- Type: `String` -- Description: Explains details of the schema version. -- Constraints: - - OPTIONAL -- Examples: - - "This version adds support for different types of Pizza crust." - -#### createdtimeutc - -- Type: `Timestamp` -- Description: Instant when the schema version was added to the registry. -- Constraints: - - OPTIONAL - - Assigned by the server. - -## 3. HTTP ("REST") API - -This section informally describes the HTTP API binding of this schema registry. -The formal definition is the [OpenAPI document](./schemaregistry.yaml) that is -part of this specification. - -This section is therefore non-normative. - -### 3.1. Path hierarchy - -Schema groups contain schemas and those contain schema versions, which are the -documents required for serialization or validation. - -These dependencies are reflected in the path structure: - -`/schemagroups/{group-id}/schemas/{schema-id}/versions/{version}` - -The name of the first segment of the path ("/schemagroups") is an illustrative -suggestion and MAY differ between implementations and the registry does not need -to be anchored at the site root. The segment names `schemas` and `versions` MUST -be used. - -- `{group-id}` corresponds to the schema group's [`id` attribute](#id) -- `{schema-id}` corresponds to the schema's [`id` attribute](#id-1) -- `{version}` corresponds to the schema version's [`version` attribute](#version) - -### 3.2. Operations at the groups level - -#### 3.2.1. List schema groups - -Schema groups are enumerated with a GET on the root of the registry hierarchy, -in the exemplary structure above identified as `/schemagroups`. - -The result is a JSON encoded array of strings enumerating the `id` values of the -schema groups. - -#### 3.2.2. Get schema group - -The details of a schema group are retrieved with a GET on the group's path in -the schema groups collection, for instance `/schemagroups/mygroup`. - -The result is a JSON object that contains the attributes of the schema group. - -#### 3.2.3. Create schema group - -A schema group is created with a PUT on the desired group's path in -the schema groups collection, for instance `/schemagroups/mygroup`. - -The payload is a JSON object that contains the attributes of the schema group. - -The operation returns the effective attributes as a JSON object when the schwema -group has been created or updated. - -#### 3.2.4. Delete schema group - -A schema group is deleted with a DELETE on the desired group's path in -the schema groups collection, for instance `/schemagroups/mygroup`. - -### 3.3 Operations at the schemas level - -#### 3.3.1. List schemas for the group - -Schemas within a schema group are enumerated with a GET on the `schemas` -collection of the group, for instance `/schemagroups/mygroup/schemas`. - -The result is a JSON encoded array of strings enumerating the `id` values of the -schemas within the group. - -#### 3.3.2. Delete all schemas from the group - -All schemas of a schema group can be deleted DELETE on the `schemas` -collection of the group, for instance `/schemagroups/mygroup/schemas`. - -#### 3.3.3. Add a new schema version - -A new schema or a new version of a schema is added to the version collection -with a POST on the desired schema's path in the schemas collection, for instance -`/schemagroups/mygroup/schemas/myschema`. - -This operation will either create a new schema and store the document under the -first version identifier assigned by the server or will update the schema by -assigning a new version to the given document and storing it. - -The payload of the request is the schema document. All further attributes such -as the `description` or the `format` indicator are passed either via the query -string or as HTTP headers. - -The ´Content-Type´ for the payload MUST be preserved by the registry and -returned when the schema is requested, independent of the format identifier. - -#### 3.3.4. Get the latest version of a schema - -The latest version of a schema is retrieved via a GET on schema's path in the -schemas collection, for instance `/schemagroups/mygroup/schemas/myschema`. - -The returned payload is the schema document. Further attributes such as the -`description` and the `format` indicator are returned as HTTP headers. - -The returned ´Content-Type´ is the same that was passed when the schema version -was registered. - -The HEAD method SHOULD also be implemented. - -#### 3.3.4. Delete a schema - -A schema including all its versions is deleted with a DELETE on schema's path in the -schemas collection, for instance `/schemagroups/mygroup/schemas/myschema` - -### 3.4 Operations at the versions level - -#### 3.4.1. List all versions of the schema - -Versions of a schema within a schema group are enumerated with a GET on the -`versions` collection of the schema, for instance -`/schemagroups/mygroup/schemas/myschemas/versions`. - -The result is a JSON encoded array of integers enumerating the `version` values of the -schemas within the group. - -#### 3.4.2. Get a specific schema version - -A specific version of a schema is retrieved via a GET on schema version's path in the -`versions` collection, for instance `/schemagroups/mygroup/schemas/myschema`. - -The returned payload is the schema document. Further attributes such as the -`description` and the `format` indicator are returned as HTTP headers. - -The returned ´Content-Type´ is the same that was passed when the schema version -was registered. - -The HEAD method SHOULD also be implemented. \ No newline at end of file diff --git a/schemaregistry/schemaregistry.yaml b/schemaregistry/schemaregistry.yaml deleted file mode 100644 index 34c06f27b..000000000 --- a/schemaregistry/schemaregistry.yaml +++ /dev/null @@ -1,315 +0,0 @@ -openapi: 3.0.0 -info: - title: Cloud Native Data Schema Registry - version: "0.1" -paths: - /schemagroups: - get: - summary: 'Get list of schema groups' - description: 'Get all schema groups in namespace.' - operationId: getGroups - responses: - '200': - description: OK - content: - application/json: - schema: - type: array - items: - type: string - tags: - - 'groups' - /schemagroups/{group-id}: - parameters: - - name: group-id - in: path - description: schema group - required: true - schema: - type: string - get: - summary: Get schema group - description: Get schema group description in registry namespace. - operationId: getGroup - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/SchemaGroup' - '404': - description: Specified group not found - tags: - - 'groups' - put: - summary: Create schema group - description: Create schema group with specified format in registry namespace. - operationId: createGroup - requestBody: - description: schema group description - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/SchemaGroup' - responses: - '201': - description: Created - headers: - Location: - schema: - type: string - '409': - description: Schema group already exists - tags: - - 'groups' - delete: - summary: Delete schema group - description: Delete schema group in schema registry namespace. - operationId: deleteGroup - responses: - '204': - description: OK no content - '404': - description: Specified group not found - tags: - - 'groups' - /schemagroups/{group-id}/schemas: - parameters: - - name: group-id - in: path - description: schema group - required: true - schema: - type: string - get: - tags: - - 'groups' - summary: List schemas for group id - description: Returns schema by group id. - operationId: getSchemasByGroup - responses: - '200': - description: OK - content: - application/json: - schema: - type: array - items: - type: string - '404': - description: Group not found - delete: - tags: - - 'groups' - summary: Deletes all schemas in group - description: Deletes all schemas under specified group id. - operationId: deleteSchemasByGroup - responses: - '204': - description: OK no content - '404': - description: Group not found - /schemagroups/{group-id}/schemas/{schema-id}: - parameters: - - name: group-id - in: path - description: schema group - required: true - schema: - type: string - - name: schema-id - in: path - description: schema id - required: true - schema: - type: string - post: - summary: Register schema - description: > - Register schema. - If schema of specified name does not exist in specified group, schema is created at version 1. - If schema of specified name exists already in specified group, schema is created at latest version + 1. - If schema with identical content already exists, existing schema's ID is returned. - operationId: createSchema - requestBody: - description: schema content - required: true - content: - application/json;format=avro: - schema: - $ref: '#/components/schemas/SchemaBytePayload' - responses: - '200': - $ref: '#/components/responses/SchemaIdResponse' - '400': - description: Invalid request - tags: - - 'registration' - get: - summary: Get latest version of schema - description: Get latest version of schema. - operationId: getLatestSchema - responses: - '200': - $ref: '#/components/responses/SchemaBytePayloadResponse' - tags: - - 'schemas' - delete: - summary: Delete schema - operationId: deleteSchema - responses: - '204': - description: OK no content - '404': - description: Matching schema not found - tags: - - 'schemas' - /schemagroups/{group-id}/schemas/{schema-id}/versions: - parameters: - - name: group-id - in: path - description: schema group - required: true - schema: - type: string - - name: schema-id - in: path - description: schema id - required: true - schema: - type: string - get: - summary: Get list of versions - description: Get list of versions for specified schema - operationId: getSchemaVersions - responses: - '200': - description: OK - content: - application/json;format=avro: - schema: - type: array - items: - type: integer - tags: - - 'versions' - /schemagroups/{group-id}/schemas/{schema-id}/versions/{version-number}: - parameters: - - name: group-id - in: path - description: schema group - required: true - schema: - type: string - - name: schema-id - in: path - description: schema id - required: true - schema: - type: string - - name: version-number - in: path - description: version number - required: true - schema: - type: integer - get: - summary: Get specified version of schema - operationId: getSchemaVersion - responses: - '200': - $ref: '#/components/responses/SchemaBytePayloadResponse' - '404': - description: Specified schema not found - tags: - - 'versions' - delete: - summary: Delete specified version of schema - operationId: deleteSchemaVersion - responses: - '204': - description: OK no content - tags: - - 'versions' - -components: - schemas: - SchemaId: - type: object - properties: - id: - type: string - SchemaBytePayload: - type: string - SchemaGroup: - type: object - properties: - id: - type: string - description: - type: string - createdtimeutc: - type: string - format: date-time - updatedtimeutc: - type: string - format: date-time - format: - type: string - groupProperties: - type: object - additionalProperties: - type: string - responses: - SchemaIdResponse: - description: OK - headers: - Location: - schema: - type: string - Schema-Id: - schema: - type: string - format: uuid - description: unique schema identifier - Schema-Id-Location: - schema: - type: string - format: url - description: location of schema resource - Schema-Version: - schema: - type: integer - description: version of returned schema - content: - application/json;format=avro: - schema: - $ref: '#/components/schemas/SchemaId' - application/json;format=protobuf: - schema: - $ref: '#/components/schemas/SchemaId' - SchemaBytePayloadResponse: - description: OK - headers: - Location: - schema: - type: string - Schema-Id: - schema: - type: string - description: schema identifier - Schema-Id-Location: - schema: - type: string - format: url - description: location of schema resource - Schema-Version: - schema: - type: integer - description: version of returned schema - content: - application/json;format=avro: - schema: - $ref: '#/components/schemas/SchemaBytePayload' \ No newline at end of file diff --git a/spec.md b/spec.md index dfa6412e6..b5af9890a 100644 --- a/spec.md +++ b/spec.md @@ -5,10 +5,6 @@ CloudEvents is a vendor-neutral specification for defining the format of event data. -## Status of this document - -This document is a working draft. - ## Table of Contents - [Overview](#overview) diff --git a/subscriptions-api-openapi.yaml b/subscriptions-api-openapi.yaml deleted file mode 100644 index be0b91f29..000000000 --- a/subscriptions-api-openapi.yaml +++ /dev/null @@ -1,248 +0,0 @@ -openapi: "3.0.2" -info: - title: CloudEvents Subscriptions API - version: "0.1 WIP" -servers: - - url: https://server.example.com/v0.1 -paths: - /subscriptions: - get: - description: Retrieve multiple subscriptions - responses: - "200": - description: OK - content: - application/json: - schema: - type: array - description: a list of subscriptions - items: - $ref: "#/components/schemas/Subscription" - post: - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/SubscriptionRequest" - responses: - "200": - description: Created successfully - content: - application/json: - schema: - $ref: "#/components/schemas/Subscription" - headers: - Location: - schema: - type: string - format: url - "400": - description: Invalid or malformed request - options: - description: Discover supported features and methods for this endpoint - responses: - "200": - description: OK - headers: - Allow: - schema: - type: string - default: "GET,POST,OPTIONS" - /subscriptions/{id}: - get: - description: Retrieve one or multiple subscriptions - parameters: - - in: "path" - name: "id" - description: identifier of a specific subscription - required: false - schema: - type: string - responses: - "200": - description: OK - content: - application/json: - schema: - $ref: "#/components/schemas/Subscription" - "404": - description: Subscription not found - put: - description: Update a subscription - parameters: - - in: "path" - name: "id" - required: true - schema: - type: string - description: The id of an existing subscription - - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/Subscription" - responses: - "200": - description: OK - content: - application/json: - schema: - $ref: "#/components/schemas/Subscription" - "400": - description: Invalid or malformed request - "404": - description: Subscription not found - delete: - description: Delete a subscription - parameters: - - in: "path" - name: "id" - required: true - schema: - type: string - description: The id of an existing subscription - responses: - "200": - description: Successfully deleted - "404": - description: Subscription not found - options: - description: Discover supported features and methods for this endpoint - parameters: - - in: "path" - name: "id" - description: identifier of a specific subscription - required: false - schema: - type: string - responses: - "200": - description: OK - headers: - Allow: - schema: - type: string - default: "GET,PUT,POST,DELETE,OPTIONS" -components: - schemas: - SubscriptionRequest: - properties: - protocol: - type: string - enum: ["HTTP", "MQTT3", "MQTT5", "AMQP", "NATS", "KAFKA"] - description: REQUIRED. Identifier of a delivery protocol. - example: "HTTP" - protocolsettings: - type: object - anyOf: - - $ref: "#/components/schemas/HTTPSettings" - - $ref: "#/components/schemas/MQTTSettings" - - $ref: "#/components/schemas/AMQPSettings" - - $ref: "#/components/schemas/NATSSettings" - - $ref: "#/components/schemas/ApacheKafkaSettings" - description: OPTIONAL. A set of settings specific to the selected delivery protocol provider. - sink: - type: string - format: url - description: REQUIRED. The address to which events shall be delivered using the selected protocol. - example: "https://endpoint.example.com/webhook" - filter: - $ref: "#/components/schemas/Filter" - required: - - protocol - - protocolsettings - - sink - Subscription: - properties: - id: - type: string - description: REQUIRED. The unique identifier of the subscription in the scope of the subscription manager. - example: 1119920371 - protocol: - type: string - enum: ["HTTP", "MQTT3", "MQTT5", "AMQP", "NATS", "KAFKA"] - description: REQUIRED. Identifier of a delivery protocol. - example: "HTTP" - protocolsettings: - type: object - anyOf: - - $ref: "#/components/schemas/HTTPSettings" - - $ref: "#/components/schemas/MQTTSettings" - - $ref: "#/components/schemas/AMQPSettings" - - $ref: "#/components/schemas/NATSSettings" - - $ref: "#/components/schemas/ApacheKafkaSettings" - description: OPTIONAL. A set of settings specific to the selected delivery protocol provider. - sink: - type: string - format: url - description: REQUIRED. The address to which events shall be delivered using the selected protocol. - example: "https://endpoint.example.com/webhook" - filter: - $ref: "#/components/schemas/Filter" - required: - - id - - protocol - Filter: - properties: - dialect: - type: string - description: Filter dialect - example: "simple" - default: "simple" - conditions: - type: array - description: Filter conditions - items: - type: object - HTTPSettings: - properties: - headers: - type: object - method: - type: string - MQTTSettings: - properties: - topicname: - type: string - qos: - type: integer - format: int32 - retain: - type: boolean - expiry: - type: integer - format: int32 - userproperties: - type: object - required: - - topicname - AMQPSettings: - properties: - address: - type: string - linkname: - type: string - sendersettlementmode: - type: string - enum: ["settled", "unsettled"] - linkproperties: - type: object - ApacheKafkaSettings: - properties: - topicname: - type: string - partitionkeyextractor: - type: string - clientid: - type: string - ackmode: - type: integer - required: - - topicname - NATSSettings: - properties: - subject: - type: string - required: - - subject diff --git a/subscriptions-api.md b/subscriptions-api.md deleted file mode 100644 index bcdc8d0f4..000000000 --- a/subscriptions-api.md +++ /dev/null @@ -1,705 +0,0 @@ -# CNCF CloudEvents – Subscriptions API - Version 0.1-wip - -## Abstract - -This specification defines mechanisms, including an API definition, for CNCF -CloudEvents event consumers to subscribe to events originating from event -producers on behalf of event sources. The software entity handling these -subscriptions and responsible for distributing events is abstractly referred to -as a "subscription manager". - -## Status of this document - -This document is a working draft. - -## 1. Introduction - -A subscription manager responsible for a specific set of events can reside -immediately at or near the event producer or it can reside in some middleware -infrastructure. This document does not formalize the relationship between the -original event producer and the subscription manager, and how the subscription -manager obtains the events it distributes to subscribers. - -This document also does not formalize the relationship between a specific set of -events and the subscription manager. An event producer that produces multiple -different types of events can offer one subscription manager for all events or a -subscription manager for each type of event, or any other combination. An event -producer can also offer up the same set of events for subscription at multiple -concurrent subscription managers. Regardless of relationship between the event -producer(s) and the subscription manager(s), the advertisement of the -subscription offers are published in a CloudEvents Discovery service. - -As with the core CloudEvents specification, the goal of this specification is to -reuse mechanisms based on existing standards and conventions where such exist -and only introduce new mechanisms where needed. - -Therefore, this specification not only defines a new subscription management API -for certain use-cases, but also refers to existing mechanisms available in the -specifications of transport protocols for which CloudEvents bindings exist. - -For instance, introducing and mandating a CloudEvents-specific subscription -mechanism for MQTT would only complicate implementations while not providing any -obvious advantage. Using any of the referred native subscription mechanisms of -the respective transport protocols is therefore within the scope and in -compliance with this specification. - -## 2. 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](https://tools.ietf.org/html/rfc2119). - -### Terminology - -This specification uses the following terms: - -#### Source - -An event source is a logical entity in a system on behalf of which events are -produced based on occurrences. - -#### Producer - -The entity producing the event. The event might reflect an occurrence on a -source elsewhere in the system. The producer is the concrete entity that creates -and sends the event related to an occurrence. - -#### Intermediary - -An "intermediary" (also referred to as middleware) receives an event for the -purpose of forwarding it to the next receiver, which might be another -intermediary or a consumer. A typical task for an intermediary is to route the -event to receivers based on the information in the event context. - -#### Consumer - -An entity receiving and processing events. Consumers might receive events from -producers directly or via intermediaries. A consumer might listen and wait for -events to be delivered to it or it might actively solicit them from the producer -or intermediary. - -#### Subscription - -A relationship established between a consumer and a producer or an intermediary. -The subscription reflects the consumer's interest in receiving events and -describes the method for how to deliver those events. - -#### Subscription Manager - -An entity, defined in this specification, that manages the lifecycle of a -subscription on behalf of an event consumer and that distributes events to -registered consumers. - -## 3. Event Subscriptions - -This specification defines mechanisms for CNCF CloudEvents event consumers to -subscribe to events originating from producers on behalf of event sources. The -software entity handling these subscriptions and responsible for distributing -events is abstractly referred to as a "subscription manager". - -A compliant CloudEvents subscription manager MUST support at least one of the -transport protocols referenced in this specification and it MUST implement the -subscription mechanism referred to or defined in this specification. - -In some cases, the event producer MAY delegate the role of the subscription -manager to some intermediary, in which case produced events are made available -to the intermediary, and the intermediary's subscription manager determines who -receives copies of the published events. In other cases, the event producer MAY -take on the subscription manager role by itself. - -In this specification, we distinguish two styles of relationships between an -event consumer and a subscription manager, whereby the key differentiator is how -the event delivery channel to the consumer is initiated: - -- Subscriptions with consumer-solicited delivery ("pull"-style) are configured - on the subscription manager for delivering events through a communication - channel (like an AMQP link or a MQTT connection) initiated by the consumer and - connecting to the subscription manager. These kinds of subscriptions are - typically offered by messaging or eventing middleware and their lifetime might - be bounded by the lifetime of the communication channel. - -- Subscriptions with subscription-manager-initiated delivery ("push"-style) are - configured on the subscription manager for delivering events through a - communication channel that the subscription manager initiates when events are - available for delivery on the subscription. The configuration of such a - subscription MUST contain all information needed for the subscription manager - to select a transport protocol, establish the desired communication channel, - and deliver the event(s). - -An end-to-end solution using CloudEvents might use only one of these styles or a -combination of those. - -For instance, the solution might use an MQTT broker to handle delivery of events -into connected devices that connect into the broker and subscribe on a -particular MQTT topic, which acts as the subscription manager in the sense of -this specification ("pull"-style). The events that ought to be shared with the -connected devices might however originate elsewhere in the overall solution, and -some event router middleware's subscription manager might therefore be -configured to initiate delivery of events ("push"-style) into the given MQTT -broker topic whenever such events are available. - -### 3.1 Native Subscription Management Mechanisms - -MQTT, AMQP, NATS, and Apache Kafka are protocols with a formal CloudEvents -binding that have native mechanisms filling the role of a subscription manager. - -Using any of these subscription management mechanisms ought to allow an -application to claim conformance with this specification. More specifically, an -application that uses an MQTT or AMQP message broker as its middleware component -ought be able to use the native capabilities of those protocols to subscribe to -CloudEvents event streams without requiring CloudEvents Subscription -API-specific mechanisms or extensions. The conformance section in this document -formally enumerates the requirements. - -_The descriptions of the protocol subscription mechanisms in this section are -non-normative. Please refer to the protocol specifications or documentation for -normative definitions._ - -#### 3.1.1. MQTT 3.x/5.x - -The MQTT 3.x/5.x protocol has a native "SUBSCRIBE" (and matching "UNSUBSCRIBE") -operation, which allows a consumer to solicit messages matching a pattern -against the MQTT broker's topic path hierarchy. - -Once an MQTT consumer has issued one or multiple SUBSCRIBE requests, matching -events for any of the MQTT session's active subscription are delivered by the -broker to the consumer without requiring further interactions. Depending on the -quality-of-service (QoS) level of the subscription, individual deliveries might -have to be acknowledged by the consumer. - -The lifetime of a subscription is bounded by lifetime of the MQTT session. - -Events are published using the "PUBLISH" operation on a path into the topic -hierarchy, and all current subscriptions whose topic filters match the path -receive a message. - -The operations are normatively defined in the -[MQTT 3.1.1](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.html) and -[MQTT 5.0](http://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html) -specifications. - -#### 3.1.2. AMQP 1.0 - -The AMQP 1.0 protocol has a built-in subscription mechanism. - -When an AMQP container establishes a receive-role link to another container, it -can specify a "distribution-mode" on the link source in the other container. If -the distribution mode is "copy", each such established link receives a copy of -the message stream available at the distribution node. If the distribution mode -is "move", messages are exclusively owned by the link and are removed from the -source when the transfer is settled successfully. - -Supporting the "copy" mode, is OPTIONAL for the underlying implementation of the -broker - -The link source can also be configured with filters. The AMQP core specification -does not define concrete filter types, but the AMQP Filter Expressions 1.0 -extension specification and the Apache Qpid project's filter definitions do. - -#### 3.1.3. NATS - -The NATS protocol has a native subscribe operation "SUB" (and matching "UNSUB"), -which allows a client to solicit a stream of messages that match a given subject -or a wildcard. - -Events are published using the "PUB" operation with a subject name that is then -matched against the existing subscriptions. - -#### 3.1.4. Apache Kafka - -Apache Kafka allows consumers to fetch events stored in topic partitions once or -multiple times. - -While Apache Kafka does not have a server-side subscribe operation and also does -not provide filtering capabilities, it allows the fetching client to fully -control from which offset in the partition's log store events are being read -from. This allows multiple parties to retrieve the same set of events from the -stream. - -The management of the subscription and selecting which events are being fetched -and dispatched into the application lies completely with the consumer in the -Apache Kafka case. - -#### 3.1.5. HTTP - -HTTP does not have a built-in subscription mechanism that allows for -establishing a flow of events similar to the aforementioned protocols. HTTP -allows for modeling pull-style retrieval of events from a store and, with HTTP/2 -"server push", even for continuous delivery an event stream triggered by a -initial request, but for event delivery scenarios, these techniques are -applications of HTTP rather than inherent features of HTTP per-se. - -### 3.2. Subscription Manager API - -The subscription manager API defines a subscription object and a protocol for -creating, updating and deleting subscriptions on a subscription manager. - -The subscription object describes the consumer's interest in events and defines -the delivery method. The protocol allows to configure subscriptions on the -subscription manager. Especially in case of subscription manager initiated -("push"-style) delivery, the protocol is used to express the consumer's interest -to the subscription manager before the subscription manager can initiate -delivery. - -The protocol used to configure the subscription manager is decoupled from the -delivery protocol, meaning that an application can configure a push delivery -into an AMQP destination using an API call initiated over HTTP. - -A subscription manager that natively exists in a middleware implementation might -also have a separate CloudEvents subscription manager API endpoint -implementation. If such a separate API endpoint exists and creating -subscriptions is not feasible on such a separate API endpoint, the respective -operation might not be available. For instance, creating an MQTT subscription is -not feasible from outside an MQTT connection, but an existing subscription might -be enumerable through a subscription collection and deleting the subscription -from the collection might terminate it. - -#### 3.2.1. Subscription Object - -A subscription manager manages a collection of subscriptions. The upper limit on -how many subscriptions are supported is implementation specific. - -Each subscription is represented by an object that has the following properties: - -- **id** (string) – REQUIRED. The unique identifier of the subscription in the - scope of the subscription manager. This value MUST be unique within the scope - of the subscription manager and MUST be immutable. -- **protocol** (string) - REQUIRED. Identifier of a delivery protocol. Because - of WebSocket tunneling options for AMQP, MQTT and other protocols, the URI - scheme is not sufficient to identify the protocol. The protocols with existing - CloudEvents bindings are identified as "AMQP", "MQTT3", "MQTT5", "HTTP", - "KAFKA", and "NATS". An implementation MAY add support for further protocols. -- **protocolsettings** (map) - OPTIONAL. A set of settings specific to the - selected delivery protocol provider. Options for those settings are listed in - the following subsection. An implementation MAY offer more options. Examples - for such settings are credentials, which generally vary by transport, rate - limits and retry policies, or the QoS mode for MQTT. See the - [Protocol Settings](#322-protocol-settings) section for further details. -- **sink** (URI) - REQUIRED. The address to which events SHALL be delivered - using the selected protocol. The format of the address MUST be valid for the - selected protocol or one of the protocol's own transport bindings (e.g. AMQP - over WebSockets). -- **filters** - OPTIONAL. One or more filter expressions of a particular filter - dialect that evaluates to true or false and that determines whether an - instance of a CloudEvent will be delivered to the subscription's sink. If a - filter expression evaluates to false, the event MUST NOT be sent to the sink. - If the expression evaluates to true, the event MUST be attempted to be - delivered. Support for particular filter dialects might vary across different - subscription managers. If a filter dialect is specified in a subscription that - is unsupported by the subscription manager, creation or updates of the - subscription MUST be rejected with an error. See the - [Filters](#323-filters) section for further details. -- **config** (map) - OPTIONAL. A set of key/value pairs that modify the - configuation of the subscription. The `key` MUST be ones of the - `subscriptionconfig` keys specified in the Discovery Endpoint Service - definition. The `value` MUST conform to the data type specified by the - value in the `subscriptionconfig` entry for the `key`. - -Below is an example JSON serialization of a susbcription: - -```JSON -{ - "id": "sub-193-18365", - "protocol": "HTTP", - "protocolsettings": { - "method": "POST" - }, - "sink": "http://example.com/event-processor", - "filters": [{ - "dialect": "basic", - "type": "prefix", - "property": "type", - "value": "com.example" - }], - "config": { - "data": "hello", - "interval": 5 - } -} -``` - -#### 3.2.2 Protocol Settings - -This section enumerates protocol-specific delivery options for the -protocol-settings map, including default values where necessary. - -##### 3.2.2.1. HTTP - -For HTTP, the following settings properties SHOULD be supported by all -implementations. - -- **headers** (map) – OPTIONAL. A set of key/value pairs that is copied into the - HTTP request as custom headers. -- **method** (string) – OPTIONAL. The HTTP method to use for sending the - message. This defaults to POST if not set. - -##### 3.2.2.2. MQTT - -All implementations that support MQTT MUST support the _topicname_ settings. All -other settings SHOULD be supported. - -- **topicname** (string) – REQUIRED. The name of the MQTT topic to publish to. -- **qos** (integer) – OPTIONAL. MQTT quality of service (QoS) level: 0 (at most - once), 1 (at least once), or 2 (exactly once). This defaults to 1 if not set. -- **retain** (boolean) – OPTIONAL. MQTT retain flag: true/false. This defaults - to false if not set. -- **expiry** (integer) – OPTIONAL. MQTT expiry interval, in seconds. This value - has no default value and the message will not expire if the setting is absent. - This setting only applies to MQTT 5.0. -- **userproperties** (map) – OPTIONAL. A set of key/value pairs that are copied - into the MQTT PUBLISH packet's user property section. This setting only - applies to MQTT 5.0. - -##### 3.2.2.3. AMQP - -For AMQP, the address property MUST be supported by all implementations and -other settings properties SHOULD be supported by all implementations. - -- **address** (string) – OPTIONAL. The link target node in the AMQP container - identified by the sink URI, if not expressed in the sink URI's path portion. -- **linkname** (string) – OPTIONAL. Name to use for the AMQP link. If not set, a - random link name is used. -- **sendersettlementmode** (string) – OPTIONAL. Allows to control the sender's - settlement mode, which determines whether transfers are performed "settled" - (without acknowledgement) or "unsettled" (with acknowledgement). Default value - is unsettled. -- **linkproperties** (map) – OPTIONAL. A set of key/value pairs that are copied - into link properties for the send link. - -##### 3.2.2.4. Apache Kafka - -All implementations that support Apache Kafka MUST support the _topicname_ -settings. All other settings SHOULD be supported. - -- **topicname** (string) - REQUIRED. The name of the Kafka topic to publish to. -- **partitionkeyextractor** (string) - OPTIONAL. A partition key extractor - expression per the CloudEvents Kafka transport binding specification. -- **clientid** (string) -- **acks** (string) - -##### 3.2.2.5. NATS - -- **subject** (string) - REQUIRED. The name of the NATS subject to publish to. - -#### 3.2.3 Filters - -Filters allow for subscriptions to specify that only a subset of events -are to be delivered to the sink based on a set of criteria. The `filters` -property in a subscription is an array of filter expressions that are logically -combined with an implicit "AND" operator. This means the filter criteria -MUST evaluate to true for every filter expression in the array in order -for an event to be delivered to the target sink. - -If any of the filter expressions evaluate to false, the event MUST NOT be -sent to the sink. If all of the filter expressions evaluare to true, the -event MUST be attempted to be delivered. - -Each filter expression includes the specification of a `dialect` that -defines the type of filter and the set of additional properties that are -allowed within the filter expression. If a filter dialect is specified in a -subscription that is unsupported by the subscription manager, creation or -update of the subscription MUST be rejected with an error. - -##### 3.2.3.1 Filter Dialects - -The filter expression language supported by an event producer is indicated by -its dialect. This is intended to allow for flexibility, extensibility and to -allow for a variety of filter dialects without enumerating them all in this -specification or predicting what filtering needs every system will have in the -future. This specification defines a `basic` dialect, which all -implementations MUST support. - -The dialect for a particular filter is indicated by specifying the `dialect` -in a `filter` expression. The value of this is a URI-reference encoded unique -identifier for the filter dialect. Subscriptions specifying a `filter` -MUST specify a dialect. All other properties are dependent on the -dialect being used. - -##### 3.2.3.2. "basic" filter dialect - -The `basic` filter dialect is intended to support the most common filtering -use cases: - -- `exact` match where the filter condition and an attribute value match exactly. -- `prefix` match where the filter condition is a prefix of the attribute value. -- `suffix` match where the filter condition is a suffix of the attribute value. - -This filter dialect is intentionally constrained to these filter types, since -filtering has a potentially significant impact on the baseline performance of -all implementations. In cases where more filter types or different expression -languages are desired, further dialects can be introduced as extensions. - -Extension dialects will have varying support across event producers. It is up to -the subscriber and producer to negotiate which filter dialects can be used -within a given subscription. - -Each `basic` filter expression is defined with the following properties: - -- `type` (string) - REQUIRED. Value MUST be one of the following: - `prefix`, `suffix`, exact`. -- `property` (string) - REQUIRED. The CloudEvents attribute - (including extensions) to match the value indicated by the `value` property - against. -- `value` (string) - REQUIRED. The value to match the CloudEvents attribute - against. This expression is a string and matches are executed against the - string representation of the attribute value. - -Note: the string comparisions MUST be case sensitive and take into account all -whitespace - including leading and trailing whitespace. - -###### 3.2.3.1.1. Example: Prefix match - -This filter will select events only with the event type having the prefix of -"com.example". - -```JSON -{ - "filters": [{ - "dialect": "basic", - "type": "prefix", - "property": "type", - "value": "com.example" - }] -} -``` - -###### 3.2.3.1.2. Example: Suffix match - -This filter will select events only with the event subject having the suffix of -".jpg". - -```JSON -{ - "filters": [{ - "dialect": "basic", - "type": "suffix", - "property": "subject", - "value": ".jpg" - }] -} -``` - -###### 3.2.3.1.3. Example: Exact match - -This filter will select events only with the event type equal to -"com.example.my_event". - -```JSON -{ - "filters": [{ - "dialect": "basic", - "type": "exact", - "property": "type", - "value": "com.example.my_event" - }] -} -``` - -###### 3.2.3.1.4. Example: Exact match and suffix match - -This filter will select events only with the event type equal to -"com.example.my_event" AND the event subject having the suffix of ".jpg". - -```JSON -{ - "filters": [ - { - "dialect": "basic", - "type": "exact", - "property": "type", - "value": "com.example.my_event" - }, - { - "dialect": "basic", - "type": "suffix", - "property": "subject", - "value": ".jpg" - } - ] -} -``` - -#### 3.2.4. API Operations - -This section enumerates the abstract operations that are defined for -subscription managers. The following sections define bindings of these abstract -operations to concrete protocols. - -The operations are `Create`, `Retrieve`, `Query`, `Update`, and `Delete`. Of -those, only the `Retrieve` operation is REQUIRED for conformance. The `Create` -and `Delete` operations SHOULD be implemented. `Query` and `Update` are -OPTIONAL. - -Protocol bindings SHOULD provide a discovery mechanism for which operations are -supported. - -#### 3.2.4.1. Creating a subscription - -The **Create** operation SHOULD be supported by compliant Event Producers. It -creates a new Subscription. The client proposes a subscription object which MUST -contain all REQUIRED properties with the exception of the `ID` property, which -will be defined by the subscription manager. The subscription manager then -realizes the subscription and returns a subscription object that also contains -all OPTIONAL properties for which default values have been applied. - -Parameters: - -- subscription (subscription) - REQUIRED. Proposed subscription object. - -Result: - -- subscription (subscription) - REQUIRED. Realized subscription object. - -Errors: - -- **ok** - the operation succeeded -- **conflict** - a subscription with the given _id_ already exists -- **invalid** - the proposed subscription object contains invalid information - -Protocol bindings MAY map the Create operation such that the proposed _id_ is -ignored and the subscription manager assigns one instead. - -#### 3.2.4.2. Retrieving a Subscription - -The **Retrieve** operation MUST be supported by compliant Event Producers. It -returns the specification of the identified subscription. - -Parameters: - -- id (string) - REQUIRED. Identifier of the subscription. - -Result: - -- subscription (subscription) - REQUIRED. Subscription object. - -Errors: - -- **ok** - the operation succeeded -- **notfound** - a subscription with the given _id_ already exists - -#### 3.2.4.3. Querying for a list of Subscriptions - -The **Query** operation SHOULD be supported by compliant Event Producers. It -allows to query the list of subscriptions on the subscription manager associated -with or otherwise visible to the party making the request. If supported, it MUST -be supported at the same endpoint as the **Create** subscription operation. - -Parameters: - -- none - -Result: - -- subscription (list of subscription) - REQUIRED. List of subscription objects - -Errors: - -- **ok** - the operation succeeded and returned results -- **nocontent** - the operation succeeded and returned no results - -Protocol bindings and implementations of such bindings MAY add custom filter -constraints and pagination arguments as parameters. A request without filtering -constraints SHOULD return all available subscriptions associated with or -otherwise visible to the party making the request. - -#### 3.2.4.4. Updating a Subscription - -The Update operation MAY be supported by compliant Event Producers. To request -the update of a Subscription, the client submits a proposed subscription object -whose _id_ MUST match an existing subscription. All other properties MAY differ -from the original subscription. The subscription manager then updates the -subscription and returns a subscription object that also contains all OPTIONAL -properties for which default values have been applied. - -Parameters: - -- subscription (subscription) - REQUIRED. Proposed subscription object. - -Result: - -- subscription (subscription) - REQUIRED. Realized subscription object. - -Protocol bindings MAY map the Update and the Create operation into a composite -"upsert" operation that creates a new subscription if one with the given _id_ -does not exist. In this case, the operation is \*_Create_ and follows that -operation's rules. - -#### 3.2.8. Deleting a Subscription - -The **Delete** operation SHOULD be supported by compliant Event Producers. It -returns the specification of the identified subscription. - -Parameters: - -- id (string) - REQUIRED. Identifier of the subscription. - -Result: - -- subscription (subscription) - REQUIRED. Subscription object. - -Errors: - -- **ok** - the operation succeeded -- **notfound** - a subscription with the given _id_ already exists - -### 3.3. HTTP Binding for the Subscription API - -(TBD) This will be a straightforward mapping of the described API to a basic -HTTP CRUD API using PUT, POST, GET, DELETE, and OPTIONS. - -Placeholders: -``` -Create: -POST /subscriptions -Content-Type: application/json - -{ - "protocol": "...", - "protocolsettings": { ... } - "sink": "...", - "filters": [{ - "dialect": "...", - "type": "...", - "property": "...", - "value": "..." - }], - "config": { ... } -} - -Note: no ID in the request - -Retrieve: -GET /subscriptions/{id} - -Delete: -DELETE /subscriptions/{id} - -Update: -PUT /subscriptions/{id} -Content-Type: application/json - -{ - "protocol": "...", - "protocolsettings": { ... } - "sink": "...", - "filters": [{ - "dialect": "...", - "type": "...", - "property": "...", - "value": "i..." - }], - "config": { ... } -} - -``` - -### 3.4. AMQP Binding for the Subscription API - -(TBD) This will be a set of bi-directional exchanges for the respective -operations. - -## 4. Conformance - -(TBD) Conformance clauses. diff --git a/websockets-protocol-binding.md b/websockets-protocol-binding.md index 093569824..c3df8a783 100644 --- a/websockets-protocol-binding.md +++ b/websockets-protocol-binding.md @@ -5,10 +5,6 @@ The WebSockets Protocol Binding for CloudEvents defines how to establish and use full-duplex CloudEvents streams using [WebSockets][rfc6455]. -## Status of this document - -This document is a working draft. - ## Table of Contents 1. [Introduction](#1-introduction)