# Graph Explorer Contract This note defines the first manifest and payload contract for the interactive Fabric map and the possible reusable graph explorer engine. The contract is intentionally host-neutral. Fabric and repo-scoping should be able to use the same interaction shell by exposing a manifest and a graph payload with stable fields. ## Files - `schemas/graph-explorer-manifest.schema.yaml` validates a host manifest. - `schemas/graph-explorer-payload.schema.yaml` validates graph payloads. - `railiance_fabric.graph_explorer` provides the first Fabric registry manifest and payload projection. ## Registry Endpoints The registry service exposes the first Fabric projection: ```text GET /ui/graph-explorer GET /exports/graph-explorer/manifest GET /exports/graph-explorer ``` The local CLI can emit the same payload for repo-local inspection: ```bash railiance-fabric export --format graph-explorer ``` The manifest tells a graph shell where to load data, which fields are stable, which layers exist, which filter fields are available, and which modes the host supports. Fabric currently declares `profile_persistence: local`. That means the shell stores named map views in browser `localStorage`, supports duplicate/delete inside that browser, and can copy a URL with the current query parameters and a state blob. Local profile ids can be reopened in the same browser profile; the copied state blob is the portable sharing path until a host-backed profile API is added. The payload is compatible with Cytoscape-style element arrays: ```json { "apiVersion": "railiance.fabric/v1alpha1", "kind": "GraphExplorerPayload", "manifest_id": "railiance-fabric.registry-map", "mode": "full", "elements": [ { "data": { "id": "repo:railiance-fabric", "stableKey": "repo:railiance-fabric", "kind": "Repository", "layer": "repository", "label": "Railiance Fabric", "displayState": "show" } } ], "hidden_elements": [] } ``` ## Required Payload Semantics Every element must include: - `id`: the current element id used by the graph library. - `stableKey`: the durable id used by profile rules, manual overrides, layout state, and deep links. - `kind`: host-specific entity kind. - `layer`: host-declared layer used for layout, grouping, and color. - `displayState`: one of `show`, `blur`, or `hide`. Edges are ordinary elements whose data also includes: - `source` - `target` - `edgeType` - `strength` - `sameLayer` Hosts should also include useful optional fields when available: `label`, `name`, `description`, `repo`, `domain`, `lifecycle`, `reviewState`, `freshnessState`, `confidence`, `visualSize`, `ownership`, `unresolved`, `sourceReferences`, and `deepLinks`. Edges may include layout hints used by the client-side layout engine: `sameRepo`, `sourceRepo`, `targetRepo`, `layoutAffinity`, `layoutIdealLength`, and `layoutElasticity`. Fabric uses these hints to keep same-repo entities closer than cross-repo dependencies. Deployment-to-server edges are intentionally shortest and most elastic; deployment-to-repo edges are longer and looser so infrastructure placement does not collapse into the repo node. ## Display State Ownership The contract allows either the host service or the engine to evaluate display state. The precedence rule is fixed: 1. Default element state is `show`. 2. Rules are applied in list order; later matching rules override earlier matching rules. 3. Manual overrides win last. 4. Edges connected to hidden nodes are hidden. 5. Edges connected to blurred nodes may carry a contextual muted class or data hint. Repo-scoping currently evaluates this host-side. A future extracted engine can evaluate it client-side for static exports, but host-provided `displayState` must remain valid input. ## Fabric Layers The first Fabric manifest declares: | Layer | Purpose | |-------|---------| | `repository` | Registered source repositories, including registered-only repos. | | `server` | Endpoint hosts inferred from registered interface URLs. | | `deployment` | Service deployment instances per declared environment. | | `service` | Service declarations. | | `capability` | Capability declarations. | | `interface` | Interface declarations. | | `dependency` | Dependency declarations, including unresolved dependency nodes. | | `binding` | Binding assertions between consumer dependencies and providers. | | `library` | Future library/SBOM inventory nodes. | ## Repo-Scoping Compatibility Repo-scoping can adapt without a rewrite because its current graph payload already exposes most required fields: - `id`, `stableKey`, `kind`, `layer`, labels, and metadata-rich data objects. - `displayState`, `visibilitySource`, and `visibilityReason`. - edge `source`, `target`, `dependencyType`, `strength`, `sameLayer`, and visual width. - profile data, filter rules, manual overrides, hidden elements, and orphaned overrides. The main adapter work is manifest generation and small field aliases: `dependencyType` can map to `edgeType`, repo-scoping layers become manifest layers, and existing profile endpoints can be listed under manifest `endpoints.profiles`. ## Extraction Boundary The extracted `graph-explorer-engine` should own: - graph rendering and layout controls - filter and manual override UI - hover popups and selection detail panels - profile UI when the host declares profile endpoints - browser-local profiles, URL state, and copied state blobs - schema definitions and compatibility tests Host repos should own: - graph projection and metadata enrichment - host-side profile persistence, when a repo needs shared/team profiles - authentication and authorization - domain-specific graph modes - deep links back to source systems