lsh-framework 3.1.19 ā 3.1.20
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/README.md +9 -7
- package/dist/cli.js +90 -89
- package/dist/commands/completion.js +2 -0
- package/dist/commands/storacha.js +268 -0
- package/dist/constants/config.js +15 -0
- package/dist/constants/errors.js +11 -0
- package/dist/constants/ui.js +140 -1
- package/dist/constants/validation.js +45 -26
- package/dist/daemon/job-registry.js +2 -1
- package/dist/daemon/lshd.js +156 -15
- package/dist/daemon/saas-api-routes.js +91 -277
- package/dist/lib/api-response.js +226 -0
- package/dist/lib/command-validator.js +17 -76
- package/dist/lib/constant-time.js +126 -0
- package/dist/lib/cron-job-manager.js +1 -1
- package/dist/lib/floating-point-arithmetic.js +4 -2
- package/dist/lib/input-validator.js +318 -0
- package/dist/lib/job-storage-database.js +13 -5
- package/dist/lib/logger.js +21 -21
- package/dist/lib/metrics/index.js +34 -0
- package/dist/lib/metrics/metrics-collector.js +484 -0
- package/dist/lib/metrics/metrics-exporter.js +275 -0
- package/dist/lib/metrics/performance-profiler.js +333 -0
- package/dist/lib/metrics/types.js +70 -0
- package/dist/lib/min-heap.js +201 -0
- package/dist/lib/optimized-job-scheduler.js +355 -0
- package/dist/lib/saas-audit.js +0 -1
- package/dist/lib/saas-auth.js +1 -4
- package/dist/lib/saas-billing.js +3 -9
- package/dist/lib/saas-encryption.js +0 -1
- package/dist/lib/saas-organizations.js +0 -5
- package/dist/lib/saas-secrets.js +0 -2
- package/dist/lib/safe-eval.js +124 -0
- package/dist/lib/storacha-client.js +692 -0
- package/dist/lib/supabase-utils.js +396 -0
- package/dist/lib/validation-framework.js +415 -0
- package/dist/lib/validation-rules.js +699 -0
- package/dist/services/cron/cron-registrar.js +1 -1
- package/dist/services/secrets/secrets.js +10 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# LSH v3.
|
|
1
|
+
# LSH v3.1.19 - Encrypted Secrets Manager
|
|
2
2
|
|
|
3
3
|
**The simplest way to sync `.env` files across all your machines.**
|
|
4
4
|
|
|
@@ -8,13 +8,15 @@
|
|
|
8
8
|
[](https://github.com/gwicho38/lsh/actions/workflows/node.js.yml)
|
|
9
9
|
[](https://opensource.org/licenses/MIT)
|
|
10
10
|
|
|
11
|
-
## What's New in v3.
|
|
11
|
+
## What's New in v3.1.19
|
|
12
12
|
|
|
13
|
-
- **
|
|
14
|
-
- **
|
|
15
|
-
- **
|
|
16
|
-
- **
|
|
17
|
-
- **
|
|
13
|
+
- **Type Safety Milestone** - All `@typescript-eslint/no-explicit-any` warnings eliminated (51+ ā 0)
|
|
14
|
+
- **Constants Centralization** - Hardcoded strings moved to constants modules
|
|
15
|
+
- **API Response Builder** - Standardized API responses with `sendSuccess`, `sendError`, `ApiErrors`
|
|
16
|
+
- **Test Coverage** - 59 new tests for constants modules (142 total constants tests)
|
|
17
|
+
- **Code Quality** - Lint warnings reduced from 744 to 550 (26.1% reduction)
|
|
18
|
+
|
|
19
|
+
See [Release Notes](docs/releases/3.1.19.md) for full details.
|
|
18
20
|
|
|
19
21
|
## Quick Start
|
|
20
22
|
|
package/dist/cli.js
CHANGED
|
@@ -15,6 +15,7 @@ import { registerMigrateCommand } from './commands/migrate.js';
|
|
|
15
15
|
import { registerContextCommand } from './commands/context.js';
|
|
16
16
|
import { init_secrets } from './services/secrets/secrets.js';
|
|
17
17
|
import { loadGlobalConfigSync } from './lib/config-manager.js';
|
|
18
|
+
import { CLI_TEXT, CLI_HELP } from './constants/ui.js';
|
|
18
19
|
import * as fs from 'fs';
|
|
19
20
|
import * as path from 'path';
|
|
20
21
|
import { fileURLToPath } from 'url';
|
|
@@ -33,59 +34,59 @@ function getVersion() {
|
|
|
33
34
|
}
|
|
34
35
|
const program = new Command();
|
|
35
36
|
program
|
|
36
|
-
.name(
|
|
37
|
-
.description(
|
|
37
|
+
.name(CLI_TEXT.NAME)
|
|
38
|
+
.description(CLI_TEXT.DESCRIPTION)
|
|
38
39
|
.version(getVersion())
|
|
39
40
|
.showSuggestionAfterError(true)
|
|
40
|
-
.showHelpAfterError(
|
|
41
|
+
.showHelpAfterError(CLI_TEXT.HELP_AFTER_ERROR)
|
|
41
42
|
.allowUnknownOption(false)
|
|
42
43
|
.enablePositionalOptions();
|
|
43
44
|
// Main action - show help by default
|
|
44
45
|
program
|
|
45
|
-
.option(
|
|
46
|
-
.option(
|
|
46
|
+
.option(CLI_TEXT.OPTION_VERBOSE, CLI_TEXT.OPTION_VERBOSE_DESC)
|
|
47
|
+
.option(CLI_TEXT.OPTION_DEBUG, CLI_TEXT.OPTION_DEBUG_DESC)
|
|
47
48
|
.action(async (_options) => {
|
|
48
49
|
// No arguments - show secrets-focused help
|
|
49
|
-
console.log(
|
|
50
|
+
console.log(CLI_HELP.TITLE);
|
|
50
51
|
console.log('');
|
|
51
|
-
console.log(
|
|
52
|
-
console.log(
|
|
53
|
-
console.log(
|
|
54
|
-
console.log(
|
|
55
|
-
console.log(
|
|
56
|
-
console.log(
|
|
57
|
-
console.log(
|
|
58
|
-
console.log(
|
|
59
|
-
console.log(
|
|
60
|
-
console.log(
|
|
61
|
-
console.log(
|
|
62
|
-
console.log(
|
|
63
|
-
console.log(
|
|
64
|
-
console.log(
|
|
52
|
+
console.log(CLI_HELP.SECTION_SECRETS);
|
|
53
|
+
console.log(CLI_HELP.CMD_INIT);
|
|
54
|
+
console.log(CLI_HELP.CMD_DOCTOR);
|
|
55
|
+
console.log(CLI_HELP.CMD_SYNC);
|
|
56
|
+
console.log(CLI_HELP.CMD_PUSH);
|
|
57
|
+
console.log(CLI_HELP.CMD_PULL);
|
|
58
|
+
console.log(CLI_HELP.CMD_LIST);
|
|
59
|
+
console.log(CLI_HELP.CMD_ENV);
|
|
60
|
+
console.log(CLI_HELP.CMD_KEY);
|
|
61
|
+
console.log(CLI_HELP.CMD_CREATE);
|
|
62
|
+
console.log(CLI_HELP.CMD_GET);
|
|
63
|
+
console.log(CLI_HELP.CMD_SET);
|
|
64
|
+
console.log(CLI_HELP.CMD_DELETE);
|
|
65
|
+
console.log(CLI_HELP.CMD_STATUS);
|
|
65
66
|
console.log('');
|
|
66
|
-
console.log(
|
|
67
|
-
console.log(
|
|
68
|
-
console.log(
|
|
69
|
-
console.log(
|
|
70
|
-
console.log(
|
|
71
|
-
console.log(
|
|
67
|
+
console.log(CLI_HELP.SECTION_IPFS);
|
|
68
|
+
console.log(CLI_HELP.CMD_SYNC_INIT);
|
|
69
|
+
console.log(CLI_HELP.CMD_SYNC_PUSH);
|
|
70
|
+
console.log(CLI_HELP.CMD_SYNC_PULL);
|
|
71
|
+
console.log(CLI_HELP.CMD_SYNC_STATUS);
|
|
72
|
+
console.log(CLI_HELP.CMD_SYNC_START_STOP);
|
|
72
73
|
console.log('');
|
|
73
|
-
console.log(
|
|
74
|
-
console.log(
|
|
75
|
-
console.log(
|
|
76
|
-
console.log(
|
|
74
|
+
console.log(CLI_HELP.SECTION_QUICK_START);
|
|
75
|
+
console.log(CLI_HELP.QUICK_SYNC_INIT);
|
|
76
|
+
console.log(CLI_HELP.QUICK_SYNC_PUSH);
|
|
77
|
+
console.log(CLI_HELP.QUICK_SYNC_PULL);
|
|
77
78
|
console.log('');
|
|
78
|
-
console.log(
|
|
79
|
-
console.log(
|
|
80
|
-
console.log(
|
|
81
|
-
console.log(
|
|
79
|
+
console.log(CLI_HELP.SECTION_MORE);
|
|
80
|
+
console.log(CLI_HELP.CMD_CONFIG);
|
|
81
|
+
console.log(CLI_HELP.CMD_SELF);
|
|
82
|
+
console.log(CLI_HELP.CMD_HELP_OPT);
|
|
82
83
|
console.log('');
|
|
83
|
-
console.log(
|
|
84
|
+
console.log(CLI_HELP.DOCS_LINK);
|
|
84
85
|
});
|
|
85
86
|
// Help subcommand
|
|
86
87
|
program
|
|
87
88
|
.command('help')
|
|
88
|
-
.description(
|
|
89
|
+
.description(CLI_TEXT.HELP_DESCRIPTION)
|
|
89
90
|
.action(() => {
|
|
90
91
|
showDetailedHelp();
|
|
91
92
|
});
|
|
@@ -172,12 +173,12 @@ function findSimilarCommands(input, validCommands) {
|
|
|
172
173
|
// For suggestions, only use primary command names (not aliases)
|
|
173
174
|
const primaryCommands = program.commands.map(cmd => cmd.name());
|
|
174
175
|
const suggestions = findSimilarCommands(firstArg, primaryCommands);
|
|
175
|
-
console.error(
|
|
176
|
+
console.error(`${CLI_TEXT.ERROR_UNKNOWN_COMMAND} '${firstArg}'`);
|
|
176
177
|
if (suggestions.length > 0) {
|
|
177
|
-
console.error(
|
|
178
|
+
console.error(CLI_TEXT.DID_YOU_MEAN);
|
|
178
179
|
suggestions.forEach(cmd => console.error(` ${cmd}`));
|
|
179
180
|
}
|
|
180
|
-
console.error(
|
|
181
|
+
console.error(CLI_TEXT.RUN_HELP);
|
|
181
182
|
process.exit(1);
|
|
182
183
|
}
|
|
183
184
|
}
|
|
@@ -185,7 +186,7 @@ function findSimilarCommands(input, validCommands) {
|
|
|
185
186
|
program.configureOutput({
|
|
186
187
|
writeErr: (str) => {
|
|
187
188
|
// Intercept error messages to add suggestions
|
|
188
|
-
if (str.includes(
|
|
189
|
+
if (str.includes(CLI_TEXT.ERROR_UNKNOWN_COMMAND)) {
|
|
189
190
|
const match = str.match(/unknown command '([^']+)'/);
|
|
190
191
|
if (match) {
|
|
191
192
|
const unknownCommand = match[1];
|
|
@@ -193,10 +194,10 @@ function findSimilarCommands(input, validCommands) {
|
|
|
193
194
|
const suggestions = findSimilarCommands(unknownCommand, validCommands);
|
|
194
195
|
process.stderr.write(str);
|
|
195
196
|
if (suggestions.length > 0) {
|
|
196
|
-
process.stderr.write(
|
|
197
|
+
process.stderr.write(`${CLI_TEXT.DID_YOU_MEAN}\n`);
|
|
197
198
|
suggestions.forEach(cmd => process.stderr.write(` ${cmd}\n`));
|
|
198
199
|
}
|
|
199
|
-
process.stderr.write(
|
|
200
|
+
process.stderr.write(`${CLI_TEXT.RUN_HELP}\n`);
|
|
200
201
|
return;
|
|
201
202
|
}
|
|
202
203
|
}
|
|
@@ -204,16 +205,16 @@ function findSimilarCommands(input, validCommands) {
|
|
|
204
205
|
}
|
|
205
206
|
});
|
|
206
207
|
// Add custom error handler for unknown commands
|
|
207
|
-
program.on(
|
|
208
|
+
program.on(CLI_TEXT.EVENT_UNKNOWN_COMMAND, (operands) => {
|
|
208
209
|
const unknownCommand = operands[0];
|
|
209
210
|
const validCommands = program.commands.map(cmd => cmd.name());
|
|
210
211
|
const suggestions = findSimilarCommands(unknownCommand, validCommands);
|
|
211
|
-
console.error(
|
|
212
|
+
console.error(`${CLI_TEXT.ERROR_UNKNOWN_COMMAND} '${unknownCommand}'`);
|
|
212
213
|
if (suggestions.length > 0) {
|
|
213
|
-
console.error(
|
|
214
|
+
console.error(CLI_TEXT.DID_YOU_MEAN);
|
|
214
215
|
suggestions.forEach(cmd => console.error(` ${cmd}`));
|
|
215
216
|
}
|
|
216
|
-
console.error(
|
|
217
|
+
console.error(CLI_TEXT.RUN_HELP);
|
|
217
218
|
process.exit(1);
|
|
218
219
|
});
|
|
219
220
|
// Parse command line arguments after all commands are registered
|
|
@@ -223,56 +224,56 @@ function findSimilarCommands(input, validCommands) {
|
|
|
223
224
|
* Show detailed help
|
|
224
225
|
*/
|
|
225
226
|
function showDetailedHelp() {
|
|
226
|
-
console.log(
|
|
227
|
-
console.log(
|
|
227
|
+
console.log(CLI_HELP.TITLE);
|
|
228
|
+
console.log(CLI_HELP.SEPARATOR);
|
|
228
229
|
console.log('');
|
|
229
|
-
console.log(
|
|
230
|
-
console.log(
|
|
231
|
-
console.log(
|
|
232
|
-
console.log(
|
|
233
|
-
console.log(
|
|
230
|
+
console.log(CLI_HELP.SECTION_USAGE);
|
|
231
|
+
console.log(CLI_HELP.USAGE_DEFAULT);
|
|
232
|
+
console.log(CLI_HELP.USAGE_INIT);
|
|
233
|
+
console.log(CLI_HELP.USAGE_PUSH);
|
|
234
|
+
console.log(CLI_HELP.USAGE_PULL);
|
|
234
235
|
console.log('');
|
|
235
|
-
console.log(
|
|
236
|
-
console.log(
|
|
237
|
-
console.log(
|
|
238
|
-
console.log(
|
|
239
|
-
console.log(
|
|
240
|
-
console.log(
|
|
236
|
+
console.log(CLI_HELP.SECTION_MAIN_COMMANDS);
|
|
237
|
+
console.log(CLI_HELP.MAIN_INIT);
|
|
238
|
+
console.log(CLI_HELP.MAIN_DOCTOR);
|
|
239
|
+
console.log(CLI_HELP.MAIN_ENV);
|
|
240
|
+
console.log(CLI_HELP.MAIN_KEY);
|
|
241
|
+
console.log(CLI_HELP.MAIN_STATUS);
|
|
241
242
|
console.log('');
|
|
242
|
-
console.log(
|
|
243
|
-
console.log(
|
|
244
|
-
console.log(
|
|
245
|
-
console.log(
|
|
246
|
-
console.log(
|
|
247
|
-
console.log(
|
|
248
|
-
console.log(
|
|
249
|
-
console.log(
|
|
243
|
+
console.log(CLI_HELP.SECTION_IPFS);
|
|
244
|
+
console.log(CLI_HELP.DETAIL_SYNC_INIT);
|
|
245
|
+
console.log(CLI_HELP.DETAIL_SYNC_PUSH);
|
|
246
|
+
console.log(CLI_HELP.DETAIL_SYNC_PULL);
|
|
247
|
+
console.log(CLI_HELP.DETAIL_SYNC_STATUS);
|
|
248
|
+
console.log(CLI_HELP.DETAIL_SYNC_START);
|
|
249
|
+
console.log(CLI_HELP.DETAIL_SYNC_STOP);
|
|
250
|
+
console.log(CLI_HELP.DETAIL_SYNC_HISTORY);
|
|
250
251
|
console.log('');
|
|
251
|
-
console.log(
|
|
252
|
-
console.log(
|
|
253
|
-
console.log(
|
|
254
|
-
console.log(
|
|
252
|
+
console.log(CLI_HELP.SECTION_SELF_MANAGEMENT);
|
|
253
|
+
console.log(CLI_HELP.SELF_UPDATE);
|
|
254
|
+
console.log(CLI_HELP.SELF_VERSION);
|
|
255
|
+
console.log(CLI_HELP.SELF_UNINSTALL);
|
|
255
256
|
console.log('');
|
|
256
|
-
console.log(
|
|
257
|
+
console.log(CLI_HELP.SECTION_EXAMPLES);
|
|
257
258
|
console.log('');
|
|
258
|
-
console.log(
|
|
259
|
-
console.log(
|
|
260
|
-
console.log(
|
|
259
|
+
console.log(` ${CLI_HELP.SECTION_FIRST_TIME}`);
|
|
260
|
+
console.log(CLI_HELP.EX_SYNC_INIT);
|
|
261
|
+
console.log(CLI_HELP.EX_DOCTOR);
|
|
261
262
|
console.log('');
|
|
262
|
-
console.log(
|
|
263
|
-
console.log(
|
|
264
|
-
console.log(
|
|
265
|
-
console.log(
|
|
266
|
-
console.log(
|
|
267
|
-
console.log(
|
|
263
|
+
console.log(` ${CLI_HELP.SECTION_DAILY_USAGE}`);
|
|
264
|
+
console.log(CLI_HELP.EX_SYNC_PUSH);
|
|
265
|
+
console.log(CLI_HELP.EX_SYNC_PULL);
|
|
266
|
+
console.log(CLI_HELP.EX_ENV_MASKED);
|
|
267
|
+
console.log(CLI_HELP.EX_GET);
|
|
268
|
+
console.log(CLI_HELP.EX_SET);
|
|
268
269
|
console.log('');
|
|
269
|
-
console.log(
|
|
270
|
-
console.log(
|
|
271
|
-
console.log(
|
|
272
|
-
console.log(
|
|
273
|
-
console.log(
|
|
274
|
-
console.log(
|
|
275
|
-
console.log(
|
|
270
|
+
console.log(CLI_HELP.SECTION_FEATURES);
|
|
271
|
+
console.log(CLI_HELP.FEATURE_CROSS_PLATFORM);
|
|
272
|
+
console.log(CLI_HELP.FEATURE_ENCRYPTION);
|
|
273
|
+
console.log(CLI_HELP.FEATURE_MULTI_ENV);
|
|
274
|
+
console.log(CLI_HELP.FEATURE_TEAM);
|
|
275
|
+
console.log(CLI_HELP.FEATURE_ROTATION);
|
|
276
|
+
console.log(CLI_HELP.FEATURE_GIT_AWARE);
|
|
276
277
|
console.log('');
|
|
277
|
-
console.log(
|
|
278
|
+
console.log(CLI_HELP.NEED_HELP);
|
|
278
279
|
}
|
|
@@ -12,6 +12,7 @@ function generateBashCompletion() {
|
|
|
12
12
|
# Or save to completion directory:
|
|
13
13
|
# lsh completion bash > /etc/bash_completion.d/lsh
|
|
14
14
|
|
|
15
|
+
|
|
15
16
|
_lsh_completion() {
|
|
16
17
|
local cur prev words cword
|
|
17
18
|
_init_completion || return
|
|
@@ -215,6 +216,7 @@ function generateZshCompletion() {
|
|
|
215
216
|
# fpath=(~/.zsh/completions $fpath)
|
|
216
217
|
# autoload -Uz compinit && compinit
|
|
217
218
|
|
|
219
|
+
|
|
218
220
|
_lsh() {
|
|
219
221
|
local -a commands
|
|
220
222
|
local -a global_opts
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storacha Commands
|
|
3
|
+
* Manage Storacha (IPFS network) authentication and configuration
|
|
4
|
+
*/
|
|
5
|
+
import { getStorachaClient } from '../lib/storacha-client.js';
|
|
6
|
+
export function registerStorachaCommands(program) {
|
|
7
|
+
const storacha = program
|
|
8
|
+
.command('storacha')
|
|
9
|
+
.description('Manage Storacha (IPFS network) sync');
|
|
10
|
+
// Login command
|
|
11
|
+
storacha
|
|
12
|
+
.command('login <email>')
|
|
13
|
+
.description('Authenticate with Storacha via email')
|
|
14
|
+
.action(async (email) => {
|
|
15
|
+
try {
|
|
16
|
+
const client = getStorachaClient();
|
|
17
|
+
console.log('\nš Storacha Authentication\n');
|
|
18
|
+
console.log('ā'.repeat(60));
|
|
19
|
+
console.log('');
|
|
20
|
+
await client.login(email);
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
const err = error;
|
|
24
|
+
console.error('\nā Authentication failed:', err.message);
|
|
25
|
+
console.error('');
|
|
26
|
+
console.error('š” Troubleshooting:');
|
|
27
|
+
console.error(' - Check your email for the verification link');
|
|
28
|
+
console.error(' - Complete signup at: https://console.storacha.network/');
|
|
29
|
+
console.error(' - Ensure you have an active internet connection');
|
|
30
|
+
console.error('');
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
// Status command
|
|
35
|
+
storacha
|
|
36
|
+
.command('status')
|
|
37
|
+
.description('Show Storacha authentication and configuration status')
|
|
38
|
+
.action(async () => {
|
|
39
|
+
try {
|
|
40
|
+
const client = getStorachaClient();
|
|
41
|
+
const status = await client.getStatus();
|
|
42
|
+
console.log('\nāļø Storacha Status\n');
|
|
43
|
+
console.log('ā'.repeat(60));
|
|
44
|
+
console.log('');
|
|
45
|
+
// Authentication status
|
|
46
|
+
console.log('š Authentication:');
|
|
47
|
+
if (status.authenticated) {
|
|
48
|
+
console.log(` Status: ā
Authenticated`);
|
|
49
|
+
if (status.email) {
|
|
50
|
+
console.log(` Email: ${status.email}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
console.log(` Status: ā Not authenticated`);
|
|
55
|
+
console.log('');
|
|
56
|
+
console.log('š” To authenticate:');
|
|
57
|
+
console.log(' lsh storacha login [email protected]');
|
|
58
|
+
}
|
|
59
|
+
console.log('');
|
|
60
|
+
// Network sync status
|
|
61
|
+
console.log('š Network Sync:');
|
|
62
|
+
console.log(` Enabled: ${status.enabled ? 'ā
Yes' : 'ā No'}`);
|
|
63
|
+
if (!status.enabled) {
|
|
64
|
+
console.log('');
|
|
65
|
+
console.log('š” To enable:');
|
|
66
|
+
console.log(' export LSH_STORACHA_ENABLED=true');
|
|
67
|
+
console.log(' # Add to ~/.bashrc or ~/.zshrc for persistence');
|
|
68
|
+
}
|
|
69
|
+
console.log('');
|
|
70
|
+
// Spaces status
|
|
71
|
+
if (status.authenticated) {
|
|
72
|
+
console.log('š¦ Spaces:');
|
|
73
|
+
if (status.spaces.length === 0) {
|
|
74
|
+
console.log(' No spaces found');
|
|
75
|
+
console.log('');
|
|
76
|
+
console.log('š” Create a space:');
|
|
77
|
+
console.log(' lsh storacha space create my-space');
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
console.log(` Total: ${status.spaces.length}`);
|
|
81
|
+
if (status.currentSpace) {
|
|
82
|
+
console.log(` Current: ${status.currentSpace}`);
|
|
83
|
+
}
|
|
84
|
+
console.log('');
|
|
85
|
+
console.log(' Available spaces:');
|
|
86
|
+
status.spaces.forEach(space => {
|
|
87
|
+
const marker = space.name === status.currentSpace ? 'ā' : ' ';
|
|
88
|
+
console.log(` ${marker} ${space.name}`);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
console.log('');
|
|
92
|
+
}
|
|
93
|
+
// Quick actions
|
|
94
|
+
console.log('š” Quick Actions:');
|
|
95
|
+
if (!status.authenticated) {
|
|
96
|
+
console.log(' lsh storacha login [email protected]');
|
|
97
|
+
}
|
|
98
|
+
else if (!status.enabled) {
|
|
99
|
+
console.log(' export LSH_STORACHA_ENABLED=true');
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
console.log(' lsh push # Will sync to Storacha network');
|
|
103
|
+
console.log(' lsh pull # Will download from Storacha if needed');
|
|
104
|
+
}
|
|
105
|
+
console.log('');
|
|
106
|
+
console.log('ā'.repeat(60));
|
|
107
|
+
console.log('');
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
const err = error;
|
|
111
|
+
console.error('ā Failed to get status:', err.message);
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
// Space commands
|
|
116
|
+
const space = storacha
|
|
117
|
+
.command('space')
|
|
118
|
+
.description('Manage Storacha spaces');
|
|
119
|
+
space
|
|
120
|
+
.command('create <name>')
|
|
121
|
+
.description('Create a new space')
|
|
122
|
+
.action(async (name) => {
|
|
123
|
+
try {
|
|
124
|
+
const client = getStorachaClient();
|
|
125
|
+
const status = await client.getStatus();
|
|
126
|
+
if (!status.authenticated) {
|
|
127
|
+
console.error('ā Not authenticated');
|
|
128
|
+
console.error('');
|
|
129
|
+
console.error('š” First, authenticate:');
|
|
130
|
+
console.error(' lsh storacha login [email protected]');
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
console.log(`\nš Creating space: ${name}...\n`);
|
|
134
|
+
await client.createSpace(name);
|
|
135
|
+
console.log('');
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
const err = error;
|
|
139
|
+
console.error('\nā Failed to create space:', err.message);
|
|
140
|
+
process.exit(1);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
space
|
|
144
|
+
.command('auto')
|
|
145
|
+
.description('Auto-select space based on current project (git repo or directory name)')
|
|
146
|
+
.action(async () => {
|
|
147
|
+
try {
|
|
148
|
+
const client = getStorachaClient();
|
|
149
|
+
const status = await client.getStatus();
|
|
150
|
+
if (!status.authenticated) {
|
|
151
|
+
console.error('ā Not authenticated');
|
|
152
|
+
console.error('');
|
|
153
|
+
console.error('š” First, authenticate:');
|
|
154
|
+
console.error(' lsh storacha login [email protected]');
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
const projectName = client.getProjectName();
|
|
158
|
+
console.log(`\nš Detected project: ${projectName}\n`);
|
|
159
|
+
const spaceName = await client.ensureProjectSpace();
|
|
160
|
+
console.log(`ā
Active space: ${spaceName}\n`);
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
const err = error;
|
|
164
|
+
console.error('\nā Failed to auto-select space:', err.message);
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
space
|
|
169
|
+
.command('use <name>')
|
|
170
|
+
.description('Switch to a specific space')
|
|
171
|
+
.action(async (name) => {
|
|
172
|
+
try {
|
|
173
|
+
const client = getStorachaClient();
|
|
174
|
+
const status = await client.getStatus();
|
|
175
|
+
if (!status.authenticated) {
|
|
176
|
+
console.error('ā Not authenticated');
|
|
177
|
+
console.error('');
|
|
178
|
+
console.error('š” First, authenticate:');
|
|
179
|
+
console.error(' lsh storacha login [email protected]');
|
|
180
|
+
process.exit(1);
|
|
181
|
+
}
|
|
182
|
+
const found = await client.selectSpace(name);
|
|
183
|
+
if (found) {
|
|
184
|
+
console.log(`\nā
Switched to space: ${name}\n`);
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
console.error(`\nā Space not found: ${name}`);
|
|
188
|
+
console.error('');
|
|
189
|
+
console.error('š” To list available spaces:');
|
|
190
|
+
console.error(' lsh storacha space list');
|
|
191
|
+
console.error('');
|
|
192
|
+
console.error('š” To create a new space:');
|
|
193
|
+
console.error(` lsh storacha space create ${name}`);
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
const err = error;
|
|
199
|
+
console.error('\nā Failed to switch space:', err.message);
|
|
200
|
+
process.exit(1);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
space
|
|
204
|
+
.command('list')
|
|
205
|
+
.description('List all spaces')
|
|
206
|
+
.action(async () => {
|
|
207
|
+
try {
|
|
208
|
+
const client = getStorachaClient();
|
|
209
|
+
const status = await client.getStatus();
|
|
210
|
+
if (!status.authenticated) {
|
|
211
|
+
console.error('ā Not authenticated');
|
|
212
|
+
console.error('');
|
|
213
|
+
console.error('š” First, authenticate:');
|
|
214
|
+
console.error(' lsh storacha login [email protected]');
|
|
215
|
+
process.exit(1);
|
|
216
|
+
}
|
|
217
|
+
console.log('\nš¦ Storacha Spaces\n');
|
|
218
|
+
console.log('ā'.repeat(60));
|
|
219
|
+
console.log('');
|
|
220
|
+
if (status.spaces.length === 0) {
|
|
221
|
+
console.log('No spaces found');
|
|
222
|
+
console.log('');
|
|
223
|
+
console.log('š” Create a space:');
|
|
224
|
+
console.log(' lsh storacha space create my-space');
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
status.spaces.forEach((space, index) => {
|
|
228
|
+
const marker = space.name === status.currentSpace ? 'ā' : ' ';
|
|
229
|
+
console.log(`${marker} ${index + 1}. ${space.name}`);
|
|
230
|
+
console.log(` DID: ${space.did}`);
|
|
231
|
+
console.log(` Registered: ${space.registered}`);
|
|
232
|
+
console.log('');
|
|
233
|
+
});
|
|
234
|
+
if (status.currentSpace) {
|
|
235
|
+
console.log(`Current space: ${status.currentSpace}`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
console.log('ā'.repeat(60));
|
|
239
|
+
console.log('');
|
|
240
|
+
}
|
|
241
|
+
catch (error) {
|
|
242
|
+
const err = error;
|
|
243
|
+
console.error('ā Failed to list spaces:', err.message);
|
|
244
|
+
process.exit(1);
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
// Enable/disable commands
|
|
248
|
+
storacha
|
|
249
|
+
.command('enable')
|
|
250
|
+
.description('Enable Storacha network sync')
|
|
251
|
+
.action(() => {
|
|
252
|
+
const client = getStorachaClient();
|
|
253
|
+
client.enable();
|
|
254
|
+
console.log('');
|
|
255
|
+
console.log('š” For persistence, add to your shell profile:');
|
|
256
|
+
console.log(' echo "export LSH_STORACHA_ENABLED=true" >> ~/.bashrc');
|
|
257
|
+
console.log(' # or ~/.zshrc for zsh');
|
|
258
|
+
console.log('');
|
|
259
|
+
});
|
|
260
|
+
storacha
|
|
261
|
+
.command('disable')
|
|
262
|
+
.description('Disable Storacha network sync (local cache only)')
|
|
263
|
+
.action(() => {
|
|
264
|
+
const client = getStorachaClient();
|
|
265
|
+
client.disable();
|
|
266
|
+
console.log('');
|
|
267
|
+
});
|
|
268
|
+
}
|
package/dist/constants/config.js
CHANGED
|
@@ -34,6 +34,7 @@ export const ENV_VARS = {
|
|
|
34
34
|
LSH_LOCAL_STORAGE_QUIET: 'LSH_LOCAL_STORAGE_QUIET',
|
|
35
35
|
LSH_V1_COMPAT: 'LSH_V1_COMPAT',
|
|
36
36
|
DISABLE_IPFS_SYNC: 'DISABLE_IPFS_SYNC',
|
|
37
|
+
LSH_USE_OPTIMIZED_SCHEDULER: 'LSH_USE_OPTIMIZED_SCHEDULER',
|
|
37
38
|
// Logging
|
|
38
39
|
LSH_LOG_LEVEL: 'LSH_LOG_LEVEL',
|
|
39
40
|
LSH_LOG_FORMAT: 'LSH_LOG_FORMAT',
|
|
@@ -51,6 +52,13 @@ export const ENV_VARS = {
|
|
|
51
52
|
REDIS_URL: 'REDIS_URL',
|
|
52
53
|
// Monitoring
|
|
53
54
|
MONITORING_API_PORT: 'MONITORING_API_PORT',
|
|
55
|
+
// Metrics collection
|
|
56
|
+
LSH_METRICS_ENABLED: 'LSH_METRICS_ENABLED',
|
|
57
|
+
LSH_METRICS_INTERVAL: 'LSH_METRICS_INTERVAL',
|
|
58
|
+
LSH_METRICS_EXPORT_FORMAT: 'LSH_METRICS_EXPORT_FORMAT',
|
|
59
|
+
LSH_METRICS_RETENTION: 'LSH_METRICS_RETENTION',
|
|
60
|
+
LSH_PROFILING_ENABLED: 'LSH_PROFILING_ENABLED',
|
|
61
|
+
LSH_PROFILING_SAMPLE_RATE: 'LSH_PROFILING_SAMPLE_RATE',
|
|
54
62
|
// Stripe billing
|
|
55
63
|
STRIPE_SECRET_KEY: 'STRIPE_SECRET_KEY',
|
|
56
64
|
STRIPE_WEBHOOK_SECRET: 'STRIPE_WEBHOOK_SECRET',
|
|
@@ -87,6 +95,9 @@ export const DEFAULTS = {
|
|
|
87
95
|
DEFAULT_EMAIL_FROM: 'noreply@lsh.dev',
|
|
88
96
|
// Timeouts and intervals (in milliseconds)
|
|
89
97
|
CHECK_INTERVAL_MS: 2000,
|
|
98
|
+
SCHEDULER_MIN_CHECK_INTERVAL_MS: 100,
|
|
99
|
+
SCHEDULER_MAX_CHECK_INTERVAL_MS: 60000,
|
|
100
|
+
SCHEDULER_DUE_BUFFER_MS: 50,
|
|
90
101
|
REQUEST_TIMEOUT_MS: 10000,
|
|
91
102
|
DAEMON_RESTART_DELAY_MS: 1000,
|
|
92
103
|
JOB_TIMEOUT_1H_MS: 3600000,
|
|
@@ -115,6 +126,10 @@ export const DEFAULTS = {
|
|
|
115
126
|
MAX_RECORDS_PER_JOB: 1000,
|
|
116
127
|
MAX_TOTAL_RECORDS: 50000,
|
|
117
128
|
METRICS_RETENTION_DAYS: 90,
|
|
129
|
+
// Metrics collection defaults
|
|
130
|
+
METRICS_COLLECTION_INTERVAL_MS: 60000, // 1 minute
|
|
131
|
+
METRICS_EXPORT_FORMAT: 'prometheus',
|
|
132
|
+
PROFILING_SAMPLE_RATE: 0.1, // 10% sampling by default
|
|
118
133
|
// Shell defaults
|
|
119
134
|
DEFAULT_SHELL_UNIX: '/bin/sh',
|
|
120
135
|
DEFAULT_SHELL_WIN: 'cmd.exe',
|
package/dist/constants/errors.js
CHANGED
|
@@ -70,6 +70,17 @@ To fix this:
|
|
|
70
70
|
BASE64_COMMAND: 'Base64 encoded command detected',
|
|
71
71
|
DYNAMIC_EVAL: 'Dynamic command evaluation detected',
|
|
72
72
|
NULL_BYTE: 'Null byte injection detected',
|
|
73
|
+
// Warning-level security messages (command validator)
|
|
74
|
+
RECURSIVE_DELETE: 'Recursive deletion command',
|
|
75
|
+
SUDO_ELEVATED: 'Elevated privileges requested',
|
|
76
|
+
CHMOD_777: 'Overly permissive file permissions',
|
|
77
|
+
DISK_WRITE: 'Writing to disk device',
|
|
78
|
+
INSECURE_SSL: 'Insecure SSL certificate validation disabled',
|
|
79
|
+
FORK_BOMB: 'Fork bomb pattern detected',
|
|
80
|
+
EXCESSIVE_CHAINING: 'Excessive command chaining detected',
|
|
81
|
+
EXCESSIVE_PIPES: 'Excessive pipe usage detected',
|
|
82
|
+
NESTED_SUBSTITUTION: 'Nested command substitution detected',
|
|
83
|
+
CONTROL_CHARS: 'Control characters detected in command',
|
|
73
84
|
};
|
|
74
85
|
export const RISK_LEVELS = {
|
|
75
86
|
CRITICAL: 'critical',
|