@camstack/system 1.2.356 → 1.2.358

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 (76) hide show
  1. package/dist/addon-runner.js +1 -1
  2. package/dist/addon-runner.mjs +1 -1
  3. package/dist/auth/user-manager.d.ts +43 -2
  4. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  5. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  6. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  7. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  8. package/dist/builtins/alerts/alerts.addon.js +1 -1
  9. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  10. package/dist/builtins/autotrack/index.js +2 -2
  11. package/dist/builtins/autotrack/index.mjs +2 -2
  12. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
  13. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
  14. package/dist/builtins/calendars/calendars.addon.js +1 -1
  15. package/dist/builtins/calendars/calendars.addon.mjs +1 -1
  16. package/dist/builtins/camera-grid/index.js +1 -1
  17. package/dist/builtins/camera-grid/index.mjs +1 -1
  18. package/dist/builtins/composer/composer.addon.js +8 -8
  19. package/dist/builtins/composer/composer.addon.mjs +8 -8
  20. package/dist/builtins/console-logging/index.js +1 -1
  21. package/dist/builtins/console-logging/index.mjs +1 -1
  22. package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
  23. package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
  24. package/dist/builtins/device-manager/device-manager.addon.js +9 -9
  25. package/dist/builtins/device-manager/device-manager.addon.mjs +9 -9
  26. package/dist/builtins/hub-forwarder/index.js +1 -1
  27. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  28. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  29. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  30. package/dist/builtins/local-auth/admin-account-boot.d.ts +27 -0
  31. package/dist/builtins/local-auth/auth-schema.d.ts +3 -2
  32. package/dist/builtins/local-auth/local-auth.addon.js +281 -8
  33. package/dist/builtins/local-auth/local-auth.addon.mjs +291 -22
  34. package/dist/builtins/local-network/local-network.addon.d.ts +26 -0
  35. package/dist/builtins/local-network/local-network.addon.js +74 -25
  36. package/dist/builtins/local-network/local-network.addon.mjs +74 -25
  37. package/dist/builtins/loki-logging/index.js +1 -1
  38. package/dist/builtins/loki-logging/index.mjs +1 -1
  39. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  40. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  41. package/dist/builtins/platform-probe/index.js +1 -1
  42. package/dist/builtins/platform-probe/index.mjs +1 -1
  43. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  44. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  45. package/dist/builtins/snapshot/index.js +1 -1
  46. package/dist/builtins/snapshot/index.mjs +1 -1
  47. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  48. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  49. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
  50. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
  51. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  52. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  53. package/dist/builtins/system-config/system-config.addon.js +1 -1
  54. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  55. package/dist/builtins/winston-logging/index.js +1 -1
  56. package/dist/builtins/winston-logging/index.mjs +1 -1
  57. package/dist/{child-cap-dispatch-wbIQJctP.js → child-cap-dispatch-BWk99kmA.js} +2 -2
  58. package/dist/{child-cap-dispatch-BcRHQBKW.mjs → child-cap-dispatch-C2dFiu87.mjs} +2 -2
  59. package/dist/{composition-sources-CeO0K2cl.js → composition-sources-BaHPH661.js} +1 -1
  60. package/dist/{composition-sources-BBfqepyT.mjs → composition-sources-D8Hapyav.mjs} +1 -1
  61. package/dist/{dist-B7WRgEZY.mjs → dist-D3bhbMY3.mjs} +321 -65
  62. package/dist/{dist-CFVOy8VT.js → dist-DzAHit0a.js} +332 -64
  63. package/dist/index.js +19 -143
  64. package/dist/index.mjs +6 -142
  65. package/dist/kernel/config-manager.d.ts +1 -1
  66. package/dist/kernel/config-schema.d.ts +6 -3
  67. package/dist/{retired-settings-keys-DKRjfz0U.mjs → retired-settings-keys-B6AFmtlO.mjs} +1 -1
  68. package/dist/{retired-settings-keys-CRlTzxaS.js → retired-settings-keys-CkXoPjKy.js} +1 -1
  69. package/dist/tls/boot-tls.d.ts +29 -0
  70. package/dist/tls/https-listener.d.ts +30 -0
  71. package/dist/tls/index.d.ts +4 -1
  72. package/dist/tls/tls-actions.d.ts +29 -0
  73. package/dist/tls/tls-status.d.ts +12 -1
  74. package/dist/{tls-ue_Xefmv.js → tls-CCMX7MjX.js} +319 -54
  75. package/dist/{tls-DTlVWwAI.mjs → tls-CJHogwTl.mjs} +246 -53
  76. package/package.json +3 -3
@@ -1,9 +1,9 @@
1
1
  import { r as __exportAll, t as __commonJSMin } from "./chunk-CNf5ZN-e.mjs";
2
2
  import { X509Certificate, createPrivateKey, randomBytes, webcrypto } from "node:crypto";
3
- import { chmod, writeFile } from "node:fs/promises";
3
+ import { chmod, mkdir, writeFile } from "node:fs/promises";
4
4
  import { join } from "node:path";
5
5
  import * as os from "node:os";
6
- import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
6
+ import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
7
7
  import { createServer } from "node:http";
8
8
  import { isIP } from "node:net";
9
9
  //#region src/http/lan-http-bind.ts
@@ -11861,45 +11861,6 @@ function loadTlsCert(certPath, keyPath) {
11861
11861
  };
11862
11862
  }
11863
11863
  //#endregion
11864
- //#region src/tls/uploaded-cert.ts
11865
- /**
11866
- * Operator-supplied material must parse, match its key, and carry
11867
- * `extendedKeyUsage = serverAuth` — the same leaf defects D227 refused
11868
- * to keep generating.
11869
- */
11870
- function validateUploadedTls(certPem, keyPem) {
11871
- let leaf;
11872
- try {
11873
- leaf = new X509Certificate(certPem);
11874
- } catch {
11875
- return {
11876
- ok: false,
11877
- error: "Certificate PEM could not be parsed."
11878
- };
11879
- }
11880
- try {
11881
- if (!leaf.checkPrivateKey(createPrivateKey(keyPem))) return {
11882
- ok: false,
11883
- error: "Private key does not match the certificate."
11884
- };
11885
- } catch {
11886
- return {
11887
- ok: false,
11888
- error: "Private key PEM could not be parsed."
11889
- };
11890
- }
11891
- const eku = leaf.keyUsage;
11892
- if (eku === void 0 || !eku.includes("1.3.6.1.5.5.7.3.1")) return {
11893
- ok: false,
11894
- error: "Certificate is missing extendedKeyUsage = serverAuth."
11895
- };
11896
- return {
11897
- ok: true,
11898
- fingerprintSha256: leaf.fingerprint256,
11899
- validTo: new Date(leaf.validTo).toISOString()
11900
- };
11901
- }
11902
- //#endregion
11903
11864
  //#region src/tls/tls-status.ts
11904
11865
  function tlsDir(dataDir) {
11905
11866
  return join(dataDir, "tls");
@@ -11932,10 +11893,51 @@ function writeExtraSans(dataDir, sans) {
11932
11893
  mkdirSync(tlsDir(dataDir), { recursive: true });
11933
11894
  writeFileSync(join(tlsDir(dataDir), "extra-sans.json"), `${JSON.stringify(sans)}\n`, "utf-8");
11934
11895
  }
11935
- function readTlsAccessStatus(dataDir, restartRequired = false) {
11896
+ /** Where an upload's own CA is kept — never over the local CA's `camstack-ca.crt`. */
11897
+ var UPLOADED_CA_FILE = "uploaded-ca.crt";
11898
+ /** Every certificate in a PEM bundle, in order. */
11899
+ function splitPemCertificates(pem) {
11900
+ const blocks = pem.match(/-----BEGIN CERTIFICATE-----[\s\S]+?-----END CERTIFICATE-----/g);
11901
+ return blocks === null ? [] : blocks.map((block) => `${block}\n`);
11902
+ }
11903
+ /**
11904
+ * The certificate that signed `leaf`, from the upload itself: the CA the
11905
+ * operator supplied, else the rest of the uploaded chain. `null` when the
11906
+ * upload did not include it — and then nothing may stand in for it: the
11907
+ * local CA did not sign an uploaded leaf, so handing it out as "the CA" would
11908
+ * tell a client to trust a root that verifies nothing it is served.
11909
+ */
11910
+ function uploadedIssuer(dir, leaf, chainPem) {
11911
+ const caPath = join(dir, UPLOADED_CA_FILE);
11912
+ const candidates = [...existsSync(caPath) ? splitPemCertificates(readFileSync(caPath, "utf-8")) : [], ...splitPemCertificates(chainPem).slice(1)];
11913
+ for (const pem of candidates) try {
11914
+ const cert = new X509Certificate(pem);
11915
+ if (leaf.checkIssued(cert) && leaf.verify(cert.publicKey)) return {
11916
+ pem,
11917
+ cert
11918
+ };
11919
+ } catch {}
11920
+ return null;
11921
+ }
11922
+ function generatedIssuer(dir) {
11923
+ const caPath = join(dir, "camstack-ca.crt");
11924
+ if (!existsSync(caPath)) return null;
11925
+ const pem = readFileSync(caPath, "utf-8");
11926
+ return {
11927
+ pem,
11928
+ cert: new X509Certificate(pem)
11929
+ };
11930
+ }
11931
+ /**
11932
+ * What the node's certificate is, and whether the listener serves it.
11933
+ * `servedLeafFingerprint` is the leaf the HTTPS listener presents right now
11934
+ * (`servedHttpsLeafFingerprint()`), or `null` when unknown; a restart is
11935
+ * required exactly when the listener serves a different leaf than the one
11936
+ * on disk — a measured fact, not a flag a mutation remembered to set.
11937
+ */
11938
+ function readTlsAccessStatus(dataDir, servedLeafFingerprint) {
11936
11939
  const dir = tlsDir(dataDir);
11937
11940
  const certPath = join(dir, "camstack.crt");
11938
- const caPath = join(dir, "camstack-ca.crt");
11939
11941
  const mode = readTlsMode(dataDir);
11940
11942
  if (!existsSync(certPath)) return {
11941
11943
  mode: "disabled",
@@ -11943,24 +11945,24 @@ function readTlsAccessStatus(dataDir, restartRequired = false) {
11943
11945
  caFingerprintSha256: null,
11944
11946
  validTo: null,
11945
11947
  sans: [],
11946
- caCertPem: existsSync(caPath) ? readFileSync(caPath, "utf-8") : null,
11948
+ caCertPem: (mode === "uploaded" ? null : generatedIssuer(dir))?.pem ?? null,
11947
11949
  reissueError: null,
11948
- restartRequired
11950
+ restartRequired: false
11949
11951
  };
11950
11952
  try {
11951
- const leaf = new X509Certificate(readFileSync(certPath));
11952
- const caPem = existsSync(caPath) ? readFileSync(caPath, "utf-8") : null;
11953
- const ca = caPem !== null ? new X509Certificate(caPem) : null;
11953
+ const chainPem = readFileSync(certPath, "utf-8");
11954
+ const leaf = new X509Certificate(chainPem);
11955
+ const ca = mode === "uploaded" ? uploadedIssuer(dir, leaf, chainPem) : generatedIssuer(dir);
11954
11956
  const san = leaf.subjectAltName ?? "";
11955
11957
  return {
11956
11958
  mode,
11957
11959
  leafFingerprintSha256: leaf.fingerprint256,
11958
- caFingerprintSha256: ca?.fingerprint256 ?? null,
11960
+ caFingerprintSha256: ca?.cert.fingerprint256 ?? null,
11959
11961
  validTo: new Date(leaf.validTo).toISOString(),
11960
11962
  sans: san === "" ? [] : san.split(", "),
11961
- caCertPem: caPem,
11963
+ caCertPem: ca?.pem ?? null,
11962
11964
  reissueError: null,
11963
- restartRequired
11965
+ restartRequired: servedLeafFingerprint !== null && servedLeafFingerprint !== leaf.fingerprint256
11964
11966
  };
11965
11967
  } catch {
11966
11968
  return {
@@ -11971,9 +11973,200 @@ function readTlsAccessStatus(dataDir, restartRequired = false) {
11971
11973
  sans: [],
11972
11974
  caCertPem: null,
11973
11975
  reissueError: "Certificate on disk could not be parsed.",
11974
- restartRequired
11976
+ restartRequired: false
11975
11977
  };
11976
11978
  }
11977
11979
  }
11978
11980
  //#endregion
11979
- export { registerLanHttpHandler as C, readLanHttpState as S, DEFAULT_LAN_HTTP_PORT as _, writeTlsMode as a, bindPendingLanHttp as b, loadTlsCert as c, collectCertIdentity as d, CA_VALIDITY_DAYS as f, evaluateExistingCert as g, SERVER_AUTH_OID as h, writeExtraSans as i, reissueTlsLeaf as l, MAX_LEAF_VALIDITY_DAYS as m, readTlsAccessStatus as n, validateUploadedTls as o, LEAF_RENEWAL_WINDOW_DAYS as p, readTlsMode as r, ensureTlsCert as s, readExtraSans as t, CA_COMMON_NAME as u, allFamiliesListenHost as v, closeLanHttp as x, applyLanHttp as y };
11981
+ //#region src/tls/boot-tls.ts
11982
+ /**
11983
+ * Decide what the listener serves at boot. The admin UI (Network → Local
11984
+ * access) is the only way to set a certificate (D726): it either leaves the
11985
+ * hub on its generated local-CA leaf (D227) or uploads one, recorded by the
11986
+ * `tls/mode` marker. An uploaded certificate is served verbatim — running it
11987
+ * through `ensureTlsCert` would replace it on the first restart, because a
11988
+ * leaf the local root did not issue is one of that rule's reissue triggers.
11989
+ */
11990
+ async function prepareBootTls(dataDir, options) {
11991
+ const certPath = join(dataDir, "tls", "camstack.crt");
11992
+ const keyPath = join(dataDir, "tls", "camstack.key");
11993
+ const marked = readTlsMode(dataDir);
11994
+ if (marked === "uploaded" && existsSync(certPath) && existsSync(keyPath)) return {
11995
+ mode: "uploaded",
11996
+ pair: loadTlsCert(certPath, keyPath),
11997
+ ensured: void 0,
11998
+ uploadedMissing: false
11999
+ };
12000
+ const uploadedMissing = marked === "uploaded";
12001
+ if (uploadedMissing) writeTlsMode(dataDir, "generated");
12002
+ const ensured = await ensureTlsCert(dataDir, options);
12003
+ return {
12004
+ mode: "generated",
12005
+ pair: loadTlsCert(ensured.certPath, ensured.keyPath),
12006
+ ensured,
12007
+ uploadedMissing
12008
+ };
12009
+ }
12010
+ //#endregion
12011
+ //#region src/tls/https-listener.ts
12012
+ var SLOT_KEY = Symbol.for("camstack.tls.https-listener");
12013
+ var EMPTY_SLOT = {
12014
+ reload: null,
12015
+ servedLeafFingerprint: null
12016
+ };
12017
+ function isSlot(value) {
12018
+ if (typeof value !== "object" || value === null) return false;
12019
+ if (!("reload" in value) || !("servedLeafFingerprint" in value)) return false;
12020
+ const reload = value.reload;
12021
+ const served = value.servedLeafFingerprint;
12022
+ return (reload === null || typeof reload === "function") && (served === null || typeof served === "string");
12023
+ }
12024
+ function readSlot() {
12025
+ const current = Reflect.get(globalThis, SLOT_KEY);
12026
+ return isSlot(current) ? current : EMPTY_SLOT;
12027
+ }
12028
+ function writeSlot(next) {
12029
+ Reflect.set(globalThis, SLOT_KEY, next);
12030
+ }
12031
+ /** SHA-256 fingerprint of the first certificate (the leaf) in a PEM chain. */
12032
+ function leafFingerprintOf(chain) {
12033
+ return new X509Certificate(chain).fingerprint256;
12034
+ }
12035
+ /**
12036
+ * Called once by the server after its HTTPS listener is up, with the pair it
12037
+ * was started on. From here on a certificate action swaps the served
12038
+ * certificate in place (`setSecureContext`) — new handshakes get the new
12039
+ * leaf, open connections keep theirs, nothing restarts.
12040
+ */
12041
+ function registerHttpsListener(server, pair) {
12042
+ writeSlot({
12043
+ reload: (next) => server.setSecureContext({
12044
+ cert: next.cert,
12045
+ key: next.key
12046
+ }),
12047
+ servedLeafFingerprint: leafFingerprintOf(pair.cert)
12048
+ });
12049
+ }
12050
+ /** Forget the listener — on shutdown, and between specs. */
12051
+ function clearHttpsListener() {
12052
+ writeSlot(EMPTY_SLOT);
12053
+ }
12054
+ /**
12055
+ * The leaf the HTTPS listener serves now, or `null` when this process has no
12056
+ * registered listener (TLS off, or a process that does not own one) — in
12057
+ * which case nobody can say, and `null` is the honest answer.
12058
+ */
12059
+ function servedHttpsLeafFingerprint() {
12060
+ return readSlot().servedLeafFingerprint;
12061
+ }
12062
+ /** Serve `pair` from now on. Never throws: the outcome says what happened. */
12063
+ function reloadHttpsListener(pair) {
12064
+ const slot = readSlot();
12065
+ if (slot.reload === null) return { kind: "no-listener" };
12066
+ try {
12067
+ const servedLeafFingerprint = leafFingerprintOf(pair.cert);
12068
+ slot.reload(pair);
12069
+ writeSlot({
12070
+ reload: slot.reload,
12071
+ servedLeafFingerprint
12072
+ });
12073
+ return {
12074
+ kind: "reloaded",
12075
+ servedLeafFingerprint
12076
+ };
12077
+ } catch (err) {
12078
+ return {
12079
+ kind: "failed",
12080
+ error: err instanceof Error ? err.message : String(err)
12081
+ };
12082
+ }
12083
+ }
12084
+ //#endregion
12085
+ //#region src/tls/uploaded-cert.ts
12086
+ /**
12087
+ * Operator-supplied material must parse, match its key, and carry
12088
+ * `extendedKeyUsage = serverAuth` — the same leaf defects D227 refused
12089
+ * to keep generating.
12090
+ */
12091
+ function validateUploadedTls(certPem, keyPem) {
12092
+ let leaf;
12093
+ try {
12094
+ leaf = new X509Certificate(certPem);
12095
+ } catch {
12096
+ return {
12097
+ ok: false,
12098
+ error: "Certificate PEM could not be parsed."
12099
+ };
12100
+ }
12101
+ try {
12102
+ if (!leaf.checkPrivateKey(createPrivateKey(keyPem))) return {
12103
+ ok: false,
12104
+ error: "Private key does not match the certificate."
12105
+ };
12106
+ } catch {
12107
+ return {
12108
+ ok: false,
12109
+ error: "Private key PEM could not be parsed."
12110
+ };
12111
+ }
12112
+ const eku = leaf.keyUsage;
12113
+ if (eku === void 0 || !eku.includes("1.3.6.1.5.5.7.3.1")) return {
12114
+ ok: false,
12115
+ error: "Certificate is missing extendedKeyUsage = serverAuth."
12116
+ };
12117
+ return {
12118
+ ok: true,
12119
+ fingerprintSha256: leaf.fingerprint256,
12120
+ validTo: new Date(leaf.validTo).toISOString()
12121
+ };
12122
+ }
12123
+ //#endregion
12124
+ //#region src/tls/tls-actions.ts
12125
+ function withNewline(pem) {
12126
+ return pem.endsWith("\n") ? pem : `${pem}\n`;
12127
+ }
12128
+ /**
12129
+ * Store an operator's certificate. The leaf (or chain) and key replace the
12130
+ * served pair; a CA, when given, goes to its own file. The local CA
12131
+ * (`camstack-ca.crt` + key) is never touched — it did not sign the upload,
12132
+ * and it is what "Revert to generated" and every device that trusts it
12133
+ * still need.
12134
+ */
12135
+ async function storeUploadedCertificate(dataDir, input) {
12136
+ const valid = validateUploadedTls(input.certPem, input.keyPem);
12137
+ if (!valid.ok) throw new Error(valid.error);
12138
+ const dir = join(dataDir, "tls");
12139
+ await mkdir(dir, { recursive: true });
12140
+ await writeFile(join(dir, "camstack.crt"), withNewline(input.certPem));
12141
+ await writeFile(join(dir, "camstack.key"), withNewline(input.keyPem), { mode: 384 });
12142
+ const caPath = join(dir, UPLOADED_CA_FILE);
12143
+ if (input.caPem !== void 0 && input.caPem.trim() !== "") await writeFile(caPath, withNewline(input.caPem));
12144
+ else rmSync(caPath, { force: true });
12145
+ writeTlsMode(dataDir, "uploaded");
12146
+ }
12147
+ /** Issue a new generated leaf under the local CA. Refused while an upload is served. */
12148
+ async function regenerateCertificate(dataDir, options) {
12149
+ if (readTlsMode(dataDir) === "uploaded") throw new Error("Cannot regenerate an uploaded certificate — revert to generated first.");
12150
+ await reissueTlsLeaf(dataDir, options);
12151
+ }
12152
+ /** Drop the upload and serve the generated local-CA leaf again (D227). */
12153
+ async function revertToGeneratedCertificate(dataDir, options) {
12154
+ writeTlsMode(dataDir, "generated");
12155
+ rmSync(join(dataDir, "tls", UPLOADED_CA_FILE), { force: true });
12156
+ await ensureTlsCert(dataDir, options);
12157
+ }
12158
+ /**
12159
+ * Put the pair on disk on the HTTPS listener. Called after every action, so
12160
+ * "the certificate changed" and "clients see it" are the same moment.
12161
+ */
12162
+ function applyCertificateToListener(dataDir) {
12163
+ const certPath = join(dataDir, "tls", "camstack.crt");
12164
+ const keyPath = join(dataDir, "tls", "camstack.key");
12165
+ if (!existsSync(certPath) || !existsSync(keyPath)) return {
12166
+ kind: "failed",
12167
+ error: `No certificate pair under ${join(dataDir, "tls")}`
12168
+ };
12169
+ return reloadHttpsListener(loadTlsCert(certPath, keyPath));
12170
+ }
12171
+ //#endregion
12172
+ export { allFamiliesListenHost as A, collectCertIdentity as C, SERVER_AUTH_OID as D, MAX_LEAF_VALIDITY_DAYS as E, registerLanHttpHandler as F, bindPendingLanHttp as M, closeLanHttp as N, evaluateExistingCert as O, readLanHttpState as P, CA_COMMON_NAME as S, LEAF_RENEWAL_WINDOW_DAYS as T, writeExtraSans as _, validateUploadedTls as a, loadTlsCert as b, registerHttpsListener as c, prepareBootTls as d, UPLOADED_CA_FILE as f, splitPemCertificates as g, readTlsMode as h, storeUploadedCertificate as i, applyLanHttp as j, DEFAULT_LAN_HTTP_PORT as k, reloadHttpsListener as l, readTlsAccessStatus as m, regenerateCertificate as n, clearHttpsListener as o, readExtraSans as p, revertToGeneratedCertificate as r, leafFingerprintOf as s, applyCertificateToListener as t, servedHttpsLeafFingerprint as u, writeTlsMode as v, CA_VALIDITY_DAYS as w, reissueTlsLeaf as x, ensureTlsCert as y };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/system",
3
- "version": "1.2.356",
3
+ "version": "1.2.358",
4
4
  "description": "Core addon for CamStack — builtins, pipeline, process management, auth, logging, events",
5
5
  "keywords": [
6
6
  "camstack",
@@ -53,7 +53,7 @@
53
53
  "category": "system",
54
54
  "name": "SQLite Settings",
55
55
  "entry": "./dist/builtins/sqlite-storage/sqlite-settings.addon.js",
56
- "description": "The relational ENGINE behind the data door (SQLite WAL). Registers `data-store-provider`, an internal collection cap; the public `settings-store` door is owned by `storage-orchestrator`, which dispatches here. Callers never reach this addon directly — that is what makes the engine replaceable. It ALSO registers `vector-store` (sqlite-vec) from the same database file and the same open handle, and `database-snapshot`: the verified copy of its database that the nightly backup archives in place of the live files, written by this runner on a thread over its own connection ([D693]). Runs in its OWN process (`execution.isolate`) — `better-sqlite3` `Statement.run` does not belong on the event loop that serves the API ([D181]).",
56
+ "description": "The relational ENGINE behind the data door (SQLite WAL). Registers `data-store-provider`, an internal collection cap; the public `settings-store` door is owned by `storage-orchestrator`, which dispatches here. Callers never reach this addon directly — that is what makes the engine replaceable. It ALSO registers `vector-store` (sqlite-vec) from the same database file and the same open handle, and `database-snapshot`: the verified copy of its database that the nightly backup archives in place of the live files, written by this runner on a thread over its own connection. Runs in its OWN process (`execution.isolate`) — `better-sqlite3` `Statement.run` does not belong on the event loop that serves the API.",
57
57
  "execution": {
58
58
  "isolate": true,
59
59
  "heapProfile": "heavy",
@@ -363,7 +363,7 @@
363
363
  "id": "composer",
364
364
  "category": "system",
365
365
  "name": "Composer",
366
- "description": "Runs every DECLARATIVE composition (a core block whose source is `composition`): declares the composed device under the shared Blocks integration, registers its caps natively, and derives each field from other devices' state by `from` / expression — event-driven, no polling. Hub-only. Runs in its OWN runner (`execution.isolate` + `group: composer`): frame-free and low-crash, grouped with no device provider or data plane (D29, D659).",
366
+ "description": "Runs every DECLARATIVE composition (a core block whose source is `composition`): declares the composed device under the shared Blocks integration, registers its caps natively, and derives each field from other devices' state by `from` / expression — event-driven, no polling. Hub-only. Runs in its OWN runner (`execution.isolate` + `group: composer`): frame-free and low-crash, grouped with no device provider or data plane.",
367
367
  "entry": "./dist/builtins/composer/index.js",
368
368
  "protected": true,
369
369
  "execution": {