# Knowledge graph

Decepticon's attack graph uses the typed models in
[decepticon_core.types.kg](../packages/decepticon-core/decepticon_core/types/kg.py)
and Neo4j-backed stores. A tool or specialist must actually record an
observation; an engagement transcript does not automatically populate every
host, vulnerability or finding into the graph.

## Deployment and partitioning

The default Compose `neo4j` service joins both `sandbox-net` and
`decepticon-net`. The host browser and Bolt listeners bind to loopback, with
configurable `NEO4J_HTTP_PORT` (7474) and `NEO4J_BOLT_PORT` (7687).
`NEO4J_PASSWORD` is generated by normal onboarding; the public raw-Compose
fallback is not a credential to assume for an installed deployment.

Skillogy uses this same Neo4j service for its catalog. BloodHound uses its own
separate `bhce-neo4j`. Graph labels/provenance and engagement partitions are
logical boundaries, not separate operating-system or database-user isolation.
See [Neo4j hardening](security/neo4j-hardening.md).

## Actual tool surfaces

Tool availability depends on the role, enabled plugin bundles and middleware.
The [research implementations](../packages/decepticon/decepticon/tools/research/tools.py)
include:

| Tool | Purpose |
| --- | --- |
| `kg_add_node(kind, label, props)` | Record a typed node |
| `kg_add_edge(src, dst, kind, weight)` | Record a typed relationship |
| `kg_query(kind, min_severity, limit)` | Query the current graph partition |
| `kg_neighbors(node_id, direction, edge_kind)` | Inspect typed neighbors |
| `kg_stats()` | Return graph statistics |
| `kg_backend_health()` | Inspect store connectivity/configuration |
| `plan_attack_chains(...)` | Rank attack paths from recorded graph evidence |
| `suggest_objectives_from_chains(...)` | Propose objectives; this does not commit OPPLAN |
| `kg_ingest_sarif`, `kg_ingest_nmap_xml`, `kg_ingest_nuclei_jsonl` | Parse supported scanner artifacts |

The [KG middleware](../packages/decepticon/decepticon/middleware/kg.py) additionally
supplies `kg_record(observations)` and `kg_ingest(scanner_kind, path)` on roles
with the KG slot. The standard slot map enables it for Analyst, AD Operator and
Contract Auditor; store configuration failures can cause that conditional slot
to be skipped with a warning. Inspect the live role before assuming availability.

Older docs listed `kg_create_node`, `kg_query_nodes`, `kg_query_paths`,
`critical_path_score`, `promote_chain`, `ingest_sarif` and `ingest_scan_output`.
Those are not the current registered research-tool names. Use the signatures
above or inspect the actual tool schema.

## Schema and evidence

`NodeKind`, `EdgeKind`, `Node` and `Edge` in the core model define the canonical
kinds and properties. Neo4j storage adds partition metadata; query it through
the store/tool surface when possible. Finding IDs, evidence pointers and
verification status must remain consistent with `findings/FIND-*.md` and
`report/` artifacts. A graph hypothesis is not an independently verified finding.

SARIF export/reimport follows the run's sandbox and engagement binding; see
[SARIF sandbox transfers](reporting-sarif.md) for limits. Some legacy research
scanner adapters retain process-local IO, so a sandbox path is not universally
readable by every ingestion function.

## Diagnostics

```bash
decepticon kg-health
```

The launcher runs `python -m decepticon.tools.research.health` in the LangGraph
container. Its JSON reports `backend`, `ok`, Neo4j URI/user/database, graph
`revision` and `stats`, or `error`; exit 0 means healthy and exit 1 means failed.
It does not run an index audit or report graph size on disk.

For direct Cypher inspection, use the selected deployment's credentials and
explicit engagement partition. Unscoped example queries can mix engagement and
catalog records; they are not a safe default for exported findings. Never
reset graph volumes to resolve a connectivity failure without a separate
explicit request to delete that data.
