require — what the engine must provide
The gateway refuses to start a connection that cannot meet every line. Each guarantee takes a minimum level from the capability ladder:native, enforced, or advisory.
native scoping means the database must enforce it — row-level security — so that it holds even for a connection that bypasses Warden. Asking for enforced accepts Warden’s governed relations. Both are defensible; the point is that you choose, and you find out at startup rather than during an incident.
approval — what needs a human
Classes are derived from the structure of the operation, never its leading keyword: a
WITH … DELETE … RETURNING wrapped in a SELECT is a delete. unbounded_mutation is a class of its own, because “change every record” deserves a different answer from “change this one”.
resources — what exists for this agent
Anything not listed is not merely denied: it is invisible.warden_describe_schema returns only permitted resources, because a schema listing is reconnaissance.
columns restricts the projection, enforced inside the statement rather than filtered from results.
scope — restricting rows to this agent
{tenant_id} comes from the agent’s scope values in warden.yaml. For PostgreSQL, each scoped table is replaced by a subquery already filtered, column-projected, and masked — so no alias, join, or expression in the agent’s own SQL can get around it.
limits
masking
Masking is applied inside the statement where the engine allows it, which is what stops
SELECT upper(email) or a join from unmasking a value. See masking.
Linting
require: block is checked at startup instead, against the real connection: warden serve probes the engine and refuses to start when a guarantee falls short of the level the policy demands.