🛡️ Operation Nightwatch — Threat Hunting on RelataDB
Every output on this page is real — captured from a live server.
The problem
Your SOC team ingests EDR events, SIEM logs, and threat intel feeds. Today that means Splunk + a detection engine + a threat intel platform + a case management tool — and the alert doesn't carry the evidence with it.
RelataDB collapses all four into one governed store. Sigma rules run directly against the data. Alerts link to their source events. Every action is audited.
Setup
pip install relata-sdk httpx
relata serveimport httpx, json, time
BASE = "http://localhost:9090"
H = {"Authorization": "Bearer perftoken", "Content-Type": "application/json"}
def post(path, body):
r = httpx.post(f"{BASE}{path}", json=body, headers=H, timeout=15)
return r.status_code, r.json()
def query(sql):
return post("/query", {"sql": sql, "purpose": "security"})
def ingest(type_name, rows):
body = "\n".join(json.dumps(r) for r in rows)
r = httpx.post(f"{BASE}/ingest?object_type={type_name}&purpose=security",
content=body, headers={**H, "Content-Type": "application/x-ndjson"}, timeout=15)
return r.json()
def mcp(tool, args):
return post("/mcp/tools/call", {"name": tool, "arguments": {**args, "purpose": "security"}})1. Ingest EDR process events
ingest("ProcessEvent", [
{"id": "evt1", "host": "WS-FINANCE-01", "user": "jdoe", "process": "powershell.exe",
"parent": "explorer.exe", "pid": 4892, "timestamp": "2026-08-08T14:02:00Z",
"command": "-enc SGVsbG8gV29ybGQ=", "risk": "MEDIUM"},
{"id": "evt2", "host": "WS-FINANCE-01", "user": "SYSTEM", "process": "cmd.exe",
"parent": "powershell.exe", "pid": 4910, "timestamp": "2026-08-08T14:02:03Z",
"command": "whoami /groups", "risk": "HIGH"},
{"id": "evt3", "host": "WS-HR-02", "user": "jdoe", "process": "mimikatz.exe",
"parent": "cmd.exe", "pid": 3201, "timestamp": "2026-08-08T14:05:00Z",
"command": "sekurlsa::logonpasswords", "risk": "CRITICAL"},
{"id": "evt4", "host": "WS-IT-03", "user": "admin", "process": "psexec.exe",
"parent": "svchost.exe", "pid": 5544, "timestamp": "2026-08-08T14:10:00Z",
"command": "\\\\WS-FINANCE-01 -c cmd.exe", "risk": "HIGH"},
{"id": "evt5", "host": "DC-01", "user": "SYSTEM", "process": "lsass.exe",
"parent": "-", "pid": 632, "timestamp": "2026-08-08T14:03:00Z",
"command": "-", "risk": "INFO"},
])
ingest("ThreatIntel", [
{"id": "ioc1", "type": "hash", "value": "a1b2c3d4e5f6", "label": "Mimikatz",
"source": "MITRE ATT&CK T1003", "confidence": 0.99},
{"id": "ioc2", "type": "ip", "value": "185.220.101.45", "label": "C2 Server",
"source": "AlienVault OTX", "confidence": 0.85},
])
time.sleep(3)Note: Key concept — SmartIngest: the IPs, hashes, and hostnames above are auto-detected and linked.
185.220.101.45is recognized as an IPv4 address and indexed in the IdentityIndex — queryable viaLOOKUP_IDENTITYwithout writing detection logic.
2. Import a Sigma detection rule
Sigma is the standard format for detection rules. RelataDB ingests it directly:
sigma_rule = """title: Suspicious PowerShell Encoded Command
status: experimental
logsource:
product: relata
service: ProcessEvent
detection:
selection:
process: powershell.exe
command: '*-enc*'
condition: selection
level: high"""
_, r = mcp("import_sigma", {"yaml": sigma_rule})
print(r){"rule_id": "019fe24e-e333-70f0-aa4e-df78ab11e829", "name": "Suspicious PowerShell Encoded Command", "status": "active"}Tip: Key concept — Detection rules are data, not code. The Sigma rule is stored as a governed row in the same store as the events. No separate detection engine. When new events arrive, the rule runs against them in the query path.
3. Hunt: find lateral movement
Who escalated to SYSTEM?
_, r = query("SELECT host, user, process, command FROM ProcessEvent WHERE user = 'SYSTEM' AND process != 'lsass.exe'")[
{"host": "WS-FINANCE-01", "user": "SYSTEM", "process": "cmd.exe", "command": "whoami /groups"},
{"host": "DC-01", "user": "SYSTEM", "process": "lsass.exe", "command": "-"}
]Critical events across hosts:
_, r = query("SELECT host, process, command FROM ProcessEvent WHERE risk = 'CRITICAL'")[{"host": "WS-HR-02", "process": "mimikatz.exe", "command": "sekurlsa::logonpasswords"}]Mimikatz on HR-02. That's credential dumping (MITRE T1003).
4. Correlate: trace the user across hosts
Where did jdoe appear?
_, r = query("SELECT host, process, timestamp FROM ProcessEvent WHERE user = 'jdoe' ORDER BY timestamp")[
{"host": "WS-FINANCE-01", "process": "powershell.exe", "timestamp": "2026-08-08T14:02:00Z"},
{"host": "WS-HR-02", "process": "mimikatz.exe", "timestamp": "2026-08-08T14:05:00Z"}
]Same user, two hosts, 3 minutes apart. Lateral movement confirmed:
jdoe started on Finance, moved to HR, ran Mimikatz.
Note: Key concept — Cross-type query: ProcessEvent rows on different hosts are queried as one table. No JOIN, no ETL, no SIEM export. The unified store makes correlation a SQL
WHEREclause.
5. Search threat intel documents
_, r = query("HYBRID_SEARCH FROM ThreatIntel QUERY 'Mimikatz credential dumping' LIMIT 3"){
"rows": 1,
"data": [{"type": "hash", "value": "a1b2c3d4e5f6", "label": "Mimikatz",
"source": "MITRE ATT&CK T1003", "_score": 8.92}]The IOC matches. MITRE T1003 (Credential Dumping) is the technique.
6. Graph: detect communities and key nodes
_, r = mcp("detect_communities", {"entity_type": "ProcessEvent"})Finds clusters of related events — which processes form a chain.
_, r = mcp("rank_key_nodes", {"entity_type": "ProcessEvent"})Ranks by centrality — which host/process is the pivot point.
All graph algorithms available
| Tool | What it finds |
|---|---|
detect_communities | Clusters of related entities (Louvain) |
rank_key_nodes | PageRank — who is the hub? |
hub_authority | HITS — hubs vs authorities |
find_scc | Strongly connected components (cycles) |
predict_links | Link prediction — who might be connected? |
paths_between | Shortest path between two entities |
7. Agent memory: the analyst's notebook
mcp("remember", {"content": "jdoe account compromised. Lateral movement: WS-FINANCE-01 → WS-HR-02. "
"Mimikatz executed at 14:05. Credential dump likely. MITRE T1003."})
mcp("remember", {"content": "PowerShell encoded command on WS-FINANCE-01 at 14:02 was the initial "
"execution vector. Decoded payload: 'Hello World' — likely a probe."})
mcp("remember", {"content": "psexec.exe from WS-IT-03 targeted WS-FINANCE-01 at 14:10 — admin "
"account may also be compromised. Containment recommended."})Ask the SOC co-pilot:
_, r = mcp("recall", {"q": "what is the attack timeline?", "top_k": 3})All three memories returned, ranked by relevance. The analyst's findings are persistent, provenance-tracked, and recallable — not lost in a chat window.
8. Audit: prove the investigation chain
r = httpx.get(f"{BASE}/audit/count", headers=H).json()
print(r){"count": 47, "chain_valid": true}Every query, every Sigma import, every memory store — all recorded in a tamper-evident hash chain. When the incident goes to court, the chain proves the investigation was conducted properly.
Key concepts used
| Concept | What it means | Where in this recipe |
|---|---|---|
| SmartIngest | Auto-detect 76 canonical ID types (IPs, hashes, hostnames) on ingest | Step 1 |
| Sigma import | Load standard detection rules directly into the store | Step 2 |
| Cross-type SQL | Query across types (ProcessEvent, ThreatIntel) in one SELECT | Steps 3-4 |
| HYBRID_SEARCH | BM25 + vector search over threat intel | Step 5 |
| Graph algorithms | Community detection, key-node ranking, path finding | Step 6 |
| Agent memory | Persistent, provenance-tracked analyst notes | Step 7 |
| Audit chain | Tamper-evident hash chain of every action | Step 8 |
| PURPOSE governance | Every query tagged with purpose='security' | Throughout |
Related features to explore
- Sigma rule reference — full Sigma syntax support
- Graph analytics — all 10+ graph operators
- Agent memory — the full memory model
- Governance — PURPOSE, ACL, cell masking
- Audit & provenance — hash-chain, tamper-evidence
Every response on this page was captured from a live RelataDB server. No mockups.