camstack 1.2.59 → 1.2.61

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.
@@ -33129,6 +33129,33 @@ var intercomCapability = {
33129
33129
  deviceNative: true,
33130
33130
  mode: "singleton",
33131
33131
  deviceTypes: [DeviceType.Camera],
33132
+ /**
33133
+ * **Auth tier: `protected` on every method — deliberate, and load-bearing.**
33134
+ *
33135
+ * Talking through a camera is an OPERATE action, not a CONFIGURE one. This
33136
+ * cap has no configuration surface at all: all six methods open, feed and
33137
+ * close one live audio session against one `deviceId`. That is the same
33138
+ * authority as `ptz.move` or `snapshot.getSnapshot`, both `protected` — and
33139
+ * the opposite of `ptz.savePreset` / `snapshot.invalidateCache`, which are
33140
+ * `admin` because they change what the device IS.
33141
+ *
33142
+ * `protected` does not mean ungated: `protectedProcedure` runs the
33143
+ * `METHOD_ACCESS_MAP` scope check, and every method here is `scope: 'device'`
33144
+ * with `access: 'create'` and a `deviceId` in its input. So a caller needs a
33145
+ * grant that covers THAT camera at `create` — a `camera-viewer` (`view`
33146
+ * only) still cannot talk, and a grant on camera 5 cannot talk through
33147
+ * camera 7.
33148
+ *
33149
+ * Every method was `auth: 'admin'` from the initial commit, which made the
33150
+ * cap unreachable by every non-admin principal — `adminProcedure` throws
33151
+ * `FORBIDDEN: Admin required` BEFORE the scope check runs, so the scope
33152
+ * machinery generated for this cap (`METHOD_ACCESS_MAP`,
33153
+ * `DEVICE_SCOPED_CAPS`, `METHOD_DEVICE_SELECTORS`) was complete and dead. The
33154
+ * `camera-operator` scope preset has promised "PTZ control, intercom,
33155
+ * snapshots" since that same commit; the promise could not be kept. Recorded
33156
+ * as D289; `scripts/check-scope-preset-promises.ts` now fails the build if a
33157
+ * preset promises a cap no row of that preset can reach.
33158
+ */
33132
33159
  methods: {
33133
33160
  /**
33134
33161
  * Open a server-side WebRTC audio-only session. Returns an SDP
@@ -33141,7 +33168,7 @@ var intercomCapability = {
33141
33168
  sdpOffer: external_exports.string()
33142
33169
  }), {
33143
33170
  kind: "mutation",
33144
- auth: "admin"
33171
+ auth: "protected"
33145
33172
  }),
33146
33173
  handleAnswer: method(external_exports.object({
33147
33174
  deviceId: external_exports.number(),
@@ -33149,7 +33176,7 @@ var intercomCapability = {
33149
33176
  sdpAnswer: external_exports.string()
33150
33177
  }), external_exports.void(), {
33151
33178
  kind: "mutation",
33152
- auth: "admin"
33179
+ auth: "protected"
33153
33180
  }),
33154
33181
  /** Close explicitly. Server also auto-closes on 30s idle. */
33155
33182
  stopSession: method(external_exports.object({
@@ -33157,7 +33184,7 @@ var intercomCapability = {
33157
33184
  sessionId: external_exports.string()
33158
33185
  }), external_exports.void(), {
33159
33186
  kind: "mutation",
33160
- auth: "admin"
33187
+ auth: "protected"
33161
33188
  }),
33162
33189
  /**
33163
33190
  * Open a raw-PCM talk session (no WebRTC SDP plumbing). Used by
@@ -33170,7 +33197,7 @@ var intercomCapability = {
33170
33197
  */
33171
33198
  startTalkSession: method(external_exports.object({ deviceId: external_exports.number() }), external_exports.object({ sessionId: external_exports.string() }), {
33172
33199
  kind: "mutation",
33173
- auth: "admin"
33200
+ auth: "protected"
33174
33201
  }),
33175
33202
  /**
33176
33203
  * Push one chunk of talk-back audio onto the active talk session.
@@ -33205,12 +33232,12 @@ var intercomCapability = {
33205
33232
  sequenceNumber: external_exports.number().int()
33206
33233
  }), external_exports.object({ accepted: external_exports.boolean() }), {
33207
33234
  kind: "mutation",
33208
- auth: "admin"
33235
+ auth: "protected"
33209
33236
  }),
33210
33237
  /** Close the raw-PCM talk session. Idempotent. */
33211
33238
  endTalkSession: method(external_exports.object({ deviceId: external_exports.number() }), external_exports.void(), {
33212
33239
  kind: "mutation",
33213
- auth: "admin"
33240
+ auth: "protected"
33214
33241
  })
33215
33242
  },
33216
33243
  events: { onStatusChanged: { data: external_exports.object({
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runDiscover
4
- } from "./chunk-UMNISWW6.js";
4
+ } from "./chunk-ARTM5NDU.js";
5
5
  import "./chunk-LMMQX4CK.js";
6
6
 
7
7
  // src/cli.ts
@@ -38,7 +38,7 @@ async function runServe(args) {
38
38
  ...typeof values.data === "string" ? { data: values.data } : {}
39
39
  };
40
40
  Object.assign(process.env, buildServeEnv(opts));
41
- await import("./launcher-WK4Q3DVU.js");
41
+ await import("./launcher-AZ7QXACO.js");
42
42
  }
43
43
 
44
44
  // src/commands/agent.ts
@@ -83,7 +83,7 @@ async function runAgent(args) {
83
83
  ...typeof values.port === "string" ? { port: values.port } : {}
84
84
  };
85
85
  Object.assign(process.env, buildAgentEnv(opts));
86
- await import("./launcher-WK4Q3DVU.js");
86
+ await import("./launcher-AZ7QXACO.js");
87
87
  }
88
88
 
89
89
  // src/commands/setup.ts
@@ -1130,7 +1130,7 @@ function isUnknown(_value) {
1130
1130
  return true;
1131
1131
  }
1132
1132
  async function resolveServerInteractive(presetNamespace) {
1133
- const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-NCRIXDCA.js");
1133
+ const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-UFN2BYNO.js");
1134
1134
  if (presetNamespace) {
1135
1135
  const spinner4 = clack.spinner();
1136
1136
  spinner4.start(`Discovering hub on LAN (namespace "${presetNamespace}")`);
@@ -5,7 +5,7 @@ import {
5
5
  filterHubNodes,
6
6
  resolveHubFromDiscovered,
7
7
  runDiscover
8
- } from "./chunk-UMNISWW6.js";
8
+ } from "./chunk-ARTM5NDU.js";
9
9
  import "./chunk-LMMQX4CK.js";
10
10
  export {
11
11
  DEFAULT_HUB_HTTPS_PORT,
@@ -23633,9 +23633,9 @@ var require_zod = __commonJS({
23633
23633
  }
23634
23634
  });
23635
23635
 
23636
- // ../system/dist/dist-C7uZ_fOb.js
23637
- var require_dist_C7uZ_fOb = __commonJS({
23638
- "../system/dist/dist-C7uZ_fOb.js"(exports) {
23636
+ // ../system/dist/dist-BPlfW-CG.js
23637
+ var require_dist_BPlfW_CG = __commonJS({
23638
+ "../system/dist/dist-BPlfW-CG.js"(exports) {
23639
23639
  "use strict";
23640
23640
  var zod = require_zod();
23641
23641
  var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
@@ -43645,6 +43645,33 @@ var require_dist_C7uZ_fOb = __commonJS({
43645
43645
  deviceNative: true,
43646
43646
  mode: "singleton",
43647
43647
  deviceTypes: [DeviceType.Camera],
43648
+ /**
43649
+ * **Auth tier: `protected` on every method — deliberate, and load-bearing.**
43650
+ *
43651
+ * Talking through a camera is an OPERATE action, not a CONFIGURE one. This
43652
+ * cap has no configuration surface at all: all six methods open, feed and
43653
+ * close one live audio session against one `deviceId`. That is the same
43654
+ * authority as `ptz.move` or `snapshot.getSnapshot`, both `protected` — and
43655
+ * the opposite of `ptz.savePreset` / `snapshot.invalidateCache`, which are
43656
+ * `admin` because they change what the device IS.
43657
+ *
43658
+ * `protected` does not mean ungated: `protectedProcedure` runs the
43659
+ * `METHOD_ACCESS_MAP` scope check, and every method here is `scope: 'device'`
43660
+ * with `access: 'create'` and a `deviceId` in its input. So a caller needs a
43661
+ * grant that covers THAT camera at `create` — a `camera-viewer` (`view`
43662
+ * only) still cannot talk, and a grant on camera 5 cannot talk through
43663
+ * camera 7.
43664
+ *
43665
+ * Every method was `auth: 'admin'` from the initial commit, which made the
43666
+ * cap unreachable by every non-admin principal — `adminProcedure` throws
43667
+ * `FORBIDDEN: Admin required` BEFORE the scope check runs, so the scope
43668
+ * machinery generated for this cap (`METHOD_ACCESS_MAP`,
43669
+ * `DEVICE_SCOPED_CAPS`, `METHOD_DEVICE_SELECTORS`) was complete and dead. The
43670
+ * `camera-operator` scope preset has promised "PTZ control, intercom,
43671
+ * snapshots" since that same commit; the promise could not be kept. Recorded
43672
+ * as D289; `scripts/check-scope-preset-promises.ts` now fails the build if a
43673
+ * preset promises a cap no row of that preset can reach.
43674
+ */
43648
43675
  methods: {
43649
43676
  /**
43650
43677
  * Open a server-side WebRTC audio-only session. Returns an SDP
@@ -43657,7 +43684,7 @@ var require_dist_C7uZ_fOb = __commonJS({
43657
43684
  sdpOffer: zod.z.string()
43658
43685
  }), {
43659
43686
  kind: "mutation",
43660
- auth: "admin"
43687
+ auth: "protected"
43661
43688
  }),
43662
43689
  handleAnswer: method(zod.z.object({
43663
43690
  deviceId: zod.z.number(),
@@ -43665,7 +43692,7 @@ var require_dist_C7uZ_fOb = __commonJS({
43665
43692
  sdpAnswer: zod.z.string()
43666
43693
  }), zod.z.void(), {
43667
43694
  kind: "mutation",
43668
- auth: "admin"
43695
+ auth: "protected"
43669
43696
  }),
43670
43697
  /** Close explicitly. Server also auto-closes on 30s idle. */
43671
43698
  stopSession: method(zod.z.object({
@@ -43673,7 +43700,7 @@ var require_dist_C7uZ_fOb = __commonJS({
43673
43700
  sessionId: zod.z.string()
43674
43701
  }), zod.z.void(), {
43675
43702
  kind: "mutation",
43676
- auth: "admin"
43703
+ auth: "protected"
43677
43704
  }),
43678
43705
  /**
43679
43706
  * Open a raw-PCM talk session (no WebRTC SDP plumbing). Used by
@@ -43686,7 +43713,7 @@ var require_dist_C7uZ_fOb = __commonJS({
43686
43713
  */
43687
43714
  startTalkSession: method(zod.z.object({ deviceId: zod.z.number() }), zod.z.object({ sessionId: zod.z.string() }), {
43688
43715
  kind: "mutation",
43689
- auth: "admin"
43716
+ auth: "protected"
43690
43717
  }),
43691
43718
  /**
43692
43719
  * Push one chunk of talk-back audio onto the active talk session.
@@ -43721,12 +43748,12 @@ var require_dist_C7uZ_fOb = __commonJS({
43721
43748
  sequenceNumber: zod.z.number().int()
43722
43749
  }), zod.z.object({ accepted: zod.z.boolean() }), {
43723
43750
  kind: "mutation",
43724
- auth: "admin"
43751
+ auth: "protected"
43725
43752
  }),
43726
43753
  /** Close the raw-PCM talk session. Idempotent. */
43727
43754
  endTalkSession: method(zod.z.object({ deviceId: zod.z.number() }), zod.z.void(), {
43728
43755
  kind: "mutation",
43729
- auth: "admin"
43756
+ auth: "protected"
43730
43757
  })
43731
43758
  },
43732
43759
  events: { onStatusChanged: { data: zod.z.object({
@@ -58686,7 +58713,7 @@ var require_alerts_addon = __commonJS({
58686
58713
  [Symbol.toStringTag]: { value: "Module" }
58687
58714
  });
58688
58715
  require_chunk_Cek0wNdY();
58689
- var require_dist10 = require_dist_C7uZ_fOb();
58716
+ var require_dist10 = require_dist_BPlfW_CG();
58690
58717
  function selectExpired(alerts, cutoffMs) {
58691
58718
  return alerts.filter((a) => a.createdAt < cutoffMs).sort((a, b) => a.createdAt - b.createdAt).map((a) => a.id);
58692
58719
  }
@@ -59505,7 +59532,7 @@ var require_console_logging = __commonJS({
59505
59532
  [Symbol.toStringTag]: { value: "Module" }
59506
59533
  });
59507
59534
  require_chunk_Cek0wNdY();
59508
- var require_dist10 = require_dist_C7uZ_fOb();
59535
+ var require_dist10 = require_dist_BPlfW_CG();
59509
59536
  var require_formatter = require_formatter_DqAKDlvN();
59510
59537
  var LEVEL_RANK = {
59511
59538
  debug: 0,
@@ -59599,7 +59626,7 @@ var require_core_blocks_addon = __commonJS({
59599
59626
  "use strict";
59600
59627
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
59601
59628
  var require_chunk = require_chunk_Cek0wNdY();
59602
- var require_dist10 = require_dist_C7uZ_fOb();
59629
+ var require_dist10 = require_dist_BPlfW_CG();
59603
59630
  var node_crypto = __require("crypto");
59604
59631
  var node_fs_promises = __require("fs/promises");
59605
59632
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -60496,11 +60523,11 @@ var require_core_blocks = __commonJS({
60496
60523
  }
60497
60524
  });
60498
60525
 
60499
- // ../system/dist/retired-settings-keys-CBU4-TJO.js
60500
- var require_retired_settings_keys_CBU4_TJO = __commonJS({
60501
- "../system/dist/retired-settings-keys-CBU4-TJO.js"(exports) {
60526
+ // ../system/dist/retired-settings-keys-DBY6ebwV.js
60527
+ var require_retired_settings_keys_DBY6ebwV = __commonJS({
60528
+ "../system/dist/retired-settings-keys-DBY6ebwV.js"(exports) {
60502
60529
  "use strict";
60503
- var require_dist10 = require_dist_C7uZ_fOb();
60530
+ var require_dist10 = require_dist_BPlfW_CG();
60504
60531
  function settingsStoreIsAuthoritativeHere(env) {
60505
60532
  const raw = (env["CAMSTACK_ROLE"] ?? "").trim().toLowerCase();
60506
60533
  return raw === "" || raw === "hub";
@@ -62714,8 +62741,8 @@ var require_device_manager_addon = __commonJS({
62714
62741
  [Symbol.toStringTag]: { value: "Module" }
62715
62742
  });
62716
62743
  require_chunk_Cek0wNdY();
62717
- var require_dist10 = require_dist_C7uZ_fOb();
62718
- var require_retired_settings_keys = require_retired_settings_keys_CBU4_TJO();
62744
+ var require_dist10 = require_dist_BPlfW_CG();
62745
+ var require_retired_settings_keys = require_retired_settings_keys_DBY6ebwV();
62719
62746
  var node_crypto = __require("crypto");
62720
62747
  var _camstack_types_node = require_node();
62721
62748
  var JOB_HISTORY = 20;
@@ -67464,7 +67491,7 @@ var require_hub_forwarder = __commonJS({
67464
67491
  [Symbol.toStringTag]: { value: "Module" }
67465
67492
  });
67466
67493
  require_chunk_Cek0wNdY();
67467
- var require_dist10 = require_dist_C7uZ_fOb();
67494
+ var require_dist10 = require_dist_BPlfW_CG();
67468
67495
  var require_formatter = require_formatter_DqAKDlvN();
67469
67496
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
67470
67497
  var HubForwarderDestination = class {
@@ -67601,7 +67628,7 @@ var require_liveness_monitor_addon = __commonJS({
67601
67628
  "use strict";
67602
67629
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
67603
67630
  require_chunk_Cek0wNdY();
67604
- var require_dist10 = require_dist_C7uZ_fOb();
67631
+ var require_dist10 = require_dist_BPlfW_CG();
67605
67632
  var NO_DEVICES = "liveness:no-devices";
67606
67633
  var ALL_OFFLINE = "liveness:all-devices-offline";
67607
67634
  var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
@@ -67791,7 +67818,7 @@ var require_local_auth_addon = __commonJS({
67791
67818
  [Symbol.toStringTag]: { value: "Module" }
67792
67819
  });
67793
67820
  var require_chunk = require_chunk_Cek0wNdY();
67794
- var require_dist10 = require_dist_C7uZ_fOb();
67821
+ var require_dist10 = require_dist_BPlfW_CG();
67795
67822
  var node_crypto = __require("crypto");
67796
67823
  node_crypto = require_chunk.__toESM(node_crypto);
67797
67824
  var crypto$1 = __require("crypto");
@@ -75604,7 +75631,7 @@ var require_loki_logging = __commonJS({
75604
75631
  [Symbol.toStringTag]: { value: "Module" }
75605
75632
  });
75606
75633
  require_chunk_Cek0wNdY();
75607
- var require_dist10 = require_dist_C7uZ_fOb();
75634
+ var require_dist10 = require_dist_BPlfW_CG();
75608
75635
  function sanitizeLabelName(raw) {
75609
75636
  const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
75610
75637
  return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
@@ -76169,7 +76196,7 @@ var require_native_metrics_addon = __commonJS({
76169
76196
  [Symbol.toStringTag]: { value: "Module" }
76170
76197
  });
76171
76198
  var require_chunk = require_chunk_Cek0wNdY();
76172
- var require_dist10 = require_dist_C7uZ_fOb();
76199
+ var require_dist10 = require_dist_BPlfW_CG();
76173
76200
  var node_fs_promises = __require("fs/promises");
76174
76201
  var node_child_process = __require("child_process");
76175
76202
  var node_util = __require("util");
@@ -78791,7 +78818,7 @@ var require_filesystem_storage_addon = __commonJS({
78791
78818
  [Symbol.toStringTag]: { value: "Module" }
78792
78819
  });
78793
78820
  var require_chunk = require_chunk_Cek0wNdY();
78794
- var require_dist10 = require_dist_C7uZ_fOb();
78821
+ var require_dist10 = require_dist_BPlfW_CG();
78795
78822
  var node_crypto = __require("crypto");
78796
78823
  var node_fs_promises = __require("fs/promises");
78797
78824
  var node_path = __require("path");
@@ -79907,8 +79934,8 @@ var require_sqlite_settings_addon = __commonJS({
79907
79934
  [Symbol.toStringTag]: { value: "Module" }
79908
79935
  });
79909
79936
  var require_chunk = require_chunk_Cek0wNdY();
79910
- var require_dist10 = require_dist_C7uZ_fOb();
79911
- var require_retired_settings_keys = require_retired_settings_keys_CBU4_TJO();
79937
+ var require_dist10 = require_dist_BPlfW_CG();
79938
+ var require_retired_settings_keys = require_retired_settings_keys_DBY6ebwV();
79912
79939
  var node_crypto = __require("crypto");
79913
79940
  var node_fs = __require("fs");
79914
79941
  var node_module = __require("module");
@@ -82187,7 +82214,7 @@ var require_storage_orchestrator_addon = __commonJS({
82187
82214
  [Symbol.toStringTag]: { value: "Module" }
82188
82215
  });
82189
82216
  var require_chunk = require_chunk_Cek0wNdY();
82190
- var require_dist10 = require_dist_C7uZ_fOb();
82217
+ var require_dist10 = require_dist_BPlfW_CG();
82191
82218
  var node_crypto = __require("crypto");
82192
82219
  var node_fs_promises = __require("fs/promises");
82193
82220
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -84068,7 +84095,7 @@ var require_system_config_addon = __commonJS({
84068
84095
  [Symbol.toStringTag]: { value: "Module" }
84069
84096
  });
84070
84097
  require_chunk_Cek0wNdY();
84071
- var require_dist10 = require_dist_C7uZ_fOb();
84098
+ var require_dist10 = require_dist_BPlfW_CG();
84072
84099
  var SECTION_TITLES = {
84073
84100
  server: "Server",
84074
84101
  auth: "Authentication"
@@ -102129,7 +102156,7 @@ var require_winston_logging = __commonJS({
102129
102156
  [Symbol.toStringTag]: { value: "Module" }
102130
102157
  });
102131
102158
  var require_chunk = require_chunk_Cek0wNdY();
102132
- var require_dist10 = require_dist_C7uZ_fOb();
102159
+ var require_dist10 = require_dist_BPlfW_CG();
102133
102160
  var require_formatter = require_formatter_DqAKDlvN();
102134
102161
  var node_path = __require("path");
102135
102162
  node_path = require_chunk.__toESM(node_path);
@@ -114617,12 +114644,12 @@ var require_dist2 = __commonJS({
114617
114644
  }
114618
114645
  });
114619
114646
 
114620
- // ../system/dist/manifest-python-deps-CRTx_j4k.js
114621
- var require_manifest_python_deps_CRTx_j4k = __commonJS({
114622
- "../system/dist/manifest-python-deps-CRTx_j4k.js"(exports) {
114647
+ // ../system/dist/manifest-python-deps-w48vOhGR.js
114648
+ var require_manifest_python_deps_w48vOhGR = __commonJS({
114649
+ "../system/dist/manifest-python-deps-w48vOhGR.js"(exports) {
114623
114650
  "use strict";
114624
114651
  var require_chunk = require_chunk_Cek0wNdY();
114625
- require_dist_C7uZ_fOb();
114652
+ require_dist_BPlfW_CG();
114626
114653
  var node_crypto = __require("crypto");
114627
114654
  node_crypto = require_chunk.__toESM(node_crypto);
114628
114655
  var _camstack_types_node = require_node();
@@ -114728,6 +114755,152 @@ var require_manifest_python_deps_CRTx_j4k = __commonJS({
114728
114755
  const top = window2.top.map((d) => `${d.childId}:${d.sent}/${d.suppressed}`).join(",");
114729
114756
  return ` fanoutMode=uds:${window2.udsMode}/cross-node:${window2.crossNodeMode} children=${window2.childrenConnected} childrenUndeclared=${window2.childrenUndeclared} fanoutSent=${window2.fanoutSent} fanoutSuppressed=${window2.fanoutSuppressed} crossNodeDelivered=${window2.crossNodeDelivered} crossNodeSuppressed=${window2.crossNodeSuppressed}` + (top.length === 0 ? "" : ` fanoutTop=${top}`);
114730
114757
  }
114758
+ function createSocketDirectionCounters() {
114759
+ return {
114760
+ reqMessages: 0,
114761
+ reqBytes: 0,
114762
+ resMessages: 0,
114763
+ resBytes: 0,
114764
+ evtMessages: 0,
114765
+ evtBytes: 0
114766
+ };
114767
+ }
114768
+ function recordSocketFrame(counters, kind, bytes) {
114769
+ if (kind === "evt") {
114770
+ counters.evtMessages += 1;
114771
+ counters.evtBytes += bytes;
114772
+ return;
114773
+ }
114774
+ if (kind === "req") {
114775
+ counters.reqMessages += 1;
114776
+ counters.reqBytes += bytes;
114777
+ return;
114778
+ }
114779
+ counters.resMessages += 1;
114780
+ counters.resBytes += bytes;
114781
+ }
114782
+ function sampleSocketDirection(counters) {
114783
+ return {
114784
+ reqMessages: counters.reqMessages,
114785
+ reqBytes: counters.reqBytes,
114786
+ resMessages: counters.resMessages,
114787
+ resBytes: counters.resBytes,
114788
+ evtMessages: counters.evtMessages,
114789
+ evtBytes: counters.evtBytes
114790
+ };
114791
+ }
114792
+ var EMPTY_SOCKET_DIRECTION = {
114793
+ reqMessages: 0,
114794
+ reqBytes: 0,
114795
+ resMessages: 0,
114796
+ resBytes: 0,
114797
+ evtMessages: 0,
114798
+ evtBytes: 0
114799
+ };
114800
+ function socketDirectionMessages(sample) {
114801
+ return sample.reqMessages + sample.resMessages + sample.evtMessages;
114802
+ }
114803
+ function socketDirectionBytes(sample) {
114804
+ return sample.reqBytes + sample.resBytes + sample.evtBytes;
114805
+ }
114806
+ function createSocketPlaneReader(sources) {
114807
+ return () => {
114808
+ try {
114809
+ const registry = sources.registry();
114810
+ if (registry === null) return void 0;
114811
+ const listed = registry.listChildren();
114812
+ const peers = [];
114813
+ for (const child of listed) {
114814
+ const traffic = registry.getChildSocketTraffic(child.childId);
114815
+ if (traffic === null) continue;
114816
+ peers.push({
114817
+ peerId: child.childId,
114818
+ tx: traffic.tx,
114819
+ rx: traffic.rx
114820
+ });
114821
+ }
114822
+ return {
114823
+ peers,
114824
+ peersConnected: listed.length
114825
+ };
114826
+ } catch {
114827
+ return;
114828
+ }
114829
+ };
114830
+ }
114831
+ var SOCKET_PLANE_TOP_N = 5;
114832
+ var EMPTY_SOCKET_PLANE_BASELINE = { peers: /* @__PURE__ */ new Map() };
114833
+ function diffDirection(current, before) {
114834
+ const previous = before ?? EMPTY_SOCKET_DIRECTION;
114835
+ return {
114836
+ reqMessages: Math.max(0, current.reqMessages - previous.reqMessages),
114837
+ reqBytes: Math.max(0, current.reqBytes - previous.reqBytes),
114838
+ resMessages: Math.max(0, current.resMessages - previous.resMessages),
114839
+ resBytes: Math.max(0, current.resBytes - previous.resBytes),
114840
+ evtMessages: Math.max(0, current.evtMessages - previous.evtMessages),
114841
+ evtBytes: Math.max(0, current.evtBytes - previous.evtBytes)
114842
+ };
114843
+ }
114844
+ function addDirection(into, add) {
114845
+ return {
114846
+ reqMessages: into.reqMessages + add.reqMessages,
114847
+ reqBytes: into.reqBytes + add.reqBytes,
114848
+ resMessages: into.resMessages + add.resMessages,
114849
+ resBytes: into.resBytes + add.resBytes,
114850
+ evtMessages: into.evtMessages + add.evtMessages,
114851
+ evtBytes: into.evtBytes + add.evtBytes
114852
+ };
114853
+ }
114854
+ function peerMessages(delta) {
114855
+ return socketDirectionMessages(delta.tx) + socketDirectionMessages(delta.rx);
114856
+ }
114857
+ function diffSocketPlane(baseline, current, topN = 5) {
114858
+ const deltas = [];
114859
+ let tx = EMPTY_SOCKET_DIRECTION;
114860
+ let rx = EMPTY_SOCKET_DIRECTION;
114861
+ for (const sample of current.peers) {
114862
+ const before = baseline.peers.get(sample.peerId);
114863
+ const delta = {
114864
+ peerId: sample.peerId,
114865
+ tx: diffDirection(sample.tx, before?.tx),
114866
+ rx: diffDirection(sample.rx, before?.rx)
114867
+ };
114868
+ tx = addDirection(tx, delta.tx);
114869
+ rx = addDirection(rx, delta.rx);
114870
+ if (peerMessages(delta) > 0) deltas.push(delta);
114871
+ }
114872
+ return {
114873
+ peersConnected: current.peersConnected,
114874
+ peersMeasured: current.peers.length,
114875
+ tx,
114876
+ rx,
114877
+ top: deltas.toSorted((a, b) => peerMessages(b) - peerMessages(a) || a.peerId.localeCompare(b.peerId)).slice(0, topN)
114878
+ };
114879
+ }
114880
+ function createSocketPlaneMeter(reader, topN = 5) {
114881
+ let baseline = EMPTY_SOCKET_PLANE_BASELINE;
114882
+ return { read: () => {
114883
+ const current = reader();
114884
+ if (current === void 0) return void 0;
114885
+ const window2 = diffSocketPlane(baseline, current, topN);
114886
+ baseline = { peers: new Map(current.peers.map((p) => [p.peerId, p])) };
114887
+ return window2;
114888
+ } };
114889
+ }
114890
+ function kb(bytes) {
114891
+ return Math.round(bytes / 1024);
114892
+ }
114893
+ function formatDirection(sample) {
114894
+ return `req:${sample.reqMessages}/${kb(sample.reqBytes)}kB,res:${sample.resMessages}/${kb(sample.resBytes)}kB,evt:${sample.evtMessages}/${kb(sample.evtBytes)}kB`;
114895
+ }
114896
+ function formatPeer(delta) {
114897
+ return `${delta.peerId}:tx=${delta.tx.reqMessages}/${delta.tx.resMessages}/${delta.tx.evtMessages}:rx=${delta.rx.reqMessages}/${delta.rx.resMessages}/${delta.rx.evtMessages}:kB=${kb(socketDirectionBytes(delta.tx))}/${kb(socketDirectionBytes(delta.rx))}`;
114898
+ }
114899
+ function formatSocketPlane(window2) {
114900
+ if (window2 === void 0) return "";
114901
+ const top = window2.top.map(formatPeer).join(",");
114902
+ return ` socketPeers=${window2.peersMeasured}/${window2.peersConnected} socketTx=${formatDirection(window2.tx)} socketRx=${formatDirection(window2.rx)}` + (top.length === 0 ? "" : ` socketTop=${top}`);
114903
+ }
114731
114904
  var DECISIVE_HEAP_SPACES = ["old_space", "large_object_space"];
114732
114905
  var HEAP_SPACE_REPORT_MIN_MB = 32;
114733
114906
  var BYTES_PER_MB = 1048576;
@@ -114941,6 +115114,7 @@ var require_manifest_python_deps_CRTx_j4k = __commonJS({
114941
115114
  function startHeapWatch(label = HUB_MAIN_HEAP_WATCH_LABEL, sink = consoleSink, intervalMs = HEAP_WATCH_INTERVAL_MS, reclaimOptions, loopDelay = createLoopDelayMeter(), execArgv = process.execArgv, announceCeilingOrigin = true, rssBudget, probes) {
114942
115115
  const readSpaces = probes?.readSpaces ?? readHeapSpaces;
114943
115116
  const eventPlane = probes?.eventPlane === void 0 ? void 0 : createEventPlaneMeter(probes.eventPlane);
115117
+ const socketPlane = probes?.socketPlane === void 0 ? void 0 : createSocketPlaneMeter(probes.socketPlane);
114944
115118
  const readMemory = reclaimOptions?.readMemory ?? (() => process.memoryUsage());
114945
115119
  const now = reclaimOptions?.now ?? (() => Date.now());
114946
115120
  const triggerMb = reclaimOptions?.triggerMb ?? 1024;
@@ -114976,7 +115150,7 @@ var require_manifest_python_deps_CRTx_j4k = __commonJS({
114976
115150
  return;
114977
115151
  }
114978
115152
  const after = read();
114979
- sink.info(`[mem] reclaim ${label} stranded=${strandedMb(sample)}MB rss=${sample.rssMb}MB\u2192${after.rssMb}MB freed=${sample.rssMb - after.rssMb}MB arrayBuffers=${sample.arrayBuffersMb}MB\u2192${after.arrayBuffersMb}MB took=${now() - startedAt}ms`);
115153
+ sink.info(`[mem] reclaim ${label} stranded=${strandedMb(sample)}MB rss=${sample.rssMb}MB\u2192${after.rssMb}MB freed=${sample.rssMb - after.rssMb}MB arrayBuffers=${sample.arrayBuffersMb}MB\u2192${after.arrayBuffersMb}MB took=${now() - startedAt}ms heapUsed=${sample.heapUsedMb}MB\u2192${after.heapUsedMb}MB`);
114980
115154
  if (passesAtFloor >= 6 && !steadyStateAnnounced) {
114981
115155
  steadyStateAnnounced = true;
114982
115156
  const nextFloorMs = reclaimIntervalMs(passesAtFloor, minIntervalMs, steadyStateIntervalMs);
@@ -115018,7 +115192,7 @@ var require_manifest_python_deps_CRTx_j4k = __commonJS({
115018
115192
  const due = at - lastLoggedAt >= intervalMs;
115019
115193
  if (mode === "escalated" || due) {
115020
115194
  lastLoggedAt = at;
115021
- const line = format2(label, sample, loopDelay?.read(), budgetMb, `${formatHeapSpaces(readSpaces())}${formatEventPlane(eventPlane?.read())}`);
115195
+ const line = format2(label, sample, loopDelay?.read(), budgetMb, `${formatHeapSpaces(readSpaces())}${formatEventPlane(eventPlane?.read())}` + formatSocketPlane(socketPlane?.read()));
115022
115196
  if (sample.nearLimit) sink.warn(`${line} \u2014 APPROACHING HEAP LIMIT`);
115023
115197
  else if (mode === "escalated") sink.warn(`${line} \u2014 heap elevated, sampling every ${probeIntervalMs}ms`);
115024
115198
  else sink.info(line);
@@ -118232,6 +118406,33 @@ var require_manifest_python_deps_CRTx_j4k = __commonJS({
118232
118406
  chunks = [];
118233
118407
  /** Sum of `chunks[i].byteLength` — tracked so length checks cost nothing. */
118234
118408
  buffered = 0;
118409
+ /** Backing store for {@link lastFrameBytes}; see that getter. */
118410
+ sizes = [];
118411
+ /**
118412
+ * On-the-wire byte length (4-byte prefix included) of each frame returned by
118413
+ * the most recent {@link push}, index-aligned with the returned array.
118414
+ *
118415
+ * It exists because the frames come back DECODED, and a decoded value has no
118416
+ * memory of how many bytes it cost — so a caller counting received bytes per
118417
+ * message kind (`SocketChannel`, feeding the `[mem]` line's per-peer socket
118418
+ * attribution) could otherwise only charge a whole `data` chunk, which may
118419
+ * hold several frames of different kinds, or half of one.
118420
+ *
118421
+ * **Only the first `frames.length` entries are meaningful**, and the array is
118422
+ * never truncated. That is deliberate and it was measured on Node 24.17:
118423
+ * `sizes.length = 0` + `push` costs **35.1–35.9 ns** per call — V8 shrinks the
118424
+ * backing store and the next call re-grows it — which is 3 % of
118425
+ * `FrameDecoder.push` itself and 15× the counter it feeds. Writing in place
118426
+ * costs **0.06–0.13 ns**. On a path that runs ~22 000 times a second, an
118427
+ * instrument may not be the most expensive thing on the line it measures.
118428
+ *
118429
+ * Read it immediately after the `push` that produced it — it is a window onto
118430
+ * the decoder, not a value. Safe because `push` is only ever driven by a
118431
+ * socket `data` event, which Node never delivers re-entrantly.
118432
+ */
118433
+ get lastFrameBytes() {
118434
+ return this.sizes;
118435
+ }
118235
118436
  push(chunk) {
118236
118437
  if (chunk.byteLength > 0) {
118237
118438
  this.chunks.push(chunk);
@@ -118249,6 +118450,7 @@ var require_manifest_python_deps_CRTx_j4k = __commonJS({
118249
118450
  body = Buffer.allocUnsafeSlow(len);
118250
118451
  frame.copy(body, 0, HEADER_BYTES);
118251
118452
  } else body = frame.subarray(HEADER_BYTES);
118453
+ this.sizes[frames.length] = total;
118252
118454
  frames.push(decode(body));
118253
118455
  }
118254
118456
  return frames;
@@ -118328,6 +118530,11 @@ var require_manifest_python_deps_CRTx_j4k = __commonJS({
118328
118530
  };
118329
118531
  closed = false;
118330
118532
  closeFired = false;
118533
+ /** Frames written to the peer, cumulative, split by kind. See
118534
+ * {@link readTraffic} and `transport/socket-traffic.ts`. */
118535
+ txCounters = createSocketDirectionCounters();
118536
+ /** Frames read from the peer, cumulative, split by kind. */
118537
+ rxCounters = createSocketDirectionCounters();
118331
118538
  constructor(socket) {
118332
118539
  this.socket = socket;
118333
118540
  socket.on("data", (chunk) => this.onData(chunk));
@@ -118395,14 +118602,41 @@ var require_manifest_python_deps_CRTx_j4k = __commonJS({
118395
118602
  this.closed = true;
118396
118603
  this.socket.destroy();
118397
118604
  }
118605
+ /**
118606
+ * This channel's cumulative traffic, both directions, split by frame kind.
118607
+ *
118608
+ * Cumulative for the life of the channel: the reporting layer subtracts the
118609
+ * previous reading, because the question is a RATE ("which peer receives the
118610
+ * 22 500 writes/s") and not a total since boot.
118611
+ */
118612
+ readTraffic() {
118613
+ return {
118614
+ tx: sampleSocketDirection(this.txCounters),
118615
+ rx: sampleSocketDirection(this.rxCounters)
118616
+ };
118617
+ }
118398
118618
  send(frame) {
118399
118619
  if (this.closed) return;
118400
- this.socket.write(encodeFrame(frame));
118620
+ const encoded = encodeFrame(frame);
118621
+ recordSocketFrame(this.txCounters, frame.k, encoded.byteLength);
118622
+ this.socket.write(encoded);
118401
118623
  }
118402
118624
  onData(chunk) {
118403
- for (const f of this.decoder.push(chunk)) this.handleFrame(f);
118625
+ const frames = this.decoder.push(chunk);
118626
+ const sizes = this.decoder.lastFrameBytes;
118627
+ for (let i = 0; i < frames.length; i += 1) this.handleFrame(frames[i], sizes[i] ?? 0);
118404
118628
  }
118405
- async handleFrame(frame) {
118629
+ /**
118630
+ * `wireBytes` is the frame's on-the-wire length, counted HERE rather than in
118631
+ * `onData` on purpose: a peer that sends a frame this decoder can parse but
118632
+ * whose shape is not a `Frame` throws on `frame.k`, and inside this async
118633
+ * method that stays the rejected promise it has always been. Reading `.k`
118634
+ * one frame earlier, synchronously in the socket's `data` handler, would
118635
+ * turn the same malformed frame into an uncaught exception on the transport
118636
+ * — a diagnostic that can crash the process it watches.
118637
+ */
118638
+ async handleFrame(frame, wireBytes) {
118639
+ recordSocketFrame(this.rxCounters, frame.k, wireBytes);
118406
118640
  if (frame.k === "req") {
118407
118641
  try {
118408
118642
  const result = await this.requestHandler(frame.body);
@@ -119123,6 +119357,22 @@ var require_manifest_python_deps_CRTx_j4k = __commonJS({
119123
119357
  };
119124
119358
  }
119125
119359
  /**
119360
+ * This child's socket traffic — bytes and messages, both directions, split by
119361
+ * frame kind — or `null` when the child is gone or its channel keeps no
119362
+ * counters (an in-process or test transport).
119363
+ *
119364
+ * The event counters above cover ONE kind of frame and, once surfaced on
119365
+ * 2026-08-29, accounted for 4% of hub-main's ~44 000 socket syscalls/s. This
119366
+ * is the same question asked of every frame the channel moves, and it is the
119367
+ * only per-peer attribution that exists: `/proc` reports one `rchar`/`wchar`
119368
+ * pair for the whole process and has no per-socket breakdown.
119369
+ */
119370
+ getChildSocketTraffic(childId) {
119371
+ const entry = this.children.get(childId);
119372
+ if (entry === void 0) return null;
119373
+ return entry.channel.readTraffic?.() ?? null;
119374
+ }
119375
+ /**
119126
119376
  * The regime the counters above were produced under, read once from
119127
119377
  * `CAMSTACK_UDS_EVENT_FANOUT` at construction.
119128
119378
  *
@@ -121618,6 +121868,18 @@ var require_manifest_python_deps_CRTx_j4k = __commonJS({
121618
121868
  return DeviceRegistry;
121619
121869
  }
121620
121870
  });
121871
+ Object.defineProperty(exports, "EMPTY_SOCKET_DIRECTION", {
121872
+ enumerable: true,
121873
+ get: function() {
121874
+ return EMPTY_SOCKET_DIRECTION;
121875
+ }
121876
+ });
121877
+ Object.defineProperty(exports, "EMPTY_SOCKET_PLANE_BASELINE", {
121878
+ enumerable: true,
121879
+ get: function() {
121880
+ return EMPTY_SOCKET_PLANE_BASELINE;
121881
+ }
121882
+ });
121621
121883
  Object.defineProperty(exports, "EVENT_PLANE_TOP_N", {
121622
121884
  enumerable: true,
121623
121885
  get: function() {
@@ -121750,6 +122012,12 @@ var require_manifest_python_deps_CRTx_j4k = __commonJS({
121750
122012
  return RUNNER_RSS_BUDGET_ENV;
121751
122013
  }
121752
122014
  });
122015
+ Object.defineProperty(exports, "SOCKET_PLANE_TOP_N", {
122016
+ enumerable: true,
122017
+ get: function() {
122018
+ return SOCKET_PLANE_TOP_N;
122019
+ }
122020
+ });
121753
122021
  Object.defineProperty(exports, "SocketChannel", {
121754
122022
  enumerable: true,
121755
122023
  get: function() {
@@ -121948,6 +122216,24 @@ var require_manifest_python_deps_CRTx_j4k = __commonJS({
121948
122216
  return createParentUnownedCallHandler;
121949
122217
  }
121950
122218
  });
122219
+ Object.defineProperty(exports, "createSocketDirectionCounters", {
122220
+ enumerable: true,
122221
+ get: function() {
122222
+ return createSocketDirectionCounters;
122223
+ }
122224
+ });
122225
+ Object.defineProperty(exports, "createSocketPlaneMeter", {
122226
+ enumerable: true,
122227
+ get: function() {
122228
+ return createSocketPlaneMeter;
122229
+ }
122230
+ });
122231
+ Object.defineProperty(exports, "createSocketPlaneReader", {
122232
+ enumerable: true,
122233
+ get: function() {
122234
+ return createSocketPlaneReader;
122235
+ }
122236
+ });
121951
122237
  Object.defineProperty(exports, "createUdsAddonContext", {
121952
122238
  enumerable: true,
121953
122239
  get: function() {
@@ -122002,6 +122288,12 @@ var require_manifest_python_deps_CRTx_j4k = __commonJS({
122002
122288
  return diffEventPlane;
122003
122289
  }
122004
122290
  });
122291
+ Object.defineProperty(exports, "diffSocketPlane", {
122292
+ enumerable: true,
122293
+ get: function() {
122294
+ return diffSocketPlane;
122295
+ }
122296
+ });
122005
122297
  Object.defineProperty(exports, "emitHeapDiagnosticReport", {
122006
122298
  enumerable: true,
122007
122299
  get: function() {
@@ -122026,6 +122318,12 @@ var require_manifest_python_deps_CRTx_j4k = __commonJS({
122026
122318
  return formatHeapSpaces;
122027
122319
  }
122028
122320
  });
122321
+ Object.defineProperty(exports, "formatSocketPlane", {
122322
+ enumerable: true,
122323
+ get: function() {
122324
+ return formatSocketPlane;
122325
+ }
122326
+ });
122029
122327
  Object.defineProperty(exports, "getBrokerEventBus", {
122030
122328
  enumerable: true,
122031
122329
  get: function() {
@@ -122164,6 +122462,12 @@ var require_manifest_python_deps_CRTx_j4k = __commonJS({
122164
122462
  return reclaimIntervalMs;
122165
122463
  }
122166
122464
  });
122465
+ Object.defineProperty(exports, "recordSocketFrame", {
122466
+ enumerable: true,
122467
+ get: function() {
122468
+ return recordSocketFrame;
122469
+ }
122470
+ });
122167
122471
  Object.defineProperty(exports, "registerEventBusService", {
122168
122472
  enumerable: true,
122169
122473
  get: function() {
@@ -122194,6 +122498,12 @@ var require_manifest_python_deps_CRTx_j4k = __commonJS({
122194
122498
  return runNpm;
122195
122499
  }
122196
122500
  });
122501
+ Object.defineProperty(exports, "sampleSocketDirection", {
122502
+ enumerable: true,
122503
+ get: function() {
122504
+ return sampleSocketDirection;
122505
+ }
122506
+ });
122197
122507
  Object.defineProperty(exports, "selectReportedSpaces", {
122198
122508
  enumerable: true,
122199
122509
  get: function() {
@@ -122230,6 +122540,18 @@ var require_manifest_python_deps_CRTx_j4k = __commonJS({
122230
122540
  return shouldReclaim;
122231
122541
  }
122232
122542
  });
122543
+ Object.defineProperty(exports, "socketDirectionBytes", {
122544
+ enumerable: true,
122545
+ get: function() {
122546
+ return socketDirectionBytes;
122547
+ }
122548
+ });
122549
+ Object.defineProperty(exports, "socketDirectionMessages", {
122550
+ enumerable: true,
122551
+ get: function() {
122552
+ return socketDirectionMessages;
122553
+ }
122554
+ });
122233
122555
  Object.defineProperty(exports, "startHeapWatch", {
122234
122556
  enumerable: true,
122235
122557
  get: function() {
@@ -126068,7 +126390,7 @@ var require_dist3 = __commonJS({
126068
126390
  "use strict";
126069
126391
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
126070
126392
  var require_chunk = require_chunk_Cek0wNdY();
126071
- var require_dist10 = require_dist_C7uZ_fOb();
126393
+ var require_dist10 = require_dist_BPlfW_CG();
126072
126394
  var require_builtins_alerts_alerts_addon = require_alerts_addon();
126073
126395
  require_alerts();
126074
126396
  var require_formatter = require_formatter_DqAKDlvN();
@@ -126094,7 +126416,7 @@ var require_dist3 = __commonJS({
126094
126416
  var require_builtins_winston_logging_index = require_winston_logging();
126095
126417
  var require_file_data_plane = require_file_data_plane_DO8KbxCe();
126096
126418
  var require_tls$1 = require_tls_BxQlomxd();
126097
- var require_manifest_python_deps = require_manifest_python_deps_CRTx_j4k();
126419
+ var require_manifest_python_deps = require_manifest_python_deps_w48vOhGR();
126098
126420
  var require_resource_monitor = require_resource_monitor_CdnzxBLP();
126099
126421
  var require_custom_action_registry = require_custom_action_registry_jY0NOZK8();
126100
126422
  var zod = require_zod();
@@ -206475,6 +206797,8 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
206475
206797
  exports.DeviceManagerAddon = require_builtins_device_manager_device_manager_addon.DeviceManagerAddon;
206476
206798
  exports.DeviceRegistry = require_manifest_python_deps.DeviceRegistry;
206477
206799
  exports.DeviceStore = require_builtins_sqlite_storage_index.DeviceStore$1;
206800
+ exports.EMPTY_SOCKET_DIRECTION = require_manifest_python_deps.EMPTY_SOCKET_DIRECTION;
206801
+ exports.EMPTY_SOCKET_PLANE_BASELINE = require_manifest_python_deps.EMPTY_SOCKET_PLANE_BASELINE;
206478
206802
  exports.EVENT_PLANE_TOP_N = require_manifest_python_deps.EVENT_PLANE_TOP_N;
206479
206803
  exports.EVENT_TOPIC_PREFIX = require_manifest_python_deps.EVENT_TOPIC_PREFIX;
206480
206804
  exports.EngineManagerResolver = EngineManagerResolver;
@@ -206548,6 +206872,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
206548
206872
  exports.ReplEngine = ReplEngine;
206549
206873
  exports.RingBuffer = RingBuffer;
206550
206874
  exports.SERVER_AUTH_OID = require_tls$1.SERVER_AUTH_OID;
206875
+ exports.SOCKET_PLANE_TOP_N = require_manifest_python_deps.SOCKET_PLANE_TOP_N;
206551
206876
  exports.ScopedLogger = ScopedLogger;
206552
206877
  exports.ScopedTokenManager = require_builtins_local_auth_local_auth_addon.ScopedTokenManager;
206553
206878
  exports.SocketChannel = require_manifest_python_deps.SocketChannel;
@@ -206633,6 +206958,9 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
206633
206958
  exports.createReadinessService = createReadinessService;
206634
206959
  exports.createReadinessServiceForRegistry = createReadinessServiceForRegistry;
206635
206960
  exports.createScopedProcessManager = createScopedProcessManager;
206961
+ exports.createSocketDirectionCounters = require_manifest_python_deps.createSocketDirectionCounters;
206962
+ exports.createSocketPlaneMeter = require_manifest_python_deps.createSocketPlaneMeter;
206963
+ exports.createSocketPlaneReader = require_manifest_python_deps.createSocketPlaneReader;
206636
206964
  exports.createStreamProbeBrokerService = createStreamProbeBrokerService;
206637
206965
  exports.createUdsAddonContext = require_manifest_python_deps.createUdsAddonContext;
206638
206966
  exports.createUdsEventBridge = require_manifest_python_deps.createUdsEventBridge;
@@ -206646,6 +206974,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
206646
206974
  exports.describeRss = require_manifest_python_deps.describeRss;
206647
206975
  exports.detectWorkspacePackagesDir = detectWorkspacePackagesDir;
206648
206976
  exports.diffEventPlane = require_manifest_python_deps.diffEventPlane;
206977
+ exports.diffSocketPlane = require_manifest_python_deps.diffSocketPlane;
206649
206978
  Object.defineProperty(exports, "downloadBinary", {
206650
206979
  enumerable: true,
206651
206980
  get: function() {
@@ -206693,6 +207022,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
206693
207022
  exports.formatEventPlane = require_manifest_python_deps.formatEventPlane;
206694
207023
  exports.formatHeapSpaces = require_manifest_python_deps.formatHeapSpaces;
206695
207024
  exports.formatLogLine = require_formatter.formatLogLine;
207025
+ exports.formatSocketPlane = require_manifest_python_deps.formatSocketPlane;
206696
207026
  exports.getBrokerEventBus = require_manifest_python_deps.getBrokerEventBus;
206697
207027
  exports.getCapUsageRegistry = require_manifest_python_deps.getCapUsageRegistry;
206698
207028
  Object.defineProperty(exports, "getFfmpegDownloadUrl", {
@@ -206772,6 +207102,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
206772
207102
  exports.readTlsMode = require_tls$1.readTlsMode;
206773
207103
  exports.readinessKey = require_dist10.readinessKey;
206774
207104
  exports.reclaimIntervalMs = require_manifest_python_deps.reclaimIntervalMs;
207105
+ exports.recordSocketFrame = require_manifest_python_deps.recordSocketFrame;
206775
207106
  exports.registerEventBusService = require_manifest_python_deps.registerEventBusService;
206776
207107
  exports.registerLanHttpHandler = require_tls$1.registerLanHttpHandler;
206777
207108
  exports.reissueTlsLeaf = require_tls$1.reissueTlsLeaf;
@@ -206780,6 +207111,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
206780
207111
  exports.resolveNpmInvocation = require_manifest_python_deps.resolveNpmInvocation;
206781
207112
  exports.runHubAddonBoot = runHubAddonBoot;
206782
207113
  exports.runNpm = require_manifest_python_deps.runNpm;
207114
+ exports.sampleSocketDirection = require_manifest_python_deps.sampleSocketDirection;
206783
207115
  exports.scheduleSelfRestart = scheduleSelfRestart;
206784
207116
  exports.scopeKey = require_dist10.scopeKey;
206785
207117
  exports.scopesAllowAddon = require_dist10.scopesAllowAddon;
@@ -206790,6 +207122,8 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
206790
207122
  exports.setHubConnected = require_manifest_python_deps.setHubConnected;
206791
207123
  exports.setNodeEventInterest = require_manifest_python_deps.setNodeEventInterest;
206792
207124
  exports.shouldReclaim = require_manifest_python_deps.shouldReclaim;
207125
+ exports.socketDirectionBytes = require_manifest_python_deps.socketDirectionBytes;
207126
+ exports.socketDirectionMessages = require_manifest_python_deps.socketDirectionMessages;
206793
207127
  exports.startHeapWatch = require_manifest_python_deps.startHeapWatch;
206794
207128
  exports.startRunnerHeapWatch = require_manifest_python_deps.startRunnerHeapWatch;
206795
207129
  exports.strandedMb = require_manifest_python_deps.strandedMb;
@@ -227689,6 +228023,33 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
227689
228023
  deviceNative: true,
227690
228024
  mode: "singleton",
227691
228025
  deviceTypes: [require_sleep.DeviceType.Camera],
228026
+ /**
228027
+ * **Auth tier: `protected` on every method — deliberate, and load-bearing.**
228028
+ *
228029
+ * Talking through a camera is an OPERATE action, not a CONFIGURE one. This
228030
+ * cap has no configuration surface at all: all six methods open, feed and
228031
+ * close one live audio session against one `deviceId`. That is the same
228032
+ * authority as `ptz.move` or `snapshot.getSnapshot`, both `protected` — and
228033
+ * the opposite of `ptz.savePreset` / `snapshot.invalidateCache`, which are
228034
+ * `admin` because they change what the device IS.
228035
+ *
228036
+ * `protected` does not mean ungated: `protectedProcedure` runs the
228037
+ * `METHOD_ACCESS_MAP` scope check, and every method here is `scope: 'device'`
228038
+ * with `access: 'create'` and a `deviceId` in its input. So a caller needs a
228039
+ * grant that covers THAT camera at `create` — a `camera-viewer` (`view`
228040
+ * only) still cannot talk, and a grant on camera 5 cannot talk through
228041
+ * camera 7.
228042
+ *
228043
+ * Every method was `auth: 'admin'` from the initial commit, which made the
228044
+ * cap unreachable by every non-admin principal — `adminProcedure` throws
228045
+ * `FORBIDDEN: Admin required` BEFORE the scope check runs, so the scope
228046
+ * machinery generated for this cap (`METHOD_ACCESS_MAP`,
228047
+ * `DEVICE_SCOPED_CAPS`, `METHOD_DEVICE_SELECTORS`) was complete and dead. The
228048
+ * `camera-operator` scope preset has promised "PTZ control, intercom,
228049
+ * snapshots" since that same commit; the promise could not be kept. Recorded
228050
+ * as D289; `scripts/check-scope-preset-promises.ts` now fails the build if a
228051
+ * preset promises a cap no row of that preset can reach.
228052
+ */
227692
228053
  methods: {
227693
228054
  /**
227694
228055
  * Open a server-side WebRTC audio-only session. Returns an SDP
@@ -227701,7 +228062,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
227701
228062
  sdpOffer: zod.z.string()
227702
228063
  }), {
227703
228064
  kind: "mutation",
227704
- auth: "admin"
228065
+ auth: "protected"
227705
228066
  }),
227706
228067
  handleAnswer: require_sleep.method(zod.z.object({
227707
228068
  deviceId: zod.z.number(),
@@ -227709,7 +228070,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
227709
228070
  sdpAnswer: zod.z.string()
227710
228071
  }), zod.z.void(), {
227711
228072
  kind: "mutation",
227712
- auth: "admin"
228073
+ auth: "protected"
227713
228074
  }),
227714
228075
  /** Close explicitly. Server also auto-closes on 30s idle. */
227715
228076
  stopSession: require_sleep.method(zod.z.object({
@@ -227717,7 +228078,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
227717
228078
  sessionId: zod.z.string()
227718
228079
  }), zod.z.void(), {
227719
228080
  kind: "mutation",
227720
- auth: "admin"
228081
+ auth: "protected"
227721
228082
  }),
227722
228083
  /**
227723
228084
  * Open a raw-PCM talk session (no WebRTC SDP plumbing). Used by
@@ -227730,7 +228091,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
227730
228091
  */
227731
228092
  startTalkSession: require_sleep.method(zod.z.object({ deviceId: zod.z.number() }), zod.z.object({ sessionId: zod.z.string() }), {
227732
228093
  kind: "mutation",
227733
- auth: "admin"
228094
+ auth: "protected"
227734
228095
  }),
227735
228096
  /**
227736
228097
  * Push one chunk of talk-back audio onto the active talk session.
@@ -227765,12 +228126,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
227765
228126
  sequenceNumber: zod.z.number().int()
227766
228127
  }), zod.z.object({ accepted: zod.z.boolean() }), {
227767
228128
  kind: "mutation",
227768
- auth: "admin"
228129
+ auth: "protected"
227769
228130
  }),
227770
228131
  /** Close the raw-PCM talk session. Idempotent. */
227771
228132
  endTalkSession: require_sleep.method(zod.z.object({ deviceId: zod.z.number() }), zod.z.void(), {
227772
228133
  kind: "mutation",
227773
- auth: "admin"
228134
+ auth: "protected"
227774
228135
  })
227775
228136
  },
227776
228137
  events: { onStatusChanged: { data: zod.z.object({
@@ -245028,7 +245389,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
245028
245389
  {
245029
245390
  id: "camera-operator",
245030
245391
  label: "Camera operator",
245031
- description: "Everything `camera-viewer` does plus PTZ control, intercom, snapshots and recording start/stop. Cannot delete devices or recordings.",
245392
+ description: "Everything `camera-viewer` does plus live control of every granted camera \u2014 PTZ movement, intercom talk-back and on-demand snapshots. Cannot delete devices, and grants nothing on system-scope caps (recording control, users, addons).",
245032
245393
  rows: [{
245033
245394
  type: "category",
245034
245395
  target: "device",
@@ -401628,6 +401989,7 @@ var require_scope_access = __commonJS({
401628
401989
  "use strict";
401629
401990
  Object.defineProperty(exports, "__esModule", { value: true });
401630
401991
  exports.DEVICE_ENUMERATION_METHODS = void 0;
401992
+ exports.referencedDeviceIds = referencedDeviceIds;
401631
401993
  exports.checkScopeAccess = checkScopeAccess;
401632
401994
  var system_1 = require_dist3();
401633
401995
  var types_1 = require_dist4();
@@ -413553,6 +413915,25 @@ var require_trpc_router = __commonJS({
413553
413915
  }
413554
413916
  });
413555
413917
 
413918
+ // ../../server/backend/dist/api/trpc/trpc-error-device-tags.js
413919
+ var require_trpc_error_device_tags = __commonJS({
413920
+ "../../server/backend/dist/api/trpc/trpc-error-device-tags.js"(exports) {
413921
+ "use strict";
413922
+ Object.defineProperty(exports, "__esModule", { value: true });
413923
+ exports.trpcErrorDeviceTags = trpcErrorDeviceTags;
413924
+ var scope_access_js_1 = require_scope_access();
413925
+ function trpcErrorDeviceTags(path, input) {
413926
+ if (path === void 0)
413927
+ return {};
413928
+ const ids = (0, scope_access_js_1.referencedDeviceIds)(path, input);
413929
+ const first = ids[0];
413930
+ if (first === void 0)
413931
+ return {};
413932
+ return ids.length > 1 ? { deviceId: first, deviceCount: ids.length } : { deviceId: first };
413933
+ }
413934
+ }
413935
+ });
413936
+
413556
413937
  // ../../server/backend/dist/api/trpc/ws-request-census.js
413557
413938
  var require_ws_request_census = __commonJS({
413558
413939
  "../../server/backend/dist/api/trpc/ws-request-census.js"(exports) {
@@ -421635,6 +422016,7 @@ var require_main4 = __commonJS({
421635
422016
  var trpc_context_1 = require_trpc_context();
421636
422017
  var trpc_router_1 = require_trpc_router();
421637
422018
  var trpc_error_principal_1 = require_trpc_error_principal();
422019
+ var trpc_error_device_tags_1 = require_trpc_error_device_tags();
421638
422020
  var ws_request_census_1 = require_ws_request_census();
421639
422021
  var addon_route_jwt_gate_js_1 = require_addon_route_jwt_gate();
421640
422022
  var session_cookie_js_1 = require_session_cookie();
@@ -421748,6 +422130,17 @@ var require_main4 = __commonJS({
421748
422130
  return broker === void 0 ? null : (0, system_1.getMoleculerEventStats)(broker);
421749
422131
  },
421750
422132
  crossNodeMode: () => (0, system_1.readMoleculerFanoutMode)()
422133
+ }),
422134
+ // The fan-out counters above answered their own question and sharpened
422135
+ // this one: the event plane is 4% of this process's ~44 000 socket
422136
+ // syscalls/s. The other 96% had no instrument — `/proc` reports one
422137
+ // rchar/wchar pair per PROCESS and has no per-socket breakdown, so the
422138
+ // best attribution available was a correlation with `hub/pipeline-
422139
+ // analytics` computed from a runner whose rchar also counts page-cache
422140
+ // reads. These counters live on the channel itself, so the attribution is
422141
+ // per peer and per frame kind. Same lazy registry, same reason.
422142
+ socketPlane: (0, system_1.createSocketPlaneReader)({
422143
+ registry: () => moleculerForEventPlane?.childRegistry ?? null
421751
422144
  })
421752
422145
  });
421753
422146
  cleanupOrphanProcesses();
@@ -421933,9 +422326,13 @@ var require_main4 = __commonJS({
421933
422326
  (0, http_request_census_hook_1.recordTrpcHttpRequest)(httpRequestCensus, req, trpcCtx.user);
421934
422327
  return trpcCtx;
421935
422328
  },
421936
- onError: ({ path: trpcPath, error, ctx }) => {
422329
+ onError: ({ path: trpcPath, error, ctx, input }) => {
421937
422330
  const trpcLogger = app.get(logging_service_1.LoggingService).createLogger("tRPC");
421938
422331
  trpcLogger.warn("tRPC error", {
422332
+ // WHICH camera. A refusal on a device-scoped path that names no
422333
+ // deviceId cannot answer "one camera or all of them?" — the
422334
+ // question always asked first (2026-08-29, `intercom.startSession`).
422335
+ tags: (0, trpc_error_device_tags_1.trpcErrorDeviceTags)(trpcPath, input),
421939
422336
  meta: {
421940
422337
  code: error.code,
421941
422338
  path: trpcPath ?? "?",
@@ -422334,9 +422731,12 @@ var require_main4 = __commonJS({
422334
422731
  (0, ws_request_census_1.identifyWsCensusSession)(opts.res, (0, trpc_error_principal_1.describeTrpcPrincipal)(wsCtx.user));
422335
422732
  return wsCtx;
422336
422733
  },
422337
- onError: ({ path: trpcPath, error, ctx }) => {
422734
+ onError: ({ path: trpcPath, error, ctx, input }) => {
422338
422735
  const trpcLogger = app.get(logging_service_1.LoggingService).createLogger("tRPC:ws");
422339
422736
  trpcLogger.warn("tRPC error", {
422737
+ // The socket the viewer uses — this is the transport that logged the
422738
+ // four `intercom.startSession` refusals with no camera on them.
422739
+ tags: (0, trpc_error_device_tags_1.trpcErrorDeviceTags)(trpcPath, input),
422340
422740
  meta: {
422341
422741
  code: error.code,
422342
422742
  path: trpcPath ?? "?",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "camstack",
3
- "version": "1.2.59",
3
+ "version": "1.2.61",
4
4
  "description": "CLI tool for managing and running CamStack server",
5
5
  "keywords": [
6
6
  "camstack",