create-nextblock 0.16.4 → 0.17.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.
Files changed (203) hide show
  1. package/CLAUDE.md +22 -0
  2. package/docker-template/.env.docker.example +69 -69
  3. package/docker-template/docker/db/init/99-jwt.sql +6 -6
  4. package/docker-template/docker/db/init/99-roles.sql +25 -25
  5. package/docker-template/docker/kong/kong.yml +112 -112
  6. package/docker-template/scripts/docker-setup.mjs +310 -310
  7. package/package.json +1 -1
  8. package/templates/nextblock-template/.browserslistrc +11 -11
  9. package/templates/nextblock-template/.swcrc +30 -30
  10. package/templates/nextblock-template/CLAUDE.md +26 -0
  11. package/templates/nextblock-template/app/(auth-pages)/sign-up/page.tsx +46 -46
  12. package/templates/nextblock-template/app/(auth-pages)/two-factor/page.tsx +51 -51
  13. package/templates/nextblock-template/app/.well-known/ucp/route.ts +16 -16
  14. package/templates/nextblock-template/app/actions/consent.ts +57 -57
  15. package/templates/nextblock-template/app/actions/twoFactorEmail.ts +22 -22
  16. package/templates/nextblock-template/app/api/ai/cortex/build-widget/route.ts +153 -153
  17. package/templates/nextblock-template/app/api/ai/generate-blocks/route.ts +96 -96
  18. package/templates/nextblock-template/app/api/brand/email-logo/route.ts +48 -48
  19. package/templates/nextblock-template/app/api/checkout/freemius/sync/route.ts +29 -29
  20. package/templates/nextblock-template/app/api/cms/check-updates/route.ts +44 -44
  21. package/templates/nextblock-template/app/api/cms/full-backup/export/route.ts +33 -33
  22. package/templates/nextblock-template/app/api/cms/full-backup/restore/route.ts +63 -63
  23. package/templates/nextblock-template/app/api/cron/reset-sandbox/route.ts +272 -205
  24. package/templates/nextblock-template/app/api/cron/reset-sandbox/sandboxResetSql.ts +10473 -8467
  25. package/templates/nextblock-template/app/api/cron/sync-currencies/route.ts +39 -39
  26. package/templates/nextblock-template/app/api/custom-blocks/db-relations/route.ts +92 -92
  27. package/templates/nextblock-template/app/api/custom-blocks/editor-definitions/route.ts +43 -43
  28. package/templates/nextblock-template/app/api/media/library/route.ts +69 -69
  29. package/templates/nextblock-template/app/api/media/r2-presigned/route.ts +53 -53
  30. package/templates/nextblock-template/app/api/visual-editing/block-draft/route.ts +47 -47
  31. package/templates/nextblock-template/app/api/visual-editing/product-draft/route.ts +47 -47
  32. package/templates/nextblock-template/app/article/[slug]/PostClientContent.tsx +442 -441
  33. package/templates/nextblock-template/app/article/[slug]/page.utils.ts +4 -1
  34. package/templates/nextblock-template/app/checkout/UcpCartHydrator.tsx +20 -20
  35. package/templates/nextblock-template/app/cms/blocks/components/BlockEditorModal.tsx +241 -241
  36. package/templates/nextblock-template/app/cms/blocks/components/CustomBlockEditorPreview.tsx +160 -160
  37. package/templates/nextblock-template/app/cms/blocks/editors/DynamicCustomBlockEditor.tsx +167 -167
  38. package/templates/nextblock-template/app/cms/components/ConnectGitHubButton.tsx +122 -122
  39. package/templates/nextblock-template/app/cms/components/CortexAiActiveContext.tsx +23 -23
  40. package/templates/nextblock-template/app/cms/components/SeoScoreBadge.tsx +3 -3
  41. package/templates/nextblock-template/app/cms/components/SystemAlertsBanner.tsx +112 -112
  42. package/templates/nextblock-template/app/cms/components/TablePagination.tsx +136 -136
  43. package/templates/nextblock-template/app/cms/components/TwoFactorReminderBanner.tsx +45 -45
  44. package/templates/nextblock-template/app/cms/components/github-connect-actions.ts +102 -102
  45. package/templates/nextblock-template/app/cms/components/system-alerts-actions.ts +31 -31
  46. package/templates/nextblock-template/app/cms/coupons/[id]/edit/page.tsx +16 -16
  47. package/templates/nextblock-template/app/cms/coupons/page.tsx +16 -16
  48. package/templates/nextblock-template/app/cms/custom-blocks/[id]/edit/page.tsx +66 -66
  49. package/templates/nextblock-template/app/cms/custom-blocks/actions.ts +519 -519
  50. package/templates/nextblock-template/app/cms/custom-blocks/components/BlocksLibraryTransferControls.tsx +256 -256
  51. package/templates/nextblock-template/app/cms/custom-blocks/components/DBRelationSelect.tsx +384 -384
  52. package/templates/nextblock-template/app/cms/custom-blocks/components/ImageR2Picker.tsx +221 -221
  53. package/templates/nextblock-template/app/cms/custom-blocks/new/page.tsx +12 -12
  54. package/templates/nextblock-template/app/cms/custom-blocks/page.tsx +438 -438
  55. package/templates/nextblock-template/app/cms/dashboard/components/DashboardComponents.tsx +200 -200
  56. package/templates/nextblock-template/app/cms/dashboard/components/DashboardOnboarding.tsx +130 -130
  57. package/templates/nextblock-template/app/cms/import-export/actions.ts +226 -226
  58. package/templates/nextblock-template/app/cms/pages/page.tsx +273 -273
  59. package/templates/nextblock-template/app/cms/posts/page.tsx +251 -251
  60. package/templates/nextblock-template/app/cms/products/categories/page.tsx +12 -12
  61. package/templates/nextblock-template/app/cms/products/new/page.tsx +135 -135
  62. package/templates/nextblock-template/app/cms/promotions/PromotionsWorkspace.tsx +456 -456
  63. package/templates/nextblock-template/app/cms/promotions/actions.ts +115 -115
  64. package/templates/nextblock-template/app/cms/promotions/page.tsx +31 -31
  65. package/templates/nextblock-template/app/cms/settings/backup-restore/BackupRestoreWorkspace.tsx +1004 -1004
  66. package/templates/nextblock-template/app/cms/settings/backup-restore/page.tsx +29 -29
  67. package/templates/nextblock-template/app/cms/settings/bot-protection/page.tsx +24 -24
  68. package/templates/nextblock-template/app/cms/settings/email/page.tsx +28 -28
  69. package/templates/nextblock-template/app/cms/settings/extra-translations/actions.ts +276 -276
  70. package/templates/nextblock-template/app/cms/settings/google-analytics/page.tsx +26 -26
  71. package/templates/nextblock-template/app/cms/settings/logos/components/DeleteLogoButton.tsx +21 -21
  72. package/templates/nextblock-template/app/cms/settings/logos/components/SetActiveLogoButton.tsx +42 -42
  73. package/templates/nextblock-template/app/cms/settings/logos/components/SiteSeoSettingsForm.tsx +133 -133
  74. package/templates/nextblock-template/app/cms/settings/privacy/page.tsx +27 -27
  75. package/templates/nextblock-template/app/cms/settings/registration/page.tsx +27 -27
  76. package/templates/nextblock-template/app/cms/settings/security/page.tsx +33 -33
  77. package/templates/nextblock-template/app/lib/site-settings.ts +105 -105
  78. package/templates/nextblock-template/app/lib/ucp/protocol.ts +190 -190
  79. package/templates/nextblock-template/app/lib/ucp/server.test.ts +56 -56
  80. package/templates/nextblock-template/app/setup/SetupWizard.tsx +678 -678
  81. package/templates/nextblock-template/app/setup/layout.tsx +13 -13
  82. package/templates/nextblock-template/app/setup/page.tsx +111 -111
  83. package/templates/nextblock-template/app/ucp/v1/carts/[id]/cancel/route.ts +38 -38
  84. package/templates/nextblock-template/app/ucp/v1/carts/[id]/route.ts +68 -68
  85. package/templates/nextblock-template/app/ucp/v1/carts/route.ts +35 -35
  86. package/templates/nextblock-template/app/ucp/v1/catalog/lookup/route.ts +35 -35
  87. package/templates/nextblock-template/app/ucp/v1/catalog/product/route.ts +35 -35
  88. package/templates/nextblock-template/app/ucp/v1/catalog/search/route.ts +34 -34
  89. package/templates/nextblock-template/components/CartTranslator.tsx +210 -210
  90. package/templates/nextblock-template/components/DeferredCartTranslator.tsx +51 -51
  91. package/templates/nextblock-template/components/DeferredGlobalSearch.tsx +68 -68
  92. package/templates/nextblock-template/components/DeferredGoogleAnalytics.tsx +70 -70
  93. package/templates/nextblock-template/components/FeatureImageHero.tsx +47 -47
  94. package/templates/nextblock-template/components/GlobalSearch.tsx +557 -557
  95. package/templates/nextblock-template/components/Header.tsx +38 -38
  96. package/templates/nextblock-template/components/PublicEnvBootstrap.tsx +30 -30
  97. package/templates/nextblock-template/components/ResponsiveNav.tsx +14 -14
  98. package/templates/nextblock-template/components/auth/AuthBotProtection.tsx +182 -182
  99. package/templates/nextblock-template/components/blocks/PostsGridClient.tsx +48 -48
  100. package/templates/nextblock-template/components/blocks/TestimonialBlock.tsx +9 -9
  101. package/templates/nextblock-template/components/blocks/publicRendererLoaders.ts +25 -25
  102. package/templates/nextblock-template/components/blocks/renderers/ButtonBlockRenderer.tsx +92 -92
  103. package/templates/nextblock-template/components/blocks/renderers/ClientTextBlockRenderer.tsx +11 -0
  104. package/templates/nextblock-template/components/blocks/renderers/PostsGridBlockRenderer.tsx +24 -24
  105. package/templates/nextblock-template/components/blocks/renderers/TestimonialBlockRenderer.tsx +57 -57
  106. package/templates/nextblock-template/components/blocks/renderers/inline/AlertWidgetRenderer.tsx +2 -2
  107. package/templates/nextblock-template/components/blocks/renderers/inline/CtaWidgetRenderer.tsx +2 -2
  108. package/templates/nextblock-template/components/media/YouTubeFacade.tsx +105 -105
  109. package/templates/nextblock-template/components/media/youtube-embed-replace.tsx +32 -32
  110. package/templates/nextblock-template/components/privacy/ConsentBanner.tsx +170 -170
  111. package/templates/nextblock-template/components/privacy/ConsentGatedAnalytics.tsx +70 -70
  112. package/templates/nextblock-template/components/renderers/CachedDynamicLayoutEngine.tsx +28 -28
  113. package/templates/nextblock-template/components/renderers/DynamicLayoutEngine.test.tsx +166 -166
  114. package/templates/nextblock-template/components/renderers/DynamicLayoutEngine.tsx +471 -471
  115. package/templates/nextblock-template/components/visual-editing/DeferredVisualEditing.tsx +21 -21
  116. package/templates/nextblock-template/context/language-rest-client.ts +32 -32
  117. package/templates/nextblock-template/docker/db/init/99-jwt.sql +6 -6
  118. package/templates/nextblock-template/docker/db/init/99-roles.sql +25 -25
  119. package/templates/nextblock-template/docker/kong/kong.yml +112 -112
  120. package/templates/nextblock-template/docs/02-ECOMMERCE-CAPABILITIES.md +364 -364
  121. package/templates/nextblock-template/docs/03-CMS-AND-EDITOR.md +1 -1
  122. package/templates/nextblock-template/docs/04-DATABASE-AND-AUTH.md +402 -282
  123. package/templates/nextblock-template/docs/05-DEVELOPER-GUIDE.md +15 -8
  124. package/templates/nextblock-template/docs/07-BLOCK-SDK-AND-EXTENSIBILITY.md +146 -146
  125. package/templates/nextblock-template/docs/08-NEXTBLOCK-CORTEX-AI-ARCHITECTURE.md +23 -4
  126. package/templates/nextblock-template/docs/10-CUSTOM-BLOCKS.md +222 -222
  127. package/templates/nextblock-template/docs/11-SELF-HOSTED-DOCKER.md +4 -1
  128. package/templates/nextblock-template/docs/13-STAYING-UP-TO-DATE.md +8 -0
  129. package/templates/nextblock-template/docs/14-MESSAGES-INBOX.md +2 -2
  130. package/templates/nextblock-template/docs/TECHNICAL_SPECIFICATION.md +95 -104
  131. package/templates/nextblock-template/lib/app-secrets.ts +39 -39
  132. package/templates/nextblock-template/lib/auth/cookies.ts +47 -47
  133. package/templates/nextblock-template/lib/auth/crypto.ts +45 -45
  134. package/templates/nextblock-template/lib/auth/trustedDevices.ts +92 -92
  135. package/templates/nextblock-template/lib/blocks/README.md +13 -13
  136. package/templates/nextblock-template/lib/botProtection/verify.ts +134 -134
  137. package/templates/nextblock-template/lib/cms/payments-reminder.test.ts +135 -135
  138. package/templates/nextblock-template/lib/cms/payments-reminder.ts +105 -105
  139. package/templates/nextblock-template/lib/cms-transfer/types.ts +145 -145
  140. package/templates/nextblock-template/lib/custom-block-definitions.ts +87 -87
  141. package/templates/nextblock-template/lib/custom-block-r2-upload-shared.ts +178 -178
  142. package/templates/nextblock-template/lib/custom-block-r2-upload.test.ts +140 -140
  143. package/templates/nextblock-template/lib/custom-block-r2-upload.ts +88 -88
  144. package/templates/nextblock-template/lib/custom-block-relations.test.ts +227 -227
  145. package/templates/nextblock-template/lib/custom-block-relations.ts +279 -279
  146. package/templates/nextblock-template/lib/custom-block-safelist.ts +14 -14
  147. package/templates/nextblock-template/lib/editor/dynamic-extension-core.test.ts +172 -172
  148. package/templates/nextblock-template/lib/editor/dynamic-extension-core.ts +213 -213
  149. package/templates/nextblock-template/lib/editor/dynamic-extension-loader.ts +22 -22
  150. package/templates/nextblock-template/lib/editor/dynamic-extensions.tsx +193 -193
  151. package/templates/nextblock-template/lib/email/branding-format.test.ts +133 -133
  152. package/templates/nextblock-template/lib/email/branding-format.ts +123 -123
  153. package/templates/nextblock-template/lib/email/branding.ts +76 -76
  154. package/templates/nextblock-template/lib/full-backup/manifest.test.ts +121 -121
  155. package/templates/nextblock-template/lib/full-backup/manifest.ts +206 -206
  156. package/templates/nextblock-template/lib/logos/active-logo.ts +53 -53
  157. package/templates/nextblock-template/lib/media/resolveMediaUrl.ts +56 -54
  158. package/templates/nextblock-template/lib/media/youtube.ts +99 -99
  159. package/templates/nextblock-template/lib/onboarding/actions.ts +31 -31
  160. package/templates/nextblock-template/lib/privacy/consent-client.ts +57 -57
  161. package/templates/nextblock-template/lib/privacy/contact-emails.ts +64 -64
  162. package/templates/nextblock-template/lib/privacy/settings.ts +115 -115
  163. package/templates/nextblock-template/lib/privacy/types.ts +69 -69
  164. package/templates/nextblock-template/lib/promotions/server.test.ts +74 -74
  165. package/templates/nextblock-template/lib/promotions/server.ts +741 -741
  166. package/templates/nextblock-template/lib/resolve-block-relations.test.ts +142 -142
  167. package/templates/nextblock-template/lib/resolve-block-relations.ts +255 -255
  168. package/templates/nextblock-template/lib/seo/page-document.ts +4 -4
  169. package/templates/nextblock-template/lib/seo/redirect-store.ts +3 -2
  170. package/templates/nextblock-template/lib/setup/actions.ts +460 -460
  171. package/templates/nextblock-template/lib/setup/env-status.ts +125 -125
  172. package/templates/nextblock-template/lib/setup/env-write.ts +111 -111
  173. package/templates/nextblock-template/lib/setup/migrations-bundle.ts +15 -175
  174. package/templates/nextblock-template/lib/setup/provisioning.ts +59 -59
  175. package/templates/nextblock-template/lib/setup/schema-apply.ts +408 -408
  176. package/templates/nextblock-template/lib/setup/system-config.ts +105 -105
  177. package/templates/nextblock-template/lib/setup/types.ts +18 -18
  178. package/templates/nextblock-template/lib/storage/provider.ts +66 -66
  179. package/templates/nextblock-template/lib/storage/supabase-storage.ts +103 -103
  180. package/templates/nextblock-template/lib/updates/github-device.ts +206 -206
  181. package/templates/nextblock-template/lib/updates/repo-identity.ts +56 -56
  182. package/templates/nextblock-template/lib/visual-editing/draft-content.test.ts +105 -105
  183. package/templates/nextblock-template/lib/visual-editing/draft-route.test.ts +42 -42
  184. package/templates/nextblock-template/lib/visual-editing/edit-info.test.ts +143 -143
  185. package/templates/nextblock-template/lib/visual-editing/edit-info.ts +94 -94
  186. package/templates/nextblock-template/lib/visual-editing/product-drafts.test.ts +81 -81
  187. package/templates/nextblock-template/lib/zod-config.ts +5 -5
  188. package/templates/nextblock-template/next-env.d.ts +1 -0
  189. package/templates/nextblock-template/package.json +1 -1
  190. package/templates/nextblock-template/public/images/cortex_post.webp +0 -0
  191. package/templates/nextblock-template/public/images/update_nextblock.webp +0 -0
  192. package/templates/nextblock-template/scripts/docker-setup.mjs +310 -310
  193. package/templates/nextblock-template/scripts/validate-editor-block-schema.ts +112 -112
  194. package/templates/nextblock-template/scripts/verify-cortex-ai-build-widget.tsx +98 -98
  195. package/templates/nextblock-template/scripts/verify-cortex-ai-generate-blocks.ts +62 -62
  196. package/templates/nextblock-template/scripts/verify-cortex-ai-global-tools.ts +537 -537
  197. package/templates/nextblock-template/scripts/verify-cortex-ai-routing.ts +58 -58
  198. package/templates/nextblock-template/scripts/verify-custom-block-definitions.ts +188 -188
  199. package/templates/nextblock-template/scripts/verify-dynamic-custom-block-extensions.ts +123 -123
  200. package/templates/nextblock-template/scripts/verify-dynamic-layout-engine.tsx +133 -133
  201. package/templates/nextblock-template/scripts/verify-milestone-2-custom-blocks.ts +65 -65
  202. package/templates/nextblock-template/tools/deploy-supabase.js +159 -159
  203. package/templates/nextblock-template/types/jsdom.d.ts +6 -6
@@ -27,7 +27,7 @@ The core problem statement — "stop cloning heavy repos; start with our CLI and
27
27
 
28
28
  ### 1.1.3 Key Stakeholders and Users
29
29
 
30
- The system recognizes three database-enforced user roles (defined as the `user_role` enum `ADMIN`, `WRITER`, `USER` in migration `00000000000000_setup_foundation_and_enums.sql`) and three additional implicit stakeholder classes observable from the scaffolding and documentation artifacts.
30
+ The system recognizes three database-enforced user roles (defined as the `user_role` enum `ADMIN`, `WRITER`, `USER` in migration `02001_baseline_schema.sql`) and three additional implicit stakeholder classes observable from the scaffolding and documentation artifacts.
31
31
 
32
32
  | Stakeholder | Role / Audience | Primary Entry Point |
33
33
  |:--|:--|:--|
@@ -267,7 +267,7 @@ The following architectural invariants are enforced at workspace level and must
267
267
 
268
268
  **Editor Capabilities** — The `@nextblock-cms/editor` library exports `Editor`, `NotionEditor`, `EditorToolbar`, `EditorBubbleMenu`, `EditorFloatingMenu`, `EnhancedFloatingMenu`, `SlashCommandList`, `DragHandle`, `HtmlContent`, and `editorExtensions`. Feature set includes Tiptap StarterKit rich text, syntax-highlighted code blocks, tables, task lists, slash commands, drag handles, image handling, character counting, typography, mathematics, emoji, mentions, inline alert and call-to-action widgets, and custom HTML-preserving extensions for `div`, `style`, `script`, `svg`, `span`, and catch-all attribute preservation. A media-picker bridge is exposed via `setOpenImagePicker()`.
269
269
 
270
- **Translation & Localization** — The set of served locales is the active rows of the `languages` table (managed at `/cms/settings/languages`; the proxy reads them with a 60-second in-memory cache and only falls back to the hardcoded `FALLBACK_LOCALES` `en`/`fr` when the DB is unreadable), backed by `languages` and `translations` tables from migration `00000000000001_setup_cms_core.sql`. First-visit language detection is admin-configurable (see F-007): browser `Accept-Language`, IP-country via host geo headers, combined, or always-default — implemented in `apps/nextblock/lib/i18n/detection.ts` and stored in `site_settings.language_detection_settings`. Content revision history is stored as snapshot + JSON Patch diff (enum `revision_type: snapshot, diff`) per migration `00000000000002_setup_content_tables.sql`.
270
+ **Translation & Localization** — The set of served locales is the active rows of the `languages` table (managed at `/cms/settings/languages`; the proxy reads them with a 60-second in-memory cache and only falls back to the hardcoded `FALLBACK_LOCALES` `en`/`fr` when the DB is unreadable), backed by `languages` and `translations` tables from migration `02001_baseline_schema.sql`. First-visit language detection is admin-configurable (see F-007): browser `Accept-Language`, IP-country via host geo headers, combined, or always-default — implemented in `apps/nextblock/lib/i18n/detection.ts` and stored in `site_settings.language_detection_settings`. Content revision history is stored as snapshot + JSON Patch diff (enum `revision_type: snapshot, diff`) per migration `02001_baseline_schema.sql`.
271
271
 
272
272
  **Page Lifecycle** — Pages move through `draft`, `published`, and `archived` statuses (enum `page_status`).
273
273
 
@@ -343,7 +343,7 @@ Profile completion is enforced via a redirect: users without a `full_name` value
343
343
 
344
344
  #### 1.3.2.3 Geographic and Market Coverage
345
345
 
346
- Shipping resolution operates at country and state granularity. Multi-currency pricing is supported with a configurable default currency seeded in migration `00000000000008_seed_platform_defaults.sql`. The database schema includes a `shipping_zone_locations.postal_code` column for future finer-grained geographic resolution, although the current runtime resolver does not yet consume it.
346
+ Shipping resolution operates at country and state granularity. Multi-currency pricing is supported with a configurable default currency seeded in migration `02001_baseline_schema.sql`. The database schema includes a `shipping_zone_locations.postal_code` column for future finer-grained geographic resolution, although the current runtime resolver does not yet consume it.
347
347
 
348
348
  #### 1.3.2.4 Data Domains Included
349
349
 
@@ -446,11 +446,14 @@ The system does not natively integrate with: alternative payment processors beyo
446
446
 
447
447
  ### 1.4.5 Database Migrations
448
448
 
449
- - `libs/db/src/supabase/migrations/00000000000000_setup_foundation_and_enums.sql` Enums: `user_role`, `page_status`, `menu_location`, `revision_type`
450
- - `libs/db/src/supabase/migrations/00000000000001_setup_cms_core.sql` — Languages, translations, media, profiles, settings
451
- - `libs/db/src/supabase/migrations/00000000000002_setup_content_tables.sql` — Pages, posts, blocks, navigation, revisions
452
- - `libs/db/src/supabase/migrations/00000000000008_seed_platform_defaults.sql` — Default settings (footer copyright, payment providers, inventory, invoice settings)
453
- - Migrations 00000000000003 through 00000000000010 Commerce catalog, fulfillment, and platform seeds
449
+ One squash generation at a time (`GGNNN_name.sql`; see §6.2.3.1 and docs/04):
450
+
451
+ - `libs/db/src/supabase/migrations/02000_catchup_gen1.sql` — Version-aware replay of the retired generation-1 forward migrations
452
+ - `libs/db/src/supabase/migrations/02001_baseline_schema.sql` — Enums (`user_role`, `page_status`, `menu_location`, `revision_type`, …), functions, every table and sequence
453
+ - `libs/db/src/supabase/migrations/02002_baseline_constraints_and_indexes.sql`Constraints and indexes
454
+ - `libs/db/src/supabase/migrations/02003_baseline_security_and_grants.sql` — RLS, policies, triggers, grants
455
+ - `libs/db/src/supabase/migrations/02004_baseline_seed.sql` — Default settings (footer copyright, payment providers, inventory, invoice settings), languages, translations, demo content
456
+ - `02005` onward — forward migrations appended since the generation-2 squash
454
457
 
455
458
  ### 1.4.6 Agent Skill Documents
456
459
 
@@ -623,7 +626,7 @@ Served locales are the active rows of the `languages` table, managed at `/cms/se
623
626
 
624
627
  Locale propagation uses the `NEXT_USER_LOCALE` cookie and the `X-User-Locale` request header, both set by the request proxy. When `rememberVisitorChoice` is `true` (default) the cookie persists for one year (`maxAge: 31_536_000` seconds); when `false` it is a session cookie, so detection re-runs each new browser session (the client `LanguageProvider` mirrors the same expiry for manual switcher choices). A valid cookie always beats detection. The client-side provider chain `LanguageProvider → TranslationsProvider` in `apps/nextblock/app/providers.tsx` bridges server-resolved locale into React context.
625
628
 
626
- **Business Value:** Unlocks multi-market deployments without requiring adopters to integrate a separate i18n library. **User Benefits:** Language switching persists across sessions; same content IDs preserve relationships across translations. **Technical Context:** Implemented at schema level (migration `00000000000001_setup_cms_core.sql`), proxy level, and provider level.
629
+ **Business Value:** Unlocks multi-market deployments without requiring adopters to integrate a separate i18n library. **User Benefits:** Language switching persists across sessions; same content IDs preserve relationships across translations. **Technical Context:** Implemented at schema level (migration `02001_baseline_schema.sql`), proxy level, and provider level.
627
630
 
628
631
  **Dependencies**
629
632
 
@@ -648,7 +651,7 @@ Locale propagation uses the `NEXT_USER_LOCALE` cookie and the `X-User-Locale` re
648
651
 
649
652
  **Description**
650
653
 
651
- Revisions are implemented in the `page_revisions` and `post_revisions` tables defined in migration `00000000000002_setup_content_tables.sql`, using a hybrid snapshot/diff model. The `revision_type` enum (`snapshot`, `diff`) distinguishes between full snapshots and JSON Patch diffs (generated via `fast-json-patch`). A UNIQUE constraint on `(page_id, version)` ensures monotonically increasing snapshot versions. The CMS surface resides under `apps/nextblock/app/cms/revisions/`.
654
+ Revisions are implemented in the `page_revisions` and `post_revisions` tables defined in migration `02001_baseline_schema.sql`, using a hybrid snapshot/diff model. The `revision_type` enum (`snapshot`, `diff`) distinguishes between full snapshots and JSON Patch diffs (generated via `fast-json-patch`). A UNIQUE constraint on `(page_id, version)` ensures monotonically increasing snapshot versions. The CMS surface resides under `apps/nextblock/app/cms/revisions/`.
652
655
 
653
656
  **Business Value:** Provides audit trail and rollback capability for authored content. **User Benefits:** Authors can restore prior states; accidental deletions are recoverable. **Technical Context:** Diff generation reduces storage overhead for frequently-updated content.
654
657
 
@@ -675,7 +678,7 @@ Revisions are implemented in the `page_revisions` and `post_revisions` tables de
675
678
 
676
679
  **Description**
677
680
 
678
- Three menu locations are supported: `HEADER`, `FOOTER`, and `SIDEBAR`, encoded by the `menu_location` enum. The `navigation_items` table (migration `00000000000002_setup_content_tables.sql`) supports hierarchical menus through a `parent_id` self-reference, explicit `order` for sibling sorting, translation group affiliation, and optional page references. Administrative CRUD operations reside at `apps/nextblock/app/cms/navigation/`.
681
+ Three menu locations are supported: `HEADER`, `FOOTER`, and `SIDEBAR`, encoded by the `menu_location` enum. The `navigation_items` table (migration `02001_baseline_schema.sql`) supports hierarchical menus through a `parent_id` self-reference, explicit `order` for sibling sorting, translation group affiliation, and optional page references. Administrative CRUD operations reside at `apps/nextblock/app/cms/navigation/`.
679
682
 
680
683
  **Dependencies**
681
684
 
@@ -729,7 +732,7 @@ Authentication is layered over Supabase Auth using `@supabase/ssr` and `@supabas
729
732
 
730
733
  **Description**
731
734
 
732
- RBAC is enforced through a three-valued `user_role` enum (`ADMIN`, `WRITER`, `USER`) defined in migration `00000000000000_setup_foundation_and_enums.sql`. Route-level enforcement is implemented in `apps/nextblock/proxy.ts` (lines 12–17): `/cms` requires `WRITER` or `ADMIN`; `/cms/admin`, `/cms/users`, and `/cms/settings` require `ADMIN` exclusively. A foundational authorization rule encoded in the `on_auth_user_created` trigger elevates the first registered user to `ADMIN` and assigns all subsequent users the `USER` role, guaranteeing each deployment has exactly one guaranteed administrator at bootstrap. Users without a `full_name` value are redirected to `/profile` before being permitted to access other authenticated surfaces. Database-layer enforcement is provided via Row-Level Security with helper functions `get_current_user_role()` and `is_admin()` (both `SECURITY DEFINER`).
735
+ RBAC is enforced through a three-valued `user_role` enum (`ADMIN`, `WRITER`, `USER`) defined in migration `02001_baseline_schema.sql`. Route-level enforcement is implemented in `apps/nextblock/proxy.ts` (lines 12–17): `/cms` requires `WRITER` or `ADMIN`; `/cms/admin`, `/cms/users`, and `/cms/settings` require `ADMIN` exclusively. A foundational authorization rule encoded in the `on_auth_user_created` trigger elevates the first registered user to `ADMIN` and assigns all subsequent users the `USER` role, guaranteeing each deployment has exactly one guaranteed administrator at bootstrap. Users without a `full_name` value are redirected to `/profile` before being permitted to access other authenticated surfaces. Database-layer enforcement is provided via Row-Level Security with helper functions `get_current_user_role()` and `is_admin()` (both `SECURITY DEFINER`).
733
736
 
734
737
  **Dependencies**
735
738
 
@@ -833,7 +836,7 @@ All features in this section are gated by F-022 (Package Activation) via `verify
833
836
 
834
837
  **Description**
835
838
 
836
- Products are modeled in migration `00000000000003_setup_catalog_and_licensing.sql` with fields including `sku`, `slug`, `title`, `type` (`physical` | `digital`), `payment_provider` (`stripe` | `freemius`), `price` as an integer in the smallest currency unit, a multi-currency `prices` JSONB column, `stock`, `status` (`draft` | `active` | `archived`), descriptions, Freemius-specific fields, UPC, and an `is_taxable` flag. A CHECK constraint named `products_type_provider_consistency_check` enforces that `physical` products use `stripe` and `digital` products use `freemius`. Related tables `product_media`, `product_attributes`, `product_attribute_terms`, `product_variants`, and `variant_attribute_mapping` model assets and variations. CMS surfaces at `apps/nextblock/app/cms/products/` provide list, create, edit, media, attribute, and variation management flows.
839
+ Products are modeled in migration `02001_baseline_schema.sql` with fields including `sku`, `slug`, `title`, `type` (`physical` | `digital`), `payment_provider` (`stripe` | `freemius`), `price` as an integer in the smallest currency unit, a multi-currency `prices` JSONB column, `stock`, `status` (`draft` | `active` | `archived`), descriptions, Freemius-specific fields, UPC, and an `is_taxable` flag. A CHECK constraint named `products_type_provider_consistency_check` enforces that `physical` products use `stripe` and `digital` products use `freemius`. Related tables `product_media`, `product_attributes`, `product_attribute_terms`, `product_variants`, and `variant_attribute_mapping` model assets and variations. CMS surfaces at `apps/nextblock/app/cms/products/` provide list, create, edit, media, attribute, and variation management flows.
837
840
 
838
841
  **Dependencies**
839
842
 
@@ -858,7 +861,7 @@ Products are modeled in migration `00000000000003_setup_catalog_and_licensing.sq
858
861
 
859
862
  **Description**
860
863
 
861
- The `inventory_items` table (migration `00000000000003_setup_catalog_and_licensing.sql`) uses SKU as key and enforces `quantity >= 0` via CHECK constraint. Tracking is globally controlled by the `trackQuantities` setting in `ecommerce_inventory_settings`. Inventory deduction during order finalization follows a resilient pattern: the runtime first calls the `apply_order_inventory_deduction()` Postgres RPC, and if that path is unavailable, falls back to direct SQL via the `POSTGRES_URL` or `DATABASE_URL` connection, as coordinated by `libs/ecommerce/src/lib/shared-inventory.ts` and `libs/ecommerce/src/lib/order-inventory.ts`.
864
+ The `inventory_items` table (migration `02001_baseline_schema.sql`) uses SKU as key and enforces `quantity >= 0` via CHECK constraint. Tracking is globally controlled by the `trackQuantities` setting in `ecommerce_inventory_settings`. Inventory deduction during order finalization follows a resilient pattern: the runtime first calls the `apply_order_inventory_deduction()` Postgres RPC, and if that path is unavailable, falls back to direct SQL via the `POSTGRES_URL` or `DATABASE_URL` connection, as coordinated by `libs/ecommerce/src/lib/shared-inventory.ts` and `libs/ecommerce/src/lib/order-inventory.ts`.
862
865
 
863
866
  **Dependencies**
864
867
 
@@ -958,7 +961,7 @@ Freemius integration lives in `libs/ecommerce/src/lib/providers/` and supports d
958
961
 
959
962
  **Description**
960
963
 
961
- The `currencies` table (migration `00000000000004_setup_fulfillment_shipping_taxes_and_currencies.sql`) stores `exchange_rate` as a `numeric(20,10)`, a single-row `is_default` constraint, `rounding_mode` (`none`, `nearest`, `up`, `down`, `charm`), `rounding_increment`, `rounding_charm_amount`, and flags `auto_update_exchange_rate` and `auto_sync_product_prices`. The default currency must satisfy `exchange_rate = 1`, `auto_update_exchange_rate = false`, and `auto_sync_product_prices = false`. FX rates are pulled from `https://api.frankfurter.dev` (overridable via `FX_API_BASE_URL`). Operations `syncStoreCurrencyRates()` and `rebaseStoreCurrencyExchangeRates()` are exposed by `libs/ecommerce/src/lib/currency-sync.ts`. A daily cron invokes `/api/cron/sync-currencies` at 18:00 UTC (`vercel.json`). Seed migration `00000000000008_seed_platform_defaults.sql` provides USD as the default.
964
+ The `currencies` table (migration `02001_baseline_schema.sql`) stores `exchange_rate` as a `numeric(20,10)`, a single-row `is_default` constraint, `rounding_mode` (`none`, `nearest`, `up`, `down`, `charm`), `rounding_increment`, `rounding_charm_amount`, and flags `auto_update_exchange_rate` and `auto_sync_product_prices`. The default currency must satisfy `exchange_rate = 1`, `auto_update_exchange_rate = false`, and `auto_sync_product_prices = false`. FX rates are pulled from `https://api.frankfurter.dev` (overridable via `FX_API_BASE_URL`). Operations `syncStoreCurrencyRates()` and `rebaseStoreCurrencyExchangeRates()` are exposed by `libs/ecommerce/src/lib/currency-sync.ts`. A daily cron invokes `/api/cron/sync-currencies` at 18:00 UTC (`vercel.json`). Seed migration `02001_baseline_schema.sql` provides USD as the default.
962
965
 
963
966
  **Dependencies**
964
967
 
@@ -1008,7 +1011,7 @@ Three shipping tables model geographic and rate configurations: `shipping_zones`
1008
1011
 
1009
1012
  **Description**
1010
1013
 
1011
- The `tax_rates` table (migration `00000000000004_setup_fulfillment_shipping_taxes_and_currencies.sql`) supports two modes: `manual` (keyed on country and state, supporting stacked rates such as GST + PST) and `automatic` (delegated to Stripe Tax via tax codes on line items). Mode selection is controlled by the `enableTaxes` and `taxCalculationMode` properties in `ecommerce_inventory_settings`. Schema constraints require `tax_rate` between 0 and 100 and enforce a uniqueness constraint on `(country_code, state_code, lower(tax_name))`. Implementation lives in `libs/ecommerce/src/lib/tax-calculation.ts` and `libs/ecommerce/src/lib/order-tax-details.ts`.
1014
+ The `tax_rates` table (migration `02001_baseline_schema.sql`) supports two modes: `manual` (keyed on country and state, supporting stacked rates such as GST + PST) and `automatic` (delegated to Stripe Tax via tax codes on line items). Mode selection is controlled by the `enableTaxes` and `taxCalculationMode` properties in `ecommerce_inventory_settings`. Schema constraints require `tax_rate` between 0 and 100 and enforce a uniqueness constraint on `(country_code, state_code, lower(tax_name))`. Implementation lives in `libs/ecommerce/src/lib/tax-calculation.ts` and `libs/ecommerce/src/lib/order-tax-details.ts`.
1012
1015
 
1013
1016
  **Dependencies**
1014
1017
 
@@ -1033,7 +1036,7 @@ The `tax_rates` table (migration `00000000000004_setup_fulfillment_shipping_taxe
1033
1036
 
1034
1037
  **Description**
1035
1038
 
1036
- Orders transition through five statuses — `pending`, `paid`, `shipped`, `cancelled`, `refunded` — and store totals (`total`, `subtotal`, `shipping_total`, `tax_total`), a JSONB `tax_details` breakdown, `exchange_rate_at_purchase` as `numeric(20,10)`, `invoice_number`, `paid_at`, and `inventory_deducted_at`. Stable invoice numbering is produced by the `order_invoice_number_seq` sequence. The `invoice_settings` site-setting (seeded by `00000000000008_seed_platform_defaults.sql`) stores business name, email, address, and tax registrations. UI components `InvoiceDocument` and `InvoiceViewerShell` in `libs/ecommerce/src/lib/` render invoices. Customer order history is surfaced via `libs/ecommerce/src/lib/customer-orders.ts`, with admin management at `apps/nextblock/app/cms/orders/` and customer self-service at `apps/nextblock/app/profile/orders/`.
1039
+ Orders transition through five statuses — `pending`, `paid`, `shipped`, `cancelled`, `refunded` — and store totals (`total`, `subtotal`, `shipping_total`, `tax_total`), a JSONB `tax_details` breakdown, `exchange_rate_at_purchase` as `numeric(20,10)`, `invoice_number`, `paid_at`, and `inventory_deducted_at`. Stable invoice numbering is produced by the `order_invoice_number_seq` sequence. The `invoice_settings` site-setting (seeded by `02001_baseline_schema.sql`) stores business name, email, address, and tax registrations. UI components `InvoiceDocument` and `InvoiceViewerShell` in `libs/ecommerce/src/lib/` render invoices. Customer order history is surfaced via `libs/ecommerce/src/lib/customer-orders.ts`, with admin management at `apps/nextblock/app/cms/orders/` and customer self-service at `apps/nextblock/app/profile/orders/`.
1037
1040
 
1038
1041
  **Dependencies**
1039
1042
 
@@ -1058,7 +1061,7 @@ Orders transition through five statuses — `pending`, `paid`, `shipped`, `cance
1058
1061
 
1059
1062
  **Description**
1060
1063
 
1061
- The `package_activations` table (migration `00000000000003_setup_catalog_and_licensing.sql`) contains `license_key`, `instance_name`, `package_id`, `status` (defaulting to `active`), `meta`, `last_validated_at`, and a UNIQUE constraint on `(license_key, package_id)`. The helper `verifyPackageOnline(packageId, customClient?)` in `libs/db/src/lib/package-validation.ts` returns a boolean based on `status === 'active'` and uses `unstable_cache` with a 60-second revalidation window. This function is invoked from four surfaces: the CMS commerce navigation visibility check, the checkout API gate at `apps/nextblock/app/api/checkout/route.ts` line 36, premium route wrappers injected during scaffold activation, and the CLI's module activation flows.
1064
+ The `package_activations` table (migration `02001_baseline_schema.sql`) contains `license_key`, `instance_name`, `package_id`, `status` (defaulting to `active`), `meta`, `last_validated_at`, and a UNIQUE constraint on `(license_key, package_id)`. The helper `verifyPackageOnline(packageId, customClient?)` in `libs/db/src/lib/package-validation.ts` returns a boolean based on `status === 'active'` and uses `unstable_cache` with a 60-second revalidation window. This function is invoked from four surfaces: the CMS commerce navigation visibility check, the checkout API gate at `apps/nextblock/app/api/checkout/route.ts` line 36, premium route wrappers injected during scaffold activation, and the CLI's module activation flows.
1062
1065
 
1063
1066
  **Dependencies**
1064
1067
 
@@ -1679,7 +1682,7 @@ The following matrix links features to the sections of the technical specificati
1679
1682
  | Package alignment | `@nextblock-cms/ecom` package name vs. `@nextblock-cms/ecommerce` alias (per §1.3.3.1) requires coordination when republished | F-013–F-022 |
1680
1683
  | Locale expansion | Locales are DB-driven: add an active `languages` row (plus translations/content); `FALLBACK_LOCALES` in `proxy.ts` is only a DB-unreachable safety net | F-007 |
1681
1684
  | Block registry updates | New block types must satisfy F-024 contract and register in `blockRegistry.ts` | F-004, F-024 |
1682
- | RLS policy review | Migration `00000000000006_setup_rls_and_grants.sql` should be audited on new table introduction | All DB-backed features |
1685
+ | RLS policy review | Migration `02001_baseline_schema.sql` should be audited on new table introduction | All DB-backed features |
1683
1686
 
1684
1687
  ### 2.4.6 Assumptions and Constraints Summary
1685
1688
 
@@ -1726,14 +1729,14 @@ The following matrix links features to the sections of the technical specificati
1726
1729
  - `apps/create-nextblock/bin/create-nextblock.js` — CLI `create` and `activate` commands (F-023)
1727
1730
  - `libs/db/src/lib/package-validation.ts` — `verifyPackageOnline()` with 60 s cache (F-022)
1728
1731
  - `libs/db/src/lib/media-actions.ts` — Role-gated media recording (F-006)
1729
- - `libs/db/src/supabase/migrations/00000000000000_setup_foundation_and_enums.sql` — `user_role`, `page_status`, `menu_location`, `revision_type` enums
1730
- - `libs/db/src/supabase/migrations/00000000000001_setup_cms_core.sql` — languages, translations, media, profiles (F-002, F-006, F-007)
1731
- - `libs/db/src/supabase/migrations/00000000000002_setup_content_tables.sql` — pages, posts, blocks, navigation, revisions (F-004, F-008, F-009)
1732
- - `libs/db/src/supabase/migrations/00000000000003_setup_catalog_and_licensing.sql` — products, variants, attributes, inventory, package_activations (F-013, F-014, F-022)
1733
- - `libs/db/src/supabase/migrations/00000000000004_setup_fulfillment_shipping_taxes_and_currencies.sql` — orders, shipping zones, tax rates, currencies (F-018–F-021)
1734
- - `libs/db/src/supabase/migrations/00000000000005_setup_functions_and_triggers.sql` — `handle_new_user()`, `on_auth_user_created` (F-002, F-003)
1735
- - `libs/db/src/supabase/migrations/00000000000006_setup_rls_and_grants.sql` — RLS policies and helper functions
1736
- - `libs/db/src/supabase/migrations/00000000000008_seed_platform_defaults.sql` — Default settings, USD currency, `en`/`fr` languages
1732
+ - `libs/db/src/supabase/migrations/02001_baseline_schema.sql` — `user_role`, `page_status`, `menu_location`, `revision_type` enums
1733
+ - `libs/db/src/supabase/migrations/02001_baseline_schema.sql` — languages, translations, media, profiles (F-002, F-006, F-007)
1734
+ - `libs/db/src/supabase/migrations/02001_baseline_schema.sql` — pages, posts, blocks, navigation, revisions (F-004, F-008, F-009)
1735
+ - `libs/db/src/supabase/migrations/02001_baseline_schema.sql` — products, variants, attributes, inventory, package_activations (F-013, F-014, F-022)
1736
+ - `libs/db/src/supabase/migrations/02001_baseline_schema.sql` — orders, shipping zones, tax rates, currencies (F-018–F-021)
1737
+ - `libs/db/src/supabase/migrations/02001_baseline_schema.sql` — `handle_new_user()`, `on_auth_user_created` (F-002, F-003)
1738
+ - `libs/db/src/supabase/migrations/02003_baseline_security_and_grants.sql` — RLS policies and helper functions
1739
+ - `libs/db/src/supabase/migrations/02004_baseline_seed.sql` — Default settings, USD currency, `en`/`fr` languages
1737
1740
  - `libs/db/src/supabase/templates/` — Six Supabase Auth email templates (F-002)
1738
1741
  - `libs/editor/README.md` — Public editor surface exports (F-005)
1739
1742
  - `libs/editor/ADVANCED_FEATURES.md` — Enhanced floating menu, placeholder behaviors (F-005)
@@ -2222,14 +2225,14 @@ Supabase PostgreSQL is the authoritative data store for all structured data in t
2222
2225
 
2223
2226
  | Migration File | Purpose |
2224
2227
  |:--|:--|
2225
- | `00000000000000_setup_foundation_and_enums.sql` | Enums: `user_role`, `page_status`, `menu_location`, `revision_type` |
2226
- | `00000000000001_setup_cms_core.sql` | `languages`, `translations`, `media`, `profiles`, `settings`, `logos` |
2227
- | `00000000000002_setup_content_tables.sql` | `pages`, `posts`, `blocks`, `navigation_items`, `page_revisions`, `post_revisions` |
2228
- | `00000000000003_setup_catalog_and_licensing.sql` | `products`, `product_variants`, `inventory_items`, `package_activations` |
2229
- | `00000000000004_setup_fulfillment_shipping_taxes_and_currencies.sql` | `currencies`, `tax_rates`, shipping tables |
2228
+ | `02001_baseline_schema.sql` | Enums: `user_role`, `page_status`, `menu_location`, `revision_type` |
2229
+ | `02001_baseline_schema.sql` | `languages`, `translations`, `media`, `profiles`, `settings`, `logos` |
2230
+ | `02001_baseline_schema.sql` | `pages`, `posts`, `blocks`, `navigation_items`, `page_revisions`, `post_revisions` |
2231
+ | `02001_baseline_schema.sql` | `products`, `product_variants`, `inventory_items`, `package_activations` |
2232
+ | `02001_baseline_schema.sql` | `currencies`, `tax_rates`, shipping tables |
2230
2233
  | `00000000000005` through `00000000000007` | Commerce extensions |
2231
- | `00000000000006_setup_rls_and_grants.sql` | Row-Level Security policies |
2232
- | `00000000000008_seed_platform_defaults.sql` | Default settings, USD currency, English language |
2234
+ | `02001_baseline_schema.sql` | Row-Level Security policies |
2235
+ | `02001_baseline_schema.sql` | Default settings, USD currency, English language |
2233
2236
  | `00000000000009` — `00000000000010` | Additional platform seeds |
2234
2237
  | `00000000000011` through `00000000000016` | Cortex AI settings, coupons, audit, drafts, and page feature images |
2235
2238
  | `00000000000017` through `00000000000024` | Product blocks, bot-protection settings, product categories + translations, hero→section migration, Cortex AI guide seed, custom block definitions, and cart sessions |
@@ -4002,14 +4005,14 @@ flowchart LR
4002
4005
 
4003
4006
  #### Database Migrations Referenced
4004
4007
 
4005
- - `00000000000000_setup_foundation_and_enums.sql` - `user_role` enum
4006
- - `00000000000001_setup_cms_core.sql` - Translations schema
4007
- - `00000000000002_setup_content_tables.sql` - Pages, posts, revisions, navigation
4008
- - `00000000000003_setup_catalog_and_licensing.sql` - Products, inventory, package_activations
4009
- - `00000000000004_setup_fulfillment_shipping_taxes_and_currencies.sql` - Orders, tax, shipping, currencies
4010
- - `00000000000005_*.sql` - `on_auth_user_created` trigger (first-user ADMIN rule)
4011
- - `00000000000006_*.sql` - RLS policies and helper functions
4012
- - `00000000000008_seed_platform_defaults.sql` - Default currency, languages, invoice settings
4008
+ - `02001_baseline_schema.sql` - `user_role` enum
4009
+ - `02001_baseline_schema.sql` - Translations schema
4010
+ - `02001_baseline_schema.sql` - Pages, posts, revisions, navigation
4011
+ - `02001_baseline_schema.sql` - Products, inventory, package_activations
4012
+ - `02001_baseline_schema.sql` - Orders, tax, shipping, currencies
4013
+ - `02003_baseline_security_and_grants.sql` - `on_auth_user_created` trigger (first-user ADMIN rule), RLS policies
4014
+ - `02001_baseline_schema.sql` - helper functions
4015
+ - `02001_baseline_schema.sql` - Default currency, languages, invoice settings
4013
4016
 
4014
4017
  #### Folders Explored
4015
4018
 
@@ -5643,7 +5646,7 @@ The design leans on the Supabase managed platform for replication, connection po
5643
5646
 
5644
5647
  #### 6.2.2.1 Enumerated Types
5645
5648
 
5646
- All domain-specific enumerations are declared in migration `00000000000000_setup_foundation_and_enums.sql` using idempotent `DO $$` guards so re-application is safe. The migration also grants `USAGE` on the `public` schema to the Supabase-managed roles `postgres`, `anon`, `authenticated`, and `service_role`.
5649
+ All domain-specific enumerations are declared in migration `02001_baseline_schema.sql` using idempotent `DO $$` guards so re-application is safe. The migration also grants `USAGE` on the `public` schema to the Supabase-managed roles `postgres`, `anon`, `authenticated`, and `service_role`.
5647
5650
 
5648
5651
  | Enum | Values | Usage |
5649
5652
  |------|--------|-------|
@@ -5654,7 +5657,7 @@ All domain-specific enumerations are declared in migration `00000000000000_setup
5654
5657
 
5655
5658
  #### 6.2.2.2 Identity and Core CMS Entities
5656
5659
 
5657
- Declared in migration `00000000000001_setup_cms_core.sql`, these tables bootstrap the authentication mirror, languages, media registry, translations, logos, and the global key/value settings store.
5660
+ Declared in migration `02001_baseline_schema.sql`, these tables bootstrap the authentication mirror, languages, media registry, translations, logos, and the global key/value settings store.
5658
5661
 
5659
5662
  | Table | Primary Key | Key Columns / Constraints |
5660
5663
  |-------|-------------|----------------------------|
@@ -5673,7 +5676,7 @@ Declared in migration `00000000000001_setup_cms_core.sql`, these tables bootstra
5673
5676
 
5674
5677
  #### 6.2.2.3 Authoring Content Entities
5675
5678
 
5676
- Declared in migration `00000000000002_setup_content_tables.sql`, these tables form the CMS authoring domain. The relationships are summarized in the ER diagram below.
5679
+ Declared in migration `02001_baseline_schema.sql`, these tables form the CMS authoring domain. The relationships are summarized in the ER diagram below.
5677
5680
 
5678
5681
  ```mermaid
5679
5682
  erDiagram
@@ -5760,7 +5763,7 @@ erDiagram
5760
5763
 
5761
5764
  #### 6.2.2.4 Commerce Entities
5762
5765
 
5763
- Declared across migrations `00000000000003_setup_catalog_and_licensing.sql` and `00000000000004_setup_fulfillment_shipping_taxes_and_currencies.sql`, commerce spans catalog, licensing, orders, shipping, taxation, and currency infrastructure.
5766
+ Declared across migration `02001_baseline_schema.sql`, commerce spans catalog, licensing, orders, shipping, taxation, and currency infrastructure.
5764
5767
 
5765
5768
  ```mermaid
5766
5769
  erDiagram
@@ -5896,7 +5899,7 @@ Both `products` and `product_variants` store prices in two redundant shapes —
5896
5899
 
5897
5900
  #### 6.2.2.5 Indexing Strategy
5898
5901
 
5899
- Migration `00000000000007_setup_indexes.sql` adds 38 secondary indexes. The strategy groups into four categories:
5902
+ Migration `02001_baseline_schema.sql` adds 38 secondary indexes. The strategy groups into four categories:
5900
5903
 
5901
5904
  | Category | Representative Indexes | Optimization Target |
5902
5905
  |----------|------------------------|---------------------|
@@ -5967,29 +5970,17 @@ The `backup.js` script reads `POSTGRES_URL` or `DATABASE_URL` via `dotenv`, pars
5967
5970
 
5968
5971
  #### 6.2.3.1 Migration Procedures
5969
5972
 
5970
- Migrations live in `libs/db/src/supabase/migrations/` and are managed via the Supabase CLI. Each file is a single SQL script prefixed by a lexicographically ordered timestamp. The **eleven consolidated migrations** represent merged historical migrations; internal comment headers preserve the original logical ordering within each file.
5973
+ Migrations live in `libs/db/src/supabase/migrations/` and are managed via the Supabase CLI plus the repo's own appliers (the `/setup` wizard, the build hook, `npm run update`, the Docker migration runner). The folder holds exactly one **squash generation**; files are named `GGNNN_name.sql` (GG = generation, NNN = contiguous sequence) and applied in lexical order. The current generation is 2 (built 2026-09-10); its first five slots are fixed and everything from `02005` upward is an ordinary forward migration.
5971
5974
 
5972
5975
  | File | Purpose | Key Outputs |
5973
5976
  |------|---------|-------------|
5974
- | `00000000000000_setup_foundation_and_enums.sql` | Foundation grants and enums | `user_role`, `page_status`, `menu_location`, `revision_type` |
5975
- | `00000000000001_setup_cms_core.sql` | Identity + content primitives | `profiles`, `user_addresses`, `languages`, `media`, `translations`, `logos`, `site_settings` |
5976
- | `00000000000002_setup_content_tables.sql` | Authoring domain | `pages`, `posts`, `blocks`, `navigation_items`, `page_revisions`, `post_revisions` |
5977
- | `00000000000003_setup_catalog_and_licensing.sql` | Commerce catalog and license registry | `products`, `product_variants`, `product_attributes`, `product_attribute_terms`, `product_media`, `variant_attribute_mapping`, `inventory_items`, `package_activations`, `freemius_plans`, `freemius_pricing` |
5978
- | `00000000000004_setup_fulfillment_shipping_taxes_and_currencies.sql` | Order lifecycle + shipping/tax + currencies | `orders`, `order_items`, `order_invoice_number_seq`, `shipping_zones`, `shipping_zone_locations`, `shipping_zone_methods`, `tax_rates`, `currencies` + 12 functions + 7 triggers |
5979
- | `00000000000005_setup_functions_and_triggers.sql` | Business logic layer | Auth helpers, first-user bootstrap, timestamp triggers, invoice sequence, inventory RPC |
5980
- | `00000000000006_setup_rls_and_grants.sql` | Security policies | Enables RLS on all tables; declares SELECT/INSERT/UPDATE/DELETE policies |
5981
- | `00000000000007_setup_indexes.sql` | Performance indexes | 38 indexes across all domains |
5982
- | `00000000000008_seed_platform_defaults.sql` | Baseline platform state | English/French languages, USD as default currency, site_settings defaults |
5983
- | `00000000000009_seed_translations.sql` | Internationalization content | Hundreds of en/es/fr i18n rows |
5984
- | `00000000000010_seed_content_scaffold.sql` | Starter content | Default logos, home/articles pages, featured posts, navigation |
5985
- | `00000000000011_setup_cortex_ai_settings.sql` | AI settings | Cortex AI configuration |
5986
- | `00000000000012_setup_commerce_coupons.sql` | Commerce coupons | Coupon tables and constraints |
5987
- | `00000000000013_setup_cortex_ai_db_mutation_audit.sql` | AI audit | Cortex AI database mutation audit support |
5988
- | `00000000000014_setup_content_drafts.sql` | Content drafts | Visual-editing draft support |
5989
- | `00000000000015_setup_product_drafts.sql` | Product drafts | Product draft workflow support |
5990
- | `00000000000016_add_feature_image_to_pages.sql` | CMS page media | Optional page feature image relationship |
5991
-
5992
- Per Section 2.4.5, the **numbered migration files in `libs/db/src/supabase/migrations/` must remain applied in order**; out-of-sequence application will violate referential integrity. For live/shared databases, new changes must be appended as new non-destructive migrations. Do not rewrite, recycle, squash, reorder, or delete migrations that may already be recorded in production.
5977
+ | `02000_catchup_gen1.sql` | Version-aware replay of the retired generation-1 forward migrations | Converges databases that sat behind generation 1; skipped on empty databases and on databases already at generation ≥ 2; sets `site_settings.migration_baseline_generation` |
5978
+ | `02001_baseline_schema.sql` | Schema | All enums, functions, tables, sequences and defaults (`IF NOT EXISTS` / `CREATE OR REPLACE`); the `auth.users` `handle_new_user` trigger |
5979
+ | `02002_baseline_constraints_and_indexes.sql` | Integrity + performance | Primary/unique/check/foreign-key constraints (catalog-guarded) and every index |
5980
+ | `02003_baseline_security_and_grants.sql` | Security | RLS enablement on every table, all policies, business/timestamp triggers, grants |
5981
+ | `02004_baseline_seed.sql` | Seed | Canonical demo content (languages, currencies, site settings, translations, media, pages/posts/blocks, navigation, shipping defaults, themes) runs only on an empty database |
5982
+
5983
+ Per Section 2.4.5, the **numbered migration files in `libs/db/src/supabase/migrations/` must remain applied in order**; out-of-sequence application will violate referential integrity. For live/shared databases, new changes must be appended as new non-destructive migrations. Do not rewrite, recycle, reorder, or delete migration files outside the documented squash runbook (`docs/04-DATABASE-AND-AUTH.md` "Squashing migrations"); a squash always ships a catch-up so existing databases converge.
5993
5984
 
5994
5985
  ##### 6.2.3.1.1 Migration Command Surface
5995
5986
 
@@ -6000,7 +5991,7 @@ The root `package.json` exposes the following migration-related scripts:
6000
5991
  | `db:migrate:check` | `node tools/scripts/push-db-migrations.js --check` | Dry-run pending remote migrations |
6001
5992
  | `db:migrate` / `db:push` | `node tools/scripts/push-db-migrations.js --confirm` | Apply pending migration files only; no reset, sandbox seed, function deploy, or config push |
6002
5993
  | `db:migrate:repair-history:check` | `node tools/scripts/repair-db-migration-history.js --check` | Preview baseline migration-history repair |
6003
- | `db:migrate:repair-history` | `node tools/scripts/repair-db-migration-history.js --confirm` | Mark existing baseline migrations as applied without running their SQL |
5994
+ | `db:migrate:repair-history` | `node tools/scripts/repair-db-migration-history.js --confirm` | Mark existing baseline migrations as applied without running their SQL; with `-- --reconcile-squash`, record a migration squash (revert retired versions, mark the new generation applied) |
6004
5995
  | `db:migrate:fresh` | `node tools/scripts/push-db-migrations.js --confirm --allow-baseline-replay` | Apply the full baseline only to a brand-new empty database |
6005
5996
  | `db:reset` | `supabase db reset --workdir libs/db/src` | Full local reset and replay |
6006
5997
  | `db:link` | `dotenv + supabase-link` via `tools/scripts/supabase-link.js` | Link local workspace to remote project |
@@ -6195,7 +6186,7 @@ Detailed in §6.2.2.8. In summary: Supabase-managed PITR and managed backups (pr
6195
6186
 
6196
6187
  #### 6.2.4.3 Privacy Controls via Row-Level Security
6197
6188
 
6198
- RLS is **enabled on every table** in migration `00000000000006_setup_rls_and_grants.sql`. The policy matrix distributes into four access tiers.
6189
+ RLS is **enabled on every table** in migration `02001_baseline_schema.sql`. The policy matrix distributes into four access tiers.
6199
6190
 
6200
6191
  | Access Tier | Representative Scope | Tables |
6201
6192
  |-------------|----------------------|--------|
@@ -6479,17 +6470,17 @@ The local Supabase stack is configured through `libs/db/src/supabase/config.toml
6479
6470
 
6480
6471
  #### 6.2.9.1 Files Examined
6481
6472
 
6482
- - `libs/db/src/supabase/migrations/00000000000000_setup_foundation_and_enums.sql` — Enums and schema grants
6483
- - `libs/db/src/supabase/migrations/00000000000001_setup_cms_core.sql` — Core CMS tables (profiles, media, languages, translations)
6484
- - `libs/db/src/supabase/migrations/00000000000002_setup_content_tables.sql` — Pages, posts, blocks, revisions, navigation
6485
- - `libs/db/src/supabase/migrations/00000000000003_setup_catalog_and_licensing.sql` — Commerce catalog and license registry
6486
- - `libs/db/src/supabase/migrations/00000000000004_setup_fulfillment_shipping_taxes_and_currencies.sql` — Orders, shipping, tax, currencies
6487
- - `libs/db/src/supabase/migrations/00000000000005_setup_functions_and_triggers.sql` — Business logic functions and triggers
6488
- - `libs/db/src/supabase/migrations/00000000000006_setup_rls_and_grants.sql` — Row-Level Security policy matrix
6489
- - `libs/db/src/supabase/migrations/00000000000007_setup_indexes.sql` — 38 secondary indexes
6490
- - `libs/db/src/supabase/migrations/00000000000008_seed_platform_defaults.sql` — Baseline platform seed
6491
- - `libs/db/src/supabase/migrations/00000000000009_seed_translations.sql` — Internationalization seed
6492
- - `libs/db/src/supabase/migrations/00000000000010_seed_content_scaffold.sql` — Starter content seed
6473
+ - `libs/db/src/supabase/migrations/02001_baseline_schema.sql` — Enums and schema grants
6474
+ - `libs/db/src/supabase/migrations/02001_baseline_schema.sql` — Core CMS tables (profiles, media, languages, translations)
6475
+ - `libs/db/src/supabase/migrations/02001_baseline_schema.sql` — Pages, posts, blocks, revisions, navigation
6476
+ - `libs/db/src/supabase/migrations/02001_baseline_schema.sql` — Commerce catalog and license registry
6477
+ - `libs/db/src/supabase/migrations/02001_baseline_schema.sql` — Orders, shipping, tax, currencies
6478
+ - `libs/db/src/supabase/migrations/02001_baseline_schema.sql` — Business logic functions and triggers
6479
+ - `libs/db/src/supabase/migrations/02003_baseline_security_and_grants.sql` — Row-Level Security policy matrix
6480
+ - `libs/db/src/supabase/migrations/02002_baseline_constraints_and_indexes.sql` — 38 secondary indexes
6481
+ - `libs/db/src/supabase/migrations/02004_baseline_seed.sql` — Baseline platform seed
6482
+ - `libs/db/src/supabase/migrations/02004_baseline_seed.sql` — Internationalization seed
6483
+ - `libs/db/src/supabase/migrations/02004_baseline_seed.sql` — Starter content seed
6493
6484
  - `libs/db/src/supabase/config.toml` — Supabase local stack configuration
6494
6485
  - `libs/db/src/lib/supabase/client.ts` — Browser client factory
6495
6486
  - `libs/db/src/lib/supabase/server.ts` — Server / SSR / service-role client factories
@@ -7507,7 +7498,7 @@ Security controls are layered so that the failure of any single layer does not r
7507
7498
  |-------|----------------------|------------------|
7508
7499
  | Edge | Request proxy — session refresh, path-prefix RBAC, security headers, CSP | `apps/nextblock/proxy.ts` |
7509
7500
  | Application | Client-layout role guard, server-action `verifyAdmin()`, role-gated page components | `app/cms/CmsClientLayout.tsx`, `app/cms/users/actions.ts` |
7510
- | Data | Row-Level Security policies, SECURITY DEFINER helpers, service-role bypass | `libs/db/src/supabase/migrations/00000000000006_setup_rls_and_grants.sql` |
7501
+ | Data | Row-Level Security policies, SECURITY DEFINER helpers, service-role bypass | `libs/db/src/supabase/migrations/02003_baseline_security_and_grants.sql` |
7511
7502
  | Integration | Webhook signature verification, Bearer-secret cron, HMAC-verified callbacks | `/api/webhooks/*`, `/api/cron/*`, `/api/revalidate/route.ts` |
7512
7503
 
7513
7504
  #### 6.4.1.3 Security Architecture Topology
@@ -7617,7 +7608,7 @@ The system manages three distinct token classes, each with differentiated lifecy
7617
7608
  | OAuth Authorization Code | Short-lived code exchange | URL query parameter, consumed immediately at `/auth/callback` |
7618
7609
  | Supabase Service Role Key | Server-only RLS bypass | Vercel environment variable (`SUPABASE_SERVICE_ROLE_KEY`) |
7619
7610
 
7620
- A **per-request nonce** is generated via `crypto.randomUUID()` in `proxy.ts` and used for the nonce-based CSP (see §6.4.4.5). JWT claims are read inside Postgres by the `get_my_claim(claim text)` SECURITY DEFINER function via `current_setting('request.jwt.claims', true)::jsonb`, which is defined in `libs/db/src/supabase/migrations/00000000000005_setup_functions_and_triggers.sql`.
7611
+ A **per-request nonce** is generated via `crypto.randomUUID()` in `proxy.ts` and used for the nonce-based CSP (see §6.4.4.5). JWT claims are read inside Postgres by the `get_my_claim(claim text)` SECURITY DEFINER function via `current_setting('request.jwt.claims', true)::jsonb`, which is defined in `libs/db/src/supabase/migrations/02001_baseline_schema.sql`.
7621
7612
 
7622
7613
  The **service role key** requires two independent compile-time and runtime guards to prevent leakage into the browser bundle:
7623
7614
 
@@ -7715,7 +7706,7 @@ The `resolvePostAuthRedirect` helper enforces four rules as a gate against open-
7715
7706
 
7716
7707
  #### 6.4.3.1 Role-Based Access Control Model
7717
7708
 
7718
- Authorization is driven by the `user_role` enum declared in migration `00000000000000_setup_foundation_and_enums.sql`, which admits three values plus an implicit fourth (Supabase's `service_role`) for server-only privilege elevation:
7709
+ Authorization is driven by the `user_role` enum declared in migration `02001_baseline_schema.sql`, which admits three values plus an implicit fourth (Supabase's `service_role`) for server-only privilege elevation:
7719
7710
 
7720
7711
  | Role | Assignment Mechanism | Zone Capabilities |
7721
7712
  |------|---------------------|-------------------|
@@ -7728,7 +7719,7 @@ Role assignment at bootstrap is governed by the `handle_new_user()` SECURITY DEF
7728
7719
 
7729
7720
  #### 6.4.3.2 Permission Management and SECURITY DEFINER Helpers
7730
7721
 
7731
- Role checks executed inside SQL contexts use SECURITY DEFINER helper functions declared in `libs/db/src/supabase/migrations/00000000000005_setup_functions_and_triggers.sql`. SECURITY DEFINER elevates the function's execution privileges to the function owner, bypassing caller-side RLS for the function body while `SET search_path = ''` prevents search-path hijacking attacks.
7722
+ Role checks executed inside SQL contexts use SECURITY DEFINER helper functions declared in `libs/db/src/supabase/migrations/02001_baseline_schema.sql`. SECURITY DEFINER elevates the function's execution privileges to the function owner, bypassing caller-side RLS for the function body while `SET search_path = ''` prevents search-path hijacking attacks.
7732
7723
 
7733
7724
  | Function | Purpose | Security Annotation |
7734
7725
  |----------|---------|---------------------|
@@ -7741,7 +7732,7 @@ These helpers form the primitive vocabulary of all RLS policies: a user's effect
7741
7732
 
7742
7733
  #### 6.4.3.3 Resource Authorization Matrix
7743
7734
 
7744
- RLS is enabled on every table in migration `00000000000006_setup_rls_and_grants.sql` (872 lines). The matrix distributes into four access tiers:
7735
+ RLS is enabled on every table in migration `02001_baseline_schema.sql` (872 lines). The matrix distributes into four access tiers:
7745
7736
 
7746
7737
  | Access Tier | Typical Policy Predicate | Representative Tables |
7747
7738
  |-------------|--------------------------|------------------------|
@@ -8127,7 +8118,7 @@ The security control matrix below enumerates the principal threats, their mitiga
8127
8118
 
8128
8119
  | Threat | Mitigation | Migration or File |
8129
8120
  |--------|-----------|-------------------|
8130
- | Public data exposure through writes | RLS writes restricted; public read only for intended tables and statuses | `migrations/00000000000006_setup_rls_and_grants.sql` |
8121
+ | Public data exposure through writes | RLS writes restricted; public read only for intended tables and statuses | `migrations/02003_baseline_security_and_grants.sql` |
8131
8122
  | Draft content leakage | Anon policy `status='published'` on pages; `status='published' AND published_at<=now()` on posts | `migration 00000000000006` |
8132
8123
  | Path traversal in uploads | `sanitizeFolder()` collapses `../`, strips leading slashes, removes illegal chars | `/api/upload/presigned-url/route.ts` |
8133
8124
  | Search-path hijacking in SECURITY DEFINER | `SET search_path = ''` on auth helper functions | `migration 00000000000005` |
@@ -8226,9 +8217,9 @@ For details beyond the scope of this section, consult:
8226
8217
 
8227
8218
  #### Database Security Surface
8228
8219
 
8229
- - `libs/db/src/supabase/migrations/00000000000000_setup_foundation_and_enums.sql` — `user_role` enum declaration
8230
- - `libs/db/src/supabase/migrations/00000000000005_setup_functions_and_triggers.sql` — `handle_new_user`, `get_current_user_role`, `is_admin`, `get_my_claim` SECURITY DEFINER functions
8231
- - `libs/db/src/supabase/migrations/00000000000006_setup_rls_and_grants.sql` — 872-line RLS policy matrix
8220
+ - `libs/db/src/supabase/migrations/02001_baseline_schema.sql` — `user_role` enum declaration
8221
+ - `libs/db/src/supabase/migrations/02001_baseline_schema.sql` — `handle_new_user`, `get_current_user_role`, `is_admin`, `get_my_claim` SECURITY DEFINER functions
8222
+ - `libs/db/src/supabase/migrations/02003_baseline_security_and_grants.sql` — 872-line RLS policy matrix
8232
8223
  - `libs/db/src/supabase/config.toml` — 341-line Supabase Auth + MFA + rate-limit configuration
8233
8224
  - `libs/db/src/supabase/templates/` — Six transactional email templates
8234
8225
 
@@ -10787,7 +10778,7 @@ Security is enforced across four layers, with compliance-relevant controls conce
10787
10778
  |:--|:--|:--|
10788
10779
  | Edge | Nonce-based CSP, HSTS, X-Frame-Options SAMEORIGIN, X-Content-Type-Options nosniff, Referrer-Policy origin-when-cross-origin, Permissions-Policy, COOP same-origin | `proxy.ts` |
10789
10780
  | Application | RBAC via `cmsRoutePermissions` (`/cms` ADMIN/WRITER; `/cms/admin`, `/cms/users`, `/cms/settings` ADMIN only); `verifyAdmin()` in server actions | `proxy.ts`, server actions |
10790
- | Data | RLS policies + SECURITY DEFINER helpers (`get_my_claim`, `get_current_user_role`, `is_admin`, `handle_new_user`) | Migration `00000000000006_setup_rls_and_grants.sql` (872 lines) |
10781
+ | Data | RLS policies + SECURITY DEFINER helpers (`get_my_claim`, `get_current_user_role`, `is_admin`, `handle_new_user`) | Migration `02001_baseline_schema.sql` (872 lines) |
10791
10782
  | Integration | Stripe `constructEvent` signature verification; Freemius HMAC-SHA-256; `CRON_SECRET` Bearer auth; `REVALIDATE_SECRET_TOKEN` via `x-revalidate-secret` header | Webhook + cron route handlers |
10792
10783
 
10793
10784
  **Service role key hardening**: `SUPABASE_SERVICE_ROLE_KEY` is guarded at runtime via `typeof window !== 'undefined'` checks and build-time via `import 'server-only'` directives to prevent browser exposure.
@@ -11300,7 +11291,7 @@ Per §4.12, the following are the codified timing constraints. Breaches surface
11300
11291
  | Vercel function invocations | Vercel dashboard | Auto-scaled; `maxDuration` capping |
11301
11292
  | Vercel bandwidth | Vercel dashboard | 1-year image cache TTL, AVIF compression |
11302
11293
  | Vercel image optimization count | Vercel dashboard | `minimumCacheTTL: 31_536_000` |
11303
- | Supabase DB CPU/IO | Supabase dashboard | RLS indexing (`00000000000007_setup_indexes.sql`) |
11294
+ | Supabase DB CPU/IO | Supabase dashboard | RLS indexing (`02001_baseline_schema.sql`) |
11304
11295
  | Supabase egress | Supabase dashboard | Server-side aggregation; `count` head queries |
11305
11296
  | R2 storage | Cloudflare dashboard | Folder path sanitization prevents duplicates |
11306
11297
  | R2 Class A writes | Cloudflare dashboard | Single direct-upload via presigned URL (vs through server) |
@@ -11702,15 +11693,15 @@ The following enum types are defined in the eleven canonical SQL migrations loca
11702
11693
 
11703
11694
  | Enum Type | Allowed Values | Migration |
11704
11695
  |:--|:--|:--|
11705
- | `user_role` | `ADMIN`, `WRITER`, `USER` | `00000000000000_setup_foundation_and_enums.sql` |
11706
- | `page_status` | `draft`, `published`, `archived` | `00000000000002_setup_content_tables.sql` |
11707
- | `menu_location` | `header`, `footer`, `sidebar` | `00000000000002_setup_content_tables.sql` |
11708
- | `revision_type` | `snapshot`, `diff` | `00000000000002_setup_content_tables.sql` |
11709
- | `product_type` | `physical`, `digital` | `00000000000003_setup_catalog_and_licensing.sql` |
11710
- | `payment_provider` | `stripe`, `freemius` | `00000000000003_setup_catalog_and_licensing.sql` |
11711
- | `order_status` | `pending`, `paid`, `shipped`, `delivered`, `refunded`, `cancelled` | `00000000000004_setup_fulfillment_shipping_taxes_and_currencies.sql` |
11712
- | `tax_calculation_mode` | `manual`, `automatic` | `00000000000004_setup_fulfillment_shipping_taxes_and_currencies.sql` |
11713
- | `inventory_deduction_method` | `rpc`, `sql-fallback` | `00000000000004_setup_fulfillment_shipping_taxes_and_currencies.sql` |
11696
+ | `user_role` | `ADMIN`, `WRITER`, `USER` | `02001_baseline_schema.sql` |
11697
+ | `page_status` | `draft`, `published`, `archived` | `02001_baseline_schema.sql` |
11698
+ | `menu_location` | `header`, `footer`, `sidebar` | `02001_baseline_schema.sql` |
11699
+ | `revision_type` | `snapshot`, `diff` | `02001_baseline_schema.sql` |
11700
+ | `product_type` | `physical`, `digital` | `02001_baseline_schema.sql` |
11701
+ | `payment_provider` | `stripe`, `freemius` | `02001_baseline_schema.sql` |
11702
+ | `order_status` | `pending`, `paid`, `shipped`, `delivered`, `refunded`, `cancelled` | `02001_baseline_schema.sql` |
11703
+ | `tax_calculation_mode` | `manual`, `automatic` | `02001_baseline_schema.sql` |
11704
+ | `inventory_deduction_method` | `rpc`, `sql-fallback` | `02001_baseline_schema.sql` |
11714
11705
 
11715
11706
  Cross-reference: Section 6.2 (Database Design), Section 4.11 (Validation Rules and Compliance Checkpoints).
11716
11707
 
@@ -12430,10 +12421,10 @@ The appendices above synthesize material from the following sections of this spe
12430
12421
 
12431
12422
  - `libs/environment.d.ts` — Typed `NodeJS.ProcessEnv` augmentation used to enumerate every environment variable listed in Section 9.1.1
12432
12423
  - `.env.example` — Environment variable inventory and sample values cross-checked against the typed augmentation
12433
- - `libs/db/src/supabase/migrations/00000000000000_setup_foundation_and_enums.sql` — `user_role` enum definition
12434
- - `libs/db/src/supabase/migrations/00000000000002_setup_content_tables.sql` — `page_status`, `menu_location`, `revision_type` enum definitions
12435
- - `libs/db/src/supabase/migrations/00000000000003_setup_catalog_and_licensing.sql` — `product_type`, `payment_provider` enum definitions
12436
- - `libs/db/src/supabase/migrations/00000000000004_setup_fulfillment_shipping_taxes_and_currencies.sql` — `order_status`, `tax_calculation_mode`, `inventory_deduction_method` enum definitions
12424
+ - `libs/db/src/supabase/migrations/02001_baseline_schema.sql` — `user_role` enum definition
12425
+ - `libs/db/src/supabase/migrations/02001_baseline_schema.sql` — `page_status`, `menu_location`, `revision_type` enum definitions
12426
+ - `libs/db/src/supabase/migrations/02001_baseline_schema.sql` — `product_type`, `payment_provider` enum definitions
12427
+ - `libs/db/src/supabase/migrations/02001_baseline_schema.sql` — `order_status`, `tax_calculation_mode`, `inventory_deduction_method` enum definitions
12437
12428
  - `libs/db/src/supabase/config.toml` — Supabase local port allocation reproduced in Section 9.1.9
12438
12429
  - `apps/nextblock/proxy.ts` — Security header set (Section 9.1.12), prefetch priority mapping (Section 9.1.13), CSP nonce, structured cache observability log schema
12439
12430
  - `apps/nextblock/app/layout.tsx` — `PUBLIC_LAYOUT_REVALIDATE_SECONDS` constant reproduced in SLA ledger
@@ -1,39 +1,39 @@
1
- import 'server-only';
2
- import { createHmac } from 'node:crypto';
3
-
4
- // Resolve the app's internal shared secrets WITHOUT requiring the operator to paste
5
- // random strings at deploy time. When an explicit env var is set it always wins;
6
- // otherwise the secret is derived deterministically from the always-present Supabase
7
- // service-role key. This is what lets a one-click Vercel deploy work with zero env
8
- // input while Draft Mode and on-demand revalidation still function out of the box.
9
- //
10
- // HMAC-SHA256 is one-way, so a leaked derived secret never exposes the service-role
11
- // key. The derived value is stable for a given Supabase project; rotating the
12
- // service-role key rotates these secrets too (set the explicit env var to pin one
13
- // independently — e.g. to configure a Supabase revalidation webhook with a fixed
14
- // token). `npm run setup` still writes explicit values locally, so dev is unchanged.
15
- //
16
- // CRON_SECRET is intentionally NOT derived here: Vercel Cron injects
17
- // `Authorization: Bearer ${process.env.CRON_SECRET}` read from the env at invocation,
18
- // so a derived value could never match it. The cron routes instead treat CRON_SECRET
19
- // as optional (enforced only when set) — see app/api/cron/*/route.ts.
20
-
21
- function deriveFromServiceRole(label: string): string {
22
- // Accept the Marketplace integration's SUPABASE_SECRET_KEY alias too, so derivation
23
- // still works on a one-click deploy that only injected the new key name.
24
- const master = (
25
- process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SUPABASE_SECRET_KEY
26
- )?.trim();
27
- if (!master) return '';
28
- return createHmac('sha256', master).update(`nextblock:${label}`).digest('hex');
29
- }
30
-
31
- /** Secret for the programmatic Draft Mode preview entry (`/api/draft?secret=`). */
32
- export function resolveDraftModeSecret(): string {
33
- return process.env.DRAFT_MODE_SECRET?.trim() || deriveFromServiceRole('draft-mode');
34
- }
35
-
36
- /** Shared secret a Supabase webhook sends to `/api/revalidate` (`x-revalidate-secret`). */
37
- export function resolveRevalidateSecret(): string {
38
- return process.env.REVALIDATE_SECRET_TOKEN?.trim() || deriveFromServiceRole('revalidate');
39
- }
1
+ import 'server-only';
2
+ import { createHmac } from 'node:crypto';
3
+
4
+ // Resolve the app's internal shared secrets WITHOUT requiring the operator to paste
5
+ // random strings at deploy time. When an explicit env var is set it always wins;
6
+ // otherwise the secret is derived deterministically from the always-present Supabase
7
+ // service-role key. This is what lets a one-click Vercel deploy work with zero env
8
+ // input while Draft Mode and on-demand revalidation still function out of the box.
9
+ //
10
+ // HMAC-SHA256 is one-way, so a leaked derived secret never exposes the service-role
11
+ // key. The derived value is stable for a given Supabase project; rotating the
12
+ // service-role key rotates these secrets too (set the explicit env var to pin one
13
+ // independently — e.g. to configure a Supabase revalidation webhook with a fixed
14
+ // token). `npm run setup` still writes explicit values locally, so dev is unchanged.
15
+ //
16
+ // CRON_SECRET is intentionally NOT derived here: Vercel Cron injects
17
+ // `Authorization: Bearer ${process.env.CRON_SECRET}` read from the env at invocation,
18
+ // so a derived value could never match it. The cron routes instead treat CRON_SECRET
19
+ // as optional (enforced only when set) — see app/api/cron/*/route.ts.
20
+
21
+ function deriveFromServiceRole(label: string): string {
22
+ // Accept the Marketplace integration's SUPABASE_SECRET_KEY alias too, so derivation
23
+ // still works on a one-click deploy that only injected the new key name.
24
+ const master = (
25
+ process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SUPABASE_SECRET_KEY
26
+ )?.trim();
27
+ if (!master) return '';
28
+ return createHmac('sha256', master).update(`nextblock:${label}`).digest('hex');
29
+ }
30
+
31
+ /** Secret for the programmatic Draft Mode preview entry (`/api/draft?secret=`). */
32
+ export function resolveDraftModeSecret(): string {
33
+ return process.env.DRAFT_MODE_SECRET?.trim() || deriveFromServiceRole('draft-mode');
34
+ }
35
+
36
+ /** Shared secret a Supabase webhook sends to `/api/revalidate` (`x-revalidate-secret`). */
37
+ export function resolveRevalidateSecret(): string {
38
+ return process.env.REVALIDATE_SECRET_TOKEN?.trim() || deriveFromServiceRole('revalidate');
39
+ }