@camstack/system 1.0.2

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 (262) hide show
  1. package/dist/addon/addon-api-factory.d.ts +35 -0
  2. package/dist/addon-routes/addon-route-registry.d.ts +37 -0
  3. package/dist/addon-runner.js +599 -0
  4. package/dist/addon-runner.mjs +597 -0
  5. package/dist/auth/api-key-manager.d.ts +26 -0
  6. package/dist/auth/auth-manager.d.ts +109 -0
  7. package/dist/auth/parse-record.d.ts +18 -0
  8. package/dist/auth/scope-matcher.d.ts +7 -0
  9. package/dist/auth/scoped-token-manager.d.ts +40 -0
  10. package/dist/auth/totp-manager.d.ts +51 -0
  11. package/dist/auth/user-manager.d.ts +34 -0
  12. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.d.ts +53 -0
  13. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +259 -0
  14. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +251 -0
  15. package/dist/builtins/addon-pages-aggregator/dedupe-pages.d.ts +6 -0
  16. package/dist/builtins/addon-pages-aggregator/index.d.ts +1 -0
  17. package/dist/builtins/addon-pages-aggregator/index.js +8 -0
  18. package/dist/builtins/addon-pages-aggregator/index.mjs +2 -0
  19. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.d.ts +47 -0
  20. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +228 -0
  21. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +220 -0
  22. package/dist/builtins/addon-widgets-aggregator/index.d.ts +1 -0
  23. package/dist/builtins/addon-widgets-aggregator/index.js +8 -0
  24. package/dist/builtins/addon-widgets-aggregator/index.mjs +2 -0
  25. package/dist/builtins/alerts/alerts.addon.d.ts +81 -0
  26. package/dist/builtins/alerts/alerts.addon.js +601 -0
  27. package/dist/builtins/alerts/alerts.addon.mjs +595 -0
  28. package/dist/builtins/alerts/index.d.ts +1 -0
  29. package/dist/builtins/alerts/index.js +4 -0
  30. package/dist/builtins/alerts/index.mjs +2 -0
  31. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.d.ts +147 -0
  32. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +2229 -0
  33. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2220 -0
  34. package/dist/builtins/backup-orchestrator/cron-helpers.d.ts +23 -0
  35. package/dist/builtins/backup-orchestrator/destination-policy.d.ts +72 -0
  36. package/dist/builtins/backup-orchestrator/download-helpers.d.ts +12 -0
  37. package/dist/builtins/backup-orchestrator/index.d.ts +2 -0
  38. package/dist/builtins/backup-orchestrator/index.js +8 -0
  39. package/dist/builtins/backup-orchestrator/index.mjs +2 -0
  40. package/dist/builtins/backup-orchestrator/manifest-store.d.ts +77 -0
  41. package/dist/builtins/console-logging/console-destination.d.ts +13 -0
  42. package/dist/builtins/console-logging/console-logging.addon.d.ts +25 -0
  43. package/dist/builtins/console-logging/index.d.ts +3 -0
  44. package/dist/builtins/console-logging/index.js +104 -0
  45. package/dist/builtins/console-logging/index.mjs +95 -0
  46. package/dist/builtins/device-manager/device-config-contribution.d.ts +32 -0
  47. package/dist/builtins/device-manager/device-event-propagator.d.ts +26 -0
  48. package/dist/builtins/device-manager/device-link-overlay.d.ts +23 -0
  49. package/dist/builtins/device-manager/device-link-resolver.d.ts +15 -0
  50. package/dist/builtins/device-manager/device-manager.addon.d.ts +452 -0
  51. package/dist/builtins/device-manager/device-manager.addon.js +3299 -0
  52. package/dist/builtins/device-manager/device-manager.addon.mjs +3292 -0
  53. package/dist/builtins/device-manager/index.d.ts +2 -0
  54. package/dist/builtins/device-manager/index.js +8 -0
  55. package/dist/builtins/device-manager/index.mjs +2 -0
  56. package/dist/builtins/hub-forwarder/hub-forwarder-destination.d.ts +44 -0
  57. package/dist/builtins/hub-forwarder/hub-forwarder.addon.d.ts +15 -0
  58. package/dist/builtins/hub-forwarder/index.d.ts +3 -0
  59. package/dist/builtins/hub-forwarder/index.js +154 -0
  60. package/dist/builtins/hub-forwarder/index.mjs +145 -0
  61. package/dist/builtins/local-auth/auth-schema.d.ts +26 -0
  62. package/dist/builtins/local-auth/index.d.ts +1 -0
  63. package/dist/builtins/local-auth/index.js +4 -0
  64. package/dist/builtins/local-auth/index.mjs +2 -0
  65. package/dist/builtins/local-auth/local-auth.addon.d.ts +18 -0
  66. package/dist/builtins/local-auth/local-auth.addon.js +8094 -0
  67. package/dist/builtins/local-auth/local-auth.addon.mjs +8063 -0
  68. package/dist/builtins/local-auth/oauth-grants.d.ts +45 -0
  69. package/dist/builtins/local-auth/oauth-session-manager.d.ts +50 -0
  70. package/dist/builtins/local-network/index.d.ts +2 -0
  71. package/dist/builtins/local-network/index.js +10 -0
  72. package/dist/builtins/local-network/index.mjs +2 -0
  73. package/dist/builtins/local-network/local-network.addon.d.ts +150 -0
  74. package/dist/builtins/local-network/local-network.addon.js +489 -0
  75. package/dist/builtins/local-network/local-network.addon.mjs +477 -0
  76. package/dist/builtins/native-metrics/index.d.ts +2 -0
  77. package/dist/builtins/native-metrics/native-metrics-provider.d.ts +48 -0
  78. package/dist/builtins/native-metrics/native-metrics.addon.d.ts +73 -0
  79. package/dist/builtins/native-metrics/native-metrics.addon.js +922 -0
  80. package/dist/builtins/native-metrics/native-metrics.addon.mjs +914 -0
  81. package/dist/builtins/platform-probe/hardware-decode-accel-probe.d.ts +37 -0
  82. package/dist/builtins/platform-probe/hardware-encoder-probe.d.ts +13 -0
  83. package/dist/builtins/platform-probe/index.d.ts +22 -0
  84. package/dist/builtins/platform-probe/index.js +834 -0
  85. package/dist/builtins/platform-probe/index.mjs +822 -0
  86. package/dist/builtins/platform-probe/inference-config-resolver.d.ts +29 -0
  87. package/dist/builtins/platform-probe/intel-accelerators.d.ts +11 -0
  88. package/dist/builtins/platform-probe/platform-scorer.d.ts +30 -0
  89. package/dist/builtins/platform-probe/runtime-packages.d.ts +6 -0
  90. package/dist/builtins/remote-access-orchestrator/enabled-providers-reconcile.d.ts +96 -0
  91. package/dist/builtins/remote-access-orchestrator/index.d.ts +1 -0
  92. package/dist/builtins/remote-access-orchestrator/index.js +8 -0
  93. package/dist/builtins/remote-access-orchestrator/index.mjs +2 -0
  94. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.d.ts +40 -0
  95. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +214 -0
  96. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +208 -0
  97. package/dist/builtins/shared/settle-sources.d.ts +22 -0
  98. package/dist/builtins/snapshot/index.d.ts +2 -0
  99. package/dist/builtins/snapshot/index.js +494 -0
  100. package/dist/builtins/snapshot/index.mjs +488 -0
  101. package/dist/builtins/snapshot/snapshot.addon.d.ts +120 -0
  102. package/dist/builtins/sqlite-storage/config-store.d.ts +8 -0
  103. package/dist/builtins/sqlite-storage/device-store.d.ts +23 -0
  104. package/dist/builtins/sqlite-storage/filesystem-browse-provider.d.ts +25 -0
  105. package/dist/builtins/sqlite-storage/filesystem-storage-provider.d.ts +83 -0
  106. package/dist/builtins/sqlite-storage/filesystem-storage.addon.d.ts +32 -0
  107. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +396 -0
  108. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +388 -0
  109. package/dist/builtins/sqlite-storage/index.d.ts +8 -0
  110. package/dist/builtins/sqlite-storage/index.js +62 -0
  111. package/dist/builtins/sqlite-storage/index.mjs +49 -0
  112. package/dist/builtins/sqlite-storage/integration-registry.d.ts +27 -0
  113. package/dist/builtins/sqlite-storage/path-guard.d.ts +4 -0
  114. package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +102 -0
  115. package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.ts +14 -0
  116. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +644 -0
  117. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +636 -0
  118. package/dist/builtins/storage-orchestrator/index.d.ts +6 -0
  119. package/dist/builtins/storage-orchestrator/index.js +10 -0
  120. package/dist/builtins/storage-orchestrator/index.mjs +2 -0
  121. package/dist/builtins/storage-orchestrator/location-store.d.ts +49 -0
  122. package/dist/builtins/storage-orchestrator/provider-discovery.d.ts +10 -0
  123. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +103 -0
  124. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1138 -0
  125. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1128 -0
  126. package/dist/builtins/storage-orchestrator/storage-orchestrator.service.d.ts +236 -0
  127. package/dist/builtins/storage-orchestrator/storage-pressure-manager.d.ts +38 -0
  128. package/dist/builtins/system-backup/system-backup.service.d.ts +137 -0
  129. package/dist/builtins/system-config/index.d.ts +1 -0
  130. package/dist/builtins/system-config/index.js +8 -0
  131. package/dist/builtins/system-config/index.mjs +2 -0
  132. package/dist/builtins/system-config/system-config.addon.d.ts +10 -0
  133. package/dist/builtins/system-config/system-config.addon.js +232 -0
  134. package/dist/builtins/system-config/system-config.addon.mjs +226 -0
  135. package/dist/builtins/winston-logging/index.d.ts +3 -0
  136. package/dist/builtins/winston-logging/index.js +156 -0
  137. package/dist/builtins/winston-logging/index.mjs +144 -0
  138. package/dist/builtins/winston-logging/winston-destination.d.ts +21 -0
  139. package/dist/builtins/winston-logging/winston-logging.addon.d.ts +19 -0
  140. package/dist/chunk-CNf5ZN-e.mjs +37 -0
  141. package/dist/chunk-Cek0wNdY.js +64 -0
  142. package/dist/download/model-download-service.d.ts +41 -0
  143. package/dist/download/model-downloader.d.ts +31 -0
  144. package/dist/events/event-bus.d.ts +10 -0
  145. package/dist/events/system-event-bus.d.ts +14 -0
  146. package/dist/feature/feature-manager.d.ts +11 -0
  147. package/dist/formatter-B7qW8bPJ.mjs +162 -0
  148. package/dist/formatter-DqAKDlvN.js +167 -0
  149. package/dist/http/authenticated-file-server.d.ts +53 -0
  150. package/dist/http/data-plane-registry.d.ts +23 -0
  151. package/dist/http/file-data-plane.d.ts +10 -0
  152. package/dist/http/reverse-proxy.d.ts +15 -0
  153. package/dist/index.d.ts +82 -0
  154. package/dist/index.js +93485 -0
  155. package/dist/index.mjs +93179 -0
  156. package/dist/intel-accelerators-Gg0P5mnl.js +20 -0
  157. package/dist/intel-accelerators-hGgpZ0pX.mjs +19 -0
  158. package/dist/kernel/addon-class-resolver.d.ts +4 -0
  159. package/dist/kernel/addon-engine-manager.d.ts +22 -0
  160. package/dist/kernel/addon-health-monitor.d.ts +154 -0
  161. package/dist/kernel/addon-installer.d.ts +208 -0
  162. package/dist/kernel/addon-loader.d.ts +106 -0
  163. package/dist/kernel/addon-manifest.d.ts +77 -0
  164. package/dist/kernel/capability-handle.d.ts +46 -0
  165. package/dist/kernel/capability-registry.d.ts +412 -0
  166. package/dist/kernel/config-manager.d.ts +212 -0
  167. package/dist/kernel/config-schema.d.ts +93 -0
  168. package/dist/kernel/custom-action-registry.d.ts +23 -0
  169. package/dist/kernel/deps/addon-deps-manager.d.ts +19 -0
  170. package/dist/kernel/deps/manifest-native-deps.d.ts +25 -0
  171. package/dist/kernel/deps/manifest-python-deps.d.ts +20 -0
  172. package/dist/kernel/device-registry.d.ts +29 -0
  173. package/dist/kernel/fs-utils.d.ts +41 -0
  174. package/dist/kernel/hwaccel/hwaccel-resolver.d.ts +19 -0
  175. package/dist/kernel/hwaccel/hwaccel-service.d.ts +4 -0
  176. package/dist/kernel/index.d.ts +74 -0
  177. package/dist/kernel/infra-capabilities.d.ts +13 -0
  178. package/dist/kernel/moleculer/addon-context-factory.d.ts +91 -0
  179. package/dist/kernel/moleculer/addon-data-plane-facility.d.ts +19 -0
  180. package/dist/kernel/moleculer/addon-runner.d.ts +1 -0
  181. package/dist/kernel/moleculer/addon-service-factory.d.ts +50 -0
  182. package/dist/kernel/moleculer/broker-factory.d.ts +50 -0
  183. package/dist/kernel/moleculer/cap-usage-registry.d.ts +46 -0
  184. package/dist/kernel/moleculer/capabilities-access.d.ts +21 -0
  185. package/dist/kernel/moleculer/child-addon-call-dispatch.d.ts +46 -0
  186. package/dist/kernel/moleculer/child-cap-dispatch.d.ts +20 -0
  187. package/dist/kernel/moleculer/cluster-secret.d.ts +15 -0
  188. package/dist/kernel/moleculer/core-cap-service.d.ts +50 -0
  189. package/dist/kernel/moleculer/crash-supervisor.d.ts +50 -0
  190. package/dist/kernel/moleculer/device-cap-proxy.d.ts +79 -0
  191. package/dist/kernel/moleculer/event-bus-core.d.ts +53 -0
  192. package/dist/kernel/moleculer/event-bus.d.ts +53 -0
  193. package/dist/kernel/moleculer/hub-log-forwarder.d.ts +36 -0
  194. package/dist/kernel/moleculer/hub-service.d.ts +35 -0
  195. package/dist/kernel/moleculer/node-registry.d.ts +126 -0
  196. package/dist/kernel/moleculer/process-context.d.ts +4 -0
  197. package/dist/kernel/moleculer/process-service.d.ts +72 -0
  198. package/dist/kernel/moleculer/provider-registry.d.ts +28 -0
  199. package/dist/kernel/moleculer/readiness-context.d.ts +62 -0
  200. package/dist/kernel/moleculer/readiness-service.d.ts +7 -0
  201. package/dist/kernel/moleculer/register-node-client.d.ts +35 -0
  202. package/dist/kernel/moleculer/remote-logger.d.ts +43 -0
  203. package/dist/kernel/moleculer/resilient-cap-call.d.ts +28 -0
  204. package/dist/kernel/moleculer/stream-probe-service.d.ts +9 -0
  205. package/dist/kernel/moleculer/trpc-links.d.ts +189 -0
  206. package/dist/kernel/moleculer/typed-array-serde.d.ts +25 -0
  207. package/dist/kernel/moleculer/worker-device-restore.d.ts +10 -0
  208. package/dist/kernel/provider-kind-drift.d.ts +12 -0
  209. package/dist/kernel/restart-coordinator.d.ts +90 -0
  210. package/dist/kernel/storage-location-registry.d.ts +40 -0
  211. package/dist/kernel/transport/cap-action-name.d.ts +100 -0
  212. package/dist/kernel/transport/cap-route-resolver.d.ts +148 -0
  213. package/dist/kernel/transport/cap-route.d.ts +148 -0
  214. package/dist/kernel/transport/child-cap-protocol.d.ts +136 -0
  215. package/dist/kernel/transport/create-local-transport.d.ts +7 -0
  216. package/dist/kernel/transport/frame-codec.d.ts +7 -0
  217. package/dist/kernel/transport/index.d.ts +27 -0
  218. package/dist/kernel/transport/local-child-client.d.ts +136 -0
  219. package/dist/kernel/transport/local-child-registry.d.ts +179 -0
  220. package/dist/kernel/transport/local-endpoint-path.d.ts +6 -0
  221. package/dist/kernel/transport/local-transport.d.ts +46 -0
  222. package/dist/kernel/transport/parent-unowned-call.d.ts +75 -0
  223. package/dist/kernel/transport/socket-channel.d.ts +27 -0
  224. package/dist/kernel/transport/uds-event-bridge.d.ts +36 -0
  225. package/dist/kernel/transport/uds-event-bus.d.ts +22 -0
  226. package/dist/kernel/transport/uds-local-transport.d.ts +18 -0
  227. package/dist/kernel/transport/uds-log-ingest.d.ts +28 -0
  228. package/dist/kernel/transport/uds-logger.d.ts +44 -0
  229. package/dist/kernel/utils/ring-buffer.d.ts +15 -0
  230. package/dist/kernel/workspace-detect.d.ts +9 -0
  231. package/dist/lifecycle/lifecycle-state-machine.d.ts +28 -0
  232. package/dist/logging/formatter.d.ts +30 -0
  233. package/dist/logging/log-manager.d.ts +54 -0
  234. package/dist/logging/log-ring-buffer.d.ts +47 -0
  235. package/dist/logging/partitioned-log-buffer.d.ts +35 -0
  236. package/dist/logging/scoped-logger.d.ts +17 -0
  237. package/dist/main-DNnMW7Z2.js +9983 -0
  238. package/dist/main-rtjOwPBR.mjs +9976 -0
  239. package/dist/manifest-python-deps-D1DbAQEv.js +6724 -0
  240. package/dist/manifest-python-deps-DZsKTbs1.mjs +6315 -0
  241. package/dist/network/network-quality.d.ts +11 -0
  242. package/dist/notification/notification-service.d.ts +37 -0
  243. package/dist/notification/toast-service.d.ts +22 -0
  244. package/dist/pipeline/engine-manager-resolver.d.ts +15 -0
  245. package/dist/pipeline/pipeline-runner.d.ts +8 -0
  246. package/dist/pipeline/pipeline-validator.d.ts +13 -0
  247. package/dist/process/resource-monitor.d.ts +11 -0
  248. package/dist/python/python-env-manager.d.ts +12 -0
  249. package/dist/repl/interfaces.d.ts +31 -0
  250. package/dist/repl/repl-engine.d.ts +8 -0
  251. package/dist/resource-monitor-ClDGFyf6.mjs +57 -0
  252. package/dist/resource-monitor-IIEanuJt.js +74 -0
  253. package/dist/settle-sources-Bhsy57y-.js +38 -0
  254. package/dist/settle-sources-CDtNC8ub.mjs +33 -0
  255. package/dist/storage/fs-storage-backend.d.ts +40 -0
  256. package/dist/storage/storage-location-manager.d.ts +23 -0
  257. package/dist/storage/storage-manager.d.ts +83 -0
  258. package/dist/tar-BgAEMRBR.js +5434 -0
  259. package/dist/tar-ByMOPNM0.mjs +5429 -0
  260. package/dist/tls/cert-manager.d.ts +26 -0
  261. package/dist/tls/index.d.ts +1 -0
  262. package/package.json +343 -0
@@ -0,0 +1,412 @@
1
+ import { CapabilityDefinition, CapabilityDeclaration, CapabilityMode, CapabilityInfo, CapabilityProviderMap, SingletonCapabilityMap, CollectionCapabilityMap, IScopedLogger, IEventBus } from '@camstack/types';
2
+ import { ConfigManager } from './config-manager.js';
3
+ /** Result of creating a capability router (opaque to the kernel). */
4
+ export type CapabilityRouter = unknown;
5
+ /** Factory that creates a tRPC router from a capability definition + provider getter. */
6
+ export type CapabilityRouterFactory = (definition: CapabilityDefinition, getProvider: () => unknown | null) => CapabilityRouter;
7
+ /** Reader function that resolves user's singleton preference for a capability. */
8
+ export type ConfigReader = (capability: string) => string | undefined;
9
+ /**
10
+ * Reader function that resolves the persisted set of disabled addonIds for a
11
+ * collection capability. Parallel to {@link ConfigReader} but for the
12
+ * collection mode — returns the addonIds an operator has disabled so the
13
+ * registry can restore them as disabled on a fresh boot. An empty array (or
14
+ * `undefined`) means "nothing persisted, all providers enabled".
15
+ *
16
+ * Wired by the server layer in `addon-registry.service.ts` to read the same
17
+ * `capabilities.collection.<cap>` ConfigService key the `capabilities` router
18
+ * writes. Keeps the registry decoupled from `ConfigService` — exactly like
19
+ * {@link ConfigReader} does for singletons.
20
+ */
21
+ export type CollectionConfigReader = (capability: string) => readonly string[] | undefined;
22
+ export declare class CapabilityRegistry {
23
+ private readonly capabilities;
24
+ private readonly logger;
25
+ private readonly eventBus;
26
+ private routerFactory;
27
+ private configReader;
28
+ private collectionConfigReader;
29
+ private configManager;
30
+ private _ready;
31
+ /** Boot-time dependency graph: capability → dependsOn names (from CapabilityDeclaration) */
32
+ private readonly capabilityDeps;
33
+ /** Per-device singleton overrides: deviceId → (capability → addonId) */
34
+ private readonly deviceOverrides;
35
+ /** capName → (nodeId → bare addonId) per-node singleton overrides. */
36
+ private readonly singletonNodeOverrides;
37
+ /** Optional reader for persisted per-node overrides: (cap, nodeId) → addonId. */
38
+ private nodeConfigReader;
39
+ /** Per-device collection filters: deviceId → (capability → addonIds[]) */
40
+ private readonly deviceCollectionFilters;
41
+ /** autoActivate flags per (capability, addonId) — from addon manifests */
42
+ private readonly autoActivateFlags;
43
+ /**
44
+ * Per-device native providers: capName → deviceId (numeric) → { addonId, provider }.
45
+ *
46
+ * Backs `DeviceContext.registerNativeCap`. Lets device-driver addons
47
+ * (OnvifCamera, RtspCamera, etc.) publish capability implementations
48
+ * scoped to a single device; the device-proxy router resolves these by
49
+ * `(capName, deviceId)` to dispatch incoming calls.
50
+ *
51
+ * Distinct from the `capabilities[].providers` map (system-wide providers
52
+ * keyed by addonId) — native providers are device-instance-scoped and
53
+ * never participate in singleton/collection resolution.
54
+ */
55
+ private readonly nativeProviders;
56
+ /**
57
+ * Wrapper provider registrations: capName → Set<addonId>. Tracked separately
58
+ * from `capabilities[].providers` because wrappers aren't system-wide
59
+ * providers — they're user-toggleable decorators addons declare via
60
+ * `ProviderRegistration.kind === 'wrapper'`. Consumers query this map (via
61
+ * `getWrappersForCap`) to render the "pick a wrapper for this device"
62
+ * dropdown in the device-bindings UI.
63
+ */
64
+ private readonly wrapperProviders;
65
+ /**
66
+ * Wrapper registrations that declared `ProviderRegistration.defaultActive:
67
+ * true`. Keyed by `capName` and valued by `addonId` — the first wrapper
68
+ * flagged default-active wins per cap. Consumed by `device-manager.getBindings`
69
+ * to synthesise a wrapper binding when no explicit activation has been
70
+ * persisted for a (device, cap) pair and no native provider exists either —
71
+ * otherwise the default wrapper would sit dormant waiting for a manual
72
+ * `setWrapperActive({active: true})` that never comes.
73
+ */
74
+ private readonly wrapperDefaults;
75
+ /**
76
+ * Pending {@link waitForProvider} waiters, keyed by
77
+ * `"${capabilityName}::${addonId}"`. Resolved by {@link registerProvider}
78
+ * as soon as the matching pair is registered — the mechanism that replaces
79
+ * the 100ms polling loop the device-management router used to run while
80
+ * waiting for forked providers to finish announcing their Moleculer service.
81
+ */
82
+ private readonly pendingWaiters;
83
+ /** Period for the "still waiting" log emitted by `waitForProvider`. */
84
+ private static readonly WAIT_HEARTBEAT_INTERVAL_MS;
85
+ constructor(logger: IScopedLogger, eventBus?: IEventBus);
86
+ /** Set the config reader for singleton preference resolution. */
87
+ setConfigReader(reader: ConfigReader): void;
88
+ /**
89
+ * Set the config reader for collection-provider enable/disable persistence.
90
+ * Consulted by {@link registerProvider} so a provider an operator disabled
91
+ * in a previous session comes back disabled after a hub reboot.
92
+ */
93
+ setCollectionConfigReader(reader: CollectionConfigReader): void;
94
+ /** Set the config manager for persisted device activation state. */
95
+ setConfigManager(manager: ConfigManager): void;
96
+ /** Register boot-time dependency edges (from CapabilityDeclaration.dependsOn). */
97
+ setDependencies(capabilityName: string, dependsOn: readonly string[]): void;
98
+ /** Set the router factory — called by the server layer once at boot. */
99
+ setRouterFactory(factory: CapabilityRouterFactory): void;
100
+ /** Mark boot complete. Before this, getProvider() returns null. */
101
+ ready(): void;
102
+ isReady(): boolean;
103
+ /**
104
+ * Declare a capability from its definition.
105
+ * Creates the auto-mounted router (if factory is set).
106
+ * Called during addon manifest loading, before providers are registered.
107
+ */
108
+ declareCapability(definition: CapabilityDefinition): void;
109
+ /**
110
+ * Register manifest metadata (dependsOn + autoActivate) for a capability,
111
+ * and — when the capability's definition declares `kind: 'wrapper'` —
112
+ * register the addon as a wrapper provider.
113
+ *
114
+ * The capability MUST already be declared via `declareCapability` from
115
+ * its full `CapabilityDefinition`. Behavioural metadata (`mode`, `kind`,
116
+ * `defaultActive`) is owned exclusively by the cap definition — never
117
+ * the manifest (D4, base-layer rework; mirrors the Session 5 A5 `mode`
118
+ * consolidation). The manifest declaration carries only the cap name,
119
+ * `dependsOn`, `autoActivate`, and `optional`.
120
+ */
121
+ declareFromManifest(declaration: CapabilityDeclaration, addonId?: string): void;
122
+ /**
123
+ * Register a provider for a capability.
124
+ * For singleton: auto-activates if user-preferred or first registered.
125
+ * For collection: adds to the collection.
126
+ *
127
+ * Phase 12 (settings redesign follow-up): throws if the same
128
+ * `(capabilityName, addonId)` pair is registered more than once.
129
+ * Previously the second call would silently replace the first via
130
+ * `state.providers.set(addonId, provider)` — that was the root cause
131
+ * of the "analysis-pipeline registered three times" bug observed in
132
+ * the kernel cleanup log (`analytics` addon called `registerProvider`
133
+ * twice plus the `analysis-pipeline` addon called it a third time).
134
+ *
135
+ * Double-register of the same pair is always a programmer error —
136
+ * two legitimately different addons implementing the same cap keep
137
+ * using different `addonId`s and the user picks one via `configReader`.
138
+ */
139
+ registerProvider(capabilityName: string, addonId: string, provider: unknown): void;
140
+ /** Unregister a provider. For singleton: clears active. For collection: removes from list. */
141
+ unregisterProvider(capabilityName: string, addonId: string): void;
142
+ /** Enable a previously disabled collection provider. */
143
+ enableCollectionProvider(capability: string, addonId: string): void;
144
+ /** Disable a collection provider (keeps it registered but excluded from active list). */
145
+ disableCollectionProvider(capability: string, addonId: string): void;
146
+ /**
147
+ * Register a native capability provider scoped to a single device.
148
+ * Throws if the same `(capName, deviceId)` is registered twice — that is
149
+ * always a programmer error: device-driver addons must call
150
+ * `DeviceContext.registerNativeCap` exactly once per cap per device.
151
+ */
152
+ registerNativeProvider(capName: string, deviceId: number, addonId: string, provider: unknown): void;
153
+ /** Remove a single native provider entry. No-op if absent. */
154
+ unregisterNativeProvider(capName: string, deviceId: number): void;
155
+ /** Remove every native provider entry for a device — called on device removal. */
156
+ unregisterAllNativeForDevice(deviceId: number): void;
157
+ /** Fallback resolver for native providers that aren't registered in-process. */
158
+ private nativeFallback;
159
+ /**
160
+ * Install a fallback resolver for cross-process native caps. When a device's
161
+ * live `IDevice` lives in a forked worker (e.g. `provider-rtsp`), the native
162
+ * cap it published via `DeviceContext.registerNativeCap` is reachable over
163
+ * the broker — but the hub's `nativeProviders` map never saw it. The fallback
164
+ * is called by {@link getNativeProvider} on local-miss and is expected to
165
+ * return a proxy object whose methods issue `broker.call` into the owning
166
+ * worker. Set once at hub boot time.
167
+ */
168
+ setNativeFallback(resolver: (capName: string, deviceId: number) => unknown | null): void;
169
+ /** Resolve the native provider for `(capName, deviceId)` or null. */
170
+ getNativeProvider<T = unknown>(capName: string, deviceId: number): T | null;
171
+ /** Resolve the addonId that registered the native provider for `(capName, deviceId)`. */
172
+ getNativeAddonId(capName: string, deviceId: number): string | null;
173
+ /** List the capability names for which this device has a native provider registered. */
174
+ getNativeCapsForDevice(deviceId: number): readonly string[];
175
+ /**
176
+ * Mark `addonId` as providing a wrapper implementation for `capName`. Called
177
+ * by `declareFromManifest` when the capability's `CapabilityDefinition` declares
178
+ * `kind: 'wrapper'` (D4 — the cap definition is the single source of truth for wrapper behaviour).
179
+ * Idempotent — re-registration keeps a single entry.
180
+ */
181
+ registerWrapper(capName: string, addonId: string, opts?: {
182
+ defaultActive?: boolean;
183
+ }): void;
184
+ /** Remove a wrapper registration. No-op if absent. */
185
+ unregisterWrapper(capName: string, addonId: string): void;
186
+ /** Remove every wrapper registration owned by `addonId`. Called on addon stop. */
187
+ unregisterAllWrappersForAddon(addonId: string): void;
188
+ /** Return the addon ids that declared a wrapper for `capName`. */
189
+ getWrappersForCap(capName: string): readonly string[];
190
+ /**
191
+ * Return the wrapper addon flagged `defaultActive: true` for `capName`, or
192
+ * null when no wrapper declared itself the default. Used by
193
+ * `device-manager.getBindings` to auto-bind default wrappers on devices
194
+ * without an explicit user activation.
195
+ */
196
+ getDefaultWrapperForCap(capName: string): string | null;
197
+ /** List capability names that have at least one wrapper flagged `defaultActive: true`. */
198
+ getCapsWithDefaultWrapper(): readonly string[];
199
+ /**
200
+ * Get the active provider for a singleton capability.
201
+ *
202
+ * When called with a declared capability name (a key of
203
+ * `CapabilityProviderMap`), the return type is inferred automatically —
204
+ * no caller-side casts needed. Arbitrary string names fall back to
205
+ * `unknown`.
206
+ */
207
+ getProvider<K extends keyof CapabilityProviderMap>(capabilityName: K): CapabilityProviderMap[K] | null;
208
+ getProvider(capabilityName: string): unknown | null;
209
+ /**
210
+ * Unified per-device resolver (D13). Resolves a `(cap, device)` pair to
211
+ * its provider transparently — native (per-device) first, then a
212
+ * device-bound system provider. Callers no longer branch on
213
+ * `kind: 'native' | 'wrapped'`; `kind` is metadata on the binding only.
214
+ *
215
+ * Resolution order:
216
+ * 1. Native provider registered for the exact `(capName, deviceId)` pair.
217
+ * 2. System provider: for singleton caps, honours per-device overrides and
218
+ * activation via `resolveForDevice`; for collection caps, returns the
219
+ * first registered provider.
220
+ * 3. `null` when neither exists.
221
+ */
222
+ getProviderForDevice<T = unknown>(capName: string, deviceId: number): T | null;
223
+ /** Get all providers for a collection capability. */
224
+ getAllProviders<K extends keyof CapabilityProviderMap>(capabilityName: K): readonly CapabilityProviderMap[K][];
225
+ getAllProviders(capabilityName: string): readonly unknown[];
226
+ /** Get provider by addon ID (for per-device resolution). */
227
+ getProviderByAddon<K extends keyof CapabilityProviderMap>(capabilityName: K, addonId: string): CapabilityProviderMap[K] | null;
228
+ getProviderByAddon<T = unknown>(capabilityName: string, addonId: string): T | null;
229
+ /**
230
+ * Wait for a specific `(capabilityName, addonId)` provider to become
231
+ * available, up to `timeoutMs`. Resolves synchronously with the live
232
+ * provider if it is already registered; otherwise queues a waiter that
233
+ * {@link registerProvider} fulfils as soon as the matching pair shows up.
234
+ * Resolves to `null` on timeout instead of rejecting — the caller
235
+ * ({@link device-management.router}) already branches on `null` to return
236
+ * a user-facing "provider not available" error.
237
+ *
238
+ * Replaces the 100ms polling loop from the post-settings-redesign
239
+ * `waitForDeviceProvider` helper. On the happy path there is zero
240
+ * overhead and zero behavioural change; on the race path the wait
241
+ * unblocks on the next `registerProvider` call without any intermediate
242
+ * sleeps. See `[WAIT-EVENT]` in the 2026-04-12 handover.
243
+ */
244
+ waitForProvider<K extends keyof CapabilityProviderMap>(capabilityName: K, addonId: string, timeoutMs: number): Promise<CapabilityProviderMap[K] | null>;
245
+ waitForProvider(capabilityName: string, addonId: string, timeoutMs: number): Promise<unknown | null>;
246
+ /**
247
+ * Get the active singleton provider for a capability.
248
+ *
249
+ * Declared capability names resolve to their typed provider via
250
+ * `SingletonCapabilityMap` — a cap declared as `collection` in its
251
+ * `.cap.ts` definition is rejected at the type level. Arbitrary strings
252
+ * (non-declared capabilities) fall back to the caller-provided `T`
253
+ * (default `unknown`) through the second overload for compatibility
254
+ * with downstream packages that extend `CapabilityProviderMap` via
255
+ * declaration merging.
256
+ *
257
+ * Hard-typed narrowing via `SingletonCapabilityMap` was introduced in
258
+ * session 5 Sprint A5 — see audit addendum finding R6.
259
+ */
260
+ getSingleton<K extends keyof SingletonCapabilityMap>(capability: K): SingletonCapabilityMap[K] | null;
261
+ getSingleton<T = unknown>(capability: string): T | null;
262
+ /** Get the addon ID of the active singleton provider. */
263
+ getSingletonAddonId(capability: string): string | null;
264
+ /**
265
+ * Override the active addon for a singleton capability. Called by the
266
+ * pipeline-orchestrator binding system so future `getSingleton(cap)`
267
+ * lookups return the addon the operator explicitly selected. If
268
+ * `addonId` is `null` or no provider is registered under that id,
269
+ * falls back to the cap-declared `preferredProvider` (when registered),
270
+ * otherwise the first-registered provider (legacy behaviour).
271
+ *
272
+ * This helper is an internal hook for the UDS-preference race (it does
273
+ * NOT read `configReader` — the operator's persisted choice is applied
274
+ * by `registerProvider`/`unregisterProvider`). For consistency with those
275
+ * paths the fallback still honours `preferredProvider` ahead of
276
+ * insertion-order first-remaining.
277
+ *
278
+ * No-op when the capability isn't declared, isn't a singleton, or the
279
+ * requested addon hasn't registered a provider for it yet.
280
+ */
281
+ setSingletonActiveAddon(capability: string, addonId: string | null): void;
282
+ /**
283
+ * Get all active collection providers for a capability.
284
+ *
285
+ * Declared capability names resolve to their typed provider via
286
+ * `CollectionCapabilityMap` — a cap declared as `singleton` in its
287
+ * `.cap.ts` definition is rejected at the type level. Arbitrary strings
288
+ * fall back to the caller-provided `T` (default `unknown`) for
289
+ * compatibility with declaration-merged extensions.
290
+ */
291
+ getCollection<K extends keyof CollectionCapabilityMap>(capability: K): readonly CollectionCapabilityMap[K][];
292
+ getCollection<T = unknown>(capability: string): readonly T[];
293
+ /**
294
+ * Like {@link getCollection} but returns `[addonId, provider]` tuples so
295
+ * callers can attribute work back to the contributing addon.
296
+ *
297
+ * Needed by the device-settings aggregator (`device-manager.addon.ts`) —
298
+ * each contributed field must carry the writer's `addonId` so the
299
+ * `deviceManager.updateDeviceField` mutation can route the write to the
300
+ * correct addon-settings store without hardcoding any addon identity.
301
+ */
302
+ getCollectionEntries<K extends keyof CollectionCapabilityMap>(capability: K): readonly (readonly [string, CollectionCapabilityMap[K]])[];
303
+ getCollectionEntries<T = unknown>(capability: string): readonly (readonly [string, T])[];
304
+ /** Get the full CapabilityDefinition for a declared capability. */
305
+ getDefinition(capability: string): CapabilityDefinition | undefined;
306
+ /** Get the mode declared for a capability. */
307
+ getMode(capability: string): CapabilityMode | undefined;
308
+ /** Get a specific addon's provider by addon ID. */
309
+ getProviderByAddonId<K extends keyof CapabilityProviderMap>(capability: K, addonId: string): CapabilityProviderMap[K] | null;
310
+ getProviderByAddonId<T = unknown>(capability: string, addonId: string): T | null;
311
+ /** Bare addonId from a registry key (`webrtc-native@dev-agent-0` → `webrtc-native`). */
312
+ private bareAddonId;
313
+ /** nodeId a provider key belongs to (bare → 'hub', `@node` → node). */
314
+ private nodeOfKey;
315
+ /** capName → (nodeId → bare addonId[]) availability derived from provider keys. */
316
+ getProvidersByNode(capability: string): Map<string, string[]>;
317
+ /**
318
+ * Resolve the BARE addon id a node should use for a singleton cap.
319
+ * Chain: per-node override → cluster-global default → first available.
320
+ * Returns null when the node hosts no provider for the cap.
321
+ */
322
+ resolveSingletonAddonIdForNode(capability: string, nodeId: string): string | null;
323
+ /** Resolve the in-process provider object for a node (hub-local only). */
324
+ getSingletonForNode<T = unknown>(capability: string, nodeId: string): T | null;
325
+ /** Per-node override accessor (for listCapabilities + tests). */
326
+ getSingletonNodeOverrides(capability: string): Map<string, string>;
327
+ /** Set the reader for persisted per-node overrides (boot restore). */
328
+ setNodeConfigReader(reader: (capability: string, nodeId: string) => string | undefined): void;
329
+ /** Clear a per-node override (UI "inherit global"). */
330
+ clearSingletonNodeOverride(capability: string, nodeId: string): void;
331
+ /**
332
+ * Set which addon should be the active singleton for a capability.
333
+ * Pass an optional `nodeId` to set a per-node override instead of the cluster-global default.
334
+ */
335
+ setActiveSingleton(capability: string, addonId: string, nodeId?: string): Promise<void>;
336
+ /**
337
+ * Check if a specific addon's capability is active system-wide.
338
+ *
339
+ * Resolution: 1. explicit system override → 2. autoActivate flag → 3. default true
340
+ */
341
+ isActiveForSystem(capability: string, addonId: string): boolean;
342
+ /** Set system-wide activation for a capability/addon pair. */
343
+ setSystemActivation(capability: string, addonId: string, active: boolean): void;
344
+ /**
345
+ * Check if a specific addon's capability is active for a device.
346
+ *
347
+ * Resolution: 1. explicit device override → 2. system activation → 3. autoActivate → 4. default true
348
+ */
349
+ isActiveForDevice(capability: string, addonId: string, deviceId: string): boolean;
350
+ /** Set device activation for a capability/addon pair. */
351
+ setDeviceActivation(deviceId: string, capability: string, addonId: string, active: boolean): void;
352
+ /**
353
+ * Get all addon/capability activations for a device.
354
+ * Returns every registered provider with its resolved active status.
355
+ */
356
+ getDeviceActivations(deviceId: string): ReadonlyArray<{
357
+ capability: string;
358
+ addonId: string;
359
+ active: boolean;
360
+ }>;
361
+ /**
362
+ * Get all addon/capability activations at system level.
363
+ * Returns every registered provider with its resolved active status.
364
+ */
365
+ getSystemActivations(): ReadonlyArray<{
366
+ capability: string;
367
+ addonId: string;
368
+ active: boolean;
369
+ }>;
370
+ /** Set a per-device singleton override. */
371
+ setDeviceOverride(deviceId: string, capability: string, addonId: string): void;
372
+ /** Clear a per-device singleton override. */
373
+ clearDeviceOverride(deviceId: string, capability: string): void;
374
+ /** Get all per-device singleton overrides for a device. */
375
+ getDeviceOverrides(deviceId: string): Map<string, string>;
376
+ /**
377
+ * Resolve a singleton provider for a specific device.
378
+ * Checks activation (autoActivate + explicit overrides) then per-device override.
379
+ */
380
+ resolveForDevice<T = unknown>(capability: string, deviceId: string): T | null;
381
+ /** Set a per-device collection filter. */
382
+ setDeviceCollectionFilter(deviceId: string, capability: string, addonIds: string[]): void;
383
+ /** Clear a per-device collection filter. */
384
+ clearDeviceCollectionFilter(deviceId: string, capability: string): void;
385
+ /**
386
+ * Resolve collection providers for a specific device.
387
+ * Filters by activation (autoActivate + explicit overrides) and optional collection filter.
388
+ */
389
+ resolveCollectionForDevice<T = unknown>(capability: string, deviceId: string): readonly T[];
390
+ /** Check if all dependencies for a capability are satisfied. */
391
+ areDependenciesMet(capabilityName: string): boolean;
392
+ /** Get topologically sorted boot order based on dependsOn. */
393
+ getBootOrder(): string[];
394
+ /** Get all auto-mounted routers. Key = capability name. */
395
+ getMountedRouters(): ReadonlyMap<string, CapabilityRouter>;
396
+ /** Get a single mounted router by capability name. */
397
+ getRouter(capabilityName: string): CapabilityRouter | null;
398
+ /** List all declared capabilities (v1-compatible shape). */
399
+ listCapabilities(): CapabilityInfo[];
400
+ /** Check if a capability is declared. */
401
+ has(capabilityName: string): boolean;
402
+ /** Check if a capability has at least one provider. */
403
+ isAvailable(capabilityName: string): boolean;
404
+ /**
405
+ * Return every declared device-scoped capability (`scope: 'device'`)
406
+ * whose `deviceTypes` list includes the given type — or caps that declare
407
+ * no explicit `deviceTypes` (treat as applies-to-all). Used by the
408
+ * bindings UI to enumerate which caps the user can wire for a device.
409
+ */
410
+ listDeviceScopedCapsForType(deviceType: string): readonly string[];
411
+ private emitEvent;
412
+ }
@@ -0,0 +1,212 @@
1
+ import { AppConfig } from './config-schema.js';
2
+ import { FeatureManifest } from '@camstack/types';
3
+ export interface AddonSettingsView {
4
+ readAddonStore(): Promise<Record<string, unknown>>;
5
+ writeAddonStore(patch: Record<string, unknown>): Promise<void>;
6
+ readDeviceStore(deviceId: number): Promise<Record<string, unknown>>;
7
+ writeDeviceStore(deviceId: number, patch: Record<string, unknown>): Promise<void>;
8
+ clearDeviceStore(deviceId: number): Promise<void>;
9
+ getSection(section: string): Promise<Record<string, unknown>>;
10
+ setSection(section: string, patch: Record<string, unknown>): Promise<void>;
11
+ /**
12
+ * Per-device runtime state — separate namespace from
13
+ * `readDeviceStore` / `writeDeviceStore` (which is the addon's
14
+ * config blob: host, password, deviceCache, …). Holds mutable
15
+ * runtime signals discovered after boot: battery snapshot, sleep
16
+ * flag, last-seen timestamps. Stored under a kernel-internal
17
+ * `__device-state` namespace so the device's config schema
18
+ * never has to know about it (clean separation of operator
19
+ * intent from runtime telemetry).
20
+ *
21
+ * Patch semantics: shallow merge. Pass the FULL persistent slice
22
+ * each call (the kernel doesn't try to compute deltas) — concrete
23
+ * implementations of `DeviceRuntimeState` already coalesce in
24
+ * memory, so the kernel just persists the latest blob.
25
+ */
26
+ readDeviceRuntimeState(deviceId: number): Promise<Record<string, unknown>>;
27
+ writeDeviceRuntimeState(deviceId: number, data: Record<string, unknown>): Promise<void>;
28
+ clearDeviceRuntimeState(deviceId: number): Promise<void>;
29
+ }
30
+ export interface ISettingsStore {
31
+ getSystem(key: string): unknown;
32
+ setSystem(key: string, value: unknown): void;
33
+ getAllSystem(): Record<string, unknown>;
34
+ /** Addon-level global settings (apply to every device unless overridden). */
35
+ getAllAddon(addonId: string): Record<string, unknown>;
36
+ setAllAddon(addonId: string, config: Record<string, unknown>): void;
37
+ /** Legacy per-provider settings (used by some older wiring paths). */
38
+ getAllProvider(providerId: string): Record<string, unknown>;
39
+ setProvider(providerId: string, key: string, value: unknown): void;
40
+ /** Legacy flat per-device settings. Kept for backward compatibility
41
+ * with pre-addon wiring; new code should use the addon-device API. */
42
+ getAllDevice(deviceId: string): Record<string, unknown>;
43
+ setDevice(deviceId: string, key: string, value: unknown): void;
44
+ /**
45
+ * Multi-level addon settings: per-device overrides for a specific addon.
46
+ *
47
+ * Resolution chain when the frontend asks for the effective value of a
48
+ * field on a given device:
49
+ * 1. schema default (from `ConfigUISchema.field.default`)
50
+ * 2. `getAllAddon(addonId)` — addon global value
51
+ * 3. `getAddonDevice(addonId, devId)` — per-device override (wins)
52
+ *
53
+ * Only fields declared with `scope: 'device'` in the addon's
54
+ * `ConfigUISchema` should ever be persisted here.
55
+ */
56
+ getAddonDevice(addonId: string, deviceId: string): Record<string, unknown>;
57
+ setAddonDevice(addonId: string, deviceId: string, values: Record<string, unknown>): void;
58
+ clearAddonDevice(addonId: string, deviceId: string): void;
59
+ }
60
+ export declare class ConfigManager {
61
+ private readonly configPath;
62
+ private bootstrapConfig;
63
+ private settingsStore;
64
+ private runtimeState;
65
+ private readonly runtimeStatePath;
66
+ constructor(configPath: string);
67
+ /**
68
+ * Wire the settings-store backend. Called once, after the `settings-store`
69
+ * capability provider has registered (normally during Phase-1 infra boot).
70
+ * Before this call, runtime reads/writes fall back to bootstrap + defaults.
71
+ */
72
+ setSettingsStore(store: ISettingsStore): void;
73
+ /**
74
+ * Get a config value by dot-notation path.
75
+ * Priority: bootstrap config (yaml) → settings-store → RUNTIME_DEFAULTS fallback.
76
+ *
77
+ * Returns `unknown` — callers must narrow via `typeof`/type guards, OR use
78
+ * the generic overload at their own risk. The generic overload exists only
79
+ * as a convenience alias for legacy call sites; it performs NO runtime
80
+ * check and is the one documented type-level bridge in this function.
81
+ */
82
+ get(path: string): unknown;
83
+ get<T>(path: string): T | undefined;
84
+ private resolveConfigValue;
85
+ /**
86
+ * Write a value to the settings-store.
87
+ * Throws if the settings store is not yet wired.
88
+ */
89
+ set(key: string, value: unknown): void;
90
+ /**
91
+ * Bulk-read all keys that belong to a logical section.
92
+ * A "section" is the first segment of a dot-notation key (e.g. 'features', 'logging').
93
+ *
94
+ * Sources are merged in priority order (lowest → highest):
95
+ * 1. RUNTIME_DEFAULTS — kernel constants.
96
+ * 2. Bootstrap config — values loaded from config.yaml at boot.
97
+ * 3. Settings-store — runtime writes via the `settings-store` capability.
98
+ *
99
+ * Higher layers override earlier ones. Merging (instead of short-circuiting
100
+ * on the first non-null source) prevents a single store-seeded key from
101
+ * shadowing the rest of the section that only lives in config.yaml.
102
+ * The kernel is agnostic about the store backend — any `ISettingsStore`
103
+ * implementation (sqlite, redis, in-memory, …) behaves identically here.
104
+ */
105
+ getSection(section: string): Record<string, unknown>;
106
+ /**
107
+ * Bulk-write a logical section to the settings-store.
108
+ * Each entry in `data` is persisted under the key `section.<entryKey>`.
109
+ */
110
+ setSection(section: string, data: Record<string, unknown>): void;
111
+ /** Read all config for an addon from addon_settings. */
112
+ getAddonConfig(addonId: string): Record<string, unknown>;
113
+ /** Write (bulk-replace) config for an addon to addon_settings. */
114
+ setAddonConfig(addonId: string, config: Record<string, unknown>): void;
115
+ /** Read all config for a provider from provider_settings. */
116
+ getProviderConfig(providerId: string): Record<string, unknown>;
117
+ /** Write (upsert) a single key for a provider to provider_settings. */
118
+ setProviderConfig(providerId: string, key: string, value: unknown): void;
119
+ /** Read all config for a device from device_settings. */
120
+ getDeviceConfig(deviceId: string): Record<string, unknown>;
121
+ /** Write (upsert) a single key for a device to device_settings. */
122
+ setDeviceConfig(deviceId: string, key: string, value: unknown): void;
123
+ /**
124
+ * Read per-device overrides for a specific addon. Returns a flat record
125
+ * of field → value. Missing keys fall back to the addon-global value via
126
+ * `getAddonConfig(addonId)` — that composition is the resolver service's
127
+ * responsibility, not ConfigManager's.
128
+ */
129
+ getAddonDevice(addonId: string, deviceId: string): Record<string, unknown>;
130
+ /**
131
+ * Write (bulk-replace) per-device overrides for a specific addon.
132
+ * Throws if the settings store is not yet wired.
133
+ */
134
+ setAddonDevice(addonId: string, deviceId: string, values: Record<string, unknown>): void;
135
+ /**
136
+ * Clear all per-device overrides for a specific addon/device pair.
137
+ * Resolution falls back to the addon-global value after this call.
138
+ * No-op if the settings store is not yet wired.
139
+ */
140
+ clearAddonDevice(addonId: string, deviceId: string): void;
141
+ createSettingsView(addonId: string): AddonSettingsView;
142
+ /** Get all system-wide activation overrides. */
143
+ getSystemActivation(): Readonly<Record<string, boolean>>;
144
+ /** Set system-wide activation for a capability/addon pair. */
145
+ setSystemActivation(capability: string, addonId: string, active: boolean): void;
146
+ /**
147
+ * Get activation overrides for a device.
148
+ * Returns a map of `{capability}/{addonId}` → active boolean.
149
+ * Missing entries mean "use system activation or autoActivate default".
150
+ */
151
+ getDeviceActivation(deviceId: string): Readonly<Record<string, boolean>>;
152
+ /**
153
+ * Get all device activation overrides.
154
+ * Returns deviceId → (`{capability}/{addonId}` → active).
155
+ */
156
+ getAllDeviceActivation(): Readonly<Record<string, Record<string, boolean>>>;
157
+ /**
158
+ * Set activation for a specific capability/addon on a device.
159
+ * Persists immediately to runtime-state.json.
160
+ *
161
+ * @param deviceId - The device to configure
162
+ * @param capability - Capability name (e.g., 'motion-detection')
163
+ * @param addonId - Addon providing the capability (e.g., 'wasm-motion')
164
+ * @param active - Whether the capability is active on this device
165
+ */
166
+ setDeviceActivation(deviceId: string, capability: string, addonId: string, active: boolean): void;
167
+ /**
168
+ * Clear all activation overrides for a device (resets to autoActivate defaults).
169
+ */
170
+ clearDeviceActivation(deviceId: string): void;
171
+ /** Get a value from the parsed bootstrap config.
172
+ * Generic overload is a documented type-level bridge — callers are responsible
173
+ * for passing a T that matches the config.yaml shape. */
174
+ getBootstrap(path: string): unknown;
175
+ getBootstrap<T>(path: string): T | undefined;
176
+ /** Features accessor -- reads from settings-store when available, falls back to RUNTIME_DEFAULTS */
177
+ get features(): FeatureManifest;
178
+ /**
179
+ * Returns a merged view of bootstrap config + runtime defaults for backward compat.
180
+ */
181
+ get raw(): AppConfig;
182
+ /** Sections that live in config.yaml. Everything else goes to the settings-store. */
183
+ private static readonly BOOTSTRAP_SECTIONS;
184
+ /**
185
+ * Atomically update one top-level section of config.yaml and sync in-memory.
186
+ * Only bootstrap sections (server, auth, mode) are written to YAML.
187
+ * Runtime settings must use setSection() which writes to the settings-store.
188
+ */
189
+ update(section: string, data: Record<string, unknown>): void;
190
+ /**
191
+ * Deep-set a value in a nested plain object using a dot-notation path.
192
+ * Returns a new object (immutable).
193
+ */
194
+ private setNested;
195
+ /**
196
+ * Apply env var overrides onto the raw YAML object.
197
+ * Only bootstrap-level env vars are applied.
198
+ */
199
+ private applyEnvOverrides;
200
+ private loadYaml;
201
+ private warnDefaultCredentials;
202
+ private getFromBootstrap;
203
+ private getFromRuntimeDefaults;
204
+ /**
205
+ * Perform a prefix-based nested lookup against the settings-store.
206
+ * e.g. path='features' matches keys 'features.streaming', 'features.notifications', etc.
207
+ * Returns an object keyed by the sub-key, or undefined if nothing is found.
208
+ */
209
+ private getNestedFromSystemSettings;
210
+ private loadRuntimeState;
211
+ private saveRuntimeState;
212
+ }