# xRegistry Service - Version 1.0-rc2
## Abstract
This specification defines an extensible model for managing metadata
registries. The metadata artifacts can be for any purpose, such as schemas
or message definitions, and the registry provides both "document" and "API"
projections of the data to enable their discovery for end-user consumption
or automation and tooling usage.
## Table of Contents
- [Overview](#overview)
- [Notations and Terminology](#notations-and-terminology)
- [Notational Conventions](#notational-conventions)
- [Terminology](#terminology)
- [Registry Design](#registry-design)
- [Registry Entity](#design-registry-entity)
- [Group Entity](#design-group-entity)
- [Resource and Version Entities](#design-resource-and-version-entities)
- [Registry Views](#design-registry-views)
- [No-Code Servers](#design-no-code-servers)
- [Protocol Bindings](#design-protocol-bindings)
- [JSON Serialization](#design-json-serialization)
- [Data Retrieval Issues](#design-data-retrieval-issues)
- [Importing Data](#design-importing-data)
- [JSON `$schema` keyword](#design-json-schema-keyword)
- [Implicit Creation of Parent Entities](#design-implicit-creation-of-parent-entities)
- [Events](#design-events)
- [Registry Model](#registry-model)
- [Implementation Customizations](#implementation-customizations)
- [Attributes and Extensions](#attributes-and-extensions)
- [Registry Collections](#registry-collections)
- [Registry Capabilities](#registry-capabilities)
- [Group Entity](#group-entity)
- [Resource Entity](#resource-entity)
- [Creating or Updating Resources and
Versions](#creating-or-updating-resources-and-versions)
- [Version Entity](#version-entity)
- [Request Flags](#request-flags)
- [Binary Flag](#binary-flag)
- [Collections Flag](#collections-flag)
- [Doc Flag](#doc-flag)
- [Epoch Flag](#epoch-flag)
- [Filter Flag](#filter-flag)
- [IgnoreDefaultVersionID Flag](#ignoredefaultversionid-flag)
- [IgnoreDefaultVersionSticky Flag](#ignoredefaultversionsticky-flag)
- [IgnoreEpoch Flag](#ignoreepoch-flag)
- [IgnoreReadOnly Flag](#ignorereadonly-flag)
- [Inline Flag](#inline-flag)
- [SetDefaultVersionID Flag](#setdefaultversionid-flag)
- [Sort Flag](#sort-flag)
- [SpecVersion Flag](#specversion-flag)
- [Error Processing](#error-processing)
## Overview
A Registry consists of two main types of entities: Resources and Groups of
such Resources.
Resources typically represent the main data of interest in the Registry, while
Groups, as the name implies, allow related Resources to be arranged together
under a single collection. Resources can, optionally, also be versioned if
needed.
This specification defines a set of common metadata that can appear on both
Resources and Groups, and allows for domain-specific extensions to be added.
Additionally, this specification defines a common interaction pattern to
manage, view and discover the entities in the Registry with the goal of
providing an interoperable framework that will enable common tooling and
automation.
See the [Registry Design](#registry-design) section for a more complete
discussion of the xRegistry concepts.
The following 3 diagrams show (from left to right):
1 - The core concepts of the Registry in its most abstract form.
2 - A Registry concept model with multiple types of Groups/Resources.
3 - A concrete sample usage of Registry that includes the use of an attribute
on "Message Definition" that is a reference to a "Schema" document - all
within the same Registry instance.
The Registry, while typically exposed as a "service", is also intended to
support exporting its data as a "document" that can then be used independently
from the service. For example, the document can be checked into a code
repository or used as input for tooling. To enable a seamless transition
between the "document" and "API" views of the data, the specification ensures
a consistent mapping between the two:
This specification is meant to be a framework from which additional
specifications can be defined that expose model-specific Resources and
metadata. See the [Endpoint](../endpoint/spec.md) and
[Schema](../schema/spec.md) extension specifications as examples.
Additionally, this specification defines the core model and semantics of
xRegistry, while secondary specifications (such as
[xRegistry HTTP Binding](./http.md)) will discuss how to expose them in a
protocol-specific way.
## 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).
For clarity, OPTIONAL attributes (specification-defined and extensions) are
OPTIONAL for clients to use, but the servers' responsibility will vary.
Server-unknown extension attributes MUST be silently stored in the backing
datastore. Specification-defined, and server-known extension attributes, MUST
generate an error if the corresponding feature is not supported or enabled.
However, as with all attributes, if accepting the attribute results in a
bad state (such as exceeding a size limit, or results in a security issue),
then the server MAY choose to reject the request.
In the pseudo JSON format snippets `?` means the preceding item is OPTIONAL,
`*` means the preceding item MAY appear zero or more times, and `+` means the
preceding item MUST appear at least once. The presence of the `#` character
means the remaining portion of the line is a comment. Whitespace characters in
the JSON snippets are used for readability and are not normative.
Use of `<...>` the notation indicates a substitutable value where that is
meant to be replaced with a runtime situational-specific value as defined by
the word/phrase in the angled brackets. For example `` would be expected
to be replaced by the "name" of the item being discussed.
Use of `` and `` are meant to represent the singular name of a
Group and Resource type used, while `` and `` are the plural
name of those respective types. Use of `` represents the singular
name of the entity referenced. For example, for a "schema document" Resource
type where its plural name is defined as `schemas` and its singular name is
defined as `schema`, the `` value would be `schema`.
Additionally, the following acronyms are defined:
- `` is the `id` of a Group.
- `` is the `id` of a Resource.
- `` is the `versionid` of a Version of a Resource.
The following are used to denote an instance of one of the associated data
types (see [Attributes and Extensions](#attributes-and-extensions) for more
information about each data type):
- ``
- ``
- ``
- ``
- ``
- ``
- ``
- ``
- ``
- ``
- ``
- ``
- ``
- ``
- ``
- ``
- ``
- ``
- `` - one of the allowable data type names (MUST be in lower case)
listed in [Attributes and Extensions](#attributes-and-extensions)
- `` - an instance of one of the above data types
### Terminology
This specification defines the following terms:
#### Aspect
The term "attribute" can be used in many different contexts. In order to avoid
any potential confusion, "attributes" that are part of an
[xRegistry model](./model.md) definition are referred to as "aspects" as a
way to indicate that they are also often mapped to "features" of the
specification.
#### Group
Groups, as the name implies, allow related Resources to be arranged together
under a single collection - the Group. The reason for the grouping is not
defined by this specification, so the owners of the Registry MAY choose to
define (or enforce) any pattern they wish. In this sense, a Group is similar
to a "directory" on a filesystem.
An additional common use for Groups is for access control. Managing access
control on individual Resources, while possible, might be cumbersome, so
moving it up to the Group could be a more manageable, and user-friendly,
implementation choice.
#### Registry
A server-side implementation of this specification. Typically, the
implementation would include model-specific Groups, Resources and extension
attributes.
There is also a "Registry" entity which acts as the root of an xRegistry
instance, under which all Groups will reside. The Registry entity itself has
metadata associated with it.
#### Resource
Resources, typically, represent the main data of interest for the Registry. In
the filesystem analogy, these would be the "files". Each Resource MUST exist
under a single Group and, similar to Groups, have a set of Registry metadata.
However, unlike a Group, which only has Registry metadata, each Resource MAY
also have a secondary domain-specific "document" associated with it. For
example, a "schema" Resource might have a "schema document" as its "document".
This specification places no restriction on the type of content stored in the
Resource's document. Additionally, Resources (unlike Groups) MAY be versioned.
#### Version
A Version is an instance of a Resource that represents a particular state of
the Resource. Each Version of a Resource has its own set of xRegistry metadata
and possibly a domain-specific document associated with it. Each Resource MUST
have at least one Version associated with it.
Clients MAY interact with specific Versions or with the Resource itself, which
is equivalent to interacting with the Resource's "default" Version. While in
many cases the "default" Version will be the "newest" Version, this
specification allows for the "default" Version to be explicitly chosen and
unaffected as other Versions are added or removed.
If versioning is not important for the use case in which the Resource is used,
the default Version can be evolved without creating new ones.
This specification places no requirements on the lifecycle of Versions.
Implementations, or users of the Registry, determine when new Versions are
created, as opposed to updating existing Versions, and how many Versions are
allowed per Resource type.
## Registry Design
As discussed in the [Overview](#overview) section, an xRegistry consists of
two main entities related to the data being managed: Groups and Resources.
However, there are other concepts that make up the overall design and this
section will cover them all in more detail.
Each entity type defined within the Registry will have both a plural and
singular "type name" associated with it. For example, a Schema Resource
might have `schemas` as its "plural" type name and `schema` as its "singular"
type name. This enables the appropriate name to be used based on the context
in which it appears. In the Schema Resource example, `schemas` would be used
when a collection of Schemas is referenced, such as in URLs (e.g.
`.../schemas/myschema`), while `schema` would be used when a single Schema
is referenced (e.g. as part of its ID name: `schemaid`).
### Design: Registry Entity
An xRegistry instance, or a "Registry", can be thought of as a single rooted
tree of entities as shown in the "xRegistry Core Spec" diagram in the
[Overview](#overview) section. At the root is the Registry entity itself.
This entity is also meant to serve a few other key purposes:
- Expose high-level metadata about the Registry itself, such as its creation
and modified timestamps, name, link to additional documentation, etc.
- The set of [capabilities](#registry-capabilities) (features) that are
supported. For example, does this Registry support filtering of query
results?
- The domain-specific ["model"](./model.md#registry-model) that defines the
types of entities being managed by the Registry. For example, the model
might define a Group called `schemagroups` that has `schemas` as the
Resources within those Groups.
### Design: Group Entity
Below the Registry, Groups serve as logical collections of related Resources.
Each Group exposes the same high-level metadata as the Registry and supports
user-defined extensions attributes. In practice, Group often act as lightweight
"directories" for Resources, but they can also encapsulate rich,
domain-specific data via custom extensions (see [Endpoint](../endpoint/spec.md)
as an example).
### Design: Resource and Version Entities
A Resource entity in the Registry holds one or more Versions of metadata, and
optionally a domain-specific document. If a Resource holds multiple Versions,
those can be organized with
[compatibility policies](#compatibility-attribute) and[
lineage](#ancestor-attribute). Each Resource
always has a default Version corresponding to one of the available Versions
that is indirectly accessed when interacting with the Resource. All held
Versions can be accessed directly through the Versions collection.
#### Document Resources vs Metadata-Only Resources
Each Version of a Resource MAY be defined to have a "domain-specific" document
associated with it. These documents MAY be stored within the Version as an
attribute, or MAY be stored external to the Version and a URL to its location
will be stored within the Version instead. This model design choice is
specified via the
[`hasdocument` aspect](./model.md#groupsstringresourcesstringhasdocument)
of the Resource type's model definition.
Typically, the domain-specific document will be used when a pre-existing
document definition already exists and an xRegistry is used as the
mechanism to expose those documents in a consistent and interoperable way.
For example, the [Schema Registry](../schema/spec.md) only has a few
xRegistry Resource extension attributes defined because most of the data of
interest will be in the Schema documents associated with the Resources.
See [Resource Metadata vs Resource
Document](#resource-metadata-vs-resource-document) for more information.
### Design: Registry Views
This specification is designed such that clients can choose how they want the
data from a server to be returned. There are three main "views" that clients
can choose from:
- Single Document View
In this view, clients retrieving all (or part) of the Registry hierarchy
as a single document. In this case, nested (or child) entities MAY be
"inlined" into the retrieved document such that the need for secondary
interactions with the server is reduced.
This is often used for cases where the documents are stored in some
document storage system (e.g. Github), or as input into local tooling that
expects all of the relevant data to be stored locally on disk.
See the [HTTP `GET /export` operation](./http.md#get-export) for one way to
generate this view.
- API View
In this view, it is assumed that the client is interested in an interactive
discovery and retrieval of the Registry data. Most often clients will "walk"
the hierarchy of entities by following the references (links) provided
within the serialization of each entity to find the data of interest. As
such, in this view, each entity is, by default, retrieved from the server
via independent "read" operations.
A query without the use of the [Doc flag](#doc-flag), is an example of how
to generate this view.
- Multiple Document View
This is a variant of the "API view". In situations where the Registry data
is stored as independent files either on disk, or in some other object
storage system, the client might want to avoid the duplication of
information that, by default, a server might generate. For example, they
might not want the default Version's metadata to be visible in the owning
Resource's serialization.
Documents generated in this view are often stored locally such that they can
be managed independently for use in tooling or stored in some source-code
control system (e.g. Github) to minimize the number of conflicting edits
between users in a very fluid environment.
A query with the use of the [Doc flag](#doc-flag), is an example of how to
generate this view.
This specification provides the mechanisms to allow for users to choose the
best "view" for their needs. Regardless of the view, the design allows for
the retrieved data to then be used as input into an xRegistry server.
### Design: No-Code Servers
One of the goals of xRegistry is to be as broadly supported as possible.
Requiring all xRegistry endpoints to support the full range of APIs of a
particular protocol binding might not be feasible in all cases. In particular,
there might be cases where someone wishes to host a read-only xRegistry server
and therefore the write operations or advanced features (such as inlining or
filtering) might not be available. In those cases, simple file serving HTTP
servers, such as blob stores, ought to be sufficient, and requiring support
for flag/query parameters and other advanced features (that could require
custom code) might not always be possible.
To support these simple (no-code) scenarios, this specification (and the
protocol binding specifications) are written such that the support for the
various operations and features (e.g. [request flags](#request-flags)) will
typically be marked as OPTIONAL (often with a "SHOULD" RFC2119 key word).
However, it is STRONGLY RECOMMENDED that full servers support as many of the
operations and features/flags when possible to enable a better user
experience, and increase interoperability.
See the [HTTP Binding](./http.md#no-code-servers) for more details on how
this might manifest itself for HTTP servers.
### Design: Protocol Bindings
This specification defines the core model and semantics of an xRegistry
server implementation without regard to what protocol might be used to
interact with it.
In general, all interactions with a server SHOULD be OPTIONAL and dictated by
the specific needs of the environment in which it is being used. However, it is
STRONGLY RECOMMENDED that servers support the "read" operations, and in
particular the ability to retrieve the "capabilities" and "model" such that
tooling can then dynamically discover the remaining data within the Registry.
Implementations MAY choose to incorporate authentication and/or authorization
mechanisms as needed, but those are out of scope for this specification.
### Design: JSON Serialization
This specification defines the JSON serialization of the xRegistry entities.
Alternative serialization formats MAY be defined.
For easy reference, the JSON serialization of a Registry adheres to this form:
```yaml
{
"specversion": "",
"registryid": "",
"self": "",
"shortself": "", ?
"xid": "",
"epoch": ,
"name": "", ?
"description": "", ?
"documentation": "", ?
"icon": "", ?
"labels": { "": "" * }, ?
"createdat": "",
"modifiedat": "",
"capabilities": { # Supported capabilities/options
"apis": [ "/capabilities", "/export", "/model" ],
"flags": [ # Query parameters
"binary",? "collections",? "doc",? "epoch",? "filter",?
"ignoredefaultversionid",? "ignoredefaultversionsticky",? "ignoreepoch",?
"ignorereadonly",? "inline", ? "setdefaultversionid",? "sort",?
"specversion",?
"" *
],
"mutable": [ # What is mutable in the Registry
"capabilities",? "entities",? "model",? ""*
], ?
"pagination": , ?
"shortself": , ?
"specversions": [ "1.0-rc2", ""* ], ?
"stickyversions": , ?
"versionmodes": [ "manual", "createdat",? "modifiedat",? "semver",?
""* ],
"": ... * # Extension capabilities
}, ?
"model": { # Full model. Only if inlined
"description": "", ?
"documentation": "", ?
"labels": { "": "" * }, ?
"attributes": { # Registry-level attributes/extensions
"": { # Attribute name (case-sensitive)
"name": "", # Same as attribute's key
"type": "", # string, decimal, array, object, ...
"target": "", ? # If "type" is "xid" or "url"
"namecharset": "", ? # If "type" is "object"
"description": "", ?
"enum": [ * ], ? # Array of scalars of type `"type"`
"strict": , ? # Just "enum" values? Default=true
"readonly": , ? # From client's POV. Default=false
"immutable": , ? # Once set, can't change. Default=false
"required": , ? # Default=false
"default": , ? # Scalar attribute's default value
"attributes": { ... }, ? # If "type" above is object
"item": { # If "type" above is map,array
"type": "", ? # map value type, or array type
"target": "", ? # If this item "type" is xid/url
"namecharset": "", ? # If this item "type" is object
"attributes": { ... }, ? # If this item "type" is object
"item": { ... } ? # If this item "type" is map,array
} ?
"ifvalues": { # If "type" is scalar
"": { # Possible attribute value
"siblingattributes": { ... } # See "attributes" above
} *
} ?
} *
},
"groups": {
"": { # Key=plural name, e.g. "endpoints"
"plural": "", # e.g. "endpoints"
"singular": "", # e.g. "endpoint"
"description": "", ?
"documentation": "", ?
"icon": "", ?
"labels": { "": "" * }, ?
"modelversion": "", ? # Version of the group model
"compatiblewith": "", ? # Statement of compatibility
"attributes": { ... }, ? # Group-level attributes/extensions
"ximportresources": [ "", * ], ? # Include these Resources
"resources": {
"": { # Key=plural name, e.g. "messages"
"plural": "", # e.g. "messages"
"singular": "", # e.g. "message"
"description": "", ?
"documentation": "", ?
"icon": "", ?
"labels": { "": "" * }, ?
"modelversion": "", ? # Version of the resource model
"compatiblewith": "", ? # Statement of compatibility
"maxversions": , ? # Num Vers(>=0). Default=0(unlimited)
"setversionid": , ? # vid settable? Default=true
"setdefaultversionsticky": , ? # sticky settable? Default=true
"hasdocument": , ? # Has separate document. Default=true
"versionmode": "", ? # 'ancestor' processing algorithm
"singleversionroot": , ? # Default=false"
"typemap": , ? # contenttype mappings
"attributes": { ... }, ? # Version attributes/extensions
"resourceattributes": { ... }, ? # Resource attributes/extensions
"metaattributes": { ... } ? # Meta attributes/extensions
} *
} ?
} *
} ?
}, ?
"modelsource": { ... }, ? # Input model, if inlined
# Repeat for each Group type
"url": "", # e.g. "endpointsurl"
"count": , # e.g. "endpointscount"
"": { # Only if inlined
"": { # Key=the Group id
"id": "", # The Group ID
"self": "",
"shortself": "", ?
"xid": "",
"epoch": ,
"name": "", ?
"description": "", ?
"documentation": "", ?
"icon": "", ?
"labels": { "": "" * }, ?
"createdat": "",
"modifiedat": "",
"deprecated": {
"effective": "", ?
"removal": "", ?
"alternative": "", ?
"documentation": ""?
}, ?
# Repeat for each Resource type in the Group
"url": "", # e.g. "messagesurl"
"count": , # e.g. "messagescount"
"": { # Only if inlined
"": { # The Resource id
"id": "",
"versionid": "", # Default Version's ID
"self": "", # Resource URL, not Version
"shortself": "", ?
"xid": "", # Resource XID, not Version
"epoch": , # Start of default Ver attrs
"name": "", ?
"isdefault": true,
"description": "", ?
"documentation": "", ?
"icon": "", ?
"labels": { "": "" * }, ?
"createdat": "",
"modifiedat": "",
"ancestor": "", # Ancestor's versionid
"contenttype": ", ? # Add default Ver extensions
"url": "", ? # If not local
"": ... Resource document ..., ? # If local & inlined & JSON
"base64": "", ? # If local & inlined & ~JSON
# End of default Ver attrs
# Resource-level helper attributes
"metaurl": "",
"meta": { # Only if inlined
"id": "",
"self": "", # URL to "meta" object
"shortself": "", ?
"xid": "",
"xref": "", ? # xid of linked Resource
"epoch": , # Resource's epoch
"createdat": "", # Resource's
"modifiedat": "", # Resource's
"readonly": , # Default=false
"compatibility": "", # Default=none
"compatibilityauthority": "", ? # Default=external
"deprecated": {
"effective": "", ?
"removal": "", ?
"alternative": "", ?
"documentation": ""?
}, ?
"defaultversionid": "",
"defaultversionurl": "",
"defaultversionsticky": # Default=false
}, ?
"versionsurl": "",
"versionscount": ,
"versions": { # Only if inlined
"": { # The Version's versionid
"id": "", # The Resource id
"versionid": "", # The Version id
"self": "", # Version URL
"shortself": "", ?
"xid": "",
"epoch": , # Version's epoch
"name": "", ?
"isdefault": , # Default=false
"description": "", ?
"documentation": "", ?
"icon": "", ?
"labels": { "": "" * }, ?
"createdat": "",
"modifiedat": "",
"ancestor": "", # Ancestor's versionid
"contenttype": "", ?
"url": "", ? # If not local
"": ... Resource document ..., ? # If inlined & JSON
"base64": "" ? # If inlined & ~JSON
} *
} ?
} *
} ?
} *
} ?
}
```
### Design: Data Retrieval Issues
In general, if a server is unable to retrieve all of the data intended to be
sent in a response, then an error
([data_retrieval_error](./spec.md#data_retrieval_error)) MUST be generated and
the request rejected without any changes being made. However, it is permissible
for a server to attempt some creative processing. For example, if while
processing a query the server can only retrieve half of the entities to be
returned at the current point in time, then it could return those with an
indication of there being more (via use of a pagination type of specification).
Then during the next query request it could return the remainder of the
data - or an error if it is still not available to retrieve the data. Note
that if an entity is to be sent, then it MUST be serialized in its entirety
(all attributes, and requested child entities) or an error MUST be generated.
### Design: Importing Data
There might be situations where someone will do a query to retrieve data
from a Registry, and then do an update operation to a Registry with that data.
Depending on the use case, they might not want some of the retrieved data
to be applied during the update. For example, they might not want the
`epoch` validation checking to occur. Rather than forcing the user to edit
the data to remove the potentially problematic attributes, a client MAY use
one of the `ignore*` [request flags](#request-flags) to ignore some of the
data in the incoming request.
### Design: JSON `$schema` keyword
Any JSON xRegistry metadata message that represents a single entity (i.e. not
a map) MAY include a top-level "$schema" attribute that points to a JSON Schema
document that describes the message contents. These notations can be used or
ignored by receivers of these messages. There is no requirement for
implementations of this specification to persist these values, to include them
in responses or to use this information.
### Design: Implicit Creation of Parent Entities
To reduce the number of interactions needed when creating an entity, all
nonexisting parent entities specified as part of `` to the entity MUST
be implicitly created. Each of those entities MUST be created with the
appropriate `id` specified in the ``. If any of those
entities have REQUIRED attributes, then they cannot be implicitly created, and
would need to be created directly. This also means that the creation of the
original entity would fail and generate an error
([required_attribute_missing](./spec.md#required_attribute_missing)) for the
appropriate parent entity.
### Design: Events
xRegistry defines a set of events that SHOULD be generated when changes are
made to the entities within a Registry. See the [xRegistry Events](./events.md)
specification for more information.
---
In summary, xRegistry is designed to be a tree of entities that, along with
its extensible metadata model, can support categorizing, managing and exposing
a wide range of metadata allowing for a dynamically discoverable, yet
interoperable, programmatic access via what might otherwise be a
domain-specific set of APIs.
The following sections will define the technical details of those xRegistry
entities.
## Registry Model
This section defines the common Registry metadata model, its semantics and
protocol-independent processing rules. It is an explicit goal for this
specification that metadata can be created and managed in files in a file
system, for instance in a Git repository, and also managed in a Registry
service that implements an xRegistry protocol binding, such as the
[HTTP Binding](./http.md).
For instance, during development of a module, the metadata about the events
raised by the modules will best be managed in a file that resides alongside the
module's source code. When the module is ready to be deployed into a concrete
system, the metadata about the events will be registered in a Registry service
along with the endpoints where those events can be subscribed to or consumed
from, and which allows discovery of the endpoints and all related metadata by
other systems at runtime.
Therefore, the hierarchical structure of the
[Registry Model](./model.md#registry-model) is defined in such a way that it
can be represented in one or more files, including but not limited to JSON, or
via the entity graph of an API.
In the remainder of this specification, in particular when defining the
attributes of the Registry entities, the terms "document view" or "API view"
will be used to indicate whether the serialization of the entity in a response
is meant for use as a stand-alone document or as part of an API message
exchange. The most notable differences are that in document view:
- References (e.g. URLs) between entities within responses will use relative
references rather than absolute ones. This is an indication to tooling that
the entity in question can be found locally and does not need an additional
API call to retrieve it.
- Duplicate data will be removed. In particular, Resources will not include
attributes from the "default" Version as part of their serialization. This is
done with the assumption the inlined/nested `versions` collection will most
likely include the "default" Version, so duplicating that information is
redundant.
Most of these differences are to make it easier for tooling to use the
"stand-alone" document view of the Registry. For a complete list of the
differences in "document view" see the [Doc Flag](#doc-flag) flag.
Note that "document view" only refers to response messages when the
[Doc Flag](#doc-flag) is used. There is no "document view" concept for
requests. However, "document view" responses are designed such that they can
be used in request messages as they still convey the same information as an
"API view" response.
Unless otherwise stated in a protocol binding specification, if the processing
of a request fails (even during the generation of the response) then an error
MUST be generated and the entire request MUST be undone. See the
[Error Processing](#error-processing) section for more information.
### Implementation Customizations
This specification does not address many of the details that would need to
be added for a live instance of a service; as often times these aspects are
very specific to the environment in which the service is running. For example,
this specification does not address authentication or authorization levels of
users, nor how to securely protect the APIs, clients or servers, from attacks.
Implementations of this specification are expected to add these various
features as needed.
Additionally, implementations MAY choose to customize the data and behavior on
a per-user basis as needed. For example, the following non-exhaustive list of
customizations might be implemented:
- User-specific capabilities - e.g. admin users might see more features than
a non-admin user.
- User-specific attribute aspects - e.g. admin users might be able to
edit a `readonly` Resource. Note that in this case the Resource's `readonly`
aspect will likely appear with a value of `true` even for an admin users.
The goal of these customizations is not to allow for implementations to
violate the specification, rather it is to allow for real-world requirements
to be met while maintaining the interoperability goals of the specification.
Implementations are encouraged to contact the xRegistry community if it is
unclear if certain customizations would violate the specification.
Implementations MAY (but are NOT REQUIRED) to validate cross-entity
constraints that might be violated due to changes in a referenced entity.
For example, [Endpoint's `envelope`](../endpoint/spec.md#envelope) attribute
mandates that all Messages in that Endpoint use that same `envelope` value.
One of those Messages might have a `basemessage` value that points to a
Message that breaks that rule. For a variety of reasons (e.g. authorization
constraints), server implementations might not be able to verify this
constraint. Likewise, the same situation might occur via the use of `xref`.
Clients need to be aware of these possibilities.
### Attributes and Extensions
#### Data Types
Unless otherwise noted, all attributes and extensions MUST be mutable and MUST
be one of the following data types:
- `any` - an attribute of this type is one whose type is not known in advance
and MUST be one of the concrete types listed here.
- `array` - an ordered list of values that are all of the same data type - one
of the types listed here.
- Some serializations, such as JSON, allow for a `null` value to
appear in an array (e.g. `[ null, 2, 3 ]` in an array of integers). In
these cases, while it is valid for the serialization being used, it is
not valid for xRegistry since `null` is not a valid `integer`. Meaning,
the serialization of an array that is syntactically valid for the
format being used, but not semantically valid per the
[xRegistry model](./model.md#registry-model) definition, MUST NOT be
accepted and MUST generate an error ([invalid_data](#invalid_data)).
- `boolean` - case-sensitive `true` or `false`.
- `decimal` - number (integer or floating point).
- `integer` - signed integer.
- `map` - set of key/value pairs, where the key MUST be of type string. The
value MUST be of one of the types defined here.
- Each key MUST:
- Be a non-empty string consisting of only lowercase alphanumeric
characters (`[a-z0-9]`), `:`, `-`, `_` or a `.`.
- Be no longer than 63 characters.
- Start with an alphanumeric character.
- Be unique within the scope of this map.
- `object` - a nested entity made up of a set of attributes of these data
types.
- `string` - sequence of Unicode characters.
- `timestamp` - an [RFC3339](https://tools.ietf.org/html/rfc3339) timestamp.
Use of a `time-zone` notation is RECOMMENDED. All timestamps returned by
a server MUST be normalized to UTC to allow for easy (and consistent)
comparisons.
- `uinteger` - unsigned integer.
- `uri` - a URI as defined in [RFC 3986](https://tools.ietf.org/html/rfc3986).
Note that it can be absolute or relative.
- `uriabsolute` - absolute URI as defined in [RFC 3986 Section
4.3](https://tools.ietf.org/html/rfc3986#section-4.3).
- `urirelative` - relative URI as defined in [RFC 3986 Section
4.2](https://tools.ietf.org/html/rfc3986#section-4.2).
- `uritemplate` - URI Template as defined in
[RFC 6570 Section 3.2.1](https://tools.ietf.org/html/rfc6570#section-3.2.1).
- `url` - an absolute URL (`urlabsolute`) or relative URL (`urlrelative`).
- `urlabsolute` - an absolute URI as defined in [RFC 3986 Section
4.3](https://datatracker.ietf.org/doc/html/rfc3986#section-4.3) with the
added "URL" constraints mentioned in [RFC 3986 Section
1.1.3](https://datatracker.ietf.org/doc/html/rfc3986#section-1.1.3).
- `urlrelative` - a relative URI as defined in [RFC 3986 Section
4.2](https://datatracker.ietf.org/doc/html/rfc3986#section-4.2) with the
added "URL" constraints mentioned in [RFC 3986 Section
1.1.3](https://datatracker.ietf.org/doc/html/rfc3986#section-1.1.3).
- `xid` - MUST be a URL (xid) reference to another entity defined within
the Registry. The actual entity attribute value MAY reference a non-existing
entity (i.e. be a dangling pointer), but the syntax MUST reference a
defined/valid type in the Registry. This type of attribute is used in
place of `url` so that the Registry can do "type checking" to ensure the
value references the correct type of Registry entity. See the definition of
the [`target` model attribute](./model.md#attributesstringtarget) for more
information. Its value MUST start with a `/`.
- `xidtype` - MUST be a URL reference to an
[xRegistry model](./model.md#registry-model) type. The reference MUST point
to one of: the Registry itself (`/`), a Group type (`/`), a
Resource type (`//`) or Version type for a Resource
(`///versions`). Its value MUST reference a
defined/valid type in the Registry. It MUST use the plural names of the
referenced types, if it is a Group, Resource or Version.
The 6 variants of URI/URL are provided to allow for strict type adherence
when needed. However, for attributes that are simply "pointers" that might
in practice be any of those 6 types, it is RECOMMENDED that `uri` be used.
Attributes that are defined to be relative URIs or URLs MUST state what they
are relative to and any constraints on their values, if any. How, or where,
this is specified is out of scope of this specification.
The "scalar" data types are:
- `boolean`
- `decimal`
- `integer`
- `string`,
- `timestamp`
- `uinteger`
- `uri`
- `uriabsolute`
- `urirelative`
- `uritemplate`,
- `url`
- `urlabsolute`
- `urlrelative`
- `xid`
- `xidtype`
Note that `any` is not a "scalar" type as its runtime value could be a complex
type such as `object`.
#### Attributes
All attributes (specification-defined and extensions) MUST adhere to the
following rules:
- Their names MUST be between 1 and 63 characters in length.
- Their names MUST only contain lowercase alphanumeric characters or an
underscore (`[a-z0-9_]`) and MUST NOT start with a digit (`[0-9]`).
- For string attributes, an empty string is a valid value and MUST NOT be
treated the same as an attribute with no value (or absence of the attribute).
- For scalar attributes, the string serialization of the attribute name and
its value MUST NOT exceed 4096 bytes. This is to ensure that it can appear
in an HTTP header without exceeding implementation limits (see
[RFC6265/Limits](https://datatracker.ietf.org/doc/html/rfc6265#section-6.1)).
In cases where larger amounts of data are needed, it is RECOMMENDED that
an attribute (of type URL) be defined that references a separate
document. For example, `documentation` can be considered such an attribute
for `description`.
- If an attribute's type is not fully defined (i.e. it is defined as an `any`
type) but a concrete type is needed to successfully process it, then the
server SHOULD default it to type `string`. For example, if an extension is
defined as a map whose values are of type `any`, but it appears in an HTTP
header with a value of `5` (and it is not clear if this would be an integer
or a string), if the server needs to convert this to a concrete data type,
then `string` is the default choice.
- There might be cases when it is not possible to know whether a field name is
part of an object (in which case it is an "attribute name"), or is part of
a map (in which case it is a "key name"). This decision would impact
verification of the field since key names allow for a superset of the
characters allowed for attribute names. This will only happen when the
`any` type has been used higher-up in the model. As a result, any portion of
the entity that appears under the scope of an `any` typed attribute or
map-value is NOT REQUIRED to be validated except to ensure that the syntax
is valid per the rules of the serialization format used.
- Attribute instances that have no value (and have no default value defined)
are semantically equivalent to having a value of `null` or not being present
at all, and for the sake of brevity, SHOULD NOT be serialized as part of its
owning entity in server responses. Likewise, specifying them with a value of
`null` in client requests SHOULD be reserved for cases where the client
needs to indicate a request to delete that attribute value rather than to
leave the attribute untouched (absent in the request), such as when `PATCH`
is used in the [HTTP Binding Protocol](./http.md).
#### Extensions
Implementations of this specification MAY define additional (extension)
attributes. However, they MUST adhere to the following rules:
- All extension attributes that appear in the serialization of an entity MUST
conform to the model definition of the Registry. This means that they MUST
satisfy at least one of the following:
- Be explicitly defined (by name) as part of the model.
- Be permitted due to the presence of the `*` (undefined) extension attribute
name at that level in the model.
- Be permitted due to the presence of an `any` type for one of its parent
attribute definitions.
- They MUST NOT conflict with the name of an attribute defined by this
specification, including the `*` and `*` attributes
that are implicitly defined. Note that if a Resource type has the
[`hasdocument` aspect](./model.md#groupsstringresourcesstringhasdocument)
set the `false` then this rule does not apply for
the `*` attributes as those attributes are not implicitly defined
for that Resource type.
- It is RECOMMENDED that extension attributes on different entities do not
use the same name unless they have the exact same semantic meaning.
- It is STRONGLY RECOMMENDED that they be named in such a way as to avoid
potential conflicts with future xRegistry specification-defined attributes.
For example, use of a model (or domain) specific prefix could be used to help
avoid possible future conflicts.
#### Common Attributes
The following attributes are used by one or more entities defined by this
specification. They are defined here once rather than repeating them throughout
the specification.
For easy reference, the JSON serialization of these attributes adheres to this
form:
- `"id": ""`
- `"self": ""`
- `"shortself": ""`
- `"xid": ""`
- `"epoch": `
- `"name": ""`
- `"description": ""`
- `"documentation": ""`
- `"icon": ""`
- `"labels": { "": "" * }`
- `"createdat": ""`
- `"modifiedat": ""`
- `"deprecated": ""`
The definition of each attribute is defined below:
##### `id` (`id`) Attribute
- Type: String
- Description: An immutable unique identifier of the owning entity.
The actual name of this attribute will vary based on the entity it
identifies. For example, a `schema` Resource would use an attribute name
of `schemaid`. This attribute MUST be named `registryid` for the Registry
itself, and MUST be named `versionid` for all Version entities.
- Constraints:
- REQUIRED.
- MUST be immutable.
- MUST be a non-empty string consisting of [RFC3986 `unreserved`
characters](https://datatracker.ietf.org/doc/html/rfc3986#section-2.3)
(ALPHA / DIGIT / `-` / `.` / `_` / `~`), `:` or `@`, MUST start with
ALPHA, DIGIT or `_` and MUST be between 1 and 128 characters in length.
- MUST be unique (case-insensitively) within the scope of the entity's
parent.
- This attribute MUST be treated as case-sensitive for look-up purposes.
For example, an HTTP request URL to an entity with the wrong case for its
`id` MUST be treated as "not found".
- In cases where an entity's `id` is specified outside of the
serialization of the entity (e.g. part of a request URL, or a map key),
its presence within the serialization of the entity is OPTIONAL. However,
if present, it MUST be the same as any other specification of the
`id` outside of the entity, and it MUST be the same as the
entity's existing `id` if one exists, otherwise an error
([mismatched_id](#mismatched_id)) MUST be generated.
- Examples:
- `a183e0a9-abf8-4763-99bc-e6b7fcc9544b`
- `myEntity`
- `myEntity.example.com`
While `id` can be something like a UUID, when possible, it is
RECOMMENDED that it be human friendly as these values will often appear in
user-facing situations such as URLs or as command-line parameters.
Additionally, In cases where [`name`](#name-attribute) is absent, the
`id` might be used as the display name.
Note, since `id` is immutable, in order to change its value, a new
entity would need to be created with the new `id` that is a deep-copy
of the existing entity. Then the existing entity would be deleted.
##### `self` Attribute
- Type: URL
- Description: A server-generated unique URL referencing the current entity.
- Each entity in the Registry MUST have a unique `self` URL value that
locates the entity in the Registry hierarchy and from where the entity can
be retrieved.
- When specified as an absolute URL, it MUST be based on the URL of the
Registry root appended with the hierarchy path of the Registry
entities/collections leading to the entity (its `xid` value).
In the case of pointing to an entity that has a `id` attribute,
the URL MUST be a combination of the URL used to retrieve its parent
appended with its `id` value.
- API View Constraints:
- REQUIRED.
- MUST be immutable.
- MUST be a non-empty absolute URL based on the URL of the Registry.
- When serializing Resources or Versions, whose Resource type's
[`hasdocument` aspect](./model.md#groupsstringresourcesstringhasdocument)
is set to `true`, then (based on the protocol binding being used) this
attribute might need to include some indicator that the xRegistry metadata
is to be returned rather than the domain-specific document. See the
[Registry Entity](./http.md#registry-entity) section for how this might
manifest itself for HTTP.
- MUST be a read-only attribute.
- Document View Constraints:
- REQUIRED.
- MUST be immutable.
- MUST be a relative URL of the form `#JSON-POINTER` where the `JSON-POINTER`
locates this entity within the current document. See [Doc Flag](#doc-flag)
for more information.
- This URL MUST NOT include any indicator signifying the entity's xRegistry
metadata rather than its domain-specific document (e.g. `$details` in the
[HTTP binding](./http.md) case).
- Examples:
- `https://example.com/registry/schemagroups/g1/schemas/s1$details` (API View)
- `https://example.com/registry/endpoints/ep1` (API View)
- `#/endpoints/ep1` (Document View)
##### `shortself` Attribute
- Type: URL
- Description: A server-generated unique absolute URL for an entity. This
attribute MUST be an alternative URL for the owning entity's `self`
attribute. The intention is that `shortself` SHOULD be shorter in length
than `self` such that it MAY be used when the length of the URL referencing
the owning entity is important. For example, in cases where the size of a
message referencing this entity needs to be as small as possible.
This specification makes no statement as to how this URL is constructed,
to which host/path it references, or whether a request to this URL
will directly perform the desired operation or whether it returns a
redirect to the full `self` URL requiring the client to resend the request.
If an entity is deleted and then a new entity is created that results in
the same `self` URL, this specification does not mandate that the same
`shorturl` be generated, but it MAY do so.
This attribute MUST only appear in the serialization if the `shortself`
capability is enabled. However, if this capability is enabled, then disabled,
and then re-enabled, the `shortself` values MUST retain their original
values. In this sense, implementations might create a `shortself` that is
known for the lifetime of the entity and the capability controls whether
the attribute is serialized or not.
- Constraints:
- REQUIRED if the `shortself` capability is enabled.
- MUST be immutable for the lifetime of the entity.
- MUST NOT appear in responses if the `shortself` capability is disabled.
- MUST be unique across all entities in the Registry.
- MUST be a non-empty absolute URL referencing the same entity as the `self`
URL, either directly or indirectly via a protocol-specific redirect.
- MUST be a read-only attribute.
- Examples:
- `https://tinyurl.com/xreg123` redirects to
`https://example.com/endpoints/e1`
##### `xid` Attribute
- Type: XID
- Description: An immutable server-generated unique identifier of the entity.
Unlike `id`, which is unique within the scope of its parent, `xid`
MUST be unique across the entire Registry, and as such is defined to be a
relative URL from the root of the Registry. This value MUST be the same as
the `` portion of its `self` URL, after the Registry's base URL,
without any protocol-specific xRegistry suffix (e.g. `$details` in the HTTP
case). Unlike some other relative URIs, `xid` values MUST NOT be shortened
based on the incoming request's URL; `xid`s are always relative to the root
path of the Registry.
This attribute is provided as a convenience for users who need a reference
to the entity without running the risk of incorrectly extracting it from
the `self` URL, which might be ambiguous at times. The `xid` value is also
meant to be used as an `xref` value (see [Cross Referencing
Resources](#cross-referencing-resources), or as the value for attributes of
type `xid` (see [`target` model
attribute](./model.md#attributesstringtarget)).
- Constraints:
- REQUIRED.
- MUST be immutable.
- MUST be a non-empty relative URL to the current entity.
- MUST be of the form:
`/[/[//[/meta | /versions/]]]`.
- MUST start with the `/` character.
- MUST be a read-only attribute.
- Examples:
- `/endpoints/ep1`
##### `epoch` Attribute
- Type: Unsigned Integer
- Description: A numeric value used to determine whether an entity has been
modified. Each time the associated entity is updated, this value MUST be
set to a new value that is greater than the current one. This attribute
MUST be updated for every update operation, even if no attributes were
explicitly updated, such as a "patch" type of operation when no attributes
are specified. This then acts like a `touch` type of operation.
During a single write operation, whether this value is incremented for
each modified attribute of the entity, or updated just once for the entire
operation is an implementation choice.
During a create operation, if this attribute is present in the request, then
it MUST be silently ignored by the server.
During an update, or delete, operation, if this attribute is present in the
request, then an error
([mismatched_epoch](#mismatched_epoch)) MUST be generated if the
request includes a non-null value that differs from the existing value.
This allows for the detection of concurrent, but conflicting, updates to the
same entity to be detected. A value of `null` MUST be treated the same as a
request with no `epoch` attribute at all, in which case a check MUST NOT
be performed.
If an entity has a nested xRegistry collection, its `epoch` value MUST
be updated each time an entity in that collection is added or removed.
However, its `epoch` value MUST NOT be updated solely due to modifications of
an existing entity in the collection.
Note that Resource entities have an `epoch` value that is serialized
as part of its [`meta` entity](#meta-entity). Its value is only incremented
when the `meta` attributes are updated, or when a Version is added, or
removed, from that Resource.
- Constraints:
- REQUIRED.
- MUST be a read-only attribute.
- MUST be an unsigned integer equal to or greater than zero.
- MUST increase in value each time the entity is updated.
- Examples:
- `0`, `1`, `2`, `3`
##### `name` Attribute
- Type: String
- Description: A human-readable name of the entity. This is often used
as the "display name" for an entity rather than the `id` especially
when the `id` might be something that isn't human friendly, like a
UUID. In cases where `name` is absent, the `id` value SHOULD be
displayed in its place.
This specification places no uniqueness constraints on this attribute.
This means that two sibling entities MAY have the same value. Therefore,
this value MUST NOT be used for unique identification purposes, the
`id` MUST be used instead.
Note that implementations MAY choose to enforce additional constraints on
this value. For example, they could mandate that `id` and `name` be
the same value. Or, it could mandate that `name` be unique within the scope
of a parent entity. How any such requirement is shared with all parties is
out of scope of this specification.
- Constraints:
- OPTIONAL.
- If present, MUST be non-empty.
- Examples:
- `My Cool Endpoint`
##### `description` Attribute
- Type: String
- Description: A human-readable summary of the purpose of the entity.
- Constraints:
- OPTIONAL.
- Examples:
- `A queue of the sensor-generated messages`
##### `documentation` Attribute
- Type: URL
- Description: A URL to additional information about this entity.
This specification does not place any constraints on the data returned from
a query to this URL.
- Constraints:
- OPTIONAL.
- If present, MUST be a non-empty URL.
- MUST support retrieving the information via a query to this URL.
- Examples:
- `https://example.com/docs/myQueue`
##### `icon` Attribute
- Type: URL
- Description: A URL to a graphical icon for the owning entity.
- Constraints:
- OPTIONAL.
- If present, MUST be a non-empty URL.
- MUST be retrievable via a query to this URL.
- STRONGLY RECOMMENDED that the icon be in SVG or PNG format and square.
- Examples:
- `https://example.com/myRegistry.svg`
##### `labels` Attribute
- Type: Map of name/value string pairs
- Description: A mechanism in which additional metadata about the entity can
be stored without changing the model definition of the entity.
- Constraints:
- OPTIONAL.
- If present, MUST be a map of zero or more name/value string pairs. See
[Attributes and Extensions](#attributes-and-extensions) for more
information.
- Keys MUST be non-empty strings.
- Values MAY be empty strings.
- Examples:
- `"labels": { "owner": "John", "verified": "" }`
##### `createdat` Attribute
- Type: Timestamp
- Description: The date/time of when the entity was created.
- Constraints:
- REQUIRED.
- MUST be a [RFC3339](https://tools.ietf.org/html/rfc3339) timestamp.
- This specification places no restrictions on the value of this attribute,
nor on its value relative to its `modifiedat` value or the current
date/time. Implementations MAY choose to restrict its values if necessary.
- If present in a write operation request, the value MUST override any
existing value, however a value of `null` MUST use the current date/time
as the new value.
- When absent in an update request, any existing value MUST remain
unchanged, or if not already set, set to the current date/time.
- During the processing of a single request, all entities that have their
`createdat` or `modifiedat` attributes set to the current date/time MUST
use the same value in all cases.
- Examples:
- `2030-12-19T06:00:00Z`
##### `modifiedat` Attribute
- Type: Timestamp
- Description: The date/time of when the entity was last updated.
- Constraints:
- REQUIRED.
- MUST be a [RFC3339](https://tools.ietf.org/html/rfc3339) timestamp
representing the time when the entity was last updated.
- This specification places no restrictions on the value of this attribute,
nor on its value relative to its `createdat` value or the current
date/time. Implementations MAY choose to restrict its values if necessary.
- Any update operation (even one that does not change any attribute, such as
a "path" type of operation with no attributes provided), MUST update this
attribute. This then acts like a `touch` type of operation.
- Updates to an existing entity in an xRegistry collection MUST NOT cause an
update to its parent entity's `modifiedat` value. However, adding or
removing an entity from a nested xRegistry collection MUST update the
`modifiedat` value of the parent entity.
- If present in a write operation request, the following applies:
- If the request value is `null` or the same as the existing value, then
the current date/time MUST be used as its new value.
- If the request value is different than the existing value, then the
request value MUST be used as its new value.
- When absent in a write operation request, it MUST be set to the current
date/time.
- During the processing of a single request, all entities that have their
`createdat` or `modifiedat` attributes set to the current date/time MUST
use the same value in all cases.
- Examples:
- `2030-12-19T06:00:00Z`
##### `deprecated` Attribute
- Type: Object containing the following properties:
- `effective`
An OPTIONAL property indicating the time when the entity entered, or will
enter, a deprecated state. The date MAY be in the past or future. If this
property is not present the entity is already in a deprecated state.
If present, this MUST be an [RFC3339][rfc3339] timestamp.
- `removal`
An OPTIONAL property indicating the time when the entity MAY be removed.
The entity MUST NOT be removed before this time. If this property is not
present, the client cannot make any assumptions as to when the entity
might be removed. Note: as with most properties, this property is mutable.
If present, this MUST be an [RFC3339][rfc3339] timestamp and MUST NOT be
sooner than the `effective` time if present.
- `alternative`
An OPTIONAL property specifying the URL to an alternative entity the
client can consider as a replacement for this entity. There is no
guarantee that the referenced entity is an exact replacement, rather the
client is expected to investigate the entity to determine if it is
appropriate.
- `docs`
An OPTIONAL property specifying the URL to additional information about
the deprecation of the entity. This specification does not mandate any
particular format or information, however some possibilities include:
reasons for the deprecation or additional information about likely
alternative entities. The URL MUST support retrieval of the information
via a query.
Note that an implementation is not mandated to use this attribute in
advance of removing an entity, but is it RECOMMENDED that they do so.
This attribute can appear on Groups and Resources, however, this
specification makes no statement as to the relationship, or validity, of the
values of each with respect to how they might impact each other.
- Constraints:
- OPTIONAL
- Examples:
- `"deprecated": {}`
- ```
"deprecated": {
"removal": "2030-12-19T00:00:00Z",
"alternative": "https://example.com/entities-v2/myentity"
}
```
### Registry Collections
Registry collections (``, `` and `versions`) that are
defined by the [Registry Model](./model.md#registry-model) MUST be serialized
according to the rules defined in this section.
The serialization of a collection is done as 3 attributes and they MUST adhere
to their respective forms as follows:
```yaml
"url": "",
"count":