@camstack/system 1.2.439 → 1.2.441

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 (103) hide show
  1. package/dist/addon-runner.js +743 -79
  2. package/dist/addon-runner.mjs +743 -79
  3. package/dist/addon-utils.js +1 -1
  4. package/dist/addon-utils.mjs +1 -1
  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 +1 -1
  10. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  11. package/dist/builtins/autotrack/index.js +1 -1
  12. package/dist/builtins/autotrack/index.mjs +1 -1
  13. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +2 -2
  14. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2 -2
  15. package/dist/builtins/calendars/calendars.addon.js +1 -1
  16. package/dist/builtins/calendars/calendars.addon.mjs +1 -1
  17. package/dist/builtins/camera-grid/index.js +1 -1
  18. package/dist/builtins/camera-grid/index.mjs +1 -1
  19. package/dist/builtins/composer/composer.addon.js +2 -2
  20. package/dist/builtins/composer/composer.addon.mjs +2 -2
  21. package/dist/builtins/console-logging/index.js +1 -1
  22. package/dist/builtins/console-logging/index.mjs +1 -1
  23. package/dist/builtins/core-blocks/block-settings-store.d.ts +1 -1
  24. package/dist/builtins/core-blocks/core-blocks.addon.js +77 -11
  25. package/dist/builtins/core-blocks/core-blocks.addon.mjs +77 -12
  26. package/dist/builtins/core-blocks/index.mjs +1 -1
  27. package/dist/builtins/device-manager/device-manager.addon.js +181 -59
  28. package/dist/builtins/device-manager/device-manager.addon.mjs +180 -60
  29. package/dist/builtins/device-manager/device-removal-hooks.d.ts +0 -11
  30. package/dist/builtins/hub-forwarder/index.js +1 -1
  31. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  32. package/dist/builtins/keychain/index.js +29 -11
  33. package/dist/builtins/keychain/index.mjs +29 -11
  34. package/dist/builtins/keychain/keychain-service.d.ts +8 -0
  35. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  36. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  37. package/dist/builtins/local-auth/local-auth.addon.js +2 -2
  38. package/dist/builtins/local-auth/local-auth.addon.mjs +2 -2
  39. package/dist/builtins/local-network/local-network.addon.js +2 -2
  40. package/dist/builtins/local-network/local-network.addon.mjs +2 -2
  41. package/dist/builtins/loki-logging/index.js +1 -1
  42. package/dist/builtins/loki-logging/index.mjs +1 -1
  43. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  44. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  45. package/dist/builtins/platform-probe/index.js +1 -1
  46. package/dist/builtins/platform-probe/index.mjs +1 -1
  47. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  48. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  49. package/dist/builtins/snapshot/index.js +1 -1
  50. package/dist/builtins/snapshot/index.mjs +1 -1
  51. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  52. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  53. package/dist/builtins/sqlite-storage/index.js +1 -1
  54. package/dist/builtins/sqlite-storage/index.mjs +1 -1
  55. package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +38 -7
  56. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +69 -3
  57. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +69 -3
  58. package/dist/builtins/sqlite-storage/storage-admin-provider.d.ts +31 -0
  59. package/dist/builtins/storage-orchestrator/hub-settings-forward.d.ts +3 -3
  60. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +4 -4
  61. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +4 -4
  62. package/dist/builtins/system-config/system-config.addon.js +2 -2
  63. package/dist/builtins/system-config/system-config.addon.mjs +2 -2
  64. package/dist/builtins/winston-logging/index.js +1 -1
  65. package/dist/builtins/winston-logging/index.mjs +1 -1
  66. package/dist/{composition-sources-B4jC2FC7.js → composition-sources-BG-W2U0d.js} +1 -1
  67. package/dist/{composition-sources-BGOSCGWa.mjs → composition-sources-ByNISOnW.mjs} +1 -1
  68. package/dist/{constants-B92BjObl.mjs → constants-DJILnUSb.mjs} +1 -1
  69. package/dist/{constants-BRsjQwi-.js → constants-UojhAJcm.js} +1 -1
  70. package/dist/{device-ca-DHG9OW2m.js → device-ca-196DAEZT.js} +1 -1
  71. package/dist/{device-ca-46BUsWD1.mjs → device-ca-D8Ri9TVz.mjs} +1 -1
  72. package/dist/{dist-yI6kF6r6.mjs → dist-BWvkuc31.mjs} +248 -27
  73. package/dist/{dist-BOWdLjoK.js → dist-BiTCcaf-.js} +265 -26
  74. package/dist/file-host-worker.js +1 -1
  75. package/dist/file-host-worker.mjs +1 -1
  76. package/dist/{hub-mdns-ciao-DGwVc2uh.mjs → hub-mdns-ciao-Cnd0bTB9.mjs} +1 -1
  77. package/dist/{hub-mdns-ciao-D7S5AJRU.js → hub-mdns-ciao-DOBTq8qr.js} +1 -1
  78. package/dist/index.js +336 -336
  79. package/dist/index.mjs +337 -337
  80. package/dist/kernel/addon-settings-store.d.ts +43 -0
  81. package/dist/kernel/config-manager.d.ts +0 -19
  82. package/dist/kernel/device-settings-store.d.ts +74 -0
  83. package/dist/kernel/legacy-blob-guard.d.ts +58 -0
  84. package/dist/kernel/moleculer/runner-addon-settings.d.ts +34 -0
  85. package/dist/kernel/moleculer/runner-device-settings.d.ts +39 -0
  86. package/dist/kernel/prefix-walk.d.ts +39 -0
  87. package/dist/kernel/sections-store.d.ts +20 -0
  88. package/dist/kernel/settings-door-view.d.ts +2 -2
  89. package/dist/kernel/settings-view-types.d.ts +5 -30
  90. package/dist/kernel/store-settings-view.d.ts +0 -3
  91. package/dist/prefix-range-D_KueXbQ.js +27 -0
  92. package/dist/prefix-range-Dl0znowN.mjs +22 -0
  93. package/dist/prefix-walk-DAOBSyH1.mjs +88 -0
  94. package/dist/prefix-walk-Dv6MLZlM.js +99 -0
  95. package/dist/{restore-archive-CpdUO-uS.mjs → restore-archive-4ziluTU3.mjs} +1 -1
  96. package/dist/{restore-archive-DiGiI6Jp.js → restore-archive-CfSSjKnA.js} +1 -1
  97. package/dist/{retired-settings-keys-UsVtLOT0.mjs → retired-settings-keys-Bhwe4ymb.mjs} +2 -2
  98. package/dist/{retired-settings-keys-CyQ7uvta.js → retired-settings-keys-D_VwZiDt.js} +10 -4
  99. package/dist/{wal-maintenance-xsvdT5Go.mjs → wal-maintenance-B57SAp4a.mjs} +0 -0
  100. package/dist/{wal-maintenance-DEL_jeG0.js → wal-maintenance-CgZTNWAz.js} +0 -0
  101. package/package.json +5 -2
  102. package/dist/{custom-action-registry-Bf_YnagS.js → custom-action-registry-BKmoaqG0.js} +1 -1
  103. package/dist/{custom-action-registry-BQnbN0DP.mjs → custom-action-registry-CyUuhATc.mjs} +1 -1
@@ -0,0 +1,99 @@
1
+ const require_prefix_range = require("./prefix-range-D_KueXbQ.js");
2
+ //#region src/kernel/prefix-walk.ts
3
+ function isRecord(value) {
4
+ return typeof value === "object" && value !== null && !Array.isArray(value);
5
+ }
6
+ function unwrapStoredValue(parsed) {
7
+ if (!isRecord(parsed) || !("value" in parsed)) return parsed;
8
+ return parsed.value;
9
+ }
10
+ /**
11
+ * Rows one page of a prefix read asks for.
12
+ *
13
+ * Below `SETTINGS_QUERY_DEFAULT_ROW_CAP` (2 000, `query-bounds.ts`) on purpose:
14
+ * this read now names its own bound, so the engine's defensive cap is never the
15
+ * thing that decides how much of the answer the caller gets.
16
+ */
17
+ var PREFIX_PAGE_ROWS = 1e3;
18
+ /**
19
+ * Pages one prefix read may take before it refuses.
20
+ *
21
+ * 512 pages is 512 000 rows — three orders of magnitude past the largest live
22
+ * scope (`addon-device-settings` for one addon over a ~1 019-device fleet) and
23
+ * still a bound, because a walk with no bound is the defect this file was
24
+ * fixing, not one to reintroduce.
25
+ */
26
+ var PREFIX_PAGE_BUDGET = 512;
27
+ /**
28
+ * Every row under `prefix`, or a throw — never the first 2 000 of them.
29
+ *
30
+ * **The defect.** This issued ONE `query` with no `limit`, and
31
+ * `queryDeclared` resolves an absent limit to `SETTINGS_QUERY_DEFAULT_ROW_CAP`
32
+ * and cuts the result there. On the live hub that fired 138 times in two hours
33
+ * (`settings-store query truncated by a defensive row cap`, collection
34
+ * `addon-device-settings`, `rowCap: 2000`, `requestedLimit: null`): a
35
+ * ~1 019-device fleet with more than two stored keys per device puts one
36
+ * addon's `<addonId>:` range past the cap. The engine warned; the door did not
37
+ * notice, and handed its caller a short map that is **shape-identical to a
38
+ * complete one**. Every device whose rows sort past the cap reads as "has no
39
+ * stored settings", which is exactly what a device with none looks like.
40
+ *
41
+ * **The fix is a keyset walk, not a bigger limit.** The cursor is the last id
42
+ * of the previous page, INCLUSIVE — so the page boundary re-reads exactly one
43
+ * row (ids are unique, so a full page always advances) and no row can fall
44
+ * between two pages the way an `OFFSET` walk drops rows under a concurrent
45
+ * write (D295 rule 1). Re-reading is free here: the accumulator is keyed by
46
+ * suffix, so the duplicate overwrites itself with its own value.
47
+ *
48
+ * `ORDER BY id` is not decoration — the cursor is only meaningful if the
49
+ * engine returns the range in the order the cursor advances through. It is the
50
+ * primary key, so the ordering is the range scan's own.
51
+ *
52
+ * @throws when the prefix cannot be expressed as a range and the collection is
53
+ * larger than one page, or when the walk exceeds {@link PREFIX_PAGE_BUDGET}.
54
+ * A throw is the point: a caller that cannot be answered completely must not
55
+ * be handed something that looks like a complete answer.
56
+ */
57
+ async function loadPrefixed(door, collection, prefix, decode = unwrapStoredValue) {
58
+ const range = require_prefix_range.prefixRange(prefix);
59
+ const result = {};
60
+ let cursor = range?.lo ?? null;
61
+ for (let page = 0;; page++) {
62
+ if (page >= PREFIX_PAGE_BUDGET) throw new Error(`settings door: reading "${prefix}" from "${collection}" exceeded ${PREFIX_PAGE_BUDGET} pages of ${PREFIX_PAGE_ROWS} rows. Refusing to return the part that was read — a partial scope read is indistinguishable from an empty one.`);
63
+ const rows = await door.query({
64
+ collection,
65
+ filter: {
66
+ ...range !== null && cursor !== null ? { whereBetween: { id: [cursor, range.hi] } } : {},
67
+ orderBy: {
68
+ field: "id",
69
+ direction: "asc"
70
+ },
71
+ limit: PREFIX_PAGE_ROWS
72
+ }
73
+ });
74
+ for (const row of rows) {
75
+ if (range !== null && (row.id < range.lo || row.id >= range.hi)) continue;
76
+ if (!row.id.startsWith(prefix)) continue;
77
+ result[row.id.slice(prefix.length)] = decode(row.data);
78
+ }
79
+ if (rows.length < PREFIX_PAGE_ROWS) return result;
80
+ const last = rows[rows.length - 1];
81
+ if (last === void 0) return result;
82
+ if (range === null) throw new Error(`settings door: prefix "${prefix}" on "${collection}" cannot be expressed as an id range, and the unfiltered read filled a page — the answer would be partial. Use an ASCII, non-empty prefix.`);
83
+ if (last.id === cursor) throw new Error(`settings door: reading "${prefix}" from "${collection}" made no progress at id "${last.id}" — ids under a prefix must be unique.`);
84
+ cursor = last.id;
85
+ }
86
+ }
87
+ //#endregion
88
+ Object.defineProperty(exports, "loadPrefixed", {
89
+ enumerable: true,
90
+ get: function() {
91
+ return loadPrefixed;
92
+ }
93
+ });
94
+ Object.defineProperty(exports, "unwrapStoredValue", {
95
+ enumerable: true,
96
+ get: function() {
97
+ return unwrapStoredValue;
98
+ }
99
+ });
@@ -1,4 +1,4 @@
1
- import { b as DATABASE_SNAPSHOT_SUFFIX } from "./dist-yI6kF6r6.mjs";
1
+ import { b as DATABASE_SNAPSHOT_SUFFIX } from "./dist-BWvkuc31.mjs";
2
2
  import { createCipheriv, createDecipheriv, createHash, createPrivateKey, createPublicKey, diffieHellman, generateKeyPairSync, hkdfSync, randomBytes } from "node:crypto";
3
3
  import { Buffer as Buffer$1 } from "buffer";
4
4
  import * as fsp from "node:fs/promises";
@@ -1,5 +1,5 @@
1
1
  const require_chunk = require("./chunk-Cek0wNdY.js");
2
- const require_dist = require("./dist-BOWdLjoK.js");
2
+ const require_dist = require("./dist-BiTCcaf-.js");
3
3
  let node_crypto = require("node:crypto");
4
4
  let buffer = require("buffer");
5
5
  let node_fs_promises = require("node:fs/promises");
@@ -1,4 +1,4 @@
1
- import { Rr as asJsonObject } from "./dist-yI6kF6r6.mjs";
1
+ import { asJsonObject } from "@camstack/types/addon";
2
2
  //#region src/builtins/sqlite-storage/retired-settings-keys.ts
3
3
  /**
4
4
  * Is THIS node the one whose settings store is the cluster's authority?
@@ -353,4 +353,4 @@ function errText(err) {
353
353
  return err instanceof Error ? err.message : String(err);
354
354
  }
355
355
  //#endregion
356
- export { purgeRetiredSettingsRows as n, retiredKeyStoreOf as r, purgeRetiredSettingsKeys as t };
356
+ export { retiredKeyStoreOf as i, purgeRetiredSettingsKeys as n, purgeRetiredSettingsRows as r, RETIRED_SETTINGS_KEYS as t };
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-BOWdLjoK.js");
1
+ let _camstack_types_addon = require("@camstack/types/addon");
2
2
  //#region src/builtins/sqlite-storage/retired-settings-keys.ts
3
3
  /**
4
4
  * Is THIS node the one whose settings store is the cluster's authority?
@@ -169,7 +169,7 @@ var RETIRED_SETTINGS_ROWS = [
169
169
  function retiredKeyStoreOf(backend) {
170
170
  return {
171
171
  async read(spec) {
172
- return require_dist.asJsonObject(await backend.get({
172
+ return (0, _camstack_types_addon.asJsonObject)(await backend.get({
173
173
  namespace: spec.namespace,
174
174
  collection: spec.collection,
175
175
  key: spec.row
@@ -194,7 +194,7 @@ function planNestedRetiredKeyPurge(blob, spec) {
194
194
  if (nestedKeys.length === 0) return [];
195
195
  const found = [];
196
196
  for (const [mapKey, value] of Object.entries(blob)) {
197
- const inner = require_dist.asJsonObject(value);
197
+ const inner = (0, _camstack_types_addon.asJsonObject)(value);
198
198
  if (inner === null) continue;
199
199
  for (const retired of nestedKeys) if (retired in inner) found.push(`${mapKey}.${retired}`);
200
200
  }
@@ -257,7 +257,7 @@ async function purgeRetiredSettingsKeys(store, logger, specs = RETIRED_SETTINGS_
257
257
  const next = Object.fromEntries(Object.entries(blob).filter(([key]) => !doomedSet.has(key)).map(([key, value]) => {
258
258
  const retired = nestedByMapKey.get(key);
259
259
  if (retired === void 0) return [key, value];
260
- const inner = require_dist.asJsonObject(value);
260
+ const inner = (0, _camstack_types_addon.asJsonObject)(value);
261
261
  if (inner === null) return [key, value];
262
262
  return [key, Object.fromEntries(Object.entries(inner).filter(([k]) => !retired.has(k)))];
263
263
  }));
@@ -353,6 +353,12 @@ function errText(err) {
353
353
  return err instanceof Error ? err.message : String(err);
354
354
  }
355
355
  //#endregion
356
+ Object.defineProperty(exports, "RETIRED_SETTINGS_KEYS", {
357
+ enumerable: true,
358
+ get: function() {
359
+ return RETIRED_SETTINGS_KEYS;
360
+ }
361
+ });
356
362
  Object.defineProperty(exports, "purgeRetiredSettingsKeys", {
357
363
  enumerable: true,
358
364
  get: function() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/system",
3
- "version": "1.2.439",
3
+ "version": "1.2.441",
4
4
  "description": "Core addon for CamStack — builtins, pipeline, process management, auth, logging, events",
5
5
  "keywords": [
6
6
  "camstack",
@@ -57,7 +57,7 @@
57
57
  "icon": "assets/sqlite-settings/icon.svg",
58
58
  "color": "#0d9488",
59
59
  "entry": "./dist/builtins/sqlite-storage/sqlite-settings.addon.js",
60
- "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.",
60
+ "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, `storage-admin` (list tables, drop one nothing owns) 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.",
61
61
  "execution": {
62
62
  "isolate": true,
63
63
  "heapProfile": "heavy",
@@ -72,6 +72,9 @@
72
72
  },
73
73
  {
74
74
  "name": "database-snapshot"
75
+ },
76
+ {
77
+ "name": "storage-admin"
75
78
  }
76
79
  ]
77
80
  },
@@ -2,10 +2,10 @@ const require_chunk = require("./chunk-Cek0wNdY.js");
2
2
  let node_crypto = require("node:crypto");
3
3
  let node_path = require("node:path");
4
4
  node_path = require_chunk.__toESM(node_path);
5
+ let _camstack_types_addon = require("@camstack/types/addon");
5
6
  let node_fs = require("node:fs");
6
7
  node_fs = require_chunk.__toESM(node_fs);
7
8
  let node_util = require("node:util");
8
- let _camstack_types_addon = require("@camstack/types/addon");
9
9
  let node_http = require("node:http");
10
10
  let node_zlib = require("node:zlib");
11
11
  let node_perf_hooks = require("node:perf_hooks");
@@ -1,10 +1,10 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import * as path$1 from "node:path";
3
3
  import path from "node:path";
4
+ import { HF_REPO, MODEL_FORMATS, describeCustomActions, hfModelUrl } from "@camstack/types/addon";
4
5
  import * as fs from "node:fs";
5
6
  import { createReadStream, promises } from "node:fs";
6
7
  import { promisify } from "node:util";
7
- import { HF_REPO, MODEL_FORMATS, describeCustomActions, hfModelUrl } from "@camstack/types/addon";
8
8
  import { createServer } from "node:http";
9
9
  import { brotliCompress, constants as constants$1, gzip } from "node:zlib";
10
10
  import { PerformanceObserver } from "node:perf_hooks";