Skip to main content

Artifacts & Bindings - XTP Internals

Artifacts

XTP stores Host- and Guest-generated plugins as a series of versions of a single "artifact." This allows XTP to maintain a history of a single plugin over time, as the author pushes new versions (or "yanks" bad versions.)

XTP Artifacts function akin to language-specific package managers, like npm or cargo. Artifacts have a compound identifier that bakes in the extension point id, type of artifact, owner of artifact, and a unique name for that artifact. This identifier lets XTP assert certain useful facts about the artifact: who can see it, what can it be used for, and which Extension Point schema it is intended to satisfy.

An artifact is created (or updated) by the act of running xtp plugin push. The Extension Point id, current logged-in user, and name field of the xtp.toml are use to identify the artifact. This artifact version is tagged as the intended "latest" version. As part of the plugin pushing process, XTP runs validations against the artifact: first XTP built-in schema checks, followed by any host-configured simulation tests. Once these tests complete successfully, the artifact's "validated" tag will point at the newly-validated version. Any "bindings" that refer to that artifact will be updated to point at the new content.

Bindings

Bindings are the artifacts the host will see when their application queries a given extension point and guest. The data structure that hosts see when requesting bindings looks like this:

{
"blur": {
"id": "ext_01j29hxk3mfpq8ad68ha6hbsex/plugin/usr_01j29hxk3jeh594yxdr6ge618c/blur",
"contentAddress": "3vMIJEz1Y5bI0-GWhoQUuR90PCQAmYboWsKC2diep-c",
"updatedAt": "2024-07-01T00:00:00.000Z"
},
"sharpen": {
"id": "ext_01j29hxk3mfpq8ad68ha6hbsex/plugin/usr_01j29hxk3jeh594yxdr6ge618c/sharpen",
"contentAddress": "rMih78nuWJV5G-tzkvfAcHndsLC5E8jwRwI-rn8MB1o",
"updatedAt": "2024-05-01T00:31:00.000Z"
}
}

The contentAddress and updatedAt fields reflect the address at which hosts can request the plugin data from XTP and the time that plugin data was validated respectively.

The plugin data can be retrieved via an authenticated call to GET /api/v1/c/<content address>.

Binding content

Bindings represent a subscription to the latest "validated" version of an artifact and can be made in advance of a valid version of the plugin artifact (or indeed, of the plugin artifact itself.)

In those cases, the Host would simply see the id of the incoming plugin without any updatedAt or contentAddress content (or null values.). In the below example, there is no valid version of blur:

{
"blur": {
"id": "ext_01j29hxk3mfpq8ad68ha6hbsex/plugin/usr_01j29hxk3jeh594yxdr6ge618c/blur"
},
"sharpen": {
"id": "ext_01j29hxk3mfpq8ad68ha6hbsex/plugin/usr_01j29hxk3jeh594yxdr6ge618c/sharpen",
"contentAddress": "rMih78nuWJV5G-tzkvfAcHndsLC5E8jwRwI-rn8MB1o",
"updatedAt": "2024-05-01T00:31:00.000Z"
}
}

Hosts are expected to select a binding name according to their application's needs. Some hosts may require a specific name, some hosts may assign special meaning to the name, and some hosts may not care. Hosts that do not specify a specific binding name will receive the latest valid binding -- no matter the name -- determined by the "updatedAt" field.

It's currently the responsibility of the host to inform the guest what the expectations around binding names are. In the future XTP may offer ready-made workflows. If you have a specific need, let us know on Discord!

Binding aliases

Guests generally won't have to think about the difference between the two, but bindings allow a plugin to be advertised to the host under a name different than the plugin's name. This distinction is similar to how imports work in languages like Python and JavaScript -- compare import { foo } from 'bar' to import { foo as myFoo } from 'bar'. Most of the time, using the exported name locally is fine, but sometimes you can't, so you have to be able to "alias" or "rebind" it. This is a forward-looking XTP feature, predicting a future where guests can bind plugins written by third-party authors.

{
"myFoo": {
"id": "ext_01j29hxk3mfpq8ad68ha6hbsex/plugin/usr_01j29hxk3jeh594yxdr6ge618c/foo",
"contentAddress": "3vMIJEz1Y5bI0-GWhoQUuR90PCQAmYboWsKC2diep-c",
"updatedAt": "2024-07-01T00:00:00.000Z"
}
}

Plugin authors can control binding aliases via xtp plugin push --as <alias> or xtp binding --name <name>. By default, bindings are assigned to the name of the plugin.