@everystack/mcp 0.3.3 → 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/index.cjs +112 -102
- package/dist/project-claude-md.md +15 -12
- package/dist/schema-patterns.md +92 -106
- package/package.json +3 -3
- package/src/gates/detectors/hand-written-migration.ts +12 -5
- package/src/index.ts +1 -1
- package/src/prompts/add-feature.ts +4 -4
- 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 +15 -12
- package/src/resources/schema-patterns.md +92 -106
package/dist/index.cjs
CHANGED
|
@@ -21631,9 +21631,21 @@ var RESOURCES = [
|
|
|
21631
21631
|
{
|
|
21632
21632
|
uri: "everystack://schema-patterns",
|
|
21633
21633
|
name: "Schema Design Patterns",
|
|
21634
|
-
description: "
|
|
21634
|
+
description: "How to declare TABLES (0.4.0): db/models/ with defineModel (field, can, relations, constraints) \u2014 NOT hand-written pgTable or drizzle-kit. Column types, keys, indexes, timestamps, soft delete, UUID vs serial, the private()/readonly()/deprecated() write surface. Read everystack://derived-objects for views/matviews/functions/triggers, and everystack://database-operations for how it reaches a database.",
|
|
21635
21635
|
filename: "schema-patterns.md"
|
|
21636
21636
|
},
|
|
21637
|
+
{
|
|
21638
|
+
uri: "everystack://derived-objects",
|
|
21639
|
+
name: "Derived Objects (Views, Matviews, Functions, Triggers)",
|
|
21640
|
+
description: "How to add or change a view, materialized view, function, trigger, or standalone sequence in 0.4.0 \u2014 declared descriptors (defineView / defineMaterializedView / defineFunction / defineSql / trigger() / defineSequence) on defineModule({ derived }), deployed by db:reconcile (NEVER migrated). Read this whenever a schema needs compute, not just tables. db/sql/ is retired.",
|
|
21641
|
+
filename: "derived-objects.md"
|
|
21642
|
+
},
|
|
21643
|
+
{
|
|
21644
|
+
uri: "everystack://database-operations",
|
|
21645
|
+
name: "Database Operations (migrate, import data, SAFE remote apply)",
|
|
21646
|
+
description: "The operational playbook: local dev (db:sync, db:branch, db:template:refresh), importing data properly (db:seed, db:backfill, ingest pipeline \u2014 never ad-hoc INSERTs), and migrating a REMOTE stage SAFELY (db:check \u2192 db:plan \u2192 db:apply with fingerprint + fast-forward verification; destructive plans require --confirm + snapshot + approvers). Snapshot-first (db:snapshot vs db:backup) and remote data import (db:seed --stage, pipeline:run, db:fork). READ THIS before touching a deployed database.",
|
|
21647
|
+
filename: "database-operations.md"
|
|
21648
|
+
},
|
|
21637
21649
|
{
|
|
21638
21650
|
uri: "everystack://deployment",
|
|
21639
21651
|
name: "Deployment Guide",
|
|
@@ -22074,7 +22086,7 @@ function registerNewAppPrompt(server) {
|
|
|
22074
22086
|
"```",
|
|
22075
22087
|
`${effectiveName}/`,
|
|
22076
22088
|
"\u251C\u2500\u2500 app/ # Expo Router pages",
|
|
22077
|
-
effectiveTier !== "V1" ? "\u251C\u2500\u2500 db/ #
|
|
22089
|
+
effectiveTier !== "V1" ? "\u251C\u2500\u2500 db/ # models/ (declared schema), backfills/, seed" : "",
|
|
22078
22090
|
"\u251C\u2500\u2500 server/ # Lambda handlers",
|
|
22079
22091
|
effectiveTier !== "V1" ? "\u2502 \u2514\u2500\u2500 api.ts # PostgREST handler" : "",
|
|
22080
22092
|
effectiveTier === "V3" ? "\u2502 \u251C\u2500\u2500 worker.ts # SQS worker handler" : "",
|
|
@@ -22085,27 +22097,29 @@ function registerNewAppPrompt(server) {
|
|
|
22085
22097
|
"```",
|
|
22086
22098
|
"",
|
|
22087
22099
|
effectiveTier !== "V1" ? [
|
|
22088
|
-
"### 3. Database Schema",
|
|
22089
|
-
`
|
|
22100
|
+
"### 3. Database Schema \u2014 declared Models (0.4.0)",
|
|
22101
|
+
`Declare tables for the ${description} as \`defineModel\` in \`db/models/\` (one file per table).`,
|
|
22102
|
+
"Do NOT hand-write db/schema.ts or run drizzle-kit \u2014 the schema is DECLARED, then compiled.",
|
|
22090
22103
|
"Follow the patterns from everystack://schema-patterns:",
|
|
22091
|
-
"-
|
|
22092
|
-
"-
|
|
22093
|
-
"-
|
|
22094
|
-
"-
|
|
22104
|
+
"- `field.uuid().primaryKey().defaultRandom()`; `field.timestamptz().defaultNow().notNull()`",
|
|
22105
|
+
"- Foreign keys via `.references(() => Model)` / relations for SSR + API embedding",
|
|
22106
|
+
"- Authorization as `can()` abilities ON the Model (compiles to RLS + grants \u2014 never hand-written)",
|
|
22107
|
+
"- Views/matviews/functions/triggers: descriptors in db/models/derived.ts (everystack://derived-objects)",
|
|
22108
|
+
"- Compose in db/models/index.ts: `defineModule({ models, derived })`",
|
|
22095
22109
|
"",
|
|
22096
|
-
"### 4.
|
|
22097
|
-
|
|
22098
|
-
"-
|
|
22099
|
-
"-
|
|
22110
|
+
"### 4. Apply the schema",
|
|
22111
|
+
'- Dev database: `everystack db:sync --database-url "$DATABASE_URL"` (state + authz + compute, one verb)',
|
|
22112
|
+
"- CI gate: `everystack db:check`",
|
|
22113
|
+
"- Protected stages: `db:plan` \u2192 `db:apply` (everystack://database-operations)",
|
|
22114
|
+
"- No hand-written migration, no CREATE POLICY, no GRANT \u2014 all generated from the Models",
|
|
22100
22115
|
"",
|
|
22101
22116
|
"### 5. Handler Configuration",
|
|
22102
22117
|
"Create server/api.ts using createPluginLambdaHandler or createLambdaHandler.",
|
|
22103
|
-
"
|
|
22118
|
+
"The per-table access config (exposedTables, rowOwnership, softDelete, hidden/protected columns,",
|
|
22119
|
+
"relations) is DERIVED from your Models via `deriveHandlerConfig(models)` \u2014 do not hand-maintain it.",
|
|
22120
|
+
"Set only the app-level options by hand:",
|
|
22104
22121
|
"- auth.verifyToken for JWT verification",
|
|
22105
22122
|
"- pgSettings for RLS context injection",
|
|
22106
|
-
"- exposedTables to limit API surface",
|
|
22107
|
-
"- rowOwnership for user-scoped mutation control",
|
|
22108
|
-
"- softDelete for reversible deletes",
|
|
22109
22123
|
"",
|
|
22110
22124
|
"### 6. Auth Setup",
|
|
22111
22125
|
"Read everystack://auth for the full auth flow.",
|
|
@@ -22116,7 +22130,7 @@ function registerNewAppPrompt(server) {
|
|
|
22116
22130
|
].join("\n") : "",
|
|
22117
22131
|
"## Validation",
|
|
22118
22132
|
"",
|
|
22119
|
-
"After scaffolding, run
|
|
22133
|
+
"After scaffolding, run `check_environment` to confirm prerequisites, and `everystack db:check` to confirm the declared schema composes.",
|
|
22120
22134
|
"",
|
|
22121
22135
|
"## Run Locally",
|
|
22122
22136
|
"",
|
|
@@ -22168,10 +22182,10 @@ function registerNewAppPrompt(server) {
|
|
|
22168
22182
|
effectiveTier === "V3" ? "- S3 bucket for file uploads" : "",
|
|
22169
22183
|
"",
|
|
22170
22184
|
"### Deploy",
|
|
22171
|
-
"Read everystack://deployment for the full walkthrough.",
|
|
22185
|
+
"Read everystack://deployment and everystack://database-operations for the full walkthrough.",
|
|
22172
22186
|
"1. `pnpm sst deploy --stage dev`",
|
|
22173
|
-
effectiveTier !== "V1" ? "2. `everystack db:
|
|
22174
|
-
effectiveTier !== "V1" ? "3. `everystack db:seed` (dev only)" : ""
|
|
22187
|
+
effectiveTier !== "V1" ? "2. `everystack db:plan --stage dev --out dev.plan.json` \u2192 review \u2192 `everystack db:apply --plan dev.plan.json --stage dev`" : "",
|
|
22188
|
+
effectiveTier !== "V1" ? "3. `everystack db:seed --stage dev` (dev only)" : ""
|
|
22175
22189
|
].filter(Boolean).join("\n")
|
|
22176
22190
|
}
|
|
22177
22191
|
}
|
|
@@ -22286,7 +22300,7 @@ var FEATURES = {
|
|
|
22286
22300
|
packages: [],
|
|
22287
22301
|
steps: [
|
|
22288
22302
|
"Events use PostgreSQL LISTEN/NOTIFY \u2014 built into the database",
|
|
22289
|
-
"
|
|
22303
|
+
"Declare the NOTIFY trigger the descriptor way (everystack://derived-objects): a defineFunction returning trigger, wired via trigger() on the Model \u2014 never a hand-written SQL trigger or a db/sql file",
|
|
22290
22304
|
"Set up a listener Lambda with persistent database connection",
|
|
22291
22305
|
"Add WebSocket fan-out for client delivery",
|
|
22292
22306
|
"Use the useSignal hook in React components for real-time updates"
|
|
@@ -22317,8 +22331,8 @@ function registerAddFeaturePrompt(server) {
|
|
|
22317
22331
|
`1. Read the ${f.resource} resource for full documentation.`,
|
|
22318
22332
|
"2. Read everystack://core for architecture context.",
|
|
22319
22333
|
feature === "auth" || feature === "security" ? "3. Read everystack://security for the security model." : "",
|
|
22320
|
-
projectPath ? `4.
|
|
22321
|
-
projectPath ?
|
|
22334
|
+
projectPath ? `4. Read the project's CLAUDE.md and structure under "${projectPath}" to understand the current state.` : "",
|
|
22335
|
+
projectPath ? "5. After changes: `pnpm test`, and if the schema changed, `everystack db:check`." : "",
|
|
22322
22336
|
"",
|
|
22323
22337
|
"## Steps",
|
|
22324
22338
|
"",
|
|
@@ -22333,7 +22347,7 @@ pnpm add ${f.packages.join(" ")}
|
|
|
22333
22347
|
"## After Setup",
|
|
22334
22348
|
"",
|
|
22335
22349
|
"- Run tests to verify the integration",
|
|
22336
|
-
"-
|
|
22350
|
+
"- If the schema changed, run `everystack db:check`",
|
|
22337
22351
|
"- Read the relevant resource docs for advanced configuration"
|
|
22338
22352
|
].filter(Boolean).join("\n")
|
|
22339
22353
|
}
|
|
@@ -22348,10 +22362,10 @@ pnpm add ${f.packages.join(" ")}
|
|
|
22348
22362
|
function registerDesignSchemaPrompt(server) {
|
|
22349
22363
|
server.prompt(
|
|
22350
22364
|
"design-schema",
|
|
22351
|
-
"Interactive schema design: plain English description \u2192
|
|
22365
|
+
"Interactive schema design (0.4.0): plain English description \u2192 declared Models (defineModel + can abilities) + derived descriptors + testing checklist. Authz and handler config are DERIVED from the Models, never hand-written.",
|
|
22352
22366
|
{
|
|
22353
22367
|
description: external_exports.string().describe('Plain English description of the data model (e.g., "blog with posts, comments, and tags")'),
|
|
22354
|
-
projectPath: external_exports.string().optional().describe("Absolute path to project root (to
|
|
22368
|
+
projectPath: external_exports.string().optional().describe("Absolute path to project root (to read the existing db/models/)")
|
|
22355
22369
|
},
|
|
22356
22370
|
async ({ description, projectPath }) => {
|
|
22357
22371
|
return {
|
|
@@ -22363,81 +22377,67 @@ function registerDesignSchemaPrompt(server) {
|
|
|
22363
22377
|
text: [
|
|
22364
22378
|
`Design a database schema for: ${description}`,
|
|
22365
22379
|
"",
|
|
22380
|
+
"IMPORTANT (0.4.0): you declare the schema, you do NOT hand-write it. Tables are",
|
|
22381
|
+
"`defineModel` in `db/models/`; authorization is `can()` abilities on the Model that",
|
|
22382
|
+
"COMPILE to RLS + grants; the handler config is DERIVED from the Models. Never hand-write",
|
|
22383
|
+
"`db/schema.ts`, a SQL migration, `CREATE POLICY`, or `GRANT` \u2014 those are generated.",
|
|
22384
|
+
"",
|
|
22366
22385
|
"## Instructions",
|
|
22367
22386
|
"",
|
|
22368
|
-
"1. Read everystack://schema-patterns for
|
|
22369
|
-
"2. Read everystack://
|
|
22370
|
-
"3. Read everystack://
|
|
22371
|
-
|
|
22387
|
+
"1. Read everystack://schema-patterns for how to declare TABLES (defineModel, field, can, relations).",
|
|
22388
|
+
"2. Read everystack://derived-objects IF the model needs views, materialized views, functions, or triggers.",
|
|
22389
|
+
"3. Read everystack://security for the authorization model (how can() abilities become RLS + grants).",
|
|
22390
|
+
"4. Read everystack://database-operations for how the declaration reaches a database (db:sync on dev).",
|
|
22391
|
+
projectPath ? `5. Read the existing \`db/models/\` under "${projectPath}" to match its conventions before adding to it.` : "",
|
|
22372
22392
|
"",
|
|
22373
22393
|
"## Deliverables",
|
|
22374
22394
|
"",
|
|
22375
22395
|
"Generate ALL of the following:",
|
|
22376
22396
|
"",
|
|
22377
|
-
"### 1.
|
|
22378
|
-
"",
|
|
22379
|
-
"Follow these conventions:",
|
|
22380
|
-
"- UUID primary keys: `uuid('id').primaryKey().defaultRandom()`",
|
|
22381
|
-
"- Timestamps: `timestamp('created_at', { withTimezone: true }).defaultNow().notNull()`",
|
|
22382
|
-
"- Soft delete columns: `deletedAt` + `deletedBy` on user-facing tables",
|
|
22383
|
-
"- Foreign keys with `.references(() => table.column)`",
|
|
22384
|
-
"- Export all tables as named exports",
|
|
22385
|
-
"- Add Drizzle `relations()` for SSR query building and API embedding",
|
|
22397
|
+
"### 1. Models (db/models/<table>.ts \u2014 one file per table)",
|
|
22386
22398
|
"",
|
|
22387
|
-
"
|
|
22399
|
+
"Declare each table with `defineModel`, following these conventions:",
|
|
22400
|
+
"- UUID primary keys: `id: field.uuid().primaryKey().defaultRandom()`",
|
|
22401
|
+
"- Timestamps: `createdAt: field.timestamptz().defaultNow().notNull()`",
|
|
22402
|
+
"- Soft delete: a `deletedAt: field.timestamptz()` field opts the table into soft-delete",
|
|
22403
|
+
"- Foreign keys via relations: `field.uuid().references(() => Author)` / `belongsTo`/`hasMany`",
|
|
22404
|
+
"- Sensitive columns: `.private()` (hidden from the API); write-guarded: `.readonly()`",
|
|
22405
|
+
"- Named exports (PascalCase model var, e.g. `export const Post = defineModel('posts', \u2026)`)",
|
|
22388
22406
|
"",
|
|
22389
|
-
"
|
|
22407
|
+
"### 2. Authorization \u2014 `can()` abilities ON each Model (NOT hand-written RLS)",
|
|
22390
22408
|
"",
|
|
22391
|
-
"
|
|
22392
|
-
"
|
|
22393
|
-
"ALTER TABLE table_name ENABLE ROW LEVEL SECURITY;",
|
|
22409
|
+
"Declare the access pattern as abilities; the compiler emits the RLS policies and GRANTs.",
|
|
22410
|
+
"Every table MUST make its read decision or `db:check` fails it:",
|
|
22394
22411
|
"",
|
|
22395
|
-
"
|
|
22396
|
-
"
|
|
22397
|
-
"
|
|
22398
|
-
"
|
|
22399
|
-
"",
|
|
22400
|
-
"
|
|
22401
|
-
"
|
|
22402
|
-
'CREATE POLICY "anon_select" ON table_name FOR SELECT TO anon USING (deleted_at IS NULL);',
|
|
22403
|
-
"",
|
|
22404
|
-
"-- Own rows only:",
|
|
22405
|
-
'CREATE POLICY "own_rows" ON table_name FOR ALL TO authenticated',
|
|
22406
|
-
" USING (user_id = current_setting('request.jwt.claims', true)::json->>'sub');",
|
|
22407
|
-
"",
|
|
22408
|
-
"-- Admin full access:",
|
|
22409
|
-
'CREATE POLICY "admin_all" ON table_name FOR ALL TO admin USING (true);',
|
|
22412
|
+
"```ts",
|
|
22413
|
+
"abilities: [",
|
|
22414
|
+
" can('read'), // public read (anon + authenticated)",
|
|
22415
|
+
" can('read', { owner: 'authorId' }), // rows the caller owns",
|
|
22416
|
+
" can('manage', { owner: 'authorId' }), // owner can write their own rows",
|
|
22417
|
+
" can('read', { role: 'admin' }), // a specific role only",
|
|
22418
|
+
"],",
|
|
22410
22419
|
"```",
|
|
22411
22420
|
"",
|
|
22412
|
-
"
|
|
22421
|
+
"A private/operational table declares `private: true` (generated, but not a generic-API",
|
|
22422
|
+
"resource). Row ownership, soft-delete, hidden/protected columns, and relations are all",
|
|
22423
|
+
"DERIVED from the Model into the handler config \u2014 do not write a createHandler options blob",
|
|
22424
|
+
"by hand.",
|
|
22413
22425
|
"",
|
|
22414
|
-
"### 3.
|
|
22426
|
+
"### 3. Derived objects (only if the model needs compute)",
|
|
22415
22427
|
"",
|
|
22416
|
-
"
|
|
22417
|
-
"
|
|
22418
|
-
"
|
|
22419
|
-
"- `rowOwnership`: for user-scoped tables",
|
|
22420
|
-
"- `softDelete`: for tables with deletedAt columns",
|
|
22421
|
-
"- `protectedFields`: fields users cannot set directly (role, deletedAt)",
|
|
22422
|
-
"- `hiddenColumns`: sensitive columns not returned in API responses",
|
|
22428
|
+
"If the design needs a view, materialized view, function, or trigger, declare it as a",
|
|
22429
|
+
"descriptor in `db/models/derived.ts` per everystack://derived-objects \u2014 NOT as a SQL",
|
|
22430
|
+
"migration. Wire them on `defineModule({ models, derived })`.",
|
|
22423
22431
|
"",
|
|
22424
|
-
"### 4. Testing
|
|
22432
|
+
"### 4. Testing + apply checklist",
|
|
22425
22433
|
"",
|
|
22426
|
-
"
|
|
22427
|
-
"- [ ] Anonymous users can read
|
|
22428
|
-
"- [ ]
|
|
22429
|
-
"- [ ] Authenticated users can only read/write their own data",
|
|
22434
|
+
"- [ ] Every table declares a read ability or `private: true` (db:check gate)",
|
|
22435
|
+
"- [ ] Anonymous users can read only what `can('read')` (no owner/role) allows",
|
|
22436
|
+
"- [ ] Owner-scoped rows are invisible and unwritable across users (IDOR)",
|
|
22430
22437
|
"- [ ] Soft-deleted rows are hidden from normal queries",
|
|
22431
|
-
|
|
22432
|
-
"- [ ]
|
|
22433
|
-
"- [ ]
|
|
22434
|
-
"",
|
|
22435
|
-
"Test each RLS policy with:",
|
|
22436
|
-
"```sql",
|
|
22437
|
-
"SET LOCAL ROLE authenticated;",
|
|
22438
|
-
`SELECT set_config('request.jwt.claims', '{"sub": "user-uuid", "role": "authenticated"}', true);`,
|
|
22439
|
-
"SELECT * FROM table_name; -- should only return own rows",
|
|
22440
|
-
"```"
|
|
22438
|
+
'- [ ] `everystack db:sync --database-url "$DATABASE_URL"` applies cleanly on a dev DB',
|
|
22439
|
+
"- [ ] `everystack db:check` passes (declared state composes; generated artifacts match)",
|
|
22440
|
+
"- [ ] `everystack db:authz:test --stage dev` proves the compiled RLS enforces the abilities"
|
|
22441
22441
|
].filter(Boolean).join("\n")
|
|
22442
22442
|
}
|
|
22443
22443
|
}
|
|
@@ -22451,7 +22451,7 @@ function registerDesignSchemaPrompt(server) {
|
|
|
22451
22451
|
function registerDeployPrompt(server) {
|
|
22452
22452
|
server.prompt(
|
|
22453
22453
|
"deploy",
|
|
22454
|
-
"Step-by-step deployment walkthrough for a specific stage. Covers AWS credentials, SST deploy,
|
|
22454
|
+
"Step-by-step deployment walkthrough for a specific stage. Covers AWS credentials, SST deploy, the SAFE schema flow (db:plan \u2192 db:apply, snapshot-first), and verification.",
|
|
22455
22455
|
{
|
|
22456
22456
|
stage: external_exports.enum(["dev", "staging", "production"]).describe("Deployment stage"),
|
|
22457
22457
|
projectPath: external_exports.string().optional().describe("Absolute path to project root")
|
|
@@ -22471,8 +22471,8 @@ function registerDeployPrompt(server) {
|
|
|
22471
22471
|
"",
|
|
22472
22472
|
"1. Read everystack://deployment for infrastructure setup.",
|
|
22473
22473
|
"2. Read everystack://security for AWS credential setup and deployment checklist.",
|
|
22474
|
-
|
|
22475
|
-
projectPath ? `4. Run
|
|
22474
|
+
"3. Read everystack://database-operations for the SAFE schema-migration flow (db:plan \u2192 db:apply, snapshot-first) \u2014 a protected stage is NOT migrated with db:migrate.",
|
|
22475
|
+
projectPath ? `4. Run check_environment with projectPath="${projectPath}" to confirm prerequisites (Node, SST, AWS credentials) before deploying.` : "",
|
|
22476
22476
|
"",
|
|
22477
22477
|
"## Pre-Deploy Checklist",
|
|
22478
22478
|
"",
|
|
@@ -22495,8 +22495,8 @@ function registerDeployPrompt(server) {
|
|
|
22495
22495
|
"### Production Safety",
|
|
22496
22496
|
"",
|
|
22497
22497
|
"- [ ] All tests pass: `pnpm test`",
|
|
22498
|
-
"- [ ]
|
|
22499
|
-
"- [ ] RLS
|
|
22498
|
+
"- [ ] `everystack db:check` passes (declared state composes; generated artifacts match)",
|
|
22499
|
+
"- [ ] RLS is declared via `can()` abilities on every Model (compiles to policies + grants)",
|
|
22500
22500
|
"- [ ] pgSettings is configured in handler",
|
|
22501
22501
|
"- [ ] No hardcoded secrets in source",
|
|
22502
22502
|
"- [ ] .env files are not committed",
|
|
@@ -22517,10 +22517,19 @@ function registerDeployPrompt(server) {
|
|
|
22517
22517
|
"- SQS queues (V3)",
|
|
22518
22518
|
"- IAM roles and policies",
|
|
22519
22519
|
"",
|
|
22520
|
-
"###
|
|
22520
|
+
"### 2. Database Schema (V2+) \u2014 the SAFE flow",
|
|
22521
|
+
"",
|
|
22522
|
+
"A protected stage is migrated by minting a reviewable plan and applying it credential-free",
|
|
22523
|
+
"(the operator never holds the database URL). See everystack://database-operations.",
|
|
22521
22524
|
"```bash",
|
|
22522
|
-
`everystack db:
|
|
22523
|
-
|
|
22525
|
+
`everystack db:check # gate: declared state composes`,
|
|
22526
|
+
`everystack db:plan --stage ${stage} --out ${stage}.plan.json # mint the edge (read-only) \u2014 REVIEW it`,
|
|
22527
|
+
isProduction ? `everystack db:snapshot --stage ${stage} # physical RDS snapshot first (instant rollback)` : "",
|
|
22528
|
+
`everystack db:apply --plan ${stage}.plan.json --stage ${stage} # verify \u2192 apply \u2192 verify`,
|
|
22529
|
+
`# destructive plans (drops / narrowing types) also need: --confirm + a snapshot + the`,
|
|
22530
|
+
`# stage's approver set (everystack db:approvers --stage ${stage} --set "\u2026")`,
|
|
22531
|
+
`everystack db:reconcile --check --stage ${stage} # confirm the compute layer (views/matviews/functions) matches`,
|
|
22532
|
+
stage === "dev" ? `everystack db:seed --stage ${stage} # dev only` : "",
|
|
22524
22533
|
"```",
|
|
22525
22534
|
"",
|
|
22526
22535
|
"### 4. Verify",
|
|
@@ -22593,9 +22602,8 @@ function registerDebugPrompt(server) {
|
|
|
22593
22602
|
"## Instructions",
|
|
22594
22603
|
"",
|
|
22595
22604
|
"1. Read everystack://core for architecture context.",
|
|
22596
|
-
projectPath ? `2.
|
|
22597
|
-
projectPath ?
|
|
22598
|
-
projectPath ? `4. Run schema_analyze with projectPath="${projectPath}" to check schema/handler alignment.` : "",
|
|
22605
|
+
projectPath ? `2. Read the project's CLAUDE.md and \`db/models/\` under "${projectPath}" to understand its schema and conventions.` : "",
|
|
22606
|
+
projectPath ? "3. If the issue is schema/database-related, run `everystack db:check` (declared state composes) and `everystack db:fingerprint` (live schema matches the Models) to localize drift." : "",
|
|
22599
22607
|
"",
|
|
22600
22608
|
"## Diagnostic Framework",
|
|
22601
22609
|
"",
|
|
@@ -22696,7 +22704,7 @@ function registerDebugPrompt(server) {
|
|
|
22696
22704
|
"1. Identify the root cause",
|
|
22697
22705
|
"2. Propose a fix with the specific code change",
|
|
22698
22706
|
"3. Verify the fix resolves the issue",
|
|
22699
|
-
"4. Run
|
|
22707
|
+
"4. Run `pnpm test` and (for schema changes) `everystack db:check` to ensure no new issues were introduced"
|
|
22700
22708
|
].filter(Boolean).join("\n")
|
|
22701
22709
|
}
|
|
22702
22710
|
}
|
|
@@ -22732,8 +22740,8 @@ function registerSecurePrompt(server) {
|
|
|
22732
22740
|
"",
|
|
22733
22741
|
"1. Read everystack://security for the complete security model.",
|
|
22734
22742
|
"2. Read everystack://auth for JWT authentication details.",
|
|
22735
|
-
projectPath ? `3.
|
|
22736
|
-
projectPath ?
|
|
22743
|
+
projectPath ? `3. Read the project's \`db/models/\` under "${projectPath}" \u2014 the \`can()\` abilities ARE the authorization; confirm every table declares a read decision.` : "",
|
|
22744
|
+
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`." : "",
|
|
22737
22745
|
"",
|
|
22738
22746
|
requested.includes("aws") ? [
|
|
22739
22747
|
"## AWS IAM Profiles",
|
|
@@ -22914,7 +22922,7 @@ function registerSecurePrompt(server) {
|
|
|
22914
22922
|
"",
|
|
22915
22923
|
"After setup, verify security:",
|
|
22916
22924
|
"",
|
|
22917
|
-
"1. Run
|
|
22925
|
+
"1. Run `everystack db:doctor` and `everystack db:authz:test --stage dev` to prove the RLS enforces the declared abilities",
|
|
22918
22926
|
"2. Test unauthenticated access returns 401",
|
|
22919
22927
|
"3. Test cross-user data isolation with RLS",
|
|
22920
22928
|
"4. Verify JWT claims propagate through pgSettings",
|
|
@@ -23402,6 +23410,7 @@ function renderFinding(f) {
|
|
|
23402
23410
|
var import_path2 = require("path");
|
|
23403
23411
|
var MIGRATION_SQL = /(?:^|\/)(?:drizzle|migrations)\/[^/]+\.sql$/i;
|
|
23404
23412
|
var GENERATED_SCHEMA = /schema\.generated\.tsx?$/;
|
|
23413
|
+
var RETIRED_DB_SQL = /(?:^|\/)db\/sql\/[^/]+\.sql$/i;
|
|
23405
23414
|
function rel(ctx, p) {
|
|
23406
23415
|
try {
|
|
23407
23416
|
return (0, import_path2.relative)(ctx.cwd, p) || p;
|
|
@@ -23413,8 +23422,8 @@ var handWrittenMigration = {
|
|
|
23413
23422
|
id: "hand-written-migration",
|
|
23414
23423
|
tier: "framework",
|
|
23415
23424
|
severity: "deny",
|
|
23416
|
-
guide: "Nobody authors migrations. Schema changes have
|
|
23417
|
-
conform: "edit db/models/ then `everystack db:sync` (dev) or `db:plan` \u2192 `db:apply` (protected) \xB7 db/
|
|
23425
|
+
guide: "Nobody authors migrations. Schema changes have two homes: the WHOLE declared database \u2014 tables/constraints/authz (defineModel) AND functions/views/matviews (defineView/defineMaterializedView/defineFunction/defineSql descriptors) \u2014 lives in db/models/ (edit the declaration, then `everystack db:sync` on dev \u2014 protected stages take `db:plan` \u2192 `db:apply`); one-shot DATA moves are authored in db/backfills/*.sql (run via db:backfill, never as a schema side effect). db/sql/ is retired \u2014 raw-SQL derived objects moved into descriptors. No migration file, ever \u2014 and generated artifacts (schema.generated.ts) are never edited.",
|
|
23426
|
+
conform: "edit db/models/ (Models + derived descriptors) then `everystack db:sync` (dev) or `db:plan` \u2192 `db:apply` (protected) \xB7 db/backfills/ for data moves",
|
|
23418
23427
|
verify: "everystack db:check passes (declared state composes; generated artifacts match regeneration) AND everystack db:fingerprint reports MATCH",
|
|
23419
23428
|
detect(ctx) {
|
|
23420
23429
|
if (ctx.tool !== "Write" && ctx.tool !== "Edit") return null;
|
|
@@ -23422,6 +23431,7 @@ var handWrittenMigration = {
|
|
|
23422
23431
|
if (!p) return null;
|
|
23423
23432
|
if (MIGRATION_SQL.test(p)) return `${rel(ctx, p)} is a SQL migration being written by hand`;
|
|
23424
23433
|
if (GENERATED_SCHEMA.test(p)) return `${rel(ctx, p)} is a generated artifact (compiled from your Models \u2014 db:check refuses hand edits)`;
|
|
23434
|
+
if (RETIRED_DB_SQL.test(p)) return `${rel(ctx, p)} is in the retired db/sql home \u2014 declare it as a descriptor (defineView/defineMaterializedView/defineFunction/defineSql) in db/models/ instead; the CLI verbs fail on this directory`;
|
|
23425
23435
|
return null;
|
|
23426
23436
|
}
|
|
23427
23437
|
};
|
|
@@ -23707,7 +23717,7 @@ async function runGovernanceCli(argv) {
|
|
|
23707
23717
|
}
|
|
23708
23718
|
|
|
23709
23719
|
// src/index.ts
|
|
23710
|
-
var version2 = (true ? "0.
|
|
23720
|
+
var version2 = (true ? "0.4.0" : null) ?? "0.3.0-dev";
|
|
23711
23721
|
var INSTRUCTIONS = [
|
|
23712
23722
|
"You govern how any agent builds everystack \u2014 a self-hosted application stack for Expo apps on AWS.",
|
|
23713
23723
|
"Your job is not only to advise but to keep the build on-script: the architecture the maintainer",
|
|
@@ -23769,7 +23779,7 @@ var INSTRUCTIONS = [
|
|
|
23769
23779
|
"1. Read everystack://core for architecture and conventions.",
|
|
23770
23780
|
"2. Read everystack://security before any deployment or auth guidance.",
|
|
23771
23781
|
"3. Load detail resources on demand when the user asks about specific features.",
|
|
23772
|
-
'4. Data lives in PostgreSQL via Models/Modules and is served through the API \u2014 never bundle large computed data into the app. NOBODY AUTHORS MIGRATIONS. Schema work has
|
|
23782
|
+
'4. Data lives in PostgreSQL via Models/Modules and is served through the API \u2014 never bundle large computed data into the app. NOBODY AUTHORS MIGRATIONS. Schema work has two homes: the WHOLE declared database \u2014 tables/constraints/authz (defineModel) AND functions/views/matviews (defineView/defineMaterializedView/defineFunction/defineSql descriptors) \u2014 is DECLARED in `db/models/` (edit the declaration, then `everystack db:sync` moves the dev database to the checkout \u2014 verified by fingerprint; the derived layer deploys via `db:reconcile`/`db:sync`); one-shot DATA moves are authored in `db/backfills/*.sql` (run via `db:backfill`, never as a schema side effect). Protected stages never take a sync: `db:plan` mints a reviewable, fingerprint-pinned edge and `db:apply` verifies at both ends \u2014 the checkout must descend from the commit declaring the target\'s state ("rebase first"), and destructive plans are confirmed, snapshotted, and approver-gated (`db:approvers`). CI runs `everystack db:check` (the merged declared state must compose; generated artifacts must match regeneration byte-for-byte). Per-branch dev databases: `db:template:refresh` + `db:branch`; deployed feature stages fork data with `db:fork`. Reuse `@everystack/ui` components; never put secret values behind `EXPO_PUBLIC_*`.',
|
|
23773
23783
|
'5. When the user wants to start a new project, run check_environment (phase "local" for dev, "deploy" for deployment) to verify prerequisites.',
|
|
23774
23784
|
"6. When the user needs to interact with deployed infrastructure, guide them to use the everystack CLI."
|
|
23775
23785
|
].join("\n");
|
|
@@ -19,12 +19,14 @@ These are enforced (everystack cheat gates) and load-bearing. Do not work around
|
|
|
19
19
|
- **Data lives in PostgreSQL, served through the API — never bundle data into the app.** A
|
|
20
20
|
large `.json`/`.csv` of computed data in the bundle is wrong; model it and serve it, or
|
|
21
21
|
render an empty state if it does not exist yet.
|
|
22
|
-
- **Nobody authors migrations. Schema work has
|
|
23
|
-
in `db/models
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
- **Nobody authors migrations. Schema work has two homes.** The WHOLE declared database
|
|
23
|
+
lives in `db/models/`: tables and authz with `defineModel`, and the derived layer —
|
|
24
|
+
functions, views, matviews — as descriptors (`defineView` / `defineMaterializedView` /
|
|
25
|
+
`defineFunction` / `defineSql`, triggers via `trigger()` on the model). Edit the
|
|
26
|
+
declaration, then `everystack db:sync` moves the dev database to your checkout (state +
|
|
27
|
+
authz + derived, fingerprint-verified). One-shot DATA moves are authored in
|
|
28
|
+
`db/backfills/*.sql` and run via `everystack db:backfill` — deliberately, never as a
|
|
29
|
+
schema side effect. Never hand-write a SQL
|
|
28
30
|
migration, never edit `db/schema.generated.ts`; `everystack db:check` must pass (the CI
|
|
29
31
|
gate: the declared state composes, generated artifacts match regeneration).
|
|
30
32
|
- **Protected stages take plans, not syncs.** `everystack db:plan` mints a reviewable edge
|
|
@@ -42,8 +44,8 @@ These are enforced (everystack cheat gates) and load-bearing. Do not work around
|
|
|
42
44
|
|
|
43
45
|
## Start Here
|
|
44
46
|
|
|
45
|
-
- `db/models/` — `defineModel` tables
|
|
46
|
-
|
|
47
|
+
- `db/models/` — the declared database: `defineModel` tables + derived descriptors
|
|
48
|
+
(`defineView`/`defineMaterializedView`/`defineFunction`/`defineSql`; deploys via `db:reconcile`/`db:sync`)
|
|
47
49
|
- `db/backfills/` — one-shot data jobs (authored SQL; run via `db:backfill`, own record)
|
|
48
50
|
- `app/` — Expo Router pages (screens, navigation, API routes)
|
|
49
51
|
- `server/` — Lambda handlers (api.ts, worker.ts, image.ts)
|
|
@@ -84,9 +86,9 @@ Declare tables with `defineModel` (`field`, `can`, relations). A package's full
|
|
|
84
86
|
live state is content-addressed (`db:fingerprint`), and every apply verifies against it. You
|
|
85
87
|
never hand-write migrations, RLS, or handler access-control — they are derived, so they cannot
|
|
86
88
|
drift; `deriveHandlerConfig(models)` derives the API config. The derived layer (functions,
|
|
87
|
-
views, matviews)
|
|
88
|
-
|
|
89
|
-
comment-only edit is a no-op. Contraction is a two-step ceremony: `field.deprecated()` first
|
|
89
|
+
views, matviews) follows the same rule: descriptors declare the structure (identity, deps,
|
|
90
|
+
authz, security posture), the body stays `sql\`\``, and reconcile *deploys* it — hand-edits
|
|
91
|
+
straight against the database surface as drift, and a comment-only edit is a no-op. Contraction is a two-step ceremony: `field.deprecated()` first
|
|
90
92
|
(the column stays readable, new writes are rejected, generated types strike it through), the
|
|
91
93
|
physical drop later — a destructive plan, confirmed, snapshotted, approver-gated.
|
|
92
94
|
|
|
@@ -118,7 +120,8 @@ Every feature starts with a failing test. Tests in `__tests__/` mirroring source
|
|
|
118
120
|
|
|
119
121
|
- Don't bundle large data into the app — it lives in the DB, served by the API.
|
|
120
122
|
- Don't hand-write migrations or edit `db/schema.ts` — edit the Model, run `db:generate`;
|
|
121
|
-
for functions/views/matviews edit `db/
|
|
123
|
+
for functions/views/matviews edit the descriptors in `db/models/` and run `db:reconcile`
|
|
124
|
+
(`db/sql/` is retired — the verbs fail on it with the migration path).
|
|
122
125
|
- Don't hand-write RLS — declare `can()` abilities.
|
|
123
126
|
- Don't hand-roll a component that exists in `@everystack/ui`; don't use inline `StyleSheet`.
|
|
124
127
|
- Don't put a secret behind `EXPO_PUBLIC_*` — that ships to the client.
|