8.11 Discovery manifests and external catalogues

A locally deployed bundle is useful even when its mount is opaque. Two newer surfaces make custom code easier to discover and distribute: a manifest describes one deployed bundle, while a catalogue publishes content-pinned bundles for tenants to install.

Give custom code a contract

Send an optional X-RS2-Manifest JSON header with the raw code-store deploy:

{
  "inputSchema":  { "type": "object", "properties": { "q": { "type": "string" } } },
  "outputSchema": { "type": "object" },
  "effect": "idempotent",
  "requestMediaType": "application/json",
  "responseMediaType": "application/json"
}

The runtime stores it beside the content-addressed bundle. It appears on the agent surface and in OpenAPI, so callers can see the schemas, media types, and retry safety of the custom action. storePattern: "store" can instead advertise a store-shaped custom service as an entity. The manifest is metadata and does not alter the bundle's content hash.

Register catalogues per tenant

"catalogues": [
  { "name": "acme", "url": "https://catalogues.acme.com/index.json" }
]

The operator must separately allowlist the catalogue and bundle hosts in serverConfig.catalogueHosts (10.7). With an empty allowlist, external catalogues are off. This two-sided rule lets a tenant choose what it wants to browse without granting it arbitrary server-side fetch.

The services mount exposes the flow:

Request Does
GET /services/catalogues Lists registrations and whether each host is operator-allowlisted
GET /services/catalogue/available Combines built-in services/adapters with external catalogue items; marks deployed versions installed
POST /services/catalogue/install {catalogue, name, version} Fetches the bundle, verifies its bytes hash to version, compile-checks, and stores it in /code/

Installation is deploy only. It never mounts the code and never invents capability grants. Take the returned code:<name>@<version> ref and add it as a service or adapter through the normal validated config edit.

A catalogue fetch that fails appears as an error entry rather than hiding the rest of the available list. A non-allowlisted host is refused before fetch, and a hash mismatch is rejected even when the host itself is trusted.

Part 9 now turns to the generated HTTP surface that exposes these contracts.


Previous: 8.10 Proxy and SMS services · Manual home · Next: Part 9 — The HTTP API & cross-cutting behavior →