Use casesSecurity and platformCompliance and audit11 / 12
How it fits together

Every change signed, with a copy kept outside the store

Every administrative change is recorded, numbered and signed with a key the store doesn't hold, and copied to your SIEM as it happens. An edit made straight to the store is caught by the server's own check, and the SIEM's copy still shows what was written. A person's runs can be erased on request, and the erasure is recorded by a hash, not a name.

1command checks the store, a file or a SIEM's copy
5 minbetween the server's own checks
0names in an erasure's record
Who changes things
QueryAPIGate
Your store
Copies outside it
delivered by a cursor per output, at least once
Audit keyStable↗
kept outside the store
↗ Administrators alice@example.com· token ci-deployer· config admin· break-glass Scoped keys change nothing, so they never appear.
↗ An erasure request history forget
jwt:alice@example.com
owners only
Someone with the store, not the key UPDATE audit_log … seq 3
straight to the store, around the core
The governed coreevery administrative changeStable↗

01 · Record

Who, how they signed in, and what changed. A password only as "changed".

password: "changed"

02 · Sign

Numbered with no gaps, chained to the entry before, signed with a key the store doesn't hold.

hmac-sha256 chain

03 · Check

Every 5 minutes, from the last entry checked. A changed, missing or reordered entry is named.

audit_chain_broken
↗

The store

PostgreSQL or queryapigate.db audit_log 1audit_key_set startup 2create_key partner-acme 3update_key 6000/minute 4update_key +warehouse · alice 5forget_caller 9e5b…e08d execution_history · events · usage_counters jwt:alice@example.com 0 runs jwt:bob@example.com 1 run
Redisusage counts ClickHouseExp↗run store
Never here: rows, parameter values.
≤ 5 min later
↗ Your SIEMStable tls://siem.example.com:6514 syslog · mutual TLS delivered_seq 5 · behind 0 verify --file ✓ entries 1 to 5
Export file /var/log/queryapigate/audit.jsonl seq 5
OpenTelemetry Collector OTLP logs · acknowledged per batch seq 5
What the auditor runsthe store, then the SIEM's copy
$ queryapigate audit verify BROKEN at entry 3 (update_key, 2026-10-13 13:22:55): changed $ queryapigate audit verify --file rsyslog.log Intact: entries 1 to 5, keyed with QUERYAPIGATE_AUDIT_KEY.
Stablecompatibility promise Expmay change in a minor release Never kept: the rows a query returns, and parameter values.
AdministratorsWho changed what, and how they signed inA token, a config file from CI, or the shared key. Scoped keys change nothing.
The governed coreRecord → sign → checkEach change numbered, chained to the one before, and signed with a key the store doesn't hold. The server checks the chain every five minutes.
Your storeThe audit log, and run historyAn edit made straight to the store breaks the chain at that entry: audit_chain_broken. Forgetting a person deletes their runs, events and usage counts, recorded by hash, not by name.
Copies outside itYour SIEM, a file, an OpenTelemetry CollectorSyslog over mutual TLS or OTLP logs, each with its own cursor, at least once.
The auditorqueryapigate audit verifyThe store, an export file, or the SIEM's own copy, checked with the same command.
Where data goesRows and parameter values are never keptEvery place data is kept or sent is listed, and a test fails if one is missing.

The same governed core as the full architecture. Where data goes →

For security and compliance teams

Answer the auditor from the running system

An auditor asks who changed which grant, and how you know the record wasn't edited. A questionnaire asks where personal data goes and which cryptography protects it. The answers are the product's own behaviour, each one checkable.

✓Every administrative change in a signed chain, with a copy in your SIEM that verifies on its own. How it works →
✓Where data goes, written down and kept true by a test. history forget erases one person's runs and usage on request, audited by hash, not by name.
Compliance and audit
# sign the chain, keep a copy, stream it
QUERYAPIGATE_AUDIT_KEY=<a long random key>
QUERYAPIGATE_AUDIT_SYSLOG_URL=tls://siem.example.com:6514
QUERYAPIGATE_AUDIT_SYSLOG_CERT=/etc/queryapigate/client.pem
QUERYAPIGATE_AUDIT_SYSLOG_KEY=/etc/queryapigate/client.key

# the store, and what the SIEM received
queryapigate audit verify
# Intact: entries 1 to 5, keyed with QUERYAPIGATE_AUDIT_KEY.
queryapigate audit verify --file rsyslog.log
# Intact: entries 1 to 5, keyed with QUERYAPIGATE_AUDIT_KEY.

# a data subject asks to be forgotten
queryapigate history forget jwt:alice@example.com --dry-run
More use casesAll twelve →

Not sure which fits?

The example APIs ship with a generated database and one scoped key per scenario, so you can try each of these in a few minutes without connecting anything of your own.

Run the examplesCompare alternatives