@camstack/addon-matter-broker 0.2.141 → 0.2.143

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 (3) hide show
  1. package/dist/addon.js +237 -61
  2. package/dist/addon.mjs +237 -61
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -13,7 +13,7 @@ let node_stream_promises = require("node:stream/promises");
13
13
  let node_net = require("node:net");
14
14
  let node_dgram = require("node:dgram");
15
15
  node_dgram = require_esm.__toESM(node_dgram, 1);
16
- //#region ../types/dist/event-category-DOl51-Ij.mjs
16
+ //#region ../types/dist/event-category-BfJwUd2S.mjs
17
17
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
18
18
  EventCategory["SystemBoot"] = "system.boot";
19
19
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -330,6 +330,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
330
330
  */
331
331
  EventCategory["PipelineDetectionBlind"] = "pipeline.detection-blind";
332
332
  /**
333
+ * A camera's motion source has fired constantly with no subject for an hour
334
+ * (motion duty or session count over the bar, zero detections) — it is not
335
+ * blind, its motion zones or sensitivity want tuning (D907). Paired with
336
+ * {@link PipelineMotionCalm}.
337
+ */
338
+ EventCategory["PipelineMotionNoisy"] = "pipeline.motion-noisy";
339
+ /** The recovery edge of {@link PipelineMotionNoisy}: the motion fell back, or a detection arrived. */
340
+ EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
341
+ /**
333
342
  * Per-camera pipeline config was mutated by the orchestrator
334
343
  * (3-level settings change via `setAgentAddonDefaults` /
335
344
  * `setCameraStepToggle` / `setCameraPipelineForAgent` or a
@@ -701,6 +710,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
701
710
  EventCategory["BackupRestored"] = "backup.restored";
702
711
  EventCategory["NotificationDispatched"] = "notification.dispatched";
703
712
  EventCategory["NotificationFailed"] = "notification.failed";
713
+ /**
714
+ * A notification rule that cannot work (D905): its stored row does not load,
715
+ * or it still names a device / delivery target the prune CONFIRMED deleted.
716
+ * One edge per rule per distinct set of reasons; never on an unanswered read.
717
+ */
718
+ EventCategory["NotificationRuleBroken"] = "notification.rule-broken";
719
+ /** The clear of {@link NotificationRuleBroken}: the rule loads and names nothing deleted. */
720
+ EventCategory["NotificationRuleRepaired"] = "notification.rule-repaired";
704
721
  EventCategory["DeviceUpdated"] = "device.updated";
705
722
  /**
706
723
  * Transport-level connectivity. Emitted by the device driver when
@@ -5561,7 +5578,7 @@ var ZodIssueCode = {
5561
5578
  var ZodFirstPartyTypeKind;
5562
5579
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5563
5580
  //#endregion
5564
- //#region ../types/dist/sleep-_sV1BE2f.mjs
5581
+ //#region ../types/dist/sleep-DJFUfKvA.mjs
5565
5582
  /**
5566
5583
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5567
5584
  * window to float samples (D455).
@@ -8160,7 +8177,7 @@ var EntryDescriptorSchema = object({
8160
8177
  /** JSON Schema of the entry body; `secret: true` marks a password field. */
8161
8178
  fields: record(string$2(), unknown())
8162
8179
  }).strict();
8163
- /** What crosses the wire and sits in the engine's catalog: JSON only, no Zod. */
8180
+ /** What crosses the wire from an addon: JSON only, no Zod. An unknown key is refused. */
8164
8181
  var RecordKindDeclarationSchema = object({
8165
8182
  database: _enum(RECORD_DATABASES).default("settings"),
8166
8183
  class: _enum(RECORD_CLASSES),
@@ -8179,14 +8196,6 @@ var RecordKindDeclarationSchema = object({
8179
8196
  secretPaths: array(string$2().min(1)).default([]),
8180
8197
  /** The id key of each array that carries a secret (`{ headers: 'name' }`). */
8181
8198
  secretArrayKeys: record(string$2(), string$2()).default({}),
8182
- /**
8183
- * RETIRED (D900): the legacy table a kind adopted from during the records
8184
- * migration. Nothing declares it any more and nothing reads it; the schema
8185
- * still ACCEPTS it because the catalog rows the migration wrote carry it
8186
- * (an orphaned kind is never redeclared) and an addon built before the
8187
- * removal still sends it. Never set it.
8188
- */
8189
- adoptsFrom: string$2().min(1).optional(),
8190
8199
  /** Kinds that must agree through `transact` sit in one file under one family name. */
8191
8200
  transactFamily: string$2().min(1).optional(),
8192
8201
  entry: EntryDescriptorSchema.optional()
@@ -12982,17 +12991,6 @@ object({
12982
12991
  createdAt: number(),
12983
12992
  updatedAt: number()
12984
12993
  });
12985
- object({
12986
- id: string$2(),
12987
- label: string$2(),
12988
- isAdmin: boolean().default(false),
12989
- allowedProviders: AllowedProviderSchema,
12990
- allowedDevices: AllowedDevicesSchema,
12991
- tokenHash: string$2(),
12992
- tokenPrefix: string$2(),
12993
- createdAt: number(),
12994
- lastUsedAt: number().optional()
12995
- });
12996
12994
  object({
12997
12995
  id: string$2(),
12998
12996
  userId: string$2(),
@@ -17023,16 +17021,36 @@ var RecordKindStateSchema = _enum([
17023
17021
  var DeclareKindResultSchema = object({
17024
17022
  kindId: number().int(),
17025
17023
  state: RecordKindStateSchema,
17026
- createdIndexes: array(string$2()),
17027
- /**
17028
- * RETIRED (D900): always `null`. It carried the records-migration boot guard;
17029
- * it stays on the wire, null, because an addon built before the removal reads
17030
- * an ABSENT field as "adoption pending" and refuses to start.
17031
- */
17032
- adoptionPending: _null()
17024
+ createdIndexes: array(string$2())
17033
17025
  });
17034
17026
  /** Keychain refs a write released (the old marker is gone from the row): the owner deletes the values. */
17035
17027
  var SecretRefsList = array(string$2());
17028
+ /**
17029
+ * One op of a `transact`: the single-row writes, each on a kind of the caller.
17030
+ * All ops of one call share ONE database file and ONE `transactFamily`.
17031
+ */
17032
+ var RecordTransactOpSchema = discriminatedUnion("op", [
17033
+ object({
17034
+ op: literal("put"),
17035
+ kind: RecordKindNameSchema,
17036
+ record: RecordInputSchema,
17037
+ ifRev: number().int().min(0).optional()
17038
+ }),
17039
+ object({
17040
+ op: literal("patch"),
17041
+ kind: RecordKindNameSchema,
17042
+ id: RecordIdSchema,
17043
+ data: RecordBodySchema,
17044
+ at: number().int().nullable().optional(),
17045
+ expiresAt: number().int().nullable().optional(),
17046
+ ifRev: number().int().min(1).optional()
17047
+ }),
17048
+ object({
17049
+ op: literal("delete"),
17050
+ kind: RecordKindNameSchema,
17051
+ id: RecordIdSchema
17052
+ })
17053
+ ]);
17036
17054
  var RecordSecretRefsSchema = record(string$2(), record(string$2(), string$2()));
17037
17055
  method(object({ kinds: record(RecordKindNameSchema, RecordKindDeclarationSchema) }), object({ kinds: record(string$2(), DeclareKindResultSchema) }), {
17038
17056
  kind: "mutation",
@@ -17139,6 +17157,16 @@ method(object({ kinds: record(RecordKindNameSchema, RecordKindDeclarationSchema)
17139
17157
  }), {
17140
17158
  kind: "mutation",
17141
17159
  auth: "admin"
17160
+ }), method(object({ ops: array(RecordTransactOpSchema).min(1).max(RECORD_BATCH_MAX) }), object({
17161
+ results: array(object({
17162
+ rev: number().int().nullable(),
17163
+ deleted: boolean()
17164
+ })),
17165
+ releasedRefs: SecretRefsList,
17166
+ secretRefs: SecretRefsList
17167
+ }), {
17168
+ kind: "mutation",
17169
+ auth: "admin"
17142
17170
  }), method(object({
17143
17171
  deviceId: number().int(),
17144
17172
  kinds: array(RecordKindNameSchema).optional()
@@ -42750,9 +42778,13 @@ var NcSystemEventKindSchema = _enum([
42750
42778
  "node-updating",
42751
42779
  "node-inference-unavailable",
42752
42780
  "detection-blind",
42781
+ "motion-noisy",
42782
+ "motion-calm",
42753
42783
  "recording-stalled",
42754
42784
  "recording-healthy",
42755
42785
  "recording-degraded",
42786
+ "device-attention-required",
42787
+ "device-attention-resolved",
42756
42788
  "storage-location-low",
42757
42789
  "storage-location-critical",
42758
42790
  "storage-location-ok",
@@ -42776,6 +42808,8 @@ var NcSystemEventKindSchema = _enum([
42776
42808
  "alert-critical",
42777
42809
  "alert-error",
42778
42810
  "alert-critical-resolved",
42811
+ "rule-broken",
42812
+ "rule-repaired",
42779
42813
  "camera-online",
42780
42814
  "camera-offline",
42781
42815
  "camera-disabled",
@@ -56091,6 +56125,16 @@ var DishwasherStatusSchema = object({
56091
56125
  powerState: string$2().nullable(),
56092
56126
  saltLevel: DishwasherConsumableLevelSchema.nullable(),
56093
56127
  rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
56128
+ /**
56129
+ * True while the appliance asks for its filter to be cleaned (smart-filter, filter-system or
56130
+ * combined care-and-filter reminder raised); false when every such reminder reads clear; null
56131
+ * when none is reported. A cleared reminder is not an unknown one.
56132
+ */
56133
+ filterCleaningDue: boolean().nullable(),
56134
+ /** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
56135
+ machineCareDue: boolean().nullable(),
56136
+ /** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
56137
+ machineCareRemainingRuns: number().int().nonnegative().nullable(),
56094
56138
  /** Option states: null when the appliance does not expose the option or has not said. */
56095
56139
  halfLoad: boolean().nullable(),
56096
56140
  hygienePlus: boolean().nullable(),
@@ -64741,16 +64785,6 @@ var UpdateUserInputSchema = object({
64741
64785
  allowedDevices: record(string$2(), union([array(string$2()), literal("*")])).optional(),
64742
64786
  scopes: array(TokenScopeSchema).optional()
64743
64787
  });
64744
- var ApiKeySummarySchema = object({
64745
- id: string$2(),
64746
- label: string$2(),
64747
- isAdmin: boolean().default(false),
64748
- allowedProviders: union([array(string$2()), literal("*")]).optional(),
64749
- allowedDevices: record(string$2(), union([array(string$2()), literal("*")])).optional(),
64750
- tokenPrefix: string$2(),
64751
- createdAt: number(),
64752
- lastUsedAt: number().optional()
64753
- });
64754
64788
  var OauthSessionSummarySchema = object({
64755
64789
  id: string$2(),
64756
64790
  userId: string$2(),
@@ -64772,8 +64806,7 @@ var TotpStatusSchema = object({
64772
64806
  confirmedAt: number().nullable()
64773
64807
  });
64774
64808
  /**
64775
- * user-management — singleton capability for user accounts and the
64776
- * legacy API-key rows.
64809
+ * user-management — singleton capability for user accounts.
64777
64810
  *
64778
64811
  * v2 model: every method gated by `auth: 'admin'`. Admin-only delegation
64779
64812
  * — the subset check on `setUserScopes` is moot
@@ -64829,10 +64862,6 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
64829
64862
  }), UserSummarySchema.extend({ passwordHash: string$2() }).nullable(), {
64830
64863
  kind: "mutation",
64831
64864
  access: "view"
64832
- }), method(_void(), array(ApiKeySummarySchema), { auth: "admin" }), method(object({ id: string$2() }), object({ success: literal(true) }), {
64833
- kind: "mutation",
64834
- auth: "admin",
64835
- access: "delete"
64836
64865
  }), method(object({ userId: string$2() }), TotpSetupResultSchema, {
64837
64866
  kind: "mutation",
64838
64867
  auth: "admin",
@@ -74288,6 +74317,12 @@ Object.freeze({
74288
74317
  addonId: null,
74289
74318
  access: "view"
74290
74319
  },
74320
+ "records.transact": {
74321
+ capName: "records",
74322
+ capScope: "system",
74323
+ addonId: null,
74324
+ access: "create"
74325
+ },
74291
74326
  "sceneMonitor.captureReference": {
74292
74327
  capName: "scene-monitor",
74293
74328
  capScope: "device",
@@ -75620,12 +75655,6 @@ Object.freeze({
75620
75655
  addonId: null,
75621
75656
  access: "view"
75622
75657
  },
75623
- "userManagement.listApiKeys": {
75624
- capName: "user-management",
75625
- capScope: "system",
75626
- addonId: null,
75627
- access: "view"
75628
- },
75629
75658
  "userManagement.listExternalIdentities": {
75630
75659
  capName: "user-management",
75631
75660
  capScope: "system",
@@ -75680,12 +75709,6 @@ Object.freeze({
75680
75709
  addonId: null,
75681
75710
  access: "create"
75682
75711
  },
75683
- "userManagement.revokeApiKey": {
75684
- capName: "user-management",
75685
- capScope: "system",
75686
- addonId: null,
75687
- access: "delete"
75688
- },
75689
75712
  "userManagement.revokeOauthSession": {
75690
75713
  capName: "user-management",
75691
75714
  capScope: "system",
@@ -79050,9 +79073,13 @@ new Map(Object.entries({
79050
79073
  "stream-online": "device-events",
79051
79074
  "stream-offline": "device-events",
79052
79075
  "detection-blind": "device-events",
79076
+ "motion-noisy": "device-events",
79077
+ "motion-calm": "device-events",
79053
79078
  "recording-stalled": "device-events",
79054
79079
  "recording-healthy": "device-events",
79055
79080
  "recording-degraded": "device-events",
79081
+ "device-attention-required": "device-events",
79082
+ "device-attention-resolved": "device-events",
79056
79083
  "node-online": "system",
79057
79084
  "node-offline": "system",
79058
79085
  "node-restarting": "system",
@@ -79069,6 +79096,8 @@ new Map(Object.entries({
79069
79096
  "alert-critical": "system",
79070
79097
  "alert-error": "system",
79071
79098
  "alert-critical-resolved": "system",
79099
+ "rule-broken": "system",
79100
+ "rule-repaired": "system",
79072
79101
  "storage-location-low": "system",
79073
79102
  "storage-location-critical": "system",
79074
79103
  "storage-location-ok": "system",
@@ -79133,6 +79162,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
79133
79162
  label: "Detecting nothing",
79134
79163
  kinds: ["detection-blind"]
79135
79164
  },
79165
+ {
79166
+ id: "motion-noise",
79167
+ family: "device-events",
79168
+ label: "Motion without a subject",
79169
+ kinds: ["motion-noisy", "motion-calm"]
79170
+ },
79136
79171
  {
79137
79172
  id: "recording",
79138
79173
  family: "device-events",
@@ -79143,6 +79178,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
79143
79178
  "recording-degraded"
79144
79179
  ]
79145
79180
  },
79181
+ {
79182
+ id: "device-attention",
79183
+ family: "device-events",
79184
+ label: "Needs attention",
79185
+ kinds: ["device-attention-required", "device-attention-resolved"]
79186
+ },
79146
79187
  {
79147
79188
  id: "nodes",
79148
79189
  family: "system",
@@ -79203,6 +79244,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
79203
79244
  "alert-critical-resolved"
79204
79245
  ]
79205
79246
  },
79247
+ {
79248
+ id: "rule-health",
79249
+ family: "system",
79250
+ label: "Notification rules",
79251
+ kinds: ["rule-broken", "rule-repaired"]
79252
+ },
79206
79253
  {
79207
79254
  id: "alarm",
79208
79255
  family: "alarm",
@@ -79276,6 +79323,7 @@ var ALERT_EPISODE = [
79276
79323
  "alert-error",
79277
79324
  "alert-critical-resolved"
79278
79325
  ];
79326
+ var DEVICE_ATTENTION = ["device-attention-required", "device-attention-resolved"];
79279
79327
  var UPDATES = [
79280
79328
  "addon-update-available",
79281
79329
  "server-update-available",
@@ -79305,9 +79353,12 @@ var DEVICE_EVENTS = [
79305
79353
  "stream-online",
79306
79354
  "stream-offline",
79307
79355
  "detection-blind",
79356
+ "motion-noisy",
79357
+ "motion-calm",
79308
79358
  "recording-stalled",
79309
79359
  "recording-healthy",
79310
79360
  "recording-degraded",
79361
+ ...DEVICE_ATTENTION,
79311
79362
  ...ALARM
79312
79363
  ];
79313
79364
  /** Every kind a summary may speak about — the two summarisable families. */
@@ -79475,7 +79526,13 @@ var STATE_SUMMARY_VARS = [
79475
79526
  [...RULE_TEXT],
79476
79527
  [...RULE_TEXT],
79477
79528
  [...RULE_TEXT],
79478
- ([...RULE_TEXT], [...ALERT_EPISODE]),
79529
+ [...RULE_TEXT],
79530
+ [...RULE_TEXT],
79531
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
79532
+ [...RULE_TEXT],
79533
+ [...RULE_TEXT],
79534
+ [...RULE_TEXT],
79535
+ [...RULE_TEXT],
79479
79536
  [...RULE_TEXT],
79480
79537
  [...RULE_TEXT],
79481
79538
  [...RULE_TEXT],
@@ -79493,11 +79550,11 @@ var STATE_SUMMARY_VARS = [
79493
79550
  [...RULE_TEXT],
79494
79551
  [...RULE_TEXT],
79495
79552
  [...RULE_TEXT],
79553
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
79496
79554
  ([...RULE_TEXT], [...ALERT_EPISODE]),
79555
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
79497
79556
  ([...RULE_TEXT], [...ALERT_EPISODE]),
79498
- ([...RULE_TEXT], [...ALERT_EPISODE]),
79499
- ([...RULE_TEXT], [...ALERT_EPISODE]),
79500
- ([...RULE_TEXT], [...ALERT_EPISODE]),
79557
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
79501
79558
  [...RULE_TEXT],
79502
79559
  [...RULE_TEXT],
79503
79560
  [...RULE_TEXT],
@@ -79518,6 +79575,125 @@ var STATE_SUMMARY_VARS = [
79518
79575
  [...RULE_TEXT],
79519
79576
  ...STATE_SUMMARY_VARS
79520
79577
  ];
79578
+ new Map([
79579
+ {
79580
+ id: "device-connectivity",
79581
+ family: "device-events",
79582
+ label: "Device connectivity (offline / back online)",
79583
+ bad: ["device-offline"],
79584
+ recovery: ["device-online"],
79585
+ snapshotLabel: "Devices offline now",
79586
+ snapshotSection: "device-state"
79587
+ },
79588
+ {
79589
+ id: "device-switch",
79590
+ family: "device-events",
79591
+ label: "Device switched off / back on",
79592
+ bad: ["device-disabled"],
79593
+ recovery: ["device-enabled"],
79594
+ snapshotLabel: "Devices switched off now",
79595
+ snapshotSection: "device-state"
79596
+ },
79597
+ {
79598
+ id: "stream-connectivity",
79599
+ family: "device-events",
79600
+ label: "Stream connectivity (offline / back online)",
79601
+ bad: ["stream-offline"],
79602
+ recovery: ["stream-online"],
79603
+ snapshotLabel: "Streams offline now",
79604
+ snapshotSection: "streams"
79605
+ },
79606
+ {
79607
+ id: "battery",
79608
+ family: "device-events",
79609
+ label: "Battery (low / back to normal)",
79610
+ bad: ["device-battery-low"],
79611
+ recovery: ["device-battery-normal"],
79612
+ snapshotLabel: "Batteries low now",
79613
+ snapshotSection: "battery"
79614
+ },
79615
+ {
79616
+ id: "consumables",
79617
+ family: "device-events",
79618
+ label: "Consumables (low / replaced)",
79619
+ bad: ["device-consumable-low"],
79620
+ recovery: ["device-consumable-normal"],
79621
+ snapshotLabel: "Consumables low now",
79622
+ snapshotSection: "consumables"
79623
+ },
79624
+ {
79625
+ id: "tanks",
79626
+ family: "device-events",
79627
+ label: "Tanks (low or full / back to normal)",
79628
+ bad: ["device-tank-low", "device-tank-full"],
79629
+ recovery: ["device-tank-normal"],
79630
+ snapshotLabel: "Tanks low or full now",
79631
+ snapshotSection: "tanks"
79632
+ },
79633
+ {
79634
+ id: "motion-noise",
79635
+ family: "device-events",
79636
+ label: "Motion without a subject (constant / calm again)",
79637
+ bad: ["motion-noisy"],
79638
+ recovery: ["motion-calm"],
79639
+ snapshotLabel: "Cameras with constant motion now",
79640
+ snapshotSection: null
79641
+ },
79642
+ {
79643
+ id: "recording-health",
79644
+ family: "device-events",
79645
+ label: "Recording health (stalled or degraded / recording again)",
79646
+ bad: ["recording-stalled", "recording-degraded"],
79647
+ recovery: ["recording-healthy"],
79648
+ snapshotLabel: "Recordings stalled now",
79649
+ snapshotSection: null
79650
+ },
79651
+ {
79652
+ id: "device-attention",
79653
+ family: "device-events",
79654
+ label: "Device needs attention (raised / resolved)",
79655
+ bad: ["device-attention-required"],
79656
+ recovery: ["device-attention-resolved"],
79657
+ snapshotLabel: "Devices needing attention now",
79658
+ snapshotSection: null
79659
+ },
79660
+ {
79661
+ id: "node-connectivity",
79662
+ family: "system",
79663
+ label: "Node connectivity (offline / back online)",
79664
+ bad: ["node-offline"],
79665
+ recovery: ["node-online"],
79666
+ snapshotLabel: "Nodes offline now",
79667
+ snapshotSection: "nodes"
79668
+ },
79669
+ {
79670
+ id: "storage-space",
79671
+ family: "system",
79672
+ label: "Storage space (low or critical / ok again)",
79673
+ bad: ["storage-location-low", "storage-location-critical"],
79674
+ recovery: ["storage-location-ok"],
79675
+ snapshotLabel: "Storage locations low now",
79676
+ snapshotSection: null
79677
+ },
79678
+ {
79679
+ id: "critical-alerts",
79680
+ family: "system",
79681
+ label: "Critical alerts (raised / resolved)",
79682
+ bad: ["alert-critical"],
79683
+ recovery: ["alert-critical-resolved"],
79684
+ snapshotLabel: "Critical alerts open now",
79685
+ snapshotSection: null
79686
+ },
79687
+ {
79688
+ id: "rule-health",
79689
+ family: "system",
79690
+ label: "Rule health (broken / repaired)",
79691
+ bad: ["rule-broken"],
79692
+ recovery: ["rule-repaired"],
79693
+ snapshotLabel: "Notification rules broken now",
79694
+ snapshotSection: null
79695
+ }
79696
+ ].flatMap((spec) => [...spec.bad, ...spec.recovery].map((kind) => [kind, spec])));
79521
79697
  new Set([
79522
79698
  "disarmed",
79523
79699
  "armed_home",
package/dist/addon.mjs CHANGED
@@ -11,7 +11,7 @@ import { networkInterfaces, tmpdir, uptime } from "node:os";
11
11
  import { finished } from "node:stream/promises";
12
12
  import { createConnection, createServer as createServer$2 } from "node:net";
13
13
  import * as dgram from "node:dgram";
14
- //#region ../types/dist/event-category-DOl51-Ij.mjs
14
+ //#region ../types/dist/event-category-BfJwUd2S.mjs
15
15
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
16
16
  EventCategory["SystemBoot"] = "system.boot";
17
17
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -328,6 +328,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
328
328
  */
329
329
  EventCategory["PipelineDetectionBlind"] = "pipeline.detection-blind";
330
330
  /**
331
+ * A camera's motion source has fired constantly with no subject for an hour
332
+ * (motion duty or session count over the bar, zero detections) — it is not
333
+ * blind, its motion zones or sensitivity want tuning (D907). Paired with
334
+ * {@link PipelineMotionCalm}.
335
+ */
336
+ EventCategory["PipelineMotionNoisy"] = "pipeline.motion-noisy";
337
+ /** The recovery edge of {@link PipelineMotionNoisy}: the motion fell back, or a detection arrived. */
338
+ EventCategory["PipelineMotionCalm"] = "pipeline.motion-calm";
339
+ /**
331
340
  * Per-camera pipeline config was mutated by the orchestrator
332
341
  * (3-level settings change via `setAgentAddonDefaults` /
333
342
  * `setCameraStepToggle` / `setCameraPipelineForAgent` or a
@@ -699,6 +708,14 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
699
708
  EventCategory["BackupRestored"] = "backup.restored";
700
709
  EventCategory["NotificationDispatched"] = "notification.dispatched";
701
710
  EventCategory["NotificationFailed"] = "notification.failed";
711
+ /**
712
+ * A notification rule that cannot work (D905): its stored row does not load,
713
+ * or it still names a device / delivery target the prune CONFIRMED deleted.
714
+ * One edge per rule per distinct set of reasons; never on an unanswered read.
715
+ */
716
+ EventCategory["NotificationRuleBroken"] = "notification.rule-broken";
717
+ /** The clear of {@link NotificationRuleBroken}: the rule loads and names nothing deleted. */
718
+ EventCategory["NotificationRuleRepaired"] = "notification.rule-repaired";
702
719
  EventCategory["DeviceUpdated"] = "device.updated";
703
720
  /**
704
721
  * Transport-level connectivity. Emitted by the device driver when
@@ -5559,7 +5576,7 @@ var ZodIssueCode = {
5559
5576
  var ZodFirstPartyTypeKind;
5560
5577
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5561
5578
  //#endregion
5562
- //#region ../types/dist/sleep-_sV1BE2f.mjs
5579
+ //#region ../types/dist/sleep-DJFUfKvA.mjs
5563
5580
  /**
5564
5581
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5565
5582
  * window to float samples (D455).
@@ -8158,7 +8175,7 @@ var EntryDescriptorSchema = object({
8158
8175
  /** JSON Schema of the entry body; `secret: true` marks a password field. */
8159
8176
  fields: record(string$2(), unknown())
8160
8177
  }).strict();
8161
- /** What crosses the wire and sits in the engine's catalog: JSON only, no Zod. */
8178
+ /** What crosses the wire from an addon: JSON only, no Zod. An unknown key is refused. */
8162
8179
  var RecordKindDeclarationSchema = object({
8163
8180
  database: _enum(RECORD_DATABASES).default("settings"),
8164
8181
  class: _enum(RECORD_CLASSES),
@@ -8177,14 +8194,6 @@ var RecordKindDeclarationSchema = object({
8177
8194
  secretPaths: array(string$2().min(1)).default([]),
8178
8195
  /** The id key of each array that carries a secret (`{ headers: 'name' }`). */
8179
8196
  secretArrayKeys: record(string$2(), string$2()).default({}),
8180
- /**
8181
- * RETIRED (D900): the legacy table a kind adopted from during the records
8182
- * migration. Nothing declares it any more and nothing reads it; the schema
8183
- * still ACCEPTS it because the catalog rows the migration wrote carry it
8184
- * (an orphaned kind is never redeclared) and an addon built before the
8185
- * removal still sends it. Never set it.
8186
- */
8187
- adoptsFrom: string$2().min(1).optional(),
8188
8197
  /** Kinds that must agree through `transact` sit in one file under one family name. */
8189
8198
  transactFamily: string$2().min(1).optional(),
8190
8199
  entry: EntryDescriptorSchema.optional()
@@ -12980,17 +12989,6 @@ object({
12980
12989
  createdAt: number(),
12981
12990
  updatedAt: number()
12982
12991
  });
12983
- object({
12984
- id: string$2(),
12985
- label: string$2(),
12986
- isAdmin: boolean().default(false),
12987
- allowedProviders: AllowedProviderSchema,
12988
- allowedDevices: AllowedDevicesSchema,
12989
- tokenHash: string$2(),
12990
- tokenPrefix: string$2(),
12991
- createdAt: number(),
12992
- lastUsedAt: number().optional()
12993
- });
12994
12992
  object({
12995
12993
  id: string$2(),
12996
12994
  userId: string$2(),
@@ -17021,16 +17019,36 @@ var RecordKindStateSchema = _enum([
17021
17019
  var DeclareKindResultSchema = object({
17022
17020
  kindId: number().int(),
17023
17021
  state: RecordKindStateSchema,
17024
- createdIndexes: array(string$2()),
17025
- /**
17026
- * RETIRED (D900): always `null`. It carried the records-migration boot guard;
17027
- * it stays on the wire, null, because an addon built before the removal reads
17028
- * an ABSENT field as "adoption pending" and refuses to start.
17029
- */
17030
- adoptionPending: _null()
17022
+ createdIndexes: array(string$2())
17031
17023
  });
17032
17024
  /** Keychain refs a write released (the old marker is gone from the row): the owner deletes the values. */
17033
17025
  var SecretRefsList = array(string$2());
17026
+ /**
17027
+ * One op of a `transact`: the single-row writes, each on a kind of the caller.
17028
+ * All ops of one call share ONE database file and ONE `transactFamily`.
17029
+ */
17030
+ var RecordTransactOpSchema = discriminatedUnion("op", [
17031
+ object({
17032
+ op: literal("put"),
17033
+ kind: RecordKindNameSchema,
17034
+ record: RecordInputSchema,
17035
+ ifRev: number().int().min(0).optional()
17036
+ }),
17037
+ object({
17038
+ op: literal("patch"),
17039
+ kind: RecordKindNameSchema,
17040
+ id: RecordIdSchema,
17041
+ data: RecordBodySchema,
17042
+ at: number().int().nullable().optional(),
17043
+ expiresAt: number().int().nullable().optional(),
17044
+ ifRev: number().int().min(1).optional()
17045
+ }),
17046
+ object({
17047
+ op: literal("delete"),
17048
+ kind: RecordKindNameSchema,
17049
+ id: RecordIdSchema
17050
+ })
17051
+ ]);
17034
17052
  var RecordSecretRefsSchema = record(string$2(), record(string$2(), string$2()));
17035
17053
  method(object({ kinds: record(RecordKindNameSchema, RecordKindDeclarationSchema) }), object({ kinds: record(string$2(), DeclareKindResultSchema) }), {
17036
17054
  kind: "mutation",
@@ -17137,6 +17155,16 @@ method(object({ kinds: record(RecordKindNameSchema, RecordKindDeclarationSchema)
17137
17155
  }), {
17138
17156
  kind: "mutation",
17139
17157
  auth: "admin"
17158
+ }), method(object({ ops: array(RecordTransactOpSchema).min(1).max(RECORD_BATCH_MAX) }), object({
17159
+ results: array(object({
17160
+ rev: number().int().nullable(),
17161
+ deleted: boolean()
17162
+ })),
17163
+ releasedRefs: SecretRefsList,
17164
+ secretRefs: SecretRefsList
17165
+ }), {
17166
+ kind: "mutation",
17167
+ auth: "admin"
17140
17168
  }), method(object({
17141
17169
  deviceId: number().int(),
17142
17170
  kinds: array(RecordKindNameSchema).optional()
@@ -42748,9 +42776,13 @@ var NcSystemEventKindSchema = _enum([
42748
42776
  "node-updating",
42749
42777
  "node-inference-unavailable",
42750
42778
  "detection-blind",
42779
+ "motion-noisy",
42780
+ "motion-calm",
42751
42781
  "recording-stalled",
42752
42782
  "recording-healthy",
42753
42783
  "recording-degraded",
42784
+ "device-attention-required",
42785
+ "device-attention-resolved",
42754
42786
  "storage-location-low",
42755
42787
  "storage-location-critical",
42756
42788
  "storage-location-ok",
@@ -42774,6 +42806,8 @@ var NcSystemEventKindSchema = _enum([
42774
42806
  "alert-critical",
42775
42807
  "alert-error",
42776
42808
  "alert-critical-resolved",
42809
+ "rule-broken",
42810
+ "rule-repaired",
42777
42811
  "camera-online",
42778
42812
  "camera-offline",
42779
42813
  "camera-disabled",
@@ -56089,6 +56123,16 @@ var DishwasherStatusSchema = object({
56089
56123
  powerState: string$2().nullable(),
56090
56124
  saltLevel: DishwasherConsumableLevelSchema.nullable(),
56091
56125
  rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
56126
+ /**
56127
+ * True while the appliance asks for its filter to be cleaned (smart-filter, filter-system or
56128
+ * combined care-and-filter reminder raised); false when every such reminder reads clear; null
56129
+ * when none is reported. A cleared reminder is not an unknown one.
56130
+ */
56131
+ filterCleaningDue: boolean().nullable(),
56132
+ /** True while the machine-care (descaling / cleaning-program) reminder is raised; false when clear; null when not reported. */
56133
+ machineCareDue: boolean().nullable(),
56134
+ /** Program runs left before the machine-care reminder is due; null when the appliance does not say. */
56135
+ machineCareRemainingRuns: number().int().nonnegative().nullable(),
56092
56136
  /** Option states: null when the appliance does not expose the option or has not said. */
56093
56137
  halfLoad: boolean().nullable(),
56094
56138
  hygienePlus: boolean().nullable(),
@@ -64739,16 +64783,6 @@ var UpdateUserInputSchema = object({
64739
64783
  allowedDevices: record(string$2(), union([array(string$2()), literal("*")])).optional(),
64740
64784
  scopes: array(TokenScopeSchema).optional()
64741
64785
  });
64742
- var ApiKeySummarySchema = object({
64743
- id: string$2(),
64744
- label: string$2(),
64745
- isAdmin: boolean().default(false),
64746
- allowedProviders: union([array(string$2()), literal("*")]).optional(),
64747
- allowedDevices: record(string$2(), union([array(string$2()), literal("*")])).optional(),
64748
- tokenPrefix: string$2(),
64749
- createdAt: number(),
64750
- lastUsedAt: number().optional()
64751
- });
64752
64786
  var OauthSessionSummarySchema = object({
64753
64787
  id: string$2(),
64754
64788
  userId: string$2(),
@@ -64770,8 +64804,7 @@ var TotpStatusSchema = object({
64770
64804
  confirmedAt: number().nullable()
64771
64805
  });
64772
64806
  /**
64773
- * user-management — singleton capability for user accounts and the
64774
- * legacy API-key rows.
64807
+ * user-management — singleton capability for user accounts.
64775
64808
  *
64776
64809
  * v2 model: every method gated by `auth: 'admin'`. Admin-only delegation
64777
64810
  * — the subset check on `setUserScopes` is moot
@@ -64827,10 +64860,6 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
64827
64860
  }), UserSummarySchema.extend({ passwordHash: string$2() }).nullable(), {
64828
64861
  kind: "mutation",
64829
64862
  access: "view"
64830
- }), method(_void(), array(ApiKeySummarySchema), { auth: "admin" }), method(object({ id: string$2() }), object({ success: literal(true) }), {
64831
- kind: "mutation",
64832
- auth: "admin",
64833
- access: "delete"
64834
64863
  }), method(object({ userId: string$2() }), TotpSetupResultSchema, {
64835
64864
  kind: "mutation",
64836
64865
  auth: "admin",
@@ -74286,6 +74315,12 @@ Object.freeze({
74286
74315
  addonId: null,
74287
74316
  access: "view"
74288
74317
  },
74318
+ "records.transact": {
74319
+ capName: "records",
74320
+ capScope: "system",
74321
+ addonId: null,
74322
+ access: "create"
74323
+ },
74289
74324
  "sceneMonitor.captureReference": {
74290
74325
  capName: "scene-monitor",
74291
74326
  capScope: "device",
@@ -75618,12 +75653,6 @@ Object.freeze({
75618
75653
  addonId: null,
75619
75654
  access: "view"
75620
75655
  },
75621
- "userManagement.listApiKeys": {
75622
- capName: "user-management",
75623
- capScope: "system",
75624
- addonId: null,
75625
- access: "view"
75626
- },
75627
75656
  "userManagement.listExternalIdentities": {
75628
75657
  capName: "user-management",
75629
75658
  capScope: "system",
@@ -75678,12 +75707,6 @@ Object.freeze({
75678
75707
  addonId: null,
75679
75708
  access: "create"
75680
75709
  },
75681
- "userManagement.revokeApiKey": {
75682
- capName: "user-management",
75683
- capScope: "system",
75684
- addonId: null,
75685
- access: "delete"
75686
- },
75687
75710
  "userManagement.revokeOauthSession": {
75688
75711
  capName: "user-management",
75689
75712
  capScope: "system",
@@ -79048,9 +79071,13 @@ new Map(Object.entries({
79048
79071
  "stream-online": "device-events",
79049
79072
  "stream-offline": "device-events",
79050
79073
  "detection-blind": "device-events",
79074
+ "motion-noisy": "device-events",
79075
+ "motion-calm": "device-events",
79051
79076
  "recording-stalled": "device-events",
79052
79077
  "recording-healthy": "device-events",
79053
79078
  "recording-degraded": "device-events",
79079
+ "device-attention-required": "device-events",
79080
+ "device-attention-resolved": "device-events",
79054
79081
  "node-online": "system",
79055
79082
  "node-offline": "system",
79056
79083
  "node-restarting": "system",
@@ -79067,6 +79094,8 @@ new Map(Object.entries({
79067
79094
  "alert-critical": "system",
79068
79095
  "alert-error": "system",
79069
79096
  "alert-critical-resolved": "system",
79097
+ "rule-broken": "system",
79098
+ "rule-repaired": "system",
79070
79099
  "storage-location-low": "system",
79071
79100
  "storage-location-critical": "system",
79072
79101
  "storage-location-ok": "system",
@@ -79131,6 +79160,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
79131
79160
  label: "Detecting nothing",
79132
79161
  kinds: ["detection-blind"]
79133
79162
  },
79163
+ {
79164
+ id: "motion-noise",
79165
+ family: "device-events",
79166
+ label: "Motion without a subject",
79167
+ kinds: ["motion-noisy", "motion-calm"]
79168
+ },
79134
79169
  {
79135
79170
  id: "recording",
79136
79171
  family: "device-events",
@@ -79141,6 +79176,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
79141
79176
  "recording-degraded"
79142
79177
  ]
79143
79178
  },
79179
+ {
79180
+ id: "device-attention",
79181
+ family: "device-events",
79182
+ label: "Needs attention",
79183
+ kinds: ["device-attention-required", "device-attention-resolved"]
79184
+ },
79144
79185
  {
79145
79186
  id: "nodes",
79146
79187
  family: "system",
@@ -79201,6 +79242,12 @@ var NC_SYSTEM_EVENT_KIND_GROUP_SPECS = [
79201
79242
  "alert-critical-resolved"
79202
79243
  ]
79203
79244
  },
79245
+ {
79246
+ id: "rule-health",
79247
+ family: "system",
79248
+ label: "Notification rules",
79249
+ kinds: ["rule-broken", "rule-repaired"]
79250
+ },
79204
79251
  {
79205
79252
  id: "alarm",
79206
79253
  family: "alarm",
@@ -79274,6 +79321,7 @@ var ALERT_EPISODE = [
79274
79321
  "alert-error",
79275
79322
  "alert-critical-resolved"
79276
79323
  ];
79324
+ var DEVICE_ATTENTION = ["device-attention-required", "device-attention-resolved"];
79277
79325
  var UPDATES = [
79278
79326
  "addon-update-available",
79279
79327
  "server-update-available",
@@ -79303,9 +79351,12 @@ var DEVICE_EVENTS = [
79303
79351
  "stream-online",
79304
79352
  "stream-offline",
79305
79353
  "detection-blind",
79354
+ "motion-noisy",
79355
+ "motion-calm",
79306
79356
  "recording-stalled",
79307
79357
  "recording-healthy",
79308
79358
  "recording-degraded",
79359
+ ...DEVICE_ATTENTION,
79309
79360
  ...ALARM
79310
79361
  ];
79311
79362
  /** Every kind a summary may speak about — the two summarisable families. */
@@ -79473,7 +79524,13 @@ var STATE_SUMMARY_VARS = [
79473
79524
  [...RULE_TEXT],
79474
79525
  [...RULE_TEXT],
79475
79526
  [...RULE_TEXT],
79476
- ([...RULE_TEXT], [...ALERT_EPISODE]),
79527
+ [...RULE_TEXT],
79528
+ [...RULE_TEXT],
79529
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
79530
+ [...RULE_TEXT],
79531
+ [...RULE_TEXT],
79532
+ [...RULE_TEXT],
79533
+ [...RULE_TEXT],
79477
79534
  [...RULE_TEXT],
79478
79535
  [...RULE_TEXT],
79479
79536
  [...RULE_TEXT],
@@ -79491,11 +79548,11 @@ var STATE_SUMMARY_VARS = [
79491
79548
  [...RULE_TEXT],
79492
79549
  [...RULE_TEXT],
79493
79550
  [...RULE_TEXT],
79551
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
79494
79552
  ([...RULE_TEXT], [...ALERT_EPISODE]),
79553
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
79495
79554
  ([...RULE_TEXT], [...ALERT_EPISODE]),
79496
- ([...RULE_TEXT], [...ALERT_EPISODE]),
79497
- ([...RULE_TEXT], [...ALERT_EPISODE]),
79498
- ([...RULE_TEXT], [...ALERT_EPISODE]),
79555
+ ([...RULE_TEXT], [...DEVICE_ATTENTION, ...ALERT_EPISODE]),
79499
79556
  [...RULE_TEXT],
79500
79557
  [...RULE_TEXT],
79501
79558
  [...RULE_TEXT],
@@ -79516,6 +79573,125 @@ var STATE_SUMMARY_VARS = [
79516
79573
  [...RULE_TEXT],
79517
79574
  ...STATE_SUMMARY_VARS
79518
79575
  ];
79576
+ new Map([
79577
+ {
79578
+ id: "device-connectivity",
79579
+ family: "device-events",
79580
+ label: "Device connectivity (offline / back online)",
79581
+ bad: ["device-offline"],
79582
+ recovery: ["device-online"],
79583
+ snapshotLabel: "Devices offline now",
79584
+ snapshotSection: "device-state"
79585
+ },
79586
+ {
79587
+ id: "device-switch",
79588
+ family: "device-events",
79589
+ label: "Device switched off / back on",
79590
+ bad: ["device-disabled"],
79591
+ recovery: ["device-enabled"],
79592
+ snapshotLabel: "Devices switched off now",
79593
+ snapshotSection: "device-state"
79594
+ },
79595
+ {
79596
+ id: "stream-connectivity",
79597
+ family: "device-events",
79598
+ label: "Stream connectivity (offline / back online)",
79599
+ bad: ["stream-offline"],
79600
+ recovery: ["stream-online"],
79601
+ snapshotLabel: "Streams offline now",
79602
+ snapshotSection: "streams"
79603
+ },
79604
+ {
79605
+ id: "battery",
79606
+ family: "device-events",
79607
+ label: "Battery (low / back to normal)",
79608
+ bad: ["device-battery-low"],
79609
+ recovery: ["device-battery-normal"],
79610
+ snapshotLabel: "Batteries low now",
79611
+ snapshotSection: "battery"
79612
+ },
79613
+ {
79614
+ id: "consumables",
79615
+ family: "device-events",
79616
+ label: "Consumables (low / replaced)",
79617
+ bad: ["device-consumable-low"],
79618
+ recovery: ["device-consumable-normal"],
79619
+ snapshotLabel: "Consumables low now",
79620
+ snapshotSection: "consumables"
79621
+ },
79622
+ {
79623
+ id: "tanks",
79624
+ family: "device-events",
79625
+ label: "Tanks (low or full / back to normal)",
79626
+ bad: ["device-tank-low", "device-tank-full"],
79627
+ recovery: ["device-tank-normal"],
79628
+ snapshotLabel: "Tanks low or full now",
79629
+ snapshotSection: "tanks"
79630
+ },
79631
+ {
79632
+ id: "motion-noise",
79633
+ family: "device-events",
79634
+ label: "Motion without a subject (constant / calm again)",
79635
+ bad: ["motion-noisy"],
79636
+ recovery: ["motion-calm"],
79637
+ snapshotLabel: "Cameras with constant motion now",
79638
+ snapshotSection: null
79639
+ },
79640
+ {
79641
+ id: "recording-health",
79642
+ family: "device-events",
79643
+ label: "Recording health (stalled or degraded / recording again)",
79644
+ bad: ["recording-stalled", "recording-degraded"],
79645
+ recovery: ["recording-healthy"],
79646
+ snapshotLabel: "Recordings stalled now",
79647
+ snapshotSection: null
79648
+ },
79649
+ {
79650
+ id: "device-attention",
79651
+ family: "device-events",
79652
+ label: "Device needs attention (raised / resolved)",
79653
+ bad: ["device-attention-required"],
79654
+ recovery: ["device-attention-resolved"],
79655
+ snapshotLabel: "Devices needing attention now",
79656
+ snapshotSection: null
79657
+ },
79658
+ {
79659
+ id: "node-connectivity",
79660
+ family: "system",
79661
+ label: "Node connectivity (offline / back online)",
79662
+ bad: ["node-offline"],
79663
+ recovery: ["node-online"],
79664
+ snapshotLabel: "Nodes offline now",
79665
+ snapshotSection: "nodes"
79666
+ },
79667
+ {
79668
+ id: "storage-space",
79669
+ family: "system",
79670
+ label: "Storage space (low or critical / ok again)",
79671
+ bad: ["storage-location-low", "storage-location-critical"],
79672
+ recovery: ["storage-location-ok"],
79673
+ snapshotLabel: "Storage locations low now",
79674
+ snapshotSection: null
79675
+ },
79676
+ {
79677
+ id: "critical-alerts",
79678
+ family: "system",
79679
+ label: "Critical alerts (raised / resolved)",
79680
+ bad: ["alert-critical"],
79681
+ recovery: ["alert-critical-resolved"],
79682
+ snapshotLabel: "Critical alerts open now",
79683
+ snapshotSection: null
79684
+ },
79685
+ {
79686
+ id: "rule-health",
79687
+ family: "system",
79688
+ label: "Rule health (broken / repaired)",
79689
+ bad: ["rule-broken"],
79690
+ recovery: ["rule-repaired"],
79691
+ snapshotLabel: "Notification rules broken now",
79692
+ snapshotSection: null
79693
+ }
79694
+ ].flatMap((spec) => [...spec.bad, ...spec.recovery].map((kind) => [kind, spec])));
79519
79695
  new Set([
79520
79696
  "disarmed",
79521
79697
  "armed_home",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-matter-broker",
3
- "version": "0.2.141",
3
+ "version": "0.2.143",
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",