@camstack/system 1.2.457 → 1.2.459

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 (106) hide show
  1. package/dist/addon-runner.js +163 -27
  2. package/dist/addon-runner.mjs +193 -57
  3. package/dist/{agent-https-CoyOZ3pC.js → agent-https-Dnr_nIVx.js} +3 -723
  4. package/dist/{agent-https-CK9Z4sSR.mjs → agent-https-Iw3RSQup.mjs} +4 -616
  5. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  6. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  7. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  8. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  9. package/dist/builtins/alerts/alerts.addon.js +5 -7
  10. package/dist/builtins/alerts/alerts.addon.mjs +5 -7
  11. package/dist/builtins/alerts/record-kinds.d.ts +1 -1
  12. package/dist/builtins/autotrack/index.js +1 -1
  13. package/dist/builtins/autotrack/index.mjs +1 -1
  14. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +242 -4
  15. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +240 -2
  16. package/dist/builtins/calendars/calendars.addon.js +2 -10
  17. package/dist/builtins/calendars/calendars.addon.mjs +2 -3
  18. package/dist/builtins/calendars/record-kinds.d.ts +1 -1
  19. package/dist/builtins/camera-grid/index.js +1 -1
  20. package/dist/builtins/camera-grid/index.mjs +1 -1
  21. package/dist/builtins/composer/composer.addon.js +2 -2
  22. package/dist/builtins/composer/composer.addon.mjs +2 -2
  23. package/dist/builtins/console-logging/index.js +1 -1
  24. package/dist/builtins/console-logging/index.mjs +1 -1
  25. package/dist/builtins/core-blocks/core-blocks.addon.js +4 -6
  26. package/dist/builtins/core-blocks/core-blocks.addon.mjs +4 -6
  27. package/dist/builtins/device-history/device-history.addon.d.ts +13 -0
  28. package/dist/builtins/device-history/device-history.addon.js +296 -233
  29. package/dist/builtins/device-history/device-history.addon.mjs +296 -233
  30. package/dist/builtins/device-history/ingest/producer-ingest.d.ts +11 -1
  31. package/dist/builtins/device-manager/device-manager.addon.js +2 -4
  32. package/dist/builtins/device-manager/device-manager.addon.mjs +2 -4
  33. package/dist/builtins/hub-forwarder/index.js +1 -1
  34. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  35. package/dist/builtins/keychain/index.js +41 -43
  36. package/dist/builtins/keychain/index.mjs +41 -43
  37. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  38. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  39. package/dist/builtins/local-auth/local-auth.addon.js +24 -40
  40. package/dist/builtins/local-auth/local-auth.addon.mjs +24 -40
  41. package/dist/builtins/local-network/local-network.addon.js +2 -2
  42. package/dist/builtins/local-network/local-network.addon.mjs +2 -2
  43. package/dist/builtins/loki-logging/index.js +1 -1
  44. package/dist/builtins/loki-logging/index.mjs +1 -1
  45. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  46. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  47. package/dist/builtins/native-metrics/node-metrics-history-recorder.d.ts +1 -2
  48. package/dist/builtins/platform-probe/coral-accelerators.d.ts +26 -9
  49. package/dist/builtins/platform-probe/index.js +11 -68
  50. package/dist/builtins/platform-probe/index.mjs +11 -68
  51. package/dist/builtins/record-entries/index.js +1 -1
  52. package/dist/builtins/record-entries/index.mjs +1 -1
  53. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  54. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  55. package/dist/builtins/snapshot/index.js +1 -1
  56. package/dist/builtins/snapshot/index.mjs +1 -1
  57. package/dist/builtins/sqlite-storage/file-host-protocol.d.ts +0 -15
  58. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  59. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  60. package/dist/builtins/sqlite-storage/index.js +1 -1
  61. package/dist/builtins/sqlite-storage/index.mjs +1 -1
  62. package/dist/builtins/sqlite-storage/owned-sqlite-file.d.ts +0 -44
  63. package/dist/builtins/sqlite-storage/records/records-catalog.d.ts +0 -2
  64. package/dist/builtins/sqlite-storage/records/records-engine-types.d.ts +0 -21
  65. package/dist/builtins/sqlite-storage/records/records-engine.d.ts +3 -20
  66. package/dist/builtins/sqlite-storage/records/records-provider.d.ts +4 -18
  67. package/dist/builtins/sqlite-storage/records/records-sql.d.ts +1 -1
  68. package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +0 -17
  69. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +21 -196
  70. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +21 -196
  71. package/dist/builtins/sqlite-storage/storage-admin-provider.d.ts +6 -14
  72. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +2 -2
  73. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +7 -9
  74. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +7 -9
  75. package/dist/builtins/system-config/system-config.addon.js +667 -40
  76. package/dist/builtins/system-config/system-config.addon.mjs +625 -15
  77. package/dist/builtins/winston-logging/index.js +1 -1
  78. package/dist/builtins/winston-logging/index.mjs +1 -1
  79. package/dist/{composition-sources-B_jeZDRJ.mjs → composition-sources-DNRZWR1j.mjs} +1 -1
  80. package/dist/{composition-sources-qKyvMAvc.js → composition-sources-b0e_2I-D.js} +1 -1
  81. package/dist/{constants-B_X9cWEK.js → constants-6OeJiZgi.js} +1 -1
  82. package/dist/{constants-cxKcZRMi.mjs → constants-BnkOdj9Q.mjs} +1 -1
  83. package/dist/coral-accelerators-Bi_c3Rft.js +175 -0
  84. package/dist/coral-accelerators-DcnZvctM.mjs +162 -0
  85. package/dist/{device-ca-BB6nHAL5.mjs → device-ca-Bnkw8GyU.mjs} +1 -1
  86. package/dist/{device-ca-CVK3YcR_.js → device-ca-CPTDs--d.js} +1 -1
  87. package/dist/{dist-C89nqNnn.js → dist-Bn-RNanh.js} +84 -140
  88. package/dist/{dist-Dhux90yB.mjs → dist-Wy8cTxg6.mjs} +85 -123
  89. package/dist/file-host-worker.js +1 -1
  90. package/dist/file-host-worker.mjs +1 -1
  91. package/dist/{hub-mdns-ciao-B8olZqqd.mjs → hub-mdns-ciao-CJu0nhla.mjs} +2 -2
  92. package/dist/{hub-mdns-ciao-DB1Y9agt.js → hub-mdns-ciao-CTBTlia4.js} +2 -2
  93. package/dist/index.js +32 -58
  94. package/dist/index.mjs +16 -42
  95. package/dist/kernel/hwaccel/hwaccel-resolver.d.ts +7 -3
  96. package/dist/{restore-archive-DyOaPeAr.mjs → restore-archive-CmP-iiG9.mjs} +84 -331
  97. package/dist/{restore-archive-4DOUR5Gu.js → restore-archive-DM1OBYq4.js} +89 -342
  98. package/dist/{wal-maintenance-DVN-DiVP.js → wal-maintenance-DUHEp_09.js} +0 -0
  99. package/dist/{wal-maintenance-BMiX6UIa.mjs → wal-maintenance-NKbwWovZ.mjs} +0 -0
  100. package/package.json +1 -1
  101. package/dist/builtins/records/legacy-table-row-count.d.ts +0 -5
  102. package/dist/builtins/records/phase6-declare-gate.d.ts +0 -28
  103. package/dist/builtins/sqlite-storage/records/count-settings-array-legacy.d.ts +0 -5
  104. package/dist/builtins/sqlite-storage/records/count-settings-brokers-legacy.d.ts +0 -6
  105. package/dist/phase6-declare-gate-BO-_jLh_.js +0 -98
  106. package/dist/phase6-declare-gate-x9ZCbQJP.mjs +0 -93
@@ -3,11 +3,11 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-C89nqNnn.js");
6
+ const require_dist = require("../../dist-Bn-RNanh.js");
7
7
  const require_safe_buffer$1 = require("../../safe-buffer-D3aoa-7X.js");
8
8
  const require_x509_es = require("../../x509.es-C4cOo48M.js");
9
- const require_constants$8 = require("../../constants-B_X9cWEK.js");
10
- const require_agent_https = require("../../agent-https-CoyOZ3pC.js");
9
+ const require_agent_https = require("../../agent-https-Dnr_nIVx.js");
10
+ const require_constants$8 = require("../../constants-6OeJiZgi.js");
11
11
  const require_src$1 = require("../../src-CnAqG6EF.js");
12
12
  let zod = require("zod");
13
13
  let node_crypto = require("node:crypto");
@@ -298,8 +298,161 @@ function parsePayload(value) {
298
298
  };
299
299
  }
300
300
  //#endregion
301
+ //#region src/kernel/moleculer/mesh-mtls/mesh-ca.ts
302
+ /**
303
+ * Hub mesh CA — EC P-256, key in the keychain, cert in `cluster.meshCa`.
304
+ *
305
+ * Distinct from the HTTPS local CA (`tls/cert-issue.ts`, RSA): the mesh CA
306
+ * signs node leaves (CN = nodeID) and unlock-ticket JWS (ES256). Issuance uses
307
+ * `@peculiar/x509` over WebCrypto — same library the HTTPS path already uses
308
+ * (installed `1.14.3`; registry latest at adoption time was `2.1.0` — stay on
309
+ * the pinned range already shipping).
310
+ */
311
+ require_x509_es.cryptoProvider.set(node_crypto.webcrypto);
312
+ var MS_PER_DAY = 864e5;
313
+ /** Key generation — EC P-256 (plan). WebCrypto DOM names are not in @types/node. */
314
+ var MESH_KEY_ALGORITHM = {
315
+ name: "ECDSA",
316
+ namedCurve: "P-256"
317
+ };
318
+ /** Signing — ECDSA with SHA-256. */
319
+ var MESH_SIGNING_ALGORITHM = {
320
+ name: "ECDSA",
321
+ hash: "SHA-256"
322
+ };
323
+ /** A node id: letters, digits, `.`, `_`, `-`; at most 63 characters; starts with a letter or digit. */
324
+ var NODE_ID_PATTERN = /^[a-z0-9][a-z0-9._-]{0,62}$/i;
325
+ /** Ids no agent may take: the hub's own, whatever the case (D857). */
326
+ var RESERVED_NODE_IDS = new Set(["hub"]);
327
+ /** True for an id an agent may carry: the pattern, and not a reserved name. */
328
+ function isValidAgentNodeId(nodeId) {
329
+ return NODE_ID_PATTERN.test(nodeId) && !RESERVED_NODE_IDS.has(nodeId.toLowerCase());
330
+ }
331
+ function freshSerial() {
332
+ return `00${(0, node_crypto.randomBytes)(16).toString("hex")}`;
333
+ }
334
+ function toPkcs8Pem(pkcs8) {
335
+ return `${require_x509_es.PemConverter.encode(pkcs8, "PRIVATE KEY")}\n`;
336
+ }
337
+ function toCertPem(cert) {
338
+ return `${cert.toString("pem")}\n`;
339
+ }
340
+ async function exportKeyPem(key) {
341
+ return toPkcs8Pem(await node_crypto.webcrypto.subtle.exportKey("pkcs8", key));
342
+ }
343
+ /** SHA-256 fingerprint of the DER cert, colon-hex uppercase (Node style). */
344
+ function caFingerprint(certPem) {
345
+ return new node_crypto.X509Certificate(certPem).fingerprint256;
346
+ }
347
+ /** Compact fingerprint (lowercase hex, no colons). */
348
+ function caFingerprintCompact(certPem) {
349
+ return (0, node_crypto.createHash)("sha256").update(new node_crypto.X509Certificate(certPem).raw).digest("hex");
350
+ }
351
+ async function generateMeshCa(now = /* @__PURE__ */ new Date()) {
352
+ const keys = await node_crypto.webcrypto.subtle.generateKey(MESH_KEY_ALGORITHM, true, ["sign", "verify"]);
353
+ const extensions = [
354
+ new require_x509_es.BasicConstraintsExtension(true, 0, true),
355
+ new require_x509_es.KeyUsagesExtension(require_x509_es.KeyUsageFlags.keyCertSign | require_x509_es.KeyUsageFlags.cRLSign, true),
356
+ await require_x509_es.SubjectKeyIdentifierExtension.create(keys.publicKey)
357
+ ];
358
+ const cert = await require_x509_es.X509CertificateGenerator.createSelfSigned({
359
+ serialNumber: freshSerial(),
360
+ name: `CN=${require_constants$8.MESH_CA_COMMON_NAME}`,
361
+ notBefore: require_x509_es.backdatedNotBefore(now),
362
+ notAfter: new Date(now.getTime() + require_constants$8.MESH_CA_VALIDITY_DAYS * MS_PER_DAY),
363
+ keys,
364
+ signingAlgorithm: MESH_SIGNING_ALGORITHM,
365
+ extensions
366
+ });
367
+ return {
368
+ certPem: toCertPem(cert),
369
+ keyPem: await exportKeyPem(keys.privateKey),
370
+ cert,
371
+ privateKey: keys.privateKey,
372
+ publicKey: keys.publicKey
373
+ };
374
+ }
375
+ async function loadMeshCa(certPem, keyPem) {
376
+ const cert = new require_x509_es.X509Certificate(certPem);
377
+ return {
378
+ certPem,
379
+ keyPem,
380
+ cert,
381
+ privateKey: await node_crypto.webcrypto.subtle.importKey("pkcs8", require_x509_es.PemConverter.decodeFirst(keyPem), MESH_KEY_ALGORITHM, true, ["sign"]),
382
+ publicKey: await cert.publicKey.export(node_crypto.webcrypto)
383
+ };
384
+ }
385
+ /**
386
+ * Issue a leaf from a CSR. CN must be present; when `expectedNodeId` is set
387
+ * it must match. Validity: 30 days.
388
+ */
389
+ async function issueMeshLeafFromCsr(ca, csrPem, opts = {}) {
390
+ const csr = new require_x509_es.Pkcs10CertificateRequest(csrPem);
391
+ if (!await csr.verify(node_crypto.webcrypto)) throw new Error("CSR signature is invalid");
392
+ const cn = subjectCn(csr.subject);
393
+ if (cn === null || cn.length === 0) throw new Error("CSR subject has no CN");
394
+ if (opts.allowReserved !== true && !isValidAgentNodeId(cn)) throw new Error(`CSR CN '${cn}' is not an id an agent may carry`);
395
+ if (opts.expectedNodeId !== void 0 && opts.expectedNodeId !== cn) throw new Error(`CSR CN '${cn}' does not match the token nodeId '${opts.expectedNodeId}'`);
396
+ const now = opts.now ?? /* @__PURE__ */ new Date();
397
+ const validDays = opts.validDays ?? 30;
398
+ const serialNumber = freshSerial();
399
+ const notAfter = new Date(now.getTime() + validDays * MS_PER_DAY);
400
+ const extensions = [
401
+ new require_x509_es.BasicConstraintsExtension(false, void 0, true),
402
+ new require_x509_es.KeyUsagesExtension(require_x509_es.KeyUsageFlags.digitalSignature, true),
403
+ new require_x509_es.ExtendedKeyUsageExtension([require_constants$8.SERVER_AUTH_OID, require_constants$8.CLIENT_AUTH_OID]),
404
+ await require_x509_es.SubjectKeyIdentifierExtension.create(csr.publicKey),
405
+ await require_x509_es.AuthorityKeyIdentifierExtension.create(ca.cert)
406
+ ];
407
+ return {
408
+ certPem: toCertPem(await require_x509_es.X509CertificateGenerator.create({
409
+ serialNumber,
410
+ subject: `CN=${cn}`,
411
+ issuer: ca.cert.subject,
412
+ notBefore: require_x509_es.backdatedNotBefore(now),
413
+ notAfter,
414
+ publicKey: csr.publicKey,
415
+ signingKey: ca.privateKey,
416
+ signingAlgorithm: MESH_SIGNING_ALGORITHM,
417
+ extensions
418
+ })),
419
+ serialNumber,
420
+ notAfter,
421
+ commonName: cn
422
+ };
423
+ }
424
+ /** Issue a leaf for a known nodeID with a freshly generated key pair (tests / hub self). */
425
+ async function issueMeshLeafForNode(ca, nodeId, opts = {}) {
426
+ const keys = await node_crypto.webcrypto.subtle.generateKey(MESH_KEY_ALGORITHM, true, ["sign", "verify"]);
427
+ return {
428
+ ...await issueMeshLeafFromCsr(ca, await createMeshCsrPem(keys, nodeId), {
429
+ expectedNodeId: nodeId,
430
+ now: opts.now,
431
+ validDays: opts.validDays,
432
+ allowReserved: true
433
+ }),
434
+ keyPem: await exportKeyPem(keys.privateKey)
435
+ };
436
+ }
437
+ function subjectCn(subject) {
438
+ return /(?:^|,)\s*CN\s*=\s*([^,]+)/i.exec(subject)?.[1]?.trim() ?? null;
439
+ }
440
+ async function createMeshCsrPem(keys, commonName) {
441
+ return `${(await require_x509_es.Pkcs10CertificateRequestGenerator.create({
442
+ name: `CN=${commonName}`,
443
+ keys,
444
+ signingAlgorithm: MESH_SIGNING_ALGORITHM
445
+ })).toString("pem")}\n`;
446
+ }
447
+ async function generateMeshKeyPair() {
448
+ return node_crypto.webcrypto.subtle.generateKey(MESH_KEY_ALGORITHM, true, ["sign", "verify"]);
449
+ }
450
+ async function exportMeshPrivateKeyPem(key) {
451
+ return exportKeyPem(key);
452
+ }
453
+ //#endregion
301
454
  //#region src/kernel/moleculer/mesh-mtls/mesh-ca-keeper.ts
302
- var SLOT$2 = Symbol.for("camstack.mesh.ca");
455
+ var SLOT$3 = Symbol.for("camstack.mesh.ca");
303
456
  var NOT_LOADED = {
304
457
  state: "unavailable",
305
458
  reason: "not-loaded"
@@ -311,10 +464,10 @@ function isState(value) {
311
464
  return state === "unavailable" && typeof Reflect.get(value, "reason") === "string";
312
465
  }
313
466
  function setProcessMeshCa(state) {
314
- Reflect.set(globalThis, SLOT$2, state);
467
+ Reflect.set(globalThis, SLOT$3, state);
315
468
  }
316
469
  function getProcessMeshCaState() {
317
- const value = Reflect.get(globalThis, SLOT$2);
470
+ const value = Reflect.get(globalThis, SLOT$3);
318
471
  return isState(value) ? value : NOT_LOADED;
319
472
  }
320
473
  function requireProcessMeshCa() {
@@ -420,7 +573,7 @@ async function loadOrGenerateMeshCa(deps) {
420
573
  try {
421
574
  return {
422
575
  state: "ready",
423
- ca: await require_agent_https.loadMeshCa(certPem, entry.value)
576
+ ca: await loadMeshCa(certPem, entry.value)
424
577
  };
425
578
  } catch (err) {
426
579
  return {
@@ -430,12 +583,12 @@ async function loadOrGenerateMeshCa(deps) {
430
583
  }
431
584
  }
432
585
  case "missing": try {
433
- const generated = await require_agent_https.generateMeshCa();
586
+ const generated = await generateMeshCa();
434
587
  await deps.secrets.put(require_constants$8.MESH_CA_KEY_REF, generated.keyPem);
435
588
  await deps.writeMeshCaCert(generated.certPem);
436
589
  return {
437
590
  state: "ready",
438
- ca: await require_agent_https.loadMeshCa(generated.certPem, generated.keyPem)
591
+ ca: await loadMeshCa(generated.certPem, generated.keyPem)
439
592
  };
440
593
  } catch (err) {
441
594
  return {
@@ -456,10 +609,10 @@ async function loadOrGenerateMeshCa(deps) {
456
609
  var MeshCrl = class {
457
610
  serials = /* @__PURE__ */ new Set();
458
611
  revoke(serialNumber) {
459
- this.serials.add(normalizeSerial(serialNumber));
612
+ this.serials.add(normalizeSerial$1(serialNumber));
460
613
  }
461
614
  isRevoked(serialNumber) {
462
- return this.serials.has(normalizeSerial(serialNumber));
615
+ return this.serials.has(normalizeSerial$1(serialNumber));
463
616
  }
464
617
  list() {
465
618
  return [...this.serials];
@@ -467,21 +620,478 @@ var MeshCrl = class {
467
620
  /** Restore from persisted serials (system-settings). */
468
621
  replaceAll(serials) {
469
622
  this.serials.clear();
470
- for (const s of serials) this.serials.add(normalizeSerial(s));
623
+ for (const s of serials) this.serials.add(normalizeSerial$1(s));
471
624
  }
472
625
  };
473
- function normalizeSerial(serial) {
626
+ function normalizeSerial$1(serial) {
474
627
  return serial.replace(/^0x/i, "").replace(/:/g, "").toLowerCase();
475
628
  }
476
- var SLOT$1 = Symbol.for("camstack.mesh.crl");
629
+ var SLOT$2 = Symbol.for("camstack.mesh.crl");
477
630
  function processMeshCrl() {
478
- const existing = Reflect.get(globalThis, SLOT$1);
631
+ const existing = Reflect.get(globalThis, SLOT$2);
479
632
  if (existing instanceof MeshCrl) return existing;
480
633
  const crl = new MeshCrl();
481
- Reflect.set(globalThis, SLOT$1, crl);
634
+ Reflect.set(globalThis, SLOT$2, crl);
482
635
  return crl;
483
636
  }
484
637
  //#endregion
638
+ //#region src/kernel/moleculer/mesh-mtls/mesh-certificate-registry.ts
639
+ /**
640
+ * The hub's record of every mesh leaf (D856): which certificate each node holds,
641
+ * when it expires, and which serials are revoked.
642
+ *
643
+ * Three ways a row appears:
644
+ * - `enroll` / `renewal` / `boot` - the hub issued it and wrote it down at the
645
+ * moment of issuing (the authoritative record);
646
+ * - `observed` - a node enrolled before this record existed (or by a path that
647
+ * did not write it) presented this leaf on its LIVE mutual-TLS connection.
648
+ *
649
+ * Revoked serials are persisted here and replayed into the in-memory CRL at boot,
650
+ * so a revocation survives a hub restart. Hub only: agents persist none of it.
651
+ */
652
+ /**
653
+ * @durable class=config owner=system-config
654
+ * write="the hub records every mesh leaf it issues (enroll, renewal, boot) and every
655
+ * leaf a connected node is observed presenting; a revocation stamps revokedAt"
656
+ * retention="a revoked or expired row is kept 90 days past its end, then reaped; a
657
+ * live row is never deleted. Forgetting a node does not delete its rows."
658
+ */
659
+ var MESH_NODE_CERTIFICATES_COLLECTION = "mesh_node_certificates";
660
+ var MESH_NODE_CERTIFICATES_COLUMNS = [
661
+ {
662
+ name: "id",
663
+ type: "TEXT",
664
+ primaryKey: true,
665
+ notNull: true
666
+ },
667
+ {
668
+ name: "nodeId",
669
+ type: "TEXT",
670
+ notNull: true
671
+ },
672
+ {
673
+ name: "serial",
674
+ type: "TEXT",
675
+ notNull: true
676
+ },
677
+ {
678
+ name: "fingerprint",
679
+ type: "TEXT",
680
+ notNull: true
681
+ },
682
+ {
683
+ name: "notBefore",
684
+ type: "INTEGER",
685
+ notNull: true
686
+ },
687
+ {
688
+ name: "notAfter",
689
+ type: "INTEGER",
690
+ notNull: true
691
+ },
692
+ {
693
+ name: "issuedAt",
694
+ type: "INTEGER",
695
+ notNull: true
696
+ },
697
+ {
698
+ name: "issuedVia",
699
+ type: "TEXT",
700
+ notNull: true
701
+ },
702
+ {
703
+ name: "revokedAt",
704
+ type: "INTEGER"
705
+ },
706
+ {
707
+ name: "revokedReason",
708
+ type: "TEXT"
709
+ }
710
+ ];
711
+ var RETENTION_MS = 90 * 864e5;
712
+ /**
713
+ * A leaf the hub signed for a renewal that did not complete. It must not be the node's
714
+ * `current` leaf, but it is NOT on the CRL: the node may still hold it (the swap
715
+ * could have landed without the hub seeing it), and cutting it off would be the
716
+ * outage the hand-over exists to prevent. If the node is later seen presenting it, it
717
+ * is reinstated.
718
+ */
719
+ var RENEWAL_ABANDONED = "renewal-abandoned";
720
+ var VIAS = [
721
+ "enroll",
722
+ "pairing",
723
+ "renewal",
724
+ "boot",
725
+ "observed"
726
+ ];
727
+ /** CN, serial, fingerprint and validity of a leaf PEM (or DER). */
728
+ function describeMeshLeaf(cert) {
729
+ const x509 = new node_crypto.X509Certificate(cert);
730
+ return {
731
+ cn: subjectCn(x509.subject) ?? "",
732
+ serial: x509.serialNumber,
733
+ fingerprint: x509.fingerprint256,
734
+ notBefore: Date.parse(x509.validFrom),
735
+ notAfter: Date.parse(x509.validTo)
736
+ };
737
+ }
738
+ function normalizeSerial(serial) {
739
+ return serial.replace(/^0x/i, "").replace(/:/g, "").toLowerCase();
740
+ }
741
+ function parse$1(data) {
742
+ const str = (k) => {
743
+ const v = data[k];
744
+ return typeof v === "string" && v.length > 0 ? v : null;
745
+ };
746
+ const num = (k) => {
747
+ const v = data[k];
748
+ return typeof v === "number" && Number.isFinite(v) ? v : null;
749
+ };
750
+ const nodeId = str("nodeId");
751
+ const serial = str("serial");
752
+ const fingerprint = str("fingerprint");
753
+ const notBefore = num("notBefore");
754
+ const notAfter = num("notAfter");
755
+ const issuedAt = num("issuedAt");
756
+ if (nodeId === null || serial === null || fingerprint === null || notBefore === null || notAfter === null || issuedAt === null) return null;
757
+ return {
758
+ nodeId,
759
+ serial,
760
+ fingerprint,
761
+ notBefore,
762
+ notAfter,
763
+ issuedAt,
764
+ issuedVia: VIAS.find((v) => v === data["issuedVia"]) ?? "observed",
765
+ revokedAt: num("revokedAt"),
766
+ revokedReason: str("revokedReason")
767
+ };
768
+ }
769
+ var MeshCertificateRegistry = class {
770
+ store;
771
+ deps;
772
+ rows = /* @__PURE__ */ new Map();
773
+ constructor(store, deps = {}) {
774
+ this.store = store;
775
+ this.deps = deps;
776
+ }
777
+ recordToBody(record) {
778
+ return {
779
+ nodeId: record.nodeId,
780
+ serial: record.serial,
781
+ fingerprint: record.fingerprint,
782
+ notBefore: record.notBefore,
783
+ notAfter: record.notAfter,
784
+ issuedAt: record.issuedAt,
785
+ issuedVia: record.issuedVia,
786
+ revokedAt: record.revokedAt,
787
+ revokedReason: record.revokedReason
788
+ };
789
+ }
790
+ now() {
791
+ return (this.deps.now ?? Date.now)();
792
+ }
793
+ async load() {
794
+ const kind = this.deps.meshKind ?? null;
795
+ if (kind !== null) {
796
+ const page = await kind.query({ limit: 1e4 });
797
+ for (const row of page.records) {
798
+ const { fingerprint: _fp, ...body } = row.data;
799
+ const record = parse$1({
800
+ ...body,
801
+ fingerprint: row.id
802
+ });
803
+ if (record !== null) this.rows.set(record.fingerprint, record);
804
+ }
805
+ return;
806
+ }
807
+ const rows = await this.store.query.query({ collection: MESH_NODE_CERTIFICATES_COLLECTION });
808
+ for (const row of rows) {
809
+ const record = parse$1(row.data);
810
+ if (record !== null) this.rows.set(record.fingerprint, record);
811
+ }
812
+ }
813
+ /** Write down a leaf the hub just issued. Idempotent per fingerprint. */
814
+ async recordIssued(nodeId, certPem, via) {
815
+ const leaf = describeMeshLeaf(certPem);
816
+ const existing = this.rows.get(leaf.fingerprint);
817
+ if (existing !== void 0) return existing;
818
+ const record = {
819
+ nodeId,
820
+ serial: leaf.serial,
821
+ fingerprint: leaf.fingerprint,
822
+ notBefore: leaf.notBefore,
823
+ notAfter: leaf.notAfter,
824
+ issuedAt: this.now(),
825
+ issuedVia: via,
826
+ revokedAt: null,
827
+ revokedReason: null
828
+ };
829
+ await this.insert(record);
830
+ this.deps.logger?.info("Mesh certificate recorded", {
831
+ tags: { nodeId },
832
+ meta: {
833
+ via,
834
+ serial: leaf.serial,
835
+ notAfter: new Date(leaf.notAfter).toISOString()
836
+ }
837
+ });
838
+ return record;
839
+ }
840
+ /**
841
+ * A node was seen presenting `leaf` on its live connection. A leaf the hub already
842
+ * knows is left alone; an unknown one is recorded `observed` (a node enrolled
843
+ * before this record existed).
844
+ */
845
+ async recordObserved(nodeId, leaf) {
846
+ const known = this.rows.get(leaf.fingerprint);
847
+ if (known !== void 0) {
848
+ if (known.revokedReason !== "renewal-abandoned") return known.revokedAt === null ? this.abandonRenewalsNewerThan(known) : false;
849
+ const reinstated = {
850
+ ...known,
851
+ revokedAt: null,
852
+ revokedReason: null
853
+ };
854
+ this.rows.set(known.fingerprint, reinstated);
855
+ await this.persist(reinstated);
856
+ this.deps.logger?.warn("An abandoned renewal leaf is in use - reinstated", {
857
+ tags: { nodeId },
858
+ meta: { serial: known.serial }
859
+ });
860
+ return true;
861
+ }
862
+ const record = {
863
+ nodeId,
864
+ serial: leaf.serial,
865
+ fingerprint: leaf.fingerprint,
866
+ notBefore: leaf.notBefore,
867
+ notAfter: leaf.notAfter,
868
+ issuedAt: this.now(),
869
+ issuedVia: "observed",
870
+ revokedAt: null,
871
+ revokedReason: null
872
+ };
873
+ await this.insert(record);
874
+ this.deps.logger?.info("Mesh certificate observed on a live connection and recorded", {
875
+ tags: { nodeId },
876
+ meta: {
877
+ serial: leaf.serial,
878
+ fingerprint: leaf.fingerprint
879
+ }
880
+ });
881
+ return true;
882
+ }
883
+ list(nodeId) {
884
+ return [...this.rows.values()].filter((r) => nodeId === void 0 || r.nodeId === nodeId).toSorted((a, b) => b.issuedAt - a.issuedAt);
885
+ }
886
+ /** The newest non-revoked leaf of a node, or `undefined`. */
887
+ currentFor(nodeId) {
888
+ return this.list(nodeId).find((r) => r.revokedAt === null);
889
+ }
890
+ /** Every non-revoked leaf of a node (a renewal in flight has two). */
891
+ liveFor(nodeId) {
892
+ return this.list(nodeId).filter((r) => r.revokedAt === null);
893
+ }
894
+ /** Stamp a leaf revoked (and mirror it into `crl`). `false` when unknown or already revoked. */
895
+ async revoke(fingerprint, reason, crl) {
896
+ const record = this.rows.get(fingerprint);
897
+ if (record === void 0 || record.revokedAt !== null) return false;
898
+ const revoked = {
899
+ ...record,
900
+ revokedAt: this.now(),
901
+ revokedReason: reason
902
+ };
903
+ this.rows.set(fingerprint, revoked);
904
+ crl?.revoke(record.serial);
905
+ await this.persist(revoked);
906
+ this.deps.logger?.warn("Mesh certificate revoked", {
907
+ tags: { nodeId: record.nodeId },
908
+ meta: {
909
+ serial: record.serial,
910
+ reason
911
+ }
912
+ });
913
+ return true;
914
+ }
915
+ /**
916
+ * Operator revocation of a whole node: EVERY leaf of the node that is not already on the
917
+ * CRL goes on it - the current one, an observed one, a renewal one, and a leaf that was set
918
+ * aside (`renewal-abandoned`: a copy of it may sit on a stolen box, and it must not stay
919
+ * valid just because the hub once set it aside). Returns the serials put on the CRL.
920
+ * A leaf revoked this way is never reinstated by `recordObserved`.
921
+ */
922
+ async revokeAllForNode(nodeId, reason, crl, keepFingerprint) {
923
+ const serials = [];
924
+ for (const record of this.list(nodeId)) {
925
+ if (keepFingerprint !== void 0 && record.fingerprint === keepFingerprint) continue;
926
+ if (record.revokedAt !== null && record.revokedReason !== "renewal-abandoned") continue;
927
+ const revoked = {
928
+ ...record,
929
+ revokedAt: record.revokedAt ?? this.now(),
930
+ revokedReason: reason
931
+ };
932
+ this.rows.set(record.fingerprint, revoked);
933
+ crl.revoke(record.serial);
934
+ await this.persist(revoked);
935
+ serials.push(record.serial);
936
+ }
937
+ if (serials.length > 0) this.deps.logger?.warn("Every mesh certificate of the node revoked", {
938
+ tags: { nodeId },
939
+ meta: {
940
+ serials,
941
+ reason
942
+ }
943
+ });
944
+ return serials;
945
+ }
946
+ /**
947
+ * At boot: a node with TWO live leaves had a renewal in flight when the hub stopped. The
948
+ * newer (renewal) one is set aside - it is not the node's current leaf until the node is
949
+ * seen presenting it, which reinstates it. It is NOT put on the CRL.
950
+ */
951
+ async settleInterruptedRenewals() {
952
+ let settled = 0;
953
+ const byNode = /* @__PURE__ */ new Map();
954
+ for (const record of this.rows.values()) {
955
+ if (record.revokedAt !== null) continue;
956
+ byNode.set(record.nodeId, [...byNode.get(record.nodeId) ?? [], record]);
957
+ }
958
+ for (const records of byNode.values()) {
959
+ if (records.length < 2) continue;
960
+ for (const record of records) if (record.issuedVia === "renewal" && await this.abandon(record.fingerprint)) settled += 1;
961
+ }
962
+ return settled;
963
+ }
964
+ /** Set a never-completed renewal leaf aside (not current, NOT on the CRL). */
965
+ /** Fingerprints of renewal leaves whose handover is running right now (this process only). */
966
+ renewalsInFlight = /* @__PURE__ */ new Set();
967
+ /**
968
+ * A renewal's leaf is "in flight" from signing until the handover ends. While it is, a node seen
969
+ * presenting its OLD leaf is simply not swapped yet: the new leaf is not set aside (that would
970
+ * flap set-aside / reinstate on the node's first connection with it).
971
+ */
972
+ beginRenewal(fingerprint) {
973
+ this.renewalsInFlight.add(fingerprint);
974
+ }
975
+ endRenewal(fingerprint) {
976
+ this.renewalsInFlight.delete(fingerprint);
977
+ }
978
+ async abandonRenewalsNewerThan(presented) {
979
+ let changed = false;
980
+ for (const record of this.liveFor(presented.nodeId)) {
981
+ if (record.fingerprint === presented.fingerprint) continue;
982
+ if (record.issuedVia !== "renewal" || record.issuedAt <= presented.issuedAt) continue;
983
+ if (this.renewalsInFlight.has(record.fingerprint)) continue;
984
+ if (await this.abandon(record.fingerprint)) changed = true;
985
+ }
986
+ return changed;
987
+ }
988
+ async abandon(fingerprint) {
989
+ const record = this.rows.get(fingerprint);
990
+ if (record === void 0 || record.revokedAt !== null) return false;
991
+ const abandoned = {
992
+ ...record,
993
+ revokedAt: this.now(),
994
+ revokedReason: RENEWAL_ABANDONED
995
+ };
996
+ this.rows.set(fingerprint, abandoned);
997
+ await this.persist(abandoned);
998
+ this.deps.logger?.warn("Renewal leaf set aside (not current, not on the CRL)", {
999
+ tags: { nodeId: record.nodeId },
1000
+ meta: { serial: record.serial }
1001
+ });
1002
+ return true;
1003
+ }
1004
+ /** Replay every persisted revocation into `crl` (hub boot). Set-aside leaves are not revocations. */
1005
+ restoreCrl(crl) {
1006
+ let restored = 0;
1007
+ for (const record of this.rows.values()) {
1008
+ if (record.revokedAt === null || record.revokedReason === "renewal-abandoned") continue;
1009
+ crl.revoke(record.serial);
1010
+ restored += 1;
1011
+ }
1012
+ return restored;
1013
+ }
1014
+ /** Is `serial` listed as revoked here? */
1015
+ isRevoked(serial) {
1016
+ const wanted = normalizeSerial(serial);
1017
+ for (const record of this.rows.values()) if (record.revokedAt !== null && record.revokedReason !== "renewal-abandoned" && normalizeSerial(record.serial) === wanted) return true;
1018
+ return false;
1019
+ }
1020
+ async reap() {
1021
+ const cutoff = this.now() - RETENTION_MS;
1022
+ const dead = [...this.rows.values()].filter((r) => (r.revokedAt ?? r.notAfter) < cutoff);
1023
+ for (const r of dead) {
1024
+ this.rows.delete(r.fingerprint);
1025
+ await this.deleteRow(r.fingerprint);
1026
+ }
1027
+ return dead.length;
1028
+ }
1029
+ async insert(record) {
1030
+ this.rows.set(record.fingerprint, record);
1031
+ const kind = this.deps.meshKind ?? null;
1032
+ if (kind !== null) {
1033
+ const parsed = require_agent_https.systemConfigRecordKinds["mesh-node-certificates"].schema.safeParse(this.recordToBody(record));
1034
+ if (!parsed.success) throw new Error(parsed.error.message);
1035
+ await kind.put({
1036
+ id: record.fingerprint,
1037
+ data: parsed.data
1038
+ });
1039
+ return;
1040
+ }
1041
+ await this.store.insert.mutate({
1042
+ collection: MESH_NODE_CERTIFICATES_COLLECTION,
1043
+ record: {
1044
+ id: record.fingerprint,
1045
+ data: { ...record }
1046
+ }
1047
+ });
1048
+ }
1049
+ async deleteRow(fingerprint) {
1050
+ const kind = this.deps.meshKind ?? null;
1051
+ if (kind !== null) {
1052
+ await kind.delete(fingerprint);
1053
+ return;
1054
+ }
1055
+ await this.store.delete.mutate({
1056
+ collection: MESH_NODE_CERTIFICATES_COLLECTION,
1057
+ key: fingerprint
1058
+ });
1059
+ }
1060
+ async persist(record) {
1061
+ try {
1062
+ const kind = this.deps.meshKind ?? null;
1063
+ if (kind !== null) {
1064
+ const parsed = require_agent_https.systemConfigRecordKinds["mesh-node-certificates"].schema.safeParse(this.recordToBody(record));
1065
+ if (!parsed.success) throw new Error(parsed.error.message);
1066
+ await kind.put({
1067
+ id: record.fingerprint,
1068
+ data: parsed.data
1069
+ });
1070
+ return;
1071
+ }
1072
+ await this.store.update.mutate({
1073
+ collection: MESH_NODE_CERTIFICATES_COLLECTION,
1074
+ id: record.fingerprint,
1075
+ data: { ...record }
1076
+ });
1077
+ } catch (error) {
1078
+ this.deps.logger?.error("Mesh certificate write failed - the change holds until restart", {
1079
+ tags: { nodeId: record.nodeId },
1080
+ meta: { error: error instanceof Error ? error.message : String(error) }
1081
+ });
1082
+ }
1083
+ }
1084
+ };
1085
+ var SLOT$1 = Symbol.for("camstack.mesh.certificate-registry");
1086
+ function setProcessMeshCertificateRegistry(registry) {
1087
+ if (registry === null) Reflect.deleteProperty(globalThis, SLOT$1);
1088
+ else Reflect.set(globalThis, SLOT$1, registry);
1089
+ }
1090
+ function getProcessMeshCertificateRegistry() {
1091
+ const value = Reflect.get(globalThis, SLOT$1);
1092
+ return value !== null && typeof value === "object" && typeof Reflect.get(value, "recordIssued") === "function" ? value : null;
1093
+ }
1094
+ //#endregion
485
1095
  //#region src/kernel/moleculer/mesh-mtls/mesh-tls-gate.ts
486
1096
  var STATE_SLOT = Symbol.for("camstack.mesh.tls-listener-state");
487
1097
  function setProcessMeshTlsListenerState(state) {
@@ -624,7 +1234,7 @@ async function runRenewal(deps, inFlight) {
624
1234
  }
625
1235
  let issued;
626
1236
  try {
627
- issued = await require_agent_https.issueMeshLeafFromCsr(deps.ca, csrPem, { expectedNodeId: nodeId });
1237
+ issued = await issueMeshLeafFromCsr(deps.ca, csrPem, { expectedNodeId: nodeId });
628
1238
  await deps.registry.recordIssued(nodeId, issued.certPem, "renewal");
629
1239
  log.info("Mesh renewal: new leaf signed and recorded", {
630
1240
  tags,
@@ -636,7 +1246,7 @@ async function runRenewal(deps, inFlight) {
636
1246
  } catch (error) {
637
1247
  return fail("issue", message(error), true);
638
1248
  }
639
- const newLeaf = require_agent_https.describeMeshLeaf(issued.certPem);
1249
+ const newLeaf = describeMeshLeaf(issued.certPem);
640
1250
  deps.registry.beginRenewal(newLeaf.fingerprint);
641
1251
  inFlight.fingerprint = newLeaf.fingerprint;
642
1252
  let resolveRegistered = () => void 0;
@@ -86154,7 +86764,7 @@ function peerIdentity(socket) {
86154
86764
  if (cert == null || typeof cert !== "object" || !("raw" in cert) || !cert.raw) return null;
86155
86765
  try {
86156
86766
  const x509 = new node_crypto.X509Certificate(cert.raw);
86157
- const cn = require_agent_https.subjectCn(x509.subject) ?? require_agent_https.subjectCn(`CN=${cert.subject?.CN ?? ""}`);
86767
+ const cn = subjectCn(x509.subject) ?? subjectCn(`CN=${cert.subject?.CN ?? ""}`);
86158
86768
  if (cn === null || cn.length === 0) return null;
86159
86769
  return {
86160
86770
  cn,
@@ -86682,7 +87292,7 @@ function newPairingId() {
86682
87292
  }
86683
87293
  /** The hub's commitment to its nonce, bound to the CA certificate it offers. */
86684
87294
  function computePairingCommitment(caCertPem, hubNonce) {
86685
- return (0, node_crypto.createHash)("sha256").update(`${PAIRING_DOMAIN}|commit|${require_agent_https.caFingerprintCompact(caCertPem)}|${hubNonce}`, "utf8").digest("hex");
87295
+ return (0, node_crypto.createHash)("sha256").update(`${PAIRING_DOMAIN}|commit|${caFingerprintCompact(caCertPem)}|${hubNonce}`, "utf8").digest("hex");
86686
87296
  }
86687
87297
  function commitmentsEqual(expected, presented) {
86688
87298
  return constantTimeEqual(expected, presented);
@@ -86692,7 +87302,7 @@ function computePairingSas(input) {
86692
87302
  const value = (0, node_crypto.createHash)("sha256").update([
86693
87303
  PAIRING_DOMAIN,
86694
87304
  "sas",
86695
- require_agent_https.caFingerprintCompact(input.caCertPem),
87305
+ caFingerprintCompact(input.caCertPem),
86696
87306
  input.agentPublicKeySpki,
86697
87307
  input.hubNonce,
86698
87308
  input.agentNonce
@@ -86708,7 +87318,7 @@ function constantTimeEqual(expected, presented) {
86708
87318
  async function describeCsr(csrPem) {
86709
87319
  const csr = new require_x509_es.Pkcs10CertificateRequest(csrPem);
86710
87320
  if (!await csr.verify(node_crypto.webcrypto)) throw new Error("the agent CSR signature is invalid");
86711
- const cn = require_agent_https.subjectCn(csr.subject);
87321
+ const cn = subjectCn(csr.subject);
86712
87322
  if (cn === null || cn.length === 0) throw new Error("the agent CSR has no CN");
86713
87323
  return {
86714
87324
  commonName: cn,
@@ -87019,23 +87629,23 @@ var AgentPairing = class {
87019
87629
  async offer(body) {
87020
87630
  this.expireIfDue();
87021
87631
  if (this.deps.isPaired()) return fail(409, "already-paired", "this agent is paired — unpair it first (from the hub or here)");
87022
- if (!require_agent_https.isValidAgentNodeId(this.deps.nodeId)) return fail(409, "invalid-node-id", `this agent's node id "${this.deps.nodeId}" cannot be paired - rename the agent`);
87632
+ if (!isValidAgentNodeId(this.deps.nodeId)) return fail(409, "invalid-node-id", `this agent's node id "${this.deps.nodeId}" cannot be paired - rename the agent`);
87023
87633
  const request = parseOffer(body);
87024
87634
  if (request === null) return fail(400, "bad-offer", "the offer is malformed");
87025
87635
  if (request.protocol !== 1) return fail(400, "unsupported-protocol", `pairing protocol ${String(request.protocol)} is not supported`);
87026
87636
  if (readCaCertificate(request.hubCaCertPem, this.now()) === null) return fail(400, "bad-ca", "the offered CA is not a valid self-signed CA certificate");
87027
87637
  if (!/^[0-9a-f]{64}$/.test(request.commitment)) return fail(400, "bad-offer", "the commitment is malformed");
87028
87638
  if (!isHttpUrl(request.hubUrl)) return fail(400, "bad-offer", "hubUrl is not an http(s) URL");
87029
- const caFingerprint = require_agent_https.caFingerprintCompact(request.hubCaCertPem);
87639
+ const caFingerprint = caFingerprintCompact(request.hubCaCertPem);
87030
87640
  const refused = this.checkOfferSignature(request, caFingerprint);
87031
87641
  if (refused !== null) return refused;
87032
87642
  const rationed = this.rationOffer(caFingerprint);
87033
87643
  if (rationed !== null) return rationed;
87034
87644
  for (const existing of [...this.sessions.values()]) if (existing.hub.caFingerprint === caFingerprint) this.end(existing, "failed");
87035
87645
  if (this.sessions.size >= 4 && !this.makeRoom()) return fail(409, "too-many-pending", "too many pairings are pending on this agent");
87036
- const keys = await require_agent_https.generateMeshKeyPair();
87037
- const csrPem = await require_agent_https.createMeshCsrPem(keys, this.deps.nodeId);
87038
- const keyPem = await require_agent_https.exportMeshPrivateKeyPem(keys.privateKey);
87646
+ const keys = await generateMeshKeyPair();
87647
+ const csrPem = await createMeshCsrPem(keys, this.deps.nodeId);
87648
+ const keyPem = await exportMeshPrivateKeyPem(keys.privateKey);
87039
87649
  const publicKeySpki = Buffer.from(await node_crypto.webcrypto.subtle.exportKey("spki", keys.publicKey)).toString("base64");
87040
87650
  if (this.sessions.size >= 4 && !this.makeRoom()) return fail(409, "too-many-pending", "too many pairings are pending on this agent");
87041
87651
  const session = {
@@ -87375,7 +87985,7 @@ var AgentPairing = class {
87375
87985
  const leaf = new node_crypto.X509Certificate(leafPem);
87376
87986
  const ca = new node_crypto.X509Certificate(session.hub.caCertPem);
87377
87987
  if (!leaf.verify(ca.publicKey)) return fail(400, "bad-leaf", "the certificate is not signed by the offered CA");
87378
- if (require_agent_https.subjectCn(leaf.subject.replaceAll("\n", ",")) !== this.deps.nodeId) return fail(400, "bad-leaf", `the certificate is not issued for "${this.deps.nodeId}"`);
87988
+ if (subjectCn(leaf.subject.replaceAll("\n", ",")) !== this.deps.nodeId) return fail(400, "bad-leaf", `the certificate is not issued for "${this.deps.nodeId}"`);
87379
87989
  if (!leaf.checkPrivateKey((0, node_crypto.createPrivateKey)(session.keyPem))) return fail(400, "bad-leaf", "the certificate does not match this agent's private key");
87380
87990
  if (Date.parse(leaf.validTo) <= this.now()) return fail(400, "bad-leaf", "the certificate is already expired");
87381
87991
  } catch {
@@ -87433,7 +88043,7 @@ function field(body, key) {
87433
88043
  }
87434
88044
  function caFingerprintOf(pem) {
87435
88045
  try {
87436
- return require_agent_https.caFingerprintCompact(pem);
88046
+ return caFingerprintCompact(pem);
87437
88047
  } catch {
87438
88048
  return null;
87439
88049
  }
@@ -87528,7 +88138,7 @@ var HubPairing = class {
87528
88138
  use: PAIRING_OFFER_USE,
87529
88139
  agentNodeId: hello.nodeId,
87530
88140
  hubNodeId: this.deps.hubNodeId,
87531
- caFingerprint: require_agent_https.caFingerprintCompact(ca.certPem),
88141
+ caFingerprint: caFingerprintCompact(ca.certPem),
87532
88142
  commitment,
87533
88143
  hubUrl,
87534
88144
  hubMeshAddress,
@@ -87645,14 +88255,14 @@ var HubPairing = class {
87645
88255
  }
87646
88256
  async complete(session) {
87647
88257
  const ca = this.deps.ca();
87648
- if (ca === null || require_agent_https.caFingerprintCompact(ca.certPem) !== require_agent_https.caFingerprintCompact(session.caCertPem)) {
88258
+ if (ca === null || caFingerprintCompact(ca.certPem) !== caFingerprintCompact(session.caCertPem)) {
87649
88259
  await this.cancel(session, "failed", "the mesh CA changed during the pairing");
87650
88260
  return;
87651
88261
  }
87652
88262
  session.state = "completing";
87653
88263
  let issuedPem = null;
87654
88264
  try {
87655
- const leaf = await require_agent_https.issueMeshLeafFromCsr(ca, session.csrPem, { expectedNodeId: session.nodeId });
88265
+ const leaf = await issueMeshLeafFromCsr(ca, session.csrPem, { expectedNodeId: session.nodeId });
87656
88266
  issuedPem = leaf.certPem;
87657
88267
  await this.deps.recordIssued(session.nodeId, leaf.certPem);
87658
88268
  session.issued = true;
@@ -87664,7 +88274,7 @@ var HubPairing = class {
87664
88274
  hubNonce: session.hubNonce,
87665
88275
  agentNonce: session.agentNonce,
87666
88276
  leafFingerprint: leafFingerprintCompact(leaf.certPem),
87667
- caFingerprint: require_agent_https.caFingerprintCompact(ca.certPem),
88277
+ caFingerprint: caFingerprintCompact(ca.certPem),
87668
88278
  hubMeshAddress: session.hubMeshAddress,
87669
88279
  hubUrl: session.hubUrl,
87670
88280
  iat: this.now(),
@@ -87718,7 +88328,7 @@ var HubPairing = class {
87718
88328
  }
87719
88329
  }
87720
88330
  assertNodeIdUsable(nodeId) {
87721
- if (!require_agent_https.isValidAgentNodeId(nodeId)) throw new Error(`"${nodeId}" cannot be an agent node id (letters, digits, . _ - ; not "hub"; at most 63 characters)`);
88331
+ if (!isValidAgentNodeId(nodeId)) throw new Error(`"${nodeId}" cannot be an agent node id (letters, digits, . _ - ; not "hub"; at most 63 characters)`);
87722
88332
  if (this.deps.isNodeConnected(nodeId)) throw new Error(`a node called "${nodeId}" is already connected to this hub — unpair it first`);
87723
88333
  const lower = nodeId.toLowerCase();
87724
88334
  const clash = (this.deps.knownNodeIds?.() ?? []).find((known) => known !== nodeId && known.toLowerCase() === lower);
@@ -87903,7 +88513,7 @@ var SystemConfigAddon = class extends require_dist.BaseAddon {
87903
88513
  };
87904
88514
  }
87905
88515
  async onShutdown() {
87906
- require_agent_https.setProcessMeshCertificateRegistry(null);
88516
+ setProcessMeshCertificateRegistry(null);
87907
88517
  setProcessMeshTlsListenerState(null);
87908
88518
  require_agent_https.setProcessAgentHttpsNames(null);
87909
88519
  this.stoppedMesh = true;
@@ -87934,14 +88544,14 @@ var SystemConfigAddon = class extends require_dist.BaseAddon {
87934
88544
  this.loadAgentHttpsNames(store, records);
87935
88545
  try {
87936
88546
  if (records === void 0) await store.declareCollection.mutate({
87937
- collection: require_agent_https.MESH_NODE_CERTIFICATES_COLLECTION,
87938
- columns: require_agent_https.MESH_NODE_CERTIFICATES_COLUMNS,
88547
+ collection: MESH_NODE_CERTIFICATES_COLLECTION,
88548
+ columns: MESH_NODE_CERTIFICATES_COLUMNS,
87939
88549
  indexes: [{
87940
88550
  name: "idx_mesh_node_certificates_node",
87941
88551
  columns: ["nodeId"]
87942
88552
  }]
87943
88553
  });
87944
- const registry = new require_agent_https.MeshCertificateRegistry(store, {
88554
+ const registry = new MeshCertificateRegistry(store, {
87945
88555
  logger: this.ctx.logger,
87946
88556
  meshKind
87947
88557
  });
@@ -87949,7 +88559,7 @@ var SystemConfigAddon = class extends require_dist.BaseAddon {
87949
88559
  const restored = registry.restoreCrl(processMeshCrl());
87950
88560
  const settled = await registry.settleInterruptedRenewals();
87951
88561
  if (settled > 0) this.ctx.logger.warn("A mesh renewal was interrupted by a hub restart - its new leaf was set aside", { meta: { settled } });
87952
- require_agent_https.setProcessMeshCertificateRegistry(registry);
88562
+ setProcessMeshCertificateRegistry(registry);
87953
88563
  if (restored > 0) this.ctx.logger.info("Mesh revocations restored into the CRL", { meta: { restored } });
87954
88564
  return registry;
87955
88565
  } catch (err) {
@@ -87983,7 +88593,7 @@ var SystemConfigAddon = class extends require_dist.BaseAddon {
87983
88593
  await openMeshTlsWhenRevocationsLoaded({
87984
88594
  loadRegistry: () => this.initMeshCertificateRegistry(),
87985
88595
  open: async (registry) => {
87986
- const hubLeaf = await require_agent_https.issueMeshLeafForNode(ca, "hub");
88596
+ const hubLeaf = await issueMeshLeafForNode(ca, "hub");
87987
88597
  await registry.recordIssued("hub", hubLeaf.certPem, "boot").catch((err) => {
87988
88598
  this.ctx.logger.warn("Hub mesh leaf could not be recorded", { meta: { error: err instanceof Error ? err.message : String(err) } });
87989
88599
  });
@@ -88290,8 +88900,11 @@ exports.AGENT_UI_UNLOCK_VERSION = AGENT_UI_UNLOCK_VERSION;
88290
88900
  exports.AgentPairing = AgentPairing;
88291
88901
  exports.Errors = Errors;
88292
88902
  exports.HubPairing = HubPairing;
88903
+ exports.MESH_NODE_CERTIFICATES_COLLECTION = MESH_NODE_CERTIFICATES_COLLECTION;
88904
+ exports.MESH_NODE_CERTIFICATES_COLUMNS = MESH_NODE_CERTIFICATES_COLUMNS;
88293
88905
  exports.MESH_TLS_PORT_HELLO_FIELD = MESH_TLS_PORT_HELLO_FIELD;
88294
88906
  exports.MeshCaKeeper = MeshCaKeeper;
88907
+ exports.MeshCertificateRegistry = MeshCertificateRegistry;
88295
88908
  exports.MeshCrl = MeshCrl;
88296
88909
  exports.PAIRING_CODE_DIGITS = PAIRING_CODE_DIGITS;
88297
88910
  exports.PAIRING_MAX_CODE_ATTEMPTS = PAIRING_MAX_CODE_ATTEMPTS;
@@ -88301,26 +88914,39 @@ exports.PAIRING_PIN_DIGITS = PAIRING_PIN_DIGITS;
88301
88914
  exports.PAIRING_PROTOCOL = PAIRING_PROTOCOL;
88302
88915
  exports.PAIRING_TTL_MS = PAIRING_TTL_MS;
88303
88916
  exports.PairingHttpError = PairingHttpError;
88917
+ exports.RENEWAL_ABANDONED = RENEWAL_ABANDONED;
88304
88918
  exports.SYSTEM_CONFIG_CLUSTER_SECTION_ID = SYSTEM_CONFIG_CLUSTER_SECTION_ID;
88305
88919
  exports.ServiceBroker = ServiceBroker;
88306
88920
  exports.SystemConfigAddon = SystemConfigAddon;
88307
88921
  exports.default = SystemConfigAddon;
88308
88922
  exports.TlsTcpTransporter = TlsTcpTransporter;
88309
88923
  exports.UnlockTicketJtiStore = UnlockTicketJtiStore;
88924
+ exports.caFingerprint = caFingerprint;
88925
+ exports.caFingerprintCompact = caFingerprintCompact;
88310
88926
  exports.computePairingCommitment = computePairingCommitment;
88311
88927
  exports.computePairingSas = computePairingSas;
88312
88928
  exports.createCidrMatcher = createCidrMatcher;
88929
+ exports.createMeshCsrPem = createMeshCsrPem;
88313
88930
  exports.describeCsr = describeCsr;
88931
+ exports.describeMeshLeaf = describeMeshLeaf;
88314
88932
  exports.dropProcessPeer = dropProcessPeer;
88315
88933
  exports.emitProcessNodeRegistered = emitProcessNodeRegistered;
88934
+ exports.exportMeshPrivateKeyPem = exportMeshPrivateKeyPem;
88935
+ exports.generateMeshCa = generateMeshCa;
88936
+ exports.generateMeshKeyPair = generateMeshKeyPair;
88316
88937
  exports.getProcessMeshCaState = getProcessMeshCaState;
88938
+ exports.getProcessMeshCertificateRegistry = getProcessMeshCertificateRegistry;
88317
88939
  exports.getProcessMeshTlsListenerState = getProcessMeshTlsListenerState;
88318
88940
  exports.getProcessNodeMeshTransport = getProcessNodeMeshTransport;
88319
88941
  exports.getProcessPeerLeaf = getProcessPeerLeaf;
88320
88942
  exports.hubHostFromMeshAddress = hubHostFromMeshAddress;
88321
88943
  exports.isAllowedAgentDashboardReturnTo = isAllowedAgentDashboardReturnTo;
88322
88944
  exports.isProcessVerifiedMeshPeer = isProcessVerifiedMeshPeer;
88945
+ exports.isValidAgentNodeId = isValidAgentNodeId;
88946
+ exports.issueMeshLeafForNode = issueMeshLeafForNode;
88947
+ exports.issueMeshLeafFromCsr = issueMeshLeafFromCsr;
88323
88948
  exports.keyFingerprintShort = keyFingerprintShort;
88949
+ exports.loadMeshCa = loadMeshCa;
88324
88950
  exports.mintAgentUiUnlockTicket = mintAgentUiUnlockTicket;
88325
88951
  exports.normalizeIp = normalizeIp;
88326
88952
  exports.onProcessNodeRegistered = onProcessNodeRegistered;
@@ -88332,6 +88958,7 @@ exports.readCidrSetting = readCidrSetting;
88332
88958
  exports.renewMeshCertificate = renewMeshCertificate;
88333
88959
  exports.requireProcessMeshCa = requireProcessMeshCa;
88334
88960
  exports.revokeMeshCertificate = revokeMeshCertificate;
88961
+ exports.setProcessMeshCertificateRegistry = setProcessMeshCertificateRegistry;
88335
88962
  exports.setProcessMeshPeerTransportLookup = setProcessMeshPeerTransportLookup;
88336
88963
  exports.setProcessMeshTlsEnabler = setProcessMeshTlsEnabler;
88337
88964
  exports.setProcessMeshTlsListenerState = setProcessMeshTlsListenerState;