@camstack/system 1.2.349 → 1.2.351

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 (68) hide show
  1. package/dist/addon-runner.js +2 -2
  2. package/dist/addon-runner.mjs +1 -1
  3. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  4. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  5. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  6. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  7. package/dist/builtins/alerts/alerts.addon.d.ts +8 -0
  8. package/dist/builtins/alerts/alerts.addon.js +146 -31
  9. package/dist/builtins/alerts/alerts.addon.mjs +146 -31
  10. package/dist/builtins/alerts/device-label.d.ts +8 -0
  11. package/dist/builtins/autotrack/index.js +1 -1
  12. package/dist/builtins/autotrack/index.mjs +1 -1
  13. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
  14. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
  15. package/dist/builtins/calendars/calendars.addon.js +3 -2
  16. package/dist/builtins/calendars/calendars.addon.mjs +3 -2
  17. package/dist/builtins/camera-grid/index.js +1 -1
  18. package/dist/builtins/camera-grid/index.mjs +1 -1
  19. package/dist/builtins/composer/composer.addon.js +2 -2
  20. package/dist/builtins/composer/composer.addon.mjs +2 -2
  21. package/dist/builtins/console-logging/index.js +1 -1
  22. package/dist/builtins/console-logging/index.mjs +1 -1
  23. package/dist/builtins/core-blocks/block-type-defs.d.ts +20 -5
  24. package/dist/builtins/core-blocks/core-blocks.addon.js +171 -26
  25. package/dist/builtins/core-blocks/core-blocks.addon.mjs +171 -26
  26. package/dist/builtins/device-manager/device-bindings-store.d.ts +3 -1
  27. package/dist/builtins/device-manager/device-manager.addon.js +5 -57
  28. package/dist/builtins/device-manager/device-manager.addon.mjs +5 -57
  29. package/dist/builtins/hub-forwarder/index.js +1 -1
  30. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  31. package/dist/builtins/liveness-monitor/liveness-checks.d.ts +7 -0
  32. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +8 -4
  33. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +8 -4
  34. package/dist/builtins/local-auth/local-auth.addon.js +1 -1
  35. package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
  36. package/dist/builtins/local-network/local-network.addon.js +1 -1
  37. package/dist/builtins/local-network/local-network.addon.mjs +1 -1
  38. package/dist/builtins/loki-logging/index.js +1 -1
  39. package/dist/builtins/loki-logging/index.mjs +1 -1
  40. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  41. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  42. package/dist/builtins/platform-probe/index.js +1 -1
  43. package/dist/builtins/platform-probe/index.mjs +1 -1
  44. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  45. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  46. package/dist/builtins/snapshot/index.js +1 -1
  47. package/dist/builtins/snapshot/index.mjs +1 -1
  48. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  49. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  50. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
  51. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
  52. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +2 -2
  53. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +2 -2
  54. package/dist/builtins/system-config/system-config.addon.js +1 -1
  55. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  56. package/dist/builtins/winston-logging/index.js +1 -1
  57. package/dist/builtins/winston-logging/index.mjs +1 -1
  58. package/dist/{child-cap-dispatch-Pkx_sEKR.mjs → child-cap-dispatch-BAfa6tjj.mjs} +1 -1
  59. package/dist/{child-cap-dispatch-DiDBYNY4.js → child-cap-dispatch-B_0-zpI6.js} +1 -1
  60. package/dist/{composition-sources-w_NIID5d.js → composition-sources-CUfM-BYp.js} +1 -1
  61. package/dist/{composition-sources-DK-hFG7I.mjs → composition-sources-CoFGIGCc.mjs} +1 -1
  62. package/dist/{dist-C6CPaa8G.mjs → dist-DADwBtU5.mjs} +144 -13
  63. package/dist/{dist-DvAczrLl.js → dist-DeGPW01G.js} +144 -13
  64. package/dist/index.js +2 -2
  65. package/dist/index.mjs +2 -2
  66. package/dist/{retired-settings-keys-BQYjCJWI.js → retired-settings-keys-D8G5o4Fc.js} +1 -1
  67. package/dist/{retired-settings-keys-tmMQQ9OH.mjs → retired-settings-keys-bUUnyTMg.mjs} +1 -1
  68. package/package.json +1 -1
@@ -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-DvAczrLl.js");
7
- const require_retired_settings_keys = require("../../retired-settings-keys-BQYjCJWI.js");
6
+ const require_dist = require("../../dist-DeGPW01G.js");
7
+ const require_retired_settings_keys = require("../../retired-settings-keys-D8G5o4Fc.js");
8
8
  let zod = require("zod");
9
9
  let node_crypto = require("node:crypto");
10
10
  let _camstack_types_node = require("@camstack/types/node");
@@ -1621,16 +1621,6 @@ async function listDeviceIdsByCaps(deps, input) {
1621
1621
  const wanted = new Set(input.capNames);
1622
1622
  return (await getAllBindings(deps)).filter((row) => row.entries.some((entry) => wanted.has(entry.capName))).map((row) => row.deviceId);
1623
1623
  }
1624
- /**
1625
- * Resolve a numeric deviceId to a stableId via persisted meta.
1626
- * Used only by the device-identity section of the device-details
1627
- * aggregator (see `buildBaseDeviceSection`) to surface the stableId as
1628
- * a readonly display field. All runtime/registry lookups are keyed by
1629
- * numeric deviceId; this helper is display-only.
1630
- */
1631
- async function lookupPersistedStableId(deps, deviceId) {
1632
- return (await deps.rows.get(deviceId))?.meta.stableId;
1633
- }
1634
1624
  //#endregion
1635
1625
  //#region src/builtins/device-manager/day-night-config-schema.ts
1636
1626
  var MODE_LABELS = {
@@ -3653,52 +3643,9 @@ async function deriveDeviceConfigContribution(deps, registry, def, entry, device
3653
3643
  async function buildBaseDeviceSection(deps, deviceId) {
3654
3644
  const hubRegistry = deps.ctx.kernel?.deviceRegistry;
3655
3645
  const hubLocal = hubRegistry ? resolveDeviceById(hubRegistry, deviceId) : null;
3656
- const stableId = hubLocal?.device.stableId ?? await lookupPersistedStableId(deps.bindingsDeps, deviceId);
3657
3646
  const nativeOwner = resolveNativeDeviceOwner(deps, deviceId);
3658
- const addonId = hubLocal?.addonId ?? nativeOwner?.addonId ?? null;
3659
3647
  if (!hubLocal && !nativeOwner) return null;
3660
- const sections = [{
3661
- id: "device-identity",
3662
- title: "Identity",
3663
- tab: "general",
3664
- order: 0,
3665
- fields: [
3666
- {
3667
- type: "text",
3668
- key: "_deviceId",
3669
- label: "Device ID",
3670
- readonlyField: true,
3671
- value: String(deviceId)
3672
- },
3673
- {
3674
- type: "text",
3675
- key: "_stableId",
3676
- label: "Stable ID",
3677
- readonlyField: true,
3678
- value: stableId ?? ""
3679
- },
3680
- {
3681
- type: "text",
3682
- key: "_addonId",
3683
- label: "Driver",
3684
- readonlyField: true,
3685
- value: addonId ?? "unknown"
3686
- },
3687
- ...hubLocal ? [{
3688
- type: "text",
3689
- key: "_type",
3690
- label: "Type",
3691
- readonlyField: true,
3692
- value: hubLocal.device.type
3693
- }, {
3694
- type: "text",
3695
- key: "_online",
3696
- label: "Online",
3697
- readonlyField: true,
3698
- value: hubLocal.device.online ? "yes" : "no"
3699
- }] : []
3700
- ]
3701
- }];
3648
+ const sections = [];
3702
3649
  const driverResult = await resolveDriverConfigSchema(deps, deviceId, hubLocal);
3703
3650
  if (driverResult.status === "ok") for (const section of driverResult.schema.sections) sections.push({
3704
3651
  id: section.id,
@@ -3722,6 +3669,7 @@ async function buildBaseDeviceSection(deps, deviceId) {
3722
3669
  variant: "warning"
3723
3670
  }]
3724
3671
  });
3672
+ if (sections.length === 0) return null;
3725
3673
  return {
3726
3674
  sections,
3727
3675
  ...driverResult.status === "ok" && driverResult.schema.tabs ? { tabs: [...driverResult.schema.tabs] } : {}
@@ -4950,7 +4898,7 @@ async function reloadMigratedDevices(pctx, targets) {
4950
4898
  * keyed by the number in a separate store, and until 2026-09-01 they simply
4951
4899
  * stayed put. Measured on the live hub after replacing a Hikvision (id 618)
4952
4900
  * with a Reolink: device 618 — Reolink hardware — was dialled at
4953
- * `192.168.1.245:80` with `deviceCache.model="DS-2DE2A404IW-DE3/W"`, the
4901
+ * `192.168.x.x:80` with `deviceCache.model="DS-2DE2A404IW-DE3/W"`, the
4954
4902
  * Hikvision's address, credentials and cached model, and never came online.
4955
4903
  * Device 4362 wore the Reolink's config on Hikvision hardware. The two devices
4956
4904
  * were wearing each other's identity.
@@ -1,5 +1,5 @@
1
- import { $t as normalizeUnit, At as formatMinutes, C as FieldClaimSchema, Ct as enumerateSchemaFields, E as LocationIconIdSchema, Et as expandContainer, F as STREAM_PROFILE_META, Gn as DeviceFeature, Ht as locationIconKey, Jn as errMsg, Kn as DeviceRole, O as MINUTES_PER_DAY, Rt as legacyAutoLinkIds, S as FieldClaimModeSchema, St as enumerateItemArrayFields, Yn as BaseAddon, Z as buildStreamParamsConfigSchema, _ as DAY_NAMES, _t as deviceExtensionCapability, b as DeviceStatusSchema, br as EventCategory, bt as deviceStatusCapability, lt as createDeviceExtensionProvider, mn as runtimeStatePolicyFor, mt as defineExtensionSlotProvider, nn as parseStreamParamsFormPatch, o as CAMERA_SWITCH_ORDER, qn as DeviceType, s as CAP_NAMES_WITH_STATUS, t as ALL_CAPABILITY_DEFINITIONS, tr as WELL_KNOWN_TAB_MAP, ur as isDeviceConfigCap, vr as sleep$1, vt as deviceManagerCapability, yn as siteZoneKey, yt as deviceStateCapability } from "../../dist-C6CPaa8G.mjs";
2
- import { n as purgeRetiredSettingsRows } from "../../retired-settings-keys-tmMQQ9OH.mjs";
1
+ import { $t as normalizeUnit, At as formatMinutes, C as FieldClaimSchema, Ct as enumerateSchemaFields, E as LocationIconIdSchema, Et as expandContainer, F as STREAM_PROFILE_META, Gn as DeviceFeature, Ht as locationIconKey, Jn as errMsg, Kn as DeviceRole, O as MINUTES_PER_DAY, Rt as legacyAutoLinkIds, S as FieldClaimModeSchema, St as enumerateItemArrayFields, Yn as BaseAddon, Z as buildStreamParamsConfigSchema, _ as DAY_NAMES, _t as deviceExtensionCapability, b as DeviceStatusSchema, br as EventCategory, bt as deviceStatusCapability, lt as createDeviceExtensionProvider, mn as runtimeStatePolicyFor, mt as defineExtensionSlotProvider, nn as parseStreamParamsFormPatch, o as CAMERA_SWITCH_ORDER, qn as DeviceType, s as CAP_NAMES_WITH_STATUS, t as ALL_CAPABILITY_DEFINITIONS, tr as WELL_KNOWN_TAB_MAP, ur as isDeviceConfigCap, vr as sleep$1, vt as deviceManagerCapability, yn as siteZoneKey, yt as deviceStateCapability } from "../../dist-DADwBtU5.mjs";
2
+ import { n as purgeRetiredSettingsRows } from "../../retired-settings-keys-bUUnyTMg.mjs";
3
3
  import { z } from "zod";
4
4
  import { randomUUID } from "node:crypto";
5
5
  import { canonicalDeviceFingerprint } from "@camstack/types/node";
@@ -1616,16 +1616,6 @@ async function listDeviceIdsByCaps(deps, input) {
1616
1616
  const wanted = new Set(input.capNames);
1617
1617
  return (await getAllBindings(deps)).filter((row) => row.entries.some((entry) => wanted.has(entry.capName))).map((row) => row.deviceId);
1618
1618
  }
1619
- /**
1620
- * Resolve a numeric deviceId to a stableId via persisted meta.
1621
- * Used only by the device-identity section of the device-details
1622
- * aggregator (see `buildBaseDeviceSection`) to surface the stableId as
1623
- * a readonly display field. All runtime/registry lookups are keyed by
1624
- * numeric deviceId; this helper is display-only.
1625
- */
1626
- async function lookupPersistedStableId(deps, deviceId) {
1627
- return (await deps.rows.get(deviceId))?.meta.stableId;
1628
- }
1629
1619
  //#endregion
1630
1620
  //#region src/builtins/device-manager/day-night-config-schema.ts
1631
1621
  var MODE_LABELS = {
@@ -3648,52 +3638,9 @@ async function deriveDeviceConfigContribution(deps, registry, def, entry, device
3648
3638
  async function buildBaseDeviceSection(deps, deviceId) {
3649
3639
  const hubRegistry = deps.ctx.kernel?.deviceRegistry;
3650
3640
  const hubLocal = hubRegistry ? resolveDeviceById(hubRegistry, deviceId) : null;
3651
- const stableId = hubLocal?.device.stableId ?? await lookupPersistedStableId(deps.bindingsDeps, deviceId);
3652
3641
  const nativeOwner = resolveNativeDeviceOwner(deps, deviceId);
3653
- const addonId = hubLocal?.addonId ?? nativeOwner?.addonId ?? null;
3654
3642
  if (!hubLocal && !nativeOwner) return null;
3655
- const sections = [{
3656
- id: "device-identity",
3657
- title: "Identity",
3658
- tab: "general",
3659
- order: 0,
3660
- fields: [
3661
- {
3662
- type: "text",
3663
- key: "_deviceId",
3664
- label: "Device ID",
3665
- readonlyField: true,
3666
- value: String(deviceId)
3667
- },
3668
- {
3669
- type: "text",
3670
- key: "_stableId",
3671
- label: "Stable ID",
3672
- readonlyField: true,
3673
- value: stableId ?? ""
3674
- },
3675
- {
3676
- type: "text",
3677
- key: "_addonId",
3678
- label: "Driver",
3679
- readonlyField: true,
3680
- value: addonId ?? "unknown"
3681
- },
3682
- ...hubLocal ? [{
3683
- type: "text",
3684
- key: "_type",
3685
- label: "Type",
3686
- readonlyField: true,
3687
- value: hubLocal.device.type
3688
- }, {
3689
- type: "text",
3690
- key: "_online",
3691
- label: "Online",
3692
- readonlyField: true,
3693
- value: hubLocal.device.online ? "yes" : "no"
3694
- }] : []
3695
- ]
3696
- }];
3643
+ const sections = [];
3697
3644
  const driverResult = await resolveDriverConfigSchema(deps, deviceId, hubLocal);
3698
3645
  if (driverResult.status === "ok") for (const section of driverResult.schema.sections) sections.push({
3699
3646
  id: section.id,
@@ -3717,6 +3664,7 @@ async function buildBaseDeviceSection(deps, deviceId) {
3717
3664
  variant: "warning"
3718
3665
  }]
3719
3666
  });
3667
+ if (sections.length === 0) return null;
3720
3668
  return {
3721
3669
  sections,
3722
3670
  ...driverResult.status === "ok" && driverResult.schema.tabs ? { tabs: [...driverResult.schema.tabs] } : {}
@@ -4945,7 +4893,7 @@ async function reloadMigratedDevices(pctx, targets) {
4945
4893
  * keyed by the number in a separate store, and until 2026-09-01 they simply
4946
4894
  * stayed put. Measured on the live hub after replacing a Hikvision (id 618)
4947
4895
  * with a Reolink: device 618 — Reolink hardware — was dialled at
4948
- * `192.168.1.245:80` with `deviceCache.model="DS-2DE2A404IW-DE3/W"`, the
4896
+ * `192.168.x.x:80` with `deviceCache.model="DS-2DE2A404IW-DE3/W"`, the
4949
4897
  * Hikvision's address, credentials and cached model, and never came online.
4950
4898
  * Device 4362 wore the Reolink's config on Hikvision hardware. The two devices
4951
4899
  * were wearing each other's identity.
@@ -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-DvAczrLl.js");
6
+ const require_dist = require("../../dist-DeGPW01G.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 { Ut as logDestinationCapability, Yn as BaseAddon } from "../../dist-C6CPaa8G.mjs";
1
+ import { Ut as logDestinationCapability, Yn as BaseAddon } from "../../dist-DADwBtU5.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;
@@ -4,6 +4,11 @@ export type RecordingActiveMode = RecordingStatus['activeMode'];
4
4
  /** What the monitor learned about one camera this tick. */
5
5
  export interface CameraFootage {
6
6
  readonly deviceId: number;
7
+ /**
8
+ * Operator-facing name. Prefer this in the finding message; the numeric id
9
+ * stays on `deviceId` for tags / stable finding ids.
10
+ */
11
+ readonly name?: string;
7
12
  readonly online: boolean;
8
13
  /**
9
14
  * ms-epoch of the newest recorded segment within the lookback window, or
@@ -44,6 +49,8 @@ export interface LivenessFinding {
44
49
  readonly message: string;
45
50
  /** Present on per-camera findings. Always the numeric id. */
46
51
  readonly deviceId?: number;
52
+ /** Operator name when known — alert surfaces prefer this over the id. */
53
+ readonly deviceName?: string;
47
54
  }
48
55
  /**
49
56
  * Evaluate every invariant against one tick's facts.
@@ -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-DvAczrLl.js");
3
+ const require_dist = require("../../dist-DeGPW01G.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";
@@ -35,12 +35,14 @@ function evaluateLiveness(facts) {
35
35
  const silentFor = facts.nowMs - cam.lastSegmentMs;
36
36
  if (silentFor <= facts.staleAfterMs) continue;
37
37
  if (cam.activeMode !== null && cam.activeMode !== "continuous") continue;
38
+ const label = typeof cam.name === "string" && cam.name.trim().length > 0 ? cam.name.trim() : `Camera ${String(cam.deviceId)}`;
38
39
  findings.push({
39
40
  id: `${NO_FOOTAGE_PREFIX}${cam.deviceId}`,
40
41
  severity: "error",
41
42
  title: "Recording stopped",
42
- message: `Camera ${cam.deviceId} is online and was recording, but has produced no segment for ${minutes(silentFor)} minutes.`,
43
- deviceId: cam.deviceId
43
+ message: `${label} is online and was recording, but has produced no segment for ${minutes(silentFor)} minutes.`,
44
+ deviceId: cam.deviceId,
45
+ ...typeof cam.name === "string" && cam.name.trim().length > 0 ? { deviceName: cam.name.trim() } : {}
44
46
  });
45
47
  }
46
48
  return findings;
@@ -153,6 +155,7 @@ var LivenessMonitorAddon = class extends require_dist.BaseAddon {
153
155
  const activeMode = lastSegmentMs !== null && nowMs - lastSegmentMs > staleAfterMs ? require_dist.RecordingStatusSchema.parse(await this.ctx.api.recordingArchive.getStatus.query({ deviceId: device.id })).activeMode : null;
154
156
  cameras.push({
155
157
  deviceId: device.id,
158
+ name: device.name,
156
159
  online: device.online === true,
157
160
  lastSegmentMs,
158
161
  activeMode
@@ -221,7 +224,8 @@ var LivenessMonitorAddon = class extends require_dist.BaseAddon {
221
224
  severity: finding.severity,
222
225
  title: finding.title,
223
226
  message: finding.message,
224
- ...finding.deviceId !== void 0 ? { deviceId: finding.deviceId } : {}
227
+ ...finding.deviceId !== void 0 ? { deviceId: finding.deviceId } : {},
228
+ ...finding.deviceName !== void 0 ? { name: finding.deviceName } : {}
225
229
  }));
226
230
  }
227
231
  for (const id of [...this.active]) {
@@ -1,4 +1,4 @@
1
- import { A as RECORDING_SOURCE_CAMSTACK_ADDON, Jn as errMsg, N as RecordingStatusSchema, Yn as BaseAddon, ar as createEvent, br as EventCategory } from "../../dist-C6CPaa8G.mjs";
1
+ import { A as RECORDING_SOURCE_CAMSTACK_ADDON, Jn as errMsg, N as RecordingStatusSchema, Yn as BaseAddon, ar as createEvent, br as EventCategory } from "../../dist-DADwBtU5.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";
@@ -33,12 +33,14 @@ function evaluateLiveness(facts) {
33
33
  const silentFor = facts.nowMs - cam.lastSegmentMs;
34
34
  if (silentFor <= facts.staleAfterMs) continue;
35
35
  if (cam.activeMode !== null && cam.activeMode !== "continuous") continue;
36
+ const label = typeof cam.name === "string" && cam.name.trim().length > 0 ? cam.name.trim() : `Camera ${String(cam.deviceId)}`;
36
37
  findings.push({
37
38
  id: `${NO_FOOTAGE_PREFIX}${cam.deviceId}`,
38
39
  severity: "error",
39
40
  title: "Recording stopped",
40
- message: `Camera ${cam.deviceId} is online and was recording, but has produced no segment for ${minutes(silentFor)} minutes.`,
41
- deviceId: cam.deviceId
41
+ message: `${label} is online and was recording, but has produced no segment for ${minutes(silentFor)} minutes.`,
42
+ deviceId: cam.deviceId,
43
+ ...typeof cam.name === "string" && cam.name.trim().length > 0 ? { deviceName: cam.name.trim() } : {}
42
44
  });
43
45
  }
44
46
  return findings;
@@ -151,6 +153,7 @@ var LivenessMonitorAddon = class extends BaseAddon {
151
153
  const activeMode = lastSegmentMs !== null && nowMs - lastSegmentMs > staleAfterMs ? RecordingStatusSchema.parse(await this.ctx.api.recordingArchive.getStatus.query({ deviceId: device.id })).activeMode : null;
152
154
  cameras.push({
153
155
  deviceId: device.id,
156
+ name: device.name,
154
157
  online: device.online === true,
155
158
  lastSegmentMs,
156
159
  activeMode
@@ -219,7 +222,8 @@ var LivenessMonitorAddon = class extends BaseAddon {
219
222
  severity: finding.severity,
220
223
  title: finding.title,
221
224
  message: finding.message,
222
- ...finding.deviceId !== void 0 ? { deviceId: finding.deviceId } : {}
225
+ ...finding.deviceId !== void 0 ? { deviceId: finding.deviceId } : {},
226
+ ...finding.deviceName !== void 0 ? { name: finding.deviceName } : {}
223
227
  }));
224
228
  }
225
229
  for (const id of [...this.active]) {
@@ -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-DvAczrLl.js");
6
+ const require_dist = require("../../dist-DeGPW01G.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 { Dn as userManagementCapability, I as ScopedTokenSchema, K as authProviderCapability, V as UserRecordSchema, Yn as BaseAddon, r as ApiKeyRecordSchema } from "../../dist-C6CPaa8G.mjs";
2
+ import { Dn as userManagementCapability, I as ScopedTokenSchema, K as authProviderCapability, V as UserRecordSchema, Yn as BaseAddon, r as ApiKeyRecordSchema } from "../../dist-DADwBtU5.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,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-DvAczrLl.js");
3
+ const require_dist = require("../../dist-DeGPW01G.js");
4
4
  const require_tls = require("../../tls-ue_Xefmv.js");
5
5
  let node_fs_promises = require("node:fs/promises");
6
6
  let node_path = require("node:path");
@@ -1,4 +1,4 @@
1
- import { Vt as localNetworkCapability, Yn as BaseAddon, br as EventCategory } from "../../dist-C6CPaa8G.mjs";
1
+ import { Vt as localNetworkCapability, Yn as BaseAddon, br as EventCategory } from "../../dist-DADwBtU5.mjs";
2
2
  import { S as readLanHttpState, _ as DEFAULT_LAN_HTTP_PORT, a as writeTlsMode, i as writeExtraSans, l as reissueTlsLeaf, n as readTlsAccessStatus, o as validateUploadedTls, r as readTlsMode, s as ensureTlsCert, t as readExtraSans, y as applyLanHttp } from "../../tls-DTlVWwAI.mjs";
3
3
  import { mkdir, writeFile } from "node:fs/promises";
4
4
  import { join } 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-DvAczrLl.js");
6
+ const require_dist = require("../../dist-DeGPW01G.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 { Ut as logDestinationCapability, Yn as BaseAddon } from "../../dist-C6CPaa8G.mjs";
1
+ import { Ut as logDestinationCapability, Yn as BaseAddon } from "../../dist-DADwBtU5.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-DvAczrLl.js");
6
+ const require_dist = require("../../dist-DeGPW01G.js");
7
7
  const require_proc_stat = require("../../proc-stat-DL-WUOhl.js");
8
8
  let node_fs_promises = require("node:fs/promises");
9
9
  let node_os = require("node:os");
@@ -1,4 +1,4 @@
1
- import { Jn as errMsg, Yn as BaseAddon, Yt as metricsProviderCapability, ar as createEvent, br as EventCategory, kt as foldSnapshotByFunction, ln as resolveBucketMs, sn as reducePoints } from "../../dist-C6CPaa8G.mjs";
1
+ import { Jn as errMsg, Yn as BaseAddon, Yt as metricsProviderCapability, ar as createEvent, br as EventCategory, kt as foldSnapshotByFunction, ln as resolveBucketMs, sn as reducePoints } from "../../dist-DADwBtU5.mjs";
2
2
  import { a as parseProcStat, i as nodeProcReader, n as elapsedSecSince, o as parseProcStatusRss, r as lifetimeCpuPercent, t as commandFromCmdline } from "../../proc-stat-CbC55Kqi.mjs";
3
3
  import { access, readFile, readdir } from "node:fs/promises";
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-DvAczrLl.js");
6
+ const require_dist = require("../../dist-DeGPW01G.js");
7
7
  let node_os = require("node:os");
8
8
  node_os = require_chunk.__toESM(node_os);
9
9
  let node_fs = require("node:fs");
@@ -1,5 +1,5 @@
1
1
  import { o as __toESM } from "../../chunk-CNf5ZN-e.mjs";
2
- import { Jn as errMsg, Yn as BaseAddon, _n as scoreRuntimes, br as EventCategory, in as platformProbeCapability, sr as emitReadiness, xt as enumerateInferenceDevices } from "../../dist-C6CPaa8G.mjs";
2
+ import { Jn as errMsg, Yn as BaseAddon, _n as scoreRuntimes, br as EventCategory, in as platformProbeCapability, sr as emitReadiness, xt as enumerateInferenceDevices } from "../../dist-DADwBtU5.mjs";
3
3
  import * as os from "node:os";
4
4
  import * as fs from "node:fs";
5
5
  import { execFile } from "node:child_process";
@@ -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-DvAczrLl.js");
6
+ const require_dist = require("../../dist-DeGPW01G.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 { Yn as BaseAddon, br as EventCategory } from "../../dist-C6CPaa8G.mjs";
1
+ import { Yn as BaseAddon, br as EventCategory } from "../../dist-DADwBtU5.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-DvAczrLl.js");
6
+ const require_dist = require("../../dist-DeGPW01G.js");
7
7
  const require_snapshot_courtesy = require("../../snapshot-courtesy-D_C5-nC0.js");
8
8
  let zod = require("zod");
9
9
  let node_crypto = require("node:crypto");
@@ -1,4 +1,4 @@
1
- import { En as streamQualityLabel, Gn as DeviceFeature, J as bareAddonId, Jn as errMsg, Jt as memoizePinnedFfmpeg, Y as batteryCapability, Yn as BaseAddon, a as BatteryStatusSchema, bn as snapshotCapability, br as EventCategory, fr as nodePin, ht as deriveBatteryPresence, qn as DeviceType } from "../../dist-C6CPaa8G.mjs";
1
+ import { En as streamQualityLabel, Gn as DeviceFeature, J as bareAddonId, Jn as errMsg, Jt as memoizePinnedFfmpeg, Y as batteryCapability, Yn as BaseAddon, a as BatteryStatusSchema, bn as snapshotCapability, br as EventCategory, fr as nodePin, ht as deriveBatteryPresence, qn as DeviceType } from "../../dist-DADwBtU5.mjs";
2
2
  import { i as renderCourtesyOverlayJpeg, n as courtesyCacheKey, r as renderCourtesyJpeg } from "../../snapshot-courtesy-CyFs1M3I.mjs";
3
3
  import { z } from "zod";
4
4
  import { randomUUID } from "node:crypto";
@@ -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-DvAczrLl.js");
6
+ const require_dist = require("../../dist-DeGPW01G.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 { Ot as filesystemBrowseCapability, Yn as BaseAddon, wn as storageProviderCapability } from "../../dist-C6CPaa8G.mjs";
1
+ import { Ot as filesystemBrowseCapability, Yn as BaseAddon, wn as storageProviderCapability } from "../../dist-DADwBtU5.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,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-DvAczrLl.js");
6
+ const require_dist = require("../../dist-DeGPW01G.js");
7
7
  const require_hub_cap_forward = require("../../hub-cap-forward-DmHNjbB0.js");
8
8
  let zod = require("zod");
9
9
  let node_crypto = require("node:crypto");
@@ -1745,7 +1745,7 @@ function resolveMinFreePercent(config, providerDefaultPercent, capacity, notice)
1745
1745
  *
1746
1746
  * Measured on the live hub, 2026-09-13. `storage.listLocations` returned two
1747
1747
  * `backups` locations with byte-identical capacity — `/data/backups` on
1748
- * `filesystem-storage` and `//192.168.1.89/backups` on `smb-storage`, both
1748
+ * `filesystem-storage` and `//192.168.x.x/backups` on `smb-storage`, both
1749
1749
  * `total 506107977728 / available 193348673536`. `owned` differed correctly
1750
1750
  * (9.9 GB vs 1.6 GB), so nothing about the rendering was at fault: the probe
1751
1751
  * simply never looked at the provider. It `path.resolve`d the SMB row's
@@ -1,4 +1,4 @@
1
- import { B as StorageMigrationJobSchema, Kt as mayReadLocation, L as StorageCleanupJobSchema, Mn as withLocationMode, Pt as isLocationEnabled, R as StorageLocationModeSchema, Sn as storageMigrationCapability, T as LegacyStorageLocationDefaultSchema, Tt as evictionPolicyOfLocation, Xt as modeMayWrite, Yn as BaseAddon, br as EventCategory, et as collectSecretConfigKeys, fn as resolveLocationMode, j as REDACTED_SECRET, jt as gbToBytes, pr as parseJsonObject, qt as mayWriteToLocation, vn as settingsStoreCapability, xn as storageCapability, z as StorageLocationTypeSchema, zt as legacyModeOf } from "../../dist-C6CPaa8G.mjs";
1
+ import { B as StorageMigrationJobSchema, Kt as mayReadLocation, L as StorageCleanupJobSchema, Mn as withLocationMode, Pt as isLocationEnabled, R as StorageLocationModeSchema, Sn as storageMigrationCapability, T as LegacyStorageLocationDefaultSchema, Tt as evictionPolicyOfLocation, Xt as modeMayWrite, Yn as BaseAddon, br as EventCategory, et as collectSecretConfigKeys, fn as resolveLocationMode, j as REDACTED_SECRET, jt as gbToBytes, pr as parseJsonObject, qt as mayWriteToLocation, vn as settingsStoreCapability, xn as storageCapability, z as StorageLocationTypeSchema, zt as legacyModeOf } from "../../dist-DADwBtU5.mjs";
2
2
  import { t as HUB_CAP_FWD_ACTION } from "../../hub-cap-forward-BdT320dq.mjs";
3
3
  import { z } from "zod";
4
4
  import { randomUUID } from "node:crypto";
@@ -1740,7 +1740,7 @@ function resolveMinFreePercent(config, providerDefaultPercent, capacity, notice)
1740
1740
  *
1741
1741
  * Measured on the live hub, 2026-09-13. `storage.listLocations` returned two
1742
1742
  * `backups` locations with byte-identical capacity — `/data/backups` on
1743
- * `filesystem-storage` and `//192.168.1.89/backups` on `smb-storage`, both
1743
+ * `filesystem-storage` and `//192.168.x.x/backups` on `smb-storage`, both
1744
1744
  * `total 506107977728 / available 193348673536`. `owned` differed correctly
1745
1745
  * (9.9 GB vs 1.6 GB), so nothing about the rendering was at fault: the probe
1746
1746
  * simply never looked at the provider. It `path.resolve`d the SMB row's
@@ -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-DvAczrLl.js");
6
+ const require_dist = require("../../dist-DeGPW01G.js");
7
7
  //#region src/builtins/system-config/system-config.addon.ts
8
8
  /**
9
9
  * Built-in `system-config` addon — Phase 4 of the settings redesign.
@@ -1,4 +1,4 @@
1
- import { Jn as errMsg, Yn as BaseAddon, lr as hydrateSchema } from "../../dist-C6CPaa8G.mjs";
1
+ import { Jn as errMsg, Yn as BaseAddon, lr as hydrateSchema } from "../../dist-DADwBtU5.mjs";
2
2
  //#region src/builtins/system-config/system-config.addon.ts
3
3
  /**
4
4
  * Built-in `system-config` addon — Phase 4 of the settings redesign.
@@ -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-DvAczrLl.js");
6
+ const require_dist = require("../../dist-DeGPW01G.js");
7
7
  const require_formatter = require("../../formatter-DqAKDlvN.js");
8
8
  let node_path = require("node:path");
9
9
  node_path = require_chunk.__toESM(node_path);
@@ -1,4 +1,4 @@
1
- import { Ut as logDestinationCapability, Yn as BaseAddon } from "../../dist-C6CPaa8G.mjs";
1
+ import { Ut as logDestinationCapability, Yn as BaseAddon } from "../../dist-DADwBtU5.mjs";
2
2
  import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
3
3
  import * as path$1 from "node:path";
4
4
  import path from "node:path";
@@ -1,4 +1,4 @@
1
- import { ar as createEvent, br as EventCategory$1 } from "./dist-C6CPaa8G.mjs";
1
+ import { ar as createEvent, br as EventCategory$1 } from "./dist-DADwBtU5.mjs";
2
2
  import { a as parseProcStat, i as nodeProcReader } from "./proc-stat-CbC55Kqi.mjs";
3
3
  import "./hub-cap-forward-BdT320dq.mjs";
4
4
  import * as crypto$1 from "node:crypto";
@@ -1,5 +1,5 @@
1
1
  const require_chunk = require("./chunk-Cek0wNdY.js");
2
- const require_dist = require("./dist-DvAczrLl.js");
2
+ const require_dist = require("./dist-DeGPW01G.js");
3
3
  const require_proc_stat = require("./proc-stat-DL-WUOhl.js");
4
4
  require("./hub-cap-forward-DmHNjbB0.js");
5
5
  let node_crypto = require("node:crypto");
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-DvAczrLl.js");
1
+ const require_dist = require("./dist-DeGPW01G.js");
2
2
  //#region src/builtins/core-blocks/composition-sources.ts
3
3
  /**
4
4
  * Describe what a composition reads and writes for SAVE-time validation
@@ -1,4 +1,4 @@
1
- import { Jn as errMsg, Vn as compositionSourceKey } from "./dist-C6CPaa8G.mjs";
1
+ import { Jn as errMsg, Vn as compositionSourceKey } from "./dist-DADwBtU5.mjs";
2
2
  //#region src/builtins/core-blocks/composition-sources.ts
3
3
  /**
4
4
  * Describe what a composition reads and writes for SAVE-time validation