@camstack/addon-export-google 0.1.62 → 0.1.64

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.
@@ -77,7 +77,7 @@ function createApiDeviceGateway(deps) {
77
77
  };
78
78
  }
79
79
  //#endregion
80
- //#region ../types/dist/event-category-DAXzJeTX.mjs
80
+ //#region ../types/dist/event-category-ZyX6jcse.mjs
81
81
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
82
82
  EventCategory["SystemBoot"] = "system.boot";
83
83
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -638,7 +638,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
638
638
  * a package zone — a newly-appeared stationary object of a package class
639
639
  * that cleared the class / zone / dwell / size gates. Payload:
640
640
  * `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
641
- * entryId, className, zoneIds, keyFrameMediaKey?, bbox, timestamp }`.
641
+ * entryId, className, zoneIds, keyFrameMediaId?, bbox, timestamp }`.
642
642
  * Telemetry (D8): the durable record is the `package-events` store row;
643
643
  * this bus topic drives notifier rules + live UI. See
644
644
  * docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
@@ -5424,7 +5424,7 @@ var ZodIssueCode = {
5424
5424
  var ZodFirstPartyTypeKind;
5425
5425
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5426
5426
  //#endregion
5427
- //#region ../types/dist/sleep-BnujYGPe.mjs
5427
+ //#region ../types/dist/sleep-CnLyvg3w.mjs
5428
5428
  /**
5429
5429
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5430
5430
  * window to float samples (D455).
@@ -7387,13 +7387,30 @@ new Set([
7387
7387
  "scene",
7388
7388
  "motion",
7389
7389
  "object",
7390
- "audio"
7390
+ "audio",
7391
+ "mosaic"
7391
7392
  ]);
7392
- new Set([
7393
+ /**
7394
+ * The owner types that are event tables, in the order the event-media resolver
7395
+ * should consider them. Exported so a consumer asking "is this key an event?"
7396
+ * does not re-spell the list and drift from it.
7397
+ */
7398
+ var EVENT_OWNER_TYPES = [
7393
7399
  "motion",
7394
7400
  "object",
7395
7401
  "audio"
7396
- ]);
7402
+ ];
7403
+ /**
7404
+ * The same list as a Zod enum, for the cap inputs that must NAME the table
7405
+ * (D482: `getEventMedia` / `listEventMedia` take an owner, and an owner is
7406
+ * `(table, id)`).
7407
+ *
7408
+ * Built FROM {@link EVENT_OWNER_TYPES} rather than re-spelled: a fourth event
7409
+ * table would otherwise be accepted by the codec and refused at the door, with
7410
+ * nothing failing until a caller asked.
7411
+ */
7412
+ var EventOwnerTypeSchema = _enum(EVENT_OWNER_TYPES);
7413
+ new Set(EVENT_OWNER_TYPES);
7397
7414
  /**
7398
7415
  * Build an `IAddonRouteProvider` from a list of routes. Implements
7399
7416
  * both the operator-facing `getRoutes` (returning route descriptors
@@ -12655,6 +12672,16 @@ method(object({
12655
12672
  filter: QueryFilterSchema.optional(),
12656
12673
  columns: array(string()).readonly().optional()
12657
12674
  }), array(SettingsRecordSchema).readonly()), method(object({
12675
+ namespace: string().optional(),
12676
+ collection: string(),
12677
+ /** Declared columns identifying the slot; must be covered by a UNIQUE
12678
+ * index on the collection. Never empty. */
12679
+ conflict: array(string()).readonly(),
12680
+ record: BulkRecordSchema
12681
+ }), object({
12682
+ /** The id the row HAS: assigned by SQLite on an insert, or the existing
12683
+ * row's own id on an update. */
12684
+ id: union([string(), number()]) }), { kind: "mutation" }), method(object({
12658
12685
  namespace: string().optional(),
12659
12686
  collection: string(),
12660
12687
  record: object({
@@ -12789,6 +12816,14 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
12789
12816
  id: union([string(), number()]) }), {
12790
12817
  kind: "mutation",
12791
12818
  auth: "admin"
12819
+ }), method(object({
12820
+ namespace: string().optional(),
12821
+ collection: string(),
12822
+ conflict: array(string()).readonly(),
12823
+ record: BulkRecordSchema
12824
+ }), object({ id: union([string(), number()]) }), {
12825
+ kind: "mutation",
12826
+ auth: "admin"
12792
12827
  }), method(object({
12793
12828
  namespace: string().optional(),
12794
12829
  collection: string(),
@@ -19046,8 +19081,8 @@ var TrackPositionSchema = object({
19046
19081
  var TrackSnapshotSchema = object({
19047
19082
  timestamp: number(),
19048
19083
  position: TrackPositionSchema,
19049
- /** MediaStore key; resolve via `getTrackMedia({ trackId })`. */
19050
- mediaKey: string()
19084
+ /** The snapshot's media row id (D482); resolve via `listTrackMedia({ trackId })`. */
19085
+ mediaId: number().int()
19051
19086
  });
19052
19087
  /**
19053
19088
  * Normalized 0..1 trajectory envelope (min/max over every position bbox,
@@ -19651,14 +19686,14 @@ var ObjectEventSchema = object({
19651
19686
  * pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
19652
19687
  frameWidth: number().optional(),
19653
19688
  frameHeight: number().optional(),
19654
- /** MediaStore key for the crop attached to this event (if any). */
19655
- mediaKey: string().optional(),
19656
- /** Design B: MediaStore key of the track's native-resolution key frame (the
19689
+ /** Media row id of the crop attached to this event (if any) — D482. */
19690
+ mediaId: number().int().optional(),
19691
+ /** Design B: media row id of the track's native-resolution key frame (the
19657
19692
  * best-detection full frame). Resolve via the event-media data-plane
19658
- * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`) for a detail view that
19693
+ * (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`) for a detail view that
19659
19694
  * draws `bbox` over the native frame. Absent on legacy rows / non-decoded
19660
- * sources — consumers fall back to `mediaKey` (the tight crop). */
19661
- keyFrameMediaKey: string().optional(),
19695
+ * sources — consumers fall back to `mediaId` (the tight crop). */
19696
+ keyFrameMediaId: number().int().optional(),
19662
19697
  /** Populated by B5 (recording playback URL for this event). */
19663
19698
  mediaUrl: string().optional(),
19664
19699
  /** The parent track's key-event importance [0,1], propagated to every object
@@ -19708,7 +19743,7 @@ var MediaFileKindEnum = _enum([
19708
19743
  * hub-main's heap on the way past — for an `<img>` that would have cached it.
19709
19744
  *
19710
19745
  * `url` points at the `event-media` data plane
19711
- * (`/addon/<addonId>/event-media/<storedKey>`), which serves the same blob
19746
+ * (`/addon/<addonId>/event-media/m/<mediaId>` — D482), which serves the same blob
19712
19747
  * with an ETag and `Cache-Control: immutable`, honours conditional GETs, can
19713
19748
  * render a `?variant=thumb`, and streams. The hub gate in front of it requires
19714
19749
  * a bearer or the session cookie (`access: 'authenticated'`), so the bytes are
@@ -19716,10 +19751,13 @@ var MediaFileKindEnum = _enum([
19716
19751
  * `data-plane-access.ts` for the rule and the one gap it does not close
19717
19752
  * (per-device scoping).
19718
19753
  *
19719
- * The URL is built from the row's **stored** key, which is not always its
19720
- * published `kind`: a track's face/plate crop is stored as `crop` under
19754
+ * The URL is built from the row's own id, which since D482 says nothing about
19755
+ * the row's owner or kind — and that is the point. The published `kind` is not
19756
+ * the stored one (a track's face/plate crop is stored as `crop` under
19721
19757
  * `('face'|'plate', '<prefix>-<trackId>')` and published as
19722
- * `faceCrop`/`plateCrop`. `MediaStore.getByKey` knows only the stored key.
19758
+ * `faceCrop`/`plateCrop`), and under the old composite key the URL had to be
19759
+ * taken from `row.key` verbatim or it 404'd exactly those two rows. An id
19760
+ * cannot be mis-reconstructed, because there is nothing in it to reconstruct.
19723
19761
  *
19724
19762
  * ## `base64` is TRANSITIONAL and is going away
19725
19763
  *
@@ -19732,7 +19770,19 @@ var MediaFileKindEnum = _enum([
19732
19770
  * `analytics-query-facade.ts`; nothing else reads it.
19733
19771
  */
19734
19772
  var MediaFileSchema = object({
19735
- key: string(),
19773
+ /**
19774
+ * The media row's OWN id — the rowid SQLite assigned it (D482).
19775
+ *
19776
+ * It used to be the row's composite key, `<ownerType>:<ownerId>:<fileKind>
19777
+ * [:<timestampMs>]`, which embedded a FOREIGN id. D474 made event ids
19778
+ * per-table rowid aliases, so `object:101314` and `motion:101314` are two
19779
+ * different rows that spell the same number, and a track whose
19780
+ * `bestEventId` was an object event was served a motion event's snapshot —
19781
+ * a night-time thumbnail on an afternoon track, with no error anywhere. A
19782
+ * surrogate id cannot name the wrong row's owner, because it names no owner
19783
+ * at all.
19784
+ */
19785
+ mediaId: number().int(),
19736
19786
  kind: MediaFileKindEnum,
19737
19787
  sizeBytes: number(),
19738
19788
  timestamp: number()
@@ -19840,7 +19890,7 @@ var RetrainTrackSchema = object({
19840
19890
  });
19841
19891
  /** A frame the picker may offer — an index row, no blob was read to produce it. */
19842
19892
  var RetrainFrameCandidateSchema = object({
19843
- mediaKey: string(),
19893
+ mediaId: number().int(),
19844
19894
  kind: MediaFileKindEnum,
19845
19895
  timestamp: number(),
19846
19896
  sizeBytes: number().int(),
@@ -19854,7 +19904,7 @@ var RetrainFrameSchema = object({
19854
19904
  deviceId: number(),
19855
19905
  trackId: string(),
19856
19906
  /** Provenance only. It may already point at nothing — that is expected. */
19857
- sourceMediaKey: string(),
19907
+ sourceMediaId: number().int(),
19858
19908
  sourceKind: MediaFileKindEnum,
19859
19909
  sizeBytes: number().int(),
19860
19910
  width: number().int(),
@@ -19870,7 +19920,7 @@ var RetrainCopyRefusalSchema = _enum([
19870
19920
  var RetrainFrameSelectionSchema = object({
19871
19921
  copied: array(RetrainFrameSchema).readonly(),
19872
19922
  refused: array(object({
19873
- sourceMediaKey: string(),
19923
+ sourceMediaId: number().int(),
19874
19924
  reason: RetrainCopyRefusalSchema
19875
19925
  })).readonly()
19876
19926
  });
@@ -19878,7 +19928,7 @@ var RetrainFrameListSchema = object({
19878
19928
  candidates: array(RetrainFrameCandidateSchema).readonly(),
19879
19929
  copies: array(RetrainFrameSchema).readonly(),
19880
19930
  /** What the page pre-selects — the native key frame when one survives. */
19881
- autoPickMediaKey: string().optional()
19931
+ autoPickMediaId: number().int().optional()
19882
19932
  });
19883
19933
  /** What the operator asked the assist to look for. */
19884
19934
  var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
@@ -19973,9 +20023,11 @@ var RecentTracksQueryInput = object({
19973
20023
  });
19974
20024
  /**
19975
20025
  * A Summary (D359): the per-camera session envelope that references tracks.
19976
- * `groupShotKey` is the media key of its group shot (`ownerKind: 'summary'`,
19977
- * served by the event-media plane by key), null until the first frame with a
19978
- * member visible has been materialised.
20026
+ * `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
20027
+ * 'summary'`, served by the event-media plane at `/m/<id>`), null until the
20028
+ * first frame with a member visible has been materialised (D482 — it was the
20029
+ * row's composite key, which embedded the owner and could name another table's
20030
+ * row once event ids became per-table rowids).
19979
20031
  */
19980
20032
  var SummarySchema = object({
19981
20033
  id: string(),
@@ -19984,7 +20036,7 @@ var SummarySchema = object({
19984
20036
  lastActiveAt: number(),
19985
20037
  sealedAt: number().nullable(),
19986
20038
  memberCount: number().int().nonnegative(),
19987
- groupShotKey: string().nullable()
20039
+ groupShotMediaId: number().int().nullable()
19988
20040
  });
19989
20041
  var SummariesQueryInput = object({
19990
20042
  deviceIds: array(number()).min(1),
@@ -20538,7 +20590,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
20538
20590
  }), method(object({
20539
20591
  deviceId: number(),
20540
20592
  trackId: string(),
20541
- mediaKeys: array(string()).min(1)
20593
+ mediaIds: array(number().int()).min(1)
20542
20594
  }), RetrainFrameSelectionSchema, {
20543
20595
  kind: "mutation",
20544
20596
  auth: "admin"
@@ -20606,7 +20658,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
20606
20658
  kind: "query",
20607
20659
  auth: "admin"
20608
20660
  }), method(object({
20609
- eventId: string(),
20661
+ /** Which of the three event tables owns the row. */
20662
+ ownerType: EventOwnerTypeSchema,
20663
+ /** The event's rowid in that table (D474: an event id is a number). */
20664
+ eventId: number().int(),
20610
20665
  kind: MediaFileKindEnum.optional(),
20611
20666
  deviceId: number()
20612
20667
  }), array(MediaFileSchema).readonly()), method(object({
@@ -20617,7 +20672,8 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
20617
20672
  trackId: string(),
20618
20673
  deviceId: number()
20619
20674
  }), array(MediaFileInfoSchema).readonly()), method(object({
20620
- eventId: string(),
20675
+ ownerType: EventOwnerTypeSchema,
20676
+ eventId: number().int(),
20621
20677
  deviceId: number()
20622
20678
  }), array(MediaFileInfoSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
20623
20679
  kind: "mutation",
@@ -25092,8 +25148,8 @@ var IdentitySchema = object({
25092
25148
  id: string(),
25093
25149
  name: string(),
25094
25150
  sampleCount: number().int().nonnegative(),
25095
- coverMediaKey: string().optional(),
25096
- /** Inline base64 of the cover sample's crop, resolved from `coverMediaKey`.
25151
+ coverMediaId: number().int().optional(),
25152
+ /** Inline base64 of the cover sample's crop, resolved from `coverMediaId`.
25097
25153
  * Lets the UI render the person's face avatar instead of a placeholder icon. */
25098
25154
  coverBase64: string().optional()
25099
25155
  });
@@ -25119,8 +25175,8 @@ var IdentitySampleAuditRowSchema = object({
25119
25175
  enrolledAt: number().int(),
25120
25176
  deviceId: number().int().optional(),
25121
25177
  source: _enum(["detected", "photo"]),
25122
- /** The enrolled crop's media key, so the panel can show the evidence. */
25123
- mediaKey: string().optional(),
25178
+ /** The enrolled crop's media row id, so the panel can show the evidence. */
25179
+ mediaId: number().int().optional(),
25124
25180
  /**
25125
25181
  * False = the sample is stamped with a DIFFERENT face model, and a cosine
25126
25182
  * across feature spaces is a well-formed float with no meaning. Every number
@@ -25189,15 +25245,15 @@ var FaceInfoSchema = object({
25189
25245
  */
25190
25246
  cropUrl: string().optional(),
25191
25247
  /** Design B: the face bbox (pixel space) on the key frame — lets a detail
25192
- * view draw the box over the native `keyFrameMediaKey` frame. Absent on
25248
+ * view draw the box over the native `keyFrameMediaId` frame. Absent on
25193
25249
  * legacy rows written before design B. */
25194
25250
  faceBbox: BoundingBoxSchema.optional(),
25195
25251
  /** Design B: MediaStore key of the track's native-resolution key frame.
25196
25252
  * Fetch the native JPEG via the event-media data-plane
25197
- * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`). Absent when the
25253
+ * (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`). Absent when the
25198
25254
  * track produced no key frame (e.g. native/onboard source) — the UI falls
25199
25255
  * back to the inline `base64` face crop. */
25200
- keyFrameMediaKey: string().optional(),
25256
+ keyFrameMediaId: number().int().optional(),
25201
25257
  /** Winning identity-match cosine (0..1) for this face's track, when an
25202
25258
  * identity was auto-confirmed. Lets the UI surface WHY a face was assigned
25203
25259
  * (confidence badge / low-confidence audit). Absent on legacy rows and on
@@ -25266,11 +25322,14 @@ var FaceClusterSchema = object({
25266
25322
  * `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
25267
25323
  * dialog already rendering its key FRAME from the `event-media` plane.
25268
25324
  *
25269
- * `url` is `/addon/<addonId>/event-media/<encoded key>`. The plane resolves a
25270
- * media key directly, so this needed no new plane and no new access decision.
25325
+ * `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
25326
+ * resolves a media row by its own id, so this needed no new plane and no new
25327
+ * access decision.
25271
25328
  */
25272
25329
  var MediaFileLiteSchema$1 = object({
25273
- key: string(),
25330
+ /** The media row's own id — the same address `MediaFileRef.mediaId` carries
25331
+ * (D482). It was the row's composite key, which embedded the owner. */
25332
+ mediaId: number().int(),
25274
25333
  kind: string(),
25275
25334
  url: string(),
25276
25335
  sizeBytes: number(),
@@ -25287,7 +25346,7 @@ method(object({
25287
25346
  * covers inline, ~10 KB of base64 per row, on a query this UI mounts
25288
25347
  * four times and the viewer holds at `staleTime: 30_000`.
25289
25348
  *
25290
- * Nothing loses its avatar: `coverMediaKey` is already on every row and
25349
+ * Nothing loses its avatar: `coverMediaId` is already on every row and
25291
25350
  * the `event-media` plane serves that key `immutable` with an ETag.
25292
25351
  *
25293
25352
  * **This is an INPUT field, so it does not reach the addon until the
@@ -27755,8 +27814,8 @@ var VehicleSchema = object({
27755
27814
  id: string(),
27756
27815
  name: string(),
27757
27816
  sampleCount: number().int().nonnegative(),
27758
- coverMediaKey: string().optional(),
27759
- /** Inline base64 of the cover sample's plate crop, resolved from `coverMediaKey`. */
27817
+ coverMediaId: number().int().optional(),
27818
+ /** Inline base64 of the cover sample's plate crop, resolved from `coverMediaId`. */
27760
27819
  coverBase64: string().optional()
27761
27820
  });
27762
27821
  var VehicleSampleInfoSchema = object({
@@ -27789,7 +27848,7 @@ var PlateInfoSchema = object({
27789
27848
  /** keyFrame parity: the plate bbox (pixel space) on the native key frame. */
27790
27849
  plateBbox: BoundingBoxSchema.optional(),
27791
27850
  /** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
27792
- keyFrameMediaKey: string().optional(),
27851
+ keyFrameMediaId: number().int().optional(),
27793
27852
  base64: string().optional(),
27794
27853
  /**
27795
27854
  * Same crop as a data-plane URL, always present when the plate has a stored
@@ -27810,11 +27869,14 @@ var PlateInfoSchema = object({
27810
27869
  * `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
27811
27870
  * dialog already rendering its key FRAME from the `event-media` plane.
27812
27871
  *
27813
- * `url` is `/addon/<addonId>/event-media/<encoded key>`. The plane resolves a
27814
- * media key directly, so this needed no new plane and no new access decision.
27872
+ * `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
27873
+ * resolves a media row by its own id, so this needed no new plane and no new
27874
+ * access decision.
27815
27875
  */
27816
27876
  var MediaFileLiteSchema = object({
27817
- key: string(),
27877
+ /** The media row's own id — the same address `MediaFileRef.mediaId` carries
27878
+ * (D482). It was the row's composite key, which embedded the owner. */
27879
+ mediaId: number().int(),
27818
27880
  kind: string(),
27819
27881
  url: string(),
27820
27882
  sizeBytes: number(),
@@ -27873,7 +27935,7 @@ method(object({
27873
27935
  }), method(object({
27874
27936
  /** Inline {@link VehicleSchema.coverBase64} on every row. Default
27875
27937
  * `false` — the vehicle twin of `faceGallery.listIdentities`'s
27876
- * option; `coverMediaKey` + the `event-media` plane carry the picture.
27938
+ * option; `coverMediaId` + the `event-media` plane carry the picture.
27877
27939
  * INPUT field: stripped by the hub router until the train ships, which
27878
27940
  * resolves to `false` and is exactly the intended default. */
27879
27941
  includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
@@ -29197,7 +29259,14 @@ var SceneReferenceSchema = object({
29197
29259
  modelId: string(),
29198
29260
  condition: SceneConditionSchema,
29199
29261
  capturedAt: number(),
29200
- thumbnailMediaId: string().optional(),
29262
+ /**
29263
+ * The reference thumbnail's media ROW id (D482).
29264
+ *
29265
+ * The name already said `mediaId` while the value was the row's composite
29266
+ * key — a leftover that read as done and was not. It is the row's own id
29267
+ * now, addressed at `/addon/<addonId>/event-media/m/<id>`.
29268
+ */
29269
+ thumbnailMediaId: number().int().optional(),
29201
29270
  /** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
29202
29271
  * anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
29203
29272
  * normalized rect frame a different piece of world, and the scene would
@@ -30652,7 +30721,7 @@ var StationaryObjectSchema = object({
30652
30721
  /** Enrichment label carried from the source track (identity / plate). */
30653
30722
  label: string().optional(),
30654
30723
  /** Native-resolution key-frame media key for the parked object's best image. */
30655
- keyFrameMediaKey: string().optional()
30724
+ keyFrameMediaId: number().int().optional()
30656
30725
  });
30657
30726
  var CameraOccupancySnapshotSchema = object({
30658
30727
  /** Frame timestamp of the inference result that produced this snapshot. */
@@ -31808,6 +31877,12 @@ Object.freeze({
31808
31877
  addonId: null,
31809
31878
  access: "create"
31810
31879
  },
31880
+ "dataStoreProvider.upsert": {
31881
+ capName: "data-store-provider",
31882
+ capScope: "system",
31883
+ addonId: null,
31884
+ access: "create"
31885
+ },
31811
31886
  "dayNight.getOptions": {
31812
31887
  capName: "day-night",
31813
31888
  capScope: "device",
@@ -35672,6 +35747,12 @@ Object.freeze({
35672
35747
  addonId: null,
35673
35748
  access: "create"
35674
35749
  },
35750
+ "settingsStore.upsert": {
35751
+ capName: "settings-store",
35752
+ capScope: "system",
35753
+ addonId: null,
35754
+ access: "create"
35755
+ },
35675
35756
  "smtpProvider.getStatus": {
35676
35757
  capName: "smtp-provider",
35677
35758
  capScope: "system",
@@ -73,7 +73,7 @@ function createApiDeviceGateway(deps) {
73
73
  };
74
74
  }
75
75
  //#endregion
76
- //#region ../types/dist/event-category-DAXzJeTX.mjs
76
+ //#region ../types/dist/event-category-ZyX6jcse.mjs
77
77
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
78
78
  EventCategory["SystemBoot"] = "system.boot";
79
79
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -634,7 +634,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
634
634
  * a package zone — a newly-appeared stationary object of a package class
635
635
  * that cleared the class / zone / dwell / size gates. Payload:
636
636
  * `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
637
- * entryId, className, zoneIds, keyFrameMediaKey?, bbox, timestamp }`.
637
+ * entryId, className, zoneIds, keyFrameMediaId?, bbox, timestamp }`.
638
638
  * Telemetry (D8): the durable record is the `package-events` store row;
639
639
  * this bus topic drives notifier rules + live UI. See
640
640
  * docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
@@ -5420,7 +5420,7 @@ var ZodIssueCode = {
5420
5420
  var ZodFirstPartyTypeKind;
5421
5421
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5422
5422
  //#endregion
5423
- //#region ../types/dist/sleep-BnujYGPe.mjs
5423
+ //#region ../types/dist/sleep-CnLyvg3w.mjs
5424
5424
  /**
5425
5425
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5426
5426
  * window to float samples (D455).
@@ -7383,13 +7383,30 @@ new Set([
7383
7383
  "scene",
7384
7384
  "motion",
7385
7385
  "object",
7386
- "audio"
7386
+ "audio",
7387
+ "mosaic"
7387
7388
  ]);
7388
- new Set([
7389
+ /**
7390
+ * The owner types that are event tables, in the order the event-media resolver
7391
+ * should consider them. Exported so a consumer asking "is this key an event?"
7392
+ * does not re-spell the list and drift from it.
7393
+ */
7394
+ var EVENT_OWNER_TYPES = [
7389
7395
  "motion",
7390
7396
  "object",
7391
7397
  "audio"
7392
- ]);
7398
+ ];
7399
+ /**
7400
+ * The same list as a Zod enum, for the cap inputs that must NAME the table
7401
+ * (D482: `getEventMedia` / `listEventMedia` take an owner, and an owner is
7402
+ * `(table, id)`).
7403
+ *
7404
+ * Built FROM {@link EVENT_OWNER_TYPES} rather than re-spelled: a fourth event
7405
+ * table would otherwise be accepted by the codec and refused at the door, with
7406
+ * nothing failing until a caller asked.
7407
+ */
7408
+ var EventOwnerTypeSchema = _enum(EVENT_OWNER_TYPES);
7409
+ new Set(EVENT_OWNER_TYPES);
7393
7410
  /**
7394
7411
  * Build an `IAddonRouteProvider` from a list of routes. Implements
7395
7412
  * both the operator-facing `getRoutes` (returning route descriptors
@@ -12651,6 +12668,16 @@ method(object({
12651
12668
  filter: QueryFilterSchema.optional(),
12652
12669
  columns: array(string()).readonly().optional()
12653
12670
  }), array(SettingsRecordSchema).readonly()), method(object({
12671
+ namespace: string().optional(),
12672
+ collection: string(),
12673
+ /** Declared columns identifying the slot; must be covered by a UNIQUE
12674
+ * index on the collection. Never empty. */
12675
+ conflict: array(string()).readonly(),
12676
+ record: BulkRecordSchema
12677
+ }), object({
12678
+ /** The id the row HAS: assigned by SQLite on an insert, or the existing
12679
+ * row's own id on an update. */
12680
+ id: union([string(), number()]) }), { kind: "mutation" }), method(object({
12654
12681
  namespace: string().optional(),
12655
12682
  collection: string(),
12656
12683
  record: object({
@@ -12785,6 +12812,14 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
12785
12812
  id: union([string(), number()]) }), {
12786
12813
  kind: "mutation",
12787
12814
  auth: "admin"
12815
+ }), method(object({
12816
+ namespace: string().optional(),
12817
+ collection: string(),
12818
+ conflict: array(string()).readonly(),
12819
+ record: BulkRecordSchema
12820
+ }), object({ id: union([string(), number()]) }), {
12821
+ kind: "mutation",
12822
+ auth: "admin"
12788
12823
  }), method(object({
12789
12824
  namespace: string().optional(),
12790
12825
  collection: string(),
@@ -19042,8 +19077,8 @@ var TrackPositionSchema = object({
19042
19077
  var TrackSnapshotSchema = object({
19043
19078
  timestamp: number(),
19044
19079
  position: TrackPositionSchema,
19045
- /** MediaStore key; resolve via `getTrackMedia({ trackId })`. */
19046
- mediaKey: string()
19080
+ /** The snapshot's media row id (D482); resolve via `listTrackMedia({ trackId })`. */
19081
+ mediaId: number().int()
19047
19082
  });
19048
19083
  /**
19049
19084
  * Normalized 0..1 trajectory envelope (min/max over every position bbox,
@@ -19647,14 +19682,14 @@ var ObjectEventSchema = object({
19647
19682
  * pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
19648
19683
  frameWidth: number().optional(),
19649
19684
  frameHeight: number().optional(),
19650
- /** MediaStore key for the crop attached to this event (if any). */
19651
- mediaKey: string().optional(),
19652
- /** Design B: MediaStore key of the track's native-resolution key frame (the
19685
+ /** Media row id of the crop attached to this event (if any) — D482. */
19686
+ mediaId: number().int().optional(),
19687
+ /** Design B: media row id of the track's native-resolution key frame (the
19653
19688
  * best-detection full frame). Resolve via the event-media data-plane
19654
- * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`) for a detail view that
19689
+ * (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`) for a detail view that
19655
19690
  * draws `bbox` over the native frame. Absent on legacy rows / non-decoded
19656
- * sources — consumers fall back to `mediaKey` (the tight crop). */
19657
- keyFrameMediaKey: string().optional(),
19691
+ * sources — consumers fall back to `mediaId` (the tight crop). */
19692
+ keyFrameMediaId: number().int().optional(),
19658
19693
  /** Populated by B5 (recording playback URL for this event). */
19659
19694
  mediaUrl: string().optional(),
19660
19695
  /** The parent track's key-event importance [0,1], propagated to every object
@@ -19704,7 +19739,7 @@ var MediaFileKindEnum = _enum([
19704
19739
  * hub-main's heap on the way past — for an `<img>` that would have cached it.
19705
19740
  *
19706
19741
  * `url` points at the `event-media` data plane
19707
- * (`/addon/<addonId>/event-media/<storedKey>`), which serves the same blob
19742
+ * (`/addon/<addonId>/event-media/m/<mediaId>` — D482), which serves the same blob
19708
19743
  * with an ETag and `Cache-Control: immutable`, honours conditional GETs, can
19709
19744
  * render a `?variant=thumb`, and streams. The hub gate in front of it requires
19710
19745
  * a bearer or the session cookie (`access: 'authenticated'`), so the bytes are
@@ -19712,10 +19747,13 @@ var MediaFileKindEnum = _enum([
19712
19747
  * `data-plane-access.ts` for the rule and the one gap it does not close
19713
19748
  * (per-device scoping).
19714
19749
  *
19715
- * The URL is built from the row's **stored** key, which is not always its
19716
- * published `kind`: a track's face/plate crop is stored as `crop` under
19750
+ * The URL is built from the row's own id, which since D482 says nothing about
19751
+ * the row's owner or kind — and that is the point. The published `kind` is not
19752
+ * the stored one (a track's face/plate crop is stored as `crop` under
19717
19753
  * `('face'|'plate', '<prefix>-<trackId>')` and published as
19718
- * `faceCrop`/`plateCrop`. `MediaStore.getByKey` knows only the stored key.
19754
+ * `faceCrop`/`plateCrop`), and under the old composite key the URL had to be
19755
+ * taken from `row.key` verbatim or it 404'd exactly those two rows. An id
19756
+ * cannot be mis-reconstructed, because there is nothing in it to reconstruct.
19719
19757
  *
19720
19758
  * ## `base64` is TRANSITIONAL and is going away
19721
19759
  *
@@ -19728,7 +19766,19 @@ var MediaFileKindEnum = _enum([
19728
19766
  * `analytics-query-facade.ts`; nothing else reads it.
19729
19767
  */
19730
19768
  var MediaFileSchema = object({
19731
- key: string(),
19769
+ /**
19770
+ * The media row's OWN id — the rowid SQLite assigned it (D482).
19771
+ *
19772
+ * It used to be the row's composite key, `<ownerType>:<ownerId>:<fileKind>
19773
+ * [:<timestampMs>]`, which embedded a FOREIGN id. D474 made event ids
19774
+ * per-table rowid aliases, so `object:101314` and `motion:101314` are two
19775
+ * different rows that spell the same number, and a track whose
19776
+ * `bestEventId` was an object event was served a motion event's snapshot —
19777
+ * a night-time thumbnail on an afternoon track, with no error anywhere. A
19778
+ * surrogate id cannot name the wrong row's owner, because it names no owner
19779
+ * at all.
19780
+ */
19781
+ mediaId: number().int(),
19732
19782
  kind: MediaFileKindEnum,
19733
19783
  sizeBytes: number(),
19734
19784
  timestamp: number()
@@ -19836,7 +19886,7 @@ var RetrainTrackSchema = object({
19836
19886
  });
19837
19887
  /** A frame the picker may offer — an index row, no blob was read to produce it. */
19838
19888
  var RetrainFrameCandidateSchema = object({
19839
- mediaKey: string(),
19889
+ mediaId: number().int(),
19840
19890
  kind: MediaFileKindEnum,
19841
19891
  timestamp: number(),
19842
19892
  sizeBytes: number().int(),
@@ -19850,7 +19900,7 @@ var RetrainFrameSchema = object({
19850
19900
  deviceId: number(),
19851
19901
  trackId: string(),
19852
19902
  /** Provenance only. It may already point at nothing — that is expected. */
19853
- sourceMediaKey: string(),
19903
+ sourceMediaId: number().int(),
19854
19904
  sourceKind: MediaFileKindEnum,
19855
19905
  sizeBytes: number().int(),
19856
19906
  width: number().int(),
@@ -19866,7 +19916,7 @@ var RetrainCopyRefusalSchema = _enum([
19866
19916
  var RetrainFrameSelectionSchema = object({
19867
19917
  copied: array(RetrainFrameSchema).readonly(),
19868
19918
  refused: array(object({
19869
- sourceMediaKey: string(),
19919
+ sourceMediaId: number().int(),
19870
19920
  reason: RetrainCopyRefusalSchema
19871
19921
  })).readonly()
19872
19922
  });
@@ -19874,7 +19924,7 @@ var RetrainFrameListSchema = object({
19874
19924
  candidates: array(RetrainFrameCandidateSchema).readonly(),
19875
19925
  copies: array(RetrainFrameSchema).readonly(),
19876
19926
  /** What the page pre-selects — the native key frame when one survives. */
19877
- autoPickMediaKey: string().optional()
19927
+ autoPickMediaId: number().int().optional()
19878
19928
  });
19879
19929
  /** What the operator asked the assist to look for. */
19880
19930
  var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
@@ -19969,9 +20019,11 @@ var RecentTracksQueryInput = object({
19969
20019
  });
19970
20020
  /**
19971
20021
  * A Summary (D359): the per-camera session envelope that references tracks.
19972
- * `groupShotKey` is the media key of its group shot (`ownerKind: 'summary'`,
19973
- * served by the event-media plane by key), null until the first frame with a
19974
- * member visible has been materialised.
20022
+ * `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
20023
+ * 'summary'`, served by the event-media plane at `/m/<id>`), null until the
20024
+ * first frame with a member visible has been materialised (D482 — it was the
20025
+ * row's composite key, which embedded the owner and could name another table's
20026
+ * row once event ids became per-table rowids).
19975
20027
  */
19976
20028
  var SummarySchema = object({
19977
20029
  id: string(),
@@ -19980,7 +20032,7 @@ var SummarySchema = object({
19980
20032
  lastActiveAt: number(),
19981
20033
  sealedAt: number().nullable(),
19982
20034
  memberCount: number().int().nonnegative(),
19983
- groupShotKey: string().nullable()
20035
+ groupShotMediaId: number().int().nullable()
19984
20036
  });
19985
20037
  var SummariesQueryInput = object({
19986
20038
  deviceIds: array(number()).min(1),
@@ -20534,7 +20586,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
20534
20586
  }), method(object({
20535
20587
  deviceId: number(),
20536
20588
  trackId: string(),
20537
- mediaKeys: array(string()).min(1)
20589
+ mediaIds: array(number().int()).min(1)
20538
20590
  }), RetrainFrameSelectionSchema, {
20539
20591
  kind: "mutation",
20540
20592
  auth: "admin"
@@ -20602,7 +20654,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
20602
20654
  kind: "query",
20603
20655
  auth: "admin"
20604
20656
  }), method(object({
20605
- eventId: string(),
20657
+ /** Which of the three event tables owns the row. */
20658
+ ownerType: EventOwnerTypeSchema,
20659
+ /** The event's rowid in that table (D474: an event id is a number). */
20660
+ eventId: number().int(),
20606
20661
  kind: MediaFileKindEnum.optional(),
20607
20662
  deviceId: number()
20608
20663
  }), array(MediaFileSchema).readonly()), method(object({
@@ -20613,7 +20668,8 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
20613
20668
  trackId: string(),
20614
20669
  deviceId: number()
20615
20670
  }), array(MediaFileInfoSchema).readonly()), method(object({
20616
- eventId: string(),
20671
+ ownerType: EventOwnerTypeSchema,
20672
+ eventId: number().int(),
20617
20673
  deviceId: number()
20618
20674
  }), array(MediaFileInfoSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
20619
20675
  kind: "mutation",
@@ -25088,8 +25144,8 @@ var IdentitySchema = object({
25088
25144
  id: string(),
25089
25145
  name: string(),
25090
25146
  sampleCount: number().int().nonnegative(),
25091
- coverMediaKey: string().optional(),
25092
- /** Inline base64 of the cover sample's crop, resolved from `coverMediaKey`.
25147
+ coverMediaId: number().int().optional(),
25148
+ /** Inline base64 of the cover sample's crop, resolved from `coverMediaId`.
25093
25149
  * Lets the UI render the person's face avatar instead of a placeholder icon. */
25094
25150
  coverBase64: string().optional()
25095
25151
  });
@@ -25115,8 +25171,8 @@ var IdentitySampleAuditRowSchema = object({
25115
25171
  enrolledAt: number().int(),
25116
25172
  deviceId: number().int().optional(),
25117
25173
  source: _enum(["detected", "photo"]),
25118
- /** The enrolled crop's media key, so the panel can show the evidence. */
25119
- mediaKey: string().optional(),
25174
+ /** The enrolled crop's media row id, so the panel can show the evidence. */
25175
+ mediaId: number().int().optional(),
25120
25176
  /**
25121
25177
  * False = the sample is stamped with a DIFFERENT face model, and a cosine
25122
25178
  * across feature spaces is a well-formed float with no meaning. Every number
@@ -25185,15 +25241,15 @@ var FaceInfoSchema = object({
25185
25241
  */
25186
25242
  cropUrl: string().optional(),
25187
25243
  /** Design B: the face bbox (pixel space) on the key frame — lets a detail
25188
- * view draw the box over the native `keyFrameMediaKey` frame. Absent on
25244
+ * view draw the box over the native `keyFrameMediaId` frame. Absent on
25189
25245
  * legacy rows written before design B. */
25190
25246
  faceBbox: BoundingBoxSchema.optional(),
25191
25247
  /** Design B: MediaStore key of the track's native-resolution key frame.
25192
25248
  * Fetch the native JPEG via the event-media data-plane
25193
- * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`). Absent when the
25249
+ * (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`). Absent when the
25194
25250
  * track produced no key frame (e.g. native/onboard source) — the UI falls
25195
25251
  * back to the inline `base64` face crop. */
25196
- keyFrameMediaKey: string().optional(),
25252
+ keyFrameMediaId: number().int().optional(),
25197
25253
  /** Winning identity-match cosine (0..1) for this face's track, when an
25198
25254
  * identity was auto-confirmed. Lets the UI surface WHY a face was assigned
25199
25255
  * (confidence badge / low-confidence audit). Absent on legacy rows and on
@@ -25262,11 +25318,14 @@ var FaceClusterSchema = object({
25262
25318
  * `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
25263
25319
  * dialog already rendering its key FRAME from the `event-media` plane.
25264
25320
  *
25265
- * `url` is `/addon/<addonId>/event-media/<encoded key>`. The plane resolves a
25266
- * media key directly, so this needed no new plane and no new access decision.
25321
+ * `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
25322
+ * resolves a media row by its own id, so this needed no new plane and no new
25323
+ * access decision.
25267
25324
  */
25268
25325
  var MediaFileLiteSchema$1 = object({
25269
- key: string(),
25326
+ /** The media row's own id — the same address `MediaFileRef.mediaId` carries
25327
+ * (D482). It was the row's composite key, which embedded the owner. */
25328
+ mediaId: number().int(),
25270
25329
  kind: string(),
25271
25330
  url: string(),
25272
25331
  sizeBytes: number(),
@@ -25283,7 +25342,7 @@ method(object({
25283
25342
  * covers inline, ~10 KB of base64 per row, on a query this UI mounts
25284
25343
  * four times and the viewer holds at `staleTime: 30_000`.
25285
25344
  *
25286
- * Nothing loses its avatar: `coverMediaKey` is already on every row and
25345
+ * Nothing loses its avatar: `coverMediaId` is already on every row and
25287
25346
  * the `event-media` plane serves that key `immutable` with an ETag.
25288
25347
  *
25289
25348
  * **This is an INPUT field, so it does not reach the addon until the
@@ -27751,8 +27810,8 @@ var VehicleSchema = object({
27751
27810
  id: string(),
27752
27811
  name: string(),
27753
27812
  sampleCount: number().int().nonnegative(),
27754
- coverMediaKey: string().optional(),
27755
- /** Inline base64 of the cover sample's plate crop, resolved from `coverMediaKey`. */
27813
+ coverMediaId: number().int().optional(),
27814
+ /** Inline base64 of the cover sample's plate crop, resolved from `coverMediaId`. */
27756
27815
  coverBase64: string().optional()
27757
27816
  });
27758
27817
  var VehicleSampleInfoSchema = object({
@@ -27785,7 +27844,7 @@ var PlateInfoSchema = object({
27785
27844
  /** keyFrame parity: the plate bbox (pixel space) on the native key frame. */
27786
27845
  plateBbox: BoundingBoxSchema.optional(),
27787
27846
  /** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
27788
- keyFrameMediaKey: string().optional(),
27847
+ keyFrameMediaId: number().int().optional(),
27789
27848
  base64: string().optional(),
27790
27849
  /**
27791
27850
  * Same crop as a data-plane URL, always present when the plate has a stored
@@ -27806,11 +27865,14 @@ var PlateInfoSchema = object({
27806
27865
  * `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
27807
27866
  * dialog already rendering its key FRAME from the `event-media` plane.
27808
27867
  *
27809
- * `url` is `/addon/<addonId>/event-media/<encoded key>`. The plane resolves a
27810
- * media key directly, so this needed no new plane and no new access decision.
27868
+ * `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
27869
+ * resolves a media row by its own id, so this needed no new plane and no new
27870
+ * access decision.
27811
27871
  */
27812
27872
  var MediaFileLiteSchema = object({
27813
- key: string(),
27873
+ /** The media row's own id — the same address `MediaFileRef.mediaId` carries
27874
+ * (D482). It was the row's composite key, which embedded the owner. */
27875
+ mediaId: number().int(),
27814
27876
  kind: string(),
27815
27877
  url: string(),
27816
27878
  sizeBytes: number(),
@@ -27869,7 +27931,7 @@ method(object({
27869
27931
  }), method(object({
27870
27932
  /** Inline {@link VehicleSchema.coverBase64} on every row. Default
27871
27933
  * `false` — the vehicle twin of `faceGallery.listIdentities`'s
27872
- * option; `coverMediaKey` + the `event-media` plane carry the picture.
27934
+ * option; `coverMediaId` + the `event-media` plane carry the picture.
27873
27935
  * INPUT field: stripped by the hub router until the train ships, which
27874
27936
  * resolves to `false` and is exactly the intended default. */
27875
27937
  includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
@@ -29193,7 +29255,14 @@ var SceneReferenceSchema = object({
29193
29255
  modelId: string(),
29194
29256
  condition: SceneConditionSchema,
29195
29257
  capturedAt: number(),
29196
- thumbnailMediaId: string().optional(),
29258
+ /**
29259
+ * The reference thumbnail's media ROW id (D482).
29260
+ *
29261
+ * The name already said `mediaId` while the value was the row's composite
29262
+ * key — a leftover that read as done and was not. It is the row's own id
29263
+ * now, addressed at `/addon/<addonId>/event-media/m/<id>`.
29264
+ */
29265
+ thumbnailMediaId: number().int().optional(),
29197
29266
  /** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
29198
29267
  * anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
29199
29268
  * normalized rect frame a different piece of world, and the scene would
@@ -30648,7 +30717,7 @@ var StationaryObjectSchema = object({
30648
30717
  /** Enrichment label carried from the source track (identity / plate). */
30649
30718
  label: string().optional(),
30650
30719
  /** Native-resolution key-frame media key for the parked object's best image. */
30651
- keyFrameMediaKey: string().optional()
30720
+ keyFrameMediaId: number().int().optional()
30652
30721
  });
30653
30722
  var CameraOccupancySnapshotSchema = object({
30654
30723
  /** Frame timestamp of the inference result that produced this snapshot. */
@@ -31804,6 +31873,12 @@ Object.freeze({
31804
31873
  addonId: null,
31805
31874
  access: "create"
31806
31875
  },
31876
+ "dataStoreProvider.upsert": {
31877
+ capName: "data-store-provider",
31878
+ capScope: "system",
31879
+ addonId: null,
31880
+ access: "create"
31881
+ },
31807
31882
  "dayNight.getOptions": {
31808
31883
  capName: "day-night",
31809
31884
  capScope: "device",
@@ -35668,6 +35743,12 @@ Object.freeze({
35668
35743
  addonId: null,
35669
35744
  access: "create"
35670
35745
  },
35746
+ "settingsStore.upsert": {
35747
+ capName: "settings-store",
35748
+ capScope: "system",
35749
+ addonId: null,
35750
+ access: "create"
35751
+ },
35671
35752
  "smtpProvider.getStatus": {
35672
35753
  capName: "smtp-provider",
35673
35754
  capScope: "system",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-export-google",
3
- "version": "0.1.62",
3
+ "version": "0.1.64",
4
4
  "description": "Google Home export — hub-side smart-home fulfillment (SYNC / QUERY / EXECUTE / DISCONNECT) for the non-camera fleet, served over the hub's own OAuth account link. No Google credential is stored, sent or required.",
5
5
  "keywords": [
6
6
  "camstack",