Skip to content

ADR 0003: In-process graph engines, Neo4j optional via Cypher export

  • Status: accepted (unchanged from v0.1, re-validated on real data)
  • Date: 2026-09-26

Context

The spec sketches Neo4j as the graph store. The real catalog is small: 697 techniques, 153 controls, 2,877 rules, 116 log sources: 3,843 nodes and 9,744 edges for the Acme posture.

Decision

Keep all engines in-process on Python sets and NetworkX. Neo4j stays an optional exploration target: python -m vantage graph --format cypher emits an idempotent, injection-safe MERGE script, and docker compose --profile neo4j up starts a localhost-only Neo4j.

Measured on the real catalog (results/coverage.md, part C, realdata run 37092934843 on the GitHub ubuntu runner): a full coverage computation takes 2.9 ms; ranking every single point of failure takes 2 ms with the one-pass algorithm, versus 7.7 s by brute-force recomputation, with identical results (checked in the benchmark and by a property test). On a loaded laptop the brute-force check took minutes; the one-pass ranking stays in milliseconds.

Consequences

  • Zero infrastructure for users and CI; what-if queries are interactive in the web UI.
  • Ad-hoc graph queries need the Cypher export; there is no live Neo4j sync.