@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/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: "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",
@@ -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/ # Schema, migrations, seed" : "",
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
- `Create db/schema.ts with tables for the ${description}.`,
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
- "- 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",
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. Migrations",
22097
- "- Generate: `npx drizzle-kit generate`",
22098
- "- Add RLS policies in a custom SQL migration",
22099
- "- Reference the RLS templates from everystack://security",
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
- "Include:",
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 the project_validate tool to check for common mistakes.",
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:migrate`" : "",
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
- "Create database trigger functions for table change notifications",
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. 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.` : "",
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
- "- Run project_validate to check for configuration issues",
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 Drizzle schema + migrations + RLS policies + handler config + testing checklist.",
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 analyze existing schema)")
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 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.` : "",
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. Drizzle Schema (db/schema.ts)",
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
- "### 2. SQL Migration with RLS",
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
- "Generate a custom SQL migration that includes:",
22407
+ "### 2. Authorization \u2014 `can()` abilities ON each Model (NOT hand-written RLS)",
22390
22408
  "",
22391
- "```sql",
22392
- "-- For each table:",
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
- "-- 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);',
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
- "Adapt the policies to the specific access patterns for each table.",
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. Handler Configuration",
22426
+ "### 3. Derived objects (only if the model needs compute)",
22415
22427
  "",
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",
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 Checklist",
22432
+ "### 4. Testing + apply checklist",
22425
22433
  "",
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",
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
- "- [ ] 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
- "```"
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, migrations, and verification.",
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
- 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.` : "",
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
- "- [ ] No security warnings: run project_validate",
22499
- "- [ ] RLS policies are in place for all tables",
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
- "### 3. Database Setup (V2+)",
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:migrate --stage ${stage}`,
22523
- stage === "dev" ? `everystack db:seed --stage ${stage} # dev only` : "",
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. 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.` : "",
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 project_validate to ensure no new issues were introduced"
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. Run project_validate with projectPath="${projectPath}" to find existing security gaps.` : "",
22736
- projectPath ? `4. Run schema_analyze with projectPath="${projectPath}" to check schema security.` : "",
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 project_validate to check for gaps",
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 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",
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.3.3" : null) ?? "0.3.0-dev";
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 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_*`.',
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 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.