@nextblock-cms/db 0.16.1 → 0.16.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/supabase/migrations/00000000000003_baseline_seed.sql +468 -468
- package/supabase/migrations/00000000000006_home_live_demo_promo.sql +67 -67
- package/supabase/migrations/00000000000007_home_live_demo_promo_copy_fix.sql +49 -49
- package/supabase/migrations/00000000000009_home_live_demo_promo_contrast.sql +52 -52
- package/supabase/migrations/00000000000014_site_themes.sql +254 -254
- package/supabase/migrations/00000000000015_scheduled_publishing.sql +43 -43
- package/supabase/migrations/00000000000016_product_revisions_and_revision_baseline.sql +310 -310
- package/supabase/migrations/00000000000017_cortex_ai_mcp_server.sql +91 -91
- package/supabase/migrations/00000000000018_site_scripts.sql +96 -96
- package/supabase/migrations/00000000000019_site_script_revisions.sql +85 -85
- package/supabase/migrations/00000000000020_updating_article.sql +162 -162
- package/supabase/migrations/00000000000021_updating_article_git_merge.sql +91 -91
- package/supabase/migrations/00000000000022_updating_article_accuracy.sql +94 -94
- package/supabase/migrations/00000000000023_updating_article_layout_not_host.sql +87 -87
- package/supabase/migrations/00000000000024_updating_article_newline_fix.sql +70 -70
- package/supabase/migrations/00000000000025_rebrand_nextblock_dev.sql +53 -53
- package/supabase/migrations/00000000000026_product_inquiries.sql +118 -118
- package/supabase/migrations/00000000000027_message_threads.sql +391 -391
- package/supabase/migrations/00000000000028_interaction_replies.sql +86 -86
- package/supabase/migrations/00000000000029_form_endpoints_default_empty.sql +52 -52
- package/supabase/migrations/00000000000030_seo_redirects_and_robots.sql +149 -149
- package/supabase/migrations/00000000000031_seo_robots_settings_admin_only.sql +35 -35
- package/supabase/migrations/00000000000032_seed_seo_score_optimizations.sql +1172 -0
- package/supabase/migrations/00000000000033_seed_seo_score_optimizations_p2.sql +353 -0
- package/supabase/migrations/00000000000034_seed_seo_french_legal_readability.sql +101 -0
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
-- Restrict writes to the robots.txt settings row to ADMIN only.
|
|
2
|
-
--
|
|
3
|
-
-- `site_settings.seo_robots_settings` is the row that decides whether the whole site
|
|
4
|
-
-- is crawlable: app/robots.ts reads it on every /robots.txt hit and serves a blanket
|
|
5
|
-
-- `Disallow: /` when `isIndexingEnabled` is false. The CMS only offers that switch
|
|
6
|
-
-- under /cms/settings/seo, and `saveRobotsSettings` re-checks for ADMIN before it
|
|
7
|
-
-- writes — but RLS is the independent boundary, and it did not agree. The baseline
|
|
8
|
-
-- write policies let ADMIN *or* WRITER write any key outside the sensitive array, so
|
|
9
|
-
-- a WRITER holding a normal session could PATCH this row through PostgREST and take
|
|
10
|
-
-- the entire site out of Google. That failure is quiet (nothing in the CMS shows it),
|
|
11
|
-
-- slow to notice (search traffic decays over weeks) and hard to attribute after the
|
|
12
|
-
-- fact, which is why the database has to refuse it rather than trusting the one
|
|
13
|
-
-- server action that happens to guard it today.
|
|
14
|
-
--
|
|
15
|
-
-- The SELECT policy is deliberately NOT touched. This key must stay anon-READABLE:
|
|
16
|
-
-- app/robots.ts reads it with the anon (SSG) client on every crawl, and adding the key
|
|
17
|
-
-- to the read policy's sensitive array would make robots.txt fall back to its
|
|
18
|
-
-- permissive defaults for every crawler. Only INSERT/UPDATE/DELETE move to ADMIN-only,
|
|
19
|
-
-- matching the UI boundary — exactly the shape migration 00000000000011 used for
|
|
20
|
-
-- language_detection_settings, which is anon-readable for the same reason.
|
|
21
|
-
--
|
|
22
|
-
-- Every key already present in each policy's array is preserved (dropping one would
|
|
23
|
-
-- silently widen write access back to WRITER for that key); `seo_robots_settings` is
|
|
24
|
-
-- appended to the three write policies only.
|
|
25
|
-
|
|
26
|
-
DROP POLICY IF EXISTS site_settings_insert_policy ON public.site_settings;
|
|
27
|
-
CREATE POLICY site_settings_insert_policy ON public.site_settings FOR INSERT TO authenticated WITH CHECK ((((key <> ALL (ARRAY['cortex_ai_openrouter_api_key'::text, 'bot_protection_secret'::text, 'email_secret'::text, 'payment_secret'::text, 'language_detection_settings'::text, 'cortex_ai_pexels_api_key'::text, 'cortex_ai_unsplash_access_key'::text, 'cortex_ai_mcp_settings'::text, 'seo_robots_settings'::text])) AND (( SELECT public.get_current_user_role() AS get_current_user_role) = ANY (ARRAY['ADMIN'::public.user_role, 'WRITER'::public.user_role]))) OR ((key = ANY (ARRAY['cortex_ai_openrouter_api_key'::text, 'bot_protection_secret'::text, 'email_secret'::text, 'payment_secret'::text, 'language_detection_settings'::text, 'cortex_ai_pexels_api_key'::text, 'cortex_ai_unsplash_access_key'::text, 'cortex_ai_mcp_settings'::text, 'seo_robots_settings'::text])) AND (( SELECT public.get_current_user_role() AS get_current_user_role) = 'ADMIN'::public.user_role))));
|
|
28
|
-
|
|
29
|
-
DROP POLICY IF EXISTS site_settings_update_policy ON public.site_settings;
|
|
30
|
-
CREATE POLICY site_settings_update_policy ON public.site_settings FOR UPDATE TO authenticated USING ((((key <> ALL (ARRAY['cortex_ai_openrouter_api_key'::text, 'bot_protection_secret'::text, 'email_secret'::text, 'payment_secret'::text, 'language_detection_settings'::text, 'cortex_ai_pexels_api_key'::text, 'cortex_ai_unsplash_access_key'::text, 'cortex_ai_mcp_settings'::text, 'seo_robots_settings'::text])) AND (( SELECT public.get_current_user_role() AS get_current_user_role) = ANY (ARRAY['ADMIN'::public.user_role, 'WRITER'::public.user_role]))) OR ((key = ANY (ARRAY['cortex_ai_openrouter_api_key'::text, 'bot_protection_secret'::text, 'email_secret'::text, 'payment_secret'::text, 'language_detection_settings'::text, 'cortex_ai_pexels_api_key'::text, 'cortex_ai_unsplash_access_key'::text, 'cortex_ai_mcp_settings'::text, 'seo_robots_settings'::text])) AND (( SELECT public.get_current_user_role() AS get_current_user_role) = 'ADMIN'::public.user_role)))) WITH CHECK ((((key <> ALL (ARRAY['cortex_ai_openrouter_api_key'::text, 'bot_protection_secret'::text, 'email_secret'::text, 'payment_secret'::text, 'language_detection_settings'::text, 'cortex_ai_pexels_api_key'::text, 'cortex_ai_unsplash_access_key'::text, 'cortex_ai_mcp_settings'::text, 'seo_robots_settings'::text])) AND (( SELECT public.get_current_user_role() AS get_current_user_role) = ANY (ARRAY['ADMIN'::public.user_role, 'WRITER'::public.user_role]))) OR ((key = ANY (ARRAY['cortex_ai_openrouter_api_key'::text, 'bot_protection_secret'::text, 'email_secret'::text, 'payment_secret'::text, 'language_detection_settings'::text, 'cortex_ai_pexels_api_key'::text, 'cortex_ai_unsplash_access_key'::text, 'cortex_ai_mcp_settings'::text, 'seo_robots_settings'::text])) AND (( SELECT public.get_current_user_role() AS get_current_user_role) = 'ADMIN'::public.user_role))));
|
|
31
|
-
|
|
32
|
-
DROP POLICY IF EXISTS site_settings_delete_policy ON public.site_settings;
|
|
33
|
-
CREATE POLICY site_settings_delete_policy ON public.site_settings FOR DELETE TO authenticated USING ((((key <> ALL (ARRAY['cortex_ai_openrouter_api_key'::text, 'bot_protection_secret'::text, 'email_secret'::text, 'payment_secret'::text, 'language_detection_settings'::text, 'cortex_ai_pexels_api_key'::text, 'cortex_ai_unsplash_access_key'::text, 'cortex_ai_mcp_settings'::text, 'seo_robots_settings'::text])) AND (( SELECT public.get_current_user_role() AS get_current_user_role) = ANY (ARRAY['ADMIN'::public.user_role, 'WRITER'::public.user_role]))) OR ((key = ANY (ARRAY['cortex_ai_openrouter_api_key'::text, 'bot_protection_secret'::text, 'email_secret'::text, 'payment_secret'::text, 'language_detection_settings'::text, 'cortex_ai_pexels_api_key'::text, 'cortex_ai_unsplash_access_key'::text, 'cortex_ai_mcp_settings'::text, 'seo_robots_settings'::text])) AND (( SELECT public.get_current_user_role() AS get_current_user_role) = 'ADMIN'::public.user_role))));
|
|
34
|
-
|
|
35
|
-
-- Forward-only and idempotent.
|
|
1
|
+
-- Restrict writes to the robots.txt settings row to ADMIN only.
|
|
2
|
+
--
|
|
3
|
+
-- `site_settings.seo_robots_settings` is the row that decides whether the whole site
|
|
4
|
+
-- is crawlable: app/robots.ts reads it on every /robots.txt hit and serves a blanket
|
|
5
|
+
-- `Disallow: /` when `isIndexingEnabled` is false. The CMS only offers that switch
|
|
6
|
+
-- under /cms/settings/seo, and `saveRobotsSettings` re-checks for ADMIN before it
|
|
7
|
+
-- writes — but RLS is the independent boundary, and it did not agree. The baseline
|
|
8
|
+
-- write policies let ADMIN *or* WRITER write any key outside the sensitive array, so
|
|
9
|
+
-- a WRITER holding a normal session could PATCH this row through PostgREST and take
|
|
10
|
+
-- the entire site out of Google. That failure is quiet (nothing in the CMS shows it),
|
|
11
|
+
-- slow to notice (search traffic decays over weeks) and hard to attribute after the
|
|
12
|
+
-- fact, which is why the database has to refuse it rather than trusting the one
|
|
13
|
+
-- server action that happens to guard it today.
|
|
14
|
+
--
|
|
15
|
+
-- The SELECT policy is deliberately NOT touched. This key must stay anon-READABLE:
|
|
16
|
+
-- app/robots.ts reads it with the anon (SSG) client on every crawl, and adding the key
|
|
17
|
+
-- to the read policy's sensitive array would make robots.txt fall back to its
|
|
18
|
+
-- permissive defaults for every crawler. Only INSERT/UPDATE/DELETE move to ADMIN-only,
|
|
19
|
+
-- matching the UI boundary — exactly the shape migration 00000000000011 used for
|
|
20
|
+
-- language_detection_settings, which is anon-readable for the same reason.
|
|
21
|
+
--
|
|
22
|
+
-- Every key already present in each policy's array is preserved (dropping one would
|
|
23
|
+
-- silently widen write access back to WRITER for that key); `seo_robots_settings` is
|
|
24
|
+
-- appended to the three write policies only.
|
|
25
|
+
|
|
26
|
+
DROP POLICY IF EXISTS site_settings_insert_policy ON public.site_settings;
|
|
27
|
+
CREATE POLICY site_settings_insert_policy ON public.site_settings FOR INSERT TO authenticated WITH CHECK ((((key <> ALL (ARRAY['cortex_ai_openrouter_api_key'::text, 'bot_protection_secret'::text, 'email_secret'::text, 'payment_secret'::text, 'language_detection_settings'::text, 'cortex_ai_pexels_api_key'::text, 'cortex_ai_unsplash_access_key'::text, 'cortex_ai_mcp_settings'::text, 'seo_robots_settings'::text])) AND (( SELECT public.get_current_user_role() AS get_current_user_role) = ANY (ARRAY['ADMIN'::public.user_role, 'WRITER'::public.user_role]))) OR ((key = ANY (ARRAY['cortex_ai_openrouter_api_key'::text, 'bot_protection_secret'::text, 'email_secret'::text, 'payment_secret'::text, 'language_detection_settings'::text, 'cortex_ai_pexels_api_key'::text, 'cortex_ai_unsplash_access_key'::text, 'cortex_ai_mcp_settings'::text, 'seo_robots_settings'::text])) AND (( SELECT public.get_current_user_role() AS get_current_user_role) = 'ADMIN'::public.user_role))));
|
|
28
|
+
|
|
29
|
+
DROP POLICY IF EXISTS site_settings_update_policy ON public.site_settings;
|
|
30
|
+
CREATE POLICY site_settings_update_policy ON public.site_settings FOR UPDATE TO authenticated USING ((((key <> ALL (ARRAY['cortex_ai_openrouter_api_key'::text, 'bot_protection_secret'::text, 'email_secret'::text, 'payment_secret'::text, 'language_detection_settings'::text, 'cortex_ai_pexels_api_key'::text, 'cortex_ai_unsplash_access_key'::text, 'cortex_ai_mcp_settings'::text, 'seo_robots_settings'::text])) AND (( SELECT public.get_current_user_role() AS get_current_user_role) = ANY (ARRAY['ADMIN'::public.user_role, 'WRITER'::public.user_role]))) OR ((key = ANY (ARRAY['cortex_ai_openrouter_api_key'::text, 'bot_protection_secret'::text, 'email_secret'::text, 'payment_secret'::text, 'language_detection_settings'::text, 'cortex_ai_pexels_api_key'::text, 'cortex_ai_unsplash_access_key'::text, 'cortex_ai_mcp_settings'::text, 'seo_robots_settings'::text])) AND (( SELECT public.get_current_user_role() AS get_current_user_role) = 'ADMIN'::public.user_role)))) WITH CHECK ((((key <> ALL (ARRAY['cortex_ai_openrouter_api_key'::text, 'bot_protection_secret'::text, 'email_secret'::text, 'payment_secret'::text, 'language_detection_settings'::text, 'cortex_ai_pexels_api_key'::text, 'cortex_ai_unsplash_access_key'::text, 'cortex_ai_mcp_settings'::text, 'seo_robots_settings'::text])) AND (( SELECT public.get_current_user_role() AS get_current_user_role) = ANY (ARRAY['ADMIN'::public.user_role, 'WRITER'::public.user_role]))) OR ((key = ANY (ARRAY['cortex_ai_openrouter_api_key'::text, 'bot_protection_secret'::text, 'email_secret'::text, 'payment_secret'::text, 'language_detection_settings'::text, 'cortex_ai_pexels_api_key'::text, 'cortex_ai_unsplash_access_key'::text, 'cortex_ai_mcp_settings'::text, 'seo_robots_settings'::text])) AND (( SELECT public.get_current_user_role() AS get_current_user_role) = 'ADMIN'::public.user_role))));
|
|
31
|
+
|
|
32
|
+
DROP POLICY IF EXISTS site_settings_delete_policy ON public.site_settings;
|
|
33
|
+
CREATE POLICY site_settings_delete_policy ON public.site_settings FOR DELETE TO authenticated USING ((((key <> ALL (ARRAY['cortex_ai_openrouter_api_key'::text, 'bot_protection_secret'::text, 'email_secret'::text, 'payment_secret'::text, 'language_detection_settings'::text, 'cortex_ai_pexels_api_key'::text, 'cortex_ai_unsplash_access_key'::text, 'cortex_ai_mcp_settings'::text, 'seo_robots_settings'::text])) AND (( SELECT public.get_current_user_role() AS get_current_user_role) = ANY (ARRAY['ADMIN'::public.user_role, 'WRITER'::public.user_role]))) OR ((key = ANY (ARRAY['cortex_ai_openrouter_api_key'::text, 'bot_protection_secret'::text, 'email_secret'::text, 'payment_secret'::text, 'language_detection_settings'::text, 'cortex_ai_pexels_api_key'::text, 'cortex_ai_unsplash_access_key'::text, 'cortex_ai_mcp_settings'::text, 'seo_robots_settings'::text])) AND (( SELECT public.get_current_user_role() AS get_current_user_role) = 'ADMIN'::public.user_role))));
|
|
34
|
+
|
|
35
|
+
-- Forward-only and idempotent.
|