- Python 100%
| demo | ||
| src/quo | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| CHANGELOG.md | ||
| demo.py | ||
| pyproject.toml | ||
| README.md | ||
| requirements.txt | ||
QUO — Autonomous Infrastructure Governance & Drift Remediation
QUO is a local-first, AI-augmented autonomous agent that detects, analyzes, and remediates configuration drift in critical infrastructure files. It bridges deterministic enforcement (SHA-256 integrity verification, policy gates) with AI-driven reasoning via Ollama (Qwen 2.5 3B) and orchestrates the full lifecycle through a LangGraph state machine.
Drift events flow through a configurable workflow: static severity-based policy evaluation, notification preparation, and optionally human-in-the-loop approval via Telegram before enforcement. The system is designed with fail-closed integrity, append-only forensic logging, and a hexagonal (ports-and-adapters) architecture that makes notification backends swappable.
Architecture
src/quo/
├── cli.py Bootstrap — config → observability → runtime → signal wait
├── config/ Resolves CLI args, env vars, and defaults into QUOConfig
├── domain/ Event types (QUODriftEvent, QUOHITLDecision) and payloads
├── services/ Policy engine, SHA-256 integrity verification, watcher
│ ├── watcher/ Polls live files vs vault baselines; emits QUODriftEvents on drift
│ ├── integrity/ Streaming SHA-256 hashing with fail-closed verification
│ └── policy_engine/ Stub — planned YAML-based governance rule evaluation
├── graph/ LangGraph state machine (orchestration, routing, nodes)
│ ├── state.py QUOAgentState TypedDict — shared workflow state
│ ├── factory.py StateGraph construction with AsyncSqliteSaver checkpointing
│ ├── runtime.py QUOGraph wrapper — invoke, HITL registry, shutdown
│ ├── routing.py Conditional edge routing between graph nodes
│ └── nodes/
│ ├── policy_gate.py Severity-based policy evaluation (high/critical → audit)
│ ├── notifier.py Notification preparation + HITL requirement flagging
│ ├── auditor.py Stub — planned LLM-based risk analysis via Ollama
│ ├── hitl_wait.py Stub — planned interrupt/resume point
│ └── enforcer.py Stub — planned MCP-based remediation execution
├── runtime/ Service assembly, lifecycle management, drift consumer loop
├── integrations/ Telegram adapter (alerts + inline approve/reject buttons)
├── observability/ Append-only JSONL forensic logger with stdout mirroring
└── application/ Protocol interfaces (QUONotificationPort)
Workflow
File Change → Watcher → asyncio.Queue → DriftConsumer → LangGraph StateGraph → Notification / Enforcement
- Detection —
QUOWatcherServicepolls every protected file against its vault baseline (SHA-256) and pushes aQUODriftEventonto anasyncio.Queuefor each new deviation. A clean boot emits nothing, a file moving further away from baseline emits again, and a return to baseline silently re-arms. - Consumption —
drift_consumerpulls events from the queue, builds graph state, and invokes the compiled LangGraph with a uniquethread_idfor checkpoint isolation. - Policy Gate —
policy_gate_nodeapplies severity-based rules:high/critical→ audit path, everything else → notify path. - Auditor (stub) — Planned: delegates to Ollama (Qwen 2.5 3B) for LLM-based risk scoring and remediation recommendations.
- Notifier —
notifier_nodeprepares the alert payload and flagshigh/criticalevents as requiring HITL. - HITL Wait (stub) — Planned: pauses execution via LangGraph
interrupt_before, awaiting operator approve/reject through Telegram inline buttons. - Enforcer (stub) — Planned: executes remediation through a sandboxed MCP subprocess, keeping the main runtime unprivileged.
Getting Started
Prerequisites
- Python 3.12+
- Ollama (optional, for LLM-based risk analysis) —
qwen2.5:3brecommended - Docker + Docker Compose (optional, for the demo sandbox only)
Installation
git clone <repo-url> && cd quo
python -m venv .venv && source .venv/bin/activate
pip install -e .
pip install -r requirements.txt
The pyproject.toml declares no runtime dependencies; use the pinned requirements.txt until that is resolved.
Configuration
Configuration is resolved with priority CLI args > environment variables > defaults.
cp .env.example .env
Key environment variables:
| Variable | Default | Description |
|---|---|---|
QUO_MODE |
PRODUCTION |
PRODUCTION or DRY_RUN (log only, no modifications) |
OLLAMA_HOST |
http://localhost:11434 |
Ollama endpoint for LLM inference |
OLLAMA_MODEL |
qwen2.5:3b |
Model used as the reasoning layer |
TELEGRAM_BOT_TOKEN |
— | Bot token from @BotFather (optional — without it, QUO runs without HITL) |
TELEGRAM_CHAT_ID |
— | Chat ID from @userinfobot |
QUO_WATCH_FILES |
— | Comma-separated file paths to monitor |
QUO_WATCH_PATH |
watch/live |
Base directory where watched files are surfaced (shared volume) |
QUO_STATE_PATH |
watch/state |
Bind-mounted live state (.bashrc, hosts) not covered by the live volume |
QUO_VAULT_PATH |
vault |
Golden baseline directory containing MANIFEST.sha256 |
QUO_DB_PATH |
data/quo_state.sqlite |
LangGraph checkpoint database |
QUO_LOG_PATH |
logs/audit_trail.jsonl |
Append-only forensic audit log |
QUO_MCP_SERVER_SCRIPT |
mcp/server.py |
MCP enforcement server path |
Run
python -m quo # production mode
python -m quo --dry-run # simulate only, no file modifications
Without a Telegram token, QUO runs without HITL and auto-remediates based on policy thresholds.
Demo Sandbox
python -m demo # or: python demo.py
Launches a Docker Compose stack with two containers:
- quo-target — "victim" node built from Alpine 3.19 (
demo/Dockerfile.target) with writable configuration files. Because Docker bind-manages/etc/hostsand/root/.bashrclies outside the shared volume, both are surfaced to the watcher via bind-mounteddemo/state/files (state/hosts,state/.bashrc). - quo-agent — QUO daemon:
demo/bootstrap.pyseeds golden baselines into/watch/live(shared volume aliasing the target's/etc),/watch/state(bind-mounted state files), and/watch/vault, then the watcher polls those surfaces against the vaultMANIFEST.sha256.
An interactive menu lets you inject five simulated attacks and watch QUO respond in real time:
| Attack | Target | Risk |
|---|---|---|
| Enable SSH root login | /etc/ssh/sshd_config |
HIGH |
| Enable SSH password auth | /etc/ssh/sshd_config |
HIGH |
| Add passwordless sudoer backdoor | /etc/sudoers |
CRITICAL |
| Inject exfiltration hook | /root/.bashrc |
MEDIUM |
| Poison /etc/hosts (DNS hijack) | /etc/hosts |
MEDIUM |
Severities shown are those reported by the watcher for each demo attack. Every injected attack produces exactly one alert (a second change to an already-dirty file re-alerts); the Restore all menu action copies golden baselines back without spurious events.
Attacks are defined declaratively in demo/attacks.yaml, making it trivial to add new test vectors without touching Python code.
Monitoring:
docker logs -f quo-agent
docker exec quo-agent tail -f /app/logs/audit_trail.jsonl
Press q in the menu to tear down all containers and volumes.
Entry Points
| Command | Description |
|---|---|
python -m quo |
Start the QUO agent daemon (blocks on SIGINT/SIGTERM) |
python -m demo |
Interactive Docker sandbox with simulated attacks (or python demo.py) |
quo |
Same as python -m quo (installed via pip install -e .) |
Key Design Properties
- LangGraph orchestration — Drift events flow through a
StateGraphwith conditional edges, thread-isolated checkpointing viaAsyncSqliteSaver, and interrupt/resume capability for HITL workflows. - Fail-closed integrity —
QUOIntegrityEngineuses streaming SHA-256 with constant-time comparison (hmac.compare_digest), timing-attack resistant. ReturnsFalsefor any error: missing files, unreadable files, missing hashes, or mismatches. - Hexagonal (ports-and-adapters) architecture —
QUONotificationPortprotocol class defines a clean adapter boundary. Telegram is the current implementation; Slack, email, or other channels can be swapped in without touching core logic. - Queue-based decoupling — Watcher and consumer communicate via
asyncio.Queue, preventing backpressure propagation. - Append-only forensics —
QUOForensicLoggerwrites UTC-timestamped JSONL entries with automatic module attribution (viainspect.stack()). Stdout mirroring for live observability. - Dry-run mode —
QUO_MODE=DRY_RUNor--dry-runlogs all intended actions without executing them, enabling safe testing on production systems. - Signal-driven lifecycle — SIGINT/SIGTERM triggers graceful
stop_runtime()with ordered shutdown: cancel tasks, stop services, flush checkpoints. - Thread-isolated checkpointing — Each drift event receives a unique
thread_id, ensuring complete workflow isolation and replay capability.
Development Status
QUO is in early-stage MVP development.
Implemented:
- Config resolution pipeline (CLI args > env vars > defaults)
- Append-only forensic JSONL logging
- LangGraph assembly with SQLite checkpointing (
AsyncSqliteSaver) - Telegram integration with inline Approve/Reject buttons for HITL
- Drift event domain models (
QUODriftEvent,QUODriftPayload,QUORiskAssessment,QUOHITLDecision) with risk separated from raw drift facts - SHA-256 integrity engine with manifest loading (
MANIFEST.sha256) - Runtime lifecycle (start/stop/signal handling)
- Static severity-based policy gate node (high/critical → audit)
- Notification preparation node with HITL requirement flagging
- Polling filesystem watcher: SHA-256 comparison against vault baselines, one alert per new deviation, silent re-arm on restore (no false positives on clean boot)
- Unified drift diff generation (golden vs live, truncated for large diffs)
- Interactive Docker demo sandbox with 5 attack scenarios (data-driven via YAML) — all five verified to alert
- Live coverage of state files outside the shared volume (
/etc/hosts,/root/.bashrc) via a bind-mounted state root (QUO_STATE_PATH) and a custom target image (demo/Dockerfile.target) requirements.txtwith pinned dependencies (multi-stage image build installs to prefix)QUOGraphwrapper with HITL registry and checkpoint lifecycle managementTotal=FalseTypedDict graph state for progressive enrichment across nodes
Planned / In Progress:
- LLM-based auditor node (Ollama Qwen 2.5 3B for risk scoring)
- HITL interrupt/resume via LangGraph
interrupt_before - MCP enforcement server for sandboxed remediation execution
- YAML-based policy engine (governance rule evaluation)
License
DATORUM — Autonomous Infrastructure Governance