@camstack/server 1.2.593 → 1.2.594

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 (256) hide show
  1. package/dist/addon-root-inventory.js +11 -50
  2. package/dist/agent/addon-scan.js +6 -44
  3. package/dist/agent/agent-addon-runtime.js +3 -8
  4. package/dist/agent/agent-addon-updates.js +12 -52
  5. package/dist/agent/agent-cap-dispatch-service.js +3 -5
  6. package/dist/agent/agent-config.js +7 -42
  7. package/dist/agent/agent-deploy-swap.js +5 -41
  8. package/dist/agent/agent-group-runner.js +8 -47
  9. package/dist/agent/agent-http-auth.js +10 -22
  10. package/dist/agent/agent-http.js +69 -115
  11. package/dist/agent/agent-hub-addon-update.js +10 -16
  12. package/dist/agent/agent-hub-registration.js +4 -7
  13. package/dist/agent/agent-infra-capabilities.js +5 -9
  14. package/dist/agent/agent-json-file.js +5 -42
  15. package/dist/agent/agent-mesh-gate.js +5 -8
  16. package/dist/agent/agent-node-certificates.js +25 -28
  17. package/dist/agent/agent-pairing-local.js +10 -47
  18. package/dist/agent/agent-pairing-routes.js +16 -20
  19. package/dist/agent/agent-pairing-store.js +18 -58
  20. package/dist/agent/agent-reconnect.js +1 -4
  21. package/dist/agent/agent-service.js +42 -78
  22. package/dist/agent/agent-sniffing-listener.js +11 -48
  23. package/dist/agent/agent-undeploy.js +5 -41
  24. package/dist/agent/agent-update-routes.js +14 -19
  25. package/dist/agent/agent-update-service.js +38 -80
  26. package/dist/agent/apply-model-distribution.js +1 -4
  27. package/dist/agent/apply-stage-dev-uploads.js +6 -9
  28. package/dist/agent/derive-hub-url.js +3 -8
  29. package/dist/agent/fetch-bundle-from-hub.js +6 -9
  30. package/dist/agent/hubs-found.js +6 -43
  31. package/dist/agent/infra-boot-guard.js +1 -4
  32. package/dist/agent/infra-boot-plan.js +2 -6
  33. package/dist/agent/main.js +158 -186
  34. package/dist/agent/register-agent-cap-dispatch.js +3 -6
  35. package/dist/agent/serial-queue.js +2 -7
  36. package/dist/agent-status-page.js +1 -4
  37. package/dist/api/addon-upload.js +22 -61
  38. package/dist/api/agent-addon-delivery.js +6 -11
  39. package/dist/api/auth-whoami.js +1 -4
  40. package/dist/api/backup-download-pump.js +5 -9
  41. package/dist/api/backup-download.js +7 -10
  42. package/dist/api/core/addon-settings.router.js +16 -19
  43. package/dist/api/core/agent-pairing.router.js +76 -79
  44. package/dist/api/core/agents.router.js +21 -24
  45. package/dist/api/core/auth-admin-tokens.procedures.js +48 -52
  46. package/dist/api/core/auth-device-cert.procedures.js +62 -67
  47. package/dist/api/core/auth-limits.js +16 -25
  48. package/dist/api/core/auth-reauth.procedures.js +32 -37
  49. package/dist/api/core/auth-revoke-credentials.procedures.js +22 -26
  50. package/dist/api/core/auth-sessions.procedures.js +52 -56
  51. package/dist/api/core/auth.router.js +300 -304
  52. package/dist/api/core/cap-providers.js +74 -121
  53. package/dist/api/core/capabilities.router.js +34 -37
  54. package/dist/api/core/capability-preference-writes.js +10 -17
  55. package/dist/api/core/certificates.router.js +106 -109
  56. package/dist/api/core/cluster-nodes.router.js +15 -18
  57. package/dist/api/core/collection-preference.js +2 -6
  58. package/dist/api/core/event-bus-proxy.router.js +34 -37
  59. package/dist/api/core/failure-contributions.js +4 -8
  60. package/dist/api/core/hwaccel.router.js +17 -20
  61. package/dist/api/core/integration-secrets.js +8 -12
  62. package/dist/api/core/lifecycle-job-runner.js +13 -49
  63. package/dist/api/core/live-events.router.js +29 -32
  64. package/dist/api/core/load-contributions.js +4 -8
  65. package/dist/api/core/logging-settings.js +30 -43
  66. package/dist/api/core/logs.router.js +40 -43
  67. package/dist/api/core/notifications.router.js +15 -18
  68. package/dist/api/core/public-event-filter.js +4 -8
  69. package/dist/api/core/repl.router.js +18 -21
  70. package/dist/api/core/request-census-settings.js +11 -16
  71. package/dist/api/core/server-management.provider.js +1 -4
  72. package/dist/api/core/server-name.js +9 -17
  73. package/dist/api/core/site-location.js +16 -24
  74. package/dist/api/core/stream-probe.router.js +21 -24
  75. package/dist/api/core/system-events.router.js +23 -26
  76. package/dist/api/cors/cors-policy.js +20 -29
  77. package/dist/api/cors/register-cors-policy.js +9 -14
  78. package/dist/api/deploy-stage-registry.js +6 -10
  79. package/dist/api/dev-uploads-bundle.js +12 -50
  80. package/dist/api/health/adaptive-probe.routes.js +9 -13
  81. package/dist/api/health/health.routes.js +8 -13
  82. package/dist/api/hub-cluster-url.js +3 -9
  83. package/dist/api/model-distributor.js +12 -50
  84. package/dist/api/oauth2/consent-page.js +10 -13
  85. package/dist/api/oauth2/oauth2-routes.js +17 -25
  86. package/dist/api/oauth2/private-host.js +1 -4
  87. package/dist/api/server-upload-propagate.js +15 -51
  88. package/dist/api/server-upload.js +13 -50
  89. package/dist/api/sse-no-compression.js +1 -4
  90. package/dist/api/static/frame-policy.js +4 -9
  91. package/dist/api/static/precompressed-asset.js +15 -57
  92. package/dist/api/static/spa-mount.js +8 -47
  93. package/dist/api/static/spa-static.js +5 -12
  94. package/dist/api/tarball-manifest.js +7 -44
  95. package/dist/api/trpc/cap-mount-helpers.js +7 -12
  96. package/dist/api/trpc/cap-route-error-formatter.js +10 -13
  97. package/dist/api/trpc/cap-router-runtime.js +40 -51
  98. package/dist/api/trpc/client-ip.js +9 -20
  99. package/dist/api/trpc/core-cap-bridge.js +32 -42
  100. package/dist/api/trpc/device-collection-dispatch.js +23 -27
  101. package/dist/api/trpc/device-config-secret-redaction.js +24 -40
  102. package/dist/api/trpc/generated-cap-mounts.js +218 -222
  103. package/dist/api/trpc/generated-cap-routers.js +4688 -4850
  104. package/dist/api/trpc/http-request-census-hook.js +8 -11
  105. package/dist/api/trpc/http-request-census.js +34 -41
  106. package/dist/api/trpc/http-request-census.singleton.js +4 -8
  107. package/dist/api/trpc/localized-schema-paths.js +1 -4
  108. package/dist/api/trpc/principal-visibility.js +14 -22
  109. package/dist/api/trpc/remote-addon-update-grant.js +1 -4
  110. package/dist/api/trpc/scope-access.js +10 -15
  111. package/dist/api/trpc/server-provided-caps.js +3 -7
  112. package/dist/api/trpc/share-view-access.js +6 -14
  113. package/dist/api/trpc/trpc-error-device-tags.js +3 -6
  114. package/dist/api/trpc/trpc-error-principal.js +2 -6
  115. package/dist/api/trpc/trpc.context.js +20 -25
  116. package/dist/api/trpc/trpc.middleware.js +38 -46
  117. package/dist/api/trpc/trpc.router.js +58 -99
  118. package/dist/api/trpc/user-error.js +5 -8
  119. package/dist/api/trpc/ws-request-census.js +17 -24
  120. package/dist/api/trpc/ws-slow-consumer-guard.js +11 -16
  121. package/dist/api/upload-auth.js +5 -9
  122. package/dist/auth/addon-route-jwt-gate.js +4 -7
  123. package/dist/auth/addon-route-share-gate.js +7 -12
  124. package/dist/auth/app-confirm-page.js +17 -22
  125. package/dist/auth/app-confirm-routes.js +26 -31
  126. package/dist/auth/app-confirmations.js +7 -44
  127. package/dist/auth/app-page-shell.js +17 -30
  128. package/dist/auth/app-page-strings.js +11 -17
  129. package/dist/auth/app-passkey-page.js +16 -21
  130. package/dist/auth/app-passkey-routes.js +37 -41
  131. package/dist/auth/app-refused-route.js +13 -18
  132. package/dist/auth/auth-network-policy.js +11 -15
  133. package/dist/auth/auth-provider-gate.js +4 -9
  134. package/dist/auth/auth-rate-limit.js +3 -7
  135. package/dist/auth/client-address.js +6 -9
  136. package/dist/auth/device-enroll-proofs.js +6 -43
  137. package/dist/auth/external-link-intents.js +3 -7
  138. package/dist/auth/hub-sessions.js +6 -12
  139. package/dist/auth/native-link-completions.js +7 -11
  140. package/dist/auth/native-return.js +9 -13
  141. package/dist/auth/passkey-provider.js +26 -32
  142. package/dist/auth/second-factors.js +6 -10
  143. package/dist/auth/session-connections.js +6 -12
  144. package/dist/auth/session-cookie.js +12 -23
  145. package/dist/auth/session-lifetimes.js +8 -12
  146. package/dist/auth/session-mint.js +4 -11
  147. package/dist/auth/sso-finish-app.js +13 -16
  148. package/dist/auth/sso-finish-deps.js +21 -27
  149. package/dist/auth/sso-finish.js +28 -38
  150. package/dist/auth/sso-routes.js +22 -25
  151. package/dist/auth/used-bridge-ids.js +1 -5
  152. package/dist/boot/boot-config.js +16 -55
  153. package/dist/boot/init-sequence.js +1 -4
  154. package/dist/boot/integration-id-backfill.js +3 -8
  155. package/dist/boot/platform-keychain-key.js +5 -42
  156. package/dist/boot/post-boot.service.js +14 -18
  157. package/dist/boot/reconcile-lifecycle-jobs.js +3 -6
  158. package/dist/boot/retired-public-url-env.js +4 -8
  159. package/dist/bootstrap-packages.js +1 -4
  160. package/dist/closure-node-modules.js +2 -38
  161. package/dist/closure-patches/patch-reach.json +6 -2
  162. package/dist/core/addon/addon-call-gateway.js +1 -5
  163. package/dist/core/addon/addon-package.service.js +83 -123
  164. package/dist/core/addon/addon-process-view.js +2 -6
  165. package/dist/core/addon/addon-realign-plan.js +1 -4
  166. package/dist/core/addon/addon-registry.service.js +199 -185
  167. package/dist/core/addon/addon-row-manifest.js +1 -4
  168. package/dist/core/addon/addon-search.service.js +3 -7
  169. package/dist/core/addon/addon-settings-provider.js +1 -3
  170. package/dist/core/addon/addon-uninstall.js +4 -11
  171. package/dist/core/addon/addon.tokens.js +2 -5
  172. package/dist/core/addon/device-meta-mirror.js +8 -13
  173. package/dist/core/addon/forked-custom-actions.js +6 -11
  174. package/dist/core/addon/integration-visibility.js +3 -6
  175. package/dist/core/addon/materialize-route-path.js +1 -4
  176. package/dist/core/addon/package-dir-utils.js +8 -45
  177. package/dist/core/addon/prune-misplaced-addons.js +5 -43
  178. package/dist/core/addon/runner-convergence.js +1 -4
  179. package/dist/core/addon/runner-serialization.js +1 -4
  180. package/dist/core/addon/runner-spawn-fanout.js +3 -8
  181. package/dist/core/addon/settings-door-wiring.js +5 -8
  182. package/dist/core/addon/single-flight-refresh.js +1 -4
  183. package/dist/core/addon-bridge/addon-bridge.service.js +7 -44
  184. package/dist/core/addon-pages/addon-pages.service.js +3 -40
  185. package/dist/core/addon-widgets/addon-widgets.service.js +4 -42
  186. package/dist/core/agent/agent-addon-backfill.js +9 -17
  187. package/dist/core/agent/agent-delivery-ledger.js +3 -7
  188. package/dist/core/agent/agent-liveness-event.js +2 -6
  189. package/dist/core/agent/agent-pairing-http.js +41 -45
  190. package/dist/core/agent/agent-registry.service.js +53 -92
  191. package/dist/core/agent/cluster-node-history-mirror.js +3 -7
  192. package/dist/core/agent/cluster-node-history-store.js +113 -58
  193. package/dist/core/agent/hub-agent-pairing.js +1 -5
  194. package/dist/core/agent/node-certificates-client.js +3 -6
  195. package/dist/core/agent/node-directory.js +1 -4
  196. package/dist/core/app-links/well-known-app-links.js +2 -6
  197. package/dist/core/auth/auth.service.js +3 -8
  198. package/dist/core/auth/handoff-code.service.js +11 -49
  199. package/dist/core/auth/record-kinds.js +35 -0
  200. package/dist/core/auth/share-token.service.js +174 -122
  201. package/dist/core/capability/capability.service.js +1 -5
  202. package/dist/core/config/config.schema.js +1 -6
  203. package/dist/core/config/config.service.js +2 -6
  204. package/dist/core/events/event-bus.service.js +3 -7
  205. package/dist/core/feature/feature.service.js +2 -6
  206. package/dist/core/lifecycle/lifecycle-runner.singleton.js +5 -10
  207. package/dist/core/lifecycle/lifecycle-state-machine.js +1 -5
  208. package/dist/core/logging/log-ring-buffer.js +1 -5
  209. package/dist/core/logging/logging.service.js +5 -9
  210. package/dist/core/logging/scoped-logger.js +1 -5
  211. package/dist/core/moleculer/agent-readiness-pull.js +1 -4
  212. package/dist/core/moleculer/agent-registration-request.js +3 -7
  213. package/dist/core/moleculer/cap-call-fn.js +39 -5
  214. package/dist/core/moleculer/cap-route-authority.js +3 -8
  215. package/dist/core/moleculer/hub-mesh-guard.js +5 -9
  216. package/dist/core/moleculer/moleculer.service.js +108 -119
  217. package/dist/core/network/network-quality.service.js +2 -6
  218. package/dist/core/notification/notification-wrapper.service.js +3 -7
  219. package/dist/core/notification/toast-wrapper.service.js +3 -7
  220. package/dist/core/provider/provider.tokens.js +1 -4
  221. package/dist/core/repl/repl-engine.service.js +4 -8
  222. package/dist/core/runner-health/runner-boot-check.js +7 -15
  223. package/dist/core/runner-health/update-preflight.js +9 -14
  224. package/dist/core/server-update/server-update.service.js +12 -49
  225. package/dist/core/server-update/system-apply-closure-patches.js +6 -42
  226. package/dist/core/server-update/system-ensure-prebuilds.js +3 -6
  227. package/dist/core/server-update/system-exec-npm.js +2 -5
  228. package/dist/core/storage/fs-storage-backend.js +1 -5
  229. package/dist/core/storage/storage-location-manager.js +1 -5
  230. package/dist/core/storage/storage.service.js +2 -6
  231. package/dist/core/streaming/ffmpeg-stream-info.js +3 -8
  232. package/dist/core/streaming/stream-probe.service.js +12 -16
  233. package/dist/core/streaming/ttl-cache.js +1 -5
  234. package/dist/core/topology/topology-emitter.service.js +19 -23
  235. package/dist/core/update-availability-emitter.js +3 -7
  236. package/dist/core/update-availability-store.js +8 -45
  237. package/dist/core/updates/agent-installed-packages.js +5 -9
  238. package/dist/core/updates/restart-marker.js +3 -8
  239. package/dist/core/updates/update-check-scheduler.js +13 -18
  240. package/dist/core/updates/wrapper-update-checker.js +3 -7
  241. package/dist/first-boot-addon-plan.js +2 -6
  242. package/dist/framework-nodepath.js +2 -38
  243. package/dist/i18n/request-lang.js +7 -11
  244. package/dist/launcher.js +30 -65
  245. package/dist/lifecycle-journal-path.js +2 -38
  246. package/dist/main.js +287 -324
  247. package/dist/manual-boot.js +120 -157
  248. package/dist/node-role.js +1 -4
  249. package/dist/package-inventory.js +7 -48
  250. package/dist/pending-restore.js +7 -43
  251. package/dist/single-copy-cleanup-runner.js +9 -45
  252. package/dist/single-copy-cleanup.js +7 -15
  253. package/dist/sqlite-restore.js +9 -48
  254. package/dist/starter.js +4 -39
  255. package/dist/ui-serving/lazy-ui-serving.js +3 -39
  256. package/package.json +13 -13
@@ -1,29 +1,27 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ClusterNodeHistoryStore = void 0;
4
- const zod_1 = require("zod");
5
- const types_1 = require("@camstack/types");
6
- const DescriptorSchema = zod_1.z.object({
7
- id: zod_1.z.string(),
8
- name: zod_1.z.string(),
9
- hostname: zod_1.z.string(),
10
- platform: zod_1.z.string(),
11
- arch: zod_1.z.string(),
12
- cpuModel: zod_1.z.string().nullable(),
13
- cpuCores: zod_1.z.number(),
14
- memoryMB: zod_1.z.number(),
15
- engines: zod_1.z.array(zod_1.z.string()).readonly(),
16
- isHub: zod_1.z.boolean(),
17
- localIps: zod_1.z.array(zod_1.z.string()).readonly(),
18
- addonIds: zod_1.z.array(zod_1.z.string()).readonly(),
19
- packages: zod_1.z
20
- .array(zod_1.z.object({ name: zod_1.z.string(), version: zod_1.z.string().nullable() }))
1
+ import { ClusterNodeHistoryBodySchema, readAllRows, } from '@camstack/system';
2
+ import { z } from 'zod';
3
+ import { errMsg } from '@camstack/types';
4
+ const DescriptorSchema = z.object({
5
+ id: z.string(),
6
+ name: z.string(),
7
+ hostname: z.string(),
8
+ platform: z.string(),
9
+ arch: z.string(),
10
+ cpuModel: z.string().nullable(),
11
+ cpuCores: z.number(),
12
+ memoryMB: z.number(),
13
+ engines: z.array(z.string()).readonly(),
14
+ isHub: z.boolean(),
15
+ localIps: z.array(z.string()).readonly(),
16
+ addonIds: z.array(z.string()).readonly(),
17
+ packages: z
18
+ .array(z.object({ name: z.string(), version: z.string().nullable() }))
21
19
  .readonly()
22
20
  .optional(),
23
21
  });
24
22
  /** Shape of a `settings-store.query` record's `data` for this collection. */
25
- const RowDataSchema = zod_1.z.object({
26
- lastActive: zod_1.z.number(),
23
+ const RowDataSchema = z.object({
24
+ lastActive: z.number(),
27
25
  descriptor: DescriptorSchema,
28
26
  });
29
27
  /**
@@ -79,13 +77,19 @@ function samePackages(a, b) {
79
77
  return a === b;
80
78
  return (a.length === b.length && a.every((p, i) => p.name === b[i]?.name && p.version === b[i]?.version));
81
79
  }
82
- class ClusterNodeHistoryStore {
80
+ export class ClusterNodeHistoryStore {
83
81
  resolveSettingsStore;
84
82
  logger;
85
83
  declared = false;
86
- constructor(resolveSettingsStore, logger) {
84
+ resolveKind;
85
+ constructor(resolveSettingsStore, logger, resolveKind = () => null) {
87
86
  this.resolveSettingsStore = resolveSettingsStore;
88
87
  this.logger = logger;
88
+ this.resolveKind = resolveKind;
89
+ }
90
+ /** Hub wiring after `records.forOwner('cluster-agent').declare(...)`. */
91
+ bindRecordsKind(resolver) {
92
+ this.resolveKind = resolver;
89
93
  }
90
94
  /**
91
95
  * Idempotently declare the typed collection. Returns the resolved provider
@@ -93,6 +97,8 @@ class ClusterNodeHistoryStore {
93
97
  * unreachable) — callers treat null as "skip, best-effort".
94
98
  */
95
99
  async ensureDeclared() {
100
+ if (this.resolveKind() !== null)
101
+ return this.resolveSettingsStore();
96
102
  const store = this.resolveSettingsStore();
97
103
  if (!store)
98
104
  return null;
@@ -112,7 +118,7 @@ class ClusterNodeHistoryStore {
112
118
  }
113
119
  catch (err) {
114
120
  this.logger.warn('declareCollection failed (best-effort)', {
115
- meta: { error: (0, types_1.errMsg)(err) },
121
+ meta: { error: errMsg(err) },
116
122
  });
117
123
  return null;
118
124
  }
@@ -143,21 +149,17 @@ class ClusterNodeHistoryStore {
143
149
  // Carry the package roster forward. `listNodes()` does not resolve it
144
150
  // (only the reconcile does), so writing this descriptor blind would erase
145
151
  // the back-fill's intended set on the very next topology poll.
146
- const existing = await this.readRow(store, descriptor.id);
152
+ const existing = await this.readStored(descriptor.id);
147
153
  const packages = descriptor.packages ?? existing?.descriptor.packages;
148
154
  const next = packages === undefined ? descriptor : { ...descriptor, packages };
149
155
  if (existing !== null && !this.worthWriting(existing, next))
150
156
  return;
151
- await store.set({
152
- collection: COLLECTION,
153
- key: descriptor.id,
154
- value: { lastActive: Date.now(), descriptor: next },
155
- });
157
+ await this.writeStored(descriptor.id, Date.now(), next);
156
158
  }
157
159
  catch (err) {
158
160
  this.logger.warn('snapshot upsert failed (best-effort)', {
159
161
  tags: { nodeId: descriptor.id },
160
- meta: { error: (0, types_1.errMsg)(err) },
162
+ meta: { error: errMsg(err) },
161
163
  });
162
164
  }
163
165
  }
@@ -172,13 +174,48 @@ class ClusterNodeHistoryStore {
172
174
  return !descriptorsEqual(existing.descriptor, next);
173
175
  }
174
176
  /** Read one node's row, validated. `null` when absent or malformed. */
175
- async readRow(store, nodeId) {
177
+ async readStored(nodeId) {
178
+ const kind = this.resolveKind();
179
+ if (kind !== null) {
180
+ const row = await kind.get(nodeId);
181
+ if (row === null)
182
+ return null;
183
+ const parsed = RowDataSchema.safeParse({
184
+ lastActive: row.at ?? 0,
185
+ descriptor: row.data.descriptor,
186
+ });
187
+ return parsed.success ? parsed.data : null;
188
+ }
189
+ const store = this.resolveSettingsStore();
190
+ if (!store)
191
+ return null;
192
+ return this.readRowLegacy(store, nodeId);
193
+ }
194
+ async readRowLegacy(store, nodeId) {
176
195
  const raw = await store.get({ collection: COLLECTION, key: nodeId });
177
196
  if (raw === null || raw === undefined)
178
197
  return null;
179
198
  const parsed = RowDataSchema.safeParse(raw);
180
199
  return parsed.success ? parsed.data : null;
181
200
  }
201
+ async writeStored(nodeId, lastActive, descriptor) {
202
+ const kind = this.resolveKind();
203
+ if (kind !== null) {
204
+ const body = ClusterNodeHistoryBodySchema.safeParse({ descriptor });
205
+ if (!body.success)
206
+ return;
207
+ await kind.put({ id: nodeId, at: lastActive, data: body.data });
208
+ return;
209
+ }
210
+ const store = this.resolveSettingsStore();
211
+ if (!store)
212
+ return;
213
+ await store.set({
214
+ collection: COLLECTION,
215
+ key: nodeId,
216
+ value: { lastActive, descriptor },
217
+ });
218
+ }
182
219
  /** A placeholder descriptor for a node the topology pass has not seen yet. */
183
220
  static placeholderDescriptor(nodeId) {
184
221
  return {
@@ -206,12 +243,12 @@ class ClusterNodeHistoryStore {
206
243
  if (!store)
207
244
  return [];
208
245
  try {
209
- return (await this.readRow(store, nodeId))?.descriptor.packages ?? [];
246
+ return (await this.readStored(nodeId))?.descriptor.packages ?? [];
210
247
  }
211
248
  catch (err) {
212
249
  this.logger.warn('getPackages failed (best-effort)', {
213
250
  tags: { nodeId },
214
- meta: { error: (0, types_1.errMsg)(err) },
251
+ meta: { error: errMsg(err) },
215
252
  });
216
253
  return [];
217
254
  }
@@ -231,7 +268,7 @@ class ClusterNodeHistoryStore {
231
268
  if (!store)
232
269
  return;
233
270
  try {
234
- const existing = await this.readRow(store, nodeId);
271
+ const existing = await this.readStored(nodeId);
235
272
  const merged = new Map((existing?.descriptor.packages ?? []).map((p) => [p.name, p]));
236
273
  // The node's current declaration wins on version — it is the authority on
237
274
  // what it is actually running.
@@ -241,16 +278,12 @@ class ClusterNodeHistoryStore {
241
278
  ...(existing?.descriptor ?? ClusterNodeHistoryStore.placeholderDescriptor(nodeId)),
242
279
  packages: [...merged.values()],
243
280
  };
244
- await store.set({
245
- collection: COLLECTION,
246
- key: nodeId,
247
- value: { lastActive: existing?.lastActive ?? Date.now(), descriptor },
248
- });
281
+ await this.writeStored(nodeId, existing?.lastActive ?? Date.now(), descriptor);
249
282
  }
250
283
  catch (err) {
251
284
  this.logger.warn('recordPackages failed (best-effort)', {
252
285
  tags: { nodeId },
253
- meta: { error: (0, types_1.errMsg)(err) },
286
+ meta: { error: errMsg(err) },
254
287
  });
255
288
  }
256
289
  }
@@ -266,7 +299,7 @@ class ClusterNodeHistoryStore {
266
299
  if (!store)
267
300
  return;
268
301
  try {
269
- const existing = await this.readRow(store, nodeId);
302
+ const existing = await this.readStored(nodeId);
270
303
  if (existing === null)
271
304
  return;
272
305
  const current = existing.descriptor.packages;
@@ -276,13 +309,9 @@ class ClusterNodeHistoryStore {
276
309
  const remaining = current.filter((p) => !drop.has(p.name));
277
310
  if (remaining.length === current.length)
278
311
  return;
279
- await store.set({
280
- collection: COLLECTION,
281
- key: nodeId,
282
- value: {
283
- lastActive: existing.lastActive,
284
- descriptor: { ...existing.descriptor, packages: remaining },
285
- },
312
+ await this.writeStored(nodeId, existing.lastActive, {
313
+ ...existing.descriptor,
314
+ packages: remaining,
286
315
  });
287
316
  this.logger.info('pruned node package record', {
288
317
  tags: { nodeId },
@@ -292,7 +321,7 @@ class ClusterNodeHistoryStore {
292
321
  catch (err) {
293
322
  this.logger.warn('prunePackages failed (best-effort)', {
294
323
  tags: { nodeId },
295
- meta: { error: (0, types_1.errMsg)(err) },
324
+ meta: { error: errMsg(err) },
296
325
  });
297
326
  }
298
327
  }
@@ -306,6 +335,18 @@ class ClusterNodeHistoryStore {
306
335
  if (!store)
307
336
  return;
308
337
  try {
338
+ const existing = await this.readStored(nodeId);
339
+ if (existing === null)
340
+ return;
341
+ const kind = this.resolveKind();
342
+ if (kind !== null) {
343
+ await kind.put({
344
+ id: nodeId,
345
+ at: Date.now(),
346
+ data: { descriptor: existing.descriptor },
347
+ });
348
+ return;
349
+ }
309
350
  await store.update({
310
351
  collection: COLLECTION,
311
352
  id: nodeId,
@@ -315,7 +356,7 @@ class ClusterNodeHistoryStore {
315
356
  catch (err) {
316
357
  this.logger.warn('touch failed (best-effort)', {
317
358
  tags: { nodeId },
318
- meta: { error: (0, types_1.errMsg)(err) },
359
+ meta: { error: errMsg(err) },
319
360
  });
320
361
  }
321
362
  }
@@ -335,8 +376,17 @@ class ClusterNodeHistoryStore {
335
376
  if (!store)
336
377
  return null;
337
378
  try {
338
- const rows = await store.query({ collection: COLLECTION });
379
+ const kind = this.resolveKind();
339
380
  const result = [];
381
+ const rows = kind !== null
382
+ ? (await readAllRows(kind)).map((row) => ({
383
+ id: row.id,
384
+ data: { lastActive: row.at ?? 0, descriptor: row.data.descriptor },
385
+ }))
386
+ : (await store.query({ collection: COLLECTION })).map((row) => ({
387
+ id: row.id,
388
+ data: row.data,
389
+ }));
340
390
  for (const row of rows) {
341
391
  const parsed = RowDataSchema.safeParse(row.data);
342
392
  if (!parsed.success) {
@@ -350,7 +400,7 @@ class ClusterNodeHistoryStore {
350
400
  return result;
351
401
  }
352
402
  catch (err) {
353
- this.logger.warn('history read failed (best-effort)', { meta: { error: (0, types_1.errMsg)(err) } });
403
+ this.logger.warn('history read failed (best-effort)', { meta: { error: errMsg(err) } });
354
404
  return null;
355
405
  }
356
406
  }
@@ -370,8 +420,14 @@ class ClusterNodeHistoryStore {
370
420
  // Read first: `delete` on this provider is idempotent and cannot tell a
371
421
  // removal from a no-op, and "there was nothing to remove" is the answer
372
422
  // that stops an operator repeating a working action forever.
373
- const existed = (await this.readRow(store, nodeId)) !== null;
374
- await store.delete({ collection: COLLECTION, key: nodeId });
423
+ const existed = (await this.readStored(nodeId)) !== null;
424
+ const kind = this.resolveKind();
425
+ if (kind !== null) {
426
+ await kind.delete(nodeId);
427
+ }
428
+ else {
429
+ await store.delete({ collection: COLLECTION, key: nodeId });
430
+ }
375
431
  if (!existed) {
376
432
  this.logger.info('cluster node had no history row to forget', { tags: { nodeId } });
377
433
  return 'not-found';
@@ -382,10 +438,9 @@ class ClusterNodeHistoryStore {
382
438
  catch (err) {
383
439
  this.logger.warn('forget failed (best-effort)', {
384
440
  tags: { nodeId },
385
- meta: { error: (0, types_1.errMsg)(err) },
441
+ meta: { error: errMsg(err) },
386
442
  });
387
443
  return 'failed';
388
444
  }
389
445
  }
390
446
  }
391
- exports.ClusterNodeHistoryStore = ClusterNodeHistoryStore;
@@ -1,12 +1,9 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.HubAgentPairing = void 0;
4
1
  /** A browse takes seconds; a list asked within this window reuses the last scan. */
5
2
  const SCAN_REUSE_MS = 4_000;
6
3
  /** A typed address is remembered this long without being heard again. */
7
4
  const ADDRESS_MEMORY_MS = 30 * 60_000;
8
5
  const DEFAULT_PORT = 4444;
9
- class HubAgentPairing {
6
+ export class HubAgentPairing {
10
7
  deps;
11
8
  scanned = null;
12
9
  scanning = null;
@@ -120,4 +117,3 @@ class HubAgentPairing {
120
117
  };
121
118
  }
122
119
  }
123
- exports.HubAgentPairing = HubAgentPairing;
@@ -1,6 +1,3 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createNodeCertificatesClient = createNodeCertificatesClient;
4
1
  /**
5
2
  * The hub's typed handle on a node's `node-certificates` capability (D856).
6
3
  *
@@ -9,8 +6,8 @@ exports.createNodeCertificatesClient = createNodeCertificatesClient;
9
6
  * offline, capability not declared by an old agent) or a malformed answer becomes
10
7
  * a plain error naming the node - never a cast.
11
8
  */
12
- const types_1 = require("@camstack/types");
13
- function createNodeCertificatesClient(moleculer, nodeId) {
9
+ import { nodeCertificatesCapability } from '@camstack/types';
10
+ export function createNodeCertificatesClient(moleculer, nodeId) {
14
11
  const proxy = moleculer?.createCapabilityProxy('node-certificates', nodeId) ?? null;
15
12
  if (proxy === null)
16
13
  return null;
@@ -25,7 +22,7 @@ function createNodeCertificatesClient(moleculer, nodeId) {
25
22
  }
26
23
  return parsed.data;
27
24
  };
28
- const m = types_1.nodeCertificatesCapability.methods;
25
+ const m = nodeCertificatesCapability.methods;
29
26
  return {
30
27
  getCertificates: () => call('getCertificates', m.getCertificates.output, {}),
31
28
  prepareMeshRenewal: () => call('prepareMeshRenewal', m.prepareMeshRenewal.output, {}),
@@ -1,6 +1,3 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.toNodeDirectory = toNodeDirectory;
4
1
  /**
5
2
  * The cheap node list (D637): live liveness plus the durable history, merged.
6
3
  *
@@ -11,7 +8,7 @@ exports.toNodeDirectory = toNodeDirectory;
11
8
  * - `history === null` = unreadable, so the answer is INCOMPLETE and a picker
12
9
  * must not call a missing id removed (D315).
13
10
  */
14
- function toNodeDirectory(live, history) {
11
+ export function toNodeDirectory(live, history) {
15
12
  const rows = history ?? [];
16
13
  const names = new Map(rows.map((row) => [row.id, row.name]));
17
14
  const hubs = new Set(rows.filter((row) => row.isHub).map((row) => row.id));
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  /**
3
2
  * well-known-app-links — the two files a Universal/App Link needs the DOMAIN
4
3
  * to vouch for.
@@ -19,16 +18,13 @@
19
18
  * ACCEPTED and produces a valid file that fails auto-verification (the OS
20
19
  * shows a disambiguation dialog): same trade-off the Zentik file ships with.
21
20
  */
22
- Object.defineProperty(exports, "__esModule", { value: true });
23
- exports.buildAppLinkFiles = buildAppLinkFiles;
24
- exports.parseCertFingerprints = parseCertFingerprints;
25
21
  /** Apple team + bundle ids, mirrored from the viewer's app.config.ts. */
26
22
  const APPLE_TEAM_ID = 'C3F24V5NS5';
27
23
  const BUNDLE_ID = 'com.apocaliss92.camstack';
28
24
  const BUNDLE_ID_DEV = 'com.apocaliss92.camstack.dev';
29
25
  /** The only path family the app claims on this domain. */
30
26
  const VIEWER_COMPONENT = '/viewer/camstack/*';
31
- function buildAppLinkFiles(androidCertSha256) {
27
+ export function buildAppLinkFiles(androidCertSha256) {
32
28
  const appIds = [`${APPLE_TEAM_ID}.${BUNDLE_ID}`, `${APPLE_TEAM_ID}.${BUNDLE_ID_DEV}`];
33
29
  return {
34
30
  appleAppSiteAssociation: {
@@ -56,7 +52,7 @@ function buildAppLinkFiles(androidCertSha256) {
56
52
  };
57
53
  }
58
54
  /** Parse the comma-separated env form; junk and empties dropped. */
59
- function parseCertFingerprints(raw) {
55
+ export function parseCertFingerprints(raw) {
60
56
  if (raw === undefined)
61
57
  return [];
62
58
  return raw
@@ -1,13 +1,10 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AuthService = exports.SessionRevokedError = void 0;
4
- const system_1 = require("@camstack/system");
1
+ import { AuthManager } from '@camstack/system';
5
2
  /**
6
3
  * A session-grade token whose server-side session is gone (logged out,
7
4
  * revoked, expired) or cannot be checked right now. Every caller of
8
5
  * `verifyToken` already treats a throw as "not authenticated".
9
6
  */
10
- class SessionRevokedError extends Error {
7
+ export class SessionRevokedError extends Error {
11
8
  reason;
12
9
  constructor(reason) {
13
10
  super(`Session is no longer valid (${reason})`);
@@ -15,14 +12,13 @@ class SessionRevokedError extends Error {
15
12
  this.name = 'SessionRevokedError';
16
13
  }
17
14
  }
18
- exports.SessionRevokedError = SessionRevokedError;
19
15
  /** A v2 session token: string `userId`, boolean `isAdmin`, no `kind` (not a bridge/challenge). */
20
16
  function isSessionGrade(payload) {
21
17
  return (Reflect.get(payload, 'kind') === undefined &&
22
18
  typeof payload.userId === 'string' &&
23
19
  typeof payload.isAdmin === 'boolean');
24
20
  }
25
- class AuthService extends system_1.AuthManager {
21
+ export class AuthService extends AuthManager {
26
22
  sessionCheck = null;
27
23
  /**
28
24
  * Wire the login-session check (`hub-sessions.ts`). From then on EVERY
@@ -53,4 +49,3 @@ class AuthService extends system_1.AuthManager {
53
49
  return payload;
54
50
  }
55
51
  }
56
- exports.AuthService = AuthService;
@@ -1,41 +1,4 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.HandoffCodeService = exports.HANDOFF_CODE_MAX_PENDING = exports.HANDOFF_CODE_TTL_MS = exports.HANDOFF_CODE_PREFIX = void 0;
37
- exports.pkceChallenge = pkceChallenge;
38
- const types_1 = require("@camstack/types");
1
+ import { userError } from '@camstack/types';
39
2
  /**
40
3
  * HandoffCodeService — one-time login handoff codes for the native-app
41
4
  * auth handoff (viewer "Sign in with CamStack").
@@ -59,26 +22,26 @@ const types_1 = require("@camstack/types");
59
22
  * (the browser just re-runs the handoff), and a bounded store +
60
23
  * prune-on-mint keeps the map from growing.
61
24
  */
62
- const crypto = __importStar(require("node:crypto"));
25
+ import * as crypto from 'node:crypto';
63
26
  /** Wire prefix — `chc_` = CamStack Handoff Code (cf. `cst_`/`csv_`). */
64
- exports.HANDOFF_CODE_PREFIX = 'chc_';
65
- exports.HANDOFF_CODE_TTL_MS = 60_000;
27
+ export const HANDOFF_CODE_PREFIX = 'chc_';
28
+ export const HANDOFF_CODE_TTL_MS = 60_000;
66
29
  /** Hard bound on concurrently-pending codes (mint is auth-gated, so this
67
30
  * only guards against a runaway authenticated client). */
68
- exports.HANDOFF_CODE_MAX_PENDING = 1_000;
31
+ export const HANDOFF_CODE_MAX_PENDING = 1_000;
69
32
  /** RFC 7636 S256: `base64url(sha256(verifier))`. */
70
- function pkceChallenge(verifier) {
33
+ export function pkceChallenge(verifier) {
71
34
  return crypto.createHash('sha256').update(verifier).digest('base64url');
72
35
  }
73
36
  function hashCode(code) {
74
37
  return crypto.createHash('sha256').update(code).digest('hex');
75
38
  }
76
- class HandoffCodeService {
39
+ export class HandoffCodeService {
77
40
  now;
78
41
  ttlMs;
79
42
  /** Keyed by SHA-256(raw code). */
80
43
  pending = new Map();
81
- constructor(now = Date.now, ttlMs = exports.HANDOFF_CODE_TTL_MS) {
44
+ constructor(now = Date.now, ttlMs = HANDOFF_CODE_TTL_MS) {
82
45
  this.now = now;
83
46
  this.ttlMs = ttlMs;
84
47
  }
@@ -87,10 +50,10 @@ class HandoffCodeService {
87
50
  * legitimate flow never has anywhere near this many in flight). */
88
51
  create(userId, options = {}) {
89
52
  this.prune();
90
- if (this.pending.size >= exports.HANDOFF_CODE_MAX_PENDING) {
91
- throw (0, types_1.userError)('server.handoff-busy', undefined, 'Too many pending handoff codes — try again shortly');
53
+ if (this.pending.size >= HANDOFF_CODE_MAX_PENDING) {
54
+ throw userError('server.handoff-busy', undefined, 'Too many pending handoff codes — try again shortly');
92
55
  }
93
- const code = `${exports.HANDOFF_CODE_PREFIX}${crypto.randomBytes(32).toString('hex')}`;
56
+ const code = `${HANDOFF_CODE_PREFIX}${crypto.randomBytes(32).toString('hex')}`;
94
57
  const expiresAt = this.now() + this.ttlMs;
95
58
  this.pending.set(hashCode(code), {
96
59
  userId,
@@ -144,4 +107,3 @@ class HandoffCodeService {
144
107
  }
145
108
  }
146
109
  }
147
- exports.HandoffCodeService = HandoffCodeService;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Record kinds owned by `core-auth` (hub-resident, phase 6 / §2.8).
3
+ */
4
+ import { defineRecordKinds, SHARE_VIEW_KINDS } from '@camstack/types';
5
+ import { z } from 'zod';
6
+ const ShareTokenScopeSchema = z.object({
7
+ kind: z.enum(SHARE_VIEW_KINDS),
8
+ deviceIds: z.array(z.number().int().nonnegative()).min(1).max(64),
9
+ talk: z.boolean().optional(),
10
+ });
11
+ export const SHARE_VIEW_TOKENS_LEGACY = 'share_view_tokens';
12
+ const ShareViewTokenBodySchema = z.object({
13
+ userId: z.string(),
14
+ tokenHash: z.string(),
15
+ tokenPrefix: z.string(),
16
+ scope: ShareTokenScopeSchema,
17
+ createdAt: z.number(),
18
+ expiresAt: z.number().nullable(),
19
+ lastUsedAt: z.number().nullish(),
20
+ });
21
+ export const coreAuthRecordKinds = defineRecordKinds({
22
+ 'share-view-tokens': {
23
+ schema: ShareViewTokenBodySchema,
24
+ class: 'config',
25
+ writeTrigger: 'operator mints a share link; validate touches lastUsedAt',
26
+ device: 'none',
27
+ at: 'none',
28
+ indexes: [
29
+ { name: 'hash', fields: ['tokenHash'], unique: true },
30
+ { name: 'user', fields: ['userId'] },
31
+ ],
32
+ retention: { none: 'revoke only; expiry enforced at validate' },
33
+ adoptsFrom: SHARE_VIEW_TOKENS_LEGACY,
34
+ },
35
+ });