Skip to content

Architecture

flowchart LR
  subgraph Evidence["Evidence: read-only"]
    OTRF["OTRF / Mordor JSON"] --> P
    EVTX[".evtx via python-evtx"] --> P
    PL["plaso json_line / l2tcsv"] --> P
    VOL["Volatility 3 JSON"] --> P
    AUTH["auth.log"] --> P
  end
  P["parsers/*<br/>map to Event + SHA-256"] --> L[("custody ledger<br/>hash chain to SQLite")]
  P --> G[("provenance graph<br/>networkx or in-memory")]
  G --> F["fusion<br/>corroborations"]
  F --> R["rule engine<br/>GUID to PID to cross-entity to fallback"]
  R --> AF["anti-forensics scan"]
  R --> AT["ATT&CK heuristics + rarity"]
  AT --> S["story reconstructor"]
  AF --> S
  S --> C["confidence scorer<br/>calibrated edges"]
  C --> OUT{"outputs"}
  OUT --> MD["Markdown / HTML / PDF report"]
  OUT --> JS["JSON"]
  OUT --> CY["Cypher to Neo4j"]
  OUT --> API["FastAPI + vis-timeline UI"]

Module map

Module Responsibility
models.py Pydantic contracts: Event, CausalEdge, IncidentStory, CustodyRecord, TamperingIndicator
integrity.py Canonical event hashing, stable ids, in-memory hash-chained ledger
custody_store.py Append-only SQLite persistence and offline verification
entities.py Lossy identity keys: PID, image, host, user (ADR 0003)
parsers/ One connector per artefact family; windows.py is the shared Windows mapper
graph.py Temporal provenance graph with corroboration side-table
fusion.py Same fact seen by several artefacts becomes one primary node plus corroborations
rules.py Indexed causal rule engine and packaged per-rule calibration (ADR 0002)
attack.py ATT&CK heuristic tags and per-case rarity, combined into event suspicion
antiforensics.py Tampering indicators
stories.py Story roots, subtrees, suspicion/confidence, unknown windows (ADR 0004)
confidence.py Reliability × corroboration × temporal fit × edge strength, with tamper penalty
report.py Court-style report (Markdown to HTML, optional WeasyPrint PDF)
export.py JSON, Cypher and live Neo4j push
api.py, web/ FastAPI and a single-page timeline/graph UI
reconstruct.py, normalize.py, generators.py v0.1 path view, legacy normaliser, synthetic scenarios

Trust boundaries

  • Evidence is only ever read. The API only reads beneath REVENANT_EVIDENCE_ROOT and binds to localhost by default.
  • XML from .evtx is parsed with defusedxml when available.
  • Unreadable artefacts are recorded in the ledger and the report, never silently dropped.