supabase
Handles the full Supabase workflow from schema changes to deployment, with built-in security guardrails that catch common traps like RLS...
bknd-assign-permissions
Use when assigning permissions to roles in Bknd. Covers permission syntax (simple strings, extended format), permission effects (allow/deny), policies with conditions, entity-specific permissions, and fine-grained access control patterns.
Full skill instructions
Configure detailed permissions for roles using simple strings, extended format with effects, and conditional policies.
auth: { enabled: true })guard: { enabled: true })UI steps: Admin Panel > Auth > Roles > Select role
Note: Permission assignment requires code mode. UI is read-only.
Assign basic permissions as string array:
import { serve } from "bknd/adapter/bun";
import { em, entity, text } from "bknd";
const schema = em({
posts: entity("posts", { title: text().required() }),
});
serve({
connection: { url: "file:data.db" },
config: {
data: schema.toJSON(),
auth: {
enabled: true,
guard: { enabled: true },
roles: {
editor: {
implicit_allow: false,
permissions: [
"data.entity.read", // Read any entity
"data.entity.create", // Create in any entity
"data.entity.update", // Update any entity
// No delete permission
],
},
},
},
},
});
| Permission | Filterable | Description |
|---|---|---|
data.entity.read | Yes | Read entity records |
data.entity.create | Yes | Create new records |
data.entity.update | Yes | Update existing records |
data.entity.delete | Yes | Delete records |
data.database.sync | No | Sync database schema |
data.raw.query | No | Execute raw SELECT |
data.raw.mutate | No | Execute raw INSERT/UPDATE/DELETE |
Filterable means you can add conditions/filters via policies.
Use objects for explicit allow/deny effects:
{
roles: {
moderator: {
implicit_allow: false,
permissions: [
{ permission: "data.entity.read", effect: "allow" },
{ permission: "data.entity.update", effect: "allow" },
{ permission: "data.entity.delete", effect: "deny" }, // Explicit deny
],
},
},
}
| Effect | Description |
|---|---|
allow | Grant the permission (default) |
deny | Explicitly block the permission |
Deny overrides allow - useful when implicit_allow: true but you want to block specific actions.
Add policies for fine-grained control:
{
roles: {
content_editor: {
implicit_allow: false,
permissions: [
{
permission: "data.entity.read",
effect: "allow",
policies: [
{
description: "Only read posts and comments",
condition: { entity: { $in: ["posts", "comments"] } },
effect: "allow",
},
],
},
{
permission: "data.entity.create",
effect: "allow",
policies: [
{
condition: { entity: { $in: ["posts", "comments"] } },
effect: "allow",
},
],
},
],
},
},
}
{
description?: string, // Human-readable (optional)
condition?: ObjectQuery, // When policy applies
effect: "allow" | "deny" | "filter",
filter?: ObjectQuery, // Row filter (for effect: "filter")
}
| Effect | Purpose |
|---|---|
allow | Grant when condition met |
deny | Block when condition met |
filter | Apply row-level filter to results |
| Operator | Description | Example |
|---|---|---|
$eq | Equal | { entity: { $eq: "posts" } } |
$ne | Not equal | { entity: { $ne: "users" } } |
$in | In array | { entity: { $in: ["posts", "comments"] } } |
$nin | Not in array | { entity: { $nin: ["users", "secrets"] } } |
$gt | Greater than | { age: { $gt: 18 } } |
$gte | Greater or equal | { level: { $gte: 5 } } |
$lt | Less than | { count: { $lt: 100 } } |
$lte | Less or equal | { priority: { $lte: 3 } } |
Reference runtime context with @variable:
| Placeholder | Description |
|---|---|
@user.id | Current user's ID |
@user.email | Current user's email |
@user.role | Current user's role |
@entity | Current entity name |
@id | Current record ID |
Example - user can only update their own profile:
{
permissions: [
{
permission: "data.entity.update",
effect: "allow",
policies: [
{
condition: { entity: "users", "@id": "@user.id" },
effect: "allow",
},
],
},
],
}
Grant different permissions per entity:
{
roles: {
blog_author: {
implicit_allow: false,
permissions: [
// Full CRUD on posts
{
permission: "data.entity.read",
effect: "allow",
policies: [{ condition: { entity: "posts" }, effect: "allow" }],
},
{
permission: "data.entity.create",
effect: "allow",
policies: [{ condition: { entity: "posts" }, effect: "allow" }],
},
{
permission: "data.entity.update",
effect: "allow",
policies: [{ condition: { entity: "posts" }, effect: "allow" }],
},
{
permission: "data.entity.delete",
effect: "allow",
policies: [{ condition: { entity: "posts" }, effect: "allow" }],
},
// Read-only on categories
{
permission: "data.entity.read",
effect: "allow",
policies: [{ condition: { entity: "categories" }, effect: "allow" }],
},
],
},
},
}
{
roles: {
viewer: {
implicit_allow: false,
permissions: ["data.entity.read"],
},
},
}
{
roles: {
contributor: {
implicit_allow: false,
permissions: [
"data.entity.read",
"data.entity.create",
"data.entity.update",
{ permission: "data.entity.delete", effect: "deny" },
],
},
},
}
{
roles: {
admin: {
implicit_allow: true, // Allow all by default
permissions: [
// But deny raw database access
{ permission: "data.raw.query", effect: "deny" },
{ permission: "data.raw.mutate", effect: "deny" },
],
},
},
}
{
roles: {
content_manager: {
implicit_allow: false,
permissions: [
// Content entities: full CRUD
{
permission: "data.entity.read",
effect: "allow",
policies: [{
condition: { entity: { $in: ["posts", "pages", "comments", "media"] } },
effect: "allow",
}],
},
{
permission: "data.entity.create",
effect: "allow",
policies: [{
condition: { entity: { $in: ["posts", "pages", "comments", "media"] } },
effect: "allow",
}],
},
{
permission: "data.entity.update",
effect: "allow",
policies: [{
condition: { entity: { $in: ["posts", "pages", "comments", "media"] } },
effect: "allow",
}],
},
{
permission: "data.entity.delete",
effect: "allow",
policies: [{
condition: { entity: { $in: ["posts", "pages", "comments"] } }, // No media delete
effect: "allow",
}],
},
],
},
},
}
{
roles: {
user: {
implicit_allow: false,
permissions: [
// Can read most entities
"data.entity.read",
// But never access secrets entity
{
permission: "data.entity.read",
effect: "deny",
policies: [{
condition: { entity: "secrets" },
effect: "deny",
}],
},
],
},
},
}
For complex role definitions:
// helpers/permissions.ts
type EntityPermission = "read" | "create" | "update" | "delete";
function entityPermissions(
entities: string[],
actions: EntityPermission[]
) {
const permMap: Record<EntityPermission, string> = {
read: "data.entity.read",
create: "data.entity.create",
update: "data.entity.update",
delete: "data.entity.delete",
};
return actions.map((action) => ({
permission: permMap[action],
effect: "allow" as const,
policies: [{
condition: { entity: { $in: entities } },
effect: "allow" as const,
}],
}));
}
// Usage
{
roles: {
blog_author: {
implicit_allow: false,
permissions: [
...entityPermissions(["posts", "comments"], ["read", "create", "update"]),
...entityPermissions(["categories", "tags"], ["read"]),
],
},
},
}
Test permission assignments:
1. Login as user with role:
curl -X POST http://localhost:7654/api/auth/password/login \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]", "password": "password123"}'
2. Test allowed permission:
curl http://localhost:7654/api/data/posts \
-H "Authorization: Bearer <token>"
# Should return 200 with data
3. Test denied permission:
curl -X DELETE http://localhost:7654/api/data/posts/1 \
-H "Authorization: Bearer <token>"
# Should return 403 Forbidden
4. Test entity-specific permission:
# If only posts/comments allowed:
curl http://localhost:7654/api/data/users \
-H "Authorization: Bearer <token>"
# Should return 403 if users entity not in allowed list
Problem: Changed permissions but old behavior persists
Fix: Restart server - role config is loaded at startup:
# Stop and restart
bknd run
Problem: Deny effect not blocking access
Fix: Check policy condition - deny only applies when condition matches:
// WRONG - no condition, may not match
{ permission: "data.entity.delete", effect: "deny" }
// CORRECT - simple deny at permission level
{
permissions: [
"data.entity.read",
"data.entity.create",
// Don't include delete at all
],
}
Problem: Entity-specific permission not working
Fix: Verify entity name matches exactly:
// WRONG - entity name case matters
{ condition: { entity: "Posts" } }
// CORRECT - use exact entity name
{ condition: { entity: "posts" } }
Problem: Confusing behavior with multiple policies
Fix: Understand evaluation order - first matching policy wins:
{
policies: [
// More specific first
{ condition: { entity: "secrets" }, effect: "deny" },
// General fallback last
{ effect: "allow" },
],
}
Problem: @user.id appearing literally in filter
Fix: Variables only work in filter and condition fields:
// CORRECT usage
{
condition: { "@id": "@user.id" }, // Works
filter: { user_id: "@user.id" }, // Works
}
DO:
$in operator for multiple entitiesimplicit_allowDON'T:
data.raw.* to non-admin roles (SQL injection risk)implicit_allow: true with deny policies (confusing)Handles the full Supabase workflow from schema changes to deployment, with built-in security guardrails that catch common traps like RLS...
Comprehensive guides and best practices for Neon Serverless Postgres, covering setup, connection methods, authentication, and platform APIs.
Guide for setting up and using Firebase Authentication. Use this skill when the user's app requires user sign-in, user management, or secure data access using auth rules.
A skill to evaluate how secure Firestore security rules are. Use this when Firestore security rules are updated to ensure that the generated rules are extremely secure and robust.
Official skill for integrating Firebase AI Logic (Gemini API) into web applications. Covers setup, multimodal inference, structured output, and security.
Complete Better Auth server and client setup with database adapters, session management, plugins, and security configuration.
Deploy and manage projects on Vercel using token-based authentication. Use when working with Vercel CLI using access tokens rather than interactive login — e.g. "deploy to vercel", "set up vercel", "add environment variables to vercel".
Complete Cloudflare platform integration with decision trees for compute, storage, AI, networking, security, and infrastructure-as-code.
Run Azure compliance and security audits with azqr plus Key Vault expiration checks. Covers best-practice assessment, resource review, policy/compliance validation, and security posture checks. WHEN: compliance scan, security audit, BEFORE running azqr (compliance cli tool), Azure best practices, Key Vault expiration check, expired certificates, expiring secrets, orphaned resources, compliance assessment.
Send, read, and manage Gmail messages, drafts, labels, and account settings.
Comprehensive website auditing across 230+ rules in 21 categories including SEO, performance, security, and accessibility.
Shared authentication, CLI syntax, and output formatting patterns for gws Google Workspace commands.
Discover your celebrity doppelgänger with StarByFace!
GeoSpy: Pricing, Features, FAQs, and Alternatives for AI Teams
Detect AI-generated voices to protect against audio fraud.
Ensure Your Content's Originality with AI Plagiarism Checker
Upscale images by 400% without quality loss
Protect your social media from copyright disputes
Accurately Detect AI-Generated Content with TheChecker.AI
Chrome extension that detects and flags AI-generated content