Components
UI
React + Vite + TypeScript. Talks only to the server. Dashboard, Tripwires
(with the install command and per-endpoint instances), Endpoints,
Integrations (config forms rendered from each plugin’s manifest).
Server
FastAPI. Serves the JSON UI contract and the plain-text agent protocol,
generates honeytokens, signs/verifies callbacks, and fans alerts out through
plugins.
Agent
Pure Bash (
curl + openssl), delivered by a deploy plugin. Enrolls, pulls
its unique instances, plants them, and watches for reads.api/routes.py (endpoints),
db.py / store.py (the database seam), models.py (Pydantic schemas that
mirror the UI’s types), tokens/ (honeytoken generators + the recommended-path
catalog), plugins/ (the framework), and services/ (deploy, alerting, signing,
content rendering, integrations).
Data model
The model is definition → instance - see Core concepts for the full vocabulary.Tripwire - the definition
A credential recipe
(
name, token_type, path, source) that lives on no machine.Endpoint - a self-enrolled machine
A box that ran an install
command and registered itself (
hostname, platform).Deployment - one tripwire x one endpoint
Deploying a tripwire
mints one deployment per endpoint, each with its own bait content and
own HMAC secret - so a leak on one box can’t forge another’s triggers, and
a read is attributable to exactly one endpoint.
Alert - the verified read
On a read, the agent fires an
HMAC-signed, enriched callback; the server records an alert and fans it out to
SIEM / EDR / webhook.
Database
The store is built on SQLAlchemy + Alembic, so the schema is portable and versioned. SQLite ships in the monolith with zero setup. Swap the backend by how far you need to go:- Different file/location - set
THUMPER_DBto a SQLAlchemy URL pointing at another SQLite file. - Different engine - point
THUMPER_DBat PostgreSQL or MySQL. The engine is selected from that URL; SQLite-specific PRAGMAs (WAL, foreign keys) are applied only when the dialect is SQLite. Alembic migrations bring any supported engine to the current schema on startup.
Plugins
Deploy and alert are both plugin seams. Drop a directory underplugins/{deploy,alert}/<name>/ with a manifest.yaml and a plugin.py, and
the loader discovers it on startup - its config_schema is rendered into a UI
config form automatically. See Writing a plugin.