@nextblock-cms/db 0.11.3 → 0.12.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 (62) hide show
  1. package/lib/supabase/server.d.ts +9 -0
  2. package/lib/supabase/types.d.ts +9 -0
  3. package/package.json +1 -1
  4. package/supabase/migrations/00000000000000_baseline_schema.sql +2454 -0
  5. package/supabase/migrations/00000000000001_baseline_constraints_and_indexes.sql +1071 -0
  6. package/supabase/migrations/00000000000002_baseline_security_and_grants.sql +1335 -0
  7. package/supabase/migrations/00000000000003_baseline_seed.sql +468 -0
  8. package/supabase/migrations/00000000000004_default_logo_email_safe.sql +24 -0
  9. package/supabase/migrations/00000000000005_add_custom_canonical.sql +13 -0
  10. package/supabase/migrations/00000000000006_home_live_demo_promo.sql +67 -0
  11. package/supabase/migrations/00000000000007_home_live_demo_promo_copy_fix.sql +49 -0
  12. package/supabase/templates/confirmation.html +1 -1
  13. package/supabase/templates/email_change.html +1 -1
  14. package/supabase/templates/invite.html +1 -1
  15. package/supabase/templates/magic_link.html +1 -1
  16. package/supabase/templates/reauthentication.html +1 -1
  17. package/supabase/templates/recovery.html +1 -1
  18. package/supabase/migrations/00000000000000_setup_foundation_and_enums.sql +0 -40
  19. package/supabase/migrations/00000000000001_setup_cms_core.sql +0 -124
  20. package/supabase/migrations/00000000000002_setup_content_tables.sql +0 -138
  21. package/supabase/migrations/00000000000003_setup_catalog_and_licensing.sql +0 -160
  22. package/supabase/migrations/00000000000004_setup_fulfillment_shipping_taxes_and_currencies.sql +0 -797
  23. package/supabase/migrations/00000000000005_setup_functions_and_triggers.sql +0 -767
  24. package/supabase/migrations/00000000000006_setup_rls_and_grants.sql +0 -872
  25. package/supabase/migrations/00000000000007_setup_indexes.sql +0 -158
  26. package/supabase/migrations/00000000000008_seed_platform_defaults.sql +0 -155
  27. package/supabase/migrations/00000000000009_seed_translations.sql +0 -801
  28. package/supabase/migrations/00000000000010_seed_content_scaffold.sql +0 -1088
  29. package/supabase/migrations/00000000000011_setup_cortex_ai_settings.sql +0 -81
  30. package/supabase/migrations/00000000000012_setup_commerce_coupons.sql +0 -275
  31. package/supabase/migrations/00000000000013_setup_cortex_ai_db_mutation_audit.sql +0 -47
  32. package/supabase/migrations/00000000000014_setup_content_drafts.sql +0 -119
  33. package/supabase/migrations/00000000000015_setup_product_drafts.sql +0 -97
  34. package/supabase/migrations/00000000000016_add_feature_image_to_pages.sql +0 -8
  35. package/supabase/migrations/00000000000017_add_product_blocks.sql +0 -118
  36. package/supabase/migrations/00000000000018_setup_bot_protection_settings.sql +0 -77
  37. package/supabase/migrations/00000000000019_add_product_categories.sql +0 -64
  38. package/supabase/migrations/00000000000020_add_category_translations.sql +0 -10
  39. package/supabase/migrations/00000000000021_migrate_hero_blocks_to_sections.sql +0 -29
  40. package/supabase/migrations/00000000000022_seed_cortex_ai_guide_post.sql +0 -184
  41. package/supabase/migrations/00000000000023_setup_custom_block_definitions.sql +0 -183
  42. package/supabase/migrations/00000000000024_setup_ucp_cart_sessions.sql +0 -72
  43. package/supabase/migrations/00000000000025_add_sale_schedule_columns.sql +0 -406
  44. package/supabase/migrations/00000000000026_seed_on_sale_translation.sql +0 -9
  45. package/supabase/migrations/00000000000027_setup_privacy_and_mfa.sql +0 -479
  46. package/supabase/migrations/00000000000028_clear_advisor_warnings.sql +0 -93
  47. package/supabase/migrations/00000000000029_refresh_setup_article.sql +0 -252
  48. package/supabase/migrations/00000000000030_setup_system_configuration.sql +0 -80
  49. package/supabase/migrations/00000000000031_seed_footer_navigation.sql +0 -85
  50. package/supabase/migrations/00000000000032_neutralize_seeded_contact_emails.sql +0 -34
  51. package/supabase/migrations/00000000000033_setup_config_settings.sql +0 -99
  52. package/supabase/migrations/00000000000034_enable_staff_2fa_reminder_default.sql +0 -15
  53. package/supabase/migrations/00000000000035_reassert_advisor_fixes.sql +0 -33
  54. package/supabase/migrations/00000000000036_setup_system_alerts.sql +0 -72
  55. package/supabase/migrations/00000000000037_refresh_setup_article_install_paths.sql +0 -317
  56. package/supabase/migrations/00000000000038_seed_consent_banner_translations.sql +0 -126
  57. package/supabase/migrations/00000000000039_setup_interactions.sql +0 -153
  58. package/supabase/migrations/00000000000040_add_profiles_fk_to_interactions.sql +0 -8
  59. package/supabase/migrations/00000000000041_seed_interactions_translations.sql +0 -145
  60. package/supabase/migrations/00000000000042_seed_deploy_to_vercel_ctas.sql +0 -72
  61. package/supabase/migrations/00000000000043_swap_home_hero_media_to_youtube.sql +0 -42
  62. package/supabase/migrations/00000000000044_swap_article_nx_graph_for_youtube.sql +0 -66
@@ -1,81 +0,0 @@
1
- -- 00000000000011_setup_cortex_ai_settings.sql
2
- -- NextBlock Cortex AI settings and sensitive BYOK policy hardening.
3
-
4
- COMMENT ON TABLE public.site_settings IS 'Key-value store for global site settings. Sensitive keys such as Cortex AI BYOK are protected by row-level policies.';
5
-
6
- DROP POLICY IF EXISTS site_settings_read_policy ON public.site_settings;
7
- DROP POLICY IF EXISTS site_settings_insert_policy ON public.site_settings;
8
- DROP POLICY IF EXISTS site_settings_update_policy ON public.site_settings;
9
- DROP POLICY IF EXISTS site_settings_delete_policy ON public.site_settings;
10
- DROP POLICY IF EXISTS site_settings_sensitive_read_policy ON public.site_settings;
11
- DROP POLICY IF EXISTS site_settings_sensitive_insert_policy ON public.site_settings;
12
- DROP POLICY IF EXISTS site_settings_sensitive_update_policy ON public.site_settings;
13
- DROP POLICY IF EXISTS site_settings_sensitive_delete_policy ON public.site_settings;
14
-
15
- CREATE POLICY site_settings_read_policy
16
- ON public.site_settings
17
- FOR SELECT
18
- TO public
19
- USING (
20
- key <> 'cortex_ai_openrouter_api_key'
21
- OR (
22
- key = 'cortex_ai_openrouter_api_key'
23
- AND (SELECT auth.role()) = 'authenticated'
24
- AND (SELECT public.get_current_user_role()) = 'ADMIN'
25
- )
26
- );
27
-
28
- CREATE POLICY site_settings_insert_policy
29
- ON public.site_settings
30
- FOR INSERT
31
- TO authenticated
32
- WITH CHECK (
33
- (
34
- key <> 'cortex_ai_openrouter_api_key'
35
- AND (SELECT public.get_current_user_role()) IN ('ADMIN', 'WRITER')
36
- )
37
- OR (
38
- key = 'cortex_ai_openrouter_api_key'
39
- AND (SELECT public.get_current_user_role()) = 'ADMIN'
40
- )
41
- );
42
-
43
- CREATE POLICY site_settings_update_policy
44
- ON public.site_settings
45
- FOR UPDATE
46
- TO authenticated
47
- USING (
48
- (
49
- key <> 'cortex_ai_openrouter_api_key'
50
- AND (SELECT public.get_current_user_role()) IN ('ADMIN', 'WRITER')
51
- )
52
- OR (
53
- key = 'cortex_ai_openrouter_api_key'
54
- AND (SELECT public.get_current_user_role()) = 'ADMIN'
55
- )
56
- )
57
- WITH CHECK (
58
- (
59
- key <> 'cortex_ai_openrouter_api_key'
60
- AND (SELECT public.get_current_user_role()) IN ('ADMIN', 'WRITER')
61
- )
62
- OR (
63
- key = 'cortex_ai_openrouter_api_key'
64
- AND (SELECT public.get_current_user_role()) = 'ADMIN'
65
- )
66
- );
67
-
68
- CREATE POLICY site_settings_delete_policy
69
- ON public.site_settings
70
- FOR DELETE
71
- TO authenticated
72
- USING (
73
- (
74
- key <> 'cortex_ai_openrouter_api_key'
75
- AND (SELECT public.get_current_user_role()) IN ('ADMIN', 'WRITER')
76
- )
77
- OR (
78
- key = 'cortex_ai_openrouter_api_key'
79
- AND (SELECT public.get_current_user_role()) = 'ADMIN'
80
- )
81
- );
@@ -1,275 +0,0 @@
1
- -- 00000000000012_setup_commerce_coupons.sql
2
- -- Unified commerce coupons for Stripe and Freemius checkout.
3
-
4
- CREATE TABLE public.coupons (
5
- id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
6
- code text NOT NULL,
7
- name text NOT NULL,
8
- internal_note text,
9
- provider_scope text NOT NULL DEFAULT 'all',
10
- discount_type text NOT NULL,
11
- discount_amount integer NOT NULL,
12
- is_active boolean NOT NULL DEFAULT true,
13
- starts_at timestamptz,
14
- ends_at timestamptz,
15
- redemption_limit integer,
16
- redemptions_count integer NOT NULL DEFAULT 0,
17
- freemius_sync_status text NOT NULL DEFAULT 'not_synced',
18
- freemius_sync_error text,
19
- created_at timestamptz NOT NULL DEFAULT now(),
20
- updated_at timestamptz NOT NULL DEFAULT now(),
21
- CONSTRAINT coupons_code_not_blank CHECK (char_length(btrim(code)) > 0),
22
- CONSTRAINT coupons_name_not_blank CHECK (char_length(btrim(name)) > 0),
23
- CONSTRAINT coupons_provider_scope_valid
24
- CHECK (provider_scope IN ('all', 'stripe', 'freemius')),
25
- CONSTRAINT coupons_discount_type_valid
26
- CHECK (discount_type IN ('percent', 'fixed')),
27
- CONSTRAINT coupons_discount_amount_positive
28
- CHECK (discount_amount > 0),
29
- CONSTRAINT coupons_percent_amount_valid
30
- CHECK (discount_type <> 'percent' OR discount_amount <= 100),
31
- CONSTRAINT coupons_redemption_limit_positive
32
- CHECK (redemption_limit IS NULL OR redemption_limit > 0),
33
- CONSTRAINT coupons_redemptions_count_nonnegative
34
- CHECK (redemptions_count >= 0),
35
- CONSTRAINT coupons_date_window_valid
36
- CHECK (starts_at IS NULL OR ends_at IS NULL OR starts_at < ends_at),
37
- CONSTRAINT coupons_freemius_sync_status_valid
38
- CHECK (freemius_sync_status IN ('not_synced', 'pending', 'synced', 'failed', 'not_required'))
39
- );
40
-
41
- CREATE UNIQUE INDEX coupons_code_unique
42
- ON public.coupons (upper(code));
43
-
44
- COMMENT ON TABLE public.coupons IS
45
- 'Unified commerce coupons managed by NextBlock CMS and applied through provider-aware checkout.';
46
- COMMENT ON COLUMN public.coupons.provider_scope IS
47
- 'Provider eligibility: all, stripe, or freemius.';
48
- COMMENT ON COLUMN public.coupons.discount_amount IS
49
- 'Percent value for percent coupons, or fixed minor-unit amount for fixed coupons.';
50
- COMMENT ON COLUMN public.coupons.freemius_sync_status IS
51
- 'Aggregate status for syncing this coupon to Freemius product coupon records.';
52
-
53
- CREATE TABLE public.coupon_products (
54
- coupon_id uuid NOT NULL REFERENCES public.coupons(id) ON DELETE CASCADE,
55
- product_id uuid NOT NULL REFERENCES public.products(id) ON DELETE CASCADE,
56
- created_at timestamptz NOT NULL DEFAULT now(),
57
- PRIMARY KEY (coupon_id, product_id)
58
- );
59
-
60
- COMMENT ON TABLE public.coupon_products IS
61
- 'Optional product allow-list for coupons. No rows means all products in the provider scope are eligible.';
62
-
63
- CREATE TABLE public.coupon_freemius_mappings (
64
- id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
65
- coupon_id uuid NOT NULL REFERENCES public.coupons(id) ON DELETE CASCADE,
66
- product_id uuid REFERENCES public.products(id) ON DELETE SET NULL,
67
- freemius_product_id text NOT NULL,
68
- freemius_coupon_id text,
69
- freemius_coupon_code text NOT NULL,
70
- sync_status text NOT NULL DEFAULT 'pending',
71
- sync_error text,
72
- remote_payload jsonb,
73
- last_synced_at timestamptz,
74
- created_at timestamptz NOT NULL DEFAULT now(),
75
- updated_at timestamptz NOT NULL DEFAULT now(),
76
- CONSTRAINT coupon_freemius_mappings_product_not_blank
77
- CHECK (char_length(btrim(freemius_product_id)) > 0),
78
- CONSTRAINT coupon_freemius_mappings_code_not_blank
79
- CHECK (char_length(btrim(freemius_coupon_code)) > 0),
80
- CONSTRAINT coupon_freemius_mappings_sync_status_valid
81
- CHECK (sync_status IN ('pending', 'synced', 'failed', 'deleted'))
82
- );
83
-
84
- CREATE UNIQUE INDEX coupon_freemius_mappings_coupon_product_unique
85
- ON public.coupon_freemius_mappings (coupon_id, freemius_product_id);
86
-
87
- CREATE TABLE public.coupon_redemptions (
88
- id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
89
- coupon_id uuid REFERENCES public.coupons(id) ON DELETE SET NULL,
90
- order_id uuid REFERENCES public.orders(id) ON DELETE CASCADE,
91
- coupon_code text NOT NULL,
92
- provider text NOT NULL CHECK (provider IN ('stripe', 'freemius')),
93
- discount_total integer NOT NULL DEFAULT 0 CHECK (discount_total >= 0),
94
- user_id uuid REFERENCES auth.users(id) ON DELETE SET NULL,
95
- customer_email text,
96
- metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
97
- redeemed_at timestamptz NOT NULL DEFAULT now(),
98
- CONSTRAINT coupon_redemptions_code_not_blank CHECK (char_length(btrim(coupon_code)) > 0)
99
- );
100
-
101
- CREATE UNIQUE INDEX coupon_redemptions_order_unique
102
- ON public.coupon_redemptions (order_id)
103
- WHERE order_id IS NOT NULL;
104
-
105
- ALTER TABLE public.orders
106
- ADD COLUMN coupon_id uuid REFERENCES public.coupons(id) ON DELETE SET NULL,
107
- ADD COLUMN coupon_code text,
108
- ADD COLUMN discount_total integer NOT NULL DEFAULT 0 CHECK (discount_total >= 0),
109
- ADD COLUMN discount_details jsonb;
110
-
111
- COMMENT ON COLUMN public.orders.coupon_code IS
112
- 'Coupon code applied to the order at checkout time.';
113
- COMMENT ON COLUMN public.orders.discount_total IS
114
- 'Total discount applied to this order in the smallest currency unit.';
115
- COMMENT ON COLUMN public.orders.discount_details IS
116
- 'Provider-aware coupon quote details captured at checkout.';
117
-
118
- CREATE OR REPLACE FUNCTION public.handle_coupons_write()
119
- RETURNS trigger
120
- LANGUAGE plpgsql
121
- SET search_path = ''
122
- AS $$
123
- BEGIN
124
- NEW.code := upper(regexp_replace(btrim(NEW.code), '\s+', '', 'g'));
125
- NEW.name := btrim(NEW.name);
126
- NEW.provider_scope := lower(btrim(NEW.provider_scope));
127
- NEW.discount_type := lower(btrim(NEW.discount_type));
128
- NEW.freemius_sync_status := lower(btrim(COALESCE(NEW.freemius_sync_status, 'not_synced')));
129
- NEW.updated_at := now();
130
-
131
- IF NEW.created_at IS NULL THEN
132
- NEW.created_at := now();
133
- END IF;
134
-
135
- RETURN NEW;
136
- END;
137
- $$;
138
-
139
- CREATE OR REPLACE FUNCTION public.handle_coupon_freemius_mappings_write()
140
- RETURNS trigger
141
- LANGUAGE plpgsql
142
- SET search_path = ''
143
- AS $$
144
- BEGIN
145
- NEW.freemius_product_id := btrim(NEW.freemius_product_id);
146
- NEW.freemius_coupon_code := upper(regexp_replace(btrim(NEW.freemius_coupon_code), '\s+', '', 'g'));
147
- NEW.sync_status := lower(btrim(COALESCE(NEW.sync_status, 'pending')));
148
- NEW.updated_at := now();
149
-
150
- IF NEW.created_at IS NULL THEN
151
- NEW.created_at := now();
152
- END IF;
153
-
154
- RETURN NEW;
155
- END;
156
- $$;
157
-
158
- DROP TRIGGER IF EXISTS on_coupons_write ON public.coupons;
159
- CREATE TRIGGER on_coupons_write
160
- BEFORE INSERT OR UPDATE ON public.coupons
161
- FOR EACH ROW
162
- EXECUTE FUNCTION public.handle_coupons_write();
163
-
164
- DROP TRIGGER IF EXISTS on_coupon_freemius_mappings_write ON public.coupon_freemius_mappings;
165
- CREATE TRIGGER on_coupon_freemius_mappings_write
166
- BEFORE INSERT OR UPDATE ON public.coupon_freemius_mappings
167
- FOR EACH ROW
168
- EXECUTE FUNCTION public.handle_coupon_freemius_mappings_write();
169
-
170
- CREATE INDEX idx_coupons_active_dates
171
- ON public.coupons (is_active, starts_at, ends_at);
172
-
173
- CREATE INDEX idx_coupon_products_product_id
174
- ON public.coupon_products (product_id);
175
-
176
- CREATE INDEX idx_coupon_freemius_mappings_product_id
177
- ON public.coupon_freemius_mappings (product_id)
178
- WHERE product_id IS NOT NULL;
179
-
180
- CREATE INDEX idx_coupon_freemius_mappings_freemius_product_id
181
- ON public.coupon_freemius_mappings (freemius_product_id);
182
-
183
- CREATE INDEX idx_coupon_redemptions_coupon_id
184
- ON public.coupon_redemptions (coupon_id);
185
-
186
- CREATE INDEX idx_coupon_redemptions_user_id
187
- ON public.coupon_redemptions (user_id)
188
- WHERE user_id IS NOT NULL;
189
-
190
- CREATE INDEX idx_orders_coupon_id
191
- ON public.orders (coupon_id)
192
- WHERE coupon_id IS NOT NULL;
193
-
194
- ALTER TABLE public.coupons ENABLE ROW LEVEL SECURITY;
195
- ALTER TABLE public.coupon_products ENABLE ROW LEVEL SECURITY;
196
- ALTER TABLE public.coupon_freemius_mappings ENABLE ROW LEVEL SECURITY;
197
- ALTER TABLE public.coupon_redemptions ENABLE ROW LEVEL SECURITY;
198
-
199
- GRANT ALL ON public.coupons TO authenticated, service_role;
200
- GRANT ALL ON public.coupon_products TO authenticated, service_role;
201
- GRANT ALL ON public.coupon_freemius_mappings TO authenticated, service_role;
202
- GRANT ALL ON public.coupon_redemptions TO authenticated, service_role;
203
-
204
- CREATE POLICY coupons_admin_select_policy
205
- ON public.coupons
206
- FOR SELECT
207
- TO authenticated
208
- USING (((SELECT public.is_admin()) IS TRUE));
209
-
210
- CREATE POLICY coupons_admin_insert_policy
211
- ON public.coupons
212
- FOR INSERT
213
- TO authenticated
214
- WITH CHECK (((SELECT public.is_admin()) IS TRUE));
215
-
216
- CREATE POLICY coupons_admin_update_policy
217
- ON public.coupons
218
- FOR UPDATE
219
- TO authenticated
220
- USING (((SELECT public.is_admin()) IS TRUE))
221
- WITH CHECK (((SELECT public.is_admin()) IS TRUE));
222
-
223
- CREATE POLICY coupons_admin_delete_policy
224
- ON public.coupons
225
- FOR DELETE
226
- TO authenticated
227
- USING (((SELECT public.is_admin()) IS TRUE));
228
-
229
- CREATE POLICY coupons_service_role_policy
230
- ON public.coupons
231
- FOR ALL
232
- TO service_role
233
- USING (true)
234
- WITH CHECK (true);
235
-
236
- CREATE POLICY coupon_products_admin_policy
237
- ON public.coupon_products
238
- FOR ALL
239
- TO authenticated
240
- USING (((SELECT public.is_admin()) IS TRUE))
241
- WITH CHECK (((SELECT public.is_admin()) IS TRUE));
242
-
243
- CREATE POLICY coupon_products_service_role_policy
244
- ON public.coupon_products
245
- FOR ALL
246
- TO service_role
247
- USING (true)
248
- WITH CHECK (true);
249
-
250
- CREATE POLICY coupon_freemius_mappings_admin_policy
251
- ON public.coupon_freemius_mappings
252
- FOR ALL
253
- TO authenticated
254
- USING (((SELECT public.is_admin()) IS TRUE))
255
- WITH CHECK (((SELECT public.is_admin()) IS TRUE));
256
-
257
- CREATE POLICY coupon_freemius_mappings_service_role_policy
258
- ON public.coupon_freemius_mappings
259
- FOR ALL
260
- TO service_role
261
- USING (true)
262
- WITH CHECK (true);
263
-
264
- CREATE POLICY coupon_redemptions_admin_select_policy
265
- ON public.coupon_redemptions
266
- FOR SELECT
267
- TO authenticated
268
- USING (((SELECT public.is_admin()) IS TRUE));
269
-
270
- CREATE POLICY coupon_redemptions_service_role_policy
271
- ON public.coupon_redemptions
272
- FOR ALL
273
- TO service_role
274
- USING (true)
275
- WITH CHECK (true);
@@ -1,47 +0,0 @@
1
- -- 00000000000013_setup_cortex_ai_db_mutation_audit.sql
2
- -- Durable audit trail for confirmed Cortex AI database mutations.
3
-
4
- CREATE TABLE IF NOT EXISTS public.cortex_ai_db_mutation_audit (
5
- id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
6
- actor_user_id uuid REFERENCES public.profiles(id) ON DELETE SET NULL,
7
- tool_name text NOT NULL,
8
- action_name text NOT NULL,
9
- target_tables text[] NOT NULL DEFAULT '{}'::text[],
10
- operation_summary text NOT NULL,
11
- payload_hash text NOT NULL,
12
- payload jsonb NOT NULL DEFAULT '{}'::jsonb,
13
- preview jsonb NOT NULL DEFAULT '{}'::jsonb,
14
- status text NOT NULL CHECK (status IN ('success', 'failure')),
15
- error_message text,
16
- created_at timestamptz NOT NULL DEFAULT now()
17
- );
18
-
19
- COMMENT ON TABLE public.cortex_ai_db_mutation_audit IS
20
- 'Audit trail for confirmed Cortex AI database mutation attempts.';
21
- COMMENT ON COLUMN public.cortex_ai_db_mutation_audit.payload IS
22
- 'Redacted tool input payload for the confirmed mutation attempt.';
23
- COMMENT ON COLUMN public.cortex_ai_db_mutation_audit.preview IS
24
- 'Redacted confirmation preview shown before the mutation was confirmed.';
25
-
26
- ALTER TABLE public.cortex_ai_db_mutation_audit ENABLE ROW LEVEL SECURITY;
27
-
28
- GRANT SELECT, INSERT ON public.cortex_ai_db_mutation_audit TO authenticated, service_role;
29
-
30
- DROP POLICY IF EXISTS cortex_ai_db_mutation_audit_admin_read_policy
31
- ON public.cortex_ai_db_mutation_audit;
32
-
33
- CREATE POLICY cortex_ai_db_mutation_audit_admin_read_policy
34
- ON public.cortex_ai_db_mutation_audit
35
- FOR SELECT
36
- TO authenticated
37
- USING ((SELECT public.get_current_user_role()) = 'ADMIN');
38
-
39
- DROP POLICY IF EXISTS cortex_ai_db_mutation_audit_service_role_policy
40
- ON public.cortex_ai_db_mutation_audit;
41
-
42
- CREATE POLICY cortex_ai_db_mutation_audit_service_role_policy
43
- ON public.cortex_ai_db_mutation_audit
44
- FOR ALL
45
- TO service_role
46
- USING (true)
47
- WITH CHECK (true);
@@ -1,119 +0,0 @@
1
- -- 00000000000014_setup_content_drafts.sql
2
- -- Draft snapshots for front-end visual editing.
3
-
4
- CREATE TABLE IF NOT EXISTS public.content_drafts (
5
- id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
6
- parent_type text NOT NULL CHECK (parent_type IN ('page', 'post')),
7
- parent_id bigint NOT NULL,
8
- author_id uuid REFERENCES public.profiles(id) ON DELETE SET NULL,
9
- base_version integer NOT NULL DEFAULT 1,
10
- meta jsonb NOT NULL DEFAULT '{}'::jsonb,
11
- blocks jsonb NOT NULL DEFAULT '[]'::jsonb,
12
- created_at timestamptz NOT NULL DEFAULT now(),
13
- updated_at timestamptz NOT NULL DEFAULT now(),
14
- CONSTRAINT content_drafts_parent_unique UNIQUE (parent_type, parent_id),
15
- CONSTRAINT content_drafts_blocks_array CHECK (jsonb_typeof(blocks) = 'array'),
16
- CONSTRAINT content_drafts_meta_object CHECK (jsonb_typeof(meta) = 'object')
17
- );
18
-
19
- ALTER TABLE public.content_drafts
20
- ADD COLUMN IF NOT EXISTS parent_type text,
21
- ADD COLUMN IF NOT EXISTS parent_id bigint,
22
- ADD COLUMN IF NOT EXISTS author_id uuid REFERENCES public.profiles(id) ON DELETE SET NULL,
23
- ADD COLUMN IF NOT EXISTS base_version integer NOT NULL DEFAULT 1,
24
- ADD COLUMN IF NOT EXISTS meta jsonb NOT NULL DEFAULT '{}'::jsonb,
25
- ADD COLUMN IF NOT EXISTS blocks jsonb NOT NULL DEFAULT '[]'::jsonb,
26
- ADD COLUMN IF NOT EXISTS created_at timestamptz NOT NULL DEFAULT now(),
27
- ADD COLUMN IF NOT EXISTS updated_at timestamptz NOT NULL DEFAULT now();
28
-
29
- DO $$
30
- BEGIN
31
- IF NOT EXISTS (
32
- SELECT 1 FROM pg_constraint
33
- WHERE conname = 'content_drafts_parent_unique'
34
- AND conrelid = 'public.content_drafts'::regclass
35
- ) THEN
36
- ALTER TABLE public.content_drafts
37
- ADD CONSTRAINT content_drafts_parent_unique UNIQUE (parent_type, parent_id);
38
- END IF;
39
-
40
- IF NOT EXISTS (
41
- SELECT 1 FROM pg_constraint
42
- WHERE conname = 'content_drafts_blocks_array'
43
- AND conrelid = 'public.content_drafts'::regclass
44
- ) THEN
45
- ALTER TABLE public.content_drafts
46
- ADD CONSTRAINT content_drafts_blocks_array CHECK (jsonb_typeof(blocks) = 'array');
47
- END IF;
48
-
49
- IF NOT EXISTS (
50
- SELECT 1 FROM pg_constraint
51
- WHERE conname = 'content_drafts_meta_object'
52
- AND conrelid = 'public.content_drafts'::regclass
53
- ) THEN
54
- ALTER TABLE public.content_drafts
55
- ADD CONSTRAINT content_drafts_meta_object CHECK (jsonb_typeof(meta) = 'object');
56
- END IF;
57
- END $$;
58
-
59
- COMMENT ON TABLE public.content_drafts IS
60
- 'Draft snapshots used by Draft Mode and front-end visual editing before publishing to live page/post rows.';
61
- COMMENT ON COLUMN public.content_drafts.parent_type IS
62
- 'The content table this draft belongs to: page or post.';
63
- COMMENT ON COLUMN public.content_drafts.parent_id IS
64
- 'ID of the page or post being drafted.';
65
- COMMENT ON COLUMN public.content_drafts.base_version IS
66
- 'Published page/post version the draft was created from.';
67
- COMMENT ON COLUMN public.content_drafts.meta IS
68
- 'Draft page/post metadata snapshot.';
69
- COMMENT ON COLUMN public.content_drafts.blocks IS
70
- 'Ordered draft block snapshot, including block ids, block types, content, language ids, and order values.';
71
-
72
- CREATE INDEX IF NOT EXISTS content_drafts_author_id_idx ON public.content_drafts (author_id);
73
- CREATE INDEX IF NOT EXISTS content_drafts_parent_idx ON public.content_drafts (parent_type, parent_id);
74
- CREATE INDEX IF NOT EXISTS content_drafts_updated_at_idx ON public.content_drafts (updated_at DESC);
75
-
76
- DROP TRIGGER IF EXISTS on_content_drafts_update ON public.content_drafts;
77
- CREATE TRIGGER on_content_drafts_update
78
- BEFORE UPDATE ON public.content_drafts
79
- FOR EACH ROW
80
- EXECUTE FUNCTION public.set_current_timestamp_updated_at();
81
-
82
- ALTER TABLE public.content_drafts ENABLE ROW LEVEL SECURITY;
83
-
84
- DROP POLICY IF EXISTS content_drafts_select_policy
85
- ON public.content_drafts;
86
-
87
- CREATE POLICY content_drafts_select_policy
88
- ON public.content_drafts
89
- FOR SELECT
90
- TO authenticated
91
- USING ((SELECT public.get_current_user_role()) IN ('ADMIN', 'WRITER'));
92
-
93
- DROP POLICY IF EXISTS content_drafts_insert_policy
94
- ON public.content_drafts;
95
-
96
- CREATE POLICY content_drafts_insert_policy
97
- ON public.content_drafts
98
- FOR INSERT
99
- TO authenticated
100
- WITH CHECK ((SELECT public.get_current_user_role()) IN ('ADMIN', 'WRITER'));
101
-
102
- DROP POLICY IF EXISTS content_drafts_update_policy
103
- ON public.content_drafts;
104
-
105
- CREATE POLICY content_drafts_update_policy
106
- ON public.content_drafts
107
- FOR UPDATE
108
- TO authenticated
109
- USING ((SELECT public.get_current_user_role()) IN ('ADMIN', 'WRITER'))
110
- WITH CHECK ((SELECT public.get_current_user_role()) IN ('ADMIN', 'WRITER'));
111
-
112
- DROP POLICY IF EXISTS content_drafts_delete_policy
113
- ON public.content_drafts;
114
-
115
- CREATE POLICY content_drafts_delete_policy
116
- ON public.content_drafts
117
- FOR DELETE
118
- TO authenticated
119
- USING ((SELECT public.get_current_user_role()) IN ('ADMIN', 'WRITER'));
@@ -1,97 +0,0 @@
1
- -- 00000000000015_setup_product_drafts.sql
2
- -- Product draft snapshots for front-end visual editing.
3
-
4
- CREATE TABLE IF NOT EXISTS public.product_drafts (
5
- id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
6
- product_id uuid NOT NULL REFERENCES public.products(id) ON DELETE CASCADE,
7
- author_id uuid REFERENCES public.profiles(id) ON DELETE SET NULL,
8
- meta jsonb NOT NULL DEFAULT '{}'::jsonb,
9
- created_at timestamptz NOT NULL DEFAULT now(),
10
- updated_at timestamptz NOT NULL DEFAULT now(),
11
- CONSTRAINT product_drafts_product_unique UNIQUE (product_id),
12
- CONSTRAINT product_drafts_meta_object CHECK (jsonb_typeof(meta) = 'object')
13
- );
14
-
15
- ALTER TABLE public.product_drafts
16
- ADD COLUMN IF NOT EXISTS product_id uuid REFERENCES public.products(id) ON DELETE CASCADE,
17
- ADD COLUMN IF NOT EXISTS author_id uuid REFERENCES public.profiles(id) ON DELETE SET NULL,
18
- ADD COLUMN IF NOT EXISTS meta jsonb NOT NULL DEFAULT '{}'::jsonb,
19
- ADD COLUMN IF NOT EXISTS created_at timestamptz NOT NULL DEFAULT now(),
20
- ADD COLUMN IF NOT EXISTS updated_at timestamptz NOT NULL DEFAULT now();
21
-
22
- DO $$
23
- BEGIN
24
- IF NOT EXISTS (
25
- SELECT 1 FROM pg_constraint
26
- WHERE conname = 'product_drafts_product_unique'
27
- AND conrelid = 'public.product_drafts'::regclass
28
- ) THEN
29
- ALTER TABLE public.product_drafts
30
- ADD CONSTRAINT product_drafts_product_unique UNIQUE (product_id);
31
- END IF;
32
-
33
- IF NOT EXISTS (
34
- SELECT 1 FROM pg_constraint
35
- WHERE conname = 'product_drafts_meta_object'
36
- AND conrelid = 'public.product_drafts'::regclass
37
- ) THEN
38
- ALTER TABLE public.product_drafts
39
- ADD CONSTRAINT product_drafts_meta_object CHECK (jsonb_typeof(meta) = 'object');
40
- END IF;
41
- END $$;
42
-
43
- COMMENT ON TABLE public.product_drafts IS
44
- 'Draft product metadata snapshots used by Draft Mode and front-end visual editing before publishing to live product rows.';
45
- COMMENT ON COLUMN public.product_drafts.product_id IS
46
- 'ID of the product being drafted.';
47
- COMMENT ON COLUMN public.product_drafts.meta IS
48
- 'Draft product metadata snapshot. Front-end visual editing currently mutates visible title, short_description, and description_json fields.';
49
-
50
- CREATE INDEX IF NOT EXISTS product_drafts_author_id_idx ON public.product_drafts (author_id);
51
- CREATE INDEX IF NOT EXISTS product_drafts_product_id_idx ON public.product_drafts (product_id);
52
- CREATE INDEX IF NOT EXISTS product_drafts_updated_at_idx ON public.product_drafts (updated_at DESC);
53
-
54
- DROP TRIGGER IF EXISTS on_product_drafts_update ON public.product_drafts;
55
- CREATE TRIGGER on_product_drafts_update
56
- BEFORE UPDATE ON public.product_drafts
57
- FOR EACH ROW
58
- EXECUTE FUNCTION public.set_current_timestamp_updated_at();
59
-
60
- ALTER TABLE public.product_drafts ENABLE ROW LEVEL SECURITY;
61
-
62
- DROP POLICY IF EXISTS product_drafts_select_policy
63
- ON public.product_drafts;
64
-
65
- CREATE POLICY product_drafts_select_policy
66
- ON public.product_drafts
67
- FOR SELECT
68
- TO authenticated
69
- USING ((SELECT public.get_current_user_role()) IN ('ADMIN', 'WRITER'));
70
-
71
- DROP POLICY IF EXISTS product_drafts_insert_policy
72
- ON public.product_drafts;
73
-
74
- CREATE POLICY product_drafts_insert_policy
75
- ON public.product_drafts
76
- FOR INSERT
77
- TO authenticated
78
- WITH CHECK ((SELECT public.get_current_user_role()) IN ('ADMIN', 'WRITER'));
79
-
80
- DROP POLICY IF EXISTS product_drafts_update_policy
81
- ON public.product_drafts;
82
-
83
- CREATE POLICY product_drafts_update_policy
84
- ON public.product_drafts
85
- FOR UPDATE
86
- TO authenticated
87
- USING ((SELECT public.get_current_user_role()) IN ('ADMIN', 'WRITER'))
88
- WITH CHECK ((SELECT public.get_current_user_role()) IN ('ADMIN', 'WRITER'));
89
-
90
- DROP POLICY IF EXISTS product_drafts_delete_policy
91
- ON public.product_drafts;
92
-
93
- CREATE POLICY product_drafts_delete_policy
94
- ON public.product_drafts
95
- FOR DELETE
96
- TO authenticated
97
- USING ((SELECT public.get_current_user_role()) IN ('ADMIN', 'WRITER'));
@@ -1,8 +0,0 @@
1
- ALTER TABLE public.pages
2
- ADD COLUMN IF NOT EXISTS feature_image_id uuid REFERENCES public.media(id) ON DELETE SET NULL;
3
-
4
- COMMENT ON COLUMN public.pages.feature_image_id IS
5
- 'ID of the media item to be used as the page feature image.';
6
-
7
- CREATE INDEX IF NOT EXISTS idx_pages_feature_image_id
8
- ON public.pages (feature_image_id);