# NBGM Specification v0.1 Network-Based Graph Model (NBGM) baseline for Vantage Point. **Status:** draft baseline **Version:** `vantage.nbgm/v0.1` **Related:** `INTENT.md`, `SCOPE.md` --- ## 1. Purpose This document defines the domain-agnostic graph model that Vantage Point uses to represent, inspect, and reason about dependency structures. An NBGM is a typed graph of entities (nodes) and relationships (edges) with attributes and provenance. Meaning is not baked into the core model. Domains attach interpretation through bindings, lenses, and vantage points. The vocabulary is grounded in Tamara Munzner's nested design model and the Network-Based Graph Model framing in Meyer, Sedlmair, and Munzner ([BELIV 2012](https://miriah.github.io/publications/nbgm-beliv.pdf)). In that framing, a **network** is a data-abstraction block: nodes, links, and attributes are the structural primitives on which tasks, encodings, and algorithms are stacked. ### 1.1 Scope of v0.1 In scope: - core identity and typing rules for nodes and edges - attribute model and namespaces - provenance and lineage - a baseline catalog of inspection operations - alignment notes for repo-native graph bindings (for example Railiance Fabric) Out of scope for v0.1: - storage engines, query languages, or visualization encodings - domain-specific node/edge type catalogs - lens and vantage-point configuration schemas - validation tooling and serialization formats (future workplans) ### 1.2 Design principles 1. **Neutral core, interpreted surface.** The model stores facts; bindings supply domain semantics. 2. **Inspectable by default.** Every element should be explainable: what it is, why it exists, and how it was derived. 3. **Provenance over assertion.** Observed and derived facts carry origin, method, confidence, and freshness. 4. **Perspective-friendly structure.** The same graph supports multiple inspection operations without duplicating source data. 5. **Composable bindings.** Repo-native declarations, scanners, and exports can project into NBGM without becoming the authoring authority. --- ## 2. Terminology | Term | Definition | |------|------------| | **Graph** | A bounded collection of nodes and edges sharing one identity and metadata envelope. | | **Node** | An entity vertex with stable identity, kind, and attributes. | | **Edge** | A directed or undirected relationship between two nodes. | | **Kind** | A domain-defined type label for a node or edge (for example `Service`, `requires`). | | **Attribute** | A named property on a node or edge, optionally typed and namespaced. | | **Provenance** | Metadata describing how and when a fact entered the graph. | | **Binding** | A domain projection that maps external declarations or observations into NBGM elements. | | **Lens** | A named interpretation layer that selects, re-labels, or aggregates graph elements for a task. | | **Vantage point** | A saved or ephemeral lens plus inspection context (focus, depth, filters). | | **Inspection operation** | A read-only graph query or explanation primitive. | --- ## 3. Graph envelope Every NBGM instance is wrapped in a graph envelope. ```yaml apiVersion: vantage.nbgm/v0.1 kind: Graph metadata: id: example.ecosystem title: Example ecosystem graph domain: infotech # optional binding domain created_at: "2026-06-24T00:00:00Z" updated_at: "2026-06-24T00:00:00Z" source_bindings: - binding_id: railiance-fabric.export source_ref: railiance-fabric/registry spec: node_count: 0 # informational; implementations may omit edge_count: 0 default_direction: directed ``` ### 3.1 Required envelope fields | Field | Requirement | |-------|-------------| | `apiVersion` | Must be `vantage.nbgm/v0.1` for this revision. | | `kind` | Must be `Graph`. | | `metadata.id` | Stable graph identifier. Prefer dotted, lower-case slugs. | | `metadata.title` | Human-readable graph name. | | `metadata.updated_at` | ISO-8601 timestamp of last material change. | | `spec.default_direction` | `directed` or `undirected`. Edge-level direction may override. | ### 3.2 Optional envelope fields - `metadata.domain` — primary interpretation domain for the graph. - `metadata.created_at` — first materialization time. - `metadata.source_bindings[]` — list of bindings that produced or refreshed the graph. - `metadata.labels` — arbitrary string tags for indexing and filtering. - `metadata.description` — narrative summary of graph intent and coverage. --- ## 4. Nodes A node represents one addressable entity in the modeled system. ```yaml kind: Node metadata: id: railiance-platform.openbao stable_key: railiance-platform.openbao # durable id across renames name: OpenBao labels: repo: railiance-platform domain: railiance spec: node_kind: Service lifecycle: active # planned | active | deprecated | retired layer: service # optional stratification hint attributes: core: description: Runtime secrets service display: label: OpenBao visual_weight: 1.0 provenance: assertion_type: declared # declared | observed | derived | inferred sources: - ref: fabric/services/openbao.yaml method: declaration_load observed_at: "2026-06-24T00:00:00Z" confidence: 1.0 freshness_state: current # current | stale | unknown ``` ### 4.1 Identity rules 1. `metadata.id` is unique within a graph. 2. `metadata.stable_key` is optional but recommended when display ids may change. Profile rules, deep links, and temporal comparison should prefer `stable_key` when present. 3. IDs should be stable across re-ingestion when the underlying entity is unchanged. Bindings must document their ID strategy. ### 4.2 Required node fields | Field | Requirement | |-------|-------------| | `metadata.id` | Unique node identifier. | | `spec.node_kind` | Domain-defined entity kind. | | `provenance.assertion_type` | How the node fact was obtained. | | `provenance.sources[]` | At least one source record for non-synthetic nodes. | ### 4.3 Recommended node fields | Field | Purpose | |-------|---------| | `metadata.name` | Short display name. | | `metadata.labels` | Cross-cutting indices (`repo`, `domain`, `environment`, etc.). | | `spec.lifecycle` | Entity lifecycle state. | | `spec.layer` | Layer or stratum for layout and filtering. | | `attributes.core` | Domain-neutral or lightly-bound descriptive fields. | | `provenance.confidence` | Numeric confidence in `[0, 1]`. | | `provenance.freshness_state` | Whether the fact is current enough to trust for the active task. | ### 4.4 Node kinds `spec.node_kind` is binding-defined. Vantage Point does not mandate a global ontology in v0.1. Bindings should publish their kind catalog and mapping rules. Examples from existing ecosystem graphs: | Binding | Example node kinds | |---------|-------------------| | Railiance Fabric | `Repository`, `Service`, `Capability`, `Interface` | | Repo-scoping | `Fact`, `Evidence`, `Feature`, `Capability`, `Ability`, `Scope` | Bindings may attach additional kind metadata under `attributes.binding.*` but must not overload `spec.node_kind` with multiple meanings. --- ## 5. Edges An edge represents a relationship between exactly two nodes. ```yaml kind: Edge metadata: id: railiance-platform.state-hub.requires.runtime-secrets stable_key: railiance-platform.state-hub->runtime-secrets spec: edge_kind: requires source_id: railiance-platform.state-hub target_id: railiance-platform.openbao direction: directed # directed | undirected cardinality: many_to_one # optional: one_to_one | one_to_many | many_to_one | many_to_many strength: required # optional qualitative or numeric weight same_layer: false attributes: core: criticality: high environments: [dev, staging, prod] provenance: assertion_type: declared sources: - ref: fabric/dependencies/state-hub-runtime-secrets.yaml method: declaration_load observed_at: "2026-06-24T00:00:00Z" confidence: 1.0 freshness_state: current ``` ### 5.1 Required edge fields | Field | Requirement | |-------|-------------| | `metadata.id` | Unique edge identifier within the graph. | | `spec.edge_kind` | Domain-defined relationship type. | | `spec.source_id` | Existing node `metadata.id`. | | `spec.target_id` | Existing node `metadata.id`. | | `spec.direction` | `directed` or `undirected`. | | `provenance` | Same minimum provenance requirements as nodes. | ### 5.2 Edge semantics - **Directed edges** express dependency, production, consumption, containment, or influence from `source_id` to `target_id`. - **Undirected edges** express equivalence, association, or co-location when direction would be misleading. - `spec.same_layer: true` marks intra-layer normalization or peer links that should be visually and analytically distinct from cross-layer dependencies. - `spec.strength` may be categorical (`required`, `optional`, `weak`) or numeric. Bindings must document their scale. ### 5.3 Multi-edges Multiple edges may connect the same node pair when they differ in `edge_kind`, binding origin, or distinguishing attributes. Re-ingestion should update the same logical edge in place when `metadata.stable_key` or a binding-supplied dedupe key matches. --- ## 6. Attributes Attributes carry descriptive, analytical, and presentational facts on nodes and edges. They are grouped by namespace to keep the neutral core separable from binding-specific and display-specific data. ### 6.1 Namespaces | Namespace | Purpose | Examples | |-----------|---------|----------| | `core` | Stable descriptive fields useful across lenses | `description`, `owner`, `version` | | `display` | Presentation hints for explorers | `label`, `color`, `visual_weight`, `display_state` | | `analytical` | Metrics and derived indicators | `fan_in`, `cycle_member`, `cluster_id` | | `binding` | Binding-private structured payload | Fabric deployment overlays, scanner hashes | | `temporal` | Time-oriented fields | `valid_from`, `valid_to`, `observed_at` | Namespaces are conventional in v0.1. Implementations may store them as nested objects (`attributes.core.description`) or flattened keys with a prefix (`core.description`). ### 6.2 Attribute records Each attribute SHOULD be representable as: ```yaml name: description namespace: core value: Runtime secrets service value_type: string # string | number | boolean | enum | object | array | timestamp cardinality: single # single | multi mutable: true # whether re-ingestion may change this field in place source: declared # declared | observed | derived | inferred ``` ### 6.3 Typing and validation v0.1 does not mandate a global attribute schema. Bindings SHOULD publish: - allowed attributes per node/edge kind - value types and enumerations - required vs optional attributes - deprecation notes for renamed attributes Inspection operations must treat unknown attributes as opaque but returnable. ### 6.4 Display state When a graph is prepared for interactive exploration, elements may carry a display attribute: | Value | Meaning | |-------|---------| | `show` | Fully visible with normal styling and labels. | | `blur` | Visible but de-emphasized; details on hover or selection. | | `hide` | Excluded from the active view but retained in the source graph. | Display state is a vantage-point concern. It does not change graph truth data. --- ## 7. Provenance Provenance makes graph facts auditable. Every node and edge MUST include a provenance block sufficient to answer: 1. How was this fact introduced? 2. From what source material or observation? 3. How much should an operator trust it right now? ### 7.1 Assertion types | Type | Meaning | |------|---------| | `declared` | Authored by a repo-local declaration or human assertion. | | `observed` | Captured from runtime, repository scan, or external system query. | | `derived` | Computed from other graph elements or transformations. | | `inferred` | Produced by heuristic or ML extraction with weaker guarantees. | ### 7.2 Source records Each `provenance.sources[]` entry SHOULD include: | Field | Requirement | |-------|-------------| | `ref` | Pointer to source artifact (path, URL, export id, scan id). | | `method` | Binding-specific ingestion or transformation step. | | `observed_at` | ISO-8601 timestamp for when the source was read or captured. | Optional source fields: - `actor` — human, service, or agent that triggered ingestion - `version` — source artifact version or commit - `checksum` — content hash for reproducibility - `notes` — free-text operator context ### 7.3 Confidence and freshness - `confidence` is a float in `[0, 1]`. Bindings should define default confidence by assertion type when not explicitly set. - `freshness_state` is one of `current`, `stale`, or `unknown`. - `freshness_evaluated_at` MAY record when freshness was last assessed. Derived and inferred facts SHOULD reference upstream source ids or derivation recipes under `provenance.derived_from[]`: ```yaml provenance: assertion_type: derived derived_from: - node_id: repo:railiance-fabric - edge_id: railiance-fabric.state-hub.requires.runtime-secrets derivation: method: impact_closure recipe_version: "1" ``` ### 7.4 Lineage inspection Provenance must be sufficient for the `explain` inspection operation (see section 8.6) to reconstruct a human-readable chain from source artifacts to the displayed fact. --- ## 8. Inspection operations Inspection operations are read-only primitives over an NBGM graph. They are the stable API surface between graph stores, agents, and vantage-point UIs. Implementations MAY expose additional operations but SHOULD support the v0.1 baseline set or declare partial support explicitly. ### 8.1 Operation envelope Operation requests and responses use a common envelope: ```yaml apiVersion: vantage.nbgm/v0.1 kind: InspectionRequest metadata: operation: neighborhood graph_id: example.ecosystem spec: parameters: {} ``` ```yaml apiVersion: vantage.nbgm/v0.1 kind: InspectionResponse metadata: operation: neighborhood graph_id: example.ecosystem spec: complete: true result: {} warnings: [] ``` ### 8.2 `lookup` **Purpose:** Fetch one node or edge by id or stable key. | Parameter | Required | Description | |-----------|----------|-------------| | `element_type` | yes | `node` or `edge` | | `id` | one of | Primary identifier | | `stable_key` | one of | Durable identifier | **Result:** The matching element or `not_found`. ### 8.3 `neighborhood` **Purpose:** Expand around a focus node to a controlled depth. | Parameter | Required | Description | |-----------|----------|-------------| | `focus_id` | yes | Starting node id | | `depth` | yes | Hop count (1–N) | | `edge_kinds` | no | Relationship filter | | `direction` | no | `out`, `in`, or `both` (default `both`) | | `max_nodes` | no | Safety cap | **Result:** Subgraph of nodes and edges reachable under the parameters. ### 8.4 `path` **Purpose:** Find connecting paths between nodes for dependency or impact analysis. | Parameter | Required | Description | |-----------|----------|-------------| | `source_id` | yes | Start node | | `target_id` | yes | End node | | `edge_kinds` | no | Allowed relationship types | | `max_depth` | no | Search bound | | `strategy` | no | `shortest`, `all_bounded`, or `weighted` | **Result:** Zero or more paths, each an ordered list of node and edge ids. ### 8.5 `filter` **Purpose:** Select a subgraph by declarative predicates. | Parameter | Required | Description | |-----------|----------|-------------| | `predicate` | yes | Structured filter over kinds, labels, attributes, lifecycle, freshness | | `include_isolated` | no | Keep nodes with no matching edges (default false) | **Result:** Induced subgraph containing matching elements and connecting edges when requested. ### 8.6 `explain` **Purpose:** Produce a human- and agent-readable justification for an element. | Parameter | Required | Description | |-----------|----------|-------------| | `element_type` | yes | `node` or `edge` | | `id` | yes | Element identifier | | `include_derivation` | no | Expand derived-from chain (default true) | **Result:** - element summary - provenance sources and timestamps - confidence and freshness assessment - optional upstream path for derived/inferred facts ### 8.7 `summarize` **Purpose:** Aggregate statistics for a subgraph or whole graph. | Parameter | Required | Description | |-----------|----------|-------------| | `scope` | no | Whole graph or subgraph selector | | `metrics` | no | Requested aggregates | **Default metrics:** - counts by `node_kind` and `edge_kind` - unresolved or stale fact counts - top hubs by in-degree and out-degree - connected component count ### 8.8 `compare` **Purpose:** Diff two graph snapshots that share identity rules. | Parameter | Required | Description | |-----------|----------|-------------| | `baseline_graph` | yes | Reference graph id or snapshot | | `candidate_graph` | yes | Graph to compare | | `match_key` | no | `id` or `stable_key` (default `stable_key`) | **Result:** - `added`, `removed`, and `changed` nodes and edges - attribute-level deltas for changed elements - provenance changes when sources or confidence differ ### 8.9 `violations` **Purpose:** Evaluate structural expectations declared by a binding or lens. | Parameter | Required | Description | |-----------|----------|-------------| | `rule_set` | yes | Binding-published constraint set | | `severity_at_least` | no | Minimum severity to return | **Result:** List of violations with element refs, rule id, severity, and recommended inspection follow-up. ### 8.10 Operation composition Vantage points compose inspection operations rather than mutating the graph: ```text filter(layer=service) -> neighborhood(focus=selected, depth=2, edge_kinds=[requires]) -> summarize(metrics=[hub_rank]) -> explain(id=top_hub) ``` Bindings and lenses may publish recommended operation chains for common tasks. --- ## 9. Binding alignment NBGM is intentionally abstract. Existing repo-native graph models should project into it without losing source-of-truth boundaries. ### 9.1 Railiance Fabric mapping | Fabric concept | NBGM element | Notes | |----------------|--------------|-------| | Declaration `metadata.id` | `Node.metadata.id` | Preserve dotted ids. | | Declaration kind | `Node.spec.node_kind` | `Service`, `Capability`, etc. | | Dependency requirement | `Edge.spec.edge_kind = requires` | Directed to provider capability or interface node. | | Binding assertion | `Edge.spec.edge_kind = binds` | Resolves consumer requirement. | | `metadata.source_links` | `provenance.sources[].ref` | Multiple links become multiple source records. | | Graph export payload | NBGM graph envelope + elements | Explorer display fields map to `attributes.display`. | Fabric remains authoritative for declarations. Vantage Point consumes exports as an inspection-ready NBGM binding. ### 9.2 Repo-scoping mapping | Repo-scoping layer | NBGM usage | |--------------------|------------| | `facts`, `evidence`, `features`, `capabilities`, `abilities`, `scope` | `Node.spec.layer` and `Node.spec.node_kind` | | Evidence bridges | `Edge` with `edge_kind` reflecting support/challenge/link semantics | | Display states in profiles | `attributes.display.display_state` | ### 9.3 Source-of-truth rule Authoritative data lives in repo-native declarations, scans, or curated stores. NBGM graphs are inspection-ready projections. Re-ingestion refreshes projections; it does not rewrite authoritative sources. --- ## 10. Examples ### 10.1 Minimal service dependency graph ```yaml apiVersion: vantage.nbgm/v0.1 kind: Graph metadata: id: demo.minimal title: Minimal dependency demo updated_at: "2026-06-24T00:00:00Z" spec: default_direction: directed elements: - kind: Node metadata: id: consumer.app name: Consumer App spec: node_kind: Service provenance: assertion_type: declared sources: - ref: fabric/services/consumer.yaml method: declaration_load observed_at: "2026-06-24T00:00:00Z" - kind: Node metadata: id: provider.db name: Database spec: node_kind: Service provenance: assertion_type: declared sources: - ref: fabric/services/database.yaml method: declaration_load observed_at: "2026-06-24T00:00:00Z" - kind: Edge metadata: id: consumer.app.requires.provider.db spec: edge_kind: requires source_id: consumer.app target_id: provider.db direction: directed provenance: assertion_type: declared sources: - ref: fabric/dependencies/consumer-db.yaml method: declaration_load observed_at: "2026-06-24T00:00:00Z" ``` ### 10.2 Neighborhood inspection ```yaml apiVersion: vantage.nbgm/v0.1 kind: InspectionRequest metadata: operation: neighborhood graph_id: demo.minimal spec: parameters: focus_id: consumer.app depth: 2 direction: out edge_kinds: [requires] ``` --- ## 11. Open questions for v0.2 - Canonical serialization format (single JSON schema vs multi-document YAML) - Global registries for cross-domain `node_kind` and `edge_kind` aliases - Lens and vantage-point configuration schema - Standard binding interface for incremental graph refresh - Normative confidence and freshness scoring recipes per assertion type --- ## 12. References - `INTENT.md` — project purpose and guiding principles - `SCOPE.md` — repository boundary - Meyer, Sedlmair, Munzner — *The Four-Level Nested Model Revisited: Blocks and Guidelines* ([PDF](https://miriah.github.io/publications/nbgm-beliv.pdf)) - Railiance Fabric — `docs/declaration-schema.md`, `docs/graph-explorer-contract.md` - Repo-scoping — dependency visualization layer model (`RREG-WP-0010`)