@camstack/system 1.2.191 → 1.2.193

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  2. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  3. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  4. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  5. package/dist/builtins/alerts/alerts.addon.js +1 -1
  6. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  7. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
  8. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
  9. package/dist/builtins/console-logging/index.js +1 -1
  10. package/dist/builtins/console-logging/index.mjs +1 -1
  11. package/dist/builtins/core-blocks/core-blocks.addon.js +1 -1
  12. package/dist/builtins/core-blocks/core-blocks.addon.mjs +1 -1
  13. package/dist/builtins/device-manager/device-manager.addon.js +2 -2
  14. package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
  15. package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
  16. package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
  17. package/dist/builtins/hub-forwarder/index.js +1 -1
  18. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  19. package/dist/builtins/liveness-monitor/liveness-checks.d.ts +11 -21
  20. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +12 -6
  21. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +12 -6
  22. package/dist/builtins/local-auth/local-auth.addon.js +1 -1
  23. package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
  24. package/dist/builtins/local-network/local-network.addon.js +1 -1
  25. package/dist/builtins/local-network/local-network.addon.mjs +1 -1
  26. package/dist/builtins/loki-logging/index.js +1 -1
  27. package/dist/builtins/loki-logging/index.mjs +1 -1
  28. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  29. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  30. package/dist/builtins/platform-probe/index.js +1 -1
  31. package/dist/builtins/platform-probe/index.mjs +1 -1
  32. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  33. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  34. package/dist/builtins/snapshot/index.js +1 -1
  35. package/dist/builtins/snapshot/index.mjs +1 -1
  36. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  37. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  38. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
  39. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
  40. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  41. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  42. package/dist/builtins/system-config/system-config.addon.js +1 -1
  43. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  44. package/dist/builtins/winston-logging/index.js +1 -1
  45. package/dist/builtins/winston-logging/index.mjs +1 -1
  46. package/dist/{dist-TP8pJtEo.mjs → dist-1eWNHQel.mjs} +98 -3
  47. package/dist/{dist-Ci7Ln6Rt.js → dist-B0Cf6q_P.js} +103 -2
  48. package/dist/index.js +1 -1
  49. package/dist/index.mjs +1 -1
  50. package/dist/{retired-settings-keys-Ye3I5xd0.js → retired-settings-keys-mP95OCUi.js} +1 -1
  51. package/dist/{retired-settings-keys-B0SJy5Et.mjs → retired-settings-keys-nBzXKu6p.mjs} +1 -1
  52. package/package.json +1 -1
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-Ci7Ln6Rt.js");
6
+ const require_dist = require("../../dist-B0Cf6q_P.js");
7
7
  const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
8
8
  let node_crypto = require("node:crypto");
9
9
  let node_path = require("node:path");
@@ -1,4 +1,4 @@
1
- import { E as addonPagesCapability, Ft as BaseAddon, Pt as errMsg, sn as EventCategory } from "../../dist-TP8pJtEo.mjs";
1
+ import { D as addonPagesCapability, Ft as errMsg, It as BaseAddon, cn as EventCategory } from "../../dist-1eWNHQel.mjs";
2
2
  import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
3
3
  import { createHash, randomUUID } from "node:crypto";
4
4
  import * as path$1 from "node:path";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-Ci7Ln6Rt.js");
6
+ const require_dist = require("../../dist-B0Cf6q_P.js");
7
7
  const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
8
8
  let node_crypto = require("node:crypto");
9
9
  let node_path = require("node:path");
@@ -1,4 +1,4 @@
1
- import { Ft as BaseAddon, O as addonWidgetsCapability, Pt as errMsg, sn as EventCategory } from "../../dist-TP8pJtEo.mjs";
1
+ import { Ft as errMsg, It as BaseAddon, cn as EventCategory, k as addonWidgetsCapability } from "../../dist-1eWNHQel.mjs";
2
2
  import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
3
3
  import { createHash, randomUUID } from "node:crypto";
4
4
  import * as path$1 from "node:path";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-Ci7Ln6Rt.js");
6
+ const require_dist = require("../../dist-B0Cf6q_P.js");
7
7
  //#region src/builtins/alerts/prune-policy.ts
8
8
  /**
9
9
  * Ids older than `cutoffMs`, oldest first.
@@ -1,4 +1,4 @@
1
- import { Ft as BaseAddon, Jt as createEvent, Pt as errMsg, k as alertsCapability, n as AlertSchema, sn as EventCategory } from "../../dist-TP8pJtEo.mjs";
1
+ import { A as alertsCapability, Ft as errMsg, It as BaseAddon, Yt as createEvent, cn as EventCategory, n as AlertSchema } from "../../dist-1eWNHQel.mjs";
2
2
  //#region src/builtins/alerts/prune-policy.ts
3
3
  /**
4
4
  * Ids older than `cutoffMs`, oldest first.
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-Ci7Ln6Rt.js");
6
+ const require_dist = require("../../dist-B0Cf6q_P.js");
7
7
  let node_crypto = require("node:crypto");
8
8
  let buffer = require("buffer");
9
9
  let node_fs_promises = require("node:fs/promises");
@@ -1,4 +1,4 @@
1
- import { Ft as BaseAddon, j as backupCapability, sn as EventCategory } from "../../dist-TP8pJtEo.mjs";
1
+ import { It as BaseAddon, M as backupCapability, cn as EventCategory } from "../../dist-1eWNHQel.mjs";
2
2
  import { randomBytes, randomUUID } from "node:crypto";
3
3
  import { Buffer as Buffer$1 } from "buffer";
4
4
  import * as fsp from "node:fs/promises";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-Ci7Ln6Rt.js");
6
+ const require_dist = require("../../dist-B0Cf6q_P.js");
7
7
  const require_formatter = require("../../formatter-DqAKDlvN.js");
8
8
  //#region src/builtins/console-logging/console-destination.ts
9
9
  var LEVEL_RANK = {
@@ -1,4 +1,4 @@
1
- import { Ft as BaseAddon, ct as logDestinationCapability } from "../../dist-TP8pJtEo.mjs";
1
+ import { It as BaseAddon, lt as logDestinationCapability } from "../../dist-1eWNHQel.mjs";
2
2
  import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
3
3
  //#region src/builtins/console-logging/console-destination.ts
4
4
  var LEVEL_RANK = {
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("../../chunk-Cek0wNdY.js");
3
- const require_dist = require("../../dist-Ci7Ln6Rt.js");
3
+ const require_dist = require("../../dist-B0Cf6q_P.js");
4
4
  let node_crypto = require("node:crypto");
5
5
  let node_fs_promises = require("node:fs/promises");
6
6
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -1,4 +1,4 @@
1
- import { Ft as BaseAddon, I as coreBlockAddonId, L as coreBlockIdFromAddonId, Pt as errMsg, R as coreBlocksCapability, c as CORE_BLOCK_ADDON_PREFIX, d as DeclaredDevices, l as CoreBlockSchema, s as CORE_BLOCKS_ADDON_ID } from "../../dist-TP8pJtEo.mjs";
1
+ import { Ft as errMsg, It as BaseAddon, L as coreBlockAddonId, R as coreBlockIdFromAddonId, c as CORE_BLOCK_ADDON_PREFIX, d as DeclaredDevices, l as CoreBlockSchema, s as CORE_BLOCKS_ADDON_ID, z as coreBlocksCapability } from "../../dist-1eWNHQel.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import * as fs from "node:fs/promises";
4
4
  import * as path$1 from "node:path";
@@ -3,8 +3,8 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-Ci7Ln6Rt.js");
7
- const require_retired_settings_keys = require("../../retired-settings-keys-Ye3I5xd0.js");
6
+ const require_dist = require("../../dist-B0Cf6q_P.js");
7
+ const require_retired_settings_keys = require("../../retired-settings-keys-mP95OCUi.js");
8
8
  let node_crypto = require("node:crypto");
9
9
  let _camstack_types_node = require("@camstack/types/node");
10
10
  //#region src/builtins/device-manager/adoption-job-engine.ts
@@ -1,5 +1,5 @@
1
- import { $t as isDeviceConfigCap, Bt as DeviceRole, Ft as BaseAddon, H as deviceManagerCapability, J as enumerateSchemaFields, P as buildStreamParamsConfigSchema, Pt as errMsg, U as deviceStateCapability, Vt as DeviceType, W as deviceStatusCapability, Wt as WELL_KNOWN_TAB_MAP, a as CAMERA_SWITCH_ORDER, b as STREAM_PROFILE_META, f as DeviceStatusSchema, ft as normalizeUnit, mt as parseStreamParamsFormPatch, o as CAP_NAMES_WITH_STATUS, on as sleep, q as enumerateItemArrayFields, sn as EventCategory, t as ALL_CAPABILITY_DEFINITIONS, xt as runtimeStatePolicyFor, yt as resolveContainerPrimaryChild, zt as DeviceFeature } from "../../dist-TP8pJtEo.mjs";
2
- import { n as purgeRetiredSettingsRows } from "../../retired-settings-keys-B0SJy5Et.mjs";
1
+ import { Bt as DeviceFeature, F as buildStreamParamsConfigSchema, Ft as errMsg, G as deviceStatusCapability, Gt as WELL_KNOWN_TAB_MAP, Ht as DeviceType, It as BaseAddon, J as enumerateItemArrayFields, St as runtimeStatePolicyFor, U as deviceManagerCapability, Vt as DeviceRole, W as deviceStateCapability, Y as enumerateSchemaFields, a as CAMERA_SWITCH_ORDER, bt as resolveContainerPrimaryChild, cn as EventCategory, en as isDeviceConfigCap, f as DeviceStatusSchema, ht as parseStreamParamsFormPatch, o as CAP_NAMES_WITH_STATUS, pt as normalizeUnit, sn as sleep, t as ALL_CAPABILITY_DEFINITIONS, x as STREAM_PROFILE_META } from "../../dist-1eWNHQel.mjs";
2
+ import { n as purgeRetiredSettingsRows } from "../../retired-settings-keys-nBzXKu6p.mjs";
3
3
  import { randomUUID } from "node:crypto";
4
4
  import { canonicalDeviceFingerprint } from "@camstack/types/node";
5
5
  //#region src/builtins/device-manager/adoption-job-engine.ts
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-Ci7Ln6Rt.js");
6
+ const require_dist = require("../../dist-B0Cf6q_P.js");
7
7
  //#region src/builtins/doorbell/trigger-engine.ts
8
8
  /**
9
9
  * Pure trigger logic for the virtual-doorbell builtin — edge detection over
@@ -1,4 +1,4 @@
1
- import { Ft as BaseAddon, G as doorbellCapability, Jt as createEvent, M as bareAddonId, Pt as errMsg, Vt as DeviceType, Y as evaluateSensorEdge, _ as SOURCE_CAPS, nt as isSameAddonId, rt as isSourceCap, sn as EventCategory, v as SOURCE_DEVICE_TYPES } from "../../dist-TP8pJtEo.mjs";
1
+ import { Ft as errMsg, Ht as DeviceType, It as BaseAddon, K as doorbellCapability, N as bareAddonId, X as evaluateSensorEdge, Yt as createEvent, cn as EventCategory, it as isSourceCap, rt as isSameAddonId, v as SOURCE_CAPS, y as SOURCE_DEVICE_TYPES } from "../../dist-1eWNHQel.mjs";
2
2
  //#region src/builtins/doorbell/trigger-engine.ts
3
3
  /**
4
4
  * Pure trigger logic for the virtual-doorbell builtin — edge detection over
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-Ci7Ln6Rt.js");
6
+ const require_dist = require("../../dist-B0Cf6q_P.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 { Ft as BaseAddon, ct as logDestinationCapability } from "../../dist-TP8pJtEo.mjs";
1
+ import { It as BaseAddon, lt as logDestinationCapability } from "../../dist-1eWNHQel.mjs";
2
2
  import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
3
3
  //#region src/builtins/hub-forwarder/hub-forwarder-destination.ts
4
4
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
@@ -1,24 +1,6 @@
1
- /**
2
- * The liveness invariants, as pure functions.
3
- *
4
- * On 2026-08-03 the hub ran for four hours with zero devices, zero published
5
- * streams and zero recordings, and nothing said a word. Three separate defects
6
- * caused it — optional chaining that no-oped, an `if` with no `else`, a JSON
7
- * parse that returned `{}` — and each was silent at the point of failure. All
8
- * three were fixed and a log line added at each. This module exists for the
9
- * CLASS rather than the instances: assert what must be true of a working node,
10
- * and report when it is not.
11
- *
12
- * **Every check here is unambiguous, on purpose.** An alert that fires on a
13
- * quiet night is one an operator learns to ignore, and an ignored alert is
14
- * worse than no alert. So "the pipeline emitted no tracks recently" is NOT a
15
- * check — a camera can legitimately see nothing for hours — while "a camera
16
- * that has been recording all day stopped producing segments" is: continuous
17
- * recording produces segments whether or not anything moves.
18
- *
19
- * I/O lives in the addon; everything here is a function of facts, so the
20
- * outage can be replayed in a test.
21
- */
1
+ import { RecordingStatus } from '@camstack/types';
2
+ /** The recording mode a camera is running under, as `recording.getStatus` reports it. */
3
+ export type RecordingActiveMode = RecordingStatus['activeMode'];
22
4
  /** What the monitor learned about one camera this tick. */
23
5
  export interface CameraFootage {
24
6
  readonly deviceId: number;
@@ -33,6 +15,14 @@ export interface CameraFootage {
33
15
  * stopped is a fault, a camera that never records is a configuration.
34
16
  */
35
17
  readonly lastSegmentMs: number | null;
18
+ /**
19
+ * The recording mode the camera runs under, asked only when it looks silent
20
+ * (`null` = not asked, the footage was recent). Silence is a fault ONLY for a
21
+ * `continuous` recorder: an `events` recorder that has seen nothing move is
22
+ * doing its job, and `off` is the operator's own switch. Seven events-mode
23
+ * cameras alerted for a whole quiet night on 2026-09-06.
24
+ */
25
+ readonly activeMode: RecordingActiveMode | null;
36
26
  }
37
27
  export interface LivenessFacts {
38
28
  readonly nowMs: number;
@@ -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-Ci7Ln6Rt.js");
3
+ const require_dist = require("../../dist-B0Cf6q_P.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";
@@ -34,6 +34,7 @@ function evaluateLiveness(facts) {
34
34
  if (!cam.online) continue;
35
35
  const silentFor = facts.nowMs - cam.lastSegmentMs;
36
36
  if (silentFor <= facts.staleAfterMs) continue;
37
+ if (cam.activeMode !== null && cam.activeMode !== "continuous") continue;
37
38
  findings.push({
38
39
  id: `${NO_FOOTAGE_PREFIX}${cam.deviceId}`,
39
40
  severity: "error",
@@ -147,11 +148,16 @@ var LivenessMonitorAddon = class extends require_dist.BaseAddon {
147
148
  };
148
149
  const cameraDevices = devices.filter((d) => d.isCamera === true);
149
150
  const cameras = [];
150
- for (const device of cameraDevices) cameras.push({
151
- deviceId: device.id,
152
- online: device.online === true,
153
- lastSegmentMs: await this.lastSegmentMs(device.id, nowMs, staleAfterMs)
154
- });
151
+ for (const device of cameraDevices) {
152
+ const lastSegmentMs = await this.lastSegmentMs(device.id, nowMs, staleAfterMs);
153
+ const activeMode = lastSegmentMs !== null && nowMs - lastSegmentMs > staleAfterMs ? require_dist.RecordingStatusSchema.parse(await this.ctx.api.recording.getStatus.query({ deviceId: device.id })).activeMode : null;
154
+ cameras.push({
155
+ deviceId: device.id,
156
+ online: device.online === true,
157
+ lastSegmentMs,
158
+ activeMode
159
+ });
160
+ }
155
161
  return {
156
162
  nowMs,
157
163
  deviceCount: devices.length,
@@ -1,4 +1,4 @@
1
- import { Ft as BaseAddon, Jt as createEvent, Pt as errMsg, sn as EventCategory } from "../../dist-TP8pJtEo.mjs";
1
+ import { Ft as errMsg, It as BaseAddon, Yt as createEvent, _ as RecordingStatusSchema, cn as EventCategory } from "../../dist-1eWNHQel.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";
@@ -32,6 +32,7 @@ function evaluateLiveness(facts) {
32
32
  if (!cam.online) continue;
33
33
  const silentFor = facts.nowMs - cam.lastSegmentMs;
34
34
  if (silentFor <= facts.staleAfterMs) continue;
35
+ if (cam.activeMode !== null && cam.activeMode !== "continuous") continue;
35
36
  findings.push({
36
37
  id: `${NO_FOOTAGE_PREFIX}${cam.deviceId}`,
37
38
  severity: "error",
@@ -145,11 +146,16 @@ var LivenessMonitorAddon = class extends BaseAddon {
145
146
  };
146
147
  const cameraDevices = devices.filter((d) => d.isCamera === true);
147
148
  const cameras = [];
148
- for (const device of cameraDevices) cameras.push({
149
- deviceId: device.id,
150
- online: device.online === true,
151
- lastSegmentMs: await this.lastSegmentMs(device.id, nowMs, staleAfterMs)
152
- });
149
+ for (const device of cameraDevices) {
150
+ const lastSegmentMs = await this.lastSegmentMs(device.id, nowMs, staleAfterMs);
151
+ const activeMode = lastSegmentMs !== null && nowMs - lastSegmentMs > staleAfterMs ? RecordingStatusSchema.parse(await this.ctx.api.recording.getStatus.query({ deviceId: device.id })).activeMode : null;
152
+ cameras.push({
153
+ deviceId: device.id,
154
+ online: device.online === true,
155
+ lastSegmentMs,
156
+ activeMode
157
+ });
158
+ }
153
159
  return {
154
160
  nowMs,
155
161
  deviceCount: devices.length,
@@ -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-Ci7Ln6Rt.js");
6
+ const require_dist = require("../../dist-B0Cf6q_P.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 { A as authProviderCapability, Ft as BaseAddon, T as UserRecordSchema, jt as userManagementCapability, r as ApiKeyRecordSchema, x as ScopedTokenSchema } from "../../dist-TP8pJtEo.mjs";
2
+ import { E as UserRecordSchema, It as BaseAddon, Mt as userManagementCapability, S as ScopedTokenSchema, j as authProviderCapability, r as ApiKeyRecordSchema } from "../../dist-1eWNHQel.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-Ci7Ln6Rt.js");
3
+ const require_dist = require("../../dist-B0Cf6q_P.js");
4
4
  const require_tls = require("../../tls-BxQlomxd.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 { Ft as BaseAddon, sn as EventCategory, st as localNetworkCapability } from "../../dist-TP8pJtEo.mjs";
1
+ import { It as BaseAddon, cn as EventCategory, ct as localNetworkCapability } from "../../dist-1eWNHQel.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-DOTmtLCW.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-Ci7Ln6Rt.js");
6
+ const require_dist = require("../../dist-B0Cf6q_P.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 { Ft as BaseAddon, ct as logDestinationCapability } from "../../dist-TP8pJtEo.mjs";
1
+ import { It as BaseAddon, lt as logDestinationCapability } from "../../dist-1eWNHQel.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-Ci7Ln6Rt.js");
6
+ const require_dist = require("../../dist-B0Cf6q_P.js");
7
7
  let node_fs_promises = require("node:fs/promises");
8
8
  let node_child_process = require("node:child_process");
9
9
  let node_util = require("node:util");
@@ -1,4 +1,4 @@
1
- import { Ft as BaseAddon, Jt as createEvent, Pt as errMsg, Q as foldSnapshotByFunction, _t as reducePoints, dt as metricsProviderCapability, sn as EventCategory, vt as resolveBucketMs } from "../../dist-TP8pJtEo.mjs";
1
+ import { $ as foldSnapshotByFunction, Ft as errMsg, It as BaseAddon, Yt as createEvent, cn as EventCategory, ft as metricsProviderCapability, vt as reducePoints, yt as resolveBucketMs } from "../../dist-1eWNHQel.mjs";
2
2
  import { readFile, readdir } from "node:fs/promises";
3
3
  import { execFile, execFileSync } from "node:child_process";
4
4
  import { promisify } from "node:util";
@@ -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-Ci7Ln6Rt.js");
6
+ const require_dist = require("../../dist-B0Cf6q_P.js");
7
7
  let node_child_process = require("node:child_process");
8
8
  let node_util = require("node:util");
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 { Ft as BaseAddon, K as enumerateInferenceDevices, Pt as errMsg, Xt as emitReadiness, ht as platformProbeCapability, sn as EventCategory, wt as scoreRuntimes } from "../../dist-TP8pJtEo.mjs";
2
+ import { Ft as errMsg, It as BaseAddon, Tt as scoreRuntimes, Zt as emitReadiness, cn as EventCategory, gt as platformProbeCapability, q as enumerateInferenceDevices } from "../../dist-1eWNHQel.mjs";
3
3
  import { execFile } from "node:child_process";
4
4
  import { promisify } from "node:util";
5
5
  import * as fs from "node:fs";
@@ -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-Ci7Ln6Rt.js");
6
+ const require_dist = require("../../dist-B0Cf6q_P.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 { Ft as BaseAddon, sn as EventCategory } from "../../dist-TP8pJtEo.mjs";
1
+ import { It as BaseAddon, cn as EventCategory } from "../../dist-1eWNHQel.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-Ci7Ln6Rt.js");
6
+ const require_dist = require("../../dist-B0Cf6q_P.js");
7
7
  let zod = require("zod");
8
8
  let node_crypto = require("node:crypto");
9
9
  let _camstack_types_node = require("@camstack/types/node");
@@ -1,4 +1,4 @@
1
- import { At as streamQualityLabel, Et as snapshotCapability, Ft as BaseAddon, M as bareAddonId, N as batteryCapability, Pt as errMsg, V as deriveBatteryPresence, Vt as DeviceType, en as nodePin, i as BatteryStatusSchema, sn as EventCategory, zt as DeviceFeature } from "../../dist-TP8pJtEo.mjs";
1
+ import { Bt as DeviceFeature, Dt as snapshotCapability, Ft as errMsg, H as deriveBatteryPresence, Ht as DeviceType, It as BaseAddon, N as bareAddonId, P as batteryCapability, cn as EventCategory, i as BatteryStatusSchema, jt as streamQualityLabel, tn as nodePin } from "../../dist-1eWNHQel.mjs";
2
2
  import { z } from "zod";
3
3
  import { randomUUID } from "node:crypto";
4
4
  import { signExpiringUrl, verifyExpiringUrl } from "@camstack/types/node";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-Ci7Ln6Rt.js");
6
+ const require_dist = require("../../dist-B0Cf6q_P.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 { Ft as BaseAddon, Z as filesystemBrowseCapability, kt as storageProviderCapability } from "../../dist-TP8pJtEo.mjs";
1
+ import { At as storageProviderCapability, It as BaseAddon, Q as filesystemBrowseCapability } from "../../dist-1eWNHQel.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-Ci7Ln6Rt.js");
6
+ const require_dist = require("../../dist-B0Cf6q_P.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");
@@ -1,4 +1,4 @@
1
- import { C as StorageLocationTypeSchema, Dt as storageCapability, F as collectSecretConfigKeys, Ft as BaseAddon, Ot as storageMigrationCapability, S as StorageCleanupJobSchema, Tt as settingsStoreCapability, h as REDACTED_SECRET, tn as parseJsonObject, w as StorageMigrationJobSchema } from "../../dist-TP8pJtEo.mjs";
1
+ import { C as StorageCleanupJobSchema, Et as settingsStoreCapability, I as collectSecretConfigKeys, It as BaseAddon, Ot as storageCapability, T as StorageMigrationJobSchema, h as REDACTED_SECRET, kt as storageMigrationCapability, nn as parseJsonObject, w as StorageLocationTypeSchema } from "../../dist-1eWNHQel.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";
@@ -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-Ci7Ln6Rt.js");
6
+ const require_dist = require("../../dist-B0Cf6q_P.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 { Ft as BaseAddon, Pt as errMsg, Qt as hydrateSchema } from "../../dist-TP8pJtEo.mjs";
1
+ import { $t as hydrateSchema, Ft as errMsg, It as BaseAddon } from "../../dist-1eWNHQel.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-Ci7Ln6Rt.js");
6
+ const require_dist = require("../../dist-B0Cf6q_P.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 { Ft as BaseAddon, ct as logDestinationCapability } from "../../dist-TP8pJtEo.mjs";
1
+ import { It as BaseAddon, lt as logDestinationCapability } from "../../dist-1eWNHQel.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,5 +1,5 @@
1
1
  import { z } from "zod";
2
- //#region ../types/dist/event-category-BZL-fdNj.mjs
2
+ //#region ../types/dist/event-category-zAv7pMUz.mjs
3
3
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4
4
  EventCategory["SystemBoot"] = "system.boot";
5
5
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -371,6 +371,13 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
371
371
  */
372
372
  EventCategory["BatteryOnStatusChanged"] = "battery.onStatusChanged";
373
373
  /**
374
+ * Cap event fired by every device that registers the `network-link`
375
+ * capability. Mirrors the cap definition's `onStatusChanged`. Carries
376
+ * `{ deviceId, status: NetworkLinkStatus }` — a link switch or a signal
377
+ * reading that moved.
378
+ */
379
+ EventCategory["NetworkLinkOnStatusChanged"] = "network-link.onStatusChanged";
380
+ /**
374
381
  * Emitted by the battery cap provider WHEN `wakeForStream` enters the
375
382
  * "wake in progress" window — between the Baichuan wake-up issue and
376
383
  * the camera's first dialed-back RTP packet. The stream-broker
@@ -24536,6 +24543,88 @@ onStatusChanged: { data: z.object({
24536
24543
  volatileStateFields: ["lastUpdated"]
24537
24544
  };
24538
24545
  /**
24546
+ * Network-link snapshot. Same shape for every provider (a Reolink wifi
24547
+ * camera, a Home Assistant device with a signal-strength sensor, a Tapo
24548
+ * plug): one slice under `device.runtimeState['network-link']`, one badge,
24549
+ * one Home Assistant projection.
24550
+ */
24551
+ var NetworkLinkStatusSchema = z.object({
24552
+ /** The link the device is on. `'unknown'` = not read yet, not "no link". */
24553
+ type: z.enum([
24554
+ "wifi",
24555
+ "ethernet",
24556
+ "cellular",
24557
+ "unknown"
24558
+ ]),
24559
+ /**
24560
+ * Link quality, 0..100 inclusive, normalised by the provider from whatever
24561
+ * the firmware reports (bars, RSSI, a vendor scale). **`null` means NOT
24562
+ * KNOWN or NOT APPLICABLE** — a wired link has no signal, and a wireless
24563
+ * one whose reading has not landed must not be drawn at 0 %. Consumers
24564
+ * SKIP a null rather than coerce it.
24565
+ */
24566
+ signalPercent: z.number().min(0).max(100).nullable(),
24567
+ /** Raw received signal strength in dBm, when the firmware reports one. */
24568
+ rssiDbm: z.number().optional(),
24569
+ /** Network name of a wireless link, when the firmware reports it. */
24570
+ ssid: z.string().optional(),
24571
+ /** Ms epoch of the last observation. Lets consumers reason about freshness. */
24572
+ lastUpdated: z.number()
24573
+ });
24574
+ var networkLinkCapability = {
24575
+ name: "network-link",
24576
+ scope: "device",
24577
+ deviceNative: true,
24578
+ mode: "singleton",
24579
+ deviceTypes: [
24580
+ DeviceType.Camera,
24581
+ DeviceType.Sensor,
24582
+ DeviceType.Button,
24583
+ DeviceType.Switch,
24584
+ DeviceType.Light,
24585
+ DeviceType.Lock,
24586
+ DeviceType.Siren
24587
+ ],
24588
+ methods: {},
24589
+ events: {
24590
+ /**
24591
+ * Emitted whenever the cached status changes (a link switch, a signal
24592
+ * reading that moved). Mirrored on the parent chain by the
24593
+ * DeviceEventPropagator like `battery.onStatusChanged`.
24594
+ */
24595
+ onStatusChanged: { data: z.object({
24596
+ deviceId: z.number(),
24597
+ status: NetworkLinkStatusSchema
24598
+ }) } },
24599
+ status: {
24600
+ schema: NetworkLinkStatusSchema,
24601
+ kind: "push",
24602
+ empty: {
24603
+ type: "unknown",
24604
+ signalPercent: null,
24605
+ lastUpdated: 0
24606
+ }
24607
+ },
24608
+ /**
24609
+ * Runtime-state slice — every provider stores the same shape under
24610
+ * `device.runtimeState['network-link']`, read once by the badge and the
24611
+ * Home Assistant projector regardless of the driver.
24612
+ */
24613
+ runtimeState: NetworkLinkStatusSchema,
24614
+ /**
24615
+ * Runtime-state durability: **restored** — a link reading is slow to
24616
+ * change and a sleeping battery camera may not report for hours; the
24617
+ * restored slice is what the badge shows until the next read.
24618
+ *
24619
+ * See `RuntimeStateDurability`. Enforced by
24620
+ * `scripts/check-runtime-state-durability.ts`.
24621
+ */
24622
+ durability: "restored",
24623
+ /** Clock fields: written, but excluded from the compare that decides
24624
+ * whether persisting is worth a SQLite commit. */
24625
+ volatileStateFields: ["lastUpdated"]
24626
+ };
24627
+ /**
24539
24628
  * Generic boolean sensor — last-resort fallback when no domain-
24540
24629
  * specific binary cap fits (Home Assistant `binary_sensor` without a
24541
24630
  * known `device_class`, or a domain we haven't typed yet). Pure
@@ -34603,6 +34692,7 @@ var CAP_NAMES_WITH_STATUS = [
34603
34692
  "motion-zones",
34604
34693
  "mqtt-broker",
34605
34694
  "native-object-detection",
34695
+ "network-link",
34606
34696
  "notifier",
34607
34697
  "numeric-sensor",
34608
34698
  "osd",
@@ -34729,6 +34819,7 @@ var ALL_CAPABILITY_DEFINITIONS = [
34729
34819
  mqttBrokerCapability,
34730
34820
  nativeObjectDetectionCapability,
34731
34821
  networkAccessCapability,
34822
+ networkLinkCapability,
34732
34823
  networkQualityCapability,
34733
34824
  nodesCapability,
34734
34825
  notificationOutputCapability,
@@ -42666,7 +42757,7 @@ Object.freeze({
42666
42757
  });
42667
42758
  /**
42668
42759
  * Per-cap runtime-state policy, projected from every `*.cap.ts` that declares
42669
- * `runtimeState`. 64 caps: 34 `restored`, 30 `session`.
42760
+ * `runtimeState`. 65 caps: 35 `restored`, 30 `session`.
42670
42761
  *
42671
42762
  * A cap absent from this map has no runtime-state slice at all. A cap PRESENT
42672
42763
  * with `durability: 'session'` has one and has decided not to keep it.
@@ -42828,6 +42919,10 @@ var RUNTIME_STATE_POLICY = {
42828
42919
  durability: "restored",
42829
42920
  volatileFields: ["lastFetchedAt"]
42830
42921
  },
42922
+ "network-link": {
42923
+ durability: "restored",
42924
+ volatileFields: ["lastUpdated"]
42925
+ },
42831
42926
  "notifier": {
42832
42927
  durability: "session",
42833
42928
  volatileFields: []
@@ -43594,4 +43689,4 @@ function enumerateInferenceDevices(hw) {
43594
43689
  return out;
43595
43690
  }
43596
43691
  //#endregion
43597
- export { isArrayOutputSchema as $, isDeviceConfigCap as $t, authProviderCapability as A, streamQualityLabel as At, decodeVectorBase64 as B, DeviceRole as Bt, StorageLocationTypeSchema as C, scopesAllowDeviceCap as Ct, addonSettingsCapability as D, storageCapability as Dt, addonPagesCapability as E, snapshotCapability as Et, collectSecretConfigKeys as F, BaseAddon as Ft, doorbellCapability as G, asJsonObject as Gt, deviceManagerCapability as H, ReadinessRegistry as Ht, coreBlockAddonId as I, DATAPLANE_SECRET_HEADER as It, enumerateSchemaFields as J, createEvent as Jt, enumerateInferenceDevices as K, asNumber as Kt, coreBlockIdFromAddonId as L, DEVICE_SETTINGS_CONTRIBUTION_METHODS as Lt, bareAddonId as M, vectorDimFromBase64 as Mt, batteryCapability as N, vectorStoreCapability as Nt, addonWidgetsCapability as O, storageMigrationCapability as Ot, buildStreamParamsConfigSchema as P, errMsg as Pt, foldSnapshotByFunction as Q, hydrateSchema as Qt, coreBlocksCapability as R, DEVICE_STATUS_METHOD as Rt, StorageCleanupJobSchema as S, scopesAllowAddon as St, UserRecordSchema as T, settingsStoreCapability as Tt, deviceStateCapability as U, ReadinessTimeoutError as Ut, deriveBatteryPresence as V, DeviceType as Vt, deviceStatusCapability as W, WELL_KNOWN_TAB_MAP as Wt, extractNestedAddonId as X, emitReadiness as Xt, evaluateSensorEdge as Y, emitDownForOwnedCaps as Yt, filesystemBrowseCapability as Z, expandCapMethods as Zt, SOURCE_CAPS as _, reducePoints as _t, CAMERA_SWITCH_ORDER as a, scopeKey as an, kebabToCamel as at, STREAM_PROFILE_META as b, resolveMethodAuth as bt, CORE_BLOCK_ADDON_PREFIX as c, logDestinationCapability as ct, DeclaredDevices as d, metricsProviderCapability as dt, nodePin as en, isCollectionArrayMethod as et, DeviceStatusSchema as f, normalizeUnit as ft, RUNTIME_DEFAULTS as g, procedureAuthKey as gt, REDACTED_SECRET as h, platformProbeCapability as ht, BatteryStatusSchema as i, resolveCapMount as in, isVoidInput as it, backupCapability as j, userManagementCapability as jt, alertsCapability as k, storageProviderCapability as kt, CoreBlockSchema as l, logLevelAtMost as lt, METHOD_ACCESS_MAP as m, parseStreamParamsFormPatch as mt, AlertSchema as n, parseJsonUnknown as nn, isSameAddonId as nt, CAP_NAMES_WITH_STATUS as o, sleep as on, lifecycleJobSchema as ot, LOG_LEVEL_RANK as p, objectInputDeclaresAddonId as pt, enumerateItemArrayFields as q, asString as qt, ApiKeyRecordSchema as r, readinessKey as rn, isSourceCap as rt, CORE_BLOCKS_ADDON_ID as s, EventCategory as sn, localNetworkCapability as st, ALL_CAPABILITY_DEFINITIONS as t, parseJsonObject as tn, isObjectInput as tt, DEFAULT_FIRST_SIGHTING_FRESHNESS_MS as u, looseSchema as ut, SOURCE_DEVICE_TYPES as v, resolveBucketMs as vt, StorageMigrationJobSchema as w, scoreRuntimes as wt, ScopedTokenSchema as x, runtimeStatePolicyFor as xt, STORAGE_ACCESS_FALLBACK as y, resolveContainerPrimaryChild as yt, dataStoreProviderCapability as z, DeviceFeature as zt };
43692
+ export { foldSnapshotByFunction as $, hydrateSchema as $t, alertsCapability as A, storageProviderCapability as At, dataStoreProviderCapability as B, DeviceFeature as Bt, StorageCleanupJobSchema as C, scopesAllowAddon as Ct, addonPagesCapability as D, snapshotCapability as Dt, UserRecordSchema as E, settingsStoreCapability as Et, buildStreamParamsConfigSchema as F, errMsg as Ft, deviceStatusCapability as G, WELL_KNOWN_TAB_MAP as Gt, deriveBatteryPresence as H, DeviceType as Ht, collectSecretConfigKeys as I, BaseAddon as It, enumerateItemArrayFields as J, asString as Jt, doorbellCapability as K, asJsonObject as Kt, coreBlockAddonId as L, DATAPLANE_SECRET_HEADER as Lt, backupCapability as M, userManagementCapability as Mt, bareAddonId as N, vectorDimFromBase64 as Nt, addonSettingsCapability as O, storageCapability as Ot, batteryCapability as P, vectorStoreCapability as Pt, filesystemBrowseCapability as Q, expandCapMethods as Qt, coreBlockIdFromAddonId as R, DEVICE_SETTINGS_CONTRIBUTION_METHODS as Rt, ScopedTokenSchema as S, runtimeStatePolicyFor as St, StorageMigrationJobSchema as T, scoreRuntimes as Tt, deviceManagerCapability as U, ReadinessRegistry as Ut, decodeVectorBase64 as V, DeviceRole as Vt, deviceStateCapability as W, ReadinessTimeoutError as Wt, evaluateSensorEdge as X, emitDownForOwnedCaps as Xt, enumerateSchemaFields as Y, createEvent as Yt, extractNestedAddonId as Z, emitReadiness as Zt, RecordingStatusSchema as _, procedureAuthKey as _t, CAMERA_SWITCH_ORDER as a, resolveCapMount as an, isVoidInput as at, STORAGE_ACCESS_FALLBACK as b, resolveContainerPrimaryChild as bt, CORE_BLOCK_ADDON_PREFIX as c, EventCategory as cn, localNetworkCapability as ct, DeclaredDevices as d, looseSchema as dt, isDeviceConfigCap as en, isArrayOutputSchema as et, DeviceStatusSchema as f, metricsProviderCapability as ft, RUNTIME_DEFAULTS as g, platformProbeCapability as gt, REDACTED_SECRET as h, parseStreamParamsFormPatch as ht, BatteryStatusSchema as i, readinessKey as in, isSourceCap as it, authProviderCapability as j, streamQualityLabel as jt, addonWidgetsCapability as k, storageMigrationCapability as kt, CoreBlockSchema as l, logDestinationCapability as lt, METHOD_ACCESS_MAP as m, objectInputDeclaresAddonId as mt, AlertSchema as n, parseJsonObject as nn, isObjectInput as nt, CAP_NAMES_WITH_STATUS as o, scopeKey as on, kebabToCamel as ot, LOG_LEVEL_RANK as p, normalizeUnit as pt, enumerateInferenceDevices as q, asNumber as qt, ApiKeyRecordSchema as r, parseJsonUnknown as rn, isSameAddonId as rt, CORE_BLOCKS_ADDON_ID as s, sleep as sn, lifecycleJobSchema as st, ALL_CAPABILITY_DEFINITIONS as t, nodePin as tn, isCollectionArrayMethod as tt, DEFAULT_FIRST_SIGHTING_FRESHNESS_MS as u, logLevelAtMost as ut, SOURCE_CAPS as v, reducePoints as vt, StorageLocationTypeSchema as w, scopesAllowDeviceCap as wt, STREAM_PROFILE_META as x, resolveMethodAuth as xt, SOURCE_DEVICE_TYPES as y, resolveBucketMs as yt, coreBlocksCapability as z, DEVICE_STATUS_METHOD as zt };
@@ -1,5 +1,5 @@
1
1
  let zod = require("zod");
2
- //#region ../types/dist/event-category-BZL-fdNj.mjs
2
+ //#region ../types/dist/event-category-zAv7pMUz.mjs
3
3
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4
4
  EventCategory["SystemBoot"] = "system.boot";
5
5
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -371,6 +371,13 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
371
371
  */
372
372
  EventCategory["BatteryOnStatusChanged"] = "battery.onStatusChanged";
373
373
  /**
374
+ * Cap event fired by every device that registers the `network-link`
375
+ * capability. Mirrors the cap definition's `onStatusChanged`. Carries
376
+ * `{ deviceId, status: NetworkLinkStatus }` — a link switch or a signal
377
+ * reading that moved.
378
+ */
379
+ EventCategory["NetworkLinkOnStatusChanged"] = "network-link.onStatusChanged";
380
+ /**
374
381
  * Emitted by the battery cap provider WHEN `wakeForStream` enters the
375
382
  * "wake in progress" window — between the Baichuan wake-up issue and
376
383
  * the camera's first dialed-back RTP packet. The stream-broker
@@ -24536,6 +24543,88 @@ onStatusChanged: { data: zod.z.object({
24536
24543
  volatileStateFields: ["lastUpdated"]
24537
24544
  };
24538
24545
  /**
24546
+ * Network-link snapshot. Same shape for every provider (a Reolink wifi
24547
+ * camera, a Home Assistant device with a signal-strength sensor, a Tapo
24548
+ * plug): one slice under `device.runtimeState['network-link']`, one badge,
24549
+ * one Home Assistant projection.
24550
+ */
24551
+ var NetworkLinkStatusSchema = zod.z.object({
24552
+ /** The link the device is on. `'unknown'` = not read yet, not "no link". */
24553
+ type: zod.z.enum([
24554
+ "wifi",
24555
+ "ethernet",
24556
+ "cellular",
24557
+ "unknown"
24558
+ ]),
24559
+ /**
24560
+ * Link quality, 0..100 inclusive, normalised by the provider from whatever
24561
+ * the firmware reports (bars, RSSI, a vendor scale). **`null` means NOT
24562
+ * KNOWN or NOT APPLICABLE** — a wired link has no signal, and a wireless
24563
+ * one whose reading has not landed must not be drawn at 0 %. Consumers
24564
+ * SKIP a null rather than coerce it.
24565
+ */
24566
+ signalPercent: zod.z.number().min(0).max(100).nullable(),
24567
+ /** Raw received signal strength in dBm, when the firmware reports one. */
24568
+ rssiDbm: zod.z.number().optional(),
24569
+ /** Network name of a wireless link, when the firmware reports it. */
24570
+ ssid: zod.z.string().optional(),
24571
+ /** Ms epoch of the last observation. Lets consumers reason about freshness. */
24572
+ lastUpdated: zod.z.number()
24573
+ });
24574
+ var networkLinkCapability = {
24575
+ name: "network-link",
24576
+ scope: "device",
24577
+ deviceNative: true,
24578
+ mode: "singleton",
24579
+ deviceTypes: [
24580
+ DeviceType.Camera,
24581
+ DeviceType.Sensor,
24582
+ DeviceType.Button,
24583
+ DeviceType.Switch,
24584
+ DeviceType.Light,
24585
+ DeviceType.Lock,
24586
+ DeviceType.Siren
24587
+ ],
24588
+ methods: {},
24589
+ events: {
24590
+ /**
24591
+ * Emitted whenever the cached status changes (a link switch, a signal
24592
+ * reading that moved). Mirrored on the parent chain by the
24593
+ * DeviceEventPropagator like `battery.onStatusChanged`.
24594
+ */
24595
+ onStatusChanged: { data: zod.z.object({
24596
+ deviceId: zod.z.number(),
24597
+ status: NetworkLinkStatusSchema
24598
+ }) } },
24599
+ status: {
24600
+ schema: NetworkLinkStatusSchema,
24601
+ kind: "push",
24602
+ empty: {
24603
+ type: "unknown",
24604
+ signalPercent: null,
24605
+ lastUpdated: 0
24606
+ }
24607
+ },
24608
+ /**
24609
+ * Runtime-state slice — every provider stores the same shape under
24610
+ * `device.runtimeState['network-link']`, read once by the badge and the
24611
+ * Home Assistant projector regardless of the driver.
24612
+ */
24613
+ runtimeState: NetworkLinkStatusSchema,
24614
+ /**
24615
+ * Runtime-state durability: **restored** — a link reading is slow to
24616
+ * change and a sleeping battery camera may not report for hours; the
24617
+ * restored slice is what the badge shows until the next read.
24618
+ *
24619
+ * See `RuntimeStateDurability`. Enforced by
24620
+ * `scripts/check-runtime-state-durability.ts`.
24621
+ */
24622
+ durability: "restored",
24623
+ /** Clock fields: written, but excluded from the compare that decides
24624
+ * whether persisting is worth a SQLite commit. */
24625
+ volatileStateFields: ["lastUpdated"]
24626
+ };
24627
+ /**
24539
24628
  * Generic boolean sensor — last-resort fallback when no domain-
24540
24629
  * specific binary cap fits (Home Assistant `binary_sensor` without a
24541
24630
  * known `device_class`, or a domain we haven't typed yet). Pure
@@ -34603,6 +34692,7 @@ var CAP_NAMES_WITH_STATUS = [
34603
34692
  "motion-zones",
34604
34693
  "mqtt-broker",
34605
34694
  "native-object-detection",
34695
+ "network-link",
34606
34696
  "notifier",
34607
34697
  "numeric-sensor",
34608
34698
  "osd",
@@ -34729,6 +34819,7 @@ var ALL_CAPABILITY_DEFINITIONS = [
34729
34819
  mqttBrokerCapability,
34730
34820
  nativeObjectDetectionCapability,
34731
34821
  networkAccessCapability,
34822
+ networkLinkCapability,
34732
34823
  networkQualityCapability,
34733
34824
  nodesCapability,
34734
34825
  notificationOutputCapability,
@@ -42666,7 +42757,7 @@ Object.freeze({
42666
42757
  });
42667
42758
  /**
42668
42759
  * Per-cap runtime-state policy, projected from every `*.cap.ts` that declares
42669
- * `runtimeState`. 64 caps: 34 `restored`, 30 `session`.
42760
+ * `runtimeState`. 65 caps: 35 `restored`, 30 `session`.
42670
42761
  *
42671
42762
  * A cap absent from this map has no runtime-state slice at all. A cap PRESENT
42672
42763
  * with `durability: 'session'` has one and has decided not to keep it.
@@ -42828,6 +42919,10 @@ var RUNTIME_STATE_POLICY = {
42828
42919
  durability: "restored",
42829
42920
  volatileFields: ["lastFetchedAt"]
42830
42921
  },
42922
+ "network-link": {
42923
+ durability: "restored",
42924
+ volatileFields: ["lastUpdated"]
42925
+ },
42831
42926
  "notifier": {
42832
42927
  durability: "session",
42833
42928
  volatileFields: []
@@ -43750,6 +43845,12 @@ Object.defineProperty(exports, "ReadinessTimeoutError", {
43750
43845
  return ReadinessTimeoutError;
43751
43846
  }
43752
43847
  });
43848
+ Object.defineProperty(exports, "RecordingStatusSchema", {
43849
+ enumerable: true,
43850
+ get: function() {
43851
+ return RecordingStatusSchema;
43852
+ }
43853
+ });
43753
43854
  Object.defineProperty(exports, "SOURCE_CAPS", {
43754
43855
  enumerable: true,
43755
43856
  get: function() {
package/dist/index.js CHANGED
@@ -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-Ci7Ln6Rt.js");
3
+ const require_dist = require("./dist-B0Cf6q_P.js");
4
4
  const require_builtins_alerts_alerts_addon = require("./builtins/alerts/alerts.addon.js");
5
5
  require("./builtins/alerts/index.js");
6
6
  const require_formatter = require("./formatter-DqAKDlvN.js");
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { a as __toCommonJS, i as __require, n as __esmMin, o as __toESM$1, r as __exportAll, t as __commonJSMin$1 } from "./chunk-CNf5ZN-e.mjs";
2
- import { $ as isArrayOutputSchema, Ct as scopesAllowDeviceCap, D as addonSettingsCapability, Gt as asJsonObject$1, Ht as ReadinessRegistry, It as DATAPLANE_SECRET_HEADER$1, Jt as createEvent, Kt as asNumber, Lt as DEVICE_SETTINGS_CONTRIBUTION_METHODS, Pt as errMsg$1, Rt as DEVICE_STATUS_METHOD, St as scopesAllowAddon, Ut as ReadinessTimeoutError, X as extractNestedAddonId, Yt as emitDownForOwnedCaps, Zt as expandCapMethods, an as scopeKey, at as kebabToCamel, bt as resolveMethodAuth, et as isCollectionArrayMethod, g as RUNTIME_DEFAULTS, gt as procedureAuthKey, in as resolveCapMount, it as isVoidInput, lt as logLevelAtMost, m as METHOD_ACCESS_MAP, nn as parseJsonUnknown, ot as lifecycleJobSchema, p as LOG_LEVEL_RANK, pt as objectInputDeclaresAddonId, qt as asString$1, rn as readinessKey, sn as EventCategory$1, t as ALL_CAPABILITY_DEFINITIONS, tn as parseJsonObject, tt as isObjectInput, ut as looseSchema } from "./dist-TP8pJtEo.mjs";
2
+ import { Ct as scopesAllowAddon, Ft as errMsg$1, Jt as asString$1, Kt as asJsonObject$1, Lt as DATAPLANE_SECRET_HEADER$1, O as addonSettingsCapability, Qt as expandCapMethods, Rt as DEVICE_SETTINGS_CONTRIBUTION_METHODS, Ut as ReadinessRegistry, Wt as ReadinessTimeoutError, Xt as emitDownForOwnedCaps, Yt as createEvent, Z as extractNestedAddonId, _t as procedureAuthKey, an as resolveCapMount, at as isVoidInput, cn as EventCategory$1, dt as looseSchema, et as isArrayOutputSchema, g as RUNTIME_DEFAULTS, in as readinessKey, m as METHOD_ACCESS_MAP, mt as objectInputDeclaresAddonId, nn as parseJsonObject, nt as isObjectInput, on as scopeKey, ot as kebabToCamel, p as LOG_LEVEL_RANK, qt as asNumber, rn as parseJsonUnknown, st as lifecycleJobSchema, t as ALL_CAPABILITY_DEFINITIONS, tt as isCollectionArrayMethod, ut as logLevelAtMost, wt as scopesAllowDeviceCap, xt as resolveMethodAuth, zt as DEVICE_STATUS_METHOD } from "./dist-1eWNHQel.mjs";
3
3
  import { AlertCenterAddon } from "./builtins/alerts/alerts.addon.mjs";
4
4
  import "./builtins/alerts/index.mjs";
5
5
  import { t as formatLogLine } from "./formatter-B7qW8bPJ.mjs";
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-Ci7Ln6Rt.js");
1
+ const require_dist = require("./dist-B0Cf6q_P.js");
2
2
  //#region src/builtins/sqlite-storage/retired-settings-keys.ts
3
3
  /**
4
4
  * Is THIS node the one whose settings store is the cluster's authority?
@@ -1,4 +1,4 @@
1
- import { Gt as asJsonObject } from "./dist-TP8pJtEo.mjs";
1
+ import { Kt as asJsonObject } from "./dist-1eWNHQel.mjs";
2
2
  //#region src/builtins/sqlite-storage/retired-settings-keys.ts
3
3
  /**
4
4
  * Is THIS node the one whose settings store is the cluster's authority?
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/system",
3
- "version": "1.2.191",
3
+ "version": "1.2.193",
4
4
  "description": "Core addon for CamStack — builtins, pipeline, process management, auth, logging, events",
5
5
  "keywords": [
6
6
  "camstack",