@camstack/addon-export-alexa 1.2.81 → 1.2.83

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.
@@ -8017,17 +8017,29 @@ var HHMM = /^([01]\d|2[0-3]):[0-5]\d$/;
8017
8017
  /**
8018
8018
  * DERIVED per-camera storage summary — the single field cheap consumers read
8019
8019
  * (the viewer's status dot, the camera list) instead of walking `bands`:
8020
- * - `off` — no band covers the camera (or it is disabled).
8021
- * - `events` — every band records around triggers only.
8022
- * - `continuous` — at least one band records continuously.
8023
- *
8024
- * NEVER authored: the recorder stamps it from the authoritative `bands` on
8025
- * every save (`activeModeForConfig`). Writing it has no effect.
8020
+ * - `off` — no band covers the camera (or it is disabled).
8021
+ * - `events` — every band records around triggers only.
8022
+ * - `continuous` — at least one band records continuously.
8023
+ * - `on-device-decision`— the DEVICE decides: recording runs for as long as the
8024
+ * camera raises its own `recording-signal` level (a robot that cleans). There
8025
+ * is no schedule to author, because there is no hour to program — see
8026
+ * {@link RecordingConfigSchema}`.deviceDecision`.
8027
+ *
8028
+ * NEVER authored: the recorder stamps it from the authoritative intent
8029
+ * (`bands` + `deviceDecision`) on every save (`activeModeForConfig`). Writing it
8030
+ * has no effect.
8031
+ *
8032
+ * `on-device-decision` is named for WHO decides, not for how the recording is
8033
+ * requested. `on-demand` was rejected: in this repo's vocabulary a "demand" is
8034
+ * something the operator makes (the live gate is the recorder's own "demand
8035
+ * window"), and a knob whose name suggests the operator starts it while the
8036
+ * device actually does is the D62 shape — a control nobody can predict.
8026
8037
  */
8027
8038
  var RecordingStorageModeSchema = _enum([
8028
8039
  "off",
8029
8040
  "events",
8030
- "continuous"
8041
+ "continuous",
8042
+ "on-device-decision"
8031
8043
  ]);
8032
8044
  /**
8033
8045
  * Le macro classi che possono aprire una finestra di registrazione — le stesse
@@ -8077,22 +8089,7 @@ var RecordingTriggersSchema = object({
8077
8089
  * il livello: un contatto trovato già aperto al riavvio del runner non fa
8078
8090
  * registrare.
8079
8091
  */
8080
- sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional(),
8081
- /**
8082
- * La camera registra per tutta la durata del SEGNALE che lei stessa
8083
- * pubblica — la cap `recording-signal` (`active: true` mentre il device è in
8084
- * funzione: un robot che pulisce). È un LIVELLO, non un fronte: la finestra
8085
- * resta aperta finché il segnale è alto e si chiude `postBufferSec` dopo la
8086
- * caduta, così una pulizia di quaranta minuti è UNA clip.
8087
- *
8088
- * Non nomina un device: il segnale è della camera stessa, tenuto fresco dal
8089
- * suo provider (D224); il recorder lo ascolta su `DeviceStateChanged` e lo
8090
- * riconcilia leggendo la slice via RPC, con un tetto oltre il quale un
8091
- * segnale mai abbassato (un evento perso) non può tenere aperta una
8092
- * registrazione (D11). Vedi `recorder/addon/band-decision.ts`
8093
- * (`holdTrigger` / `releaseTrigger`).
8094
- */
8095
- deviceSignal: boolean().optional()
8092
+ sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional()
8096
8093
  });
8097
8094
  /**
8098
8095
  * Mode of a single recording band — the recorder per-band vocabulary.
@@ -8122,13 +8119,28 @@ var RecordingBandSchema = object({
8122
8119
  end: string().regex(HHMM),
8123
8120
  mode: RecordingBandModeSchema,
8124
8121
  triggers: RecordingBandTriggersSchema.optional(),
8122
+ /**
8123
+ * RETIRED (D381). A band no longer carries a pre-buffer of its own.
8124
+ *
8125
+ * It was the retroactive KEEP bound — which already-written segments survive
8126
+ * a trigger — and it had to be at least as wide as the widest pre-roll the
8127
+ * broker could serve, or the gate would delete the seconds the ring had just
8128
+ * handed the writer. That "at least as wide as" is the tell: it was a second
8129
+ * expression of the broker's retention, in different units, in a different
8130
+ * addon, with an invariant the operator had to maintain by hand. The keep
8131
+ * bound is now derived from the one prebuffer ceiling and there is nothing
8132
+ * left to configure here.
8133
+ *
8134
+ * The key survives in the SHAPE so a config written before that record still
8135
+ * parses and can be migrated deliberately — `RecordingBandSchema` is not
8136
+ * strict, so simply deleting it would strip an operator's value in silence on
8137
+ * the next save (the failure D380 came one commit from shipping). Nothing
8138
+ * reads it: {@link stripRetiredBandPreBufferSec} removes it on load.
8139
+ */
8125
8140
  preBufferSec: number().min(0).optional(),
8126
8141
  postBufferSec: number().min(0).optional()
8127
8142
  });
8128
- ({
8129
- preBufferSec: 15,
8130
- postBufferSec: 30
8131
- }).postBufferSec * 1e3;
8143
+ ({ postBufferSec: 30 }).postBufferSec * 1e3;
8132
8144
  /**
8133
8145
  * Per-device retention overrides. Every field is optional; an unset or `0`
8134
8146
  * value inherits the node-wide recorder default. Only footage-lifetime limits
@@ -8176,8 +8188,29 @@ var RecordingConfigSchema = object({
8176
8188
  * "off" is the absence of a covering band, never a band value.
8177
8189
  */
8178
8190
  bands: array(RecordingBandSchema).default([]),
8191
+ /**
8192
+ * THE device-decided intent: record for as long as the camera itself raises
8193
+ * `recording-signal` (`active: true` while the device is in function — a
8194
+ * robot that cleans). AUTHORED, unlike `mode`, and the only authored
8195
+ * recording intent that is not a band.
8196
+ *
8197
+ * It carries NO schedule on purpose. A band is an HOUR, and this feature has
8198
+ * no hour to program: the device decides. What it costs the operator is one
8199
+ * flag — "this camera can record on its own" — and what it buys is the same
8200
+ * hold/release the recorder already implements (D371, `holdTrigger` /
8201
+ * `releaseTrigger`): the window opens on the rise, stays open for the whole
8202
+ * job however long it is, and closes one pad after the fall.
8203
+ *
8204
+ * EXCLUSIVE with `bands` (below): two authorities deciding when the same
8205
+ * camera records is the D62 failure. `off` remains `enabled: false`, so an
8206
+ * operator switching this camera off is REPORTED off, never as broken.
8207
+ */
8208
+ deviceDecision: boolean().optional(),
8179
8209
  retention: RecordingRetentionSchema.optional()
8180
- }).strict();
8210
+ }).strict().refine((config) => config.deviceDecision !== true || config.bands.length === 0, {
8211
+ message: "deviceDecision is a whole-config mode and carries no schedule: it cannot be combined with bands",
8212
+ path: ["bands"]
8213
+ });
8181
8214
  /**
8182
8215
  * Entity-relocation job state (storage entity-routing spec, Phase 4).
8183
8216
  *
@@ -20968,11 +21001,7 @@ var CameraAudioStatusSchema = object({
20968
21001
  });
20969
21002
  /** Recording block — null when no recording cap is active for this device. */
20970
21003
  var CameraRecordingStatusSchema = object({
20971
- mode: _enum([
20972
- "off",
20973
- "continuous",
20974
- "events"
20975
- ]),
21004
+ mode: RecordingStorageModeSchema,
20976
21005
  active: boolean(),
20977
21006
  storageBytes: number()
20978
21007
  });
@@ -27378,11 +27407,10 @@ DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceI
27378
27407
  var RecordingStatusSchema = object({
27379
27408
  deviceId: number(),
27380
27409
  enabled: boolean(),
27381
- activeMode: _enum([
27382
- "off",
27383
- "continuous",
27384
- "events"
27385
- ]),
27410
+ /** THE derived storage mode, from the one definition
27411
+ * (`deriveRecordingMode`) — never a second enum. A duplicated list is how
27412
+ * `on-device-decision` could have reached the recorder and not the status. */
27413
+ activeMode: RecordingStorageModeSchema,
27386
27414
  nodeId: string(),
27387
27415
  storageBytes: number()
27388
27416
  });
@@ -7990,17 +7990,29 @@ var HHMM = /^([01]\d|2[0-3]):[0-5]\d$/;
7990
7990
  /**
7991
7991
  * DERIVED per-camera storage summary — the single field cheap consumers read
7992
7992
  * (the viewer's status dot, the camera list) instead of walking `bands`:
7993
- * - `off` — no band covers the camera (or it is disabled).
7994
- * - `events` — every band records around triggers only.
7995
- * - `continuous` — at least one band records continuously.
7996
- *
7997
- * NEVER authored: the recorder stamps it from the authoritative `bands` on
7998
- * every save (`activeModeForConfig`). Writing it has no effect.
7993
+ * - `off` — no band covers the camera (or it is disabled).
7994
+ * - `events` — every band records around triggers only.
7995
+ * - `continuous` — at least one band records continuously.
7996
+ * - `on-device-decision`— the DEVICE decides: recording runs for as long as the
7997
+ * camera raises its own `recording-signal` level (a robot that cleans). There
7998
+ * is no schedule to author, because there is no hour to program — see
7999
+ * {@link RecordingConfigSchema}`.deviceDecision`.
8000
+ *
8001
+ * NEVER authored: the recorder stamps it from the authoritative intent
8002
+ * (`bands` + `deviceDecision`) on every save (`activeModeForConfig`). Writing it
8003
+ * has no effect.
8004
+ *
8005
+ * `on-device-decision` is named for WHO decides, not for how the recording is
8006
+ * requested. `on-demand` was rejected: in this repo's vocabulary a "demand" is
8007
+ * something the operator makes (the live gate is the recorder's own "demand
8008
+ * window"), and a knob whose name suggests the operator starts it while the
8009
+ * device actually does is the D62 shape — a control nobody can predict.
7999
8010
  */
8000
8011
  var RecordingStorageModeSchema = _enum([
8001
8012
  "off",
8002
8013
  "events",
8003
- "continuous"
8014
+ "continuous",
8015
+ "on-device-decision"
8004
8016
  ]);
8005
8017
  /**
8006
8018
  * Le macro classi che possono aprire una finestra di registrazione — le stesse
@@ -8050,22 +8062,7 @@ var RecordingTriggersSchema = object({
8050
8062
  * il livello: un contatto trovato già aperto al riavvio del runner non fa
8051
8063
  * registrare.
8052
8064
  */
8053
- sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional(),
8054
- /**
8055
- * La camera registra per tutta la durata del SEGNALE che lei stessa
8056
- * pubblica — la cap `recording-signal` (`active: true` mentre il device è in
8057
- * funzione: un robot che pulisce). È un LIVELLO, non un fronte: la finestra
8058
- * resta aperta finché il segnale è alto e si chiude `postBufferSec` dopo la
8059
- * caduta, così una pulizia di quaranta minuti è UNA clip.
8060
- *
8061
- * Non nomina un device: il segnale è della camera stessa, tenuto fresco dal
8062
- * suo provider (D224); il recorder lo ascolta su `DeviceStateChanged` e lo
8063
- * riconcilia leggendo la slice via RPC, con un tetto oltre il quale un
8064
- * segnale mai abbassato (un evento perso) non può tenere aperta una
8065
- * registrazione (D11). Vedi `recorder/addon/band-decision.ts`
8066
- * (`holdTrigger` / `releaseTrigger`).
8067
- */
8068
- deviceSignal: boolean().optional()
8065
+ sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional()
8069
8066
  });
8070
8067
  /**
8071
8068
  * Mode of a single recording band — the recorder per-band vocabulary.
@@ -8095,13 +8092,28 @@ var RecordingBandSchema = object({
8095
8092
  end: string().regex(HHMM),
8096
8093
  mode: RecordingBandModeSchema,
8097
8094
  triggers: RecordingBandTriggersSchema.optional(),
8095
+ /**
8096
+ * RETIRED (D381). A band no longer carries a pre-buffer of its own.
8097
+ *
8098
+ * It was the retroactive KEEP bound — which already-written segments survive
8099
+ * a trigger — and it had to be at least as wide as the widest pre-roll the
8100
+ * broker could serve, or the gate would delete the seconds the ring had just
8101
+ * handed the writer. That "at least as wide as" is the tell: it was a second
8102
+ * expression of the broker's retention, in different units, in a different
8103
+ * addon, with an invariant the operator had to maintain by hand. The keep
8104
+ * bound is now derived from the one prebuffer ceiling and there is nothing
8105
+ * left to configure here.
8106
+ *
8107
+ * The key survives in the SHAPE so a config written before that record still
8108
+ * parses and can be migrated deliberately — `RecordingBandSchema` is not
8109
+ * strict, so simply deleting it would strip an operator's value in silence on
8110
+ * the next save (the failure D380 came one commit from shipping). Nothing
8111
+ * reads it: {@link stripRetiredBandPreBufferSec} removes it on load.
8112
+ */
8098
8113
  preBufferSec: number().min(0).optional(),
8099
8114
  postBufferSec: number().min(0).optional()
8100
8115
  });
8101
- ({
8102
- preBufferSec: 15,
8103
- postBufferSec: 30
8104
- }).postBufferSec * 1e3;
8116
+ ({ postBufferSec: 30 }).postBufferSec * 1e3;
8105
8117
  /**
8106
8118
  * Per-device retention overrides. Every field is optional; an unset or `0`
8107
8119
  * value inherits the node-wide recorder default. Only footage-lifetime limits
@@ -8149,8 +8161,29 @@ var RecordingConfigSchema = object({
8149
8161
  * "off" is the absence of a covering band, never a band value.
8150
8162
  */
8151
8163
  bands: array(RecordingBandSchema).default([]),
8164
+ /**
8165
+ * THE device-decided intent: record for as long as the camera itself raises
8166
+ * `recording-signal` (`active: true` while the device is in function — a
8167
+ * robot that cleans). AUTHORED, unlike `mode`, and the only authored
8168
+ * recording intent that is not a band.
8169
+ *
8170
+ * It carries NO schedule on purpose. A band is an HOUR, and this feature has
8171
+ * no hour to program: the device decides. What it costs the operator is one
8172
+ * flag — "this camera can record on its own" — and what it buys is the same
8173
+ * hold/release the recorder already implements (D371, `holdTrigger` /
8174
+ * `releaseTrigger`): the window opens on the rise, stays open for the whole
8175
+ * job however long it is, and closes one pad after the fall.
8176
+ *
8177
+ * EXCLUSIVE with `bands` (below): two authorities deciding when the same
8178
+ * camera records is the D62 failure. `off` remains `enabled: false`, so an
8179
+ * operator switching this camera off is REPORTED off, never as broken.
8180
+ */
8181
+ deviceDecision: boolean().optional(),
8152
8182
  retention: RecordingRetentionSchema.optional()
8153
- }).strict();
8183
+ }).strict().refine((config) => config.deviceDecision !== true || config.bands.length === 0, {
8184
+ message: "deviceDecision is a whole-config mode and carries no schedule: it cannot be combined with bands",
8185
+ path: ["bands"]
8186
+ });
8154
8187
  /**
8155
8188
  * Entity-relocation job state (storage entity-routing spec, Phase 4).
8156
8189
  *
@@ -20941,11 +20974,7 @@ var CameraAudioStatusSchema = object({
20941
20974
  });
20942
20975
  /** Recording block — null when no recording cap is active for this device. */
20943
20976
  var CameraRecordingStatusSchema = object({
20944
- mode: _enum([
20945
- "off",
20946
- "continuous",
20947
- "events"
20948
- ]),
20977
+ mode: RecordingStorageModeSchema,
20949
20978
  active: boolean(),
20950
20979
  storageBytes: number()
20951
20980
  });
@@ -27351,11 +27380,10 @@ DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceI
27351
27380
  var RecordingStatusSchema = object({
27352
27381
  deviceId: number(),
27353
27382
  enabled: boolean(),
27354
- activeMode: _enum([
27355
- "off",
27356
- "continuous",
27357
- "events"
27358
- ]),
27383
+ /** THE derived storage mode, from the one definition
27384
+ * (`deriveRecordingMode`) — never a second enum. A duplicated list is how
27385
+ * `on-device-decision` could have reached the recorder and not the status. */
27386
+ activeMode: RecordingStorageModeSchema,
27359
27387
  nodeId: string(),
27360
27388
  storageBytes: number()
27361
27389
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-export-alexa",
3
- "version": "1.2.81",
3
+ "version": "1.2.83",
4
4
  "description": "Alexa Smart Home Skill export — hub-side OAuth provider + directive handler. The companion AWS Lambda forwards Alexa directives to this addon's /addon/export-alexa/directive endpoint.",
5
5
  "keywords": [
6
6
  "camstack",