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.
- package/CHANGELOG.md +7 -0
- package/README.md +76 -0
- package/dist/chunk-GPBTYWDD.js +496 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +9 -0
- package/dist/index.d.ts +103 -0
- package/dist/index.js +26 -0
- package/dist/resources/SPAPS_SURFACE_CONTRACT.md +125 -0
- package/dist/resources/glossary.md +36 -0
- package/dist/resources/llms.txt +15 -0
- package/dist/wizard/step-01-setup.md +149 -0
- package/dist/wizard/step-02-environment.md +291 -0
- package/dist/wizard/step-03-sdk-init.md +351 -0
- package/dist/wizard/step-04-email-auth.md +311 -0
- package/dist/wizard/step-05-wallet-auth.md +368 -0
- package/dist/wizard/step-06-magic-link.md +560 -0
- package/dist/wizard/step-07-payments.md +529 -0
- package/dist/wizard/step-08-whitelist.md +338 -0
- package/dist/wizard/step-09-admin.md +579 -0
- package/dist/wizard/step-10-errors.md +525 -0
- package/dist/wizard/step-11-ui-polish.md +640 -0
- package/dist/wizard/step-12-testing.md +588 -0
- package/dist/wizard/wizard.lock +67 -0
- package/package.json +66 -0
|
@@ -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!
|