# State Hub Integration Contract Railiance Fabric is the authoring and validation layer for ecosystem graph declarations. State Hub should ingest Fabric outputs as a read model for coordination, search, dashboards, and planning. It should not become the primary authoring surface for services, capabilities, interfaces, dependencies, or bindings. ## Source-Of-Truth Boundary | Layer | Owns | Does Not Own | |-------|------|--------------| | Participating repos | Declaration files under `fabric/` | Global graph interpretation | | Railiance Fabric | Schemas, type catalogs, validation, graph construction, exports | State Hub tasks/progress/decisions | | State Hub | Read-model storage, links to repos/workstreams/tasks/progress, dashboard/search views | Editing Fabric declarations | The flow is: ```text repo-local fabric/*.yaml | v railiance-fabric validate/export | v State Hub graph read model | v dashboard, search, planning, progress links ``` ## Export Shape The CLI emits `FabricGraphExport` JSON: ```bash railiance-fabric export --format json ``` Schema: `schemas/state-hub-export.schema.yaml` Top-level shape: ```yaml apiVersion: railiance.fabric/v1alpha1 kind: FabricGraphExport nodes: [] edges: [] ``` Node fields: | Field | Meaning | |-------|---------| | `id` | Stable graph id from declaration metadata. | | `kind` | Declaration kind: service, capability, interface, dependency, or binding. | | `name` | Human-readable name. | | `repo` | Owning repo slug. | | `domain` | Owning domain slug. | | `lifecycle` | Declaration lifecycle. | Edge fields: | Field | Meaning | |-------|---------| | `from` | Source node id. | | `to` | Target node id. | | `type` | Relationship type, such as `provides`, `exposes`, `available_via`, `consumes`, `binds:exact`, or `uses_interface`. | ## Proposed State Hub Read Model Add a State Hub ingestion endpoint or job that stores the latest graph export per source repo: ```text POST /fabric/graph-exports ``` Suggested payload: ```json { "repo_slug": "railiance-fabric", "commit": "", "generated_at": "2026-05-17T00:00:00Z", "graph": { "apiVersion": "railiance.fabric/v1alpha1", "kind": "FabricGraphExport", "nodes": [], "edges": [] } } ``` Suggested storage: ```text fabric_graph_exports id repo_id commit generated_at graph_json created_at fabric_graph_nodes export_id graph_id kind name repo_slug domain_slug lifecycle fabric_graph_edges export_id from_graph_id to_graph_id edge_type ``` The normalized node/edge tables are optional at first. State Hub can begin with `fabric_graph_exports.graph_json` and materialize node/edge tables once query needs harden. ## Linking To Existing State Hub Entities State Hub should enrich graph nodes by matching: - `node.repo` -> `managed_repos.slug` - `node.domain` -> `domains.slug` - workplan source links -> `workstreams.slug` or file-backed workplan index - progress events -> `repo_id` and related workstream/task when available These links are annotations on the read model. They should never overwrite the repo-owned declaration files. ## Ingestion Rules 1. Reject exports that fail `schemas/state-hub-export.schema.yaml`. 2. Record the source repo and commit for every accepted export. 3. Replace the previous latest export for the same repo only after the new export validates. 4. Preserve historical exports long enough to compare graph drift. 5. Surface validation errors as State Hub progress events or human-review tasks, but do not auto-edit declaration files. ## Initial Dashboard Queries State Hub should be able to answer: - providers for a capability type - consumers of a capability or interface - unresolved dependencies - blast radius for an interface id or type - graph nodes by repo/domain/lifecycle These are the same query families exposed locally by Railiance Fabric. The hub read model should match local answers for the same export.