bknd-create-role
Use when defining a new role in Bknd authorization system. Covers role properties (implicit_allow, is_default, permissions), permission assignment, role hierarchies, and common role patterns (admin, editor, viewer, anonymous).
What this skill does
# Create Role
Define a new role in Bknd's authorization system to control user access.
## Prerequisites
- Bknd project initialized with code-first configuration
- Auth enabled (`auth: { enabled: true }`)
- Guard enabled for authorization (`guard: { enabled: true }`)
## When to Use UI Mode
- Viewing existing roles
- Quick toggle of role settings
**UI steps:** Admin Panel > Auth > Roles
**Note:** Role creation requires code mode. UI only shows existing roles.
## When to Use Code Mode
- Creating new roles
- Setting role permissions
- Configuring default roles
- Setting up role hierarchies
## Code Approach
### Step 1: Enable Guard
Roles require the guard system to be enabled:
```typescript
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 }, // Required for roles
roles: {
// Roles defined here
},
},
},
});
```
### Step 2: Define a Basic Role
Create a role with explicit permissions:
```typescript
{
auth: {
enabled: true,
guard: { enabled: true },
roles: {
viewer: {
implicit_allow: false, // Deny by default
permissions: [
"data.entity.read", // Grant read access only
],
},
},
},
}
```
### Role Properties
| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `implicit_allow` | boolean | `false` | Allow all unless denied |
| `is_default` | boolean | `false` | Use when user has no role |
| `permissions` | array | `[]` | Permissions granted to role |
### Step 3: Create Admin Role (Full Access)
Grant full access with `implicit_allow`:
```typescript
{
roles: {
admin: {
implicit_allow: true, // Can do everything
},
},
}
```
**Warning:** `implicit_allow: true` grants ALL permissions. Use only for admin roles.
### Step 4: Create Editor Role (Partial Access)
Grant specific CRUD permissions:
```typescript
{
roles: {
editor: {
implicit_allow: false,
permissions: [
"data.entity.read",
"data.entity.create",
"data.entity.update",
// No delete permission
],
},
},
}
```
### Step 5: Create Default Role
Set a role for users without assigned role:
```typescript
{
roles: {
anonymous: {
is_default: true, // Applied when no role
implicit_allow: false,
permissions: [
"data.entity.read", // Read-only access
],
},
},
}
```
**Note:** Only ONE role can have `is_default: true`.
### Step 6: Set Registration Role
Assign role to newly registered users:
```typescript
{
auth: {
enabled: true,
default_role_register: "user", // Role for new registrations
roles: {
user: {
implicit_allow: false,
permissions: ["data.entity.read"],
},
},
},
}
```
## Available Permissions
| Permission | Description |
|------------|-------------|
| `data.entity.read` | Read any entity records |
| `data.entity.create` | Create records in any entity |
| `data.entity.update` | Update records in any entity |
| `data.entity.delete` | Delete records from any entity |
| `data.database.sync` | Sync database schema |
| `data.raw.query` | Execute raw SELECT queries |
| `data.raw.mutate` | Execute raw INSERT/UPDATE/DELETE |
## Common Role Patterns
### Multi-Tier Access System
```typescript
{
auth: {
enabled: true,
guard: { enabled: true },
default_role_register: "user",
roles: {
// Full access
admin: {
implicit_allow: true,
},
// Content management
editor: {
implicit_allow: false,
permissions: [
"data.entity.read",
"data.entity.create",
"data.entity.update",
"data.entity.delete",
],
},
// Create and read
contributor: {
implicit_allow: false,
permissions: [
"data.entity.read",
"data.entity.create",
],
},
// Authenticated read-only
user: {
implicit_allow: false,
permissions: [
"data.entity.read",
],
},
// Unauthenticated/guest
anonymous: {
is_default: true,
implicit_allow: false,
permissions: [
"data.entity.read",
],
},
},
},
}
```
### Closed System (No Public Access)
```typescript
{
auth: {
enabled: true,
guard: { enabled: true },
allow_register: false, // Disable self-registration
roles: {
admin: {
implicit_allow: true,
},
member: {
implicit_allow: false,
permissions: [
"data.entity.read",
"data.entity.create",
"data.entity.update",
],
},
// No default role - unauthenticated users get NO access
},
},
}
```
### API Consumer Role
```typescript
{
roles: {
api_client: {
implicit_allow: false,
permissions: [
"data.entity.read",
"data.entity.create",
// No update/delete - API clients create data only
],
},
},
}
```
## Permission Effects
Use extended format for allow/deny effects:
```typescript
{
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
],
},
},
}
```
## Role Assignment
### Assign During User Creation (Seed)
```typescript
{
options: {
seed: async (ctx) => {
await ctx.app.module.auth.createUser({
email: "[email protected]",
password: "secure-password",
role: "admin", // Assign admin role
});
},
},
}
```
### Assign During Registration
```typescript
{
auth: {
default_role_register: "user", // All registrations get "user" role
},
}
```
### Update User Role (API)
```typescript
const api = getApi(app);
// Update user's role
await api.data.updateOne("users", userId, {
role: "editor",
});
```
## Verification
Test role permissions:
**1. Create user with role:**
```bash
curl -X POST http://localhost:7654/api/auth/password/register \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]", "password": "password123"}'
```
**2. Login and get token:**
```bash
curl -X POST http://localhost:7654/api/auth/password/login \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]", "password": "password123"}'
```
**3. Test permission (should succeed for read):**
```bash
curl http://localhost:7654/api/data/posts \
-H "Authorization: Bearer <token>"
```
**4. Test denied permission (should fail for delete if not allowed):**
```bash
curl -X DELETE http://localhost:7654/api/data/posts/1 \
-H "Authorization: Bearer <token>"
# Returns 403 if delete not in permissions
```
## Common Pitfalls
### No Default Role
**Problem:** `User has no role` error for unauthenticated users
**Fix:** Set a default role:
```typescript
{
roles: {
anonymous: {
is_default: true,
permissions: ["data.entity.read"],
},
},
}
```
### Multiple Default Roles
**Problem:** Unpredictable behavior with multiple `is_default: true`
**Fix:** Only ONE role should be default:
```typescript
{
roles: {
user: { is_default: true }, // Only one!
guest: { /* no is_default */ },
},
}
```
### Role Not Found
**Problem:** `Role "admin" not found` when assigning
**Fix:** Define role before referencing:
```typescript
{
auth: {
roles: {
admin: { implicit_allow: true }, // Define first
},
default_role_register: "admin", // Then reference
},
}
```
### Guard Not Enabled
**Problem:** RoRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.