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 🔗

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 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 and Schema extension specifications as examples.

Additionally, this specification defines the core model and semantics of xRegistry, while secondary specifications (such as xRegistry HTTP Binding) 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.

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 <NAME> would be expected to be replaced by the "name" of the item being discussed.

Use of <GROUP> and <RESOURCE> are meant to represent the singular name of a Group and Resource type used, while <GROUPS> and <RESOURCES> are the plural name of those respective types. Use of <SINGULAR> 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 <SINGULAR> value would be schema.

Additionally, the following acronyms are defined:

The following are used to denote an instance of one of the associated data types (see Attributes and Extensions for more information about each data type):

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 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 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 section. At the root is the Registry entity itself. This entity is also meant to serve a few other key purposes:

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 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 and lineage. 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 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 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 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:

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) 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 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:

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

  "capabilities": {                     # Supported capabilities/options
    "apis": [ "/capabilities", "/export", "/model" ],
    "flags": [                          # Query parameters
      "binary",? "collections",? "doc",? "epoch",? "filter",?
      "ignoredefaultversionid",? "ignoredefaultversionsticky",? "ignoreepoch",?
      "ignorereadonly",?  "inline", ? "setdefaultversionid",?  "sort",?
      "specversion",?
      "<STRING>" *
    ],
    "mutable": [                        # What is mutable in the Registry
      "capabilities",? "entities",? "model",? "<STRING>"*
    ], ?
    "pagination": <BOOLEAN>, ?
    "shortself": <BOOLEAN>, ?
    "specversions": [ "1.0-rc2", "<STRING>"* ], ?
    "stickyversions": <BOOLEAN>, ?
    "versionmodes": [ "manual", "createdat",? "modifiedat",? "semver",?
      "<STRING>"* ],

    "<STRING>": ... *                   # Extension capabilities
  }, ?

  "model": {                            # Full model. Only if inlined
    "description": "<STRING>", ?
    "documentation": "<URL>", ?
    "labels": { "<STRING>": "<STRING>" * }, ?
    "attributes": {                     # Registry-level attributes/extensions
      "<STRING>": {                     # Attribute name (case-sensitive)
        "name": "<STRING>",             # Same as attribute's key
        "type": "<TYPE>",               # string, decimal, array, object, ...
        "target": "<XIDTYPE>", ?        # If "type" is "xid" or "url"
        "namecharset": "<STRING>", ?    # If "type" is "object"
        "description": "<STRING>", ?
        "enum": [ <VALUE> * ], ?        # Array of scalars of type `"type"`
        "strict": <BOOLEAN>, ?          # Just "enum" values? Default=true
        "readonly": <BOOLEAN>, ?        # From client's POV. Default=false
        "immutable": <BOOLEAN>, ?       # Once set, can't change. Default=false
        "required": <BOOLEAN>, ?        # Default=false
        "default": <VALUE>, ?           # Scalar attribute's default value

        "attributes": { ... }, ?        # If "type" above is object
        "item": {                       # If "type" above is map,array
          "type": "<TYPE>", ?           # map value type, or array type
          "target": "<XIDTYPE>", ?      # If this item "type" is xid/url
          "namecharset": "<STRING>", ?  # 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
          "<STRING>": {                 # Possible attribute value
            "siblingattributes": { ... } # See "attributes" above
          } *
        } ?
      } *
    },

    "groups": {
      "<STRING>": {                       # Key=plural name, e.g. "endpoints"
        "plural": "<STRING>",             # e.g. "endpoints"
        "singular": "<STRING>",           # e.g. "endpoint"
        "description": "<STRING>", ?
        "documentation": "<URL>", ?
        "icon": "<URL>", ?
        "labels": { "<STRING>": "<STRING>" * }, ?
        "modelversion": "<STRING>", ?     # Version of the group model
        "compatiblewith": "<URI>", ?      # Statement of compatibility
        "attributes": { ... }, ?          # Group-level attributes/extensions
        "ximportresources": [ "<XIDTYPE>", * ], ?   # Include these Resources

        "resources": {
          "<STRING>": {                   # Key=plural name, e.g. "messages"
            "plural": "<STRING>",         # e.g. "messages"
            "singular": "<STRING>",       # e.g. "message"
            "description": "<STRING>", ?
            "documentation": "<URL>", ?
            "icon": "<URL>", ?
            "labels": { "<STRING>": "<STRING>" * }, ?
            "modelversion": "<STRING>", ? # Version of the resource model
            "compatiblewith": "<URI>", ?  # Statement of compatibility
            "maxversions": <UINTEGER>, ?  # Num Vers(>=0). Default=0(unlimited)
            "setversionid": <BOOLEAN>, ?  # vid settable? Default=true
            "setdefaultversionsticky": <BOOLEAN>, ? # sticky settable? Default=true
            "hasdocument": <BOOLEAN>, ?   # Has separate document. Default=true
            "versionmode": "<STRING>", ?  # 'ancestor' processing algorithm
            "singleversionroot": <BOOLEAN>, ? # Default=false"
            "typemap": <MAP>, ?               # contenttype mappings
            "attributes": { ... }, ?          # Version attributes/extensions
            "resourceattributes": { ... }, ?  # Resource attributes/extensions
            "metaattributes": { ... } ?       # Meta attributes/extensions
          } *
        } ?
      } *
    } ?
  }, ?
  "modelsource": { ... }, ?                        # Input model, if inlined

  # Repeat for each Group type
  "<GROUPS>url": "<URL>",                          # e.g. "endpointsurl"
  "<GROUPS>count": <UINTEGER>,                     # e.g. "endpointscount"
  "<GROUPS>": {                                    # Only if inlined
    "<KEY>": {                                     # Key=the Group id
      "<GROUP>id": "<STRING>",                     # The Group ID
      "self": "<URL>",
      "shortself": "<URL>", ?
      "xid": "<XID>",
      "epoch": <UINTEGER>,
      "name": "<STRING>", ?
      "description": "<STRING>", ?
      "documentation": "<URL>", ?
      "icon": "<URL>", ?
      "labels": { "<STRING>": "<STRING>" * }, ?
      "createdat": "<TIMESTAMP>",
      "modifiedat": "<TIMESTAMP>",
      "deprecated": {
        "effective": "<TIMESTAMP>", ?
        "removal": "<TIMESTAMP>", ?
        "alternative": "<URL>", ?
        "documentation": "<URL>"?
      }, ?

      # Repeat for each Resource type in the Group
      "<RESOURCES>url": "<URL>",                   # e.g. "messagesurl"
      "<RESOURCES>count": <UINTEGER>,              # e.g. "messagescount"
      "<RESOURCES>": {                             # Only if inlined
        "<KEY>": {                                 # The Resource id
          "<RESOURCE>id": "<STRING>",
          "versionid": "<STRING>",                 # Default Version's ID
          "self": "<URL>",                         # Resource URL, not Version
          "shortself": "<URL>", ?
          "xid": "<XID>",                          # Resource XID, not Version
          "epoch": <UINTEGER>,                     # Start of default Ver attrs
          "name": "<STRING>", ?
          "isdefault": true,
          "description": "<STRING>", ?
          "documentation": "<URL>", ?
          "icon": "<URL>", ?
          "labels": { "<STRING>": "<STRING>" * }, ?
          "createdat": "<TIMESTAMP>",
          "modifiedat": "<TIMESTAMP>",
          "ancestor": "<STRING>",                  # Ancestor's versionid
          "contenttype": "<STRING>, ?              # Add default Ver extensions

          "<RESOURCE>url": "<URL>", ?              # If not local
          "<RESOURCE>": ... Resource document ..., ? # If local & inlined & JSON
          "<RESOURCE>base64": "<STRING>", ?        # If local & inlined & ~JSON
                                                   # End of default Ver attrs
          # Resource-level helper attributes
          "metaurl": "<URL>",
          "meta": {                                # Only if inlined
            "<RESOURCE>id": "<STRING>",
            "self": "<URL>",                       # URL to "meta" object
            "shortself": "<URL>", ?
            "xid": "<XID>",
            "xref": "<XID>", ?                     # xid of linked Resource
            "epoch": <UINTEGER>,                   # Resource's epoch
            "createdat": "<TIMESTAMP>",            # Resource's
            "modifiedat": "<TIMESTAMP>",           # Resource's
            "readonly": <BOOLEAN>,                 # Default=false
            "compatibility": "<STRING>",           # Default=none
            "compatibilityauthority": "<STRING>", ?  # Default=external
            "deprecated": {
              "effective": "<TIMESTAMP>", ?
              "removal": "<TIMESTAMP>", ?
              "alternative": "<URL>", ?
              "documentation": "<URL>"?
            }, ?

            "defaultversionid": "<STRING>",
            "defaultversionurl": "<URL>",
            "defaultversionsticky": <BOOLEAN>      # Default=false
          }, ?
          "versionsurl": "<URL>",
          "versionscount": <UINTEGER>,
          "versions": {                            # Only if inlined
            "<KEY>": {                             # The Version's versionid
              "<RESOURCE>id": "<STRING>",          # The Resource id
              "versionid": "<STRING>",             # The Version id
              "self": "<URL>",                     # Version URL
              "shortself": "<URL>", ?
              "xid": "<XID>",
              "epoch": <UINTEGER>,                 # Version's epoch
              "name": "<STRING>", ?
              "isdefault": <BOOLEAN>,              # Default=false
              "description": "<STRING>", ?
              "documentation": "<URL>", ?
              "icon": "<URL>", ?
              "labels": { "<STRING>": "<STRING>" * }, ?
              "createdat": "<TIMESTAMP>",
              "modifiedat": "<TIMESTAMP>",
              "ancestor": "<STRING>",              # Ancestor's versionid
              "contenttype": "<STRING>", ?

              "<RESOURCE>url": "<URL>", ?                # If not local
              "<RESOURCE>": ... Resource document ..., ? # If inlined & JSON
              "<RESOURCE>base64": "<STRING>" ?           # 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) 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 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 <PATH> to the entity MUST be implicitly created. Each of those entities MUST be created with the appropriate <SINGULAR>id specified in the <PATH>. 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) 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 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.

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 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:

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 flag.

Note that "document view" only refers to response messages when the 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 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:

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 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:

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:

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:

Extensions 🔗

Implementations of this specification MAY define additional (extension) attributes. However, they MUST adhere to the following rules:

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:

The definition of each attribute is defined below:

<SINGULAR>id (id) Attribute 🔗

While <SINGULAR>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 is absent, the <SINGULAR>id might be used as the display name.

Note, since <SINGULAR>id is immutable, in order to change its value, a new entity would need to be created with the new <SINGULAR>id that is a deep-copy of the existing entity. Then the existing entity would be deleted.

self Attribute 🔗
shortself Attribute 🔗
xid Attribute 🔗
epoch Attribute 🔗
name Attribute 🔗
description Attribute 🔗
documentation Attribute 🔗
icon Attribute 🔗
labels Attribute 🔗
createdat Attribute 🔗
modifiedat Attribute 🔗
deprecated Attribute 🔗

Registry Collections 🔗

Registry collections (<GROUPS>, <RESOURCES> and versions) that are defined by the 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:

"<COLLECTION>url": "<URL>",
"<COLLECTION>count": <UINTEGER>,
"<COLLECTION>": {
  # Map of entities in the collection, key is the "<SINGULAR>id" of the entity
}

Where:

When the <COLLECTION> attribute is expected to be present in the serialization, but the number of entities in the collection is zero, it MUST still be included as an empty map (e.g. {}).

The set of entities that are part of the <COLLECTION> attribute is a point-in-time view of the Registry. There is no guarantee that a future query to the <COLLECTION>url will return the exact same collection since the contents of the Registry might have changed. This specification makes no statement as to whether a subsequent query that is missing previously returned entities is an indication of those entities being deleted or not.

Examples:

Sample schemagroups collection attributes, with schemagroups inlined.

"schemagroupsurl": "http://registry.example.com/schemagroups",
"schemagroupscount": 9
"schemagroups": {
  "Contoso.ERP": {...},
  "Fabrikam.InkJetPrinter": {...},
  "Fabrikam.Lumen": {...},
  "Fabrikam.RoboVac": {...},
  "Fabrikam.SmartOven": {...},
  "Fabrikam.Watchkam": {...},
  "WaterBoiler": {...},
  "WindGenerator": {...}
},

The requirements on the presence of the 3 <COLLECTION>* attributes varies between document and API views, and is defined below:

Collections in Document View 🔗

In document view:

Collections in API View 🔗

In API view:

Updating Nested Registry Collections 🔗

When updating an entity that can contain xRegistry collections, the request MAY contain the 3 collection attributes. The <COLLECTION>url and <COLLECTION>count attributes MUST be silently ignored by the server.

If the <COLLECTION> attribute is present, the server MUST process each entity in the collection map as a request to create or update that entity according to the semantics of the operation method used. An entry in the map that isn't a valid entity (e.g. is null) MUST generate an error (bad_request).

For example, in the case of HTTP:

PUT https://example.com/endpoints/ep1

{
  "endpointid": "ep1",
  "name": "A cool endpoint",

  "messages": {
    "mymsg1": { ... },
    "mymsg2:" { ... }
  }
}

will not only create/update an endpoint Group with an endpointid of ep1 but will also create/update its message Resources (mymsg1 and mymsg2).

Any error while processing a nested collection entity MUST result in the entire request being rejected.

An absent <COLLECTION> attribute, or empty map, MUST be interpreted as a request to not modify the collection at all.

If a client wishes to delete an entity from the collection, or replace the entire collection, the client MUST use a "delete" type of operations on the collection. This means that delete operations on these entities would need to be handled in dedicated operations, separate from update operations.

In cases where a Resource update operation includes attributes meant to be applied to the "default" Version of a Resource, and the incoming inlined versions collections includes that "default" Version, the Resource's default Version attributes MUST be silently ignored. This is to avoid any possible conflicting data between the two sets of data for that Version. In other words, the Version attributes in the incoming versions collection wins.

To better understand this scenario, consider the following HTTP request to update a Message where the defaultversionid is v1:

PUT http://example.com/endpoints/ep1/messages/msg1

{
  "messageid": "msg1",
  "versionid": "v1",
  "name": "Blob Created"

  "versions": {
    "v1": {
      "messageid": "msg1",
      "versionid": "v1",
      "name": "Blob Created Message Definition"
    }
  }
}

If the versions collection were not present with the v1 entity then the top-level attributes would be used to update the default Version (v1 in this case). However, because it is present, the request to update v1 becomes ambiguous because it is not clear if the server is meant to use the top-level attributes or if it is to use the attributes under the v1 entity of the versions collection. When both sets of attributes are the same, then it does not matter. However, in this example, the name attributes have different values. The paragraph above mandates that in these potentially ambiguous cases the entity in the versions collection is to be used and the top-level attributes are to be ignored. So, in this case the name of the default (v1) Version will be Blob Created Message Definition.

Registry Entity 🔗

The Registry entity represents the root of a Registry and is the main entry-point for traversal and discovery.

The serialization of the Registry entity MUST adhere to this form:

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

  "capabilities": { Registry capabilities }, ?   # Only if inlined
  "model": { Registry model }, ?                 # Only if inlined
  "modelsource": { Registry model }, ?           # Only if inlined

  # Repeat for each Group type
  "<GROUPS>url": "<URL>",                        # e.g. "endpointsurl"
  "<GROUPS>count": <UINTEGER>,                   # e.g. "endpointscount"
  "<GROUPS>": { Groups collection } ?            # Only if inlined
}

The Registry entity includes the following common attributes:

and the following Registry-level attributes:

specversion Attribute 🔗

capabilities Attribute 🔗

model Attribute 🔗

modelsource Attribute 🔗

<GROUPS> Collections 🔗

Registry Capabilities 🔗

In order to programmatically discover which capabilities are supported by an implementation, servers SHOULD support exposing this information via a "capabilities" map that lists each supported feature along with any related configuration detail that will help in successful usage of that feature.

The "key" of the capabilities-map is the "name" of each feature, and the "value" is a feature-specific set of configuration values, with the most basic being a <BOOLEAN> value of true to indicate support for the feature.

The JSON serialization of capabilities map MUST be of the form:

{
  "apis": [ "<STRING>" * ], ?
  "flags": [ "<STRING>" * ], ?
  "mutable": [ "<STRING>" * ], ?
  "pagination": <BOOLEAN>, ?
  "shortself": <BOOLEAN>, ?
  "specversions": [ "<STRING>" ], ?
  "stickyversions": <BOOLEAN>, ?
  "versionmodes": [ "<STRING>" ], ?

  "<STRING>": ... capability configuration ... *   // Extension capabilities
}

Where:

All capability values, including extensions, MUST be defined as one of the following:

When serializing their supported capabilities, servers MUST include all capabilities (including extensions) since the absence of a capability indicates lack of support for that feature. However, absence, presence, or configuration values of a feature in the map MAY vary based on the authorization level of the client making the request.

The list of values for the arrays MUST be case-insensitive and MAY include extension values.

For clarity, servers MUST include all supported capabilities in the serialization, even if they are set to their default values or have empty lists.

It is RECOMMENDED that protocols for this specification support retrieval of the capabilities via the inlining of the Registry entity's capabilities attribute well as a stand-alone map independent of the Registry entity (e.g. GET /capabilities in the HTTP case). However, as with all interactions with a server, security/access controls MAY be needed.

The following defines the specification-defined capabilities:

apis 🔗

flags 🔗

mutable 🔗

pagination 🔗

shortself 🔗

specversions 🔗

stickyversions 🔗

Updating the Capabilities of a Server 🔗

Implementations MAY support clients updating the capabilities of the server. If so, they SHOULD support it via updates to the Registry entity's capabilities attribute as well as updates via a stand-alone map independent of the the Registry entity (e.g. PUT /capabilities in the HTTP case).

The request to update the capabilities SHOULD include a serialization of the capability map as described above. Whether it includes the full set of supported capabilities or a subset will vary based on the protocol defined. However, the following rules apply in both cases.

For any capability that is an array of strings, a value of "*" MAY be used to indicate that the server MUST replace "*" with the full set of items that are available. An error (capability_error) MUST be generated if "*" appears along with any other value in the list. "*" MUST NOT appear in the serialization in any server's response.

Regardless of the mechanism used to update the capabilities, the Registry's epoch value MUST be incremented upon each update.

The enum of values allows for some special cases:

A request to update a capability with a value that is compliant with the format of the capabilities definition MAY still generate an error (capability_error) if the server determines it cannot support the request. For example, due to authorization concerns or the value, while syntactically valid, isn't allowed in certain situations.

When processing a request to update the capabilities, the semantic changes MUST NOT take effect until after the processing of the current request. Note that if the response includes the serialization of the Registry's capabilities, then the changes MUST appear in that serialization.

The above requirement is driven by the idea that modifying the capabilities of a server and modifying any entity data are typically two very distinct actions, and will not normally happen at the same time. However, if the situation does occur, a consistent (interoperable) processing order needs to be defined.

Offered Capabilities 🔗

In order for an authorized client to update the capabilities of a server it might need to first discover the list of available values for each capability. This information is described via a map (similar to the capability map itself) where each supported capability's name is the key of the map, and the corresponding value provides details about the capability (e.g. allowed values and pointer to its documentation).

The JSON serialization of the capabilities offering map MUST be of the form:

{
  "<STRING>": {
    "type": "<TYPE>",
    "item": {
      "type": "<TYPE>"
    }, ?
    "enum": [ <VALUE>, * ], ?
    "min": <VALUE>, ?
    "max": <VALUE>, ?
    "documentation": "<URL>" ?
  } *
}

Where:

Notice the syntax borrows much of the same structure from the xRegistry model definition language.

To maximize discoverability for clients, even in cases where there is no variability allowed for certain capabilities, they MUST still be listed in a server's "offering" serialization.

For example, if pagination is not supported, but is a known feature, then a server MUST still include:

  "pagination": {
    "type": "boolean",
    "enum": [ false ]
  }

in the serialization of its capabilities offering map.

Examples:

{
  "apis": {
    "type": "string",
    "enum": [ "/capabilities", "/export", "/model", /"modelsource" ]
  },
  "flags": {
    "type": "string",
    "enum": [ "binary", "collections", "doc", "epoch", "filter",
      "ignoredefaultversionid", "ignoredefaultversionsticky", "ignoreepoch",
      "ignorereadonly", "inline", "setdefaultversionid", "sort",
      "specversion" ]
  },
  "pagination": {
    "type": "boolean",
    "enum": [ false, true ]
  },
  "shortself": {
    "type": "boolean",
    "enum": [ false, true ]
  },
  "specversions": {
    "type": "string",
    "enum": [ "1.0-rc2" ]
  },
  "stickyversions": {
    "type": "boolean",
    "enum": [ true ]
  },
  "versionmodes": [ "manual" ]
}

Group Entity 🔗

Groups represent entities that typically act as a collection mechanism for related Resources. However, it is worth noting that Groups do not have to have Resources associated with them. It is possible to have Groups be the main (or only) entity of a Registry. Each Group type MAY have any number of Resource types within it. This specification does not define how the Resources within a Group type are related to each other.

The serialization of a Group entity MUST adhere to this form:

{
  "<GROUP>id": "<STRING>",
  "self": "<URL>",
  "shortself": "<URL>", ?
  "xid": "<XID>",
  "epoch": <UINTEGER>,
  "name": "<STRING>", ?
  "description": "<STRING>", ?
  "documentation": "<URL>", ?
  "icon": "<URL>", ?
  "labels": { "<STRING>": "<STRING>" * }, ?
  "createdat": "<TIMESTAMP>",
  "modifiedat": "<TIMESTAMP>",
  "deprecated": {
    "effective": "<TIMESTAMP>", ?
    "removal": "<TIMESTAMP>", ?
    "alternative": "<URL>", ?
    "documentation": "<URL>"?
  }, ?

  # Repeat for each Resource type in the Group
  "<RESOURCES>url": "<URL>",                  # e.g. "messagesurl"
  "<RESOURCES>count": <UINTEGER>,             # e.g. "messagescount"
  "<RESOURCES>": { Resources collection } ?   # If inlined
}

Group extension attributes would also appear as additional top-level JSON attributes.

Groups include the following common attributes:

and the following Group-level attributes:

<RESOURCES> Collections 🔗

Resource Entity 🔗

Resources typically represent the main entity that the Registry is managing. Each Resource is associated with a Group to aid in their discovery and to show a relationship with Resources in that same Group. Resources appear within the Group's <RESOURCES> collection.

Resources, like all entities in the Registry, can be modified but Resources can also have a version history associated with them, allowing for users to retrieve previous Versions of the Resource. In this respect, Resources have a 2-layered definition. The first layer is the Resource entity itself, and the second layer is its versions collection - the version history of the Resource.

The Resource entity serves three purposes:

1 - It represents the collection of historical Versions of the data being managed. This is true even if the Resource type is defined to not use versioning, meaning the number of Versions allowed is just one. The Versions will appear as nested xRegistry collection under the versions attribute.

2 - It acts as an alias for the "default" Version of the Resource. This means that any operation (read or write) that deals with attributes exposed via the Resource, but are inherited from the "default" Version, MUST act upon that Version's corresponding attribute. See Default Version of a Resource, Updating Nested Registry Collections and Version Entity for additional semantics that apply to write operations on Resources.

3 - It has a set of attributes for Resource-level metadata - data that is not specific to one Version of the Resource but instead applies to the Resource in general. Most of these attributes appear under a meta entity so as to keep them separate from any default Version-level attributes that might appear. Note that these attributes do not appear on the Versions.

When a Resource is serialized as xRegistry metadata without the inherited default Version attributes, such as when the doc flag is used, it MUST adhere to the following:

{
  "<RESOURCE>id": "<STRING>",
  "self": "<URL>",                           # URL to Resource, not Version
  "shortself": "<URL>", ?
  "xid": "<XID>",                            # Relative URI to Resource

  "metaurl": "<URL>",                        # URL to 'meta' entity
  "meta": { meta entity }, ?                 # Only if inlined
  "versionsurl": "<URL>",                    # Absolute URL to versions
  "versionscount": <UINTEGER>,               # Size of versions collection
  "versions": { map of Versions }            # Only if inlined
}

When the default Version attributes do appear in the xRegistry metadata serialization of the Resource (e.g. the doc flag is not used) it MUST adhere to the following:

{
  "<RESOURCE>id": "<STRING>",
  "versionid": "<STRING>",                   # Default Version's ID
  "self": "<URL>",
  "shortself": "<URL>", ?
  "xid": "<XID>",
  "epoch": <UINTEGER>,                       # Start of default Ver attributes
  "name": "<STRING>", ?
  "isdefault": true,
  "description": "<STRING>", ?
  "documentation": "<URL>", ?
  "icon": "<URL>", ?
  "labels": { "<STRING>": "<STRING>" * }, ?
  "createdat": "<TIMESTAMP>",
  "modifiedat": "<TIMESTAMP>",
  "ancestor": "<STRING>",
  "contenttype": "<STRING>, ?

  "<RESOURCE>url": "<URL>", ?                # If not local
  "<RESOURCE>": ... Resource document ..., ? # If local & inlined & JSON
  "<RESOURCE>base64": "<STRING>", ?          # If local & inlined & ~JSON
                                             # End of default Ver attributes
  "metaurl": "<URL>",
  "meta": { meta entity }, ?                 # Only if inlined
  "versionsurl": "<URL>",
  "versionscount": <UINTEGER>,
  "versions": { map of Versions } ?          # Only if inlined
}

Note that the Version attributes that conflict with the Resource attributes (e.g. self, shortself, xid) are not inherited by this serialization. Their values are for the Resource and not the default Version's.

Resource Attributes 🔗

The Resource entity includes the following common attributes:

and the following Resource-level attributes:

metaurl Attribute 🔗
meta Attribute 🔗
versions Collection 🔗

Resource Metadata vs Resource Document 🔗

Unlike Groups, which consist entirely of xRegistry managed metadata, Resource Versions often have their own domain-specific data and document format that needs to be kept distinct from the Version metadata. As discussed previously, the model definition for Resource types has a hasdocument aspect indicating whether a Resource type defines its own separate document or not.

This specification does not define any requirements for the contents of this separate document, and it doesn't even need to be stored within the Registry. The Version MAY choose to simply store a URL reference to the externally managed document instead. When the document is stored within the Registry, it can be managed as an opaque array of bytes and is available via the Version <RESOURCE> or <RESOURCE>base64 attributes.

When a Resource is configured to possibly have a separate document, clients can choose whether they want to interact with that document or with the xRegistry metadata. In this sense, there are two "views" of the Resource/Version that client can choose from.

Each xRegistry binding specification will define the mechanism by which clients can indicate which view of the Resource/Version they want to interacting with. For HTTP, see the Resource Metadata vs Resource Document section for more information, in particular about the use of the $details URL suffix. Those specifications will also define any protocol-specific serialization rules when the Resource domain-specific document view is used.

Creating or Updating Resources and Versions 🔗

The following rules apply to the processing of write operations for Resources and Versions:

When the xRegistry metadata is serialized as a JSON object, the processing of the 3 Version-level <RESOURCE>* attributes MUST follow these rules:

Cross Referencing Resources 🔗

Typically, Resources exist within the scope of a single Group, however there might be situations where a Resource needs to be related to multiple Groups. In these cases, there are two options. First, a copy of the Resource could be made into the second Group. The obvious downside to this is that there's no relationship between the two Resources and any changes to one would need to be done in the other - running the risk of them getting out of sync.

The second, and better, option is to create a cross-reference from one (the "source" Resource) to the other ("target" Resource). This is done by setting the xref attribute on the source Resource to be the xid of the target Resource.

For example: a schema Resource instance defined as:

{
  "schemaid": "mySchema",
  "meta": {
    "xref": "/schemagroups/group2/schemas/sharedSchema"
  }
}

means that mySchema references sharedSchema, which exists in group2. When this source Resource (mySchema) is retrieved, all of the target Resource's attributes (except its <RESOURCE>id) will appear as if they were locally defined.

So, if the target Resource (sharedSchema) is defined as:

{
  "resourceid": "sharedSchema",
  "versionid": "v1",
  "self": "http://example.com/schemagroups/group2/schemas/sharedSchema",
  "xid": "/schemagroups/group2/schemas/sharedSchema",
  "epoch": 2,
  "isdefault": true,
  "createdat": "2024-01-01-T12:00:00Z",
  "modifiedat": "2024-01-01-T12:01:00Z",
  "ancestor": "v1",

  "metaurl": "http://example.com/schemagroups/group2/schemas/sharedSchema/meta",
  "versionscount": 1,
  "versionsurl": "http://example.com/schemagroups/group2/schemas/sharedSchema/versions"
}

then the resulting serialization of the source Resource would be:

{
  "resourceid": "mySchema",
  "versionid": "v1",
  "self": "http://example.com/schemagroups/group1/schemas/mySchema",
  "xid": "/schemagroups/group1/schemas/mySchema",
  "epoch": 2,
  "isdefault": true,
  "createdat": "2024-01-01-T12:00:00Z",
  "modifiedat": "2024-01-01-T12:01:00Z",
  "ancestor": "v1",

  "metaurl": "http://example.com/schemagroups/group1/schemas/mySchema/meta",
  "meta": {
    "resourceid": "mySchema",
    "self": "http://example.com/schemagroups/group1/schemas/mySchema/meta",
    "xid": "/schemagroups/group1/schemas/mySchema/meta",
    "xref": "/schemagroups/group2/schemas/sharedSchema",
    "createdat": "2024-01-01-T12:00:00Z",
    "modifiedat": "2024-01-01-T12:01:00Z",
    "readonly": false,
    "compatibility": "none",
    "defaultversionid": "v1",
    "defaultversionurl": "http://example.com/schemagroups/group1/schemas/mySchema/versions/v1",
    "defaultversionsticky": false
  },
  "versionscount": 1,
  "versionsurl": "http://example.com/schemagroups/group1/schemas/mySchema/versions"
}

Note:

From a consumption (read) perspective, aside from the presence of the xref attribute, the Resource appears to be a normal Resource that exists within group1. All of the specification-defined features (e.g. inline, filter request flags) MAY be used when retrieving the Resource.

However, from a write perspective it is quite different. In order to update the target Resource's attributes (or nested entities), a write operation MUST be done on the appropriate target Resource entity directly. Write operations on the source MAY be done, however, the changes are limited to converting it from a "cross-reference" Resource back into a "normal" Resource. See the following for more information:

When converting a "normal" Resource into a cross-reference Resource (adding an xref value), or creating/updating a Resource that is a cross-reference Resource, the following MUST be adhered to:

When converting a cross-reference Resource back into a "normal" Resource, the following MUST be adhered to:

If the target Resource itself is a cross-reference Resource, then including the target Resource's attributes MUST NOT be done when serializing the source Resource. Recursive, or transitively, following of xref XIDs is not done.

Both the source and target Resources MUST be of the same Resource model type, simply having similar Resource type definitions is not sufficient. This implies that the [ximportresources]./model.md#groupsstringximportresources) feature to reference a Resource type from another Group type definition MUST be used.

An xref value that points to a non-existing Resource, either because it was deleted, never existed or the current client does not have permission to see it, is not an error and is not a condition that a server is REQUIRED to detect. In these "dangling xref" situations, the serialization of the source Resource will not include any target Resource attributes or nested collections. Rather, it will only show the <RESOURCE>id and xref attributes.

Meta Entity 🔗

The meta entity (within a Resource) contains most of the Resource-level attributes that are global to the Resource, and not Version-specific. It is an entity in its own right, meaning it supports the normal "read" and "write" operation targeted directly to it.

Each Resource MUST have a Meta entity, and when the Resource is deleted then the Meta entity MUST also be deleted. Delete requests directed to the Meta entity MUST generate an error (action_not_supported).

A non-patch type of write operation that includes a Resource, as a mechanism to update its meta entity would need to include the Resource's default Version attributes in the request. If not, the server will interpret it as a request to delete the default Version attributes, which is probably not the desired result. Instead, a write operation directly targeted to the meta entity would be a better choice, or a "patch" type of operation where only the meta entity is included in the request.

The serialization of the Meta entity MUST adhere to this form:

{
  "<RESOURCE>id": "<STRING>",               # Resource ID
  "self": "<URL>",                          # URL to this "meta" entity
  "shortself": "<URL>", ?
  "xid": "<XID>",                           # Relative URI to this "meta"
  "xref": "<XID>", ?                        # Ptr to linked Resource
  "epoch": <UINTEGER>,                      # Resource's epoch
  "createdat": "<TIMESTAMP>",               # Resource's
  "modifiedat": "<TIMESTAMP>",              # Resource's
  "readonly": <BOOLEAN>,                    # Default=false
  "compatibility": "<STRING>",              # Default=none
  "compatibilityauthority": "<STRING>", ?   # Default=external
  "deprecated": { ... }, ?

  "defaultversionid": "<STRING>",
  "defaultversionurl": "<URL>",
  "defaultversionsticky": <BOOLEAN>
}

Meta extension attributes would also appear as additional top-level JSON attributes.

The Meta entity includes the following common attributes:

and the following Meta-level attributes:

xref Attribute 🔗

readonly Attribute 🔗

compatibility Attribute 🔗

compatibilityauthority Attribute 🔗

defaultversionid Attribute 🔗

defaultversionurl Attribute 🔗

defaultversionsticky Attribute 🔗

Version Entity 🔗

Versions represent historical instances of a Resource. When a Resource is updated, there are two actions that might take place. First, the update can completely replace an existing Version of the Resource. This is most typically done when the previous state of the Resource is no longer needed, and there is no reason to allow people to reference it. The second situation is when both the old and new Versions of a Resource are meaningful and both might need to be referenced. In this case, the update will cause a new Version of the Resource to be created and will have a unique versionid within the scope of the owning Resource.

For example, updating the data of Resource without creating a new Version would make sense if there is an error in the description field. But, adding additional data to the document of a Resource might require a new Version and a new versionid (e.g. changing it from "1.0" to "1.1").

This specification does not mandate a particular versioning algorithm or Version identification (versionid) scheme.

When a Version is serialized as xRegistry metadata it MUST adhere to the following:

{
  "<RESOURCE>id": "<STRING>",                  # <SINGULAR>id of Resource
  "versionid": "<STRING>",
  "self": "<URL>",
  "shortself": "<URL>", ?
  "xid": "<XID>",
  "epoch": <UINTEGER>,
  "name": "<STRING>", ?
  "isdefault": <BOOLEAN>,
  "description": "<STRING>", ?
  "documentation": "<URL>", ?
  "icon": "<URL>", ?
  "labels": { "<STRING>": "<STRING>" * }, ?
  "createdat": "<TIMESTAMP>",
  "modifiedat": "<TIMESTAMP>",
  "ancestor": "<STRING>",
  "contenttype": "<STRING>", ?

  "<RESOURCE>url": "<URL>", ?                  # If not local
  "<RESOURCE>": ... Resource document ..., ?   # If inlined & JSON
  "<RESOURCE>base64": "<STRING>" ?             # If inlined & ~JSON
}

Version extension attributes would also appear as additional top-level JSON attributes.

Versions include the following common attributes:

and the following Version-level attributes:

versionid Attribute 🔗

isdefault Attribute 🔗

ancestor Attribute 🔗

contenttype Attribute 🔗

<RESOURCE>url Attribute 🔗

<RESOURCE> Attribute 🔗

<RESOURCE>base64 Attribute 🔗


When accessing a Versions's xRegistry metadata, often it is to view or update the xRegistry metadata and not the document, as such, including the potentially large amount of data from the Version's document in request and response messages could be cumbersome. To address this, the <RESOURCE> and <RESOURCE>base64 attributes do not appear by default as part of the serialization of the Version. Rather, they MUST only appear in responses when the Inline Flag, with a value of <RESOURCE>, is used. Likewise, in requests, these attributes are OPTIONAL and would only need to be used when a change to the document's content is needed at the same time as updates to the Version's metadata. However, the <RESOURCE>url attribute MUST always appear if it has a value, just like any other attribute.

Note that the serialization of a Version MUST only use at most one of these 3 attributes at a time.

Client and server implementations MUST be prepared for any of these 3 attributes to be used. In the case of <RESOURCE> or <RESOURCE>base64, implementations can not assume that a previous use of one means that all subsequent messages of that entity will use the same attribute. For example, a client can use <RESOURCE> to populate the value, but the server is free to use <RESOURCE>base64 when returning the data.

Version IDs 🔗

If a server does not support client-side specification of the versionid of a new Version (see the setversionid aspect in the Registry Model), or if a client chooses to not specify the versionid, then the server MUST assign new Version an versionid that is unique within the scope of its owning Resource.

Servers MAY have their own algorithm for the creation of new Version versionid values, but the default algorithm is as follows:

With this default versioning algorithm, when semantic versioning is needed, it is RECOMMENDED to include a major version identifier in the Resource <RESOURCE>id, like "com.example.event.v1" or "com.example.event.2024-02", so that incompatible, but historically related Resources can be more easily identified by users and developers. The Version's versionid then functions as the semantic minor version identifier.

Default Version of a Resource 🔗

As Versions of a Resource are added or removed, there needs to be a mechanism by which the "default" one is determined. There are two options for how this might be done:

  1. Newest = Default. The newest Version (based on the Resource's versionmode algorithm) MUST be the "default" Version. This is the default choice.

  2. Client explicitly chooses the "default". In this option, a client has explicitly chosen which Version is the "default" and it will not change until a client chooses another Version, or that Version is deleted (in which case the server MUST revert back to option 1 (newest = default), if the client did not use the SetDefaultVersionID to choose the next "default" Version - see below). This is referred to as the default Version being "sticky" as it will not change until explicitly requested by a client.

If supported (as determined by the setdefaultversionsticky aspect, a client MAY choose the "default" Version two ways:

  1. Via the Resource defaultversionsticky and defaultversionid attributes in its meta entity.
  2. Via the SetDefaultVersionID Flagthat is available on certain APIs.

Updating a Resource's defaultversionid, regardless of the mechanism used to do so, MUST adhere to the following rules:

Deleting Entities 🔗

Each protocol binding will define how to delete entities, and in most cases the operation will be straight-forward since the action will likely either be a "delete" operation directed to the entity in question, or in the case of deleting multiple entities, it will be directed to the owning collection along with a map of entity IDs to be deleted.

When deleting multiple entities, the list of entities to delete MUST be specified as a map. There will be 3 possible ways in which the map will be serialized:

1 - Deleting multiple entities (no epoch value checking)

{
  "<KEY>": {}                             # <SINGULAR>id of entity
} ?

While this could have been represented as an array of IDs, for consistency with the next two variants, and with what a query for the list of entities in a collection will return, it's a map.

2 - Deleting multiple non-Resource entities with epoch value checking

{
  "<KEY>": {                              # <SINGULAR>id of entity
    "epoch": <UINTEGER> ?
  } *
} ?

Since each entity now has an epoch value associated with it, the server MUST perform epoch value checking and reject the entire request if any fail. This is similar to what an "update" operation would look like.

3 - Deleting multiple Resource entities with epoch value checking

{
  "<KEY>": {                              # <SINGULAR>id of Resource
    "meta": {
      "epoch": <UINTEGER> ?
    } ?
  } *
} ?

Since a Resource's epoch value is part of its meta entity, and not a top-level Resource attribute, for consistency with what the retrieval of a Resource would look like, the epoch value in this case MUST appear under a meta entity within the Resource. And the normal epoch value checking rules would apply.

This special serialization rules for Resources was done because an epoch value that appears as a top-level attribute is likely done when a client mistakenly uses a Version's serialization rather than the owning Resource's.

If an epoch value only appears at the top-level (and not within meta) then an error (misplaced_epoch) MUST be generated. If epoch appears in both places then the top-level one MUST be silently ignored.


Regardless of type of "delete" being done, the following rules apply:

Request Flags 🔗

This specification allows for clients to configure server-side processing via the use of "flags" (configuration options) on requests. The allowable flags might vary based on the specific operation being performed, and some will influence the processing of the request while some will influence the how the response message will be generated.

Implementations of this specification SHOULD support all specification-defined flags.

The following sections define each flag and then the protocol-specific specifications will indicate how they are to be serialized on each request:

See: Request Flags in the HTTP binding specification for the HTTP usage.

Binary Flag 🔗

The binary flag MAY be used on requests to indicate that the server MUST use the <RESOURCE>base64 attribute instead of the <RESOURCE> attribute when serializing any Resource's domain-specific document in the response message. Note, the presence of this flag does not change when the document is inlined, just how it is serialized if it is inlined.

This flag is intended for cases where the client wishes to avoid the server modifying the bytes of the document in any way - such as "pretty printing" it.

This flag MAY be used on any request but will only influence the serialization of Resource and Version entities that have a domain-specific document.

Collections Flag 🔗

The collections flag MAY be used on requests directed to the Registry itself or to Group instances to indicate that the response message MUST NOT include any attributes from the top-level entity (Registry or Group), but instead MUST include only all of the nested xRegistry Collection maps that are defined at that level. Specifying it on a request directed to some other part of the Registry MUST generate an error (bad_flag). Use of this flag MUST implicitly turn on inlining within a value of *.

Servers MAY choose to include, or exclude, the sibling <COLLECTION>url and <COLLECTION>count attributes for those top-level collections.

Note that this feature only applies to the root entity of the response and not to any nested entities/collections.

This feature is meant to be used when the Collections of the Registry, or Group, are of interest but not the top-level metadata. For example, this could be used to export one or more Group types from a Registry where the resulting JSON document is then used to import them into another Registry. If the Registry-level attributes were present in the output then they would need to be removed prior to the import, otherwise they would override the target Registry's values.

A query result when using this feature is designed to be used on a future "write" operation to a Registry (or Group) where the nested Collections are to be updated without modifying the attributes of the root entity of the operation.

For example, to export all of the Groups of one Registry into another, without modifying the Registry entity's attributes, can be done via HTTP by taking the results from:

GET http://sourceRegistry.com/?collections

and using it as input into:

POST http://targetRegistry.com/

Doc Flag 🔗

The doc flag MAY be used to indicate that the response MUST use "document view" when serializing entities and MUST be modified to do the following:

All of the relative URLs mentioned in the last bullet above MUST begin with # and be followed by a JSON Pointer reference to the entity within the response, e.g. #/endpoints/e1. This means that they are relative to the root of the document (response) generated, and not necessarily relative to the root of the Registry. Additionally, when those URLs are relative and reference a Resource or Version, any protocol-specific modifications to the URLs (e.g. the HTTP $details suffix) MUST NOT be present despite the semantics of the suffix being applied (as noted below).

For clarity, if a Registry has a Schema Resource at /schemagroups/g1/schemas/s1, then this entity's self URL (when serialized in document view) would change based on the path specified on the GET request:

GET Path self URL
http://example.com/myreg #/schemagroups/g1/schemas/s1
http://example.com/myreg/schemagroups #/g1/schemas/s1
http://example.com/myreg/schemagroups/g1/ #/schemas/s1
http://example.com/myreg/schemagroups/g1/schemas #/s1
http://example.com/myreg/schemagroups/g1/schemas/s1 #/

This feature is useful when a client wants to minimize the amount of data returned by a server because the duplication of that data (typically used for human readability purposes) isn't necessary. For example, if tooling would ignore the duplication, or if the data will be used to populate a new Registry, then this feature might be used. It also makes the output more of a "stand-alone" document that minimizes external references.

For clarity, the serialization of a Resource in document view MUST adhere to the following:

{
  "<RESOURCE>id": "<STRING>",
  "self": "<URL>",
  "shortself": "<URL>", ?
  "xid": "<XID>",

  "metaurl": "<URL>",
  "meta": {
    "<RESOURCE>id": "<STRING>",
    "self": "<URL>",
    "shortself": "<URL>", ?
    "xid": "<XID>",
    "xref": "<XID>" ?
    # The following attributes are absent if 'xref' is set
    "epoch": <UINTEGER>,
    "createdat": "<TIMESTAMP>",
    "modifiedat": "<TIMESTAMP>",
    "ancestor": "<STRING>",
    "readonly": <BOOLEAN>,
    "compatibility": "<STRING>",
    "compatibilityauthority": "<STRING>", ?
    "deprecated": { ... }, ?

    "defaultversionid": "<STRING>",
    "defaultversionurl": "<URL>"
    "defaultversionsticky": <BOOLEAN>
  }
}

Note that the meta entity's attributes epoch through defaultversionsticky MUST be excluded if xref is set because those would appear as part of the target Resource's meta entity. Also notice the default Version's attributes do not appear.

If this flag is used on a request directed to a Resource's versions collection, or to one of its Versions, but the Resource is defined as an xref to another Resource, then the server MUST generate an error (cannot_doc_xref) and SHOULD indicate that using this flag on this part of the hierarchy is not valid - due to those entities not technically existing in document view.

Epoch Flag 🔗

The epoch flag MAY be used on any delete operation directed to a single entity if the protocol being used doesn't normally include the serialization of the "to be deleted" entity in the request. In those cases, this flag is used to request that the entity's current epoch value matches this flag's value for the purpose of the server's epoch conflict checking algorithm.

Filter Flag 🔗

The filter flag MAY be used to indicate that the response MUST include only those entities that match the specified filter criteria expressions. This means that any Registry Collection's attributes MUST be modified to match the resulting subset. In particular:

Parameters to this flag include one or more filter expressions. Each protocol binding will indicate how to express logical ANDs and ORs between those expressions. Regardless of how it is expressed the following rules apply:

The format of a filter expression is one of:

[<PATH>.]<ATTRIBUTE>
[<PATH>.]<ATTRIBUTE>=null
[<PATH>.]<ATTRIBUTE>=[<VALUE>]
[<PATH>.]<ATTRIBUTE><<VALUE>
[<PATH>.]<ATTRIBUTE><=<VALUE>
[<PATH>.]<ATTRIBUTE>><VALUE>
[<PATH>.]<ATTRIBUTE>>=<VALUE>
[<PATH>.]<ATTRIBUTE>!=<VALUE>
[<PATH>.]<ATTRIBUTE><><VALUE>

Where:

For comparing an <ATTRIBUTE> to the specified <VALUE>, and for purposes of sorting (see the Sort flag), the type of the attribute impacts how the comparisons are done:

See the Sort section for more details concerning sorting.

Additionally, wildcards (*) MAY be used in string <VALUE>s with the following constraints:

If the request references an entity (not a collection), and the expression references an attribute in that entity (i.e. there is no <PATH>), then if the expression does not match the entity, that entity MUST NOT be returned. In other words, a 404 Not Found would be generated in the HTTP protocol case.

Examples:

Using the HTTP protocol binding syntax:

Request Path Filter query Commentary
/ ?filter=endpoints.description=*cool* Only endpoints with the word cool in the description
/endpoints ?filter=description=*CooL* Similar results as previous, with a different request URL
/ ?filter=endpoints.messages.versions.versionid=1.0 Only versions (and their owning parents) that have a versionid of 1.0
/ ?filter=endpoints.name=myendpoint,endpoints.description=*cool*& filter=schemagroups.labels.stage=dev Only endpoints whose name is myendpoint and whose description contains the word cool, as well as any schemagroups with a label name/value pair of stage/dev
/ ?filter=description=no-match Returns a 404 if the Registry's description doesn't equal no-match
/ ?filter=endpoints.messages.meta.readonly=true Only messages that are readonly

Specifying a filter does not imply inlining. Inlining MAY be used at the same time but MUST NOT result in additional entities being included in the results unless they are children of a matching leaf entity.

For example, in the following entity URL paths representing a Registry:

mygroups/g1/myresources/r1/versions/v1
mygroups/g1/myresources/r1/versions/v2
mygroups/g1/myresources/r2/versions/v1
mygroups/g2/myresources/r3/versions/v1

This HTTP request:

GET /?filter=mygroups.myresources.myresourceid=r1&inline=*

would result in the following entities (and their parents along the specified paths) being returned:

mygroups/g1/myresources/r1/versions/v1  # versions are due to inlining
mygroups/g1/myresources/r1/versions/v2

However, this request:

GET /?filter=mygroups.mygroupid=g2&filter=mygroups.myresources.myresourceid=r1&inline=*

would result in the following returned:

mygroups/g1/myresources/r1/versions/v1   # from 2nd ?filter
mygroups/g1/myresources/r1/versions/v2   # from 2nd ?filter
mygroups/g2/myresources/r3/versions/v1   # from 1nd ?filter

And, this request:

GET /?filter=mygroups.mygroupid=g1&filter=mygroups.myresources.myresourceid=r1&inline=*

would result in the following being returned:

mygroups/g1/myresources/r1/versions/v1   # from 2nd ?filter
mygroups/g1/myresources/r1/versions/v2   # from 2nd ?filter
mygroups/g1/myresources/r2/versions/v1   # from 1st ?filter

And, finally this request:

GET /?filter=mygroups.mygroupid=g1,mygroups.myresources.myresourceid=r1&inline=*

would result in the following being returned:

mygroups/g1/myresources/r1/versions/v1
mygroups/g1/myresources/r1/versions/v2

Notice the first part of the filter expression (to the left of the "and" (,)) has no impact on the results because the list of resulting leaves in that subtree is not changed by that search criteria.

IgnoreDefaultVersionID Flag 🔗

The ignoredefaultversionid flag MAY be used on any write operation to indicate that any defaultversionid attribute included in the request MUST be ignored.

This flag is useful in cases where there is a desire to not change any existing Resource's defaultversionid values based on the data in the write operation request, and the incoming data is not easily modifiable to remove the defaultversionid attributes that might be in there.

IgnoreDefaultVersionSticky Flag 🔗

The ignoredefaultversionsticky flag MAY be used on any write operation to indicate that any defaultversionsticky attribute included in the request MUST be ignored.

This flag is useful in cases where there is a desire to not change any existing Resource's defaultversionsticky values based on the data in the write operation request, and the incoming data is not easily modifiable to remove the defaultversionsticky attributes that might be in there.

IgnoreEpoch Flag 🔗

The ignoreepoch flag MAY be used on any write operation to indicate that any epoch attribute included in the request MUST be ignored.

This flag is useful in cases where there is a desire to not change any existing entity's epoch values based on the data in the write operation request, and the incoming data is not easily modifiable to remove the epoch attributes that might be in there.

IgnoreReadOnly Flag 🔗

The ignorereadonly flag MAY be used on any write operation to indicate that any attempt to modify a read-only entity MUST be silently ignored.

This flag is useful in cases where detecting attempts to update read-only entity is not desired and the incoming data is not easily modifiable to remove the read-only entity.

Inline Flag 🔗

The inline flag MAY be used on requests to indicate whether nested collections/objects, or certain (potentially large) attributes, are to be included in the response message.

The inline flag on a request indicates that the response MUST include the contents of all specified inlineable attributes. Inlineable attributes include:

While the <RESOURCE> and <RESOURCE>base64 attributes are defined as two separate attributes, they are technically two separate "views" of the same underlying data. As such, the usage of each will be based on the content type of the Resource, and specifying <RESOURCE> in the inline flag value MUST be interpreted as a request for the appropriate attribute. In other words, <RESOURCE>base64 is not a valid inline value.

Use of this feature is useful for cases where the contents of the Registry are to be represented as a single (self-contained) document.

Some examples using the HTTP protocol binding:

The value of the inline flag is a list of <PATH> values where each is a string indicating which inlineable attribute to show in the response. References to nested attributes are represented using a dot (.) notation where the xRegistry collection names along the hierarchy are concatenated. For example: endpoints.messages.versions will inline all Versions of Messages. Non-leaf parts of the <PATH> MUST only reference xRegistry collection names and not any specific entity IDs since <PATH> is meant to be an abstract traversal of the model.

To reference an attribute with a dot as part of its name, the JSONPath escaping mechanism MUST be used: ['my.name']. For example, prop1.my.name.prop2 would be specified as prop1['my.name'].prop2 if my.name is the name of an attribute.

There MAY be multiple <PATH>s specified in a single request and each protocol binding specification will indicate how the list is specified.

The * value MAY be used to indicate that all nested inlineable attributes at that level in the hierarchy (and below) MUST be inlined - except model, modelsource and capabilities at the root of the Registry. These three are excluded since the data associated with them are configuration related. To include their data the request MUST include <PATH> values of model, modelsource or capabilities explicitly. Use of * MUST only be used as the last part of the <PATH> (in its entirety). For example, foo* and *.foo are not valid <PATH> values, but * and endpoints.* are.

An inline flag without any value MAY be supported and if so it MUST have the same semantic meaning as a value of *.

The specific value of <PATH> will vary based on where the request is directed. For example, a request to the root of the Registry MUST start with a <GROUPS> name, while a request directed at a Group would start with a <RESOURCES> name.

For example, given a Registry with a model that has endpoints as a Group and messages as a Resource within endpoints, the table below shows some <PATH> values and a description of the result for the HTTP protocol:

HTTP GET Path Example ?inline=<PATH> values Comment
/ ?inline=endpoints Inlines the endpoints collection, but just one level of it, not any nested inlineable attributes
/ ?inline=endpoints.messages.versions Inlines the versions collection of all messages. Note that this implicitly means the parent entities (messages and endpoints would also be inlined - however any other <GROUPS> or <RESOURCE>s types would not be
/endpoints ?inline=messages Inlines just messages and not any nested attributes. Note we don't need to specify the parent <GROUP> since the URL already included it
/endpoints/ep1 ?inline=messages.versions Similar to the previous endpoints.messages.version example
/endpoints/ep1 ?inline=messages.message Inline the Resource document
/endpoints/ep1 ?inline=endpoints Invalid, already in endpoints and there is no <RESOURCE> called endpoints
/ ?inline=endpoints.messages.meta Inlines the meta entity of each message returned.
/ ?inline=endpoints.* Inlines everything for all endpoints.

Note that asking for an attribute to be inlined will implicitly cause all of its parents to be inlined as well, but just the parent's collections needed to show the child. In other words, just the collection in the parent in which the child appears, not all collections in the parent.

When specifying a collection to be inlined, it MUST be specified using the plural name for the collection in its defined case.

A request to inline an unknown, or non-inlineable, attribute MUST generate an error (invalid_data).

Note: If the Registry cannot return all expected data in one response because it is too large then it MUST generate an error (too_large). In those cases, the client will need to query the individual inlineable collection attributes in isolation so the Registry can leverage a pagination type of feature to iteratively retrieve the entities.

SetDefaultVersionID Flag 🔗

The setdefaultversionid flag MAY be used on any write operation directed to a Resource or Version where a Version is created, delete or updated but access to the meta.defaultversionid attribute is not available via that operation. This is to allow for the update to the Resource/Version to happen along with the change to the defaultversionid within the same operation. Without this ability there might be times where the default Version of the Resource could (temporarily) be pointing to the wrong Version.

This flag MUST include a single parameter, a string containing the versionid of the Version that is to become the new default Version.

The following rules apply:

Any use of this flag on a Resource that has the setdefaultversionsticky aspect set to false MUST generate an error (bad_flag).

Sort Flag 🔗

When a request is directed at a collection of Groups, Resources or Versions, the Sort flag MAY be used to indicate the order in which the entities of that collection are to be returned (i.e. sorted).

This flag MUST include a single parameter, a string containing the attribute (<ATTRIBUTE>) name to use as the "sort key" plus an OPTIONAL indication of whether the results are to be sorted in ascending or descending order.

The following rules apply:

If the specified attribute is not found within the entities being sorted then implementations SHOULD treat that entity's sort-key value as NULL.

When a pagination type of feature is used to return the results, but the sort flag is not specified, then the server MUST sort the results on the entities' <SINGULAR>id value in ascending order. When pagination is not used, it is RECOMMENDED that servers still sort the results by <SINGULAR>id (asc) for consistency.

Sorting MUST be done using the data type comparison rules as specified in the filter Flag section. However, there are certain situations that might introduce ambiguity between implementations. For example, not all persistent stores support NaNs (Not-a-Number values), or if the data type of an attribute changes on a per-instance basis then consistent sorting across implementations on that attribute might be challenging. While interoperability is critical, requiring consistency in these edge cases could be excessively burdensome for implementations. To that end, this specification does not mandate the exact ordering in these situations, aside from the requirement that an implementation MUST sort the result the same way each time.

Entities that do not have a value for the specified attribute MUST be treated the same as if they had the "lowest" possible value for that attribute. If more than one entity shares the same attribute value then the <SINGULAR>id MUST be used as a secondary sorting key, using the same asc/desc value specified for the primary sorting key.

Some examples using the HTTP protocol binding:

SpecVersion Flag 🔗

The SpecVersion flag MAY be used to indicate the xRegistry specification version that the response MUST adhere to. The parameter value of this flag MUST be a case-insensitive string.

If the specified version is not supported, then an error (unsupported_specversion) MUST be generated. When not specified, the default value MUST be the newest version of this specification supported by the server.

When comparing specversion strings, the server MUST silently ignore the "patch" version number and only consider the "major.minor" version numbers. This is because any "patch" version updates will only contain clarifications and ought not require any code changes for server implementations. Therefore, all patch versions of the same "major.minor" version MUST be forwards and backwards compatible.

However, due to the potential for semantics changes of versions with suffix values (e.g. v2.0.0-rc1), the suffix value MUST be part of the comparison checking.

Error Processing 🔗

If an error occurs during the processing of a request, even if the error was during the creation of the response (e.g. an invalid inline value was provided), then an error MUST be generated and the entire request MUST be undone.

In general, when an error is generated, it SHOULD be sent back to the client. However, this MAY not happen if the server determines there is a good reason to not do so - such as due to security concerns.

Most of the error conditions mentioned in this specification will include a reference to one of the errors listed in this section. While it is RECOMMENDED that implementations use those errors (for consistency), they MAY choose to use a more appropriate one (or a custom one).

Each protocol binding specification will define how error SHOULD be returned back to clients.

In the definition of each error the following rules apply:

<CODE>, "type", "instance" and title fields are REQUIRED. All other fields are OPTIONAL unless overwise stated as part of the error definition. Any substitutable information (as denoted by the <...> syntax) defined as part of an error MUST be populated appropriately.

HTTP response codes and status text are defined in the HTTP Semantics specification.

In the following list of errors, the Code, Type and Instance values MUST be as specified. The other field values are recommendations and MAY be modified as appropriate, including being specified in a language other than English.

The following list of protocol-independent errors are defined:

action_not_supported 🔗

In the case of using the HTTP protocol binding, this error MUST include the HTTP Allow header in the response indicating which HTTP methods the API supports, if any.

ancestor_circular_reference 🔗

bad_flag 🔗

bad_request 🔗

This error is purposely generic and can be used when there isn't a more condition-specific error that would be more appropriate. Implementations SHOULD attempt to use a more specific error when possible.

cannot_doc_xref 🔗

capability_error 🔗

compatibility_violation 🔗

data_retrieval_error 🔗

defaultversionid_not_allowed 🔗

invalid_character 🔗

invalid_data 🔗

mismatched_epoch 🔗

mismatched_id 🔗

misplaced_epoch 🔗

missing_versions 🔗

model_compliance_error 🔗

model_error 🔗

multiple_roots 🔗

not_found 🔗

readonly 🔗

required_attribute_missing 🔗

server_error 🔗

This error MAY be used when it appears that the incoming request was valid but something unexpected happened in the server that caused an error condition.

too_large 🔗

too_many_versions 🔗

unknown_attribute 🔗

unknown_id 🔗

unsupported_specversion 🔗

versionid_not_allowed 🔗