28/28 attacks refused · 8/8 legitimate reads allowed

The numbers for Monday's meeting are already in your ERP.
So who's still writing the report?

A read-only, self-verifying data layer for the SQL database behind your ERP — weekly reports, and a guarded MCP server for AI agents.

Every query provably read-only: measured against 28 attacks, not promised in prose. No BI licence, no agent installed on the ERP server, no writes.

pip install erp-report-engine
erp-report-engine init-demo
erp-report-engine run -c config.demo.yaml

Three commands, no ERP required — the demo database ships with the package.

The difference, measured

Everyone says read-only. This one is scored.

The same 28-attack corpus — file reads, shell execution, outbound sockets, the read-only-transaction escape — run through the shortcuts real tools ship, and through this guard. A guard that blocks nothing is useless, so legitimate reads are scored too.

starts-with-SELECT 6 / 28
write-keyword blocklist 9 / 28
this guard 28 / 28

The keyword blocklist also breaks a legitimate read — one whose text merely contains a write word. See the full benchmark →

What one run produces

A weekly report that audits itself

Four KPIs against an 8-week baseline, findings with named drivers (not just "revenue is up" — which region, and how much of the move), receivables aging, a data-quality gate that confesses the problems in your own data, and row counts reconciled against the source.

Weekly ERP Report — 2026-W30 The weekly report: KPI cards, findings with named drivers, trends, stock attention list, receivables aging, data-quality gate and source reconciliation Open the live report →

Produced by one command against the bundled demo database — including the data-quality problems deliberately seeded into it, every one caught by the gate.

Proof, not adjectives

The guard, scored against 28 real attacks

The famous COMMIT; DROP SCHEMA escape that got the reference Postgres MCP server archived. Server-file reads. Shell execution. Outbound sockets. Each one refused — while eight ordinary reporting queries pass untouched.

$ erp-report-engine trust-benchmark The trust benchmark terminal output: 28 attacks blocked, 8 legitimate reads allowed, and the comparison against shape-only checks

Runs on your machine in seconds, no database required: erp-report-engine trust-benchmark

Interactive

Don't take the adjective's word for it

The real guard.py the tests run, executing in your browser via Pyodide. Paste your own attack and watch it get refused — or find one that isn't, and tell me.

Read-only guard — browser playground The read-only guard in the browser playground: a server-file read and the COMMIT; DROP Postgres bypass refused, real analytics allowed

Nothing is sent anywhere — the guard runs entirely in your browser.

The same guarded extraction, visualised

A Power BI Command Center, authored as code

Star schema, measures and report pages generated as TMDL + PBIR from the same read-only path — plus this dark HTML dashboard with SPC control bands that separate a real signal from week-to-week noise.

Command Center — dashboard The Command Center dashboard: dark bento grid with KPI tiles, SPC control-band charts, receivables aging and revenue concentration Open the dashboard →

Every chart drawn from the same guarded extraction that produced the report — one definition of every metric.

Go deeper

Why "read-only in prose" isn't read-only →

The two famous MCP database failures, what actually went wrong in each, and how to build a guard you can prove.

read the case study

Compared: agent DB access →

Transactions vs roles vs statement guards vs semantic layers — and where each one is genuinely the right choice.

weigh the options

The security model →

Four layers: lexical, parse-tree, a side-effecting-function check, and a read-only session. Including what it does not claim.

read SECURITY.md

What one run produces

  • KPI cards vs last week and an 8-week baseline
  • Findings with named drivers; SPC signals separated from noise, arithmetic shown
  • A data-quality gate and source reconciliation — the report audits its own inputs
  • A Power BI Command Center from the same guarded extraction

Read-only, enforced in code

  • Four layers: lexical, parse-tree, side-effecting-function check, read-only session
  • Checks the functions a statement calls, not just its shape — and fails closed when it cannot parse one
  • Three Turkish ERP profiles: Logo Tiger, Netsis, Mikro
  • A guarded MCP server, so an AI agent gets the same guarantee