spaps-mcp 0.1.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.
@@ -0,0 +1,338 @@
1
+ # SPAPS Integration Step 8/12: Whitelist Operations
2
+
3
+ ## Prerequisites Check
4
+
5
+ Before starting, confirm you have completed:
6
+ - ✅ Step 1-7: Full authentication and payment implementation
7
+ - ✅ Have admin credentials ready
8
+ - ✅ Understanding that whitelist is NOT in the main SDK
9
+
10
+ ## Required TodoWrite List
11
+
12
+ Create a TodoWrite with EXACTLY these items:
13
+
14
+ ```javascript
15
+ TodoWrite({
16
+ todos: [
17
+ { content: "Create whitelist checker component", status: "pending", activeForm: "Creating whitelist checker component" },
18
+ { content: "Note that whitelist is NOT in main SDK", status: "pending", activeForm: "Noting whitelist is not in SDK" },
19
+ { content: "Choose implementation approach (Direct API or WhitelistManager)", status: "pending", activeForm: "Choosing implementation approach" },
20
+ { content: "Implement admin authentication pattern", status: "pending", activeForm: "Implementing admin authentication" },
21
+ { content: "Add whitelist check functionality", status: "pending", activeForm: "Adding whitelist check" },
22
+ { content: "Test with vip@example.com", status: "pending", activeForm: "Testing whitelist check" },
23
+ { content: "Handle authorization errors", status: "pending", activeForm: "Handling authorization errors" },
24
+ { content: "Request step 9 of SPAPS integration wizard", status: "pending", activeForm: "Requesting next step" }
25
+ ]
26
+ })
27
+ ```
28
+
29
+ ## Important Context
30
+
31
+ ⚠️ **CRITICAL**: The whitelist functionality is NOT in the main SDK exports!
32
+
33
+ You have **TWO OPTIONS** for implementation:
34
+
35
+ ### Option 1: Direct API Calls (Recommended for Learning)
36
+ Make direct HTTP requests to the whitelist endpoints with admin JWT token.
37
+
38
+ ### Option 2: WhitelistManager Utility (Advanced)
39
+ Use the `WhitelistManager` class from `spaps-sdk/admin-utils` (separate import).
40
+
41
+ ## Implementation Options
42
+
43
+ ### Option 1: Direct API Calls (Recommended)
44
+
45
+ This approach helps you understand the underlying API structure:
46
+
47
+ ```typescript
48
+ // components/admin/whitelist-checker.tsx
49
+ 'use client'
50
+
51
+ import { useState } from 'react'
52
+ import { Button } from "@/components/ui/button"
53
+ import { Input } from "@/components/ui/input"
54
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
55
+ import { toast } from "sonner"
56
+ import { sdk } from '@/lib/spaps'
57
+ import { TokenManager } from 'spaps-sdk'
58
+
59
+ export function WhitelistChecker() {
60
+ const [email, setEmail] = useState('')
61
+ const [isLoading, setIsLoading] = useState(false)
62
+ const [result, setResult] = useState<any>(null)
63
+
64
+ const checkWhitelist = async () => {
65
+ setIsLoading(true)
66
+ try {
67
+ // Step 1: Authenticate as admin first
68
+ const adminAuth = await sdk.auth.signInWithPassword({
69
+ email: process.env.NEXT_PUBLIC_ADMIN_EMAIL || 'admin@example.com',
70
+ password: process.env.NEXT_PUBLIC_ADMIN_PASSWORD || 'Admin123!'
71
+ })
72
+
73
+ // Step 2: Make direct API call with admin JWT
74
+ const response = await fetch(
75
+ `${process.env.NEXT_PUBLIC_SPAPS_API_URL}/api/v1/whitelist/check?email=${encodeURIComponent(email)}`,
76
+ {
77
+ headers: {
78
+ 'Authorization': `Bearer ${adminAuth.access_token}`,
79
+ 'X-API-Key': process.env.NEXT_PUBLIC_SPAPS_API_KEY || 'test_key_local_dev_only',
80
+ 'Content-Type': 'application/json'
81
+ }
82
+ }
83
+ )
84
+
85
+ if (!response.ok) {
86
+ if (response.status === 403) {
87
+ throw new Error('Admin privileges required')
88
+ }
89
+ throw new Error(`HTTP ${response.status}`)
90
+ }
91
+
92
+ const data = await response.json()
93
+ setResult(data)
94
+
95
+ if (data.isWhitelisted) {
96
+ toast.success(`✅ ${email} is whitelisted!`)
97
+ } else {
98
+ toast.info(`❌ ${email} is not whitelisted`)
99
+ }
100
+ } catch (error: any) {
101
+ toast.error(`Failed: ${error.message}`)
102
+ } finally {
103
+ setIsLoading(false)
104
+ }
105
+ }
106
+
107
+ // ... rest of component
108
+ }
109
+ ```
110
+
111
+ ### Option 2: WhitelistManager Utility (Advanced)
112
+
113
+ This approach uses the built-in utility class for cleaner code:
114
+
115
+ ```typescript
116
+ // lib/admin-utils.ts
117
+ import { WhitelistManager } from 'spaps-sdk/admin-utils'
118
+ import { sdk } from './spaps'
119
+
120
+ let whitelistManager: WhitelistManager | null = null
121
+
122
+ export async function getWhitelistManager() {
123
+ if (whitelistManager) return whitelistManager
124
+
125
+ // Authenticate as admin
126
+ const adminAuth = await sdk.auth.signInWithPassword({
127
+ email: process.env.NEXT_PUBLIC_ADMIN_EMAIL!,
128
+ password: process.env.NEXT_PUBLIC_ADMIN_PASSWORD!
129
+ })
130
+
131
+ // Create WhitelistManager instance
132
+ whitelistManager = new WhitelistManager({
133
+ apiUrl: process.env.NEXT_PUBLIC_SPAPS_API_URL || 'http://localhost:3301',
134
+ apiKey: process.env.NEXT_PUBLIC_SPAPS_API_KEY || 'test_key_local_dev_only',
135
+ adminToken: adminAuth.access_token
136
+ })
137
+
138
+ return whitelistManager
139
+ }
140
+
141
+ // components/admin/whitelist-checker.tsx
142
+ import { getWhitelistManager } from '@/lib/admin-utils'
143
+
144
+ export function WhitelistChecker() {
145
+ const checkWhitelist = async () => {
146
+ try {
147
+ const manager = await getWhitelistManager()
148
+
149
+ // Check if email is whitelisted
150
+ const entry = await manager.check(email)
151
+
152
+ if (entry) {
153
+ toast.success(`✅ ${email} is whitelisted (Tier: ${entry.tier})`)
154
+ setResult(entry)
155
+ } else {
156
+ toast.info(`❌ ${email} is not whitelisted`)
157
+ setResult({ isWhitelisted: false })
158
+ }
159
+ } catch (error: any) {
160
+ toast.error(`Failed: ${error.message}`)
161
+ }
162
+ }
163
+
164
+ // Additional operations available with WhitelistManager:
165
+ const addToWhitelist = async () => {
166
+ const manager = await getWhitelistManager()
167
+ await manager.add(email, 'premium', { bypass_payment: true })
168
+ }
169
+
170
+ const removeFromWhitelist = async () => {
171
+ const manager = await getWhitelistManager()
172
+ await manager.remove(email)
173
+ }
174
+
175
+ const getStats = async () => {
176
+ const manager = await getWhitelistManager()
177
+ const stats = await manager.getStats()
178
+ console.log('Whitelist stats:', stats)
179
+ }
180
+ }
181
+ ```
182
+
183
+ ## Available WhitelistManager Methods
184
+
185
+ If using Option 2, these methods are available:
186
+
187
+ ```typescript
188
+ interface WhitelistManager {
189
+ check(email: string): Promise<WhitelistEntry | null>
190
+ add(email: string, tier: 'basic' | 'premium' | 'enterprise', options?: {...}): Promise<WhitelistEntry>
191
+ bulkAdd(emails: Array<{email: string, tier?: string}>): Promise<BulkResult>
192
+ list(options?: {limit?: number, offset?: number, tier?: string}): Promise<WhitelistList>
193
+ update(email: string, updates: {...}): Promise<WhitelistEntry>
194
+ remove(email: string): Promise<void>
195
+ getStats(): Promise<WhitelistStats>
196
+ clearAll(): Promise<number> // Use with caution!
197
+ }
198
+ ```
199
+
200
+ ## Admin Operations Beyond Whitelist
201
+
202
+ You can also perform other admin operations:
203
+
204
+ ```typescript
205
+ // Product sync
206
+ const syncProducts = async () => {
207
+ const adminAuth = await sdk.auth.signInWithPassword({
208
+ email: 'admin@example.com',
209
+ password: 'Admin123!'
210
+ })
211
+
212
+ const response = await fetch(
213
+ `${process.env.NEXT_PUBLIC_SPAPS_API_URL}/api/v1/admin/products/sync`,
214
+ {
215
+ method: 'POST',
216
+ headers: {
217
+ 'Authorization': `Bearer ${adminAuth.access_token}`,
218
+ 'X-API-Key': process.env.NEXT_PUBLIC_SPAPS_API_KEY,
219
+ 'Content-Type': 'application/json'
220
+ }
221
+ }
222
+ )
223
+
224
+ return response.json()
225
+ }
226
+ ```
227
+
228
+ ## Validation Checklist
229
+
230
+ ✅ **Implementation Choice**:
231
+ - Decided between Direct API or WhitelistManager approach
232
+ - Understand pros/cons of each approach
233
+
234
+ ✅ **Authentication**:
235
+ - Admin credentials stored securely (environment variables)
236
+ - Admin authentication implemented before whitelist calls
237
+ - JWT token properly passed in Authorization header
238
+
239
+ ✅ **Error Handling**:
240
+ - Handle 403 Forbidden (not admin)
241
+ - Handle 401 Unauthorized (invalid token)
242
+ - Handle network errors
243
+ - Show user-friendly error messages
244
+
245
+ ✅ **Testing**:
246
+ - Test with `vip@example.com` (should be whitelisted in local mode)
247
+ - Test with random email (should not be whitelisted)
248
+ - Test without admin auth (should fail with 403)
249
+
250
+ ## Common Mistakes to Avoid
251
+
252
+ ❌ **Looking for whitelist in main SDK**:
253
+ ```javascript
254
+ // WRONG - This doesn't exist!
255
+ sdk.whitelist.check(email)
256
+ sdk.admin.whitelist.add(email)
257
+ ```
258
+
259
+ ❌ **Not authenticating as admin first**:
260
+ ```javascript
261
+ // WRONG - Missing admin auth
262
+ fetch('/api/v1/whitelist/check', {
263
+ headers: { 'X-API-Key': apiKey } // Missing JWT!
264
+ })
265
+ ```
266
+
267
+ ❌ **Using regular user token**:
268
+ ```javascript
269
+ // WRONG - Must be admin token
270
+ const userToken = TokenManager.getAccessToken() // Regular user token won't work
271
+ ```
272
+
273
+ ✅ **CORRECT - Always authenticate as admin**:
274
+ ```javascript
275
+ const adminAuth = await sdk.auth.signInWithPassword({
276
+ email: 'admin@example.com',
277
+ password: 'Admin123!'
278
+ })
279
+ // Now use adminAuth.access_token for whitelist operations
280
+ ```
281
+
282
+ ## Testing Requirements
283
+
284
+ 1. **Successful Whitelist Check**:
285
+ - Email: `vip@example.com`
286
+ - Should return: `{ isWhitelisted: true, tier: 'premium' }`
287
+
288
+ 2. **Non-whitelisted Email**:
289
+ - Email: `regular@example.com`
290
+ - Should return: `{ isWhitelisted: false }`
291
+
292
+ 3. **Authorization Failure**:
293
+ - Use non-admin credentials
294
+ - Should get 403 Forbidden error
295
+
296
+ ## Troubleshooting
297
+
298
+ If whitelist operations fail:
299
+
300
+ 1. **Check Admin Credentials**:
301
+ ```bash
302
+ # Test admin login
303
+ curl -X POST http://localhost:3301/api/auth/login \
304
+ -H "Content-Type: application/json" \
305
+ -d '{"email":"admin@example.com","password":"Admin123!"}'
306
+ ```
307
+
308
+ 2. **Verify JWT Token**:
309
+ ```javascript
310
+ console.log('Admin token:', adminAuth.access_token)
311
+ // Should be a long JWT string
312
+ ```
313
+
314
+ 3. **Check API Endpoint**:
315
+ ```javascript
316
+ console.log('Whitelist URL:', `${process.env.NEXT_PUBLIC_SPAPS_API_URL}/api/v1/whitelist/check`)
317
+ // Should be: http://localhost:3301/api/v1/whitelist/check
318
+ ```
319
+
320
+ ## Next Step
321
+
322
+ When ALL todos are ✅ complete and whitelist checking works:
323
+
324
+ ```javascript
325
+ mcp__product-manager__get_agent_instructions({
326
+ category: "spaps-integration",
327
+ project: "spaps-demo",
328
+ step: 9
329
+ })
330
+ ```
331
+
332
+ ## Summary
333
+
334
+ Whitelist operations require admin privileges and are NOT in the main SDK. You can either:
335
+ 1. **Direct API calls** - More control, better for learning
336
+ 2. **WhitelistManager utility** - Cleaner code, more features
337
+
338
+ Both approaches work perfectly - choose based on your needs!