create-nextblock 0.17.0 → 0.17.2

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.
@@ -178,11 +178,17 @@ Production rule:
178
178
  - Add a new forward-only `.sql` file under
179
179
  `libs/db/src/supabase/migrations` for each production schema/data change.
180
180
  - Use `npm run db:migrate:check` before `npm run db:migrate`.
181
- - If `db:migrate:check` lists historical baseline migrations such as
182
- `00000000000000_setup_foundation_and_enums.sql` on an existing production database, do
183
- not run `db:migrate` yet. Run `npm run db:migrate:repair-history:check`,
184
- then `npm run db:migrate:repair-history`, then check again. The expected
185
- result after repair is that only new unapplied migrations remain.
181
+ - Migration files are named `GGNNN_<snake_name>.sql` (GG = squash generation, NNN =
182
+ sequence, contiguous). The next number is the highest sequence on disk + 1 in the same
183
+ generation; `db:migrate:check` prints it and fails on any other name shape. See
184
+ [04-DATABASE-AND-AUTH.md](./04-DATABASE-AND-AUTH.md) "Migration Structure".
185
+ - If `db:migrate:check` lists the generation baseline (`02001_baseline_schema.sql` …) as
186
+ pending on an existing database whose history is empty, do not run `db:migrate` yet.
187
+ Run `npm run db:migrate:repair-history:check`, then `npm run db:migrate:repair-history`,
188
+ then check again. If instead it shows retired 14-digit versions "recorded remotely with
189
+ no local file" beside the pending baseline, the database has not crossed the squash:
190
+ run `npm run db:migrate:repair-history:check -- --reconcile-squash`, then the same without
191
+ `:check`. The expected result after either repair is that only new unapplied migrations remain.
186
192
  - Do not use `npm run db:reset`, `npm run sandbox:reset`,
187
193
  `npm run db:migrate:fresh`, or `npm run db:push:sandbox` against production.
188
194
 
@@ -198,9 +204,10 @@ The migration-only script:
198
204
  - runs `supabase db push` without `--include-all`
199
205
  - never runs a reset, seed script, function deploy, or config push
200
206
 
201
- Because the migration set started as a squashed baseline, contributors should
202
- treat the existing baseline files as grouped domains. New production changes
203
- after the baseline should be appended as new migrations.
207
+ The migration set is a squashed baseline (one generation at a time — see
208
+ [04-DATABASE-AND-AUTH.md](./04-DATABASE-AND-AUTH.md) "Migration Structure"). Treat the
209
+ baseline files as grouped domains and append every new production change as a new
210
+ `GGNNN` migration; never edit the baseline or the catch-up.
204
211
 
205
212
  ## Sandbox Reset Operations
206
213
 
@@ -82,7 +82,7 @@ Known incomplete or future work:
82
82
 
83
83
  | File | Purpose |
84
84
  | --- | --- |
85
- | `libs/db/src/supabase/migrations/00000000000011_setup_cortex_ai_settings.sql` | RLS hardening for the sensitive `site_settings` Cortex AI key row. |
85
+ | `libs/db/src/supabase/migrations/02003_baseline_security_and_grants.sql` (originally `00000000000011_setup_cortex_ai_settings`, folded in by the generation-2 squash) | RLS hardening for the sensitive `site_settings` Cortex AI key row. |
86
86
  | `apps/nextblock/app/api/cron/reset-sandbox/route.ts` | Sandbox reset route. Upserts active package activation for `cortex-ai` when `FREEMIUS_AI_SANDBOX_KEY` exists. |
87
87
  | `apps/nextblock/app/api/cron/reset-sandbox/sandboxResetSql.ts` | Generated SQL bundle that includes the Cortex AI migration. |
88
88
 
@@ -271,7 +271,7 @@ The value is a JSON envelope:
271
271
  }
272
272
  ```
273
273
 
274
- The migration `00000000000011_setup_cortex_ai_settings.sql` hardens RLS:
274
+ The migration `libs/db/src/supabase/migrations/02003_baseline_security_and_grants.sql` (originally `00000000000011_setup_cortex_ai_settings`, folded in by the generation-2 squash) hardens RLS:
275
275
 
276
276
  - Public users can read non-sensitive site settings.
277
277
  - The sensitive Cortex AI key row is readable only by authenticated admins.
@@ -1061,7 +1061,7 @@ Cortex can insert real photos into pages at zero inference cost, and external im
1061
1061
  - In `libs/cortex/src/lib/ai-global-agent-tools.ts`; registered in `createCortexGlobalAgentTools`.
1062
1062
  - Input: `{ query: string, count?: 1-15 (default 6), orientation?: 'landscape'|'portrait'|'square' }`.
1063
1063
  - Key resolution: `resolveCortexAiStockPhotoProvider(supabase)` prefers an admin-stored, encrypted key in `site_settings` (`cortex_ai_pexels_api_key` / `cortex_ai_unsplash_access_key`, read via the service-role client), then falls back to the `PEXELS_API_KEY` / `UNSPLASH_ACCESS_KEY` env vars. Pexels wins when both exist. Returns a clear "not configured" message if neither is set. Both are free API keys.
1064
- - The stored keys are protected by migration `00000000000012_cortex_ai_stock_photo_settings.sql`, which adds them to the `site_settings` sensitive-keys RLS group (admin-only read/write, never anon-readable), and encrypted with the same envelope as the OpenRouter BYOK key.
1064
+ - The stored keys are protected by migration `libs/db/src/supabase/migrations/02003_baseline_security_and_grants.sql` (originally `00000000000012_cortex_ai_stock_photo_settings`, folded in by the generation-2 squash), which adds them to the `site_settings` sensitive-keys RLS group (admin-only read/write, never anon-readable), and encrypted with the same envelope as the OpenRouter BYOK key.
1065
1065
  - **The model is told up front whether stock photos are available.** The global-agent route resolves the provider and injects it into the system prompt: available → "use search_stock_photos"; not configured → "do NOT call search_stock_photos; use gradient/theme backgrounds." So a missing key never wastes a tool call, and the keys are never mandatory — Cortex builds pages either way.
1066
1066
  - Admin UI: `/cms/settings/cortex-ai` has a Stock Photos card (save/clear Pexels + Unsplash keys, step-by-step, and why) via `saveStockPhotoKeysAction` / `clearStockPhotoKeysAction`.
1067
1067
  - Rate-limit fallback: `resolveCortexAiStockPhotoProviders` returns ALL configured providers ordered Pexels→Unsplash; `executeSearchStockPhotos` tries them in order, falling through to the next on error/HTTP 429/empty results, and returns `attemptedProviders`.
@@ -1106,7 +1106,7 @@ from inside the editor.
1106
1106
  | `apps/nextblock/app/cms/settings/cortex-ai/mcp-actions.ts` | Admin server actions: settings, mint, revoke. |
1107
1107
  | `apps/nextblock/app/cms/settings/cortex-ai/McpServerSettingsCard.tsx` | Settings UI + copy-paste client config. |
1108
1108
  | `apps/nextblock/app/cms/settings/cortex-ai/require-admin.ts` | Shared admin gate (also used by `actions.ts`). |
1109
- | `libs/db/src/supabase/migrations/00000000000017_cortex_ai_mcp_server.sql` | `mcp_access_tokens` table + `cortex_ai_mcp_settings` RLS. |
1109
+ | `libs/db/src/supabase/migrations/02003_baseline_security_and_grants.sql` (originally `00000000000017_cortex_ai_mcp_server`, folded in by the generation-2 squash) | `mcp_access_tokens` table + `cortex_ai_mcp_settings` RLS. |
1110
1110
 
1111
1111
  ### Protocol decisions
1112
1112
 
@@ -1241,7 +1241,7 @@ tools cannot read token hashes or insert rows.
1241
1241
  ### Marketing surfaces that describe the MCP server
1242
1242
 
1243
1243
  Three seeded content rows sell the MCP story and are kept at 100/100 in the built-in SEO
1244
- engine (`libs/utils/src/lib/seo`). Migration `00000000000037_reposition_marketing_and_cortex_mcp.sql`
1244
+ engine (`libs/utils/src/lib/seo`). Migration `libs/db/src/supabase/migrations/02004_baseline_seed.sql` (originally `00000000000037_reposition_marketing_and_cortex_mcp`, folded in by the generation-2 squash)
1245
1245
  owns them; the sandbox reset route (`enrichCortexAiProducts`) mirrors the product sections
1246
1246
  because it deletes and re-inserts product blocks after the SQL replay, so edit both together.
1247
1247
 
@@ -25,7 +25,7 @@ revisions without special-casing.
25
25
  ## Data Model
26
26
 
27
27
  The table is created in
28
- `libs/db/src/supabase/migrations/00000000000023_setup_custom_block_definitions.sql`.
28
+ `libs/db/src/supabase/migrations/02001_baseline_schema.sql` (originally `00000000000023_setup_custom_block_definitions`, folded in by the generation-2 squash).
29
29
 
30
30
  `public.custom_block_definitions`:
31
31
 
@@ -103,7 +103,10 @@ Both named volumes persist your database and uploaded media across restarts.
103
103
  > `public._nextblock_docker_migrations` — a different tracker from the one every other
104
104
  > install uses), so applying the same SQL from the updater as well would run it through two
105
105
  > trackers. The updater refreshes the SQL on disk and hands the schema step to the stack.
106
- > Full details in [docs/13](./13-STAYING-UP-TO-DATE.md).
106
+ > Full details in [docs/13](./13-STAYING-UP-TO-DATE.md). Migration squashes (new
107
+ > `GG000`–`GG004` generations, see [docs/04](./04-DATABASE-AND-AUTH.md)) need nothing
108
+ > extra here: the generation's catch-up file consults `public._nextblock_docker_migrations`
109
+ > by file stem, so it replays only what this stack never applied.
107
110
 
108
111
  ### Ports (override with env vars)
109
112
 
@@ -167,15 +167,18 @@ the question entirely by resolving everything in-app, so the button prompts for
167
167
 
168
168
  ## Cron jobs and the Hobby plan
169
169
 
170
- `vercel.json` declares two crons (`/api/cron/reset-sandbox` at 03:00 and
171
- `/api/cron/sync-currencies` at 18:00). Vercel's **Hobby (free) tier allows up to 100
172
- cron jobs, each running at most once per day** both jobs are daily, so they deploy
173
- fine on the free tier. (Hobby timing is approximate, ±59 min, which is irrelevant for
174
- daily jobs; only sub-daily schedules like `0 * * * *` are rejected on Hobby.)
175
-
176
- `reset-sandbox` only does work in sandbox mode it returns 404 otherwise so on a
177
- normal deploy it is a harmless no-op. Delete it from `vercel.json` if you'd rather not
178
- see it scheduled.
170
+ `vercel.json` declares two crons: `/api/cron/reset-sandbox` **every 15 minutes**
171
+ (`*/15 * * * *`) and `/api/cron/sync-currencies` daily at 18:00 UTC. The 15-minute
172
+ schedule is what keeps the public sandbox at `cms.nextblock.dev` fresh; that project
173
+ runs on **Vercel Pro**, which allows cron schedules down to once per minute with
174
+ per-minute precision.
175
+
176
+ Vercel’s **Hobby (free) tier only allows cron jobs that run at most once per day**
177
+ (timing is approximate, ±59 min), and **a sub-daily schedule fails the deployment**
178
+ outright. So on a Hobby project you must **delete the `reset-sandbox` entry from
179
+ `vercel.json`** before deploying. Nothing is lost: `reset-sandbox` only does work in
180
+ sandbox mode — it returns 404 otherwise — so on a normal deploy it is a harmless
181
+ no-op anyway. `sync-currencies` is daily and deploys fine on Hobby.
179
182
 
180
183
  ## After deploy
181
184
 
@@ -278,6 +278,14 @@ types forward while leaving the schema behind — the app would then fail at run
278
278
  project → `node_modules/@nextblock-cms/db`), deduping by version, so even a user who only
279
279
  ran `npm install` gets the new SQL.
280
280
 
281
+ > **Migration squashes.** Every so often the folder is squashed into a new *generation*
282
+ > (`02000`–`02004`, then `02005+`; see [docs/04](./04-DATABASE-AND-AUTH.md) → "Migration
283
+ > Structure"). An install crosses a squash with no manual step: the new generation's files
284
+ > are simply pending, its `GG000_catchup_*` file replays only the retired migrations this
285
+ > database never recorded, the baseline DDL is idempotent, and the seed skips any database
286
+ > that already holds content. Retired files that linger in `<project>/supabase/migrations`
287
+ > are harmless — they are already recorded, so nothing applies them twice.
288
+
281
289
  ### Build-time migrations
282
290
 
283
291
  A build-time hook ([`apps/nextblock/tools/build-migrate.mjs`](../apps/nextblock/tools/build-migrate.mjs))
@@ -285,8 +285,8 @@ Trusted platform headers (`x-vercel-forwarded-for`, `x-real-ip`) are preferred o
285
285
 
286
286
  ## Files
287
287
 
288
- - `libs/db/src/supabase/migrations/00000000000027_message_threads.sql` — private lane, `form_endpoints`, the form-block data migration
289
- - `libs/db/src/supabase/migrations/00000000000028_interaction_replies.sql` — `parent_id`, the reply CHECK, and the indexes `cms_interactions` never had
288
+ - `libs/db/src/supabase/migrations/02001_baseline_schema.sql` (originally `00000000000027_message_threads`, folded in by the generation-2 squash) — private lane, `form_endpoints`, the form-block data migration
289
+ - `libs/db/src/supabase/migrations/02001_baseline_schema.sql` (originally `00000000000028_interaction_replies`, folded in by the generation-2 squash) — `parent_id`, the reply CHECK, and the indexes `cms_interactions` never had
290
290
  - `apps/nextblock/lib/messages/thread-token.ts` (+ `.test.ts`) — mint, parse, verify
291
291
  - `apps/nextblock/lib/messages/threads.ts` — thread creation, recipient resolution, both notification emails
292
292
  - `apps/nextblock/app/thread/**` — the visitor's page and the token-exchange route