@nextsparkjs/plugin-social-media-publisher 0.1.0-beta.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.
@@ -0,0 +1,515 @@
1
+ # Configuration
2
+
3
+ ## Overview
4
+
5
+ The Social Media Publisher plugin requires specific configuration for Facebook OAuth, token encryption, and security settings. This guide covers all configuration options and best practices.
6
+
7
+ ## Environment Variables
8
+
9
+ ### Required Variables
10
+
11
+ ```bash
12
+ # ==============================================
13
+ # FACEBOOK OAUTH
14
+ # ==============================================
15
+
16
+ # Facebook App ID
17
+ FACEBOOK_CLIENT_ID=your_app_id
18
+
19
+ # Facebook App Secret
20
+ FACEBOOK_CLIENT_SECRET=your_app_secret
21
+
22
+ # ==============================================
23
+ # APPLICATION
24
+ # ==============================================
25
+
26
+ # Base URL (used for OAuth redirects)
27
+ NEXT_PUBLIC_APP_URL=https://yourdomain.com
28
+
29
+ # ==============================================
30
+ # SECURITY
31
+ # ==============================================
32
+
33
+ # 32-byte encryption key for tokens (64 hex characters)
34
+ OAUTH_ENCRYPTION_KEY=your_encryption_key_here
35
+ ```
36
+
37
+ ### Variable Details
38
+
39
+ #### `FACEBOOK_CLIENT_ID`
40
+
41
+ **Purpose:** Facebook App ID for OAuth authentication
42
+
43
+ **Where to Find:**
44
+ 1. Go to [Facebook Developers](https://developers.facebook.com/)
45
+ 2. Select your app
46
+ 3. Settings → Basic
47
+ 4. Copy "App ID"
48
+
49
+ **Example:**
50
+ ```bash
51
+ FACEBOOK_CLIENT_ID=123456789012345
52
+ ```
53
+
54
+ **Notes:**
55
+ - Same app can be used for Facebook Pages and Instagram Business
56
+ - No quotes needed
57
+ - Numeric string
58
+
59
+ #### `FACEBOOK_CLIENT_SECRET`
60
+
61
+ **Purpose:** Facebook App Secret for token exchange
62
+
63
+ **Where to Find:**
64
+ 1. Same location as App ID
65
+ 2. Settings → Basic
66
+ 3. Click "Show" next to "App Secret"
67
+ 4. Copy the secret
68
+
69
+ **Example:**
70
+ ```bash
71
+ FACEBOOK_CLIENT_SECRET=a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
72
+ ```
73
+
74
+ **Security:**
75
+ - ⚠️ **Never commit to version control**
76
+ - ⚠️ **Never expose in client-side code**
77
+ - ⚠️ **Never log or display**
78
+ - ✅ Store in environment variables
79
+ - ✅ Use secrets manager in production (AWS Secrets Manager, etc.)
80
+ - ✅ Rotate periodically
81
+
82
+ #### `NEXT_PUBLIC_APP_URL`
83
+
84
+ **Purpose:** Base URL for OAuth redirect URIs
85
+
86
+ **Format:** `https://domain.com` (no trailing slash)
87
+
88
+ **Examples:**
89
+ ```bash
90
+ # Development
91
+ NEXT_PUBLIC_APP_URL=http://localhost:5173
92
+
93
+ # Production
94
+ NEXT_PUBLIC_APP_URL=https://yourapp.com
95
+ ```
96
+
97
+ **Important:**
98
+ - Must match exactly the URL configured in Facebook App
99
+ - No trailing slash
100
+ - Include protocol (`http://` or `https://`)
101
+ - Port number if using non-standard ports
102
+
103
+ #### `OAUTH_ENCRYPTION_KEY`
104
+
105
+ **Purpose:** Encrypt OAuth tokens before storing in database
106
+
107
+ **Format:** 64 hexadecimal characters (32 bytes)
108
+
109
+ **Generate:**
110
+ ```bash
111
+ node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
112
+ ```
113
+
114
+ **Example:**
115
+ ```bash
116
+ OAUTH_ENCRYPTION_KEY=a7f9b2c8d1e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9
117
+ ```
118
+
119
+ **Security:**
120
+ - ✅ Must be exactly 64 hex characters
121
+ - ✅ Generate unique key per environment
122
+ - ✅ Never commit to git
123
+ - ✅ Store securely
124
+ - ⚠️ Changing key invalidates all existing tokens (users must reconnect)
125
+
126
+ ## OAuth Scopes
127
+
128
+ ### Instagram Business Permissions
129
+
130
+ ```typescript
131
+ [
132
+ 'pages_show_list', // Required: List Facebook Pages
133
+ 'instagram_basic', // Required: Read Instagram profile
134
+ 'instagram_content_publish', // Required: Publish to Instagram
135
+ 'instagram_manage_insights' // Optional: Read analytics
136
+ ]
137
+ ```
138
+
139
+ **What Each Permission Does:**
140
+
141
+ **`pages_show_list`** (Required)
142
+ - Lists Facebook Pages user manages
143
+ - Needed to find Pages with Instagram accounts
144
+ - Prerequisite for Instagram access
145
+
146
+ **`instagram_basic`** (Required)
147
+ - Read Instagram Business Account profile
148
+ - Get account ID, username, follower count
149
+ - Required even for publishing
150
+
151
+ **`instagram_content_publish`** (Required)
152
+ - Create and publish Instagram posts
153
+ - Photos and videos
154
+ - Cannot publish without this
155
+
156
+ **`instagram_manage_insights`** (Optional)
157
+ - Read Instagram analytics
158
+ - Post performance metrics
159
+ - Account insights
160
+ - Not required for publishing
161
+
162
+ ### Facebook Pages Permissions
163
+
164
+ ```typescript
165
+ [
166
+ 'pages_show_list', // Required: List Pages
167
+ 'pages_manage_posts', // Required: Create/publish posts
168
+ 'pages_read_engagement', // Optional: Read likes/comments
169
+ 'read_insights' // Optional: Read analytics
170
+ ]
171
+ ```
172
+
173
+ **What Each Permission Does:**
174
+
175
+ **`pages_show_list`** (Required)
176
+ - Lists Facebook Pages user manages
177
+ - Required to fetch Pages
178
+
179
+ **`pages_manage_posts`** (Required)
180
+ - Create posts on Pages
181
+ - Edit posts
182
+ - Delete posts
183
+ - Required for publishing
184
+
185
+ **`pages_read_engagement`** (Optional)
186
+ - Read post reactions
187
+ - Read comments
188
+ - Track engagement
189
+ - Not required for publishing
190
+
191
+ **`read_insights`** (Optional)
192
+ - Page analytics
193
+ - Visitor demographics
194
+ - Performance metrics
195
+ - Not required for publishing
196
+
197
+ ## Facebook App Configuration
198
+
199
+ ### OAuth Settings
200
+
201
+ **Location:** Facebook App → Products → Facebook Login → Settings
202
+
203
+ **Valid OAuth Redirect URIs:**
204
+ ```
205
+ Development:
206
+ http://localhost:5173/api/v1/plugin/social-media-publisher/social/connect/callback
207
+
208
+ Staging:
209
+ https://staging.yourapp.com/api/v1/plugin/social-media-publisher/social/connect/callback
210
+
211
+ Production:
212
+ https://yourapp.com/api/v1/plugin/social-media-publisher/social/connect/callback
213
+ ```
214
+
215
+ **Client OAuth Login:** ON
216
+ **Web OAuth Login:** ON
217
+ **Force Web OAuth Reauthentication:** OFF
218
+ **Embedded Browser OAuth Login:** OFF
219
+
220
+ ### App Domains
221
+
222
+ **Location:** Settings → Basic → App Domains
223
+
224
+ Add your domains:
225
+ ```
226
+ localhost (for development)
227
+ yourapp.com (for production)
228
+ staging.yourapp.com (for staging)
229
+ ```
230
+
231
+ ### Privacy and Terms URLs
232
+
233
+ **Required for Live Mode:**
234
+
235
+ **Privacy Policy URL:**
236
+ ```
237
+ https://yourapp.com/privacy
238
+ ```
239
+
240
+ **Terms of Service URL:**
241
+ ```
242
+ https://yourapp.com/terms
243
+ ```
244
+
245
+ ### App Review (Production)
246
+
247
+ **For Production Use:** Submit app for review to use permissions with non-admin users.
248
+
249
+ **Checklist:**
250
+ - [ ] App icon uploaded (1024x1024px)
251
+ - [ ] Category selected (e.g., "Business and Pages")
252
+ - [ ] Privacy policy URL added
253
+ - [ ] Terms of service URL added
254
+ - [ ] Detailed description of how you use each permission
255
+ - [ ] Screen recording showing OAuth flow
256
+ - [ ] Screenshots of publishing interface
257
+ - [ ] Business verification completed (for certain permissions)
258
+
259
+ ## Security Configuration
260
+
261
+ ### Token Encryption
262
+
263
+ **Algorithm:** AES-256-GCM
264
+ **Key Size:** 256 bits (32 bytes)
265
+ **IV:** Unique per token (96 bits)
266
+ **Tag:** 128 bits (for authentication)
267
+
268
+ **Storage Format:**
269
+ ```
270
+ encrypted:iv:keyId
271
+
272
+ Example:
273
+ a3f9b2c8d1e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2:9f7e3ab5c2:key_2024_01
274
+ ```
275
+
276
+ **Key Rotation:**
277
+
278
+ If you need to rotate encryption keys:
279
+
280
+ 1. Generate new key
281
+ 2. Set new `OAUTH_ENCRYPTION_KEY`
282
+ 3. All existing tokens become invalid
283
+ 4. Users must reconnect accounts
284
+ 5. Consider migration script for seamless transition
285
+
286
+ **Migration Script Example:**
287
+ ```typescript
288
+ // Decrypt with old key, re-encrypt with new key
289
+ const oldKey = process.env.OLD_OAUTH_ENCRYPTION_KEY
290
+ const newKey = process.env.OAUTH_ENCRYPTION_KEY
291
+
292
+ // ... migration logic
293
+ ```
294
+
295
+ ### Row-Level Security (RLS)
296
+
297
+ **Purpose:** Ensure users can only access social platforms for clients they own.
298
+
299
+ **Policy:**
300
+ ```sql
301
+ -- Users can only SELECT social platforms for their clients
302
+ CREATE POLICY "clients_social_platforms_select_own"
303
+ ON "clients_social_platforms" FOR SELECT
304
+ USING (
305
+ "parentId" IN (
306
+ SELECT id FROM "clients"
307
+ WHERE "userId" = current_setting('app.current_user_id', true)
308
+ )
309
+ );
310
+
311
+ -- Users can only INSERT social platforms for their clients
312
+ CREATE POLICY "clients_social_platforms_insert_own"
313
+ ON "clients_social_platforms" FOR INSERT
314
+ WITH CHECK (
315
+ "parentId" IN (
316
+ SELECT id FROM "clients"
317
+ WHERE "userId" = current_setting('app.current_user_id', true)
318
+ )
319
+ );
320
+
321
+ -- Similar policies for UPDATE and DELETE
322
+ ```
323
+
324
+ **Verify RLS is Active:**
325
+ ```sql
326
+ -- Check RLS is enabled
327
+ SELECT tablename, rowsecurity
328
+ FROM pg_tables
329
+ WHERE tablename = 'clients_social_platforms';
330
+
331
+ -- Should return: rowsecurity = true
332
+ ```
333
+
334
+ ### Audit Configuration
335
+
336
+ **Retention:** Audit logs are **immutable** and never deleted automatically.
337
+
338
+ **Recommended Retention Policy:**
339
+ ```sql
340
+ -- Archive logs older than 1 year
341
+ CREATE TABLE "audit_logs_archive" (
342
+ LIKE "audit_logs" INCLUDING ALL
343
+ );
344
+
345
+ -- Move old logs
346
+ INSERT INTO "audit_logs_archive"
347
+ SELECT * FROM "audit_logs"
348
+ WHERE "createdAt" < NOW() - INTERVAL '1 year';
349
+
350
+ -- Optionally delete from main table
351
+ DELETE FROM "audit_logs"
352
+ WHERE "createdAt" < NOW() - INTERVAL '1 year';
353
+ ```
354
+
355
+ ## Token Refresh Configuration
356
+
357
+ ### Automatic Refresh Settings
358
+
359
+ **Refresh Threshold:** 10 minutes before expiration
360
+ **Token Lifetime:** 60 days (long-lived Facebook tokens)
361
+ **Retry Logic:** None (fail fast if refresh fails)
362
+
363
+ **Threshold Configuration:**
364
+
365
+ Currently hardcoded in publish endpoint:
366
+ ```typescript
367
+ const REFRESH_THRESHOLD_MINUTES = 10
368
+ ```
369
+
370
+ To customize, edit:
371
+ ```typescript
372
+ // contents/plugins/social-media-publisher/api/social/publish/route.ts
373
+ const REFRESH_THRESHOLD_MINUTES = 60 // Refresh 1 hour before expiration
374
+ ```
375
+
376
+ **Trade-offs:**
377
+ - Lower threshold (10 min): More last-minute refreshes
378
+ - Higher threshold (60 min): More proactive, but more refresh API calls
379
+
380
+ ### Refresh Endpoint
381
+
382
+ **Meta Token Exchange:**
383
+ ```
384
+ GET https://graph.facebook.com/v18.0/oauth/access_token
385
+ ?grant_type=fb_exchange_token
386
+ &client_id={app_id}
387
+ &client_secret={app_secret}
388
+ &fb_exchange_token={current_token}
389
+ ```
390
+
391
+ **Response:**
392
+ ```json
393
+ {
394
+ "access_token": "new_long_lived_token",
395
+ "token_type": "bearer",
396
+ "expires_in": 5184000 // 60 days in seconds
397
+ }
398
+ ```
399
+
400
+ ## Environment-Specific Configuration
401
+
402
+ ### Development
403
+
404
+ ```bash
405
+ # .env.development
406
+ FACEBOOK_CLIENT_ID=dev_app_id
407
+ FACEBOOK_CLIENT_SECRET=dev_app_secret
408
+ NEXT_PUBLIC_APP_URL=http://localhost:5173
409
+ OAUTH_ENCRYPTION_KEY=dev_key_here
410
+ ```
411
+
412
+ **Notes:**
413
+ - Use test Facebook App
414
+ - Can use same account for testing
415
+ - Admins/Developers/Testers can test without App Review
416
+
417
+ ### Staging
418
+
419
+ ```bash
420
+ # .env.staging
421
+ FACEBOOK_CLIENT_ID=staging_app_id
422
+ FACEBOOK_CLIENT_SECRET=staging_app_secret
423
+ NEXT_PUBLIC_APP_URL=https://staging.yourapp.com
424
+ OAUTH_ENCRYPTION_KEY=staging_key_here
425
+ ```
426
+
427
+ **Notes:**
428
+ - Separate Facebook App recommended
429
+ - Use different encryption key
430
+ - Test App Review process
431
+
432
+ ### Production
433
+
434
+ ```bash
435
+ # .env.production
436
+ FACEBOOK_CLIENT_ID=prod_app_id
437
+ FACEBOOK_CLIENT_SECRET=prod_app_secret
438
+ NEXT_PUBLIC_APP_URL=https://yourapp.com
439
+ OAUTH_ENCRYPTION_KEY=prod_key_here
440
+ ```
441
+
442
+ **Notes:**
443
+ - App must be in Live mode
444
+ - Permissions approved via App Review
445
+ - Unique encryption key
446
+ - Use secrets manager for credential storage
447
+
448
+ ## Troubleshooting Configuration
449
+
450
+ ### Invalid Redirect URI Error
451
+
452
+ **Check:**
453
+ 1. `NEXT_PUBLIC_APP_URL` matches Facebook App settings exactly
454
+ 2. No trailing slash in URL
455
+ 3. Protocol (http/https) correct
456
+ 4. Port number included if non-standard
457
+
458
+ ### Token Encryption Failures
459
+
460
+ **Check:**
461
+ 1. `OAUTH_ENCRYPTION_KEY` is exactly 64 hex characters
462
+ 2. Key hasn't changed since accounts were connected
463
+ 3. Key is valid hexadecimal
464
+
465
+ **Validate Key:**
466
+ ```bash
467
+ # Should output 32
468
+ echo -n "your_key_here" | wc -c | awk '{print $1/2}'
469
+ ```
470
+
471
+ ### Permission Errors
472
+
473
+ **Check:**
474
+ 1. Permissions requested in OAuth URL match Facebook App config
475
+ 2. App has permissions approved (if in Live mode)
476
+ 3. User granted all requested permissions
477
+ 4. Permissions still valid (not revoked by user)
478
+
479
+ ## Best Practices
480
+
481
+ ### Security
482
+
483
+ ✅ **Use Secrets Manager** in production (AWS, Vercel, etc.)
484
+ ✅ **Rotate secrets** periodically (quarterly recommended)
485
+ ✅ **Separate keys per environment**
486
+ ✅ **Never commit** secrets to git
487
+ ✅ **Audit access** to environment variables
488
+
489
+ ### OAuth
490
+
491
+ ✅ **Request minimum permissions** needed
492
+ ✅ **Handle permission denials** gracefully
493
+ ✅ **Show clear permission justifications** to users
494
+ ✅ **Test OAuth flow** in all environments
495
+ ✅ **Monitor token refresh** success rates
496
+
497
+ ### Token Management
498
+
499
+ ✅ **Encrypt all tokens** before storage
500
+ ✅ **Refresh proactively** (10+ min threshold)
501
+ ✅ **Handle refresh failures** gracefully
502
+ ✅ **Log refresh events** for monitoring
503
+ ✅ **Never log** decrypted tokens
504
+
505
+ ## Next Steps
506
+
507
+ ✅ Configuration complete
508
+ ✅ Environment variables set
509
+ ✅ Facebook App configured
510
+ ✅ Security enabled
511
+
512
+ **Continue to:**
513
+ - **[OAuth Integration](../02-core-features/01-oauth-integration.md)** - Connect accounts
514
+ - **[Publishing](../02-core-features/02-publishing.md)** - Start publishing
515
+ - **[Token Management](../02-core-features/03-token-management.md)** - Understand token lifecycle