@everystack/mcp 0.3.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adding-database.md +36 -23
- package/dist/cli.md +44 -3
- package/dist/core.md +19 -1
- package/dist/database-operations.md +236 -0
- package/dist/derived-objects.md +225 -0
- package/dist/gates/detectors/embedded-data-bundle.d.ts +13 -0
- package/dist/gates/detectors/embedded-data-bundle.d.ts.map +1 -0
- package/dist/gates/detectors/embedded-data-bundle.js +56 -0
- package/dist/gates/detectors/hand-written-migration.d.ts +24 -0
- package/dist/gates/detectors/hand-written-migration.d.ts.map +1 -0
- package/dist/gates/detectors/hand-written-migration.js +54 -0
- package/dist/gates/detectors/secret-in-public-env.d.ts +12 -0
- package/dist/gates/detectors/secret-in-public-env.d.ts.map +1 -0
- package/dist/gates/detectors/secret-in-public-env.js +38 -0
- package/dist/gates/engine.d.ts +28 -0
- package/dist/gates/engine.d.ts.map +1 -0
- package/dist/gates/engine.js +74 -0
- package/dist/gates/registry.d.ts +14 -0
- package/dist/gates/registry.d.ts.map +1 -0
- package/dist/gates/registry.js +21 -0
- package/dist/gates/telemetry.d.ts +47 -0
- package/dist/gates/telemetry.d.ts.map +1 -0
- package/dist/gates/telemetry.js +121 -0
- package/dist/gates/types.d.ts +67 -0
- package/dist/gates/types.d.ts.map +1 -0
- package/dist/gates/types.js +14 -0
- package/dist/governance/cli.d.ts +57 -0
- package/dist/governance/cli.d.ts.map +1 -0
- package/dist/governance/cli.js +169 -0
- package/dist/governance/grounding.d.ts +78 -0
- package/dist/governance/grounding.d.ts.map +1 -0
- package/dist/governance/grounding.js +299 -0
- package/dist/index.cjs +119 -107
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +94 -0
- package/dist/project-claude-md.md +35 -18
- package/dist/prompts/add-feature.d.ts +3 -0
- package/dist/prompts/add-feature.d.ts.map +1 -0
- package/dist/prompts/add-feature.js +154 -0
- package/dist/prompts/claude-md.d.ts +12 -0
- package/dist/prompts/claude-md.d.ts.map +1 -0
- package/dist/prompts/claude-md.js +87 -0
- package/dist/prompts/debug.d.ts +3 -0
- package/dist/prompts/debug.d.ts.map +1 -0
- package/dist/prompts/debug.js +129 -0
- package/dist/prompts/deploy.d.ts +3 -0
- package/dist/prompts/deploy.d.ts.map +1 -0
- package/dist/prompts/deploy.js +118 -0
- package/dist/prompts/design-schema.d.ts +3 -0
- package/dist/prompts/design-schema.d.ts.map +1 -0
- package/dist/prompts/design-schema.js +97 -0
- package/dist/prompts/governance-setup.d.ts +9 -0
- package/dist/prompts/governance-setup.d.ts.map +1 -0
- package/dist/prompts/governance-setup.js +76 -0
- package/dist/prompts/index.d.ts +3 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +20 -0
- package/dist/prompts/new-app.d.ts +3 -0
- package/dist/prompts/new-app.d.ts.map +1 -0
- package/dist/prompts/new-app.js +203 -0
- package/dist/prompts/runbook.d.ts +12 -0
- package/dist/prompts/runbook.d.ts.map +1 -0
- package/dist/prompts/runbook.js +70 -0
- package/dist/prompts/secure.d.ts +3 -0
- package/dist/prompts/secure.d.ts.map +1 -0
- package/dist/prompts/secure.js +219 -0
- package/dist/resources/index.d.ts +12 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +182 -0
- package/dist/schema-patterns.md +92 -106
- package/dist/tools/check-environment.d.ts +25 -0
- package/dist/tools/check-environment.d.ts.map +1 -0
- package/dist/tools/check-environment.js +281 -0
- package/dist/tools/index.d.ts +3 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +18 -0
- package/dist/tools/project-status.d.ts +28 -0
- package/dist/tools/project-status.d.ts.map +1 -0
- package/dist/tools/project-status.js +138 -0
- package/dist/tools/project-validate.d.ts +19 -0
- package/dist/tools/project-validate.d.ts.map +1 -0
- package/dist/tools/project-validate.js +323 -0
- package/dist/tools/schema-analyze.d.ts +46 -0
- package/dist/tools/schema-analyze.d.ts.map +1 -0
- package/dist/tools/schema-analyze.js +336 -0
- package/package.json +3 -3
- package/src/gates/detectors/hand-written-migration.ts +29 -13
- package/src/index.ts +1 -1
- package/src/prompts/add-feature.ts +4 -4
- package/src/prompts/claude-md.ts +4 -2
- package/src/prompts/debug.ts +3 -4
- package/src/prompts/deploy.ts +17 -8
- package/src/prompts/design-schema.ts +45 -59
- package/src/prompts/new-app.ts +21 -19
- package/src/prompts/secure.ts +3 -3
- package/src/resources/adding-database.md +36 -23
- package/src/resources/cli.md +44 -3
- package/src/resources/core.md +19 -1
- package/src/resources/database-operations.md +236 -0
- package/src/resources/derived-objects.md +225 -0
- package/src/resources/index.ts +15 -1
- package/src/resources/project-claude-md.md +35 -18
- package/src/resources/schema-patterns.md +92 -106
|
@@ -4,10 +4,10 @@ import { z } from 'zod';
|
|
|
4
4
|
export function registerDesignSchemaPrompt(server: McpServer): void {
|
|
5
5
|
server.prompt(
|
|
6
6
|
'design-schema',
|
|
7
|
-
'Interactive schema design: plain English description →
|
|
7
|
+
'Interactive schema design (0.4.0): plain English description → declared Models (defineModel + can abilities) + derived descriptors + testing checklist. Authz and handler config are DERIVED from the Models, never hand-written.',
|
|
8
8
|
{
|
|
9
9
|
description: z.string().describe('Plain English description of the data model (e.g., "blog with posts, comments, and tags")'),
|
|
10
|
-
projectPath: z.string().optional().describe('Absolute path to project root (to
|
|
10
|
+
projectPath: z.string().optional().describe('Absolute path to project root (to read the existing db/models/)'),
|
|
11
11
|
},
|
|
12
12
|
async ({ description, projectPath }) => {
|
|
13
13
|
return {
|
|
@@ -19,81 +19,67 @@ export function registerDesignSchemaPrompt(server: McpServer): void {
|
|
|
19
19
|
text: [
|
|
20
20
|
`Design a database schema for: ${description}`,
|
|
21
21
|
'',
|
|
22
|
+
'IMPORTANT (0.4.0): you declare the schema, you do NOT hand-write it. Tables are',
|
|
23
|
+
'`defineModel` in `db/models/`; authorization is `can()` abilities on the Model that',
|
|
24
|
+
'COMPILE to RLS + grants; the handler config is DERIVED from the Models. Never hand-write',
|
|
25
|
+
'`db/schema.ts`, a SQL migration, `CREATE POLICY`, or `GRANT` — those are generated.',
|
|
26
|
+
'',
|
|
22
27
|
'## Instructions',
|
|
23
28
|
'',
|
|
24
|
-
'1. Read everystack://schema-patterns for
|
|
25
|
-
'2. Read everystack://
|
|
26
|
-
'3. Read everystack://
|
|
27
|
-
|
|
29
|
+
'1. Read everystack://schema-patterns for how to declare TABLES (defineModel, field, can, relations).',
|
|
30
|
+
'2. Read everystack://derived-objects IF the model needs views, materialized views, functions, or triggers.',
|
|
31
|
+
'3. Read everystack://security for the authorization model (how can() abilities become RLS + grants).',
|
|
32
|
+
'4. Read everystack://database-operations for how the declaration reaches a database (db:sync on dev).',
|
|
33
|
+
projectPath ? `5. Read the existing \`db/models/\` under "${projectPath}" to match its conventions before adding to it.` : '',
|
|
28
34
|
'',
|
|
29
35
|
'## Deliverables',
|
|
30
36
|
'',
|
|
31
37
|
'Generate ALL of the following:',
|
|
32
38
|
'',
|
|
33
|
-
'### 1.
|
|
34
|
-
'',
|
|
35
|
-
'Follow these conventions:',
|
|
36
|
-
'- UUID primary keys: `uuid(\'id\').primaryKey().defaultRandom()`',
|
|
37
|
-
'- Timestamps: `timestamp(\'created_at\', { withTimezone: true }).defaultNow().notNull()`',
|
|
38
|
-
'- Soft delete columns: `deletedAt` + `deletedBy` on user-facing tables',
|
|
39
|
-
'- Foreign keys with `.references(() => table.column)`',
|
|
40
|
-
'- Export all tables as named exports',
|
|
41
|
-
'- Add Drizzle `relations()` for SSR query building and API embedding',
|
|
42
|
-
'',
|
|
43
|
-
'### 2. SQL Migration with RLS',
|
|
44
|
-
'',
|
|
45
|
-
'Generate a custom SQL migration that includes:',
|
|
39
|
+
'### 1. Models (db/models/<table>.ts — one file per table)',
|
|
46
40
|
'',
|
|
47
|
-
'
|
|
48
|
-
'
|
|
49
|
-
'
|
|
41
|
+
'Declare each table with `defineModel`, following these conventions:',
|
|
42
|
+
'- UUID primary keys: `id: field.uuid().primaryKey().defaultRandom()`',
|
|
43
|
+
'- Timestamps: `createdAt: field.timestamptz().defaultNow().notNull()`',
|
|
44
|
+
'- Soft delete: a `deletedAt: field.timestamptz()` field opts the table into soft-delete',
|
|
45
|
+
'- Foreign keys via relations: `field.uuid().references(() => Author)` / `belongsTo`/`hasMany`',
|
|
46
|
+
'- Sensitive columns: `.private()` (hidden from the API); write-guarded: `.readonly()`',
|
|
47
|
+
'- Named exports (PascalCase model var, e.g. `export const Post = defineModel(\'posts\', …)`)',
|
|
50
48
|
'',
|
|
51
|
-
'
|
|
52
|
-
'GRANT SELECT ON table_name TO anon;',
|
|
53
|
-
'GRANT SELECT, INSERT, UPDATE, DELETE ON table_name TO authenticated;',
|
|
54
|
-
'GRANT ALL ON table_name TO admin;',
|
|
49
|
+
'### 2. Authorization — `can()` abilities ON each Model (NOT hand-written RLS)',
|
|
55
50
|
'',
|
|
56
|
-
'
|
|
57
|
-
'
|
|
58
|
-
'CREATE POLICY "anon_select" ON table_name FOR SELECT TO anon USING (deleted_at IS NULL);',
|
|
51
|
+
'Declare the access pattern as abilities; the compiler emits the RLS policies and GRANTs.',
|
|
52
|
+
'Every table MUST make its read decision or `db:check` fails it:',
|
|
59
53
|
'',
|
|
60
|
-
'
|
|
61
|
-
'
|
|
62
|
-
|
|
63
|
-
'',
|
|
64
|
-
'
|
|
65
|
-
'
|
|
54
|
+
'```ts',
|
|
55
|
+
'abilities: [',
|
|
56
|
+
" can('read'), // public read (anon + authenticated)",
|
|
57
|
+
" can('read', { owner: 'authorId' }), // rows the caller owns",
|
|
58
|
+
" can('manage', { owner: 'authorId' }), // owner can write their own rows",
|
|
59
|
+
" can('read', { role: 'admin' }), // a specific role only",
|
|
60
|
+
'],',
|
|
66
61
|
'```',
|
|
67
62
|
'',
|
|
68
|
-
'
|
|
63
|
+
'A private/operational table declares `private: true` (generated, but not a generic-API',
|
|
64
|
+
'resource). Row ownership, soft-delete, hidden/protected columns, and relations are all',
|
|
65
|
+
'DERIVED from the Model into the handler config — do not write a createHandler options blob',
|
|
66
|
+
'by hand.',
|
|
69
67
|
'',
|
|
70
|
-
'### 3.
|
|
68
|
+
'### 3. Derived objects (only if the model needs compute)',
|
|
71
69
|
'',
|
|
72
|
-
'
|
|
73
|
-
'
|
|
74
|
-
'
|
|
75
|
-
'- `rowOwnership`: for user-scoped tables',
|
|
76
|
-
'- `softDelete`: for tables with deletedAt columns',
|
|
77
|
-
'- `protectedFields`: fields users cannot set directly (role, deletedAt)',
|
|
78
|
-
'- `hiddenColumns`: sensitive columns not returned in API responses',
|
|
70
|
+
'If the design needs a view, materialized view, function, or trigger, declare it as a',
|
|
71
|
+
'descriptor in `db/models/derived.ts` per everystack://derived-objects — NOT as a SQL',
|
|
72
|
+
'migration. Wire them on `defineModule({ models, derived })`.',
|
|
79
73
|
'',
|
|
80
|
-
'### 4. Testing
|
|
74
|
+
'### 4. Testing + apply checklist',
|
|
81
75
|
'',
|
|
82
|
-
'
|
|
83
|
-
'- [ ] Anonymous users can read
|
|
84
|
-
'- [ ]
|
|
85
|
-
'- [ ] Authenticated users can only read/write their own data',
|
|
76
|
+
'- [ ] Every table declares a read ability or `private: true` (db:check gate)',
|
|
77
|
+
'- [ ] Anonymous users can read only what `can(\'read\')` (no owner/role) allows',
|
|
78
|
+
'- [ ] Owner-scoped rows are invisible and unwritable across users (IDOR)',
|
|
86
79
|
'- [ ] Soft-deleted rows are hidden from normal queries',
|
|
87
|
-
'- [ ]
|
|
88
|
-
'- [ ]
|
|
89
|
-
'- [ ]
|
|
90
|
-
'',
|
|
91
|
-
'Test each RLS policy with:',
|
|
92
|
-
'```sql',
|
|
93
|
-
'SET LOCAL ROLE authenticated;',
|
|
94
|
-
"SELECT set_config('request.jwt.claims', '{\"sub\": \"user-uuid\", \"role\": \"authenticated\"}', true);",
|
|
95
|
-
'SELECT * FROM table_name; -- should only return own rows',
|
|
96
|
-
'```',
|
|
80
|
+
'- [ ] `everystack db:sync --database-url "$DATABASE_URL"` applies cleanly on a dev DB',
|
|
81
|
+
'- [ ] `everystack db:check` passes (declared state composes; generated artifacts match)',
|
|
82
|
+
'- [ ] `everystack db:authz:test --stage dev` proves the compiled RLS enforces the abilities',
|
|
97
83
|
].filter(Boolean).join('\n'),
|
|
98
84
|
},
|
|
99
85
|
},
|
package/src/prompts/new-app.ts
CHANGED
|
@@ -106,7 +106,7 @@ export function registerNewAppPrompt(server: McpServer): void {
|
|
|
106
106
|
'```',
|
|
107
107
|
`${effectiveName}/`,
|
|
108
108
|
'├── app/ # Expo Router pages',
|
|
109
|
-
effectiveTier !== 'V1' ? '├── db/ #
|
|
109
|
+
effectiveTier !== 'V1' ? '├── db/ # models/ (declared schema), backfills/, seed' : '',
|
|
110
110
|
'├── server/ # Lambda handlers',
|
|
111
111
|
effectiveTier !== 'V1' ? '│ └── api.ts # PostgREST handler' : '',
|
|
112
112
|
effectiveTier === 'V3' ? '│ ├── worker.ts # SQS worker handler' : '',
|
|
@@ -117,27 +117,29 @@ export function registerNewAppPrompt(server: McpServer): void {
|
|
|
117
117
|
'```',
|
|
118
118
|
'',
|
|
119
119
|
effectiveTier !== 'V1' ? [
|
|
120
|
-
'### 3. Database Schema',
|
|
121
|
-
`
|
|
120
|
+
'### 3. Database Schema — declared Models (0.4.0)',
|
|
121
|
+
`Declare tables for the ${description} as \`defineModel\` in \`db/models/\` (one file per table).`,
|
|
122
|
+
'Do NOT hand-write db/schema.ts or run drizzle-kit — the schema is DECLARED, then compiled.',
|
|
122
123
|
'Follow the patterns from everystack://schema-patterns:',
|
|
123
|
-
'-
|
|
124
|
-
'-
|
|
125
|
-
'-
|
|
126
|
-
'-
|
|
124
|
+
'- `field.uuid().primaryKey().defaultRandom()`; `field.timestamptz().defaultNow().notNull()`',
|
|
125
|
+
'- Foreign keys via `.references(() => Model)` / relations for SSR + API embedding',
|
|
126
|
+
'- Authorization as `can()` abilities ON the Model (compiles to RLS + grants — never hand-written)',
|
|
127
|
+
'- Views/matviews/functions/triggers: descriptors in db/models/derived.ts (everystack://derived-objects)',
|
|
128
|
+
'- Compose in db/models/index.ts: `defineModule({ models, derived })`',
|
|
127
129
|
'',
|
|
128
|
-
'### 4.
|
|
129
|
-
'-
|
|
130
|
-
'-
|
|
131
|
-
'-
|
|
130
|
+
'### 4. Apply the schema',
|
|
131
|
+
'- Dev database: `everystack db:sync --database-url "$DATABASE_URL"` (state + authz + compute, one verb)',
|
|
132
|
+
'- CI gate: `everystack db:check`',
|
|
133
|
+
'- Protected stages: `db:plan` → `db:apply` (everystack://database-operations)',
|
|
134
|
+
'- No hand-written migration, no CREATE POLICY, no GRANT — all generated from the Models',
|
|
132
135
|
'',
|
|
133
136
|
'### 5. Handler Configuration',
|
|
134
137
|
'Create server/api.ts using createPluginLambdaHandler or createLambdaHandler.',
|
|
135
|
-
'
|
|
138
|
+
'The per-table access config (exposedTables, rowOwnership, softDelete, hidden/protected columns,',
|
|
139
|
+
'relations) is DERIVED from your Models via `deriveHandlerConfig(models)` — do not hand-maintain it.',
|
|
140
|
+
'Set only the app-level options by hand:',
|
|
136
141
|
'- auth.verifyToken for JWT verification',
|
|
137
142
|
'- pgSettings for RLS context injection',
|
|
138
|
-
'- exposedTables to limit API surface',
|
|
139
|
-
'- rowOwnership for user-scoped mutation control',
|
|
140
|
-
'- softDelete for reversible deletes',
|
|
141
143
|
'',
|
|
142
144
|
'### 6. Auth Setup',
|
|
143
145
|
'Read everystack://auth for the full auth flow.',
|
|
@@ -148,7 +150,7 @@ export function registerNewAppPrompt(server: McpServer): void {
|
|
|
148
150
|
].join('\n') : '',
|
|
149
151
|
'## Validation',
|
|
150
152
|
'',
|
|
151
|
-
'After scaffolding, run
|
|
153
|
+
'After scaffolding, run `check_environment` to confirm prerequisites, and `everystack db:check` to confirm the declared schema composes.',
|
|
152
154
|
'',
|
|
153
155
|
'## Run Locally',
|
|
154
156
|
'',
|
|
@@ -200,10 +202,10 @@ export function registerNewAppPrompt(server: McpServer): void {
|
|
|
200
202
|
effectiveTier === 'V3' ? '- S3 bucket for file uploads' : '',
|
|
201
203
|
'',
|
|
202
204
|
'### Deploy',
|
|
203
|
-
'Read everystack://deployment for the full walkthrough.',
|
|
205
|
+
'Read everystack://deployment and everystack://database-operations for the full walkthrough.',
|
|
204
206
|
'1. `pnpm sst deploy --stage dev`',
|
|
205
|
-
effectiveTier !== 'V1' ? '2. `everystack db:
|
|
206
|
-
effectiveTier !== 'V1' ? '3. `everystack db:seed` (dev only)' : '',
|
|
207
|
+
effectiveTier !== 'V1' ? '2. `everystack db:plan --stage dev --out dev.plan.json` → review → `everystack db:apply --plan dev.plan.json --stage dev`' : '',
|
|
208
|
+
effectiveTier !== 'V1' ? '3. `everystack db:seed --stage dev` (dev only)' : '',
|
|
207
209
|
].filter(Boolean).join('\n'),
|
|
208
210
|
},
|
|
209
211
|
},
|
package/src/prompts/secure.ts
CHANGED
|
@@ -29,8 +29,8 @@ export function registerSecurePrompt(server: McpServer): void {
|
|
|
29
29
|
'',
|
|
30
30
|
'1. Read everystack://security for the complete security model.',
|
|
31
31
|
'2. Read everystack://auth for JWT authentication details.',
|
|
32
|
-
projectPath ? `3.
|
|
33
|
-
projectPath ?
|
|
32
|
+
projectPath ? `3. Read the project's \`db/models/\` under "${projectPath}" — the \`can()\` abilities ARE the authorization; confirm every table declares a read decision.` : '',
|
|
33
|
+
projectPath ? '4. Run the real security tooling: `everystack db:doctor` (least-privilege + RLS posture), `everystack db:authz:test --stage dev` (the compiled RLS enforces the abilities), and `everystack security:audit`.' : '',
|
|
34
34
|
'',
|
|
35
35
|
requested.includes('aws') ? [
|
|
36
36
|
'## AWS IAM Profiles',
|
|
@@ -215,7 +215,7 @@ export function registerSecurePrompt(server: McpServer): void {
|
|
|
215
215
|
'',
|
|
216
216
|
'After setup, verify security:',
|
|
217
217
|
'',
|
|
218
|
-
'1. Run
|
|
218
|
+
'1. Run `everystack db:doctor` and `everystack db:authz:test --stage dev` to prove the RLS enforces the declared abilities',
|
|
219
219
|
'2. Test unauthenticated access returns 401',
|
|
220
220
|
'3. Test cross-user data isolation with RLS',
|
|
221
221
|
'4. Verify JWT claims propagate through pgSettings',
|
|
@@ -13,7 +13,7 @@ You already have a running Expo app. Now you're adding:
|
|
|
13
13
|
- **@everystack/logging** — structured logging so you can see what your app is doing.
|
|
14
14
|
- **@everystack/security** — device attestation and biometric auth.
|
|
15
15
|
- **@everystack/query** — React hooks that make it easy to fetch and display data.
|
|
16
|
-
- **
|
|
16
|
+
- **@everystack/model** — declares your database tables in TypeScript with `defineModel`. You describe what data you want to store and who can read/write it, and everystack generates the migration and the typed schema for you.
|
|
17
17
|
|
|
18
18
|
## Step 1: Install PostgreSQL
|
|
19
19
|
|
|
@@ -64,24 +64,31 @@ You should see a table with the value `1`. If so, your database is ready.
|
|
|
64
64
|
From your project directory:
|
|
65
65
|
|
|
66
66
|
```bash
|
|
67
|
-
pnpm add @everystack/api @everystack/auth @everystack/admin @everystack/logging @everystack/security @everystack/query
|
|
67
|
+
pnpm add @everystack/api @everystack/auth @everystack/admin @everystack/logging @everystack/security @everystack/query @everystack/model
|
|
68
68
|
pnpm add drizzle-orm
|
|
69
|
-
pnpm add -D drizzle-kit
|
|
70
69
|
```
|
|
71
70
|
|
|
72
|
-
## Step 4:
|
|
71
|
+
## Step 4: Declare your database schema
|
|
73
72
|
|
|
74
|
-
The schema defines what data your app stores. Create
|
|
73
|
+
The schema defines what data your app stores. Create your tables in `db/models/` — one
|
|
74
|
+
`defineModel` per table (for example `db/models/post.ts`), composed onto a `defineModule`
|
|
75
|
+
in `db/models/index.ts`.
|
|
75
76
|
|
|
76
|
-
A
|
|
77
|
+
A model is like designing a spreadsheet before you start filling in data. You decide what columns each table has, what type of data goes in each column, and how tables relate to each other — plus who can read and write each table.
|
|
77
78
|
|
|
78
|
-
|
|
79
|
+
You do **not** hand-write `db/schema.ts` and you do **not** run `drizzle-kit generate` —
|
|
80
|
+
everystack generates the migration and the typed artifact from your Models.
|
|
79
81
|
|
|
80
|
-
-
|
|
81
|
-
|
|
82
|
-
-
|
|
83
|
-
-
|
|
84
|
-
-
|
|
82
|
+
Read everystack://schema-patterns for the `defineModel` patterns and examples. Key conventions:
|
|
83
|
+
|
|
84
|
+
- UUID primary keys with `field.uuid().primaryKey().defaultRandom()`
|
|
85
|
+
- `createdAt` and `updatedAt` timestamps on all tables
|
|
86
|
+
- Foreign key references with `.references('users', 'id')`
|
|
87
|
+
- Relations declared on the Model (used for both SSR and API query embedding)
|
|
88
|
+
- Authorization declared with `can()` abilities (compiles to grants + RLS)
|
|
89
|
+
|
|
90
|
+
For views, materialized views, functions, and triggers, read everystack://derived-objects
|
|
91
|
+
— they are declared as descriptors and deploy via `db:reconcile`, not migrations.
|
|
85
92
|
|
|
86
93
|
## Step 5: Configure the handler
|
|
87
94
|
|
|
@@ -121,29 +128,35 @@ export async function POST(request: Request) {
|
|
|
121
128
|
// ... PATCH, DELETE
|
|
122
129
|
```
|
|
123
130
|
|
|
124
|
-
## Step 8:
|
|
131
|
+
## Step 8: Move your database to match your Models
|
|
125
132
|
|
|
126
|
-
|
|
133
|
+
`db:sync` makes your local dev database match your checkout — tables, authz, and the
|
|
134
|
+
derived layer — in one command. You never run `drizzle-kit` or write a SQL migration.
|
|
127
135
|
|
|
128
136
|
```bash
|
|
129
|
-
|
|
130
|
-
npx drizzle-kit migrate
|
|
137
|
+
everystack db:sync --database-url "$DATABASE_URL"
|
|
131
138
|
```
|
|
132
139
|
|
|
133
|
-
|
|
140
|
+
This is the dev edit loop: change `db/models/`, run `db:sync`, test, repeat. When you're
|
|
141
|
+
ready to record the change as a migration for protected stages, run `everystack db:generate`
|
|
142
|
+
(and later reach a deployed stage with `db:plan` → `db:apply`).
|
|
143
|
+
|
|
144
|
+
Read everystack://database-operations for the full workflow — the dev loop, importing data,
|
|
145
|
+
and safely migrating a deployed stage.
|
|
134
146
|
|
|
135
147
|
## Step 9: Security
|
|
136
148
|
|
|
137
149
|
**This is not optional.** Read everystack://security for the three-layer security model.
|
|
138
150
|
|
|
139
|
-
Your database needs Row Level Security (RLS)
|
|
151
|
+
Your database needs Row Level Security (RLS) — rules that control who can see and change what data. Even if your app code has a bug, the database enforces access control.
|
|
140
152
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
153
|
+
In everystack you **declare** this on your Models rather than hand-writing SQL: `can()`
|
|
154
|
+
abilities on each `defineModel` compile to database roles (`anon`, `authenticated`,
|
|
155
|
+
`admin`), GRANTs, and RLS policies, and `db:sync` deploys them. `db:check` (the CI gate)
|
|
156
|
+
refuses a table without RLS. Never hand-write `CREATE ROLE`, `GRANT`, or `CREATE POLICY`.
|
|
145
157
|
|
|
146
|
-
The security resource
|
|
158
|
+
The security resource explains the policies your abilities compile to and the patterns
|
|
159
|
+
behind them.
|
|
147
160
|
|
|
148
161
|
## Step 10: Verify
|
|
149
162
|
|
package/src/resources/cli.md
CHANGED
|
@@ -28,11 +28,52 @@ everystack update --channel staging --platform web
|
|
|
28
28
|
Flags: `--channel` (default: production), `--message`, `--platform` (ios/android/web/all), `--skip-export`.
|
|
29
29
|
|
|
30
30
|
### Database
|
|
31
|
+
|
|
32
|
+
You declare tables in `db/models/` (`defineModel`) and derived objects as descriptors;
|
|
33
|
+
these verbs move a database. Full operational guidance: everystack://database-operations.
|
|
34
|
+
|
|
35
|
+
**Schema (declare → deploy)**
|
|
36
|
+
```bash
|
|
37
|
+
everystack db:sync # Make a dev DB match your checkout — state + authz + compute, one verb
|
|
38
|
+
everystack db:generate # STATE layer (tables) → next migration file (--dry-run prints the SQL, writes nothing)
|
|
39
|
+
everystack db:reconcile # Deploy the compute layer only (views/matviews/functions/triggers)
|
|
40
|
+
everystack db:check # CI gate: declared state composes + generated artifacts match regeneration
|
|
41
|
+
everystack db:fingerprint # Content-address the live base schema vs the Models — MATCH/MISMATCH
|
|
42
|
+
everystack db:diff # The state edge between two declared states — no DB, CI-pure
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Safe remote migration (protected stages)**
|
|
46
|
+
```bash
|
|
47
|
+
everystack db:plan --stage X --out X.plan.json # Mint a reviewable edge — read-only, ephemeral
|
|
48
|
+
everystack db:apply --plan X.plan.json --stage X # Verify → apply → verify, credential-free via the ops Lambda
|
|
49
|
+
everystack db:approvers --stage X --set "…" # Declare who may run destructive applies (STS-verified)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Backups & safety**
|
|
53
|
+
```bash
|
|
54
|
+
everystack db:snapshot --stage X # Physical RDS snapshot (instant DR)
|
|
55
|
+
everystack db:snapshots --stage X # List manual RDS snapshots
|
|
56
|
+
everystack db:backup --stage X # Logical pg_dump → private S3 backups bucket
|
|
57
|
+
everystack db:backups --stage X # List logical backups
|
|
58
|
+
everystack db:backup:download <id> --stage X # Presigned download URL (1h)
|
|
59
|
+
everystack db:restore --from <id> --stage X --confirm # Restore a backup INTO a stage (destructive)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Local dev databases**
|
|
63
|
+
```bash
|
|
64
|
+
everystack db:template:refresh # Build the dev template from declared state + seed
|
|
65
|
+
everystack db:branch # Per-git-branch dev DB from the template (--list / --prune)
|
|
66
|
+
everystack db:fork --from-stage src --stage tgt --confirm # Fork a deployed stage's DB into a feature stage
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Data**
|
|
31
70
|
```bash
|
|
32
|
-
everystack db:
|
|
33
|
-
everystack db:
|
|
71
|
+
everystack db:seed --stage dev # Declarative seed script (dev only; refuses on production)
|
|
72
|
+
everystack db:backfill --apply # One-shot data moves from db/backfills/*.sql (own record)
|
|
73
|
+
everystack pipeline:run --stage X # Ingest pipeline (credential-free in the ops Lambda)
|
|
74
|
+
everystack db:migrate # Run the generated migration on a deployed stage via Lambda invoke
|
|
34
75
|
everystack db:psql --stage dev -c "SELECT * FROM posts" # Read-only SQL via Lambda
|
|
35
|
-
everystack console --stage dev
|
|
76
|
+
everystack console --stage dev # Interactive REPL with db + schema
|
|
36
77
|
```
|
|
37
78
|
|
|
38
79
|
The REPL has `db`, `schema`, `eq`, `and`, `or`, `gt`, `lt`, `count`, `sum`, `avg`, `sql`, `desc`, `asc` in scope.
|
package/src/resources/core.md
CHANGED
|
@@ -158,11 +158,24 @@ const { data } = await api.rpc('timeline', { limit: 20 });
|
|
|
158
158
|
|
|
159
159
|
All infrastructure commands use **AWS IAM credentials** (not shared secrets).
|
|
160
160
|
|
|
161
|
+
You declare tables in `db/models/` with `defineModel` and the derived layer as descriptors
|
|
162
|
+
(see everystack://derived-objects); the CLI moves the database — you never run
|
|
163
|
+
`drizzle-kit` or hand-write a migration. Full operational guidance:
|
|
164
|
+
everystack://database-operations.
|
|
165
|
+
|
|
161
166
|
| Command | What it does |
|
|
162
167
|
|---------|-------------|
|
|
163
168
|
| `everystack update --channel production` | OTA deploy (no infrastructure changes) |
|
|
164
|
-
| `everystack db:
|
|
169
|
+
| `everystack db:sync` | Dev DB ← your checkout (state + authz + compute), one verb |
|
|
170
|
+
| `everystack db:generate` | STATE layer (tables) → next migration file |
|
|
171
|
+
| `everystack db:reconcile` | Deploy the compute layer (views/matviews/functions/triggers) |
|
|
172
|
+
| `everystack db:check` | CI gate: declared state composes + artifacts match regeneration |
|
|
173
|
+
| `everystack db:plan --stage X` | Mint a reviewable, fingerprint-pinned edge (read-only) |
|
|
174
|
+
| `everystack db:apply --plan … --stage X` | Verify → apply → verify, credential-free via the ops Lambda |
|
|
175
|
+
| `everystack db:snapshot / db:backup --stage X` | Physical RDS snapshot / logical pg_dump before a risky migration |
|
|
165
176
|
| `everystack db:seed` | Seed database via Lambda invoke (dev only) |
|
|
177
|
+
| `everystack db:backfill --apply` | One-shot data moves from `db/backfills/*.sql` |
|
|
178
|
+
| `everystack db:migrate` | Run the generated migration on a deployed stage via Lambda invoke |
|
|
166
179
|
| `everystack db:psql --stage dev -c "SQL"` | Execute read-only SQL via Lambda |
|
|
167
180
|
| `everystack console --stage dev` | Interactive REPL with db + schema in scope |
|
|
168
181
|
| `everystack logs:errors --stage dev` | Query recent error logs |
|
|
@@ -173,6 +186,11 @@ All infrastructure commands use **AWS IAM credentials** (not shared secrets).
|
|
|
173
186
|
| `everystack diag URL` | Diagnose deployed page freshness |
|
|
174
187
|
| `everystack analyze:ssr` | Static analysis for SSR anti-patterns |
|
|
175
188
|
|
|
189
|
+
On a dev database you `db:sync` freely; a protected stage takes `db:plan` → `db:apply`
|
|
190
|
+
(fingerprint-verified, snapshot + approver gates on destructive plans); `db:check` is the
|
|
191
|
+
per-PR CI gate; `db:reconcile` deploys compute; `db:seed`/`db:backfill` move data;
|
|
192
|
+
`db:snapshot`/`db:backup` are the safety net.
|
|
193
|
+
|
|
176
194
|
## Key Patterns
|
|
177
195
|
|
|
178
196
|
**Schema-agnostic.** The library knows nothing about your tables. You pass your Drizzle schema to `createHandler()`. Your schema, your migrations, your database.
|