@camstack/addon-matter-broker 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 +292 -58
  2. package/dist/addon.mjs +292 -58
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -13,7 +13,7 @@ let node_stream_promises = require("node:stream/promises");
13
13
  let node_net = require("node:net");
14
14
  let node_dgram = require("node:dgram");
15
15
  node_dgram = require_esm.__toESM(node_dgram, 1);
16
- //#region ../types/dist/event-category-DAXzJeTX.mjs
16
+ //#region ../types/dist/event-category-ZyX6jcse.mjs
17
17
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
18
18
  EventCategory["SystemBoot"] = "system.boot";
19
19
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -574,7 +574,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
574
574
  * a package zone — a newly-appeared stationary object of a package class
575
575
  * that cleared the class / zone / dwell / size gates. Payload:
576
576
  * `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
577
- * entryId, className, zoneIds, keyFrameMediaKey?, bbox, timestamp }`.
577
+ * entryId, className, zoneIds, keyFrameMediaId?, bbox, timestamp }`.
578
578
  * Telemetry (D8): the durable record is the `package-events` store row;
579
579
  * this bus topic drives notifier rules + live UI. See
580
580
  * docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
@@ -5360,7 +5360,7 @@ var ZodIssueCode = {
5360
5360
  var ZodFirstPartyTypeKind;
5361
5361
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5362
5362
  //#endregion
5363
- //#region ../types/dist/sleep-BnujYGPe.mjs
5363
+ //#region ../types/dist/sleep-DBKu2-U5.mjs
5364
5364
  /**
5365
5365
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5366
5366
  * window to float samples (D455).
@@ -7327,13 +7327,30 @@ new Set([
7327
7327
  "scene",
7328
7328
  "motion",
7329
7329
  "object",
7330
- "audio"
7330
+ "audio",
7331
+ "mosaic"
7331
7332
  ]);
7332
- new Set([
7333
+ /**
7334
+ * The owner types that are event tables, in the order the event-media resolver
7335
+ * should consider them. Exported so a consumer asking "is this key an event?"
7336
+ * does not re-spell the list and drift from it.
7337
+ */
7338
+ var EVENT_OWNER_TYPES = [
7333
7339
  "motion",
7334
7340
  "object",
7335
7341
  "audio"
7336
- ]);
7342
+ ];
7343
+ /**
7344
+ * The same list as a Zod enum, for the cap inputs that must NAME the table
7345
+ * (D482: `getEventMedia` / `listEventMedia` take an owner, and an owner is
7346
+ * `(table, id)`).
7347
+ *
7348
+ * Built FROM {@link EVENT_OWNER_TYPES} rather than re-spelled: a fourth event
7349
+ * table would otherwise be accepted by the codec and refused at the door, with
7350
+ * nothing failing until a caller asked.
7351
+ */
7352
+ var EventOwnerTypeSchema = _enum(EVENT_OWNER_TYPES);
7353
+ new Set(EVENT_OWNER_TYPES);
7337
7354
  var EncodeProfileSchema = object({
7338
7355
  video: object({
7339
7356
  codec: _enum([
@@ -7372,7 +7389,23 @@ var EncodeProfileSchema = object({
7372
7389
  "zerolatency",
7373
7390
  "film",
7374
7391
  "animation"
7375
- ]).optional()
7392
+ ]).optional(),
7393
+ /**
7394
+ * ONE slice per access unit.
7395
+ *
7396
+ * `-tune zerolatency` turns on x264's sliced threads, and a frame then leaves
7397
+ * the encoder as five NAL slices that share one RTP timestamp and carry one
7398
+ * marker bit. A libwebrtc depacketiser sees five frame-starts and one
7399
+ * frame-end per frame: the first pictures render and the video then freezes
7400
+ * for good while the audio, on its own plane, plays on. Measured on this hub
7401
+ * 2026-09-13 against the Echo, and reduced to one slice by this flag alone.
7402
+ *
7403
+ * A NAMED field and not a raw flag, because {@link EgressEncodeSchema} omits
7404
+ * `outputArgs` on purpose: an opaque array is part of the sharing key, so two
7405
+ * consumers meaning the same thing spelled differently would stop sharing one
7406
+ * child. Absent means "whatever the encoder does" — today's behaviour.
7407
+ */
7408
+ singleSlicePerFrame: boolean().optional()
7376
7409
  }),
7377
7410
  audio: union([literal("passthrough"), object({
7378
7411
  codec: _enum([
@@ -7422,7 +7455,7 @@ var BASE_LIVE_EGRESS_PROFILE = {
7422
7455
  audio: "passthrough"
7423
7456
  };
7424
7457
  ({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
7425
- ({ ...BASE_LIVE_EGRESS_PROFILE });
7458
+ ({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
7426
7459
  /**
7427
7460
  * Deep wiring healthcheck — snapshot of active reachability probes across
7428
7461
  * every declared capability + widget of every installed plugin, on every
@@ -12581,6 +12614,16 @@ method(object({
12581
12614
  filter: QueryFilterSchema.optional(),
12582
12615
  columns: array(string$2()).readonly().optional()
12583
12616
  }), array(SettingsRecordSchema).readonly()), method(object({
12617
+ namespace: string$2().optional(),
12618
+ collection: string$2(),
12619
+ /** Declared columns identifying the slot; must be covered by a UNIQUE
12620
+ * index on the collection. Never empty. */
12621
+ conflict: array(string$2()).readonly(),
12622
+ record: BulkRecordSchema
12623
+ }), object({
12624
+ /** The id the row HAS: assigned by SQLite on an insert, or the existing
12625
+ * row's own id on an update. */
12626
+ id: union([string$2(), number()]) }), { kind: "mutation" }), method(object({
12584
12627
  namespace: string$2().optional(),
12585
12628
  collection: string$2(),
12586
12629
  record: object({
@@ -12715,6 +12758,14 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
12715
12758
  id: union([string$2(), number()]) }), {
12716
12759
  kind: "mutation",
12717
12760
  auth: "admin"
12761
+ }), method(object({
12762
+ namespace: string$2().optional(),
12763
+ collection: string$2(),
12764
+ conflict: array(string$2()).readonly(),
12765
+ record: BulkRecordSchema
12766
+ }), object({ id: union([string$2(), number()]) }), {
12767
+ kind: "mutation",
12768
+ auth: "admin"
12718
12769
  }), method(object({
12719
12770
  namespace: string$2().optional(),
12720
12771
  collection: string$2(),
@@ -19214,8 +19265,8 @@ var TrackPositionSchema = object({
19214
19265
  var TrackSnapshotSchema = object({
19215
19266
  timestamp: number(),
19216
19267
  position: TrackPositionSchema,
19217
- /** MediaStore key; resolve via `getTrackMedia({ trackId })`. */
19218
- mediaKey: string$2()
19268
+ /** The snapshot's media row id (D482); resolve via `listTrackMedia({ trackId })`. */
19269
+ mediaId: number().int()
19219
19270
  });
19220
19271
  /**
19221
19272
  * Normalized 0..1 trajectory envelope (min/max over every position bbox,
@@ -19819,14 +19870,14 @@ var ObjectEventSchema = object({
19819
19870
  * pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
19820
19871
  frameWidth: number().optional(),
19821
19872
  frameHeight: number().optional(),
19822
- /** MediaStore key for the crop attached to this event (if any). */
19823
- mediaKey: string$2().optional(),
19824
- /** Design B: MediaStore key of the track's native-resolution key frame (the
19873
+ /** Media row id of the crop attached to this event (if any) — D482. */
19874
+ mediaId: number().int().optional(),
19875
+ /** Design B: media row id of the track's native-resolution key frame (the
19825
19876
  * best-detection full frame). Resolve via the event-media data-plane
19826
- * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`) for a detail view that
19877
+ * (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`) for a detail view that
19827
19878
  * draws `bbox` over the native frame. Absent on legacy rows / non-decoded
19828
- * sources — consumers fall back to `mediaKey` (the tight crop). */
19829
- keyFrameMediaKey: string$2().optional(),
19879
+ * sources — consumers fall back to `mediaId` (the tight crop). */
19880
+ keyFrameMediaId: number().int().optional(),
19830
19881
  /** Populated by B5 (recording playback URL for this event). */
19831
19882
  mediaUrl: string$2().optional(),
19832
19883
  /** The parent track's key-event importance [0,1], propagated to every object
@@ -19876,7 +19927,7 @@ var MediaFileKindEnum = _enum([
19876
19927
  * hub-main's heap on the way past — for an `<img>` that would have cached it.
19877
19928
  *
19878
19929
  * `url` points at the `event-media` data plane
19879
- * (`/addon/<addonId>/event-media/<storedKey>`), which serves the same blob
19930
+ * (`/addon/<addonId>/event-media/m/<mediaId>` — D482), which serves the same blob
19880
19931
  * with an ETag and `Cache-Control: immutable`, honours conditional GETs, can
19881
19932
  * render a `?variant=thumb`, and streams. The hub gate in front of it requires
19882
19933
  * a bearer or the session cookie (`access: 'authenticated'`), so the bytes are
@@ -19884,10 +19935,13 @@ var MediaFileKindEnum = _enum([
19884
19935
  * `data-plane-access.ts` for the rule and the one gap it does not close
19885
19936
  * (per-device scoping).
19886
19937
  *
19887
- * The URL is built from the row's **stored** key, which is not always its
19888
- * published `kind`: a track's face/plate crop is stored as `crop` under
19938
+ * The URL is built from the row's own id, which since D482 says nothing about
19939
+ * the row's owner or kind — and that is the point. The published `kind` is not
19940
+ * the stored one (a track's face/plate crop is stored as `crop` under
19889
19941
  * `('face'|'plate', '<prefix>-<trackId>')` and published as
19890
- * `faceCrop`/`plateCrop`. `MediaStore.getByKey` knows only the stored key.
19942
+ * `faceCrop`/`plateCrop`), and under the old composite key the URL had to be
19943
+ * taken from `row.key` verbatim or it 404'd exactly those two rows. An id
19944
+ * cannot be mis-reconstructed, because there is nothing in it to reconstruct.
19891
19945
  *
19892
19946
  * ## `base64` is TRANSITIONAL and is going away
19893
19947
  *
@@ -19900,7 +19954,19 @@ var MediaFileKindEnum = _enum([
19900
19954
  * `analytics-query-facade.ts`; nothing else reads it.
19901
19955
  */
19902
19956
  var MediaFileSchema = object({
19903
- key: string$2(),
19957
+ /**
19958
+ * The media row's OWN id — the rowid SQLite assigned it (D482).
19959
+ *
19960
+ * It used to be the row's composite key, `<ownerType>:<ownerId>:<fileKind>
19961
+ * [:<timestampMs>]`, which embedded a FOREIGN id. D474 made event ids
19962
+ * per-table rowid aliases, so `object:101314` and `motion:101314` are two
19963
+ * different rows that spell the same number, and a track whose
19964
+ * `bestEventId` was an object event was served a motion event's snapshot —
19965
+ * a night-time thumbnail on an afternoon track, with no error anywhere. A
19966
+ * surrogate id cannot name the wrong row's owner, because it names no owner
19967
+ * at all.
19968
+ */
19969
+ mediaId: number().int(),
19904
19970
  kind: MediaFileKindEnum,
19905
19971
  sizeBytes: number(),
19906
19972
  timestamp: number()
@@ -20008,7 +20074,7 @@ var RetrainTrackSchema = object({
20008
20074
  });
20009
20075
  /** A frame the picker may offer — an index row, no blob was read to produce it. */
20010
20076
  var RetrainFrameCandidateSchema = object({
20011
- mediaKey: string$2(),
20077
+ mediaId: number().int(),
20012
20078
  kind: MediaFileKindEnum,
20013
20079
  timestamp: number(),
20014
20080
  sizeBytes: number().int(),
@@ -20022,7 +20088,7 @@ var RetrainFrameSchema = object({
20022
20088
  deviceId: number(),
20023
20089
  trackId: string$2(),
20024
20090
  /** Provenance only. It may already point at nothing — that is expected. */
20025
- sourceMediaKey: string$2(),
20091
+ sourceMediaId: number().int(),
20026
20092
  sourceKind: MediaFileKindEnum,
20027
20093
  sizeBytes: number().int(),
20028
20094
  width: number().int(),
@@ -20038,7 +20104,7 @@ var RetrainCopyRefusalSchema = _enum([
20038
20104
  var RetrainFrameSelectionSchema = object({
20039
20105
  copied: array(RetrainFrameSchema).readonly(),
20040
20106
  refused: array(object({
20041
- sourceMediaKey: string$2(),
20107
+ sourceMediaId: number().int(),
20042
20108
  reason: RetrainCopyRefusalSchema
20043
20109
  })).readonly()
20044
20110
  });
@@ -20046,7 +20112,7 @@ var RetrainFrameListSchema = object({
20046
20112
  candidates: array(RetrainFrameCandidateSchema).readonly(),
20047
20113
  copies: array(RetrainFrameSchema).readonly(),
20048
20114
  /** What the page pre-selects — the native key frame when one survives. */
20049
- autoPickMediaKey: string$2().optional()
20115
+ autoPickMediaId: number().int().optional()
20050
20116
  });
20051
20117
  /** What the operator asked the assist to look for. */
20052
20118
  var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
@@ -20141,9 +20207,11 @@ var RecentTracksQueryInput = object({
20141
20207
  });
20142
20208
  /**
20143
20209
  * A Summary (D359): the per-camera session envelope that references tracks.
20144
- * `groupShotKey` is the media key of its group shot (`ownerKind: 'summary'`,
20145
- * served by the event-media plane by key), null until the first frame with a
20146
- * member visible has been materialised.
20210
+ * `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
20211
+ * 'summary'`, served by the event-media plane at `/m/<id>`), null until the
20212
+ * first frame with a member visible has been materialised (D482 — it was the
20213
+ * row's composite key, which embedded the owner and could name another table's
20214
+ * row once event ids became per-table rowids).
20147
20215
  */
20148
20216
  var SummarySchema = object({
20149
20217
  id: string$2(),
@@ -20152,19 +20220,115 @@ var SummarySchema = object({
20152
20220
  lastActiveAt: number(),
20153
20221
  sealedAt: number().nullable(),
20154
20222
  memberCount: number().int().nonnegative(),
20155
- groupShotKey: string$2().nullable()
20223
+ groupShotMediaId: number().int().nullable()
20156
20224
  });
20157
20225
  var SummariesQueryInput = object({
20158
20226
  deviceIds: array(number()).min(1),
20159
20227
  since: number().optional(),
20160
20228
  until: number().optional(),
20161
- limit: number().int().min(1).max(200).default(50)
20229
+ limit: number().int().min(1).max(200).default(50),
20230
+ /** The same member-wise filter {@link listRecentSummaries} takes — one
20231
+ * meaning of "dog" on every summary surface. */
20232
+ classes: array(string$2().min(1).max(60)).max(40).optional()
20162
20233
  });
20163
- var SummariesPageSchema = object({ summaries: array(SummarySchema).readonly() });
20164
20234
  var SummaryDetailSchema = object({
20165
20235
  summary: SummarySchema,
20166
- /** Member track ids, in absorption order. */
20167
- trackIds: array(string$2()).readonly()
20236
+ /** Members in absorption order, oldest join first. */
20237
+ members: array(object({
20238
+ trackId: string$2(),
20239
+ /**
20240
+ * The track's class at the time it JOINED, or `null` when it was unresolved
20241
+ * and the track no longer exists to fill it.
20242
+ *
20243
+ * The join, not the latest opinion: class voting can re-decide a track's
20244
+ * class afterwards, and a group's composition is the history of who came
20245
+ * together. A consumer counts these to badge a thumbnail — "two people and a
20246
+ * dog" — rather than being handed a second, denormalised tally that would
20247
+ * drift from the members it claims to describe.
20248
+ */
20249
+ className: string$2().nullable(),
20250
+ /** `primary` is the one member that carries the group's identity. */
20251
+ role: _enum([
20252
+ "primary",
20253
+ "sibling",
20254
+ "child"
20255
+ ]).nullable(),
20256
+ joinedAt: number(),
20257
+ /** Tier 1 — the sub-class (`dog`, `van`), resolved from the member's track
20258
+ * at read time. Absent when nothing resolved, never an empty string. */
20259
+ label: string$2().optional(),
20260
+ /** Tier 2 — the instance: a person's name, a plate. Absent when the pipeline
20261
+ * recognised nobody, and absent for a member whose track has been pruned —
20262
+ * a thumbnail that names the wrong person is worse than one naming nobody. */
20263
+ subLabel: string$2().optional()
20264
+ })).readonly()
20265
+ });
20266
+ /**
20267
+ * What a LIST of groups carries: the envelope plus what it is MADE OF.
20268
+ *
20269
+ * Coarse on purpose — the operator's rule is "only the rough data on the list,
20270
+ * we extend when we notice we need more". Enough to draw the card ("two people
20271
+ * and a dog") and no more. The MEMBERS, their names and the per-member links
20272
+ * are on {@link getSummary}: shipping every member of every group so a client
20273
+ * can count them turns a page of two hundred groups into a thousand records to
20274
+ * draw two hundred badges.
20275
+ */
20276
+ var SummaryListItemSchema = object({
20277
+ summary: SummarySchema,
20278
+ /** Class counts, most numerous first; `className: null` is a member whose
20279
+ * class never resolved, counted so the counts add up to `memberCount`. */
20280
+ classes: array(object({
20281
+ className: string$2().nullable(),
20282
+ count: number().int().positive()
20283
+ })).readonly()
20284
+ });
20285
+ var SummariesPageSchema = object({ summaries: array(SummaryListItemSchema).readonly() });
20286
+ /**
20287
+ * The paged feed, deliberately the SAME shape as {@link RecentTracksQueryInput}.
20288
+ *
20289
+ * The reel on the cameras page and the Events gallery both ride a cursor, so a
20290
+ * summaries feed that could only answer "the last N for these cameras"
20291
+ * (`listSummaries`) would make groups available in the timeline and nowhere
20292
+ * else. Two feeds with different ordering contracts would be two ideas of what
20293
+ * "newest" means, on one screen.
20294
+ */
20295
+ var RecentSummariesQueryInput = object({
20296
+ /** Devices to merge. An empty array yields an empty page. */
20297
+ deviceIds: array(number()),
20298
+ /** Window lower bound on `lastActiveAt` (inclusive). */
20299
+ since: number().optional(),
20300
+ /** Window upper bound on `lastActiveAt` (inclusive). */
20301
+ until: number().optional(),
20302
+ limit: number().int().min(1).max(500).default(100),
20303
+ /** Opaque continuation cursor from a previous page's `nextCursor`. */
20304
+ cursor: string$2().optional(),
20305
+ /**
20306
+ * Restrict to these classes — THE SAME FIELD `listRecentTracks` takes, and
20307
+ * deliberately the same name: the events filter tree emits one list of ticked
20308
+ * taxonomy nodes, and a summaries feed that called it something else would
20309
+ * make the operator's one filter component produce two shapes.
20310
+ *
20311
+ * A question about the MEMBERS: a group matches when ANY of them does. "Show
20312
+ * me the arrivals with a dog" has to return the group of four people who had
20313
+ * one with them; a filter on the group's own fields could only ever answer
20314
+ * about its primary.
20315
+ *
20316
+ * Matched against all THREE tiers of a member — the class (`animal`), the
20317
+ * sub-class (`dog`) and the instance (a name, a plate) — because which tier a
20318
+ * ticked node lives on is the taxonomy's business, not the caller's. `dog` is
20319
+ * an event kind in the tree and a tier-1 label on an `animal` track; a filter
20320
+ * that read only the class would answer "animal" and never "dog".
20321
+ *
20322
+ * ABSENT or EMPTY means no filter — absent is not a selection of none.
20323
+ */
20324
+ classes: array(string$2().min(1).max(60)).max(40).optional()
20325
+ });
20326
+ var RecentSummariesPageSchema = object({
20327
+ /** Ordered by (`lastActiveAt` DESC, id DESC). Same light item as
20328
+ * {@link listSummaries} — one list shape, so a card renders the same
20329
+ * whichever feed drew it. */
20330
+ summaries: array(SummaryListItemSchema).readonly(),
20331
+ nextCursor: string$2().nullable()
20168
20332
  });
20169
20333
  var RecentTracksPageSchema = object({
20170
20334
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
@@ -20578,7 +20742,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
20578
20742
  classes: array(string$2()).optional(),
20579
20743
  /** See {@link ExcludeSourcesDoc}. */
20580
20744
  excludeSources: array(TrackSourceSchema).optional()
20581
- }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(object({ id: string$2() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
20745
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(RecentSummariesQueryInput, RecentSummariesPageSchema), method(object({ id: string$2() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
20582
20746
  kind: "mutation",
20583
20747
  auth: "admin"
20584
20748
  }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(EventKindsForDeviceSchema).readonly()), method(object({
@@ -20706,7 +20870,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
20706
20870
  }), method(object({
20707
20871
  deviceId: number(),
20708
20872
  trackId: string$2(),
20709
- mediaKeys: array(string$2()).min(1)
20873
+ mediaIds: array(number().int()).min(1)
20710
20874
  }), RetrainFrameSelectionSchema, {
20711
20875
  kind: "mutation",
20712
20876
  auth: "admin"
@@ -20774,7 +20938,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
20774
20938
  kind: "query",
20775
20939
  auth: "admin"
20776
20940
  }), method(object({
20777
- eventId: string$2(),
20941
+ /** Which of the three event tables owns the row. */
20942
+ ownerType: EventOwnerTypeSchema,
20943
+ /** The event's rowid in that table (D474: an event id is a number). */
20944
+ eventId: number().int(),
20778
20945
  kind: MediaFileKindEnum.optional(),
20779
20946
  deviceId: number()
20780
20947
  }), array(MediaFileSchema).readonly()), method(object({
@@ -20785,7 +20952,8 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
20785
20952
  trackId: string$2(),
20786
20953
  deviceId: number()
20787
20954
  }), array(MediaFileInfoSchema).readonly()), method(object({
20788
- eventId: string$2(),
20955
+ ownerType: EventOwnerTypeSchema,
20956
+ eventId: number().int(),
20789
20957
  deviceId: number()
20790
20958
  }), array(MediaFileInfoSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
20791
20959
  kind: "mutation",
@@ -25995,8 +26163,8 @@ var IdentitySchema = object({
25995
26163
  id: string$2(),
25996
26164
  name: string$2(),
25997
26165
  sampleCount: number().int().nonnegative(),
25998
- coverMediaKey: string$2().optional(),
25999
- /** Inline base64 of the cover sample's crop, resolved from `coverMediaKey`.
26166
+ coverMediaId: number().int().optional(),
26167
+ /** Inline base64 of the cover sample's crop, resolved from `coverMediaId`.
26000
26168
  * Lets the UI render the person's face avatar instead of a placeholder icon. */
26001
26169
  coverBase64: string$2().optional()
26002
26170
  });
@@ -26022,8 +26190,8 @@ var IdentitySampleAuditRowSchema = object({
26022
26190
  enrolledAt: number().int(),
26023
26191
  deviceId: number().int().optional(),
26024
26192
  source: _enum(["detected", "photo"]),
26025
- /** The enrolled crop's media key, so the panel can show the evidence. */
26026
- mediaKey: string$2().optional(),
26193
+ /** The enrolled crop's media row id, so the panel can show the evidence. */
26194
+ mediaId: number().int().optional(),
26027
26195
  /**
26028
26196
  * False = the sample is stamped with a DIFFERENT face model, and a cosine
26029
26197
  * across feature spaces is a well-formed float with no meaning. Every number
@@ -26092,15 +26260,15 @@ var FaceInfoSchema = object({
26092
26260
  */
26093
26261
  cropUrl: string$2().optional(),
26094
26262
  /** Design B: the face bbox (pixel space) on the key frame — lets a detail
26095
- * view draw the box over the native `keyFrameMediaKey` frame. Absent on
26263
+ * view draw the box over the native `keyFrameMediaId` frame. Absent on
26096
26264
  * legacy rows written before design B. */
26097
26265
  faceBbox: BoundingBoxSchema.optional(),
26098
26266
  /** Design B: MediaStore key of the track's native-resolution key frame.
26099
26267
  * Fetch the native JPEG via the event-media data-plane
26100
- * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`). Absent when the
26268
+ * (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`). Absent when the
26101
26269
  * track produced no key frame (e.g. native/onboard source) — the UI falls
26102
26270
  * back to the inline `base64` face crop. */
26103
- keyFrameMediaKey: string$2().optional(),
26271
+ keyFrameMediaId: number().int().optional(),
26104
26272
  /** Winning identity-match cosine (0..1) for this face's track, when an
26105
26273
  * identity was auto-confirmed. Lets the UI surface WHY a face was assigned
26106
26274
  * (confidence badge / low-confidence audit). Absent on legacy rows and on
@@ -26169,11 +26337,14 @@ var FaceClusterSchema = object({
26169
26337
  * `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
26170
26338
  * dialog already rendering its key FRAME from the `event-media` plane.
26171
26339
  *
26172
- * `url` is `/addon/<addonId>/event-media/<encoded key>`. The plane resolves a
26173
- * media key directly, so this needed no new plane and no new access decision.
26340
+ * `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
26341
+ * resolves a media row by its own id, so this needed no new plane and no new
26342
+ * access decision.
26174
26343
  */
26175
26344
  var MediaFileLiteSchema$1 = object({
26176
- key: string$2(),
26345
+ /** The media row's own id — the same address `MediaFileRef.mediaId` carries
26346
+ * (D482). It was the row's composite key, which embedded the owner. */
26347
+ mediaId: number().int(),
26177
26348
  kind: string$2(),
26178
26349
  url: string$2(),
26179
26350
  sizeBytes: number(),
@@ -26190,7 +26361,7 @@ method(object({
26190
26361
  * covers inline, ~10 KB of base64 per row, on a query this UI mounts
26191
26362
  * four times and the viewer holds at `staleTime: 30_000`.
26192
26363
  *
26193
- * Nothing loses its avatar: `coverMediaKey` is already on every row and
26364
+ * Nothing loses its avatar: `coverMediaId` is already on every row and
26194
26365
  * the `event-media` plane serves that key `immutable` with an ETag.
26195
26366
  *
26196
26367
  * **This is an INPUT field, so it does not reach the addon until the
@@ -29553,8 +29724,8 @@ var VehicleSchema = object({
29553
29724
  id: string$2(),
29554
29725
  name: string$2(),
29555
29726
  sampleCount: number().int().nonnegative(),
29556
- coverMediaKey: string$2().optional(),
29557
- /** Inline base64 of the cover sample's plate crop, resolved from `coverMediaKey`. */
29727
+ coverMediaId: number().int().optional(),
29728
+ /** Inline base64 of the cover sample's plate crop, resolved from `coverMediaId`. */
29558
29729
  coverBase64: string$2().optional()
29559
29730
  });
29560
29731
  var VehicleSampleInfoSchema = object({
@@ -29587,7 +29758,7 @@ var PlateInfoSchema = object({
29587
29758
  /** keyFrame parity: the plate bbox (pixel space) on the native key frame. */
29588
29759
  plateBbox: BoundingBoxSchema.optional(),
29589
29760
  /** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
29590
- keyFrameMediaKey: string$2().optional(),
29761
+ keyFrameMediaId: number().int().optional(),
29591
29762
  base64: string$2().optional(),
29592
29763
  /**
29593
29764
  * Same crop as a data-plane URL, always present when the plate has a stored
@@ -29608,11 +29779,14 @@ var PlateInfoSchema = object({
29608
29779
  * `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
29609
29780
  * dialog already rendering its key FRAME from the `event-media` plane.
29610
29781
  *
29611
- * `url` is `/addon/<addonId>/event-media/<encoded key>`. The plane resolves a
29612
- * media key directly, so this needed no new plane and no new access decision.
29782
+ * `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
29783
+ * resolves a media row by its own id, so this needed no new plane and no new
29784
+ * access decision.
29613
29785
  */
29614
29786
  var MediaFileLiteSchema = object({
29615
- key: string$2(),
29787
+ /** The media row's own id — the same address `MediaFileRef.mediaId` carries
29788
+ * (D482). It was the row's composite key, which embedded the owner. */
29789
+ mediaId: number().int(),
29616
29790
  kind: string$2(),
29617
29791
  url: string$2(),
29618
29792
  sizeBytes: number(),
@@ -29671,7 +29845,7 @@ method(object({
29671
29845
  }), method(object({
29672
29846
  /** Inline {@link VehicleSchema.coverBase64} on every row. Default
29673
29847
  * `false` — the vehicle twin of `faceGallery.listIdentities`'s
29674
- * option; `coverMediaKey` + the `event-media` plane carry the picture.
29848
+ * option; `coverMediaId` + the `event-media` plane carry the picture.
29675
29849
  * INPUT field: stripped by the hub router until the train ships, which
29676
29850
  * resolves to `false` and is exactly the intended default. */
29677
29851
  includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly()), method(object({ name: string$2().min(1) }), VehicleSchema, {
@@ -31240,7 +31414,14 @@ var SceneReferenceSchema = object({
31240
31414
  modelId: string$2(),
31241
31415
  condition: SceneConditionSchema,
31242
31416
  capturedAt: number(),
31243
- thumbnailMediaId: string$2().optional(),
31417
+ /**
31418
+ * The reference thumbnail's media ROW id (D482).
31419
+ *
31420
+ * The name already said `mediaId` while the value was the row's composite
31421
+ * key — a leftover that read as done and was not. It is the row's own id
31422
+ * now, addressed at `/addon/<addonId>/event-media/m/<id>`.
31423
+ */
31424
+ thumbnailMediaId: number().int().optional(),
31244
31425
  /** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
31245
31426
  * anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
31246
31427
  * normalized rect frame a different piece of world, and the scene would
@@ -32331,7 +32512,29 @@ var LoggingSettingsPatchSchema = object({
32331
32512
  * disarmed the channels it did not mention would make the Levels page and
32332
32513
  * the Diagnostics page fight over the same value.
32333
32514
  */
32334
- channels: array(LogChannelWindowPatchSchema).readonly().optional()
32515
+ channels: array(LogChannelWindowPatchSchema).readonly().optional(),
32516
+ /**
32517
+ * How many days the analytics OPS LOG is kept — the audit trail of what
32518
+ * retention actually deleted.
32519
+ *
32520
+ * It lives HERE, on the logging document, and not on the analytics addon's
32521
+ * settings form, on the operator's instruction: every other log-ish window in
32522
+ * this system is configured through this one document, and a retention audit
32523
+ * configured somewhere else is a second place to look when the question is
32524
+ * "what happened to my data".
32525
+ *
32526
+ * That placement has a cost worth stating: this document ships in the
32527
+ * framework closure, so this knob needs a published `@camstack/server` while
32528
+ * the four windows beside it (D485) reach a node on `camstack deploy`.
32529
+ *
32530
+ * `retention-model.ts` argued this one must NOT follow a device window,
32531
+ * because the audit trail is the history of the SWEEP and not of the camera.
32532
+ * That argument stands and is untouched — what changes is that 30 days stops
32533
+ * being a constant nobody can reach. `0` keeps it forever. The floor is 1 day
32534
+ * rather than 0-as-delete: an audit log truncated to nothing is precisely the
32535
+ * state in which the next 9.5 GiB leak cannot be explained.
32536
+ */
32537
+ opsLogRetentionDays: number().int().min(0).max(3650).optional()
32335
32538
  });
32336
32539
  /**
32337
32540
  * Which LAYER of the hierarchy is addressed. Absent = the cluster layer.
@@ -32404,6 +32607,14 @@ var LoggingSettingsStateSchema = object({
32404
32607
  channels: array(LogChannelDescriptorSchema).readonly(),
32405
32608
  /** The channels ARMED right now, each with its deadline. */
32406
32609
  activeChannels: array(LogChannelWindowStateSchema).readonly(),
32610
+ /**
32611
+ * The ops-log window in days, as it is in force. `0` = kept forever.
32612
+ *
32613
+ * Reported rather than left to the caller's memory of what it wrote: this is
32614
+ * the value the analytics sweep will actually use, and an operator asking how
32615
+ * long their audit trail lives should not have to infer it from a default.
32616
+ */
32617
+ opsLogRetentionDays: number().int().min(0),
32407
32618
  persisted: boolean()
32408
32619
  });
32409
32620
  method(_void(), FeatureManifestSchema), method(_void(), HealthStatusSchema), method(_void(), FeatureManifestSchema), method(_void(), array(NetworkAddressSchema).readonly()), method(_void(), unknown().nullable(), { auth: "admin" }), method(record(string$2(), unknown()), _null(), {
@@ -33224,7 +33435,7 @@ var StationaryObjectSchema = object({
33224
33435
  /** Enrichment label carried from the source track (identity / plate). */
33225
33436
  label: string$2().optional(),
33226
33437
  /** Native-resolution key-frame media key for the parked object's best image. */
33227
- keyFrameMediaKey: string$2().optional()
33438
+ keyFrameMediaId: number().int().optional()
33228
33439
  });
33229
33440
  var CameraOccupancySnapshotSchema = object({
33230
33441
  /** Frame timestamp of the inference result that produced this snapshot. */
@@ -35962,6 +36173,12 @@ Object.freeze({
35962
36173
  addonId: null,
35963
36174
  access: "create"
35964
36175
  },
36176
+ "dataStoreProvider.upsert": {
36177
+ capName: "data-store-provider",
36178
+ capScope: "system",
36179
+ addonId: null,
36180
+ access: "create"
36181
+ },
35965
36182
  "dayNight.getOptions": {
35966
36183
  capName: "day-night",
35967
36184
  capScope: "device",
@@ -38398,6 +38615,12 @@ Object.freeze({
38398
38615
  addonId: null,
38399
38616
  access: "view"
38400
38617
  },
38618
+ "pipelineAnalytics.listRecentSummaries": {
38619
+ capName: "pipeline-analytics",
38620
+ capScope: "device",
38621
+ addonId: null,
38622
+ access: "view"
38623
+ },
38401
38624
  "pipelineAnalytics.listRecentTracks": {
38402
38625
  capName: "pipeline-analytics",
38403
38626
  capScope: "device",
@@ -39826,6 +40049,12 @@ Object.freeze({
39826
40049
  addonId: null,
39827
40050
  access: "create"
39828
40051
  },
40052
+ "settingsStore.upsert": {
40053
+ capName: "settings-store",
40054
+ capScope: "system",
40055
+ addonId: null,
40056
+ access: "create"
40057
+ },
39829
40058
  "smtpProvider.getStatus": {
39830
40059
  capName: "smtp-provider",
39831
40060
  capScope: "system",
@@ -42219,6 +42448,11 @@ Object.freeze({
42219
42448
  form: "single",
42220
42449
  optional: true
42221
42450
  }],
42451
+ "pipelineAnalytics.listRecentSummaries": [{
42452
+ name: "deviceIds",
42453
+ form: "array",
42454
+ optional: false
42455
+ }],
42222
42456
  "pipelineAnalytics.listRecentTracks": [{
42223
42457
  name: "deviceIds",
42224
42458
  form: "array",
package/dist/addon.mjs CHANGED
@@ -11,7 +11,7 @@ import { networkInterfaces, tmpdir, uptime } from "node:os";
11
11
  import { finished } from "node:stream/promises";
12
12
  import { createConnection, createServer as createServer$2 } from "node:net";
13
13
  import * as dgram from "node:dgram";
14
- //#region ../types/dist/event-category-DAXzJeTX.mjs
14
+ //#region ../types/dist/event-category-ZyX6jcse.mjs
15
15
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
16
16
  EventCategory["SystemBoot"] = "system.boot";
17
17
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -572,7 +572,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
572
572
  * a package zone — a newly-appeared stationary object of a package class
573
573
  * that cleared the class / zone / dwell / size gates. Payload:
574
574
  * `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
575
- * entryId, className, zoneIds, keyFrameMediaKey?, bbox, timestamp }`.
575
+ * entryId, className, zoneIds, keyFrameMediaId?, bbox, timestamp }`.
576
576
  * Telemetry (D8): the durable record is the `package-events` store row;
577
577
  * this bus topic drives notifier rules + live UI. See
578
578
  * docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
@@ -5358,7 +5358,7 @@ var ZodIssueCode = {
5358
5358
  var ZodFirstPartyTypeKind;
5359
5359
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5360
5360
  //#endregion
5361
- //#region ../types/dist/sleep-BnujYGPe.mjs
5361
+ //#region ../types/dist/sleep-DBKu2-U5.mjs
5362
5362
  /**
5363
5363
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5364
5364
  * window to float samples (D455).
@@ -7325,13 +7325,30 @@ new Set([
7325
7325
  "scene",
7326
7326
  "motion",
7327
7327
  "object",
7328
- "audio"
7328
+ "audio",
7329
+ "mosaic"
7329
7330
  ]);
7330
- new Set([
7331
+ /**
7332
+ * The owner types that are event tables, in the order the event-media resolver
7333
+ * should consider them. Exported so a consumer asking "is this key an event?"
7334
+ * does not re-spell the list and drift from it.
7335
+ */
7336
+ var EVENT_OWNER_TYPES = [
7331
7337
  "motion",
7332
7338
  "object",
7333
7339
  "audio"
7334
- ]);
7340
+ ];
7341
+ /**
7342
+ * The same list as a Zod enum, for the cap inputs that must NAME the table
7343
+ * (D482: `getEventMedia` / `listEventMedia` take an owner, and an owner is
7344
+ * `(table, id)`).
7345
+ *
7346
+ * Built FROM {@link EVENT_OWNER_TYPES} rather than re-spelled: a fourth event
7347
+ * table would otherwise be accepted by the codec and refused at the door, with
7348
+ * nothing failing until a caller asked.
7349
+ */
7350
+ var EventOwnerTypeSchema = _enum(EVENT_OWNER_TYPES);
7351
+ new Set(EVENT_OWNER_TYPES);
7335
7352
  var EncodeProfileSchema = object({
7336
7353
  video: object({
7337
7354
  codec: _enum([
@@ -7370,7 +7387,23 @@ var EncodeProfileSchema = object({
7370
7387
  "zerolatency",
7371
7388
  "film",
7372
7389
  "animation"
7373
- ]).optional()
7390
+ ]).optional(),
7391
+ /**
7392
+ * ONE slice per access unit.
7393
+ *
7394
+ * `-tune zerolatency` turns on x264's sliced threads, and a frame then leaves
7395
+ * the encoder as five NAL slices that share one RTP timestamp and carry one
7396
+ * marker bit. A libwebrtc depacketiser sees five frame-starts and one
7397
+ * frame-end per frame: the first pictures render and the video then freezes
7398
+ * for good while the audio, on its own plane, plays on. Measured on this hub
7399
+ * 2026-09-13 against the Echo, and reduced to one slice by this flag alone.
7400
+ *
7401
+ * A NAMED field and not a raw flag, because {@link EgressEncodeSchema} omits
7402
+ * `outputArgs` on purpose: an opaque array is part of the sharing key, so two
7403
+ * consumers meaning the same thing spelled differently would stop sharing one
7404
+ * child. Absent means "whatever the encoder does" — today's behaviour.
7405
+ */
7406
+ singleSlicePerFrame: boolean().optional()
7374
7407
  }),
7375
7408
  audio: union([literal("passthrough"), object({
7376
7409
  codec: _enum([
@@ -7420,7 +7453,7 @@ var BASE_LIVE_EGRESS_PROFILE = {
7420
7453
  audio: "passthrough"
7421
7454
  };
7422
7455
  ({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
7423
- ({ ...BASE_LIVE_EGRESS_PROFILE });
7456
+ ({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
7424
7457
  /**
7425
7458
  * Deep wiring healthcheck — snapshot of active reachability probes across
7426
7459
  * every declared capability + widget of every installed plugin, on every
@@ -12579,6 +12612,16 @@ method(object({
12579
12612
  filter: QueryFilterSchema.optional(),
12580
12613
  columns: array(string$2()).readonly().optional()
12581
12614
  }), array(SettingsRecordSchema).readonly()), method(object({
12615
+ namespace: string$2().optional(),
12616
+ collection: string$2(),
12617
+ /** Declared columns identifying the slot; must be covered by a UNIQUE
12618
+ * index on the collection. Never empty. */
12619
+ conflict: array(string$2()).readonly(),
12620
+ record: BulkRecordSchema
12621
+ }), object({
12622
+ /** The id the row HAS: assigned by SQLite on an insert, or the existing
12623
+ * row's own id on an update. */
12624
+ id: union([string$2(), number()]) }), { kind: "mutation" }), method(object({
12582
12625
  namespace: string$2().optional(),
12583
12626
  collection: string$2(),
12584
12627
  record: object({
@@ -12713,6 +12756,14 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
12713
12756
  id: union([string$2(), number()]) }), {
12714
12757
  kind: "mutation",
12715
12758
  auth: "admin"
12759
+ }), method(object({
12760
+ namespace: string$2().optional(),
12761
+ collection: string$2(),
12762
+ conflict: array(string$2()).readonly(),
12763
+ record: BulkRecordSchema
12764
+ }), object({ id: union([string$2(), number()]) }), {
12765
+ kind: "mutation",
12766
+ auth: "admin"
12716
12767
  }), method(object({
12717
12768
  namespace: string$2().optional(),
12718
12769
  collection: string$2(),
@@ -19212,8 +19263,8 @@ var TrackPositionSchema = object({
19212
19263
  var TrackSnapshotSchema = object({
19213
19264
  timestamp: number(),
19214
19265
  position: TrackPositionSchema,
19215
- /** MediaStore key; resolve via `getTrackMedia({ trackId })`. */
19216
- mediaKey: string$2()
19266
+ /** The snapshot's media row id (D482); resolve via `listTrackMedia({ trackId })`. */
19267
+ mediaId: number().int()
19217
19268
  });
19218
19269
  /**
19219
19270
  * Normalized 0..1 trajectory envelope (min/max over every position bbox,
@@ -19817,14 +19868,14 @@ var ObjectEventSchema = object({
19817
19868
  * pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
19818
19869
  frameWidth: number().optional(),
19819
19870
  frameHeight: number().optional(),
19820
- /** MediaStore key for the crop attached to this event (if any). */
19821
- mediaKey: string$2().optional(),
19822
- /** Design B: MediaStore key of the track's native-resolution key frame (the
19871
+ /** Media row id of the crop attached to this event (if any) — D482. */
19872
+ mediaId: number().int().optional(),
19873
+ /** Design B: media row id of the track's native-resolution key frame (the
19823
19874
  * best-detection full frame). Resolve via the event-media data-plane
19824
- * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`) for a detail view that
19875
+ * (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`) for a detail view that
19825
19876
  * draws `bbox` over the native frame. Absent on legacy rows / non-decoded
19826
- * sources — consumers fall back to `mediaKey` (the tight crop). */
19827
- keyFrameMediaKey: string$2().optional(),
19877
+ * sources — consumers fall back to `mediaId` (the tight crop). */
19878
+ keyFrameMediaId: number().int().optional(),
19828
19879
  /** Populated by B5 (recording playback URL for this event). */
19829
19880
  mediaUrl: string$2().optional(),
19830
19881
  /** The parent track's key-event importance [0,1], propagated to every object
@@ -19874,7 +19925,7 @@ var MediaFileKindEnum = _enum([
19874
19925
  * hub-main's heap on the way past — for an `<img>` that would have cached it.
19875
19926
  *
19876
19927
  * `url` points at the `event-media` data plane
19877
- * (`/addon/<addonId>/event-media/<storedKey>`), which serves the same blob
19928
+ * (`/addon/<addonId>/event-media/m/<mediaId>` — D482), which serves the same blob
19878
19929
  * with an ETag and `Cache-Control: immutable`, honours conditional GETs, can
19879
19930
  * render a `?variant=thumb`, and streams. The hub gate in front of it requires
19880
19931
  * a bearer or the session cookie (`access: 'authenticated'`), so the bytes are
@@ -19882,10 +19933,13 @@ var MediaFileKindEnum = _enum([
19882
19933
  * `data-plane-access.ts` for the rule and the one gap it does not close
19883
19934
  * (per-device scoping).
19884
19935
  *
19885
- * The URL is built from the row's **stored** key, which is not always its
19886
- * published `kind`: a track's face/plate crop is stored as `crop` under
19936
+ * The URL is built from the row's own id, which since D482 says nothing about
19937
+ * the row's owner or kind — and that is the point. The published `kind` is not
19938
+ * the stored one (a track's face/plate crop is stored as `crop` under
19887
19939
  * `('face'|'plate', '<prefix>-<trackId>')` and published as
19888
- * `faceCrop`/`plateCrop`. `MediaStore.getByKey` knows only the stored key.
19940
+ * `faceCrop`/`plateCrop`), and under the old composite key the URL had to be
19941
+ * taken from `row.key` verbatim or it 404'd exactly those two rows. An id
19942
+ * cannot be mis-reconstructed, because there is nothing in it to reconstruct.
19889
19943
  *
19890
19944
  * ## `base64` is TRANSITIONAL and is going away
19891
19945
  *
@@ -19898,7 +19952,19 @@ var MediaFileKindEnum = _enum([
19898
19952
  * `analytics-query-facade.ts`; nothing else reads it.
19899
19953
  */
19900
19954
  var MediaFileSchema = object({
19901
- key: string$2(),
19955
+ /**
19956
+ * The media row's OWN id — the rowid SQLite assigned it (D482).
19957
+ *
19958
+ * It used to be the row's composite key, `<ownerType>:<ownerId>:<fileKind>
19959
+ * [:<timestampMs>]`, which embedded a FOREIGN id. D474 made event ids
19960
+ * per-table rowid aliases, so `object:101314` and `motion:101314` are two
19961
+ * different rows that spell the same number, and a track whose
19962
+ * `bestEventId` was an object event was served a motion event's snapshot —
19963
+ * a night-time thumbnail on an afternoon track, with no error anywhere. A
19964
+ * surrogate id cannot name the wrong row's owner, because it names no owner
19965
+ * at all.
19966
+ */
19967
+ mediaId: number().int(),
19902
19968
  kind: MediaFileKindEnum,
19903
19969
  sizeBytes: number(),
19904
19970
  timestamp: number()
@@ -20006,7 +20072,7 @@ var RetrainTrackSchema = object({
20006
20072
  });
20007
20073
  /** A frame the picker may offer — an index row, no blob was read to produce it. */
20008
20074
  var RetrainFrameCandidateSchema = object({
20009
- mediaKey: string$2(),
20075
+ mediaId: number().int(),
20010
20076
  kind: MediaFileKindEnum,
20011
20077
  timestamp: number(),
20012
20078
  sizeBytes: number().int(),
@@ -20020,7 +20086,7 @@ var RetrainFrameSchema = object({
20020
20086
  deviceId: number(),
20021
20087
  trackId: string$2(),
20022
20088
  /** Provenance only. It may already point at nothing — that is expected. */
20023
- sourceMediaKey: string$2(),
20089
+ sourceMediaId: number().int(),
20024
20090
  sourceKind: MediaFileKindEnum,
20025
20091
  sizeBytes: number().int(),
20026
20092
  width: number().int(),
@@ -20036,7 +20102,7 @@ var RetrainCopyRefusalSchema = _enum([
20036
20102
  var RetrainFrameSelectionSchema = object({
20037
20103
  copied: array(RetrainFrameSchema).readonly(),
20038
20104
  refused: array(object({
20039
- sourceMediaKey: string$2(),
20105
+ sourceMediaId: number().int(),
20040
20106
  reason: RetrainCopyRefusalSchema
20041
20107
  })).readonly()
20042
20108
  });
@@ -20044,7 +20110,7 @@ var RetrainFrameListSchema = object({
20044
20110
  candidates: array(RetrainFrameCandidateSchema).readonly(),
20045
20111
  copies: array(RetrainFrameSchema).readonly(),
20046
20112
  /** What the page pre-selects — the native key frame when one survives. */
20047
- autoPickMediaKey: string$2().optional()
20113
+ autoPickMediaId: number().int().optional()
20048
20114
  });
20049
20115
  /** What the operator asked the assist to look for. */
20050
20116
  var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
@@ -20139,9 +20205,11 @@ var RecentTracksQueryInput = object({
20139
20205
  });
20140
20206
  /**
20141
20207
  * A Summary (D359): the per-camera session envelope that references tracks.
20142
- * `groupShotKey` is the media key of its group shot (`ownerKind: 'summary'`,
20143
- * served by the event-media plane by key), null until the first frame with a
20144
- * member visible has been materialised.
20208
+ * `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
20209
+ * 'summary'`, served by the event-media plane at `/m/<id>`), null until the
20210
+ * first frame with a member visible has been materialised (D482 — it was the
20211
+ * row's composite key, which embedded the owner and could name another table's
20212
+ * row once event ids became per-table rowids).
20145
20213
  */
20146
20214
  var SummarySchema = object({
20147
20215
  id: string$2(),
@@ -20150,19 +20218,115 @@ var SummarySchema = object({
20150
20218
  lastActiveAt: number(),
20151
20219
  sealedAt: number().nullable(),
20152
20220
  memberCount: number().int().nonnegative(),
20153
- groupShotKey: string$2().nullable()
20221
+ groupShotMediaId: number().int().nullable()
20154
20222
  });
20155
20223
  var SummariesQueryInput = object({
20156
20224
  deviceIds: array(number()).min(1),
20157
20225
  since: number().optional(),
20158
20226
  until: number().optional(),
20159
- limit: number().int().min(1).max(200).default(50)
20227
+ limit: number().int().min(1).max(200).default(50),
20228
+ /** The same member-wise filter {@link listRecentSummaries} takes — one
20229
+ * meaning of "dog" on every summary surface. */
20230
+ classes: array(string$2().min(1).max(60)).max(40).optional()
20160
20231
  });
20161
- var SummariesPageSchema = object({ summaries: array(SummarySchema).readonly() });
20162
20232
  var SummaryDetailSchema = object({
20163
20233
  summary: SummarySchema,
20164
- /** Member track ids, in absorption order. */
20165
- trackIds: array(string$2()).readonly()
20234
+ /** Members in absorption order, oldest join first. */
20235
+ members: array(object({
20236
+ trackId: string$2(),
20237
+ /**
20238
+ * The track's class at the time it JOINED, or `null` when it was unresolved
20239
+ * and the track no longer exists to fill it.
20240
+ *
20241
+ * The join, not the latest opinion: class voting can re-decide a track's
20242
+ * class afterwards, and a group's composition is the history of who came
20243
+ * together. A consumer counts these to badge a thumbnail — "two people and a
20244
+ * dog" — rather than being handed a second, denormalised tally that would
20245
+ * drift from the members it claims to describe.
20246
+ */
20247
+ className: string$2().nullable(),
20248
+ /** `primary` is the one member that carries the group's identity. */
20249
+ role: _enum([
20250
+ "primary",
20251
+ "sibling",
20252
+ "child"
20253
+ ]).nullable(),
20254
+ joinedAt: number(),
20255
+ /** Tier 1 — the sub-class (`dog`, `van`), resolved from the member's track
20256
+ * at read time. Absent when nothing resolved, never an empty string. */
20257
+ label: string$2().optional(),
20258
+ /** Tier 2 — the instance: a person's name, a plate. Absent when the pipeline
20259
+ * recognised nobody, and absent for a member whose track has been pruned —
20260
+ * a thumbnail that names the wrong person is worse than one naming nobody. */
20261
+ subLabel: string$2().optional()
20262
+ })).readonly()
20263
+ });
20264
+ /**
20265
+ * What a LIST of groups carries: the envelope plus what it is MADE OF.
20266
+ *
20267
+ * Coarse on purpose — the operator's rule is "only the rough data on the list,
20268
+ * we extend when we notice we need more". Enough to draw the card ("two people
20269
+ * and a dog") and no more. The MEMBERS, their names and the per-member links
20270
+ * are on {@link getSummary}: shipping every member of every group so a client
20271
+ * can count them turns a page of two hundred groups into a thousand records to
20272
+ * draw two hundred badges.
20273
+ */
20274
+ var SummaryListItemSchema = object({
20275
+ summary: SummarySchema,
20276
+ /** Class counts, most numerous first; `className: null` is a member whose
20277
+ * class never resolved, counted so the counts add up to `memberCount`. */
20278
+ classes: array(object({
20279
+ className: string$2().nullable(),
20280
+ count: number().int().positive()
20281
+ })).readonly()
20282
+ });
20283
+ var SummariesPageSchema = object({ summaries: array(SummaryListItemSchema).readonly() });
20284
+ /**
20285
+ * The paged feed, deliberately the SAME shape as {@link RecentTracksQueryInput}.
20286
+ *
20287
+ * The reel on the cameras page and the Events gallery both ride a cursor, so a
20288
+ * summaries feed that could only answer "the last N for these cameras"
20289
+ * (`listSummaries`) would make groups available in the timeline and nowhere
20290
+ * else. Two feeds with different ordering contracts would be two ideas of what
20291
+ * "newest" means, on one screen.
20292
+ */
20293
+ var RecentSummariesQueryInput = object({
20294
+ /** Devices to merge. An empty array yields an empty page. */
20295
+ deviceIds: array(number()),
20296
+ /** Window lower bound on `lastActiveAt` (inclusive). */
20297
+ since: number().optional(),
20298
+ /** Window upper bound on `lastActiveAt` (inclusive). */
20299
+ until: number().optional(),
20300
+ limit: number().int().min(1).max(500).default(100),
20301
+ /** Opaque continuation cursor from a previous page's `nextCursor`. */
20302
+ cursor: string$2().optional(),
20303
+ /**
20304
+ * Restrict to these classes — THE SAME FIELD `listRecentTracks` takes, and
20305
+ * deliberately the same name: the events filter tree emits one list of ticked
20306
+ * taxonomy nodes, and a summaries feed that called it something else would
20307
+ * make the operator's one filter component produce two shapes.
20308
+ *
20309
+ * A question about the MEMBERS: a group matches when ANY of them does. "Show
20310
+ * me the arrivals with a dog" has to return the group of four people who had
20311
+ * one with them; a filter on the group's own fields could only ever answer
20312
+ * about its primary.
20313
+ *
20314
+ * Matched against all THREE tiers of a member — the class (`animal`), the
20315
+ * sub-class (`dog`) and the instance (a name, a plate) — because which tier a
20316
+ * ticked node lives on is the taxonomy's business, not the caller's. `dog` is
20317
+ * an event kind in the tree and a tier-1 label on an `animal` track; a filter
20318
+ * that read only the class would answer "animal" and never "dog".
20319
+ *
20320
+ * ABSENT or EMPTY means no filter — absent is not a selection of none.
20321
+ */
20322
+ classes: array(string$2().min(1).max(60)).max(40).optional()
20323
+ });
20324
+ var RecentSummariesPageSchema = object({
20325
+ /** Ordered by (`lastActiveAt` DESC, id DESC). Same light item as
20326
+ * {@link listSummaries} — one list shape, so a card renders the same
20327
+ * whichever feed drew it. */
20328
+ summaries: array(SummaryListItemSchema).readonly(),
20329
+ nextCursor: string$2().nullable()
20166
20330
  });
20167
20331
  var RecentTracksPageSchema = object({
20168
20332
  /** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
@@ -20576,7 +20740,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
20576
20740
  classes: array(string$2()).optional(),
20577
20741
  /** See {@link ExcludeSourcesDoc}. */
20578
20742
  excludeSources: array(TrackSourceSchema).optional()
20579
- }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(object({ id: string$2() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
20743
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(RecentSummariesQueryInput, RecentSummariesPageSchema), method(object({ id: string$2() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
20580
20744
  kind: "mutation",
20581
20745
  auth: "admin"
20582
20746
  }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(EventKindsForDeviceSchema).readonly()), method(object({
@@ -20704,7 +20868,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
20704
20868
  }), method(object({
20705
20869
  deviceId: number(),
20706
20870
  trackId: string$2(),
20707
- mediaKeys: array(string$2()).min(1)
20871
+ mediaIds: array(number().int()).min(1)
20708
20872
  }), RetrainFrameSelectionSchema, {
20709
20873
  kind: "mutation",
20710
20874
  auth: "admin"
@@ -20772,7 +20936,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
20772
20936
  kind: "query",
20773
20937
  auth: "admin"
20774
20938
  }), method(object({
20775
- eventId: string$2(),
20939
+ /** Which of the three event tables owns the row. */
20940
+ ownerType: EventOwnerTypeSchema,
20941
+ /** The event's rowid in that table (D474: an event id is a number). */
20942
+ eventId: number().int(),
20776
20943
  kind: MediaFileKindEnum.optional(),
20777
20944
  deviceId: number()
20778
20945
  }), array(MediaFileSchema).readonly()), method(object({
@@ -20783,7 +20950,8 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
20783
20950
  trackId: string$2(),
20784
20951
  deviceId: number()
20785
20952
  }), array(MediaFileInfoSchema).readonly()), method(object({
20786
- eventId: string$2(),
20953
+ ownerType: EventOwnerTypeSchema,
20954
+ eventId: number().int(),
20787
20955
  deviceId: number()
20788
20956
  }), array(MediaFileInfoSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
20789
20957
  kind: "mutation",
@@ -25993,8 +26161,8 @@ var IdentitySchema = object({
25993
26161
  id: string$2(),
25994
26162
  name: string$2(),
25995
26163
  sampleCount: number().int().nonnegative(),
25996
- coverMediaKey: string$2().optional(),
25997
- /** Inline base64 of the cover sample's crop, resolved from `coverMediaKey`.
26164
+ coverMediaId: number().int().optional(),
26165
+ /** Inline base64 of the cover sample's crop, resolved from `coverMediaId`.
25998
26166
  * Lets the UI render the person's face avatar instead of a placeholder icon. */
25999
26167
  coverBase64: string$2().optional()
26000
26168
  });
@@ -26020,8 +26188,8 @@ var IdentitySampleAuditRowSchema = object({
26020
26188
  enrolledAt: number().int(),
26021
26189
  deviceId: number().int().optional(),
26022
26190
  source: _enum(["detected", "photo"]),
26023
- /** The enrolled crop's media key, so the panel can show the evidence. */
26024
- mediaKey: string$2().optional(),
26191
+ /** The enrolled crop's media row id, so the panel can show the evidence. */
26192
+ mediaId: number().int().optional(),
26025
26193
  /**
26026
26194
  * False = the sample is stamped with a DIFFERENT face model, and a cosine
26027
26195
  * across feature spaces is a well-formed float with no meaning. Every number
@@ -26090,15 +26258,15 @@ var FaceInfoSchema = object({
26090
26258
  */
26091
26259
  cropUrl: string$2().optional(),
26092
26260
  /** Design B: the face bbox (pixel space) on the key frame — lets a detail
26093
- * view draw the box over the native `keyFrameMediaKey` frame. Absent on
26261
+ * view draw the box over the native `keyFrameMediaId` frame. Absent on
26094
26262
  * legacy rows written before design B. */
26095
26263
  faceBbox: BoundingBoxSchema.optional(),
26096
26264
  /** Design B: MediaStore key of the track's native-resolution key frame.
26097
26265
  * Fetch the native JPEG via the event-media data-plane
26098
- * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`). Absent when the
26266
+ * (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`). Absent when the
26099
26267
  * track produced no key frame (e.g. native/onboard source) — the UI falls
26100
26268
  * back to the inline `base64` face crop. */
26101
- keyFrameMediaKey: string$2().optional(),
26269
+ keyFrameMediaId: number().int().optional(),
26102
26270
  /** Winning identity-match cosine (0..1) for this face's track, when an
26103
26271
  * identity was auto-confirmed. Lets the UI surface WHY a face was assigned
26104
26272
  * (confidence badge / low-confidence audit). Absent on legacy rows and on
@@ -26167,11 +26335,14 @@ var FaceClusterSchema = object({
26167
26335
  * `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
26168
26336
  * dialog already rendering its key FRAME from the `event-media` plane.
26169
26337
  *
26170
- * `url` is `/addon/<addonId>/event-media/<encoded key>`. The plane resolves a
26171
- * media key directly, so this needed no new plane and no new access decision.
26338
+ * `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
26339
+ * resolves a media row by its own id, so this needed no new plane and no new
26340
+ * access decision.
26172
26341
  */
26173
26342
  var MediaFileLiteSchema$1 = object({
26174
- key: string$2(),
26343
+ /** The media row's own id — the same address `MediaFileRef.mediaId` carries
26344
+ * (D482). It was the row's composite key, which embedded the owner. */
26345
+ mediaId: number().int(),
26175
26346
  kind: string$2(),
26176
26347
  url: string$2(),
26177
26348
  sizeBytes: number(),
@@ -26188,7 +26359,7 @@ method(object({
26188
26359
  * covers inline, ~10 KB of base64 per row, on a query this UI mounts
26189
26360
  * four times and the viewer holds at `staleTime: 30_000`.
26190
26361
  *
26191
- * Nothing loses its avatar: `coverMediaKey` is already on every row and
26362
+ * Nothing loses its avatar: `coverMediaId` is already on every row and
26192
26363
  * the `event-media` plane serves that key `immutable` with an ETag.
26193
26364
  *
26194
26365
  * **This is an INPUT field, so it does not reach the addon until the
@@ -29551,8 +29722,8 @@ var VehicleSchema = object({
29551
29722
  id: string$2(),
29552
29723
  name: string$2(),
29553
29724
  sampleCount: number().int().nonnegative(),
29554
- coverMediaKey: string$2().optional(),
29555
- /** Inline base64 of the cover sample's plate crop, resolved from `coverMediaKey`. */
29725
+ coverMediaId: number().int().optional(),
29726
+ /** Inline base64 of the cover sample's plate crop, resolved from `coverMediaId`. */
29556
29727
  coverBase64: string$2().optional()
29557
29728
  });
29558
29729
  var VehicleSampleInfoSchema = object({
@@ -29585,7 +29756,7 @@ var PlateInfoSchema = object({
29585
29756
  /** keyFrame parity: the plate bbox (pixel space) on the native key frame. */
29586
29757
  plateBbox: BoundingBoxSchema.optional(),
29587
29758
  /** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
29588
- keyFrameMediaKey: string$2().optional(),
29759
+ keyFrameMediaId: number().int().optional(),
29589
29760
  base64: string$2().optional(),
29590
29761
  /**
29591
29762
  * Same crop as a data-plane URL, always present when the plate has a stored
@@ -29606,11 +29777,14 @@ var PlateInfoSchema = object({
29606
29777
  * `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
29607
29778
  * dialog already rendering its key FRAME from the `event-media` plane.
29608
29779
  *
29609
- * `url` is `/addon/<addonId>/event-media/<encoded key>`. The plane resolves a
29610
- * media key directly, so this needed no new plane and no new access decision.
29780
+ * `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
29781
+ * resolves a media row by its own id, so this needed no new plane and no new
29782
+ * access decision.
29611
29783
  */
29612
29784
  var MediaFileLiteSchema = object({
29613
- key: string$2(),
29785
+ /** The media row's own id — the same address `MediaFileRef.mediaId` carries
29786
+ * (D482). It was the row's composite key, which embedded the owner. */
29787
+ mediaId: number().int(),
29614
29788
  kind: string$2(),
29615
29789
  url: string$2(),
29616
29790
  sizeBytes: number(),
@@ -29669,7 +29843,7 @@ method(object({
29669
29843
  }), method(object({
29670
29844
  /** Inline {@link VehicleSchema.coverBase64} on every row. Default
29671
29845
  * `false` — the vehicle twin of `faceGallery.listIdentities`'s
29672
- * option; `coverMediaKey` + the `event-media` plane carry the picture.
29846
+ * option; `coverMediaId` + the `event-media` plane carry the picture.
29673
29847
  * INPUT field: stripped by the hub router until the train ships, which
29674
29848
  * resolves to `false` and is exactly the intended default. */
29675
29849
  includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly()), method(object({ name: string$2().min(1) }), VehicleSchema, {
@@ -31238,7 +31412,14 @@ var SceneReferenceSchema = object({
31238
31412
  modelId: string$2(),
31239
31413
  condition: SceneConditionSchema,
31240
31414
  capturedAt: number(),
31241
- thumbnailMediaId: string$2().optional(),
31415
+ /**
31416
+ * The reference thumbnail's media ROW id (D482).
31417
+ *
31418
+ * The name already said `mediaId` while the value was the row's composite
31419
+ * key — a leftover that read as done and was not. It is the row's own id
31420
+ * now, addressed at `/addon/<addonId>/event-media/m/<id>`.
31421
+ */
31422
+ thumbnailMediaId: number().int().optional(),
31242
31423
  /** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
31243
31424
  * anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
31244
31425
  * normalized rect frame a different piece of world, and the scene would
@@ -32329,7 +32510,29 @@ var LoggingSettingsPatchSchema = object({
32329
32510
  * disarmed the channels it did not mention would make the Levels page and
32330
32511
  * the Diagnostics page fight over the same value.
32331
32512
  */
32332
- channels: array(LogChannelWindowPatchSchema).readonly().optional()
32513
+ channels: array(LogChannelWindowPatchSchema).readonly().optional(),
32514
+ /**
32515
+ * How many days the analytics OPS LOG is kept — the audit trail of what
32516
+ * retention actually deleted.
32517
+ *
32518
+ * It lives HERE, on the logging document, and not on the analytics addon's
32519
+ * settings form, on the operator's instruction: every other log-ish window in
32520
+ * this system is configured through this one document, and a retention audit
32521
+ * configured somewhere else is a second place to look when the question is
32522
+ * "what happened to my data".
32523
+ *
32524
+ * That placement has a cost worth stating: this document ships in the
32525
+ * framework closure, so this knob needs a published `@camstack/server` while
32526
+ * the four windows beside it (D485) reach a node on `camstack deploy`.
32527
+ *
32528
+ * `retention-model.ts` argued this one must NOT follow a device window,
32529
+ * because the audit trail is the history of the SWEEP and not of the camera.
32530
+ * That argument stands and is untouched — what changes is that 30 days stops
32531
+ * being a constant nobody can reach. `0` keeps it forever. The floor is 1 day
32532
+ * rather than 0-as-delete: an audit log truncated to nothing is precisely the
32533
+ * state in which the next 9.5 GiB leak cannot be explained.
32534
+ */
32535
+ opsLogRetentionDays: number().int().min(0).max(3650).optional()
32333
32536
  });
32334
32537
  /**
32335
32538
  * Which LAYER of the hierarchy is addressed. Absent = the cluster layer.
@@ -32402,6 +32605,14 @@ var LoggingSettingsStateSchema = object({
32402
32605
  channels: array(LogChannelDescriptorSchema).readonly(),
32403
32606
  /** The channels ARMED right now, each with its deadline. */
32404
32607
  activeChannels: array(LogChannelWindowStateSchema).readonly(),
32608
+ /**
32609
+ * The ops-log window in days, as it is in force. `0` = kept forever.
32610
+ *
32611
+ * Reported rather than left to the caller's memory of what it wrote: this is
32612
+ * the value the analytics sweep will actually use, and an operator asking how
32613
+ * long their audit trail lives should not have to infer it from a default.
32614
+ */
32615
+ opsLogRetentionDays: number().int().min(0),
32405
32616
  persisted: boolean()
32406
32617
  });
32407
32618
  method(_void(), FeatureManifestSchema), method(_void(), HealthStatusSchema), method(_void(), FeatureManifestSchema), method(_void(), array(NetworkAddressSchema).readonly()), method(_void(), unknown().nullable(), { auth: "admin" }), method(record(string$2(), unknown()), _null(), {
@@ -33222,7 +33433,7 @@ var StationaryObjectSchema = object({
33222
33433
  /** Enrichment label carried from the source track (identity / plate). */
33223
33434
  label: string$2().optional(),
33224
33435
  /** Native-resolution key-frame media key for the parked object's best image. */
33225
- keyFrameMediaKey: string$2().optional()
33436
+ keyFrameMediaId: number().int().optional()
33226
33437
  });
33227
33438
  var CameraOccupancySnapshotSchema = object({
33228
33439
  /** Frame timestamp of the inference result that produced this snapshot. */
@@ -35960,6 +36171,12 @@ Object.freeze({
35960
36171
  addonId: null,
35961
36172
  access: "create"
35962
36173
  },
36174
+ "dataStoreProvider.upsert": {
36175
+ capName: "data-store-provider",
36176
+ capScope: "system",
36177
+ addonId: null,
36178
+ access: "create"
36179
+ },
35963
36180
  "dayNight.getOptions": {
35964
36181
  capName: "day-night",
35965
36182
  capScope: "device",
@@ -38396,6 +38613,12 @@ Object.freeze({
38396
38613
  addonId: null,
38397
38614
  access: "view"
38398
38615
  },
38616
+ "pipelineAnalytics.listRecentSummaries": {
38617
+ capName: "pipeline-analytics",
38618
+ capScope: "device",
38619
+ addonId: null,
38620
+ access: "view"
38621
+ },
38399
38622
  "pipelineAnalytics.listRecentTracks": {
38400
38623
  capName: "pipeline-analytics",
38401
38624
  capScope: "device",
@@ -39824,6 +40047,12 @@ Object.freeze({
39824
40047
  addonId: null,
39825
40048
  access: "create"
39826
40049
  },
40050
+ "settingsStore.upsert": {
40051
+ capName: "settings-store",
40052
+ capScope: "system",
40053
+ addonId: null,
40054
+ access: "create"
40055
+ },
39827
40056
  "smtpProvider.getStatus": {
39828
40057
  capName: "smtp-provider",
39829
40058
  capScope: "system",
@@ -42217,6 +42446,11 @@ Object.freeze({
42217
42446
  form: "single",
42218
42447
  optional: true
42219
42448
  }],
42449
+ "pipelineAnalytics.listRecentSummaries": [{
42450
+ name: "deviceIds",
42451
+ form: "array",
42452
+ optional: false
42453
+ }],
42220
42454
  "pipelineAnalytics.listRecentTracks": [{
42221
42455
  name: "deviceIds",
42222
42456
  form: "array",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-matter-broker",
3
- "version": "0.2.98",
3
+ "version": "0.2.100",
4
4
  "description": "Matter broker addon for CamStack — owns a Matter fabric (commissioning + the long-lived controller) via the matter.js controller and brokers commissioned Matter nodes into CamStack",
5
5
  "keywords": [
6
6
  "camstack",