@camstack/addon-matter-broker 0.2.74 → 0.2.76

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
@@ -7863,17 +7863,29 @@ var HHMM = /^([01]\d|2[0-3]):[0-5]\d$/;
7863
7863
  /**
7864
7864
  * DERIVED per-camera storage summary — the single field cheap consumers read
7865
7865
  * (the viewer's status dot, the camera list) instead of walking `bands`:
7866
- * - `off` — no band covers the camera (or it is disabled).
7867
- * - `events` — every band records around triggers only.
7868
- * - `continuous` — at least one band records continuously.
7869
- *
7870
- * NEVER authored: the recorder stamps it from the authoritative `bands` on
7871
- * every save (`activeModeForConfig`). Writing it has no effect.
7866
+ * - `off` — no band covers the camera (or it is disabled).
7867
+ * - `events` — every band records around triggers only.
7868
+ * - `continuous` — at least one band records continuously.
7869
+ * - `on-device-decision`— the DEVICE decides: recording runs for as long as the
7870
+ * camera raises its own `recording-signal` level (a robot that cleans). There
7871
+ * is no schedule to author, because there is no hour to program — see
7872
+ * {@link RecordingConfigSchema}`.deviceDecision`.
7873
+ *
7874
+ * NEVER authored: the recorder stamps it from the authoritative intent
7875
+ * (`bands` + `deviceDecision`) on every save (`activeModeForConfig`). Writing it
7876
+ * has no effect.
7877
+ *
7878
+ * `on-device-decision` is named for WHO decides, not for how the recording is
7879
+ * requested. `on-demand` was rejected: in this repo's vocabulary a "demand" is
7880
+ * something the operator makes (the live gate is the recorder's own "demand
7881
+ * window"), and a knob whose name suggests the operator starts it while the
7882
+ * device actually does is the D62 shape — a control nobody can predict.
7872
7883
  */
7873
7884
  var RecordingStorageModeSchema = _enum([
7874
7885
  "off",
7875
7886
  "events",
7876
- "continuous"
7887
+ "continuous",
7888
+ "on-device-decision"
7877
7889
  ]);
7878
7890
  /**
7879
7891
  * Le macro classi che possono aprire una finestra di registrazione — le stesse
@@ -7923,22 +7935,7 @@ var RecordingTriggersSchema = object({
7923
7935
  * il livello: un contatto trovato già aperto al riavvio del runner non fa
7924
7936
  * registrare.
7925
7937
  */
7926
- sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional(),
7927
- /**
7928
- * La camera registra per tutta la durata del SEGNALE che lei stessa
7929
- * pubblica — la cap `recording-signal` (`active: true` mentre il device è in
7930
- * funzione: un robot che pulisce). È un LIVELLO, non un fronte: la finestra
7931
- * resta aperta finché il segnale è alto e si chiude `postBufferSec` dopo la
7932
- * caduta, così una pulizia di quaranta minuti è UNA clip.
7933
- *
7934
- * Non nomina un device: il segnale è della camera stessa, tenuto fresco dal
7935
- * suo provider (D224); il recorder lo ascolta su `DeviceStateChanged` e lo
7936
- * riconcilia leggendo la slice via RPC, con un tetto oltre il quale un
7937
- * segnale mai abbassato (un evento perso) non può tenere aperta una
7938
- * registrazione (D11). Vedi `recorder/addon/band-decision.ts`
7939
- * (`holdTrigger` / `releaseTrigger`).
7940
- */
7941
- deviceSignal: boolean().optional()
7938
+ sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional()
7942
7939
  });
7943
7940
  /**
7944
7941
  * Mode of a single recording band — the recorder per-band vocabulary.
@@ -7968,13 +7965,28 @@ var RecordingBandSchema = object({
7968
7965
  end: string$2().regex(HHMM),
7969
7966
  mode: RecordingBandModeSchema,
7970
7967
  triggers: RecordingBandTriggersSchema.optional(),
7968
+ /**
7969
+ * RETIRED (D381). A band no longer carries a pre-buffer of its own.
7970
+ *
7971
+ * It was the retroactive KEEP bound — which already-written segments survive
7972
+ * a trigger — and it had to be at least as wide as the widest pre-roll the
7973
+ * broker could serve, or the gate would delete the seconds the ring had just
7974
+ * handed the writer. That "at least as wide as" is the tell: it was a second
7975
+ * expression of the broker's retention, in different units, in a different
7976
+ * addon, with an invariant the operator had to maintain by hand. The keep
7977
+ * bound is now derived from the one prebuffer ceiling and there is nothing
7978
+ * left to configure here.
7979
+ *
7980
+ * The key survives in the SHAPE so a config written before that record still
7981
+ * parses and can be migrated deliberately — `RecordingBandSchema` is not
7982
+ * strict, so simply deleting it would strip an operator's value in silence on
7983
+ * the next save (the failure D380 came one commit from shipping). Nothing
7984
+ * reads it: {@link stripRetiredBandPreBufferSec} removes it on load.
7985
+ */
7971
7986
  preBufferSec: number().min(0).optional(),
7972
7987
  postBufferSec: number().min(0).optional()
7973
7988
  });
7974
- ({
7975
- preBufferSec: 15,
7976
- postBufferSec: 30
7977
- }).postBufferSec * 1e3;
7989
+ ({ postBufferSec: 30 }).postBufferSec * 1e3;
7978
7990
  /**
7979
7991
  * Per-device retention overrides. Every field is optional; an unset or `0`
7980
7992
  * value inherits the node-wide recorder default. Only footage-lifetime limits
@@ -8022,8 +8034,29 @@ var RecordingConfigSchema = object({
8022
8034
  * "off" is the absence of a covering band, never a band value.
8023
8035
  */
8024
8036
  bands: array(RecordingBandSchema).default([]),
8037
+ /**
8038
+ * THE device-decided intent: record for as long as the camera itself raises
8039
+ * `recording-signal` (`active: true` while the device is in function — a
8040
+ * robot that cleans). AUTHORED, unlike `mode`, and the only authored
8041
+ * recording intent that is not a band.
8042
+ *
8043
+ * It carries NO schedule on purpose. A band is an HOUR, and this feature has
8044
+ * no hour to program: the device decides. What it costs the operator is one
8045
+ * flag — "this camera can record on its own" — and what it buys is the same
8046
+ * hold/release the recorder already implements (D371, `holdTrigger` /
8047
+ * `releaseTrigger`): the window opens on the rise, stays open for the whole
8048
+ * job however long it is, and closes one pad after the fall.
8049
+ *
8050
+ * EXCLUSIVE with `bands` (below): two authorities deciding when the same
8051
+ * camera records is the D62 failure. `off` remains `enabled: false`, so an
8052
+ * operator switching this camera off is REPORTED off, never as broken.
8053
+ */
8054
+ deviceDecision: boolean().optional(),
8025
8055
  retention: RecordingRetentionSchema.optional()
8026
- }).strict();
8056
+ }).strict().refine((config) => config.deviceDecision !== true || config.bands.length === 0, {
8057
+ message: "deviceDecision is a whole-config mode and carries no schedule: it cannot be combined with bands",
8058
+ path: ["bands"]
8059
+ });
8027
8060
  /**
8028
8061
  * Entity-relocation job state (storage entity-routing spec, Phase 4).
8029
8062
  *
@@ -21105,11 +21138,7 @@ var CameraAudioStatusSchema = object({
21105
21138
  });
21106
21139
  /** Recording block — null when no recording cap is active for this device. */
21107
21140
  var CameraRecordingStatusSchema = object({
21108
- mode: _enum([
21109
- "off",
21110
- "continuous",
21111
- "events"
21112
- ]),
21141
+ mode: RecordingStorageModeSchema,
21113
21142
  active: boolean(),
21114
21143
  storageBytes: number()
21115
21144
  });
@@ -29380,11 +29409,10 @@ DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceI
29380
29409
  var RecordingStatusSchema = object({
29381
29410
  deviceId: number(),
29382
29411
  enabled: boolean(),
29383
- activeMode: _enum([
29384
- "off",
29385
- "continuous",
29386
- "events"
29387
- ]),
29412
+ /** THE derived storage mode, from the one definition
29413
+ * (`deriveRecordingMode`) — never a second enum. A duplicated list is how
29414
+ * `on-device-decision` could have reached the recorder and not the status. */
29415
+ activeMode: RecordingStorageModeSchema,
29388
29416
  nodeId: string$2(),
29389
29417
  storageBytes: number()
29390
29418
  });
package/dist/addon.mjs CHANGED
@@ -7861,17 +7861,29 @@ var HHMM = /^([01]\d|2[0-3]):[0-5]\d$/;
7861
7861
  /**
7862
7862
  * DERIVED per-camera storage summary — the single field cheap consumers read
7863
7863
  * (the viewer's status dot, the camera list) instead of walking `bands`:
7864
- * - `off` — no band covers the camera (or it is disabled).
7865
- * - `events` — every band records around triggers only.
7866
- * - `continuous` — at least one band records continuously.
7867
- *
7868
- * NEVER authored: the recorder stamps it from the authoritative `bands` on
7869
- * every save (`activeModeForConfig`). Writing it has no effect.
7864
+ * - `off` — no band covers the camera (or it is disabled).
7865
+ * - `events` — every band records around triggers only.
7866
+ * - `continuous` — at least one band records continuously.
7867
+ * - `on-device-decision`— the DEVICE decides: recording runs for as long as the
7868
+ * camera raises its own `recording-signal` level (a robot that cleans). There
7869
+ * is no schedule to author, because there is no hour to program — see
7870
+ * {@link RecordingConfigSchema}`.deviceDecision`.
7871
+ *
7872
+ * NEVER authored: the recorder stamps it from the authoritative intent
7873
+ * (`bands` + `deviceDecision`) on every save (`activeModeForConfig`). Writing it
7874
+ * has no effect.
7875
+ *
7876
+ * `on-device-decision` is named for WHO decides, not for how the recording is
7877
+ * requested. `on-demand` was rejected: in this repo's vocabulary a "demand" is
7878
+ * something the operator makes (the live gate is the recorder's own "demand
7879
+ * window"), and a knob whose name suggests the operator starts it while the
7880
+ * device actually does is the D62 shape — a control nobody can predict.
7870
7881
  */
7871
7882
  var RecordingStorageModeSchema = _enum([
7872
7883
  "off",
7873
7884
  "events",
7874
- "continuous"
7885
+ "continuous",
7886
+ "on-device-decision"
7875
7887
  ]);
7876
7888
  /**
7877
7889
  * Le macro classi che possono aprire una finestra di registrazione — le stesse
@@ -7921,22 +7933,7 @@ var RecordingTriggersSchema = object({
7921
7933
  * il livello: un contatto trovato già aperto al riavvio del runner non fa
7922
7934
  * registrare.
7923
7935
  */
7924
- sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional(),
7925
- /**
7926
- * La camera registra per tutta la durata del SEGNALE che lei stessa
7927
- * pubblica — la cap `recording-signal` (`active: true` mentre il device è in
7928
- * funzione: un robot che pulisce). È un LIVELLO, non un fronte: la finestra
7929
- * resta aperta finché il segnale è alto e si chiude `postBufferSec` dopo la
7930
- * caduta, così una pulizia di quaranta minuti è UNA clip.
7931
- *
7932
- * Non nomina un device: il segnale è della camera stessa, tenuto fresco dal
7933
- * suo provider (D224); il recorder lo ascolta su `DeviceStateChanged` e lo
7934
- * riconcilia leggendo la slice via RPC, con un tetto oltre il quale un
7935
- * segnale mai abbassato (un evento perso) non può tenere aperta una
7936
- * registrazione (D11). Vedi `recorder/addon/band-decision.ts`
7937
- * (`holdTrigger` / `releaseTrigger`).
7938
- */
7939
- deviceSignal: boolean().optional()
7936
+ sensorDeviceIds: array(number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional()
7940
7937
  });
7941
7938
  /**
7942
7939
  * Mode of a single recording band — the recorder per-band vocabulary.
@@ -7966,13 +7963,28 @@ var RecordingBandSchema = object({
7966
7963
  end: string$2().regex(HHMM),
7967
7964
  mode: RecordingBandModeSchema,
7968
7965
  triggers: RecordingBandTriggersSchema.optional(),
7966
+ /**
7967
+ * RETIRED (D381). A band no longer carries a pre-buffer of its own.
7968
+ *
7969
+ * It was the retroactive KEEP bound — which already-written segments survive
7970
+ * a trigger — and it had to be at least as wide as the widest pre-roll the
7971
+ * broker could serve, or the gate would delete the seconds the ring had just
7972
+ * handed the writer. That "at least as wide as" is the tell: it was a second
7973
+ * expression of the broker's retention, in different units, in a different
7974
+ * addon, with an invariant the operator had to maintain by hand. The keep
7975
+ * bound is now derived from the one prebuffer ceiling and there is nothing
7976
+ * left to configure here.
7977
+ *
7978
+ * The key survives in the SHAPE so a config written before that record still
7979
+ * parses and can be migrated deliberately — `RecordingBandSchema` is not
7980
+ * strict, so simply deleting it would strip an operator's value in silence on
7981
+ * the next save (the failure D380 came one commit from shipping). Nothing
7982
+ * reads it: {@link stripRetiredBandPreBufferSec} removes it on load.
7983
+ */
7969
7984
  preBufferSec: number().min(0).optional(),
7970
7985
  postBufferSec: number().min(0).optional()
7971
7986
  });
7972
- ({
7973
- preBufferSec: 15,
7974
- postBufferSec: 30
7975
- }).postBufferSec * 1e3;
7987
+ ({ postBufferSec: 30 }).postBufferSec * 1e3;
7976
7988
  /**
7977
7989
  * Per-device retention overrides. Every field is optional; an unset or `0`
7978
7990
  * value inherits the node-wide recorder default. Only footage-lifetime limits
@@ -8020,8 +8032,29 @@ var RecordingConfigSchema = object({
8020
8032
  * "off" is the absence of a covering band, never a band value.
8021
8033
  */
8022
8034
  bands: array(RecordingBandSchema).default([]),
8035
+ /**
8036
+ * THE device-decided intent: record for as long as the camera itself raises
8037
+ * `recording-signal` (`active: true` while the device is in function — a
8038
+ * robot that cleans). AUTHORED, unlike `mode`, and the only authored
8039
+ * recording intent that is not a band.
8040
+ *
8041
+ * It carries NO schedule on purpose. A band is an HOUR, and this feature has
8042
+ * no hour to program: the device decides. What it costs the operator is one
8043
+ * flag — "this camera can record on its own" — and what it buys is the same
8044
+ * hold/release the recorder already implements (D371, `holdTrigger` /
8045
+ * `releaseTrigger`): the window opens on the rise, stays open for the whole
8046
+ * job however long it is, and closes one pad after the fall.
8047
+ *
8048
+ * EXCLUSIVE with `bands` (below): two authorities deciding when the same
8049
+ * camera records is the D62 failure. `off` remains `enabled: false`, so an
8050
+ * operator switching this camera off is REPORTED off, never as broken.
8051
+ */
8052
+ deviceDecision: boolean().optional(),
8023
8053
  retention: RecordingRetentionSchema.optional()
8024
- }).strict();
8054
+ }).strict().refine((config) => config.deviceDecision !== true || config.bands.length === 0, {
8055
+ message: "deviceDecision is a whole-config mode and carries no schedule: it cannot be combined with bands",
8056
+ path: ["bands"]
8057
+ });
8025
8058
  /**
8026
8059
  * Entity-relocation job state (storage entity-routing spec, Phase 4).
8027
8060
  *
@@ -21103,11 +21136,7 @@ var CameraAudioStatusSchema = object({
21103
21136
  });
21104
21137
  /** Recording block — null when no recording cap is active for this device. */
21105
21138
  var CameraRecordingStatusSchema = object({
21106
- mode: _enum([
21107
- "off",
21108
- "continuous",
21109
- "events"
21110
- ]),
21139
+ mode: RecordingStorageModeSchema,
21111
21140
  active: boolean(),
21112
21141
  storageBytes: number()
21113
21142
  });
@@ -29378,11 +29407,10 @@ DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceI
29378
29407
  var RecordingStatusSchema = object({
29379
29408
  deviceId: number(),
29380
29409
  enabled: boolean(),
29381
- activeMode: _enum([
29382
- "off",
29383
- "continuous",
29384
- "events"
29385
- ]),
29410
+ /** THE derived storage mode, from the one definition
29411
+ * (`deriveRecordingMode`) — never a second enum. A duplicated list is how
29412
+ * `on-device-decision` could have reached the recorder and not the status. */
29413
+ activeMode: RecordingStorageModeSchema,
29386
29414
  nodeId: string$2(),
29387
29415
  storageBytes: number()
29388
29416
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-matter-broker",
3
- "version": "0.2.74",
3
+ "version": "0.2.76",
4
4
  "description": "Matter broker addon for CamStack — owns a Matter fabric (commissioning + the long-lived controller) via the matter.js controller and brokers commissioned Matter nodes into CamStack",
5
5
  "keywords": [
6
6
  "camstack",