superapp
BackendPermissions

Validate

Validate data on insert and update operations before it reaches the database.

Chat in Claude

Validate rules check the values a user is trying to write. If the data does not match the rules, the request is rejected with 403 Forbidden before any SQL is executed.

permissions: {
  create_orders: {
    table: 'main.orders',
    roles: ['sales'],
    insert: {
      columns: ['amount', 'status', 'customer_id'],
      validate: {
        amount: { $gte: 0 },
        status: { $in: ['draft'] },
      },
    },
  },
}

A user trying to insert { amount: -50, status: 'draft' } gets rejected because amount fails the $gte: 0 validate rule.

How Validate Works

Validate runs before the query. It compares the request body values against the rules:

  1. Extract the values from the request body
  2. Apply each validate operator to the corresponding value
  3. If any rule fails, return 403 with the failing field
  4. If all pass, proceed to query execution

Validate vs. Where

WhereValidate
PurposeRow-level security (which rows)Value validation (what values)
Applies toselect, update, deleteinsert, update
MechanismAdds WHERE clauseValidates request body
FailureSilently excludes rowsReturns 403 error

Examples

Range Validation

insert: {
  columns: ['amount', 'status'],
  validate: {
    amount: { $gte: 0, $lte: 100_000 },
  },
}
// Allows: { amount: 500 }
// Rejects: { amount: -1 }, { amount: 200_000 }

Enum Validation

insert: {
  columns: ['status'],
  validate: {
    status: { $in: ['draft', 'active', 'closed'] },
  },
}
// Allows: { status: 'draft' }
// Rejects: { status: 'deleted' }, { status: 'archived' }

Multiple Field Validation

insert: {
  columns: ['amount', 'status', 'priority'],
  validate: {
    amount: { $gte: 0, $lte: 100_000 },
    status: { $in: ['draft', 'active', 'closed'] },
    priority: { $gte: 1, $lte: 5 },
  },
}
// All three fields are validated independently
// ALL must pass for the request to proceed

Update Validation

Validate also applies to update operations, validating the new values:

permissions: {
  edit_org_orders: {
    table: 'main.orders',
    roles: ['editor'],
    update: {
      columns: '*',
      where: { organization_id: { $in: '$user.org_ids' } },
      validate: {
        status: { $in: ['draft', 'active', 'closed'] },
        amount: { $gte: 0, $lte: 100_000 },
      },
    },
  },
}
// User can update orders in their org,
// but only set status to draft/active/closed
// and amount between 0 and 100,000

Validate with Session Variables

You can reference $user.* in validate values:

insert: {
  columns: ['organization_id', 'name'],
  validate: {
    organization_id: { $eq: '$user.current_org_id' },
  },
}
// Ensures users can only write to their own organization

Supported Operators

All comparison operators are available in validate rules: $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin.

On this page