@camstack/system 1.2.112 → 1.2.114

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 (52) hide show
  1. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  2. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  3. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  4. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  5. package/dist/builtins/alerts/alerts.addon.js +1 -1
  6. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  7. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
  8. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
  9. package/dist/builtins/console-logging/index.js +1 -1
  10. package/dist/builtins/console-logging/index.mjs +1 -1
  11. package/dist/builtins/core-blocks/core-blocks.addon.js +1 -1
  12. package/dist/builtins/core-blocks/core-blocks.addon.mjs +1 -1
  13. package/dist/builtins/device-manager/device-manager.addon.js +2 -2
  14. package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
  15. package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
  16. package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
  17. package/dist/builtins/hub-forwarder/index.js +1 -1
  18. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  19. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  20. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  21. package/dist/builtins/local-auth/local-auth.addon.js +1 -1
  22. package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
  23. package/dist/builtins/local-network/local-network.addon.d.ts +33 -1
  24. package/dist/builtins/local-network/local-network.addon.js +87 -2
  25. package/dist/builtins/local-network/local-network.addon.mjs +87 -3
  26. package/dist/builtins/loki-logging/index.js +1 -1
  27. package/dist/builtins/loki-logging/index.mjs +1 -1
  28. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  29. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  30. package/dist/builtins/platform-probe/index.js +1 -1
  31. package/dist/builtins/platform-probe/index.mjs +1 -1
  32. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  33. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  34. package/dist/builtins/snapshot/index.js +1 -1
  35. package/dist/builtins/snapshot/index.mjs +1 -1
  36. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  37. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  38. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +2 -2
  39. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +2 -2
  40. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  41. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  42. package/dist/builtins/system-config/system-config.addon.js +1 -1
  43. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  44. package/dist/builtins/winston-logging/index.js +1 -1
  45. package/dist/builtins/winston-logging/index.mjs +1 -1
  46. package/dist/{dist-IPLFQ_-A.js → dist-C1Aea3c6.js} +176 -8
  47. package/dist/{dist-bkg2-2g3.mjs → dist-CJ8RRSvQ.mjs} +176 -8
  48. package/dist/index.js +1 -1
  49. package/dist/index.mjs +1 -1
  50. package/dist/{retired-settings-keys-B-I7w1Ta.js → retired-settings-keys-B52KsNz8.js} +1 -1
  51. package/dist/{retired-settings-keys-C7rRSzbP.mjs → retired-settings-keys-C1efPfyW.mjs} +1 -1
  52. package/package.json +1 -1
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-IPLFQ_-A.js");
6
+ const require_dist = require("../../dist-C1Aea3c6.js");
7
7
  const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
8
8
  let node_crypto = require("node:crypto");
9
9
  let node_path = require("node:path");
@@ -1,4 +1,4 @@
1
- import { Gt as EventCategory, v as addonPagesCapability, vt as errMsg, yt as BaseAddon } from "../../dist-bkg2-2g3.mjs";
1
+ import { Gt as EventCategory, v as addonPagesCapability, vt as errMsg, yt as BaseAddon } from "../../dist-CJ8RRSvQ.mjs";
2
2
  import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
3
3
  import { createHash, randomUUID } from "node:crypto";
4
4
  import * as path$1 from "node:path";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-IPLFQ_-A.js");
6
+ const require_dist = require("../../dist-C1Aea3c6.js");
7
7
  const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
8
8
  let node_crypto = require("node:crypto");
9
9
  let node_path = require("node:path");
@@ -1,4 +1,4 @@
1
- import { Gt as EventCategory, b as addonWidgetsCapability, vt as errMsg, yt as BaseAddon } from "../../dist-bkg2-2g3.mjs";
1
+ import { Gt as EventCategory, b as addonWidgetsCapability, vt as errMsg, yt as BaseAddon } from "../../dist-CJ8RRSvQ.mjs";
2
2
  import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
3
3
  import { createHash, randomUUID } from "node:crypto";
4
4
  import * as path$1 from "node:path";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-IPLFQ_-A.js");
6
+ const require_dist = require("../../dist-C1Aea3c6.js");
7
7
  //#region src/builtins/alerts/prune-policy.ts
8
8
  /**
9
9
  * Ids older than `cutoffMs`, oldest first.
@@ -1,4 +1,4 @@
1
- import { Gt as EventCategory, Mt as createEvent, n as AlertSchema, vt as errMsg, x as alertsCapability, yt as BaseAddon } from "../../dist-bkg2-2g3.mjs";
1
+ import { Gt as EventCategory, Mt as createEvent, n as AlertSchema, vt as errMsg, x as alertsCapability, yt as BaseAddon } from "../../dist-CJ8RRSvQ.mjs";
2
2
  //#region src/builtins/alerts/prune-policy.ts
3
3
  /**
4
4
  * Ids older than `cutoffMs`, oldest first.
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-IPLFQ_-A.js");
6
+ const require_dist = require("../../dist-C1Aea3c6.js");
7
7
  let node_crypto = require("node:crypto");
8
8
  let buffer = require("buffer");
9
9
  let node_fs_promises = require("node:fs/promises");
@@ -1,4 +1,4 @@
1
- import { C as backupCapability, Gt as EventCategory, yt as BaseAddon } from "../../dist-bkg2-2g3.mjs";
1
+ import { C as backupCapability, Gt as EventCategory, yt as BaseAddon } from "../../dist-CJ8RRSvQ.mjs";
2
2
  import { randomBytes, randomUUID } from "node:crypto";
3
3
  import { Buffer as Buffer$1 } from "buffer";
4
4
  import * as fsp from "node:fs/promises";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-IPLFQ_-A.js");
6
+ const require_dist = require("../../dist-C1Aea3c6.js");
7
7
  const require_formatter = require("../../formatter-DqAKDlvN.js");
8
8
  //#region src/builtins/console-logging/console-destination.ts
9
9
  var LEVEL_RANK = {
@@ -1,4 +1,4 @@
1
- import { X as logDestinationCapability, yt as BaseAddon } from "../../dist-bkg2-2g3.mjs";
1
+ import { X as logDestinationCapability, yt as BaseAddon } from "../../dist-CJ8RRSvQ.mjs";
2
2
  import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
3
3
  //#region src/builtins/console-logging/console-destination.ts
4
4
  var LEVEL_RANK = {
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("../../chunk-Cek0wNdY.js");
3
- const require_dist = require("../../dist-IPLFQ_-A.js");
3
+ const require_dist = require("../../dist-C1Aea3c6.js");
4
4
  let node_crypto = require("node:crypto");
5
5
  let node_fs_promises = require("node:fs/promises");
6
6
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -1,4 +1,4 @@
1
- import { D as coreBlockAddonId, O as coreBlockIdFromAddonId, c as CoreBlockSchema, k as coreBlocksCapability, l as DeclaredDevices, o as CORE_BLOCKS_ADDON_ID, s as CORE_BLOCK_ADDON_PREFIX, vt as errMsg, yt as BaseAddon } from "../../dist-bkg2-2g3.mjs";
1
+ import { D as coreBlockAddonId, O as coreBlockIdFromAddonId, c as CoreBlockSchema, k as coreBlocksCapability, l as DeclaredDevices, o as CORE_BLOCKS_ADDON_ID, s as CORE_BLOCK_ADDON_PREFIX, vt as errMsg, yt as BaseAddon } from "../../dist-CJ8RRSvQ.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import * as fs from "node:fs/promises";
4
4
  import * as path$1 from "node:path";
@@ -3,8 +3,8 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-IPLFQ_-A.js");
7
- const require_retired_settings_keys = require("../../retired-settings-keys-B-I7w1Ta.js");
6
+ const require_dist = require("../../dist-C1Aea3c6.js");
7
+ const require_retired_settings_keys = require("../../retired-settings-keys-B52KsNz8.js");
8
8
  let node_crypto = require("node:crypto");
9
9
  let _camstack_types_node = require("@camstack/types/node");
10
10
  //#region src/builtins/device-manager/adoption-job-engine.ts
@@ -1,5 +1,5 @@
1
- import { Ct as DeviceFeature, E as buildStreamParamsConfigSchema, F as deviceStatusCapability, Gt as EventCategory, Lt as isDeviceConfigCap, N as deviceManagerCapability, Ot as WELL_KNOWN_TAB_MAP, P as deviceStateCapability, R as enumerateItemArrayFields, Tt as DeviceType, Wt as sleep, a as CAP_NAMES_WITH_STATUS, at as runtimeStatePolicyFor, et as normalizeUnit, nt as parseStreamParamsFormPatch, p as STREAM_PROFILE_META, t as ALL_CAPABILITY_DEFINITIONS, u as DeviceStatusSchema, vt as errMsg, wt as DeviceRole, yt as BaseAddon, z as enumerateSchemaFields } from "../../dist-bkg2-2g3.mjs";
2
- import { n as purgeRetiredSettingsRows } from "../../retired-settings-keys-C7rRSzbP.mjs";
1
+ import { Ct as DeviceFeature, E as buildStreamParamsConfigSchema, F as deviceStatusCapability, Gt as EventCategory, Lt as isDeviceConfigCap, N as deviceManagerCapability, Ot as WELL_KNOWN_TAB_MAP, P as deviceStateCapability, R as enumerateItemArrayFields, Tt as DeviceType, Wt as sleep, a as CAP_NAMES_WITH_STATUS, at as runtimeStatePolicyFor, et as normalizeUnit, nt as parseStreamParamsFormPatch, p as STREAM_PROFILE_META, t as ALL_CAPABILITY_DEFINITIONS, u as DeviceStatusSchema, vt as errMsg, wt as DeviceRole, yt as BaseAddon, z as enumerateSchemaFields } from "../../dist-CJ8RRSvQ.mjs";
2
+ import { n as purgeRetiredSettingsRows } from "../../retired-settings-keys-C1efPfyW.mjs";
3
3
  import { randomUUID } from "node:crypto";
4
4
  import { canonicalDeviceFingerprint } from "@camstack/types/node";
5
5
  //#region src/builtins/device-manager/adoption-job-engine.ts
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-IPLFQ_-A.js");
6
+ const require_dist = require("../../dist-C1Aea3c6.js");
7
7
  //#region src/builtins/doorbell/trigger-engine.ts
8
8
  /**
9
9
  * Pure trigger logic for the virtual-doorbell builtin — edge detection over
@@ -1,4 +1,4 @@
1
- import { G as isSameAddonId, Gt as EventCategory, I as doorbellCapability, Mt as createEvent, Tt as DeviceType, vt as errMsg, w as bareAddonId, yt as BaseAddon } from "../../dist-bkg2-2g3.mjs";
1
+ import { G as isSameAddonId, Gt as EventCategory, I as doorbellCapability, Mt as createEvent, Tt as DeviceType, vt as errMsg, w as bareAddonId, yt as BaseAddon } from "../../dist-CJ8RRSvQ.mjs";
2
2
  //#region src/builtins/doorbell/trigger-engine.ts
3
3
  /**
4
4
  * Pure trigger logic for the virtual-doorbell builtin — edge detection over
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-IPLFQ_-A.js");
6
+ const require_dist = require("../../dist-C1Aea3c6.js");
7
7
  const require_formatter = require("../../formatter-DqAKDlvN.js");
8
8
  //#region src/builtins/hub-forwarder/hub-forwarder-destination.ts
9
9
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
@@ -1,4 +1,4 @@
1
- import { X as logDestinationCapability, yt as BaseAddon } from "../../dist-bkg2-2g3.mjs";
1
+ import { X as logDestinationCapability, yt as BaseAddon } from "../../dist-CJ8RRSvQ.mjs";
2
2
  import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
3
3
  //#region src/builtins/hub-forwarder/hub-forwarder-destination.ts
4
4
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  require("../../chunk-Cek0wNdY.js");
3
- const require_dist = require("../../dist-IPLFQ_-A.js");
3
+ const require_dist = require("../../dist-C1Aea3c6.js");
4
4
  //#region src/builtins/liveness-monitor/liveness-checks.ts
5
5
  var NO_DEVICES = "liveness:no-devices";
6
6
  var ALL_OFFLINE = "liveness:all-devices-offline";
@@ -1,4 +1,4 @@
1
- import { Gt as EventCategory, Mt as createEvent, vt as errMsg, yt as BaseAddon } from "../../dist-bkg2-2g3.mjs";
1
+ import { Gt as EventCategory, Mt as createEvent, vt as errMsg, yt as BaseAddon } from "../../dist-CJ8RRSvQ.mjs";
2
2
  //#region src/builtins/liveness-monitor/liveness-checks.ts
3
3
  var NO_DEVICES = "liveness:no-devices";
4
4
  var ALL_OFFLINE = "liveness:all-devices-offline";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-IPLFQ_-A.js");
6
+ const require_dist = require("../../dist-C1Aea3c6.js");
7
7
  let node_crypto = require("node:crypto");
8
8
  node_crypto = require_chunk.__toESM(node_crypto);
9
9
  let crypto$1 = require("crypto");
@@ -1,5 +1,5 @@
1
1
  import { i as __require, o as __toESM, t as __commonJSMin } from "../../chunk-CNf5ZN-e.mjs";
2
- import { S as authProviderCapability, _ as UserRecordSchema, ht as userManagementCapability, m as ScopedTokenSchema, r as ApiKeyRecordSchema, yt as BaseAddon } from "../../dist-bkg2-2g3.mjs";
2
+ import { S as authProviderCapability, _ as UserRecordSchema, ht as userManagementCapability, m as ScopedTokenSchema, r as ApiKeyRecordSchema, yt as BaseAddon } from "../../dist-CJ8RRSvQ.mjs";
3
3
  import * as crypto$2 from "node:crypto";
4
4
  import { createHash, randomUUID, timingSafeEqual } from "node:crypto";
5
5
  import nodeCrypto from "crypto";
@@ -1,4 +1,4 @@
1
- import { ProviderRegistration, LocalInterface, ConnectionEndpoint, BaseAddon } from '@camstack/types';
1
+ import { ProviderRegistration, LocalInterface, ConnectionEndpoint, AdvertisedLocalPort, BaseAddon } from '@camstack/types';
2
2
  /**
3
3
  * Cached mesh-reachable endpoint, learned from the `mesh-network`
4
4
  * provider via the `MeshNetworkChanged` event-tail + pull-reconcile.
@@ -10,6 +10,15 @@ interface MeshEndpointCache {
10
10
  /** Hub HTTPS port the mesh endpoint targets. */
11
11
  readonly port: number;
12
12
  }
13
+ /** The three places a hub listen port can be learned, most authoritative first. */
14
+ export interface ListenPortSources {
15
+ /** `server.port` from the hub's live config section; null when unreadable. */
16
+ readonly configured: number | null;
17
+ /** `CAMSTACK_PORT` off the environment; null when unset / unparseable. */
18
+ readonly env: number | null;
19
+ /** The port the CALLER passed. A guess about our socket, not a fact. */
20
+ readonly callerHint: number | null;
21
+ }
13
22
  interface LocalNetworkConfig {
14
23
  /** Empty = "auto" (every non-loopback / non-link-local address
15
24
  * participates). Non-empty restricts the candidate set to only
@@ -77,9 +86,32 @@ export declare class LocalNetworkAddon extends BaseAddon<LocalNetworkConfig> {
77
86
  * not joined simply contributes nothing.
78
87
  */
79
88
  private reconcileMeshEndpoint;
89
+ /**
90
+ * The port this hub is actually listening on, plus the provenance of the
91
+ * number. The boot loader merges the `CAMSTACK_PORT` env override into the
92
+ * persisted `server` section (`server/backend/src/boot/boot-config.ts`), so
93
+ * reading that section gives the authoritative live port — no new setting,
94
+ * and the same source `tailscale-client` already stamps its mesh endpoints
95
+ * from, so the two cannot drift.
96
+ */
97
+ private resolveAdvertisedListenPort;
98
+ /** `server.port` from the live config section, or null when unreadable. */
99
+ private readConfiguredPort;
80
100
  private enumerate;
81
101
  private detectChanges;
82
102
  }
103
+ /**
104
+ * Pick the port to advertise, and say where it came from.
105
+ *
106
+ * The caller's hint ranks BELOW everything the hub knows about itself and above
107
+ * nothing but the compiled default — it is kept only so a client written
108
+ * against the old echoing contract behaves exactly as it did before, and it is
109
+ * labelled `caller-hint` so that client's successor can refuse to trust it.
110
+ * Values outside the valid port range are dropped rather than advertised: a
111
+ * malformed `server.port` must fall through to the next source, not produce a
112
+ * URL nothing can bind.
113
+ */
114
+ export declare function resolveAdvertisedPort(sources: ListenPortSources): AdvertisedLocalPort;
83
115
  /**
84
116
  * Lift `os.networkInterfaces()` into our `LocalInterface[]` shape with
85
117
  * kind classification + preferred flag. Pure — takes the raw result so
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("../../chunk-Cek0wNdY.js");
3
- const require_dist = require("../../dist-IPLFQ_-A.js");
3
+ const require_dist = require("../../dist-C1Aea3c6.js");
4
4
  let node_os = require("node:os");
5
5
  node_os = require_chunk.__toESM(node_os);
6
6
  //#region src/builtins/local-network/local-network.addon.ts
@@ -28,6 +28,12 @@ node_os = require_chunk.__toESM(node_os);
28
28
  */
29
29
  var MESH_PROVIDER_ADDON_IDS = ["tailscale-client"];
30
30
  var POLL_INTERVAL_MS = 3e4;
31
+ /**
32
+ * Compiled-in boot default — mirrors `CONFIG_DEFAULTS.server.port` in
33
+ * `server/backend/src/boot/boot-config.ts`. Used only when neither the live
34
+ * config section, the env, nor the caller says anything.
35
+ */
36
+ var DEFAULT_HUB_PORT = 4443;
31
37
  var LocalNetworkAddon = class extends require_dist.BaseAddon {
32
38
  pollTimer = null;
33
39
  lastSnapshotKey = "";
@@ -84,8 +90,17 @@ var LocalNetworkAddon = class extends require_dist.BaseAddon {
84
90
  const scheme = input.scheme ?? "http";
85
91
  const allow = this.config.allowedAddresses;
86
92
  const interfaces = applyAllowlist(this.enumerate(), allow);
93
+ const localPort = await this.resolveAdvertisedListenPort(input.port ?? null);
94
+ if (input.port !== void 0 && input.port !== localPort.port) this.ctx.logger.info("local-network: caller port hint overridden", { meta: {
95
+ hint: input.port,
96
+ advertised: localPort.port,
97
+ source: localPort.source
98
+ } });
87
99
  await this.reconcileMeshEndpoint();
88
- return { endpoints: buildEndpoints(interfaces, input.port, includeLoopback, ipv4Only, this.publicHostname, scheme, this.meshEndpoint) };
100
+ return {
101
+ endpoints: buildEndpoints(interfaces, localPort.port, includeLoopback, ipv4Only, this.publicHostname, scheme, this.meshEndpoint),
102
+ localPort
103
+ };
89
104
  },
90
105
  getNotificationEndpoint: async () => ({
91
106
  baseUrl: this.config.notificationBaseUrl === "" ? null : this.config.notificationBaseUrl,
@@ -214,6 +229,39 @@ var LocalNetworkAddon = class extends require_dist.BaseAddon {
214
229
  }
215
230
  }
216
231
  }
232
+ /**
233
+ * The port this hub is actually listening on, plus the provenance of the
234
+ * number. The boot loader merges the `CAMSTACK_PORT` env override into the
235
+ * persisted `server` section (`server/backend/src/boot/boot-config.ts`), so
236
+ * reading that section gives the authoritative live port — no new setting,
237
+ * and the same source `tailscale-client` already stamps its mesh endpoints
238
+ * from, so the two cannot drift.
239
+ */
240
+ async resolveAdvertisedListenPort(callerHint) {
241
+ const envRaw = Number.parseInt(process.env["CAMSTACK_PORT"] ?? "", 10);
242
+ return resolveAdvertisedPort({
243
+ configured: await this.readConfiguredPort(),
244
+ env: Number.isNaN(envRaw) ? null : envRaw,
245
+ callerHint
246
+ });
247
+ }
248
+ /** `server.port` from the live config section, or null when unreadable. */
249
+ async readConfiguredPort() {
250
+ const settings = this.ctx.settings;
251
+ if (!settings) return null;
252
+ try {
253
+ const raw = (await settings.getSection("server"))["port"];
254
+ if (typeof raw === "number") return raw;
255
+ if (typeof raw === "string") {
256
+ const parsed = Number.parseInt(raw, 10);
257
+ return Number.isNaN(parsed) ? null : parsed;
258
+ }
259
+ return null;
260
+ } catch (err) {
261
+ this.ctx.logger.warn("local-network: could not read server.port", { meta: { error: err instanceof Error ? err.message : String(err) } });
262
+ return null;
263
+ }
264
+ }
217
265
  enumerate() {
218
266
  return enumerateOsInterfaces(node_os.networkInterfaces());
219
267
  }
@@ -238,6 +286,42 @@ var LocalNetworkAddon = class extends require_dist.BaseAddon {
238
286
  });
239
287
  }
240
288
  };
289
+ /**
290
+ * Pick the port to advertise, and say where it came from.
291
+ *
292
+ * The caller's hint ranks BELOW everything the hub knows about itself and above
293
+ * nothing but the compiled default — it is kept only so a client written
294
+ * against the old echoing contract behaves exactly as it did before, and it is
295
+ * labelled `caller-hint` so that client's successor can refuse to trust it.
296
+ * Values outside the valid port range are dropped rather than advertised: a
297
+ * malformed `server.port` must fall through to the next source, not produce a
298
+ * URL nothing can bind.
299
+ */
300
+ function resolveAdvertisedPort(sources) {
301
+ const configured = validPort(sources.configured);
302
+ if (configured !== null) return {
303
+ port: configured,
304
+ source: "server-config"
305
+ };
306
+ const env = validPort(sources.env);
307
+ if (env !== null) return {
308
+ port: env,
309
+ source: "server-env"
310
+ };
311
+ const hint = validPort(sources.callerHint);
312
+ if (hint !== null) return {
313
+ port: hint,
314
+ source: "caller-hint"
315
+ };
316
+ return {
317
+ port: DEFAULT_HUB_PORT,
318
+ source: "default"
319
+ };
320
+ }
321
+ function validPort(value) {
322
+ if (value === null) return null;
323
+ return Number.isInteger(value) && value >= 1 && value <= 65535 ? value : null;
324
+ }
241
325
  function enumerateOsInterfaces(ifaces) {
242
326
  const raw = [];
243
327
  for (const [name, addrs] of Object.entries(ifaces)) {
@@ -515,3 +599,4 @@ exports.explainNonPlausible = explainNonPlausible;
515
599
  exports.isPlausibleAutoSeed = isPlausibleAutoSeed;
516
600
  exports.pickPreferred = pickPreferred;
517
601
  exports.prefixLen = prefixLen;
602
+ exports.resolveAdvertisedPort = resolveAdvertisedPort;
@@ -1,4 +1,4 @@
1
- import { Gt as EventCategory, Y as localNetworkCapability, yt as BaseAddon } from "../../dist-bkg2-2g3.mjs";
1
+ import { Gt as EventCategory, Y as localNetworkCapability, yt as BaseAddon } from "../../dist-CJ8RRSvQ.mjs";
2
2
  import * as os from "node:os";
3
3
  //#region src/builtins/local-network/local-network.addon.ts
4
4
  /**
@@ -25,6 +25,12 @@ import * as os from "node:os";
25
25
  */
26
26
  var MESH_PROVIDER_ADDON_IDS = ["tailscale-client"];
27
27
  var POLL_INTERVAL_MS = 3e4;
28
+ /**
29
+ * Compiled-in boot default — mirrors `CONFIG_DEFAULTS.server.port` in
30
+ * `server/backend/src/boot/boot-config.ts`. Used only when neither the live
31
+ * config section, the env, nor the caller says anything.
32
+ */
33
+ var DEFAULT_HUB_PORT = 4443;
28
34
  var LocalNetworkAddon = class extends BaseAddon {
29
35
  pollTimer = null;
30
36
  lastSnapshotKey = "";
@@ -81,8 +87,17 @@ var LocalNetworkAddon = class extends BaseAddon {
81
87
  const scheme = input.scheme ?? "http";
82
88
  const allow = this.config.allowedAddresses;
83
89
  const interfaces = applyAllowlist(this.enumerate(), allow);
90
+ const localPort = await this.resolveAdvertisedListenPort(input.port ?? null);
91
+ if (input.port !== void 0 && input.port !== localPort.port) this.ctx.logger.info("local-network: caller port hint overridden", { meta: {
92
+ hint: input.port,
93
+ advertised: localPort.port,
94
+ source: localPort.source
95
+ } });
84
96
  await this.reconcileMeshEndpoint();
85
- return { endpoints: buildEndpoints(interfaces, input.port, includeLoopback, ipv4Only, this.publicHostname, scheme, this.meshEndpoint) };
97
+ return {
98
+ endpoints: buildEndpoints(interfaces, localPort.port, includeLoopback, ipv4Only, this.publicHostname, scheme, this.meshEndpoint),
99
+ localPort
100
+ };
86
101
  },
87
102
  getNotificationEndpoint: async () => ({
88
103
  baseUrl: this.config.notificationBaseUrl === "" ? null : this.config.notificationBaseUrl,
@@ -211,6 +226,39 @@ var LocalNetworkAddon = class extends BaseAddon {
211
226
  }
212
227
  }
213
228
  }
229
+ /**
230
+ * The port this hub is actually listening on, plus the provenance of the
231
+ * number. The boot loader merges the `CAMSTACK_PORT` env override into the
232
+ * persisted `server` section (`server/backend/src/boot/boot-config.ts`), so
233
+ * reading that section gives the authoritative live port — no new setting,
234
+ * and the same source `tailscale-client` already stamps its mesh endpoints
235
+ * from, so the two cannot drift.
236
+ */
237
+ async resolveAdvertisedListenPort(callerHint) {
238
+ const envRaw = Number.parseInt(process.env["CAMSTACK_PORT"] ?? "", 10);
239
+ return resolveAdvertisedPort({
240
+ configured: await this.readConfiguredPort(),
241
+ env: Number.isNaN(envRaw) ? null : envRaw,
242
+ callerHint
243
+ });
244
+ }
245
+ /** `server.port` from the live config section, or null when unreadable. */
246
+ async readConfiguredPort() {
247
+ const settings = this.ctx.settings;
248
+ if (!settings) return null;
249
+ try {
250
+ const raw = (await settings.getSection("server"))["port"];
251
+ if (typeof raw === "number") return raw;
252
+ if (typeof raw === "string") {
253
+ const parsed = Number.parseInt(raw, 10);
254
+ return Number.isNaN(parsed) ? null : parsed;
255
+ }
256
+ return null;
257
+ } catch (err) {
258
+ this.ctx.logger.warn("local-network: could not read server.port", { meta: { error: err instanceof Error ? err.message : String(err) } });
259
+ return null;
260
+ }
261
+ }
214
262
  enumerate() {
215
263
  return enumerateOsInterfaces(os.networkInterfaces());
216
264
  }
@@ -235,6 +283,42 @@ var LocalNetworkAddon = class extends BaseAddon {
235
283
  });
236
284
  }
237
285
  };
286
+ /**
287
+ * Pick the port to advertise, and say where it came from.
288
+ *
289
+ * The caller's hint ranks BELOW everything the hub knows about itself and above
290
+ * nothing but the compiled default — it is kept only so a client written
291
+ * against the old echoing contract behaves exactly as it did before, and it is
292
+ * labelled `caller-hint` so that client's successor can refuse to trust it.
293
+ * Values outside the valid port range are dropped rather than advertised: a
294
+ * malformed `server.port` must fall through to the next source, not produce a
295
+ * URL nothing can bind.
296
+ */
297
+ function resolveAdvertisedPort(sources) {
298
+ const configured = validPort(sources.configured);
299
+ if (configured !== null) return {
300
+ port: configured,
301
+ source: "server-config"
302
+ };
303
+ const env = validPort(sources.env);
304
+ if (env !== null) return {
305
+ port: env,
306
+ source: "server-env"
307
+ };
308
+ const hint = validPort(sources.callerHint);
309
+ if (hint !== null) return {
310
+ port: hint,
311
+ source: "caller-hint"
312
+ };
313
+ return {
314
+ port: DEFAULT_HUB_PORT,
315
+ source: "default"
316
+ };
317
+ }
318
+ function validPort(value) {
319
+ if (value === null) return null;
320
+ return Number.isInteger(value) && value >= 1 && value <= 65535 ? value : null;
321
+ }
238
322
  function enumerateOsInterfaces(ifaces) {
239
323
  const raw = [];
240
324
  for (const [name, addrs] of Object.entries(ifaces)) {
@@ -502,4 +586,4 @@ function formatKind(kind) {
502
586
  }
503
587
  }
504
588
  //#endregion
505
- export { LocalNetworkAddon, applyAllowlist, autoSeedAllowlist, buildEndpoints, classifyKind, enumerateOsInterfaces, explainNonPlausible, isPlausibleAutoSeed, pickPreferred, prefixLen };
589
+ export { LocalNetworkAddon, applyAllowlist, autoSeedAllowlist, buildEndpoints, classifyKind, enumerateOsInterfaces, explainNonPlausible, isPlausibleAutoSeed, pickPreferred, prefixLen, resolveAdvertisedPort };
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-IPLFQ_-A.js");
6
+ const require_dist = require("../../dist-C1Aea3c6.js");
7
7
  //#region src/builtins/loki-logging/loki-payload.ts
8
8
  /**
9
9
  * Loki rejects a label name that is not a valid Prometheus label
@@ -1,4 +1,4 @@
1
- import { X as logDestinationCapability, yt as BaseAddon } from "../../dist-bkg2-2g3.mjs";
1
+ import { X as logDestinationCapability, yt as BaseAddon } from "../../dist-CJ8RRSvQ.mjs";
2
2
  //#region src/builtins/loki-logging/loki-payload.ts
3
3
  /**
4
4
  * Loki rejects a label name that is not a valid Prometheus label
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-IPLFQ_-A.js");
6
+ const require_dist = require("../../dist-C1Aea3c6.js");
7
7
  let node_child_process = require("node:child_process");
8
8
  let node_util = require("node:util");
9
9
  let node_os = require("node:os");
@@ -1,4 +1,4 @@
1
- import { $ as metricsProviderCapability, Gt as EventCategory, Mt as createEvent, yt as BaseAddon } from "../../dist-bkg2-2g3.mjs";
1
+ import { $ as metricsProviderCapability, Gt as EventCategory, Mt as createEvent, yt as BaseAddon } from "../../dist-CJ8RRSvQ.mjs";
2
2
  import { execFile, execFileSync } from "node:child_process";
3
3
  import { promisify } from "node:util";
4
4
  import * as os from "node:os";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-IPLFQ_-A.js");
6
+ const require_dist = require("../../dist-C1Aea3c6.js");
7
7
  let node_child_process = require("node:child_process");
8
8
  let node_util = require("node:util");
9
9
  let node_os = require("node:os");
@@ -1,5 +1,5 @@
1
1
  import { o as __toESM } from "../../chunk-CNf5ZN-e.mjs";
2
- import { Gt as EventCategory, L as enumerateInferenceDevices, Pt as emitReadiness, ct as scoreRuntimes, rt as platformProbeCapability, vt as errMsg, yt as BaseAddon } from "../../dist-bkg2-2g3.mjs";
2
+ import { Gt as EventCategory, L as enumerateInferenceDevices, Pt as emitReadiness, ct as scoreRuntimes, rt as platformProbeCapability, vt as errMsg, yt as BaseAddon } from "../../dist-CJ8RRSvQ.mjs";
3
3
  import { execFile } from "node:child_process";
4
4
  import { promisify } from "node:util";
5
5
  import * as os from "node:os";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-IPLFQ_-A.js");
6
+ const require_dist = require("../../dist-C1Aea3c6.js");
7
7
  //#region src/builtins/remote-access-orchestrator/enabled-providers-reconcile.ts
8
8
  /**
9
9
  * Reconcile the durable `enabledProviders` set against authoritative
@@ -1,4 +1,4 @@
1
- import { Gt as EventCategory, yt as BaseAddon } from "../../dist-bkg2-2g3.mjs";
1
+ import { Gt as EventCategory, yt as BaseAddon } from "../../dist-CJ8RRSvQ.mjs";
2
2
  //#region src/builtins/remote-access-orchestrator/enabled-providers-reconcile.ts
3
3
  /**
4
4
  * Reconcile the durable `enabledProviders` set against authoritative
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-IPLFQ_-A.js");
6
+ const require_dist = require("../../dist-C1Aea3c6.js");
7
7
  let zod = require("zod");
8
8
  let node_crypto = require("node:crypto");
9
9
  let _camstack_types_node = require("@camstack/types/node");
@@ -1,4 +1,4 @@
1
- import { Ct as DeviceFeature, Gt as EventCategory, M as deriveBatteryPresence, Rt as nodePin, T as batteryCapability, Tt as DeviceType, i as BatteryStatusSchema, mt as streamQualityLabel, ut as snapshotCapability, vt as errMsg, w as bareAddonId, yt as BaseAddon } from "../../dist-bkg2-2g3.mjs";
1
+ import { Ct as DeviceFeature, Gt as EventCategory, M as deriveBatteryPresence, Rt as nodePin, T as batteryCapability, Tt as DeviceType, i as BatteryStatusSchema, mt as streamQualityLabel, ut as snapshotCapability, vt as errMsg, w as bareAddonId, yt as BaseAddon } from "../../dist-CJ8RRSvQ.mjs";
2
2
  import { z } from "zod";
3
3
  import { randomUUID } from "node:crypto";
4
4
  import { signExpiringUrl, verifyExpiringUrl } from "@camstack/types/node";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-IPLFQ_-A.js");
6
+ const require_dist = require("../../dist-C1Aea3c6.js");
7
7
  let node_crypto = require("node:crypto");
8
8
  let node_fs_promises = require("node:fs/promises");
9
9
  let node_path = require("node:path");
@@ -1,4 +1,4 @@
1
- import { V as filesystemBrowseCapability, pt as storageProviderCapability, yt as BaseAddon } from "../../dist-bkg2-2g3.mjs";
1
+ import { V as filesystemBrowseCapability, pt as storageProviderCapability, yt as BaseAddon } from "../../dist-CJ8RRSvQ.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { mkdir, readdir, realpath, statfs } from "node:fs/promises";
4
4
  import * as path$1 from "node:path";
@@ -3,8 +3,8 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-IPLFQ_-A.js");
7
- const require_retired_settings_keys = require("../../retired-settings-keys-B-I7w1Ta.js");
6
+ const require_dist = require("../../dist-C1Aea3c6.js");
7
+ const require_retired_settings_keys = require("../../retired-settings-keys-B52KsNz8.js");
8
8
  let node_crypto = require("node:crypto");
9
9
  let node_fs = require("node:fs");
10
10
  let node_module = require("node:module");
@@ -1,5 +1,5 @@
1
- import { A as dataStoreProviderCapability, Bt as parseJsonUnknown, _t as vectorStoreCapability, f as RUNTIME_DEFAULTS, gt as vectorDimFromBase64, j as decodeVectorBase64, kt as asJsonObject, vt as errMsg, w as bareAddonId, yt as BaseAddon } from "../../dist-bkg2-2g3.mjs";
2
- import { r as retiredKeyStoreOf, t as purgeRetiredSettingsKeys } from "../../retired-settings-keys-C7rRSzbP.mjs";
1
+ import { A as dataStoreProviderCapability, Bt as parseJsonUnknown, _t as vectorStoreCapability, f as RUNTIME_DEFAULTS, gt as vectorDimFromBase64, j as decodeVectorBase64, kt as asJsonObject, vt as errMsg, w as bareAddonId, yt as BaseAddon } from "../../dist-CJ8RRSvQ.mjs";
2
+ import { r as retiredKeyStoreOf, t as purgeRetiredSettingsKeys } from "../../retired-settings-keys-C1efPfyW.mjs";
3
3
  import { createRequire } from "node:module";
4
4
  import { randomUUID } from "node:crypto";
5
5
  import { statSync } from "node:fs";