@camstack/addon-export-hap 1.2.110 → 1.2.112
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/hap-export.addon.js +274 -56
- package/dist/hap-export.addon.mjs +274 -56
- package/package.json +1 -1
package/dist/hap-export.addon.js
CHANGED
|
@@ -84,7 +84,7 @@ function carryForward(base, existing, keys) {
|
|
|
84
84
|
return out;
|
|
85
85
|
}
|
|
86
86
|
//#endregion
|
|
87
|
-
//#region ../types/dist/event-category-
|
|
87
|
+
//#region ../types/dist/event-category-ZyX6jcse.mjs
|
|
88
88
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
89
89
|
EventCategory["SystemBoot"] = "system.boot";
|
|
90
90
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -645,7 +645,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
645
645
|
* a package zone — a newly-appeared stationary object of a package class
|
|
646
646
|
* that cleared the class / zone / dwell / size gates. Payload:
|
|
647
647
|
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
648
|
-
* entryId, className, zoneIds,
|
|
648
|
+
* entryId, className, zoneIds, keyFrameMediaId?, bbox, timestamp }`.
|
|
649
649
|
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
650
650
|
* this bus topic drives notifier rules + live UI. See
|
|
651
651
|
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
@@ -5431,7 +5431,7 @@ var ZodIssueCode = {
|
|
|
5431
5431
|
var ZodFirstPartyTypeKind;
|
|
5432
5432
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5433
5433
|
//#endregion
|
|
5434
|
-
//#region ../types/dist/sleep-
|
|
5434
|
+
//#region ../types/dist/sleep-DBKu2-U5.mjs
|
|
5435
5435
|
/**
|
|
5436
5436
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5437
5437
|
* window to float samples (D455).
|
|
@@ -7951,13 +7951,30 @@ new Set([
|
|
|
7951
7951
|
"scene",
|
|
7952
7952
|
"motion",
|
|
7953
7953
|
"object",
|
|
7954
|
-
"audio"
|
|
7954
|
+
"audio",
|
|
7955
|
+
"mosaic"
|
|
7955
7956
|
]);
|
|
7956
|
-
|
|
7957
|
+
/**
|
|
7958
|
+
* The owner types that are event tables, in the order the event-media resolver
|
|
7959
|
+
* should consider them. Exported so a consumer asking "is this key an event?"
|
|
7960
|
+
* does not re-spell the list and drift from it.
|
|
7961
|
+
*/
|
|
7962
|
+
var EVENT_OWNER_TYPES = [
|
|
7957
7963
|
"motion",
|
|
7958
7964
|
"object",
|
|
7959
7965
|
"audio"
|
|
7960
|
-
]
|
|
7966
|
+
];
|
|
7967
|
+
/**
|
|
7968
|
+
* The same list as a Zod enum, for the cap inputs that must NAME the table
|
|
7969
|
+
* (D482: `getEventMedia` / `listEventMedia` take an owner, and an owner is
|
|
7970
|
+
* `(table, id)`).
|
|
7971
|
+
*
|
|
7972
|
+
* Built FROM {@link EVENT_OWNER_TYPES} rather than re-spelled: a fourth event
|
|
7973
|
+
* table would otherwise be accepted by the codec and refused at the door, with
|
|
7974
|
+
* nothing failing until a caller asked.
|
|
7975
|
+
*/
|
|
7976
|
+
var EventOwnerTypeSchema = _enum(EVENT_OWNER_TYPES);
|
|
7977
|
+
new Set(EVENT_OWNER_TYPES);
|
|
7961
7978
|
var EncodeProfileSchema = object({
|
|
7962
7979
|
video: object({
|
|
7963
7980
|
codec: _enum([
|
|
@@ -13136,6 +13153,16 @@ method(object({
|
|
|
13136
13153
|
filter: QueryFilterSchema.optional(),
|
|
13137
13154
|
columns: array(string()).readonly().optional()
|
|
13138
13155
|
}), array(SettingsRecordSchema).readonly()), method(object({
|
|
13156
|
+
namespace: string().optional(),
|
|
13157
|
+
collection: string(),
|
|
13158
|
+
/** Declared columns identifying the slot; must be covered by a UNIQUE
|
|
13159
|
+
* index on the collection. Never empty. */
|
|
13160
|
+
conflict: array(string()).readonly(),
|
|
13161
|
+
record: BulkRecordSchema
|
|
13162
|
+
}), object({
|
|
13163
|
+
/** The id the row HAS: assigned by SQLite on an insert, or the existing
|
|
13164
|
+
* row's own id on an update. */
|
|
13165
|
+
id: union([string(), number()]) }), { kind: "mutation" }), method(object({
|
|
13139
13166
|
namespace: string().optional(),
|
|
13140
13167
|
collection: string(),
|
|
13141
13168
|
record: object({
|
|
@@ -13270,6 +13297,14 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
|
|
|
13270
13297
|
id: union([string(), number()]) }), {
|
|
13271
13298
|
kind: "mutation",
|
|
13272
13299
|
auth: "admin"
|
|
13300
|
+
}), method(object({
|
|
13301
|
+
namespace: string().optional(),
|
|
13302
|
+
collection: string(),
|
|
13303
|
+
conflict: array(string()).readonly(),
|
|
13304
|
+
record: BulkRecordSchema
|
|
13305
|
+
}), object({ id: union([string(), number()]) }), {
|
|
13306
|
+
kind: "mutation",
|
|
13307
|
+
auth: "admin"
|
|
13273
13308
|
}), method(object({
|
|
13274
13309
|
namespace: string().optional(),
|
|
13275
13310
|
collection: string(),
|
|
@@ -19567,8 +19602,8 @@ var TrackPositionSchema = object({
|
|
|
19567
19602
|
var TrackSnapshotSchema = object({
|
|
19568
19603
|
timestamp: number(),
|
|
19569
19604
|
position: TrackPositionSchema,
|
|
19570
|
-
/**
|
|
19571
|
-
|
|
19605
|
+
/** The snapshot's media row id (D482); resolve via `listTrackMedia({ trackId })`. */
|
|
19606
|
+
mediaId: number().int()
|
|
19572
19607
|
});
|
|
19573
19608
|
/**
|
|
19574
19609
|
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
@@ -20172,14 +20207,14 @@ var ObjectEventSchema = object({
|
|
|
20172
20207
|
* pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
|
|
20173
20208
|
frameWidth: number().optional(),
|
|
20174
20209
|
frameHeight: number().optional(),
|
|
20175
|
-
/**
|
|
20176
|
-
|
|
20177
|
-
/** Design B:
|
|
20210
|
+
/** Media row id of the crop attached to this event (if any) — D482. */
|
|
20211
|
+
mediaId: number().int().optional(),
|
|
20212
|
+
/** Design B: media row id of the track's native-resolution key frame (the
|
|
20178
20213
|
* best-detection full frame). Resolve via the event-media data-plane
|
|
20179
|
-
* (`/addon/<addonId>/event-media/<
|
|
20214
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`) for a detail view that
|
|
20180
20215
|
* draws `bbox` over the native frame. Absent on legacy rows / non-decoded
|
|
20181
|
-
* sources — consumers fall back to `
|
|
20182
|
-
|
|
20216
|
+
* sources — consumers fall back to `mediaId` (the tight crop). */
|
|
20217
|
+
keyFrameMediaId: number().int().optional(),
|
|
20183
20218
|
/** Populated by B5 (recording playback URL for this event). */
|
|
20184
20219
|
mediaUrl: string().optional(),
|
|
20185
20220
|
/** The parent track's key-event importance [0,1], propagated to every object
|
|
@@ -20229,7 +20264,7 @@ var MediaFileKindEnum = _enum([
|
|
|
20229
20264
|
* hub-main's heap on the way past — for an `<img>` that would have cached it.
|
|
20230
20265
|
*
|
|
20231
20266
|
* `url` points at the `event-media` data plane
|
|
20232
|
-
* (`/addon/<addonId>/event-media/<
|
|
20267
|
+
* (`/addon/<addonId>/event-media/m/<mediaId>` — D482), which serves the same blob
|
|
20233
20268
|
* with an ETag and `Cache-Control: immutable`, honours conditional GETs, can
|
|
20234
20269
|
* render a `?variant=thumb`, and streams. The hub gate in front of it requires
|
|
20235
20270
|
* a bearer or the session cookie (`access: 'authenticated'`), so the bytes are
|
|
@@ -20237,10 +20272,13 @@ var MediaFileKindEnum = _enum([
|
|
|
20237
20272
|
* `data-plane-access.ts` for the rule and the one gap it does not close
|
|
20238
20273
|
* (per-device scoping).
|
|
20239
20274
|
*
|
|
20240
|
-
* The URL is built from the row's
|
|
20241
|
-
*
|
|
20275
|
+
* The URL is built from the row's own id, which since D482 says nothing about
|
|
20276
|
+
* the row's owner or kind — and that is the point. The published `kind` is not
|
|
20277
|
+
* the stored one (a track's face/plate crop is stored as `crop` under
|
|
20242
20278
|
* `('face'|'plate', '<prefix>-<trackId>')` and published as
|
|
20243
|
-
* `faceCrop`/`plateCrop
|
|
20279
|
+
* `faceCrop`/`plateCrop`), and under the old composite key the URL had to be
|
|
20280
|
+
* taken from `row.key` verbatim or it 404'd exactly those two rows. An id
|
|
20281
|
+
* cannot be mis-reconstructed, because there is nothing in it to reconstruct.
|
|
20244
20282
|
*
|
|
20245
20283
|
* ## `base64` is TRANSITIONAL and is going away
|
|
20246
20284
|
*
|
|
@@ -20253,7 +20291,19 @@ var MediaFileKindEnum = _enum([
|
|
|
20253
20291
|
* `analytics-query-facade.ts`; nothing else reads it.
|
|
20254
20292
|
*/
|
|
20255
20293
|
var MediaFileSchema = object({
|
|
20256
|
-
|
|
20294
|
+
/**
|
|
20295
|
+
* The media row's OWN id — the rowid SQLite assigned it (D482).
|
|
20296
|
+
*
|
|
20297
|
+
* It used to be the row's composite key, `<ownerType>:<ownerId>:<fileKind>
|
|
20298
|
+
* [:<timestampMs>]`, which embedded a FOREIGN id. D474 made event ids
|
|
20299
|
+
* per-table rowid aliases, so `object:101314` and `motion:101314` are two
|
|
20300
|
+
* different rows that spell the same number, and a track whose
|
|
20301
|
+
* `bestEventId` was an object event was served a motion event's snapshot —
|
|
20302
|
+
* a night-time thumbnail on an afternoon track, with no error anywhere. A
|
|
20303
|
+
* surrogate id cannot name the wrong row's owner, because it names no owner
|
|
20304
|
+
* at all.
|
|
20305
|
+
*/
|
|
20306
|
+
mediaId: number().int(),
|
|
20257
20307
|
kind: MediaFileKindEnum,
|
|
20258
20308
|
sizeBytes: number(),
|
|
20259
20309
|
timestamp: number()
|
|
@@ -20361,7 +20411,7 @@ var RetrainTrackSchema = object({
|
|
|
20361
20411
|
});
|
|
20362
20412
|
/** A frame the picker may offer — an index row, no blob was read to produce it. */
|
|
20363
20413
|
var RetrainFrameCandidateSchema = object({
|
|
20364
|
-
|
|
20414
|
+
mediaId: number().int(),
|
|
20365
20415
|
kind: MediaFileKindEnum,
|
|
20366
20416
|
timestamp: number(),
|
|
20367
20417
|
sizeBytes: number().int(),
|
|
@@ -20375,7 +20425,7 @@ var RetrainFrameSchema = object({
|
|
|
20375
20425
|
deviceId: number(),
|
|
20376
20426
|
trackId: string(),
|
|
20377
20427
|
/** Provenance only. It may already point at nothing — that is expected. */
|
|
20378
|
-
|
|
20428
|
+
sourceMediaId: number().int(),
|
|
20379
20429
|
sourceKind: MediaFileKindEnum,
|
|
20380
20430
|
sizeBytes: number().int(),
|
|
20381
20431
|
width: number().int(),
|
|
@@ -20391,7 +20441,7 @@ var RetrainCopyRefusalSchema = _enum([
|
|
|
20391
20441
|
var RetrainFrameSelectionSchema = object({
|
|
20392
20442
|
copied: array(RetrainFrameSchema).readonly(),
|
|
20393
20443
|
refused: array(object({
|
|
20394
|
-
|
|
20444
|
+
sourceMediaId: number().int(),
|
|
20395
20445
|
reason: RetrainCopyRefusalSchema
|
|
20396
20446
|
})).readonly()
|
|
20397
20447
|
});
|
|
@@ -20399,7 +20449,7 @@ var RetrainFrameListSchema = object({
|
|
|
20399
20449
|
candidates: array(RetrainFrameCandidateSchema).readonly(),
|
|
20400
20450
|
copies: array(RetrainFrameSchema).readonly(),
|
|
20401
20451
|
/** What the page pre-selects — the native key frame when one survives. */
|
|
20402
|
-
|
|
20452
|
+
autoPickMediaId: number().int().optional()
|
|
20403
20453
|
});
|
|
20404
20454
|
/** What the operator asked the assist to look for. */
|
|
20405
20455
|
var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
|
|
@@ -20494,9 +20544,11 @@ var RecentTracksQueryInput = object({
|
|
|
20494
20544
|
});
|
|
20495
20545
|
/**
|
|
20496
20546
|
* A Summary (D359): the per-camera session envelope that references tracks.
|
|
20497
|
-
* `
|
|
20498
|
-
* served by the event-media plane
|
|
20499
|
-
* member visible has been materialised
|
|
20547
|
+
* `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
|
|
20548
|
+
* 'summary'`, served by the event-media plane at `/m/<id>`), null until the
|
|
20549
|
+
* first frame with a member visible has been materialised (D482 — it was the
|
|
20550
|
+
* row's composite key, which embedded the owner and could name another table's
|
|
20551
|
+
* row once event ids became per-table rowids).
|
|
20500
20552
|
*/
|
|
20501
20553
|
var SummarySchema = object({
|
|
20502
20554
|
id: string(),
|
|
@@ -20505,19 +20557,115 @@ var SummarySchema = object({
|
|
|
20505
20557
|
lastActiveAt: number(),
|
|
20506
20558
|
sealedAt: number().nullable(),
|
|
20507
20559
|
memberCount: number().int().nonnegative(),
|
|
20508
|
-
|
|
20560
|
+
groupShotMediaId: number().int().nullable()
|
|
20509
20561
|
});
|
|
20510
20562
|
var SummariesQueryInput = object({
|
|
20511
20563
|
deviceIds: array(number()).min(1),
|
|
20512
20564
|
since: number().optional(),
|
|
20513
20565
|
until: number().optional(),
|
|
20514
|
-
limit: number().int().min(1).max(200).default(50)
|
|
20566
|
+
limit: number().int().min(1).max(200).default(50),
|
|
20567
|
+
/** The same member-wise filter {@link listRecentSummaries} takes — one
|
|
20568
|
+
* meaning of "dog" on every summary surface. */
|
|
20569
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
20515
20570
|
});
|
|
20516
|
-
var SummariesPageSchema = object({ summaries: array(SummarySchema).readonly() });
|
|
20517
20571
|
var SummaryDetailSchema = object({
|
|
20518
20572
|
summary: SummarySchema,
|
|
20519
|
-
/**
|
|
20520
|
-
|
|
20573
|
+
/** Members in absorption order, oldest join first. */
|
|
20574
|
+
members: array(object({
|
|
20575
|
+
trackId: string(),
|
|
20576
|
+
/**
|
|
20577
|
+
* The track's class at the time it JOINED, or `null` when it was unresolved
|
|
20578
|
+
* and the track no longer exists to fill it.
|
|
20579
|
+
*
|
|
20580
|
+
* The join, not the latest opinion: class voting can re-decide a track's
|
|
20581
|
+
* class afterwards, and a group's composition is the history of who came
|
|
20582
|
+
* together. A consumer counts these to badge a thumbnail — "two people and a
|
|
20583
|
+
* dog" — rather than being handed a second, denormalised tally that would
|
|
20584
|
+
* drift from the members it claims to describe.
|
|
20585
|
+
*/
|
|
20586
|
+
className: string().nullable(),
|
|
20587
|
+
/** `primary` is the one member that carries the group's identity. */
|
|
20588
|
+
role: _enum([
|
|
20589
|
+
"primary",
|
|
20590
|
+
"sibling",
|
|
20591
|
+
"child"
|
|
20592
|
+
]).nullable(),
|
|
20593
|
+
joinedAt: number(),
|
|
20594
|
+
/** Tier 1 — the sub-class (`dog`, `van`), resolved from the member's track
|
|
20595
|
+
* at read time. Absent when nothing resolved, never an empty string. */
|
|
20596
|
+
label: string().optional(),
|
|
20597
|
+
/** Tier 2 — the instance: a person's name, a plate. Absent when the pipeline
|
|
20598
|
+
* recognised nobody, and absent for a member whose track has been pruned —
|
|
20599
|
+
* a thumbnail that names the wrong person is worse than one naming nobody. */
|
|
20600
|
+
subLabel: string().optional()
|
|
20601
|
+
})).readonly()
|
|
20602
|
+
});
|
|
20603
|
+
/**
|
|
20604
|
+
* What a LIST of groups carries: the envelope plus what it is MADE OF.
|
|
20605
|
+
*
|
|
20606
|
+
* Coarse on purpose — the operator's rule is "only the rough data on the list,
|
|
20607
|
+
* we extend when we notice we need more". Enough to draw the card ("two people
|
|
20608
|
+
* and a dog") and no more. The MEMBERS, their names and the per-member links
|
|
20609
|
+
* are on {@link getSummary}: shipping every member of every group so a client
|
|
20610
|
+
* can count them turns a page of two hundred groups into a thousand records to
|
|
20611
|
+
* draw two hundred badges.
|
|
20612
|
+
*/
|
|
20613
|
+
var SummaryListItemSchema = object({
|
|
20614
|
+
summary: SummarySchema,
|
|
20615
|
+
/** Class counts, most numerous first; `className: null` is a member whose
|
|
20616
|
+
* class never resolved, counted so the counts add up to `memberCount`. */
|
|
20617
|
+
classes: array(object({
|
|
20618
|
+
className: string().nullable(),
|
|
20619
|
+
count: number().int().positive()
|
|
20620
|
+
})).readonly()
|
|
20621
|
+
});
|
|
20622
|
+
var SummariesPageSchema = object({ summaries: array(SummaryListItemSchema).readonly() });
|
|
20623
|
+
/**
|
|
20624
|
+
* The paged feed, deliberately the SAME shape as {@link RecentTracksQueryInput}.
|
|
20625
|
+
*
|
|
20626
|
+
* The reel on the cameras page and the Events gallery both ride a cursor, so a
|
|
20627
|
+
* summaries feed that could only answer "the last N for these cameras"
|
|
20628
|
+
* (`listSummaries`) would make groups available in the timeline and nowhere
|
|
20629
|
+
* else. Two feeds with different ordering contracts would be two ideas of what
|
|
20630
|
+
* "newest" means, on one screen.
|
|
20631
|
+
*/
|
|
20632
|
+
var RecentSummariesQueryInput = object({
|
|
20633
|
+
/** Devices to merge. An empty array yields an empty page. */
|
|
20634
|
+
deviceIds: array(number()),
|
|
20635
|
+
/** Window lower bound on `lastActiveAt` (inclusive). */
|
|
20636
|
+
since: number().optional(),
|
|
20637
|
+
/** Window upper bound on `lastActiveAt` (inclusive). */
|
|
20638
|
+
until: number().optional(),
|
|
20639
|
+
limit: number().int().min(1).max(500).default(100),
|
|
20640
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`. */
|
|
20641
|
+
cursor: string().optional(),
|
|
20642
|
+
/**
|
|
20643
|
+
* Restrict to these classes — THE SAME FIELD `listRecentTracks` takes, and
|
|
20644
|
+
* deliberately the same name: the events filter tree emits one list of ticked
|
|
20645
|
+
* taxonomy nodes, and a summaries feed that called it something else would
|
|
20646
|
+
* make the operator's one filter component produce two shapes.
|
|
20647
|
+
*
|
|
20648
|
+
* A question about the MEMBERS: a group matches when ANY of them does. "Show
|
|
20649
|
+
* me the arrivals with a dog" has to return the group of four people who had
|
|
20650
|
+
* one with them; a filter on the group's own fields could only ever answer
|
|
20651
|
+
* about its primary.
|
|
20652
|
+
*
|
|
20653
|
+
* Matched against all THREE tiers of a member — the class (`animal`), the
|
|
20654
|
+
* sub-class (`dog`) and the instance (a name, a plate) — because which tier a
|
|
20655
|
+
* ticked node lives on is the taxonomy's business, not the caller's. `dog` is
|
|
20656
|
+
* an event kind in the tree and a tier-1 label on an `animal` track; a filter
|
|
20657
|
+
* that read only the class would answer "animal" and never "dog".
|
|
20658
|
+
*
|
|
20659
|
+
* ABSENT or EMPTY means no filter — absent is not a selection of none.
|
|
20660
|
+
*/
|
|
20661
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
20662
|
+
});
|
|
20663
|
+
var RecentSummariesPageSchema = object({
|
|
20664
|
+
/** Ordered by (`lastActiveAt` DESC, id DESC). Same light item as
|
|
20665
|
+
* {@link listSummaries} — one list shape, so a card renders the same
|
|
20666
|
+
* whichever feed drew it. */
|
|
20667
|
+
summaries: array(SummaryListItemSchema).readonly(),
|
|
20668
|
+
nextCursor: string().nullable()
|
|
20521
20669
|
});
|
|
20522
20670
|
var RecentTracksPageSchema = object({
|
|
20523
20671
|
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
@@ -20931,7 +21079,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20931
21079
|
classes: array(string()).optional(),
|
|
20932
21080
|
/** See {@link ExcludeSourcesDoc}. */
|
|
20933
21081
|
excludeSources: array(TrackSourceSchema).optional()
|
|
20934
|
-
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
21082
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(RecentSummariesQueryInput, RecentSummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
20935
21083
|
kind: "mutation",
|
|
20936
21084
|
auth: "admin"
|
|
20937
21085
|
}), 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({
|
|
@@ -21059,7 +21207,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
21059
21207
|
}), method(object({
|
|
21060
21208
|
deviceId: number(),
|
|
21061
21209
|
trackId: string(),
|
|
21062
|
-
|
|
21210
|
+
mediaIds: array(number().int()).min(1)
|
|
21063
21211
|
}), RetrainFrameSelectionSchema, {
|
|
21064
21212
|
kind: "mutation",
|
|
21065
21213
|
auth: "admin"
|
|
@@ -21127,7 +21275,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
21127
21275
|
kind: "query",
|
|
21128
21276
|
auth: "admin"
|
|
21129
21277
|
}), method(object({
|
|
21130
|
-
|
|
21278
|
+
/** Which of the three event tables owns the row. */
|
|
21279
|
+
ownerType: EventOwnerTypeSchema,
|
|
21280
|
+
/** The event's rowid in that table (D474: an event id is a number). */
|
|
21281
|
+
eventId: number().int(),
|
|
21131
21282
|
kind: MediaFileKindEnum.optional(),
|
|
21132
21283
|
deviceId: number()
|
|
21133
21284
|
}), array(MediaFileSchema).readonly()), method(object({
|
|
@@ -21138,7 +21289,8 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
21138
21289
|
trackId: string(),
|
|
21139
21290
|
deviceId: number()
|
|
21140
21291
|
}), array(MediaFileInfoSchema).readonly()), method(object({
|
|
21141
|
-
|
|
21292
|
+
ownerType: EventOwnerTypeSchema,
|
|
21293
|
+
eventId: number().int(),
|
|
21142
21294
|
deviceId: number()
|
|
21143
21295
|
}), array(MediaFileInfoSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
|
|
21144
21296
|
kind: "mutation",
|
|
@@ -25621,8 +25773,8 @@ var IdentitySchema = object({
|
|
|
25621
25773
|
id: string(),
|
|
25622
25774
|
name: string(),
|
|
25623
25775
|
sampleCount: number().int().nonnegative(),
|
|
25624
|
-
|
|
25625
|
-
/** Inline base64 of the cover sample's crop, resolved from `
|
|
25776
|
+
coverMediaId: number().int().optional(),
|
|
25777
|
+
/** Inline base64 of the cover sample's crop, resolved from `coverMediaId`.
|
|
25626
25778
|
* Lets the UI render the person's face avatar instead of a placeholder icon. */
|
|
25627
25779
|
coverBase64: string().optional()
|
|
25628
25780
|
});
|
|
@@ -25648,8 +25800,8 @@ var IdentitySampleAuditRowSchema = object({
|
|
|
25648
25800
|
enrolledAt: number().int(),
|
|
25649
25801
|
deviceId: number().int().optional(),
|
|
25650
25802
|
source: _enum(["detected", "photo"]),
|
|
25651
|
-
/** The enrolled crop's media
|
|
25652
|
-
|
|
25803
|
+
/** The enrolled crop's media row id, so the panel can show the evidence. */
|
|
25804
|
+
mediaId: number().int().optional(),
|
|
25653
25805
|
/**
|
|
25654
25806
|
* False = the sample is stamped with a DIFFERENT face model, and a cosine
|
|
25655
25807
|
* across feature spaces is a well-formed float with no meaning. Every number
|
|
@@ -25718,15 +25870,15 @@ var FaceInfoSchema = object({
|
|
|
25718
25870
|
*/
|
|
25719
25871
|
cropUrl: string().optional(),
|
|
25720
25872
|
/** Design B: the face bbox (pixel space) on the key frame — lets a detail
|
|
25721
|
-
* view draw the box over the native `
|
|
25873
|
+
* view draw the box over the native `keyFrameMediaId` frame. Absent on
|
|
25722
25874
|
* legacy rows written before design B. */
|
|
25723
25875
|
faceBbox: BoundingBoxSchema.optional(),
|
|
25724
25876
|
/** Design B: MediaStore key of the track's native-resolution key frame.
|
|
25725
25877
|
* Fetch the native JPEG via the event-media data-plane
|
|
25726
|
-
* (`/addon/<addonId>/event-media/<
|
|
25878
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`). Absent when the
|
|
25727
25879
|
* track produced no key frame (e.g. native/onboard source) — the UI falls
|
|
25728
25880
|
* back to the inline `base64` face crop. */
|
|
25729
|
-
|
|
25881
|
+
keyFrameMediaId: number().int().optional(),
|
|
25730
25882
|
/** Winning identity-match cosine (0..1) for this face's track, when an
|
|
25731
25883
|
* identity was auto-confirmed. Lets the UI surface WHY a face was assigned
|
|
25732
25884
|
* (confidence badge / low-confidence audit). Absent on legacy rows and on
|
|
@@ -25795,11 +25947,14 @@ var FaceClusterSchema = object({
|
|
|
25795
25947
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
25796
25948
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
25797
25949
|
*
|
|
25798
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
25799
|
-
* media
|
|
25950
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
25951
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
25952
|
+
* access decision.
|
|
25800
25953
|
*/
|
|
25801
25954
|
var MediaFileLiteSchema$1 = object({
|
|
25802
|
-
|
|
25955
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
25956
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
25957
|
+
mediaId: number().int(),
|
|
25803
25958
|
kind: string(),
|
|
25804
25959
|
url: string(),
|
|
25805
25960
|
sizeBytes: number(),
|
|
@@ -25816,7 +25971,7 @@ method(object({
|
|
|
25816
25971
|
* covers inline, ~10 KB of base64 per row, on a query this UI mounts
|
|
25817
25972
|
* four times and the viewer holds at `staleTime: 30_000`.
|
|
25818
25973
|
*
|
|
25819
|
-
* Nothing loses its avatar: `
|
|
25974
|
+
* Nothing loses its avatar: `coverMediaId` is already on every row and
|
|
25820
25975
|
* the `event-media` plane serves that key `immutable` with an ETag.
|
|
25821
25976
|
*
|
|
25822
25977
|
* **This is an INPUT field, so it does not reach the addon until the
|
|
@@ -28300,8 +28455,8 @@ var VehicleSchema = object({
|
|
|
28300
28455
|
id: string(),
|
|
28301
28456
|
name: string(),
|
|
28302
28457
|
sampleCount: number().int().nonnegative(),
|
|
28303
|
-
|
|
28304
|
-
/** Inline base64 of the cover sample's plate crop, resolved from `
|
|
28458
|
+
coverMediaId: number().int().optional(),
|
|
28459
|
+
/** Inline base64 of the cover sample's plate crop, resolved from `coverMediaId`. */
|
|
28305
28460
|
coverBase64: string().optional()
|
|
28306
28461
|
});
|
|
28307
28462
|
var VehicleSampleInfoSchema = object({
|
|
@@ -28334,7 +28489,7 @@ var PlateInfoSchema = object({
|
|
|
28334
28489
|
/** keyFrame parity: the plate bbox (pixel space) on the native key frame. */
|
|
28335
28490
|
plateBbox: BoundingBoxSchema.optional(),
|
|
28336
28491
|
/** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
|
|
28337
|
-
|
|
28492
|
+
keyFrameMediaId: number().int().optional(),
|
|
28338
28493
|
base64: string().optional(),
|
|
28339
28494
|
/**
|
|
28340
28495
|
* Same crop as a data-plane URL, always present when the plate has a stored
|
|
@@ -28355,11 +28510,14 @@ var PlateInfoSchema = object({
|
|
|
28355
28510
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
28356
28511
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
28357
28512
|
*
|
|
28358
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
28359
|
-
* media
|
|
28513
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
28514
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
28515
|
+
* access decision.
|
|
28360
28516
|
*/
|
|
28361
28517
|
var MediaFileLiteSchema = object({
|
|
28362
|
-
|
|
28518
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
28519
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
28520
|
+
mediaId: number().int(),
|
|
28363
28521
|
kind: string(),
|
|
28364
28522
|
url: string(),
|
|
28365
28523
|
sizeBytes: number(),
|
|
@@ -28418,7 +28576,7 @@ method(object({
|
|
|
28418
28576
|
}), method(object({
|
|
28419
28577
|
/** Inline {@link VehicleSchema.coverBase64} on every row. Default
|
|
28420
28578
|
* `false` — the vehicle twin of `faceGallery.listIdentities`'s
|
|
28421
|
-
* option; `
|
|
28579
|
+
* option; `coverMediaId` + the `event-media` plane carry the picture.
|
|
28422
28580
|
* INPUT field: stripped by the hub router until the train ships, which
|
|
28423
28581
|
* resolves to `false` and is exactly the intended default. */
|
|
28424
28582
|
includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
|
|
@@ -29742,7 +29900,14 @@ var SceneReferenceSchema = object({
|
|
|
29742
29900
|
modelId: string(),
|
|
29743
29901
|
condition: SceneConditionSchema,
|
|
29744
29902
|
capturedAt: number(),
|
|
29745
|
-
|
|
29903
|
+
/**
|
|
29904
|
+
* The reference thumbnail's media ROW id (D482).
|
|
29905
|
+
*
|
|
29906
|
+
* The name already said `mediaId` while the value was the row's composite
|
|
29907
|
+
* key — a leftover that read as done and was not. It is the row's own id
|
|
29908
|
+
* now, addressed at `/addon/<addonId>/event-media/m/<id>`.
|
|
29909
|
+
*/
|
|
29910
|
+
thumbnailMediaId: number().int().optional(),
|
|
29746
29911
|
/** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
|
|
29747
29912
|
* anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
|
|
29748
29913
|
* normalized rect frame a different piece of world, and the scene would
|
|
@@ -30565,7 +30730,29 @@ var LoggingSettingsPatchSchema = object({
|
|
|
30565
30730
|
* disarmed the channels it did not mention would make the Levels page and
|
|
30566
30731
|
* the Diagnostics page fight over the same value.
|
|
30567
30732
|
*/
|
|
30568
|
-
channels: array(LogChannelWindowPatchSchema).readonly().optional()
|
|
30733
|
+
channels: array(LogChannelWindowPatchSchema).readonly().optional(),
|
|
30734
|
+
/**
|
|
30735
|
+
* How many days the analytics OPS LOG is kept — the audit trail of what
|
|
30736
|
+
* retention actually deleted.
|
|
30737
|
+
*
|
|
30738
|
+
* It lives HERE, on the logging document, and not on the analytics addon's
|
|
30739
|
+
* settings form, on the operator's instruction: every other log-ish window in
|
|
30740
|
+
* this system is configured through this one document, and a retention audit
|
|
30741
|
+
* configured somewhere else is a second place to look when the question is
|
|
30742
|
+
* "what happened to my data".
|
|
30743
|
+
*
|
|
30744
|
+
* That placement has a cost worth stating: this document ships in the
|
|
30745
|
+
* framework closure, so this knob needs a published `@camstack/server` while
|
|
30746
|
+
* the four windows beside it (D485) reach a node on `camstack deploy`.
|
|
30747
|
+
*
|
|
30748
|
+
* `retention-model.ts` argued this one must NOT follow a device window,
|
|
30749
|
+
* because the audit trail is the history of the SWEEP and not of the camera.
|
|
30750
|
+
* That argument stands and is untouched — what changes is that 30 days stops
|
|
30751
|
+
* being a constant nobody can reach. `0` keeps it forever. The floor is 1 day
|
|
30752
|
+
* rather than 0-as-delete: an audit log truncated to nothing is precisely the
|
|
30753
|
+
* state in which the next 9.5 GiB leak cannot be explained.
|
|
30754
|
+
*/
|
|
30755
|
+
opsLogRetentionDays: number().int().min(0).max(3650).optional()
|
|
30569
30756
|
});
|
|
30570
30757
|
/**
|
|
30571
30758
|
* Which LAYER of the hierarchy is addressed. Absent = the cluster layer.
|
|
@@ -30638,6 +30825,14 @@ var LoggingSettingsStateSchema = object({
|
|
|
30638
30825
|
channels: array(LogChannelDescriptorSchema).readonly(),
|
|
30639
30826
|
/** The channels ARMED right now, each with its deadline. */
|
|
30640
30827
|
activeChannels: array(LogChannelWindowStateSchema).readonly(),
|
|
30828
|
+
/**
|
|
30829
|
+
* The ops-log window in days, as it is in force. `0` = kept forever.
|
|
30830
|
+
*
|
|
30831
|
+
* Reported rather than left to the caller's memory of what it wrote: this is
|
|
30832
|
+
* the value the analytics sweep will actually use, and an operator asking how
|
|
30833
|
+
* long their audit trail lives should not have to infer it from a default.
|
|
30834
|
+
*/
|
|
30835
|
+
opsLogRetentionDays: number().int().min(0),
|
|
30641
30836
|
persisted: boolean()
|
|
30642
30837
|
});
|
|
30643
30838
|
method(_void(), FeatureManifestSchema), method(_void(), HealthStatusSchema), method(_void(), FeatureManifestSchema), method(_void(), array(NetworkAddressSchema).readonly()), method(_void(), unknown().nullable(), { auth: "admin" }), method(record(string(), unknown()), _null(), {
|
|
@@ -31215,7 +31410,7 @@ var StationaryObjectSchema = object({
|
|
|
31215
31410
|
/** Enrichment label carried from the source track (identity / plate). */
|
|
31216
31411
|
label: string().optional(),
|
|
31217
31412
|
/** Native-resolution key-frame media key for the parked object's best image. */
|
|
31218
|
-
|
|
31413
|
+
keyFrameMediaId: number().int().optional()
|
|
31219
31414
|
});
|
|
31220
31415
|
var CameraOccupancySnapshotSchema = object({
|
|
31221
31416
|
/** Frame timestamp of the inference result that produced this snapshot. */
|
|
@@ -32371,6 +32566,12 @@ Object.freeze({
|
|
|
32371
32566
|
addonId: null,
|
|
32372
32567
|
access: "create"
|
|
32373
32568
|
},
|
|
32569
|
+
"dataStoreProvider.upsert": {
|
|
32570
|
+
capName: "data-store-provider",
|
|
32571
|
+
capScope: "system",
|
|
32572
|
+
addonId: null,
|
|
32573
|
+
access: "create"
|
|
32574
|
+
},
|
|
32374
32575
|
"dayNight.getOptions": {
|
|
32375
32576
|
capName: "day-night",
|
|
32376
32577
|
capScope: "device",
|
|
@@ -34807,6 +35008,12 @@ Object.freeze({
|
|
|
34807
35008
|
addonId: null,
|
|
34808
35009
|
access: "view"
|
|
34809
35010
|
},
|
|
35011
|
+
"pipelineAnalytics.listRecentSummaries": {
|
|
35012
|
+
capName: "pipeline-analytics",
|
|
35013
|
+
capScope: "device",
|
|
35014
|
+
addonId: null,
|
|
35015
|
+
access: "view"
|
|
35016
|
+
},
|
|
34810
35017
|
"pipelineAnalytics.listRecentTracks": {
|
|
34811
35018
|
capName: "pipeline-analytics",
|
|
34812
35019
|
capScope: "device",
|
|
@@ -36235,6 +36442,12 @@ Object.freeze({
|
|
|
36235
36442
|
addonId: null,
|
|
36236
36443
|
access: "create"
|
|
36237
36444
|
},
|
|
36445
|
+
"settingsStore.upsert": {
|
|
36446
|
+
capName: "settings-store",
|
|
36447
|
+
capScope: "system",
|
|
36448
|
+
addonId: null,
|
|
36449
|
+
access: "create"
|
|
36450
|
+
},
|
|
36238
36451
|
"smtpProvider.getStatus": {
|
|
36239
36452
|
capName: "smtp-provider",
|
|
36240
36453
|
capScope: "system",
|
|
@@ -38628,6 +38841,11 @@ Object.freeze({
|
|
|
38628
38841
|
form: "single",
|
|
38629
38842
|
optional: true
|
|
38630
38843
|
}],
|
|
38844
|
+
"pipelineAnalytics.listRecentSummaries": [{
|
|
38845
|
+
name: "deviceIds",
|
|
38846
|
+
form: "array",
|
|
38847
|
+
optional: false
|
|
38848
|
+
}],
|
|
38631
38849
|
"pipelineAnalytics.listRecentTracks": [{
|
|
38632
38850
|
name: "deviceIds",
|
|
38633
38851
|
form: "array",
|
|
@@ -72,7 +72,7 @@ function carryForward(base, existing, keys) {
|
|
|
72
72
|
return out;
|
|
73
73
|
}
|
|
74
74
|
//#endregion
|
|
75
|
-
//#region ../types/dist/event-category-
|
|
75
|
+
//#region ../types/dist/event-category-ZyX6jcse.mjs
|
|
76
76
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
77
77
|
EventCategory["SystemBoot"] = "system.boot";
|
|
78
78
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -633,7 +633,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
633
633
|
* a package zone — a newly-appeared stationary object of a package class
|
|
634
634
|
* that cleared the class / zone / dwell / size gates. Payload:
|
|
635
635
|
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
636
|
-
* entryId, className, zoneIds,
|
|
636
|
+
* entryId, className, zoneIds, keyFrameMediaId?, bbox, timestamp }`.
|
|
637
637
|
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
638
638
|
* this bus topic drives notifier rules + live UI. See
|
|
639
639
|
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
@@ -5419,7 +5419,7 @@ var ZodIssueCode = {
|
|
|
5419
5419
|
var ZodFirstPartyTypeKind;
|
|
5420
5420
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5421
5421
|
//#endregion
|
|
5422
|
-
//#region ../types/dist/sleep-
|
|
5422
|
+
//#region ../types/dist/sleep-DBKu2-U5.mjs
|
|
5423
5423
|
/**
|
|
5424
5424
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5425
5425
|
* window to float samples (D455).
|
|
@@ -7939,13 +7939,30 @@ new Set([
|
|
|
7939
7939
|
"scene",
|
|
7940
7940
|
"motion",
|
|
7941
7941
|
"object",
|
|
7942
|
-
"audio"
|
|
7942
|
+
"audio",
|
|
7943
|
+
"mosaic"
|
|
7943
7944
|
]);
|
|
7944
|
-
|
|
7945
|
+
/**
|
|
7946
|
+
* The owner types that are event tables, in the order the event-media resolver
|
|
7947
|
+
* should consider them. Exported so a consumer asking "is this key an event?"
|
|
7948
|
+
* does not re-spell the list and drift from it.
|
|
7949
|
+
*/
|
|
7950
|
+
var EVENT_OWNER_TYPES = [
|
|
7945
7951
|
"motion",
|
|
7946
7952
|
"object",
|
|
7947
7953
|
"audio"
|
|
7948
|
-
]
|
|
7954
|
+
];
|
|
7955
|
+
/**
|
|
7956
|
+
* The same list as a Zod enum, for the cap inputs that must NAME the table
|
|
7957
|
+
* (D482: `getEventMedia` / `listEventMedia` take an owner, and an owner is
|
|
7958
|
+
* `(table, id)`).
|
|
7959
|
+
*
|
|
7960
|
+
* Built FROM {@link EVENT_OWNER_TYPES} rather than re-spelled: a fourth event
|
|
7961
|
+
* table would otherwise be accepted by the codec and refused at the door, with
|
|
7962
|
+
* nothing failing until a caller asked.
|
|
7963
|
+
*/
|
|
7964
|
+
var EventOwnerTypeSchema = _enum(EVENT_OWNER_TYPES);
|
|
7965
|
+
new Set(EVENT_OWNER_TYPES);
|
|
7949
7966
|
var EncodeProfileSchema = object({
|
|
7950
7967
|
video: object({
|
|
7951
7968
|
codec: _enum([
|
|
@@ -13124,6 +13141,16 @@ method(object({
|
|
|
13124
13141
|
filter: QueryFilterSchema.optional(),
|
|
13125
13142
|
columns: array(string()).readonly().optional()
|
|
13126
13143
|
}), array(SettingsRecordSchema).readonly()), method(object({
|
|
13144
|
+
namespace: string().optional(),
|
|
13145
|
+
collection: string(),
|
|
13146
|
+
/** Declared columns identifying the slot; must be covered by a UNIQUE
|
|
13147
|
+
* index on the collection. Never empty. */
|
|
13148
|
+
conflict: array(string()).readonly(),
|
|
13149
|
+
record: BulkRecordSchema
|
|
13150
|
+
}), object({
|
|
13151
|
+
/** The id the row HAS: assigned by SQLite on an insert, or the existing
|
|
13152
|
+
* row's own id on an update. */
|
|
13153
|
+
id: union([string(), number()]) }), { kind: "mutation" }), method(object({
|
|
13127
13154
|
namespace: string().optional(),
|
|
13128
13155
|
collection: string(),
|
|
13129
13156
|
record: object({
|
|
@@ -13258,6 +13285,14 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
|
|
|
13258
13285
|
id: union([string(), number()]) }), {
|
|
13259
13286
|
kind: "mutation",
|
|
13260
13287
|
auth: "admin"
|
|
13288
|
+
}), method(object({
|
|
13289
|
+
namespace: string().optional(),
|
|
13290
|
+
collection: string(),
|
|
13291
|
+
conflict: array(string()).readonly(),
|
|
13292
|
+
record: BulkRecordSchema
|
|
13293
|
+
}), object({ id: union([string(), number()]) }), {
|
|
13294
|
+
kind: "mutation",
|
|
13295
|
+
auth: "admin"
|
|
13261
13296
|
}), method(object({
|
|
13262
13297
|
namespace: string().optional(),
|
|
13263
13298
|
collection: string(),
|
|
@@ -19555,8 +19590,8 @@ var TrackPositionSchema = object({
|
|
|
19555
19590
|
var TrackSnapshotSchema = object({
|
|
19556
19591
|
timestamp: number(),
|
|
19557
19592
|
position: TrackPositionSchema,
|
|
19558
|
-
/**
|
|
19559
|
-
|
|
19593
|
+
/** The snapshot's media row id (D482); resolve via `listTrackMedia({ trackId })`. */
|
|
19594
|
+
mediaId: number().int()
|
|
19560
19595
|
});
|
|
19561
19596
|
/**
|
|
19562
19597
|
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
@@ -20160,14 +20195,14 @@ var ObjectEventSchema = object({
|
|
|
20160
20195
|
* pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
|
|
20161
20196
|
frameWidth: number().optional(),
|
|
20162
20197
|
frameHeight: number().optional(),
|
|
20163
|
-
/**
|
|
20164
|
-
|
|
20165
|
-
/** Design B:
|
|
20198
|
+
/** Media row id of the crop attached to this event (if any) — D482. */
|
|
20199
|
+
mediaId: number().int().optional(),
|
|
20200
|
+
/** Design B: media row id of the track's native-resolution key frame (the
|
|
20166
20201
|
* best-detection full frame). Resolve via the event-media data-plane
|
|
20167
|
-
* (`/addon/<addonId>/event-media/<
|
|
20202
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`) for a detail view that
|
|
20168
20203
|
* draws `bbox` over the native frame. Absent on legacy rows / non-decoded
|
|
20169
|
-
* sources — consumers fall back to `
|
|
20170
|
-
|
|
20204
|
+
* sources — consumers fall back to `mediaId` (the tight crop). */
|
|
20205
|
+
keyFrameMediaId: number().int().optional(),
|
|
20171
20206
|
/** Populated by B5 (recording playback URL for this event). */
|
|
20172
20207
|
mediaUrl: string().optional(),
|
|
20173
20208
|
/** The parent track's key-event importance [0,1], propagated to every object
|
|
@@ -20217,7 +20252,7 @@ var MediaFileKindEnum = _enum([
|
|
|
20217
20252
|
* hub-main's heap on the way past — for an `<img>` that would have cached it.
|
|
20218
20253
|
*
|
|
20219
20254
|
* `url` points at the `event-media` data plane
|
|
20220
|
-
* (`/addon/<addonId>/event-media/<
|
|
20255
|
+
* (`/addon/<addonId>/event-media/m/<mediaId>` — D482), which serves the same blob
|
|
20221
20256
|
* with an ETag and `Cache-Control: immutable`, honours conditional GETs, can
|
|
20222
20257
|
* render a `?variant=thumb`, and streams. The hub gate in front of it requires
|
|
20223
20258
|
* a bearer or the session cookie (`access: 'authenticated'`), so the bytes are
|
|
@@ -20225,10 +20260,13 @@ var MediaFileKindEnum = _enum([
|
|
|
20225
20260
|
* `data-plane-access.ts` for the rule and the one gap it does not close
|
|
20226
20261
|
* (per-device scoping).
|
|
20227
20262
|
*
|
|
20228
|
-
* The URL is built from the row's
|
|
20229
|
-
*
|
|
20263
|
+
* The URL is built from the row's own id, which since D482 says nothing about
|
|
20264
|
+
* the row's owner or kind — and that is the point. The published `kind` is not
|
|
20265
|
+
* the stored one (a track's face/plate crop is stored as `crop` under
|
|
20230
20266
|
* `('face'|'plate', '<prefix>-<trackId>')` and published as
|
|
20231
|
-
* `faceCrop`/`plateCrop
|
|
20267
|
+
* `faceCrop`/`plateCrop`), and under the old composite key the URL had to be
|
|
20268
|
+
* taken from `row.key` verbatim or it 404'd exactly those two rows. An id
|
|
20269
|
+
* cannot be mis-reconstructed, because there is nothing in it to reconstruct.
|
|
20232
20270
|
*
|
|
20233
20271
|
* ## `base64` is TRANSITIONAL and is going away
|
|
20234
20272
|
*
|
|
@@ -20241,7 +20279,19 @@ var MediaFileKindEnum = _enum([
|
|
|
20241
20279
|
* `analytics-query-facade.ts`; nothing else reads it.
|
|
20242
20280
|
*/
|
|
20243
20281
|
var MediaFileSchema = object({
|
|
20244
|
-
|
|
20282
|
+
/**
|
|
20283
|
+
* The media row's OWN id — the rowid SQLite assigned it (D482).
|
|
20284
|
+
*
|
|
20285
|
+
* It used to be the row's composite key, `<ownerType>:<ownerId>:<fileKind>
|
|
20286
|
+
* [:<timestampMs>]`, which embedded a FOREIGN id. D474 made event ids
|
|
20287
|
+
* per-table rowid aliases, so `object:101314` and `motion:101314` are two
|
|
20288
|
+
* different rows that spell the same number, and a track whose
|
|
20289
|
+
* `bestEventId` was an object event was served a motion event's snapshot —
|
|
20290
|
+
* a night-time thumbnail on an afternoon track, with no error anywhere. A
|
|
20291
|
+
* surrogate id cannot name the wrong row's owner, because it names no owner
|
|
20292
|
+
* at all.
|
|
20293
|
+
*/
|
|
20294
|
+
mediaId: number().int(),
|
|
20245
20295
|
kind: MediaFileKindEnum,
|
|
20246
20296
|
sizeBytes: number(),
|
|
20247
20297
|
timestamp: number()
|
|
@@ -20349,7 +20399,7 @@ var RetrainTrackSchema = object({
|
|
|
20349
20399
|
});
|
|
20350
20400
|
/** A frame the picker may offer — an index row, no blob was read to produce it. */
|
|
20351
20401
|
var RetrainFrameCandidateSchema = object({
|
|
20352
|
-
|
|
20402
|
+
mediaId: number().int(),
|
|
20353
20403
|
kind: MediaFileKindEnum,
|
|
20354
20404
|
timestamp: number(),
|
|
20355
20405
|
sizeBytes: number().int(),
|
|
@@ -20363,7 +20413,7 @@ var RetrainFrameSchema = object({
|
|
|
20363
20413
|
deviceId: number(),
|
|
20364
20414
|
trackId: string(),
|
|
20365
20415
|
/** Provenance only. It may already point at nothing — that is expected. */
|
|
20366
|
-
|
|
20416
|
+
sourceMediaId: number().int(),
|
|
20367
20417
|
sourceKind: MediaFileKindEnum,
|
|
20368
20418
|
sizeBytes: number().int(),
|
|
20369
20419
|
width: number().int(),
|
|
@@ -20379,7 +20429,7 @@ var RetrainCopyRefusalSchema = _enum([
|
|
|
20379
20429
|
var RetrainFrameSelectionSchema = object({
|
|
20380
20430
|
copied: array(RetrainFrameSchema).readonly(),
|
|
20381
20431
|
refused: array(object({
|
|
20382
|
-
|
|
20432
|
+
sourceMediaId: number().int(),
|
|
20383
20433
|
reason: RetrainCopyRefusalSchema
|
|
20384
20434
|
})).readonly()
|
|
20385
20435
|
});
|
|
@@ -20387,7 +20437,7 @@ var RetrainFrameListSchema = object({
|
|
|
20387
20437
|
candidates: array(RetrainFrameCandidateSchema).readonly(),
|
|
20388
20438
|
copies: array(RetrainFrameSchema).readonly(),
|
|
20389
20439
|
/** What the page pre-selects — the native key frame when one survives. */
|
|
20390
|
-
|
|
20440
|
+
autoPickMediaId: number().int().optional()
|
|
20391
20441
|
});
|
|
20392
20442
|
/** What the operator asked the assist to look for. */
|
|
20393
20443
|
var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
|
|
@@ -20482,9 +20532,11 @@ var RecentTracksQueryInput = object({
|
|
|
20482
20532
|
});
|
|
20483
20533
|
/**
|
|
20484
20534
|
* A Summary (D359): the per-camera session envelope that references tracks.
|
|
20485
|
-
* `
|
|
20486
|
-
* served by the event-media plane
|
|
20487
|
-
* member visible has been materialised
|
|
20535
|
+
* `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
|
|
20536
|
+
* 'summary'`, served by the event-media plane at `/m/<id>`), null until the
|
|
20537
|
+
* first frame with a member visible has been materialised (D482 — it was the
|
|
20538
|
+
* row's composite key, which embedded the owner and could name another table's
|
|
20539
|
+
* row once event ids became per-table rowids).
|
|
20488
20540
|
*/
|
|
20489
20541
|
var SummarySchema = object({
|
|
20490
20542
|
id: string(),
|
|
@@ -20493,19 +20545,115 @@ var SummarySchema = object({
|
|
|
20493
20545
|
lastActiveAt: number(),
|
|
20494
20546
|
sealedAt: number().nullable(),
|
|
20495
20547
|
memberCount: number().int().nonnegative(),
|
|
20496
|
-
|
|
20548
|
+
groupShotMediaId: number().int().nullable()
|
|
20497
20549
|
});
|
|
20498
20550
|
var SummariesQueryInput = object({
|
|
20499
20551
|
deviceIds: array(number()).min(1),
|
|
20500
20552
|
since: number().optional(),
|
|
20501
20553
|
until: number().optional(),
|
|
20502
|
-
limit: number().int().min(1).max(200).default(50)
|
|
20554
|
+
limit: number().int().min(1).max(200).default(50),
|
|
20555
|
+
/** The same member-wise filter {@link listRecentSummaries} takes — one
|
|
20556
|
+
* meaning of "dog" on every summary surface. */
|
|
20557
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
20503
20558
|
});
|
|
20504
|
-
var SummariesPageSchema = object({ summaries: array(SummarySchema).readonly() });
|
|
20505
20559
|
var SummaryDetailSchema = object({
|
|
20506
20560
|
summary: SummarySchema,
|
|
20507
|
-
/**
|
|
20508
|
-
|
|
20561
|
+
/** Members in absorption order, oldest join first. */
|
|
20562
|
+
members: array(object({
|
|
20563
|
+
trackId: string(),
|
|
20564
|
+
/**
|
|
20565
|
+
* The track's class at the time it JOINED, or `null` when it was unresolved
|
|
20566
|
+
* and the track no longer exists to fill it.
|
|
20567
|
+
*
|
|
20568
|
+
* The join, not the latest opinion: class voting can re-decide a track's
|
|
20569
|
+
* class afterwards, and a group's composition is the history of who came
|
|
20570
|
+
* together. A consumer counts these to badge a thumbnail — "two people and a
|
|
20571
|
+
* dog" — rather than being handed a second, denormalised tally that would
|
|
20572
|
+
* drift from the members it claims to describe.
|
|
20573
|
+
*/
|
|
20574
|
+
className: string().nullable(),
|
|
20575
|
+
/** `primary` is the one member that carries the group's identity. */
|
|
20576
|
+
role: _enum([
|
|
20577
|
+
"primary",
|
|
20578
|
+
"sibling",
|
|
20579
|
+
"child"
|
|
20580
|
+
]).nullable(),
|
|
20581
|
+
joinedAt: number(),
|
|
20582
|
+
/** Tier 1 — the sub-class (`dog`, `van`), resolved from the member's track
|
|
20583
|
+
* at read time. Absent when nothing resolved, never an empty string. */
|
|
20584
|
+
label: string().optional(),
|
|
20585
|
+
/** Tier 2 — the instance: a person's name, a plate. Absent when the pipeline
|
|
20586
|
+
* recognised nobody, and absent for a member whose track has been pruned —
|
|
20587
|
+
* a thumbnail that names the wrong person is worse than one naming nobody. */
|
|
20588
|
+
subLabel: string().optional()
|
|
20589
|
+
})).readonly()
|
|
20590
|
+
});
|
|
20591
|
+
/**
|
|
20592
|
+
* What a LIST of groups carries: the envelope plus what it is MADE OF.
|
|
20593
|
+
*
|
|
20594
|
+
* Coarse on purpose — the operator's rule is "only the rough data on the list,
|
|
20595
|
+
* we extend when we notice we need more". Enough to draw the card ("two people
|
|
20596
|
+
* and a dog") and no more. The MEMBERS, their names and the per-member links
|
|
20597
|
+
* are on {@link getSummary}: shipping every member of every group so a client
|
|
20598
|
+
* can count them turns a page of two hundred groups into a thousand records to
|
|
20599
|
+
* draw two hundred badges.
|
|
20600
|
+
*/
|
|
20601
|
+
var SummaryListItemSchema = object({
|
|
20602
|
+
summary: SummarySchema,
|
|
20603
|
+
/** Class counts, most numerous first; `className: null` is a member whose
|
|
20604
|
+
* class never resolved, counted so the counts add up to `memberCount`. */
|
|
20605
|
+
classes: array(object({
|
|
20606
|
+
className: string().nullable(),
|
|
20607
|
+
count: number().int().positive()
|
|
20608
|
+
})).readonly()
|
|
20609
|
+
});
|
|
20610
|
+
var SummariesPageSchema = object({ summaries: array(SummaryListItemSchema).readonly() });
|
|
20611
|
+
/**
|
|
20612
|
+
* The paged feed, deliberately the SAME shape as {@link RecentTracksQueryInput}.
|
|
20613
|
+
*
|
|
20614
|
+
* The reel on the cameras page and the Events gallery both ride a cursor, so a
|
|
20615
|
+
* summaries feed that could only answer "the last N for these cameras"
|
|
20616
|
+
* (`listSummaries`) would make groups available in the timeline and nowhere
|
|
20617
|
+
* else. Two feeds with different ordering contracts would be two ideas of what
|
|
20618
|
+
* "newest" means, on one screen.
|
|
20619
|
+
*/
|
|
20620
|
+
var RecentSummariesQueryInput = object({
|
|
20621
|
+
/** Devices to merge. An empty array yields an empty page. */
|
|
20622
|
+
deviceIds: array(number()),
|
|
20623
|
+
/** Window lower bound on `lastActiveAt` (inclusive). */
|
|
20624
|
+
since: number().optional(),
|
|
20625
|
+
/** Window upper bound on `lastActiveAt` (inclusive). */
|
|
20626
|
+
until: number().optional(),
|
|
20627
|
+
limit: number().int().min(1).max(500).default(100),
|
|
20628
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`. */
|
|
20629
|
+
cursor: string().optional(),
|
|
20630
|
+
/**
|
|
20631
|
+
* Restrict to these classes — THE SAME FIELD `listRecentTracks` takes, and
|
|
20632
|
+
* deliberately the same name: the events filter tree emits one list of ticked
|
|
20633
|
+
* taxonomy nodes, and a summaries feed that called it something else would
|
|
20634
|
+
* make the operator's one filter component produce two shapes.
|
|
20635
|
+
*
|
|
20636
|
+
* A question about the MEMBERS: a group matches when ANY of them does. "Show
|
|
20637
|
+
* me the arrivals with a dog" has to return the group of four people who had
|
|
20638
|
+
* one with them; a filter on the group's own fields could only ever answer
|
|
20639
|
+
* about its primary.
|
|
20640
|
+
*
|
|
20641
|
+
* Matched against all THREE tiers of a member — the class (`animal`), the
|
|
20642
|
+
* sub-class (`dog`) and the instance (a name, a plate) — because which tier a
|
|
20643
|
+
* ticked node lives on is the taxonomy's business, not the caller's. `dog` is
|
|
20644
|
+
* an event kind in the tree and a tier-1 label on an `animal` track; a filter
|
|
20645
|
+
* that read only the class would answer "animal" and never "dog".
|
|
20646
|
+
*
|
|
20647
|
+
* ABSENT or EMPTY means no filter — absent is not a selection of none.
|
|
20648
|
+
*/
|
|
20649
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
20650
|
+
});
|
|
20651
|
+
var RecentSummariesPageSchema = object({
|
|
20652
|
+
/** Ordered by (`lastActiveAt` DESC, id DESC). Same light item as
|
|
20653
|
+
* {@link listSummaries} — one list shape, so a card renders the same
|
|
20654
|
+
* whichever feed drew it. */
|
|
20655
|
+
summaries: array(SummaryListItemSchema).readonly(),
|
|
20656
|
+
nextCursor: string().nullable()
|
|
20509
20657
|
});
|
|
20510
20658
|
var RecentTracksPageSchema = object({
|
|
20511
20659
|
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
@@ -20919,7 +21067,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20919
21067
|
classes: array(string()).optional(),
|
|
20920
21068
|
/** See {@link ExcludeSourcesDoc}. */
|
|
20921
21069
|
excludeSources: array(TrackSourceSchema).optional()
|
|
20922
|
-
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
21070
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(RecentSummariesQueryInput, RecentSummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
20923
21071
|
kind: "mutation",
|
|
20924
21072
|
auth: "admin"
|
|
20925
21073
|
}), 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({
|
|
@@ -21047,7 +21195,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
21047
21195
|
}), method(object({
|
|
21048
21196
|
deviceId: number(),
|
|
21049
21197
|
trackId: string(),
|
|
21050
|
-
|
|
21198
|
+
mediaIds: array(number().int()).min(1)
|
|
21051
21199
|
}), RetrainFrameSelectionSchema, {
|
|
21052
21200
|
kind: "mutation",
|
|
21053
21201
|
auth: "admin"
|
|
@@ -21115,7 +21263,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
21115
21263
|
kind: "query",
|
|
21116
21264
|
auth: "admin"
|
|
21117
21265
|
}), method(object({
|
|
21118
|
-
|
|
21266
|
+
/** Which of the three event tables owns the row. */
|
|
21267
|
+
ownerType: EventOwnerTypeSchema,
|
|
21268
|
+
/** The event's rowid in that table (D474: an event id is a number). */
|
|
21269
|
+
eventId: number().int(),
|
|
21119
21270
|
kind: MediaFileKindEnum.optional(),
|
|
21120
21271
|
deviceId: number()
|
|
21121
21272
|
}), array(MediaFileSchema).readonly()), method(object({
|
|
@@ -21126,7 +21277,8 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
21126
21277
|
trackId: string(),
|
|
21127
21278
|
deviceId: number()
|
|
21128
21279
|
}), array(MediaFileInfoSchema).readonly()), method(object({
|
|
21129
|
-
|
|
21280
|
+
ownerType: EventOwnerTypeSchema,
|
|
21281
|
+
eventId: number().int(),
|
|
21130
21282
|
deviceId: number()
|
|
21131
21283
|
}), array(MediaFileInfoSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
|
|
21132
21284
|
kind: "mutation",
|
|
@@ -25609,8 +25761,8 @@ var IdentitySchema = object({
|
|
|
25609
25761
|
id: string(),
|
|
25610
25762
|
name: string(),
|
|
25611
25763
|
sampleCount: number().int().nonnegative(),
|
|
25612
|
-
|
|
25613
|
-
/** Inline base64 of the cover sample's crop, resolved from `
|
|
25764
|
+
coverMediaId: number().int().optional(),
|
|
25765
|
+
/** Inline base64 of the cover sample's crop, resolved from `coverMediaId`.
|
|
25614
25766
|
* Lets the UI render the person's face avatar instead of a placeholder icon. */
|
|
25615
25767
|
coverBase64: string().optional()
|
|
25616
25768
|
});
|
|
@@ -25636,8 +25788,8 @@ var IdentitySampleAuditRowSchema = object({
|
|
|
25636
25788
|
enrolledAt: number().int(),
|
|
25637
25789
|
deviceId: number().int().optional(),
|
|
25638
25790
|
source: _enum(["detected", "photo"]),
|
|
25639
|
-
/** The enrolled crop's media
|
|
25640
|
-
|
|
25791
|
+
/** The enrolled crop's media row id, so the panel can show the evidence. */
|
|
25792
|
+
mediaId: number().int().optional(),
|
|
25641
25793
|
/**
|
|
25642
25794
|
* False = the sample is stamped with a DIFFERENT face model, and a cosine
|
|
25643
25795
|
* across feature spaces is a well-formed float with no meaning. Every number
|
|
@@ -25706,15 +25858,15 @@ var FaceInfoSchema = object({
|
|
|
25706
25858
|
*/
|
|
25707
25859
|
cropUrl: string().optional(),
|
|
25708
25860
|
/** Design B: the face bbox (pixel space) on the key frame — lets a detail
|
|
25709
|
-
* view draw the box over the native `
|
|
25861
|
+
* view draw the box over the native `keyFrameMediaId` frame. Absent on
|
|
25710
25862
|
* legacy rows written before design B. */
|
|
25711
25863
|
faceBbox: BoundingBoxSchema.optional(),
|
|
25712
25864
|
/** Design B: MediaStore key of the track's native-resolution key frame.
|
|
25713
25865
|
* Fetch the native JPEG via the event-media data-plane
|
|
25714
|
-
* (`/addon/<addonId>/event-media/<
|
|
25866
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`). Absent when the
|
|
25715
25867
|
* track produced no key frame (e.g. native/onboard source) — the UI falls
|
|
25716
25868
|
* back to the inline `base64` face crop. */
|
|
25717
|
-
|
|
25869
|
+
keyFrameMediaId: number().int().optional(),
|
|
25718
25870
|
/** Winning identity-match cosine (0..1) for this face's track, when an
|
|
25719
25871
|
* identity was auto-confirmed. Lets the UI surface WHY a face was assigned
|
|
25720
25872
|
* (confidence badge / low-confidence audit). Absent on legacy rows and on
|
|
@@ -25783,11 +25935,14 @@ var FaceClusterSchema = object({
|
|
|
25783
25935
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
25784
25936
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
25785
25937
|
*
|
|
25786
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
25787
|
-
* media
|
|
25938
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
25939
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
25940
|
+
* access decision.
|
|
25788
25941
|
*/
|
|
25789
25942
|
var MediaFileLiteSchema$1 = object({
|
|
25790
|
-
|
|
25943
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
25944
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
25945
|
+
mediaId: number().int(),
|
|
25791
25946
|
kind: string(),
|
|
25792
25947
|
url: string(),
|
|
25793
25948
|
sizeBytes: number(),
|
|
@@ -25804,7 +25959,7 @@ method(object({
|
|
|
25804
25959
|
* covers inline, ~10 KB of base64 per row, on a query this UI mounts
|
|
25805
25960
|
* four times and the viewer holds at `staleTime: 30_000`.
|
|
25806
25961
|
*
|
|
25807
|
-
* Nothing loses its avatar: `
|
|
25962
|
+
* Nothing loses its avatar: `coverMediaId` is already on every row and
|
|
25808
25963
|
* the `event-media` plane serves that key `immutable` with an ETag.
|
|
25809
25964
|
*
|
|
25810
25965
|
* **This is an INPUT field, so it does not reach the addon until the
|
|
@@ -28288,8 +28443,8 @@ var VehicleSchema = object({
|
|
|
28288
28443
|
id: string(),
|
|
28289
28444
|
name: string(),
|
|
28290
28445
|
sampleCount: number().int().nonnegative(),
|
|
28291
|
-
|
|
28292
|
-
/** Inline base64 of the cover sample's plate crop, resolved from `
|
|
28446
|
+
coverMediaId: number().int().optional(),
|
|
28447
|
+
/** Inline base64 of the cover sample's plate crop, resolved from `coverMediaId`. */
|
|
28293
28448
|
coverBase64: string().optional()
|
|
28294
28449
|
});
|
|
28295
28450
|
var VehicleSampleInfoSchema = object({
|
|
@@ -28322,7 +28477,7 @@ var PlateInfoSchema = object({
|
|
|
28322
28477
|
/** keyFrame parity: the plate bbox (pixel space) on the native key frame. */
|
|
28323
28478
|
plateBbox: BoundingBoxSchema.optional(),
|
|
28324
28479
|
/** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
|
|
28325
|
-
|
|
28480
|
+
keyFrameMediaId: number().int().optional(),
|
|
28326
28481
|
base64: string().optional(),
|
|
28327
28482
|
/**
|
|
28328
28483
|
* Same crop as a data-plane URL, always present when the plate has a stored
|
|
@@ -28343,11 +28498,14 @@ var PlateInfoSchema = object({
|
|
|
28343
28498
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
28344
28499
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
28345
28500
|
*
|
|
28346
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
28347
|
-
* media
|
|
28501
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
28502
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
28503
|
+
* access decision.
|
|
28348
28504
|
*/
|
|
28349
28505
|
var MediaFileLiteSchema = object({
|
|
28350
|
-
|
|
28506
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
28507
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
28508
|
+
mediaId: number().int(),
|
|
28351
28509
|
kind: string(),
|
|
28352
28510
|
url: string(),
|
|
28353
28511
|
sizeBytes: number(),
|
|
@@ -28406,7 +28564,7 @@ method(object({
|
|
|
28406
28564
|
}), method(object({
|
|
28407
28565
|
/** Inline {@link VehicleSchema.coverBase64} on every row. Default
|
|
28408
28566
|
* `false` — the vehicle twin of `faceGallery.listIdentities`'s
|
|
28409
|
-
* option; `
|
|
28567
|
+
* option; `coverMediaId` + the `event-media` plane carry the picture.
|
|
28410
28568
|
* INPUT field: stripped by the hub router until the train ships, which
|
|
28411
28569
|
* resolves to `false` and is exactly the intended default. */
|
|
28412
28570
|
includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
|
|
@@ -29730,7 +29888,14 @@ var SceneReferenceSchema = object({
|
|
|
29730
29888
|
modelId: string(),
|
|
29731
29889
|
condition: SceneConditionSchema,
|
|
29732
29890
|
capturedAt: number(),
|
|
29733
|
-
|
|
29891
|
+
/**
|
|
29892
|
+
* The reference thumbnail's media ROW id (D482).
|
|
29893
|
+
*
|
|
29894
|
+
* The name already said `mediaId` while the value was the row's composite
|
|
29895
|
+
* key — a leftover that read as done and was not. It is the row's own id
|
|
29896
|
+
* now, addressed at `/addon/<addonId>/event-media/m/<id>`.
|
|
29897
|
+
*/
|
|
29898
|
+
thumbnailMediaId: number().int().optional(),
|
|
29734
29899
|
/** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
|
|
29735
29900
|
* anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
|
|
29736
29901
|
* normalized rect frame a different piece of world, and the scene would
|
|
@@ -30553,7 +30718,29 @@ var LoggingSettingsPatchSchema = object({
|
|
|
30553
30718
|
* disarmed the channels it did not mention would make the Levels page and
|
|
30554
30719
|
* the Diagnostics page fight over the same value.
|
|
30555
30720
|
*/
|
|
30556
|
-
channels: array(LogChannelWindowPatchSchema).readonly().optional()
|
|
30721
|
+
channels: array(LogChannelWindowPatchSchema).readonly().optional(),
|
|
30722
|
+
/**
|
|
30723
|
+
* How many days the analytics OPS LOG is kept — the audit trail of what
|
|
30724
|
+
* retention actually deleted.
|
|
30725
|
+
*
|
|
30726
|
+
* It lives HERE, on the logging document, and not on the analytics addon's
|
|
30727
|
+
* settings form, on the operator's instruction: every other log-ish window in
|
|
30728
|
+
* this system is configured through this one document, and a retention audit
|
|
30729
|
+
* configured somewhere else is a second place to look when the question is
|
|
30730
|
+
* "what happened to my data".
|
|
30731
|
+
*
|
|
30732
|
+
* That placement has a cost worth stating: this document ships in the
|
|
30733
|
+
* framework closure, so this knob needs a published `@camstack/server` while
|
|
30734
|
+
* the four windows beside it (D485) reach a node on `camstack deploy`.
|
|
30735
|
+
*
|
|
30736
|
+
* `retention-model.ts` argued this one must NOT follow a device window,
|
|
30737
|
+
* because the audit trail is the history of the SWEEP and not of the camera.
|
|
30738
|
+
* That argument stands and is untouched — what changes is that 30 days stops
|
|
30739
|
+
* being a constant nobody can reach. `0` keeps it forever. The floor is 1 day
|
|
30740
|
+
* rather than 0-as-delete: an audit log truncated to nothing is precisely the
|
|
30741
|
+
* state in which the next 9.5 GiB leak cannot be explained.
|
|
30742
|
+
*/
|
|
30743
|
+
opsLogRetentionDays: number().int().min(0).max(3650).optional()
|
|
30557
30744
|
});
|
|
30558
30745
|
/**
|
|
30559
30746
|
* Which LAYER of the hierarchy is addressed. Absent = the cluster layer.
|
|
@@ -30626,6 +30813,14 @@ var LoggingSettingsStateSchema = object({
|
|
|
30626
30813
|
channels: array(LogChannelDescriptorSchema).readonly(),
|
|
30627
30814
|
/** The channels ARMED right now, each with its deadline. */
|
|
30628
30815
|
activeChannels: array(LogChannelWindowStateSchema).readonly(),
|
|
30816
|
+
/**
|
|
30817
|
+
* The ops-log window in days, as it is in force. `0` = kept forever.
|
|
30818
|
+
*
|
|
30819
|
+
* Reported rather than left to the caller's memory of what it wrote: this is
|
|
30820
|
+
* the value the analytics sweep will actually use, and an operator asking how
|
|
30821
|
+
* long their audit trail lives should not have to infer it from a default.
|
|
30822
|
+
*/
|
|
30823
|
+
opsLogRetentionDays: number().int().min(0),
|
|
30629
30824
|
persisted: boolean()
|
|
30630
30825
|
});
|
|
30631
30826
|
method(_void(), FeatureManifestSchema), method(_void(), HealthStatusSchema), method(_void(), FeatureManifestSchema), method(_void(), array(NetworkAddressSchema).readonly()), method(_void(), unknown().nullable(), { auth: "admin" }), method(record(string(), unknown()), _null(), {
|
|
@@ -31203,7 +31398,7 @@ var StationaryObjectSchema = object({
|
|
|
31203
31398
|
/** Enrichment label carried from the source track (identity / plate). */
|
|
31204
31399
|
label: string().optional(),
|
|
31205
31400
|
/** Native-resolution key-frame media key for the parked object's best image. */
|
|
31206
|
-
|
|
31401
|
+
keyFrameMediaId: number().int().optional()
|
|
31207
31402
|
});
|
|
31208
31403
|
var CameraOccupancySnapshotSchema = object({
|
|
31209
31404
|
/** Frame timestamp of the inference result that produced this snapshot. */
|
|
@@ -32359,6 +32554,12 @@ Object.freeze({
|
|
|
32359
32554
|
addonId: null,
|
|
32360
32555
|
access: "create"
|
|
32361
32556
|
},
|
|
32557
|
+
"dataStoreProvider.upsert": {
|
|
32558
|
+
capName: "data-store-provider",
|
|
32559
|
+
capScope: "system",
|
|
32560
|
+
addonId: null,
|
|
32561
|
+
access: "create"
|
|
32562
|
+
},
|
|
32362
32563
|
"dayNight.getOptions": {
|
|
32363
32564
|
capName: "day-night",
|
|
32364
32565
|
capScope: "device",
|
|
@@ -34795,6 +34996,12 @@ Object.freeze({
|
|
|
34795
34996
|
addonId: null,
|
|
34796
34997
|
access: "view"
|
|
34797
34998
|
},
|
|
34999
|
+
"pipelineAnalytics.listRecentSummaries": {
|
|
35000
|
+
capName: "pipeline-analytics",
|
|
35001
|
+
capScope: "device",
|
|
35002
|
+
addonId: null,
|
|
35003
|
+
access: "view"
|
|
35004
|
+
},
|
|
34798
35005
|
"pipelineAnalytics.listRecentTracks": {
|
|
34799
35006
|
capName: "pipeline-analytics",
|
|
34800
35007
|
capScope: "device",
|
|
@@ -36223,6 +36430,12 @@ Object.freeze({
|
|
|
36223
36430
|
addonId: null,
|
|
36224
36431
|
access: "create"
|
|
36225
36432
|
},
|
|
36433
|
+
"settingsStore.upsert": {
|
|
36434
|
+
capName: "settings-store",
|
|
36435
|
+
capScope: "system",
|
|
36436
|
+
addonId: null,
|
|
36437
|
+
access: "create"
|
|
36438
|
+
},
|
|
36226
36439
|
"smtpProvider.getStatus": {
|
|
36227
36440
|
capName: "smtp-provider",
|
|
36228
36441
|
capScope: "system",
|
|
@@ -38616,6 +38829,11 @@ Object.freeze({
|
|
|
38616
38829
|
form: "single",
|
|
38617
38830
|
optional: true
|
|
38618
38831
|
}],
|
|
38832
|
+
"pipelineAnalytics.listRecentSummaries": [{
|
|
38833
|
+
name: "deviceIds",
|
|
38834
|
+
form: "array",
|
|
38835
|
+
optional: false
|
|
38836
|
+
}],
|
|
38619
38837
|
"pipelineAnalytics.listRecentTracks": [{
|
|
38620
38838
|
name: "deviceIds",
|
|
38621
38839
|
form: "array",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-export-hap",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.112",
|
|
4
4
|
"description": "HomeKit (HAP) exporter for CamStack devices. Publishes each exposed device as its own HomeKit accessory: cameras and doorbells with SRTP streaming, HomeKit Secure Video, motion, two-way audio, PTZ and battery; switches, lights, locks and sensors through a capability→service table.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|