@camstack/addon-provider-tuya 0.2.98 → 0.2.100

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 +131 -50
  2. package/dist/addon.mjs +131 -50
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -819,7 +819,7 @@ async function discoverDevices(options = {}, binder = createDgramBinder()) {
819
819
  return [...byId.values()];
820
820
  }
821
821
  //#endregion
822
- //#region ../types/dist/event-category-DAXzJeTX.mjs
822
+ //#region ../types/dist/event-category-ZyX6jcse.mjs
823
823
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
824
824
  EventCategory["SystemBoot"] = "system.boot";
825
825
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -1380,7 +1380,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
1380
1380
  * a package zone — a newly-appeared stationary object of a package class
1381
1381
  * that cleared the class / zone / dwell / size gates. Payload:
1382
1382
  * `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
1383
- * entryId, className, zoneIds, keyFrameMediaKey?, bbox, timestamp }`.
1383
+ * entryId, className, zoneIds, keyFrameMediaId?, bbox, timestamp }`.
1384
1384
  * Telemetry (D8): the durable record is the `package-events` store row;
1385
1385
  * this bus topic drives notifier rules + live UI. See
1386
1386
  * docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
@@ -6166,7 +6166,7 @@ var ZodIssueCode = {
6166
6166
  var ZodFirstPartyTypeKind;
6167
6167
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
6168
6168
  //#endregion
6169
- //#region ../types/dist/sleep-BnujYGPe.mjs
6169
+ //#region ../types/dist/sleep-CnLyvg3w.mjs
6170
6170
  /**
6171
6171
  * The audio chunk plane's byte format, and the ONE expansion from a coded
6172
6172
  * window to float samples (D455).
@@ -8133,13 +8133,30 @@ new Set([
8133
8133
  "scene",
8134
8134
  "motion",
8135
8135
  "object",
8136
- "audio"
8136
+ "audio",
8137
+ "mosaic"
8137
8138
  ]);
8138
- new Set([
8139
+ /**
8140
+ * The owner types that are event tables, in the order the event-media resolver
8141
+ * should consider them. Exported so a consumer asking "is this key an event?"
8142
+ * does not re-spell the list and drift from it.
8143
+ */
8144
+ var EVENT_OWNER_TYPES = [
8139
8145
  "motion",
8140
8146
  "object",
8141
8147
  "audio"
8142
- ]);
8148
+ ];
8149
+ /**
8150
+ * The same list as a Zod enum, for the cap inputs that must NAME the table
8151
+ * (D482: `getEventMedia` / `listEventMedia` take an owner, and an owner is
8152
+ * `(table, id)`).
8153
+ *
8154
+ * Built FROM {@link EVENT_OWNER_TYPES} rather than re-spelled: a fourth event
8155
+ * table would otherwise be accepted by the codec and refused at the door, with
8156
+ * nothing failing until a caller asked.
8157
+ */
8158
+ var EventOwnerTypeSchema = _enum(EVENT_OWNER_TYPES);
8159
+ new Set(EVENT_OWNER_TYPES);
8143
8160
  var EncodeProfileSchema = object({
8144
8161
  video: object({
8145
8162
  codec: _enum([
@@ -13338,6 +13355,16 @@ method(object({
13338
13355
  filter: QueryFilterSchema.optional(),
13339
13356
  columns: array(string()).readonly().optional()
13340
13357
  }), array(SettingsRecordSchema).readonly()), method(object({
13358
+ namespace: string().optional(),
13359
+ collection: string(),
13360
+ /** Declared columns identifying the slot; must be covered by a UNIQUE
13361
+ * index on the collection. Never empty. */
13362
+ conflict: array(string()).readonly(),
13363
+ record: BulkRecordSchema
13364
+ }), object({
13365
+ /** The id the row HAS: assigned by SQLite on an insert, or the existing
13366
+ * row's own id on an update. */
13367
+ id: union([string(), number()]) }), { kind: "mutation" }), method(object({
13341
13368
  namespace: string().optional(),
13342
13369
  collection: string(),
13343
13370
  record: object({
@@ -13472,6 +13499,14 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
13472
13499
  id: union([string(), number()]) }), {
13473
13500
  kind: "mutation",
13474
13501
  auth: "admin"
13502
+ }), method(object({
13503
+ namespace: string().optional(),
13504
+ collection: string(),
13505
+ conflict: array(string()).readonly(),
13506
+ record: BulkRecordSchema
13507
+ }), object({ id: union([string(), number()]) }), {
13508
+ kind: "mutation",
13509
+ auth: "admin"
13475
13510
  }), method(object({
13476
13511
  namespace: string().optional(),
13477
13512
  collection: string(),
@@ -19971,8 +20006,8 @@ var TrackPositionSchema = object({
19971
20006
  var TrackSnapshotSchema = object({
19972
20007
  timestamp: number(),
19973
20008
  position: TrackPositionSchema,
19974
- /** MediaStore key; resolve via `getTrackMedia({ trackId })`. */
19975
- mediaKey: string()
20009
+ /** The snapshot's media row id (D482); resolve via `listTrackMedia({ trackId })`. */
20010
+ mediaId: number().int()
19976
20011
  });
19977
20012
  /**
19978
20013
  * Normalized 0..1 trajectory envelope (min/max over every position bbox,
@@ -20576,14 +20611,14 @@ var ObjectEventSchema = object({
20576
20611
  * pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
20577
20612
  frameWidth: number().optional(),
20578
20613
  frameHeight: number().optional(),
20579
- /** MediaStore key for the crop attached to this event (if any). */
20580
- mediaKey: string().optional(),
20581
- /** Design B: MediaStore key of the track's native-resolution key frame (the
20614
+ /** Media row id of the crop attached to this event (if any) — D482. */
20615
+ mediaId: number().int().optional(),
20616
+ /** Design B: media row id of the track's native-resolution key frame (the
20582
20617
  * best-detection full frame). Resolve via the event-media data-plane
20583
- * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`) for a detail view that
20618
+ * (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`) for a detail view that
20584
20619
  * draws `bbox` over the native frame. Absent on legacy rows / non-decoded
20585
- * sources — consumers fall back to `mediaKey` (the tight crop). */
20586
- keyFrameMediaKey: string().optional(),
20620
+ * sources — consumers fall back to `mediaId` (the tight crop). */
20621
+ keyFrameMediaId: number().int().optional(),
20587
20622
  /** Populated by B5 (recording playback URL for this event). */
20588
20623
  mediaUrl: string().optional(),
20589
20624
  /** The parent track's key-event importance [0,1], propagated to every object
@@ -20633,7 +20668,7 @@ var MediaFileKindEnum = _enum([
20633
20668
  * hub-main's heap on the way past — for an `<img>` that would have cached it.
20634
20669
  *
20635
20670
  * `url` points at the `event-media` data plane
20636
- * (`/addon/<addonId>/event-media/<storedKey>`), which serves the same blob
20671
+ * (`/addon/<addonId>/event-media/m/<mediaId>` — D482), which serves the same blob
20637
20672
  * with an ETag and `Cache-Control: immutable`, honours conditional GETs, can
20638
20673
  * render a `?variant=thumb`, and streams. The hub gate in front of it requires
20639
20674
  * a bearer or the session cookie (`access: 'authenticated'`), so the bytes are
@@ -20641,10 +20676,13 @@ var MediaFileKindEnum = _enum([
20641
20676
  * `data-plane-access.ts` for the rule and the one gap it does not close
20642
20677
  * (per-device scoping).
20643
20678
  *
20644
- * The URL is built from the row's **stored** key, which is not always its
20645
- * published `kind`: a track's face/plate crop is stored as `crop` under
20679
+ * The URL is built from the row's own id, which since D482 says nothing about
20680
+ * the row's owner or kind — and that is the point. The published `kind` is not
20681
+ * the stored one (a track's face/plate crop is stored as `crop` under
20646
20682
  * `('face'|'plate', '<prefix>-<trackId>')` and published as
20647
- * `faceCrop`/`plateCrop`. `MediaStore.getByKey` knows only the stored key.
20683
+ * `faceCrop`/`plateCrop`), and under the old composite key the URL had to be
20684
+ * taken from `row.key` verbatim or it 404'd exactly those two rows. An id
20685
+ * cannot be mis-reconstructed, because there is nothing in it to reconstruct.
20648
20686
  *
20649
20687
  * ## `base64` is TRANSITIONAL and is going away
20650
20688
  *
@@ -20657,7 +20695,19 @@ var MediaFileKindEnum = _enum([
20657
20695
  * `analytics-query-facade.ts`; nothing else reads it.
20658
20696
  */
20659
20697
  var MediaFileSchema = object({
20660
- key: string(),
20698
+ /**
20699
+ * The media row's OWN id — the rowid SQLite assigned it (D482).
20700
+ *
20701
+ * It used to be the row's composite key, `<ownerType>:<ownerId>:<fileKind>
20702
+ * [:<timestampMs>]`, which embedded a FOREIGN id. D474 made event ids
20703
+ * per-table rowid aliases, so `object:101314` and `motion:101314` are two
20704
+ * different rows that spell the same number, and a track whose
20705
+ * `bestEventId` was an object event was served a motion event's snapshot —
20706
+ * a night-time thumbnail on an afternoon track, with no error anywhere. A
20707
+ * surrogate id cannot name the wrong row's owner, because it names no owner
20708
+ * at all.
20709
+ */
20710
+ mediaId: number().int(),
20661
20711
  kind: MediaFileKindEnum,
20662
20712
  sizeBytes: number(),
20663
20713
  timestamp: number()
@@ -20765,7 +20815,7 @@ var RetrainTrackSchema = object({
20765
20815
  });
20766
20816
  /** A frame the picker may offer — an index row, no blob was read to produce it. */
20767
20817
  var RetrainFrameCandidateSchema = object({
20768
- mediaKey: string(),
20818
+ mediaId: number().int(),
20769
20819
  kind: MediaFileKindEnum,
20770
20820
  timestamp: number(),
20771
20821
  sizeBytes: number().int(),
@@ -20779,7 +20829,7 @@ var RetrainFrameSchema = object({
20779
20829
  deviceId: number(),
20780
20830
  trackId: string(),
20781
20831
  /** Provenance only. It may already point at nothing — that is expected. */
20782
- sourceMediaKey: string(),
20832
+ sourceMediaId: number().int(),
20783
20833
  sourceKind: MediaFileKindEnum,
20784
20834
  sizeBytes: number().int(),
20785
20835
  width: number().int(),
@@ -20795,7 +20845,7 @@ var RetrainCopyRefusalSchema = _enum([
20795
20845
  var RetrainFrameSelectionSchema = object({
20796
20846
  copied: array(RetrainFrameSchema).readonly(),
20797
20847
  refused: array(object({
20798
- sourceMediaKey: string(),
20848
+ sourceMediaId: number().int(),
20799
20849
  reason: RetrainCopyRefusalSchema
20800
20850
  })).readonly()
20801
20851
  });
@@ -20803,7 +20853,7 @@ var RetrainFrameListSchema = object({
20803
20853
  candidates: array(RetrainFrameCandidateSchema).readonly(),
20804
20854
  copies: array(RetrainFrameSchema).readonly(),
20805
20855
  /** What the page pre-selects — the native key frame when one survives. */
20806
- autoPickMediaKey: string().optional()
20856
+ autoPickMediaId: number().int().optional()
20807
20857
  });
20808
20858
  /** What the operator asked the assist to look for. */
20809
20859
  var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
@@ -20898,9 +20948,11 @@ var RecentTracksQueryInput = object({
20898
20948
  });
20899
20949
  /**
20900
20950
  * A Summary (D359): the per-camera session envelope that references tracks.
20901
- * `groupShotKey` is the media key of its group shot (`ownerKind: 'summary'`,
20902
- * served by the event-media plane by key), null until the first frame with a
20903
- * member visible has been materialised.
20951
+ * `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
20952
+ * 'summary'`, served by the event-media plane at `/m/<id>`), null until the
20953
+ * first frame with a member visible has been materialised (D482 — it was the
20954
+ * row's composite key, which embedded the owner and could name another table's
20955
+ * row once event ids became per-table rowids).
20904
20956
  */
20905
20957
  var SummarySchema = object({
20906
20958
  id: string(),
@@ -20909,7 +20961,7 @@ var SummarySchema = object({
20909
20961
  lastActiveAt: number(),
20910
20962
  sealedAt: number().nullable(),
20911
20963
  memberCount: number().int().nonnegative(),
20912
- groupShotKey: string().nullable()
20964
+ groupShotMediaId: number().int().nullable()
20913
20965
  });
20914
20966
  var SummariesQueryInput = object({
20915
20967
  deviceIds: array(number()).min(1),
@@ -21463,7 +21515,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
21463
21515
  }), method(object({
21464
21516
  deviceId: number(),
21465
21517
  trackId: string(),
21466
- mediaKeys: array(string()).min(1)
21518
+ mediaIds: array(number().int()).min(1)
21467
21519
  }), RetrainFrameSelectionSchema, {
21468
21520
  kind: "mutation",
21469
21521
  auth: "admin"
@@ -21531,7 +21583,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
21531
21583
  kind: "query",
21532
21584
  auth: "admin"
21533
21585
  }), method(object({
21534
- eventId: string(),
21586
+ /** Which of the three event tables owns the row. */
21587
+ ownerType: EventOwnerTypeSchema,
21588
+ /** The event's rowid in that table (D474: an event id is a number). */
21589
+ eventId: number().int(),
21535
21590
  kind: MediaFileKindEnum.optional(),
21536
21591
  deviceId: number()
21537
21592
  }), array(MediaFileSchema).readonly()), method(object({
@@ -21542,7 +21597,8 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
21542
21597
  trackId: string(),
21543
21598
  deviceId: number()
21544
21599
  }), array(MediaFileInfoSchema).readonly()), method(object({
21545
- eventId: string(),
21600
+ ownerType: EventOwnerTypeSchema,
21601
+ eventId: number().int(),
21546
21602
  deviceId: number()
21547
21603
  }), array(MediaFileInfoSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
21548
21604
  kind: "mutation",
@@ -26743,8 +26799,8 @@ var IdentitySchema = object({
26743
26799
  id: string(),
26744
26800
  name: string(),
26745
26801
  sampleCount: number().int().nonnegative(),
26746
- coverMediaKey: string().optional(),
26747
- /** Inline base64 of the cover sample's crop, resolved from `coverMediaKey`.
26802
+ coverMediaId: number().int().optional(),
26803
+ /** Inline base64 of the cover sample's crop, resolved from `coverMediaId`.
26748
26804
  * Lets the UI render the person's face avatar instead of a placeholder icon. */
26749
26805
  coverBase64: string().optional()
26750
26806
  });
@@ -26770,8 +26826,8 @@ var IdentitySampleAuditRowSchema = object({
26770
26826
  enrolledAt: number().int(),
26771
26827
  deviceId: number().int().optional(),
26772
26828
  source: _enum(["detected", "photo"]),
26773
- /** The enrolled crop's media key, so the panel can show the evidence. */
26774
- mediaKey: string().optional(),
26829
+ /** The enrolled crop's media row id, so the panel can show the evidence. */
26830
+ mediaId: number().int().optional(),
26775
26831
  /**
26776
26832
  * False = the sample is stamped with a DIFFERENT face model, and a cosine
26777
26833
  * across feature spaces is a well-formed float with no meaning. Every number
@@ -26840,15 +26896,15 @@ var FaceInfoSchema = object({
26840
26896
  */
26841
26897
  cropUrl: string().optional(),
26842
26898
  /** Design B: the face bbox (pixel space) on the key frame — lets a detail
26843
- * view draw the box over the native `keyFrameMediaKey` frame. Absent on
26899
+ * view draw the box over the native `keyFrameMediaId` frame. Absent on
26844
26900
  * legacy rows written before design B. */
26845
26901
  faceBbox: BoundingBoxSchema.optional(),
26846
26902
  /** Design B: MediaStore key of the track's native-resolution key frame.
26847
26903
  * Fetch the native JPEG via the event-media data-plane
26848
- * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`). Absent when the
26904
+ * (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`). Absent when the
26849
26905
  * track produced no key frame (e.g. native/onboard source) — the UI falls
26850
26906
  * back to the inline `base64` face crop. */
26851
- keyFrameMediaKey: string().optional(),
26907
+ keyFrameMediaId: number().int().optional(),
26852
26908
  /** Winning identity-match cosine (0..1) for this face's track, when an
26853
26909
  * identity was auto-confirmed. Lets the UI surface WHY a face was assigned
26854
26910
  * (confidence badge / low-confidence audit). Absent on legacy rows and on
@@ -26917,11 +26973,14 @@ var FaceClusterSchema = object({
26917
26973
  * `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
26918
26974
  * dialog already rendering its key FRAME from the `event-media` plane.
26919
26975
  *
26920
- * `url` is `/addon/<addonId>/event-media/<encoded key>`. The plane resolves a
26921
- * media key directly, so this needed no new plane and no new access decision.
26976
+ * `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
26977
+ * resolves a media row by its own id, so this needed no new plane and no new
26978
+ * access decision.
26922
26979
  */
26923
26980
  var MediaFileLiteSchema$1 = object({
26924
- key: string(),
26981
+ /** The media row's own id — the same address `MediaFileRef.mediaId` carries
26982
+ * (D482). It was the row's composite key, which embedded the owner. */
26983
+ mediaId: number().int(),
26925
26984
  kind: string(),
26926
26985
  url: string(),
26927
26986
  sizeBytes: number(),
@@ -26938,7 +26997,7 @@ method(object({
26938
26997
  * covers inline, ~10 KB of base64 per row, on a query this UI mounts
26939
26998
  * four times and the viewer holds at `staleTime: 30_000`.
26940
26999
  *
26941
- * Nothing loses its avatar: `coverMediaKey` is already on every row and
27000
+ * Nothing loses its avatar: `coverMediaId` is already on every row and
26942
27001
  * the `event-media` plane serves that key `immutable` with an ETag.
26943
27002
  *
26944
27003
  * **This is an INPUT field, so it does not reach the addon until the
@@ -30301,8 +30360,8 @@ var VehicleSchema = object({
30301
30360
  id: string(),
30302
30361
  name: string(),
30303
30362
  sampleCount: number().int().nonnegative(),
30304
- coverMediaKey: string().optional(),
30305
- /** Inline base64 of the cover sample's plate crop, resolved from `coverMediaKey`. */
30363
+ coverMediaId: number().int().optional(),
30364
+ /** Inline base64 of the cover sample's plate crop, resolved from `coverMediaId`. */
30306
30365
  coverBase64: string().optional()
30307
30366
  });
30308
30367
  var VehicleSampleInfoSchema = object({
@@ -30335,7 +30394,7 @@ var PlateInfoSchema = object({
30335
30394
  /** keyFrame parity: the plate bbox (pixel space) on the native key frame. */
30336
30395
  plateBbox: BoundingBoxSchema.optional(),
30337
30396
  /** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
30338
- keyFrameMediaKey: string().optional(),
30397
+ keyFrameMediaId: number().int().optional(),
30339
30398
  base64: string().optional(),
30340
30399
  /**
30341
30400
  * Same crop as a data-plane URL, always present when the plate has a stored
@@ -30356,11 +30415,14 @@ var PlateInfoSchema = object({
30356
30415
  * `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
30357
30416
  * dialog already rendering its key FRAME from the `event-media` plane.
30358
30417
  *
30359
- * `url` is `/addon/<addonId>/event-media/<encoded key>`. The plane resolves a
30360
- * media key directly, so this needed no new plane and no new access decision.
30418
+ * `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
30419
+ * resolves a media row by its own id, so this needed no new plane and no new
30420
+ * access decision.
30361
30421
  */
30362
30422
  var MediaFileLiteSchema = object({
30363
- key: string(),
30423
+ /** The media row's own id — the same address `MediaFileRef.mediaId` carries
30424
+ * (D482). It was the row's composite key, which embedded the owner. */
30425
+ mediaId: number().int(),
30364
30426
  kind: string(),
30365
30427
  url: string(),
30366
30428
  sizeBytes: number(),
@@ -30419,7 +30481,7 @@ method(object({
30419
30481
  }), method(object({
30420
30482
  /** Inline {@link VehicleSchema.coverBase64} on every row. Default
30421
30483
  * `false` — the vehicle twin of `faceGallery.listIdentities`'s
30422
- * option; `coverMediaKey` + the `event-media` plane carry the picture.
30484
+ * option; `coverMediaId` + the `event-media` plane carry the picture.
30423
30485
  * INPUT field: stripped by the hub router until the train ships, which
30424
30486
  * resolves to `false` and is exactly the intended default. */
30425
30487
  includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
@@ -31988,7 +32050,14 @@ var SceneReferenceSchema = object({
31988
32050
  modelId: string(),
31989
32051
  condition: SceneConditionSchema,
31990
32052
  capturedAt: number(),
31991
- thumbnailMediaId: string().optional(),
32053
+ /**
32054
+ * The reference thumbnail's media ROW id (D482).
32055
+ *
32056
+ * The name already said `mediaId` while the value was the row's composite
32057
+ * key — a leftover that read as done and was not. It is the row's own id
32058
+ * now, addressed at `/addon/<addonId>/event-media/m/<id>`.
32059
+ */
32060
+ thumbnailMediaId: number().int().optional(),
31992
32061
  /** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
31993
32062
  * anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
31994
32063
  * normalized rect frame a different piece of world, and the scene would
@@ -33972,7 +34041,7 @@ var StationaryObjectSchema = object({
33972
34041
  /** Enrichment label carried from the source track (identity / plate). */
33973
34042
  label: string().optional(),
33974
34043
  /** Native-resolution key-frame media key for the parked object's best image. */
33975
- keyFrameMediaKey: string().optional()
34044
+ keyFrameMediaId: number().int().optional()
33976
34045
  });
33977
34046
  var CameraOccupancySnapshotSchema = object({
33978
34047
  /** Frame timestamp of the inference result that produced this snapshot. */
@@ -36710,6 +36779,12 @@ Object.freeze({
36710
36779
  addonId: null,
36711
36780
  access: "create"
36712
36781
  },
36782
+ "dataStoreProvider.upsert": {
36783
+ capName: "data-store-provider",
36784
+ capScope: "system",
36785
+ addonId: null,
36786
+ access: "create"
36787
+ },
36713
36788
  "dayNight.getOptions": {
36714
36789
  capName: "day-night",
36715
36790
  capScope: "device",
@@ -40574,6 +40649,12 @@ Object.freeze({
40574
40649
  addonId: null,
40575
40650
  access: "create"
40576
40651
  },
40652
+ "settingsStore.upsert": {
40653
+ capName: "settings-store",
40654
+ capScope: "system",
40655
+ addonId: null,
40656
+ access: "create"
40657
+ },
40577
40658
  "smtpProvider.getStatus": {
40578
40659
  capName: "smtp-provider",
40579
40660
  capScope: "system",
package/dist/addon.mjs CHANGED
@@ -818,7 +818,7 @@ async function discoverDevices(options = {}, binder = createDgramBinder()) {
818
818
  return [...byId.values()];
819
819
  }
820
820
  //#endregion
821
- //#region ../types/dist/event-category-DAXzJeTX.mjs
821
+ //#region ../types/dist/event-category-ZyX6jcse.mjs
822
822
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
823
823
  EventCategory["SystemBoot"] = "system.boot";
824
824
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -1379,7 +1379,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
1379
1379
  * a package zone — a newly-appeared stationary object of a package class
1380
1380
  * that cleared the class / zone / dwell / size gates. Payload:
1381
1381
  * `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
1382
- * entryId, className, zoneIds, keyFrameMediaKey?, bbox, timestamp }`.
1382
+ * entryId, className, zoneIds, keyFrameMediaId?, bbox, timestamp }`.
1383
1383
  * Telemetry (D8): the durable record is the `package-events` store row;
1384
1384
  * this bus topic drives notifier rules + live UI. See
1385
1385
  * docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
@@ -6165,7 +6165,7 @@ var ZodIssueCode = {
6165
6165
  var ZodFirstPartyTypeKind;
6166
6166
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
6167
6167
  //#endregion
6168
- //#region ../types/dist/sleep-BnujYGPe.mjs
6168
+ //#region ../types/dist/sleep-CnLyvg3w.mjs
6169
6169
  /**
6170
6170
  * The audio chunk plane's byte format, and the ONE expansion from a coded
6171
6171
  * window to float samples (D455).
@@ -8132,13 +8132,30 @@ new Set([
8132
8132
  "scene",
8133
8133
  "motion",
8134
8134
  "object",
8135
- "audio"
8135
+ "audio",
8136
+ "mosaic"
8136
8137
  ]);
8137
- new Set([
8138
+ /**
8139
+ * The owner types that are event tables, in the order the event-media resolver
8140
+ * should consider them. Exported so a consumer asking "is this key an event?"
8141
+ * does not re-spell the list and drift from it.
8142
+ */
8143
+ var EVENT_OWNER_TYPES = [
8138
8144
  "motion",
8139
8145
  "object",
8140
8146
  "audio"
8141
- ]);
8147
+ ];
8148
+ /**
8149
+ * The same list as a Zod enum, for the cap inputs that must NAME the table
8150
+ * (D482: `getEventMedia` / `listEventMedia` take an owner, and an owner is
8151
+ * `(table, id)`).
8152
+ *
8153
+ * Built FROM {@link EVENT_OWNER_TYPES} rather than re-spelled: a fourth event
8154
+ * table would otherwise be accepted by the codec and refused at the door, with
8155
+ * nothing failing until a caller asked.
8156
+ */
8157
+ var EventOwnerTypeSchema = _enum(EVENT_OWNER_TYPES);
8158
+ new Set(EVENT_OWNER_TYPES);
8142
8159
  var EncodeProfileSchema = object({
8143
8160
  video: object({
8144
8161
  codec: _enum([
@@ -13337,6 +13354,16 @@ method(object({
13337
13354
  filter: QueryFilterSchema.optional(),
13338
13355
  columns: array(string()).readonly().optional()
13339
13356
  }), array(SettingsRecordSchema).readonly()), method(object({
13357
+ namespace: string().optional(),
13358
+ collection: string(),
13359
+ /** Declared columns identifying the slot; must be covered by a UNIQUE
13360
+ * index on the collection. Never empty. */
13361
+ conflict: array(string()).readonly(),
13362
+ record: BulkRecordSchema
13363
+ }), object({
13364
+ /** The id the row HAS: assigned by SQLite on an insert, or the existing
13365
+ * row's own id on an update. */
13366
+ id: union([string(), number()]) }), { kind: "mutation" }), method(object({
13340
13367
  namespace: string().optional(),
13341
13368
  collection: string(),
13342
13369
  record: object({
@@ -13471,6 +13498,14 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
13471
13498
  id: union([string(), number()]) }), {
13472
13499
  kind: "mutation",
13473
13500
  auth: "admin"
13501
+ }), method(object({
13502
+ namespace: string().optional(),
13503
+ collection: string(),
13504
+ conflict: array(string()).readonly(),
13505
+ record: BulkRecordSchema
13506
+ }), object({ id: union([string(), number()]) }), {
13507
+ kind: "mutation",
13508
+ auth: "admin"
13474
13509
  }), method(object({
13475
13510
  namespace: string().optional(),
13476
13511
  collection: string(),
@@ -19970,8 +20005,8 @@ var TrackPositionSchema = object({
19970
20005
  var TrackSnapshotSchema = object({
19971
20006
  timestamp: number(),
19972
20007
  position: TrackPositionSchema,
19973
- /** MediaStore key; resolve via `getTrackMedia({ trackId })`. */
19974
- mediaKey: string()
20008
+ /** The snapshot's media row id (D482); resolve via `listTrackMedia({ trackId })`. */
20009
+ mediaId: number().int()
19975
20010
  });
19976
20011
  /**
19977
20012
  * Normalized 0..1 trajectory envelope (min/max over every position bbox,
@@ -20575,14 +20610,14 @@ var ObjectEventSchema = object({
20575
20610
  * pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
20576
20611
  frameWidth: number().optional(),
20577
20612
  frameHeight: number().optional(),
20578
- /** MediaStore key for the crop attached to this event (if any). */
20579
- mediaKey: string().optional(),
20580
- /** Design B: MediaStore key of the track's native-resolution key frame (the
20613
+ /** Media row id of the crop attached to this event (if any) — D482. */
20614
+ mediaId: number().int().optional(),
20615
+ /** Design B: media row id of the track's native-resolution key frame (the
20581
20616
  * best-detection full frame). Resolve via the event-media data-plane
20582
- * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`) for a detail view that
20617
+ * (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`) for a detail view that
20583
20618
  * draws `bbox` over the native frame. Absent on legacy rows / non-decoded
20584
- * sources — consumers fall back to `mediaKey` (the tight crop). */
20585
- keyFrameMediaKey: string().optional(),
20619
+ * sources — consumers fall back to `mediaId` (the tight crop). */
20620
+ keyFrameMediaId: number().int().optional(),
20586
20621
  /** Populated by B5 (recording playback URL for this event). */
20587
20622
  mediaUrl: string().optional(),
20588
20623
  /** The parent track's key-event importance [0,1], propagated to every object
@@ -20632,7 +20667,7 @@ var MediaFileKindEnum = _enum([
20632
20667
  * hub-main's heap on the way past — for an `<img>` that would have cached it.
20633
20668
  *
20634
20669
  * `url` points at the `event-media` data plane
20635
- * (`/addon/<addonId>/event-media/<storedKey>`), which serves the same blob
20670
+ * (`/addon/<addonId>/event-media/m/<mediaId>` — D482), which serves the same blob
20636
20671
  * with an ETag and `Cache-Control: immutable`, honours conditional GETs, can
20637
20672
  * render a `?variant=thumb`, and streams. The hub gate in front of it requires
20638
20673
  * a bearer or the session cookie (`access: 'authenticated'`), so the bytes are
@@ -20640,10 +20675,13 @@ var MediaFileKindEnum = _enum([
20640
20675
  * `data-plane-access.ts` for the rule and the one gap it does not close
20641
20676
  * (per-device scoping).
20642
20677
  *
20643
- * The URL is built from the row's **stored** key, which is not always its
20644
- * published `kind`: a track's face/plate crop is stored as `crop` under
20678
+ * The URL is built from the row's own id, which since D482 says nothing about
20679
+ * the row's owner or kind — and that is the point. The published `kind` is not
20680
+ * the stored one (a track's face/plate crop is stored as `crop` under
20645
20681
  * `('face'|'plate', '<prefix>-<trackId>')` and published as
20646
- * `faceCrop`/`plateCrop`. `MediaStore.getByKey` knows only the stored key.
20682
+ * `faceCrop`/`plateCrop`), and under the old composite key the URL had to be
20683
+ * taken from `row.key` verbatim or it 404'd exactly those two rows. An id
20684
+ * cannot be mis-reconstructed, because there is nothing in it to reconstruct.
20647
20685
  *
20648
20686
  * ## `base64` is TRANSITIONAL and is going away
20649
20687
  *
@@ -20656,7 +20694,19 @@ var MediaFileKindEnum = _enum([
20656
20694
  * `analytics-query-facade.ts`; nothing else reads it.
20657
20695
  */
20658
20696
  var MediaFileSchema = object({
20659
- key: string(),
20697
+ /**
20698
+ * The media row's OWN id — the rowid SQLite assigned it (D482).
20699
+ *
20700
+ * It used to be the row's composite key, `<ownerType>:<ownerId>:<fileKind>
20701
+ * [:<timestampMs>]`, which embedded a FOREIGN id. D474 made event ids
20702
+ * per-table rowid aliases, so `object:101314` and `motion:101314` are two
20703
+ * different rows that spell the same number, and a track whose
20704
+ * `bestEventId` was an object event was served a motion event's snapshot —
20705
+ * a night-time thumbnail on an afternoon track, with no error anywhere. A
20706
+ * surrogate id cannot name the wrong row's owner, because it names no owner
20707
+ * at all.
20708
+ */
20709
+ mediaId: number().int(),
20660
20710
  kind: MediaFileKindEnum,
20661
20711
  sizeBytes: number(),
20662
20712
  timestamp: number()
@@ -20764,7 +20814,7 @@ var RetrainTrackSchema = object({
20764
20814
  });
20765
20815
  /** A frame the picker may offer — an index row, no blob was read to produce it. */
20766
20816
  var RetrainFrameCandidateSchema = object({
20767
- mediaKey: string(),
20817
+ mediaId: number().int(),
20768
20818
  kind: MediaFileKindEnum,
20769
20819
  timestamp: number(),
20770
20820
  sizeBytes: number().int(),
@@ -20778,7 +20828,7 @@ var RetrainFrameSchema = object({
20778
20828
  deviceId: number(),
20779
20829
  trackId: string(),
20780
20830
  /** Provenance only. It may already point at nothing — that is expected. */
20781
- sourceMediaKey: string(),
20831
+ sourceMediaId: number().int(),
20782
20832
  sourceKind: MediaFileKindEnum,
20783
20833
  sizeBytes: number().int(),
20784
20834
  width: number().int(),
@@ -20794,7 +20844,7 @@ var RetrainCopyRefusalSchema = _enum([
20794
20844
  var RetrainFrameSelectionSchema = object({
20795
20845
  copied: array(RetrainFrameSchema).readonly(),
20796
20846
  refused: array(object({
20797
- sourceMediaKey: string(),
20847
+ sourceMediaId: number().int(),
20798
20848
  reason: RetrainCopyRefusalSchema
20799
20849
  })).readonly()
20800
20850
  });
@@ -20802,7 +20852,7 @@ var RetrainFrameListSchema = object({
20802
20852
  candidates: array(RetrainFrameCandidateSchema).readonly(),
20803
20853
  copies: array(RetrainFrameSchema).readonly(),
20804
20854
  /** What the page pre-selects — the native key frame when one survives. */
20805
- autoPickMediaKey: string().optional()
20855
+ autoPickMediaId: number().int().optional()
20806
20856
  });
20807
20857
  /** What the operator asked the assist to look for. */
20808
20858
  var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
@@ -20897,9 +20947,11 @@ var RecentTracksQueryInput = object({
20897
20947
  });
20898
20948
  /**
20899
20949
  * A Summary (D359): the per-camera session envelope that references tracks.
20900
- * `groupShotKey` is the media key of its group shot (`ownerKind: 'summary'`,
20901
- * served by the event-media plane by key), null until the first frame with a
20902
- * member visible has been materialised.
20950
+ * `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
20951
+ * 'summary'`, served by the event-media plane at `/m/<id>`), null until the
20952
+ * first frame with a member visible has been materialised (D482 — it was the
20953
+ * row's composite key, which embedded the owner and could name another table's
20954
+ * row once event ids became per-table rowids).
20903
20955
  */
20904
20956
  var SummarySchema = object({
20905
20957
  id: string(),
@@ -20908,7 +20960,7 @@ var SummarySchema = object({
20908
20960
  lastActiveAt: number(),
20909
20961
  sealedAt: number().nullable(),
20910
20962
  memberCount: number().int().nonnegative(),
20911
- groupShotKey: string().nullable()
20963
+ groupShotMediaId: number().int().nullable()
20912
20964
  });
20913
20965
  var SummariesQueryInput = object({
20914
20966
  deviceIds: array(number()).min(1),
@@ -21462,7 +21514,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
21462
21514
  }), method(object({
21463
21515
  deviceId: number(),
21464
21516
  trackId: string(),
21465
- mediaKeys: array(string()).min(1)
21517
+ mediaIds: array(number().int()).min(1)
21466
21518
  }), RetrainFrameSelectionSchema, {
21467
21519
  kind: "mutation",
21468
21520
  auth: "admin"
@@ -21530,7 +21582,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
21530
21582
  kind: "query",
21531
21583
  auth: "admin"
21532
21584
  }), method(object({
21533
- eventId: string(),
21585
+ /** Which of the three event tables owns the row. */
21586
+ ownerType: EventOwnerTypeSchema,
21587
+ /** The event's rowid in that table (D474: an event id is a number). */
21588
+ eventId: number().int(),
21534
21589
  kind: MediaFileKindEnum.optional(),
21535
21590
  deviceId: number()
21536
21591
  }), array(MediaFileSchema).readonly()), method(object({
@@ -21541,7 +21596,8 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
21541
21596
  trackId: string(),
21542
21597
  deviceId: number()
21543
21598
  }), array(MediaFileInfoSchema).readonly()), method(object({
21544
- eventId: string(),
21599
+ ownerType: EventOwnerTypeSchema,
21600
+ eventId: number().int(),
21545
21601
  deviceId: number()
21546
21602
  }), array(MediaFileInfoSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
21547
21603
  kind: "mutation",
@@ -26742,8 +26798,8 @@ var IdentitySchema = object({
26742
26798
  id: string(),
26743
26799
  name: string(),
26744
26800
  sampleCount: number().int().nonnegative(),
26745
- coverMediaKey: string().optional(),
26746
- /** Inline base64 of the cover sample's crop, resolved from `coverMediaKey`.
26801
+ coverMediaId: number().int().optional(),
26802
+ /** Inline base64 of the cover sample's crop, resolved from `coverMediaId`.
26747
26803
  * Lets the UI render the person's face avatar instead of a placeholder icon. */
26748
26804
  coverBase64: string().optional()
26749
26805
  });
@@ -26769,8 +26825,8 @@ var IdentitySampleAuditRowSchema = object({
26769
26825
  enrolledAt: number().int(),
26770
26826
  deviceId: number().int().optional(),
26771
26827
  source: _enum(["detected", "photo"]),
26772
- /** The enrolled crop's media key, so the panel can show the evidence. */
26773
- mediaKey: string().optional(),
26828
+ /** The enrolled crop's media row id, so the panel can show the evidence. */
26829
+ mediaId: number().int().optional(),
26774
26830
  /**
26775
26831
  * False = the sample is stamped with a DIFFERENT face model, and a cosine
26776
26832
  * across feature spaces is a well-formed float with no meaning. Every number
@@ -26839,15 +26895,15 @@ var FaceInfoSchema = object({
26839
26895
  */
26840
26896
  cropUrl: string().optional(),
26841
26897
  /** Design B: the face bbox (pixel space) on the key frame — lets a detail
26842
- * view draw the box over the native `keyFrameMediaKey` frame. Absent on
26898
+ * view draw the box over the native `keyFrameMediaId` frame. Absent on
26843
26899
  * legacy rows written before design B. */
26844
26900
  faceBbox: BoundingBoxSchema.optional(),
26845
26901
  /** Design B: MediaStore key of the track's native-resolution key frame.
26846
26902
  * Fetch the native JPEG via the event-media data-plane
26847
- * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`). Absent when the
26903
+ * (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`). Absent when the
26848
26904
  * track produced no key frame (e.g. native/onboard source) — the UI falls
26849
26905
  * back to the inline `base64` face crop. */
26850
- keyFrameMediaKey: string().optional(),
26906
+ keyFrameMediaId: number().int().optional(),
26851
26907
  /** Winning identity-match cosine (0..1) for this face's track, when an
26852
26908
  * identity was auto-confirmed. Lets the UI surface WHY a face was assigned
26853
26909
  * (confidence badge / low-confidence audit). Absent on legacy rows and on
@@ -26916,11 +26972,14 @@ var FaceClusterSchema = object({
26916
26972
  * `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
26917
26973
  * dialog already rendering its key FRAME from the `event-media` plane.
26918
26974
  *
26919
- * `url` is `/addon/<addonId>/event-media/<encoded key>`. The plane resolves a
26920
- * media key directly, so this needed no new plane and no new access decision.
26975
+ * `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
26976
+ * resolves a media row by its own id, so this needed no new plane and no new
26977
+ * access decision.
26921
26978
  */
26922
26979
  var MediaFileLiteSchema$1 = object({
26923
- key: string(),
26980
+ /** The media row's own id — the same address `MediaFileRef.mediaId` carries
26981
+ * (D482). It was the row's composite key, which embedded the owner. */
26982
+ mediaId: number().int(),
26924
26983
  kind: string(),
26925
26984
  url: string(),
26926
26985
  sizeBytes: number(),
@@ -26937,7 +26996,7 @@ method(object({
26937
26996
  * covers inline, ~10 KB of base64 per row, on a query this UI mounts
26938
26997
  * four times and the viewer holds at `staleTime: 30_000`.
26939
26998
  *
26940
- * Nothing loses its avatar: `coverMediaKey` is already on every row and
26999
+ * Nothing loses its avatar: `coverMediaId` is already on every row and
26941
27000
  * the `event-media` plane serves that key `immutable` with an ETag.
26942
27001
  *
26943
27002
  * **This is an INPUT field, so it does not reach the addon until the
@@ -30300,8 +30359,8 @@ var VehicleSchema = object({
30300
30359
  id: string(),
30301
30360
  name: string(),
30302
30361
  sampleCount: number().int().nonnegative(),
30303
- coverMediaKey: string().optional(),
30304
- /** Inline base64 of the cover sample's plate crop, resolved from `coverMediaKey`. */
30362
+ coverMediaId: number().int().optional(),
30363
+ /** Inline base64 of the cover sample's plate crop, resolved from `coverMediaId`. */
30305
30364
  coverBase64: string().optional()
30306
30365
  });
30307
30366
  var VehicleSampleInfoSchema = object({
@@ -30334,7 +30393,7 @@ var PlateInfoSchema = object({
30334
30393
  /** keyFrame parity: the plate bbox (pixel space) on the native key frame. */
30335
30394
  plateBbox: BoundingBoxSchema.optional(),
30336
30395
  /** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
30337
- keyFrameMediaKey: string().optional(),
30396
+ keyFrameMediaId: number().int().optional(),
30338
30397
  base64: string().optional(),
30339
30398
  /**
30340
30399
  * Same crop as a data-plane URL, always present when the plate has a stored
@@ -30355,11 +30414,14 @@ var PlateInfoSchema = object({
30355
30414
  * `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
30356
30415
  * dialog already rendering its key FRAME from the `event-media` plane.
30357
30416
  *
30358
- * `url` is `/addon/<addonId>/event-media/<encoded key>`. The plane resolves a
30359
- * media key directly, so this needed no new plane and no new access decision.
30417
+ * `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
30418
+ * resolves a media row by its own id, so this needed no new plane and no new
30419
+ * access decision.
30360
30420
  */
30361
30421
  var MediaFileLiteSchema = object({
30362
- key: string(),
30422
+ /** The media row's own id — the same address `MediaFileRef.mediaId` carries
30423
+ * (D482). It was the row's composite key, which embedded the owner. */
30424
+ mediaId: number().int(),
30363
30425
  kind: string(),
30364
30426
  url: string(),
30365
30427
  sizeBytes: number(),
@@ -30418,7 +30480,7 @@ method(object({
30418
30480
  }), method(object({
30419
30481
  /** Inline {@link VehicleSchema.coverBase64} on every row. Default
30420
30482
  * `false` — the vehicle twin of `faceGallery.listIdentities`'s
30421
- * option; `coverMediaKey` + the `event-media` plane carry the picture.
30483
+ * option; `coverMediaId` + the `event-media` plane carry the picture.
30422
30484
  * INPUT field: stripped by the hub router until the train ships, which
30423
30485
  * resolves to `false` and is exactly the intended default. */
30424
30486
  includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
@@ -31987,7 +32049,14 @@ var SceneReferenceSchema = object({
31987
32049
  modelId: string(),
31988
32050
  condition: SceneConditionSchema,
31989
32051
  capturedAt: number(),
31990
- thumbnailMediaId: string().optional(),
32052
+ /**
32053
+ * The reference thumbnail's media ROW id (D482).
32054
+ *
32055
+ * The name already said `mediaId` while the value was the row's composite
32056
+ * key — a leftover that read as done and was not. It is the row's own id
32057
+ * now, addressed at `/addon/<addonId>/event-media/m/<id>`.
32058
+ */
32059
+ thumbnailMediaId: number().int().optional(),
31991
32060
  /** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
31992
32061
  * anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
31993
32062
  * normalized rect frame a different piece of world, and the scene would
@@ -33971,7 +34040,7 @@ var StationaryObjectSchema = object({
33971
34040
  /** Enrichment label carried from the source track (identity / plate). */
33972
34041
  label: string().optional(),
33973
34042
  /** Native-resolution key-frame media key for the parked object's best image. */
33974
- keyFrameMediaKey: string().optional()
34043
+ keyFrameMediaId: number().int().optional()
33975
34044
  });
33976
34045
  var CameraOccupancySnapshotSchema = object({
33977
34046
  /** Frame timestamp of the inference result that produced this snapshot. */
@@ -36709,6 +36778,12 @@ Object.freeze({
36709
36778
  addonId: null,
36710
36779
  access: "create"
36711
36780
  },
36781
+ "dataStoreProvider.upsert": {
36782
+ capName: "data-store-provider",
36783
+ capScope: "system",
36784
+ addonId: null,
36785
+ access: "create"
36786
+ },
36712
36787
  "dayNight.getOptions": {
36713
36788
  capName: "day-night",
36714
36789
  capScope: "device",
@@ -40573,6 +40648,12 @@ Object.freeze({
40573
40648
  addonId: null,
40574
40649
  access: "create"
40575
40650
  },
40651
+ "settingsStore.upsert": {
40652
+ capName: "settings-store",
40653
+ capScope: "system",
40654
+ addonId: null,
40655
+ access: "create"
40656
+ },
40576
40657
  "smtpProvider.getStatus": {
40577
40658
  capName: "smtp-provider",
40578
40659
  capScope: "system",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-tuya",
3
- "version": "0.2.98",
3
+ "version": "0.2.100",
4
4
  "description": "Tuya / Smart Life device-provider addon for CamStack — account-onboarded (Tuya IoT cloud fetch of device localKeys) + LOCAL DP control via the @apocaliss92/nodetuya encrypted-LAN client, exposing switch / water-heater-family kettle entities",
5
5
  "keywords": [
6
6
  "camstack",