Why it matters
Scanner findings without context are noise. A SQL injection finding is just a finding; the same finding linked to a design review that predicted "injection: high" four weeks earlier becomes a guardrail-escape signal. The graph is what lets the triage agent ask: was this prediction made? Should a guardrail have caught it? Is this a recurring pattern? Without the graph, every finding is unmoored.
Node types design_review spec → threat list, approved deps, channel allowlist threat class, severity, summary, source review guardrail id, target, enforcement mode, version write_event file, content_hash, verdict, fired guardrails dep_install package set, registry verdict, signals finding scanner, rule_id, file, line range, correlations triage_verdict finding → verdict, confidence, evidence Edges threat ──derived_from──▶ design_review guardrail ──enforces──▶ threat write_event ──checked_by──▶ guardrail finding ──correlated_with──▶ threat / guardrail / write_event triage_verdict ──evaluates──▶ finding
What you can ask it
"Show me all live code derived from threats we flagged in Q1."
"Which guardrails fired most often this week, and which specs triggered them?"
"Which threats we predicted ended up with no enforcing guardrail?"
"For finding X, walk me back to the spec and the predictions made about it."
"Which design reviews resulted in a guardrail-escape in the last 30 days?"
Access
Three audiences, three modes. Agents query it via MCP (flowrail-lineage and triage call into it on demand). Dashboards render it visually at /reviews/<dr_id> and /graph. Compliance pulls structured event-log reports through the export API or Settings, Export.