@camstack/server 1.0.1 → 1.0.3

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 (39) hide show
  1. package/dist/api/addon-upload.js +17 -3
  2. package/dist/api/bridge-addons.router.js +1 -1
  3. package/dist/api/capabilities.router.js +3 -3
  4. package/dist/api/core/cap-providers.js +3 -3
  5. package/dist/api/core/logs.router.js +1 -1
  6. package/dist/api/core/notifications.router.js +1 -1
  7. package/dist/api/core/repl.router.js +1 -1
  8. package/dist/api/health/health.routes.js +7 -2
  9. package/dist/api/trpc/cap-route-error-formatter.js +3 -3
  10. package/dist/api/trpc/core-cap-bridge.js +2 -2
  11. package/dist/api/trpc/generated-cap-routers.js +4 -4
  12. package/dist/boot/boot-config.js +2 -2
  13. package/dist/boot/post-boot.service.js +2 -2
  14. package/dist/core/addon/addon-call-gateway.js +1 -1
  15. package/dist/core/addon/addon-package.service.js +37 -43
  16. package/dist/core/addon/addon-registry.service.js +67 -52
  17. package/dist/core/addon-bridge/addon-bridge.service.js +6 -6
  18. package/dist/core/addon-pages/addon-pages.service.js +1 -1
  19. package/dist/core/auth/auth.service.js +2 -2
  20. package/dist/core/config/config.schema.js +4 -4
  21. package/dist/core/config/config.service.js +2 -2
  22. package/dist/core/events/event-bus.service.js +2 -2
  23. package/dist/core/feature/feature.service.js +2 -2
  24. package/dist/core/lifecycle/lifecycle-state-machine.js +3 -3
  25. package/dist/core/logging/log-ring-buffer.js +3 -3
  26. package/dist/core/logging/logging.service.js +3 -3
  27. package/dist/core/logging/scoped-logger.js +3 -3
  28. package/dist/core/moleculer/cap-route-authority.js +2 -2
  29. package/dist/core/moleculer/moleculer.service.js +29 -23
  30. package/dist/core/network/network-quality.service.js +2 -2
  31. package/dist/core/notification/notification-wrapper.service.js +2 -2
  32. package/dist/core/notification/toast-wrapper.service.js +2 -2
  33. package/dist/core/repl/repl-engine.service.js +2 -2
  34. package/dist/core/storage/fs-storage-backend.js +3 -3
  35. package/dist/core/storage/storage-location-manager.js +3 -3
  36. package/dist/core/storage/storage.service.js +2 -2
  37. package/dist/launcher.js +23 -12
  38. package/dist/main.js +14 -5
  39. package/package.json +2 -3
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MoleculerService = void 0;
4
4
  exports.buildChildUdsManifest = buildChildUdsManifest;
5
- const kernel_1 = require("@camstack/kernel");
5
+ const system_1 = require("@camstack/system");
6
6
  const cap_call_fn_js_1 = require("./cap-call-fn.js");
7
7
  const cap_route_authority_js_1 = require("./cap-route-authority.js");
8
8
  const types_1 = require("@camstack/types");
@@ -23,7 +23,7 @@ class MoleculerService {
23
23
  * D3 authority: union of every node's manifest delivered via
24
24
  * `$hub.registerNode`. Populated by `onRegisterNode` in `hubDeps`.
25
25
  */
26
- nodeRegistry = new kernel_1.HubNodeRegistry();
26
+ nodeRegistry = new system_1.HubNodeRegistry();
27
27
  nodeCallFns = new Map();
28
28
  /**
29
29
  * D3: callback invoked whenever a bare-ID agent node completes the
@@ -107,7 +107,7 @@ class MoleculerService {
107
107
  // `no-unsafe-assignment`. Going via `unknown` documents the boundary.
108
108
  this.clusterSecret =
109
109
  process.env['CAMSTACK_CLUSTER_SECRET'] ?? this.config.get('cluster.secret');
110
- const broker = (0, kernel_1.createBroker)({
110
+ const broker = (0, system_1.createBroker)({
111
111
  nodeID: 'hub',
112
112
  mode: 'hub',
113
113
  logLevel: this.config.get('moleculer.logLevel') ?? 'warn',
@@ -182,12 +182,18 @@ class MoleculerService {
182
182
  this.removeNodeFromRegistry(nodeId);
183
183
  },
184
184
  expectedClusterSecretHash: this.clusterSecret
185
- ? (0, kernel_1.hashClusterSecret)(this.clusterSecret)
185
+ ? (0, system_1.hashClusterSecret)(this.clusterSecret)
186
186
  : undefined,
187
187
  };
188
- const hubService = (0, kernel_1.createHubService)(hubDeps);
188
+ const hubService = (0, system_1.createHubService)(hubDeps);
189
189
  this.brokerSafe.createService(hubService);
190
- const dataDir = this.config.get('dataDir') ?? 'camstack-data';
190
+ // Forked addon-runner children must root their storage (addons-data,
191
+ // the sqlite settings DB) under the SAME data path as the hub's main
192
+ // process. The configured key is `server.dataPath` (populated from the
193
+ // CAMSTACK_DATA env var); reading the non-existent `dataDir` key here
194
+ // made every child silently fall back to the relative `camstack-data`,
195
+ // so the DB escaped the mounted data dir in container deployments.
196
+ const dataDir = this.config.get('server.dataPath') ?? 'camstack-data';
191
197
  // UDS local transport: the hub hosts a LocalChildRegistry so its
192
198
  // forked addon-runners route cap calls directly over a Unix-domain
193
199
  // socket instead of through Moleculer. The broker stays available as
@@ -207,7 +213,7 @@ class MoleculerService {
207
213
  // capabilities the resolver can see. Before F0 this fell through
208
214
  // UDS_NO_ROUTE → the child's own brokerTransportLink; F1+F2 removes that
209
215
  // child broker, so the parent must own this path.
210
- const onUnownedCall = (0, kernel_1.createParentUnownedCallHandler)({
216
+ const onUnownedCall = (0, system_1.createParentUnownedCallHandler)({
211
217
  getResolver: () => this.resolver,
212
218
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- moleculer types unresolvable; see `broker` getter docstring
213
219
  broker: this.broker,
@@ -233,8 +239,8 @@ class MoleculerService {
233
239
  : undefined),
234
240
  },
235
241
  });
236
- const registry = new kernel_1.LocalChildRegistry({
237
- server: (0, kernel_1.createLocalTransport)().createServer(nodeId),
242
+ const registry = new system_1.LocalChildRegistry({
243
+ server: (0, system_1.createLocalTransport)().createServer(nodeId),
238
244
  onUnownedCall,
239
245
  logger: {
240
246
  info: (msg, meta) => logger.info(msg, meta !== null && meta !== undefined
@@ -278,7 +284,7 @@ class MoleculerService {
278
284
  // This runs in PARALLEL with the existing $hub.log / onLog broker path —
279
285
  // both stay active until Phase F removes the broker path.
280
286
  registry.onChildLog((childId, entry) => {
281
- this.logging.writeFromWorker((0, kernel_1.udsChildLogToWorkerEntry)(childId, entry));
287
+ this.logging.writeFromWorker((0, system_1.udsChildLogToWorkerEntry)(childId, entry));
282
288
  });
283
289
  // D1: answer readiness-snapshot requests from UDS children so they can
284
290
  // hydrate without a `$readiness.getSnapshot` Moleculer call.
@@ -289,7 +295,7 @@ class MoleculerService {
289
295
  // Keep `$readiness.getSnapshot` intact — Phase F removes it.
290
296
  registry.onReadinessSnapshotRequest(() => this.readinessRegistry.getSnapshotForTransport());
291
297
  this.localChildRegistry = registry;
292
- parentUdsPath = (0, kernel_1.localEndpointPath)(nodeId);
298
+ parentUdsPath = (0, system_1.localEndpointPath)(nodeId);
293
299
  logger.info('UDS child registry listening', { meta: { path: parentUdsPath } });
294
300
  }
295
301
  catch (err) {
@@ -297,7 +303,7 @@ class MoleculerService {
297
303
  meta: { err: err instanceof Error ? err.message : String(err) },
298
304
  });
299
305
  }
300
- const processService = (0, kernel_1.createProcessService)(this.brokerSafe.nodeID, dataDir, undefined, undefined, parentUdsPath);
306
+ const processService = (0, system_1.createProcessService)(this.brokerSafe.nodeID, dataDir, undefined, undefined, parentUdsPath);
301
307
  this.brokerSafe.createService(processService);
302
308
  // $addonHost — REMOVED (Sprint 6). Three-level settings are now
303
309
  // served by the `addon-settings` singleton capability. Per-addon
@@ -313,19 +319,19 @@ class MoleculerService {
313
319
  // handshake, not dynamically after post-start `createService()`.
314
320
  // Without this, cross-node broadcasts (camstack.evt.<category>) would
315
321
  // arrive unreliably for the first ~10s after each node joins.
316
- (0, kernel_1.registerEventBusService)(this.broker);
322
+ (0, system_1.registerEventBusService)(this.broker);
317
323
  // Register the hub-authoritative `$readiness.getSnapshot` service
318
324
  // BEFORE broker.start() so workers / agents see it in their initial
319
325
  // INFO packet — post-start `createService` calls propagate via
320
326
  // heartbeat (several seconds) and would force workers to poll.
321
- this.brokerSafe.createService((0, kernel_1.createReadinessServiceForRegistry)(this.readinessRegistry));
327
+ this.brokerSafe.createService((0, system_1.createReadinessServiceForRegistry)(this.readinessRegistry));
322
328
  // Register the hub-authoritative `$stream-probe` service —
323
329
  // workers route RTSP probe + field-probe through this action when
324
330
  // the tRPC WSS link isn't available (default path for forked
325
331
  // workers). Keeps ffprobe + HTTP-reachability as a single
326
332
  // hub-side implementation; see `createStreamProbeBrokerService`
327
333
  // for the shape.
328
- this.brokerSafe.createService((0, kernel_1.createStreamProbeBrokerService)({
334
+ this.brokerSafe.createService((0, system_1.createStreamProbeBrokerService)({
329
335
  probe: (url, options) => this.streamProbe.probe(url, options),
330
336
  probeField: (key, value) => this.streamProbe.probeField(key, value),
331
337
  }));
@@ -334,7 +340,7 @@ class MoleculerService {
334
340
  // returns the backend list for whichever host the caller targets.
335
341
  // Admin UI uses this to show per-agent hwaccel info on the
336
342
  // pipeline / NodeDetail pages.
337
- this.brokerSafe.createService((0, kernel_1.createHwAccelService)((0, kernel_1.createKernelHwAccel)()));
343
+ this.brokerSafe.createService((0, system_1.createHwAccelService)((0, system_1.createKernelHwAccel)()));
338
344
  await this.brokerSafe.start();
339
345
  logger.info('Moleculer broker started (TCP transport)');
340
346
  // Construct the CapRouteResolver now that both the broker and
@@ -343,7 +349,7 @@ class MoleculerService {
343
349
  // children connecting/disconnecting after this point are picked up
344
350
  // correctly. The localChildRegistry reference is captured and may be
345
351
  // null if UDS failed to start.
346
- this.resolver = new kernel_1.CapRouteResolver({
352
+ this.resolver = new system_1.CapRouteResolver({
347
353
  hubNodeId: this.brokerSafe.nodeID,
348
354
  broker: this.brokerSafe,
349
355
  hubLocalRegistry: this.localChildRegistry,
@@ -370,7 +376,7 @@ class MoleculerService {
370
376
  // shared broker bus and broker.broadcast is live.
371
377
  if (this.localChildRegistry !== null) {
372
378
  const hubNodeId = this.brokerSafe.nodeID;
373
- this.udsEventBridgeDispose = (0, kernel_1.createUdsEventBridge)({
379
+ this.udsEventBridgeDispose = (0, system_1.createUdsEventBridge)({
374
380
  registry: this.localChildRegistry,
375
381
  parentBus: this.eventBus,
376
382
  parentNodeId: hubNodeId,
@@ -447,7 +453,7 @@ class MoleculerService {
447
453
  return await resolver.dispatch(route, methodName, params);
448
454
  }
449
455
  catch (err) {
450
- if (err instanceof kernel_1.CapRouteError &&
456
+ if (err instanceof system_1.CapRouteError &&
451
457
  (err.reason === 'no-provider' || err.reason === 'node-offline')) {
452
458
  // Resolver couldn't find the cap — try the legacy callFn store as a
453
459
  // fallback. This covers caps registered in nodeCallFns (e.g. agent
@@ -482,7 +488,7 @@ class MoleculerService {
482
488
  if (callFn) {
483
489
  return callFn(methodName, params);
484
490
  }
485
- throw new kernel_1.CapRouteError(capabilityName, methodName, {
491
+ throw new system_1.CapRouteError(capabilityName, methodName, {
486
492
  reason: 'no-provider',
487
493
  nodeId,
488
494
  rejected: [
@@ -562,7 +568,7 @@ class MoleculerService {
562
568
  for (const addon of manifest) {
563
569
  const registryKey = registryKeyFor(addon.addonId);
564
570
  for (const capName of addon.capabilities) {
565
- if ((0, kernel_1.isInfraCapability)(capName))
571
+ if ((0, system_1.isInfraCapability)(capName))
566
572
  continue;
567
573
  const capDef = registry.getDefinition(capName);
568
574
  if (!capDef)
@@ -614,7 +620,7 @@ class MoleculerService {
614
620
  udsChildId,
615
621
  getLocalChildRegistry: () => this.localChildRegistry,
616
622
  getResolver: () => this.resolver,
617
- legacyBrokerCall: (method, methodParams, targetNode) => (0, kernel_1.callWithServiceDiscovery)(this.brokerSafe, addonId, (0, kernel_1.capActionName)(addonId, capName, method, false), (0, kernel_1.serializeTypedArrays)(methodParams), { nodeID: targetNode, timeout: 60_000 }),
623
+ legacyBrokerCall: (method, methodParams, targetNode) => (0, system_1.callWithServiceDiscovery)(this.brokerSafe, addonId, (0, system_1.capActionName)(addonId, capName, method, false), (0, system_1.serializeTypedArrays)(methodParams), { nodeID: targetNode, timeout: 60_000 }),
618
624
  onUdsRoute: (cap) => {
619
625
  if (!this.udsRoutedCaps.has(cap)) {
620
626
  this.udsRoutedCaps.add(cap);
@@ -778,7 +784,7 @@ class MoleculerService {
778
784
  // Resolver found a route — proxy is reachable.
779
785
  }
780
786
  catch (err) {
781
- if (err instanceof kernel_1.CapRouteError &&
787
+ if (err instanceof system_1.CapRouteError &&
782
788
  (err.reason === 'no-provider' || err.reason === 'node-offline')) {
783
789
  // Check legacy callFn store and hub-local child fallbacks.
784
790
  if (!this.isReachableViaLegacy(nodeId, capabilityName))
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.NetworkQualityService = void 0;
4
- const core_1 = require("@camstack/core");
5
- class NetworkQualityService extends core_1.NetworkQualityTracker {
4
+ const system_1 = require("@camstack/system");
5
+ class NetworkQualityService extends system_1.NetworkQualityTracker {
6
6
  }
7
7
  exports.NetworkQualityService = NetworkQualityService;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.NotificationServiceWrapper = void 0;
4
- const core_1 = require("@camstack/core");
4
+ const system_1 = require("@camstack/system");
5
5
  /**
6
6
  * NestJS-injectable wrapper around the core NotificationService.
7
7
  *
@@ -18,7 +18,7 @@ class NotificationServiceWrapper {
18
18
  }
19
19
  get service() {
20
20
  if (!this._service) {
21
- this._service = new core_1.NotificationService(this.logging.createLogger('notifications'));
21
+ this._service = new system_1.NotificationService(this.logging.createLogger('notifications'));
22
22
  const registry = this.caps.getRegistry();
23
23
  if (registry) {
24
24
  this._service.setRegistry(registry);
@@ -1,14 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ToastServiceWrapper = void 0;
4
- const core_1 = require("@camstack/core");
4
+ const system_1 = require("@camstack/system");
5
5
  /**
6
6
  * NestJS-injectable wrapper around the core ToastService.
7
7
  *
8
8
  * Provides toast broadcasting to connected UI clients.
9
9
  */
10
10
  class ToastServiceWrapper {
11
- _service = new core_1.ToastService();
11
+ _service = new system_1.ToastService();
12
12
  get service() {
13
13
  return this._service;
14
14
  }
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ReplEngineService = void 0;
4
- const core_1 = require("@camstack/core");
4
+ const system_1 = require("@camstack/system");
5
5
  const types_1 = require("@camstack/types");
6
- class ReplEngineService extends core_1.ReplEngine {
6
+ class ReplEngineService extends system_1.ReplEngine {
7
7
  /**
8
8
  * Lazily-instantiated `SystemMirror` shared across REPL sessions.
9
9
  * Holds a single warm-boot mirror that every `sm.getDeviceById(id)`
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FsStorageBackend = void 0;
4
- // Re-export from @camstack/core
5
- var core_1 = require("@camstack/core");
6
- Object.defineProperty(exports, "FsStorageBackend", { enumerable: true, get: function () { return core_1.FsStorageBackend; } });
4
+ // Re-export from @camstack/system
5
+ var system_1 = require("@camstack/system");
6
+ Object.defineProperty(exports, "FsStorageBackend", { enumerable: true, get: function () { return system_1.FsStorageBackend; } });
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.StorageLocationManager = void 0;
4
- // Re-export from @camstack/core
5
- var core_1 = require("@camstack/core");
6
- Object.defineProperty(exports, "StorageLocationManager", { enumerable: true, get: function () { return core_1.StorageLocationManager; } });
4
+ // Re-export from @camstack/system
5
+ var system_1 = require("@camstack/system");
6
+ Object.defineProperty(exports, "StorageLocationManager", { enumerable: true, get: function () { return system_1.StorageLocationManager; } });
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.StorageService = void 0;
4
- const core_1 = require("@camstack/core");
5
- class StorageService extends core_1.StorageManager {
4
+ const system_1 = require("@camstack/system");
5
+ class StorageService extends system_1.StorageManager {
6
6
  }
7
7
  exports.StorageService = StorageService;
package/dist/launcher.js CHANGED
@@ -36,18 +36,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  /**
37
37
  * Launcher -- entry point that ensures required addons are installed
38
38
  * before main.ts loads. This solves the chicken-and-egg problem:
39
- * main.ts has static imports from @camstack/core, but core lives in
39
+ * main.ts has static imports from @camstack/system, but core lives in
40
40
  * data/addons/ and may not exist on first boot.
41
41
  *
42
42
  * 1. Run AddonInstaller.ensureRequiredPackages (zero core dependencies)
43
- * 2. Create symlinks so @camstack/core resolves from data/addons/
44
- * 3. Dynamically import main.ts (which has static @camstack/core imports)
43
+ * 2. Create symlinks so @camstack/system resolves from data/addons/
44
+ * 3. Dynamically import main.ts (which has static @camstack/system imports)
45
45
  */
46
46
  const fs = __importStar(require("node:fs"));
47
47
  const path = __importStar(require("node:path"));
48
48
  const tar = __importStar(require("tar"));
49
49
  const yaml = __importStar(require("js-yaml"));
50
- const kernel_1 = require("@camstack/kernel");
50
+ const system_1 = require("@camstack/system");
51
51
  /** Path of the manifest file embedded inside every archive. */
52
52
  const ARCHIVE_MANIFEST_NAME = '.camstack-backup-manifest.json';
53
53
  /** Resolve the data directory from env or default */
@@ -135,12 +135,17 @@ function parseInstallSource(value) {
135
135
  /**
136
136
  * Locate + parse `config.yaml` relative to the data dir. Returns the
137
137
  * raw object on success, `null` when missing or unparseable. The
138
- * launcher uses this BEFORE @camstack/core is imported so it must stay
138
+ * launcher uses this BEFORE @camstack/system is imported so it must stay
139
139
  * free of core deps — just js-yaml + the kernel's bootstrapSchema for
140
140
  * shape validation by the call site.
141
141
  */
142
142
  function readConfigYaml(dataDir) {
143
+ // CONFIG_PATH (when set) is the authoritative location and must win — it
144
+ // is what main.ts reads/writes. Without this the launcher would miss the
145
+ // `bootstrap.*` section of a relocated config.yaml (e.g. a separate
146
+ // /config mount) and silently fall back to defaults.
143
147
  const candidates = [
148
+ ...(process.env.CONFIG_PATH ? [path.resolve(process.env.CONFIG_PATH)] : []),
144
149
  path.resolve(dataDir, '..', 'config.yaml'),
145
150
  path.resolve(dataDir, 'config.yaml'),
146
151
  path.resolve(process.cwd(), 'config.yaml'),
@@ -169,7 +174,7 @@ function readBootstrapInstallSource(dataDir) {
169
174
  const raw = readConfigYaml(dataDir);
170
175
  if (raw === null)
171
176
  return undefined;
172
- const validation = kernel_1.bootstrapSchema.safeParse(raw);
177
+ const validation = system_1.bootstrapSchema.safeParse(raw);
173
178
  if (!validation.success)
174
179
  return undefined;
175
180
  return parseInstallSource(validation.data.bootstrap.installSource);
@@ -181,7 +186,7 @@ function readBootstrapInstallSource(dataDir) {
181
186
  * kernel's REQUIRED_PACKAGES constant).
182
187
  *
183
188
  * Inline YAML parse rather than going through ConfigManager: the
184
- * launcher runs before @camstack/core is imported and must stay free of
189
+ * launcher runs before @camstack/system is imported and must stay free of
185
190
  * core dependencies. Just yaml.load + bootstrapSchema (kernel) for
186
191
  * shape validation.
187
192
  */
@@ -189,7 +194,7 @@ function readBootstrapRequiredAddons(dataDir) {
189
194
  const raw = readConfigYaml(dataDir);
190
195
  if (raw === null)
191
196
  return null;
192
- const validation = kernel_1.bootstrapSchema.safeParse(raw);
197
+ const validation = system_1.bootstrapSchema.safeParse(raw);
193
198
  if (!validation.success) {
194
199
  console.warn(`[launcher] config.yaml failed bootstrapSchema validation: ${validation.error.message}`);
195
200
  return null;
@@ -198,7 +203,13 @@ function readBootstrapRequiredAddons(dataDir) {
198
203
  }
199
204
  async function launch() {
200
205
  const dataDir = DATA_DIR;
201
- const addonsDir = path.resolve(dataDir, 'addons');
206
+ // Addons live in a real `node_modules`-shaped dir so ESM `import` resolves
207
+ // every @camstack/* (system + addon-*) from there via the standard
208
+ // walk-up — NODE_PATH only covers CJS, which is why forked ESM addon
209
+ // runners couldn't resolve `@camstack/types` from a plain `addons/` dir.
210
+ // `CAMSTACK_ADDONS_DIR` lets the Docker/Electron images point at their
211
+ // node_modules path (e.g. /data/node_modules); dev keeps `<dataDir>/addons`.
212
+ const addonsDir = process.env['CAMSTACK_ADDONS_DIR'] ?? path.resolve(dataDir, 'addons');
202
213
  // Restore must happen first so the snapshot's `addons/` is what the
203
214
  // installer + symlink step pick up — otherwise we'd install a stale
204
215
  // set and overwrite it a step later.
@@ -230,14 +241,14 @@ async function launch() {
230
241
  console.log(`[launcher] Using bundled addons from ${bundledDir}`);
231
242
  }
232
243
  else if (explicitSource === 'local' || explicitSource === 'symlink') {
233
- workspaceDir = (0, kernel_1.detectWorkspacePackagesDir)(__dirname);
244
+ workspaceDir = (0, system_1.detectWorkspacePackagesDir)(__dirname);
234
245
  if (workspaceDir === null) {
235
246
  console.warn(`[launcher] installSource=${explicitSource} requested but no workspace ` +
236
247
  `packages/ dir found from ${__dirname} — falling back to 'npm'`);
237
248
  resolvedSource = 'npm';
238
249
  }
239
250
  }
240
- const installer = new kernel_1.AddonInstaller({
251
+ const installer = new system_1.AddonInstaller({
241
252
  addonsDir,
242
253
  workspacePackagesDir: workspaceDir ?? undefined,
243
254
  installSource: resolvedSource,
@@ -291,7 +302,7 @@ async function launch() {
291
302
  Module._initPaths();
292
303
  console.log(`[launcher] NODE_PATH extended with: ${extraNodePaths.join(sep)}`);
293
304
  }
294
- // Now safe to load main.ts (which has static imports from @camstack/core)
305
+ // Now safe to load main.ts (which has static imports from @camstack/system)
295
306
  console.log('[launcher] Starting server...');
296
307
  await Promise.resolve().then(() => __importStar(require('./main')));
297
308
  }
package/dist/main.js CHANGED
@@ -77,7 +77,7 @@ const auth_whoami_1 = require("./api/auth-whoami");
77
77
  const session_cookie_js_1 = require("./auth/session-cookie.js");
78
78
  const health_routes_1 = require("./api/health/health.routes");
79
79
  const oauth2_routes_js_1 = require("./api/oauth2/oauth2-routes.js");
80
- const core_1 = require("@camstack/core");
80
+ const system_1 = require("@camstack/system");
81
81
  const boot_config_1 = require("./boot/boot-config");
82
82
  const manual_boot_1 = require("./manual-boot");
83
83
  const post_boot_service_1 = require("./boot/post-boot.service");
@@ -173,7 +173,13 @@ async function bootstrap() {
173
173
  // SPA fallback — set later when admin UI is resolved, used by addon route catch-all
174
174
  let spaIndexHtml = null;
175
175
  // --- Phase 1 + 2: Load config, setup storage locations, TLS ---
176
- const configPath = process.env.CONFIG_PATH ?? path.join(process.cwd(), 'camstack-data', 'config.yaml');
176
+ // Resolution order: explicit CONFIG_PATH wins (lets operators put the
177
+ // bootstrap config on its own mount, e.g. a /config volume). Otherwise
178
+ // default it UNDER the data root (CAMSTACK_DATA) so a plain data-dir mount
179
+ // also persists config.yaml. Falls back to the historical cwd-relative
180
+ // path for local/dev runs where neither env var is set.
181
+ const configPath = process.env.CONFIG_PATH ??
182
+ path.join(process.env.CAMSTACK_DATA ?? path.join(process.cwd(), 'camstack-data'), 'config.yaml');
177
183
  const bootstrapConfig = (0, boot_config_1.loadBootstrapConfig)(configPath);
178
184
  const infra = await (0, boot_config_1.setupInfra)(configPath, bootstrapConfig);
179
185
  const { dataPath, tlsOptions } = infra;
@@ -225,8 +231,8 @@ async function bootstrap() {
225
231
  // If registration fails, start in degraded mode: serve a health warning endpoint.
226
232
  // Instantiate new core services
227
233
  const loggingService = app.get(logging_service_1.LoggingService);
228
- const addonRouteRegistry = new core_1.AddonRouteRegistry();
229
- const dataPlaneRegistry = new core_1.DataPlaneRegistry();
234
+ const addonRouteRegistry = new system_1.AddonRouteRegistry();
235
+ const dataPlaneRegistry = new system_1.DataPlaneRegistry();
230
236
  // Use Fastify-managed notification/toast wrappers (globally provided by NotificationModule)
231
237
  const { NotificationServiceWrapper } = await Promise.resolve().then(() => __importStar(require('./core/notification/notification-wrapper.service')));
232
238
  const { ToastServiceWrapper } = await Promise.resolve().then(() => __importStar(require('./core/notification/toast-wrapper.service')));
@@ -290,6 +296,9 @@ async function bootstrap() {
290
296
  moleculer,
291
297
  agentRegistry: app.get(agent_registry_service_1.AgentRegistryService),
292
298
  hubVersion,
299
+ // Read the live flag at request time — flips to true once the tRPC
300
+ // router finishes registering (see `trpcRegistered = true` below).
301
+ isReady: () => trpcRegistered,
293
302
  });
294
303
  console.log(`[bootstrap] Health routes registered (hub v${hubVersion})`);
295
304
  }
@@ -707,7 +716,7 @@ async function bootstrap() {
707
716
  const upstreamPath = `/${subPath}${query}`;
708
717
  // Take over the socket — `proxyToUpstream` drives the raw response.
709
718
  reply.hijack();
710
- (0, core_1.proxyToUpstream)({
719
+ (0, system_1.proxyToUpstream)({
711
720
  baseUrl: dpMatch.endpoint.baseUrl,
712
721
  secret: dpMatch.endpoint.secret,
713
722
  upstreamPath,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/server",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "private": false,
5
5
  "files": [
6
6
  "dist",
@@ -27,8 +27,7 @@
27
27
  "@camstack/addon-pipeline": "*",
28
28
  "@camstack/addon-pipeline-orchestrator": "*",
29
29
  "@camstack/addon-post-analysis": "*",
30
- "@camstack/core": "*",
31
- "@camstack/kernel": "*",
30
+ "@camstack/system": "*",
32
31
  "@camstack/sdk": "*",
33
32
  "@camstack/shm-ring": "*",
34
33
  "@camstack/types": "*",