vibecodingmachine-core 2025.11.2-9.855 → 2025.12.6-1702

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,445 @@
1
+ /**
2
+ * AWS Infrastructure Setup for Vibe Coding Machine Multi-Computer Sync
3
+ *
4
+ * This script sets up:
5
+ * 1. DynamoDB table for requirements storage
6
+ * 2. Cognito User Pool with Google OAuth
7
+ * 3. API Gateway for REST endpoints
8
+ * 4. Lambda functions for sync logic
9
+ */
10
+
11
+ const {
12
+ DynamoDBClient,
13
+ CreateTableCommand,
14
+ DescribeTableCommand
15
+ } = require('@aws-sdk/client-dynamodb');
16
+
17
+ const {
18
+ CognitoIdentityProviderClient,
19
+ CreateUserPoolCommand,
20
+ CreateUserPoolClientCommand,
21
+ CreateIdentityProviderCommand,
22
+ DescribeUserPoolCommand
23
+ } = require('@aws-sdk/client-cognito-identity-provider');
24
+
25
+ const region = process.env.AWS_REGION || 'us-east-1';
26
+
27
+ /**
28
+ * Create DynamoDB table for requirements sync
29
+ */
30
+ async function createDynamoDBTable() {
31
+ const client = new DynamoDBClient({ region });
32
+ const tableName = 'vibecodingmachine-requirements';
33
+
34
+ try {
35
+ // Check if table already exists
36
+ try {
37
+ const describeCommand = new DescribeTableCommand({ TableName: tableName });
38
+ await client.send(describeCommand);
39
+ console.log(`✓ DynamoDB table '${tableName}' already exists`);
40
+ return { tableName, status: 'exists' };
41
+ } catch (error) {
42
+ if (error.name !== 'ResourceNotFoundException') {
43
+ throw error;
44
+ }
45
+ }
46
+
47
+ // Create table
48
+ const command = new CreateTableCommand({
49
+ TableName: tableName,
50
+ KeySchema: [
51
+ { AttributeName: 'computerId', KeyType: 'HASH' }, // Partition key
52
+ { AttributeName: 'timestamp', KeyType: 'RANGE' } // Sort key
53
+ ],
54
+ AttributeDefinitions: [
55
+ { AttributeName: 'computerId', AttributeType: 'S' },
56
+ { AttributeName: 'timestamp', AttributeType: 'N' },
57
+ { AttributeName: 'requirementId', AttributeType: 'S' }
58
+ ],
59
+ GlobalSecondaryIndexes: [
60
+ {
61
+ IndexName: 'requirementId-index',
62
+ KeySchema: [
63
+ { AttributeName: 'requirementId', KeyType: 'HASH' }
64
+ ],
65
+ Projection: { ProjectionType: 'ALL' }
66
+ },
67
+ {
68
+ IndexName: 'timestamp-index',
69
+ KeySchema: [
70
+ { AttributeName: 'timestamp', KeyType: 'HASH' }
71
+ ],
72
+ Projection: { ProjectionType: 'ALL' }
73
+ }
74
+ ],
75
+ BillingMode: 'PAY_PER_REQUEST', // On-demand pricing (no ProvisionedThroughput needed)
76
+ StreamSpecification: {
77
+ StreamEnabled: true,
78
+ StreamViewType: 'NEW_AND_OLD_IMAGES'
79
+ },
80
+ TimeToLiveSpecification: {
81
+ Enabled: true,
82
+ AttributeName: 'ttl'
83
+ },
84
+ Tags: [
85
+ { Key: 'Application', Value: 'VibeCodingMachine' },
86
+ { Key: 'Purpose', Value: 'RequirementsSync' }
87
+ ]
88
+ });
89
+
90
+ const response = await client.send(command);
91
+ console.log(`✓ Created DynamoDB table '${tableName}'`);
92
+ console.log(` ARN: ${response.TableDescription.TableArn}`);
93
+
94
+ return {
95
+ tableName,
96
+ status: 'created',
97
+ arn: response.TableDescription.TableArn
98
+ };
99
+ } catch (error) {
100
+ console.error(`✗ Failed to create DynamoDB table:`, error.message);
101
+ throw error;
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Create or update Cognito User Pool with Google OAuth
107
+ */
108
+ async function setupCognitoWithGoogle() {
109
+ const client = new CognitoIdentityProviderClient({ region });
110
+
111
+ // Use existing user pool if specified
112
+ const existingPoolId = process.env.COGNITO_USER_POOL_ID;
113
+
114
+ if (existingPoolId) {
115
+ console.log(`✓ Using existing Cognito User Pool: ${existingPoolId}`);
116
+
117
+ // Add Google OAuth provider if not already configured
118
+ try {
119
+ const googleClientId = process.env.GOOGLE_CLIENT_ID;
120
+ const googleClientSecret = process.env.GOOGLE_CLIENT_SECRET;
121
+
122
+ if (!googleClientId || !googleClientSecret) {
123
+ console.log('⚠ Google OAuth credentials not provided. Skipping Google provider setup.');
124
+ console.log(' Set GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET environment variables.');
125
+ return { userPoolId: existingPoolId, status: 'existing' };
126
+ }
127
+
128
+ const providerCommand = new CreateIdentityProviderCommand({
129
+ UserPoolId: existingPoolId,
130
+ ProviderName: 'Google',
131
+ ProviderType: 'Google',
132
+ ProviderDetails: {
133
+ client_id: googleClientId,
134
+ client_secret: googleClientSecret,
135
+ authorize_scopes: 'openid email profile'
136
+ },
137
+ AttributeMapping: {
138
+ email: 'email',
139
+ name: 'name',
140
+ picture: 'picture',
141
+ username: 'sub'
142
+ }
143
+ });
144
+
145
+ await client.send(providerCommand);
146
+ console.log('✓ Added Google OAuth provider to Cognito User Pool');
147
+ } catch (error) {
148
+ if (error.name === 'DuplicateProviderException') {
149
+ console.log('✓ Google OAuth provider already configured');
150
+ } else {
151
+ console.error('⚠ Failed to add Google provider:', error.message);
152
+ }
153
+ }
154
+
155
+ return { userPoolId: existingPoolId, status: 'existing' };
156
+ }
157
+
158
+ // Create new user pool
159
+ console.log('Creating new Cognito User Pool...');
160
+
161
+ try {
162
+ const poolCommand = new CreateUserPoolCommand({
163
+ PoolName: 'vibecodingmachine-users',
164
+ Policies: {
165
+ PasswordPolicy: {
166
+ MinimumLength: 8,
167
+ RequireUppercase: true,
168
+ RequireLowercase: true,
169
+ RequireNumbers: true,
170
+ RequireSymbols: false
171
+ }
172
+ },
173
+ AutoVerifiedAttributes: ['email'],
174
+ UsernameAttributes: ['email'],
175
+ Schema: [
176
+ {
177
+ Name: 'email',
178
+ AttributeDataType: 'String',
179
+ Required: true,
180
+ Mutable: true
181
+ },
182
+ {
183
+ Name: 'name',
184
+ AttributeDataType: 'String',
185
+ Required: false,
186
+ Mutable: true
187
+ }
188
+ ],
189
+ UserPoolTags: {
190
+ Application: 'VibeCodingMachine',
191
+ Purpose: 'Authentication'
192
+ }
193
+ });
194
+
195
+ const poolResponse = await client.send(poolCommand);
196
+ const userPoolId = poolResponse.UserPool.Id;
197
+
198
+ console.log(`✓ Created Cognito User Pool: ${userPoolId}`);
199
+
200
+ // Add Google OAuth provider first (if credentials provided)
201
+ const googleClientId = process.env.GOOGLE_CLIENT_ID;
202
+ const googleClientSecret = process.env.GOOGLE_CLIENT_SECRET;
203
+
204
+ let supportedProviders = ['COGNITO'];
205
+
206
+ if (googleClientId && googleClientSecret) {
207
+ try {
208
+ const providerCommand = new CreateIdentityProviderCommand({
209
+ UserPoolId: userPoolId,
210
+ ProviderName: 'Google',
211
+ ProviderType: 'Google',
212
+ ProviderDetails: {
213
+ client_id: googleClientId,
214
+ client_secret: googleClientSecret,
215
+ authorize_scopes: 'openid email profile'
216
+ },
217
+ AttributeMapping: {
218
+ email: 'email',
219
+ name: 'name',
220
+ picture: 'picture',
221
+ username: 'sub'
222
+ }
223
+ });
224
+
225
+ await client.send(providerCommand);
226
+ console.log('✓ Added Google OAuth provider to Cognito User Pool');
227
+ supportedProviders.push('Google');
228
+ } catch (error) {
229
+ console.log('⚠ Could not add Google provider:', error.message);
230
+ console.log(' You can add it later via AWS Console');
231
+ }
232
+ } else {
233
+ console.log('⚠ Google OAuth credentials not provided');
234
+ console.log(' Set GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET to enable Google login');
235
+ }
236
+
237
+ // Create app client
238
+ const clientCommand = new CreateUserPoolClientCommand({
239
+ UserPoolId: userPoolId,
240
+ ClientName: 'vibecodingmachine-client',
241
+ GenerateSecret: false, // Public client for PKCE
242
+ RefreshTokenValidity: 30,
243
+ AccessTokenValidity: 1,
244
+ IdTokenValidity: 1,
245
+ TokenValidityUnits: {
246
+ RefreshToken: 'days',
247
+ AccessToken: 'hours',
248
+ IdToken: 'hours'
249
+ },
250
+ ExplicitAuthFlows: [
251
+ 'ALLOW_REFRESH_TOKEN_AUTH',
252
+ 'ALLOW_USER_SRP_AUTH'
253
+ ],
254
+ AllowedOAuthFlows: ['code'],
255
+ AllowedOAuthScopes: ['openid', 'email', 'profile'],
256
+ AllowedOAuthFlowsUserPoolClient: true,
257
+ SupportedIdentityProviders: supportedProviders,
258
+ CallbackURLs: [
259
+ 'http://localhost:3000/callback',
260
+ 'vibecodingmachine://callback'
261
+ ],
262
+ LogoutURLs: [
263
+ 'http://localhost:3000/logout',
264
+ 'vibecodingmachine://logout'
265
+ ]
266
+ });
267
+
268
+ const clientResponse = await client.send(clientCommand);
269
+ const appClientId = clientResponse.UserPoolClient.ClientId;
270
+
271
+ console.log(`✓ Created Cognito App Client: ${appClientId}`);
272
+
273
+ return {
274
+ userPoolId,
275
+ appClientId,
276
+ status: 'created'
277
+ };
278
+ } catch (error) {
279
+ console.error('✗ Failed to create Cognito User Pool:', error.message);
280
+ throw error;
281
+ }
282
+ }
283
+
284
+ /**
285
+ * Create computers DynamoDB table
286
+ */
287
+ async function createComputersTable() {
288
+ const client = new DynamoDBClient({ region });
289
+ const tableName = 'vibecodingmachine-computers';
290
+
291
+ try {
292
+ // Check if table already exists
293
+ try {
294
+ const describeCommand = new DescribeTableCommand({ TableName: tableName });
295
+ await client.send(describeCommand);
296
+ console.log(`✓ Computers table '${tableName}' already exists`);
297
+ return { tableName, status: 'exists' };
298
+ } catch (error) {
299
+ if (error.name !== 'ResourceNotFoundException') {
300
+ throw error;
301
+ }
302
+ }
303
+
304
+ // Create table
305
+ const command = new CreateTableCommand({
306
+ TableName: tableName,
307
+ KeySchema: [
308
+ { AttributeName: 'computerId', KeyType: 'HASH' } // Partition key
309
+ ],
310
+ AttributeDefinitions: [
311
+ { AttributeName: 'computerId', AttributeType: 'S' }
312
+ ],
313
+ BillingMode: 'PAY_PER_REQUEST',
314
+ Tags: [
315
+ { Key: 'Application', Value: 'VibeCodingMachine' },
316
+ { Key: 'Purpose', Value: 'ComputerRegistry' }
317
+ ]
318
+ });
319
+
320
+ const response = await client.send(command);
321
+ console.log(`✓ Created computers table '${tableName}'`);
322
+
323
+ return {
324
+ tableName,
325
+ status: 'created',
326
+ arn: response.TableDescription.TableArn
327
+ };
328
+ } catch (error) {
329
+ console.error(`✗ Failed to create computers table:`, error.message);
330
+ throw error;
331
+ }
332
+ }
333
+
334
+ /**
335
+ * Create beta customers DynamoDB table
336
+ */
337
+ async function createBetaCustomersTable() {
338
+ const client = new DynamoDBClient({ region });
339
+ const tableName = 'vibecodingmachine-beta-customers';
340
+
341
+ try {
342
+ // Check if table already exists
343
+ try {
344
+ const describeCommand = new DescribeTableCommand({ TableName: tableName });
345
+ await client.send(describeCommand);
346
+ console.log(`✓ Beta customers table '${tableName}' already exists`);
347
+ return { tableName, status: 'exists' };
348
+ } catch (error) {
349
+ if (error.name !== 'ResourceNotFoundException') {
350
+ throw error;
351
+ }
352
+ }
353
+
354
+ // Create table
355
+ const command = new CreateTableCommand({
356
+ TableName: tableName,
357
+ KeySchema: [
358
+ { AttributeName: 'email', KeyType: 'HASH' } // Partition key
359
+ ],
360
+ AttributeDefinitions: [
361
+ { AttributeName: 'email', AttributeType: 'S' }
362
+ ],
363
+ BillingMode: 'PAY_PER_REQUEST',
364
+ Tags: [
365
+ { Key: 'Application', Value: 'VibeCodingMachine' },
366
+ { Key: 'Purpose', Value: 'BetaAccess' }
367
+ ]
368
+ });
369
+
370
+ const response = await client.send(command);
371
+ console.log(`✓ Created beta customers table '${tableName}'`);
372
+
373
+ return {
374
+ tableName,
375
+ status: 'created',
376
+ arn: response.TableDescription.TableArn
377
+ };
378
+ } catch (error) {
379
+ console.error(`✗ Failed to create beta customers table:`, error.message);
380
+ throw error;
381
+ }
382
+ }
383
+
384
+ /**
385
+ * Main setup function
386
+ */
387
+ async function setup() {
388
+ console.log('🚀 Setting up AWS infrastructure for Vibe Coding Machine\n');
389
+
390
+ try {
391
+ // 1. Create DynamoDB tables
392
+ console.log('1. Setting up DynamoDB tables...');
393
+ const requirementsTable = await createDynamoDBTable();
394
+ const computersTable = await createComputersTable();
395
+ const betaTable = await createBetaCustomersTable();
396
+ console.log('');
397
+
398
+ // 2. Setup Cognito with Google OAuth
399
+ console.log('2. Setting up Cognito with Google OAuth...');
400
+ const cognito = await setupCognitoWithGoogle();
401
+ console.log('');
402
+
403
+ // 3. Output configuration
404
+ console.log('✅ Setup complete!\n');
405
+ console.log('Configuration:');
406
+ console.log('─────────────────────────────────────────');
407
+ console.log(`AWS_REGION=${region}`);
408
+ console.log(`DYNAMODB_TABLE_NAME=${requirementsTable.tableName}`);
409
+ console.log(`DYNAMODB_COMPUTERS_TABLE_NAME=${computersTable.tableName}`);
410
+ console.log(`DYNAMODB_BETA_TABLE_NAME=${betaTable.tableName}`);
411
+ if (cognito.userPoolId) {
412
+ console.log(`COGNITO_USER_POOL_ID=${cognito.userPoolId}`);
413
+ }
414
+ if (cognito.appClientId) {
415
+ console.log(`COGNITO_APP_CLIENT_ID=${cognito.appClientId}`);
416
+ }
417
+ console.log('─────────────────────────────────────────\n');
418
+
419
+ console.log('Next steps:');
420
+ console.log('1. Add the above configuration to your .env file');
421
+ console.log('2. Set up Google OAuth credentials in Google Cloud Console');
422
+ console.log('3. Configure Cognito domain for OAuth flows');
423
+ console.log('4. Deploy Lambda functions for sync logic');
424
+ console.log('5. Set up API Gateway endpoints\n');
425
+
426
+ return {
427
+ requirementsTable,
428
+ computersTable,
429
+ betaTable,
430
+ cognito
431
+ };
432
+ } catch (error) {
433
+ console.error('\n❌ Setup failed:', error.message);
434
+ throw error;
435
+ }
436
+ }
437
+
438
+ // Run setup if called directly
439
+ if (require.main === module) {
440
+ setup()
441
+ .then(() => process.exit(0))
442
+ .catch(() => process.exit(1));
443
+ }
444
+
445
+ module.exports = { setup, createDynamoDBTable, createComputersTable, setupCognitoWithGoogle, createBetaCustomersTable };