@kardoe/quickback 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/claude.d.ts +13 -0
- package/dist/commands/claude.d.ts.map +1 -0
- package/dist/commands/claude.js +305 -0
- package/dist/commands/claude.js.map +1 -0
- package/dist/commands/compile.d.ts.map +1 -1
- package/dist/commands/compile.js +43 -1
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/docs.d.ts +10 -0
- package/dist/commands/docs.d.ts.map +1 -0
- package/dist/commands/docs.js +69 -0
- package/dist/commands/docs.js.map +1 -0
- package/dist/commands/skill.d.ts +13 -0
- package/dist/commands/skill.d.ts.map +1 -0
- package/dist/commands/skill.js +305 -0
- package/dist/commands/skill.js.map +1 -0
- package/dist/docs/content.d.ts +7 -0
- package/dist/docs/content.d.ts.map +1 -0
- package/dist/docs/content.js +92 -0
- package/dist/docs/content.js.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/auth.d.ts +5 -1
- package/dist/lib/auth.d.ts.map +1 -1
- package/dist/lib/auth.js +11 -1
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/compiler-stubs.d.ts +15 -0
- package/dist/lib/compiler-stubs.d.ts.map +1 -1
- package/dist/lib/compiler-stubs.js +21 -0
- package/dist/lib/compiler-stubs.js.map +1 -1
- package/dist/lib/file-loader.d.ts +55 -0
- package/dist/lib/file-loader.d.ts.map +1 -1
- package/dist/lib/file-loader.js +153 -3
- package/dist/lib/file-loader.js.map +1 -1
- package/dist/lib/markdown-renderer.d.ts +8 -0
- package/dist/lib/markdown-renderer.d.ts.map +1 -0
- package/dist/lib/markdown-renderer.js +151 -0
- package/dist/lib/markdown-renderer.js.map +1 -0
- package/package.json +8 -3
- package/src/skill/SKILL.md +452 -0
- package/src/skill/agents/quickback-specialist/AGENT.md +103 -0
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: quickback
|
|
3
|
+
description: Quickback API engine documentation - use when working with Quickback projects, defining resources, schemas, security pillars (Firewall, Access, Guards, Masking), actions, webhooks, or deployment
|
|
4
|
+
allowed-tools: Read, Grep, Glob
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Quickback: The Universal API Engine for B2B SaaS
|
|
8
|
+
|
|
9
|
+
Quickback gives you a **complete, secure, multi-tenant backend in minutes**.
|
|
10
|
+
|
|
11
|
+
You define your data model and business rules in TypeScript, and Quickback compiles them into production-ready APIs with authentication, permissions, multi-tenancy, and audit logging—all enforced by **auditable, static code** you can read and verify.
|
|
12
|
+
|
|
13
|
+
## Getting Started
|
|
14
|
+
|
|
15
|
+
**Always use the CLI to initialize new projects:**
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# Install the CLI
|
|
19
|
+
npm install -g @kardoe/quickback
|
|
20
|
+
|
|
21
|
+
# Create a new project (scaffolds correct structure)
|
|
22
|
+
quickback create cloudflare my-app
|
|
23
|
+
|
|
24
|
+
# Or for other templates
|
|
25
|
+
quickback create bun my-app
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
This creates the correct project structure with all configuration files.
|
|
29
|
+
|
|
30
|
+
## Architecture
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
┌─────────────────────────────────────────────────────────┐
|
|
34
|
+
│ YOU DEFINE (in TypeScript) │
|
|
35
|
+
│ • Drizzle schema (your data models) │
|
|
36
|
+
│ • Security layers (Firewall, Access, Guards, Masking) │
|
|
37
|
+
│ • CRUD configuration │
|
|
38
|
+
│ • Actions (your business operations) │
|
|
39
|
+
├─────────────────────────────────────────────────────────┤
|
|
40
|
+
│ QUICKBACK COMPILES TO (Static, Signed, Auditable Code) │
|
|
41
|
+
│ • Database migrations (via Drizzle) │
|
|
42
|
+
│ • API route handlers (in a Hono project) │
|
|
43
|
+
│ • Typed client SDK for your frontend │
|
|
44
|
+
│ • AI tool definitions │
|
|
45
|
+
│ • OpenAPI specification │
|
|
46
|
+
│ • Compliance manifest │
|
|
47
|
+
└─────────────────────────────────────────────────────────┘
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Security & Compliance Pillars
|
|
51
|
+
|
|
52
|
+
| Requirement | Quickback Solution |
|
|
53
|
+
|---|---|
|
|
54
|
+
| **Multi-tenant data isolation** | **Firewall** — Enforces multi-tenancy and ownership via compiled WHERE clauses |
|
|
55
|
+
| **Role-based permissions** | **Access** — Declare required authentication status and roles, compiled into middleware |
|
|
56
|
+
| **Protect sensitive fields** | **Guards** — Allow-lists for writable fields, enforced at compile time |
|
|
57
|
+
| **Mask PII in responses** | **Masking** — Declarative PII masks compiled directly into API responses |
|
|
58
|
+
| **Workflow state machines** | **Actions** — Typed state transitions with preconditions |
|
|
59
|
+
| **AI-safe mutation boundaries** | **Actions** — Constrained, typed tools an AI can safely call |
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
# Project Configuration
|
|
64
|
+
|
|
65
|
+
## quickback.config.ts
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
import { defineConfig, defineRuntime, defineDatabase, defineAuth } from '@quickback/compiler';
|
|
69
|
+
|
|
70
|
+
export default defineConfig({
|
|
71
|
+
name: "my-saas-app",
|
|
72
|
+
providers: {
|
|
73
|
+
runtime: defineRuntime("cloudflare"),
|
|
74
|
+
database: defineDatabase("cloudflare-d1"),
|
|
75
|
+
auth: defineAuth("better-auth"),
|
|
76
|
+
},
|
|
77
|
+
build: {
|
|
78
|
+
outputDir: "dist",
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Automatic Audit Fields
|
|
84
|
+
|
|
85
|
+
Quickback automatically injects these fields into every table:
|
|
86
|
+
- `createdAt`, `modifiedAt`, `deletedAt` (timestamps)
|
|
87
|
+
- `createdBy`, `modifiedBy`, `deletedBy` (user IDs)
|
|
88
|
+
|
|
89
|
+
Do NOT add these to your schema.ts files.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
# Feature Definitions (Combined Mode)
|
|
94
|
+
|
|
95
|
+
Features live in `quickback/features/{name}/` with one file per table using `defineTable()`.
|
|
96
|
+
|
|
97
|
+
**Important**: Legacy mode (separate schema.ts + resource.ts) is no longer supported.
|
|
98
|
+
|
|
99
|
+
## Example: todos.ts
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
|
|
103
|
+
import { defineTable } from "@quickback/compiler";
|
|
104
|
+
|
|
105
|
+
export const todos = sqliteTable("todos", {
|
|
106
|
+
id: integer("id").primaryKey(),
|
|
107
|
+
title: text("title").notNull(),
|
|
108
|
+
completed: integer("completed", { mode: "boolean" }).default(false),
|
|
109
|
+
userId: text("user_id").notNull(),
|
|
110
|
+
organizationId: text("organization_id").notNull(),
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
export default defineTable(todos, {
|
|
114
|
+
crud: ["create", "read", "update", "delete"],
|
|
115
|
+
|
|
116
|
+
firewall: {
|
|
117
|
+
organization: { column: "organizationId" },
|
|
118
|
+
owner: { column: "userId" },
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
guards: {
|
|
122
|
+
createable: ["title", "completed"],
|
|
123
|
+
updatable: ["title", "completed"],
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
masking: {
|
|
127
|
+
userId: { type: "redact", show: { roles: ["admin"] } },
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
# Security Pillars
|
|
135
|
+
|
|
136
|
+
## 1. Firewall - Data Isolation
|
|
137
|
+
|
|
138
|
+
Compiles WHERE clauses to isolate data by ownership.
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
firewall: {
|
|
142
|
+
organization: {}, // WHERE organizationId = ctx.activeOrgId
|
|
143
|
+
owner: { mode: 'optional' }, // AND (ownerId = ctx.userId OR ownerId IS NULL)
|
|
144
|
+
team: {}, // WHERE teamId = ctx.activeTeamId
|
|
145
|
+
softDelete: {}, // AND deletedAt IS NULL
|
|
146
|
+
exception: true, // No filtering (public resources)
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Column Overrides
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
firewall: {
|
|
154
|
+
organization: {
|
|
155
|
+
column: 'tenant_id', // Instead of 'organizationId'
|
|
156
|
+
source: 'ctx.tenant.id', // Instead of 'ctx.activeOrgId'
|
|
157
|
+
},
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## 2. Access - Permission Checks
|
|
162
|
+
|
|
163
|
+
Role-based and record-based access control.
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
crud: {
|
|
167
|
+
list: { access: { roles: ['member'] } },
|
|
168
|
+
get: { access: { roles: ['member'] } },
|
|
169
|
+
create: { access: { roles: ['admin', 'manager'] } },
|
|
170
|
+
update: {
|
|
171
|
+
access: {
|
|
172
|
+
or: [
|
|
173
|
+
{ roles: ['admin'] },
|
|
174
|
+
{ record: { createdBy: { equals: '$ctx.userId' } } },
|
|
175
|
+
],
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
delete: { access: { roles: ['admin'] } },
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**Record Conditions**: `equals`, `notEquals`, `in`, `notIn`, `greaterThan`, `lessThan`
|
|
183
|
+
|
|
184
|
+
## 3. Guards - Field Protection
|
|
185
|
+
|
|
186
|
+
Controls which fields can be modified.
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
guards: {
|
|
190
|
+
createable: ['name', 'description'], // Allowed on POST
|
|
191
|
+
updatable: ['description'], // Allowed on PATCH
|
|
192
|
+
immutable: ['invoiceNumber'], // Set once, never change
|
|
193
|
+
protected: { status: ['approve'] }, // Only via actions
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**System-managed fields** (always protected):
|
|
198
|
+
- `createdAt`, `createdBy` - Set on INSERT
|
|
199
|
+
- `modifiedAt`, `modifiedBy` - Set on INSERT/UPDATE
|
|
200
|
+
- `deletedAt`, `deletedBy` - Set on soft DELETE
|
|
201
|
+
|
|
202
|
+
## 4. Masking - Response Transformation
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
masking: {
|
|
206
|
+
ssn: {
|
|
207
|
+
type: 'ssn', // ***-**-6789
|
|
208
|
+
show: { roles: ['admin', 'hr'] },
|
|
209
|
+
},
|
|
210
|
+
email: {
|
|
211
|
+
type: 'email', // p***@e****.com
|
|
212
|
+
show: { roles: ['admin'], or: 'owner' },
|
|
213
|
+
},
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
**Mask types**: `email`, `phone`, `ssn`, `creditCard`, `name`, `redact`, `custom`
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
# Actions - Custom Business Logic
|
|
222
|
+
|
|
223
|
+
Actions are custom API endpoints for business logic beyond CRUD.
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
// definitions/features/todos/actions.ts
|
|
227
|
+
export default {
|
|
228
|
+
name: "todos",
|
|
229
|
+
schema: "./schema",
|
|
230
|
+
|
|
231
|
+
actions: {
|
|
232
|
+
complete: {
|
|
233
|
+
description: "Mark todo as complete",
|
|
234
|
+
input: {
|
|
235
|
+
type: "object",
|
|
236
|
+
properties: {
|
|
237
|
+
completedAt: { type: "string", format: "datetime", optional: true },
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
guard: {
|
|
241
|
+
roles: ["owner", "member", "admin"],
|
|
242
|
+
record: { completed: { equals: false } },
|
|
243
|
+
},
|
|
244
|
+
sideEffects: "sync",
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
};
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
**Generated Route**: `POST /api/v1/todos/:id/complete`
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
# API Reference
|
|
255
|
+
|
|
256
|
+
## CRUD Operations
|
|
257
|
+
|
|
258
|
+
| Method | Endpoint | Description |
|
|
259
|
+
|--------|----------|-------------|
|
|
260
|
+
| `GET` | `/api/v1/{resource}` | List records |
|
|
261
|
+
| `GET` | `/api/v1/{resource}/:id` | Get single record |
|
|
262
|
+
| `POST` | `/api/v1/{resource}` | Create record |
|
|
263
|
+
| `PATCH` | `/api/v1/{resource}/:id` | Update record |
|
|
264
|
+
| `DELETE` | `/api/v1/{resource}/:id` | Delete record |
|
|
265
|
+
| `PUT` | `/api/v1/{resource}/:id` | Upsert (if enabled) |
|
|
266
|
+
|
|
267
|
+
## Query Parameters
|
|
268
|
+
|
|
269
|
+
### Pagination
|
|
270
|
+
|
|
271
|
+
| Param | Default | Max |
|
|
272
|
+
|-------|---------|-----|
|
|
273
|
+
| `limit` | 50 | 100 |
|
|
274
|
+
| `offset` | 0 | - |
|
|
275
|
+
|
|
276
|
+
### Filtering Operators
|
|
277
|
+
|
|
278
|
+
| Operator | Example | SQL |
|
|
279
|
+
|----------|---------|-----|
|
|
280
|
+
| `.gt` | `?amount.gt=100` | `amount > 100` |
|
|
281
|
+
| `.gte` | `?amount.gte=100` | `amount >= 100` |
|
|
282
|
+
| `.lt` | `?amount.lt=1000` | `amount < 1000` |
|
|
283
|
+
| `.lte` | `?amount.lte=1000` | `amount <= 1000` |
|
|
284
|
+
| `.ne` | `?status.ne=cancelled` | `status != 'cancelled'` |
|
|
285
|
+
| `.like` | `?title.like=urgent` | `title LIKE '%urgent%'` |
|
|
286
|
+
| `.in` | `?status.in=draft,pending` | `status IN ('draft','pending')` |
|
|
287
|
+
|
|
288
|
+
### Sorting
|
|
289
|
+
|
|
290
|
+
```
|
|
291
|
+
?sort=createdAt&order=desc
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Response Format
|
|
295
|
+
|
|
296
|
+
```json
|
|
297
|
+
{
|
|
298
|
+
"data": [{ "id": "...", "title": "Todo 1" }],
|
|
299
|
+
"pagination": {
|
|
300
|
+
"limit": 10,
|
|
301
|
+
"offset": 0,
|
|
302
|
+
"count": 2
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
# Resource Styles
|
|
310
|
+
|
|
311
|
+
## Controlled Resources (Default)
|
|
312
|
+
|
|
313
|
+
Server generates IDs, guards restrict modifications.
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
// HTTP Methods: POST, PATCH, GET, LIST, DELETE
|
|
317
|
+
export default defineTable(invoices, {
|
|
318
|
+
guards: {
|
|
319
|
+
createable: ['description', 'amount'],
|
|
320
|
+
updatable: ['description'],
|
|
321
|
+
},
|
|
322
|
+
crud: { create: {}, update: {}, get: {}, list: {}, delete: {} },
|
|
323
|
+
});
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
## External/Sync Resources (PUT enabled)
|
|
327
|
+
|
|
328
|
+
Client provides IDs, no field restrictions.
|
|
329
|
+
|
|
330
|
+
```typescript
|
|
331
|
+
// Database config: generateId: false
|
|
332
|
+
// HTTP Methods: POST, PUT, PATCH, GET, LIST, DELETE
|
|
333
|
+
export default defineTable(external_orders, {
|
|
334
|
+
guards: false, // Enables PUT
|
|
335
|
+
crud: {
|
|
336
|
+
put: { access: { roles: ['sync-service'] } },
|
|
337
|
+
get: {},
|
|
338
|
+
list: {}
|
|
339
|
+
},
|
|
340
|
+
});
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
**PUT Rule**: Only available when BOTH `generateId: false` AND `guards: false`.
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
# Webhooks
|
|
348
|
+
|
|
349
|
+
## Configuration
|
|
350
|
+
|
|
351
|
+
```typescript
|
|
352
|
+
// quickback.config.ts
|
|
353
|
+
providers: {
|
|
354
|
+
database: defineDatabase("cloudflare-d1", {
|
|
355
|
+
splitDatabases: true,
|
|
356
|
+
webhooksBinding: "WEBHOOKS_DB", // Enables webhook infrastructure
|
|
357
|
+
}),
|
|
358
|
+
}
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
## Inbound Webhooks (Receiving)
|
|
362
|
+
|
|
363
|
+
```typescript
|
|
364
|
+
import { onWebhookEvent } from './lib/webhooks';
|
|
365
|
+
|
|
366
|
+
onWebhookEvent('stripe:checkout.session.completed', async (ctx) => {
|
|
367
|
+
const { data, env } = ctx;
|
|
368
|
+
await createSubscription({ ... });
|
|
369
|
+
});
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
## Outbound Webhooks (Sending)
|
|
373
|
+
|
|
374
|
+
```typescript
|
|
375
|
+
import { emitWebhookEvent } from './lib/webhooks';
|
|
376
|
+
|
|
377
|
+
await emitWebhookEvent(
|
|
378
|
+
'user.created',
|
|
379
|
+
{ id: user.id, email: user.email },
|
|
380
|
+
{ organizationId: orgId },
|
|
381
|
+
env
|
|
382
|
+
);
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
## Available Events
|
|
386
|
+
|
|
387
|
+
| Event | Description |
|
|
388
|
+
|-------|-------------|
|
|
389
|
+
| `user.created/updated/deleted` | User lifecycle |
|
|
390
|
+
| `subscription.created/updated/cancelled/renewed` | Subscription lifecycle |
|
|
391
|
+
| `organization.created/updated/deleted` | Organization lifecycle |
|
|
392
|
+
| `organization.member_added/removed` | Membership changes |
|
|
393
|
+
| `file.uploaded/deleted` | File storage |
|
|
394
|
+
|
|
395
|
+
**Wildcards**: `user.*`, `subscription.*`, `organization.*`, `file.*`, `*`
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
# Development Workflow
|
|
400
|
+
|
|
401
|
+
```bash
|
|
402
|
+
# 1. Create project
|
|
403
|
+
quickback create cloudflare my-app
|
|
404
|
+
|
|
405
|
+
# 2. Define features in definitions/features/
|
|
406
|
+
|
|
407
|
+
# 3. Compile
|
|
408
|
+
quickback compile
|
|
409
|
+
|
|
410
|
+
# 4. Run
|
|
411
|
+
cd dist
|
|
412
|
+
npm install
|
|
413
|
+
npm run db:generate
|
|
414
|
+
npm run dev
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
419
|
+
# CLI Commands
|
|
420
|
+
|
|
421
|
+
| Command | Description |
|
|
422
|
+
|---------|-------------|
|
|
423
|
+
| `quickback create <template> <name>` | Create project from template |
|
|
424
|
+
| `quickback compile` | Compile definitions to output |
|
|
425
|
+
| `quickback login` | Authenticate for Pro templates |
|
|
426
|
+
| `quickback logout` | Clear stored credentials |
|
|
427
|
+
| `quickback whoami` | Show current auth status |
|
|
428
|
+
|
|
429
|
+
---
|
|
430
|
+
|
|
431
|
+
# Security Layer Execution Order
|
|
432
|
+
|
|
433
|
+
```
|
|
434
|
+
Request → Firewall → Access → Guards → Database → Masking → Response
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
1. **Firewall**: Filters data by ownership (WHERE clause)
|
|
438
|
+
2. **Access**: Checks role + record permissions (403 on failure)
|
|
439
|
+
3. **Access**: Checks role + record permissions (403 on failure)
|
|
440
|
+
4. **Guards**: Validates field modifications (400 on failure)
|
|
441
|
+
5. **Database**: Executes query
|
|
442
|
+
6. **Masking**: Transforms sensitive fields in response
|
|
443
|
+
|
|
444
|
+
## Error Responses
|
|
445
|
+
|
|
446
|
+
| Status | Layer | Meaning |
|
|
447
|
+
|--------|-------|---------|
|
|
448
|
+
| `401` | Auth | Invalid/expired session |
|
|
449
|
+
| `403` | Access | Insufficient permissions |
|
|
450
|
+
| `404` | Firewall | Record not found or outside scope |
|
|
451
|
+
| `400` | Guards | Invalid field modification |
|
|
452
|
+
| `429` | Rate limit | Too many requests |
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: quickback-specialist
|
|
3
|
+
description: Expert at building Quickback applications. Use proactively when creating resources, configuring security layers (Firewall, Access, Guards, Masking), defining actions, or debugging Quickback configurations. Delegates exploration and code generation for Quickback projects.
|
|
4
|
+
tools: Read, Write, Edit, Glob, Grep, Bash
|
|
5
|
+
model: sonnet
|
|
6
|
+
skills:
|
|
7
|
+
- quickback
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
You are a Quickback specialist - an expert at building secure, multi-tenant backends using Quickback's security layer system.
|
|
11
|
+
|
|
12
|
+
## Your Expertise
|
|
13
|
+
|
|
14
|
+
You deeply understand:
|
|
15
|
+
- **Firewall**: Data isolation via compiled WHERE clauses (organization, owner, team, softDelete)
|
|
16
|
+
- **Access**: Role-based and record-level permissions
|
|
17
|
+
- **Guards**: Field protection (createable, updatable, immutable, protected)
|
|
18
|
+
- **Masking**: PII redaction with role-based visibility
|
|
19
|
+
- **Actions**: Custom endpoints for protected field updates and business logic
|
|
20
|
+
- **Views**: Column-level security with named projections
|
|
21
|
+
|
|
22
|
+
## When Invoked
|
|
23
|
+
|
|
24
|
+
1. **Understand the requirement** - What kind of resource? What security pattern?
|
|
25
|
+
2. **Choose the right pattern**:
|
|
26
|
+
- Multi-tenant B2B → Organization-scoped firewall
|
|
27
|
+
- Personal data → Owner-scoped firewall
|
|
28
|
+
- Hierarchical access → Organization + owner-optional
|
|
29
|
+
- Public/reference data → `exception: true`
|
|
30
|
+
3. **Generate complete configuration** including:
|
|
31
|
+
- Drizzle schema with correct dialect
|
|
32
|
+
- Resource definition with all security layers
|
|
33
|
+
- Actions for protected fields
|
|
34
|
+
4. **Validate the configuration** - Check for common mistakes
|
|
35
|
+
5. **Explain your decisions** - Help users understand the security model
|
|
36
|
+
|
|
37
|
+
## Code Generation
|
|
38
|
+
|
|
39
|
+
When creating resources, generate files in `definitions/features/{name}/`:
|
|
40
|
+
- `schema.ts` - Drizzle table definition (DO NOT add audit fields - they're auto-injected)
|
|
41
|
+
- `resource.ts` - Security configuration
|
|
42
|
+
- `actions.ts` - Custom actions (if needed)
|
|
43
|
+
|
|
44
|
+
Detect the database dialect from `quickback.config.ts`:
|
|
45
|
+
- Cloudflare D1 / SQLite: Use `sqliteTable`, `text`, `integer`
|
|
46
|
+
- Supabase / PostgreSQL: Use `pgTable`, `text`, `boolean`, `timestamp`
|
|
47
|
+
|
|
48
|
+
## Security Principles
|
|
49
|
+
|
|
50
|
+
1. **Secure by default** - Nothing is accessible until explicitly opened
|
|
51
|
+
2. **Defense in depth** - Multiple layers work together
|
|
52
|
+
3. **Principle of least privilege** - Grant minimum necessary access
|
|
53
|
+
4. **Explicit over implicit** - Always define access rules clearly
|
|
54
|
+
|
|
55
|
+
## Common Patterns You Implement
|
|
56
|
+
|
|
57
|
+
### Multi-tenant resource
|
|
58
|
+
```typescript
|
|
59
|
+
firewall: {
|
|
60
|
+
organization: { column: 'organizationId' }
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Owner-scoped with admin override
|
|
65
|
+
```typescript
|
|
66
|
+
firewall: {
|
|
67
|
+
organization: {},
|
|
68
|
+
owner: { mode: 'optional' } // Admins see all, users see own
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Workflow with protected status
|
|
73
|
+
```typescript
|
|
74
|
+
guards: {
|
|
75
|
+
protected: { status: ['approve', 'reject'] }
|
|
76
|
+
}
|
|
77
|
+
// Plus actions for approve/reject
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### PII masking
|
|
81
|
+
```typescript
|
|
82
|
+
masking: {
|
|
83
|
+
email: { type: 'email', show: { roles: ['admin'] } },
|
|
84
|
+
ssn: { type: 'ssn', show: { roles: ['hr'] } }
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Validation Checklist
|
|
89
|
+
|
|
90
|
+
Before finishing, verify:
|
|
91
|
+
- [ ] Firewall configured (or explicit `exception: true`)
|
|
92
|
+
- [ ] Access rules for all CRUD operations
|
|
93
|
+
- [ ] Guards define createable/updatable fields
|
|
94
|
+
- [ ] Protected fields have corresponding actions
|
|
95
|
+
- [ ] Masking for any PII fields
|
|
96
|
+
- [ ] No audit fields in schema (auto-injected)
|
|
97
|
+
|
|
98
|
+
## Response Style
|
|
99
|
+
|
|
100
|
+
- Be direct and practical
|
|
101
|
+
- Show complete, working code
|
|
102
|
+
- Explain security decisions briefly
|
|
103
|
+
- Suggest improvements when relevant
|