xRegistry Events
September 24, 2025 ยท View on GitHub
Abstract
This specification defines the events that an xRegistry server MAY generate.
Table of Contents
Overview
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" ]
}
}
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.
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.
Event Definition
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:
- Only one of
created,updatedordeletedevent MUST be generated persubject. - If the interaction involved more than one of those actions, then the single
event generated MUST be chosen in the following order of precedence:
deleted,created,updated. - Only one event with the same
typeandsubjectcombination MUST be generated.
The following sections specify the metadata defined for xRegistry events. Implementations MAY define additional metadata.
CloudEvent 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:createdupdateddeprecationdeleted
Not 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.
CloudEvent 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.
CloudEvent 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.
CloudEvent 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:
- MUST be a non-empty string.
- MUST be case-insensitively unique within the scope of the Registry instance, for the lifetime of the Registry.
- All events generated from the same interaction MUST have the same
xregcorrelationidvalue. 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.
CloudEvent 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
subjectentity. -
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-
nullvalues, and all attributes from the new default Version that have non-nullvalues. Any duplicate attribute names MUST be removed. -
This attribute MUST NOT appear on the
createdordeletedevents. -
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.
Entity Events
This section defines which <ACTION> values are applicable for each <ENTITY>
value.
registry Events
- Action:
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>countattributes names.While the
<GROUPS>attribute is present inchangeddue to the child collection changing, in order to see which specific Groups were impacted theio.xregistry.group.createdandio.xregistry.group.deletedevents would need to be examined. -
MUST be generated when
model,modelsourceorcapabilitiesare updated and the appropriate attribute MUST appear inchanged, 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
- Action:
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
changedlist. -
A
io.xregistry.registry.updatedevent will also be generated where themodelattribute will be included inchanged, 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
- Action:
updated-
MUST be generated when the Registry's
modelsourceattribute is updated. -
MUST NOT include a
changedlist. -
A
io.xregistry.registry.updatedevent will also be generated where themodelsourceattribute will be included inchanged, 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
- Action:
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.updatedevent will also be generated where thecapabilitiesattribute will be included inchanged, if present.
-
group Events
-
Action:
created-
MUST be generated when a new Group is created.
-
A
io.xregistry.registry.updatedevent will also be generated where the<GROUPS>and<GROUPS>countattributes will be included inchanged, 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>countattributes names.While the
<RESOURCES>attribute is present due to the child collection changing, in order to see which specific Resources were impacted theio.xregistry.resource.createdandio.xregistry.resource.deletedevents would need to be examined.This includes any updates to the
deprecatedsub-object, even though aio.xregistry.group.deprecationevent is also generated. And in that situation justdeprecatedwould be included inchanged, if present. To see which specific top-leveldeprecatedattributes were changed, theio.xregistry.group.deprecationevent would need to be examined.
-
-
Action:
deprecation-
MUST be generated when a Group's
deprecatedsub-object is set, deleted or any of its attributes updated, where "changed", if present, includes the list of top-level attribute names from thedeprecatedsub-object that were modified. -
A
io.xregistry.group.updatedevent will also be generated where thedeprecatedattribute will be included inchanged, if present.
-
-
Action:
deleted-
MUST be generated when a Group is deleted.
-
A
io.xregistry.registry.updatedevent will also be generated where the<GROUPS>and<GROUPS>countattributes will be included inchanged, 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.createdevent will also be generated since at least one Version will also be created. -
A
io.xregistry.registry.updatedevent will also be generated where the<RESOURCES>and<RESOURCES>countattributes will be included inchanged, 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
metaattribute is updated, wherechanged, if present, includes (at least) the changed top-levelmetaattributes names prefixed withmeta.. For example,meta.defaultversionid.This includes any updates to the
deprecatedsub-object, even though aio.xregistry.resource.deprecationevent is also generated. And in that situation justmeta.deprecatedwould be included inchanged, if present. To see which specific top-leveldeprecatedattributes were changed, theio.xregistry.resource.deprecationevent 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,versionsandversionscountattributes names.While the
versionattribute is present due to the child collection changing, in order to see which specific Versions were impacted theio.xregistry.version.createdandio.xregistry.version.deletedevents would need to be examined. -
Updating a Resource's
meta.defaultversionidattribute will generate aio.xregistry.resource.updatedevent but it MUST NOT generate aio.xregistry.version.updatedevent for either the prior or new default Version.
-
-
Action:
deprecation-
MUST be generated when a Resource's
meta.deprecatedsub-object is set, deleted or any of its attributes updated, where "changed", if present, includes the list of top-level attribute names from thedeprecatedsub-object that were modified. -
A
io.xregistry.resource.updatedevent will also be generated where thedeprecatedattribute will be included inchanged, if present.
-
-
Action:
deleted-
MUST be generated when a Resource is deleted.
-
A
io.xregistry.version.deletedevent will also be generated for each Version. -
A
io.xregistry.registry.updatedevent will also be generated where the<RESOURCES>and<RESOURCES>countattributes will be included inchanged, if present.
-
version Events
-
Action:
created-
MUST be generated when a new Version is created.
-
A
io.xregistry.resource.updatedevent will also be generated where theversionsandversionscountattributes will be included inchanged, if present.
-
-
Action:
updated- MUST be generated when a Version attribute is updated, where each modified
attribute MUST be included in
changed, if present.
- MUST be generated when a Version attribute is updated, where each modified
attribute MUST be included in
-
Action:
deleted-
MUST be generated when a Version is deleted.
-
A
io.xregistry.resource.updatedevent will also be generated where theversionsandversionscountattributes will be included inchanged, if present.
-
Sample xRegistry Interactions
In these examples, unless otherwise stated, assume that the Registry has the following model definition:
{
"groups": {
"dirs": {
"singular": "dir",
"resources": {
"files": {
"singular": "file"
}
}
}
}
}
Update a Registry attribute
- Interaction:
PATCH /- Body:
{ "name": "foo" }
- Events:
io.xregistry.registry.updated- Subject:
/ - Changed:
epoch,modifiedat,name
- Subject:
Create a tree of entities
- Empty Registry
- Interaction:
PUT /dirs/d1/files/f1/versions/v1- Body:
{}
- Events:
io.xregistry.registry.updated- Subject:
/ - Changed:
epoch,modifiedat,dirs,dirscount
- Subject:
io.xregistry.group.created- Subject:
/dirs/d1
- Subject:
io.xregistry.resource.created- Subject:
/dirs/d1/files/f1
- Subject:
io.xregistry.version.created- Subject:
/dirs/d1/files/f1/versions/v1
- Subject:
Update a Resource attribute (a default Version attribute)
- Current default Version is
v1 - Interaction:
PATCH /dirs/d1/files/f1- Body:
{ "name": "foo" }
- Events:
io.xregistry.resource.updated- Subject:
/dirs/d1/files/f1 - Changed:
epoch,modifiedat,name
- Subject:
io.xregistry.version.updated- Subject:
/dirs/d1/files/f1/version/v1 - Changed:
epoch,modifiedat,name
- Subject:
Update a Resource's meta sub-object
- Interaction:
PATCH /dirs/d1/files/f1/meta- Body:
{ "compatibilityauthority": "server" }
- Events:
io.xregistry.resource.updated- Subject:
/dirs/d1/files/f1 - Changed:
meta.epoch,meta.modifiedat,meta.compatibilityauthority
- Subject:
Update a Resource's meta sub-object and deprecate the Resource
- Interaction:
PATCH /dirs/d1/files/f1/meta- Body:
{ "compatibilityauthority": "server", "deprecated": {...} }
- Events:
io.xregistry.resource.updated- Subject:
/dirs/d1/files/f1 - Changed:
meta.epoch,meta.modifiedat,meta.compatibilityauthority,meta.deprecated
- Subject:
io.xregistry.resource.deprecation- Subject:
/dirs/d1/files/f1 - Changed:
<DEPRECATED-ATTRIBUTES-CHANGED-IF-ANY>
- Subject:
Import an entire Registry
- Empty Registry
- Interaction:
PUT /- Body: Registry attributes,
modelsource,capabilities, Groups, Resources, Versions
- Events:
io.xregistry.registry.updated- Subject:
/ - Changed:
epoch,modifiedat,model,modelsource,capabilities,<GROUPS>,<GROUPS>count,<OTHER-REGISTRY-ATTRIBUTES>
- Subject:
io.xregistry.model.updated- Subject:
/model
- Subject:
io.xregistry.modelsource.updated- Subject:
/modelsource
- Subject:
io.xregistry.capabilities.updated- Subject:
/capabilities
- Subject:
io.xregistry.group.createdfor each new Group- Subject:
/dirs/d1
- Subject:
io.xregistry.resource.createdfor each new Resource- Subject:
/dirs/d1/files/f1
- Subject:
io.xregistry.version.createdfor each new Version- Subject:
/dirs/d1/files/f1/versions/v1
- Subject:
Create a new Version - non-sticky
- Current default Version (v1) is not "sticky"
- Interaction:
PUT /dirs/d1/files/f1/versions/v2- Body:
{}
- Events:
io.xregistry.resource.updated- Subject:
/dirs/d1/files/f1 - Changed:
meta.defaultversionid,meta.epoch,meta.modifiedat,versions,versionscount,<ALL-OLD-AND-NEW-DEFAULT-VERSION-ATTRIBUTES>,
- Subject:
io.xregistry.version.created- Subject:
/dirs/d1/files/f1/versions/v2
- Subject:
Create a new Version - sticky
- Current default Version (v1) is "sticky"
- Interaction:
PUT /dirs/d1/files/f1/versions/v2- Body:
{}
- Events:
io.xregistry.resource.updated- Subject:
/dirs/d1/files/f1 - Changed:
meta.epoch,meta.modifiedat,versions,versionscount
- Subject:
io.xregistry.version.created- Subject:
/dirs/d1/files/f1/versions/v2
- Subject:
Change defaultversionid pointer
-
Current default Version is
v1 -
Interaction:
PATCH /dirs/d1/files/f1/meta- Body:
{ "defaultversionid": "v2" }
-
Events:
io.xregistry.resource.updated- Subject:
/dirs/d1/files/f1 - Changed:
meta.defaultversionid,meta.epoch,meta.modifiedat,<ALL-OLD-AND-NEW-DEFAULT-VERSION-ATTRIBUTES>
- Subject:
Note the no
io.xregistry.version.updatedevent is generated.
Update a Version attribute (the default Version)
- Current default Version is
v1 - Interaction:
PATCH /dirs/d1/files/f1/versions/v1- Body:
{ "name": "foo" }
- Events:
io.xregistry.resource.updated- Subject:
/dirs/d1/files/f1 - Changed:
epoch,modifiedat,name
- Subject:
io.xregistry.version.updated- Subject:
/dirs/d1/files/f1/version/v1 - Changed:
epoch,modifiedat,name
- Subject:
Update a Version attribute (not the default Version)
- Current default Version is
v1 - Interaction:
PATCH /dirs/d1/files/f1/versions/v2- Body:
{ "name": "foo" }
- Events:
io.xregistry.version.updated- Subject:
/dirs/d1/files/f1/version/v2 - Changed:
epoch,modifiedat,name
- Subject:
Create a new Version - not sticky
- Current default Version is
v1 - Interaction:
POST /dirs/d1/files/f1- Body:
{}
- Events:
io.xregistry.resource.updated- Subject:
/dirs/d1/files/f1 - Changed:
meta.defaultversionid,meta.epoch,meta.modifiedat,versions,versionscount,<ALL-OLD-AND-NEW-DEFAULT-VERSION-ATTRIBUTES>,
- Subject:
io.xregistry.version.created- Subject:
/dirs/d1/files/f1/version/v2
- Subject:
Create a new Version - sticky
- Current default Version is
v1 - Interaction:
POST /dirs/d1/files/f1- Body:
{}
- Events:
io.xregistry.resource.updated- Subject:
/dirs/d1/files/f1 - Changed:
meta.epoch,meta.modifiedat,versions,versionscount
- Subject:
io.xregistry.version.created- Subject:
/dirs/d1/files/f1/version/v2
- Subject:
Delete a Group
- Interaction:
DELETE /dirs/d1
- Events:
io.xregistry.registry.updated- Subject:
/ - Changed:
dirs,dirscount,epoch,modifiedat
- Subject:
io.xregistry.group.deleted- Subject:
/dirs/d1
- Subject:
io.xregistry.resource.deletedfor each deleted Resource- Subject:
/dirs/d1/files/f1
- Subject:
io.xregistry.version.deletedfor each deleted Version- Subject:
/dirs/d1/files/f1/versions/v1
- Subject:
Creating a Group with complete client HTTP message exchange
Client 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"
}