wardencert ships in the source repository rather than in a release: it is the tool that proves a connector before it ships, and it needs the certification profiles and fixtures that live beside the code. Running it needs access to that repository.wardencert runs a connector against a real database and checks that every guarantee it claims is one it actually provides. It is how Warden avoids the failure mode of every governance tool: a feature list that nobody has tested against an engine that does not cooperate.
For PostgreSQL it connects to a local development database, overridable for CI:
make pg-fixture creates that database, its schema, and the least-privilege role; make pg-cert runs the suite against it.
For MongoDB it connects to the server in the DSN, overridable for CI:
The certification profile seeds its own
warden_cert database on every setup, so cases cannot cascade. make mongo-fixture seeds a development database instead (WARDEN_MONGO_DB, default warden_dev) with the same two tenants’ documents; make mongo-cert runs the suite. CI certifies against a single-node replica set rather than standalone, because transactions — and so any honest fence — do not exist without one. If the DSN asks for a replica set but the address answers with a standalone (usually a local mongod squatting on the container’s port), the connector names the mismatch instead of timing out — see the troubleshooting note.
For Neo4j the profile wipes and reseeds the configured database (WARDEN_NEO4J_DB, default neo4j) — Community serves only the default database, so point this at a throwaway server:
make neo4j-fixture applies the same seed; make neo4j-cert runs the suite.
What it checks
contract — the connector behaves like a connector
contract — the connector behaves like a connector
Capability claims match the interfaces actually implemented; introspection returns a usable catalog; sessions close; an operation with no agent is refused, because one Warden cannot attribute is one it should not run.
parse and classification — structure, not keywords
parse and classification — structure, not keywords
Each statement produces the Operation IR the specification requires: class, verb, targets, predicate, mutation, blast radius. A
WITH … DELETE … RETURNING inside a SELECT classifies as a delete, because classification comes from structure and never from the leading keyword.adversarial — the corpus that tries to get past it
adversarial — the corpus that tries to get past it
Around eighty cases per profile: homoglyph and zero-width identifiers, case folding, path separators and NUL bytes in names, identifiers supplied as parameters, malformed parameter tokens, writes smuggled into read-shaped requests, server-side code, statements carried alongside commands, and deletes bounded only by something the connector cannot normalise.A case passes only if the connector refuses it, flags the hazard, or classifies it at least as seriously as required. A case that its own request already satisfies is rejected by the suite itself — a test that cannot fail is not a test.
scope and governance — restrictions that survive contact with SQL
scope and governance — restrictions that survive contact with SQL
Scope is applied to every reference to a governed table, including aliases, joins, subqueries, and CTEs; the scope value never appears in the rewritten statement as a literal; column restriction removes unpermitted columns from the projection; masking survives aliasing, functions, and joins; and applying scope never changes the blast radius a reviewer is shown.
limits, dry run, and fences
limits, dry run, and fences
Row caps are injected and reported honestly as truncation; statement timeouts cancel rather than complete; a preview’s diff matches what committing actually does; and a fence detects a modification, a deletion, or a newly matching row between preview and commit.
identity — a lease is a real, narrow, revocable principal
identity — a lease is a real, narrow, revocable principal
For a connector claiming native identity:
- each lease gets its own principal, and statements actually run as it;
- the principal is no wider than the base grant, and can’t log in;
- the engine refuses a read the base grant never included, with no policy involved;
- revocation ends a transaction already in flight and removes the principal;
- a principal named like a lease’s but not made for it is never adopted or dropped.
Reading the output
-strict, a case a profile does not cover is reported as skipped. With it, a skip fails the run — which is what stops a profile being thinned out to make a build green.
Where it runs
Every commit: the in-memory connector in thecheck job, PostgreSQL against a real server in the postgres job, MongoDB against a single-node replica set in the mongo job, and Neo4j against a live server in the neo4j job. A connector that stops satisfying the specification fails the build rather than shipping.
Writing a connector
The certification profile is the contract a new engine implements against.