@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.
- package/dist/addon.js +292 -58
- package/dist/addon.mjs +292 -58
- 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-
|
|
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,
|
|
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-
|
|
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
|
-
|
|
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
|
-
/**
|
|
19218
|
-
|
|
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
|
-
/**
|
|
19823
|
-
|
|
19824
|
-
/** Design B:
|
|
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/<
|
|
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 `
|
|
19829
|
-
|
|
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/<
|
|
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
|
|
19888
|
-
*
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
* `
|
|
20145
|
-
* served by the event-media plane
|
|
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
|
-
|
|
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
|
-
/**
|
|
20167
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
25999
|
-
/** Inline base64 of the cover sample's crop, resolved from `
|
|
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
|
|
26026
|
-
|
|
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 `
|
|
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/<
|
|
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
|
-
|
|
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/<
|
|
26173
|
-
* media
|
|
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
|
-
|
|
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: `
|
|
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
|
-
|
|
29557
|
-
/** Inline base64 of the cover sample's plate crop, resolved from `
|
|
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
|
-
|
|
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/<
|
|
29612
|
-
* media
|
|
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
|
-
|
|
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; `
|
|
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
|
-
|
|
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
|
-
|
|
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-
|
|
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,
|
|
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-
|
|
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
|
-
|
|
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
|
-
/**
|
|
19216
|
-
|
|
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
|
-
/**
|
|
19821
|
-
|
|
19822
|
-
/** Design B:
|
|
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/<
|
|
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 `
|
|
19827
|
-
|
|
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/<
|
|
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
|
|
19886
|
-
*
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
* `
|
|
20143
|
-
* served by the event-media plane
|
|
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
|
-
|
|
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
|
-
/**
|
|
20165
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
25997
|
-
/** Inline base64 of the cover sample's crop, resolved from `
|
|
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
|
|
26024
|
-
|
|
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 `
|
|
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/<
|
|
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
|
-
|
|
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/<
|
|
26171
|
-
* media
|
|
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
|
-
|
|
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: `
|
|
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
|
-
|
|
29555
|
-
/** Inline base64 of the cover sample's plate crop, resolved from `
|
|
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
|
-
|
|
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/<
|
|
29610
|
-
* media
|
|
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
|
-
|
|
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; `
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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",
|