@everystack/mcp 0.3.3 → 0.4.1

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/index.cjs CHANGED
@@ -21631,15 +21631,33 @@ var RESOURCES = [
21631
21631
  {
21632
21632
  uri: "everystack://schema-patterns",
21633
21633
  name: "Schema Design Patterns",
21634
- description: "Drizzle schema design: pgTable, column types, relations, indexes, timestamps, soft delete, UUID vs serial, migration workflow, drizzle-kit commands.",
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",
21640
21652
  description: "SST deployment: sst.config.ts setup, secrets, stages (dev/production), CloudFront, Lambda configuration, VPC, RDS Aurora Serverless, resource linking.",
21641
21653
  filename: "deployment.md"
21642
21654
  },
21655
+ {
21656
+ uri: "everystack://expo-server-deploy",
21657
+ name: "Deploying an Expo Router Server App",
21658
+ description: 'How web.output:"server" maps to AWS: the two-deployable model (sst deploy vs everystack update), where +api.ts routes run (the SSR fallback serves the published bundle), the one-plugin-list/two-venues pattern (local catch-all route + deployed Lambda entrypoint), the ops entrypoint for db:migrate, custom domains on the Router, and the local-vs-deployed database URL (sslmode). Read this when deploying any Expo Router app with SSR or +api.ts routes.',
21659
+ filename: "expo-server-deploy.md"
21660
+ },
21643
21661
  {
21644
21662
  uri: "everystack://admin",
21645
21663
  name: "Admin Dashboard",
@@ -22074,7 +22092,7 @@ function registerNewAppPrompt(server) {
22074
22092
  "```",
22075
22093
  `${effectiveName}/`,
22076
22094
  "\u251C\u2500\u2500 app/ # Expo Router pages",
22077
- effectiveTier !== "V1" ? "\u251C\u2500\u2500 db/ # Schema, migrations, seed" : "",
22095
+ effectiveTier !== "V1" ? "\u251C\u2500\u2500 db/ # models/ (declared schema), backfills/, seed" : "",
22078
22096
  "\u251C\u2500\u2500 server/ # Lambda handlers",
22079
22097
  effectiveTier !== "V1" ? "\u2502 \u2514\u2500\u2500 api.ts # PostgREST handler" : "",
22080
22098
  effectiveTier === "V3" ? "\u2502 \u251C\u2500\u2500 worker.ts # SQS worker handler" : "",
@@ -22085,27 +22103,29 @@ function registerNewAppPrompt(server) {
22085
22103
  "```",
22086
22104
  "",
22087
22105
  effectiveTier !== "V1" ? [
22088
- "### 3. Database Schema",
22089
- `Create db/schema.ts with tables for the ${description}.`,
22106
+ "### 3. Database Schema \u2014 declared Models (0.4.0)",
22107
+ `Declare tables for the ${description} as \`defineModel\` in \`db/models/\` (one file per table).`,
22108
+ "Do NOT hand-write db/schema.ts or run drizzle-kit \u2014 the schema is DECLARED, then compiled.",
22090
22109
  "Follow the patterns from everystack://schema-patterns:",
22091
- "- UUID primary keys with defaultRandom()",
22092
- "- created_at timestamps on all tables",
22093
- "- Foreign key references with proper cascading",
22094
- "- Relations for both SSR and API query embedding",
22110
+ "- `field.uuid().primaryKey().defaultRandom()`; `field.timestamptz().defaultNow().notNull()`",
22111
+ "- Foreign keys via `.references(() => Model)` / relations for SSR + API embedding",
22112
+ "- Authorization as `can()` abilities ON the Model (compiles to RLS + grants \u2014 never hand-written)",
22113
+ "- Views/matviews/functions/triggers: descriptors in db/models/derived.ts (everystack://derived-objects)",
22114
+ "- Compose in db/models/index.ts: `defineModule({ models, derived })`",
22095
22115
  "",
22096
- "### 4. Migrations",
22097
- "- Generate: `npx drizzle-kit generate`",
22098
- "- Add RLS policies in a custom SQL migration",
22099
- "- Reference the RLS templates from everystack://security",
22116
+ "### 4. Apply the schema",
22117
+ '- Dev database: `everystack db:sync --database-url "$DATABASE_URL"` (state + authz + compute, one verb)',
22118
+ "- CI gate: `everystack db:check`",
22119
+ "- Protected stages: `db:plan` \u2192 `db:apply` (everystack://database-operations)",
22120
+ "- No hand-written migration, no CREATE POLICY, no GRANT \u2014 all generated from the Models",
22100
22121
  "",
22101
22122
  "### 5. Handler Configuration",
22102
22123
  "Create server/api.ts using createPluginLambdaHandler or createLambdaHandler.",
22103
- "Include:",
22124
+ "The per-table access config (exposedTables, rowOwnership, softDelete, hidden/protected columns,",
22125
+ "relations) is DERIVED from your Models via `deriveHandlerConfig(models)` \u2014 do not hand-maintain it.",
22126
+ "Set only the app-level options by hand:",
22104
22127
  "- auth.verifyToken for JWT verification",
22105
22128
  "- pgSettings for RLS context injection",
22106
- "- exposedTables to limit API surface",
22107
- "- rowOwnership for user-scoped mutation control",
22108
- "- softDelete for reversible deletes",
22109
22129
  "",
22110
22130
  "### 6. Auth Setup",
22111
22131
  "Read everystack://auth for the full auth flow.",
@@ -22116,7 +22136,7 @@ function registerNewAppPrompt(server) {
22116
22136
  ].join("\n") : "",
22117
22137
  "## Validation",
22118
22138
  "",
22119
- "After scaffolding, run the project_validate tool to check for common mistakes.",
22139
+ "After scaffolding, run `check_environment` to confirm prerequisites, and `everystack db:check` to confirm the declared schema composes.",
22120
22140
  "",
22121
22141
  "## Run Locally",
22122
22142
  "",
@@ -22168,10 +22188,10 @@ function registerNewAppPrompt(server) {
22168
22188
  effectiveTier === "V3" ? "- S3 bucket for file uploads" : "",
22169
22189
  "",
22170
22190
  "### Deploy",
22171
- "Read everystack://deployment for the full walkthrough.",
22191
+ "Read everystack://deployment and everystack://database-operations for the full walkthrough.",
22172
22192
  "1. `pnpm sst deploy --stage dev`",
22173
- effectiveTier !== "V1" ? "2. `everystack db:migrate`" : "",
22174
- effectiveTier !== "V1" ? "3. `everystack db:seed` (dev only)" : ""
22193
+ effectiveTier !== "V1" ? "2. `everystack db:plan --stage dev --out dev.plan.json` \u2192 review \u2192 `everystack db:apply --plan dev.plan.json --stage dev`" : "",
22194
+ effectiveTier !== "V1" ? "3. `everystack db:seed --stage dev` (dev only)" : ""
22175
22195
  ].filter(Boolean).join("\n")
22176
22196
  }
22177
22197
  }
@@ -22286,7 +22306,7 @@ var FEATURES = {
22286
22306
  packages: [],
22287
22307
  steps: [
22288
22308
  "Events use PostgreSQL LISTEN/NOTIFY \u2014 built into the database",
22289
- "Create database trigger functions for table change notifications",
22309
+ "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
22310
  "Set up a listener Lambda with persistent database connection",
22291
22311
  "Add WebSocket fan-out for client delivery",
22292
22312
  "Use the useSignal hook in React components for real-time updates"
@@ -22317,8 +22337,8 @@ function registerAddFeaturePrompt(server) {
22317
22337
  `1. Read the ${f.resource} resource for full documentation.`,
22318
22338
  "2. Read everystack://core for architecture context.",
22319
22339
  feature === "auth" || feature === "security" ? "3. Read everystack://security for the security model." : "",
22320
- projectPath ? `4. Run the project_status tool with projectPath="${projectPath}" to understand the current state.` : "",
22321
- projectPath ? `5. Run the project_validate tool with projectPath="${projectPath}" after making changes.` : "",
22340
+ projectPath ? `4. Read the project's CLAUDE.md and structure under "${projectPath}" to understand the current state.` : "",
22341
+ projectPath ? "5. After changes: `pnpm test`, and if the schema changed, `everystack db:check`." : "",
22322
22342
  "",
22323
22343
  "## Steps",
22324
22344
  "",
@@ -22333,7 +22353,7 @@ pnpm add ${f.packages.join(" ")}
22333
22353
  "## After Setup",
22334
22354
  "",
22335
22355
  "- Run tests to verify the integration",
22336
- "- Run project_validate to check for configuration issues",
22356
+ "- If the schema changed, run `everystack db:check`",
22337
22357
  "- Read the relevant resource docs for advanced configuration"
22338
22358
  ].filter(Boolean).join("\n")
22339
22359
  }
@@ -22348,10 +22368,10 @@ pnpm add ${f.packages.join(" ")}
22348
22368
  function registerDesignSchemaPrompt(server) {
22349
22369
  server.prompt(
22350
22370
  "design-schema",
22351
- "Interactive schema design: plain English description \u2192 Drizzle schema + migrations + RLS policies + handler config + testing checklist.",
22371
+ "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
22372
  {
22353
22373
  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 analyze existing schema)")
22374
+ projectPath: external_exports.string().optional().describe("Absolute path to project root (to read the existing db/models/)")
22355
22375
  },
22356
22376
  async ({ description, projectPath }) => {
22357
22377
  return {
@@ -22363,81 +22383,67 @@ function registerDesignSchemaPrompt(server) {
22363
22383
  text: [
22364
22384
  `Design a database schema for: ${description}`,
22365
22385
  "",
22386
+ "IMPORTANT (0.4.0): you declare the schema, you do NOT hand-write it. Tables are",
22387
+ "`defineModel` in `db/models/`; authorization is `can()` abilities on the Model that",
22388
+ "COMPILE to RLS + grants; the handler config is DERIVED from the Models. Never hand-write",
22389
+ "`db/schema.ts`, a SQL migration, `CREATE POLICY`, or `GRANT` \u2014 those are generated.",
22390
+ "",
22366
22391
  "## Instructions",
22367
22392
  "",
22368
- "1. Read everystack://schema-patterns for Drizzle schema conventions.",
22369
- "2. Read everystack://security for RLS policy patterns.",
22370
- "3. Read everystack://handler-options for handler configuration.",
22371
- projectPath ? `4. Run schema_analyze with projectPath="${projectPath}" to understand the existing schema.` : "",
22393
+ "1. Read everystack://schema-patterns for how to declare TABLES (defineModel, field, can, relations).",
22394
+ "2. Read everystack://derived-objects IF the model needs views, materialized views, functions, or triggers.",
22395
+ "3. Read everystack://security for the authorization model (how can() abilities become RLS + grants).",
22396
+ "4. Read everystack://database-operations for how the declaration reaches a database (db:sync on dev).",
22397
+ projectPath ? `5. Read the existing \`db/models/\` under "${projectPath}" to match its conventions before adding to it.` : "",
22372
22398
  "",
22373
22399
  "## Deliverables",
22374
22400
  "",
22375
22401
  "Generate ALL of the following:",
22376
22402
  "",
22377
- "### 1. Drizzle Schema (db/schema.ts)",
22403
+ "### 1. Models (db/models/<table>.ts \u2014 one file per table)",
22378
22404
  "",
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",
22405
+ "Declare each table with `defineModel`, following these conventions:",
22406
+ "- UUID primary keys: `id: field.uuid().primaryKey().defaultRandom()`",
22407
+ "- Timestamps: `createdAt: field.timestamptz().defaultNow().notNull()`",
22408
+ "- Soft delete: a `deletedAt: field.timestamptz()` field opts the table into soft-delete",
22409
+ "- Foreign keys via relations: `field.uuid().references(() => Author)` / `belongsTo`/`hasMany`",
22410
+ "- Sensitive columns: `.private()` (hidden from the API); write-guarded: `.readonly()`",
22411
+ "- Named exports (PascalCase model var, e.g. `export const Post = defineModel('posts', \u2026)`)",
22386
22412
  "",
22387
- "### 2. SQL Migration with RLS",
22413
+ "### 2. Authorization \u2014 `can()` abilities ON each Model (NOT hand-written RLS)",
22388
22414
  "",
22389
- "Generate a custom SQL migration that includes:",
22415
+ "Declare the access pattern as abilities; the compiler emits the RLS policies and GRANTs.",
22416
+ "Every table MUST make its read decision or `db:check` fails it:",
22390
22417
  "",
22391
- "```sql",
22392
- "-- For each table:",
22393
- "ALTER TABLE table_name ENABLE ROW LEVEL SECURITY;",
22394
- "",
22395
- "-- Grant minimum required access per role:",
22396
- "GRANT SELECT ON table_name TO anon;",
22397
- "GRANT SELECT, INSERT, UPDATE, DELETE ON table_name TO authenticated;",
22398
- "GRANT ALL ON table_name TO admin;",
22399
- "",
22400
- "-- Policies per access pattern:",
22401
- "-- Public read:",
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);',
22418
+ "```ts",
22419
+ "abilities: [",
22420
+ " can('read'), // public read (anon + authenticated)",
22421
+ " can('read', { owner: 'authorId' }), // rows the caller owns",
22422
+ " can('manage', { owner: 'authorId' }), // owner can write their own rows",
22423
+ " can('read', { role: 'admin' }), // a specific role only",
22424
+ "],",
22410
22425
  "```",
22411
22426
  "",
22412
- "Adapt the policies to the specific access patterns for each table.",
22427
+ "A private/operational table declares `private: true` (generated, but not a generic-API",
22428
+ "resource). Row ownership, soft-delete, hidden/protected columns, and relations are all",
22429
+ "DERIVED from the Model into the handler config \u2014 do not write a createHandler options blob",
22430
+ "by hand.",
22413
22431
  "",
22414
- "### 3. Handler Configuration",
22432
+ "### 3. Derived objects (only if the model needs compute)",
22415
22433
  "",
22416
- "Generate the createHandler() config snippet:",
22417
- "- `exposedTables`: only tables that should be API-accessible",
22418
- "- `relations`: for embedding related data in API queries",
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",
22434
+ "If the design needs a view, materialized view, function, or trigger, declare it as a",
22435
+ "descriptor in `db/models/derived.ts` per everystack://derived-objects \u2014 NOT as a SQL",
22436
+ "migration. Wire them on `defineModule({ models, derived })`.",
22423
22437
  "",
22424
- "### 4. Testing Checklist",
22438
+ "### 4. Testing + apply checklist",
22425
22439
  "",
22426
- "Generate a testing checklist:",
22427
- "- [ ] Anonymous users can read public data",
22428
- "- [ ] Anonymous users cannot write any data",
22429
- "- [ ] Authenticated users can only read/write their own data",
22440
+ "- [ ] Every table declares a read ability or `private: true` (db:check gate)",
22441
+ "- [ ] Anonymous users can read only what `can('read')` (no owner/role) allows",
22442
+ "- [ ] Owner-scoped rows are invisible and unwritable across users (IDOR)",
22430
22443
  "- [ ] Soft-deleted rows are hidden from normal queries",
22431
- "- [ ] Admin users can access all data",
22432
- "- [ ] Foreign key constraints prevent orphaned rows",
22433
- "- [ ] RLS policies work with pgSettings claim injection",
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
- "```"
22444
+ '- [ ] `everystack db:sync --database-url "$DATABASE_URL"` applies cleanly on a dev DB',
22445
+ "- [ ] `everystack db:check` passes (declared state composes; generated artifacts match)",
22446
+ "- [ ] `everystack db:authz:test --stage dev` proves the compiled RLS enforces the abilities"
22441
22447
  ].filter(Boolean).join("\n")
22442
22448
  }
22443
22449
  }
@@ -22451,7 +22457,7 @@ function registerDesignSchemaPrompt(server) {
22451
22457
  function registerDeployPrompt(server) {
22452
22458
  server.prompt(
22453
22459
  "deploy",
22454
- "Step-by-step deployment walkthrough for a specific stage. Covers AWS credentials, SST deploy, migrations, and verification.",
22460
+ "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
22461
  {
22456
22462
  stage: external_exports.enum(["dev", "staging", "production"]).describe("Deployment stage"),
22457
22463
  projectPath: external_exports.string().optional().describe("Absolute path to project root")
@@ -22471,8 +22477,8 @@ function registerDeployPrompt(server) {
22471
22477
  "",
22472
22478
  "1. Read everystack://deployment for infrastructure setup.",
22473
22479
  "2. Read everystack://security for AWS credential setup and deployment checklist.",
22474
- projectPath ? `3. Run project_validate with projectPath="${projectPath}" to check for issues before deploying.` : "",
22475
- projectPath ? `4. Run project_status with projectPath="${projectPath}" to see current deployment state.` : "",
22480
+ "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.",
22481
+ projectPath ? `4. Run check_environment with projectPath="${projectPath}" to confirm prerequisites (Node, SST, AWS credentials) before deploying.` : "",
22476
22482
  "",
22477
22483
  "## Pre-Deploy Checklist",
22478
22484
  "",
@@ -22495,8 +22501,8 @@ function registerDeployPrompt(server) {
22495
22501
  "### Production Safety",
22496
22502
  "",
22497
22503
  "- [ ] All tests pass: `pnpm test`",
22498
- "- [ ] No security warnings: run project_validate",
22499
- "- [ ] RLS policies are in place for all tables",
22504
+ "- [ ] `everystack db:check` passes (declared state composes; generated artifacts match)",
22505
+ "- [ ] RLS is declared via `can()` abilities on every Model (compiles to policies + grants)",
22500
22506
  "- [ ] pgSettings is configured in handler",
22501
22507
  "- [ ] No hardcoded secrets in source",
22502
22508
  "- [ ] .env files are not committed",
@@ -22517,10 +22523,19 @@ function registerDeployPrompt(server) {
22517
22523
  "- SQS queues (V3)",
22518
22524
  "- IAM roles and policies",
22519
22525
  "",
22520
- "### 3. Database Setup (V2+)",
22526
+ "### 2. Database Schema (V2+) \u2014 the SAFE flow",
22527
+ "",
22528
+ "A protected stage is migrated by minting a reviewable plan and applying it credential-free",
22529
+ "(the operator never holds the database URL). See everystack://database-operations.",
22521
22530
  "```bash",
22522
- `everystack db:migrate --stage ${stage}`,
22523
- stage === "dev" ? `everystack db:seed --stage ${stage} # dev only` : "",
22531
+ `everystack db:check # gate: declared state composes`,
22532
+ `everystack db:plan --stage ${stage} --out ${stage}.plan.json # mint the edge (read-only) \u2014 REVIEW it`,
22533
+ isProduction ? `everystack db:snapshot --stage ${stage} # physical RDS snapshot first (instant rollback)` : "",
22534
+ `everystack db:apply --plan ${stage}.plan.json --stage ${stage} # verify \u2192 apply \u2192 verify`,
22535
+ `# destructive plans (drops / narrowing types) also need: --confirm + a snapshot + the`,
22536
+ `# stage's approver set (everystack db:approvers --stage ${stage} --set "\u2026")`,
22537
+ `everystack db:reconcile --check --stage ${stage} # confirm the compute layer (views/matviews/functions) matches`,
22538
+ stage === "dev" ? `everystack db:seed --stage ${stage} # dev only` : "",
22524
22539
  "```",
22525
22540
  "",
22526
22541
  "### 4. Verify",
@@ -22593,9 +22608,8 @@ function registerDebugPrompt(server) {
22593
22608
  "## Instructions",
22594
22609
  "",
22595
22610
  "1. Read everystack://core for architecture context.",
22596
- projectPath ? `2. Run project_status with projectPath="${projectPath}" to understand the project.` : "",
22597
- projectPath ? `3. Run project_validate with projectPath="${projectPath}" to find configuration issues.` : "",
22598
- projectPath ? `4. Run schema_analyze with projectPath="${projectPath}" to check schema/handler alignment.` : "",
22611
+ projectPath ? `2. Read the project's CLAUDE.md and \`db/models/\` under "${projectPath}" to understand its schema and conventions.` : "",
22612
+ 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
22613
  "",
22600
22614
  "## Diagnostic Framework",
22601
22615
  "",
@@ -22696,7 +22710,7 @@ function registerDebugPrompt(server) {
22696
22710
  "1. Identify the root cause",
22697
22711
  "2. Propose a fix with the specific code change",
22698
22712
  "3. Verify the fix resolves the issue",
22699
- "4. Run project_validate to ensure no new issues were introduced"
22713
+ "4. Run `pnpm test` and (for schema changes) `everystack db:check` to ensure no new issues were introduced"
22700
22714
  ].filter(Boolean).join("\n")
22701
22715
  }
22702
22716
  }
@@ -22732,8 +22746,8 @@ function registerSecurePrompt(server) {
22732
22746
  "",
22733
22747
  "1. Read everystack://security for the complete security model.",
22734
22748
  "2. Read everystack://auth for JWT authentication details.",
22735
- projectPath ? `3. Run project_validate with projectPath="${projectPath}" to find existing security gaps.` : "",
22736
- projectPath ? `4. Run schema_analyze with projectPath="${projectPath}" to check schema security.` : "",
22749
+ projectPath ? `3. Read the project's \`db/models/\` under "${projectPath}" \u2014 the \`can()\` abilities ARE the authorization; confirm every table declares a read decision.` : "",
22750
+ 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
22751
  "",
22738
22752
  requested.includes("aws") ? [
22739
22753
  "## AWS IAM Profiles",
@@ -22914,7 +22928,7 @@ function registerSecurePrompt(server) {
22914
22928
  "",
22915
22929
  "After setup, verify security:",
22916
22930
  "",
22917
- "1. Run project_validate to check for gaps",
22931
+ "1. Run `everystack db:doctor` and `everystack db:authz:test --stage dev` to prove the RLS enforces the declared abilities",
22918
22932
  "2. Test unauthenticated access returns 401",
22919
22933
  "3. Test cross-user data isolation with RLS",
22920
22934
  "4. Verify JWT claims propagate through pgSettings",
@@ -23402,6 +23416,7 @@ function renderFinding(f) {
23402
23416
  var import_path2 = require("path");
23403
23417
  var MIGRATION_SQL = /(?:^|\/)(?:drizzle|migrations)\/[^/]+\.sql$/i;
23404
23418
  var GENERATED_SCHEMA = /schema\.generated\.tsx?$/;
23419
+ var RETIRED_DB_SQL = /(?:^|\/)db\/sql\/[^/]+\.sql$/i;
23405
23420
  function rel(ctx, p) {
23406
23421
  try {
23407
23422
  return (0, import_path2.relative)(ctx.cwd, p) || p;
@@ -23413,8 +23428,8 @@ var handWrittenMigration = {
23413
23428
  id: "hand-written-migration",
23414
23429
  tier: "framework",
23415
23430
  severity: "deny",
23416
- guide: "Nobody authors migrations. Schema changes have three homes: tables/constraints/authz are declared in db/models/ (edit the Model, then `everystack db:sync` on dev \u2014 protected stages take `db:plan` \u2192 `db:apply`); functions/views/matviews are authored in db/sql/ (deployed by db:reconcile/db:sync); one-shot DATA moves are authored in db/backfills/*.sql (run via db:backfill, never as a schema side effect). No migration file, ever \u2014 and generated artifacts (schema.generated.ts) are never edited.",
23417
- conform: "edit db/models/ then `everystack db:sync` (dev) or `db:plan` \u2192 `db:apply` (protected) \xB7 db/sql/ for derived objects \xB7 db/backfills/ for data moves",
23431
+ 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.",
23432
+ 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
23433
  verify: "everystack db:check passes (declared state composes; generated artifacts match regeneration) AND everystack db:fingerprint reports MATCH",
23419
23434
  detect(ctx) {
23420
23435
  if (ctx.tool !== "Write" && ctx.tool !== "Edit") return null;
@@ -23422,6 +23437,7 @@ var handWrittenMigration = {
23422
23437
  if (!p) return null;
23423
23438
  if (MIGRATION_SQL.test(p)) return `${rel(ctx, p)} is a SQL migration being written by hand`;
23424
23439
  if (GENERATED_SCHEMA.test(p)) return `${rel(ctx, p)} is a generated artifact (compiled from your Models \u2014 db:check refuses hand edits)`;
23440
+ 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
23441
  return null;
23426
23442
  }
23427
23443
  };
@@ -23707,7 +23723,7 @@ async function runGovernanceCli(argv) {
23707
23723
  }
23708
23724
 
23709
23725
  // src/index.ts
23710
- var version2 = (true ? "0.3.3" : null) ?? "0.3.0-dev";
23726
+ var version2 = (true ? "0.4.1" : null) ?? "0.3.0-dev";
23711
23727
  var INSTRUCTIONS = [
23712
23728
  "You govern how any agent builds everystack \u2014 a self-hosted application stack for Expo apps on AWS.",
23713
23729
  "Your job is not only to advise but to keep the build on-script: the architecture the maintainer",
@@ -23769,7 +23785,7 @@ var INSTRUCTIONS = [
23769
23785
  "1. Read everystack://core for architecture and conventions.",
23770
23786
  "2. Read everystack://security before any deployment or auth guidance.",
23771
23787
  "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 three homes: tables/constraints/authz are DECLARED in `db/models/` (edit the Model, then `everystack db:sync` moves the dev database to the checkout \u2014 verified by fingerprint); functions/views/matviews are authored in `db/sql/` (deployed by `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_*`.',
23788
+ '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
23789
  '5. When the user wants to start a new project, run check_environment (phase "local" for dev, "deploy" for deployment) to verify prerequisites.',
23774
23790
  "6. When the user needs to interact with deployed infrastructure, guide them to use the everystack CLI."
23775
23791
  ].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 three homes.** Tables and authz are DECLARED
23
- in `db/models/` with `defineModel` edit the Model, then `everystack db:sync` moves the
24
- dev database to your checkout (state + authz + derived, fingerprint-verified). Functions,
25
- views, and matviews are **authored** in `db/sql/` and deployed by `db:reconcile`/`db:sync`.
26
- One-shot DATA moves are authored in `db/backfills/*.sql` and run via `everystack
27
- db:backfill` deliberately, never as a schema side effect. Never hand-write a SQL
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 (the source of truth for schema + authz)
46
- - `db/sql/` — functions, views, matviews (authored SQL; deploys via `db:reconcile`/`db:sync`)
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) is the exception that proves the rule: that SQL is authored, in `db/sql/`,
88
- and *deployed* by reconcile hand-edits straight against the database surface as drift, and a
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/sql/` and run `db:reconcile`.
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.