@camstack/system 1.2.27 → 1.2.29

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 (58) hide show
  1. package/dist/addon-runner.js +3 -3
  2. package/dist/addon-runner.mjs +2 -2
  3. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  4. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  5. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  6. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  7. package/dist/builtins/alerts/alerts.addon.d.ts +0 -7
  8. package/dist/builtins/alerts/alerts.addon.js +47 -25
  9. package/dist/builtins/alerts/alerts.addon.mjs +47 -25
  10. package/dist/builtins/alerts/prune-policy.d.ts +44 -0
  11. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
  12. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
  13. package/dist/builtins/console-logging/index.js +1 -1
  14. package/dist/builtins/console-logging/index.mjs +1 -1
  15. package/dist/builtins/device-manager/device-manager.addon.js +1 -1
  16. package/dist/builtins/device-manager/device-manager.addon.mjs +1 -1
  17. package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
  18. package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
  19. package/dist/builtins/hub-forwarder/index.js +1 -1
  20. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  21. package/dist/builtins/local-auth/local-auth.addon.js +1 -1
  22. package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
  23. package/dist/builtins/local-network/local-network.addon.js +1 -1
  24. package/dist/builtins/local-network/local-network.addon.mjs +1 -1
  25. package/dist/builtins/loki-logging/index.js +1 -1
  26. package/dist/builtins/loki-logging/index.mjs +1 -1
  27. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  28. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  29. package/dist/builtins/platform-probe/index.js +1 -1
  30. package/dist/builtins/platform-probe/index.mjs +1 -1
  31. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  32. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  33. package/dist/builtins/snapshot/index.js +1 -1
  34. package/dist/builtins/snapshot/index.mjs +1 -1
  35. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  36. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  37. package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +7 -1
  38. package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.ts +8 -2
  39. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +22 -4
  40. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +22 -4
  41. package/dist/builtins/storage-orchestrator/data-store-dispatch.d.ts +12 -0
  42. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +18 -7
  43. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +78 -11
  44. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +78 -11
  45. package/dist/builtins/system-config/system-config.addon.js +1 -1
  46. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  47. package/dist/builtins/winston-logging/index.js +1 -1
  48. package/dist/builtins/winston-logging/index.mjs +1 -1
  49. package/dist/{dist-BXmFvn3h.mjs → dist-B7hOpr5i.mjs} +411 -166
  50. package/dist/{dist-BxtIzexq.js → dist-CPmFYLqq.js} +416 -165
  51. package/dist/index.d.ts +2 -0
  52. package/dist/index.js +106 -2
  53. package/dist/index.mjs +102 -3
  54. package/dist/kernel/heap-watch.d.ts +36 -0
  55. package/dist/kernel/transport/uds-event-bus.d.ts +4 -1
  56. package/dist/{manifest-python-deps-KZ00cbfP.js → manifest-python-deps-BqE5j0-O.js} +25 -4
  57. package/dist/{manifest-python-deps-BNOApgK0.mjs → manifest-python-deps-Ck4-9K9m.mjs} +25 -4
  58. package/package.json +7 -3
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("./chunk-Cek0wNdY.js");
3
- const require_dist = require("./dist-BxtIzexq.js");
3
+ const require_dist = require("./dist-CPmFYLqq.js");
4
4
  const require_model_download_service = require("./model-download-service-hf0ookyy.js");
5
- const require_manifest_python_deps = require("./manifest-python-deps-KZ00cbfP.js");
5
+ const require_manifest_python_deps = require("./manifest-python-deps-BqE5j0-O.js");
6
6
  const require_resource_monitor = require("./resource-monitor-DNNomR-i.js");
7
7
  const require_builtins_sqlite_storage_filesystem_storage_addon = require("./builtins/sqlite-storage/filesystem-storage.addon.js");
8
8
  const require_builtins_sqlite_storage_sqlite_settings_addon = require("./builtins/sqlite-storage/sqlite-settings.addon.js");
@@ -24,6 +24,8 @@ require("./builtins/local-auth/index.js");
24
24
  const require_builtins_device_manager_device_manager_addon = require("./builtins/device-manager/device-manager.addon.js");
25
25
  require("./builtins/device-manager/index.js");
26
26
  const require_custom_action_registry = require("./custom-action-registry-jY0NOZK8.js");
27
+ let node_v8 = require("node:v8");
28
+ node_v8 = require_chunk.__toESM(node_v8);
27
29
  let _camstack_types_node = require("@camstack/types/node");
28
30
  let zod = require("zod");
29
31
  let node_http = require("node:http");
@@ -52,6 +54,100 @@ fs = require_chunk.__toESM(fs, 1);
52
54
  let path = require("path");
53
55
  path = require_chunk.__toESM(path, 1);
54
56
  let module$1 = require("module");
57
+ //#region src/kernel/heap-watch.ts
58
+ /**
59
+ * heap-watch — hub-main's own memory, on the record.
60
+ *
61
+ * ## Why this exists
62
+ *
63
+ * hub-main is launched with `--max-old-space-size=1536` (docker-entrypoint) and
64
+ * has logged NOTHING about its own heap. When it died on 2026-08-01/02 the only
65
+ * trace was V8's own stderr line:
66
+ *
67
+ * FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
68
+ *
69
+ * which carries no process name, no heap number and no history — the whole
70
+ * server restarts and the evidence is gone. Four of those in ~15h, and the one
71
+ * at 06:57:57 landed nine seconds after a viewer opened a WebRTC session, which
72
+ * is why the app sat in a permanent "loading": the hub was dying as it
73
+ * connected.
74
+ *
75
+ * `[mem]` reports already exist for forked addon runners (SIGUSR2 in
76
+ * `addon-runner.ts`) — hub-main, the one process that actually OOMs, was the
77
+ * one process with no telemetry at all.
78
+ *
79
+ * ## What it gives
80
+ *
81
+ * A heartbeat carrying the numbers that separate the two possible stories, and
82
+ * a WARN as the heap approaches the ceiling — the line that will exist BEFORE
83
+ * the next fatal instead of after it:
84
+ *
85
+ * - `heapUsedMb` climbing steadily between restarts → a leak;
86
+ * - `heapUsedMb` flat with a sharp jump under load → a burst allocation, and
87
+ * the timestamp says what was being served.
88
+ *
89
+ * `external`/`arrayBuffers` ride along because they are NOT bounded by
90
+ * `--max-old-space-size` and are most of the gap between a 1.5GB cap and the
91
+ * ~2.05GB RSS observed live: a diagnosis that only looks at the JS heap
92
+ * misreads that process by 500MB.
93
+ */
94
+ /** Heartbeat period. Slow enough to be free, fast enough that the sample before
95
+ * a fatal is recent. */
96
+ var HEAP_WATCH_INTERVAL_MS = 6e4;
97
+ /** Warn above this share of the heap ceiling. Chosen so the warning precedes
98
+ * the fatal by more than one interval under realistic growth. */
99
+ var HEAP_WATCH_WARN_RATIO = .8;
100
+ var MB = (bytes) => Math.round(bytes / 1048576);
101
+ /**
102
+ * Build a sample from raw readings. Pure so the thresholds are testable without
103
+ * allocating a gigabyte to reach them.
104
+ */
105
+ function buildHeapSample(mem, heapLimitBytes, warnRatio = HEAP_WATCH_WARN_RATIO) {
106
+ const usedRatio = heapLimitBytes > 0 ? mem.heapUsed / heapLimitBytes : 0;
107
+ return {
108
+ rssMb: MB(mem.rss),
109
+ heapUsedMb: MB(mem.heapUsed),
110
+ heapTotalMb: MB(mem.heapTotal),
111
+ heapLimitMb: MB(heapLimitBytes),
112
+ externalMb: MB(mem.external),
113
+ arrayBuffersMb: MB(mem.arrayBuffers),
114
+ usedRatio: Math.round(usedRatio * 100) / 100,
115
+ nearLimit: usedRatio >= warnRatio
116
+ };
117
+ }
118
+ var consoleSink = {
119
+ info: (line) => console.log(line),
120
+ warn: (line) => console.warn(line)
121
+ };
122
+ function format$1(label, s) {
123
+ return `[mem] ${label} rss=${s.rssMb}MB heapUsed=${s.heapUsedMb}MB heapTotal=${s.heapTotalMb}MB heapLimit=${s.heapLimitMb}MB used=${Math.round(s.usedRatio * 100)}% external=${s.externalMb}MB arrayBuffers=${s.arrayBuffersMb}MB`;
124
+ }
125
+ /**
126
+ * Start the heartbeat. Returns a stop function.
127
+ *
128
+ * `unref`ed so it can never hold the process open, and every read is wrapped:
129
+ * a diagnostic that can crash the process it watches is worse than none.
130
+ */
131
+ function startHeapWatch(label = "hub-main", sink = consoleSink, intervalMs = HEAP_WATCH_INTERVAL_MS) {
132
+ const tick = () => {
133
+ try {
134
+ const sample = buildHeapSample(process.memoryUsage(), node_v8.getHeapStatistics().heap_size_limit);
135
+ const line = format$1(label, sample);
136
+ if (sample.nearLimit) sink.warn(`${line} — APPROACHING HEAP LIMIT`);
137
+ else sink.info(line);
138
+ } catch {}
139
+ };
140
+ const timer = setInterval(tick, intervalMs);
141
+ timer.unref?.();
142
+ tick();
143
+ let stopped = false;
144
+ return () => {
145
+ if (stopped) return;
146
+ stopped = true;
147
+ clearInterval(timer);
148
+ };
149
+ }
150
+ //#endregion
55
151
  //#region src/events/event-bus.ts
56
152
  var EventBus = class {
57
153
  listeners = /* @__PURE__ */ new Map();
@@ -5948,6 +6044,10 @@ var INFRA_CAPABILITIES = [
5948
6044
  name: "storage-provider",
5949
6045
  required: true
5950
6046
  },
6047
+ {
6048
+ name: "data-store-provider",
6049
+ required: true
6050
+ },
5951
6051
  {
5952
6052
  name: "storage",
5953
6053
  required: true
@@ -94119,6 +94219,8 @@ exports.FsStorageBackend = FsStorageBackend;
94119
94219
  exports.HEALTH_MONITOR_GRACE_PERIOD_MS = HEALTH_MONITOR_GRACE_PERIOD_MS;
94120
94220
  exports.HEALTH_MONITOR_RETRY_INTERVALS_MS = HEALTH_MONITOR_RETRY_INTERVALS_MS;
94121
94221
  exports.HEALTH_MONITOR_TICK_MS = HEALTH_MONITOR_TICK_MS;
94222
+ exports.HEAP_WATCH_INTERVAL_MS = HEAP_WATCH_INTERVAL_MS;
94223
+ exports.HEAP_WATCH_WARN_RATIO = HEAP_WATCH_WARN_RATIO;
94122
94224
  exports.HUB_CAP_FWD_ACTION = require_manifest_python_deps.HUB_CAP_FWD_ACTION;
94123
94225
  exports.HUB_CAP_FWD_SERVICE = require_manifest_python_deps.HUB_CAP_FWD_SERVICE;
94124
94226
  exports.HubForwarderAddon = require_builtins_hub_forwarder_index.HubForwarderAddon$1;
@@ -94193,6 +94295,7 @@ Object.defineProperty(exports, "buildBinaryPath", {
94193
94295
  }
94194
94296
  });
94195
94297
  exports.buildCapRouters = buildCapRouters;
94298
+ exports.buildHeapSample = buildHeapSample;
94196
94299
  exports.buildLinkChain = require_manifest_python_deps.buildLinkChain;
94197
94300
  exports.buildNativeCapProxy = require_manifest_python_deps.buildNativeCapProxy;
94198
94301
  exports.buildNodeManifest = buildNodeManifest;
@@ -94358,6 +94461,7 @@ exports.scopesAllowDeviceCap = scopesAllowDeviceCap;
94358
94461
  exports.serializeTypedArrays = require_manifest_python_deps.serializeTypedArrays;
94359
94462
  exports.setHubConnected = require_manifest_python_deps.setHubConnected;
94360
94463
  exports.setNodeEventInterest = require_manifest_python_deps.setNodeEventInterest;
94464
+ exports.startHeapWatch = startHeapWatch;
94361
94465
  exports.stripCamstackDeps = stripCamstackDeps;
94362
94466
  exports.subscribePassthrough = require_manifest_python_deps.subscribePassthrough;
94363
94467
  exports.udsChildLogToWorkerEntry = require_manifest_python_deps.udsChildLogToWorkerEntry;
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { a as __toCommonJS, i as __require, n as __esmMin, o as __toESM$1, r as __exportAll, t as __commonJSMin$1 } from "./chunk-CNf5ZN-e.mjs";
2
- import { B as logLevelAtMost, Dt as readinessKey, Et as parseJsonUnknown$1, F as isVoidInput, I as kebabToCamel, L as lifecycleJobSchema, M as isArrayOutputSchema, N as isCollectionArrayMethod, Ot as resolveCapMount, P as isObjectInput, Tt as parseJsonObject, V as looseSchema, W as objectInputDeclaresAddonId, _t as asString$1, c as RUNTIME_DEFAULTS, ct as DEVICE_STATUS_METHOD, ft as ReadinessRegistry, gt as asNumber, ht as asJsonObject$1, it as errMsg$1, jt as EventCategory$1, k as extractNestedAddonId, kt as scopeKey, m as addonSettingsCapability, ot as DATAPLANE_SECRET_HEADER$1, pt as ReadinessTimeoutError, q as procedureAuthKey, s as METHOD_ACCESS_MAP, st as DEVICE_SETTINGS_CONTRIBUTION_METHODS, t as ALL_CAPABILITY_DEFINITIONS, vt as createEvent, xt as expandCapMethods, yt as emitDownForOwnedCaps } from "./dist-BXmFvn3h.mjs";
2
+ import { A as extractNestedAddonId, At as scopeKey, Dt as parseJsonUnknown$1, Et as parseJsonObject, F as isObjectInput, G as objectInputDeclaresAddonId, H as looseSchema, I as isVoidInput, J as procedureAuthKey, L as kebabToCamel, Mt as EventCategory$1, N as isArrayOutputSchema, Ot as readinessKey, P as isCollectionArrayMethod, R as lifecycleJobSchema, St as expandCapMethods, V as logLevelAtMost, _t as asNumber, at as errMsg$1, bt as emitDownForOwnedCaps, c as RUNTIME_DEFAULTS, ct as DEVICE_SETTINGS_CONTRIBUTION_METHODS, gt as asJsonObject$1, kt as resolveCapMount, lt as DEVICE_STATUS_METHOD, m as addonSettingsCapability, mt as ReadinessTimeoutError, pt as ReadinessRegistry, s as METHOD_ACCESS_MAP, st as DATAPLANE_SECRET_HEADER$1, t as ALL_CAPABILITY_DEFINITIONS, vt as asString$1, yt as createEvent } from "./dist-B7hOpr5i.mjs";
3
3
  import { a as downloadModel, c as getModelFilePath, d as contentTypeFor, f as createAuthenticatedFileServer, h as resolveFilePath, i as downloadFile, l as isModelDownloaded, m as parseTokenizedUrl, n as collectModelFiles, o as ensureModel, p as parseRangeHeader, r as deleteModelFromDisk, s as fetchJson, t as ModelDownloadService, u as createFileDataPlaneHandler } from "./model-download-service-Cp9f4dk6.mjs";
4
- import { $ as buildNativeCapProxy, A as createHubCapForwardService, B as AGENT_CAP_FWD_ACTION, C as brokerTransportLink, Ct as resolveAddonClass, D as localProviderLink, E as ipcParentLink, F as createUdsLogger, G as callWithServiceDiscovery, H as CapRouteResolver, I as createUdsLoggerWithControl, J as UdsLocalTransportServer, K as createLocalTransport, L as LocalChildClient, M as createUdsEventBridge, N as createUdsEventBus, O as HUB_CAP_FWD_ACTION, P as udsChildLogToWorkerEntry, Q as encodeFrame, R as LocalChildRegistry, S as brokerCallForCap, St as runNpm, T as ipcChildLink, U as CapRouteError, V as AGENT_CAP_FWD_SERVICE, W as classifyCapRoute, X as localEndpointPath, Y as SocketChannel, Z as FrameDecoder, _ as createKernelHwAccel, _t as CapabilityHandle, a as getWorkerDeviceRegistry, b as __resetCapUsageRegistryForTests, bt as installManifestNativeDeps, c as setHubConnected, ct as NATIVE_PROVIDER_SERVICE_INFIX, d as getBrokerEventBus, dt as capBareAction, et as buildUdsNativeCapProxy, f as getMoleculerEventStats, ft as capServiceName, g as AddonDepsManager, gt as DeviceRegistry, h as subscribePassthrough, ht as serializeTypedArrays, i as createUdsAddonContext, it as mountNativeCapService, j as createParentUnownedCallHandler, k as HUB_CAP_FWD_SERVICE, l as EVENT_TOPIC_PREFIX, lt as capActionName, m as setNodeEventInterest, mt as deserializeTypedArrays, n as adaptBrokerToCluster, o as getOrInitReadinessRegistry, ot as createAddonService, p as registerEventBusService, pt as parseCapAction, q as UdsLocalTransportClient, r as createAddonContext, s as getOrInitReadinessRegistryForClient, st as validateProviderRegistrations, t as installManifestPythonDeps, tt as createBrokerDeviceManagerApi, u as clusterEventTopic, ut as capActionSuffix, v as resolveHwAccel, vt as CapabilityUnavailableError, w as buildLinkChain, wt as createAddonDataPlaneFacility, x as getCapUsageRegistry, xt as resolveNpmInvocation, y as CapUsageRegistry, yt as copyBundledNativeModules, z as UDS_NO_ROUTE_PREFIX } from "./manifest-python-deps-BNOApgK0.mjs";
4
+ import { $ as buildNativeCapProxy, A as createHubCapForwardService, B as AGENT_CAP_FWD_ACTION, C as brokerTransportLink, Ct as resolveAddonClass, D as localProviderLink, E as ipcParentLink, F as createUdsLogger, G as callWithServiceDiscovery, H as CapRouteResolver, I as createUdsLoggerWithControl, J as UdsLocalTransportServer, K as createLocalTransport, L as LocalChildClient, M as createUdsEventBridge, N as createUdsEventBus, O as HUB_CAP_FWD_ACTION, P as udsChildLogToWorkerEntry, Q as encodeFrame, R as LocalChildRegistry, S as brokerCallForCap, St as runNpm, T as ipcChildLink, U as CapRouteError, V as AGENT_CAP_FWD_SERVICE, W as classifyCapRoute, X as localEndpointPath, Y as SocketChannel, Z as FrameDecoder, _ as createKernelHwAccel, _t as CapabilityHandle, a as getWorkerDeviceRegistry, b as __resetCapUsageRegistryForTests, bt as installManifestNativeDeps, c as setHubConnected, ct as NATIVE_PROVIDER_SERVICE_INFIX, d as getBrokerEventBus, dt as capBareAction, et as buildUdsNativeCapProxy, f as getMoleculerEventStats, ft as capServiceName, g as AddonDepsManager, gt as DeviceRegistry, h as subscribePassthrough, ht as serializeTypedArrays, i as createUdsAddonContext, it as mountNativeCapService, j as createParentUnownedCallHandler, k as HUB_CAP_FWD_SERVICE, l as EVENT_TOPIC_PREFIX, lt as capActionName, m as setNodeEventInterest, mt as deserializeTypedArrays, n as adaptBrokerToCluster, o as getOrInitReadinessRegistry, ot as createAddonService, p as registerEventBusService, pt as parseCapAction, q as UdsLocalTransportClient, r as createAddonContext, s as getOrInitReadinessRegistryForClient, st as validateProviderRegistrations, t as installManifestPythonDeps, tt as createBrokerDeviceManagerApi, u as clusterEventTopic, ut as capActionSuffix, v as resolveHwAccel, vt as CapabilityUnavailableError, w as buildLinkChain, wt as createAddonDataPlaneFacility, x as getCapUsageRegistry, xt as resolveNpmInvocation, y as CapUsageRegistry, yt as copyBundledNativeModules, z as UDS_NO_ROUTE_PREFIX } from "./manifest-python-deps-Ck4-9K9m.mjs";
5
5
  import { n as getSinglePidStats, t as getPidStats } from "./resource-monitor-BkP504Vq.mjs";
6
6
  import { FilesystemStorageAddon, t as FilesystemStorageProvider } from "./builtins/sqlite-storage/filesystem-storage.addon.mjs";
7
7
  import { SqliteSettingsAddon, t as SqliteSettingsBackend } from "./builtins/sqlite-storage/sqlite-settings.addon.mjs";
@@ -23,6 +23,7 @@ import "./builtins/local-auth/index.mjs";
23
23
  import { DeviceManagerAddon } from "./builtins/device-manager/device-manager.addon.mjs";
24
24
  import "./builtins/device-manager/index.mjs";
25
25
  import { t as CustomActionRegistry } from "./custom-action-registry-F__gp_VX.mjs";
26
+ import * as v8 from "node:v8";
26
27
  import { PYTHON_VERSION, buildBinaryPath, downloadBinary, ensureBinary, ensureFfmpeg, ensurePython, findInPath, getFfmpegDownloadUrl, getPlatformInfo, getPythonDownloadUrl, installPythonPackages, installPythonRequirements } from "@camstack/types/node";
27
28
  import { z } from "zod";
28
29
  import { request } from "node:http";
@@ -45,6 +46,100 @@ import { StringDecoder } from "node:string_decoder";
45
46
  import { lstatSync, readdir as readdir$1, readdirSync, readlinkSync, realpathSync } from "fs";
46
47
  import "path";
47
48
  import { createRequire } from "module";
49
+ //#region src/kernel/heap-watch.ts
50
+ /**
51
+ * heap-watch — hub-main's own memory, on the record.
52
+ *
53
+ * ## Why this exists
54
+ *
55
+ * hub-main is launched with `--max-old-space-size=1536` (docker-entrypoint) and
56
+ * has logged NOTHING about its own heap. When it died on 2026-08-01/02 the only
57
+ * trace was V8's own stderr line:
58
+ *
59
+ * FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
60
+ *
61
+ * which carries no process name, no heap number and no history — the whole
62
+ * server restarts and the evidence is gone. Four of those in ~15h, and the one
63
+ * at 06:57:57 landed nine seconds after a viewer opened a WebRTC session, which
64
+ * is why the app sat in a permanent "loading": the hub was dying as it
65
+ * connected.
66
+ *
67
+ * `[mem]` reports already exist for forked addon runners (SIGUSR2 in
68
+ * `addon-runner.ts`) — hub-main, the one process that actually OOMs, was the
69
+ * one process with no telemetry at all.
70
+ *
71
+ * ## What it gives
72
+ *
73
+ * A heartbeat carrying the numbers that separate the two possible stories, and
74
+ * a WARN as the heap approaches the ceiling — the line that will exist BEFORE
75
+ * the next fatal instead of after it:
76
+ *
77
+ * - `heapUsedMb` climbing steadily between restarts → a leak;
78
+ * - `heapUsedMb` flat with a sharp jump under load → a burst allocation, and
79
+ * the timestamp says what was being served.
80
+ *
81
+ * `external`/`arrayBuffers` ride along because they are NOT bounded by
82
+ * `--max-old-space-size` and are most of the gap between a 1.5GB cap and the
83
+ * ~2.05GB RSS observed live: a diagnosis that only looks at the JS heap
84
+ * misreads that process by 500MB.
85
+ */
86
+ /** Heartbeat period. Slow enough to be free, fast enough that the sample before
87
+ * a fatal is recent. */
88
+ var HEAP_WATCH_INTERVAL_MS = 6e4;
89
+ /** Warn above this share of the heap ceiling. Chosen so the warning precedes
90
+ * the fatal by more than one interval under realistic growth. */
91
+ var HEAP_WATCH_WARN_RATIO = .8;
92
+ var MB = (bytes) => Math.round(bytes / 1048576);
93
+ /**
94
+ * Build a sample from raw readings. Pure so the thresholds are testable without
95
+ * allocating a gigabyte to reach them.
96
+ */
97
+ function buildHeapSample(mem, heapLimitBytes, warnRatio = HEAP_WATCH_WARN_RATIO) {
98
+ const usedRatio = heapLimitBytes > 0 ? mem.heapUsed / heapLimitBytes : 0;
99
+ return {
100
+ rssMb: MB(mem.rss),
101
+ heapUsedMb: MB(mem.heapUsed),
102
+ heapTotalMb: MB(mem.heapTotal),
103
+ heapLimitMb: MB(heapLimitBytes),
104
+ externalMb: MB(mem.external),
105
+ arrayBuffersMb: MB(mem.arrayBuffers),
106
+ usedRatio: Math.round(usedRatio * 100) / 100,
107
+ nearLimit: usedRatio >= warnRatio
108
+ };
109
+ }
110
+ var consoleSink = {
111
+ info: (line) => console.log(line),
112
+ warn: (line) => console.warn(line)
113
+ };
114
+ function format$1(label, s) {
115
+ return `[mem] ${label} rss=${s.rssMb}MB heapUsed=${s.heapUsedMb}MB heapTotal=${s.heapTotalMb}MB heapLimit=${s.heapLimitMb}MB used=${Math.round(s.usedRatio * 100)}% external=${s.externalMb}MB arrayBuffers=${s.arrayBuffersMb}MB`;
116
+ }
117
+ /**
118
+ * Start the heartbeat. Returns a stop function.
119
+ *
120
+ * `unref`ed so it can never hold the process open, and every read is wrapped:
121
+ * a diagnostic that can crash the process it watches is worse than none.
122
+ */
123
+ function startHeapWatch(label = "hub-main", sink = consoleSink, intervalMs = HEAP_WATCH_INTERVAL_MS) {
124
+ const tick = () => {
125
+ try {
126
+ const sample = buildHeapSample(process.memoryUsage(), v8.getHeapStatistics().heap_size_limit);
127
+ const line = format$1(label, sample);
128
+ if (sample.nearLimit) sink.warn(`${line} — APPROACHING HEAP LIMIT`);
129
+ else sink.info(line);
130
+ } catch {}
131
+ };
132
+ const timer = setInterval(tick, intervalMs);
133
+ timer.unref?.();
134
+ tick();
135
+ let stopped = false;
136
+ return () => {
137
+ if (stopped) return;
138
+ stopped = true;
139
+ clearInterval(timer);
140
+ };
141
+ }
142
+ //#endregion
48
143
  //#region src/events/event-bus.ts
49
144
  var EventBus = class {
50
145
  listeners = /* @__PURE__ */ new Map();
@@ -5941,6 +6036,10 @@ var INFRA_CAPABILITIES = [
5941
6036
  name: "storage-provider",
5942
6037
  required: true
5943
6038
  },
6039
+ {
6040
+ name: "data-store-provider",
6041
+ required: true
6042
+ },
5944
6043
  {
5945
6044
  name: "storage",
5946
6045
  required: true
@@ -94065,4 +94164,4 @@ var LifecycleJobEngine = class {
94065
94164
  }
94066
94165
  };
94067
94166
  //#endregion
94068
- export { AGENT_CAP_FWD_ACTION, AGENT_CAP_FWD_SERVICE, AGENT_READINESS_SERVICE_NAME, ALL_CAPABILITY_DEFINITIONS, AddonApiFactory, AddonDepsManager, AddonEngineManager, AddonHealthMonitor, AddonInstaller, AddonLoader, AddonManifest, AddonRouteRegistry, AlertCenterAddon, ApiKeyManager, AuthManager, CLUSTER_SECRET_MISMATCH_TYPE, CLUSTER_SECRET_REJECTED_EXIT_CODE, CORE_CAP_SERVICE_NAME, CapRouteError, CapRouteResolver, CapUsageRegistry, CapabilityHandle, CapabilityRegistry, CapabilityUnavailableError, ConfigManager, ConfigStore, ConsoleDestination, ConsoleLoggingAddon, CustomActionRegistry, DEFAULT_DATA_PATH, DEVICE_SETTINGS_CONTRIBUTION_METHODS, DEVICE_STATUS_METHOD, DataPlaneRegistry, DeviceManagerAddon, DeviceRegistry, DeviceStore, EVENT_TOPIC_PREFIX, EngineManagerResolver, EventBus, FeatureManager, FilesystemStorageAddon, FilesystemStorageProvider, FrameDecoder, FsStorageBackend, HEALTH_MONITOR_GRACE_PERIOD_MS, HEALTH_MONITOR_RETRY_INTERVALS_MS, HEALTH_MONITOR_TICK_MS, HUB_CAP_FWD_ACTION, HUB_CAP_FWD_SERVICE, HubForwarderAddon, HubForwarderDestination, HubLogForwarder, HubNodeRegistry, INFRA_CAPABILITIES, IntegrationRegistry, JobJournal, LifecycleJobEngine, LifecycleStateMachine, LocalAuthAddon, LocalChildClient, LocalChildRegistry, LogManager, LogRingBuffer, LokiDestination, LokiLoggingAddon, METHOD_ACCESS_MAP, ModelDownloadService, NATIVE_PROVIDER_SERVICE_INFIX, NATIVE_SCAN_DEPTH, NativeMetricsAddon, NativeMetricsProvider, NetworkQualityTracker, NotificationService, PYTHON_VERSION, PipelineRunner, PipelineValidator, PythonEnvManager, RESTART_MARKER_FILE, RUNTIME_DEFAULTS, ReadinessRegistry, ReadinessTimeoutError, ReplEngine, RingBuffer, ScopedLogger, ScopedTokenManager, SocketChannel, SqliteSettingsAddon, SqliteSettingsBackend, StagingArea, StorageLocationManager, StorageManager, StorageOrchestratorAddon, StorageOrchestratorService, SystemConfigAddon, SystemEventBus, TRADITIONAL_NATIVE_PACKAGES, ToastService, UDS_NO_ROUTE_PREFIX, UdsLocalTransportClient, UdsLocalTransportServer, UserManager, WinstonDestination, WinstonLoggingAddon, __resetCapUsageRegistryForTests, adaptBrokerToCluster, addonSettingsCapability, bootstrapSchema, brokerCallForCap, brokerTransportLink, buildBinaryPath, buildCapRouters, buildLinkChain, buildNativeCapProxy, buildNodeManifest, buildStorageLocationRegistry, buildUdsNativeCapProxy, builderMountedCapNames, callRegisterNodeWithRetry, callWithServiceDiscovery, capActionName, capActionSuffix, capBareAction, capServiceName, classifyCapRoute, clearPendingRestart, clusterEventTopic, clusterSecretMatches, collectModelFiles, contentTypeFor, copyDirRecursive, copyExtraFileDirs, createAddonContext, createAddonDataPlaneFacility, createAddonService, createAuthenticatedFileServer, createBroker, createBrokerDeviceManagerApi, createCoreCapService, createFileDataPlaneHandler, createHubCapForwardService, createHubService, createKernelHwAccel, createLocalTransport, createParentUnownedCallHandler, createProcessService, createReadinessService, createReadinessServiceForRegistry, createScopedProcessManager, createStreamProbeBrokerService, createUdsAddonContext, createUdsEventBridge, createUdsEventBus, createUdsLogger, createUdsLoggerWithControl, deleteModelFromDisk, deriveAgentListenPort, describeProviderKindDrift, detectWorkspacePackagesDir, downloadBinary, downloadFile, downloadModel, emitDownForOwnedCaps, encodeFrame, ensureAddonNativePrebuilds, ensureBinary, ensureDir, ensureFfmpeg, ensureLibraryBuilt, ensureModel, ensureNativePrebuilds, ensurePython, ensureTlsCert, expandCapMethods, fetchJson, findInPath, formatLogLine, getBrokerEventBus, getCapUsageRegistry, getFfmpegDownloadUrl, getModelFilePath, getMoleculerEventStats, getOrInitReadinessRegistry, getOrInitReadinessRegistryForClient, getPidStats, getPlatformInfo, getPythonDownloadUrl, getRestartMarkerPath, getSinglePidStats, getWorkerDeviceRegistry, hasDotNode, hashClusterSecret, installManifestNativeDeps, installManifestPythonDeps, installPackageFromNpm, installPythonPackages, installPythonRequirements, ipcChildLink, ipcParentLink, isAddonDeploySource, isArrayOutputSchema, isClusterSecretMismatchError, isCollectionArrayMethod, isInfraCapability, isModelDownloaded, isSourceNewer, loadTlsCert, localEndpointPath, localProviderLink, mountNativeCapService, parseCapAction, parseRangeHeader, parseTokenizedUrl, proxyToUpstream, readPendingRestart, readinessKey, registerEventBusService, resolveFilePath, resolveHwAccel, resolveNpmInvocation, runNpm, scheduleSelfRestart, scopeKey, scopesAllowDeviceCap, serializeTypedArrays, setHubConnected, setNodeEventInterest, stripCamstackDeps, subscribePassthrough, udsChildLogToWorkerEntry, validateProviderRegistrations, writePendingRestart };
94167
+ export { AGENT_CAP_FWD_ACTION, AGENT_CAP_FWD_SERVICE, AGENT_READINESS_SERVICE_NAME, ALL_CAPABILITY_DEFINITIONS, AddonApiFactory, AddonDepsManager, AddonEngineManager, AddonHealthMonitor, AddonInstaller, AddonLoader, AddonManifest, AddonRouteRegistry, AlertCenterAddon, ApiKeyManager, AuthManager, CLUSTER_SECRET_MISMATCH_TYPE, CLUSTER_SECRET_REJECTED_EXIT_CODE, CORE_CAP_SERVICE_NAME, CapRouteError, CapRouteResolver, CapUsageRegistry, CapabilityHandle, CapabilityRegistry, CapabilityUnavailableError, ConfigManager, ConfigStore, ConsoleDestination, ConsoleLoggingAddon, CustomActionRegistry, DEFAULT_DATA_PATH, DEVICE_SETTINGS_CONTRIBUTION_METHODS, DEVICE_STATUS_METHOD, DataPlaneRegistry, DeviceManagerAddon, DeviceRegistry, DeviceStore, EVENT_TOPIC_PREFIX, EngineManagerResolver, EventBus, FeatureManager, FilesystemStorageAddon, FilesystemStorageProvider, FrameDecoder, FsStorageBackend, HEALTH_MONITOR_GRACE_PERIOD_MS, HEALTH_MONITOR_RETRY_INTERVALS_MS, HEALTH_MONITOR_TICK_MS, HEAP_WATCH_INTERVAL_MS, HEAP_WATCH_WARN_RATIO, HUB_CAP_FWD_ACTION, HUB_CAP_FWD_SERVICE, HubForwarderAddon, HubForwarderDestination, HubLogForwarder, HubNodeRegistry, INFRA_CAPABILITIES, IntegrationRegistry, JobJournal, LifecycleJobEngine, LifecycleStateMachine, LocalAuthAddon, LocalChildClient, LocalChildRegistry, LogManager, LogRingBuffer, LokiDestination, LokiLoggingAddon, METHOD_ACCESS_MAP, ModelDownloadService, NATIVE_PROVIDER_SERVICE_INFIX, NATIVE_SCAN_DEPTH, NativeMetricsAddon, NativeMetricsProvider, NetworkQualityTracker, NotificationService, PYTHON_VERSION, PipelineRunner, PipelineValidator, PythonEnvManager, RESTART_MARKER_FILE, RUNTIME_DEFAULTS, ReadinessRegistry, ReadinessTimeoutError, ReplEngine, RingBuffer, ScopedLogger, ScopedTokenManager, SocketChannel, SqliteSettingsAddon, SqliteSettingsBackend, StagingArea, StorageLocationManager, StorageManager, StorageOrchestratorAddon, StorageOrchestratorService, SystemConfigAddon, SystemEventBus, TRADITIONAL_NATIVE_PACKAGES, ToastService, UDS_NO_ROUTE_PREFIX, UdsLocalTransportClient, UdsLocalTransportServer, UserManager, WinstonDestination, WinstonLoggingAddon, __resetCapUsageRegistryForTests, adaptBrokerToCluster, addonSettingsCapability, bootstrapSchema, brokerCallForCap, brokerTransportLink, buildBinaryPath, buildCapRouters, buildHeapSample, buildLinkChain, buildNativeCapProxy, buildNodeManifest, buildStorageLocationRegistry, buildUdsNativeCapProxy, builderMountedCapNames, callRegisterNodeWithRetry, callWithServiceDiscovery, capActionName, capActionSuffix, capBareAction, capServiceName, classifyCapRoute, clearPendingRestart, clusterEventTopic, clusterSecretMatches, collectModelFiles, contentTypeFor, copyDirRecursive, copyExtraFileDirs, createAddonContext, createAddonDataPlaneFacility, createAddonService, createAuthenticatedFileServer, createBroker, createBrokerDeviceManagerApi, createCoreCapService, createFileDataPlaneHandler, createHubCapForwardService, createHubService, createKernelHwAccel, createLocalTransport, createParentUnownedCallHandler, createProcessService, createReadinessService, createReadinessServiceForRegistry, createScopedProcessManager, createStreamProbeBrokerService, createUdsAddonContext, createUdsEventBridge, createUdsEventBus, createUdsLogger, createUdsLoggerWithControl, deleteModelFromDisk, deriveAgentListenPort, describeProviderKindDrift, detectWorkspacePackagesDir, downloadBinary, downloadFile, downloadModel, emitDownForOwnedCaps, encodeFrame, ensureAddonNativePrebuilds, ensureBinary, ensureDir, ensureFfmpeg, ensureLibraryBuilt, ensureModel, ensureNativePrebuilds, ensurePython, ensureTlsCert, expandCapMethods, fetchJson, findInPath, formatLogLine, getBrokerEventBus, getCapUsageRegistry, getFfmpegDownloadUrl, getModelFilePath, getMoleculerEventStats, getOrInitReadinessRegistry, getOrInitReadinessRegistryForClient, getPidStats, getPlatformInfo, getPythonDownloadUrl, getRestartMarkerPath, getSinglePidStats, getWorkerDeviceRegistry, hasDotNode, hashClusterSecret, installManifestNativeDeps, installManifestPythonDeps, installPackageFromNpm, installPythonPackages, installPythonRequirements, ipcChildLink, ipcParentLink, isAddonDeploySource, isArrayOutputSchema, isClusterSecretMismatchError, isCollectionArrayMethod, isInfraCapability, isModelDownloaded, isSourceNewer, loadTlsCert, localEndpointPath, localProviderLink, mountNativeCapService, parseCapAction, parseRangeHeader, parseTokenizedUrl, proxyToUpstream, readPendingRestart, readinessKey, registerEventBusService, resolveFilePath, resolveHwAccel, resolveNpmInvocation, runNpm, scheduleSelfRestart, scopeKey, scopesAllowDeviceCap, serializeTypedArrays, setHubConnected, setNodeEventInterest, startHeapWatch, stripCamstackDeps, subscribePassthrough, udsChildLogToWorkerEntry, validateProviderRegistrations, writePendingRestart };
@@ -0,0 +1,36 @@
1
+ /** Heartbeat period. Slow enough to be free, fast enough that the sample before
2
+ * a fatal is recent. */
3
+ export declare const HEAP_WATCH_INTERVAL_MS = 60000;
4
+ /** Warn above this share of the heap ceiling. Chosen so the warning precedes
5
+ * the fatal by more than one interval under realistic growth. */
6
+ export declare const HEAP_WATCH_WARN_RATIO = 0.8;
7
+ export interface HeapSample {
8
+ readonly rssMb: number;
9
+ readonly heapUsedMb: number;
10
+ readonly heapTotalMb: number;
11
+ readonly heapLimitMb: number;
12
+ readonly externalMb: number;
13
+ readonly arrayBuffersMb: number;
14
+ /** heapUsed / heapLimit, 0-1. */
15
+ readonly usedRatio: number;
16
+ /** True once the heap is close enough to the ceiling to be worth shouting. */
17
+ readonly nearLimit: boolean;
18
+ }
19
+ /**
20
+ * Build a sample from raw readings. Pure so the thresholds are testable without
21
+ * allocating a gigabyte to reach them.
22
+ */
23
+ export declare function buildHeapSample(mem: NodeJS.MemoryUsage, heapLimitBytes: number, warnRatio?: number): HeapSample;
24
+ /** Minimal sink so this module stays usable before any logger exists — the
25
+ * starter runs before the kernel's logging is wired. */
26
+ export interface HeapWatchSink {
27
+ readonly info: (line: string) => void;
28
+ readonly warn: (line: string) => void;
29
+ }
30
+ /**
31
+ * Start the heartbeat. Returns a stop function.
32
+ *
33
+ * `unref`ed so it can never hold the process open, and every read is wrapped:
34
+ * a diagnostic that can crash the process it watches is worse than none.
35
+ */
36
+ export declare function startHeapWatch(label?: string, sink?: HeapWatchSink, intervalMs?: number): () => void;
@@ -5,7 +5,9 @@ import { IEventBus, SystemEvent } from '@camstack/types';
5
5
  *
6
6
  * - `emitEvent` — fire-and-forget: send a system event to the parent.
7
7
  * - `onEvent` — register the single handler for parent→child events.
8
- * (Only one handler is registered; calling again replaces the previous one.)
8
+ * (Only one handler is registered; calling again replaces the previous one.
9
+ * Because the slot is single, this module registers it exactly ONCE per
10
+ * channel — the shared-state factory below — never once per addon bus.)
9
11
  * - `updateEventPatterns` — declare this owner's live category-pattern set to
10
12
  * the parent so it can subscription-filter the event fan-out. Called after
11
13
  * every subscribe/unsubscribe with the CURRENT key set (full-set replace).
@@ -19,6 +21,7 @@ export interface UdsEventChannel {
19
21
  }
20
22
  /**
21
23
  * Create a UDS-backed `IEventBus` for use inside a forked child process.
24
+ * Returns a per-addon facade over the channel's ONE shared state (module doc).
22
25
  *
23
26
  * @param client - The UDS channel toward the parent (hub or agent).
24
27
  * @param addonId - This child's stable addon id — stamped as `sourceAddonId`
@@ -5164,7 +5164,31 @@ function udsChildLogToWorkerEntry(childId, entry) {
5164
5164
  //#endregion
5165
5165
  //#region src/kernel/transport/uds-event-bus.ts
5166
5166
  /**
5167
+ * ONE `SharedBusState` per `UdsEventChannel` (see the module doc's
5168
+ * group-runner contract). Keyed weakly so a channel torn down with its
5169
+ * process does not pin its state.
5170
+ */
5171
+ var sharedStateByChannel = /* @__PURE__ */ new WeakMap();
5172
+ /**
5173
+ * Resolve (or lazily create) the channel's shared bus state, registering the
5174
+ * single-slot `client.onEvent` handler exactly once — on first creation. The
5175
+ * handler delivers into the SHARED state, so every co-located addon's
5176
+ * subscribers see parent→child events regardless of bus construction order.
5177
+ * It does NOT call `client.emitEvent` (no echo back to the parent).
5178
+ */
5179
+ function sharedStateFor(client) {
5180
+ const existing = sharedStateByChannel.get(client);
5181
+ if (existing !== void 0) return existing;
5182
+ const created = createSharedBusState();
5183
+ sharedStateByChannel.set(client, created);
5184
+ client.onEvent((event) => {
5185
+ deliverShared(created, event);
5186
+ });
5187
+ return created;
5188
+ }
5189
+ /**
5167
5190
  * Create a UDS-backed `IEventBus` for use inside a forked child process.
5191
+ * Returns a per-addon facade over the channel's ONE shared state (module doc).
5168
5192
  *
5169
5193
  * @param client - The UDS channel toward the parent (hub or agent).
5170
5194
  * @param addonId - This child's stable addon id — stamped as `sourceAddonId`
@@ -5172,10 +5196,7 @@ function udsChildLogToWorkerEntry(childId, entry) {
5172
5196
  * events to their source addon.
5173
5197
  */
5174
5198
  function createUdsEventBus(client, addonId) {
5175
- const state = createSharedBusState();
5176
- client.onEvent((event) => {
5177
- deliverShared(state, event);
5178
- });
5199
+ const state = sharedStateFor(client);
5179
5200
  const reportPatterns = () => {
5180
5201
  client.updateEventPatterns(addonId, [...state.handlers.keys()]);
5181
5202
  };
@@ -5162,7 +5162,31 @@ function udsChildLogToWorkerEntry(childId, entry) {
5162
5162
  //#endregion
5163
5163
  //#region src/kernel/transport/uds-event-bus.ts
5164
5164
  /**
5165
+ * ONE `SharedBusState` per `UdsEventChannel` (see the module doc's
5166
+ * group-runner contract). Keyed weakly so a channel torn down with its
5167
+ * process does not pin its state.
5168
+ */
5169
+ var sharedStateByChannel = /* @__PURE__ */ new WeakMap();
5170
+ /**
5171
+ * Resolve (or lazily create) the channel's shared bus state, registering the
5172
+ * single-slot `client.onEvent` handler exactly once — on first creation. The
5173
+ * handler delivers into the SHARED state, so every co-located addon's
5174
+ * subscribers see parent→child events regardless of bus construction order.
5175
+ * It does NOT call `client.emitEvent` (no echo back to the parent).
5176
+ */
5177
+ function sharedStateFor(client) {
5178
+ const existing = sharedStateByChannel.get(client);
5179
+ if (existing !== void 0) return existing;
5180
+ const created = createSharedBusState();
5181
+ sharedStateByChannel.set(client, created);
5182
+ client.onEvent((event) => {
5183
+ deliverShared(created, event);
5184
+ });
5185
+ return created;
5186
+ }
5187
+ /**
5165
5188
  * Create a UDS-backed `IEventBus` for use inside a forked child process.
5189
+ * Returns a per-addon facade over the channel's ONE shared state (module doc).
5166
5190
  *
5167
5191
  * @param client - The UDS channel toward the parent (hub or agent).
5168
5192
  * @param addonId - This child's stable addon id — stamped as `sourceAddonId`
@@ -5170,10 +5194,7 @@ function udsChildLogToWorkerEntry(childId, entry) {
5170
5194
  * events to their source addon.
5171
5195
  */
5172
5196
  function createUdsEventBus(client, addonId) {
5173
- const state = createSharedBusState();
5174
- client.onEvent((event) => {
5175
- deliverShared(state, event);
5176
- });
5197
+ const state = sharedStateFor(client);
5177
5198
  const reportPatterns = () => {
5178
5199
  client.updateEventPatterns(addonId, [...state.handlers.keys()]);
5179
5200
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/system",
3
- "version": "1.2.27",
3
+ "version": "1.2.29",
4
4
  "description": "Core addon for CamStack — builtins, pipeline, process management, auth, logging, events",
5
5
  "keywords": [
6
6
  "camstack",
@@ -53,9 +53,10 @@
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.",
56
57
  "capabilities": [
57
58
  {
58
- "name": "settings-store"
59
+ "name": "data-store-provider"
59
60
  }
60
61
  ]
61
62
  },
@@ -134,12 +135,15 @@
134
135
  "id": "storage-orchestrator",
135
136
  "category": "system",
136
137
  "name": "Storage Orchestrator",
137
- "description": "Hub-only singleton that owns the consumer-facing `storage` cap. Holds the `locationId → StorageLocation` map, resolves `StorageLocationRef` to concrete locations, and dispatches every call to the matching `storage-provider` collection registrant (`filesystem-storage` today; future SFTP / S3 / WebDAV addons plug in alongside).",
138
+ "description": "The single data door. Owns the consumer-facing `storage` cap for bytes — the `locationId → StorageLocation` map, `StorageLocationRef` resolution, dispatch to the matching `storage-provider` registrant (`filesystem-storage` today; SFTP / S3 / WebDAV plug in alongside) — AND the `settings-store` cap for rows, dispatching to the `data-store-provider` engine (`sqlite-settings` today; a vector engine plugs in alongside). Nothing reaches an engine except through this addon.",
138
139
  "entry": "./dist/builtins/storage-orchestrator/index.js",
139
140
  "protected": true,
140
141
  "capabilities": [
141
142
  {
142
143
  "name": "storage"
144
+ },
145
+ {
146
+ "name": "settings-store"
143
147
  }
144
148
  ]
145
149
  },