chainlesschain 0.66.0 → 0.132.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/bin/chainlesschain.js +0 -0
- package/package.json +1 -1
- package/src/commands/a2a.js +380 -0
- package/src/commands/agent-network.js +254 -1
- package/src/commands/audit.js +302 -0
- package/src/commands/automation.js +271 -1
- package/src/commands/bi.js +348 -0
- package/src/commands/codegen.js +224 -0
- package/src/commands/collab.js +341 -0
- package/src/commands/compliance.js +1035 -0
- package/src/commands/cowork.js +221 -0
- package/src/commands/crosschain.js +218 -0
- package/src/commands/dbevo.js +284 -0
- package/src/commands/dev.js +252 -0
- package/src/commands/did.js +358 -0
- package/src/commands/dlp.js +341 -0
- package/src/commands/encrypt.js +341 -0
- package/src/commands/evomap.js +394 -0
- package/src/commands/export.js +256 -1
- package/src/commands/federation.js +283 -0
- package/src/commands/fusion.js +258 -0
- package/src/commands/governance.js +325 -0
- package/src/commands/hardening.js +411 -0
- package/src/commands/hook.js +148 -0
- package/src/commands/import.js +252 -0
- package/src/commands/incentive.js +322 -0
- package/src/commands/inference.js +318 -0
- package/src/commands/infra.js +244 -0
- package/src/commands/instinct.js +260 -0
- package/src/commands/ipfs.js +318 -0
- package/src/commands/kg.js +387 -0
- package/src/commands/llm.js +263 -0
- package/src/commands/lowcode.js +356 -0
- package/src/commands/marketplace.js +256 -0
- package/src/commands/mcp.js +221 -0
- package/src/commands/memory.js +248 -0
- package/src/commands/multimodal.js +296 -0
- package/src/commands/nlprog.js +356 -0
- package/src/commands/note.js +244 -0
- package/src/commands/ops.js +354 -0
- package/src/commands/orchestrate.js +166 -0
- package/src/commands/org.js +277 -0
- package/src/commands/p2p.js +390 -0
- package/src/commands/perception.js +290 -0
- package/src/commands/permmem.js +251 -0
- package/src/commands/plugin-ecosystem.js +273 -0
- package/src/commands/pqc.js +393 -0
- package/src/commands/privacy.js +321 -0
- package/src/commands/quantization.js +351 -0
- package/src/commands/rcache.js +271 -0
- package/src/commands/recommend.js +340 -0
- package/src/commands/reputation.js +261 -0
- package/src/commands/runtime.js +307 -0
- package/src/commands/scim.js +262 -0
- package/src/commands/session.js +258 -0
- package/src/commands/siem.js +246 -0
- package/src/commands/skill.js +267 -1
- package/src/commands/sla.js +259 -0
- package/src/commands/social.js +256 -0
- package/src/commands/sso.js +186 -1
- package/src/commands/stress.js +230 -0
- package/src/commands/sync.js +256 -0
- package/src/commands/tech.js +338 -0
- package/src/commands/tenant.js +351 -0
- package/src/commands/terraform.js +245 -0
- package/src/commands/tokens.js +269 -0
- package/src/commands/trust.js +249 -0
- package/src/commands/wallet.js +277 -0
- package/src/commands/workflow.js +171 -0
- package/src/commands/zkp.js +335 -0
- package/src/index.js +4 -0
- package/src/lib/a2a-protocol.js +451 -0
- package/src/lib/agent-coordinator.js +325 -0
- package/src/lib/agent-network.js +387 -0
- package/src/lib/agent-router.js +395 -0
- package/src/lib/aiops.js +478 -0
- package/src/lib/app-builder.js +239 -0
- package/src/lib/audit-logger.js +379 -0
- package/src/lib/automation-engine.js +330 -0
- package/src/lib/autonomous-developer.js +350 -0
- package/src/lib/bi-engine.js +338 -0
- package/src/lib/code-agent.js +323 -0
- package/src/lib/collaboration-governance.js +364 -0
- package/src/lib/community-governance.js +436 -0
- package/src/lib/compliance-manager.js +434 -0
- package/src/lib/content-recommendation.js +469 -0
- package/src/lib/cross-chain.js +345 -0
- package/src/lib/crypto-manager.js +350 -0
- package/src/lib/dbevo.js +338 -0
- package/src/lib/decentral-infra.js +340 -0
- package/src/lib/did-manager.js +367 -0
- package/src/lib/dlp-engine.js +389 -0
- package/src/lib/evomap-federation.js +177 -0
- package/src/lib/evomap-governance.js +276 -0
- package/src/lib/federation-hardening.js +259 -0
- package/src/lib/hardening-manager.js +348 -0
- package/src/lib/hook-manager.js +380 -0
- package/src/lib/inference-network.js +330 -0
- package/src/lib/instinct-manager.js +332 -0
- package/src/lib/ipfs-storage.js +334 -0
- package/src/lib/knowledge-exporter.js +381 -0
- package/src/lib/knowledge-graph.js +432 -0
- package/src/lib/knowledge-importer.js +379 -0
- package/src/lib/llm-providers.js +391 -0
- package/src/lib/mcp-registry.js +333 -0
- package/src/lib/memory-manager.js +330 -0
- package/src/lib/multimodal.js +346 -0
- package/src/lib/nl-programming.js +343 -0
- package/src/lib/note-versioning.js +327 -0
- package/src/lib/org-manager.js +323 -0
- package/src/lib/p2p-manager.js +387 -0
- package/src/lib/perception.js +346 -0
- package/src/lib/perf-tuning.js +4 -1
- package/src/lib/permanent-memory.js +320 -0
- package/src/lib/plugin-ecosystem.js +377 -0
- package/src/lib/pqc-manager.js +368 -0
- package/src/lib/privacy-computing.js +427 -0
- package/src/lib/protocol-fusion.js +417 -0
- package/src/lib/quantization.js +325 -0
- package/src/lib/reputation-optimizer.js +299 -0
- package/src/lib/response-cache.js +327 -0
- package/src/lib/scim-manager.js +329 -0
- package/src/lib/session-manager.js +329 -0
- package/src/lib/siem-exporter.js +333 -0
- package/src/lib/skill-loader.js +377 -0
- package/src/lib/skill-marketplace.js +325 -0
- package/src/lib/sla-manager.js +275 -0
- package/src/lib/social-manager.js +326 -0
- package/src/lib/sso-manager.js +332 -0
- package/src/lib/stress-tester.js +330 -0
- package/src/lib/sync-manager.js +326 -0
- package/src/lib/tech-learning-engine.js +369 -0
- package/src/lib/tenant-saas.js +460 -0
- package/src/lib/terraform-manager.js +363 -0
- package/src/lib/threat-intel.js +335 -0
- package/src/lib/token-incentive.js +293 -0
- package/src/lib/token-tracker.js +329 -0
- package/src/lib/trust-security.js +390 -0
- package/src/lib/ueba.js +389 -0
- package/src/lib/universal-runtime.js +325 -0
- package/src/lib/wallet-manager.js +326 -0
- package/src/lib/workflow-engine.js +322 -0
- package/src/lib/zkp-engine.js +274 -0
package/src/commands/dlp.js
CHANGED
|
@@ -16,6 +16,20 @@ import {
|
|
|
16
16
|
updatePolicy,
|
|
17
17
|
deletePolicy,
|
|
18
18
|
listDLPPolicies,
|
|
19
|
+
DLP_ACTION,
|
|
20
|
+
DLP_CHANNEL,
|
|
21
|
+
DLP_SEVERITY,
|
|
22
|
+
DLP_DEFAULT_MAX_CONTENT_SIZE,
|
|
23
|
+
createPolicyV2,
|
|
24
|
+
getPolicyV2,
|
|
25
|
+
listActivePoliciesForChannel,
|
|
26
|
+
scanContentV2,
|
|
27
|
+
listIncidentsV2,
|
|
28
|
+
getIncidentV2,
|
|
29
|
+
listBuiltinPolicyTemplates,
|
|
30
|
+
installBuiltinPolicies,
|
|
31
|
+
getDLPStatsV2,
|
|
32
|
+
getHighestUnresolvedSeverity,
|
|
19
33
|
} from "../lib/dlp-engine.js";
|
|
20
34
|
|
|
21
35
|
export function registerDlpCommand(program) {
|
|
@@ -269,6 +283,333 @@ export function registerDlpCommand(program) {
|
|
|
269
283
|
deletePolicy(db, policyId);
|
|
270
284
|
logger.success(`Policy ${chalk.cyan(policyId.slice(0, 8))} deleted`);
|
|
271
285
|
|
|
286
|
+
await shutdown();
|
|
287
|
+
} catch (err) {
|
|
288
|
+
logger.error(`Failed: ${err.message}`);
|
|
289
|
+
process.exit(1);
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
// ═══════════════════════════════════════════════════════════════
|
|
294
|
+
// V2 Canonical Subcommands (Phase 50)
|
|
295
|
+
// ═══════════════════════════════════════════════════════════════
|
|
296
|
+
|
|
297
|
+
dlp
|
|
298
|
+
.command("actions")
|
|
299
|
+
.description("List DLP actions (V2)")
|
|
300
|
+
.action(() => {
|
|
301
|
+
console.log(JSON.stringify(Object.values(DLP_ACTION), null, 2));
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
dlp
|
|
305
|
+
.command("channels")
|
|
306
|
+
.description("List DLP channels (V2)")
|
|
307
|
+
.action(() => {
|
|
308
|
+
console.log(JSON.stringify(Object.values(DLP_CHANNEL), null, 2));
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
dlp
|
|
312
|
+
.command("severities")
|
|
313
|
+
.description("List DLP severity levels (V2)")
|
|
314
|
+
.action(() => {
|
|
315
|
+
console.log(JSON.stringify(Object.values(DLP_SEVERITY), null, 2));
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
dlp
|
|
319
|
+
.command("default-max-size")
|
|
320
|
+
.description("Show default DLP scan size limit in bytes (V2)")
|
|
321
|
+
.action(() => {
|
|
322
|
+
console.log(JSON.stringify({ bytes: DLP_DEFAULT_MAX_CONTENT_SIZE }));
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
// policy-v2 create — channel-aware + description
|
|
326
|
+
policy
|
|
327
|
+
.command("create-v2 <name>")
|
|
328
|
+
.description("Create a V2 policy with channel filter + description")
|
|
329
|
+
.option("-d, --description <text>", "Description", "")
|
|
330
|
+
.option(
|
|
331
|
+
"-c, --channels <list>",
|
|
332
|
+
"Comma-separated channels (empty = all)",
|
|
333
|
+
"",
|
|
334
|
+
)
|
|
335
|
+
.option("-p, --patterns <list>", "Comma-separated regex patterns", "")
|
|
336
|
+
.option("-k, --keywords <list>", "Comma-separated keywords", "")
|
|
337
|
+
.option("-a, --action <action>", "Action", "alert")
|
|
338
|
+
.option("-s, --severity <level>", "Severity", "medium")
|
|
339
|
+
.action(async (name, options) => {
|
|
340
|
+
try {
|
|
341
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
342
|
+
if (!ctx.db) {
|
|
343
|
+
logger.error("Database not available");
|
|
344
|
+
process.exit(1);
|
|
345
|
+
}
|
|
346
|
+
const db = ctx.db.getDatabase();
|
|
347
|
+
ensureDLPTables(db);
|
|
348
|
+
|
|
349
|
+
const result = createPolicyV2(db, {
|
|
350
|
+
name,
|
|
351
|
+
description: options.description,
|
|
352
|
+
channels: options.channels
|
|
353
|
+
? options.channels
|
|
354
|
+
.split(",")
|
|
355
|
+
.map((s) => s.trim())
|
|
356
|
+
.filter(Boolean)
|
|
357
|
+
: [],
|
|
358
|
+
patterns: options.patterns
|
|
359
|
+
? options.patterns
|
|
360
|
+
.split(",")
|
|
361
|
+
.map((s) => s.trim())
|
|
362
|
+
.filter(Boolean)
|
|
363
|
+
: [],
|
|
364
|
+
keywords: options.keywords
|
|
365
|
+
? options.keywords
|
|
366
|
+
.split(",")
|
|
367
|
+
.map((s) => s.trim())
|
|
368
|
+
.filter(Boolean)
|
|
369
|
+
: [],
|
|
370
|
+
action: options.action,
|
|
371
|
+
severity: options.severity,
|
|
372
|
+
});
|
|
373
|
+
console.log(JSON.stringify(result, null, 2));
|
|
374
|
+
|
|
375
|
+
await shutdown();
|
|
376
|
+
} catch (err) {
|
|
377
|
+
logger.error(`Failed: ${err.message}`);
|
|
378
|
+
process.exit(1);
|
|
379
|
+
}
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
policy
|
|
383
|
+
.command("show-v2 <policy-id>")
|
|
384
|
+
.description("Show V2 policy with description + channels")
|
|
385
|
+
.action(async (policyId) => {
|
|
386
|
+
try {
|
|
387
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
388
|
+
if (!ctx.db) {
|
|
389
|
+
logger.error("Database not available");
|
|
390
|
+
process.exit(1);
|
|
391
|
+
}
|
|
392
|
+
const db = ctx.db.getDatabase();
|
|
393
|
+
ensureDLPTables(db);
|
|
394
|
+
|
|
395
|
+
console.log(JSON.stringify(getPolicyV2(policyId), null, 2));
|
|
396
|
+
|
|
397
|
+
await shutdown();
|
|
398
|
+
} catch (err) {
|
|
399
|
+
logger.error(`Failed: ${err.message}`);
|
|
400
|
+
process.exit(1);
|
|
401
|
+
}
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
policy
|
|
405
|
+
.command("active-for <channel>")
|
|
406
|
+
.description("List active V2 policies applicable to a channel")
|
|
407
|
+
.action(async (channel) => {
|
|
408
|
+
try {
|
|
409
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
410
|
+
if (!ctx.db) {
|
|
411
|
+
logger.error("Database not available");
|
|
412
|
+
process.exit(1);
|
|
413
|
+
}
|
|
414
|
+
const db = ctx.db.getDatabase();
|
|
415
|
+
ensureDLPTables(db);
|
|
416
|
+
|
|
417
|
+
console.log(
|
|
418
|
+
JSON.stringify(listActivePoliciesForChannel(channel), null, 2),
|
|
419
|
+
);
|
|
420
|
+
|
|
421
|
+
await shutdown();
|
|
422
|
+
} catch (err) {
|
|
423
|
+
logger.error(`Failed: ${err.message}`);
|
|
424
|
+
process.exit(1);
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
// Built-in templates
|
|
429
|
+
const templates = dlp
|
|
430
|
+
.command("templates")
|
|
431
|
+
.description("Built-in policy templates");
|
|
432
|
+
|
|
433
|
+
templates
|
|
434
|
+
.command("list")
|
|
435
|
+
.description("List built-in policy templates")
|
|
436
|
+
.action(() => {
|
|
437
|
+
console.log(JSON.stringify(listBuiltinPolicyTemplates(), null, 2));
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
templates
|
|
441
|
+
.command("install [names...]")
|
|
442
|
+
.description("Install built-in policy templates (all if no names given)")
|
|
443
|
+
.action(async (names) => {
|
|
444
|
+
try {
|
|
445
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
446
|
+
if (!ctx.db) {
|
|
447
|
+
logger.error("Database not available");
|
|
448
|
+
process.exit(1);
|
|
449
|
+
}
|
|
450
|
+
const db = ctx.db.getDatabase();
|
|
451
|
+
ensureDLPTables(db);
|
|
452
|
+
|
|
453
|
+
const installed = installBuiltinPolicies(
|
|
454
|
+
db,
|
|
455
|
+
names && names.length > 0 ? names : undefined,
|
|
456
|
+
);
|
|
457
|
+
console.log(JSON.stringify(installed, null, 2));
|
|
458
|
+
|
|
459
|
+
await shutdown();
|
|
460
|
+
} catch (err) {
|
|
461
|
+
logger.error(`Failed: ${err.message}`);
|
|
462
|
+
process.exit(1);
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
// scan-v2 — channel filter + size gate + metadata
|
|
467
|
+
dlp
|
|
468
|
+
.command("scan-v2 <content>")
|
|
469
|
+
.description("Scan content with V2 channel filter + metadata")
|
|
470
|
+
.option("-c, --channel <channel>", "Channel")
|
|
471
|
+
.option("-u, --user <id>", "User ID")
|
|
472
|
+
.option("-m, --metadata <json>", "Metadata JSON", "{}")
|
|
473
|
+
.option("--max-size <bytes>", "Override max content size")
|
|
474
|
+
.action(async (content, options) => {
|
|
475
|
+
try {
|
|
476
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
477
|
+
if (!ctx.db) {
|
|
478
|
+
logger.error("Database not available");
|
|
479
|
+
process.exit(1);
|
|
480
|
+
}
|
|
481
|
+
const db = ctx.db.getDatabase();
|
|
482
|
+
ensureDLPTables(db);
|
|
483
|
+
|
|
484
|
+
let metadata = {};
|
|
485
|
+
try {
|
|
486
|
+
metadata = JSON.parse(options.metadata);
|
|
487
|
+
} catch (_err) {
|
|
488
|
+
logger.error("Invalid --metadata JSON");
|
|
489
|
+
process.exit(1);
|
|
490
|
+
}
|
|
491
|
+
const result = scanContentV2(db, {
|
|
492
|
+
content,
|
|
493
|
+
channel: options.channel,
|
|
494
|
+
userId: options.user,
|
|
495
|
+
metadata,
|
|
496
|
+
maxContentSize: options.maxSize ? Number(options.maxSize) : undefined,
|
|
497
|
+
});
|
|
498
|
+
console.log(JSON.stringify(result, null, 2));
|
|
499
|
+
|
|
500
|
+
await shutdown();
|
|
501
|
+
} catch (err) {
|
|
502
|
+
logger.error(`Failed: ${err.message}`);
|
|
503
|
+
process.exit(1);
|
|
504
|
+
}
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
// incidents-v2 — rich filter
|
|
508
|
+
dlp
|
|
509
|
+
.command("incidents-v2")
|
|
510
|
+
.description(
|
|
511
|
+
"List V2 incidents (channel/severity/resolved/user/policy/date)",
|
|
512
|
+
)
|
|
513
|
+
.option("-c, --channel <channel>", "Filter by channel")
|
|
514
|
+
.option("-s, --severity <level>", "Filter by severity")
|
|
515
|
+
.option("-r, --resolved <bool>", "Filter by resolved (true/false)")
|
|
516
|
+
.option("-u, --user <id>", "Filter by userId")
|
|
517
|
+
.option("-p, --policy <id>", "Filter by policyId")
|
|
518
|
+
.option("--from <iso>", "fromDate ISO string")
|
|
519
|
+
.option("--to <iso>", "toDate ISO string")
|
|
520
|
+
.option("-l, --limit <n>", "Limit", "50")
|
|
521
|
+
.action(async (options) => {
|
|
522
|
+
try {
|
|
523
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
524
|
+
if (!ctx.db) {
|
|
525
|
+
logger.error("Database not available");
|
|
526
|
+
process.exit(1);
|
|
527
|
+
}
|
|
528
|
+
const db = ctx.db.getDatabase();
|
|
529
|
+
ensureDLPTables(db);
|
|
530
|
+
|
|
531
|
+
const filter = {};
|
|
532
|
+
if (options.channel) filter.channel = options.channel;
|
|
533
|
+
if (options.severity) filter.severity = options.severity;
|
|
534
|
+
if (options.resolved === "true") filter.resolved = true;
|
|
535
|
+
else if (options.resolved === "false") filter.resolved = false;
|
|
536
|
+
if (options.user) filter.userId = options.user;
|
|
537
|
+
if (options.policy) filter.policyId = options.policy;
|
|
538
|
+
if (options.from) filter.fromDate = options.from;
|
|
539
|
+
if (options.to) filter.toDate = options.to;
|
|
540
|
+
filter.limit = Number(options.limit);
|
|
541
|
+
console.log(JSON.stringify(listIncidentsV2(filter), null, 2));
|
|
542
|
+
|
|
543
|
+
await shutdown();
|
|
544
|
+
} catch (err) {
|
|
545
|
+
logger.error(`Failed: ${err.message}`);
|
|
546
|
+
process.exit(1);
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
dlp
|
|
551
|
+
.command("incident-v2 <incident-id>")
|
|
552
|
+
.description("Show V2 incident with metadata")
|
|
553
|
+
.action(async (incidentId) => {
|
|
554
|
+
try {
|
|
555
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
556
|
+
if (!ctx.db) {
|
|
557
|
+
logger.error("Database not available");
|
|
558
|
+
process.exit(1);
|
|
559
|
+
}
|
|
560
|
+
const db = ctx.db.getDatabase();
|
|
561
|
+
ensureDLPTables(db);
|
|
562
|
+
|
|
563
|
+
console.log(JSON.stringify(getIncidentV2(incidentId), null, 2));
|
|
564
|
+
|
|
565
|
+
await shutdown();
|
|
566
|
+
} catch (err) {
|
|
567
|
+
logger.error(`Failed: ${err.message}`);
|
|
568
|
+
process.exit(1);
|
|
569
|
+
}
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
dlp
|
|
573
|
+
.command("stats-v2")
|
|
574
|
+
.description(
|
|
575
|
+
"Show V2 DLP stats (byAction/bySeverity/byChannel/topPolicies)",
|
|
576
|
+
)
|
|
577
|
+
.action(async () => {
|
|
578
|
+
try {
|
|
579
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
580
|
+
if (!ctx.db) {
|
|
581
|
+
logger.error("Database not available");
|
|
582
|
+
process.exit(1);
|
|
583
|
+
}
|
|
584
|
+
const db = ctx.db.getDatabase();
|
|
585
|
+
ensureDLPTables(db);
|
|
586
|
+
|
|
587
|
+
console.log(JSON.stringify(getDLPStatsV2(), null, 2));
|
|
588
|
+
|
|
589
|
+
await shutdown();
|
|
590
|
+
} catch (err) {
|
|
591
|
+
logger.error(`Failed: ${err.message}`);
|
|
592
|
+
process.exit(1);
|
|
593
|
+
}
|
|
594
|
+
});
|
|
595
|
+
|
|
596
|
+
dlp
|
|
597
|
+
.command("highest-severity")
|
|
598
|
+
.description("Show highest unresolved incident severity (V2)")
|
|
599
|
+
.action(async () => {
|
|
600
|
+
try {
|
|
601
|
+
const ctx = await bootstrap({ verbose: program.opts().verbose });
|
|
602
|
+
if (!ctx.db) {
|
|
603
|
+
logger.error("Database not available");
|
|
604
|
+
process.exit(1);
|
|
605
|
+
}
|
|
606
|
+
const db = ctx.db.getDatabase();
|
|
607
|
+
ensureDLPTables(db);
|
|
608
|
+
|
|
609
|
+
console.log(
|
|
610
|
+
JSON.stringify({ highestSeverity: getHighestUnresolvedSeverity() }),
|
|
611
|
+
);
|
|
612
|
+
|
|
272
613
|
await shutdown();
|
|
273
614
|
} catch (err) {
|
|
274
615
|
logger.error(`Failed: ${err.message}`);
|
package/src/commands/encrypt.js
CHANGED
|
@@ -14,6 +14,35 @@ import {
|
|
|
14
14
|
getDbEncryptionStatus,
|
|
15
15
|
setDbEncryptionStatus,
|
|
16
16
|
hashPassword,
|
|
17
|
+
KEY_MATURITY_V2 as CRYPTO_KEY_MATURITY_V2,
|
|
18
|
+
CRYPTO_JOB_LIFECYCLE_V2,
|
|
19
|
+
getMaxActiveKeysPerOwnerV2 as cryptoGetMaxActiveKeys,
|
|
20
|
+
setMaxActiveKeysPerOwnerV2 as cryptoSetMaxActiveKeys,
|
|
21
|
+
getMaxPendingJobsPerKeyV2 as cryptoGetMaxPendingJobs,
|
|
22
|
+
setMaxPendingJobsPerKeyV2 as cryptoSetMaxPendingJobs,
|
|
23
|
+
getKeyIdleMsV2 as cryptoGetKeyIdleMs,
|
|
24
|
+
setKeyIdleMsV2 as cryptoSetKeyIdleMs,
|
|
25
|
+
getJobStuckMsV2,
|
|
26
|
+
setJobStuckMsV2,
|
|
27
|
+
registerKeyV2 as cryptoRegisterKey,
|
|
28
|
+
getKeyV2 as cryptoGetKey,
|
|
29
|
+
listKeysV2 as cryptoListKeys,
|
|
30
|
+
activateKeyV2 as cryptoActivateKey,
|
|
31
|
+
rotateKeyV2,
|
|
32
|
+
retireKeyV2,
|
|
33
|
+
touchKeyV2 as cryptoTouchKey,
|
|
34
|
+
createJobV2,
|
|
35
|
+
getJobV2,
|
|
36
|
+
listJobsV2,
|
|
37
|
+
startJobV2,
|
|
38
|
+
completeJobV2,
|
|
39
|
+
failJobV2,
|
|
40
|
+
cancelJobV2,
|
|
41
|
+
getActiveKeyCountV2 as cryptoGetActiveKeyCount,
|
|
42
|
+
getPendingJobCountV2,
|
|
43
|
+
autoRotateIdleKeysV2,
|
|
44
|
+
autoFailStuckJobsV2,
|
|
45
|
+
getCryptoManagerStatsV2,
|
|
17
46
|
} from "../lib/crypto-manager.js";
|
|
18
47
|
|
|
19
48
|
async function promptPassword(message = "Password:") {
|
|
@@ -230,4 +259,316 @@ export function registerEncryptCommand(program) {
|
|
|
230
259
|
process.exit(1);
|
|
231
260
|
}
|
|
232
261
|
});
|
|
262
|
+
|
|
263
|
+
// ===== V2 in-memory governance surface (no DB, no bootstrap) =====
|
|
264
|
+
|
|
265
|
+
enc
|
|
266
|
+
.command("key-maturities-v2")
|
|
267
|
+
.description("[V2] List crypto key maturity states")
|
|
268
|
+
.option("--json")
|
|
269
|
+
.action((o) => {
|
|
270
|
+
const s = Object.values(CRYPTO_KEY_MATURITY_V2);
|
|
271
|
+
if (o.json) console.log(JSON.stringify(s, null, 2));
|
|
272
|
+
else for (const v of s) logger.log(v);
|
|
273
|
+
});
|
|
274
|
+
enc
|
|
275
|
+
.command("job-lifecycles-v2")
|
|
276
|
+
.description("[V2] List crypto job lifecycle states")
|
|
277
|
+
.option("--json")
|
|
278
|
+
.action((o) => {
|
|
279
|
+
const s = Object.values(CRYPTO_JOB_LIFECYCLE_V2);
|
|
280
|
+
if (o.json) console.log(JSON.stringify(s, null, 2));
|
|
281
|
+
else for (const v of s) logger.log(v);
|
|
282
|
+
});
|
|
283
|
+
enc
|
|
284
|
+
.command("config-v2")
|
|
285
|
+
.description("[V2] Show governance config")
|
|
286
|
+
.option("--json")
|
|
287
|
+
.action((o) => {
|
|
288
|
+
const cfg = {
|
|
289
|
+
maxActiveKeysPerOwner: cryptoGetMaxActiveKeys(),
|
|
290
|
+
maxPendingJobsPerKey: cryptoGetMaxPendingJobs(),
|
|
291
|
+
keyIdleMs: cryptoGetKeyIdleMs(),
|
|
292
|
+
jobStuckMs: getJobStuckMsV2(),
|
|
293
|
+
};
|
|
294
|
+
if (o.json) console.log(JSON.stringify(cfg, null, 2));
|
|
295
|
+
else for (const [k, v] of Object.entries(cfg)) logger.log(`${k}: ${v}`);
|
|
296
|
+
});
|
|
297
|
+
enc
|
|
298
|
+
.command("set-max-active-keys-per-owner-v2 <n>")
|
|
299
|
+
.description("[V2] Set per-owner active key cap")
|
|
300
|
+
.action((n) => {
|
|
301
|
+
try {
|
|
302
|
+
cryptoSetMaxActiveKeys(Number(n));
|
|
303
|
+
logger.success(`= ${cryptoGetMaxActiveKeys()}`);
|
|
304
|
+
} catch (e) {
|
|
305
|
+
logger.error(e.message);
|
|
306
|
+
process.exit(1);
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
enc
|
|
310
|
+
.command("set-max-pending-jobs-per-key-v2 <n>")
|
|
311
|
+
.description("[V2] Set per-key pending job cap")
|
|
312
|
+
.action((n) => {
|
|
313
|
+
try {
|
|
314
|
+
cryptoSetMaxPendingJobs(Number(n));
|
|
315
|
+
logger.success(`= ${cryptoGetMaxPendingJobs()}`);
|
|
316
|
+
} catch (e) {
|
|
317
|
+
logger.error(e.message);
|
|
318
|
+
process.exit(1);
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
enc
|
|
322
|
+
.command("set-key-idle-ms-v2 <ms>")
|
|
323
|
+
.description("[V2] Set key idle threshold (ms)")
|
|
324
|
+
.action((m) => {
|
|
325
|
+
try {
|
|
326
|
+
cryptoSetKeyIdleMs(Number(m));
|
|
327
|
+
logger.success(`= ${cryptoGetKeyIdleMs()}`);
|
|
328
|
+
} catch (e) {
|
|
329
|
+
logger.error(e.message);
|
|
330
|
+
process.exit(1);
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
enc
|
|
334
|
+
.command("set-job-stuck-ms-v2 <ms>")
|
|
335
|
+
.description("[V2] Set job stuck threshold (ms)")
|
|
336
|
+
.action((m) => {
|
|
337
|
+
try {
|
|
338
|
+
setJobStuckMsV2(Number(m));
|
|
339
|
+
logger.success(`= ${getJobStuckMsV2()}`);
|
|
340
|
+
} catch (e) {
|
|
341
|
+
logger.error(e.message);
|
|
342
|
+
process.exit(1);
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
enc
|
|
347
|
+
.command("register-key-v2 <id>")
|
|
348
|
+
.description("[V2] Register a crypto key profile (PENDING)")
|
|
349
|
+
.requiredOption("-o, --owner <id>")
|
|
350
|
+
.requiredOption("-a, --algorithm <algo>")
|
|
351
|
+
.option("-p, --purpose <p>", "Purpose", "encryption")
|
|
352
|
+
.action((id, o) => {
|
|
353
|
+
try {
|
|
354
|
+
const k = cryptoRegisterKey(id, {
|
|
355
|
+
ownerId: o.owner,
|
|
356
|
+
algorithm: o.algorithm,
|
|
357
|
+
purpose: o.purpose,
|
|
358
|
+
});
|
|
359
|
+
logger.success(`key ${k.id} registered (status=${k.status})`);
|
|
360
|
+
} catch (e) {
|
|
361
|
+
logger.error(e.message);
|
|
362
|
+
process.exit(1);
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
enc
|
|
366
|
+
.command("activate-key-v2 <id>")
|
|
367
|
+
.description("[V2] Activate key (pending|rotated -> active)")
|
|
368
|
+
.action((id) => {
|
|
369
|
+
try {
|
|
370
|
+
cryptoActivateKey(id);
|
|
371
|
+
logger.success(`key ${id} active`);
|
|
372
|
+
} catch (e) {
|
|
373
|
+
logger.error(e.message);
|
|
374
|
+
process.exit(1);
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
enc
|
|
378
|
+
.command("rotate-key-v2 <id>")
|
|
379
|
+
.description("[V2] Rotate key (active -> rotated)")
|
|
380
|
+
.action((id) => {
|
|
381
|
+
try {
|
|
382
|
+
rotateKeyV2(id);
|
|
383
|
+
logger.success(`key ${id} rotated`);
|
|
384
|
+
} catch (e) {
|
|
385
|
+
logger.error(e.message);
|
|
386
|
+
process.exit(1);
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
enc
|
|
390
|
+
.command("retire-key-v2 <id>")
|
|
391
|
+
.description("[V2] Retire key (terminal)")
|
|
392
|
+
.action((id) => {
|
|
393
|
+
try {
|
|
394
|
+
retireKeyV2(id);
|
|
395
|
+
logger.success(`key ${id} retired`);
|
|
396
|
+
} catch (e) {
|
|
397
|
+
logger.error(e.message);
|
|
398
|
+
process.exit(1);
|
|
399
|
+
}
|
|
400
|
+
});
|
|
401
|
+
enc
|
|
402
|
+
.command("touch-key-v2 <id>")
|
|
403
|
+
.description("[V2] Bump key lastSeenAt")
|
|
404
|
+
.action((id) => {
|
|
405
|
+
try {
|
|
406
|
+
cryptoTouchKey(id);
|
|
407
|
+
logger.success(`key ${id} touched`);
|
|
408
|
+
} catch (e) {
|
|
409
|
+
logger.error(e.message);
|
|
410
|
+
process.exit(1);
|
|
411
|
+
}
|
|
412
|
+
});
|
|
413
|
+
enc
|
|
414
|
+
.command("get-key-v2 <id>")
|
|
415
|
+
.description("[V2] Show crypto key profile")
|
|
416
|
+
.option("--json")
|
|
417
|
+
.action((id) => {
|
|
418
|
+
const k = cryptoGetKey(id);
|
|
419
|
+
if (!k) {
|
|
420
|
+
logger.info("key not found");
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
console.log(JSON.stringify(k, null, 2));
|
|
424
|
+
});
|
|
425
|
+
enc
|
|
426
|
+
.command("list-keys-v2")
|
|
427
|
+
.description("[V2] List crypto key profiles")
|
|
428
|
+
.option("-o, --owner <id>")
|
|
429
|
+
.option("-s, --status <s>")
|
|
430
|
+
.option("-a, --algorithm <algo>")
|
|
431
|
+
.option("--json")
|
|
432
|
+
.action((o) => {
|
|
433
|
+
const list = cryptoListKeys({
|
|
434
|
+
ownerId: o.owner,
|
|
435
|
+
status: o.status,
|
|
436
|
+
algorithm: o.algorithm,
|
|
437
|
+
});
|
|
438
|
+
if (o.json) console.log(JSON.stringify(list, null, 2));
|
|
439
|
+
else
|
|
440
|
+
for (const k of list)
|
|
441
|
+
logger.log(`${k.id}\t${k.ownerId}\t${k.status}\t${k.algorithm}`);
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
enc
|
|
445
|
+
.command("create-job-v2 <id>")
|
|
446
|
+
.description("[V2] Create a queued V2 crypto job")
|
|
447
|
+
.requiredOption("-k, --key <keyId>")
|
|
448
|
+
.option("-K, --kind <kind>", "Job kind", "encrypt")
|
|
449
|
+
.action((id, o) => {
|
|
450
|
+
try {
|
|
451
|
+
const j = createJobV2(id, { keyId: o.key, kind: o.kind });
|
|
452
|
+
logger.success(`job ${j.id} queued (key=${j.keyId} kind=${j.kind})`);
|
|
453
|
+
} catch (e) {
|
|
454
|
+
logger.error(e.message);
|
|
455
|
+
process.exit(1);
|
|
456
|
+
}
|
|
457
|
+
});
|
|
458
|
+
enc
|
|
459
|
+
.command("start-job-v2 <id>")
|
|
460
|
+
.description("[V2] Start crypto job (queued -> running)")
|
|
461
|
+
.action((id) => {
|
|
462
|
+
try {
|
|
463
|
+
startJobV2(id);
|
|
464
|
+
logger.success(`job ${id} running`);
|
|
465
|
+
} catch (e) {
|
|
466
|
+
logger.error(e.message);
|
|
467
|
+
process.exit(1);
|
|
468
|
+
}
|
|
469
|
+
});
|
|
470
|
+
enc
|
|
471
|
+
.command("complete-job-v2 <id>")
|
|
472
|
+
.description("[V2] Complete crypto job (running -> completed)")
|
|
473
|
+
.action((id) => {
|
|
474
|
+
try {
|
|
475
|
+
completeJobV2(id);
|
|
476
|
+
logger.success(`job ${id} completed`);
|
|
477
|
+
} catch (e) {
|
|
478
|
+
logger.error(e.message);
|
|
479
|
+
process.exit(1);
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
enc
|
|
483
|
+
.command("fail-job-v2 <id>")
|
|
484
|
+
.description("[V2] Fail crypto job (running -> failed)")
|
|
485
|
+
.action((id) => {
|
|
486
|
+
try {
|
|
487
|
+
failJobV2(id);
|
|
488
|
+
logger.success(`job ${id} failed`);
|
|
489
|
+
} catch (e) {
|
|
490
|
+
logger.error(e.message);
|
|
491
|
+
process.exit(1);
|
|
492
|
+
}
|
|
493
|
+
});
|
|
494
|
+
enc
|
|
495
|
+
.command("cancel-job-v2 <id>")
|
|
496
|
+
.description("[V2] Cancel crypto job (queued|running -> cancelled)")
|
|
497
|
+
.action((id) => {
|
|
498
|
+
try {
|
|
499
|
+
cancelJobV2(id);
|
|
500
|
+
logger.success(`job ${id} cancelled`);
|
|
501
|
+
} catch (e) {
|
|
502
|
+
logger.error(e.message);
|
|
503
|
+
process.exit(1);
|
|
504
|
+
}
|
|
505
|
+
});
|
|
506
|
+
enc
|
|
507
|
+
.command("get-job-v2 <id>")
|
|
508
|
+
.description("[V2] Show crypto job")
|
|
509
|
+
.option("--json")
|
|
510
|
+
.action((id) => {
|
|
511
|
+
const j = getJobV2(id);
|
|
512
|
+
if (!j) {
|
|
513
|
+
logger.info("job not found");
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
console.log(JSON.stringify(j, null, 2));
|
|
517
|
+
});
|
|
518
|
+
enc
|
|
519
|
+
.command("list-jobs-v2")
|
|
520
|
+
.description("[V2] List V2 crypto jobs")
|
|
521
|
+
.option("-k, --key <keyId>")
|
|
522
|
+
.option("-s, --status <s>")
|
|
523
|
+
.option("-K, --kind <kind>")
|
|
524
|
+
.option("--json")
|
|
525
|
+
.action((o) => {
|
|
526
|
+
const list = listJobsV2({ keyId: o.key, status: o.status, kind: o.kind });
|
|
527
|
+
if (o.json) console.log(JSON.stringify(list, null, 2));
|
|
528
|
+
else
|
|
529
|
+
for (const j of list)
|
|
530
|
+
logger.log(`${j.id}\t${j.keyId}\t${j.status}\t${j.kind}`);
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
enc
|
|
534
|
+
.command("active-key-count-v2")
|
|
535
|
+
.description("[V2] Count active crypto keys (optional --owner)")
|
|
536
|
+
.option("-o, --owner <id>")
|
|
537
|
+
.action((o) => logger.log(String(cryptoGetActiveKeyCount(o.owner))));
|
|
538
|
+
enc
|
|
539
|
+
.command("pending-job-count-v2")
|
|
540
|
+
.description("[V2] Count pending crypto jobs (queued+running)")
|
|
541
|
+
.option("-k, --key <keyId>")
|
|
542
|
+
.action((o) => logger.log(String(getPendingJobCountV2(o.key))));
|
|
543
|
+
enc
|
|
544
|
+
.command("auto-rotate-idle-keys-v2")
|
|
545
|
+
.description("[V2] Rotate idle active keys")
|
|
546
|
+
.option("--now <ms>")
|
|
547
|
+
.option("--json")
|
|
548
|
+
.action((o) => {
|
|
549
|
+
const list = autoRotateIdleKeysV2(
|
|
550
|
+
o.now ? { now: Number(o.now) } : undefined,
|
|
551
|
+
);
|
|
552
|
+
if (o.json) console.log(JSON.stringify(list, null, 2));
|
|
553
|
+
else logger.success(`rotated ${list.length}`);
|
|
554
|
+
});
|
|
555
|
+
enc
|
|
556
|
+
.command("auto-fail-stuck-jobs-v2")
|
|
557
|
+
.description("[V2] Fail stuck running crypto jobs")
|
|
558
|
+
.option("--now <ms>")
|
|
559
|
+
.option("--json")
|
|
560
|
+
.action((o) => {
|
|
561
|
+
const list = autoFailStuckJobsV2(
|
|
562
|
+
o.now ? { now: Number(o.now) } : undefined,
|
|
563
|
+
);
|
|
564
|
+
if (o.json) console.log(JSON.stringify(list, null, 2));
|
|
565
|
+
else logger.success(`failed ${list.length}`);
|
|
566
|
+
});
|
|
567
|
+
enc
|
|
568
|
+
.command("stats-v2")
|
|
569
|
+
.description("[V2] Show governance stats")
|
|
570
|
+
.option("--json")
|
|
571
|
+
.action(() =>
|
|
572
|
+
console.log(JSON.stringify(getCryptoManagerStatsV2(), null, 2)),
|
|
573
|
+
);
|
|
233
574
|
}
|