Architecture
SigmaShake is designed as a deterministic, zero-dependency rule engine that operates at the AI agent's tool-call boundary.
System overview
User/Agent → Tool Call → ssg eval → Engine → Decision → Audit Log
↓
Dashboard (if ASK)
Core engine
Parser (src/engine/parser.ts)
Parses the .rules DSL into an AST of Rule objects. Features:
- Line-by-line parsing with error recovery
- Condition group splitting (AND/OR logic)
- Validation of all fields, operators, and patterns
- Support for
input.<key>generic field syntax
Evaluator (src/engine/evaluate.ts)
The evaluation algorithm:
- Sort rules by priority (descending — higher first)
- Filter to enabled rules only
- For each rule in priority order:
- Check target matches tool capability
- Check condition groups (OR between groups, AND within)
- Short-circuit on first match
- Default to
allowif no rule matches
Key properties:
- Deterministic — Same input always produces same output
- Sub-millisecond — Typically < 2ms per evaluation
- Fail-secure — Invalid regex patterns match (trigger the rule)
Database (src/engine/db.ts)
SQLite storage for persistent state:
rulestable — Serialized rule definitionsaudit_logtable — Evaluation history (auto-rotated at 50K rows)pending_approvalstable — ASK decisions awaiting human review
Indexes on timestamp, decision, tool for fast queries.
Adapters (src/engine/adapter.ts)
Client adapters translate between different AI agent formats and SigmaShake's internal ToolCall type.
Built-in adapters:
- ClaudeCodeAdapter — Native Claude Code integration with hook installation
- GenericAdapter — Universal JSON format fallback
Capability taxonomy
Tools are classified into 6 capability categories:
| Capability | Tool examples |
|---|---|
execute | Bash, shell, terminal, run |
read | Read, cat, head, view |
write | Write, Edit, create, save |
search | Glob, Grep, find, rg |
agent | Agent, spawn, delegate |
network | WebFetch, WebSearch, curl |
Rule targets map to capabilities: DENY execution blocks all tools with execute capability.
Data flow
Standard evaluation
stdin JSON → parse ToolCall → load rules → evaluate → audit log → stdout JSON
Each ssg eval is a separate process. Rules loaded fresh every time — hot reload with zero downtime.
ASK decision flow
Decision = "ask"
→ Terminal bell
→ POST /api/pending (creates approval)
→ Poll /api/pending/{id}/status (500ms interval)
→ User approves/denies in dashboard
→ Poll returns result → stdout JSON
Timeout: 60 seconds. If no response, defaults to deny.
Safety mechanisms
| Mechanism | Protection |
|---|---|
| Regex length limit (500 chars) | ReDoS prevention |
| Nested quantifier detection | ReDoS prevention |
| Glob/regex caching (LRU, 1000) | Performance |
| Loop guard (3 identical calls) | Infinite loop prevention |
| Circuit breaker (5 consecutive denies) | Agent lockout prevention |
| Input truncation (4KB) | Audit log size control |
| Auto-rotation (50K rows) | SQLite growth control |
| Parameterized SQL only | Injection prevention |
Component diagram
┌─────────────────────────────────────────────────────┐
│ sigmashake-gov │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
│ │ Parser │──→│ Evaluator│──→│ Audit Logger │ │
│ └──────────┘ └──────────┘ └──────────────────┘ │
│ ↑ ↑ ↓ │
│ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
│ │ .rules │ │ Adapters │ │ SQLite DB │ │
│ │ files │ └──────────┘ └──────────────────┘ │
│ └──────────┘ ↓ │
│ ┌──────────────────┐ │
│ │ Dashboard UI │ │
│ │ (Hono + HTMX) │ │
│ └──────────────────┘ │
└─────────────────────────────────────────────────────┘
┌─────────────── ──┐ ┌─────────────────┐
│ sigmashake-mcp │ │ sigmashake-hub │
│ (CF Worker) │ │ (CF Worker) │
│ MCP over SSE │ │ Rules Registry │
│ KV storage │ │ D1 + KV │
└─────────────────┘ └─────────────────┘