@camstack/system 1.2.458 → 1.2.460

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 (109) hide show
  1. package/dist/addon-runner.js +26 -11
  2. package/dist/addon-runner.mjs +26 -11
  3. package/dist/addon-utils.mjs +1 -1
  4. package/dist/{agent-https-DOELEug8.js → agent-https-Dnr_nIVx.js} +3 -723
  5. package/dist/{agent-https-CQA3W-3e.mjs → agent-https-Iw3RSQup.mjs} +4 -616
  6. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  7. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +4 -4
  8. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  9. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +5 -5
  10. package/dist/builtins/alerts/alerts.addon.js +5 -7
  11. package/dist/builtins/alerts/alerts.addon.mjs +5 -7
  12. package/dist/builtins/alerts/record-kinds.d.ts +1 -1
  13. package/dist/builtins/autotrack/index.js +1 -1
  14. package/dist/builtins/autotrack/index.mjs +1 -1
  15. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +242 -4
  16. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +243 -5
  17. package/dist/builtins/calendars/calendars.addon.js +2 -10
  18. package/dist/builtins/calendars/calendars.addon.mjs +2 -3
  19. package/dist/builtins/calendars/record-kinds.d.ts +1 -1
  20. package/dist/builtins/camera-grid/index.js +1 -1
  21. package/dist/builtins/camera-grid/index.mjs +1 -1
  22. package/dist/builtins/composer/composer.addon.js +2 -2
  23. package/dist/builtins/composer/composer.addon.mjs +2 -2
  24. package/dist/builtins/console-logging/index.js +1 -1
  25. package/dist/builtins/console-logging/index.mjs +1 -1
  26. package/dist/builtins/core-blocks/core-blocks.addon.js +4 -6
  27. package/dist/builtins/core-blocks/core-blocks.addon.mjs +4 -6
  28. package/dist/builtins/device-history/device-history.addon.js +1 -1
  29. package/dist/builtins/device-history/device-history.addon.mjs +1 -1
  30. package/dist/builtins/device-manager/device-manager.addon.js +2 -4
  31. package/dist/builtins/device-manager/device-manager.addon.mjs +2 -4
  32. package/dist/builtins/hub-forwarder/index.js +1 -1
  33. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  34. package/dist/builtins/keychain/index.js +41 -43
  35. package/dist/builtins/keychain/index.mjs +41 -43
  36. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  37. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  38. package/dist/builtins/local-auth/local-auth.addon.js +24 -40
  39. package/dist/builtins/local-auth/local-auth.addon.mjs +27 -43
  40. package/dist/builtins/local-network/local-network.addon.js +2 -2
  41. package/dist/builtins/local-network/local-network.addon.mjs +2 -2
  42. package/dist/builtins/loki-logging/index.js +1 -1
  43. package/dist/builtins/loki-logging/index.mjs +1 -1
  44. package/dist/builtins/native-metrics/native-metrics.addon.js +39 -4
  45. package/dist/builtins/native-metrics/native-metrics.addon.mjs +48 -13
  46. package/dist/builtins/native-metrics/node-metrics-history-recorder.d.ts +16 -2
  47. package/dist/builtins/platform-probe/coral-accelerators.d.ts +10 -1
  48. package/dist/builtins/platform-probe/index.js +7 -4
  49. package/dist/builtins/platform-probe/index.mjs +13 -10
  50. package/dist/builtins/platform-probe/platform-scorer.d.ts +4 -1
  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 +20 -20
  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-plan.d.ts +9 -4
  67. package/dist/builtins/sqlite-storage/records/records-provider.d.ts +4 -18
  68. package/dist/builtins/sqlite-storage/records/records-sql.d.ts +1 -1
  69. package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +0 -17
  70. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +21 -196
  71. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +21 -196
  72. package/dist/builtins/sqlite-storage/storage-admin-provider.d.ts +6 -14
  73. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +2 -2
  74. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +7 -9
  75. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +7 -9
  76. package/dist/builtins/system-config/system-config.addon.js +667 -40
  77. package/dist/builtins/system-config/system-config.addon.mjs +737 -127
  78. package/dist/builtins/winston-logging/index.js +1 -1
  79. package/dist/builtins/winston-logging/index.mjs +1 -1
  80. package/dist/{composition-sources-BVguN7VV.mjs → composition-sources-DNRZWR1j.mjs} +1 -1
  81. package/dist/{composition-sources-DURQNDJ4.js → composition-sources-b0e_2I-D.js} +1 -1
  82. package/dist/{constants-Njka8Cv6.js → constants-6OeJiZgi.js} +1 -1
  83. package/dist/{constants-FGjnsE2x.mjs → constants-BnkOdj9Q.mjs} +1 -1
  84. package/dist/{coral-accelerators-DcnZvctM.mjs → coral-accelerators-Qhn5TOYZ.mjs} +18 -15
  85. package/dist/{coral-accelerators-Bi_c3Rft.js → coral-accelerators-oUXmmbc2.js} +13 -10
  86. package/dist/{custom-action-registry-stpC3Zy-.mjs → custom-action-registry-DStvrQKI.mjs} +37 -37
  87. package/dist/{device-ca-lEaAQ9Xi.mjs → device-ca-Bnkw8GyU.mjs} +1 -1
  88. package/dist/{device-ca-BrVK_5s3.js → device-ca-CPTDs--d.js} +1 -1
  89. package/dist/{dist-BZQjLPiz.js → dist-Bn-RNanh.js} +29 -130
  90. package/dist/{dist-B_GRPhnY.mjs → dist-Wy8cTxg6.mjs} +30 -113
  91. package/dist/file-host-worker.js +1 -1
  92. package/dist/file-host-worker.mjs +1 -1
  93. package/dist/{hub-mdns-ciao-Bg2HfTwP.mjs → hub-mdns-ciao-CJu0nhla.mjs} +2 -2
  94. package/dist/{hub-mdns-ciao-nce3TXs_.js → hub-mdns-ciao-CTBTlia4.js} +2 -2
  95. package/dist/index.d.ts +1 -0
  96. package/dist/index.js +56 -31
  97. package/dist/index.mjs +257 -233
  98. package/dist/kernel/deps/addon-deps-manager.d.ts +9 -0
  99. package/dist/{restore-archive-C7kLDI_0.mjs → restore-archive-CM23Pq9B.mjs} +177 -424
  100. package/dist/{restore-archive-FyfZ8YMC.js → restore-archive-DM1OBYq4.js} +89 -342
  101. package/dist/{wal-maintenance-Duejh7Lx.mjs → wal-maintenance-Bj_MmDkr.mjs} +0 -0
  102. package/dist/{wal-maintenance-DfSIOj24.js → wal-maintenance-CaJjuLHq.js} +0 -0
  103. package/package.json +1 -1
  104. package/dist/builtins/records/legacy-table-row-count.d.ts +0 -5
  105. package/dist/builtins/records/phase6-declare-gate.d.ts +0 -28
  106. package/dist/builtins/sqlite-storage/records/count-settings-array-legacy.d.ts +0 -5
  107. package/dist/builtins/sqlite-storage/records/count-settings-brokers-legacy.d.ts +0 -6
  108. package/dist/phase6-declare-gate-Dag1_WR2.js +0 -98
  109. package/dist/phase6-declare-gate-Lb-mrVvz.mjs +0 -93
@@ -1,7 +1,6 @@
1
1
  const require_chunk = require("./chunk-Cek0wNdY.js");
2
- const require_dist = require("./dist-BZQjLPiz.js");
2
+ const require_dist = require("./dist-Bn-RNanh.js");
3
3
  const require_x509_es = require("./x509.es-C4cOo48M.js");
4
- const require_constants = require("./constants-Njka8Cv6.js");
5
4
  let zod = require("zod");
6
5
  let node_crypto = require("node:crypto");
7
6
  let _camstack_types_node = require("@camstack/types/node");
@@ -10,615 +9,6 @@ let node_path = require("node:path");
10
9
  let node_os = require("node:os");
11
10
  node_os = require_chunk.__toESM(node_os);
12
11
  let node_fs = require("node:fs");
13
- //#region src/kernel/moleculer/mesh-mtls/mesh-ca.ts
14
- /**
15
- * Hub mesh CA — EC P-256, key in the keychain, cert in `cluster.meshCa`.
16
- *
17
- * Distinct from the HTTPS local CA (`tls/cert-issue.ts`, RSA): the mesh CA
18
- * signs node leaves (CN = nodeID) and unlock-ticket JWS (ES256). Issuance uses
19
- * `@peculiar/x509` over WebCrypto — same library the HTTPS path already uses
20
- * (installed `1.14.3`; registry latest at adoption time was `2.1.0` — stay on
21
- * the pinned range already shipping).
22
- */
23
- require_x509_es.cryptoProvider.set(node_crypto.webcrypto);
24
- var MS_PER_DAY$2 = 864e5;
25
- /** Key generation — EC P-256 (plan). WebCrypto DOM names are not in @types/node. */
26
- var MESH_KEY_ALGORITHM = {
27
- name: "ECDSA",
28
- namedCurve: "P-256"
29
- };
30
- /** Signing — ECDSA with SHA-256. */
31
- var MESH_SIGNING_ALGORITHM = {
32
- name: "ECDSA",
33
- hash: "SHA-256"
34
- };
35
- /** A node id: letters, digits, `.`, `_`, `-`; at most 63 characters; starts with a letter or digit. */
36
- var NODE_ID_PATTERN = /^[a-z0-9][a-z0-9._-]{0,62}$/i;
37
- /** Ids no agent may take: the hub's own, whatever the case (D857). */
38
- var RESERVED_NODE_IDS = new Set(["hub"]);
39
- /** True for an id an agent may carry: the pattern, and not a reserved name. */
40
- function isValidAgentNodeId(nodeId) {
41
- return NODE_ID_PATTERN.test(nodeId) && !RESERVED_NODE_IDS.has(nodeId.toLowerCase());
42
- }
43
- function freshSerial$1() {
44
- return `00${(0, node_crypto.randomBytes)(16).toString("hex")}`;
45
- }
46
- function toPkcs8Pem$1(pkcs8) {
47
- return `${require_x509_es.PemConverter.encode(pkcs8, "PRIVATE KEY")}\n`;
48
- }
49
- function toCertPem$1(cert) {
50
- return `${cert.toString("pem")}\n`;
51
- }
52
- async function exportKeyPem$1(key) {
53
- return toPkcs8Pem$1(await node_crypto.webcrypto.subtle.exportKey("pkcs8", key));
54
- }
55
- /** SHA-256 fingerprint of the DER cert, colon-hex uppercase (Node style). */
56
- function caFingerprint(certPem) {
57
- return new node_crypto.X509Certificate(certPem).fingerprint256;
58
- }
59
- /** Compact fingerprint (lowercase hex, no colons). */
60
- function caFingerprintCompact(certPem) {
61
- return (0, node_crypto.createHash)("sha256").update(new node_crypto.X509Certificate(certPem).raw).digest("hex");
62
- }
63
- async function generateMeshCa(now = /* @__PURE__ */ new Date()) {
64
- const keys = await node_crypto.webcrypto.subtle.generateKey(MESH_KEY_ALGORITHM, true, ["sign", "verify"]);
65
- const extensions = [
66
- new require_x509_es.BasicConstraintsExtension(true, 0, true),
67
- new require_x509_es.KeyUsagesExtension(require_x509_es.KeyUsageFlags.keyCertSign | require_x509_es.KeyUsageFlags.cRLSign, true),
68
- await require_x509_es.SubjectKeyIdentifierExtension.create(keys.publicKey)
69
- ];
70
- const cert = await require_x509_es.X509CertificateGenerator.createSelfSigned({
71
- serialNumber: freshSerial$1(),
72
- name: `CN=${require_constants.MESH_CA_COMMON_NAME}`,
73
- notBefore: require_x509_es.backdatedNotBefore(now),
74
- notAfter: new Date(now.getTime() + require_constants.MESH_CA_VALIDITY_DAYS * MS_PER_DAY$2),
75
- keys,
76
- signingAlgorithm: MESH_SIGNING_ALGORITHM,
77
- extensions
78
- });
79
- return {
80
- certPem: toCertPem$1(cert),
81
- keyPem: await exportKeyPem$1(keys.privateKey),
82
- cert,
83
- privateKey: keys.privateKey,
84
- publicKey: keys.publicKey
85
- };
86
- }
87
- async function loadMeshCa(certPem, keyPem) {
88
- const cert = new require_x509_es.X509Certificate(certPem);
89
- return {
90
- certPem,
91
- keyPem,
92
- cert,
93
- privateKey: await node_crypto.webcrypto.subtle.importKey("pkcs8", require_x509_es.PemConverter.decodeFirst(keyPem), MESH_KEY_ALGORITHM, true, ["sign"]),
94
- publicKey: await cert.publicKey.export(node_crypto.webcrypto)
95
- };
96
- }
97
- /**
98
- * Issue a leaf from a CSR. CN must be present; when `expectedNodeId` is set
99
- * it must match. Validity: 30 days.
100
- */
101
- async function issueMeshLeafFromCsr(ca, csrPem, opts = {}) {
102
- const csr = new require_x509_es.Pkcs10CertificateRequest(csrPem);
103
- if (!await csr.verify(node_crypto.webcrypto)) throw new Error("CSR signature is invalid");
104
- const cn = subjectCn(csr.subject);
105
- if (cn === null || cn.length === 0) throw new Error("CSR subject has no CN");
106
- if (opts.allowReserved !== true && !isValidAgentNodeId(cn)) throw new Error(`CSR CN '${cn}' is not an id an agent may carry`);
107
- if (opts.expectedNodeId !== void 0 && opts.expectedNodeId !== cn) throw new Error(`CSR CN '${cn}' does not match the token nodeId '${opts.expectedNodeId}'`);
108
- const now = opts.now ?? /* @__PURE__ */ new Date();
109
- const validDays = opts.validDays ?? 30;
110
- const serialNumber = freshSerial$1();
111
- const notAfter = new Date(now.getTime() + validDays * MS_PER_DAY$2);
112
- const extensions = [
113
- new require_x509_es.BasicConstraintsExtension(false, void 0, true),
114
- new require_x509_es.KeyUsagesExtension(require_x509_es.KeyUsageFlags.digitalSignature, true),
115
- new require_x509_es.ExtendedKeyUsageExtension([require_constants.SERVER_AUTH_OID, require_constants.CLIENT_AUTH_OID]),
116
- await require_x509_es.SubjectKeyIdentifierExtension.create(csr.publicKey),
117
- await require_x509_es.AuthorityKeyIdentifierExtension.create(ca.cert)
118
- ];
119
- return {
120
- certPem: toCertPem$1(await require_x509_es.X509CertificateGenerator.create({
121
- serialNumber,
122
- subject: `CN=${cn}`,
123
- issuer: ca.cert.subject,
124
- notBefore: require_x509_es.backdatedNotBefore(now),
125
- notAfter,
126
- publicKey: csr.publicKey,
127
- signingKey: ca.privateKey,
128
- signingAlgorithm: MESH_SIGNING_ALGORITHM,
129
- extensions
130
- })),
131
- serialNumber,
132
- notAfter,
133
- commonName: cn
134
- };
135
- }
136
- /** Issue a leaf for a known nodeID with a freshly generated key pair (tests / hub self). */
137
- async function issueMeshLeafForNode(ca, nodeId, opts = {}) {
138
- const keys = await node_crypto.webcrypto.subtle.generateKey(MESH_KEY_ALGORITHM, true, ["sign", "verify"]);
139
- return {
140
- ...await issueMeshLeafFromCsr(ca, await createMeshCsrPem(keys, nodeId), {
141
- expectedNodeId: nodeId,
142
- now: opts.now,
143
- validDays: opts.validDays,
144
- allowReserved: true
145
- }),
146
- keyPem: await exportKeyPem$1(keys.privateKey)
147
- };
148
- }
149
- function subjectCn(subject) {
150
- return /(?:^|,)\s*CN\s*=\s*([^,]+)/i.exec(subject)?.[1]?.trim() ?? null;
151
- }
152
- async function createMeshCsrPem(keys, commonName) {
153
- return `${(await require_x509_es.Pkcs10CertificateRequestGenerator.create({
154
- name: `CN=${commonName}`,
155
- keys,
156
- signingAlgorithm: MESH_SIGNING_ALGORITHM
157
- })).toString("pem")}\n`;
158
- }
159
- async function generateMeshKeyPair() {
160
- return node_crypto.webcrypto.subtle.generateKey(MESH_KEY_ALGORITHM, true, ["sign", "verify"]);
161
- }
162
- async function exportMeshPrivateKeyPem(key) {
163
- return exportKeyPem$1(key);
164
- }
165
- //#endregion
166
- //#region src/kernel/moleculer/mesh-mtls/mesh-certificate-registry.ts
167
- /**
168
- * The hub's record of every mesh leaf (D856): which certificate each node holds,
169
- * when it expires, and which serials are revoked.
170
- *
171
- * Three ways a row appears:
172
- * - `enroll` / `renewal` / `boot` - the hub issued it and wrote it down at the
173
- * moment of issuing (the authoritative record);
174
- * - `observed` - a node enrolled before this record existed (or by a path that
175
- * did not write it) presented this leaf on its LIVE mutual-TLS connection.
176
- *
177
- * Revoked serials are persisted here and replayed into the in-memory CRL at boot,
178
- * so a revocation survives a hub restart. Hub only: agents persist none of it.
179
- */
180
- /**
181
- * @durable class=config owner=system-config
182
- * write="the hub records every mesh leaf it issues (enroll, renewal, boot) and every
183
- * leaf a connected node is observed presenting; a revocation stamps revokedAt"
184
- * retention="a revoked or expired row is kept 90 days past its end, then reaped; a
185
- * live row is never deleted. Forgetting a node does not delete its rows."
186
- */
187
- var MESH_NODE_CERTIFICATES_COLLECTION = "mesh_node_certificates";
188
- var MESH_NODE_CERTIFICATES_COLUMNS = [
189
- {
190
- name: "id",
191
- type: "TEXT",
192
- primaryKey: true,
193
- notNull: true
194
- },
195
- {
196
- name: "nodeId",
197
- type: "TEXT",
198
- notNull: true
199
- },
200
- {
201
- name: "serial",
202
- type: "TEXT",
203
- notNull: true
204
- },
205
- {
206
- name: "fingerprint",
207
- type: "TEXT",
208
- notNull: true
209
- },
210
- {
211
- name: "notBefore",
212
- type: "INTEGER",
213
- notNull: true
214
- },
215
- {
216
- name: "notAfter",
217
- type: "INTEGER",
218
- notNull: true
219
- },
220
- {
221
- name: "issuedAt",
222
- type: "INTEGER",
223
- notNull: true
224
- },
225
- {
226
- name: "issuedVia",
227
- type: "TEXT",
228
- notNull: true
229
- },
230
- {
231
- name: "revokedAt",
232
- type: "INTEGER"
233
- },
234
- {
235
- name: "revokedReason",
236
- type: "TEXT"
237
- }
238
- ];
239
- var RETENTION_MS = 90 * 864e5;
240
- /**
241
- * A leaf the hub signed for a renewal that did not complete. It must not be the node's
242
- * `current` leaf, but it is NOT on the CRL: the node may still hold it (the swap
243
- * could have landed without the hub seeing it), and cutting it off would be the
244
- * outage the hand-over exists to prevent. If the node is later seen presenting it, it
245
- * is reinstated.
246
- */
247
- var RENEWAL_ABANDONED = "renewal-abandoned";
248
- var VIAS = [
249
- "enroll",
250
- "pairing",
251
- "renewal",
252
- "boot",
253
- "observed"
254
- ];
255
- /** CN, serial, fingerprint and validity of a leaf PEM (or DER). */
256
- function describeMeshLeaf(cert) {
257
- const x509 = new node_crypto.X509Certificate(cert);
258
- return {
259
- cn: subjectCn(x509.subject) ?? "",
260
- serial: x509.serialNumber,
261
- fingerprint: x509.fingerprint256,
262
- notBefore: Date.parse(x509.validFrom),
263
- notAfter: Date.parse(x509.validTo)
264
- };
265
- }
266
- function normalizeSerial(serial) {
267
- return serial.replace(/^0x/i, "").replace(/:/g, "").toLowerCase();
268
- }
269
- function parse$1(data) {
270
- const str = (k) => {
271
- const v = data[k];
272
- return typeof v === "string" && v.length > 0 ? v : null;
273
- };
274
- const num = (k) => {
275
- const v = data[k];
276
- return typeof v === "number" && Number.isFinite(v) ? v : null;
277
- };
278
- const nodeId = str("nodeId");
279
- const serial = str("serial");
280
- const fingerprint = str("fingerprint");
281
- const notBefore = num("notBefore");
282
- const notAfter = num("notAfter");
283
- const issuedAt = num("issuedAt");
284
- if (nodeId === null || serial === null || fingerprint === null || notBefore === null || notAfter === null || issuedAt === null) return null;
285
- return {
286
- nodeId,
287
- serial,
288
- fingerprint,
289
- notBefore,
290
- notAfter,
291
- issuedAt,
292
- issuedVia: VIAS.find((v) => v === data["issuedVia"]) ?? "observed",
293
- revokedAt: num("revokedAt"),
294
- revokedReason: str("revokedReason")
295
- };
296
- }
297
- var MeshCertificateRegistry = class {
298
- store;
299
- deps;
300
- rows = /* @__PURE__ */ new Map();
301
- constructor(store, deps = {}) {
302
- this.store = store;
303
- this.deps = deps;
304
- }
305
- recordToBody(record) {
306
- return {
307
- nodeId: record.nodeId,
308
- serial: record.serial,
309
- fingerprint: record.fingerprint,
310
- notBefore: record.notBefore,
311
- notAfter: record.notAfter,
312
- issuedAt: record.issuedAt,
313
- issuedVia: record.issuedVia,
314
- revokedAt: record.revokedAt,
315
- revokedReason: record.revokedReason
316
- };
317
- }
318
- now() {
319
- return (this.deps.now ?? Date.now)();
320
- }
321
- async load() {
322
- const kind = this.deps.meshKind ?? null;
323
- if (kind !== null) {
324
- const page = await kind.query({ limit: 1e4 });
325
- for (const row of page.records) {
326
- const { fingerprint: _fp, ...body } = row.data;
327
- const record = parse$1({
328
- ...body,
329
- fingerprint: row.id
330
- });
331
- if (record !== null) this.rows.set(record.fingerprint, record);
332
- }
333
- return;
334
- }
335
- const rows = await this.store.query.query({ collection: MESH_NODE_CERTIFICATES_COLLECTION });
336
- for (const row of rows) {
337
- const record = parse$1(row.data);
338
- if (record !== null) this.rows.set(record.fingerprint, record);
339
- }
340
- }
341
- /** Write down a leaf the hub just issued. Idempotent per fingerprint. */
342
- async recordIssued(nodeId, certPem, via) {
343
- const leaf = describeMeshLeaf(certPem);
344
- const existing = this.rows.get(leaf.fingerprint);
345
- if (existing !== void 0) return existing;
346
- const record = {
347
- nodeId,
348
- serial: leaf.serial,
349
- fingerprint: leaf.fingerprint,
350
- notBefore: leaf.notBefore,
351
- notAfter: leaf.notAfter,
352
- issuedAt: this.now(),
353
- issuedVia: via,
354
- revokedAt: null,
355
- revokedReason: null
356
- };
357
- await this.insert(record);
358
- this.deps.logger?.info("Mesh certificate recorded", {
359
- tags: { nodeId },
360
- meta: {
361
- via,
362
- serial: leaf.serial,
363
- notAfter: new Date(leaf.notAfter).toISOString()
364
- }
365
- });
366
- return record;
367
- }
368
- /**
369
- * A node was seen presenting `leaf` on its live connection. A leaf the hub already
370
- * knows is left alone; an unknown one is recorded `observed` (a node enrolled
371
- * before this record existed).
372
- */
373
- async recordObserved(nodeId, leaf) {
374
- const known = this.rows.get(leaf.fingerprint);
375
- if (known !== void 0) {
376
- if (known.revokedReason !== "renewal-abandoned") return known.revokedAt === null ? this.abandonRenewalsNewerThan(known) : false;
377
- const reinstated = {
378
- ...known,
379
- revokedAt: null,
380
- revokedReason: null
381
- };
382
- this.rows.set(known.fingerprint, reinstated);
383
- await this.persist(reinstated);
384
- this.deps.logger?.warn("An abandoned renewal leaf is in use - reinstated", {
385
- tags: { nodeId },
386
- meta: { serial: known.serial }
387
- });
388
- return true;
389
- }
390
- const record = {
391
- nodeId,
392
- serial: leaf.serial,
393
- fingerprint: leaf.fingerprint,
394
- notBefore: leaf.notBefore,
395
- notAfter: leaf.notAfter,
396
- issuedAt: this.now(),
397
- issuedVia: "observed",
398
- revokedAt: null,
399
- revokedReason: null
400
- };
401
- await this.insert(record);
402
- this.deps.logger?.info("Mesh certificate observed on a live connection and recorded", {
403
- tags: { nodeId },
404
- meta: {
405
- serial: leaf.serial,
406
- fingerprint: leaf.fingerprint
407
- }
408
- });
409
- return true;
410
- }
411
- list(nodeId) {
412
- return [...this.rows.values()].filter((r) => nodeId === void 0 || r.nodeId === nodeId).toSorted((a, b) => b.issuedAt - a.issuedAt);
413
- }
414
- /** The newest non-revoked leaf of a node, or `undefined`. */
415
- currentFor(nodeId) {
416
- return this.list(nodeId).find((r) => r.revokedAt === null);
417
- }
418
- /** Every non-revoked leaf of a node (a renewal in flight has two). */
419
- liveFor(nodeId) {
420
- return this.list(nodeId).filter((r) => r.revokedAt === null);
421
- }
422
- /** Stamp a leaf revoked (and mirror it into `crl`). `false` when unknown or already revoked. */
423
- async revoke(fingerprint, reason, crl) {
424
- const record = this.rows.get(fingerprint);
425
- if (record === void 0 || record.revokedAt !== null) return false;
426
- const revoked = {
427
- ...record,
428
- revokedAt: this.now(),
429
- revokedReason: reason
430
- };
431
- this.rows.set(fingerprint, revoked);
432
- crl?.revoke(record.serial);
433
- await this.persist(revoked);
434
- this.deps.logger?.warn("Mesh certificate revoked", {
435
- tags: { nodeId: record.nodeId },
436
- meta: {
437
- serial: record.serial,
438
- reason
439
- }
440
- });
441
- return true;
442
- }
443
- /**
444
- * Operator revocation of a whole node: EVERY leaf of the node that is not already on the
445
- * CRL goes on it - the current one, an observed one, a renewal one, and a leaf that was set
446
- * aside (`renewal-abandoned`: a copy of it may sit on a stolen box, and it must not stay
447
- * valid just because the hub once set it aside). Returns the serials put on the CRL.
448
- * A leaf revoked this way is never reinstated by `recordObserved`.
449
- */
450
- async revokeAllForNode(nodeId, reason, crl, keepFingerprint) {
451
- const serials = [];
452
- for (const record of this.list(nodeId)) {
453
- if (keepFingerprint !== void 0 && record.fingerprint === keepFingerprint) continue;
454
- if (record.revokedAt !== null && record.revokedReason !== "renewal-abandoned") continue;
455
- const revoked = {
456
- ...record,
457
- revokedAt: record.revokedAt ?? this.now(),
458
- revokedReason: reason
459
- };
460
- this.rows.set(record.fingerprint, revoked);
461
- crl.revoke(record.serial);
462
- await this.persist(revoked);
463
- serials.push(record.serial);
464
- }
465
- if (serials.length > 0) this.deps.logger?.warn("Every mesh certificate of the node revoked", {
466
- tags: { nodeId },
467
- meta: {
468
- serials,
469
- reason
470
- }
471
- });
472
- return serials;
473
- }
474
- /**
475
- * At boot: a node with TWO live leaves had a renewal in flight when the hub stopped. The
476
- * newer (renewal) one is set aside - it is not the node's current leaf until the node is
477
- * seen presenting it, which reinstates it. It is NOT put on the CRL.
478
- */
479
- async settleInterruptedRenewals() {
480
- let settled = 0;
481
- const byNode = /* @__PURE__ */ new Map();
482
- for (const record of this.rows.values()) {
483
- if (record.revokedAt !== null) continue;
484
- byNode.set(record.nodeId, [...byNode.get(record.nodeId) ?? [], record]);
485
- }
486
- for (const records of byNode.values()) {
487
- if (records.length < 2) continue;
488
- for (const record of records) if (record.issuedVia === "renewal" && await this.abandon(record.fingerprint)) settled += 1;
489
- }
490
- return settled;
491
- }
492
- /** Set a never-completed renewal leaf aside (not current, NOT on the CRL). */
493
- /** Fingerprints of renewal leaves whose handover is running right now (this process only). */
494
- renewalsInFlight = /* @__PURE__ */ new Set();
495
- /**
496
- * A renewal's leaf is "in flight" from signing until the handover ends. While it is, a node seen
497
- * presenting its OLD leaf is simply not swapped yet: the new leaf is not set aside (that would
498
- * flap set-aside / reinstate on the node's first connection with it).
499
- */
500
- beginRenewal(fingerprint) {
501
- this.renewalsInFlight.add(fingerprint);
502
- }
503
- endRenewal(fingerprint) {
504
- this.renewalsInFlight.delete(fingerprint);
505
- }
506
- async abandonRenewalsNewerThan(presented) {
507
- let changed = false;
508
- for (const record of this.liveFor(presented.nodeId)) {
509
- if (record.fingerprint === presented.fingerprint) continue;
510
- if (record.issuedVia !== "renewal" || record.issuedAt <= presented.issuedAt) continue;
511
- if (this.renewalsInFlight.has(record.fingerprint)) continue;
512
- if (await this.abandon(record.fingerprint)) changed = true;
513
- }
514
- return changed;
515
- }
516
- async abandon(fingerprint) {
517
- const record = this.rows.get(fingerprint);
518
- if (record === void 0 || record.revokedAt !== null) return false;
519
- const abandoned = {
520
- ...record,
521
- revokedAt: this.now(),
522
- revokedReason: RENEWAL_ABANDONED
523
- };
524
- this.rows.set(fingerprint, abandoned);
525
- await this.persist(abandoned);
526
- this.deps.logger?.warn("Renewal leaf set aside (not current, not on the CRL)", {
527
- tags: { nodeId: record.nodeId },
528
- meta: { serial: record.serial }
529
- });
530
- return true;
531
- }
532
- /** Replay every persisted revocation into `crl` (hub boot). Set-aside leaves are not revocations. */
533
- restoreCrl(crl) {
534
- let restored = 0;
535
- for (const record of this.rows.values()) {
536
- if (record.revokedAt === null || record.revokedReason === "renewal-abandoned") continue;
537
- crl.revoke(record.serial);
538
- restored += 1;
539
- }
540
- return restored;
541
- }
542
- /** Is `serial` listed as revoked here? */
543
- isRevoked(serial) {
544
- const wanted = normalizeSerial(serial);
545
- for (const record of this.rows.values()) if (record.revokedAt !== null && record.revokedReason !== "renewal-abandoned" && normalizeSerial(record.serial) === wanted) return true;
546
- return false;
547
- }
548
- async reap() {
549
- const cutoff = this.now() - RETENTION_MS;
550
- const dead = [...this.rows.values()].filter((r) => (r.revokedAt ?? r.notAfter) < cutoff);
551
- for (const r of dead) {
552
- this.rows.delete(r.fingerprint);
553
- await this.deleteRow(r.fingerprint);
554
- }
555
- return dead.length;
556
- }
557
- async insert(record) {
558
- this.rows.set(record.fingerprint, record);
559
- const kind = this.deps.meshKind ?? null;
560
- if (kind !== null) {
561
- const parsed = systemConfigRecordKinds["mesh-node-certificates"].schema.safeParse(this.recordToBody(record));
562
- if (!parsed.success) throw new Error(parsed.error.message);
563
- await kind.put({
564
- id: record.fingerprint,
565
- data: parsed.data
566
- });
567
- return;
568
- }
569
- await this.store.insert.mutate({
570
- collection: MESH_NODE_CERTIFICATES_COLLECTION,
571
- record: {
572
- id: record.fingerprint,
573
- data: { ...record }
574
- }
575
- });
576
- }
577
- async deleteRow(fingerprint) {
578
- const kind = this.deps.meshKind ?? null;
579
- if (kind !== null) {
580
- await kind.delete(fingerprint);
581
- return;
582
- }
583
- await this.store.delete.mutate({
584
- collection: MESH_NODE_CERTIFICATES_COLLECTION,
585
- key: fingerprint
586
- });
587
- }
588
- async persist(record) {
589
- try {
590
- const kind = this.deps.meshKind ?? null;
591
- if (kind !== null) {
592
- const parsed = systemConfigRecordKinds["mesh-node-certificates"].schema.safeParse(this.recordToBody(record));
593
- if (!parsed.success) throw new Error(parsed.error.message);
594
- await kind.put({
595
- id: record.fingerprint,
596
- data: parsed.data
597
- });
598
- return;
599
- }
600
- await this.store.update.mutate({
601
- collection: MESH_NODE_CERTIFICATES_COLLECTION,
602
- id: record.fingerprint,
603
- data: { ...record }
604
- });
605
- } catch (error) {
606
- this.deps.logger?.error("Mesh certificate write failed - the change holds until restart", {
607
- tags: { nodeId: record.nodeId },
608
- meta: { error: error instanceof Error ? error.message : String(error) }
609
- });
610
- }
611
- }
612
- };
613
- var SLOT$1 = Symbol.for("camstack.mesh.certificate-registry");
614
- function setProcessMeshCertificateRegistry(registry) {
615
- if (registry === null) Reflect.deleteProperty(globalThis, SLOT$1);
616
- else Reflect.set(globalThis, SLOT$1, registry);
617
- }
618
- function getProcessMeshCertificateRegistry() {
619
- const value = Reflect.get(globalThis, SLOT$1);
620
- return value !== null && typeof value === "object" && typeof Reflect.get(value, "recordIssued") === "function" ? value : null;
621
- }
622
12
  var MeshNodeCertificateBodySchema = zod.z.object({
623
13
  nodeId: zod.z.string(),
624
14
  serial: zod.z.string(),
@@ -651,8 +41,7 @@ var _systemConfigRecordKinds = require_dist.defineRecordKinds({
651
41
  retention: {
652
42
  owner: "system-config",
653
43
  reason: "daily reap removes revoked/expired rows older than 90 days"
654
- },
655
- adoptsFrom: MESH_NODE_CERTIFICATES_COLLECTION
44
+ }
656
45
  },
657
46
  "agent-https-names": {
658
47
  schema: AgentHttpsNameBodySchema,
@@ -660,8 +49,7 @@ var _systemConfigRecordKinds = require_dist.defineRecordKinds({
660
49
  writeTrigger: "agent HTTPS certificate issuance records the CN/SAN set",
661
50
  device: "none",
662
51
  at: "none",
663
- retention: { none: "one row per node id" },
664
- adoptsFrom: AGENT_HTTPS_NAMES_COLLECTION
52
+ retention: { none: "one row per node id" }
665
53
  }
666
54
  });
667
55
  var systemConfigRecordKinds = _systemConfigRecordKinds;
@@ -1704,24 +1092,6 @@ Object.defineProperty(exports, "MAX_LEAF_VALIDITY_DAYS", {
1704
1092
  return MAX_LEAF_VALIDITY_DAYS;
1705
1093
  }
1706
1094
  });
1707
- Object.defineProperty(exports, "MESH_NODE_CERTIFICATES_COLLECTION", {
1708
- enumerable: true,
1709
- get: function() {
1710
- return MESH_NODE_CERTIFICATES_COLLECTION;
1711
- }
1712
- });
1713
- Object.defineProperty(exports, "MESH_NODE_CERTIFICATES_COLUMNS", {
1714
- enumerable: true,
1715
- get: function() {
1716
- return MESH_NODE_CERTIFICATES_COLUMNS;
1717
- }
1718
- });
1719
- Object.defineProperty(exports, "MeshCertificateRegistry", {
1720
- enumerable: true,
1721
- get: function() {
1722
- return MeshCertificateRegistry;
1723
- }
1724
- });
1725
1095
  Object.defineProperty(exports, "PERMITTED_DNS_SUFFIXES", {
1726
1096
  enumerable: true,
1727
1097
  get: function() {
@@ -1734,12 +1104,6 @@ Object.defineProperty(exports, "PERMITTED_IP_RANGES", {
1734
1104
  return PERMITTED_IP_RANGES;
1735
1105
  }
1736
1106
  });
1737
- Object.defineProperty(exports, "RENEWAL_ABANDONED", {
1738
- enumerable: true,
1739
- get: function() {
1740
- return RENEWAL_ABANDONED;
1741
- }
1742
- });
1743
1107
  Object.defineProperty(exports, "SERVER_AUTH_OID", {
1744
1108
  enumerable: true,
1745
1109
  get: function() {
@@ -1764,18 +1128,6 @@ Object.defineProperty(exports, "buildNameConstraintSet", {
1764
1128
  return buildNameConstraintSet;
1765
1129
  }
1766
1130
  });
1767
- Object.defineProperty(exports, "caFingerprint", {
1768
- enumerable: true,
1769
- get: function() {
1770
- return caFingerprint;
1771
- }
1772
- });
1773
- Object.defineProperty(exports, "caFingerprintCompact", {
1774
- enumerable: true,
1775
- get: function() {
1776
- return caFingerprintCompact;
1777
- }
1778
- });
1779
1131
  Object.defineProperty(exports, "certificateNames", {
1780
1132
  enumerable: true,
1781
1133
  get: function() {
@@ -1800,66 +1152,30 @@ Object.defineProperty(exports, "createAgentHttpsRequest", {
1800
1152
  return createAgentHttpsRequest;
1801
1153
  }
1802
1154
  });
1803
- Object.defineProperty(exports, "createMeshCsrPem", {
1804
- enumerable: true,
1805
- get: function() {
1806
- return createMeshCsrPem;
1807
- }
1808
- });
1809
1155
  Object.defineProperty(exports, "describeHttpsLeaf", {
1810
1156
  enumerable: true,
1811
1157
  get: function() {
1812
1158
  return describeHttpsLeaf;
1813
1159
  }
1814
1160
  });
1815
- Object.defineProperty(exports, "describeMeshLeaf", {
1816
- enumerable: true,
1817
- get: function() {
1818
- return describeMeshLeaf;
1819
- }
1820
- });
1821
1161
  Object.defineProperty(exports, "evaluateExistingCert", {
1822
1162
  enumerable: true,
1823
1163
  get: function() {
1824
1164
  return evaluateExistingCert;
1825
1165
  }
1826
1166
  });
1827
- Object.defineProperty(exports, "exportMeshPrivateKeyPem", {
1828
- enumerable: true,
1829
- get: function() {
1830
- return exportMeshPrivateKeyPem;
1831
- }
1832
- });
1833
1167
  Object.defineProperty(exports, "generateCa", {
1834
1168
  enumerable: true,
1835
1169
  get: function() {
1836
1170
  return generateCa;
1837
1171
  }
1838
1172
  });
1839
- Object.defineProperty(exports, "generateMeshCa", {
1840
- enumerable: true,
1841
- get: function() {
1842
- return generateMeshCa;
1843
- }
1844
- });
1845
- Object.defineProperty(exports, "generateMeshKeyPair", {
1846
- enumerable: true,
1847
- get: function() {
1848
- return generateMeshKeyPair;
1849
- }
1850
- });
1851
1173
  Object.defineProperty(exports, "getProcessAgentHttpsNames", {
1852
1174
  enumerable: true,
1853
1175
  get: function() {
1854
1176
  return getProcessAgentHttpsNames;
1855
1177
  }
1856
1178
  });
1857
- Object.defineProperty(exports, "getProcessMeshCertificateRegistry", {
1858
- enumerable: true,
1859
- get: function() {
1860
- return getProcessMeshCertificateRegistry;
1861
- }
1862
- });
1863
1179
  Object.defineProperty(exports, "installAgentHttps", {
1864
1180
  enumerable: true,
1865
1181
  get: function() {
@@ -1890,12 +1206,6 @@ Object.defineProperty(exports, "isPrivateAddress", {
1890
1206
  return isPrivateAddress;
1891
1207
  }
1892
1208
  });
1893
- Object.defineProperty(exports, "isValidAgentNodeId", {
1894
- enumerable: true,
1895
- get: function() {
1896
- return isValidAgentNodeId;
1897
- }
1898
- });
1899
1209
  Object.defineProperty(exports, "issueAgentHttpsLeaf", {
1900
1210
  enumerable: true,
1901
1211
  get: function() {
@@ -1908,18 +1218,6 @@ Object.defineProperty(exports, "issueLeaf", {
1908
1218
  return issueLeaf;
1909
1219
  }
1910
1220
  });
1911
- Object.defineProperty(exports, "issueMeshLeafForNode", {
1912
- enumerable: true,
1913
- get: function() {
1914
- return issueMeshLeafForNode;
1915
- }
1916
- });
1917
- Object.defineProperty(exports, "issueMeshLeafFromCsr", {
1918
- enumerable: true,
1919
- get: function() {
1920
- return issueMeshLeafFromCsr;
1921
- }
1922
- });
1923
1221
  Object.defineProperty(exports, "loadAgentHttps", {
1924
1222
  enumerable: true,
1925
1223
  get: function() {
@@ -1932,12 +1230,6 @@ Object.defineProperty(exports, "loadCa", {
1932
1230
  return loadCa;
1933
1231
  }
1934
1232
  });
1935
- Object.defineProperty(exports, "loadMeshCa", {
1936
- enumerable: true,
1937
- get: function() {
1938
- return loadMeshCa;
1939
- }
1940
- });
1941
1233
  Object.defineProperty(exports, "localCaCommonName", {
1942
1234
  enumerable: true,
1943
1235
  get: function() {
@@ -1986,18 +1278,6 @@ Object.defineProperty(exports, "setProcessAgentHttpsNames", {
1986
1278
  return setProcessAgentHttpsNames;
1987
1279
  }
1988
1280
  });
1989
- Object.defineProperty(exports, "setProcessMeshCertificateRegistry", {
1990
- enumerable: true,
1991
- get: function() {
1992
- return setProcessMeshCertificateRegistry;
1993
- }
1994
- });
1995
- Object.defineProperty(exports, "subjectCn", {
1996
- enumerable: true,
1997
- get: function() {
1998
- return subjectCn;
1999
- }
2000
- });
2001
1281
  Object.defineProperty(exports, "systemConfigRecordKinds", {
2002
1282
  enumerable: true,
2003
1283
  get: function() {