Zero data access by construction, not by promise
“We never read your data” is easy to say and worthless to hear unless it is built into the machinery. In RowShield it is: the scanner cannot express a query against your tables, because the only SQL it possesses is six fixed statements about structure, defined as constants in source code.
This page sets out what those statements read, why the absence of bind parameters matters, and how to audit the claim yourself rather than taking it on faith.
Six statements, all constants
A connected capture runs exactly six queries: five read pg_catalog views describing tables, columns, policies and indexes, and one reads storage.buckets metadata; a companion call reads the server version string. Catalog views describe the shape of the database — names, types, ownership, policy expressions — and contain no row contents.
Each statement is a module-level constant in the scanner package, exported together as INTROSPECTION_QUERIES. Results are parsed into typed row interfaces declared in the same file, so the entire contract with your database — statements sent, shapes expected back — fits in one reviewable place. Nothing beyond these statements is ever requested: no counts, no samples, no contents of any kind.
The engine has no other vocabulary. It cannot issue a SELECT against public.invoices because no such statement exists anywhere in the codebase to send, and it never writes at all. We also recommend a scanning role whose only ability is reading the catalog, so even the account RowShield logs in with carries less privilege than most dashboards.
Zero bind parameters, by design
Introspection takes no user input, so there is nothing to parameterise: no table names interpolated, no identifiers concatenated, no query assembled at runtime. The bytes sent to Postgres today are the bytes committed in source, character for character, on every deployment and every run.
That removes an entire class of risk. With nothing to interpolate, there is no injection surface in introspection, and no way for a malformed name in your schema to alter what executes. A statement that never varies can be read once and trusted thereafter.
It also simplifies review. A reviewer diffing two releases compares literal SQL text rather than reconstructing runtime behaviour, and an incident responder can state with certainty which statements were sent during any scan, because the set is closed and versioned in source control.
Verifying the claim yourself
Audit beats assurance. Import INTROSPECTION_QUERIES and print each member, or read it directly in packages/scanner/src/introspect.ts. If you would rather not clone the repository, write to info@getveristria.com and we will send the current text of all six statements.
Nothing about this depends on trusting us to keep a promise; the constraint is structural, which is why the export exists and why this page points at code instead of adjectives. The typed row interfaces sitting beside the statements let an auditor confirm not only what is asked but what is done with the answer, in one file, without tracing helpers across the codebase.
Abridged, the policy statement gives the flavour — catalog views, fixed literals, no variables:
-- Abridged; the full text ships as INTROSPECTION_QUERIES.policies.
select schemaname, tablename, policyname, permissive, roles, cmd, qual, with_check
from pg_catalog.pg_policies
where schemaname not in ('pg_catalog', 'information_schema');Related questions
- Could a future release quietly start reading rows?
- Any change ships inside the same exported constants, so the diff is public and reviewable, and the documentation contract requires the help pages and the code to agree. The design makes silent expansion conspicuous rather than impossible — that is what auditable means here.
- Does the external probe follow the same rule?
- The probe sees only what any internet visitor sees — public pages, bundles and Supabase endpoints — and retains none of it as content. Its safety rules are described in the probe-safety article.
Did this answer your question? If not, tell us what is missing — article corrections go straight to the person who maintains it.