Repository navigation
Recipes
These recipes are composable starting points. Replace table and field names with your Drizzle schema.
user: {
allowed: {
field: ["id", "title", "owner_id"],
where: { field: "owner_id", operator: "=", value: "$user.id" }
},
disallowed: []
}support: {
allowed: "*",
disallowed: ["password_hash", "secret_key", "recovery_token"]
}Prefer an allowlist for high-risk records because newly added schema fields will not become visible automatically.
{
type: "GET",
admin: ALL,
member: {
allowed: {
field: ["id", "name", "workspace_id"],
where: { field: "workspace_id", operator: "=", value: "$user.workspace_id" }
},
disallowed: []
}
}Repeat the workspace constraint on every protected endpoint and related table. Qualify columns in joins.
where: {
and: [
{ field: "orders.workspace_id", operator: "=", value: "$user.workspace_id" },
{ field: "orders.archived", operator: "=", value: false }
]
}{
if: {
when: { left_value: "$data.orders.status", operator: "=", value: "cancelled" },
do: { field: "orders.status", operator: "IN", value: ["draft", "submitted"] },
else: true
}
}Combine three checks: the user's reviewer role, ownership or tenant scope, and an existing submitted state before allowing $data.status = "approved".
{
table: "orders",
type: "GET",
select: ["orders.id", "customers.name"],
join: [{ table: "customers", type: "LEFT", on: { "orders.customer_id": "customers.id" } }]
}The joined table must also expose the applicable endpoint and role permissions for requested fields.
Use an array in data, and ensure payload-dependent rules are tested for every item shape. Add database constraints for invariants that must survive every access path.
Start Here
Learn & Build
- Learn VoidQL
- Build with VoidQL
- Query Operations
- Authorization Patterns
- Validation & Workflows
- Triggers & Extensibility
Use & Reference
Internals & Project