@camstack/server 0.2.2 → 1.0.1

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 (234) hide show
  1. package/{src/agent-status-page.ts → dist/agent-status-page.js} +30 -45
  2. package/dist/api/addon-upload.js +441 -0
  3. package/dist/api/addons-custom.router.js +91 -0
  4. package/dist/api/auth-whoami.js +55 -0
  5. package/dist/api/bridge-addons.router.js +109 -0
  6. package/dist/api/capabilities.router.js +229 -0
  7. package/dist/api/core/addon-settings.router.js +117 -0
  8. package/dist/api/core/agents.router.js +73 -0
  9. package/dist/api/core/auth.router.js +286 -0
  10. package/dist/api/core/bulk-update-coordinator.js +229 -0
  11. package/dist/api/core/cap-providers.js +1124 -0
  12. package/dist/api/core/capabilities.router.js +138 -0
  13. package/dist/api/core/collection-preference.js +17 -0
  14. package/dist/api/core/event-bus-proxy.router.js +45 -0
  15. package/dist/api/core/hwaccel.router.js +91 -0
  16. package/dist/api/core/live-events.router.js +61 -0
  17. package/dist/api/core/logs.router.js +172 -0
  18. package/dist/api/core/notifications.router.js +67 -0
  19. package/dist/api/core/repl.router.js +35 -0
  20. package/dist/api/core/settings-backend.router.js +121 -0
  21. package/dist/api/core/stream-probe.router.js +58 -0
  22. package/dist/api/core/system-events.router.js +100 -0
  23. package/dist/api/health/health.routes.js +68 -0
  24. package/{src/api/oauth2/consent-page.ts → dist/api/oauth2/consent-page.js} +11 -20
  25. package/dist/api/oauth2/oauth2-routes.js +219 -0
  26. package/dist/api/trpc/cap-mount-helpers.js +194 -0
  27. package/dist/api/trpc/cap-route-error-formatter.js +133 -0
  28. package/dist/api/trpc/client-ip.js +147 -0
  29. package/dist/api/trpc/core-cap-bridge.js +115 -0
  30. package/dist/api/trpc/generated-cap-mounts.js +388 -0
  31. package/dist/api/trpc/generated-cap-routers.js +7635 -0
  32. package/dist/api/trpc/scope-access.js +93 -0
  33. package/dist/api/trpc/trpc.context.js +184 -0
  34. package/dist/api/trpc/trpc.middleware.js +139 -0
  35. package/dist/api/trpc/trpc.router.js +188 -0
  36. package/dist/auth/session-cookie.js +47 -0
  37. package/dist/boot/boot-config.js +241 -0
  38. package/dist/boot/integration-id-backfill.js +76 -0
  39. package/dist/boot/post-boot.service.js +85 -0
  40. package/dist/core/addon/addon-call-gateway.js +99 -0
  41. package/dist/core/addon/addon-package.service.js +1560 -0
  42. package/dist/core/addon/addon-registry.service.js +2739 -0
  43. package/{src/core/addon/addon-row-manifest.ts → dist/core/addon/addon-row-manifest.js} +5 -5
  44. package/dist/core/addon/addon-search.service.js +62 -0
  45. package/dist/core/addon/addon-settings-provider.js +102 -0
  46. package/dist/core/addon/addon.tokens.js +5 -0
  47. package/dist/core/addon-bridge/addon-bridge.service.js +145 -0
  48. package/dist/core/addon-pages/addon-pages.service.js +107 -0
  49. package/dist/core/addon-widgets/addon-widgets.service.js +120 -0
  50. package/dist/core/agent/agent-registry.service.js +477 -0
  51. package/dist/core/auth/auth.service.js +10 -0
  52. package/dist/core/capability/capability.service.js +58 -0
  53. package/dist/core/config/config.schema.js +7 -0
  54. package/dist/core/config/config.service.js +10 -0
  55. package/dist/core/events/event-bus.service.js +83 -0
  56. package/dist/core/feature/feature.service.js +10 -0
  57. package/dist/core/lifecycle/lifecycle-state-machine.js +6 -0
  58. package/dist/core/logging/log-ring-buffer.js +6 -0
  59. package/dist/core/logging/logging.service.js +130 -0
  60. package/dist/core/logging/scoped-logger.js +6 -0
  61. package/dist/core/moleculer/cap-call-fn.js +50 -0
  62. package/dist/core/moleculer/cap-route-authority.js +122 -0
  63. package/dist/core/moleculer/moleculer.service.js +898 -0
  64. package/dist/core/network/network-quality.service.js +7 -0
  65. package/dist/core/notification/notification-wrapper.service.js +33 -0
  66. package/dist/core/notification/toast-wrapper.service.js +25 -0
  67. package/dist/core/provider/provider.tokens.js +4 -0
  68. package/dist/core/repl/repl-engine.service.js +140 -0
  69. package/dist/core/storage/fs-storage-backend.js +6 -0
  70. package/dist/core/storage/storage-location-manager.js +6 -0
  71. package/dist/core/storage/storage.service.js +7 -0
  72. package/dist/core/streaming/stream-probe.service.js +209 -0
  73. package/dist/core/topology/topology-emitter.service.js +106 -0
  74. package/dist/launcher.js +325 -0
  75. package/dist/main.js +1098 -0
  76. package/dist/manual-boot.js +227 -0
  77. package/package.json +5 -1
  78. package/src/__tests__/addon-install-e2e.test.ts +0 -74
  79. package/src/__tests__/addon-pages-e2e.test.ts +0 -200
  80. package/src/__tests__/addon-route-session.test.ts +0 -17
  81. package/src/__tests__/addon-settings-router.spec.ts +0 -67
  82. package/src/__tests__/addon-upload.spec.ts +0 -475
  83. package/src/__tests__/agent-registry.spec.ts +0 -179
  84. package/src/__tests__/agent-status-page.spec.ts +0 -82
  85. package/src/__tests__/auth-session-cookie.test.ts +0 -48
  86. package/src/__tests__/bulk-update-coordinator.spec.ts +0 -303
  87. package/src/__tests__/cap-ownership-authority.spec.ts +0 -431
  88. package/src/__tests__/cap-providers/cap-providers-location-import.spec.ts +0 -206
  89. package/src/__tests__/cap-providers/cap-usage-graph.spec.ts +0 -37
  90. package/src/__tests__/cap-providers/compute-topology-categories.spec.ts +0 -110
  91. package/src/__tests__/cap-providers/integrations-delete-cascade.spec.ts +0 -292
  92. package/src/__tests__/cap-providers-bulk-update.spec.ts +0 -408
  93. package/src/__tests__/cap-route-adapter.spec.ts +0 -302
  94. package/src/__tests__/cap-routers/_meta.spec.ts +0 -199
  95. package/src/__tests__/cap-routers/addon-settings.router.spec.ts +0 -115
  96. package/src/__tests__/cap-routers/broker-routing.router.spec.ts +0 -177
  97. package/src/__tests__/cap-routers/cap-route-error-formatter.spec.ts +0 -125
  98. package/src/__tests__/cap-routers/capabilities-node.spec.ts +0 -68
  99. package/src/__tests__/cap-routers/device-link-overlay.spec.ts +0 -137
  100. package/src/__tests__/cap-routers/device-manager-aggregate.router.spec.ts +0 -194
  101. package/src/__tests__/cap-routers/harness.ts +0 -163
  102. package/src/__tests__/cap-routers/metrics-provider.router.spec.ts +0 -133
  103. package/src/__tests__/cap-routers/null-provider-guard.spec.ts +0 -64
  104. package/src/__tests__/cap-routers/pipeline-executor.router.spec.ts +0 -159
  105. package/src/__tests__/cap-routers/settings-store.router.spec.ts +0 -291
  106. package/src/__tests__/capability-e2e.test.ts +0 -384
  107. package/src/__tests__/cli-e2e.test.ts +0 -150
  108. package/src/__tests__/core-cap-bridge.spec.ts +0 -91
  109. package/src/__tests__/dev-bootstrap-shm-ring.spec.ts +0 -40
  110. package/src/__tests__/device-settings-contribution-dispatch.spec.ts +0 -280
  111. package/src/__tests__/embedded-deps-e2e.test.ts +0 -125
  112. package/src/__tests__/event-bus-proxy-router.spec.ts +0 -75
  113. package/src/__tests__/fixtures/mock-analysis-addon-a.ts +0 -37
  114. package/src/__tests__/fixtures/mock-analysis-addon-b.ts +0 -37
  115. package/src/__tests__/fixtures/mock-log-addon.ts +0 -37
  116. package/src/__tests__/fixtures/mock-storage-addon.ts +0 -40
  117. package/src/__tests__/framework-allowlist.spec.ts +0 -96
  118. package/src/__tests__/framework-installer-defer-restart.spec.ts +0 -165
  119. package/src/__tests__/https-e2e.test.ts +0 -124
  120. package/src/__tests__/lifecycle-e2e.test.ts +0 -189
  121. package/src/__tests__/live-events-subscription.spec.ts +0 -149
  122. package/src/__tests__/moleculer/uds-readiness.spec.ts +0 -150
  123. package/src/__tests__/moleculer/uds-topology.spec.ts +0 -418
  124. package/src/__tests__/moleculer/uds-unowned-call.spec.ts +0 -383
  125. package/src/__tests__/moleculer-register-node-idempotency.spec.ts +0 -273
  126. package/src/__tests__/native-cap-route.spec.ts +0 -427
  127. package/src/__tests__/oauth2-account-linking.spec.ts +0 -867
  128. package/src/__tests__/post-boot-restart.spec.ts +0 -161
  129. package/src/__tests__/singleton-contention.test.ts +0 -499
  130. package/src/__tests__/streaming-diagnostic.test.ts +0 -615
  131. package/src/__tests__/streaming-scale.test.ts +0 -314
  132. package/src/__tests__/uds-addon-call-wiring.spec.ts +0 -242
  133. package/src/__tests__/uds-log-ingest.spec.ts +0 -183
  134. package/src/api/__tests__/addons-custom.spec.ts +0 -148
  135. package/src/api/__tests__/capabilities.router.test.ts +0 -56
  136. package/src/api/addon-upload.ts +0 -529
  137. package/src/api/addons-custom.router.ts +0 -101
  138. package/src/api/auth-whoami.ts +0 -101
  139. package/src/api/bridge-addons.router.ts +0 -122
  140. package/src/api/capabilities.router.ts +0 -265
  141. package/src/api/core/__tests__/auth-router-totp.spec.ts +0 -297
  142. package/src/api/core/__tests__/integration-markers.spec.ts +0 -10
  143. package/src/api/core/addon-settings.router.ts +0 -127
  144. package/src/api/core/agents.router.ts +0 -86
  145. package/src/api/core/auth.router.ts +0 -322
  146. package/src/api/core/bulk-update-coordinator.ts +0 -305
  147. package/src/api/core/cap-providers.ts +0 -1339
  148. package/src/api/core/capabilities.router.ts +0 -149
  149. package/src/api/core/collection-preference.ts +0 -40
  150. package/src/api/core/event-bus-proxy.router.ts +0 -45
  151. package/src/api/core/hwaccel.router.ts +0 -108
  152. package/src/api/core/live-events.router.ts +0 -67
  153. package/src/api/core/logs.router.ts +0 -195
  154. package/src/api/core/notifications.router.ts +0 -66
  155. package/src/api/core/repl.router.ts +0 -39
  156. package/src/api/core/settings-backend.router.ts +0 -140
  157. package/src/api/core/stream-probe.router.ts +0 -57
  158. package/src/api/core/system-events.router.ts +0 -125
  159. package/src/api/health/health.routes.ts +0 -117
  160. package/src/api/oauth2/__tests__/oauth2-routes.spec.ts +0 -62
  161. package/src/api/oauth2/oauth2-routes.ts +0 -281
  162. package/src/api/trpc/__tests__/client-ip.spec.ts +0 -146
  163. package/src/api/trpc/__tests__/scope-access-device.spec.ts +0 -268
  164. package/src/api/trpc/__tests__/scope-access.spec.ts +0 -102
  165. package/src/api/trpc/__tests__/webrtc-session-ua-enrich.spec.ts +0 -136
  166. package/src/api/trpc/cap-mount-helpers.ts +0 -245
  167. package/src/api/trpc/cap-route-error-formatter.ts +0 -171
  168. package/src/api/trpc/client-ip.ts +0 -147
  169. package/src/api/trpc/core-cap-bridge.ts +0 -154
  170. package/src/api/trpc/generated-cap-mounts.ts +0 -1240
  171. package/src/api/trpc/generated-cap-routers.ts +0 -11523
  172. package/src/api/trpc/scope-access.ts +0 -110
  173. package/src/api/trpc/trpc.context.ts +0 -258
  174. package/src/api/trpc/trpc.middleware.ts +0 -146
  175. package/src/api/trpc/trpc.router.ts +0 -389
  176. package/src/auth/session-cookie.ts +0 -54
  177. package/src/boot/__tests__/integration-id-backfill.spec.ts +0 -131
  178. package/src/boot/boot-config.ts +0 -259
  179. package/src/boot/integration-id-backfill.ts +0 -109
  180. package/src/boot/post-boot.service.ts +0 -105
  181. package/src/core/addon/__tests__/addon-registry-capability.test.ts +0 -62
  182. package/src/core/addon/__tests__/addon-row-manifest.spec.ts +0 -62
  183. package/src/core/addon/addon-call-gateway.ts +0 -171
  184. package/src/core/addon/addon-package.service.ts +0 -1787
  185. package/src/core/addon/addon-registry.service.ts +0 -3130
  186. package/src/core/addon/addon-search.service.ts +0 -91
  187. package/src/core/addon/addon-settings-provider.ts +0 -220
  188. package/src/core/addon/addon.tokens.ts +0 -2
  189. package/src/core/addon-bridge/addon-bridge.service.ts +0 -130
  190. package/src/core/addon-pages/addon-pages.service.spec.ts +0 -117
  191. package/src/core/addon-pages/addon-pages.service.ts +0 -82
  192. package/src/core/addon-widgets/addon-widgets.service.ts +0 -95
  193. package/src/core/agent/agent-registry.service.ts +0 -529
  194. package/src/core/auth/auth.service.spec.ts +0 -86
  195. package/src/core/auth/auth.service.ts +0 -8
  196. package/src/core/capability/capability.service.ts +0 -66
  197. package/src/core/config/config.schema.ts +0 -3
  198. package/src/core/config/config.service.spec.ts +0 -175
  199. package/src/core/config/config.service.ts +0 -7
  200. package/src/core/events/event-bus.service.spec.ts +0 -235
  201. package/src/core/events/event-bus.service.ts +0 -89
  202. package/src/core/feature/feature.service.spec.ts +0 -99
  203. package/src/core/feature/feature.service.ts +0 -8
  204. package/src/core/lifecycle/lifecycle-state-machine.spec.ts +0 -166
  205. package/src/core/lifecycle/lifecycle-state-machine.ts +0 -3
  206. package/src/core/logging/log-ring-buffer.ts +0 -3
  207. package/src/core/logging/logging.service.spec.ts +0 -287
  208. package/src/core/logging/logging.service.ts +0 -143
  209. package/src/core/logging/scoped-logger.ts +0 -3
  210. package/src/core/moleculer/cap-call-fn.spec.ts +0 -173
  211. package/src/core/moleculer/cap-call-fn.ts +0 -107
  212. package/src/core/moleculer/cap-route-authority.ts +0 -194
  213. package/src/core/moleculer/moleculer.service.ts +0 -1072
  214. package/src/core/network/network-quality.service.spec.ts +0 -53
  215. package/src/core/network/network-quality.service.ts +0 -5
  216. package/src/core/notification/notification-wrapper.service.ts +0 -34
  217. package/src/core/notification/toast-wrapper.service.ts +0 -27
  218. package/src/core/provider/provider.tokens.ts +0 -1
  219. package/src/core/repl/repl-engine.service.spec.ts +0 -444
  220. package/src/core/repl/repl-engine.service.ts +0 -155
  221. package/src/core/storage/fs-storage-backend.spec.ts +0 -70
  222. package/src/core/storage/fs-storage-backend.ts +0 -3
  223. package/src/core/storage/storage-location-manager.spec.ts +0 -130
  224. package/src/core/storage/storage-location-manager.ts +0 -3
  225. package/src/core/storage/storage.service.spec.ts +0 -73
  226. package/src/core/storage/storage.service.ts +0 -3
  227. package/src/core/streaming/stream-probe.service.ts +0 -221
  228. package/src/core/topology/topology-emitter.service.ts +0 -105
  229. package/src/launcher.ts +0 -314
  230. package/src/main.ts +0 -1245
  231. package/src/manual-boot.ts +0 -301
  232. package/tsconfig.build.json +0 -8
  233. package/tsconfig.json +0 -33
  234. package/vitest.config.ts +0 -26
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createCapabilitiesRouter = createCapabilitiesRouter;
4
+ /**
5
+ * Capability admin router — fixed core API (not a capability).
6
+ *
7
+ * Lets admins inspect the capability registry and set system/device
8
+ * overrides. Wraps `CapabilityRegistry` directly (kernel primitive).
9
+ */
10
+ const zod_1 = require("zod");
11
+ const trpc_middleware_js_1 = require("../trpc/trpc.middleware.js");
12
+ function createCapabilitiesRouter(registry, config) {
13
+ return (0, trpc_middleware_js_1.trpcRouter)({
14
+ listCapabilities: trpc_middleware_js_1.adminProcedure
15
+ .input(zod_1.z.void())
16
+ .query(() => registry?.listCapabilities() ?? []),
17
+ getCapability: trpc_middleware_js_1.adminProcedure.input(zod_1.z.object({ name: zod_1.z.string() })).query(({ input }) => {
18
+ if (!registry)
19
+ return null;
20
+ return (registry.listCapabilities().find((c) => c.name === input.name) ?? null);
21
+ }),
22
+ setActiveSingleton: trpc_middleware_js_1.adminProcedure
23
+ .input(zod_1.z.object({
24
+ capability: zod_1.z.string(),
25
+ addonId: zod_1.z.string(),
26
+ nodeId: zod_1.z.string().optional(),
27
+ }))
28
+ .output(zod_1.z.void())
29
+ .mutation(async ({ input }) => {
30
+ if (!registry)
31
+ throw new Error('Capability registry unavailable');
32
+ await registry.setActiveSingleton(input.capability, input.addonId, input.nodeId);
33
+ if (input.nodeId !== undefined) {
34
+ // Per-node override: persist under the node-qualified key so the boot
35
+ // restorer (`setNodeConfigReader`) replays it on restart.
36
+ config.set(`capabilities.singletonNode.${input.capability}.${input.nodeId}`, input.addonId);
37
+ }
38
+ else {
39
+ // Cluster-global default: persist to the SAME key the boot restorer reads
40
+ // (addon-registry `setConfigReader` → `capabilities.singleton.<cap>`).
41
+ config.set(`capabilities.singleton.${input.capability}`, input.addonId);
42
+ }
43
+ }),
44
+ clearSingletonNodeOverride: trpc_middleware_js_1.adminProcedure
45
+ .input(zod_1.z.object({ capability: zod_1.z.string(), nodeId: zod_1.z.string() }))
46
+ .output(zod_1.z.void())
47
+ .mutation(({ input }) => {
48
+ if (!registry)
49
+ throw new Error('Capability registry unavailable');
50
+ registry.clearSingletonNodeOverride(input.capability, input.nodeId);
51
+ // Persist the cleared state as null so the boot restorer doesn't re-apply
52
+ // a stale override on restart.
53
+ config.set(`capabilities.singletonNode.${input.capability}.${input.nodeId}`, null);
54
+ }),
55
+ /**
56
+ * Set the enabled set of providers for a collection capability in
57
+ * one shot. Providers already registered on the capability that are
58
+ * NOT in `enabledAddonIds` get disabled; the ones in the list are
59
+ * re-enabled. Other collections are untouched. Intended as the
60
+ * save endpoint for a bulk multi-select UI.
61
+ */
62
+ setCollectionEnabledProviders: trpc_middleware_js_1.adminProcedure
63
+ .input(zod_1.z.object({
64
+ capability: zod_1.z.string(),
65
+ enabledAddonIds: zod_1.z.array(zod_1.z.string()),
66
+ }))
67
+ .output(zod_1.z.void())
68
+ .mutation(({ input }) => {
69
+ if (!registry)
70
+ throw new Error('Capability registry unavailable');
71
+ const caps = registry.listCapabilities();
72
+ const entry = caps.find((c) => c.name === input.capability);
73
+ if (!entry)
74
+ throw new Error(`Capability "${input.capability}" not declared`);
75
+ if (entry.mode !== 'collection') {
76
+ throw new Error(`Capability "${input.capability}" is not a collection`);
77
+ }
78
+ const wanted = new Set(input.enabledAddonIds);
79
+ for (const providerId of entry.providers) {
80
+ if (wanted.has(providerId)) {
81
+ registry.enableCollectionProvider(input.capability, providerId);
82
+ }
83
+ else {
84
+ registry.disableCollectionProvider(input.capability, providerId);
85
+ }
86
+ }
87
+ }),
88
+ setDeviceCapability: trpc_middleware_js_1.adminProcedure
89
+ .input(zod_1.z.object({ deviceId: zod_1.z.string(), capability: zod_1.z.string(), addonId: zod_1.z.string() }))
90
+ .output(zod_1.z.void())
91
+ .mutation(({ input }) => {
92
+ if (!registry)
93
+ throw new Error('Capability registry unavailable');
94
+ registry.setDeviceOverride(input.deviceId, input.capability, input.addonId);
95
+ }),
96
+ clearDeviceCapability: trpc_middleware_js_1.adminProcedure
97
+ .input(zod_1.z.object({ deviceId: zod_1.z.string(), capability: zod_1.z.string() }))
98
+ .output(zod_1.z.void())
99
+ .mutation(({ input }) => {
100
+ if (!registry)
101
+ throw new Error('Capability registry unavailable');
102
+ registry.clearDeviceOverride(input.deviceId, input.capability);
103
+ }),
104
+ getDeviceCapabilities: trpc_middleware_js_1.adminProcedure
105
+ .input(zod_1.z.object({ deviceId: zod_1.z.string() }))
106
+ .output(zod_1.z.record(zod_1.z.string(), zod_1.z.string()))
107
+ .query(({ input }) => {
108
+ if (!registry)
109
+ return {};
110
+ const overrides = registry.getDeviceOverrides(input.deviceId);
111
+ const result = {};
112
+ for (const [cap, addonId] of overrides) {
113
+ result[cap] = addonId;
114
+ }
115
+ return result;
116
+ }),
117
+ setDeviceCollectionFilter: trpc_middleware_js_1.adminProcedure
118
+ .input(zod_1.z.object({
119
+ deviceId: zod_1.z.string(),
120
+ capability: zod_1.z.string(),
121
+ addonIds: zod_1.z.array(zod_1.z.string()),
122
+ }))
123
+ .output(zod_1.z.void())
124
+ .mutation(({ input }) => {
125
+ if (!registry)
126
+ throw new Error('Capability registry unavailable');
127
+ registry.setDeviceCollectionFilter(input.deviceId, input.capability, input.addonIds);
128
+ }),
129
+ clearDeviceCollectionFilter: trpc_middleware_js_1.adminProcedure
130
+ .input(zod_1.z.object({ deviceId: zod_1.z.string(), capability: zod_1.z.string() }))
131
+ .output(zod_1.z.void())
132
+ .mutation(({ input }) => {
133
+ if (!registry)
134
+ throw new Error('Capability registry unavailable');
135
+ registry.clearDeviceCollectionFilter(input.deviceId, input.capability);
136
+ }),
137
+ });
138
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.collectionPreferenceKey = collectionPreferenceKey;
4
+ exports.persistCollectionDisabled = persistCollectionDisabled;
5
+ /** ConfigService key holding the persisted disabled-set for a collection cap. */
6
+ function collectionPreferenceKey(capability) {
7
+ return `capabilities.collection.${capability}`;
8
+ }
9
+ /**
10
+ * Persist the disabled-addonId set for a collection capability. Pass the
11
+ * authoritative set straight from `registry.listCapabilities()` after the
12
+ * enable/disable mutation so the stored value always mirrors the live
13
+ * registry state.
14
+ */
15
+ function persistCollectionDisabled(configService, capability, disabled) {
16
+ configService.set(collectionPreferenceKey(capability), JSON.stringify({ disabled: [...disabled] }));
17
+ }
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createEventBusProxyRouter = createEventBusProxyRouter;
4
+ /**
5
+ * EventBus proxy router — allows forked workers to emit events to the
6
+ * hub's EventBus via tRPC.
7
+ *
8
+ * Workers call `trpc.eventBusProxy.emit.mutate(event)` from their
9
+ * `context.eventBus.emit()` implementation. The hub-side router
10
+ * deserializes the event and emits it on the real EventBus.
11
+ *
12
+ * Subscribe/getRecent are routed through the existing `live.onEvent`
13
+ * subscription and `events` query routers — no duplication needed here.
14
+ *
15
+ * Introduced in session 7 (EventBus wiring for forked addons).
16
+ */
17
+ const zod_1 = require("zod");
18
+ const trpc_middleware_js_1 = require("../trpc/trpc.middleware.js");
19
+ const SystemEventInputSchema = zod_1.z.object({
20
+ id: zod_1.z.string(),
21
+ timestamp: zod_1.z.string(), // ISO 8601 — converted to Date on emit
22
+ source: zod_1.z.object({
23
+ type: zod_1.z.string(),
24
+ id: zod_1.z.string(),
25
+ }),
26
+ category: zod_1.z.string(),
27
+ data: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()),
28
+ });
29
+ function createEventBusProxyRouter(eventBus) {
30
+ return (0, trpc_middleware_js_1.trpcRouter)({
31
+ emit: trpc_middleware_js_1.protectedProcedure
32
+ .input(SystemEventInputSchema)
33
+ .output(zod_1.z.object({ ok: zod_1.z.literal(true) }))
34
+ .mutation(({ input }) => {
35
+ eventBus.emit({
36
+ id: input.id,
37
+ timestamp: new Date(input.timestamp),
38
+ source: { type: input.source.type, id: input.source.id },
39
+ category: input.category,
40
+ data: input.data,
41
+ });
42
+ return { ok: true };
43
+ }),
44
+ });
45
+ }
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createHwAccelRouter = createHwAccelRouter;
4
+ /**
5
+ * Hwaccel router — fixed core API (not a capability).
6
+ *
7
+ * Thin wrapper around the per-node `$hwaccel.resolve` Moleculer
8
+ * service. The hub-local instance (same process) serves the default
9
+ * `resolve` call; the per-node `resolveForNode` action targets any
10
+ * node in the cluster — used by the admin UI pipeline / NodeDetail
11
+ * pages to show the hwaccel backends available on each agent.
12
+ *
13
+ * Cross-node behaviour: `resolveForNode({ nodeId })` forwards via
14
+ * `broker.call('$hwaccel.resolve', params, { nodeID })`. Every node
15
+ * (hub + forked worker + remote agent) registers `$hwaccel` at
16
+ * bootstrap, so any reachable nodeId works.
17
+ */
18
+ const zod_1 = require("zod");
19
+ const trpc_middleware_js_1 = require("../trpc/trpc.middleware.js");
20
+ const HwAccelBackendSchema = zod_1.z.enum([
21
+ 'videotoolbox',
22
+ 'cuda',
23
+ 'nvdec',
24
+ 'vaapi',
25
+ 'qsv',
26
+ 'd3d11va',
27
+ 'dxva2',
28
+ 'amf',
29
+ 'vdpau',
30
+ 'drm',
31
+ ]);
32
+ const HwAccelPreferSchema = zod_1.z
33
+ .union([HwAccelBackendSchema, zod_1.z.literal('none')])
34
+ .nullable()
35
+ .optional();
36
+ const HwAccelResolutionSchema = zod_1.z.object({
37
+ preferred: zod_1.z.array(HwAccelBackendSchema).readonly(),
38
+ rationale: zod_1.z.string(),
39
+ });
40
+ function createHwAccelRouter(broker) {
41
+ return (0, trpc_middleware_js_1.trpcRouter)({
42
+ /** Probe the current hub process. */
43
+ resolve: trpc_middleware_js_1.adminProcedure
44
+ .input(zod_1.z.object({ prefer: HwAccelPreferSchema }).optional())
45
+ .output(HwAccelResolutionSchema)
46
+ .query(async ({ input }) => {
47
+ if (!broker)
48
+ throw new Error('Moleculer broker not available');
49
+ const params = { prefer: input?.prefer ?? null };
50
+ return broker.call('$hwaccel.resolve', params);
51
+ }),
52
+ /** Probe a specific node in the cluster — used by per-agent UI cards. */
53
+ resolveForNode: trpc_middleware_js_1.adminProcedure
54
+ .input(zod_1.z.object({ nodeId: zod_1.z.string(), prefer: HwAccelPreferSchema }))
55
+ .output(HwAccelResolutionSchema)
56
+ .query(async ({ input }) => {
57
+ if (!broker)
58
+ throw new Error('Moleculer broker not available');
59
+ const params = { prefer: input.prefer ?? null };
60
+ return broker.call('$hwaccel.resolve', params, {
61
+ nodeID: input.nodeId,
62
+ });
63
+ }),
64
+ /** List every node currently reachable and the hwaccel each resolves to. */
65
+ resolveAll: trpc_middleware_js_1.adminProcedure
66
+ .output(zod_1.z.array(zod_1.z.object({
67
+ nodeId: zod_1.z.string(),
68
+ resolution: HwAccelResolutionSchema,
69
+ })))
70
+ .query(async () => {
71
+ if (!broker)
72
+ throw new Error('Moleculer broker not available');
73
+ const registry = broker.registry;
74
+ const nodes = registry.getNodeList({ onlyAvailable: true });
75
+ const results = await Promise.all(nodes.map(async (n) => {
76
+ try {
77
+ const resolution = (await broker.call('$hwaccel.resolve', { prefer: null }, { nodeID: n.id }));
78
+ return { nodeId: n.id, resolution };
79
+ }
80
+ catch (err) {
81
+ const msg = err instanceof Error ? err.message : String(err);
82
+ return {
83
+ nodeId: n.id,
84
+ resolution: { preferred: [], rationale: `resolve failed: ${msg}` },
85
+ };
86
+ }
87
+ }));
88
+ return results;
89
+ }),
90
+ });
91
+ }
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createLiveEventsRouter = createLiveEventsRouter;
4
+ /**
5
+ * Live events router — fixed core API (not a capability).
6
+ *
7
+ * Higher-level live-subscription API consumed by the admin UI dashboard.
8
+ * Wraps `EventBusService` with per-device permission enforcement.
9
+ */
10
+ const zod_1 = require("zod");
11
+ const trpc_middleware_js_1 = require("../trpc/trpc.middleware.js");
12
+ function createLiveEventsRouter(eb, ar) {
13
+ return (0, trpc_middleware_js_1.trpcRouter)({
14
+ recentSystemEvents: trpc_middleware_js_1.protectedProcedure
15
+ .input(zod_1.z
16
+ .object({
17
+ category: zod_1.z.string().optional(),
18
+ limit: zod_1.z.number().optional(),
19
+ })
20
+ .optional())
21
+ .query(({ input }) => eb.getRecent(input ?? {}, input?.limit ?? 50)),
22
+ onEvent: trpc_middleware_js_1.protectedProcedure
23
+ .input(zod_1.z.object({ category: zod_1.z.string().optional() }))
24
+ .subscription(({ input }) => {
25
+ return (0, trpc_middleware_js_1.iterableSubscription)((push) => {
26
+ const filter = {};
27
+ if (input.category)
28
+ filter.category = input.category;
29
+ return eb.subscribe(filter, push);
30
+ });
31
+ }),
32
+ onDeviceEvent: trpc_middleware_js_1.protectedProcedure
33
+ .input(zod_1.z.object({ deviceId: zod_1.z.number() }))
34
+ .subscription(({ input, ctx }) => {
35
+ return (0, trpc_middleware_js_1.iterableSubscription)((push) => {
36
+ const deviceRegistry = ar.getDeviceRegistry();
37
+ const device = deviceRegistry.getById(input.deviceId);
38
+ if (!device)
39
+ throw new Error(`Device id=${input.deviceId} not found`);
40
+ // Permission check — new IDevice has no providerId; admin bypass only
41
+ if (!ctx.user.isAdmin) {
42
+ const ad = ctx.user.permissions?.allowedDevices;
43
+ if (!ad)
44
+ throw new Error('Access denied');
45
+ // Find which addon owns this device to determine the provider key
46
+ const ownerAddonId = deviceRegistry.getAddonId(input.deviceId);
47
+ if (!ownerAddonId)
48
+ throw new Error('Access denied');
49
+ const pd = ad[ownerAddonId];
50
+ // Permission lists are still keyed by stableId — that's the
51
+ // external admin-facing identifier. Resolve the device's
52
+ // stableId for the membership check.
53
+ if (!pd || (pd !== '*' && !pd.includes(device.stableId))) {
54
+ throw new Error('Access denied');
55
+ }
56
+ }
57
+ return eb.subscribe({ source: { type: 'device', id: input.deviceId } }, push);
58
+ });
59
+ }),
60
+ });
61
+ }
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createLogsRouter = createLogsRouter;
4
+ /**
5
+ * Logs router — fixed core API (not a capability).
6
+ *
7
+ * Queries and streams log entries via `LoggingService` (thin NestJS DI
8
+ * wrapper over `LogManager` from `@camstack/core`). Admin can read
9
+ * everything; viewers/protected users only see entries matching their
10
+ * allowed providers scope (filtered in `query`).
11
+ */
12
+ const zod_1 = require("zod");
13
+ const trpc_middleware_js_1 = require("../trpc/trpc.middleware.js");
14
+ const LogLevelSchema = zod_1.z.enum(['debug', 'info', 'warn', 'error']);
15
+ const LogTagsSchema = zod_1.z.object({
16
+ agentId: zod_1.z.string().optional(),
17
+ nodeId: zod_1.z.string().optional(),
18
+ /** Numeric progressive id (or its string form for legacy callers). */
19
+ deviceId: zod_1.z.union([zod_1.z.string(), zod_1.z.number()]).optional(),
20
+ /** Parent container id — set on every accessory child's logs (and on the
21
+ * container's own logs). Filtering by it returns the whole container subtree
22
+ * (container + all children) in one query. */
23
+ containerDeviceId: zod_1.z.union([zod_1.z.string(), zod_1.z.number()]).optional(),
24
+ deviceName: zod_1.z.string().optional(),
25
+ integrationId: zod_1.z.string().optional(),
26
+ addonId: zod_1.z.string().optional(),
27
+ streamId: zod_1.z.string().optional(),
28
+ streamName: zod_1.z.string().optional(),
29
+ sessionId: zod_1.z.string().optional(),
30
+ /**
31
+ * Correlation id used to scope a single short-lived operation
32
+ * (e.g. a `testCreationField` probe). The Add-Device modal generates
33
+ * one per dialog open and providers tag their loggers with it so the
34
+ * modal can stream test logs without a deviceId (the device doesn't
35
+ * exist yet).
36
+ */
37
+ requestId: zod_1.z.string().optional(),
38
+ });
39
+ /** Wire shape of a log entry — timestamp is serialised to ISO string by tRPC. */
40
+ const LogEntrySchema = zod_1.z.object({
41
+ timestamp: zod_1.z.string(),
42
+ level: zod_1.z.string(),
43
+ scope: zod_1.z.string().optional(),
44
+ message: zod_1.z.string(),
45
+ tags: zod_1.z.record(zod_1.z.string(), zod_1.z.string().optional()).optional(),
46
+ /**
47
+ * Ad-hoc structured payload attached to the log call (e.g.
48
+ * `{error, brokerId, sourceType, url}` for stream-broker errors).
49
+ * Tags are filterable structural fields; meta is the per-call
50
+ * payload operators read in the expanded LogStream row.
51
+ */
52
+ meta: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()).optional(),
53
+ });
54
+ const LogEntryArraySchema = zod_1.z.array(LogEntrySchema);
55
+ function createLogsRouter(logging) {
56
+ return (0, trpc_middleware_js_1.trpcRouter)({
57
+ query: trpc_middleware_js_1.adminProcedure
58
+ .input(zod_1.z.object({
59
+ level: LogLevelSchema.optional(),
60
+ since: zod_1.z.number().optional(),
61
+ until: zod_1.z.number().optional(),
62
+ limit: zod_1.z.number().optional(),
63
+ tags: LogTagsSchema.optional(),
64
+ }))
65
+ .output(LogEntryArraySchema)
66
+ .query(({ input, ctx }) => {
67
+ const filter = { limit: input.limit ?? 100 };
68
+ if (input.level)
69
+ filter.level = input.level;
70
+ if (input.since !== undefined)
71
+ filter.since = new Date(input.since);
72
+ if (input.until !== undefined)
73
+ filter.until = new Date(input.until);
74
+ if (input.tags)
75
+ filter.tags = input.tags;
76
+ const entries = logging.query(filter);
77
+ const filtered = (() => {
78
+ if (!ctx.user.isAdmin) {
79
+ const ap = ctx.user.permissions?.allowedProviders;
80
+ if (ap && ap !== '*') {
81
+ const allowed = ap;
82
+ return entries.filter((e) => {
83
+ const addonId = e.tags?.addonId;
84
+ if (typeof addonId !== 'string')
85
+ return false;
86
+ return allowed.some((p) => {
87
+ const bare = p.startsWith('addon:') ? p.slice('addon:'.length) : p;
88
+ return addonId === bare || addonId.startsWith(bare);
89
+ });
90
+ });
91
+ }
92
+ }
93
+ return entries;
94
+ })();
95
+ return filtered.map((e) => ({
96
+ timestamp: e.timestamp instanceof Date ? e.timestamp.toISOString() : String(e.timestamp),
97
+ level: e.level,
98
+ ...(e.scope !== undefined ? { scope: e.scope } : {}),
99
+ message: e.message,
100
+ // Tags carry mixed primitive types (numeric deviceId is common —
101
+ // see kernel/capability-registry.ts logging calls). The wire
102
+ // schema is Record<string,string>, so stringify here. Mirrors
103
+ // the same normalisation applied in `subscribe` below.
104
+ tags: e.tags
105
+ ? Object.fromEntries(Object.entries(e.tags).map(([k, v]) => [
106
+ k,
107
+ v === undefined ? undefined : String(v),
108
+ ]))
109
+ : undefined,
110
+ ...(e.meta !== undefined ? { meta: e.meta } : {}),
111
+ }));
112
+ }),
113
+ /**
114
+ * Drop matching entries from the in-memory ring buffer. Powers
115
+ * the UI's "Clear logs" button — without server-side purge, the
116
+ * cleared rows reappear on the next page open from the historical
117
+ * `query`. Admin-only so a viewer can't wipe context other ops
118
+ * are reading.
119
+ */
120
+ clear: trpc_middleware_js_1.adminProcedure
121
+ .input(zod_1.z.object({
122
+ level: LogLevelSchema.optional(),
123
+ since: zod_1.z.number().optional(),
124
+ until: zod_1.z.number().optional(),
125
+ tags: LogTagsSchema.optional(),
126
+ }))
127
+ .output(zod_1.z.object({ removed: zod_1.z.number().int().nonnegative() }))
128
+ .mutation(({ input }) => {
129
+ const filter = {};
130
+ if (input.level)
131
+ filter.level = input.level;
132
+ if (input.since !== undefined)
133
+ filter.since = new Date(input.since);
134
+ if (input.until !== undefined)
135
+ filter.until = new Date(input.until);
136
+ if (input.tags)
137
+ filter.tags = input.tags;
138
+ const removed = logging.clear(filter);
139
+ return { removed };
140
+ }),
141
+ subscribe: trpc_middleware_js_1.protectedProcedure
142
+ .input(zod_1.z.object({
143
+ level: LogLevelSchema.optional(),
144
+ tags: LogTagsSchema.optional(),
145
+ }))
146
+ .subscription(({ input }) => {
147
+ return (0, trpc_middleware_js_1.iterableSubscription)((push) => {
148
+ return logging.subscribe({
149
+ level: input.level,
150
+ tags: input.tags,
151
+ }, (entry) => {
152
+ const stringifiedTags = entry.tags
153
+ ? Object.fromEntries(Object.entries(entry.tags).map(([k, v]) => [
154
+ k,
155
+ v === undefined ? undefined : String(v),
156
+ ]))
157
+ : undefined;
158
+ push({
159
+ timestamp: entry.timestamp instanceof Date
160
+ ? entry.timestamp.toISOString()
161
+ : String(entry.timestamp),
162
+ level: entry.level,
163
+ message: entry.message,
164
+ scope: entry.scope,
165
+ tags: stringifiedTags,
166
+ meta: entry.meta,
167
+ });
168
+ });
169
+ });
170
+ }),
171
+ });
172
+ }
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createNotificationsRouter = createNotificationsRouter;
4
+ /**
5
+ * Notifications router — fixed core API (not a capability).
6
+ *
7
+ * Routes events by category to registered outputs. The NotificationService
8
+ * is a singleton from @camstack/core; individual outputs are still provided
9
+ * by addons via the `notification-output` capability collection.
10
+ */
11
+ const zod_1 = require("zod");
12
+ const trpc_middleware_js_1 = require("../trpc/trpc.middleware.js");
13
+ const NotificationOutputSchema = zod_1.z.object({
14
+ id: zod_1.z.string(),
15
+ name: zod_1.z.string(),
16
+ icon: zod_1.z.string(),
17
+ });
18
+ const SendTestResultSchema = zod_1.z.object({
19
+ success: zod_1.z.boolean(),
20
+ error: zod_1.z.string().optional(),
21
+ });
22
+ function createNotificationsRouter(ns) {
23
+ return (0, trpc_middleware_js_1.trpcRouter)({
24
+ listOutputs: trpc_middleware_js_1.protectedProcedure
25
+ .input(zod_1.z.void())
26
+ .output(zod_1.z.array(NotificationOutputSchema).readonly())
27
+ .query(() => {
28
+ if (!ns)
29
+ return [];
30
+ return ns.getOutputs();
31
+ }),
32
+ getRouting: trpc_middleware_js_1.protectedProcedure
33
+ .input(zod_1.z.void())
34
+ .output(zod_1.z.record(zod_1.z.string(), zod_1.z.array(zod_1.z.string())))
35
+ .query(() => {
36
+ if (!ns)
37
+ return {};
38
+ const routing = ns.getRouting();
39
+ const result = {};
40
+ for (const [category, outputIds] of routing) {
41
+ result[category] = [...outputIds];
42
+ }
43
+ return result;
44
+ }),
45
+ setRouting: trpc_middleware_js_1.adminProcedure
46
+ .input(zod_1.z.object({ category: zod_1.z.string(), outputIds: zod_1.z.array(zod_1.z.string()) }))
47
+ .output(zod_1.z.void())
48
+ .mutation(({ input }) => {
49
+ if (!ns)
50
+ throw new Error('Notification service unavailable');
51
+ ns.setRouting(input.category, input.outputIds);
52
+ }),
53
+ sendTest: trpc_middleware_js_1.adminProcedure
54
+ .input(zod_1.z.object({ outputId: zod_1.z.string() }))
55
+ .output(SendTestResultSchema)
56
+ .mutation(async ({ input }) => {
57
+ if (!ns)
58
+ return { success: false, error: 'Notification service unavailable' };
59
+ const output = ns.getOutput(input.outputId);
60
+ if (!output)
61
+ return { success: false, error: `Output "${input.outputId}" not found` };
62
+ if (!output.sendTest)
63
+ return { success: false, error: 'Output does not support test notifications' };
64
+ return output.sendTest();
65
+ }),
66
+ });
67
+ }
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createReplRouter = createReplRouter;
4
+ /**
5
+ * REPL router — fixed core API (not a capability).
6
+ *
7
+ * The REPL engine is a single NestJS-backed service in the backend
8
+ * (`ReplEngineService` extends `ReplEngine` from `@camstack/core`).
9
+ * Only super_admin can execute code.
10
+ */
11
+ const zod_1 = require("zod");
12
+ const trpc_middleware_js_1 = require("../trpc/trpc.middleware.js");
13
+ const ReplScopeSchema = zod_1.z.discriminatedUnion('type', [
14
+ zod_1.z.object({ type: zod_1.z.literal('system') }),
15
+ zod_1.z.object({ type: zod_1.z.literal('device'), deviceId: zod_1.z.number() }),
16
+ zod_1.z.object({ type: zod_1.z.literal('provider'), providerId: zod_1.z.string() }),
17
+ zod_1.z.object({ type: zod_1.z.literal('addon'), addonId: zod_1.z.string() }),
18
+ ]);
19
+ const ReplResultSchema = zod_1.z.object({
20
+ output: zod_1.z.string(),
21
+ error: zod_1.z.string().optional(),
22
+ duration: zod_1.z.number().optional(),
23
+ });
24
+ function createReplRouter(repl) {
25
+ return (0, trpc_middleware_js_1.trpcRouter)({
26
+ execute: trpc_middleware_js_1.adminProcedure
27
+ .input(zod_1.z.object({ code: zod_1.z.string().max(10000), scope: ReplScopeSchema }))
28
+ .output(ReplResultSchema)
29
+ .mutation(({ input }) => repl.execute(input.code, { scope: input.scope, variables: {} })),
30
+ completions: trpc_middleware_js_1.adminProcedure
31
+ .input(zod_1.z.object({ partial: zod_1.z.string(), scope: ReplScopeSchema }))
32
+ .output(zod_1.z.array(zod_1.z.string()).readonly())
33
+ .query(({ input }) => repl.getCompletions(input.partial, { scope: input.scope, variables: {} })),
34
+ });
35
+ }