@camstack/addon-notifiers 1.2.78 → 1.2.80

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.
package/dist/addon.js CHANGED
@@ -7982,17 +7982,29 @@ var HHMM = /^([01]\d|2[0-3]):[0-5]\d$/;
7982
7982
  /**
7983
7983
  * DERIVED per-camera storage summary — the single field cheap consumers read
7984
7984
  * (the viewer's status dot, the camera list) instead of walking `bands`:
7985
- * - `off` — no band covers the camera (or it is disabled).
7986
- * - `events` — every band records around triggers only.
7987
- * - `continuous` — at least one band records continuously.
7988
- *
7989
- * NEVER authored: the recorder stamps it from the authoritative `bands` on
7990
- * every save (`activeModeForConfig`). Writing it has no effect.
7985
+ * - `off` — no band covers the camera (or it is disabled).
7986
+ * - `events` — every band records around triggers only.
7987
+ * - `continuous` — at least one band records continuously.
7988
+ * - `on-device-decision`— the DEVICE decides: recording runs for as long as the
7989
+ * camera raises its own `recording-signal` level (a robot that cleans). There
7990
+ * is no schedule to author, because there is no hour to program — see
7991
+ * {@link RecordingConfigSchema}`.deviceDecision`.
7992
+ *
7993
+ * NEVER authored: the recorder stamps it from the authoritative intent
7994
+ * (`bands` + `deviceDecision`) on every save (`activeModeForConfig`). Writing it
7995
+ * has no effect.
7996
+ *
7997
+ * `on-device-decision` is named for WHO decides, not for how the recording is
7998
+ * requested. `on-demand` was rejected: in this repo's vocabulary a "demand" is
7999
+ * something the operator makes (the live gate is the recorder's own "demand
8000
+ * window"), and a knob whose name suggests the operator starts it while the
8001
+ * device actually does is the D62 shape — a control nobody can predict.
7991
8002
  */
7992
8003
  var RecordingStorageModeSchema = _enum([
7993
8004
  "off",
7994
8005
  "events",
7995
- "continuous"
8006
+ "continuous",
8007
+ "on-device-decision"
7996
8008
  ]);
7997
8009
  /**
7998
8010
  * Le macro classi che possono aprire una finestra di registrazione — le stesse
@@ -8042,22 +8054,7 @@ var RecordingTriggersSchema = object({
8042
8054
  * il livello: un contatto trovato già aperto al riavvio del runner non fa
8043
8055
  * registrare.
8044
8056
  */
8045
- sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional(),
8046
- /**
8047
- * La camera registra per tutta la durata del SEGNALE che lei stessa
8048
- * pubblica — la cap `recording-signal` (`active: true` mentre il device è in
8049
- * funzione: un robot che pulisce). È un LIVELLO, non un fronte: la finestra
8050
- * resta aperta finché il segnale è alto e si chiude `postBufferSec` dopo la
8051
- * caduta, così una pulizia di quaranta minuti è UNA clip.
8052
- *
8053
- * Non nomina un device: il segnale è della camera stessa, tenuto fresco dal
8054
- * suo provider (D224); il recorder lo ascolta su `DeviceStateChanged` e lo
8055
- * riconcilia leggendo la slice via RPC, con un tetto oltre il quale un
8056
- * segnale mai abbassato (un evento perso) non può tenere aperta una
8057
- * registrazione (D11). Vedi `recorder/addon/band-decision.ts`
8058
- * (`holdTrigger` / `releaseTrigger`).
8059
- */
8060
- deviceSignal: boolean().optional()
8057
+ sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional()
8061
8058
  });
8062
8059
  /**
8063
8060
  * Mode of a single recording band — the recorder per-band vocabulary.
@@ -8141,8 +8138,29 @@ var RecordingConfigSchema = object({
8141
8138
  * "off" is the absence of a covering band, never a band value.
8142
8139
  */
8143
8140
  bands: array(RecordingBandSchema).default([]),
8141
+ /**
8142
+ * THE device-decided intent: record for as long as the camera itself raises
8143
+ * `recording-signal` (`active: true` while the device is in function — a
8144
+ * robot that cleans). AUTHORED, unlike `mode`, and the only authored
8145
+ * recording intent that is not a band.
8146
+ *
8147
+ * It carries NO schedule on purpose. A band is an HOUR, and this feature has
8148
+ * no hour to program: the device decides. What it costs the operator is one
8149
+ * flag — "this camera can record on its own" — and what it buys is the same
8150
+ * hold/release the recorder already implements (D371, `holdTrigger` /
8151
+ * `releaseTrigger`): the window opens on the rise, stays open for the whole
8152
+ * job however long it is, and closes one pad after the fall.
8153
+ *
8154
+ * EXCLUSIVE with `bands` (below): two authorities deciding when the same
8155
+ * camera records is the D62 failure. `off` remains `enabled: false`, so an
8156
+ * operator switching this camera off is REPORTED off, never as broken.
8157
+ */
8158
+ deviceDecision: boolean().optional(),
8144
8159
  retention: RecordingRetentionSchema.optional()
8145
- }).strict();
8160
+ }).strict().refine((config) => config.deviceDecision !== true || config.bands.length === 0, {
8161
+ message: "deviceDecision is a whole-config mode and carries no schedule: it cannot be combined with bands",
8162
+ path: ["bands"]
8163
+ });
8146
8164
  /**
8147
8165
  * Entity-relocation job state (storage entity-routing spec, Phase 4).
8148
8166
  *
@@ -20845,11 +20863,7 @@ var CameraAudioStatusSchema = object({
20845
20863
  });
20846
20864
  /** Recording block — null when no recording cap is active for this device. */
20847
20865
  var CameraRecordingStatusSchema = object({
20848
- mode: _enum([
20849
- "off",
20850
- "continuous",
20851
- "events"
20852
- ]),
20866
+ mode: RecordingStorageModeSchema,
20853
20867
  active: boolean(),
20854
20868
  storageBytes: number()
20855
20869
  });
@@ -27255,11 +27269,10 @@ DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceI
27255
27269
  var RecordingStatusSchema = object({
27256
27270
  deviceId: number(),
27257
27271
  enabled: boolean(),
27258
- activeMode: _enum([
27259
- "off",
27260
- "continuous",
27261
- "events"
27262
- ]),
27272
+ /** THE derived storage mode, from the one definition
27273
+ * (`deriveRecordingMode`) — never a second enum. A duplicated list is how
27274
+ * `on-device-decision` could have reached the recorder and not the status. */
27275
+ activeMode: RecordingStorageModeSchema,
27263
27276
  nodeId: string(),
27264
27277
  storageBytes: number()
27265
27278
  });
package/dist/addon.mjs CHANGED
@@ -7955,17 +7955,29 @@ var HHMM = /^([01]\d|2[0-3]):[0-5]\d$/;
7955
7955
  /**
7956
7956
  * DERIVED per-camera storage summary — the single field cheap consumers read
7957
7957
  * (the viewer's status dot, the camera list) instead of walking `bands`:
7958
- * - `off` — no band covers the camera (or it is disabled).
7959
- * - `events` — every band records around triggers only.
7960
- * - `continuous` — at least one band records continuously.
7961
- *
7962
- * NEVER authored: the recorder stamps it from the authoritative `bands` on
7963
- * every save (`activeModeForConfig`). Writing it has no effect.
7958
+ * - `off` — no band covers the camera (or it is disabled).
7959
+ * - `events` — every band records around triggers only.
7960
+ * - `continuous` — at least one band records continuously.
7961
+ * - `on-device-decision`— the DEVICE decides: recording runs for as long as the
7962
+ * camera raises its own `recording-signal` level (a robot that cleans). There
7963
+ * is no schedule to author, because there is no hour to program — see
7964
+ * {@link RecordingConfigSchema}`.deviceDecision`.
7965
+ *
7966
+ * NEVER authored: the recorder stamps it from the authoritative intent
7967
+ * (`bands` + `deviceDecision`) on every save (`activeModeForConfig`). Writing it
7968
+ * has no effect.
7969
+ *
7970
+ * `on-device-decision` is named for WHO decides, not for how the recording is
7971
+ * requested. `on-demand` was rejected: in this repo's vocabulary a "demand" is
7972
+ * something the operator makes (the live gate is the recorder's own "demand
7973
+ * window"), and a knob whose name suggests the operator starts it while the
7974
+ * device actually does is the D62 shape — a control nobody can predict.
7964
7975
  */
7965
7976
  var RecordingStorageModeSchema = _enum([
7966
7977
  "off",
7967
7978
  "events",
7968
- "continuous"
7979
+ "continuous",
7980
+ "on-device-decision"
7969
7981
  ]);
7970
7982
  /**
7971
7983
  * Le macro classi che possono aprire una finestra di registrazione — le stesse
@@ -8015,22 +8027,7 @@ var RecordingTriggersSchema = object({
8015
8027
  * il livello: un contatto trovato già aperto al riavvio del runner non fa
8016
8028
  * registrare.
8017
8029
  */
8018
- sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional(),
8019
- /**
8020
- * La camera registra per tutta la durata del SEGNALE che lei stessa
8021
- * pubblica — la cap `recording-signal` (`active: true` mentre il device è in
8022
- * funzione: un robot che pulisce). È un LIVELLO, non un fronte: la finestra
8023
- * resta aperta finché il segnale è alto e si chiude `postBufferSec` dopo la
8024
- * caduta, così una pulizia di quaranta minuti è UNA clip.
8025
- *
8026
- * Non nomina un device: il segnale è della camera stessa, tenuto fresco dal
8027
- * suo provider (D224); il recorder lo ascolta su `DeviceStateChanged` e lo
8028
- * riconcilia leggendo la slice via RPC, con un tetto oltre il quale un
8029
- * segnale mai abbassato (un evento perso) non può tenere aperta una
8030
- * registrazione (D11). Vedi `recorder/addon/band-decision.ts`
8031
- * (`holdTrigger` / `releaseTrigger`).
8032
- */
8033
- deviceSignal: boolean().optional()
8030
+ sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional()
8034
8031
  });
8035
8032
  /**
8036
8033
  * Mode of a single recording band — the recorder per-band vocabulary.
@@ -8114,8 +8111,29 @@ var RecordingConfigSchema = object({
8114
8111
  * "off" is the absence of a covering band, never a band value.
8115
8112
  */
8116
8113
  bands: array(RecordingBandSchema).default([]),
8114
+ /**
8115
+ * THE device-decided intent: record for as long as the camera itself raises
8116
+ * `recording-signal` (`active: true` while the device is in function — a
8117
+ * robot that cleans). AUTHORED, unlike `mode`, and the only authored
8118
+ * recording intent that is not a band.
8119
+ *
8120
+ * It carries NO schedule on purpose. A band is an HOUR, and this feature has
8121
+ * no hour to program: the device decides. What it costs the operator is one
8122
+ * flag — "this camera can record on its own" — and what it buys is the same
8123
+ * hold/release the recorder already implements (D371, `holdTrigger` /
8124
+ * `releaseTrigger`): the window opens on the rise, stays open for the whole
8125
+ * job however long it is, and closes one pad after the fall.
8126
+ *
8127
+ * EXCLUSIVE with `bands` (below): two authorities deciding when the same
8128
+ * camera records is the D62 failure. `off` remains `enabled: false`, so an
8129
+ * operator switching this camera off is REPORTED off, never as broken.
8130
+ */
8131
+ deviceDecision: boolean().optional(),
8117
8132
  retention: RecordingRetentionSchema.optional()
8118
- }).strict();
8133
+ }).strict().refine((config) => config.deviceDecision !== true || config.bands.length === 0, {
8134
+ message: "deviceDecision is a whole-config mode and carries no schedule: it cannot be combined with bands",
8135
+ path: ["bands"]
8136
+ });
8119
8137
  /**
8120
8138
  * Entity-relocation job state (storage entity-routing spec, Phase 4).
8121
8139
  *
@@ -20818,11 +20836,7 @@ var CameraAudioStatusSchema = object({
20818
20836
  });
20819
20837
  /** Recording block — null when no recording cap is active for this device. */
20820
20838
  var CameraRecordingStatusSchema = object({
20821
- mode: _enum([
20822
- "off",
20823
- "continuous",
20824
- "events"
20825
- ]),
20839
+ mode: RecordingStorageModeSchema,
20826
20840
  active: boolean(),
20827
20841
  storageBytes: number()
20828
20842
  });
@@ -27228,11 +27242,10 @@ DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceI
27228
27242
  var RecordingStatusSchema = object({
27229
27243
  deviceId: number(),
27230
27244
  enabled: boolean(),
27231
- activeMode: _enum([
27232
- "off",
27233
- "continuous",
27234
- "events"
27235
- ]),
27245
+ /** THE derived storage mode, from the one definition
27246
+ * (`deriveRecordingMode`) — never a second enum. A duplicated list is how
27247
+ * `on-device-decision` could have reached the recorder and not the status. */
27248
+ activeMode: RecordingStorageModeSchema,
27236
27249
  nodeId: string(),
27237
27250
  storageBytes: number()
27238
27251
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-notifiers",
3
- "version": "1.2.78",
3
+ "version": "1.2.80",
4
4
  "description": "System notifiers addon for CamStack — a `notification-output` collection provider hosting per-kind notifier adapters (ntfy, pushover, gotify, telegram, discord, webhook, zentik).",
5
5
  "keywords": [
6
6
  "camstack",