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.
Files changed (143) hide show
  1. package/bin/chainlesschain.js +0 -0
  2. package/package.json +1 -1
  3. package/src/commands/a2a.js +380 -0
  4. package/src/commands/agent-network.js +254 -1
  5. package/src/commands/audit.js +302 -0
  6. package/src/commands/automation.js +271 -1
  7. package/src/commands/bi.js +348 -0
  8. package/src/commands/codegen.js +224 -0
  9. package/src/commands/collab.js +341 -0
  10. package/src/commands/compliance.js +1035 -0
  11. package/src/commands/cowork.js +221 -0
  12. package/src/commands/crosschain.js +218 -0
  13. package/src/commands/dbevo.js +284 -0
  14. package/src/commands/dev.js +252 -0
  15. package/src/commands/did.js +358 -0
  16. package/src/commands/dlp.js +341 -0
  17. package/src/commands/encrypt.js +341 -0
  18. package/src/commands/evomap.js +394 -0
  19. package/src/commands/export.js +256 -1
  20. package/src/commands/federation.js +283 -0
  21. package/src/commands/fusion.js +258 -0
  22. package/src/commands/governance.js +325 -0
  23. package/src/commands/hardening.js +411 -0
  24. package/src/commands/hook.js +148 -0
  25. package/src/commands/import.js +252 -0
  26. package/src/commands/incentive.js +322 -0
  27. package/src/commands/inference.js +318 -0
  28. package/src/commands/infra.js +244 -0
  29. package/src/commands/instinct.js +260 -0
  30. package/src/commands/ipfs.js +318 -0
  31. package/src/commands/kg.js +387 -0
  32. package/src/commands/llm.js +263 -0
  33. package/src/commands/lowcode.js +356 -0
  34. package/src/commands/marketplace.js +256 -0
  35. package/src/commands/mcp.js +221 -0
  36. package/src/commands/memory.js +248 -0
  37. package/src/commands/multimodal.js +296 -0
  38. package/src/commands/nlprog.js +356 -0
  39. package/src/commands/note.js +244 -0
  40. package/src/commands/ops.js +354 -0
  41. package/src/commands/orchestrate.js +166 -0
  42. package/src/commands/org.js +277 -0
  43. package/src/commands/p2p.js +390 -0
  44. package/src/commands/perception.js +290 -0
  45. package/src/commands/permmem.js +251 -0
  46. package/src/commands/plugin-ecosystem.js +273 -0
  47. package/src/commands/pqc.js +393 -0
  48. package/src/commands/privacy.js +321 -0
  49. package/src/commands/quantization.js +351 -0
  50. package/src/commands/rcache.js +271 -0
  51. package/src/commands/recommend.js +340 -0
  52. package/src/commands/reputation.js +261 -0
  53. package/src/commands/runtime.js +307 -0
  54. package/src/commands/scim.js +262 -0
  55. package/src/commands/session.js +258 -0
  56. package/src/commands/siem.js +246 -0
  57. package/src/commands/skill.js +267 -1
  58. package/src/commands/sla.js +259 -0
  59. package/src/commands/social.js +256 -0
  60. package/src/commands/sso.js +186 -1
  61. package/src/commands/stress.js +230 -0
  62. package/src/commands/sync.js +256 -0
  63. package/src/commands/tech.js +338 -0
  64. package/src/commands/tenant.js +351 -0
  65. package/src/commands/terraform.js +245 -0
  66. package/src/commands/tokens.js +269 -0
  67. package/src/commands/trust.js +249 -0
  68. package/src/commands/wallet.js +277 -0
  69. package/src/commands/workflow.js +171 -0
  70. package/src/commands/zkp.js +335 -0
  71. package/src/index.js +4 -0
  72. package/src/lib/a2a-protocol.js +451 -0
  73. package/src/lib/agent-coordinator.js +325 -0
  74. package/src/lib/agent-network.js +387 -0
  75. package/src/lib/agent-router.js +395 -0
  76. package/src/lib/aiops.js +478 -0
  77. package/src/lib/app-builder.js +239 -0
  78. package/src/lib/audit-logger.js +379 -0
  79. package/src/lib/automation-engine.js +330 -0
  80. package/src/lib/autonomous-developer.js +350 -0
  81. package/src/lib/bi-engine.js +338 -0
  82. package/src/lib/code-agent.js +323 -0
  83. package/src/lib/collaboration-governance.js +364 -0
  84. package/src/lib/community-governance.js +436 -0
  85. package/src/lib/compliance-manager.js +434 -0
  86. package/src/lib/content-recommendation.js +469 -0
  87. package/src/lib/cross-chain.js +345 -0
  88. package/src/lib/crypto-manager.js +350 -0
  89. package/src/lib/dbevo.js +338 -0
  90. package/src/lib/decentral-infra.js +340 -0
  91. package/src/lib/did-manager.js +367 -0
  92. package/src/lib/dlp-engine.js +389 -0
  93. package/src/lib/evomap-federation.js +177 -0
  94. package/src/lib/evomap-governance.js +276 -0
  95. package/src/lib/federation-hardening.js +259 -0
  96. package/src/lib/hardening-manager.js +348 -0
  97. package/src/lib/hook-manager.js +380 -0
  98. package/src/lib/inference-network.js +330 -0
  99. package/src/lib/instinct-manager.js +332 -0
  100. package/src/lib/ipfs-storage.js +334 -0
  101. package/src/lib/knowledge-exporter.js +381 -0
  102. package/src/lib/knowledge-graph.js +432 -0
  103. package/src/lib/knowledge-importer.js +379 -0
  104. package/src/lib/llm-providers.js +391 -0
  105. package/src/lib/mcp-registry.js +333 -0
  106. package/src/lib/memory-manager.js +330 -0
  107. package/src/lib/multimodal.js +346 -0
  108. package/src/lib/nl-programming.js +343 -0
  109. package/src/lib/note-versioning.js +327 -0
  110. package/src/lib/org-manager.js +323 -0
  111. package/src/lib/p2p-manager.js +387 -0
  112. package/src/lib/perception.js +346 -0
  113. package/src/lib/perf-tuning.js +4 -1
  114. package/src/lib/permanent-memory.js +320 -0
  115. package/src/lib/plugin-ecosystem.js +377 -0
  116. package/src/lib/pqc-manager.js +368 -0
  117. package/src/lib/privacy-computing.js +427 -0
  118. package/src/lib/protocol-fusion.js +417 -0
  119. package/src/lib/quantization.js +325 -0
  120. package/src/lib/reputation-optimizer.js +299 -0
  121. package/src/lib/response-cache.js +327 -0
  122. package/src/lib/scim-manager.js +329 -0
  123. package/src/lib/session-manager.js +329 -0
  124. package/src/lib/siem-exporter.js +333 -0
  125. package/src/lib/skill-loader.js +377 -0
  126. package/src/lib/skill-marketplace.js +325 -0
  127. package/src/lib/sla-manager.js +275 -0
  128. package/src/lib/social-manager.js +326 -0
  129. package/src/lib/sso-manager.js +332 -0
  130. package/src/lib/stress-tester.js +330 -0
  131. package/src/lib/sync-manager.js +326 -0
  132. package/src/lib/tech-learning-engine.js +369 -0
  133. package/src/lib/tenant-saas.js +460 -0
  134. package/src/lib/terraform-manager.js +363 -0
  135. package/src/lib/threat-intel.js +335 -0
  136. package/src/lib/token-incentive.js +293 -0
  137. package/src/lib/token-tracker.js +329 -0
  138. package/src/lib/trust-security.js +390 -0
  139. package/src/lib/ueba.js +389 -0
  140. package/src/lib/universal-runtime.js +325 -0
  141. package/src/lib/wallet-manager.js +326 -0
  142. package/src/lib/workflow-engine.js +322 -0
  143. package/src/lib/zkp-engine.js +274 -0
@@ -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}`);
@@ -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
  }