aios-core 4.2.2 → 4.2.3
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.
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
# - SHA256 hashes for change detection
|
|
8
8
|
# - File types for categorization
|
|
9
9
|
#
|
|
10
|
-
version: 4.2.
|
|
11
|
-
generated_at: "2026-02-16T00:
|
|
10
|
+
version: 4.2.3
|
|
11
|
+
generated_at: "2026-02-16T00:47:03.699Z"
|
|
12
12
|
generator: scripts/generate-install-manifest.js
|
|
13
13
|
file_count: 992
|
|
14
14
|
files:
|
package/package.json
CHANGED
|
@@ -264,13 +264,18 @@ async function stepLicenseGateCI(options) {
|
|
|
264
264
|
/**
|
|
265
265
|
* Interactive email/password license gate flow.
|
|
266
266
|
*
|
|
267
|
-
*
|
|
267
|
+
* New flow (PRO-11 v2):
|
|
268
|
+
* 1. Email → checkEmail API → { isBuyer, hasAccount }
|
|
269
|
+
* 2. NOT buyer → "No Pro access found" → STOP
|
|
270
|
+
* 3. IS buyer + HAS account → Password → Login (with retry) → Activate
|
|
271
|
+
* 4. IS buyer + NO account → Password + Confirm → Signup → Verify email → Login → Activate
|
|
268
272
|
*
|
|
269
273
|
* @returns {Promise<Object>} Result with { success, key, activationResult }
|
|
270
274
|
*/
|
|
271
275
|
async function stepLicenseGateWithEmail() {
|
|
272
276
|
const inquirer = require('inquirer');
|
|
273
277
|
|
|
278
|
+
// Step 1: Get email
|
|
274
279
|
const { email } = await inquirer.prompt([
|
|
275
280
|
{
|
|
276
281
|
type: 'input',
|
|
@@ -288,53 +293,147 @@ async function stepLicenseGateWithEmail() {
|
|
|
288
293
|
},
|
|
289
294
|
]);
|
|
290
295
|
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
296
|
+
const trimmedEmail = email.trim();
|
|
297
|
+
|
|
298
|
+
// Step 2: Check buyer status + account existence
|
|
299
|
+
const loader = module.exports._testing ? module.exports._testing.loadLicenseApi : loadLicenseApi;
|
|
300
|
+
const licenseModule = loader();
|
|
301
|
+
|
|
302
|
+
if (!licenseModule) {
|
|
303
|
+
return {
|
|
304
|
+
success: false,
|
|
305
|
+
error: 'Pro license module not available. Ensure @aios-fullstack/pro is installed.',
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const { LicenseApiClient } = licenseModule;
|
|
310
|
+
const client = new LicenseApiClient();
|
|
311
|
+
|
|
312
|
+
// Check connectivity
|
|
313
|
+
const online = await client.isOnline();
|
|
314
|
+
if (!online) {
|
|
315
|
+
return {
|
|
316
|
+
success: false,
|
|
317
|
+
error: 'License server is unreachable. Check your internet connection and try again.',
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const checkSpinner = createSpinner('Verifying your access...');
|
|
322
|
+
checkSpinner.start();
|
|
323
|
+
|
|
324
|
+
let checkResult;
|
|
325
|
+
try {
|
|
326
|
+
checkResult = await client.checkEmail(trimmedEmail);
|
|
327
|
+
} catch (checkError) {
|
|
328
|
+
checkSpinner.fail(`Verification failed: ${checkError.message}`);
|
|
329
|
+
return { success: false, error: checkError.message };
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Step 2a: NOT a buyer → stop
|
|
333
|
+
if (!checkResult.isBuyer) {
|
|
334
|
+
checkSpinner.fail('No AIOS Pro access found for this email.');
|
|
335
|
+
console.log('');
|
|
336
|
+
showInfo('If you believe this is an error, please contact support:');
|
|
337
|
+
showInfo(' Email: support@synkra.ai');
|
|
338
|
+
showInfo(' Purchase Pro: https://pro.synkra.ai');
|
|
339
|
+
return { success: false, error: 'Email not found in Pro buyers list.' };
|
|
340
|
+
}
|
|
305
341
|
|
|
306
|
-
|
|
342
|
+
// Step 2b: IS a buyer
|
|
343
|
+
if (checkResult.hasAccount) {
|
|
344
|
+
checkSpinner.succeed('Pro access confirmed! Account found.');
|
|
345
|
+
// Flow 3: Existing account → Login with password (retry loop)
|
|
346
|
+
return loginWithRetry(client, trimmedEmail);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
checkSpinner.succeed('Pro access confirmed! Let\'s create your account.');
|
|
350
|
+
// Flow 4: New account → Create account flow
|
|
351
|
+
return createAccountFlow(client, trimmedEmail);
|
|
307
352
|
}
|
|
308
353
|
|
|
309
354
|
/**
|
|
310
|
-
*
|
|
311
|
-
*
|
|
312
|
-
* Asks for confirmation, then password with confirmation.
|
|
313
|
-
* Calls signup API and logs in to get session token.
|
|
355
|
+
* Login flow with password retry (max 3 attempts).
|
|
314
356
|
*
|
|
315
357
|
* @param {object} client - LicenseApiClient instance
|
|
316
|
-
* @param {string} email -
|
|
317
|
-
* @returns {Promise<Object>} Result with { success,
|
|
358
|
+
* @param {string} email - Verified buyer email
|
|
359
|
+
* @returns {Promise<Object>} Result with { success, key, activationResult }
|
|
318
360
|
*/
|
|
319
|
-
async function
|
|
361
|
+
async function loginWithRetry(client, email) {
|
|
320
362
|
const inquirer = require('inquirer');
|
|
321
363
|
|
|
322
|
-
|
|
323
|
-
|
|
364
|
+
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
|
365
|
+
const { password } = await inquirer.prompt([
|
|
366
|
+
{
|
|
367
|
+
type: 'password',
|
|
368
|
+
name: 'password',
|
|
369
|
+
message: colors.primary('Password:'),
|
|
370
|
+
mask: '*',
|
|
371
|
+
validate: (input) => {
|
|
372
|
+
if (!input || input.length < MIN_PASSWORD_LENGTH) {
|
|
373
|
+
return `Password must be at least ${MIN_PASSWORD_LENGTH} characters`;
|
|
374
|
+
}
|
|
375
|
+
return true;
|
|
376
|
+
},
|
|
377
|
+
},
|
|
378
|
+
]);
|
|
324
379
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
},
|
|
332
|
-
]);
|
|
380
|
+
const spinner = createSpinner('Authenticating...');
|
|
381
|
+
spinner.start();
|
|
382
|
+
|
|
383
|
+
try {
|
|
384
|
+
const loginResult = await client.login(email, password);
|
|
385
|
+
spinner.succeed('Authenticated successfully.');
|
|
333
386
|
|
|
334
|
-
|
|
335
|
-
|
|
387
|
+
// Wait for email verification if needed
|
|
388
|
+
if (!loginResult.emailVerified) {
|
|
389
|
+
const verifyResult = await waitForEmailVerification(client, loginResult.sessionToken);
|
|
390
|
+
if (!verifyResult.success) {
|
|
391
|
+
return verifyResult;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// Activate Pro
|
|
396
|
+
return activateProByAuth(client, loginResult.sessionToken);
|
|
397
|
+
} catch (loginError) {
|
|
398
|
+
if (loginError.code === 'INVALID_CREDENTIALS') {
|
|
399
|
+
const remaining = MAX_RETRIES - attempt;
|
|
400
|
+
if (remaining > 0) {
|
|
401
|
+
spinner.fail(`Incorrect password. ${remaining} attempt${remaining > 1 ? 's' : ''} remaining.`);
|
|
402
|
+
showInfo('Forgot your password? Visit https://pro.synkra.ai/reset-password');
|
|
403
|
+
} else {
|
|
404
|
+
spinner.fail('Maximum login attempts reached.');
|
|
405
|
+
showInfo('Forgot your password? Visit https://pro.synkra.ai/reset-password');
|
|
406
|
+
showInfo('Or contact support: support@synkra.ai');
|
|
407
|
+
return { success: false, error: 'Maximum login attempts reached.' };
|
|
408
|
+
}
|
|
409
|
+
} else if (loginError.code === 'AUTH_RATE_LIMITED') {
|
|
410
|
+
spinner.fail(loginError.message);
|
|
411
|
+
return { success: false, error: loginError.message };
|
|
412
|
+
} else {
|
|
413
|
+
spinner.fail(`Authentication failed: ${loginError.message}`);
|
|
414
|
+
return { success: false, error: loginError.message };
|
|
415
|
+
}
|
|
416
|
+
}
|
|
336
417
|
}
|
|
337
418
|
|
|
419
|
+
return { success: false, error: 'Maximum login attempts reached.' };
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Create account flow for new buyers.
|
|
424
|
+
*
|
|
425
|
+
* Asks for password, creates account, waits for email verification.
|
|
426
|
+
*
|
|
427
|
+
* @param {object} client - LicenseApiClient instance
|
|
428
|
+
* @param {string} email - Verified buyer email
|
|
429
|
+
* @returns {Promise<Object>} Result with { success, key, activationResult }
|
|
430
|
+
*/
|
|
431
|
+
async function createAccountFlow(client, email) {
|
|
432
|
+
const inquirer = require('inquirer');
|
|
433
|
+
|
|
434
|
+
console.log('');
|
|
435
|
+
showInfo('Create your AIOS Pro account to get started.');
|
|
436
|
+
|
|
338
437
|
// Ask for password with confirmation
|
|
339
438
|
const { newPassword } = await inquirer.prompt([
|
|
340
439
|
{
|
|
@@ -370,29 +469,79 @@ async function promptCreateAccount(client, email) {
|
|
|
370
469
|
const spinner = createSpinner('Creating account...');
|
|
371
470
|
spinner.start();
|
|
372
471
|
|
|
472
|
+
let sessionToken;
|
|
373
473
|
try {
|
|
374
474
|
await client.signup(email, confirmPassword);
|
|
375
475
|
spinner.succeed('Account created! Verification email sent.');
|
|
376
|
-
|
|
377
|
-
// Login to get session token
|
|
378
|
-
const loginResult = await client.login(email, confirmPassword);
|
|
379
|
-
return { success: true, sessionToken: loginResult.sessionToken };
|
|
380
476
|
} catch (signupError) {
|
|
381
477
|
if (signupError.code === 'EMAIL_ALREADY_REGISTERED') {
|
|
382
|
-
spinner.
|
|
383
|
-
|
|
384
|
-
return { success: false, error: signupError.message };
|
|
478
|
+
spinner.info('Account already exists. Switching to login...');
|
|
479
|
+
return loginWithRetry(client, email);
|
|
385
480
|
}
|
|
386
481
|
spinner.fail(`Account creation failed: ${signupError.message}`);
|
|
387
482
|
return { success: false, error: signupError.message };
|
|
388
483
|
}
|
|
484
|
+
|
|
485
|
+
// Wait for email verification
|
|
486
|
+
console.log('');
|
|
487
|
+
showInfo('Please check your email and click the verification link.');
|
|
488
|
+
|
|
489
|
+
// Login after signup to get session token
|
|
490
|
+
try {
|
|
491
|
+
const loginResult = await client.login(email, confirmPassword);
|
|
492
|
+
sessionToken = loginResult.sessionToken;
|
|
493
|
+
} catch {
|
|
494
|
+
// Login might fail if email not verified yet — that's OK, we'll poll
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
if (sessionToken) {
|
|
498
|
+
const verifyResult = await waitForEmailVerification(client, sessionToken);
|
|
499
|
+
if (!verifyResult.success) {
|
|
500
|
+
return verifyResult;
|
|
501
|
+
}
|
|
502
|
+
} else {
|
|
503
|
+
// Need to wait for verification then login
|
|
504
|
+
showInfo('Waiting for email verification...');
|
|
505
|
+
showInfo('After verifying, the installation will continue automatically.');
|
|
506
|
+
|
|
507
|
+
// Poll by trying to login periodically
|
|
508
|
+
const startTime = Date.now();
|
|
509
|
+
while (Date.now() - startTime < VERIFY_POLL_TIMEOUT_MS) {
|
|
510
|
+
await new Promise((resolve) => setTimeout(resolve, VERIFY_POLL_INTERVAL_MS));
|
|
511
|
+
try {
|
|
512
|
+
const loginResult = await client.login(email, confirmPassword);
|
|
513
|
+
sessionToken = loginResult.sessionToken;
|
|
514
|
+
if (loginResult.emailVerified) {
|
|
515
|
+
showSuccess('Email verified!');
|
|
516
|
+
break;
|
|
517
|
+
}
|
|
518
|
+
// Got session but not verified yet — use the verification polling
|
|
519
|
+
const verifyResult = await waitForEmailVerification(client, sessionToken);
|
|
520
|
+
if (!verifyResult.success) {
|
|
521
|
+
return verifyResult;
|
|
522
|
+
}
|
|
523
|
+
break;
|
|
524
|
+
} catch {
|
|
525
|
+
// Still waiting for verification
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
if (!sessionToken) {
|
|
530
|
+
showError('Email verification timed out after 10 minutes.');
|
|
531
|
+
showInfo('Run the installer again to retry.');
|
|
532
|
+
return { success: false, error: 'Email verification timed out.' };
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// Activate Pro
|
|
537
|
+
return activateProByAuth(client, sessionToken);
|
|
389
538
|
}
|
|
390
539
|
|
|
391
540
|
/**
|
|
392
|
-
* Authenticate with email and password.
|
|
541
|
+
* Authenticate with email and password (CI mode / pre-provided credentials).
|
|
393
542
|
*
|
|
394
|
-
*
|
|
395
|
-
*
|
|
543
|
+
* For interactive mode, use stepLicenseGateWithEmail() instead (buyer-first flow).
|
|
544
|
+
* This function is used when credentials are pre-provided (CI, CLI args).
|
|
396
545
|
*
|
|
397
546
|
* @param {string} email - User email
|
|
398
547
|
* @param {string} password - User password
|
|
@@ -421,120 +570,57 @@ async function authenticateWithEmail(email, password) {
|
|
|
421
570
|
};
|
|
422
571
|
}
|
|
423
572
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
573
|
+
// CI mode: check buyer first, then try login or auto-signup
|
|
574
|
+
const checkSpinner = createSpinner('Verifying access...');
|
|
575
|
+
checkSpinner.start();
|
|
427
576
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
break; // Success, exit retry loop
|
|
439
|
-
} catch (loginError) {
|
|
440
|
-
if (loginError.code === 'INVALID_CREDENTIALS') {
|
|
441
|
-
spinner.stop();
|
|
442
|
-
|
|
443
|
-
// Try to determine if account exists by attempting signup
|
|
444
|
-
// If signup fails with EMAIL_ALREADY_REGISTERED, account exists (wrong password)
|
|
445
|
-
// If signup succeeds or would succeed, account doesn't exist (new user)
|
|
446
|
-
if (isCIEnvironment()) {
|
|
447
|
-
// CI mode: try auto-signup
|
|
448
|
-
try {
|
|
449
|
-
await client.signup(email, currentPassword);
|
|
450
|
-
showSuccess('Account created. Verification email sent!');
|
|
451
|
-
emailVerified = false;
|
|
452
|
-
const loginAfterSignup = await client.login(email, currentPassword);
|
|
453
|
-
sessionToken = loginAfterSignup.sessionToken;
|
|
454
|
-
break;
|
|
455
|
-
} catch (signupError) {
|
|
456
|
-
if (signupError.code === 'EMAIL_ALREADY_REGISTERED') {
|
|
457
|
-
showError('Account exists but the password is incorrect.');
|
|
458
|
-
showInfo('Forgot your password? Visit https://pro.synkra.ai/reset-password or contact support@synkra.ai');
|
|
459
|
-
return { success: false, error: signupError.message };
|
|
460
|
-
}
|
|
461
|
-
return { success: false, error: signupError.message };
|
|
462
|
-
}
|
|
463
|
-
}
|
|
577
|
+
try {
|
|
578
|
+
const checkResult = await client.checkEmail(email);
|
|
579
|
+
if (!checkResult.isBuyer) {
|
|
580
|
+
checkSpinner.fail('No AIOS Pro access found for this email.');
|
|
581
|
+
return { success: false, error: 'Email not found in Pro buyers list.' };
|
|
582
|
+
}
|
|
583
|
+
checkSpinner.succeed('Pro access confirmed.');
|
|
584
|
+
} catch {
|
|
585
|
+
checkSpinner.info('Buyer check unavailable, proceeding with login...');
|
|
586
|
+
}
|
|
464
587
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
588
|
+
// Try login
|
|
589
|
+
const spinner = createSpinner('Authenticating...');
|
|
590
|
+
spinner.start();
|
|
468
591
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
// Try a lightweight signup to probe. If EMAIL_ALREADY_REGISTERED, account exists.
|
|
472
|
-
await client.signup(email, currentPassword);
|
|
473
|
-
// Signup succeeded — account was just created
|
|
474
|
-
accountCheckSpinner.succeed('Account created! Verification email sent.');
|
|
475
|
-
const loginAfterSignup = await client.login(email, currentPassword);
|
|
476
|
-
sessionToken = loginAfterSignup.sessionToken;
|
|
477
|
-
emailVerified = false;
|
|
478
|
-
break;
|
|
479
|
-
} catch (probeError) {
|
|
480
|
-
if (probeError.code === 'EMAIL_ALREADY_REGISTERED') {
|
|
481
|
-
accountExists = true;
|
|
482
|
-
accountCheckSpinner.stop();
|
|
483
|
-
} else {
|
|
484
|
-
accountCheckSpinner.stop();
|
|
485
|
-
// Unknown error during probe — offer create account flow
|
|
486
|
-
const signupResult = await promptCreateAccount(client, email);
|
|
487
|
-
if (!signupResult.success) {
|
|
488
|
-
return signupResult;
|
|
489
|
-
}
|
|
490
|
-
sessionToken = signupResult.sessionToken;
|
|
491
|
-
emailVerified = false;
|
|
492
|
-
break;
|
|
493
|
-
}
|
|
494
|
-
}
|
|
592
|
+
let sessionToken;
|
|
593
|
+
let emailVerified;
|
|
495
594
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
return true;
|
|
515
|
-
},
|
|
516
|
-
},
|
|
517
|
-
]);
|
|
518
|
-
currentPassword = retryPassword;
|
|
519
|
-
continue; // Retry login
|
|
520
|
-
} else {
|
|
521
|
-
showError('Maximum login attempts reached.');
|
|
522
|
-
showInfo('Forgot your password? Visit https://pro.synkra.ai/reset-password or contact support@synkra.ai');
|
|
523
|
-
return { success: false, error: 'Maximum login attempts reached.' };
|
|
524
|
-
}
|
|
595
|
+
try {
|
|
596
|
+
const loginResult = await client.login(email, password);
|
|
597
|
+
sessionToken = loginResult.sessionToken;
|
|
598
|
+
emailVerified = loginResult.emailVerified;
|
|
599
|
+
spinner.succeed('Authenticated successfully.');
|
|
600
|
+
} catch (loginError) {
|
|
601
|
+
if (loginError.code === 'INVALID_CREDENTIALS') {
|
|
602
|
+
spinner.info('Login failed, attempting signup...');
|
|
603
|
+
try {
|
|
604
|
+
await client.signup(email, password);
|
|
605
|
+
showSuccess('Account created. Verification email sent!');
|
|
606
|
+
emailVerified = false;
|
|
607
|
+
const loginAfterSignup = await client.login(email, password);
|
|
608
|
+
sessionToken = loginAfterSignup.sessionToken;
|
|
609
|
+
} catch (signupError) {
|
|
610
|
+
if (signupError.code === 'EMAIL_ALREADY_REGISTERED') {
|
|
611
|
+
showError('Account exists but the password is incorrect.');
|
|
612
|
+
return { success: false, error: 'Invalid password.' };
|
|
525
613
|
}
|
|
526
|
-
|
|
527
|
-
spinner.fail(loginError.message);
|
|
528
|
-
return { success: false, error: loginError.message };
|
|
529
|
-
} else {
|
|
530
|
-
spinner.fail(`Authentication failed: ${loginError.message}`);
|
|
531
|
-
return { success: false, error: loginError.message };
|
|
614
|
+
return { success: false, error: signupError.message };
|
|
532
615
|
}
|
|
616
|
+
} else {
|
|
617
|
+
spinner.fail(`Authentication failed: ${loginError.message}`);
|
|
618
|
+
return { success: false, error: loginError.message };
|
|
533
619
|
}
|
|
534
620
|
}
|
|
535
621
|
|
|
536
622
|
if (!sessionToken) {
|
|
537
|
-
return { success: false, error: 'Authentication failed
|
|
623
|
+
return { success: false, error: 'Authentication failed.' };
|
|
538
624
|
}
|
|
539
625
|
|
|
540
626
|
// Wait for email verification if needed
|
|
@@ -1070,11 +1156,12 @@ module.exports = {
|
|
|
1070
1156
|
authenticateWithEmail,
|
|
1071
1157
|
waitForEmailVerification,
|
|
1072
1158
|
activateProByAuth,
|
|
1159
|
+
loginWithRetry,
|
|
1160
|
+
createAccountFlow,
|
|
1073
1161
|
stepLicenseGateCI,
|
|
1074
1162
|
stepLicenseGateWithKey,
|
|
1075
1163
|
stepLicenseGateWithKeyInteractive,
|
|
1076
1164
|
stepLicenseGateWithEmail,
|
|
1077
|
-
promptCreateAccount,
|
|
1078
1165
|
loadLicenseApi,
|
|
1079
1166
|
loadFeatureGate,
|
|
1080
1167
|
loadProScaffolder,
|