@fayz-ai/plugin-marketing 0.2.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,13 +1,31 @@
1
- // Inline copy of 001_content_planner.sql for manifest.migrations[] (the
2
- // forward-compat install-lifecycle delivery). The .sql file next to this is
3
- // what beauty-saas' db-apply actually executes today — keep both in sync.
1
+ // AUTO-GENERATED from 000_plg_rename.sql, 001_content_planner.sql, 002_multi_platform.sql, 003_recording_ops.sql — regenerate with scripts/embed-migrations.mjs
2
+ // SQL files are the source of truth; this inline copy lets the manifest declare
3
+ // migrations as data. Do not edit by hand — run the embed script instead.
4
+
5
+ export const MIGRATION_000_PLG_RENAME = `-- 000_plg_rename.sql — rename legacy marketing tables to plg_marketing_* for pools
6
+ -- provisioned before the industry-pool rename. Guarded: fires only when legacy
7
+ -- name exists and target does not, so fresh pools skip every branch.
8
+ DO $$
9
+ BEGIN
10
+ IF to_regclass('public.mkt_social_accounts') IS NOT NULL AND to_regclass('public.plg_marketing_social_accounts') IS NULL THEN
11
+ ALTER TABLE public.mkt_social_accounts RENAME TO plg_marketing_social_accounts;
12
+ END IF;
13
+ IF to_regclass('public.mkt_content_plans') IS NOT NULL AND to_regclass('public.plg_marketing_content_plans') IS NULL THEN
14
+ ALTER TABLE public.mkt_content_plans RENAME TO plg_marketing_content_plans;
15
+ END IF;
16
+ IF to_regclass('public.mkt_content_posts') IS NOT NULL AND to_regclass('public.plg_marketing_content_posts') IS NULL THEN
17
+ ALTER TABLE public.mkt_content_posts RENAME TO plg_marketing_content_posts;
18
+ END IF;
19
+ END $$;
20
+ `
21
+
4
22
  export const MIGRATION_001_CONTENT_PLANNER = `-- Marketing Plugin: Content Planner
5
- -- Prefix: mkt_
23
+ -- Prefix: plg_marketing_
6
24
  -- Social accounts + content plans + posts (Notion-style markdown pages).
7
25
 
8
- CREATE TABLE IF NOT EXISTS public.mkt_social_accounts (
26
+ CREATE TABLE IF NOT EXISTS public.plg_marketing_social_accounts (
9
27
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
10
- tenant_id uuid NOT NULL REFERENCES saas_core.tenants(id) ON DELETE CASCADE,
28
+ tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
11
29
  name text NOT NULL,
12
30
  handle text,
13
31
  platform text NOT NULL DEFAULT 'instagram'
@@ -15,13 +33,13 @@ CREATE TABLE IF NOT EXISTS public.mkt_social_accounts (
15
33
  is_active boolean NOT NULL DEFAULT true,
16
34
  created_at timestamptz NOT NULL DEFAULT now()
17
35
  );
18
- ALTER TABLE public.mkt_social_accounts ENABLE ROW LEVEL SECURITY;
19
- CREATE INDEX IF NOT EXISTS idx_mkt_social_accounts_tenant ON public.mkt_social_accounts(tenant_id);
36
+ ALTER TABLE public.plg_marketing_social_accounts ENABLE ROW LEVEL SECURITY;
37
+ CREATE INDEX IF NOT EXISTS idx_plg_marketing_social_accounts_tenant ON public.plg_marketing_social_accounts(tenant_id);
20
38
 
21
- CREATE TABLE IF NOT EXISTS public.mkt_content_plans (
39
+ CREATE TABLE IF NOT EXISTS public.plg_marketing_content_plans (
22
40
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
23
- tenant_id uuid NOT NULL REFERENCES saas_core.tenants(id) ON DELETE CASCADE,
24
- account_id uuid NOT NULL REFERENCES public.mkt_social_accounts(id) ON DELETE CASCADE,
41
+ tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
42
+ account_id uuid NOT NULL REFERENCES public.plg_marketing_social_accounts(id) ON DELETE CASCADE,
25
43
  name text NOT NULL,
26
44
  status text NOT NULL DEFAULT 'active'
27
45
  CHECK (status IN ('draft', 'active', 'archived')),
@@ -36,14 +54,14 @@ CREATE TABLE IF NOT EXISTS public.mkt_content_plans (
36
54
  created_at timestamptz NOT NULL DEFAULT now(),
37
55
  updated_at timestamptz NOT NULL DEFAULT now()
38
56
  );
39
- ALTER TABLE public.mkt_content_plans ENABLE ROW LEVEL SECURITY;
40
- CREATE INDEX IF NOT EXISTS idx_mkt_content_plans_tenant ON public.mkt_content_plans(tenant_id);
41
- CREATE INDEX IF NOT EXISTS idx_mkt_content_plans_account ON public.mkt_content_plans(account_id);
57
+ ALTER TABLE public.plg_marketing_content_plans ENABLE ROW LEVEL SECURITY;
58
+ CREATE INDEX IF NOT EXISTS idx_plg_marketing_content_plans_tenant ON public.plg_marketing_content_plans(tenant_id);
59
+ CREATE INDEX IF NOT EXISTS idx_plg_marketing_content_plans_account ON public.plg_marketing_content_plans(account_id);
42
60
 
43
- CREATE TABLE IF NOT EXISTS public.mkt_content_posts (
61
+ CREATE TABLE IF NOT EXISTS public.plg_marketing_content_posts (
44
62
  id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
45
- tenant_id uuid NOT NULL REFERENCES saas_core.tenants(id) ON DELETE CASCADE,
46
- plan_id uuid NOT NULL REFERENCES public.mkt_content_plans(id) ON DELETE CASCADE,
63
+ tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
64
+ plan_id uuid NOT NULL REFERENCES public.plg_marketing_content_plans(id) ON DELETE CASCADE,
47
65
  week_number integer NOT NULL DEFAULT 1,
48
66
  position integer NOT NULL DEFAULT 0,
49
67
  title text NOT NULL,
@@ -58,51 +76,51 @@ CREATE TABLE IF NOT EXISTS public.mkt_content_posts (
58
76
  created_at timestamptz NOT NULL DEFAULT now(),
59
77
  updated_at timestamptz NOT NULL DEFAULT now()
60
78
  );
61
- ALTER TABLE public.mkt_content_posts ENABLE ROW LEVEL SECURITY;
62
- CREATE INDEX IF NOT EXISTS idx_mkt_content_posts_tenant ON public.mkt_content_posts(tenant_id);
63
- CREATE INDEX IF NOT EXISTS idx_mkt_content_posts_plan ON public.mkt_content_posts(plan_id, week_number, position);
64
- CREATE INDEX IF NOT EXISTS idx_mkt_content_posts_status ON public.mkt_content_posts(tenant_id, status);
65
-
66
- -- RLS policies for mkt_social_accounts
67
- DROP POLICY IF EXISTS mkt_social_accounts_select ON public.mkt_social_accounts;
68
- DROP POLICY IF EXISTS mkt_social_accounts_insert ON public.mkt_social_accounts;
69
- DROP POLICY IF EXISTS mkt_social_accounts_update ON public.mkt_social_accounts;
70
- DROP POLICY IF EXISTS mkt_social_accounts_delete ON public.mkt_social_accounts;
71
- CREATE POLICY mkt_social_accounts_select ON public.mkt_social_accounts FOR SELECT TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
72
- CREATE POLICY mkt_social_accounts_insert ON public.mkt_social_accounts FOR INSERT TO authenticated WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));
73
- CREATE POLICY mkt_social_accounts_update ON public.mkt_social_accounts FOR UPDATE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
74
- CREATE POLICY mkt_social_accounts_delete ON public.mkt_social_accounts FOR DELETE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
75
- GRANT SELECT, INSERT, UPDATE, DELETE ON public.mkt_social_accounts TO authenticated;
76
-
77
- -- RLS policies for mkt_content_plans
78
- DROP POLICY IF EXISTS mkt_content_plans_select ON public.mkt_content_plans;
79
- DROP POLICY IF EXISTS mkt_content_plans_insert ON public.mkt_content_plans;
80
- DROP POLICY IF EXISTS mkt_content_plans_update ON public.mkt_content_plans;
81
- DROP POLICY IF EXISTS mkt_content_plans_delete ON public.mkt_content_plans;
82
- CREATE POLICY mkt_content_plans_select ON public.mkt_content_plans FOR SELECT TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
83
- CREATE POLICY mkt_content_plans_insert ON public.mkt_content_plans FOR INSERT TO authenticated WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));
84
- CREATE POLICY mkt_content_plans_update ON public.mkt_content_plans FOR UPDATE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
85
- CREATE POLICY mkt_content_plans_delete ON public.mkt_content_plans FOR DELETE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
86
- GRANT SELECT, INSERT, UPDATE, DELETE ON public.mkt_content_plans TO authenticated;
87
-
88
- -- RLS policies for mkt_content_posts
89
- DROP POLICY IF EXISTS mkt_content_posts_select ON public.mkt_content_posts;
90
- DROP POLICY IF EXISTS mkt_content_posts_insert ON public.mkt_content_posts;
91
- DROP POLICY IF EXISTS mkt_content_posts_update ON public.mkt_content_posts;
92
- DROP POLICY IF EXISTS mkt_content_posts_delete ON public.mkt_content_posts;
93
- CREATE POLICY mkt_content_posts_select ON public.mkt_content_posts FOR SELECT TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
94
- CREATE POLICY mkt_content_posts_insert ON public.mkt_content_posts FOR INSERT TO authenticated WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));
95
- CREATE POLICY mkt_content_posts_update ON public.mkt_content_posts FOR UPDATE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
96
- CREATE POLICY mkt_content_posts_delete ON public.mkt_content_posts FOR DELETE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
97
- GRANT SELECT, INSERT, UPDATE, DELETE ON public.mkt_content_posts TO authenticated;`
98
-
99
- // Inline copy of 002_multi_platform.sql — same keep-in-sync contract as 001.
79
+ ALTER TABLE public.plg_marketing_content_posts ENABLE ROW LEVEL SECURITY;
80
+ CREATE INDEX IF NOT EXISTS idx_plg_marketing_content_posts_tenant ON public.plg_marketing_content_posts(tenant_id);
81
+ CREATE INDEX IF NOT EXISTS idx_plg_marketing_content_posts_plan ON public.plg_marketing_content_posts(plan_id, week_number, position);
82
+ CREATE INDEX IF NOT EXISTS idx_plg_marketing_content_posts_status ON public.plg_marketing_content_posts(tenant_id, status);
83
+
84
+ -- RLS policies for plg_marketing_social_accounts
85
+ DROP POLICY IF EXISTS plg_marketing_social_accounts_select ON public.plg_marketing_social_accounts;
86
+ DROP POLICY IF EXISTS plg_marketing_social_accounts_insert ON public.plg_marketing_social_accounts;
87
+ DROP POLICY IF EXISTS plg_marketing_social_accounts_update ON public.plg_marketing_social_accounts;
88
+ DROP POLICY IF EXISTS plg_marketing_social_accounts_delete ON public.plg_marketing_social_accounts;
89
+ CREATE POLICY plg_marketing_social_accounts_select ON public.plg_marketing_social_accounts FOR SELECT TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
90
+ CREATE POLICY plg_marketing_social_accounts_insert ON public.plg_marketing_social_accounts FOR INSERT TO authenticated WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));
91
+ CREATE POLICY plg_marketing_social_accounts_update ON public.plg_marketing_social_accounts FOR UPDATE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
92
+ CREATE POLICY plg_marketing_social_accounts_delete ON public.plg_marketing_social_accounts FOR DELETE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
93
+ GRANT SELECT, INSERT, UPDATE, DELETE ON public.plg_marketing_social_accounts TO authenticated;
94
+
95
+ -- RLS policies for plg_marketing_content_plans
96
+ DROP POLICY IF EXISTS plg_marketing_content_plans_select ON public.plg_marketing_content_plans;
97
+ DROP POLICY IF EXISTS plg_marketing_content_plans_insert ON public.plg_marketing_content_plans;
98
+ DROP POLICY IF EXISTS plg_marketing_content_plans_update ON public.plg_marketing_content_plans;
99
+ DROP POLICY IF EXISTS plg_marketing_content_plans_delete ON public.plg_marketing_content_plans;
100
+ CREATE POLICY plg_marketing_content_plans_select ON public.plg_marketing_content_plans FOR SELECT TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
101
+ CREATE POLICY plg_marketing_content_plans_insert ON public.plg_marketing_content_plans FOR INSERT TO authenticated WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));
102
+ CREATE POLICY plg_marketing_content_plans_update ON public.plg_marketing_content_plans FOR UPDATE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
103
+ CREATE POLICY plg_marketing_content_plans_delete ON public.plg_marketing_content_plans FOR DELETE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
104
+ GRANT SELECT, INSERT, UPDATE, DELETE ON public.plg_marketing_content_plans TO authenticated;
105
+
106
+ -- RLS policies for plg_marketing_content_posts
107
+ DROP POLICY IF EXISTS plg_marketing_content_posts_select ON public.plg_marketing_content_posts;
108
+ DROP POLICY IF EXISTS plg_marketing_content_posts_insert ON public.plg_marketing_content_posts;
109
+ DROP POLICY IF EXISTS plg_marketing_content_posts_update ON public.plg_marketing_content_posts;
110
+ DROP POLICY IF EXISTS plg_marketing_content_posts_delete ON public.plg_marketing_content_posts;
111
+ CREATE POLICY plg_marketing_content_posts_select ON public.plg_marketing_content_posts FOR SELECT TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
112
+ CREATE POLICY plg_marketing_content_posts_insert ON public.plg_marketing_content_posts FOR INSERT TO authenticated WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));
113
+ CREATE POLICY plg_marketing_content_posts_update ON public.plg_marketing_content_posts FOR UPDATE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
114
+ CREATE POLICY plg_marketing_content_posts_delete ON public.plg_marketing_content_posts FOR DELETE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
115
+ GRANT SELECT, INSERT, UPDATE, DELETE ON public.plg_marketing_content_posts TO authenticated;
116
+ `
117
+
100
118
  export const MIGRATION_002_MULTI_PLATFORM = `-- Marketing Plugin: multi-platform accounts + per-post targets.
101
119
  -- An account is a brand/profile that publishes to MANY platforms (Instagram,
102
120
  -- YouTube, TikTok, ...). Posts optionally narrow the target platforms; an
103
121
  -- empty array means "inherit the account's platforms".
104
122
 
105
- ALTER TABLE public.mkt_social_accounts
123
+ ALTER TABLE public.plg_marketing_social_accounts
106
124
  ADD COLUMN IF NOT EXISTS platforms text[] NOT NULL DEFAULT '{instagram}';
107
125
 
108
126
  -- Backfill from the legacy single-platform column, then drop it (also drops
@@ -111,29 +129,28 @@ DO $$
111
129
  BEGIN
112
130
  IF EXISTS (
113
131
  SELECT 1 FROM information_schema.columns
114
- WHERE table_schema = 'public' AND table_name = 'mkt_social_accounts' AND column_name = 'platform'
132
+ WHERE table_schema = 'public' AND table_name = 'plg_marketing_social_accounts' AND column_name = 'platform'
115
133
  ) THEN
116
- UPDATE public.mkt_social_accounts
134
+ UPDATE public.plg_marketing_social_accounts
117
135
  SET platforms = ARRAY[platform]
118
136
  WHERE platform IS NOT NULL AND platforms = '{instagram}';
119
- ALTER TABLE public.mkt_social_accounts DROP COLUMN platform;
137
+ ALTER TABLE public.plg_marketing_social_accounts DROP COLUMN platform;
120
138
  END IF;
121
139
  END $$;
122
140
 
123
- ALTER TABLE public.mkt_content_posts
124
- ADD COLUMN IF NOT EXISTS platforms text[] NOT NULL DEFAULT '{}';`
125
-
141
+ ALTER TABLE public.plg_marketing_content_posts
142
+ ADD COLUMN IF NOT EXISTS platforms text[] NOT NULL DEFAULT '{}';
143
+ `
126
144
 
127
- // Inline copy of 003_recording_ops.sql — same keep-in-sync contract as 001.
128
145
  export const MIGRATION_003_RECORDING_OPS = `-- Marketing Plugin: recording-day ops on posts.
129
146
  -- checklist: shooting checklist items [{ id, text, done }] — the on-set
130
147
  -- companion for recording day. media_url: uploaded asset (static posts get a
131
148
  -- caption + final art instead of a script).
132
149
 
133
- ALTER TABLE public.mkt_content_posts
150
+ ALTER TABLE public.plg_marketing_content_posts
134
151
  ADD COLUMN IF NOT EXISTS checklist jsonb NOT NULL DEFAULT '[]';
135
152
 
136
- ALTER TABLE public.mkt_content_posts
153
+ ALTER TABLE public.plg_marketing_content_posts
137
154
  ADD COLUMN IF NOT EXISTS media_url text;
138
155
 
139
156
  -- Public media bucket for content assets (mirrors the avatars-bucket pattern:
@@ -142,11 +159,19 @@ INSERT INTO storage.buckets (id, name, public)
142
159
  VALUES ('mkt-media', 'mkt-media', true)
143
160
  ON CONFLICT (id) DO NOTHING;
144
161
 
145
- DROP POLICY IF EXISTS mkt_media_read ON storage.objects;
146
- DROP POLICY IF EXISTS mkt_media_insert ON storage.objects;
147
- DROP POLICY IF EXISTS mkt_media_update ON storage.objects;
148
- DROP POLICY IF EXISTS mkt_media_delete ON storage.objects;
149
- CREATE POLICY mkt_media_read ON storage.objects FOR SELECT TO public USING (bucket_id = 'mkt-media');
150
- CREATE POLICY mkt_media_insert ON storage.objects FOR INSERT TO authenticated WITH CHECK (bucket_id = 'mkt-media');
151
- CREATE POLICY mkt_media_update ON storage.objects FOR UPDATE TO authenticated USING (bucket_id = 'mkt-media');
152
- CREATE POLICY mkt_media_delete ON storage.objects FOR DELETE TO authenticated USING (bucket_id = 'mkt-media');`
162
+ DROP POLICY IF EXISTS plg_marketing_media_read ON storage.objects;
163
+ DROP POLICY IF EXISTS plg_marketing_media_insert ON storage.objects;
164
+ DROP POLICY IF EXISTS plg_marketing_media_update ON storage.objects;
165
+ DROP POLICY IF EXISTS plg_marketing_media_delete ON storage.objects;
166
+ CREATE POLICY plg_marketing_media_read ON storage.objects FOR SELECT TO public USING (bucket_id = 'mkt-media');
167
+ CREATE POLICY plg_marketing_media_insert ON storage.objects FOR INSERT TO authenticated WITH CHECK (bucket_id = 'mkt-media');
168
+ CREATE POLICY plg_marketing_media_update ON storage.objects FOR UPDATE TO authenticated USING (bucket_id = 'mkt-media');
169
+ CREATE POLICY plg_marketing_media_delete ON storage.objects FOR DELETE TO authenticated USING (bucket_id = 'mkt-media');
170
+ `
171
+
172
+ export const MIGRATIONS: Array<{ id: string; sql: string }> = [
173
+ { id: "000_plg_rename", sql: MIGRATION_000_PLG_RENAME },
174
+ { id: "001_content_planner", sql: MIGRATION_001_CONTENT_PLANNER },
175
+ { id: "002_multi_platform", sql: MIGRATION_002_MULTI_PLATFORM },
176
+ { id: "003_recording_ops", sql: MIGRATION_003_RECORDING_OPS },
177
+ ]
@@ -11,7 +11,7 @@ import {
11
11
  // see src/migrations/001_content_planner.sql.
12
12
  // ---------------------------------------------------------------------------
13
13
 
14
- export const mktSocialAccounts = pgTable('mkt_social_accounts', {
14
+ export const mktSocialAccounts = pgTable('plg_marketing_social_accounts', {
15
15
  id: uuid('id').primaryKey().defaultRandom(),
16
16
  tenantId: tenantId(),
17
17
  name: text('name').notNull(),
@@ -20,9 +20,9 @@ export const mktSocialAccounts = pgTable('mkt_social_accounts', {
20
20
  platforms: text('platforms').array().notNull().default(['instagram']),
21
21
  isActive: boolean('is_active').notNull().default(true),
22
22
  ...createdAt,
23
- }, (t) => [index('idx_mkt_social_accounts_tenant').on(t.tenantId)])
23
+ }, (t) => [index('idx_plg_marketing_social_accounts_tenant').on(t.tenantId)])
24
24
 
25
- export const mktContentPlans = pgTable('mkt_content_plans', {
25
+ export const mktContentPlans = pgTable('plg_marketing_content_plans', {
26
26
  id: uuid('id').primaryKey().defaultRandom(),
27
27
  tenantId: tenantId(),
28
28
  accountId: uuid('account_id').notNull().references(() => mktSocialAccounts.id, { onDelete: 'cascade' }),
@@ -38,11 +38,11 @@ export const mktContentPlans = pgTable('mkt_content_plans', {
38
38
  briefMd: text('brief_md').notNull().default(''),
39
39
  ...timestamps,
40
40
  }, (t) => [
41
- index('idx_mkt_content_plans_tenant').on(t.tenantId),
42
- index('idx_mkt_content_plans_account').on(t.accountId),
41
+ index('idx_plg_marketing_content_plans_tenant').on(t.tenantId),
42
+ index('idx_plg_marketing_content_plans_account').on(t.accountId),
43
43
  ])
44
44
 
45
- export const mktContentPosts = pgTable('mkt_content_posts', {
45
+ export const mktContentPosts = pgTable('plg_marketing_content_posts', {
46
46
  id: uuid('id').primaryKey().defaultRandom(),
47
47
  tenantId: tenantId(),
48
48
  planId: uuid('plan_id').notNull().references(() => mktContentPlans.id, { onDelete: 'cascade' }),
@@ -63,7 +63,7 @@ export const mktContentPosts = pgTable('mkt_content_posts', {
63
63
  contentMd: text('content_md').notNull().default(''),
64
64
  ...timestamps,
65
65
  }, (t) => [
66
- index('idx_mkt_content_posts_tenant').on(t.tenantId),
67
- index('idx_mkt_content_posts_plan').on(t.planId, t.weekNumber, t.position),
68
- index('idx_mkt_content_posts_status').on(t.tenantId, t.status),
66
+ index('idx_plg_marketing_content_posts_tenant').on(t.tenantId),
67
+ index('idx_plg_marketing_content_posts_plan').on(t.planId, t.weekNumber, t.position),
68
+ index('idx_plg_marketing_content_posts_status').on(t.tenantId, t.status),
69
69
  ])