Files
railiance-fabric/docs/ecosystem-registry-service.md

11 KiB

Ecosystem Registry Service Direction

This note compares Railiance Fabric with adjacent projects and standards before starting a service implementation for registering repositories, libraries, services, capabilities, interfaces, and dependencies.

Recommendation

Build a small Railiance Ecosystem Registry service as the API and indexed read model over repo-owned Fabric declarations.

The registry should not replace the fabric/ files in each repo. Repositories remain the source of truth. The service validates, snapshots, queries, and projects that model so agents, humans, and State Hub can interact with the ecosystem graph without cloning every repo or rerunning the local CLI.

The closest external model to compare against is CNCF xRegistry. xRegistry is specifically about metadata registries, with both file/document and API views. Railiance should borrow that shape where useful, especially for versioned resources, import/export, filtering, and contract registries. Railiance should not begin by claiming xRegistry compliance; it should keep a compatible path.

Standards And Projects To Compare

Project or standard What it is good at What Railiance should borrow What not to copy as the core
CNCF xRegistry Vendor-neutral metadata registries with REST APIs, document views, versioned resources, endpoint/schema/message extensions. Use as the primary comparison for registry API shape, versioned metadata, import/export, filtering, document/API symmetry, and future endpoint/message/schema projections. Do not make every Fabric concept an xRegistry resource on day one; keep the Railiance graph model readable and repo-native first.
Backstage Software Catalog Developer portal catalog entities such as Component, API, Resource, System, Domain, ownership, relations, and catalog-info.yaml. Support Backstage export/import projections for teams that want a portal later. Borrow the ownership and domain/system vocabulary where it aligns. Do not make Backstage the authoritative store or require its plugin/runtime model before Railiance needs a portal.
CycloneDX Supply-chain inventory for components, services, dependencies, relationships, and vulnerability/security context. Use CycloneDX SBOM/SaaSBOM imports for libraries, packages, third-party services, component dependency graphs, and provenance facets. Do not stretch CycloneDX into the whole ecosystem model; it is strongest for bill-of-materials and supply-chain evidence.
OpenAPI Machine-readable HTTP API contracts. Attach OpenAPI documents to Fabric InterfaceDeclaration records for HTTP APIs and expose them through the registry. Do not use OpenAPI to describe non-HTTP dependencies or ownership relationships.
AsyncAPI Machine-readable event/message-driven API contracts with channels, messages, operations, and protocol bindings. Attach AsyncAPI documents to event-stream interfaces and use its vocabulary for channel/message contracts. Do not use AsyncAPI for general service inventory.
CloudEvents Common event envelope metadata across services, platforms, and systems. Use CloudEvents as the preferred event envelope for registry events and for Fabric event interfaces when the ecosystem needs portable event metadata. Do not use CloudEvents as a catalog model; it is an event envelope.
Open Service Broker API Lifecycle commands for service catalogs, provisioning, binding, unbinding, and deprovisioning. Borrow the clear distinction between service catalog, service instance, and binding if Railiance later adds self-service provisioning. Do not implement provisioning as part of the initial registry; registration and discovery come first.
Score Platform-agnostic workload intent for container workloads, with runtime requirements resolved by a platform. Optionally import workload requirements into Fabric dependencies when repos already use Score. Do not make Score mandatory; it is workload runtime intent, not an ecosystem graph.
OpenLineage Job, run, dataset, and facet model for observing data movement and transformation. Use its facet idea for extensible metadata and consider data-lineage projections later. Do not use it as the general service/capability/dependency model.

Service Boundary

The registry service should own:

  • repository registration and repository metadata snapshots
  • ingestion of validated Fabric graph exports
  • validation results per repo and commit
  • indexed graph queries across all registered repos
  • version history and drift comparisons between snapshots
  • optional ingestion of supporting artifacts such as CycloneDX SBOMs, OpenAPI documents, AsyncAPI documents, and Score workload files
  • State Hub export or event emission for coordination views

The registry service should not own:

  • hand-editing repo declarations through a central UI
  • deployment orchestration
  • service provisioning
  • policy enforcement gates before the model has adoption
  • replacing State Hub workstreams, tasks, progress, or planning state
  • replacing a developer portal

Initial Data Model

Railiance Fabric already has first-class declarations for:

  • ServiceDeclaration
  • CapabilityDeclaration
  • InterfaceDeclaration
  • DependencyDeclaration
  • BindingAssertion

The registry service should add service-level records around those declarations:

Entity Purpose
Repository Registered source repo, URL, default branch, State Hub repo id, scan config, last accepted snapshot.
Snapshot Immutable ingest result for a repo at a commit.
Graph Node Indexed projection of a service, capability, interface, dependency, or binding.
Graph Edge Indexed relationship such as provides, exposes, consumes, binds, or uses interface.
Artifact Supporting document such as CycloneDX SBOM, OpenAPI, AsyncAPI, Score, README, or source link.
Validation Result Errors, warnings, schema versions, catalog versions, and unresolved references.
Registry Event Change event emitted when a repo, snapshot, node, edge, or validation result changes.

API Shape

Start with a small HTTP API that mirrors the local CLI answers:

POST /repositories
GET  /repositories
GET  /repositories/{repo_slug}

POST /repositories/{repo_slug}/snapshots
GET  /repositories/{repo_slug}/snapshots
GET  /repositories/{repo_slug}/snapshots/latest

GET  /graph/nodes
GET  /graph/nodes/{graph_id}
GET  /graph/providers?capability_type=runtime-secrets
GET  /graph/consumers?target=railiance-platform.openbao.kv-v2
GET  /graph/unresolved
GET  /graph/blast-radius?interface_id=openbao-kv-v2-mount

POST /artifacts
GET  /artifacts/{artifact_id}

GET  /exports/state-hub
GET  /exports/backstage
GET  /exports/xregistry

POST /repositories/{repo_slug}/snapshots should accept the current FabricGraphExport plus source metadata:

{
  "repo_slug": "railiance-fabric",
  "commit": "git-sha",
  "generated_at": "2026-05-17T00:00:00Z",
  "graph": {
    "apiVersion": "railiance.fabric/v1alpha1",
    "kind": "FabricGraphExport",
    "nodes": [],
    "edges": []
  }
}

Interoperability Direction

The first implementation should be Railiance-native but deliberately projection-friendly:

  • Backstage projection: export Component, API, Resource, System, and Domain entities from Fabric nodes where possible.
  • xRegistry projection: expose schemas, messages, endpoints, and possibly Fabric-specific registry groups once the internal model settles.
  • CycloneDX import: attach SBOM components, services, and dependencies to repo and service nodes.
  • OpenAPI/AsyncAPI attachment: connect contract documents to interface nodes and validate that declared interface type/version metadata is consistent.
  • CloudEvents events: emit registry changes such as railiance.fabric.repository.registered, railiance.fabric.snapshot.accepted, and railiance.fabric.validation.failed.
  • Score import: map workload resources and dependencies into draft Fabric dependency declarations only when a repo opts in.

Suggested Architecture

repo-local fabric/*.yaml
        |
        v
railiance-fabric validate/export
        |
        v
Ecosystem Registry ingest API
        |
        +--> snapshot store
        +--> graph index
        +--> artifact index
        +--> validation result store
        |
        +--> State Hub export/events
        +--> Backstage/xRegistry projections
        +--> query API for agents and humans

Keep the first service boring: the existing Python loader and validator should be reused. A lightweight Python HTTP service with a local relational store is enough for the first useful version. Once ingestion and query semantics are stable, the backing store can be replaced or expanded.

First Implementation Slice

  1. Service scaffold using the existing loader, validator, and graph export model.
  2. Repository registration endpoint with repo slug, URL, default branch, and optional State Hub repo id.
  3. Snapshot ingest endpoint that validates a FabricGraphExport and stores it atomically.
  4. Query endpoints for providers, consumers, unresolved dependencies, dependency paths, and blast radius.
  5. State Hub export endpoint matching docs/state-hub-integration.md.
  6. Contract attachment for OpenAPI and AsyncAPI documents.
  7. CycloneDX SBOM attachment for library/package inventory.
  8. CloudEvents-style registry events once mutation endpoints exist.

Open Design Questions

  • Should the registry pull repos itself, or should repos/agents push validated exports from CI? Push is simpler and keeps credentials narrower.
  • Should repository registration live first in State Hub and sync into Fabric Registry, or should Fabric Registry own its own repo registry and annotate State Hub ids? The current boundary suggests Fabric Registry owns graph registration, State Hub owns planning/coordination.
  • Should the first storage backend be SQLite for local operations or Postgres from the start? SQLite is enough for proving semantics; Postgres is better once multiple agents write concurrently.
  • Should xRegistry compatibility be a projection only, or should the internal registry model follow xRegistry group/resource/version terminology? Start as projection; revisit after the first API is exercised.