chainlesschain 0.81.0 → 0.143.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 (209) hide show
  1. package/bin/chainlesschain.js +0 -0
  2. package/package.json +1 -1
  3. package/src/commands/a2a.js +62 -0
  4. package/src/commands/activitypub.js +61 -0
  5. package/src/commands/agent-network.js +254 -1
  6. package/src/commands/agent.js +117 -0
  7. package/src/commands/audit.js +302 -0
  8. package/src/commands/automation.js +271 -1
  9. package/src/commands/bi.js +61 -0
  10. package/src/commands/bm25.js +78 -0
  11. package/src/commands/browse.js +64 -0
  12. package/src/commands/ccron.js +78 -0
  13. package/src/commands/codegen.js +224 -0
  14. package/src/commands/collab.js +341 -0
  15. package/src/commands/compliance.js +1075 -0
  16. package/src/commands/compt.js +78 -0
  17. package/src/commands/consol.js +231 -0
  18. package/src/commands/cowork.js +263 -0
  19. package/src/commands/crosschain.js +62 -0
  20. package/src/commands/dao.js +62 -0
  21. package/src/commands/dbevo.js +284 -0
  22. package/src/commands/dev.js +252 -0
  23. package/src/commands/did.js +358 -0
  24. package/src/commands/dlp.js +61 -0
  25. package/src/commands/economy.js +56 -0
  26. package/src/commands/encrypt.js +341 -0
  27. package/src/commands/evolution.js +56 -0
  28. package/src/commands/evomap.js +61 -0
  29. package/src/commands/export.js +256 -1
  30. package/src/commands/fflag.js +178 -0
  31. package/src/commands/fusion.js +258 -0
  32. package/src/commands/git.js +45 -0
  33. package/src/commands/governance.js +325 -0
  34. package/src/commands/hardening.js +411 -0
  35. package/src/commands/hmemory.js +56 -0
  36. package/src/commands/hook.js +148 -0
  37. package/src/commands/import.js +252 -0
  38. package/src/commands/incentive.js +322 -0
  39. package/src/commands/inference.js +42 -0
  40. package/src/commands/infra.js +244 -0
  41. package/src/commands/instinct.js +260 -0
  42. package/src/commands/ipfs.js +318 -0
  43. package/src/commands/itbudget.js +45 -0
  44. package/src/commands/kg.js +387 -0
  45. package/src/commands/llm.js +263 -0
  46. package/src/commands/lowcode.js +44 -0
  47. package/src/commands/matrix.js +62 -0
  48. package/src/commands/mcp.js +221 -0
  49. package/src/commands/mcpscaf.js +41 -0
  50. package/src/commands/meminj.js +41 -0
  51. package/src/commands/memory.js +248 -0
  52. package/src/commands/multimodal.js +296 -0
  53. package/src/commands/nlprog.js +356 -0
  54. package/src/commands/nostr.js +62 -0
  55. package/src/commands/note.js +244 -0
  56. package/src/commands/ops.js +354 -0
  57. package/src/commands/orchestrate.js +166 -0
  58. package/src/commands/orchgov.js +45 -0
  59. package/src/commands/org.js +277 -0
  60. package/src/commands/p2p.js +390 -0
  61. package/src/commands/pdfp.js +78 -0
  62. package/src/commands/perception.js +290 -0
  63. package/src/commands/perf.js +39 -0
  64. package/src/commands/perm.js +45 -0
  65. package/src/commands/permmem.js +251 -0
  66. package/src/commands/pipeline.js +57 -1
  67. package/src/commands/planmode.js +45 -0
  68. package/src/commands/plugin-ecosystem.js +273 -0
  69. package/src/commands/pqc.js +393 -0
  70. package/src/commands/promcomp.js +82 -0
  71. package/src/commands/quantization.js +351 -0
  72. package/src/commands/rcache.js +271 -0
  73. package/src/commands/recommend.js +382 -0
  74. package/src/commands/runtime.js +307 -0
  75. package/src/commands/scim.js +262 -0
  76. package/src/commands/seshhook.js +41 -0
  77. package/src/commands/seshsearch.js +41 -0
  78. package/src/commands/seshtail.js +41 -0
  79. package/src/commands/seshu.js +41 -0
  80. package/src/commands/session.js +258 -0
  81. package/src/commands/sganal.js +78 -0
  82. package/src/commands/siem.js +40 -0
  83. package/src/commands/skill.js +267 -1
  84. package/src/commands/slotfill.js +41 -0
  85. package/src/commands/social.js +290 -0
  86. package/src/commands/sso.js +186 -1
  87. package/src/commands/svccont.js +45 -0
  88. package/src/commands/sync.js +256 -0
  89. package/src/commands/tech.js +338 -0
  90. package/src/commands/tenant.js +351 -0
  91. package/src/commands/tms.js +45 -0
  92. package/src/commands/tokens.js +269 -0
  93. package/src/commands/topiccls.js +45 -0
  94. package/src/commands/trust.js +249 -0
  95. package/src/commands/uprof.js +45 -0
  96. package/src/commands/vcheck.js +78 -0
  97. package/src/commands/wallet.js +277 -0
  98. package/src/commands/webfetch.js +41 -0
  99. package/src/commands/workflow.js +171 -0
  100. package/src/commands/zkp.js +62 -0
  101. package/src/harness/prompt-compressor.js +331 -0
  102. package/src/index.js +65 -1
  103. package/src/lib/a2a-protocol.js +105 -0
  104. package/src/lib/activitypub-bridge.js +105 -0
  105. package/src/lib/agent-coordinator.js +325 -0
  106. package/src/lib/agent-economy.js +105 -0
  107. package/src/lib/agent-network.js +387 -0
  108. package/src/lib/agent-router.js +395 -0
  109. package/src/lib/aiops.js +478 -0
  110. package/src/lib/app-builder.js +105 -0
  111. package/src/lib/audit-logger.js +379 -0
  112. package/src/lib/automation-engine.js +330 -0
  113. package/src/lib/autonomous-agent.js +105 -0
  114. package/src/lib/autonomous-developer.js +350 -0
  115. package/src/lib/bi-engine.js +105 -0
  116. package/src/lib/bm25-search.js +81 -0
  117. package/src/lib/browser-automation.js +105 -0
  118. package/src/lib/code-agent.js +323 -0
  119. package/src/lib/collaboration-governance.js +364 -0
  120. package/src/lib/community-governance.js +436 -0
  121. package/src/lib/compliance-framework-reporter.js +105 -0
  122. package/src/lib/compliance-manager.js +434 -0
  123. package/src/lib/compression-telemetry.js +81 -0
  124. package/src/lib/content-recommendation.js +469 -0
  125. package/src/lib/content-recommender.js +105 -0
  126. package/src/lib/cowork-cron.js +81 -0
  127. package/src/lib/cowork-task-runner.js +105 -0
  128. package/src/lib/cross-chain.js +105 -0
  129. package/src/lib/crypto-manager.js +350 -0
  130. package/src/lib/dao-governance.js +105 -0
  131. package/src/lib/dbevo.js +338 -0
  132. package/src/lib/decentral-infra.js +340 -0
  133. package/src/lib/did-manager.js +367 -0
  134. package/src/lib/dlp-engine.js +105 -0
  135. package/src/lib/evolution-system.js +105 -0
  136. package/src/lib/evomap-manager.js +105 -0
  137. package/src/lib/execution-backend.js +105 -0
  138. package/src/lib/feature-flags.js +85 -0
  139. package/src/lib/git-integration.js +105 -0
  140. package/src/lib/hardening-manager.js +348 -0
  141. package/src/lib/hierarchical-memory.js +105 -0
  142. package/src/lib/hook-manager.js +380 -0
  143. package/src/lib/inference-network.js +105 -0
  144. package/src/lib/instinct-manager.js +332 -0
  145. package/src/lib/ipfs-storage.js +334 -0
  146. package/src/lib/iteration-budget.js +105 -0
  147. package/src/lib/knowledge-exporter.js +381 -0
  148. package/src/lib/knowledge-graph.js +432 -0
  149. package/src/lib/knowledge-importer.js +379 -0
  150. package/src/lib/llm-providers.js +391 -0
  151. package/src/lib/matrix-bridge.js +105 -0
  152. package/src/lib/mcp-registry.js +333 -0
  153. package/src/lib/mcp-scaffold.js +81 -0
  154. package/src/lib/memory-injection.js +81 -0
  155. package/src/lib/memory-manager.js +330 -0
  156. package/src/lib/multimodal.js +346 -0
  157. package/src/lib/nl-programming.js +343 -0
  158. package/src/lib/nostr-bridge.js +105 -0
  159. package/src/lib/note-versioning.js +327 -0
  160. package/src/lib/orchestrator.js +105 -0
  161. package/src/lib/org-manager.js +323 -0
  162. package/src/lib/p2p-manager.js +387 -0
  163. package/src/lib/pdf-parser.js +81 -0
  164. package/src/lib/perception.js +346 -0
  165. package/src/lib/perf-tuning.js +109 -1
  166. package/src/lib/permanent-memory.js +320 -0
  167. package/src/lib/permission-engine.js +81 -0
  168. package/src/lib/pipeline-orchestrator.js +105 -0
  169. package/src/lib/plan-mode.js +81 -0
  170. package/src/lib/plugin-ecosystem.js +377 -0
  171. package/src/lib/pqc-manager.js +368 -0
  172. package/src/lib/prompt-compressor.js +1 -10
  173. package/src/lib/protocol-fusion.js +417 -0
  174. package/src/lib/quantization.js +325 -0
  175. package/src/lib/response-cache.js +327 -0
  176. package/src/lib/scim-manager.js +329 -0
  177. package/src/lib/service-container.js +81 -0
  178. package/src/lib/session-consolidator.js +105 -0
  179. package/src/lib/session-hooks.js +81 -0
  180. package/src/lib/session-manager.js +329 -0
  181. package/src/lib/session-search.js +81 -0
  182. package/src/lib/session-tail.js +81 -0
  183. package/src/lib/session-usage.js +83 -0
  184. package/src/lib/siem-exporter.js +105 -0
  185. package/src/lib/skill-loader.js +377 -0
  186. package/src/lib/slot-filler.js +81 -0
  187. package/src/lib/social-graph-analytics.js +81 -0
  188. package/src/lib/social-graph.js +81 -0
  189. package/src/lib/social-manager.js +326 -0
  190. package/src/lib/sso-manager.js +332 -0
  191. package/src/lib/sub-agent-registry.js +110 -0
  192. package/src/lib/sync-manager.js +326 -0
  193. package/src/lib/task-model-selector.js +81 -0
  194. package/src/lib/tech-learning-engine.js +369 -0
  195. package/src/lib/tenant-saas.js +460 -0
  196. package/src/lib/threat-intel.js +335 -0
  197. package/src/lib/todo-manager.js +105 -0
  198. package/src/lib/token-incentive.js +293 -0
  199. package/src/lib/token-tracker.js +329 -0
  200. package/src/lib/topic-classifier.js +105 -0
  201. package/src/lib/trust-security.js +390 -0
  202. package/src/lib/ueba.js +389 -0
  203. package/src/lib/universal-runtime.js +325 -0
  204. package/src/lib/user-profile.js +81 -0
  205. package/src/lib/version-checker.js +81 -0
  206. package/src/lib/wallet-manager.js +326 -0
  207. package/src/lib/web-fetch.js +81 -0
  208. package/src/lib/workflow-engine.js +322 -0
  209. package/src/lib/zkp-engine.js +105 -0
@@ -362,3 +362,382 @@ export function purgeLogs(db, daysToKeep = 90) {
362
362
  export function getRecentEvents(db, limit = 20) {
363
363
  return queryLogs(db, { limit });
364
364
  }
365
+
366
+ /* ═══════════════════════════════════════════════════════════════
367
+ V2 SURFACE (Phase 11 canonical) — strictly additive
368
+ ═══════════════════════════════════════════════════════════════ */
369
+
370
+ export const LOG_STATUS_V2 = Object.freeze({
371
+ ACTIVE: "active",
372
+ ARCHIVED: "archived",
373
+ PURGED: "purged",
374
+ });
375
+
376
+ export const INTEGRITY_STATUS_V2 = Object.freeze({
377
+ UNVERIFIED: "unverified",
378
+ VERIFIED: "verified",
379
+ CORRUPTED: "corrupted",
380
+ });
381
+
382
+ export const ALERT_STATUS_V2 = Object.freeze({
383
+ OPEN: "open",
384
+ ACKNOWLEDGED: "acknowledged",
385
+ RESOLVED: "resolved",
386
+ DISMISSED: "dismissed",
387
+ });
388
+
389
+ export const EVENT_TYPES_V2 = Object.freeze([
390
+ "auth",
391
+ "permission",
392
+ "data",
393
+ "system",
394
+ "file",
395
+ "did",
396
+ "crypto",
397
+ "api",
398
+ ]);
399
+
400
+ export const RISK_LEVELS_V2 = Object.freeze([
401
+ "low",
402
+ "medium",
403
+ "high",
404
+ "critical",
405
+ ]);
406
+
407
+ export const AUDIT_DEFAULT_MAX_ALERTS_PER_ACTOR = 10;
408
+ export const AUDIT_DEFAULT_ARCHIVE_RETENTION_MS = 30 * 24 * 60 * 60 * 1000; // 30 days
409
+ export const AUDIT_DEFAULT_PURGE_RETENTION_MS = 365 * 24 * 60 * 60 * 1000; // 365 days
410
+
411
+ let _maxAlertsPerActor = AUDIT_DEFAULT_MAX_ALERTS_PER_ACTOR;
412
+ let _archiveRetentionMs = AUDIT_DEFAULT_ARCHIVE_RETENTION_MS;
413
+ let _purgeRetentionMs = AUDIT_DEFAULT_PURGE_RETENTION_MS;
414
+
415
+ const _logStatesV2 = new Map();
416
+ const _alertStatesV2 = new Map();
417
+ let _lastChainHash = null;
418
+
419
+ const LOG_TRANSITIONS_V2 = new Map([
420
+ ["active", new Set(["archived", "purged"])],
421
+ ["archived", new Set(["purged"])],
422
+ ]);
423
+ const LOG_TERMINALS_V2 = new Set(["purged"]);
424
+
425
+ const ALERT_TRANSITIONS_V2 = new Map([
426
+ ["open", new Set(["acknowledged", "dismissed"])],
427
+ ["acknowledged", new Set(["resolved", "dismissed"])],
428
+ ]);
429
+ const ALERT_TERMINALS_V2 = new Set(["resolved", "dismissed"]);
430
+
431
+ function _positiveInt(n, label) {
432
+ const v = Number(n);
433
+ if (!Number.isFinite(v) || v <= 0) {
434
+ throw new Error(`${label} must be a positive integer`);
435
+ }
436
+ return Math.floor(v);
437
+ }
438
+
439
+ export function setMaxAlertsPerActor(n) {
440
+ _maxAlertsPerActor = _positiveInt(n, "maxAlertsPerActor");
441
+ return _maxAlertsPerActor;
442
+ }
443
+
444
+ export function setArchiveRetentionMs(ms) {
445
+ _archiveRetentionMs = _positiveInt(ms, "archiveRetentionMs");
446
+ return _archiveRetentionMs;
447
+ }
448
+
449
+ export function setPurgeRetentionMs(ms) {
450
+ _purgeRetentionMs = _positiveInt(ms, "purgeRetentionMs");
451
+ return _purgeRetentionMs;
452
+ }
453
+
454
+ export function getMaxAlertsPerActor() {
455
+ return _maxAlertsPerActor;
456
+ }
457
+
458
+ export function getArchiveRetentionMs() {
459
+ return _archiveRetentionMs;
460
+ }
461
+
462
+ export function getPurgeRetentionMs() {
463
+ return _purgeRetentionMs;
464
+ }
465
+
466
+ export function getOpenAlertCount(actor) {
467
+ let count = 0;
468
+ for (const entry of _alertStatesV2.values()) {
469
+ if (entry.status === ALERT_STATUS_V2.OPEN) {
470
+ if (!actor || entry.actor === actor) count += 1;
471
+ }
472
+ }
473
+ return count;
474
+ }
475
+
476
+ function _hashChainEntry(prevHash, entry) {
477
+ const payload = JSON.stringify({
478
+ logId: entry.logId,
479
+ eventType: entry.eventType,
480
+ operation: entry.operation,
481
+ actor: entry.actor,
482
+ riskLevel: entry.riskLevel,
483
+ createdAt: entry.createdAt,
484
+ prev: prevHash || "",
485
+ });
486
+ return crypto.createHash("sha256").update(payload).digest("hex");
487
+ }
488
+
489
+ /* ── Log V2 (hash-chained) ──────────────────────────────────── */
490
+
491
+ export function logEventV2(
492
+ db,
493
+ {
494
+ logId,
495
+ eventType,
496
+ operation,
497
+ actor,
498
+ target,
499
+ details,
500
+ riskLevel,
501
+ ipAddress,
502
+ userAgent,
503
+ success,
504
+ errorMessage,
505
+ } = {},
506
+ ) {
507
+ if (!logId) throw new Error("logId is required");
508
+ if (!operation) throw new Error("operation is required");
509
+ if (!eventType) throw new Error("eventType is required");
510
+ if (!EVENT_TYPES_V2.includes(eventType)) {
511
+ throw new Error(`Invalid eventType: ${eventType}`);
512
+ }
513
+ if (_logStatesV2.has(logId)) {
514
+ throw new Error(`Log already registered: ${logId}`);
515
+ }
516
+ const risk = riskLevel || assessRisk(eventType, operation, details);
517
+ if (!RISK_LEVELS_V2.includes(risk)) {
518
+ throw new Error(`Invalid riskLevel: ${risk}`);
519
+ }
520
+ const now = Date.now();
521
+ const entry = {
522
+ logId,
523
+ eventType,
524
+ operation,
525
+ actor: actor || null,
526
+ target: target || null,
527
+ details: sanitizeDetails(details) || null,
528
+ riskLevel: risk,
529
+ ipAddress: ipAddress || null,
530
+ userAgent: userAgent || null,
531
+ success: success !== false,
532
+ errorMessage: errorMessage || null,
533
+ status: LOG_STATUS_V2.ACTIVE,
534
+ integrityStatus: INTEGRITY_STATUS_V2.UNVERIFIED,
535
+ prevHash: _lastChainHash,
536
+ hash: null,
537
+ createdAt: now,
538
+ updatedAt: now,
539
+ };
540
+ entry.hash = _hashChainEntry(_lastChainHash, entry);
541
+ _lastChainHash = entry.hash;
542
+ _logStatesV2.set(logId, entry);
543
+
544
+ // Auto-create alert on critical events
545
+ if (risk === "critical" && actor) {
546
+ const openCount = getOpenAlertCount(actor);
547
+ if (openCount < _maxAlertsPerActor) {
548
+ const alertId = `alert-${logId}`;
549
+ _alertStatesV2.set(alertId, {
550
+ alertId,
551
+ logId,
552
+ actor,
553
+ operation,
554
+ riskLevel: risk,
555
+ status: ALERT_STATUS_V2.OPEN,
556
+ reason: null,
557
+ metadata: {},
558
+ createdAt: now,
559
+ updatedAt: now,
560
+ });
561
+ }
562
+ }
563
+
564
+ return { ...entry };
565
+ }
566
+
567
+ export function getLogStatusV2(logId) {
568
+ const entry = _logStatesV2.get(logId);
569
+ return entry ? { ...entry } : null;
570
+ }
571
+
572
+ export function setLogStatusV2(db, logId, newStatus, patch = {}) {
573
+ const entry = _logStatesV2.get(logId);
574
+ if (!entry) throw new Error(`Log not found: ${logId}`);
575
+ if (!Object.values(LOG_STATUS_V2).includes(newStatus)) {
576
+ throw new Error(`Invalid log status: ${newStatus}`);
577
+ }
578
+ if (LOG_TERMINALS_V2.has(entry.status)) {
579
+ throw new Error(`Log is terminal: ${entry.status}`);
580
+ }
581
+ const allowed = LOG_TRANSITIONS_V2.get(entry.status) || new Set();
582
+ if (!allowed.has(newStatus)) {
583
+ throw new Error(`Invalid transition: ${entry.status} → ${newStatus}`);
584
+ }
585
+ entry.status = newStatus;
586
+ entry.updatedAt = Date.now();
587
+ if (patch.reason !== undefined) entry.reason = patch.reason;
588
+ return { ...entry };
589
+ }
590
+
591
+ export function verifyChainV2() {
592
+ const results = [];
593
+ let prevHash = null;
594
+ const entries = [..._logStatesV2.values()].sort(
595
+ (a, b) => a.createdAt - b.createdAt,
596
+ );
597
+ for (const entry of entries) {
598
+ const expected = _hashChainEntry(prevHash, entry);
599
+ const valid = expected === entry.hash && entry.prevHash === prevHash;
600
+ entry.integrityStatus = valid
601
+ ? INTEGRITY_STATUS_V2.VERIFIED
602
+ : INTEGRITY_STATUS_V2.CORRUPTED;
603
+ results.push({
604
+ logId: entry.logId,
605
+ valid,
606
+ integrityStatus: entry.integrityStatus,
607
+ });
608
+ prevHash = entry.hash;
609
+ }
610
+ return results;
611
+ }
612
+
613
+ export function autoArchiveLogs(db, nowMs = Date.now()) {
614
+ const archived = [];
615
+ for (const entry of _logStatesV2.values()) {
616
+ if (entry.status !== LOG_STATUS_V2.ACTIVE) continue;
617
+ if (nowMs - entry.createdAt > _archiveRetentionMs) {
618
+ entry.status = LOG_STATUS_V2.ARCHIVED;
619
+ entry.updatedAt = nowMs;
620
+ archived.push({ ...entry });
621
+ }
622
+ }
623
+ return archived;
624
+ }
625
+
626
+ export function autoPurgeLogs(db, nowMs = Date.now()) {
627
+ const purged = [];
628
+ for (const entry of _logStatesV2.values()) {
629
+ if (entry.status !== LOG_STATUS_V2.ARCHIVED) continue;
630
+ if (nowMs - entry.createdAt > _purgeRetentionMs) {
631
+ entry.status = LOG_STATUS_V2.PURGED;
632
+ entry.updatedAt = nowMs;
633
+ purged.push({ ...entry });
634
+ }
635
+ }
636
+ return purged;
637
+ }
638
+
639
+ /* ── Alert V2 ───────────────────────────────────────────────── */
640
+
641
+ export function getAlertStatusV2(alertId) {
642
+ const entry = _alertStatesV2.get(alertId);
643
+ return entry ? { ...entry } : null;
644
+ }
645
+
646
+ export function setAlertStatusV2(db, alertId, newStatus, patch = {}) {
647
+ const entry = _alertStatesV2.get(alertId);
648
+ if (!entry) throw new Error(`Alert not found: ${alertId}`);
649
+ if (!Object.values(ALERT_STATUS_V2).includes(newStatus)) {
650
+ throw new Error(`Invalid alert status: ${newStatus}`);
651
+ }
652
+ if (ALERT_TERMINALS_V2.has(entry.status)) {
653
+ throw new Error(`Alert is terminal: ${entry.status}`);
654
+ }
655
+ const allowed = ALERT_TRANSITIONS_V2.get(entry.status) || new Set();
656
+ if (!allowed.has(newStatus)) {
657
+ throw new Error(`Invalid transition: ${entry.status} → ${newStatus}`);
658
+ }
659
+ entry.status = newStatus;
660
+ entry.updatedAt = Date.now();
661
+ if (patch.reason !== undefined) entry.reason = patch.reason;
662
+ if (patch.metadata) entry.metadata = { ...entry.metadata, ...patch.metadata };
663
+ return { ...entry };
664
+ }
665
+
666
+ export function acknowledgeAlert(db, alertId, reason) {
667
+ return setAlertStatusV2(db, alertId, ALERT_STATUS_V2.ACKNOWLEDGED, {
668
+ reason,
669
+ });
670
+ }
671
+
672
+ export function resolveAlert(db, alertId, reason) {
673
+ return setAlertStatusV2(db, alertId, ALERT_STATUS_V2.RESOLVED, { reason });
674
+ }
675
+
676
+ export function dismissAlert(db, alertId, reason) {
677
+ return setAlertStatusV2(db, alertId, ALERT_STATUS_V2.DISMISSED, { reason });
678
+ }
679
+
680
+ /* ── Stats V2 ───────────────────────────────────────────────── */
681
+
682
+ export function getAuditStatsV2() {
683
+ const logsByStatus = { active: 0, archived: 0, purged: 0 };
684
+ const logsByRisk = { low: 0, medium: 0, high: 0, critical: 0 };
685
+ const logsByIntegrity = { unverified: 0, verified: 0, corrupted: 0 };
686
+ const logsByEventType = {
687
+ auth: 0,
688
+ permission: 0,
689
+ data: 0,
690
+ system: 0,
691
+ file: 0,
692
+ did: 0,
693
+ crypto: 0,
694
+ api: 0,
695
+ };
696
+ const alertsByStatus = {
697
+ open: 0,
698
+ acknowledged: 0,
699
+ resolved: 0,
700
+ dismissed: 0,
701
+ };
702
+
703
+ for (const entry of _logStatesV2.values()) {
704
+ if (logsByStatus[entry.status] !== undefined)
705
+ logsByStatus[entry.status] += 1;
706
+ if (logsByRisk[entry.riskLevel] !== undefined)
707
+ logsByRisk[entry.riskLevel] += 1;
708
+ if (logsByIntegrity[entry.integrityStatus] !== undefined)
709
+ logsByIntegrity[entry.integrityStatus] += 1;
710
+ if (logsByEventType[entry.eventType] !== undefined)
711
+ logsByEventType[entry.eventType] += 1;
712
+ }
713
+ for (const entry of _alertStatesV2.values()) {
714
+ if (alertsByStatus[entry.status] !== undefined)
715
+ alertsByStatus[entry.status] += 1;
716
+ }
717
+
718
+ return {
719
+ totalLogs: _logStatesV2.size,
720
+ totalAlerts: _alertStatesV2.size,
721
+ activeAlerts: alertsByStatus.open,
722
+ maxAlertsPerActor: _maxAlertsPerActor,
723
+ archiveRetentionMs: _archiveRetentionMs,
724
+ purgeRetentionMs: _purgeRetentionMs,
725
+ lastChainHash: _lastChainHash,
726
+ logsByStatus,
727
+ logsByRisk,
728
+ logsByIntegrity,
729
+ logsByEventType,
730
+ alertsByStatus,
731
+ };
732
+ }
733
+
734
+ /* ── Reset (for testing) ───────────────────────────────────── */
735
+
736
+ export function _resetStateV2() {
737
+ _logStatesV2.clear();
738
+ _alertStatesV2.clear();
739
+ _lastChainHash = null;
740
+ _maxAlertsPerActor = AUDIT_DEFAULT_MAX_ALERTS_PER_ACTOR;
741
+ _archiveRetentionMs = AUDIT_DEFAULT_ARCHIVE_RETENTION_MS;
742
+ _purgeRetentionMs = AUDIT_DEFAULT_PURGE_RETENTION_MS;
743
+ }
@@ -946,3 +946,333 @@ export function getConfig() {
946
946
  nodeTypes: Object.values(NODE_TYPE),
947
947
  };
948
948
  }
949
+
950
+ /* ═══════════════════════════════════════════════════════════════
951
+ * V2 Surface — Automation engine governance layer.
952
+ * Tracks per-owner automation maturity + per-automation execution
953
+ * lifecycle independent of legacy SQLite tables.
954
+ * ═══════════════════════════════════════════════════════════════ */
955
+
956
+ export const AUTOMATION_MATURITY_V2 = Object.freeze({
957
+ DRAFT: "draft",
958
+ ACTIVE: "active",
959
+ PAUSED: "paused",
960
+ RETIRED: "retired",
961
+ });
962
+
963
+ export const EXECUTION_LIFECYCLE_V2 = Object.freeze({
964
+ QUEUED: "queued",
965
+ RUNNING: "running",
966
+ SUCCEEDED: "succeeded",
967
+ FAILED: "failed",
968
+ CANCELLED: "cancelled",
969
+ });
970
+
971
+ const AUTOMATION_TRANSITIONS_V2 = new Map([
972
+ ["draft", new Set(["active", "retired"])],
973
+ ["active", new Set(["paused", "retired"])],
974
+ ["paused", new Set(["active", "retired"])],
975
+ ["retired", new Set()],
976
+ ]);
977
+ const AUTOMATION_TERMINALS_V2 = new Set(["retired"]);
978
+
979
+ const EXECUTION_TRANSITIONS_V2 = new Map([
980
+ ["queued", new Set(["running", "cancelled"])],
981
+ ["running", new Set(["succeeded", "failed", "cancelled"])],
982
+ ["succeeded", new Set()],
983
+ ["failed", new Set()],
984
+ ["cancelled", new Set()],
985
+ ]);
986
+ const EXECUTION_TERMINALS_V2 = new Set(["succeeded", "failed", "cancelled"]);
987
+
988
+ export const AUTOMATION_DEFAULT_MAX_ACTIVE_PER_OWNER = 20;
989
+ export const AUTOMATION_DEFAULT_MAX_RUNNING_PER_AUTOMATION = 3;
990
+ export const AUTOMATION_DEFAULT_AUTOMATION_IDLE_MS = 1000 * 60 * 60 * 24 * 14; // 14 days
991
+ export const AUTOMATION_DEFAULT_EXECUTION_STUCK_MS = 1000 * 60 * 30; // 30 min
992
+
993
+ const _automationsV2 = new Map();
994
+ const _executionsV2 = new Map();
995
+ let _maxActiveAutomationsPerOwnerV2 = AUTOMATION_DEFAULT_MAX_ACTIVE_PER_OWNER;
996
+ let _maxRunningExecutionsPerAutomationV2 =
997
+ AUTOMATION_DEFAULT_MAX_RUNNING_PER_AUTOMATION;
998
+ let _automationIdleMsV2 = AUTOMATION_DEFAULT_AUTOMATION_IDLE_MS;
999
+ let _executionStuckMsV2 = AUTOMATION_DEFAULT_EXECUTION_STUCK_MS;
1000
+
1001
+ function _posIntAutomationV2(n, label) {
1002
+ const v = Math.floor(Number(n));
1003
+ if (!Number.isFinite(v) || v <= 0)
1004
+ throw new Error(`${label} must be a positive integer`);
1005
+ return v;
1006
+ }
1007
+
1008
+ export function getMaxActiveAutomationsPerOwnerV2() {
1009
+ return _maxActiveAutomationsPerOwnerV2;
1010
+ }
1011
+ export function setMaxActiveAutomationsPerOwnerV2(n) {
1012
+ _maxActiveAutomationsPerOwnerV2 = _posIntAutomationV2(
1013
+ n,
1014
+ "maxActiveAutomationsPerOwner",
1015
+ );
1016
+ }
1017
+ export function getMaxRunningExecutionsPerAutomationV2() {
1018
+ return _maxRunningExecutionsPerAutomationV2;
1019
+ }
1020
+ export function setMaxRunningExecutionsPerAutomationV2(n) {
1021
+ _maxRunningExecutionsPerAutomationV2 = _posIntAutomationV2(
1022
+ n,
1023
+ "maxRunningExecutionsPerAutomation",
1024
+ );
1025
+ }
1026
+ export function getAutomationIdleMsV2() {
1027
+ return _automationIdleMsV2;
1028
+ }
1029
+ export function setAutomationIdleMsV2(n) {
1030
+ _automationIdleMsV2 = _posIntAutomationV2(n, "automationIdleMs");
1031
+ }
1032
+ export function getExecutionStuckMsV2() {
1033
+ return _executionStuckMsV2;
1034
+ }
1035
+ export function setExecutionStuckMsV2(n) {
1036
+ _executionStuckMsV2 = _posIntAutomationV2(n, "executionStuckMs");
1037
+ }
1038
+
1039
+ export function getActiveAutomationCountV2(ownerId) {
1040
+ let n = 0;
1041
+ for (const a of _automationsV2.values()) {
1042
+ if (a.ownerId === ownerId && a.status === "active") n += 1;
1043
+ }
1044
+ return n;
1045
+ }
1046
+
1047
+ export function getRunningExecutionCountV2(automationId) {
1048
+ let n = 0;
1049
+ for (const e of _executionsV2.values()) {
1050
+ if (e.automationId === automationId && e.status === "running") n += 1;
1051
+ }
1052
+ return n;
1053
+ }
1054
+
1055
+ function _copyAutomationV2(a) {
1056
+ return { ...a, metadata: { ...a.metadata } };
1057
+ }
1058
+ function _copyExecutionV2(e) {
1059
+ return { ...e, metadata: { ...e.metadata } };
1060
+ }
1061
+
1062
+ export function registerAutomationV2(
1063
+ id,
1064
+ { ownerId, name, metadata = {}, now = Date.now() } = {},
1065
+ ) {
1066
+ if (!id || typeof id !== "string") throw new Error("id must be a string");
1067
+ if (!ownerId || typeof ownerId !== "string")
1068
+ throw new Error("ownerId must be a string");
1069
+ if (!name || typeof name !== "string")
1070
+ throw new Error("name must be a string");
1071
+ if (_automationsV2.has(id))
1072
+ throw new Error(`automation ${id} already exists`);
1073
+ const a = {
1074
+ id,
1075
+ ownerId,
1076
+ name,
1077
+ status: "draft",
1078
+ createdAt: now,
1079
+ lastSeenAt: now,
1080
+ activatedAt: null,
1081
+ retiredAt: null,
1082
+ metadata: { ...metadata },
1083
+ };
1084
+ _automationsV2.set(id, a);
1085
+ return _copyAutomationV2(a);
1086
+ }
1087
+
1088
+ export function getAutomationV2(id) {
1089
+ const a = _automationsV2.get(id);
1090
+ return a ? _copyAutomationV2(a) : null;
1091
+ }
1092
+
1093
+ export function listAutomationsV2({ ownerId, status } = {}) {
1094
+ const out = [];
1095
+ for (const a of _automationsV2.values()) {
1096
+ if (ownerId && a.ownerId !== ownerId) continue;
1097
+ if (status && a.status !== status) continue;
1098
+ out.push(_copyAutomationV2(a));
1099
+ }
1100
+ return out;
1101
+ }
1102
+
1103
+ export function setAutomationStatusV2(id, next, { now = Date.now() } = {}) {
1104
+ const a = _automationsV2.get(id);
1105
+ if (!a) throw new Error(`automation ${id} not found`);
1106
+ if (!AUTOMATION_TRANSITIONS_V2.has(next))
1107
+ throw new Error(`unknown automation status: ${next}`);
1108
+ if (AUTOMATION_TERMINALS_V2.has(a.status))
1109
+ throw new Error(`automation ${id} is in terminal state ${a.status}`);
1110
+ const allowed = AUTOMATION_TRANSITIONS_V2.get(a.status);
1111
+ if (!allowed.has(next))
1112
+ throw new Error(`cannot transition automation from ${a.status} to ${next}`);
1113
+ if (next === "active") {
1114
+ if (a.status === "draft") {
1115
+ const count = getActiveAutomationCountV2(a.ownerId);
1116
+ if (count >= _maxActiveAutomationsPerOwnerV2)
1117
+ throw new Error(
1118
+ `owner ${a.ownerId} already at active-automation cap (${_maxActiveAutomationsPerOwnerV2})`,
1119
+ );
1120
+ }
1121
+ if (!a.activatedAt) a.activatedAt = now;
1122
+ }
1123
+ if (next === "retired" && !a.retiredAt) a.retiredAt = now;
1124
+ a.status = next;
1125
+ a.lastSeenAt = now;
1126
+ return _copyAutomationV2(a);
1127
+ }
1128
+
1129
+ export function activateAutomationV2(id, opts) {
1130
+ return setAutomationStatusV2(id, "active", opts);
1131
+ }
1132
+ export function pauseAutomationV2(id, opts) {
1133
+ return setAutomationStatusV2(id, "paused", opts);
1134
+ }
1135
+ export function retireAutomationV2(id, opts) {
1136
+ return setAutomationStatusV2(id, "retired", opts);
1137
+ }
1138
+
1139
+ export function touchAutomationV2(id, { now = Date.now() } = {}) {
1140
+ const a = _automationsV2.get(id);
1141
+ if (!a) throw new Error(`automation ${id} not found`);
1142
+ a.lastSeenAt = now;
1143
+ return _copyAutomationV2(a);
1144
+ }
1145
+
1146
+ export function createExecutionV2(
1147
+ id,
1148
+ { automationId, metadata = {}, now = Date.now() } = {},
1149
+ ) {
1150
+ if (!id || typeof id !== "string") throw new Error("id must be a string");
1151
+ if (!automationId || typeof automationId !== "string")
1152
+ throw new Error("automationId must be a string");
1153
+ if (_executionsV2.has(id)) throw new Error(`execution ${id} already exists`);
1154
+ const e = {
1155
+ id,
1156
+ automationId,
1157
+ status: "queued",
1158
+ createdAt: now,
1159
+ lastSeenAt: now,
1160
+ startedAt: null,
1161
+ settledAt: null,
1162
+ metadata: { ...metadata },
1163
+ };
1164
+ _executionsV2.set(id, e);
1165
+ return _copyExecutionV2(e);
1166
+ }
1167
+
1168
+ export function getExecutionV2(id) {
1169
+ const e = _executionsV2.get(id);
1170
+ return e ? _copyExecutionV2(e) : null;
1171
+ }
1172
+
1173
+ export function listExecutionsV2({ automationId, status } = {}) {
1174
+ const out = [];
1175
+ for (const e of _executionsV2.values()) {
1176
+ if (automationId && e.automationId !== automationId) continue;
1177
+ if (status && e.status !== status) continue;
1178
+ out.push(_copyExecutionV2(e));
1179
+ }
1180
+ return out;
1181
+ }
1182
+
1183
+ export function setExecutionStatusV2(id, next, { now = Date.now() } = {}) {
1184
+ const e = _executionsV2.get(id);
1185
+ if (!e) throw new Error(`execution ${id} not found`);
1186
+ if (!EXECUTION_TRANSITIONS_V2.has(next))
1187
+ throw new Error(`unknown execution status: ${next}`);
1188
+ if (EXECUTION_TERMINALS_V2.has(e.status))
1189
+ throw new Error(`execution ${id} is in terminal state ${e.status}`);
1190
+ const allowed = EXECUTION_TRANSITIONS_V2.get(e.status);
1191
+ if (!allowed.has(next))
1192
+ throw new Error(`cannot transition execution from ${e.status} to ${next}`);
1193
+ if (next === "running") {
1194
+ const count = getRunningExecutionCountV2(e.automationId);
1195
+ if (count >= _maxRunningExecutionsPerAutomationV2)
1196
+ throw new Error(
1197
+ `automation ${e.automationId} already at running-execution cap (${_maxRunningExecutionsPerAutomationV2})`,
1198
+ );
1199
+ if (!e.startedAt) e.startedAt = now;
1200
+ }
1201
+ if (EXECUTION_TERMINALS_V2.has(next) && !e.settledAt) e.settledAt = now;
1202
+ e.status = next;
1203
+ e.lastSeenAt = now;
1204
+ return _copyExecutionV2(e);
1205
+ }
1206
+
1207
+ export function startExecutionV2(id, opts) {
1208
+ return setExecutionStatusV2(id, "running", opts);
1209
+ }
1210
+ export function succeedExecutionV2(id, opts) {
1211
+ return setExecutionStatusV2(id, "succeeded", opts);
1212
+ }
1213
+ export function failExecutionV2(id, opts) {
1214
+ return setExecutionStatusV2(id, "failed", opts);
1215
+ }
1216
+ export function cancelExecutionV2(id, opts) {
1217
+ return setExecutionStatusV2(id, "cancelled", opts);
1218
+ }
1219
+
1220
+ export function autoPauseIdleAutomationsV2({ now = Date.now() } = {}) {
1221
+ const flipped = [];
1222
+ for (const a of _automationsV2.values()) {
1223
+ if (a.status !== "active") continue;
1224
+ if (now - a.lastSeenAt > _automationIdleMsV2) {
1225
+ a.status = "paused";
1226
+ a.lastSeenAt = now;
1227
+ flipped.push(_copyAutomationV2(a));
1228
+ }
1229
+ }
1230
+ return flipped;
1231
+ }
1232
+
1233
+ export function autoFailStuckExecutionsV2({ now = Date.now() } = {}) {
1234
+ const flipped = [];
1235
+ for (const e of _executionsV2.values()) {
1236
+ if (e.status !== "running") continue;
1237
+ if (now - e.lastSeenAt > _executionStuckMsV2) {
1238
+ e.status = "failed";
1239
+ e.lastSeenAt = now;
1240
+ if (!e.settledAt) e.settledAt = now;
1241
+ flipped.push(_copyExecutionV2(e));
1242
+ }
1243
+ }
1244
+ return flipped;
1245
+ }
1246
+
1247
+ export function getAutomationEngineStatsV2() {
1248
+ const automationsByStatus = {};
1249
+ for (const v of Object.values(AUTOMATION_MATURITY_V2))
1250
+ automationsByStatus[v] = 0;
1251
+ for (const a of _automationsV2.values()) automationsByStatus[a.status] += 1;
1252
+
1253
+ const executionsByStatus = {};
1254
+ for (const v of Object.values(EXECUTION_LIFECYCLE_V2))
1255
+ executionsByStatus[v] = 0;
1256
+ for (const e of _executionsV2.values()) executionsByStatus[e.status] += 1;
1257
+
1258
+ return {
1259
+ totalAutomationsV2: _automationsV2.size,
1260
+ totalExecutionsV2: _executionsV2.size,
1261
+ maxActiveAutomationsPerOwner: _maxActiveAutomationsPerOwnerV2,
1262
+ maxRunningExecutionsPerAutomation: _maxRunningExecutionsPerAutomationV2,
1263
+ automationIdleMs: _automationIdleMsV2,
1264
+ executionStuckMs: _executionStuckMsV2,
1265
+ automationsByStatus,
1266
+ executionsByStatus,
1267
+ };
1268
+ }
1269
+
1270
+ export function _resetStateAutomationEngineV2() {
1271
+ _automationsV2.clear();
1272
+ _executionsV2.clear();
1273
+ _maxActiveAutomationsPerOwnerV2 = AUTOMATION_DEFAULT_MAX_ACTIVE_PER_OWNER;
1274
+ _maxRunningExecutionsPerAutomationV2 =
1275
+ AUTOMATION_DEFAULT_MAX_RUNNING_PER_AUTOMATION;
1276
+ _automationIdleMsV2 = AUTOMATION_DEFAULT_AUTOMATION_IDLE_MS;
1277
+ _executionStuckMsV2 = AUTOMATION_DEFAULT_EXECUTION_STUCK_MS;
1278
+ }