Architecture

Antemure is a Rust control plane built from three cooperating agent layers running a single cycle on each endpoint, with a hub that aggregates and learns across the fleet. This page describes the real mechanism — the loop, the entity model, the daemon lifecycle, and how nodes and the hub exchange data.

Three layers

  1. Security agent — observes and enforces. Runs the collectors, raises each event's risk through a deterministic policy engine, and publishes to an in-process event bus.
  2. Reasoning agent — investigates and decides. Scores heuristically first, then (above threshold) fans out a multi-angle AI investigation and synthesizes one verdict with proposed actions.
  3. Remediation agent — fixes and verifies through a constrained, allowlisted, self-protecting tool layer, then re-checks that the threat is gone.

The layers share a local SQLite store (WAL + FTS5 full-text over the node's events) and an in-memory entity graph.

The detect → reason → remediate → verify cycle

One orchestrator cycle runs these steps:

  1. Drain — execute anything a human approved since the last cycle; expire stale authorizations.
  2. Observe — poll all collectors; persist events; upsert entities.
  3. Prune absent — drop entities whose real referent is gone (dead PID, deleted file, verified against /proc and the filesystem). This is how a remediated threat leaves the model so the next diff comes back clean and the incident can close.
  4. Baseline (first run) — snapshot and skip reasoning, so the whole machine doesn't diff as “new.”
  5. Fleet immunity — match local entities/events against the shared threat watchlist; a hit raises a risk-0.8 event.
  6. Reason — heuristic score, then AI investigation if over threshold (see Investigation & Remediation).
  7. Remediate — gated by risk tier and authorization; the LLM agent is primary, the constrained tool API is the fallback.
  8. Persist incident — one open incident per episode (updated, not duplicated), with a full investigation trail hashed with SHA-256 for audit; enqueue a SOAR event; fire webhook + SIEM export.
  9. Verify & re-baseline — close the incident only when resolution is verified; a diff-clean cycle whose artifacts are still on disk holds the incident open and suppresses re-baselining, so a resident threat is never absorbed as “normal.”

Risk bands: 0.0–0.2 Info, 0.2–0.4 Low, 0.4–0.6 Medium, 0.6–0.8 High, >0.8 Critical.

The endpoint entity model

The reasoning agent queries an in-memory graph of typed entities and edges. Entity types span Machine, User, Process, File, Network, Credential, Persistence, Service, Config, SupplyChain and AiAgent, plus container/Kubernetes types (Container, Pod, Image, Workload, Namespace, Cluster, ServiceAccount, Role). Edges are typed too (Spawned, Touches, Connects, PersistsTo, …). Upserts report whether an entity is new; absent-pruning closes the loop.

Daemon lifecycle

The daemon is GUI-less and runs a multi-threaded Tokio runtime. On start it performs zero-touch enrollment, validates its license, registers with the hub, and starts concurrent tasks: the web server (:18900), an optional Kubernetes admission webhook over TLS (:8443), a fleet-config poll (every 300 s), the reverse relay client, and a SOAR device-event delivery loop.

It is event-driven, not fixed-poll: a filesystem/audit watcher over the watch, config and protect roots (and audit.log) wakes a cycle within a ~750 ms debounce; a 30 s heartbeat (AURA_HEARTBEAT_SECS) is only a backstop, and a 2 s floor prevents hot-spinning. Hub enrollment and registration self-heal each cycle — a 401/403 from the hub re-enrolls from the join token.

Node ↔ hub data flow

The node always dials the hub, so it works through NAT with no inbound port. Outbound: register/heartbeat every 30 s, SOAR incident events, SIEM export. Inbound config: the node pulls GET /api/fleet/config and applies a fleet-managed overlay covering models, remediation behavior, autonomy, risk threshold (clamped 0.3–0.95), spend caps, retention, SIEM/archive, license state and custom collectors. While a node is managed, those hub-pushed values override the local file and environment.

The hub aggregates by polling each node: a 5 s snapshot loop (summary, latest reasoning, activity), a 45 s knowledge-graph ingest (incident history) and a 20 s telemetry ingest with a watermark cursor.

Reverse relay & multi-hub failover

To reach a NAT'd node's loopback API, the daemon opens an outbound WebSocket relay (wss://<hub>/api/relay/connect, bearer-authenticated with the node token). The hub's polls become relay-aware: it forwards the HTTP request over the tunnel when the node is connected, else direct. No inbound ports are required on endpoints — the shape is a reverse tunnel (Cloudflare-Tunnel / Tailscale-Funnel style).

hub_url accepts a comma-separated list; the relay client and heartbeat dial each hub in order until one answers, with capped exponential backoff — that is the HA failover mechanism.

Knowledge graph & fleet immunity

The hub keeps a knowledge graph (a SQLite nodes/edges store, knowledge.db) of incidents, ATT&CK techniques, indicators, remediations and hosts, deduped by deterministic ids. When a new incident arrives, the graph returns proven remediations (verified-first by weight) for its techniques and indicators — so the fleet gets smarter with every incident. Separately, fleet immunity pushes one node's incident indicators to every other node's watchlist; a local match raises a proactive risk-0.8 event. (Node-local SQLite uses FTS5 for event full-text; the hub graph and telemetry stores are plain SQLite.)

Licensing

The Access8 license key (cp_…) is validated against the control plane (AURA_ACCESS8_URL, default control.secureinsights.ai) and recorded as the node's tier. It gates the entitlement-only collectors (credential scan, supply-chain, AI-agent) and serves as the default bearer for the hosted gateway. An unlicensed node fails open: it keeps detecting and reasoning permissively. The hub can push license_state to the fleet so managed nodes adopt entitlement without each calling Access8.