lsh-framework 1.7.3 → 1.8.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/dist/commands/init.js +7 -17
- package/dist/lib/secrets-manager.js +79 -91
- package/dist/services/secrets/secrets.js +8 -24
- package/package.json +1 -1
package/dist/commands/init.js
CHANGED
|
@@ -257,8 +257,9 @@ async function saveConfiguration(config) {
|
|
|
257
257
|
// File doesn't exist, start fresh
|
|
258
258
|
}
|
|
259
259
|
// Update or add configuration
|
|
260
|
-
|
|
261
|
-
|
|
260
|
+
const updates = {
|
|
261
|
+
LSH_SECRETS_KEY: config.encryptionKey,
|
|
262
|
+
};
|
|
262
263
|
if (config.storageType === 'supabase' && config.supabaseUrl && config.supabaseKey) {
|
|
263
264
|
updates.SUPABASE_URL = config.supabaseUrl;
|
|
264
265
|
updates.SUPABASE_ANON_KEY = config.supabaseKey;
|
|
@@ -326,23 +327,12 @@ function showSuccessMessage(config) {
|
|
|
326
327
|
console.log(chalk.bold.green('✨ Setup complete!'));
|
|
327
328
|
console.log(chalk.gray('━'.repeat(50)));
|
|
328
329
|
console.log('');
|
|
329
|
-
// Show encryption key
|
|
330
|
-
console.log(chalk.yellow('
|
|
330
|
+
// Show encryption key
|
|
331
|
+
console.log(chalk.yellow('📝 Your encryption key (save this securely):'));
|
|
331
332
|
console.log(chalk.cyan(` ${config.encryptionKey}`));
|
|
332
333
|
console.log('');
|
|
333
|
-
console.log(chalk.
|
|
334
|
-
console.log('');
|
|
335
|
-
console.log(chalk.gray(' Add to your shell profile:'));
|
|
336
|
-
console.log(chalk.cyan(` echo 'export LSH_SECRETS_KEY="${config.encryptionKey}"' >> ~/.zshrc`));
|
|
337
|
-
console.log(chalk.cyan(' source ~/.zshrc'));
|
|
338
|
-
console.log('');
|
|
339
|
-
console.log(chalk.gray(' Then verify it\'s set:'));
|
|
340
|
-
console.log(chalk.cyan(' echo $LSH_SECRETS_KEY'));
|
|
341
|
-
console.log('');
|
|
342
|
-
console.log(chalk.gray(' Share this key securely with your team:'));
|
|
343
|
-
console.log(chalk.gray(' - Use 1Password, LastPass, or Bitwarden'));
|
|
344
|
-
console.log(chalk.gray(' - Send via encrypted email or Signal'));
|
|
345
|
-
console.log(chalk.gray(' - Never commit to git or post in public channels'));
|
|
334
|
+
console.log(chalk.gray(' This key is saved in your .env file.'));
|
|
335
|
+
console.log(chalk.gray(' Share it with your team to sync secrets.'));
|
|
346
336
|
console.log('');
|
|
347
337
|
// Storage info
|
|
348
338
|
if (config.storageType === 'supabase') {
|
|
@@ -159,8 +159,8 @@ export class SecretsManager {
|
|
|
159
159
|
}
|
|
160
160
|
message += `\nThis is likely unintentional and could break your application.\n\n`;
|
|
161
161
|
message += `To proceed anyway, use the --force flag:\n`;
|
|
162
|
-
message += ` lsh
|
|
163
|
-
message += ` lsh
|
|
162
|
+
message += ` lsh push --force\n`;
|
|
163
|
+
message += ` lsh sync --force\n`;
|
|
164
164
|
return message;
|
|
165
165
|
}
|
|
166
166
|
/**
|
|
@@ -371,84 +371,45 @@ export class SecretsManager {
|
|
|
371
371
|
return environment;
|
|
372
372
|
}
|
|
373
373
|
/**
|
|
374
|
-
*
|
|
375
|
-
* SECURITY: Key must be in shell profile, NEVER in project .env
|
|
374
|
+
* Generate encryption key if not set
|
|
376
375
|
*/
|
|
377
376
|
async ensureEncryptionKey() {
|
|
378
|
-
if (process.env.LSH_SECRETS_KEY
|
|
379
|
-
return true; // Key already set
|
|
380
|
-
}
|
|
381
|
-
// DO NOT AUTO-GENERATE - This is a security violation
|
|
382
|
-
console.log('');
|
|
383
|
-
logger.error('❌ LSH_SECRETS_KEY environment variable not set');
|
|
384
|
-
console.log('');
|
|
385
|
-
logger.error('🔒 For security, this key must be stored in your shell profile,');
|
|
386
|
-
logger.error(' NOT in your project\'s .env file.');
|
|
387
|
-
console.log('');
|
|
388
|
-
logger.error('📝 Quick setup:');
|
|
389
|
-
console.log('');
|
|
390
|
-
logger.error(' 1. Generate a key:');
|
|
391
|
-
logger.error(' lsh key');
|
|
392
|
-
console.log('');
|
|
393
|
-
logger.error(' 2. Add to your shell profile:');
|
|
394
|
-
logger.error(' echo "export LSH_SECRETS_KEY=\'your-key-here\'" >> ~/.zshrc');
|
|
395
|
-
logger.error(' source ~/.zshrc');
|
|
396
|
-
console.log('');
|
|
397
|
-
logger.error(' 3. Verify it\'s set:');
|
|
398
|
-
logger.error(' echo $LSH_SECRETS_KEY');
|
|
399
|
-
console.log('');
|
|
400
|
-
logger.error('📖 See SECURITY.md for complete details and team sharing.');
|
|
401
|
-
console.log('');
|
|
402
|
-
throw new Error('LSH_SECRETS_KEY not set in environment');
|
|
403
|
-
}
|
|
404
|
-
/**
|
|
405
|
-
* Check if LSH_SECRETS_KEY is in .env file (security violation)
|
|
406
|
-
* SECURITY: Keys in .env files create circular encryption and expose secrets
|
|
407
|
-
*/
|
|
408
|
-
checkForKeyInEnvFile() {
|
|
409
|
-
// Skip check in test environment
|
|
410
|
-
if (process.env.NODE_ENV === 'test' || process.env.JEST_WORKER_ID) {
|
|
411
|
-
return;
|
|
377
|
+
if (process.env.LSH_SECRETS_KEY) {
|
|
378
|
+
return true; // Key already set
|
|
412
379
|
}
|
|
380
|
+
logger.warn('⚠️ No encryption key found. Generating a new key...');
|
|
381
|
+
const key = crypto.randomBytes(32).toString('hex');
|
|
382
|
+
// Try to add to .env file
|
|
413
383
|
const envPath = path.join(process.cwd(), '.env');
|
|
414
|
-
if (!fs.existsSync(envPath)) {
|
|
415
|
-
return; // No .env file, nothing to check
|
|
416
|
-
}
|
|
417
384
|
try {
|
|
418
|
-
|
|
385
|
+
let content = '';
|
|
386
|
+
if (fs.existsSync(envPath)) {
|
|
387
|
+
content = fs.readFileSync(envPath, 'utf8');
|
|
388
|
+
if (!content.endsWith('\n')) {
|
|
389
|
+
content += '\n';
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
// Check if LSH_SECRETS_KEY already exists (but empty)
|
|
419
393
|
if (content.includes('LSH_SECRETS_KEY=')) {
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
logger.error(' - Creates circular encryption (key encrypts itself)');
|
|
425
|
-
logger.error(' - Exposes key if .env is accidentally committed');
|
|
426
|
-
logger.error(' - Makes IPFS storage completely insecure');
|
|
427
|
-
console.log('');
|
|
428
|
-
logger.error('🔧 Fix this immediately:');
|
|
429
|
-
console.log('');
|
|
430
|
-
logger.error(' 1. Copy the key value from .env');
|
|
431
|
-
logger.error(' 2. Add to your shell profile:');
|
|
432
|
-
logger.error(' echo "export LSH_SECRETS_KEY=\'your-key\'" >> ~/.zshrc');
|
|
433
|
-
logger.error(' source ~/.zshrc');
|
|
434
|
-
console.log('');
|
|
435
|
-
logger.error(' 3. Remove LSH_SECRETS_KEY line from .env:');
|
|
436
|
-
logger.error(' # Edit .env and DELETE the LSH_SECRETS_KEY= line');
|
|
437
|
-
console.log('');
|
|
438
|
-
logger.error(' 4. Verify it\'s set correctly:');
|
|
439
|
-
logger.error(' echo $LSH_SECRETS_KEY');
|
|
440
|
-
console.log('');
|
|
441
|
-
logger.error('📖 See SECURITY.md for complete details.');
|
|
442
|
-
console.log('');
|
|
443
|
-
throw new Error('LSH_SECRETS_KEY must not be in .env file');
|
|
394
|
+
content = content.replace(/LSH_SECRETS_KEY=.*$/m, `LSH_SECRETS_KEY=${key}`);
|
|
395
|
+
}
|
|
396
|
+
else {
|
|
397
|
+
content += `\n# LSH Secrets Encryption Key (do not commit!)\nLSH_SECRETS_KEY=${key}\n`;
|
|
444
398
|
}
|
|
399
|
+
fs.writeFileSync(envPath, content, 'utf8');
|
|
400
|
+
// Set in current process
|
|
401
|
+
process.env.LSH_SECRETS_KEY = key;
|
|
402
|
+
this.encryptionKey = key;
|
|
403
|
+
logger.info('✅ Generated and saved encryption key to .env');
|
|
404
|
+
logger.info('💡 Load it now: export LSH_SECRETS_KEY=' + key.substring(0, 8) + '...');
|
|
405
|
+
return true;
|
|
445
406
|
}
|
|
446
407
|
catch (error) {
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
}
|
|
451
|
-
|
|
408
|
+
const _err = error;
|
|
409
|
+
logger.error(`Failed to save encryption key: ${_err.message}`);
|
|
410
|
+
logger.info('Please set it manually:');
|
|
411
|
+
logger.info(`export LSH_SECRETS_KEY=${key}`);
|
|
412
|
+
return false;
|
|
452
413
|
}
|
|
453
414
|
}
|
|
454
415
|
/**
|
|
@@ -544,7 +505,7 @@ LSH_SECRETS_KEY=${this.encryptionKey}
|
|
|
544
505
|
* Smart sync command - automatically set up and synchronize secrets
|
|
545
506
|
* This is the new enhanced sync that does everything automatically
|
|
546
507
|
*/
|
|
547
|
-
async smartSync(envFilePath = '.env', environment = 'dev', autoExecute = true, loadMode = false, force = false) {
|
|
508
|
+
async smartSync(envFilePath = '.env', environment = 'dev', autoExecute = true, loadMode = false, force = false, forceRekey = false) {
|
|
548
509
|
// In load mode, suppress all logger output to prevent zsh glob interpretation
|
|
549
510
|
// Save original level and restore at the end
|
|
550
511
|
const originalLogLevel = loadMode ? logger['config'].level : undefined;
|
|
@@ -567,19 +528,17 @@ LSH_SECRETS_KEY=${this.encryptionKey}
|
|
|
567
528
|
}
|
|
568
529
|
out();
|
|
569
530
|
}
|
|
570
|
-
// Step 1:
|
|
571
|
-
this.checkForKeyInEnvFile(); // Must be BEFORE ensureEncryptionKey
|
|
572
|
-
// Step 2: Ensure encryption key exists
|
|
531
|
+
// Step 1: Ensure encryption key exists
|
|
573
532
|
if (!process.env.LSH_SECRETS_KEY) {
|
|
574
533
|
logger.info('🔑 No encryption key found...');
|
|
575
534
|
await this.ensureEncryptionKey();
|
|
576
535
|
out();
|
|
577
536
|
}
|
|
578
|
-
// Step
|
|
537
|
+
// Step 2: Ensure .gitignore includes .env
|
|
579
538
|
if (this.gitInfo?.isGitRepo) {
|
|
580
539
|
ensureEnvInGitignore(process.cwd());
|
|
581
540
|
}
|
|
582
|
-
// Step
|
|
541
|
+
// Step 3: Check current status
|
|
583
542
|
const status = await this.status(envFilePath, effectiveEnv);
|
|
584
543
|
out('📊 Current Status:');
|
|
585
544
|
out(` Encryption key: ${status.keySet ? '✅' : '❌'}`);
|
|
@@ -589,14 +548,43 @@ LSH_SECRETS_KEY=${this.encryptionKey}
|
|
|
589
548
|
out(` Key matches: ${status.keyMatches ? '✅' : '❌'}`);
|
|
590
549
|
}
|
|
591
550
|
out();
|
|
592
|
-
// Step
|
|
551
|
+
// Step 4: Determine action and execute if auto mode
|
|
593
552
|
let _action = 'in-sync';
|
|
594
553
|
if (status.cloudExists && status.keyMatches === false) {
|
|
554
|
+
if (forceRekey) {
|
|
555
|
+
// Force re-keying: push local secrets with current key
|
|
556
|
+
_action = 'push';
|
|
557
|
+
out('🔄 Force re-keying: Re-encrypting cloud secrets with current key...');
|
|
558
|
+
if (autoExecute) {
|
|
559
|
+
if (!status.localExists) {
|
|
560
|
+
out('❌ Cannot re-key: No local .env file found');
|
|
561
|
+
out(`💡 Pull with original key first, or create new .env`);
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
out(' Pushing to cloud with new key...');
|
|
565
|
+
await this.push(envFilePath, effectiveEnv, true); // Force push
|
|
566
|
+
out();
|
|
567
|
+
out('✅ Re-keying complete! Cloud secrets now encrypted with current key.');
|
|
568
|
+
}
|
|
569
|
+
else {
|
|
570
|
+
out('💡 Run: lsh push -f ${envFilePath} -e ${environment}');
|
|
571
|
+
}
|
|
572
|
+
out();
|
|
573
|
+
// Output export commands in load mode
|
|
574
|
+
if (loadMode && fs.existsSync(envFilePath)) {
|
|
575
|
+
console.log(this.generateExportCommands(envFilePath));
|
|
576
|
+
}
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
// No force-rekey: show error and options
|
|
595
580
|
_action = 'key-mismatch';
|
|
596
581
|
out('⚠️ Encryption key mismatch!');
|
|
597
582
|
out(' The local key does not match the cloud storage.');
|
|
598
|
-
out(
|
|
599
|
-
out(
|
|
583
|
+
out();
|
|
584
|
+
out(' Options:');
|
|
585
|
+
out(` 1. Use the original key (recommended if you have it)`);
|
|
586
|
+
out(` 2. Re-encrypt with current key: lsh push -f ${envFilePath} -e ${environment}`);
|
|
587
|
+
out(` 3. Re-key during sync: lsh sync --force-rekey -f ${envFilePath} -e ${environment}`);
|
|
600
588
|
out();
|
|
601
589
|
return;
|
|
602
590
|
}
|
|
@@ -612,7 +600,7 @@ LSH_SECRETS_KEY=${this.encryptionKey}
|
|
|
612
600
|
out('✅ Setup complete! Edit your .env and run sync again to update.');
|
|
613
601
|
}
|
|
614
602
|
else {
|
|
615
|
-
out('💡 Run: lsh
|
|
603
|
+
out('💡 Run: lsh create && lsh push');
|
|
616
604
|
}
|
|
617
605
|
out();
|
|
618
606
|
// Output export commands in load mode
|
|
@@ -630,7 +618,7 @@ LSH_SECRETS_KEY=${this.encryptionKey}
|
|
|
630
618
|
out('✅ Secrets pushed to cloud!');
|
|
631
619
|
}
|
|
632
620
|
else {
|
|
633
|
-
out(`💡 Run: lsh
|
|
621
|
+
out(`💡 Run: lsh push -f ${envFilePath} -e ${environment}`);
|
|
634
622
|
}
|
|
635
623
|
out();
|
|
636
624
|
// Output export commands in load mode
|
|
@@ -648,7 +636,7 @@ LSH_SECRETS_KEY=${this.encryptionKey}
|
|
|
648
636
|
out('✅ Secrets pulled from cloud!');
|
|
649
637
|
}
|
|
650
638
|
else {
|
|
651
|
-
out(`💡 Run: lsh
|
|
639
|
+
out(`💡 Run: lsh pull -f ${envFilePath} -e ${environment}`);
|
|
652
640
|
}
|
|
653
641
|
out();
|
|
654
642
|
// Output export commands in load mode
|
|
@@ -685,7 +673,7 @@ LSH_SECRETS_KEY=${this.encryptionKey}
|
|
|
685
673
|
out('✅ Secrets synced to cloud!');
|
|
686
674
|
}
|
|
687
675
|
else {
|
|
688
|
-
out(`💡 Run: lsh
|
|
676
|
+
out(`💡 Run: lsh push -f ${envFilePath} -e ${environment}`);
|
|
689
677
|
}
|
|
690
678
|
}
|
|
691
679
|
else {
|
|
@@ -699,7 +687,7 @@ LSH_SECRETS_KEY=${this.encryptionKey}
|
|
|
699
687
|
out('✅ Secrets synced from cloud!');
|
|
700
688
|
}
|
|
701
689
|
else {
|
|
702
|
-
out(`💡 Run: lsh
|
|
690
|
+
out(`💡 Run: lsh pull -f ${envFilePath} -e ${environment}`);
|
|
703
691
|
}
|
|
704
692
|
}
|
|
705
693
|
out();
|
|
@@ -764,22 +752,22 @@ LSH_SECRETS_KEY=${this.encryptionKey}
|
|
|
764
752
|
const suggestions = [];
|
|
765
753
|
if (!status.keySet) {
|
|
766
754
|
suggestions.push('⚠️ No encryption key set!');
|
|
767
|
-
suggestions.push(' Generate a key: lsh
|
|
755
|
+
suggestions.push(' Generate a key: lsh key');
|
|
768
756
|
suggestions.push(' Add it to .env: LSH_SECRETS_KEY=<your-key>');
|
|
769
757
|
suggestions.push(' Load it: export $(cat .env | xargs)');
|
|
770
758
|
}
|
|
771
759
|
if (status.cloudExists && status.keyMatches === false) {
|
|
772
760
|
suggestions.push('⚠️ Encryption key does not match cloud storage!');
|
|
773
761
|
suggestions.push(' Either use the original key, or push new secrets:');
|
|
774
|
-
suggestions.push(` lsh
|
|
762
|
+
suggestions.push(` lsh push -f ${envFilePath} -e ${environment}`);
|
|
775
763
|
}
|
|
776
764
|
if (!status.localExists && status.cloudExists && status.keyMatches) {
|
|
777
765
|
suggestions.push('💡 Cloud secrets available but no local file');
|
|
778
|
-
suggestions.push(` Pull from cloud: lsh
|
|
766
|
+
suggestions.push(` Pull from cloud: lsh pull -f ${envFilePath} -e ${environment}`);
|
|
779
767
|
}
|
|
780
768
|
if (status.localExists && !status.cloudExists) {
|
|
781
769
|
suggestions.push('💡 Local .env exists but not in cloud');
|
|
782
|
-
suggestions.push(` Push to cloud: lsh
|
|
770
|
+
suggestions.push(` Push to cloud: lsh push -f ${envFilePath} -e ${environment}`);
|
|
783
771
|
}
|
|
784
772
|
if (status.localExists && status.cloudExists && status.keyMatches) {
|
|
785
773
|
if (status.localModified && status.cloudModified) {
|
|
@@ -788,11 +776,11 @@ LSH_SECRETS_KEY=${this.encryptionKey}
|
|
|
788
776
|
const daysDiff = Math.floor(timeDiff / (1000 * 60 * 60 * 24));
|
|
789
777
|
if (localNewer && daysDiff > 0) {
|
|
790
778
|
suggestions.push('💡 Local file is newer than cloud');
|
|
791
|
-
suggestions.push(` Push to cloud: lsh
|
|
779
|
+
suggestions.push(` Push to cloud: lsh push -f ${envFilePath} -e ${environment}`);
|
|
792
780
|
}
|
|
793
781
|
else if (!localNewer && daysDiff > 0) {
|
|
794
782
|
suggestions.push('💡 Cloud is newer than local file');
|
|
795
|
-
suggestions.push(` Pull from cloud: lsh
|
|
783
|
+
suggestions.push(` Pull from cloud: lsh pull -f ${envFilePath} -e ${environment}`);
|
|
796
784
|
}
|
|
797
785
|
else {
|
|
798
786
|
suggestions.push('✅ Local and cloud are in sync!');
|
|
@@ -7,7 +7,6 @@ import * as fs from 'fs';
|
|
|
7
7
|
import * as path from 'path';
|
|
8
8
|
import * as readline from 'readline';
|
|
9
9
|
import { getGitRepoInfo } from '../../lib/git-utils.js';
|
|
10
|
-
import chalk from 'chalk';
|
|
11
10
|
export async function init_secrets(program) {
|
|
12
11
|
// Push secrets to cloud
|
|
13
12
|
program
|
|
@@ -198,27 +197,11 @@ export async function init_secrets(program) {
|
|
|
198
197
|
}
|
|
199
198
|
else {
|
|
200
199
|
// Interactive output with tips
|
|
201
|
-
console.log('');
|
|
202
|
-
console.log('
|
|
203
|
-
console.log(
|
|
204
|
-
console.log('');
|
|
205
|
-
console.log(
|
|
206
|
-
console.log('');
|
|
207
|
-
console.log(chalk.gray(' 1. Add to your shell profile:'));
|
|
208
|
-
console.log(chalk.cyan(` echo 'export LSH_SECRETS_KEY="${key}"' >> ~/.zshrc`));
|
|
209
|
-
console.log(chalk.cyan(' source ~/.zshrc'));
|
|
210
|
-
console.log('');
|
|
211
|
-
console.log(chalk.gray(' 2. Verify it\'s set:'));
|
|
212
|
-
console.log(chalk.cyan(' echo $LSH_SECRETS_KEY'));
|
|
213
|
-
console.log('');
|
|
214
|
-
console.log(chalk.gray(' 3. Share securely with your team:'));
|
|
215
|
-
console.log(chalk.gray(' - Use 1Password, LastPass, or Bitwarden'));
|
|
216
|
-
console.log(chalk.gray(' - Send via encrypted email or Signal'));
|
|
217
|
-
console.log(chalk.gray(' - NEVER commit to git or .env file'));
|
|
218
|
-
console.log('');
|
|
219
|
-
console.log(chalk.gray('💡 Quick load: eval "$(lsh key --export)"'));
|
|
220
|
-
console.log(chalk.gray('📖 Details: See SECURITY.md'));
|
|
221
|
-
console.log('');
|
|
200
|
+
console.log('\n🔑 New encryption key (add to your .env):\n');
|
|
201
|
+
console.log(`export LSH_SECRETS_KEY='${key}'\n`);
|
|
202
|
+
console.log('💡 Tip: Share this key securely with your team to sync secrets.');
|
|
203
|
+
console.log(' Never commit it to git!\n');
|
|
204
|
+
console.log('💡 To load immediately: eval "$(lsh key --export)"\n');
|
|
222
205
|
}
|
|
223
206
|
});
|
|
224
207
|
// Create .env file
|
|
@@ -267,7 +250,7 @@ API_KEY=
|
|
|
267
250
|
console.log('');
|
|
268
251
|
console.log('Next steps:');
|
|
269
252
|
console.log(` 1. Edit the file: ${options.file}`);
|
|
270
|
-
console.log(` 2. Push to cloud: lsh
|
|
253
|
+
console.log(` 2. Push to cloud: lsh push -f ${options.file}`);
|
|
271
254
|
console.log('');
|
|
272
255
|
}
|
|
273
256
|
catch (error) {
|
|
@@ -286,6 +269,7 @@ API_KEY=
|
|
|
286
269
|
.option('--legacy', 'Use legacy sync mode (suggestions only)')
|
|
287
270
|
.option('--load', 'Output eval-able export commands for loading secrets')
|
|
288
271
|
.option('--force', 'Force sync even if destructive changes detected')
|
|
272
|
+
.option('--force-rekey', 'Re-encrypt cloud secrets with current local key (use when key mismatch)')
|
|
289
273
|
.action(async (options) => {
|
|
290
274
|
const manager = new SecretsManager();
|
|
291
275
|
try {
|
|
@@ -295,7 +279,7 @@ API_KEY=
|
|
|
295
279
|
}
|
|
296
280
|
else {
|
|
297
281
|
// Use new smart sync (auto-execute)
|
|
298
|
-
await manager.smartSync(options.file, options.env, !options.dryRun, options.load, options.force);
|
|
282
|
+
await manager.smartSync(options.file, options.env, !options.dryRun, options.load, options.force, options.forceRekey);
|
|
299
283
|
}
|
|
300
284
|
}
|
|
301
285
|
catch (error) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lsh-framework",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "Simple, cross-platform encrypted secrets manager with automatic sync, IPFS audit logs, and multi-environment support. Just run lsh sync and start managing your secrets.",
|
|
5
5
|
"main": "dist/app.js",
|
|
6
6
|
"bin": {
|