xRegistry Service Model - Version 1.0-rc2 🔗

Abstract 🔗

This document describes the xRegistry model definition language that is used to define custom Groups and Resources for use within an xRegistry.

Readers are strongly encouraged to read the core xRegistry specification to learn about xRegistry itself prior to reading this specification.

Table of Contents 🔗

Overview 🔗

This specification defines the format and features of the xRegistry model language. The xRegistry model is used to define the custom Groups, Resources and attributes of the entities managed within an xRegistry service instance. It will also define the semantics, and constraints, of modifying an existing model.

Notations and Terminology 🔗

Notational Conventions 🔗

This specification adheres to the Notational Conventions defined in the core xRegistry specification.

Terminology 🔗

This specification uses the following terms as defined in the core xRegistry specification:

Registry Model 🔗

The Registry model defines the Groups, Resources, attributes and changes to specification-defined attributes that define what a Registry instance supports. This information is intended to be used by tooling that does not have knowledge of the structure of the Registry in advance and therefore will need to dynamically discover it.

The following sections will go into the details of how to create, retrieve and edit the model of a Registry, while the xRegistry protocol binding specifications will define how the operations defined in this specification will be mapped to those protocols.

The overall format of a model definition is as follows:

{
  "description": "<STRING>", ?
  "documentation": "<URL>", ?
  "labels": { "<STRING>": "<STRING>" * }, ?
  "attributes": {                      # Registry-level extensions
    "<STRING>": {                      # Attribute name
      "name": "<STRING>",              # Same as attribute's key
      "type": "<TYPE>",                # boolean, string, 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 or not. Default=true
      "matchcase": <BOOLEAN>, ?        # Strings case-sensitive? Default=false
      "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>": {
          "siblingattributes": { ... } # Siblings to this "attribute"
        } *
      } ?
    } *
  },

  "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
      "modelcompatiblewith": "<URI>", ?  # Statement of compatibility
      "attributes": { ... }, ?           # See "attributes" above
      "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
          "modelcompatiblewith": "<URI>", ? # Statement of compatibility
          "maxversions": <UINTEGER>, ?   # Num Vers(>=0). Default=0, 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>, ? # Enforce single root. Default=false
          "validateformat": <BOOLEAN>, ?    # Do Version format checks. Default=false
          "validatecompatibility": <BOOLEAN>, ? # Do Version compat checks. Default=false
          "strictvalidation": <BOOLEAN>, ?  # Block unknown format/compat. Default=false
          "consistentformat": <BOOLEAN>, ?  # Same format for all Vers. Default=false
          "typemap": <MAP>, ?               # ContentType mappings
          "attributes": { ... }, ?          # Version attributes/extensions
          "resourceattributes": { ... }, ?  # Resource attributes/extensions
          "metaattributes": { ... } ?       # Meta attributes/extensions
        } *
      } ?
    } *
  } ?
}

The following describes the attributes of the Registry model:

description 🔗

labels 🔗

attributes 🔗

attributes.<STRING> 🔗

attributes.<STRING>.name 🔗

attributes.<STRING>.type 🔗

attributes.<STRING>.target 🔗

attributes.<STRING>.namecharset 🔗

attributes.<STRING>.description 🔗

attributes.<STRING>.enum 🔗

attributes.<STRING>.strict 🔗

attributes.<STRING>.matchcase 🔗

attributes.<STRING>.readonly 🔗

attributes.<STRING>.immutable 🔗

attributes.<STRING>.required 🔗

attributes.<STRING>.default 🔗

attributes.<STRING>.attributes 🔗

attributes.<STRING>.item 🔗

attributes.<STRING>.item.type 🔗

attributes.<STRING>.item.target 🔗

attributes.<STRING>.item.namecharset 🔗

attributes.<STRING>.item.attributes 🔗

attributes.<STRING>.item.item 🔗

attributes.<STRING>.ifvalues 🔗

groups 🔗

groups.<STRING> 🔗

groups.<STRING>.plural 🔗

groups.<STRING>.singular 🔗

groups.<STRING>.description 🔗

groups.<STRING>.icon 🔗

groups.<STRING>.labels 🔗

groups.<STRING>.modelversion 🔗

groups.<STRING>.modelcompatiblewith 🔗

groups.<STRING>.attributes 🔗

groups.<STRING>.ximportresources 🔗

groups.<STRING>.resources 🔗

groups.<STRING>.resources.` 🔗

groups.<STRING>.resources.<STRING>.plural 🔗

groups.<STRING>.resources.<STRING>.singular 🔗

groups.<STRING>.resources.<STRING>.description 🔗

groups.<STRING>.resources.<STRING>.icon 🔗

groups.<STRING>.resources.<STRING>.labels 🔗

groups.<STRING>.resources.<STRING>.modelversion 🔗

groups.<STRING>.resources.<STRING>.modelcompatiblewith 🔗

groups.<STRING>.resources.<STRING>.maxversions 🔗

groups.<STRING>.resources.<STRING>.setversionid 🔗

groups.<STRING>.resources.<STRING>.setdefaultversionsticky 🔗

groups.<STRING>.resources.<STRING>.hasdocument 🔗

groups.<STRING>.resources.<STRING>.versionmode 🔗

groups.<STRING>.resources.<STRING>.singleversionroot 🔗

groups.<STRING>.resources.<STRING>.validateformat 🔗

groups.<STRING>.resources.<STRING>.validatecompatibility 🔗

groups.<STRING>.resources.<STRING>.strictvalidation 🔗

groups.<STRING>.resources.<STRING>.consistentformat 🔗

groups.<STRING>.resources.<STRING>.typemap 🔗

groups.<STRING>.resources.<STRING>.attributes 🔗

groups.<STRING>.resources.<STRING>.resourceattributes 🔗

groups.<STRING>.resources.<STRING>.metaattributes 🔗


Clarifying the usage of the attributes, resourceattributes and metaattributes:

Retrieving the Registry Model 🔗

The Registry model is available in two forms:

The full "model" view can be thought of as a full schema definition of what the message exchanges with the server might look like. As such, it MUST include:

The "modelsource" view of the model is just what was provided by the user when the model was defined, or last edited. It is expected that this view of the model is much smaller than the full model and only includes domain-specific information. While specification-defined attributes MAY appear in this document, they are NOT RECOMMENDED since the server will automatically add them so users do not need to concern themselves with those details.

The modelsource document is always a semantic subset of the full model document.

xRegistry protocol binding specifications will typically define a way to retrieve these two model views as both stand-alone entities and inlined as part of the Registry entity.

For the sake of brevity, this specification doesn't include the full definition of the specification-defined attributes as part of the snippets of output. However, an example of a full model definition of a Registry can be can be found in this sample sample-model-full.json.

When retrieving the modelsource, the response MUST only include what was specified in the request to define the model - it MUST NOT include any auto-added specification defined metadata that will appear under model.

Creating or Updating the Registry Model 🔗

A server MAY support updating the model of a Registry via:

To enable support for a wide range of use cases, but to also ensure interoperability across implementations, the following rules have been defined with respect to how models are defined or updated:

Any specification attributes not included in a request to define, or update, a model MUST be included in the resulting full model. In other words, the full Registry's model consists of the specification-defined attributes overlaid with the attributes that are explicitly-defined as part of a modelsource update request.

Note: there is no mechanism defined to delete specification-defined attributes from the model.

Registries MAY support extension attributes to the model language (meaning, new attributes within the model definitions themselves), but only if the server supports them. Servers MUST generate an error (model_error) if a model definition includes unknown model language attributes.

Once a Registry has been created, changes to the model MAY be supported by server implementations. This specification makes no statement as to what types of changes are allowed beyond the following requirements:

Any request to update the model that does not adhere to those requirements MUST generate an error (model_compliance_error).

How the server guarantees that all entities in the Registry are compliant with the model is an implementation detail. For example, while it is NOT RECOMMENDED, it is valid for an implementation to modify (or even delete) existing entities to ensure model compliance. Instead, it is RECOMMENDED that the model update requests generate an error (model_compliance_error) if existing entities are not compliant.

For the purposes of validating that the existing entities in the Registry are compliant with the model, the mechanisms used to define the model (e.g. $include vs ximportresources vs defined locally) MUST NOT impact that analysis. In other words, model updates that have no semantic changes but rather switch between one of those 3 mechanisms MUST NOT invalidate any existing entities in the Registry.

Additionally, it is STRONGLY RECOMMENDED that model updates be limited to backwards compatible changes.

Implementations MAY choose to limit the types of changes made to the model, or not support model updates at all.

The xRegistry model definition used to create a sample xRegistry can be found here, while the resulting "full" model (with all of the system-defined aspects added) can be found here.

Reuse of Resource Definitions 🔗

When a Resource type definition is to be shared between Groups, rather than creating a duplicate Resource definition, the ximportresources mechanism MAY be used instead. The ximportresources attribute on a Group definition allows for a list of <XIDTYPE> references to other Resource types that are to be included within this Group.

For example, the following abbreviated model definition defines one Resource type (messages) under the messagegroups Group, that is also used by the endpoints Group.

"modelsource": {
  "groups": {
    "messagegroups": {
      "singular": "messagegroup",
      "resources": {
        "messages": {
          "singular": "message"
        }
      }
    },
    "endpoints": {
      "singular": "endpoint",
      "ximportresources": [ "/messagegroups/messages" ]
    }
  }
}

The format of the ximportresources specification is:

"ximportresources": [ "<XIDTYPE>", * ]

where:

Locally defined Resources MAY be defined within a Group that uses the ximportresources feature, however, Resource plural and singular values MUST be unique across all imported and locally defined Resources.

See Cross Referencing Resources for more additional information.

Includes in the xRegistry Model Data 🔗

There might be times when it is necessary for an xRegistry model to reuse portions of another xRegistry model defined elsewhere. Rather than forcing the duplication of the model definitions, an "include" type of JSON directive MAY be used.

The general formats of the include are:

"$include": "<PATH-TO-DOCUMENT>#<JSON-POINTER-IN-DOC>"

or

"$includes": [ "<PATH-TO-DOCUMENT>#<JSON-POINTER-IN-DOC>" * ]

where the first form specifies a single reference to be included, and the second form specifies multiple. The fragment (#...) portion is OPTIONAL.

For example:

"$include": "http://example.com/xreg-model.json#/groups/mygroup/attributes"

is asking for the attributes of a Group called mygroup to be included at this location of the current model definition.

These directives MAY be used in any JSON Object or Map entity in an xRegistry model definition. The following rules apply for how to process the include directive:

When the directives are used in a request to update the model, the server MUST resolve all includes prior to updating the model. The original (source) model definition, with any "include" directives, MUST be available via the modelsource attribute/entity. The expanded model (after the resolution of any includes, and after all specification-defined attributes have been added), MUST be available via the model attribute/entity. The directives MUST only be processed during the initial update of the model. In order to have them re-evaluated, a subsequent model update request (with those directive) MUST be sent.

When there is tooling used outside of the server, e.g. in an xRegistry client, if that tooling resolves the "include" directives prior to sending the model to the server, then the directives will not appear in the modelsource view of the the model. Ideally, tooling SHOULD allow users to choose whether the resolution of the directives are done locally or by the server.

Examples:

A model definition that includes xRegistry attributes from a file on a remote server, and adds the definition of one attribute to a Group named mygroups from an external Group named group1 in another xRegistry.

{
  "attributes": {
    "$include": "http://example.com/someattributes",
    "myattribute": {
      "name": "myattribute",
      "type": "string"
    }
  }
  "groups": {
    "mygroups": {
      "singular": "mygroup",
      "attributes": {
        "attr1": {
          "$include": "http://example.com/model#/groups/group1/attributes/attr1"
        }
        ... remainder of model excluded for brevity ...
      }
    }
  }
}

where http://example.com/someattributes might look like:

{
  "myattr": {
    "name": "myattr",
    "type": "string"
  }
}

and the second include target might look like:

{
  "name": "attr1",
  "type": "string"
}