@kardoe/quickback 0.5.12 → 0.5.13

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.13";
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.13",
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,42 @@ 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"] } },
137
149
  },
138
150
  });
139
151
  ```
@@ -144,12 +156,9 @@ Tables without a `defineTable()` default export get no API routes:
144
156
 
145
157
  ```typescript
146
158
  // 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
159
+ export const roomAmenities = sqliteTable('room_amenities', {
160
+ roomId: text('room_id').notNull(),
161
+ amenityId: text('amenity_id').notNull(),
153
162
  });
154
163
  ```
155
164
 
@@ -202,18 +211,18 @@ Role-based and record-based access control. Deny by default.
202
211
 
203
212
  ```typescript
204
213
  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'] } },
214
+ list: { access: { roles: ['member'] } },
215
+ get: { access: { roles: ['member'] } },
216
+ create: { access: { roles: ['admin', 'manager'] } },
208
217
  update: {
209
218
  access: {
210
219
  or: [
211
- { roles: ['owner', 'hiring-manager'] },
220
+ { roles: ['admin'] },
212
221
  { record: { createdBy: { equals: '$ctx.userId' } } },
213
222
  ],
214
223
  },
215
224
  },
216
- delete: { access: { roles: ['owner', 'hiring-manager'] } },
225
+ delete: { access: { roles: ['admin'] } },
217
226
  }
218
227
  ```
219
228
 
@@ -244,10 +253,10 @@ Controls which fields can be modified.
244
253
 
245
254
  ```typescript
246
255
  guards: {
247
- createable: ['candidateId', 'jobId', 'notes'],
248
- updatable: ['notes'],
249
- immutable: ['appliedAt'],
250
- protected: { stage: ['advance-stage'] },
256
+ createable: ['name', 'description'], // Allowed on POST
257
+ updatable: ['description'], // Allowed on PATCH
258
+ immutable: ['invoiceNumber'], // Set once, never change
259
+ protected: { status: ['approve'] }, // Only via named actions
251
260
  }
252
261
  ```
253
262
 
@@ -282,13 +291,13 @@ export default defineTable(external_orders, {
282
291
 
283
292
  ```typescript
284
293
  masking: {
285
- email: {
286
- type: 'email',
287
- show: { roles: ['hiring-manager', 'recruiter'] },
294
+ ssn: {
295
+ type: 'ssn', // *****6789
296
+ show: { roles: ['admin', 'hr'] },
288
297
  },
289
- phone: {
290
- type: 'phone',
291
- show: { roles: ['hiring-manager', 'recruiter'] },
298
+ email: {
299
+ type: 'email', // p***@e******.com
300
+ show: { roles: ['admin'], or: 'owner' },
292
301
  },
293
302
  }
294
303
  ```
@@ -324,89 +333,45 @@ The compiler warns if sensitive columns aren't explicitly configured:
324
333
  Views are named projections that control which fields are visible based on role.
325
334
 
326
335
  ```typescript
327
- export default defineTable(candidates, {
336
+ export default defineTable(customers, {
328
337
  // ... firewall, guards, etc.
329
338
 
330
339
  views: {
331
- pipeline: {
332
- fields: ['id', 'name', 'email', 'source'],
333
- access: { roles: ['owner', 'hiring-manager', 'recruiter', 'interviewer'] },
340
+ summary: {
341
+ fields: ['id', 'name', 'email'],
342
+ access: { roles: ['member', 'admin'] },
334
343
  },
335
344
  full: {
336
- fields: ['id', 'name', 'email', 'phone', 'resumeUrl', 'source'],
337
- access: { roles: ['owner', 'hiring-manager', 'recruiter'] },
345
+ fields: ['id', 'name', 'email', 'phone', 'ssn', 'address'],
346
+ access: { roles: ['admin'] },
338
347
  },
339
348
  },
340
349
  });
341
350
  ```
342
351
 
343
352
  **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)
353
+ - `GET /api/v1/customers/views/summary` — returns only id, name, email
354
+ - `GET /api/v1/customers/views/full` — returns all fields (admin only)
346
355
 
347
356
  Views support the same query parameters as list (filtering, sorting, pagination). Masking still applies to returned fields.
348
357
 
349
358
  ---
350
359
 
351
- # References — FK Target Mapping
352
-
353
- When FK columns don't match the target table name by convention (e.g., `vendorId` points to the `contact` table), declare explicit references:
354
-
355
- ```typescript
356
- export default defineTable(items, {
357
- references: {
358
- clientId: "contact",
359
- vendorId: "contact",
360
- salesCodeId: "salesCode",
361
- taxLocationId: "taxLocation",
362
- },
363
- // ...
364
- });
365
- ```
366
-
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
- ---
372
-
373
- # Input Hints — CMS Form Controls
374
-
375
- Control how the CMS renders form inputs for specific columns:
376
-
377
- ```typescript
378
- export default defineTable(invoice, {
379
- inputHints: {
380
- status: "select",
381
- sortOrder: "radio",
382
- isPartialPaymentDisabled: "checkbox",
383
- headerMessage: "textarea",
384
- footerMessage: "textarea",
385
- },
386
- // ...
387
- });
388
- ```
389
-
390
- Available values: `select`, `multi-select`, `radio`, `checkbox`, `textarea`, `lookup`, `hidden`, `color`, `date`, `datetime`, `time`, `currency`.
391
-
392
- Input hints are emitted in schema-registry.json as `inputHints` on the table metadata.
393
-
394
- ---
395
-
396
360
  # Validation
397
361
 
398
362
  Field-level validation rules compiled into the API:
399
363
 
400
364
  ```typescript
401
- export default defineTable(jobs, {
365
+ export default defineTable(rooms, {
402
366
  // ... other config
403
367
 
404
368
  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 },
369
+ name: { minLength: 1, maxLength: 100 },
370
+ capacity: { min: 1, max: 1000 },
371
+ roomType: { enum: ['meeting', 'conference', 'breakout'] },
372
+ email: { email: true },
373
+ website: { url: true },
374
+ code: { pattern: '^[A-Z]{3}$' },
410
375
  },
411
376
  });
412
377
  ```
@@ -418,54 +383,51 @@ export default defineTable(jobs, {
418
383
  Actions are custom API endpoints for business logic beyond CRUD. Defined in a separate `actions.ts` file using `defineActions()`.
419
384
 
420
385
  ```typescript
421
- // quickback/features/applications/actions.ts
422
- import { applications } from './applications';
386
+ // quickback/features/todos/actions.ts
387
+ import { todos } from './todos';
423
388
  import { defineActions } from '@quickback/compiler';
424
389
  import { z } from 'zod';
425
390
 
426
- export default defineActions(applications, {
427
- 'advance-stage': {
428
- description: "Move application to the next pipeline stage",
391
+ export default defineActions(todos, {
392
+ complete: {
393
+ description: "Mark todo as complete",
429
394
  input: z.object({
430
- stage: z.enum(["screening", "interview", "offer", "hired"]),
431
- notes: z.string().optional(),
395
+ completedAt: z.string().datetime().optional(),
432
396
  }),
433
- access: {
434
- roles: ["owner", "hiring-manager"],
435
- record: { stage: { notEquals: "rejected" } },
397
+ guard: {
398
+ roles: ["member", "admin"],
399
+ record: { completed: { equals: false } },
436
400
  },
437
401
  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;
402
+ // Inline handler
403
+ await db.update(todos).set({ completed: true }).where(eq(todos.id, record.id));
404
+ return { success: true };
443
405
  },
444
406
  sideEffects: "sync",
445
407
  },
446
408
 
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
409
+ archive: {
410
+ description: "Archive a todo",
411
+ input: z.object({}),
412
+ guard: { roles: ["admin"] },
413
+ handler: "./handlers/archive", // OR: external file handler
452
414
  },
453
415
  });
454
416
  ```
455
417
 
456
- **Generated Route**: `POST /api/v1/applications/:id/advance-stage`
418
+ **Generated Route**: `POST /api/v1/todos/:id/complete`
457
419
 
458
420
  ### Record-based vs Standalone Actions
459
421
 
460
422
  **Record-based** (default) — operates on a specific record via `:id`:
461
423
  ```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",
424
+ approve: {
425
+ description: "Approve an invoice",
426
+ input: z.object({ notes: z.string().optional() }),
427
+ guard: { roles: ["admin"] },
428
+ handler: "./handlers/approve",
467
429
  }
468
- // → POST /api/v1/applications/:id/advance-stage
430
+ // → POST /api/v1/invoices/:id/approve
469
431
  ```
470
432
 
471
433
  **Standalone** — custom endpoint not tied to a record:
@@ -476,10 +438,10 @@ chat: {
476
438
  method: "POST",
477
439
  responseType: "stream",
478
440
  input: z.object({ message: z.string() }),
479
- access: { roles: ["recruiter", "hiring-manager"] },
441
+ guard: { roles: ["member"] },
480
442
  handler: "./handlers/chat",
481
443
  }
482
- // → POST /api/v1/applications/chat
444
+ // → POST /api/v1/todos/chat
483
445
  ```
484
446
 
485
447
  ### Action Options
@@ -583,7 +545,7 @@ OR'd LIKE across all `text()` schema columns (system columns excluded). Combine
583
545
 
584
546
  ```json
585
547
  {
586
- "data": [{ "id": "...", "name": "Jane Smith", "source": "linkedin" }],
548
+ "data": [{ "id": "...", "title": "Todo 1" }],
587
549
  "pagination": {
588
550
  "limit": 10,
589
551
  "offset": 0,
@@ -766,15 +728,16 @@ Detect from `quickback.config.ts` and use the correct imports:
766
728
 
767
729
  Full documentation at https://docs.quickback.dev
768
730
 
769
- - [Getting Started](https://docs.quickback.dev/compiler/getting-started)
770
- - [Concepts](https://docs.quickback.dev/compiler/definitions/concepts)
771
- - [Full Example](https://docs.quickback.dev/compiler/getting-started/full-example)
772
- - [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
- - [Firewall](https://docs.quickback.dev/compiler/definitions/firewall)
777
- - [Access](https://docs.quickback.dev/compiler/definitions/access)
778
- - [Guards](https://docs.quickback.dev/compiler/definitions/guards)
779
- - [Masking](https://docs.quickback.dev/compiler/definitions/masking)
780
- - [CLI Reference](https://docs.quickback.dev/compiler/cloud-compiler/cli)
731
+ - [Quick Start](https://docs.quickback.dev/definitions/quick-start)
732
+ - [Concepts](https://docs.quickback.dev/definitions/concepts)
733
+ - [Database Schema](https://docs.quickback.dev/definitions/database-schema)
734
+ - [CRUD Endpoints](https://docs.quickback.dev/definitions/crud-endpoints)
735
+ - [Views](https://docs.quickback.dev/definitions/views)
736
+ - [Actions](https://docs.quickback.dev/definitions/actions)
737
+ - [Firewall](https://docs.quickback.dev/definitions/firewall)
738
+ - [Access](https://docs.quickback.dev/definitions/access)
739
+ - [Guards](https://docs.quickback.dev/definitions/guards)
740
+ - [Masking](https://docs.quickback.dev/definitions/masking)
741
+ - [CLI Reference](https://docs.quickback.dev/compiler/cli)
742
+ - [Cloudflare Stack](https://docs.quickback.dev/stack/cloudflare)
743
+ - [Quick Reference](https://docs.quickback.dev/stack/reference)
@@ -44,6 +44,11 @@ Generate files in `quickback/features/{name}/`:
44
44
  - `actions.ts` - Custom actions via `defineActions()` with Zod schemas (if needed)
45
45
  - `handlers/` - Action handler files (if needed)
46
46
 
47
+ When explaining compile outputs:
48
+ - Runtime outputs remain in `build.outputDir`.
49
+ - Drizzle and migration state artifacts should live in `quickback/drizzle/...` when a `quickback/` folder exists.
50
+ - Security contract reports should live in `quickback/reports/...` when a `quickback/` folder exists.
51
+
47
52
  Detect the database dialect from `quickback.config.ts`:
48
53
  - Cloudflare D1 / SQLite: Use `sqliteTable`, `text`, `integer` from `drizzle-orm/sqlite-core`
49
54
  - Supabase / PostgreSQL: Use `pgTable`, `text`, `boolean`, `timestamp` from `drizzle-orm/pg-core`
@@ -51,37 +56,35 @@ Detect the database dialect from `quickback.config.ts`:
51
56
  ### Table Definition Pattern
52
57
 
53
58
  ```typescript
54
- import { sqliteTable, text } from "drizzle-orm/sqlite-core";
59
+ import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
55
60
  import { defineTable } from "@quickback/compiler";
56
61
 
57
- export const candidates = sqliteTable("candidates", {
58
- id: text("id").primaryKey(),
62
+ export const todos = sqliteTable("todos", {
63
+ id: integer("id").primaryKey(),
64
+ title: text("title").notNull(),
65
+ completed: integer("completed", { mode: "boolean" }).default(false),
66
+ userId: text("user_id").notNull(),
59
67
  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
68
  });
66
69
 
67
- export default defineTable(candidates, {
70
+ export default defineTable(todos, {
68
71
  firewall: {
69
- organization: {},
72
+ organization: {}, // Auto-detects 'organizationId' column
73
+ owner: {}, // Auto-detects 'userId' column
70
74
  },
71
75
  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" },
76
+ list: { access: { roles: ["member", "admin"] } },
77
+ get: { access: { roles: ["member", "admin"] } },
78
+ create: { access: { roles: ["member", "admin"] } },
79
+ update: { access: { roles: ["admin"] } },
80
+ delete: { access: { roles: ["admin"] }, mode: "soft" },
77
81
  },
78
82
  guards: {
79
- createable: ["name", "email", "phone", "resumeUrl", "source"],
80
- updatable: ["name", "phone"],
83
+ createable: ["title", "completed"],
84
+ updatable: ["title", "completed"],
81
85
  },
82
86
  masking: {
83
- email: { type: "email", show: { roles: ["hiring-manager", "recruiter"] } },
84
- phone: { type: "phone", show: { roles: ["hiring-manager", "recruiter"] } },
87
+ userId: { type: "redact", show: { roles: ["admin"] } },
85
88
  },
86
89
  });
87
90
  ```
@@ -89,28 +92,24 @@ export default defineTable(candidates, {
89
92
  ### Actions Pattern
90
93
 
91
94
  ```typescript
92
- // quickback/features/applications/actions.ts
93
- import { applications } from './applications';
95
+ // quickback/features/todos/actions.ts
96
+ import { todos } from './todos';
94
97
  import { defineActions } from '@quickback/compiler';
95
98
  import { z } from 'zod';
96
99
 
97
- export default defineActions(applications, {
98
- 'advance-stage': {
99
- description: "Move application to the next pipeline stage",
100
+ export default defineActions(todos, {
101
+ complete: {
102
+ description: "Mark todo as complete",
100
103
  input: z.object({
101
- stage: z.enum(["screening", "interview", "offer", "hired"]),
102
- notes: z.string().optional(),
104
+ completedAt: z.string().datetime().optional(),
103
105
  }),
104
- access: {
105
- roles: ["owner", "hiring-manager"],
106
- record: { stage: { notEquals: "rejected" } },
106
+ guard: {
107
+ roles: ["member", "admin"],
108
+ record: { completed: { equals: false } },
107
109
  },
108
110
  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;
111
+ await db.update(todos).set({ completed: true }).where(eq(todos.id, record.id));
112
+ return { success: true };
114
113
  },
115
114
  },
116
115
  });
@@ -143,29 +142,29 @@ firewall: {
143
142
  ### Workflow with protected status
144
143
  ```typescript
145
144
  guards: {
146
- protected: { stage: ['advance-stage', 'reject'] }
145
+ protected: { status: ['approve', 'reject'] }
147
146
  }
148
- // Plus defineActions() for advance-stage/reject
147
+ // Plus defineActions() for approve/reject
149
148
  ```
150
149
 
151
150
  ### PII masking
152
151
  ```typescript
153
152
  masking: {
154
- email: { type: 'email', show: { roles: ['hiring-manager', 'recruiter'] } },
155
- phone: { type: 'phone', show: { roles: ['hiring-manager', 'recruiter'] } },
153
+ email: { type: 'email', show: { roles: ['admin'] } },
154
+ ssn: { type: 'ssn', show: { roles: ['hr'] } }
156
155
  }
157
156
  ```
158
157
 
159
158
  ### Views (column-level security)
160
159
  ```typescript
161
160
  views: {
162
- pipeline: {
163
- fields: ['id', 'name', 'source', 'stage'],
164
- access: { roles: ['owner', 'hiring-manager', 'recruiter', 'interviewer'] },
161
+ summary: {
162
+ fields: ['id', 'name', 'email'],
163
+ access: { roles: ['member', 'admin'] },
165
164
  },
166
165
  full: {
167
- fields: ['id', 'name', 'email', 'phone', 'resumeUrl', 'source', 'stage'],
168
- access: { roles: ['owner', 'hiring-manager', 'recruiter'] },
166
+ fields: ['id', 'name', 'email', 'phone', 'ssn'],
167
+ access: { roles: ['admin'] },
169
168
  },
170
169
  }
171
170
  ```
@@ -179,7 +178,7 @@ chat: {
179
178
  method: "POST",
180
179
  responseType: "stream",
181
180
  input: z.object({ message: z.string() }),
182
- access: { roles: ["recruiter", "hiring-manager"] },
181
+ guard: { roles: ["member"] },
183
182
  handler: "./handlers/chat",
184
183
  }
185
184
  ```