Feature: The Relationship Graph
Relevant source files
The following files were used as context for generating this wiki page:The Relationship Graph, also referred to as the Provenance Graph, is a core component of Aldeci designed to provide a queryable knowledge graph for security and compliance investigations. It links disparate development artifacts such as commits, CI/CD jobs, build artifacts, SBOM components, and CVEs into a unified, traceable structure. This enables auditors, developers, and security responders to quickly answer questions about lineage, exposure to known exploits (KEV), and version regressions across software releases.
The system is built on a SQLite database for persistent storage and uses the NetworkX library for in-memory graph analysis and querying. Data is ingested via a dedicated worker script and exposed through a FastAPI-based REST API. This allows for both automated analysis within CI/CD pipelines and interactive exploration through UIs or direct API calls. For more details on related features, see Provenance Attestations & Signing and Evidence Bundles & CI Agent.
Sources: readme_updated.md:70, readme_updated.md:476, services/graph/graph.py:1-560, docs/PROVENANCE-GRAPH.md:1-160
Architecture
The graph service consists of three main parts: a data ingestion worker, a core service managing the graph data, and an API layer for queries.
- Graph Worker (
scripts/graph_worker.py): A script responsible for populating the graph. It consumes various artifacts like git history, SBOMs, risk reports, and attestations, and uses theGraphServiceto load them into the database. - Graph Service (
services/graph/graph.py): The central component that manages the graph's state. It initializes the SQLite database, defines the schema, and provides methods for loading data and executing complex queries (e.g., lineage tracing, anomaly detection). It usesNetworkXfor graph operations. - API Router (
backend/api/graph/router.py): A FastAPI router that exposes the graph's query capabilities via REST endpoints. It provides a user-friendly interface for retrieving lineage, KEV-affected components, and downgrade anomalies.
The following diagram illustrates the high-level architecture of the Provenance Graph service.
Data Ingestion
Data is loaded into the graph using the graph_worker.py script. This worker orchestrates the ingestion of different data sources by calling the loader methods within the GraphService. The worker is designed to be run as a background process or as part of a CI pipeline to keep the graph database up-to-date with the latest release information.
The ingestion flow is as follows:
- The worker script is invoked with paths to artifacts such as a normalized SBOM, a risk report, and a directory of attestations.
- It initializes the
GraphService. - It calls specific loader methods on the service, such as
load_git_history,load_sbom_components, andload_risk_scores. - Each loader method parses its respective input and creates corresponding nodes and edges in the SQLite database.
Database Schema
The graph's data is persisted in a SQLite database, typically named graph.db. The schema is defined and created by the _create_tables method in services/graph/graph.py. It consists of three main tables: nodes, edges, and releases.
nodes: Stores individual entities like commits, artifacts, components, and CVEs. Each node has a unique ID, a type, and a JSON blob for attributes.edges: Defines the relationships between nodes, creating the graph structure. It stores the source and target node IDs, a label describing the relationship (e.g.,contains,built_from), and a JSON blob for attributes.releases: Tracks release tags and their associated commit SHAs.
The diagram below shows the entity relationships.
Sources: services/graph/graph.py:87-106
Core Service and Queries
The GraphService class in services/graph/graph.py is the brain of the feature. It orchestrates database interactions and provides the main query functionalities.
Key GraphService Methods
| Method | Description |
|---|---|
__init__ | Initializes the service, connects to the SQLite DB, and creates tables if they don't exist. |
load_git_history | Parses git commit history and loads commits as nodes and parent-child relationships as edges. |
load_sbom_components | Ingests a normalized SBOM, creating nodes for components and edges linking them to artifacts. |
load_risk_scores | Processes a risk report, adding CVE nodes and attaching risk metadata to component and CVE nodes. |
query_lineage(artifact_path) | Traces the full provenance of a given artifact back to its source commits. |
query_kev_regressions(n) | Finds components with CISA KEV-listed vulnerabilities that were introduced in the last n releases. |
query_downgrade_anomalies(n) | Detects if any component versions were downgraded between the last n releases. |
Sources: services/graph/graph.py:65-560
Query Logic Example: Lineage Tracing
The query_lineage function demonstrates the power of the graph. When a user requests the lineage of an artifact:
- The service finds the starting artifact node in the graph.
- It performs a backward traversal (a reverse breadth-first search) on the in-memory
NetworkXgraph. - It follows edges like
containsandbuilt_fromto trace from the artifact to its constituent components, then to the build job, and finally to the source git commit. - The resulting subgraph, containing all nodes and edges in the trace, is returned.
Sources: services/graph/graph.py:483-509
API Endpoints
The provenance graph is exposed via a REST API defined in backend/api/graph/router.py. This allows for easy integration with UIs, dashboards, and other automated tools.
The following sequence diagram shows a typical API interaction to query for KEV-affected components.
API Endpoint Summary
| Endpoint | Method | Parameters | Description |
|---|---|---|---|
/api/v1/graph/lineage | GET | artifact: str | Returns the full provenance lineage for a given artifact path. |
/api/v1/graph/kev-components | GET | n: int = 3 | Lists components with KEV-flagged CVEs across the last n releases. |
/api/v1/graph/anomalies | GET | releases: int = 2, limit: int = 10 | Surfaces component version downgrades and other anomalies between recent releases. |
Sources: backend/api/graph/router.py:80-200, readme_updated.md:932-934
CLI Interaction
In addition to the API, some graph functionalities can be invoked via the command line, primarily through the fixops-ci agent. This is useful for integrating graph queries into automated CI/CD checks.
| Command | Mapped Capability | Description |
|---|---|---|
fixops-ci graph lineage --artifact | graph.lineage | Traces the lineage of a specified artifact. |
fixops-ci graph kev | graph.kev_in_last | Queries for components affected by KEVs. |
fixops-ci graph anomalies | graph.anomalies | Detects downgrade anomalies between releases. |
Sources: tools/docgen/api_cli_map.py:46-49, readme_updated.md:49
Conclusion
The Relationship Graph is a powerful and essential feature in Aldeci for ensuring supply chain integrity and accelerating security investigations. By creating and maintaining a detailed network of relationships between code, builds, artifacts, and vulnerabilities, it provides a single source of truth for provenance. The combination of a persistent SQLite backend, an efficient NetworkX query layer, a dedicated ingestion worker, and a clean API makes it a robust and versatile tool for developers, auditors, and security teams.
*Sources: readme_updated.md:696, docs/PROVENANCE-GRAPH.md *