@kardoe/quickback 0.5.12 → 0.5.14

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.
@@ -11,7 +11,7 @@
11
11
  * │ └── definitions/features/...
12
12
  * ├── src/ ← compiled code written here
13
13
  * ├── supabase/migrations/ ← for Supabase provider
14
- * ├── drizzle/ ← for D1/SQLite providers
14
+ * ├── drizzle/ ← for D1/SQLite providers (when quickback/ folder is not used)
15
15
  * └── package.json
16
16
  */
17
17
  export declare function compile(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/commands/compile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAwDH,wBAAsB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAuN7C"}
1
+ {"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../src/commands/compile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AA2FH,wBAAsB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CA0O7C"}
@@ -11,10 +11,10 @@
11
11
  * │ └── definitions/features/...
12
12
  * ├── src/ ← compiled code written here
13
13
  * ├── supabase/migrations/ ← for Supabase provider
14
- * ├── drizzle/ ← for D1/SQLite providers
14
+ * ├── drizzle/ ← for D1/SQLite providers (when quickback/ folder is not used)
15
15
  * └── package.json
16
16
  */
17
- import { join, dirname } from 'path';
17
+ import { join, dirname, resolve } from 'path';
18
18
  import fs from 'fs/promises';
19
19
  import pc from 'picocolors';
20
20
  import ora from 'ora';
@@ -22,6 +22,7 @@ import { callCompiler, getApiUrl } from '../lib/api-client.js';
22
22
  import { getStoredToken, getStoredUser } from '../lib/auth.js';
23
23
  import { loadConfig, loadFeatures, findConfigPath, findFeaturesDir, findServicesDir, loadServices, loadDrizzleMeta } from '../lib/file-loader.js';
24
24
  import { writeFilesWithMerge } from '../lib/file-writer.js';
25
+ import { isSecurityReportArtifactContent, partitionGeneratedFiles } from '../lib/artifact-routing.js';
25
26
  import { runCommand } from '../lib/shell.js';
26
27
  const DRIZZLE_META_RELATIVE_DIRS = [
27
28
  'drizzle/auth/meta',
@@ -30,6 +31,15 @@ const DRIZZLE_META_RELATIVE_DIRS = [
30
31
  'drizzle/webhooks/meta',
31
32
  'drizzle/meta',
32
33
  ];
34
+ function areSamePath(a, b) {
35
+ return resolve(a) === resolve(b);
36
+ }
37
+ async function resolveQuickbackStateDir(projectRoot, outputDir) {
38
+ const quickbackDir = join(projectRoot, 'quickback');
39
+ if (areSamePath(quickbackDir, outputDir))
40
+ return undefined;
41
+ return await pathExists(quickbackDir) ? quickbackDir : undefined;
42
+ }
33
43
  async function pathExists(path) {
34
44
  try {
35
45
  await fs.access(path);
@@ -41,7 +51,7 @@ async function pathExists(path) {
41
51
  }
42
52
  async function syncDrizzleMetaToQuickback(projectRoot, outputDir) {
43
53
  const quickbackDir = join(projectRoot, 'quickback');
44
- if (quickbackDir === outputDir)
54
+ if (areSamePath(quickbackDir, outputDir))
45
55
  return 0;
46
56
  if (!await pathExists(quickbackDir))
47
57
  return 0;
@@ -63,6 +73,22 @@ async function syncDrizzleMetaToQuickback(projectRoot, outputDir) {
63
73
  }
64
74
  return synced;
65
75
  }
76
+ async function syncSecurityReportsToQuickback(projectRoot, outputDir, generatedFiles) {
77
+ const quickbackDir = join(projectRoot, 'quickback');
78
+ if (areSamePath(quickbackDir, outputDir))
79
+ return 0;
80
+ if (!await pathExists(quickbackDir))
81
+ return 0;
82
+ const reportFiles = generatedFiles.filter((file) => file.path.endsWith('.json') && isSecurityReportArtifactContent(file.content));
83
+ let synced = 0;
84
+ for (const file of reportFiles) {
85
+ const targetPath = join(quickbackDir, file.path);
86
+ await fs.mkdir(dirname(targetPath), { recursive: true });
87
+ await fs.writeFile(targetPath, file.content, 'utf-8');
88
+ synced += 1;
89
+ }
90
+ return synced;
91
+ }
66
92
  export async function compile() {
67
93
  console.log(pc.bold('Quickback Compiler'));
68
94
  // Show auth status
@@ -202,10 +228,23 @@ export async function compile() {
202
228
  }
203
229
  console.log();
204
230
  }
231
+ const quickbackStateDir = await resolveQuickbackStateDir(projectRoot, outputDir);
232
+ const shouldRouteStateArtifactsToQuickback = Boolean(quickbackStateDir);
233
+ const { runtimeFiles, stateFiles } = partitionGeneratedFiles(result.files);
205
234
  spinner.start('Writing output...');
206
235
  // Use merge strategy - don't wipe existing files, just update generated ones
207
- await writeFilesWithMerge(outputDir, result.files);
208
- spinner.succeed(`Output written to ${pc.cyan(outputDir)}`);
236
+ await writeFilesWithMerge(outputDir, shouldRouteStateArtifactsToQuickback ? runtimeFiles : result.files);
237
+ if (quickbackStateDir && stateFiles.length > 0) {
238
+ await writeFilesWithMerge(quickbackStateDir, stateFiles);
239
+ spinner.succeed(`Output written to ${pc.cyan(outputDir)} (state artifacts synced to ${pc.cyan(quickbackStateDir)})`);
240
+ const legacyDrizzlePath = join(outputDir, 'drizzle');
241
+ if (await pathExists(legacyDrizzlePath)) {
242
+ console.log(pc.yellow(' Legacy output/drizzle detected. New compiles write migration/state artifacts to quickback/drizzle.'));
243
+ }
244
+ }
245
+ else {
246
+ spinner.succeed(`Output written to ${pc.cyan(outputDir)}`);
247
+ }
209
248
  // Run post-compile commands from providers
210
249
  if (result.commands && result.commands.length > 0) {
211
250
  console.log(pc.gray('\nRunning post-compile commands...\n'));
@@ -235,6 +274,12 @@ export async function compile() {
235
274
  if (syncedMetaFiles > 0) {
236
275
  console.log(pc.gray(` Synced ${syncedMetaFiles} Drizzle meta file(s) to quickback/drizzle`));
237
276
  }
277
+ const syncedSecurityReportFiles = shouldRouteStateArtifactsToQuickback
278
+ ? 0
279
+ : await syncSecurityReportsToQuickback(projectRoot, outputDir, result.files);
280
+ if (syncedSecurityReportFiles > 0) {
281
+ console.log(pc.gray(` Synced ${syncedSecurityReportFiles} security report file(s) to quickback/reports`));
282
+ }
238
283
  // Print next steps
239
284
  console.log(pc.green('\n✔ Compilation complete!'));
240
285
  console.log(`\nGenerated files for: ${pc.cyan(result.meta.features.join(', ') || 'no features')}`);
@@ -1 +1 @@
1
- {"version":3,"file":"compile.js","sourceRoot":"","sources":["../../src/commands/compile.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"compile.js","sourceRoot":"","sources":["../../src/commands/compile.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/docs/content.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAyZzC,CAAC;AAEF,eAAO,MAAM,UAAU,UAuGtB,CAAC"}
1
+ {"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/docs/content.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CA6ZzC,CAAC;AAEF,eAAO,MAAM,UAAU,UAwGtB,CAAC"}
@@ -89,9 +89,13 @@ export const DOCS = {
89
89
  "title": "Inline Editing",
90
90
  "content": "# Inline Editing\n\nThe CMS provides spreadsheet-style inline editing in Data Table mode, plus auto-generated create and edit forms in the record detail view. All editable fields are determined from your table's guard configuration.\n\n## Spreadsheet Editing\n\nIn Data Table mode, every editable cell becomes an inline editor. Select a cell, start typing, and the value is saved automatically when you move to another cell or press Enter.\n\n### Editable Fields\n\nThe CMS determines which fields are editable from the table's guards:\n\n- **`guards.updatable`** fields are editable in existing records\n- **`guards.createable`** fields are editable in new record forms\n- **`guards.immutable`** fields are locked after creation (shown as disabled in edit mode)\n- **`guards.protected`** fields can only be changed via actions (marked \"Updated via actions only\")\n\nIf a table has no explicit guard config, the CMS falls back to making all non-system columns editable (excluding `id`, audit fields, `organizationId`, and `deletedAt`).\n\n## Cell Types\n\nEach column type gets a specialized editor:\n\n### Text\n\nStandard text input. Type freely and press Enter or Tab to save.\n\n### Number\n\nNumeric input with step controls. Supports decimal values (step `0.01` for currency fields). The CMS detects money fields from column names containing `amount`, `total`, `price`, `cost`, `balance`, `rate`, etc.\n\n### Boolean\n\nA Yes/No dropdown. Click to toggle between the two values.\n\n### FK Typeahead\n\nForeign key columns (ending in `Id`) get a typeahead dropdown with server-side search:\n\n- **Debounced search** — Queries are debounced at 200ms to avoid flooding the API\n- **Server-side filtering** — Sends `?search=query&pageSize=20` to the FK target table's list endpoint\n- **Keyboard navigation** — Arrow keys to navigate options, Enter to select, Escape to close\n- **Auto-loads initial options** — Opens with the first 20 records sorted by display column\n- **Display labels** — Shows the target table's display column value (e.g., \"John Smith\" instead of `usr_abc123`)\n\nThe FK target table is derived by stripping the `Id` suffix from the column name. For example, `contactId` searches the `contact` table, and `accountCodeId` searches the `accountCode` table.\n\n### Enum / Select\n\nColumns with `validation.enum` render as a select dropdown with all allowed values.\n\n## Display Labels\n\nFK cells in the table view show human-readable names instead of raw IDs. The API enriches list responses with `_label` fields:\n\n```\ncontactId: \"cnt_abc123\" → displays \"Acme Corporation\"\nprojectId: \"prj_xyz789\" → displays \"Beach House Renovation\"\n```\n\nThe label comes from the referenced table's display column (auto-detected from `name`, `title`, `code`, etc.). This works in both Table mode and Data Table mode.\n\n## Keyboard Shortcuts\n\n| Shortcut | Action |\n|----------|--------|\n| Arrow keys | Navigate between cells |\n| Tab | Move to next editable cell |\n| Shift + Tab | Move to previous editable cell |\n| Enter | Start editing / confirm edit and move down |\n| Escape | Cancel current edit / deselect cell |\n| Type any character | Start editing the selected cell |\n\n### Navigation Flow\n\n1. **Select** a cell by clicking or using arrow keys\n2. **Edit** by pressing Enter, Tab, or just typing\n3. **Save** by pressing Enter (moves down), Tab (moves right to next editable), or clicking elsewhere\n4. **Cancel** by pressing Escape (reverts to previous value)\n\nWhen you press Tab, the cursor skips non-editable cells and jumps to the next editable cell in the row. At the end of a row, it wraps to the first editable cell of the next row.\n\n## Record Detail View\n\nClicking a row in Table mode navigates to the record detail view. Fields are automatically grouped by type:\n\n| Group | Fields Included |\n|-------|----------------|\n| Identity | `name`, `code`, `status`, `title`, `companyName`, fields ending in `Type` or `Status` |\n| Contact Info | `email`, `phone`, `mobile`, `website`, `address1`, `address2`, `city`, `state`, `zip`, `country` |\n| Financial | Money fields, fields with `Percent`, `Rate`, `Markup`, `Discount`, `Currency`, `exchange` |\n| References | All FK columns (ending in `Id`, excluding `id` and `organizationId`) |\n| Settings | Boolean fields |\n| Dates | Date/time fields |\n| Audit | `createdAt`, `createdBy`, `modifiedAt`, `modifiedBy` |\n| Other | Remaining ungrouped fields |\n\nEach group is rendered as a card with the group label as a header. Fields display formatted values — dates are localized, money shows currency formatting, booleans render as Yes/No badges, enums use color-coded pills, and FK references are clickable links to the target record.\n\n## Auto-Generated Forms\n\nThe CMS generates create and edit forms from the table's guard configuration:\n\n### Create Form\n\nShows all fields listed in `guards.createable`. Required fields (notNull without a default) are marked with a red asterisk. Validation rules from the schema (min/max length, enum constraints, email format) are enforced client-side.\n\n### Edit Form\n\nShows all fields listed in `guards.updatable`. Additionally:\n\n- **Immutable fields** appear as disabled inputs with a lock icon\n- **Protected fields** appear as disabled inputs with the note \"Updated via actions only\"\n- **Validation** is applied on submit, with error messages shown per field\n\n### Field Input Types\n\nThe auto-form selects the appropriate input control based on column type and validation:\n\n| Detection | Input Type |\n|-----------|-----------|\n| `mode: \"boolean\"` | Checkbox |\n| `validation.enum` present | Select dropdown |\n| Column name matches date pattern | Date/time picker |\n| Column name matches money pattern | Number input (step 0.01) |\n| Column name matches URL pattern | URL input |\n| `validation.email: true` | Email input |\n| `type: \"integer\"` or `type: \"real\"` | Number input |\n| Long text (description, notes) | Textarea |\n| Default | Text input |\n\n## Next Steps\n\n- **[Table Views](/cms/table-views)** — Browse mode and view projections\n- **[Security](/cms/security)** — How guards control editability\n- **[Actions](/cms/actions)** — Trigger actions from the detail view"
91
91
  },
92
+ "cms/record-layouts": {
93
+ "title": "Record Layouts",
94
+ "content": "# Record Layouts\n\nThe CMS record detail page groups fields into collapsible sections. By default, fields are auto-grouped by naming heuristics (Identity, Contact Info, Financial, etc.). With **record layouts**, you control the exact grouping.\n\nThere are two layers:\n\n1. **Code-defined layouts** — developers configure named layouts in `defineTable()`\n2. **User-created views** — end-users create and save custom views via the CMS UI\n\n## Code-Defined Layouts\n\nAdd a `layouts` property to your `defineTable()` config:\n\n```typescript\nexport default defineTable(contacts, {\n firewall: { organization: {} },\n crud: { /* ... */ },\n layouts: {\n default: {\n sections: [\n { label: \"Contact Info\", columns: 2, fields: [\"name\", \"email\", \"phone\", \"mobile\"] },\n { label: \"Address\", columns: 2, fields: [\"address1\", \"address2\", \"city\", \"state\", \"zip\"] },\n { label: \"Internal Notes\", collapsed: true, fields: [\"notes\", \"internalNotes\"] }\n ]\n },\n compact: {\n sections: [\n { label: \"Summary\", fields: [\"name\", \"status\", \"email\"] }\n ]\n }\n }\n});\n```\n\nEach layout has an ordered list of sections. Each section specifies:\n\n| Property | Type | Default | Description |\n|----------|------|---------|-------------|\n| `label` | string | required | Section header text |\n| `fields` | string[] | required | Column names to display |\n| `columns` | `1 \\| 2` | `1` | Number of columns for field layout |\n| `collapsed` | boolean | `false` | Whether the section starts collapsed |\n\nFields not assigned to any section are collected into an \"Other Fields\" section at the bottom.\n\n### Layout Switcher\n\nWhen a table has multiple named layouts, a dropdown appears in the record detail header. Selections persist per table using `localStorage`.\n\nIf only one layout is defined, it's used automatically without showing a dropdown.\n\n## User-Created Custom Views\n\nEnd-users can create their own record layouts via the CMS UI. These are stored in the database and can be shared with other organization members.\n\n### Creating a View\n\n1. Open any record detail page\n2. Click the **+ View** button in the header\n3. In the view builder dialog:\n - Name your view\n - Add sections and assign fields from a dropdown\n - Set columns (1 or 2) and collapsed state per section\n - Optionally share with your organization\n4. Click **Create View**\n\nThe new view appears in the layout dropdown alongside code-defined layouts.\n\n### Editing and Deleting Views\n\n- Click the **gear icon** next to the dropdown to edit the current custom view\n- Click the **trash icon** to delete it (with confirmation)\n- Code-defined layouts cannot be edited or deleted from the CMS\n\n### Access Control\n\n| Operation | Who Can Do It |\n|-----------|---------------|\n| Create a view | Any member, admin, or owner |\n| Edit/delete own views | The creator |\n| Edit/delete any view | Admins and owners |\n| View shared views | All organization members |\n\n### Setting Up the Custom View Feature\n\nTo enable user-created views, add a `customView` table to your Quickback project:\n\n```typescript\n// quickback/features/cms/custom-view.ts\n\nexport const customView = sqliteTable(\"custom_view\", {\n id: text(\"id\").primaryKey(),\n organizationId: text(\"organization_id\").notNull(),\n tableName: text(\"table_name\").notNull(),\n name: text(\"name\").notNull(),\n description: text(\"description\"),\n layoutConfig: text(\"layout_config\").notNull(),\n isShared: integer(\"is_shared\", { mode: \"boolean\" }).default(false),\n});\n\nexport default defineTable(customView, {\n displayColumn: \"name\",\n firewall: { organization: {} },\n crud: {\n list: { access: { roles: [\"owner\", \"admin\", \"member\"] } },\n get: { access: { roles: [\"owner\", \"admin\", \"member\"] } },\n create: { access: { roles: [\"owner\", \"admin\", \"member\"] } },\n update: {\n access: {\n or: [\n { roles: [\"owner\", \"admin\"] },\n { roles: [\"member\"], record: { createdBy: { equals: \"$userId\" } } }\n ]\n }\n },\n delete: {\n access: {\n or: [\n { roles: [\"owner\", \"admin\"] },\n { roles: [\"member\"], record: { createdBy: { equals: \"$userId\" } } }\n ]\n },\n mode: \"hard\"\n }\n },\n guards: {\n createable: [\"tableName\", \"name\", \"description\", \"layoutConfig\", \"isShared\"],\n updatable: [\"name\", \"description\", \"layoutConfig\", \"isShared\"]\n }\n});\n```\n\nCompile your project to generate the API endpoints. The CMS will automatically detect the `customView` table and enable the view builder UI.\n\n## Fallback Behavior\n\n| Scenario | Result |\n|----------|--------|\n| No `layouts` config, no custom views | Auto-grouping by naming heuristics |\n| `layouts` config defined | Uses \"default\" layout or first available |\n| Multiple layouts | Dropdown for switching, persisted per table |\n| Custom views created | Appear in dropdown below code-defined layouts |\n\n## Next Steps\n\n- **[Table Views](/cms/table-views)** — Column projections for list views\n- **[Schema Format](/cms/schema-format)** — Full TypeScript type reference\n- **[Database Schema](/compiler/definitions/database-schema)** — defineTable() configuration reference"
95
+ },
92
96
  "cms/schema-format": {
93
97
  "title": "Schema Format Reference",
94
- "content": "# Schema Format Reference\n\nThe schema registry is a JSON file with a well-defined structure. Below are the complete TypeScript type definitions used by both the compiler (to generate) and the CMS (to consume).\n\n## SchemaRegistry\n\nThe top-level type:\n\n```typescript\ninterface SchemaRegistry {\n generatedAt: string;\n generatedBy: string;\n version: string;\n features: Record<string, string[]>;\n tables: Record<string, TableMeta>;\n tablesByFeature: Record<string, string[]>;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `generatedAt` | ISO 8601 timestamp of when the registry was generated |\n| `generatedBy` | Always `\"quickback-compiler\"` |\n| `version` | Compiler version string |\n| `features` | Map of feature name to array of source file names |\n| `tables` | Map of camelCase table name to full table metadata |\n| `tablesByFeature` | Map of feature name to array of table names in that feature |\n\n## TableMeta\n\nFull metadata for a single table:\n\n```typescript\ninterface TableMeta {\n name: string;\n dbName: string;\n feature: string;\n columns: ColumnMeta[];\n firewall: Record<string, unknown>;\n crud: Record<string, CrudConfig>;\n guards: GuardsConfig;\n masking: Record<string, MaskingRule>;\n views: Record<string, ViewConfig>;\n validation: Record<string, ValidationRule>;\n actions: ActionMeta[];\n displayColumn?: string;\n inputHints?: Record<string, string>;\n internal?: boolean;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `name` | camelCase table name (e.g., `\"accountCode\"`) |\n| `dbName` | Snake_case SQL table name (e.g., `\"account_code\"`) |\n| `feature` | Parent feature name (e.g., `\"accounting\"`) |\n| `columns` | Ordered array of column metadata |\n| `firewall` | Tenant isolation config (organization, owner, softDelete, exception) |\n| `crud` | Per-operation (create, read, update, delete) access config |\n| `guards` | Field-level create/update/immutable/protected rules |\n| `masking` | Per-field masking rules keyed by column name |\n| `views` | Named column projections keyed by view name |\n| `validation` | Per-field validation rules keyed by column name |\n| `actions` | Array of action definitions for this table |\n| `displayColumn` | Column used as human-readable label (auto-detected or explicit) |\n| `inputHints` | Map of column name to preferred CMS input type (e.g., `\"select\"`, `\"textarea\"`, `\"checkbox\"`) |\n| `internal` | When `true`, table is hidden from CMS sidebar |\n\n## ColumnMeta\n\nMetadata for a single column:\n\n```typescript\ninterface ColumnMeta {\n name: string;\n dbName: string;\n type: \"text\" | \"integer\" | \"real\" | \"blob\";\n mode?: \"boolean\";\n primaryKey: boolean;\n notNull: boolean;\n defaultValue?: string | number | boolean;\n fkTarget?: string;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `name` | camelCase property name |\n| `dbName` | Snake_case SQL column name |\n| `type` | SQLite storage type |\n| `mode` | When `\"boolean\"`, an integer column represents true/false |\n| `primaryKey` | Whether this column is the primary key |\n| `notNull` | Whether the column has a NOT NULL constraint |\n| `defaultValue` | Static default value (strings, numbers, or booleans) |\n| `fkTarget` | Target table name for FK columns (e.g., `\"contact\"` for a `vendorId` column) |\n\n## CRUDConfig\n\nPer-operation access control:\n\n```typescript\ninterface CrudConfig {\n access?: AccessRule;\n mode?: string;\n}\n\ninterface AccessRule {\n roles?: string[];\n or?: Array<{\n roles?: string[];\n record?: Record<string, unknown>;\n }>;\n record?: Record<string, unknown>;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `access.roles` | Array of roles allowed for this operation |\n| `access.or` | Alternative access conditions (any must match) |\n| `access.record` | Record-level conditions for access |\n| `mode` | Operation mode (e.g., `\"batch\"` for bulk create) |\n\n## GuardsConfig\n\nField-level control for create and update operations:\n\n```typescript\ninterface GuardsConfig {\n createable: string[];\n updatable: string[];\n immutable: string[];\n protected: Record<string, string[]>;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `createable` | Fields that can be set during record creation |\n| `updatable` | Fields that can be modified on existing records |\n| `immutable` | Fields that can be set on create but never changed |\n| `protected` | Fields only modifiable via named actions (field name to action names) |\n\n## ActionMeta\n\nMetadata for a custom action:\n\n```typescript\ninterface ActionMeta {\n name: string;\n description: string;\n inputFields: ActionInputField[];\n access?: {\n roles: string[];\n record?: Record<string, unknown>;\n };\n standalone?: boolean;\n path?: string;\n method?: string;\n responseType?: string;\n sideEffects?: string;\n cms?: CmsConfig;\n}\n\ninterface CmsConfig {\n label?: string;\n icon?: string;\n confirm?: string | boolean;\n destructive?: boolean;\n category?: string;\n hidden?: boolean;\n successMessage?: string;\n onSuccess?: 'refresh' | 'redirect:list' | 'close';\n order?: number;\n}\n\ninterface ActionInputField {\n name: string;\n type: string;\n required: boolean;\n default?: unknown;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `name` | Action identifier (e.g., `\"approve\"`, `\"applyPayment\"`) |\n| `description` | Human-readable description shown in dialog |\n| `inputFields` | Array of input field definitions |\n| `access.roles` | Roles allowed to execute this action |\n| `access.record` | Record conditions (e.g., `{ status: { equals: \"pending\" } }`) |\n| `standalone` | When `true`, action is not tied to a specific record |\n| `path` | Custom API path (overrides default) |\n| `method` | HTTP method (defaults to POST) |\n| `responseType` | `\"file\"` for download responses |\n| `sideEffects` | `\"sync\"` for actions with synchronous side effects |\n| `cms` | Optional CMS rendering metadata (label, icon, confirm, destructive, category, hidden, successMessage, onSuccess, order) |\n\n### ActionInputField\n\n| Field | Description |\n|-------|-------------|\n| `name` | Field identifier |\n| `type` | Zod type string: `\"string\"`, `\"number\"`, `\"boolean\"`, `\"array<string>\"` |\n| `required` | Whether the field must be provided |\n| `default` | Default value pre-filled in the form |\n\n## ViewConfig\n\nNamed column projection with access control:\n\n```typescript\ninterface ViewConfig {\n fields: string[];\n access: AccessRule;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `fields` | Array of column names to include in this view |\n| `access` | Role-based access rules (same shape as CrudConfig access) |\n\n## MaskingRule\n\nPer-field data masking:\n\n```typescript\ninterface MaskingRule {\n type: \"email\" | \"phone\" | \"ssn\" | \"redact\";\n show: {\n roles: string[];\n or?: string;\n };\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `type` | Masking pattern to apply |\n| `show.roles` | Roles that see the unmasked value |\n| `show.or` | Alternative condition for showing unmasked value |\n\n### Masking Patterns\n\n| Type | Input | Output |\n|------|-------|--------|\n| `email` | `john@acme.com` | `j***@acme.com` |\n| `phone` | `(555) 123-4567` | `***-***-4567` |\n| `ssn` | `123-45-6789` | `***-**-6789` |\n| `redact` | Any string | `------` |\n\n## ValidationRule\n\nPer-field validation constraints:\n\n```typescript\ninterface ValidationRule {\n minLength?: number;\n maxLength?: number;\n min?: number;\n max?: number;\n enum?: string[];\n email?: boolean;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `minLength` | Minimum string length |\n| `maxLength` | Maximum string length |\n| `min` | Minimum numeric value |\n| `max` | Maximum numeric value |\n| `enum` | Array of allowed string values |\n| `email` | When `true`, validates email format |\n\n## Next Steps\n\n- **[Schema Registry](/cms/schema-registry)** — How the registry is generated and used\n- **[Components Reference](/cms/components)** — All CMS React components"
98
+ "content": "# Schema Format Reference\n\nThe schema registry is a JSON file with a well-defined structure. Below are the complete TypeScript type definitions used by both the compiler (to generate) and the CMS (to consume).\n\n## SchemaRegistry\n\nThe top-level type:\n\n```typescript\ninterface SchemaRegistry {\n generatedAt: string;\n generatedBy: string;\n version: string;\n features: Record<string, string[]>;\n tables: Record<string, TableMeta>;\n tablesByFeature: Record<string, string[]>;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `generatedAt` | ISO 8601 timestamp of when the registry was generated |\n| `generatedBy` | Always `\"quickback-compiler\"` |\n| `version` | Compiler version string |\n| `features` | Map of feature name to array of source file names |\n| `tables` | Map of camelCase table name to full table metadata |\n| `tablesByFeature` | Map of feature name to array of table names in that feature |\n\n## TableMeta\n\nFull metadata for a single table:\n\n```typescript\ninterface TableMeta {\n name: string;\n dbName: string;\n feature: string;\n columns: ColumnMeta[];\n firewall: Record<string, unknown>;\n crud: Record<string, CrudConfig>;\n guards: GuardsConfig;\n masking: Record<string, MaskingRule>;\n views: Record<string, ViewConfig>;\n validation: Record<string, ValidationRule>;\n actions: ActionMeta[];\n displayColumn?: string;\n inputHints?: Record<string, string>;\n layouts?: Record<string, CmsLayout>;\n internal?: boolean;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `name` | camelCase table name (e.g., `\"accountCode\"`) |\n| `dbName` | Snake_case SQL table name (e.g., `\"account_code\"`) |\n| `feature` | Parent feature name (e.g., `\"accounting\"`) |\n| `columns` | Ordered array of column metadata |\n| `firewall` | Tenant isolation config (organization, owner, softDelete, exception) |\n| `crud` | Per-operation (create, read, update, delete) access config |\n| `guards` | Field-level create/update/immutable/protected rules |\n| `masking` | Per-field masking rules keyed by column name |\n| `views` | Named column projections keyed by view name |\n| `validation` | Per-field validation rules keyed by column name |\n| `actions` | Array of action definitions for this table |\n| `displayColumn` | Column used as human-readable label (auto-detected or explicit) |\n| `inputHints` | Map of column name to preferred CMS input type (e.g., `\"select\"`, `\"textarea\"`, `\"checkbox\"`) |\n| `layouts` | Named record page layouts keyed by layout name (see CmsLayout below) |\n| `internal` | When `true`, table is hidden from CMS sidebar |\n\n## ColumnMeta\n\nMetadata for a single column:\n\n```typescript\ninterface ColumnMeta {\n name: string;\n dbName: string;\n type: \"text\" | \"integer\" | \"real\" | \"blob\";\n mode?: \"boolean\";\n primaryKey: boolean;\n notNull: boolean;\n defaultValue?: string | number | boolean;\n fkTarget?: string;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `name` | camelCase property name |\n| `dbName` | Snake_case SQL column name |\n| `type` | SQLite storage type |\n| `mode` | When `\"boolean\"`, an integer column represents true/false |\n| `primaryKey` | Whether this column is the primary key |\n| `notNull` | Whether the column has a NOT NULL constraint |\n| `defaultValue` | Static default value (strings, numbers, or booleans) |\n| `fkTarget` | Target table name for FK columns (e.g., `\"contact\"` for a `vendorId` column) |\n\n## CRUDConfig\n\nPer-operation access control:\n\n```typescript\ninterface CrudConfig {\n access?: AccessRule;\n mode?: string;\n}\n\ninterface AccessRule {\n roles?: string[];\n or?: Array<{\n roles?: string[];\n record?: Record<string, unknown>;\n }>;\n record?: Record<string, unknown>;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `access.roles` | Array of roles allowed for this operation |\n| `access.or` | Alternative access conditions (any must match) |\n| `access.record` | Record-level conditions for access |\n| `mode` | Operation mode (e.g., `\"batch\"` for bulk create) |\n\n## GuardsConfig\n\nField-level control for create and update operations:\n\n```typescript\ninterface GuardsConfig {\n createable: string[];\n updatable: string[];\n immutable: string[];\n protected: Record<string, string[]>;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `createable` | Fields that can be set during record creation |\n| `updatable` | Fields that can be modified on existing records |\n| `immutable` | Fields that can be set on create but never changed |\n| `protected` | Fields only modifiable via named actions (field name to action names) |\n\n## ActionMeta\n\nMetadata for a custom action:\n\n```typescript\ninterface ActionMeta {\n name: string;\n description: string;\n inputFields: ActionInputField[];\n access?: {\n roles: string[];\n record?: Record<string, unknown>;\n };\n standalone?: boolean;\n path?: string;\n method?: string;\n responseType?: string;\n sideEffects?: string;\n cms?: CmsConfig;\n}\n\ninterface CmsConfig {\n label?: string;\n icon?: string;\n confirm?: string | boolean;\n destructive?: boolean;\n category?: string;\n hidden?: boolean;\n successMessage?: string;\n onSuccess?: 'refresh' | 'redirect:list' | 'close';\n order?: number;\n}\n\ninterface ActionInputField {\n name: string;\n type: string;\n required: boolean;\n default?: unknown;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `name` | Action identifier (e.g., `\"approve\"`, `\"applyPayment\"`) |\n| `description` | Human-readable description shown in dialog |\n| `inputFields` | Array of input field definitions |\n| `access.roles` | Roles allowed to execute this action |\n| `access.record` | Record conditions (e.g., `{ status: { equals: \"pending\" } }`) |\n| `standalone` | When `true`, action is not tied to a specific record |\n| `path` | Custom API path (overrides default) |\n| `method` | HTTP method (defaults to POST) |\n| `responseType` | `\"file\"` for download responses |\n| `sideEffects` | `\"sync\"` for actions with synchronous side effects |\n| `cms` | Optional CMS rendering metadata (label, icon, confirm, destructive, category, hidden, successMessage, onSuccess, order) |\n\n### ActionInputField\n\n| Field | Description |\n|-------|-------------|\n| `name` | Field identifier |\n| `type` | Zod type string: `\"string\"`, `\"number\"`, `\"boolean\"`, `\"array<string>\"` |\n| `required` | Whether the field must be provided |\n| `default` | Default value pre-filled in the form |\n\n## ViewConfig\n\nNamed column projection with access control:\n\n```typescript\ninterface ViewConfig {\n fields: string[];\n access: AccessRule;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `fields` | Array of column names to include in this view |\n| `access` | Role-based access rules (same shape as CrudConfig access) |\n\n## CmsLayout\n\nNamed record page layout with ordered sections:\n\n```typescript\ninterface CmsLayout {\n sections: CmsLayoutSection[];\n}\n\ninterface CmsLayoutSection {\n label: string;\n fields: string[];\n columns?: 1 | 2;\n collapsed?: boolean;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `sections` | Ordered array of field sections |\n\n### CmsLayoutSection\n\n| Field | Description |\n|-------|-------------|\n| `label` | Section header text |\n| `fields` | Array of column names to display in this section |\n| `columns` | `1` (default) or `2` for two-column field layout |\n| `collapsed` | When `true`, section starts collapsed with a toggle to expand |\n\nFields not assigned to any section in the active layout are collected into an \"Other Fields\" section.\n\n## MaskingRule\n\nPer-field data masking:\n\n```typescript\ninterface MaskingRule {\n type: \"email\" | \"phone\" | \"ssn\" | \"redact\";\n show: {\n roles: string[];\n or?: string;\n };\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `type` | Masking pattern to apply |\n| `show.roles` | Roles that see the unmasked value |\n| `show.or` | Alternative condition for showing unmasked value |\n\n### Masking Patterns\n\n| Type | Input | Output |\n|------|-------|--------|\n| `email` | `john@acme.com` | `j***@acme.com` |\n| `phone` | `(555) 123-4567` | `***-***-4567` |\n| `ssn` | `123-45-6789` | `***-**-6789` |\n| `redact` | Any string | `------` |\n\n## ValidationRule\n\nPer-field validation constraints:\n\n```typescript\ninterface ValidationRule {\n minLength?: number;\n maxLength?: number;\n min?: number;\n max?: number;\n enum?: string[];\n email?: boolean;\n}\n```\n\n| Field | Description |\n|-------|-------------|\n| `minLength` | Minimum string length |\n| `maxLength` | Maximum string length |\n| `min` | Minimum numeric value |\n| `max` | Maximum numeric value |\n| `enum` | Array of allowed string values |\n| `email` | When `true`, validates email format |\n\n## Next Steps\n\n- **[Schema Registry](/cms/schema-registry)** — How the registry is generated and used\n- **[Components Reference](/cms/components)** — All CMS React components"
95
99
  },
96
100
  "cms/schema-registry": {
97
101
  "title": "Schema Registry",
@@ -119,7 +123,7 @@ export const DOCS = {
119
123
  },
120
124
  "compiler/cloud-compiler": {
121
125
  "title": "Cloud Compiler",
122
- "content": "Quickback offers a hosted compiler at `https://compiler.quickback.dev`. The CLI uses it to turn your definitions into a complete backend.\n\n## How It Works\n\n```\n┌──────────────┐ ┌──────────────────────┐\n│ quickback │ POST │ compiler.quickback │\n│ CLI │────────▶│ .dev/compile │\n│ │ │ │\n│ Sends: │ │ Returns: │\n│ - config │ │ - Hono routes │\n│ - features │◀────────│ - Drizzle migrations │\n│ - meta │ │ - TypeScript SDK │\n└──────────────┘ └──────────────────────┘\n```\n\n1. The CLI reads your `quickback.config.ts` and feature definitions.\n2. It sends them to the cloud compiler as a JSON payload.\n3. The compiler generates all backend files (routes, migrations, SDK, OpenAPI spec).\n4. The CLI writes the generated files to your project.\n\n## Quick Start\n\n```bash\n# 1. Install the CLI\nnpm install -g @kardoe/quickback\n\n# 2. Create a project\nquickback create cloudflare my-app\ncd my-app\n\n# 3. Log in\nquickback login\n\n# 4. Compile\nquickback compile\n```\n\n## Existing Databases\n\nWhen recompiling an existing project, the CLI automatically sends your Drizzle meta files so the compiler generates **incremental** migrations instead of fresh `CREATE TABLE` statements.\n\nMeta files are loaded from:\n- `drizzle/auth/meta/`\n- `drizzle/features/meta/`\n- `drizzle/files/meta/`\n- `drizzle/webhooks/meta/`\n- `drizzle/meta/` (legacy single database mode)\n- `quickback/drizzle/...` mirrors (same paths under `quickback/`)\n\nAfter each compile, the CLI syncs generated meta JSON files back into `quickback/drizzle/...` (when a `quickback/` folder exists) so future compiles can always send the latest migration state.\n\nNo extra configuration needed — the CLI handles this automatically.\n\n## Next Steps\n\n- [CLI Reference](/compiler/cloud-compiler/cli) — All CLI commands\n- [Authentication](/compiler/cloud-compiler/authentication) — Login flow and API keys\n- [Endpoints](/compiler/cloud-compiler/endpoints) — Compiler API reference\n- [Troubleshooting](/compiler/cloud-compiler/troubleshooting) — Common issues\n- [Local Compiler](/compiler/cloud-compiler/local-compiler) — Run the compiler locally"
126
+ "content": "Quickback offers a hosted compiler at `https://compiler.quickback.dev`. The CLI uses it to turn your definitions into a complete backend.\n\n## How It Works\n\n```\n┌──────────────┐ ┌──────────────────────┐\n│ quickback │ POST │ compiler.quickback │\n│ CLI │────────▶│ .dev/compile │\n│ │ │ │\n│ Sends: │ │ Returns: │\n│ - config │ │ - Hono routes │\n│ - features │◀────────│ - Drizzle migrations │\n│ - meta │ │ - TypeScript SDK │\n└──────────────┘ └──────────────────────┘\n```\n\n1. The CLI reads your `quickback.config.ts` and feature definitions.\n2. It sends them to the cloud compiler as a JSON payload.\n3. The compiler generates all backend files (routes, migrations, SDK, OpenAPI spec).\n4. The CLI writes the generated files to your project.\n\n## Quick Start\n\n```bash\n# 1. Install the CLI\nnpm install -g @kardoe/quickback\n\n# 2. Create a project\nquickback create cloudflare my-app\ncd my-app\n\n# 3. Log in\nquickback login\n\n# 4. Compile\nquickback compile\n```\n\n## Existing Databases\n\nWhen recompiling an existing project, the CLI automatically sends your Drizzle meta files so the compiler generates **incremental** migrations instead of fresh `CREATE TABLE` statements.\n\nMeta files are loaded from:\n- `drizzle/auth/meta/`\n- `drizzle/features/meta/`\n- `drizzle/files/meta/`\n- `drizzle/webhooks/meta/`\n- `drizzle/meta/` (legacy single database mode)\n- `quickback/drizzle/...` mirrors (same paths under `quickback/`)\n\nWhen a `quickback/` folder exists and compile output is project root, the CLI writes state artifacts directly into `quickback/`:\n- `quickback/drizzle/...` for Drizzle migration SQL/meta artifacts\n- `quickback/reports/...` for security contract report artifacts\n\nThe CLI also syncs Drizzle meta JSON into `quickback/drizzle/...` as a compatibility fallback for tool-generated meta files.\n\nNo extra configuration needed — the CLI handles this automatically.\n\n## Next Steps\n\n- [CLI Reference](/compiler/cloud-compiler/cli) — All CLI commands\n- [Authentication](/compiler/cloud-compiler/authentication) — Login flow and API keys\n- [Endpoints](/compiler/cloud-compiler/endpoints) — Compiler API reference\n- [Troubleshooting](/compiler/cloud-compiler/troubleshooting) — Common issues\n- [Local Compiler](/compiler/cloud-compiler/local-compiler) — Run the compiler locally"
123
127
  },
124
128
  "compiler/cloud-compiler/local-compiler": {
125
129
  "title": "Local Compiler",
@@ -135,7 +139,7 @@ export const DOCS = {
135
139
  },
136
140
  "compiler/config/output": {
137
141
  "title": "Output Structure",
138
- "content": "The compiler generates a complete project structure based on your definitions and provider configuration. The output varies depending on your runtime (Cloudflare vs Bun) and enabled features.\n\n**Warning:** Never edit files in `src/` directly. They are overwritten on every compile. Make changes in your `quickback/` definitions instead.\n\n## Cloudflare Output\n\n```\nsrc/\n├── index.ts # Hono app entry point (Workers export)\n├── env.d.ts # Cloudflare bindings TypeScript types\n├── db/\n│ ├── index.ts # Database connection factory\n│ ├── auth-schema.ts # Auth table schemas (dual mode)\n│ └── features-schema.ts # Feature table schemas (dual mode)\n├── auth/\n│ └── index.ts # Better Auth instance & config\n├── features/\n│ └── {feature}/\n│ ├── schema.ts # Drizzle table definition\n│ ├── routes.ts # CRUD + action endpoints\n│ └── actions.ts # Action handlers (if defined)\n├── lib/\n│ ├── access.ts # Access control helpers\n│ ├── types.ts # Runtime type definitions\n│ ├── masks.ts # Field masking utilities\n│ ├── services.ts # Service layer\n│ ├── audit-wrapper.ts # Auto-inject audit fields\n│ └── security-audit.ts # Unsafe cross-tenant audit logger (when needed)\n└── middleware/\n ├── auth.ts # Auth context middleware\n ├── db.ts # Database instance middleware\n └── services.ts # Service injection middleware\n\ndrizzle/\n├── auth/ # Auth migrations (dual mode)\n│ ├── meta/\n│ │ ├── _journal.json\n│ │ └── 0000_snapshot.json\n│ └── 0000_initial.sql\n├── features/ # Feature migrations (dual mode)\n│ ├── meta/\n│ │ ├── _journal.json\n│ │ └── 0000_snapshot.json\n│ └── 0000_initial.sql\n└── audit/ # Unsafe cross-tenant action audit migrations (when needed)\n ├── meta/\n └── 0000_initial.sql\n\n# Root config files\n├── package.json\n├── tsconfig.json\n├── wrangler.toml # Cloudflare Workers config\n├── drizzle.config.ts # Features DB drizzle config\n├── drizzle.auth.config.ts # Auth DB drizzle config (dual mode)\n└── drizzle.audit.config.ts # Audit DB drizzle config (when unsafe actions exist)\n```\n\n## Bun Output\n\n```\nsrc/\n├── index.ts # Hono app entry point (Bun server)\n├── db/\n│ ├── index.ts # SQLite connection (bun:sqlite)\n│ └── schema.ts # Combined schema (single DB)\n├── auth/\n│ └── index.ts # Better Auth instance\n├── features/\n│ └── {feature}/\n│ ├── schema.ts\n│ ├── routes.ts\n│ └── actions.ts\n├── lib/\n│ ├── access.ts\n│ ├── types.ts\n│ ├── masks.ts\n│ ├── services.ts\n│ └── audit-wrapper.ts\n└── middleware/\n ├── auth.ts\n ├── db.ts\n └── services.ts\n\ndrizzle/ # Single migration directory\n├── meta/\n│ ├── _journal.json\n│ └── 0000_snapshot.json\n└── 0000_initial.sql\n\ndata/ # SQLite database files\n└── app.db\n\n├── package.json\n├── tsconfig.json\n└── drizzle.config.ts\n```\n\n## Key Differences by Runtime\n\n| Aspect | Cloudflare | Bun |\n|--------|-----------|-----|\n| Entry point | Workers `export default` | `Bun.serve()` with port |\n| Database | D1 bindings (dual mode) | SQLite file (single DB) |\n| Types | `env.d.ts` for bindings | No extra types needed |\n| Config | `wrangler.toml` | `.env` file |\n| Migrations | `drizzle/auth/` + `drizzle/features/` | `drizzle/` |\n| Drizzle configs | 2 configs (auth + features) | 1 config |\n\n## Optional Output Files\n\nThese files are generated only when the corresponding features are configured:\n\n### Embeddings\n\nWhen any feature has `embeddings` configured:\n\n```\nsrc/\n├── lib/\n│ └── embeddings.ts # Embedding helpers\n├── routes/\n│ └── embeddings.ts # POST /api/v1/embeddings endpoint\n└── queue-consumer.ts # Queue handler for async embedding jobs\n```\n\n### File Storage (R2)\n\nWhen `fileStorage` is configured:\n\n```\nsrc/\n└── routes/\n └── storage.ts # File upload/download endpoints\ndrizzle/\n└── files/ # File metadata migrations\n ├── meta/\n └── 0000_*.sql\n```\n\n### Webhooks\n\nWhen webhooks are enabled:\n\n```\nsrc/\n└── lib/\n └── webhooks/\n ├── index.ts # Webhook module entry\n ├── sign.ts # Webhook payload signing\n ├── handlers.ts # Handler registry\n ├── emit.ts # Queue emission helpers\n ├── routes.ts # Inbound/outbound endpoints\n └── providers/\n ├── index.ts\n └── stripe.ts # Stripe webhook handler\ndrizzle/\n└── webhooks/ # Webhook schema migrations\n ├── meta/\n └── 0000_*.sql\n```\n\n### Security Audit Database (Unsafe Actions)\n\nWhen any action enables unsafe cross-tenant mode (`unsafe.crossTenant: true`):\n\n```\nsrc/\n├── db/\n│ └── audit-schema.ts # audit_events table\n└── lib/\n └── security-audit.ts # mandatory audit writer\n\ndrizzle/\n└── audit/\n ├── meta/\n └── 0000_*.sql\n\n# Root\n└── drizzle.audit.config.ts\n```\n\nCloudflare output also includes an `AUDIT_DB` D1 binding in `wrangler.toml` and migration scripts:\n\n- `db:migrate:audit:local`\n- `db:migrate:audit:remote`\n\n### Security Contract Report and Signature\n\nGenerated on every compile (unless disabled via `compiler.securityContracts.report.enabled: false`):\n\n```\nreports/\n├── security-contracts.report.json # Contract evaluation summary + violations\n└── security-contracts.report.sig.json # Signature / digest envelope for the report\n```\n\nThe signature file uses HMAC-SHA256 when a signing key is configured, otherwise it falls back to SHA-256 digest mode. \nSet `compiler.securityContracts.report.signature.required: true` to fail compilation when a signing key is missing.\n\n### Realtime\n\nWhen any feature has `realtime` configured:\n\n```\nsrc/\n└── lib/\n └── realtime.ts # Broadcast helpers\n\ncloudflare-workers/ # Separate Durable Objects worker\n└── broadcast/\n ├── Broadcaster.ts\n ├── index.ts\n └── wrangler.toml\n```\n\n### Device Authorization\n\nWhen the `deviceAuthorization` plugin is enabled:\n\n```\nsrc/\n└── routes/\n └── cli-auth.ts # Device auth flow endpoints\n```\n\n## Database Schemas\n\n### Dual Database Mode (Cloudflare Default)\n\nThe compiler separates schemas into two files:\n\n**`src/db/auth-schema.ts`** — Re-exports Better Auth table schemas:\n- `users`, `sessions`, `accounts`\n- `organizations`, `members`, `invitations` (if organizations enabled)\n- Plugin-specific tables (`apiKeys`, etc.)\n\n**`src/db/features-schema.ts`** — Re-exports your feature schemas:\n- All tables defined with `defineTable()`\n- Audit field columns added automatically\n\n### Single Database Mode (Bun Default)\n\n**`src/db/schema.ts`** — Combined re-export of all schemas (auth + features).\n\n## Generated Routes\n\nFor each feature, the compiler generates a routes file at `src/features/{name}/routes.ts` containing:\n\n| Route | Generated When |\n|-------|----------------|\n| `GET /` | `crud.list` configured |\n| `GET /:id` | `crud.get` configured |\n| `POST /` | `crud.create` configured |\n| `PATCH /:id` | `crud.update` configured |\n| `DELETE /:id` | `crud.delete` configured |\n| `PUT /:id` | `crud.put` configured |\n| `POST /batch` | `crud.create` exists (auto-enabled) |\n| `PATCH /batch` | `crud.update` exists (auto-enabled) |\n| `DELETE /batch` | `crud.delete` exists (auto-enabled) |\n| `PUT /batch` | `crud.put` exists (auto-enabled) |\n| `GET /views/{name}` | `views` configured |\n| `POST /:id/{action}` | Record-based actions defined |\n| `POST /{action}` | Standalone actions defined |\n\nAll routes are mounted under `/api/v1/{feature}` in the main app.\n\n## Migrations\n\nThe compiler runs `drizzle-kit generate` during compilation to produce SQL migration files. On subsequent compiles, it uses `existingFiles` (your current migration state) to generate only incremental changes.\n\nThe CLI loads migration meta JSON from:\n\n- `drizzle/auth/meta/`\n- `drizzle/features/meta/`\n- `drizzle/files/meta/`\n- `drizzle/webhooks/meta/`\n- `drizzle/meta/` (legacy single database mode)\n- `quickback/drizzle/...` mirrors (same paths under `quickback/`)\n\nAfter compile, the CLI syncs generated meta JSON back into `quickback/drizzle/...` (when a `quickback/` folder exists) so repeated compiles keep incremental migration state in your definitions area.\n\nFor non-interactive environments (cloud compile, CI), table/column renames must be declared with `compiler.migrations.renames` in `quickback.config.ts`. This avoids interactive rename prompts during migration generation.\n\nMigration files follow the Drizzle Kit naming convention:\n```\n0000_initial.sql\n0001_add_status_column.sql\n0002_create_orders_table.sql\n```\n\n## See Also\n\n- [Providers](/compiler/config/providers) — Configure runtime, database, and auth providers\n- [Environment variables](/compiler/config/variables) — Required variables by runtime"
142
+ "content": "The compiler generates a complete project structure based on your definitions and provider configuration. The output varies depending on your runtime (Cloudflare vs Bun) and enabled features.\n\n**Warning:** Never edit files in `src/` directly. They are overwritten on every compile. Make changes in your `quickback/` definitions instead.\n\n## Cloudflare Output\n\n```\nsrc/\n├── index.ts # Hono app entry point (Workers export)\n├── env.d.ts # Cloudflare bindings TypeScript types\n├── db/\n│ ├── index.ts # Database connection factory\n│ ├── auth-schema.ts # Auth table schemas (dual mode)\n│ └── features-schema.ts # Feature table schemas (dual mode)\n├── auth/\n│ └── index.ts # Better Auth instance & config\n├── features/\n│ └── {feature}/\n│ ├── schema.ts # Drizzle table definition\n│ ├── routes.ts # CRUD + action endpoints\n│ └── actions.ts # Action handlers (if defined)\n├── lib/\n│ ├── access.ts # Access control helpers\n│ ├── types.ts # Runtime type definitions\n│ ├── masks.ts # Field masking utilities\n│ ├── services.ts # Service layer\n│ ├── audit-wrapper.ts # Auto-inject audit fields\n│ └── security-audit.ts # Unsafe cross-tenant audit logger (when needed)\n└── middleware/\n ├── auth.ts # Auth context middleware\n ├── db.ts # Database instance middleware\n └── services.ts # Service injection middleware\n\ndrizzle/\n├── auth/ # Auth migrations (dual mode)\n│ ├── meta/\n│ │ ├── _journal.json\n│ │ └── 0000_snapshot.json\n│ └── 0000_initial.sql\n├── features/ # Feature migrations (dual mode)\n│ ├── meta/\n│ │ ├── _journal.json\n│ │ └── 0000_snapshot.json\n│ └── 0000_initial.sql\n└── audit/ # Unsafe cross-tenant action audit migrations (when needed)\n ├── meta/\n └── 0000_initial.sql\n\n# Root config files\n├── package.json\n├── tsconfig.json\n├── wrangler.toml # Cloudflare Workers config\n├── drizzle.config.ts # Features DB drizzle config\n├── drizzle.auth.config.ts # Auth DB drizzle config (dual mode)\n└── drizzle.audit.config.ts # Audit DB drizzle config (when unsafe actions exist)\n```\n\n## Bun Output\n\n```\nsrc/\n├── index.ts # Hono app entry point (Bun server)\n├── db/\n│ ├── index.ts # SQLite connection (bun:sqlite)\n│ └── schema.ts # Combined schema (single DB)\n├── auth/\n│ └── index.ts # Better Auth instance\n├── features/\n│ └── {feature}/\n│ ├── schema.ts\n│ ├── routes.ts\n│ └── actions.ts\n├── lib/\n│ ├── access.ts\n│ ├── types.ts\n│ ├── masks.ts\n│ ├── services.ts\n│ └── audit-wrapper.ts\n└── middleware/\n ├── auth.ts\n ├── db.ts\n └── services.ts\n\ndrizzle/ # Single migration directory\n├── meta/\n│ ├── _journal.json\n│ └── 0000_snapshot.json\n└── 0000_initial.sql\n\ndata/ # SQLite database files\n└── app.db\n\n├── package.json\n├── tsconfig.json\n└── drizzle.config.ts\n```\n\n## Key Differences by Runtime\n\n| Aspect | Cloudflare | Bun |\n|--------|-----------|-----|\n| Entry point | Workers `export default` | `Bun.serve()` with port |\n| Database | D1 bindings (dual mode) | SQLite file (single DB) |\n| Types | `env.d.ts` for bindings | No extra types needed |\n| Config | `wrangler.toml` | `.env` file |\n| Migrations | `drizzle/auth/` + `drizzle/features/` | `drizzle/` |\n| Drizzle configs | 2 configs (auth + features) | 1 config |\n\n## Optional Output Files\n\nThese files are generated only when the corresponding features are configured:\n\n### Embeddings\n\nWhen any feature has `embeddings` configured:\n\n```\nsrc/\n├── lib/\n│ └── embeddings.ts # Embedding helpers\n├── routes/\n│ └── embeddings.ts # POST /api/v1/embeddings endpoint\n└── queue-consumer.ts # Queue handler for async embedding jobs\n```\n\n### File Storage (R2)\n\nWhen `fileStorage` is configured:\n\n```\nsrc/\n└── routes/\n └── storage.ts # File upload/download endpoints\ndrizzle/\n└── files/ # File metadata migrations\n ├── meta/\n └── 0000_*.sql\n```\n\n### Webhooks\n\nWhen webhooks are enabled:\n\n```\nsrc/\n└── lib/\n └── webhooks/\n ├── index.ts # Webhook module entry\n ├── sign.ts # Webhook payload signing\n ├── handlers.ts # Handler registry\n ├── emit.ts # Queue emission helpers\n ├── routes.ts # Inbound/outbound endpoints\n └── providers/\n ├── index.ts\n └── stripe.ts # Stripe webhook handler\ndrizzle/\n└── webhooks/ # Webhook schema migrations\n ├── meta/\n └── 0000_*.sql\n```\n\n### Security Audit Database (Unsafe Actions)\n\nWhen any action enables unsafe cross-tenant mode (`unsafe.crossTenant: true`):\n\n```\nsrc/\n├── db/\n│ └── audit-schema.ts # audit_events table\n└── lib/\n └── security-audit.ts # mandatory audit writer\n\ndrizzle/\n└── audit/\n ├── meta/\n └── 0000_*.sql\n\n# Root\n└── drizzle.audit.config.ts\n```\n\nCloudflare output also includes an `AUDIT_DB` D1 binding in `wrangler.toml` and migration scripts:\n\n- `db:migrate:audit:local`\n- `db:migrate:audit:remote`\n\n### Security Contract Report and Signature\n\nGenerated on every compile (unless disabled via `compiler.securityContracts.report.enabled: false`):\n\n```\nreports/\n├── security-contracts.report.json # Contract evaluation summary + violations\n└── security-contracts.report.sig.json # Signature / digest envelope for the report\n```\n\nThe signature file uses HMAC-SHA256 when a signing key is configured, otherwise it falls back to SHA-256 digest mode. \nSet `compiler.securityContracts.report.signature.required: true` to fail compilation when a signing key is missing.\n\n### Realtime\n\nWhen any feature has `realtime` configured:\n\n```\nsrc/\n└── lib/\n └── realtime.ts # Broadcast helpers\n\ncloudflare-workers/ # Separate Durable Objects worker\n└── broadcast/\n ├── Broadcaster.ts\n ├── index.ts\n └── wrangler.toml\n```\n\n### Device Authorization\n\nWhen the `deviceAuthorization` plugin is enabled:\n\n```\nsrc/\n└── routes/\n └── cli-auth.ts # Device auth flow endpoints\n```\n\n## Database Schemas\n\n### Dual Database Mode (Cloudflare Default)\n\nThe compiler separates schemas into two files:\n\n**`src/db/auth-schema.ts`** — Re-exports Better Auth table schemas:\n- `users`, `sessions`, `accounts`\n- `organizations`, `members`, `invitations` (if organizations enabled)\n- Plugin-specific tables (`apiKeys`, etc.)\n\n**`src/db/features-schema.ts`** — Re-exports your feature schemas:\n- All tables defined with `defineTable()`\n- Audit field columns added automatically\n\n### Single Database Mode (Bun Default)\n\n**`src/db/schema.ts`** — Combined re-export of all schemas (auth + features).\n\n## Generated Routes\n\nFor each feature, the compiler generates a routes file at `src/features/{name}/routes.ts` containing:\n\n| Route | Generated When |\n|-------|----------------|\n| `GET /` | `crud.list` configured |\n| `GET /:id` | `crud.get` configured |\n| `POST /` | `crud.create` configured |\n| `PATCH /:id` | `crud.update` configured |\n| `DELETE /:id` | `crud.delete` configured |\n| `PUT /:id` | `crud.put` configured |\n| `POST /batch` | `crud.create` exists (auto-enabled) |\n| `PATCH /batch` | `crud.update` exists (auto-enabled) |\n| `DELETE /batch` | `crud.delete` exists (auto-enabled) |\n| `PUT /batch` | `crud.put` exists (auto-enabled) |\n| `GET /views/{name}` | `views` configured |\n| `POST /:id/{action}` | Record-based actions defined |\n| `POST /{action}` | Standalone actions defined |\n\nAll routes are mounted under `/api/v1/{feature}` in the main app.\n\n## Migrations\n\nThe compiler runs `drizzle-kit generate` during compilation to produce SQL migration files. On subsequent compiles, it uses `existingFiles` (your current migration state) to generate only incremental changes.\n\nThe CLI loads migration meta JSON from:\n\n- `drizzle/auth/meta/`\n- `drizzle/features/meta/`\n- `drizzle/files/meta/`\n- `drizzle/webhooks/meta/`\n- `drizzle/meta/` (legacy single database mode)\n- `quickback/drizzle/...` mirrors (same paths under `quickback/`)\n\nWhen a `quickback/` folder exists and compile output goes to project root, the CLI writes state artifacts directly into `quickback/`:\n\n- `quickback/drizzle/...` for Drizzle migration SQL/meta artifacts\n- `quickback/reports/...` for security contract report artifacts\n\nThe CLI also syncs Drizzle meta JSON from output into `quickback/drizzle/...` as a compatibility fallback for tool-generated meta files.\n\nFor non-interactive environments (cloud compile, CI), table/column renames must be declared with `compiler.migrations.renames` in `quickback.config.ts`. This avoids interactive rename prompts during migration generation.\n\nMigration files follow the Drizzle Kit naming convention:\n```\n0000_initial.sql\n0001_add_status_column.sql\n0002_create_orders_table.sql\n```\n\n## See Also\n\n- [Providers](/compiler/config/providers) — Configure runtime, database, and auth providers\n- [Environment variables](/compiler/config/variables) — Required variables by runtime"
139
143
  },
140
144
  "compiler/config/providers": {
141
145
  "title": "Providers",
@@ -433,6 +437,7 @@ export const TOPIC_LIST = [
433
437
  "cms/connecting",
434
438
  "cms",
435
439
  "cms/inline-editing",
440
+ "cms/record-layouts",
436
441
  "cms/schema-format",
437
442
  "cms/schema-registry",
438
443
  "cms/security",
@@ -1 +1 @@
1
- {"version":3,"file":"content.js","sourceRoot":"","sources":["../../src/docs/content.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"content.js","sourceRoot":"","sources":["../../src/docs/content.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@
10
10
  */
11
11
  import pc from "picocolors";
12
12
  // Version injected at build time by scripts/inject-version.ts
13
- const CLI_VERSION = "0.5.12";
13
+ const CLI_VERSION = "0.5.14";
14
14
  function getPackageVersion() {
15
15
  return CLI_VERSION;
16
16
  }
@@ -0,0 +1,8 @@
1
+ import type { GeneratedFile } from './file-writer.js';
2
+ export declare function isSecurityReportArtifactContent(content: string): boolean;
3
+ export declare function isStateArtifactFile(file: Pick<GeneratedFile, 'path' | 'content'>): boolean;
4
+ export declare function partitionGeneratedFiles(files: GeneratedFile[]): {
5
+ runtimeFiles: GeneratedFile[];
6
+ stateFiles: GeneratedFile[];
7
+ };
8
+ //# sourceMappingURL=artifact-routing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-routing.d.ts","sourceRoot":"","sources":["../../src/lib/artifact-routing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAOtD,wBAAgB,+BAA+B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAOxE;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,OAAO,CAI1F;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,aAAa,EAAE,GACrB;IAAE,YAAY,EAAE,aAAa,EAAE,CAAC;IAAC,UAAU,EAAE,aAAa,EAAE,CAAA;CAAE,CAahE"}
@@ -0,0 +1,34 @@
1
+ const SECURITY_REPORT_KINDS = new Set([
2
+ 'quickback-security-contract-report',
3
+ 'quickback-security-contract-signature',
4
+ ]);
5
+ export function isSecurityReportArtifactContent(content) {
6
+ try {
7
+ const parsed = JSON.parse(content);
8
+ return SECURITY_REPORT_KINDS.has(parsed?.kind ?? '');
9
+ }
10
+ catch {
11
+ return false;
12
+ }
13
+ }
14
+ export function isStateArtifactFile(file) {
15
+ if (file.path.startsWith('drizzle/'))
16
+ return true;
17
+ if (!file.path.endsWith('.json'))
18
+ return false;
19
+ return isSecurityReportArtifactContent(file.content);
20
+ }
21
+ export function partitionGeneratedFiles(files) {
22
+ const runtimeFiles = [];
23
+ const stateFiles = [];
24
+ for (const file of files) {
25
+ if (isStateArtifactFile(file)) {
26
+ stateFiles.push(file);
27
+ }
28
+ else {
29
+ runtimeFiles.push(file);
30
+ }
31
+ }
32
+ return { runtimeFiles, stateFiles };
33
+ }
34
+ //# sourceMappingURL=artifact-routing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-routing.js","sourceRoot":"","sources":["../../src/lib/artifact-routing.ts"],"names":[],"mappings":"AAEA,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC;IACpC,oCAAoC;IACpC,uCAAuC;CACxC,CAAC,CAAC;AAEH,MAAM,UAAU,+BAA+B,CAAC,OAAe;IAC7D,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAsB,CAAC;QACxD,OAAO,qBAAqB,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAA6C;IAC/E,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IAClD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/C,OAAO,+BAA+B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,KAAsB;IAEtB,MAAM,YAAY,GAAoB,EAAE,CAAC;IACzC,MAAM,UAAU,GAAoB,EAAE,CAAC;IAEvC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxB,CAAC;aAAM,CAAC;YACN,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC;AACtC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=artifact-routing.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-routing.test.d.ts","sourceRoot":"","sources":["../../src/lib/artifact-routing.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,37 @@
1
+ import { describe, expect, it } from 'bun:test';
2
+ import { isStateArtifactFile, partitionGeneratedFiles } from './artifact-routing.js';
3
+ describe('artifact routing', () => {
4
+ // User story: As a developer keeping definitions in quickback/, I need drizzle migration state
5
+ // artifacts written to quickback so compile output does not keep recreating root drizzle folders.
6
+ it('classifies drizzle paths as state artifacts', () => {
7
+ expect(isStateArtifactFile({
8
+ path: 'drizzle/auth/meta/_journal.json',
9
+ content: '{"version":"1"}',
10
+ })).toBe(true);
11
+ });
12
+ // User story: As a platform operator, I need security contract reports treated as state artifacts
13
+ // so they stay alongside quickback definitions and can be reviewed across compile runs.
14
+ it('classifies security report artifacts by kind payload', () => {
15
+ expect(isStateArtifactFile({
16
+ path: 'reports/security-contracts.report.json',
17
+ content: JSON.stringify({ kind: 'quickback-security-contract-report' }),
18
+ })).toBe(true);
19
+ expect(isStateArtifactFile({
20
+ path: 'reports/security-contracts.report.sig.json',
21
+ content: JSON.stringify({ kind: 'quickback-security-contract-signature' }),
22
+ })).toBe(true);
23
+ });
24
+ // User story: As an API developer, I need runtime files to remain in outputDir so application code,
25
+ // handlers, and configs continue to compile and deploy from the generated runtime tree.
26
+ it('keeps non-state runtime files in runtime bucket', () => {
27
+ const files = [
28
+ { path: 'src/index.ts', content: 'export {};' },
29
+ { path: 'openapi.json', content: '{"openapi":"3.0.0"}' },
30
+ { path: 'drizzle/auth/meta/_journal.json', content: '{"version":"1"}' },
31
+ ];
32
+ const { runtimeFiles, stateFiles } = partitionGeneratedFiles(files);
33
+ expect(runtimeFiles.map((f) => f.path)).toEqual(['src/index.ts', 'openapi.json']);
34
+ expect(stateFiles.map((f) => f.path)).toEqual(['drizzle/auth/meta/_journal.json']);
35
+ });
36
+ });
37
+ //# sourceMappingURL=artifact-routing.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-routing.test.js","sourceRoot":"","sources":["../../src/lib/artifact-routing.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAEhD,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAErF,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,+FAA+F;IAC/F,kGAAkG;IAClG,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,CAAC,mBAAmB,CAAC;YACzB,IAAI,EAAE,iCAAiC;YACvC,OAAO,EAAE,iBAAiB;SAC3B,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,kGAAkG;IAClG,wFAAwF;IACxF,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,CAAC,mBAAmB,CAAC;YACzB,IAAI,EAAE,wCAAwC;YAC9C,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,oCAAoC,EAAE,CAAC;SACxE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACf,MAAM,CAAC,mBAAmB,CAAC;YACzB,IAAI,EAAE,4CAA4C;YAClD,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,uCAAuC,EAAE,CAAC;SAC3E,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,oGAAoG;IACpG,wFAAwF;IACxF,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,KAAK,GAAG;YACZ,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,YAAY,EAAE;YAC/C,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,qBAAqB,EAAE;YACxD,EAAE,IAAI,EAAE,iCAAiC,EAAE,OAAO,EAAE,iBAAiB,EAAE;SACxE,CAAC;QAEF,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,uBAAuB,CAAC,KAAK,CAAC,CAAC;QACpE,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC;IACrF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kardoe/quickback",
3
- "version": "0.5.12",
3
+ "version": "0.5.14",
4
4
  "description": "CLI for Quickback - one-shot backend generator",
5
5
  "author": "Paul Stenhouse",
6
6
  "license": "MIT",
@@ -84,6 +84,16 @@ export default defineConfig({
84
84
  });
85
85
  ```
86
86
 
87
+ ## Compile Output and State Artifacts
88
+
89
+ When a project has a `quickback/` folder and compiles runtime output to project root:
90
+
91
+ - Runtime code stays in `build.outputDir` (for example `src/`, `wrangler.toml`, `package.json`).
92
+ - Drizzle migration/state artifacts are written to `quickback/drizzle/...`.
93
+ - Security contract report artifacts are written to `quickback/reports/...`.
94
+
95
+ Treat `quickback/drizzle` as the canonical migration state location for repeated compiles.
96
+
87
97
  ## Automatic Audit Fields
88
98
 
89
99
  Quickback automatically injects these fields into every table:
@@ -100,40 +110,51 @@ Features live in `quickback/features/{name}/` with one file per table using `def
100
110
 
101
111
  **Important**: Legacy mode (separate schema.ts + resource.ts) is no longer supported.
102
112
 
103
- ## Example: candidates.ts
113
+ ## Example: todos.ts
104
114
 
105
115
  ```typescript
106
- import { sqliteTable, text } from "drizzle-orm/sqlite-core";
116
+ import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
107
117
  import { defineTable } from "@quickback/compiler";
108
118
 
109
- export const candidates = sqliteTable("candidates", {
110
- id: text("id").primaryKey(),
119
+ export const todos = sqliteTable("todos", {
120
+ id: integer("id").primaryKey(),
121
+ title: text("title").notNull(),
122
+ description: text("description"),
123
+ completed: integer("completed", { mode: "boolean" }).default(false),
124
+ userId: text("user_id").notNull(),
111
125
  organizationId: text("organization_id").notNull(),
112
- name: text("name").notNull(),
113
- email: text("email").notNull(),
114
- phone: text("phone"),
115
- resumeUrl: text("resume_url"),
116
- source: text("source"),
117
126
  });
118
127
 
119
- export default defineTable(candidates, {
128
+ export default defineTable(todos, {
120
129
  firewall: {
121
- organization: {},
130
+ organization: {}, // Auto-detects 'organizationId' column
131
+ owner: {}, // Auto-detects 'userId' column
122
132
  },
133
+
123
134
  crud: {
124
- list: { access: { roles: ["owner", "hiring-manager", "recruiter", "interviewer"] } },
125
- get: { access: { roles: ["owner", "hiring-manager", "recruiter", "interviewer"] } },
126
- create: { access: { roles: ["owner", "hiring-manager", "recruiter"] } },
127
- update: { access: { roles: ["owner", "hiring-manager", "recruiter"] } },
128
- delete: { access: { roles: ["owner", "hiring-manager"] }, mode: "soft" },
135
+ list: { access: { roles: ["member", "admin"] } },
136
+ get: { access: { roles: ["member", "admin"] } },
137
+ create: { access: { roles: ["member", "admin"] } },
138
+ update: { access: { roles: ["admin"] } },
139
+ delete: { access: { roles: ["admin"] }, mode: "soft" },
129
140
  },
141
+
130
142
  guards: {
131
- createable: ["name", "email", "phone", "resumeUrl", "source"],
132
- updatable: ["name", "phone"],
143
+ createable: ["title", "description", "completed"],
144
+ updatable: ["title", "description", "completed"],
133
145
  },
146
+
134
147
  masking: {
135
- email: { type: "email", show: { roles: ["hiring-manager", "recruiter"] } },
136
- phone: { type: "phone", show: { roles: ["hiring-manager", "recruiter"] } },
148
+ userId: { type: "redact", show: { roles: ["admin"] } },
149
+ },
150
+
151
+ layouts: {
152
+ default: {
153
+ sections: [
154
+ { label: "Details", columns: 2, fields: ["title", "completed"] },
155
+ { label: "Audit", collapsed: true, fields: ["userId"] },
156
+ ],
157
+ },
137
158
  },
138
159
  });
139
160
  ```
@@ -144,12 +165,9 @@ Tables without a `defineTable()` default export get no API routes:
144
165
 
145
166
  ```typescript
146
167
  // No default export = no API routes generated
147
- export const interviewScores = sqliteTable('interview_scores', {
148
- applicationId: text('application_id').notNull(),
149
- interviewerId: text('interviewer_id').notNull(),
150
- score: integer('score').notNull(),
151
- feedback: text('feedback'),
152
- organizationId: text('organization_id').notNull(), // Always scope junction tables
168
+ export const roomAmenities = sqliteTable('room_amenities', {
169
+ roomId: text('room_id').notNull(),
170
+ amenityId: text('amenity_id').notNull(),
153
171
  });
154
172
  ```
155
173
 
@@ -202,18 +220,18 @@ Role-based and record-based access control. Deny by default.
202
220
 
203
221
  ```typescript
204
222
  crud: {
205
- list: { access: { roles: ['owner', 'hiring-manager', 'recruiter', 'interviewer'] } },
206
- get: { access: { roles: ['owner', 'hiring-manager', 'recruiter', 'interviewer'] } },
207
- create: { access: { roles: ['owner', 'hiring-manager', 'recruiter'] } },
223
+ list: { access: { roles: ['member'] } },
224
+ get: { access: { roles: ['member'] } },
225
+ create: { access: { roles: ['admin', 'manager'] } },
208
226
  update: {
209
227
  access: {
210
228
  or: [
211
- { roles: ['owner', 'hiring-manager'] },
229
+ { roles: ['admin'] },
212
230
  { record: { createdBy: { equals: '$ctx.userId' } } },
213
231
  ],
214
232
  },
215
233
  },
216
- delete: { access: { roles: ['owner', 'hiring-manager'] } },
234
+ delete: { access: { roles: ['admin'] } },
217
235
  }
218
236
  ```
219
237
 
@@ -244,10 +262,10 @@ Controls which fields can be modified.
244
262
 
245
263
  ```typescript
246
264
  guards: {
247
- createable: ['candidateId', 'jobId', 'notes'],
248
- updatable: ['notes'],
249
- immutable: ['appliedAt'],
250
- protected: { stage: ['advance-stage'] },
265
+ createable: ['name', 'description'], // Allowed on POST
266
+ updatable: ['description'], // Allowed on PATCH
267
+ immutable: ['invoiceNumber'], // Set once, never change
268
+ protected: { status: ['approve'] }, // Only via named actions
251
269
  }
252
270
  ```
253
271
 
@@ -282,13 +300,13 @@ export default defineTable(external_orders, {
282
300
 
283
301
  ```typescript
284
302
  masking: {
285
- email: {
286
- type: 'email',
287
- show: { roles: ['hiring-manager', 'recruiter'] },
303
+ ssn: {
304
+ type: 'ssn', // *****6789
305
+ show: { roles: ['admin', 'hr'] },
288
306
  },
289
- phone: {
290
- type: 'phone',
291
- show: { roles: ['hiring-manager', 'recruiter'] },
307
+ email: {
308
+ type: 'email', // p***@e******.com
309
+ show: { roles: ['admin'], or: 'owner' },
292
310
  },
293
311
  }
294
312
  ```
@@ -324,92 +342,86 @@ The compiler warns if sensitive columns aren't explicitly configured:
324
342
  Views are named projections that control which fields are visible based on role.
325
343
 
326
344
  ```typescript
327
- export default defineTable(candidates, {
345
+ export default defineTable(customers, {
328
346
  // ... firewall, guards, etc.
329
347
 
330
348
  views: {
331
- pipeline: {
332
- fields: ['id', 'name', 'email', 'source'],
333
- access: { roles: ['owner', 'hiring-manager', 'recruiter', 'interviewer'] },
349
+ summary: {
350
+ fields: ['id', 'name', 'email'],
351
+ access: { roles: ['member', 'admin'] },
334
352
  },
335
353
  full: {
336
- fields: ['id', 'name', 'email', 'phone', 'resumeUrl', 'source'],
337
- access: { roles: ['owner', 'hiring-manager', 'recruiter'] },
354
+ fields: ['id', 'name', 'email', 'phone', 'ssn', 'address'],
355
+ access: { roles: ['admin'] },
338
356
  },
339
357
  },
340
358
  });
341
359
  ```
342
360
 
343
361
  **Generated endpoints**:
344
- - `GET /api/v1/candidates/views/pipeline` — returns only id, name, email, source
345
- - `GET /api/v1/candidates/views/full` — returns all fields (recruiters and above)
362
+ - `GET /api/v1/customers/views/summary` — returns only id, name, email
363
+ - `GET /api/v1/customers/views/full` — returns all fields (admin only)
346
364
 
347
365
  Views support the same query parameters as list (filtering, sorting, pagination). Masking still applies to returned fields.
348
366
 
349
367
  ---
350
368
 
351
- # References — FK Target Mapping
369
+ # Validation
352
370
 
353
- When FK columns don't match the target table name by convention (e.g., `vendorId` points to the `contact` table), declare explicit references:
371
+ Field-level validation rules compiled into the API:
354
372
 
355
373
  ```typescript
356
- export default defineTable(items, {
357
- references: {
358
- clientId: "contact",
359
- vendorId: "contact",
360
- salesCodeId: "salesCode",
361
- taxLocationId: "taxLocation",
374
+ export default defineTable(rooms, {
375
+ // ... other config
376
+
377
+ validation: {
378
+ name: { minLength: 1, maxLength: 100 },
379
+ capacity: { min: 1, max: 1000 },
380
+ roomType: { enum: ['meeting', 'conference', 'breakout'] },
381
+ email: { email: true },
382
+ website: { url: true },
383
+ code: { pattern: '^[A-Z]{3}$' },
362
384
  },
363
- // ...
364
385
  });
365
386
  ```
366
387
 
367
- Each key is a column name ending in `Id`, value is the camelCase target table name. These flow into schema-registry.json as `fkTarget` on each column, enabling the CMS to render typeahead/lookup inputs.
368
-
369
- Convention-based matching (strip `Id` suffix) still works for simple cases like `projectId` → `project`. Use `references` only when the convention doesn't match.
370
-
371
388
  ---
372
389
 
373
- # Input Hints — CMS Form Controls
390
+ # CMS Record Layouts
374
391
 
375
- Control how the CMS renders form inputs for specific columns:
392
+ Control how fields are grouped on the CMS record detail page. Without layouts, fields are auto-grouped by naming heuristics.
376
393
 
377
394
  ```typescript
378
- export default defineTable(invoice, {
379
- inputHints: {
380
- status: "select",
381
- sortOrder: "radio",
382
- isPartialPaymentDisabled: "checkbox",
383
- headerMessage: "textarea",
384
- footerMessage: "textarea",
395
+ export default defineTable(contacts, {
396
+ // ... firewall, crud, guards, etc.
397
+
398
+ layouts: {
399
+ default: {
400
+ sections: [
401
+ { label: "Contact Info", columns: 2, fields: ["name", "email", "phone", "mobile"] },
402
+ { label: "Address", columns: 2, fields: ["address1", "address2", "city", "state", "zip"] },
403
+ { label: "Internal Notes", collapsed: true, fields: ["notes", "internalNotes"] },
404
+ ],
405
+ },
406
+ compact: {
407
+ sections: [
408
+ { label: "Summary", fields: ["name", "status", "email"] },
409
+ ],
410
+ },
385
411
  },
386
- // ...
387
412
  });
388
413
  ```
389
414
 
390
- Available values: `select`, `multi-select`, `radio`, `checkbox`, `textarea`, `lookup`, `hidden`, `color`, `date`, `datetime`, `time`, `currency`.
415
+ ### Section Options
391
416
 
392
- Input hints are emitted in schema-registry.json as `inputHints` on the table metadata.
417
+ | Property | Type | Default | Description |
418
+ |----------|------|---------|-------------|
419
+ | `label` | string | required | Section header text |
420
+ | `fields` | string[] | required | Column names to display |
421
+ | `columns` | `1 \| 2` | `1` | Number of columns for field layout |
422
+ | `collapsed` | boolean | `false` | Whether the section starts collapsed |
393
423
 
394
- ---
395
-
396
- # Validation
397
-
398
- Field-level validation rules compiled into the API:
399
-
400
- ```typescript
401
- export default defineTable(jobs, {
402
- // ... other config
403
-
404
- validation: {
405
- title: { minLength: 1, maxLength: 200 },
406
- department: { minLength: 1, maxLength: 100 },
407
- status: { enum: ['draft', 'open', 'closed'] },
408
- salaryMin: { min: 0 },
409
- salaryMax: { min: 0 },
410
- },
411
- });
412
- ```
424
+ Fields not assigned to any section are collected into an "Other Fields" section. When multiple layouts are defined, a dropdown appears in the CMS record detail header.
413
425
 
414
426
  ---
415
427
 
@@ -418,54 +430,51 @@ export default defineTable(jobs, {
418
430
  Actions are custom API endpoints for business logic beyond CRUD. Defined in a separate `actions.ts` file using `defineActions()`.
419
431
 
420
432
  ```typescript
421
- // quickback/features/applications/actions.ts
422
- import { applications } from './applications';
433
+ // quickback/features/todos/actions.ts
434
+ import { todos } from './todos';
423
435
  import { defineActions } from '@quickback/compiler';
424
436
  import { z } from 'zod';
425
437
 
426
- export default defineActions(applications, {
427
- 'advance-stage': {
428
- description: "Move application to the next pipeline stage",
438
+ export default defineActions(todos, {
439
+ complete: {
440
+ description: "Mark todo as complete",
429
441
  input: z.object({
430
- stage: z.enum(["screening", "interview", "offer", "hired"]),
431
- notes: z.string().optional(),
442
+ completedAt: z.string().datetime().optional(),
432
443
  }),
433
- access: {
434
- roles: ["owner", "hiring-manager"],
435
- record: { stage: { notEquals: "rejected" } },
444
+ guard: {
445
+ roles: ["member", "admin"],
446
+ record: { completed: { equals: false } },
436
447
  },
437
448
  execute: async ({ db, record, ctx, input }) => {
438
- const [updated] = await db.update(applications)
439
- .set({ stage: input.stage, notes: input.notes ?? record.notes })
440
- .where(eq(applications.id, record.id))
441
- .returning();
442
- return updated;
449
+ // Inline handler
450
+ await db.update(todos).set({ completed: true }).where(eq(todos.id, record.id));
451
+ return { success: true };
443
452
  },
444
453
  sideEffects: "sync",
445
454
  },
446
455
 
447
- reject: {
448
- description: "Reject an application",
449
- input: z.object({ reason: z.string() }),
450
- access: { roles: ["owner", "hiring-manager"] },
451
- handler: "./handlers/reject", // OR: external file handler
456
+ archive: {
457
+ description: "Archive a todo",
458
+ input: z.object({}),
459
+ guard: { roles: ["admin"] },
460
+ handler: "./handlers/archive", // OR: external file handler
452
461
  },
453
462
  });
454
463
  ```
455
464
 
456
- **Generated Route**: `POST /api/v1/applications/:id/advance-stage`
465
+ **Generated Route**: `POST /api/v1/todos/:id/complete`
457
466
 
458
467
  ### Record-based vs Standalone Actions
459
468
 
460
469
  **Record-based** (default) — operates on a specific record via `:id`:
461
470
  ```typescript
462
- 'advance-stage': {
463
- description: "Move application to the next pipeline stage",
464
- input: z.object({ stage: z.enum(["screening", "interview", "offer", "hired"]) }),
465
- access: { roles: ["owner", "hiring-manager"] },
466
- handler: "./handlers/advance-stage",
471
+ approve: {
472
+ description: "Approve an invoice",
473
+ input: z.object({ notes: z.string().optional() }),
474
+ guard: { roles: ["admin"] },
475
+ handler: "./handlers/approve",
467
476
  }
468
- // → POST /api/v1/applications/:id/advance-stage
477
+ // → POST /api/v1/invoices/:id/approve
469
478
  ```
470
479
 
471
480
  **Standalone** — custom endpoint not tied to a record:
@@ -476,10 +485,10 @@ chat: {
476
485
  method: "POST",
477
486
  responseType: "stream",
478
487
  input: z.object({ message: z.string() }),
479
- access: { roles: ["recruiter", "hiring-manager"] },
488
+ guard: { roles: ["member"] },
480
489
  handler: "./handlers/chat",
481
490
  }
482
- // → POST /api/v1/applications/chat
491
+ // → POST /api/v1/todos/chat
483
492
  ```
484
493
 
485
494
  ### Action Options
@@ -583,7 +592,7 @@ OR'd LIKE across all `text()` schema columns (system columns excluded). Combine
583
592
 
584
593
  ```json
585
594
  {
586
- "data": [{ "id": "...", "name": "Jane Smith", "source": "linkedin" }],
595
+ "data": [{ "id": "...", "title": "Todo 1" }],
587
596
  "pagination": {
588
597
  "limit": 10,
589
598
  "offset": 0,
@@ -764,17 +773,34 @@ Detect from `quickback.config.ts` and use the correct imports:
764
773
 
765
774
  # Documentation
766
775
 
776
+ ## CLI Docs (Recommended)
777
+
778
+ The fastest way to access documentation is via the Quickback CLI. It bundles all docs offline:
779
+
780
+ ```bash
781
+ quickback docs # List all available topics
782
+ quickback docs <topic> # Show docs for a specific topic
783
+ quickback docs firewall # Example: firewall docs
784
+ quickback docs cms/record-layouts # Example: CMS record layouts
785
+ ```
786
+
787
+ ## Online Docs
788
+
767
789
  Full documentation at https://docs.quickback.dev
768
790
 
769
791
  - [Getting Started](https://docs.quickback.dev/compiler/getting-started)
770
792
  - [Concepts](https://docs.quickback.dev/compiler/definitions/concepts)
771
- - [Full Example](https://docs.quickback.dev/compiler/getting-started/full-example)
772
793
  - [Database Schema](https://docs.quickback.dev/compiler/definitions/schema)
773
- - [CRUD & API](https://docs.quickback.dev/compiler/using-the-api)
774
- - [Views](https://docs.quickback.dev/compiler/definitions/views)
775
- - [Actions](https://docs.quickback.dev/compiler/definitions/actions)
776
794
  - [Firewall](https://docs.quickback.dev/compiler/definitions/firewall)
777
795
  - [Access](https://docs.quickback.dev/compiler/definitions/access)
778
796
  - [Guards](https://docs.quickback.dev/compiler/definitions/guards)
779
797
  - [Masking](https://docs.quickback.dev/compiler/definitions/masking)
798
+ - [Views](https://docs.quickback.dev/compiler/definitions/views)
799
+ - [Validation](https://docs.quickback.dev/compiler/definitions/validation)
800
+ - [Actions](https://docs.quickback.dev/compiler/definitions/actions)
801
+ - [CRUD API](https://docs.quickback.dev/compiler/using-the-api/crud)
802
+ - [Query Parameters](https://docs.quickback.dev/compiler/using-the-api/query-params)
780
803
  - [CLI Reference](https://docs.quickback.dev/compiler/cloud-compiler/cli)
804
+ - [CMS Overview](https://docs.quickback.dev/cms)
805
+ - [CMS Record Layouts](https://docs.quickback.dev/cms/record-layouts)
806
+ - [CMS Schema Format](https://docs.quickback.dev/cms/schema-format)
@@ -19,6 +19,7 @@ You deeply understand:
19
19
  - **Actions**: Custom endpoints using `defineActions()` with Zod schemas
20
20
  - **Views**: Column-level security with named projections
21
21
  - **Validation**: Field-level validation rules
22
+ - **Layouts**: CMS record page field grouping with sections, columns, and collapsed state
22
23
 
23
24
  ## When Invoked
24
25
 
@@ -44,6 +45,11 @@ Generate files in `quickback/features/{name}/`:
44
45
  - `actions.ts` - Custom actions via `defineActions()` with Zod schemas (if needed)
45
46
  - `handlers/` - Action handler files (if needed)
46
47
 
48
+ When explaining compile outputs:
49
+ - Runtime outputs remain in `build.outputDir`.
50
+ - Drizzle and migration state artifacts should live in `quickback/drizzle/...` when a `quickback/` folder exists.
51
+ - Security contract reports should live in `quickback/reports/...` when a `quickback/` folder exists.
52
+
47
53
  Detect the database dialect from `quickback.config.ts`:
48
54
  - Cloudflare D1 / SQLite: Use `sqliteTable`, `text`, `integer` from `drizzle-orm/sqlite-core`
49
55
  - Supabase / PostgreSQL: Use `pgTable`, `text`, `boolean`, `timestamp` from `drizzle-orm/pg-core`
@@ -51,37 +57,35 @@ Detect the database dialect from `quickback.config.ts`:
51
57
  ### Table Definition Pattern
52
58
 
53
59
  ```typescript
54
- import { sqliteTable, text } from "drizzle-orm/sqlite-core";
60
+ import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
55
61
  import { defineTable } from "@quickback/compiler";
56
62
 
57
- export const candidates = sqliteTable("candidates", {
58
- id: text("id").primaryKey(),
63
+ export const todos = sqliteTable("todos", {
64
+ id: integer("id").primaryKey(),
65
+ title: text("title").notNull(),
66
+ completed: integer("completed", { mode: "boolean" }).default(false),
67
+ userId: text("user_id").notNull(),
59
68
  organizationId: text("organization_id").notNull(),
60
- name: text("name").notNull(),
61
- email: text("email").notNull(),
62
- phone: text("phone"),
63
- resumeUrl: text("resume_url"),
64
- source: text("source"),
65
69
  });
66
70
 
67
- export default defineTable(candidates, {
71
+ export default defineTable(todos, {
68
72
  firewall: {
69
- organization: {},
73
+ organization: {}, // Auto-detects 'organizationId' column
74
+ owner: {}, // Auto-detects 'userId' column
70
75
  },
71
76
  crud: {
72
- list: { access: { roles: ["owner", "hiring-manager", "recruiter", "interviewer"] } },
73
- get: { access: { roles: ["owner", "hiring-manager", "recruiter", "interviewer"] } },
74
- create: { access: { roles: ["owner", "hiring-manager", "recruiter"] } },
75
- update: { access: { roles: ["owner", "hiring-manager", "recruiter"] } },
76
- delete: { access: { roles: ["owner", "hiring-manager"] }, mode: "soft" },
77
+ list: { access: { roles: ["member", "admin"] } },
78
+ get: { access: { roles: ["member", "admin"] } },
79
+ create: { access: { roles: ["member", "admin"] } },
80
+ update: { access: { roles: ["admin"] } },
81
+ delete: { access: { roles: ["admin"] }, mode: "soft" },
77
82
  },
78
83
  guards: {
79
- createable: ["name", "email", "phone", "resumeUrl", "source"],
80
- updatable: ["name", "phone"],
84
+ createable: ["title", "completed"],
85
+ updatable: ["title", "completed"],
81
86
  },
82
87
  masking: {
83
- email: { type: "email", show: { roles: ["hiring-manager", "recruiter"] } },
84
- phone: { type: "phone", show: { roles: ["hiring-manager", "recruiter"] } },
88
+ userId: { type: "redact", show: { roles: ["admin"] } },
85
89
  },
86
90
  });
87
91
  ```
@@ -89,28 +93,24 @@ export default defineTable(candidates, {
89
93
  ### Actions Pattern
90
94
 
91
95
  ```typescript
92
- // quickback/features/applications/actions.ts
93
- import { applications } from './applications';
96
+ // quickback/features/todos/actions.ts
97
+ import { todos } from './todos';
94
98
  import { defineActions } from '@quickback/compiler';
95
99
  import { z } from 'zod';
96
100
 
97
- export default defineActions(applications, {
98
- 'advance-stage': {
99
- description: "Move application to the next pipeline stage",
101
+ export default defineActions(todos, {
102
+ complete: {
103
+ description: "Mark todo as complete",
100
104
  input: z.object({
101
- stage: z.enum(["screening", "interview", "offer", "hired"]),
102
- notes: z.string().optional(),
105
+ completedAt: z.string().datetime().optional(),
103
106
  }),
104
- access: {
105
- roles: ["owner", "hiring-manager"],
106
- record: { stage: { notEquals: "rejected" } },
107
+ guard: {
108
+ roles: ["member", "admin"],
109
+ record: { completed: { equals: false } },
107
110
  },
108
111
  execute: async ({ db, record, ctx, input }) => {
109
- const [updated] = await db.update(applications)
110
- .set({ stage: input.stage, notes: input.notes ?? record.notes })
111
- .where(eq(applications.id, record.id))
112
- .returning();
113
- return updated;
112
+ await db.update(todos).set({ completed: true }).where(eq(todos.id, record.id));
113
+ return { success: true };
114
114
  },
115
115
  },
116
116
  });
@@ -143,29 +143,29 @@ firewall: {
143
143
  ### Workflow with protected status
144
144
  ```typescript
145
145
  guards: {
146
- protected: { stage: ['advance-stage', 'reject'] }
146
+ protected: { status: ['approve', 'reject'] }
147
147
  }
148
- // Plus defineActions() for advance-stage/reject
148
+ // Plus defineActions() for approve/reject
149
149
  ```
150
150
 
151
151
  ### PII masking
152
152
  ```typescript
153
153
  masking: {
154
- email: { type: 'email', show: { roles: ['hiring-manager', 'recruiter'] } },
155
- phone: { type: 'phone', show: { roles: ['hiring-manager', 'recruiter'] } },
154
+ email: { type: 'email', show: { roles: ['admin'] } },
155
+ ssn: { type: 'ssn', show: { roles: ['hr'] } }
156
156
  }
157
157
  ```
158
158
 
159
159
  ### Views (column-level security)
160
160
  ```typescript
161
161
  views: {
162
- pipeline: {
163
- fields: ['id', 'name', 'source', 'stage'],
164
- access: { roles: ['owner', 'hiring-manager', 'recruiter', 'interviewer'] },
162
+ summary: {
163
+ fields: ['id', 'name', 'email'],
164
+ access: { roles: ['member', 'admin'] },
165
165
  },
166
166
  full: {
167
- fields: ['id', 'name', 'email', 'phone', 'resumeUrl', 'source', 'stage'],
168
- access: { roles: ['owner', 'hiring-manager', 'recruiter'] },
167
+ fields: ['id', 'name', 'email', 'phone', 'ssn'],
168
+ access: { roles: ['admin'] },
169
169
  },
170
170
  }
171
171
  ```
@@ -179,7 +179,7 @@ chat: {
179
179
  method: "POST",
180
180
  responseType: "stream",
181
181
  input: z.object({ message: z.string() }),
182
- access: { roles: ["recruiter", "hiring-manager"] },
182
+ guard: { roles: ["member"] },
183
183
  handler: "./handlers/chat",
184
184
  }
185
185
  ```
@@ -194,10 +194,24 @@ Before finishing, verify:
194
194
  - [ ] Masking for any PII fields
195
195
  - [ ] Views for different visibility levels (if needed)
196
196
  - [ ] Validation rules for constrained fields (if needed)
197
+ - [ ] Layouts for CMS record page field grouping (if needed)
197
198
  - [ ] No audit fields in schema (auto-injected)
198
199
  - [ ] Using `defineTable()` combined mode (not separate schema.ts + resource.ts)
199
200
  - [ ] Actions use `defineActions()` with Zod schemas (not JSON schema)
200
201
 
202
+ ## Accessing Documentation
203
+
204
+ When you need to look up Quickback docs, use the CLI — it bundles all docs offline:
205
+
206
+ ```bash
207
+ quickback docs # List all available topics
208
+ quickback docs <topic> # Show docs for a specific topic
209
+ quickback docs firewall # Example: firewall docs
210
+ quickback docs cms/record-layouts # Example: CMS record layouts
211
+ ```
212
+
213
+ Full online docs: https://docs.quickback.dev
214
+
201
215
  ## Response Style
202
216
 
203
217
  - Be direct and practical