Role-based access control for SQL queries. Decide whether a role may run a query before it touches the database, on-prem.
Project description
query-warden
Role-based access control for SQL queries. Decide whether a role may run a query before it ever touches the database.
Part of the Governed Agent Stack: free, on-prem building blocks for an AI agent you can point at a real database and audit.
A safety layer like sql-sop answers "is this SQL safe?" and a read-only MCP server answers "is it read-only?". Neither answers the question that gets you in trouble with an LLM near real data: "is this person allowed to see this?" query-warden is that check.
You write the policy in YAML. It parses the query with sqlglot, pulls out the tables and columns it touches, and blocks anything outside the role's allow-list. No database connection, no execution, just a decision.
Install
pip install query-warden
Policy
default_role: operator
domains:
production: [production, prod_runs, waste_log]
staff: [staff, prod_shifts]
roles:
operator:
allow_domains: [production]
deny_columns: [hourly_rate, salary] # never expose pay to the floor
analyst:
allow_tables: ["*"] # read anything
A role may allow whole domains (named groups of tables), specific tables, or "*" for everything. deny_columns blocks named columns, and a bare SELECT * is rejected when any column is denied (it could expose them). COUNT(*) is fine.
Use it
As a library:
from query_warden import Warden
warden = Warden.from_yaml("policy.yaml")
warden.check("SELECT product_id, waste_kg FROM waste_log", role="operator")
# Decision(allowed=True, role='operator', violations=[])
d = warden.check("SELECT name, hourly_rate FROM staff", role="operator")
d.allowed # False
d.reason # "role 'operator' may not query table 'staff'; role 'operator' may not access column 'hourly_rate'"
From the command line (exit 0 = allowed, 1 = denied):
query-warden check --policy policy.yaml --role operator "SELECT * FROM staff"
# DENY (role=operator): role 'operator' may not query table 'staff' ...
Where it fits
query-warden is the access-control layer in the Governed Agent Stack. Put it next to the other guards, after SQL generation and before execution:
question -> agent -> generated SQL -> [read-only] -> [sql-sop lint] -> [query-warden role check] -> database
It pairs naturally with two other tools in the stack:
- schema-scout already flags PII columns, so it can seed a starter policy ("deny these columns unless a role opts in").
- agent-blackbox can record every allow and deny, so "who tried to access what" has a tamper-evident answer.
Read-only by design
query-warden never connects to a database and never runs the query. It reasons about the SQL text alone, so it is safe to call on every query in the hot path and easy to test as a pure function.
Tests
pip install -e ".[dev]"
pytest
License
MIT.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file query_warden-0.1.0.tar.gz.
File metadata
- Download URL: query_warden-0.1.0.tar.gz
- Upload date:
- Size: 6.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
62b7d3153bb0f3ce9b6d299389b8ec7a98403c85a82bb8972d32de5f35fba683
|
|
| MD5 |
d87484eb40283e61d70bc1e87277df78
|
|
| BLAKE2b-256 |
b111e0d33b9b3c317c496769307bd86365afe0d9e772f9a5c07a7cd690238a1d
|
Provenance
The following attestation bundles were made for query_warden-0.1.0.tar.gz:
Publisher:
release.yml on Pawansingh3889/query-warden
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
query_warden-0.1.0.tar.gz -
Subject digest:
62b7d3153bb0f3ce9b6d299389b8ec7a98403c85a82bb8972d32de5f35fba683 - Sigstore transparency entry: 2103135088
- Sigstore integration time:
-
Permalink:
Pawansingh3889/query-warden@bcdfe624b2e12df374f16e9f0cb15932c0a5c137 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Pawansingh3889
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@bcdfe624b2e12df374f16e9f0cb15932c0a5c137 -
Trigger Event:
push
-
Statement type:
File details
Details for the file query_warden-0.1.0-py3-none-any.whl.
File metadata
- Download URL: query_warden-0.1.0-py3-none-any.whl
- Upload date:
- Size: 8.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ec09d4c4129e0f854ffebcea2108bafb67b6ade12030264e80f96a0c5b91384f
|
|
| MD5 |
d8db6ee40ac50318cd5e6fa2441654a3
|
|
| BLAKE2b-256 |
500f283dfe4007006c6b5da51cda5fabfa3d03e246b547e0d8e8e28009b18d86
|
Provenance
The following attestation bundles were made for query_warden-0.1.0-py3-none-any.whl:
Publisher:
release.yml on Pawansingh3889/query-warden
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
query_warden-0.1.0-py3-none-any.whl -
Subject digest:
ec09d4c4129e0f854ffebcea2108bafb67b6ade12030264e80f96a0c5b91384f - Sigstore transparency entry: 2103135671
- Sigstore integration time:
-
Permalink:
Pawansingh3889/query-warden@bcdfe624b2e12df374f16e9f0cb15932c0a5c137 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Pawansingh3889
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@bcdfe624b2e12df374f16e9f0cb15932c0a5c137 -
Trigger Event:
push
-
Statement type: