Asset Registry v1 Contract

Contract ID: CONTRACT-ASSET-REGISTRY-V1-016  ·  Schema: asset-registry.v1  ·  Status: Published  ·  Owner: Graph Indexer Guild  ·  Last updated: 2026-04-30

Purpose

Asset Registry v1 is the shared asset substrate for NIS2 asset inventory, DORA Register of Information projections, and TLPT scoping. Owned by Graph, it is represented as deterministic Graph Indexer asset nodes plus an append-only stream of asset registry events.

Audience: Graph Indexer implementers and the compliance consumers (NIS2, DORA, TLPT) that project over the asset graph. For the offline/federated transport of these events, see Asset Inventory Sync v1.

Schema Pinning

Asset Node Shape

{
  "schemaVersion": "asset-registry.v1",
  "assetId": "gn:tenant-a:asset:...",
  "type": "integration",
  "tenantId": "tenant-a",
  "attributes": {
    "provider": "github",
    "credential_ref": "cred:github-prod"
  },
  "ownership": {
    "ownerActorRef": "actor:release-owner",
    "ownerTeamRef": "team:platform",
    "credentialRefs": ["cred:github-prod"]
  },
  "criticality": "high",
  "dependsOn": ["gn:tenant-a:service:payments-api"],
  "firstSeen": "2026-04-30T08:00:00Z",
  "lastSeen": "2026-04-30T08:05:00Z",
  "tombstone": false
}

Graph node mapping (the camelCase shape above is the external/API representation; the underlying Graph node stores snake_case attributes, see AssetGraphDocumentFactory.CreateAssetNode):

V1 Taxonomy

Asset v1 types are exactly:

The enum is closed for v1 (AssetRegistryV1.AssetTypes) and is enforced both at write time (AssetRegistryV1.NormalizeType / IsAssetType) and in the persistence layer (the chk_asset_registry_events_asset_type CHECK constraint in both the Graph and Findings Ledger tables). Software components remain in the dependency/SBOM graph and may be linked to image or service assets, but they are not v1 asset types.

The first-party indexer (AssetSourceAdapter in AssetIndexingPipeline.cs) currently produces image and container assets from SBOM scans (sources scanner.sbom, scanner.sbom.container), integration assets from integration profiles (integrations.profile), service assets from runtime signals (signals.runtime), and plugin assets from the plugin catalogue (plugin.catalog). The host type is part of the closed v1 enum but has no first-party producer in the current pipeline; it is reserved for external producers that write asset nodes directly through AssetGraphDocumentFactory.

Excluded Types

The following are not asset nodes:

Credentials and people are sensitive authority/security objects. The asset registry stores only opaque references such as credential_ref, credentialRefs, ownerActorRef, or ownerTeamRef; it must not store secret values, names, email addresses, or dereferenced PII.

Lineage and Events

Asset lifecycle is append-only. Deletions are tombstones, not physical deletes.

Graph edge mapping:

Persistence event table: graph.asset_registry_events.

Event fields:

The Graph-side event table is the source for downstream Findings Ledger visibility. Findings Ledger mirrors the source rows into findings.asset_registry_events and preserves these hashes unchanged. The projection checkpoint follows Graph append order (recorded_at, event_id) while visibility queries retain replay order (occurred_at, event_hash).

Determinism and Offline Replay

Consumers

Runtime API

Graph exposes live asset registry reads under (see src/Graph/StellaOps.Graph.Api/Endpoints/AssetRegistryEndpoints.cs):

MethodRouteRequired scopeNotes
GET/graph/assetsgraph:read or graph:queryList/query via query-string params (type CSV, query, criticality, includeTombstones, includeLineage, limit, cursor, ordering).
POST/graph/assets/querygraph:read or graph:queryBody is AssetRegistryQueryRequest.
GET/graph/assets/{assetId}graph:read or graph:query`?includeLineage=true
POST/graph/assets/exportgraph:exportBody is AssetRegistryExportRequest; format is ndjson (default) or json.

All four endpoints require a resolved tenant (.RequireTenant()); reads/query/get authorize against GraphPolicies.ReadOrQuery and export against GraphPolicies.Export. The scopes graph:read and graph:export are canonical (StellaOpsScopes.GraphRead / StellaOpsScopes.GraphExport); graph:query is a Graph-API-local policy scope (GraphPolicies.GraphQueryScope) that is not part of the central StellaOpsScopes catalog.

The runtime API returns asset-registry.v1 records (the response DTO pins schemaVersion to asset-registry.v1), supports tombstone lineage when includeLineage is requested, and preserves the opaque-reference boundary for credentials and human actors. List/query results page via an opaque cursor (default limit 100, max 500) and order by asset type then asset id (or by asset id when ordering=assetId). Export responses include X-Content-SHA256 (lower-case hex of the payload) and X-Asset-Count headers, and export rows are ordered by asset type then asset id. Validation failures return 400 ASSET_REGISTRY_VALIDATION_FAILED.

Detailed request/response shapes are in eu-runtime-api-contracts-v1.md.

Change Control