This specification defines the events that an xRegistry server MAY generate.
As updates are made to entities within an xRegistry instance, events SHOULD be generated to notify interested parties of those changes. This specification defines the metadata associated with each event as [CloudEvent][https://cloudevents.io) context attributes. Whether CloudEvents are used in the generation/serialization of the events is OPTIONAL, but it is RECOMMENDED.
This specification does not mandate the mechanisms by which events are sent to consumers, nor does it mandate how consumers register interest in receiving events.
Below is a sample event serialized as a "structured" JSON CloudEvent due to a
Group's name being changed:
{
"specversion": "1.0",
"type": "io.xregistry.group.updated",
"source": "https://example.com",
"subject": "/dirs/d1",
"id": "A234-1234-1234",
"time": "2025-09-01T12:01:02Z",
"xregcorrelationid": "B9282-129301",
"data": {
"changed": [ "epoch", "modifiedat", "name" ]
}
}
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.
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/phase in the angled brackets. For example <NAME> might be expected
to be replaced by the "name" of the item being discussed.
Notification of changes to the entities within an xRegistry instance SHOULD be exposed as events. These changes could be the result of an end-user interaction with the Registry, or due to some other (possibly internal) processing of the Registry data.
A single interaction with the Registry MAY result in multiple events, however,
within the scope of one interaction (see
xregcorrelationid) the
following constraints apply:
created, updated or deleted event MUST be generated per
subject.deleted, created, updated.type and subject combination MUST be
generated.The following sections specify the metadata defined for xRegistry events. Implementations MAY define additional metadata.
type Core Context Attribute 🔗The type of action taken on the entity. The value MUST be of the form:
io.xregistry.<ENTITY>.<ACTION>
where:
<ENTITY> is the type of xRegistry entity
(subject) that was acted
upon. It MUST be one of:
registrymodelmodelsourcecapabilitiesgroupresourceversion<ACTION> is the operation performed on the entity. It MUST be one of:
createdupdateddeprecationdeletedNot all <ACTION> values are applicable to all entities. See the
Entity Events section for more information.
This context attribute MUST be present in each event.
source Core Context Attribute 🔗The xRegistry in which the entity exists. The value MUST be an absolute URL to the root of the xRegistry instance.
This context attribute MUST be present in each event.
subject Core Context Attribute 🔗The xid of the entity acted upon. While this attribute is OPTIONAL in the
CloudEvents specification, it is REQUIRED to be present in an xRegistry event.
Note: constructing a URL by appending the subject value to the source
value MUST result in an absolute URL to the entity (assuming any trailing /
on source is removed since XIDs always start with /).
This context attribute MUST be present in each event.
time Core Context Attribute 🔗The time of when the interaction occurred. This value MUST be the same for all events generated within the same interaction.
Its value MUST be an RFC3339 timestamp
normalized to UTC. Use of a time-zone notation is RECOMMENDED. The value
used SHOULD match the current date/time used by the Registry during the
processing of the interaction. Typically, this will be the modifiedat value
assigned to the entities being processed.
This context attribute is NOT REQUIRED to be present in the event, but is RECOMMENDED.
xregcorrelationid Extension Context Attribute 🔗A value that uniquely identifies the interaction in which one or more events occurred. This value has the following constraints:
xregcorrelationid value. Conceptually, this can be thought of as the
"transaction ID" of the interaction.When an interaction has a request-response message exchange pattern, and
xregcorrelationid values are included in resulting events, then the response
message for the interaction MUST include this value. In the case of an HTTP
interaction, the following HTTP header MUST be present in the response flow:
xRegistry-xregcorrelationid: <STRING>
This allows for clients to identify which events were generated as a result of each request-response operation.
This context attribute is NOT REQUIRED to be present in the event, but is RECOMMENDED.
data 🔗When present, and serialized in JSON, the data MUST be of the form:
{
"changed": [ "<STRING>", * ] ?
}
The changed attribute, when present, has the following constraints:
MUST be a list of the top-level attribute names (not values) that were
added, modified, or deleted for the subject entity.
In the case of changing a Resource's default Version pointer, the list MUST
include all attributes from the previous default Version that have non-null
values, and all attributes from the new default Version that have non-null
values. Any duplicate attribute names MUST be removed.
This attribute MUST NOT appear on the created or deleted events.
This specification does not mandate any particular order to the attribute names in the array.
There are certain events where non-top-level attributes are included, and
those will be noted in the Entity Events sections below.
When they do appear they MUST use the JSONPath dot (.) notation to express
the traversal to the attribute of interest.
If an entity is updated for multiple reasons during the processing of an
interaction, per the rules previously stated, only one updated event
will be generated. This means the attribute names of all impacted attributes
MUST be merged into one changed list.
While changed is OPTIONAL, it is RECOMMENDED to be present on event where
it is permitted due to its usefulness for consumers. However, if exposure of
this information would be inappropriate for some scenarios then it MAY be
excluded. For example, for privacy/security reasons.
While this specification only shows data being present when changed is
permitted, implementations MAY define their own metadata to be included
in the data of a CloudEvent.
This metadata (data) is NOT REQUIRED to be present in the event, but is
RECOMMENDED.
This section defines which <ACTION> values are applicable for each <ENTITY>
value.
registry Events 🔗updated
MUST be generated when a Registry's attribute is updated, where each
modified attribute MUST be included in changed, if present.
MUST be generated when a Group is created or deleted, where changed, if
present, includes (at least) epoch, modifiedat, <GROUPS> and
<GROUPS>count attributes names.
While the <GROUPS> attribute is present in changed due to the child
collection changing, in order to see which specific Groups were impacted
the io.xregistry.group.created and io.xregistry.group.deleted events
would need to be examined.
MUST be generated when model, modelsource or capabilities are
updated and the appropriate attribute MUST appear in changed, if present.
The io.xregistry.registry.created and io.xregistry.registry.updated events
are not defined as part of this specification as those operations are not
defined in the xRegistry specification. It is expected that the tooling that
performs those operations will define those events, if needed.
model Events 🔗updated
MUST be generated when the Registry's model is updated. This might occur
due to a user action (e.g. updating modelsource) or an internal (system)
action.
MUST NOT include a changed list.
A io.xregistry.registry.updated event will also be generated where the
model attribute will be included in changed, if present.
Often io.xregistry.model.updated and io.xregistry.modelsource.updated
will be generated at the same time since model updates are most likely done
by changing the modelsource attribute. However, since the model might
change for other reasons, users who are interested in all model changes need
to watch for io.xregistry.model.update events, not
io.xregistry.modelsource.updated events.
modelsource Events 🔗updated
MUST be generated when the Registry's modelsource attribute is updated.
MUST NOT include a changed list.
A io.xregistry.registry.updated event will also be generated where the
modelsource attribute will be included in changed, if present.
Often io.xregistry.model.updated and io.xregistry.modelsource.updated
will be generated at the same time since model updates are most likely done
by changing the modelsource attribute. However, since the model might
change for other reasons, users who are only interested in changes related
to user modifications of the model need to watch for
io.xregistry.modelsource.update events, not io.xregistry.model.updated
events.
capabilities Events 🔗updated
MUST be generated when a Registry's capabilities are updated, where
the top-level capability names are included in changed, if present.
A io.xregistry.registry.updated event will also be generated where the
capabilities attribute will be included in changed, if present.
group Events 🔗Action: created
MUST be generated when a new Group is created.
A io.xregistry.registry.updated event will also be generated where the
<GROUPS> and <GROUPS>count attributes will be included in changed,
if present.
Action: updated
MUST be generated when a Group's attribute is updated, where each modified
attribute MUST be included in changed, if present.
MUST be generated when a Resource is created or deleted, where changed,
if present, includes (at least) epoch, modifiedat, <RESOURCES> and
<RESOURCES>count attributes names.
While the <RESOURCES> attribute is present due to the child
collection changing, in order to see which specific Resources were impacted
the io.xregistry.resource.created and io.xregistry.resource.deleted
events would need to be examined.
This includes any updates to the deprecated sub-object, even
though a io.xregistry.group.deprecation event is also generated. And
in that situation just deprecated would be included in changed,
if present. To see which specific top-level deprecated attributes were
changed, the io.xregistry.group.deprecation event would need to be
examined.
Action: deprecation
MUST be generated when a Group's deprecated sub-object is set,
deleted or any of its attributes updated, where "changed", if present,
includes the list of top-level attribute names from the deprecated
sub-object that were modified.
A io.xregistry.group.updated event will also be generated where the
deprecated attribute will be included in changed, if present.
Action: deleted
MUST be generated when a Group is deleted.
A io.xregistry.registry.updated event will also be generated where the
<GROUPS> and <GROUPS>count attributes will be included in changed, if
present.
resource Events 🔗Action: created
MUST be generated when a new Resource is created, where each modified
attribute MUST be included in changed, if present.
At least one io.xregistry.version.created event will also be
generated since at least one Version will also be created.
A io.xregistry.registry.updated event will also be generated where the
<RESOURCES> and <RESOURCES>count attributes will be included in
changed, if present.
Action: updated
MUST be generated when a Resource's (default Version) attribute is updated,
where each modified attribute MUST be included in changed, if present.
MUST be generated when a Resource's meta attribute is updated, where
changed, if present, includes (at least) the changed top-level meta
attributes names prefixed with meta.. For example,
meta.defaultversionid.
This includes any updates to the deprecated sub-object, even
though a io.xregistry.resource.deprecation event is also generated. And
in that situation just meta.deprecated would be included in changed,
if present. To see which specific top-level deprecated attributes were
changed, the io.xregistry.resource.deprecation event would need to be
examined.
MUST be generated when a Version is created or deleted, where changed,
if present, includes (at least) meta.epoch, meta.modifiedat,
versions and versionscount attributes names.
While the version attribute is present due to the child
collection changing, in order to see which specific Versions were impacted
the io.xregistry.version.created and io.xregistry.version.deleted
events would need to be examined.
Updating a Resource's meta.defaultversionid attribute will
generate a io.xregistry.resource.updated event but it MUST NOT generate
a io.xregistry.version.updated event for either the prior or new default
Version.
Action: deprecation
MUST be generated when a Resource's meta.deprecated sub-object is set,
deleted or any of its attributes updated, where "changed", if present,
includes the list of top-level attribute names from the deprecated
sub-object that were modified.
A io.xregistry.resource.updated event will also be generated where the
deprecated attribute will be included in changed, if present.
Action: deleted
MUST be generated when a Resource is deleted.
A io.xregistry.version.deleted event will also be generated for
each Version.
A io.xregistry.registry.updated event will also be generated where the
<RESOURCES> and <RESOURCES>count attributes will be included in
changed, if present.
version Events 🔗Action: created
MUST be generated when a new Version is created.
A io.xregistry.resource.updated event will also be generated where the
versions and versionscount attributes will be included in changed, if
present.
Action: updated
changed, if present.Action: deleted
MUST be generated when a Version is deleted.
A io.xregistry.resource.updated event will also be generated where the
versions and versionscount attributes will be included in changed, if
present.
In these examples, unless otherwise stated, assume that the Registry has the following model definition:
{
"groups": {
"dirs": {
"singular": "dir",
"resources": {
"files": {
"singular": "file"
}
}
}
}
}
PATCH /{ "name": "foo" }io.xregistry.registry.updated
/epoch, modifiedat, namePUT /dirs/d1/files/f1/versions/v1{}io.xregistry.registry.updated
/epoch, modifiedat, dirs, dirscountio.xregistry.group.created
/dirs/d1io.xregistry.resource.created
/dirs/d1/files/f1io.xregistry.version.created
/dirs/d1/files/f1/versions/v1v1PATCH /dirs/d1/files/f1{ "name": "foo" }io.xregistry.resource.updated
/dirs/d1/files/f1epoch, modifiedat, nameio.xregistry.version.updated
/dirs/d1/files/f1/version/v1epoch, modifiedat, namePATCH /dirs/d1/files/f1/meta{ "compatibilityauthority": "server" }io.xregistry.resource.updated
/dirs/d1/files/f1meta.epoch, meta.modifiedat, meta.compatibilityauthorityPATCH /dirs/d1/files/f1/meta{ "compatibilityauthority": "server", "deprecated": {...} }io.xregistry.resource.updated
/dirs/d1/files/f1meta.epoch, meta.modifiedat, meta.compatibilityauthority,
meta.deprecatedio.xregistry.resource.deprecation
/dirs/d1/files/f1<DEPRECATED-ATTRIBUTES-CHANGED-IF-ANY>PUT /modelsource, capabilities, Groups,
Resources, Versionsio.xregistry.registry.updated
/epoch, modifiedat, model, modelsource, capabilities,
<GROUPS>, <GROUPS>count, <OTHER-REGISTRY-ATTRIBUTES>io.xregistry.model.updated
/modelio.xregistry.modelsource.updated
/modelsourceio.xregistry.capabilities.updated
/capabilitiesio.xregistry.group.created for each new Group
/dirs/d1io.xregistry.resource.created for each new Resource
/dirs/d1/files/f1io.xregistry.version.created for each new Version
/dirs/d1/files/f1/versions/v1PUT /dirs/d1/files/f1/versions/v2{}io.xregistry.resource.updated
/dirs/d1/files/f1meta.defaultversionid, meta.epoch, meta.modifiedat,
versions, versionscount,
<ALL-OLD-AND-NEW-DEFAULT-VERSION-ATTRIBUTES>,io.xregistry.version.created
/dirs/d1/files/f1/versions/v2PUT /dirs/d1/files/f1/versions/v2{}io.xregistry.resource.updated
/dirs/d1/files/f1meta.epoch, meta.modifiedat, versions, versionscountio.xregistry.version.created
/dirs/d1/files/f1/versions/v2defaultversionid pointer 🔗Current default Version is v1
Interaction:
PATCH /dirs/d1/files/f1/meta{ "defaultversionid": "v2" }Events:
io.xregistry.resource.updated
/dirs/d1/files/f1meta.defaultversionid, meta.epoch, meta.modifiedat,
<ALL-OLD-AND-NEW-DEFAULT-VERSION-ATTRIBUTES>Note the no io.xregistry.version.updated event is generated.
v1PATCH /dirs/d1/files/f1/versions/v1{ "name": "foo" }io.xregistry.resource.updated
/dirs/d1/files/f1epoch, modifiedat, nameio.xregistry.version.updated
/dirs/d1/files/f1/version/v1epoch, modifiedat, namev1PATCH /dirs/d1/files/f1/versions/v2{ "name": "foo" }io.xregistry.version.updated
/dirs/d1/files/f1/version/v2epoch, modifiedat, namev1POST /dirs/d1/files/f1{}io.xregistry.resource.updated
/dirs/d1/files/f1meta.defaultversionid, meta.epoch, meta.modifiedat,
versions, versionscount,
<ALL-OLD-AND-NEW-DEFAULT-VERSION-ATTRIBUTES>,io.xregistry.version.created
/dirs/d1/files/f1/version/v2v1POST /dirs/d1/files/f1{}io.xregistry.resource.updated
/dirs/d1/files/f1meta.epoch, meta.modifiedat, versions, versionscountio.xregistry.version.created
/dirs/d1/files/f1/version/v2DELETE /dirs/d1io.xregistry.registry.updated
/dirs, dirscount, epoch, modifiedatio.xregistry.group.deleted
/dirs/d1io.xregistry.resource.deleted for each deleted Resource
/dirs/d1/files/f1io.xregistry.version.deleted for each deleted Version
/dirs/d1/files/f1/versions/v1Client Request:
PUT /dirs/d1
Host: example.com
Content-Type: application/json
{}
xRegistry Response:
HTTP/1.1 200 OK
Content-Type: application/json
Date: Wed, 02 Jul 2025 12:00:01 GMT
xRegistry-xregcorrelationid: B9282-129301
{
"dirid": "d1",
"self": "http://example.com/dirs/d1",
"xid": "/dirs/d1",
"epoch": 1,
"createdat": "2025-07-02T12:00:01Z",
"modifiedat": "2025-07-02T12:00:01Z",
"filesurl": "http://example.com/dirs/d1/files",
"filescount": 0
}
Events Generated:
{
"specversion": "1.0",
"type": "io.xregistry.registry.updated",
"source": "https://example.com",
"subject": "/",
"id": "A234-1234-1234",
"time": "2025-07-02T12:00:01Z",
"xregcorrelationid": "B9282-129301",
"data": {
"changed": [ "dirs", "dirscount", "epoch", "modifiedat" ]
}
}
{
"specversion": "1.0",
"type": "io.xregistry.group.created",
"source": "https://example.com",
"subject": "/dirs/d1",
"id": "A432-4321-4321",
"time": "2025-07-02T12:00:01Z",
"xregcorrelationid": "B9282-129301"
}