@camstack/addon-provider-onvif 1.2.98 → 1.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
|
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
2
2
|
//#region \0rolldown/runtime.js
|
|
3
3
|
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
4
4
|
//#endregion
|
|
5
|
-
//#region ../types/dist/event-category-
|
|
5
|
+
//#region ../types/dist/event-category-ZyX6jcse.mjs
|
|
6
6
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
7
7
|
EventCategory["SystemBoot"] = "system.boot";
|
|
8
8
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -563,7 +563,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
563
563
|
* a package zone — a newly-appeared stationary object of a package class
|
|
564
564
|
* that cleared the class / zone / dwell / size gates. Payload:
|
|
565
565
|
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
566
|
-
* entryId, className, zoneIds,
|
|
566
|
+
* entryId, className, zoneIds, keyFrameMediaId?, bbox, timestamp }`.
|
|
567
567
|
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
568
568
|
* this bus topic drives notifier rules + live UI. See
|
|
569
569
|
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
@@ -5349,7 +5349,7 @@ var ZodIssueCode = {
|
|
|
5349
5349
|
var ZodFirstPartyTypeKind;
|
|
5350
5350
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5351
5351
|
//#endregion
|
|
5352
|
-
//#region ../types/dist/sleep-
|
|
5352
|
+
//#region ../types/dist/sleep-DBKu2-U5.mjs
|
|
5353
5353
|
/**
|
|
5354
5354
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5355
5355
|
* window to float samples (D455).
|
|
@@ -7312,13 +7312,30 @@ new Set([
|
|
|
7312
7312
|
"scene",
|
|
7313
7313
|
"motion",
|
|
7314
7314
|
"object",
|
|
7315
|
-
"audio"
|
|
7315
|
+
"audio",
|
|
7316
|
+
"mosaic"
|
|
7316
7317
|
]);
|
|
7317
|
-
|
|
7318
|
+
/**
|
|
7319
|
+
* The owner types that are event tables, in the order the event-media resolver
|
|
7320
|
+
* should consider them. Exported so a consumer asking "is this key an event?"
|
|
7321
|
+
* does not re-spell the list and drift from it.
|
|
7322
|
+
*/
|
|
7323
|
+
var EVENT_OWNER_TYPES = [
|
|
7318
7324
|
"motion",
|
|
7319
7325
|
"object",
|
|
7320
7326
|
"audio"
|
|
7321
|
-
]
|
|
7327
|
+
];
|
|
7328
|
+
/**
|
|
7329
|
+
* The same list as a Zod enum, for the cap inputs that must NAME the table
|
|
7330
|
+
* (D482: `getEventMedia` / `listEventMedia` take an owner, and an owner is
|
|
7331
|
+
* `(table, id)`).
|
|
7332
|
+
*
|
|
7333
|
+
* Built FROM {@link EVENT_OWNER_TYPES} rather than re-spelled: a fourth event
|
|
7334
|
+
* table would otherwise be accepted by the codec and refused at the door, with
|
|
7335
|
+
* nothing failing until a caller asked.
|
|
7336
|
+
*/
|
|
7337
|
+
var EventOwnerTypeSchema = _enum(EVENT_OWNER_TYPES);
|
|
7338
|
+
new Set(EVENT_OWNER_TYPES);
|
|
7322
7339
|
var EncodeProfileSchema = object({
|
|
7323
7340
|
video: object({
|
|
7324
7341
|
codec: _enum([
|
|
@@ -7357,7 +7374,23 @@ var EncodeProfileSchema = object({
|
|
|
7357
7374
|
"zerolatency",
|
|
7358
7375
|
"film",
|
|
7359
7376
|
"animation"
|
|
7360
|
-
]).optional()
|
|
7377
|
+
]).optional(),
|
|
7378
|
+
/**
|
|
7379
|
+
* ONE slice per access unit.
|
|
7380
|
+
*
|
|
7381
|
+
* `-tune zerolatency` turns on x264's sliced threads, and a frame then leaves
|
|
7382
|
+
* the encoder as five NAL slices that share one RTP timestamp and carry one
|
|
7383
|
+
* marker bit. A libwebrtc depacketiser sees five frame-starts and one
|
|
7384
|
+
* frame-end per frame: the first pictures render and the video then freezes
|
|
7385
|
+
* for good while the audio, on its own plane, plays on. Measured on this hub
|
|
7386
|
+
* 2026-09-13 against the Echo, and reduced to one slice by this flag alone.
|
|
7387
|
+
*
|
|
7388
|
+
* A NAMED field and not a raw flag, because {@link EgressEncodeSchema} omits
|
|
7389
|
+
* `outputArgs` on purpose: an opaque array is part of the sharing key, so two
|
|
7390
|
+
* consumers meaning the same thing spelled differently would stop sharing one
|
|
7391
|
+
* child. Absent means "whatever the encoder does" — today's behaviour.
|
|
7392
|
+
*/
|
|
7393
|
+
singleSlicePerFrame: boolean().optional()
|
|
7361
7394
|
}),
|
|
7362
7395
|
audio: union([literal("passthrough"), object({
|
|
7363
7396
|
codec: _enum([
|
|
@@ -7407,7 +7440,7 @@ var BASE_LIVE_EGRESS_PROFILE = {
|
|
|
7407
7440
|
audio: "passthrough"
|
|
7408
7441
|
};
|
|
7409
7442
|
({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
|
|
7410
|
-
({ ...BASE_LIVE_EGRESS_PROFILE });
|
|
7443
|
+
({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
|
|
7411
7444
|
/**
|
|
7412
7445
|
* Deep wiring healthcheck — snapshot of active reachability probes across
|
|
7413
7446
|
* every declared capability + widget of every installed plugin, on every
|
|
@@ -12415,6 +12448,16 @@ method(object({
|
|
|
12415
12448
|
filter: QueryFilterSchema.optional(),
|
|
12416
12449
|
columns: array(string()).readonly().optional()
|
|
12417
12450
|
}), array(SettingsRecordSchema).readonly()), method(object({
|
|
12451
|
+
namespace: string().optional(),
|
|
12452
|
+
collection: string(),
|
|
12453
|
+
/** Declared columns identifying the slot; must be covered by a UNIQUE
|
|
12454
|
+
* index on the collection. Never empty. */
|
|
12455
|
+
conflict: array(string()).readonly(),
|
|
12456
|
+
record: BulkRecordSchema
|
|
12457
|
+
}), object({
|
|
12458
|
+
/** The id the row HAS: assigned by SQLite on an insert, or the existing
|
|
12459
|
+
* row's own id on an update. */
|
|
12460
|
+
id: union([string(), number()]) }), { kind: "mutation" }), method(object({
|
|
12418
12461
|
namespace: string().optional(),
|
|
12419
12462
|
collection: string(),
|
|
12420
12463
|
record: object({
|
|
@@ -12549,6 +12592,14 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
|
|
|
12549
12592
|
id: union([string(), number()]) }), {
|
|
12550
12593
|
kind: "mutation",
|
|
12551
12594
|
auth: "admin"
|
|
12595
|
+
}), method(object({
|
|
12596
|
+
namespace: string().optional(),
|
|
12597
|
+
collection: string(),
|
|
12598
|
+
conflict: array(string()).readonly(),
|
|
12599
|
+
record: BulkRecordSchema
|
|
12600
|
+
}), object({ id: union([string(), number()]) }), {
|
|
12601
|
+
kind: "mutation",
|
|
12602
|
+
auth: "admin"
|
|
12552
12603
|
}), method(object({
|
|
12553
12604
|
namespace: string().optional(),
|
|
12554
12605
|
collection: string(),
|
|
@@ -18846,8 +18897,8 @@ var TrackPositionSchema = object({
|
|
|
18846
18897
|
var TrackSnapshotSchema = object({
|
|
18847
18898
|
timestamp: number(),
|
|
18848
18899
|
position: TrackPositionSchema,
|
|
18849
|
-
/**
|
|
18850
|
-
|
|
18900
|
+
/** The snapshot's media row id (D482); resolve via `listTrackMedia({ trackId })`. */
|
|
18901
|
+
mediaId: number().int()
|
|
18851
18902
|
});
|
|
18852
18903
|
/**
|
|
18853
18904
|
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
@@ -19451,14 +19502,14 @@ var ObjectEventSchema = object({
|
|
|
19451
19502
|
* pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
|
|
19452
19503
|
frameWidth: number().optional(),
|
|
19453
19504
|
frameHeight: number().optional(),
|
|
19454
|
-
/**
|
|
19455
|
-
|
|
19456
|
-
/** Design B:
|
|
19505
|
+
/** Media row id of the crop attached to this event (if any) — D482. */
|
|
19506
|
+
mediaId: number().int().optional(),
|
|
19507
|
+
/** Design B: media row id of the track's native-resolution key frame (the
|
|
19457
19508
|
* best-detection full frame). Resolve via the event-media data-plane
|
|
19458
|
-
* (`/addon/<addonId>/event-media/<
|
|
19509
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`) for a detail view that
|
|
19459
19510
|
* draws `bbox` over the native frame. Absent on legacy rows / non-decoded
|
|
19460
|
-
* sources — consumers fall back to `
|
|
19461
|
-
|
|
19511
|
+
* sources — consumers fall back to `mediaId` (the tight crop). */
|
|
19512
|
+
keyFrameMediaId: number().int().optional(),
|
|
19462
19513
|
/** Populated by B5 (recording playback URL for this event). */
|
|
19463
19514
|
mediaUrl: string().optional(),
|
|
19464
19515
|
/** The parent track's key-event importance [0,1], propagated to every object
|
|
@@ -19508,7 +19559,7 @@ var MediaFileKindEnum = _enum([
|
|
|
19508
19559
|
* hub-main's heap on the way past — for an `<img>` that would have cached it.
|
|
19509
19560
|
*
|
|
19510
19561
|
* `url` points at the `event-media` data plane
|
|
19511
|
-
* (`/addon/<addonId>/event-media/<
|
|
19562
|
+
* (`/addon/<addonId>/event-media/m/<mediaId>` — D482), which serves the same blob
|
|
19512
19563
|
* with an ETag and `Cache-Control: immutable`, honours conditional GETs, can
|
|
19513
19564
|
* render a `?variant=thumb`, and streams. The hub gate in front of it requires
|
|
19514
19565
|
* a bearer or the session cookie (`access: 'authenticated'`), so the bytes are
|
|
@@ -19516,10 +19567,13 @@ var MediaFileKindEnum = _enum([
|
|
|
19516
19567
|
* `data-plane-access.ts` for the rule and the one gap it does not close
|
|
19517
19568
|
* (per-device scoping).
|
|
19518
19569
|
*
|
|
19519
|
-
* The URL is built from the row's
|
|
19520
|
-
*
|
|
19570
|
+
* The URL is built from the row's own id, which since D482 says nothing about
|
|
19571
|
+
* the row's owner or kind — and that is the point. The published `kind` is not
|
|
19572
|
+
* the stored one (a track's face/plate crop is stored as `crop` under
|
|
19521
19573
|
* `('face'|'plate', '<prefix>-<trackId>')` and published as
|
|
19522
|
-
* `faceCrop`/`plateCrop
|
|
19574
|
+
* `faceCrop`/`plateCrop`), and under the old composite key the URL had to be
|
|
19575
|
+
* taken from `row.key` verbatim or it 404'd exactly those two rows. An id
|
|
19576
|
+
* cannot be mis-reconstructed, because there is nothing in it to reconstruct.
|
|
19523
19577
|
*
|
|
19524
19578
|
* ## `base64` is TRANSITIONAL and is going away
|
|
19525
19579
|
*
|
|
@@ -19532,7 +19586,19 @@ var MediaFileKindEnum = _enum([
|
|
|
19532
19586
|
* `analytics-query-facade.ts`; nothing else reads it.
|
|
19533
19587
|
*/
|
|
19534
19588
|
var MediaFileSchema = object({
|
|
19535
|
-
|
|
19589
|
+
/**
|
|
19590
|
+
* The media row's OWN id — the rowid SQLite assigned it (D482).
|
|
19591
|
+
*
|
|
19592
|
+
* It used to be the row's composite key, `<ownerType>:<ownerId>:<fileKind>
|
|
19593
|
+
* [:<timestampMs>]`, which embedded a FOREIGN id. D474 made event ids
|
|
19594
|
+
* per-table rowid aliases, so `object:101314` and `motion:101314` are two
|
|
19595
|
+
* different rows that spell the same number, and a track whose
|
|
19596
|
+
* `bestEventId` was an object event was served a motion event's snapshot —
|
|
19597
|
+
* a night-time thumbnail on an afternoon track, with no error anywhere. A
|
|
19598
|
+
* surrogate id cannot name the wrong row's owner, because it names no owner
|
|
19599
|
+
* at all.
|
|
19600
|
+
*/
|
|
19601
|
+
mediaId: number().int(),
|
|
19536
19602
|
kind: MediaFileKindEnum,
|
|
19537
19603
|
sizeBytes: number(),
|
|
19538
19604
|
timestamp: number()
|
|
@@ -19640,7 +19706,7 @@ var RetrainTrackSchema = object({
|
|
|
19640
19706
|
});
|
|
19641
19707
|
/** A frame the picker may offer — an index row, no blob was read to produce it. */
|
|
19642
19708
|
var RetrainFrameCandidateSchema = object({
|
|
19643
|
-
|
|
19709
|
+
mediaId: number().int(),
|
|
19644
19710
|
kind: MediaFileKindEnum,
|
|
19645
19711
|
timestamp: number(),
|
|
19646
19712
|
sizeBytes: number().int(),
|
|
@@ -19654,7 +19720,7 @@ var RetrainFrameSchema = object({
|
|
|
19654
19720
|
deviceId: number(),
|
|
19655
19721
|
trackId: string(),
|
|
19656
19722
|
/** Provenance only. It may already point at nothing — that is expected. */
|
|
19657
|
-
|
|
19723
|
+
sourceMediaId: number().int(),
|
|
19658
19724
|
sourceKind: MediaFileKindEnum,
|
|
19659
19725
|
sizeBytes: number().int(),
|
|
19660
19726
|
width: number().int(),
|
|
@@ -19670,7 +19736,7 @@ var RetrainCopyRefusalSchema = _enum([
|
|
|
19670
19736
|
var RetrainFrameSelectionSchema = object({
|
|
19671
19737
|
copied: array(RetrainFrameSchema).readonly(),
|
|
19672
19738
|
refused: array(object({
|
|
19673
|
-
|
|
19739
|
+
sourceMediaId: number().int(),
|
|
19674
19740
|
reason: RetrainCopyRefusalSchema
|
|
19675
19741
|
})).readonly()
|
|
19676
19742
|
});
|
|
@@ -19678,7 +19744,7 @@ var RetrainFrameListSchema = object({
|
|
|
19678
19744
|
candidates: array(RetrainFrameCandidateSchema).readonly(),
|
|
19679
19745
|
copies: array(RetrainFrameSchema).readonly(),
|
|
19680
19746
|
/** What the page pre-selects — the native key frame when one survives. */
|
|
19681
|
-
|
|
19747
|
+
autoPickMediaId: number().int().optional()
|
|
19682
19748
|
});
|
|
19683
19749
|
/** What the operator asked the assist to look for. */
|
|
19684
19750
|
var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
|
|
@@ -19773,9 +19839,11 @@ var RecentTracksQueryInput = object({
|
|
|
19773
19839
|
});
|
|
19774
19840
|
/**
|
|
19775
19841
|
* A Summary (D359): the per-camera session envelope that references tracks.
|
|
19776
|
-
* `
|
|
19777
|
-
* served by the event-media plane
|
|
19778
|
-
* member visible has been materialised
|
|
19842
|
+
* `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
|
|
19843
|
+
* 'summary'`, served by the event-media plane at `/m/<id>`), null until the
|
|
19844
|
+
* first frame with a member visible has been materialised (D482 — it was the
|
|
19845
|
+
* row's composite key, which embedded the owner and could name another table's
|
|
19846
|
+
* row once event ids became per-table rowids).
|
|
19779
19847
|
*/
|
|
19780
19848
|
var SummarySchema = object({
|
|
19781
19849
|
id: string(),
|
|
@@ -19784,19 +19852,115 @@ var SummarySchema = object({
|
|
|
19784
19852
|
lastActiveAt: number(),
|
|
19785
19853
|
sealedAt: number().nullable(),
|
|
19786
19854
|
memberCount: number().int().nonnegative(),
|
|
19787
|
-
|
|
19855
|
+
groupShotMediaId: number().int().nullable()
|
|
19788
19856
|
});
|
|
19789
19857
|
var SummariesQueryInput = object({
|
|
19790
19858
|
deviceIds: array(number()).min(1),
|
|
19791
19859
|
since: number().optional(),
|
|
19792
19860
|
until: number().optional(),
|
|
19793
|
-
limit: number().int().min(1).max(200).default(50)
|
|
19861
|
+
limit: number().int().min(1).max(200).default(50),
|
|
19862
|
+
/** The same member-wise filter {@link listRecentSummaries} takes — one
|
|
19863
|
+
* meaning of "dog" on every summary surface. */
|
|
19864
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
19794
19865
|
});
|
|
19795
|
-
var SummariesPageSchema = object({ summaries: array(SummarySchema).readonly() });
|
|
19796
19866
|
var SummaryDetailSchema = object({
|
|
19797
19867
|
summary: SummarySchema,
|
|
19798
|
-
/**
|
|
19799
|
-
|
|
19868
|
+
/** Members in absorption order, oldest join first. */
|
|
19869
|
+
members: array(object({
|
|
19870
|
+
trackId: string(),
|
|
19871
|
+
/**
|
|
19872
|
+
* The track's class at the time it JOINED, or `null` when it was unresolved
|
|
19873
|
+
* and the track no longer exists to fill it.
|
|
19874
|
+
*
|
|
19875
|
+
* The join, not the latest opinion: class voting can re-decide a track's
|
|
19876
|
+
* class afterwards, and a group's composition is the history of who came
|
|
19877
|
+
* together. A consumer counts these to badge a thumbnail — "two people and a
|
|
19878
|
+
* dog" — rather than being handed a second, denormalised tally that would
|
|
19879
|
+
* drift from the members it claims to describe.
|
|
19880
|
+
*/
|
|
19881
|
+
className: string().nullable(),
|
|
19882
|
+
/** `primary` is the one member that carries the group's identity. */
|
|
19883
|
+
role: _enum([
|
|
19884
|
+
"primary",
|
|
19885
|
+
"sibling",
|
|
19886
|
+
"child"
|
|
19887
|
+
]).nullable(),
|
|
19888
|
+
joinedAt: number(),
|
|
19889
|
+
/** Tier 1 — the sub-class (`dog`, `van`), resolved from the member's track
|
|
19890
|
+
* at read time. Absent when nothing resolved, never an empty string. */
|
|
19891
|
+
label: string().optional(),
|
|
19892
|
+
/** Tier 2 — the instance: a person's name, a plate. Absent when the pipeline
|
|
19893
|
+
* recognised nobody, and absent for a member whose track has been pruned —
|
|
19894
|
+
* a thumbnail that names the wrong person is worse than one naming nobody. */
|
|
19895
|
+
subLabel: string().optional()
|
|
19896
|
+
})).readonly()
|
|
19897
|
+
});
|
|
19898
|
+
/**
|
|
19899
|
+
* What a LIST of groups carries: the envelope plus what it is MADE OF.
|
|
19900
|
+
*
|
|
19901
|
+
* Coarse on purpose — the operator's rule is "only the rough data on the list,
|
|
19902
|
+
* we extend when we notice we need more". Enough to draw the card ("two people
|
|
19903
|
+
* and a dog") and no more. The MEMBERS, their names and the per-member links
|
|
19904
|
+
* are on {@link getSummary}: shipping every member of every group so a client
|
|
19905
|
+
* can count them turns a page of two hundred groups into a thousand records to
|
|
19906
|
+
* draw two hundred badges.
|
|
19907
|
+
*/
|
|
19908
|
+
var SummaryListItemSchema = object({
|
|
19909
|
+
summary: SummarySchema,
|
|
19910
|
+
/** Class counts, most numerous first; `className: null` is a member whose
|
|
19911
|
+
* class never resolved, counted so the counts add up to `memberCount`. */
|
|
19912
|
+
classes: array(object({
|
|
19913
|
+
className: string().nullable(),
|
|
19914
|
+
count: number().int().positive()
|
|
19915
|
+
})).readonly()
|
|
19916
|
+
});
|
|
19917
|
+
var SummariesPageSchema = object({ summaries: array(SummaryListItemSchema).readonly() });
|
|
19918
|
+
/**
|
|
19919
|
+
* The paged feed, deliberately the SAME shape as {@link RecentTracksQueryInput}.
|
|
19920
|
+
*
|
|
19921
|
+
* The reel on the cameras page and the Events gallery both ride a cursor, so a
|
|
19922
|
+
* summaries feed that could only answer "the last N for these cameras"
|
|
19923
|
+
* (`listSummaries`) would make groups available in the timeline and nowhere
|
|
19924
|
+
* else. Two feeds with different ordering contracts would be two ideas of what
|
|
19925
|
+
* "newest" means, on one screen.
|
|
19926
|
+
*/
|
|
19927
|
+
var RecentSummariesQueryInput = object({
|
|
19928
|
+
/** Devices to merge. An empty array yields an empty page. */
|
|
19929
|
+
deviceIds: array(number()),
|
|
19930
|
+
/** Window lower bound on `lastActiveAt` (inclusive). */
|
|
19931
|
+
since: number().optional(),
|
|
19932
|
+
/** Window upper bound on `lastActiveAt` (inclusive). */
|
|
19933
|
+
until: number().optional(),
|
|
19934
|
+
limit: number().int().min(1).max(500).default(100),
|
|
19935
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`. */
|
|
19936
|
+
cursor: string().optional(),
|
|
19937
|
+
/**
|
|
19938
|
+
* Restrict to these classes — THE SAME FIELD `listRecentTracks` takes, and
|
|
19939
|
+
* deliberately the same name: the events filter tree emits one list of ticked
|
|
19940
|
+
* taxonomy nodes, and a summaries feed that called it something else would
|
|
19941
|
+
* make the operator's one filter component produce two shapes.
|
|
19942
|
+
*
|
|
19943
|
+
* A question about the MEMBERS: a group matches when ANY of them does. "Show
|
|
19944
|
+
* me the arrivals with a dog" has to return the group of four people who had
|
|
19945
|
+
* one with them; a filter on the group's own fields could only ever answer
|
|
19946
|
+
* about its primary.
|
|
19947
|
+
*
|
|
19948
|
+
* Matched against all THREE tiers of a member — the class (`animal`), the
|
|
19949
|
+
* sub-class (`dog`) and the instance (a name, a plate) — because which tier a
|
|
19950
|
+
* ticked node lives on is the taxonomy's business, not the caller's. `dog` is
|
|
19951
|
+
* an event kind in the tree and a tier-1 label on an `animal` track; a filter
|
|
19952
|
+
* that read only the class would answer "animal" and never "dog".
|
|
19953
|
+
*
|
|
19954
|
+
* ABSENT or EMPTY means no filter — absent is not a selection of none.
|
|
19955
|
+
*/
|
|
19956
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
19957
|
+
});
|
|
19958
|
+
var RecentSummariesPageSchema = object({
|
|
19959
|
+
/** Ordered by (`lastActiveAt` DESC, id DESC). Same light item as
|
|
19960
|
+
* {@link listSummaries} — one list shape, so a card renders the same
|
|
19961
|
+
* whichever feed drew it. */
|
|
19962
|
+
summaries: array(SummaryListItemSchema).readonly(),
|
|
19963
|
+
nextCursor: string().nullable()
|
|
19800
19964
|
});
|
|
19801
19965
|
var RecentTracksPageSchema = object({
|
|
19802
19966
|
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
@@ -20210,7 +20374,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20210
20374
|
classes: array(string()).optional(),
|
|
20211
20375
|
/** See {@link ExcludeSourcesDoc}. */
|
|
20212
20376
|
excludeSources: array(TrackSourceSchema).optional()
|
|
20213
|
-
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
20377
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(RecentSummariesQueryInput, RecentSummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
20214
20378
|
kind: "mutation",
|
|
20215
20379
|
auth: "admin"
|
|
20216
20380
|
}), 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({
|
|
@@ -20338,7 +20502,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20338
20502
|
}), method(object({
|
|
20339
20503
|
deviceId: number(),
|
|
20340
20504
|
trackId: string(),
|
|
20341
|
-
|
|
20505
|
+
mediaIds: array(number().int()).min(1)
|
|
20342
20506
|
}), RetrainFrameSelectionSchema, {
|
|
20343
20507
|
kind: "mutation",
|
|
20344
20508
|
auth: "admin"
|
|
@@ -20406,7 +20570,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20406
20570
|
kind: "query",
|
|
20407
20571
|
auth: "admin"
|
|
20408
20572
|
}), method(object({
|
|
20409
|
-
|
|
20573
|
+
/** Which of the three event tables owns the row. */
|
|
20574
|
+
ownerType: EventOwnerTypeSchema,
|
|
20575
|
+
/** The event's rowid in that table (D474: an event id is a number). */
|
|
20576
|
+
eventId: number().int(),
|
|
20410
20577
|
kind: MediaFileKindEnum.optional(),
|
|
20411
20578
|
deviceId: number()
|
|
20412
20579
|
}), array(MediaFileSchema).readonly()), method(object({
|
|
@@ -20417,7 +20584,8 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20417
20584
|
trackId: string(),
|
|
20418
20585
|
deviceId: number()
|
|
20419
20586
|
}), array(MediaFileInfoSchema).readonly()), method(object({
|
|
20420
|
-
|
|
20587
|
+
ownerType: EventOwnerTypeSchema,
|
|
20588
|
+
eventId: number().int(),
|
|
20421
20589
|
deviceId: number()
|
|
20422
20590
|
}), array(MediaFileInfoSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
|
|
20423
20591
|
kind: "mutation",
|
|
@@ -24984,8 +25152,8 @@ var IdentitySchema = object({
|
|
|
24984
25152
|
id: string(),
|
|
24985
25153
|
name: string(),
|
|
24986
25154
|
sampleCount: number().int().nonnegative(),
|
|
24987
|
-
|
|
24988
|
-
/** Inline base64 of the cover sample's crop, resolved from `
|
|
25155
|
+
coverMediaId: number().int().optional(),
|
|
25156
|
+
/** Inline base64 of the cover sample's crop, resolved from `coverMediaId`.
|
|
24989
25157
|
* Lets the UI render the person's face avatar instead of a placeholder icon. */
|
|
24990
25158
|
coverBase64: string().optional()
|
|
24991
25159
|
});
|
|
@@ -25011,8 +25179,8 @@ var IdentitySampleAuditRowSchema = object({
|
|
|
25011
25179
|
enrolledAt: number().int(),
|
|
25012
25180
|
deviceId: number().int().optional(),
|
|
25013
25181
|
source: _enum(["detected", "photo"]),
|
|
25014
|
-
/** The enrolled crop's media
|
|
25015
|
-
|
|
25182
|
+
/** The enrolled crop's media row id, so the panel can show the evidence. */
|
|
25183
|
+
mediaId: number().int().optional(),
|
|
25016
25184
|
/**
|
|
25017
25185
|
* False = the sample is stamped with a DIFFERENT face model, and a cosine
|
|
25018
25186
|
* across feature spaces is a well-formed float with no meaning. Every number
|
|
@@ -25081,15 +25249,15 @@ var FaceInfoSchema = object({
|
|
|
25081
25249
|
*/
|
|
25082
25250
|
cropUrl: string().optional(),
|
|
25083
25251
|
/** Design B: the face bbox (pixel space) on the key frame — lets a detail
|
|
25084
|
-
* view draw the box over the native `
|
|
25252
|
+
* view draw the box over the native `keyFrameMediaId` frame. Absent on
|
|
25085
25253
|
* legacy rows written before design B. */
|
|
25086
25254
|
faceBbox: BoundingBoxSchema.optional(),
|
|
25087
25255
|
/** Design B: MediaStore key of the track's native-resolution key frame.
|
|
25088
25256
|
* Fetch the native JPEG via the event-media data-plane
|
|
25089
|
-
* (`/addon/<addonId>/event-media/<
|
|
25257
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`). Absent when the
|
|
25090
25258
|
* track produced no key frame (e.g. native/onboard source) — the UI falls
|
|
25091
25259
|
* back to the inline `base64` face crop. */
|
|
25092
|
-
|
|
25260
|
+
keyFrameMediaId: number().int().optional(),
|
|
25093
25261
|
/** Winning identity-match cosine (0..1) for this face's track, when an
|
|
25094
25262
|
* identity was auto-confirmed. Lets the UI surface WHY a face was assigned
|
|
25095
25263
|
* (confidence badge / low-confidence audit). Absent on legacy rows and on
|
|
@@ -25158,11 +25326,14 @@ var FaceClusterSchema = object({
|
|
|
25158
25326
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
25159
25327
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
25160
25328
|
*
|
|
25161
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
25162
|
-
* media
|
|
25329
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
25330
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
25331
|
+
* access decision.
|
|
25163
25332
|
*/
|
|
25164
25333
|
var MediaFileLiteSchema$1 = object({
|
|
25165
|
-
|
|
25334
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
25335
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
25336
|
+
mediaId: number().int(),
|
|
25166
25337
|
kind: string(),
|
|
25167
25338
|
url: string(),
|
|
25168
25339
|
sizeBytes: number(),
|
|
@@ -25179,7 +25350,7 @@ method(object({
|
|
|
25179
25350
|
* covers inline, ~10 KB of base64 per row, on a query this UI mounts
|
|
25180
25351
|
* four times and the viewer holds at `staleTime: 30_000`.
|
|
25181
25352
|
*
|
|
25182
|
-
* Nothing loses its avatar: `
|
|
25353
|
+
* Nothing loses its avatar: `coverMediaId` is already on every row and
|
|
25183
25354
|
* the `event-media` plane serves that key `immutable` with an ETag.
|
|
25184
25355
|
*
|
|
25185
25356
|
* **This is an INPUT field, so it does not reach the addon until the
|
|
@@ -27647,8 +27818,8 @@ var VehicleSchema = object({
|
|
|
27647
27818
|
id: string(),
|
|
27648
27819
|
name: string(),
|
|
27649
27820
|
sampleCount: number().int().nonnegative(),
|
|
27650
|
-
|
|
27651
|
-
/** Inline base64 of the cover sample's plate crop, resolved from `
|
|
27821
|
+
coverMediaId: number().int().optional(),
|
|
27822
|
+
/** Inline base64 of the cover sample's plate crop, resolved from `coverMediaId`. */
|
|
27652
27823
|
coverBase64: string().optional()
|
|
27653
27824
|
});
|
|
27654
27825
|
var VehicleSampleInfoSchema = object({
|
|
@@ -27681,7 +27852,7 @@ var PlateInfoSchema = object({
|
|
|
27681
27852
|
/** keyFrame parity: the plate bbox (pixel space) on the native key frame. */
|
|
27682
27853
|
plateBbox: BoundingBoxSchema.optional(),
|
|
27683
27854
|
/** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
|
|
27684
|
-
|
|
27855
|
+
keyFrameMediaId: number().int().optional(),
|
|
27685
27856
|
base64: string().optional(),
|
|
27686
27857
|
/**
|
|
27687
27858
|
* Same crop as a data-plane URL, always present when the plate has a stored
|
|
@@ -27702,11 +27873,14 @@ var PlateInfoSchema = object({
|
|
|
27702
27873
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
27703
27874
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
27704
27875
|
*
|
|
27705
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
27706
|
-
* media
|
|
27876
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
27877
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
27878
|
+
* access decision.
|
|
27707
27879
|
*/
|
|
27708
27880
|
var MediaFileLiteSchema = object({
|
|
27709
|
-
|
|
27881
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
27882
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
27883
|
+
mediaId: number().int(),
|
|
27710
27884
|
kind: string(),
|
|
27711
27885
|
url: string(),
|
|
27712
27886
|
sizeBytes: number(),
|
|
@@ -27765,7 +27939,7 @@ method(object({
|
|
|
27765
27939
|
}), method(object({
|
|
27766
27940
|
/** Inline {@link VehicleSchema.coverBase64} on every row. Default
|
|
27767
27941
|
* `false` — the vehicle twin of `faceGallery.listIdentities`'s
|
|
27768
|
-
* option; `
|
|
27942
|
+
* option; `coverMediaId` + the `event-media` plane carry the picture.
|
|
27769
27943
|
* INPUT field: stripped by the hub router until the train ships, which
|
|
27770
27944
|
* resolves to `false` and is exactly the intended default. */
|
|
27771
27945
|
includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
|
|
@@ -29131,7 +29305,14 @@ var SceneReferenceSchema = object({
|
|
|
29131
29305
|
modelId: string(),
|
|
29132
29306
|
condition: SceneConditionSchema,
|
|
29133
29307
|
capturedAt: number(),
|
|
29134
|
-
|
|
29308
|
+
/**
|
|
29309
|
+
* The reference thumbnail's media ROW id (D482).
|
|
29310
|
+
*
|
|
29311
|
+
* The name already said `mediaId` while the value was the row's composite
|
|
29312
|
+
* key — a leftover that read as done and was not. It is the row's own id
|
|
29313
|
+
* now, addressed at `/addon/<addonId>/event-media/m/<id>`.
|
|
29314
|
+
*/
|
|
29315
|
+
thumbnailMediaId: number().int().optional(),
|
|
29135
29316
|
/** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
|
|
29136
29317
|
* anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
|
|
29137
29318
|
* normalized rect frame a different piece of world, and the scene would
|
|
@@ -29945,7 +30126,29 @@ var LoggingSettingsPatchSchema = object({
|
|
|
29945
30126
|
* disarmed the channels it did not mention would make the Levels page and
|
|
29946
30127
|
* the Diagnostics page fight over the same value.
|
|
29947
30128
|
*/
|
|
29948
|
-
channels: array(LogChannelWindowPatchSchema).readonly().optional()
|
|
30129
|
+
channels: array(LogChannelWindowPatchSchema).readonly().optional(),
|
|
30130
|
+
/**
|
|
30131
|
+
* How many days the analytics OPS LOG is kept — the audit trail of what
|
|
30132
|
+
* retention actually deleted.
|
|
30133
|
+
*
|
|
30134
|
+
* It lives HERE, on the logging document, and not on the analytics addon's
|
|
30135
|
+
* settings form, on the operator's instruction: every other log-ish window in
|
|
30136
|
+
* this system is configured through this one document, and a retention audit
|
|
30137
|
+
* configured somewhere else is a second place to look when the question is
|
|
30138
|
+
* "what happened to my data".
|
|
30139
|
+
*
|
|
30140
|
+
* That placement has a cost worth stating: this document ships in the
|
|
30141
|
+
* framework closure, so this knob needs a published `@camstack/server` while
|
|
30142
|
+
* the four windows beside it (D485) reach a node on `camstack deploy`.
|
|
30143
|
+
*
|
|
30144
|
+
* `retention-model.ts` argued this one must NOT follow a device window,
|
|
30145
|
+
* because the audit trail is the history of the SWEEP and not of the camera.
|
|
30146
|
+
* That argument stands and is untouched — what changes is that 30 days stops
|
|
30147
|
+
* being a constant nobody can reach. `0` keeps it forever. The floor is 1 day
|
|
30148
|
+
* rather than 0-as-delete: an audit log truncated to nothing is precisely the
|
|
30149
|
+
* state in which the next 9.5 GiB leak cannot be explained.
|
|
30150
|
+
*/
|
|
30151
|
+
opsLogRetentionDays: number().int().min(0).max(3650).optional()
|
|
29949
30152
|
});
|
|
29950
30153
|
/**
|
|
29951
30154
|
* Which LAYER of the hierarchy is addressed. Absent = the cluster layer.
|
|
@@ -30018,6 +30221,14 @@ var LoggingSettingsStateSchema = object({
|
|
|
30018
30221
|
channels: array(LogChannelDescriptorSchema).readonly(),
|
|
30019
30222
|
/** The channels ARMED right now, each with its deadline. */
|
|
30020
30223
|
activeChannels: array(LogChannelWindowStateSchema).readonly(),
|
|
30224
|
+
/**
|
|
30225
|
+
* The ops-log window in days, as it is in force. `0` = kept forever.
|
|
30226
|
+
*
|
|
30227
|
+
* Reported rather than left to the caller's memory of what it wrote: this is
|
|
30228
|
+
* the value the analytics sweep will actually use, and an operator asking how
|
|
30229
|
+
* long their audit trail lives should not have to infer it from a default.
|
|
30230
|
+
*/
|
|
30231
|
+
opsLogRetentionDays: number().int().min(0),
|
|
30021
30232
|
persisted: boolean()
|
|
30022
30233
|
});
|
|
30023
30234
|
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(), {
|
|
@@ -30579,7 +30790,7 @@ var StationaryObjectSchema = object({
|
|
|
30579
30790
|
/** Enrichment label carried from the source track (identity / plate). */
|
|
30580
30791
|
label: string().optional(),
|
|
30581
30792
|
/** Native-resolution key-frame media key for the parked object's best image. */
|
|
30582
|
-
|
|
30793
|
+
keyFrameMediaId: number().int().optional()
|
|
30583
30794
|
});
|
|
30584
30795
|
var CameraOccupancySnapshotSchema = object({
|
|
30585
30796
|
/** Frame timestamp of the inference result that produced this snapshot. */
|
|
@@ -32561,6 +32772,12 @@ Object.freeze({
|
|
|
32561
32772
|
addonId: null,
|
|
32562
32773
|
access: "create"
|
|
32563
32774
|
},
|
|
32775
|
+
"dataStoreProvider.upsert": {
|
|
32776
|
+
capName: "data-store-provider",
|
|
32777
|
+
capScope: "system",
|
|
32778
|
+
addonId: null,
|
|
32779
|
+
access: "create"
|
|
32780
|
+
},
|
|
32564
32781
|
"dayNight.getOptions": {
|
|
32565
32782
|
capName: "day-night",
|
|
32566
32783
|
capScope: "device",
|
|
@@ -34997,6 +35214,12 @@ Object.freeze({
|
|
|
34997
35214
|
addonId: null,
|
|
34998
35215
|
access: "view"
|
|
34999
35216
|
},
|
|
35217
|
+
"pipelineAnalytics.listRecentSummaries": {
|
|
35218
|
+
capName: "pipeline-analytics",
|
|
35219
|
+
capScope: "device",
|
|
35220
|
+
addonId: null,
|
|
35221
|
+
access: "view"
|
|
35222
|
+
},
|
|
35000
35223
|
"pipelineAnalytics.listRecentTracks": {
|
|
35001
35224
|
capName: "pipeline-analytics",
|
|
35002
35225
|
capScope: "device",
|
|
@@ -36425,6 +36648,12 @@ Object.freeze({
|
|
|
36425
36648
|
addonId: null,
|
|
36426
36649
|
access: "create"
|
|
36427
36650
|
},
|
|
36651
|
+
"settingsStore.upsert": {
|
|
36652
|
+
capName: "settings-store",
|
|
36653
|
+
capScope: "system",
|
|
36654
|
+
addonId: null,
|
|
36655
|
+
access: "create"
|
|
36656
|
+
},
|
|
36428
36657
|
"smtpProvider.getStatus": {
|
|
36429
36658
|
capName: "smtp-provider",
|
|
36430
36659
|
capScope: "system",
|
|
@@ -38818,6 +39047,11 @@ Object.freeze({
|
|
|
38818
39047
|
form: "single",
|
|
38819
39048
|
optional: true
|
|
38820
39049
|
}],
|
|
39050
|
+
"pipelineAnalytics.listRecentSummaries": [{
|
|
39051
|
+
name: "deviceIds",
|
|
39052
|
+
form: "array",
|
|
39053
|
+
optional: false
|
|
39054
|
+
}],
|
|
38821
39055
|
"pipelineAnalytics.listRecentTracks": [{
|
|
38822
39056
|
name: "deviceIds",
|
|
38823
39057
|
form: "array",
|
package/dist/addon.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import { createRequire } from "node:module";
|
|
|
3
3
|
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
4
4
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
5
5
|
//#endregion
|
|
6
|
-
//#region ../types/dist/event-category-
|
|
6
|
+
//#region ../types/dist/event-category-ZyX6jcse.mjs
|
|
7
7
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
8
8
|
EventCategory["SystemBoot"] = "system.boot";
|
|
9
9
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -564,7 +564,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
564
564
|
* a package zone — a newly-appeared stationary object of a package class
|
|
565
565
|
* that cleared the class / zone / dwell / size gates. Payload:
|
|
566
566
|
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
567
|
-
* entryId, className, zoneIds,
|
|
567
|
+
* entryId, className, zoneIds, keyFrameMediaId?, bbox, timestamp }`.
|
|
568
568
|
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
569
569
|
* this bus topic drives notifier rules + live UI. See
|
|
570
570
|
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
@@ -5350,7 +5350,7 @@ var ZodIssueCode = {
|
|
|
5350
5350
|
var ZodFirstPartyTypeKind;
|
|
5351
5351
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5352
5352
|
//#endregion
|
|
5353
|
-
//#region ../types/dist/sleep-
|
|
5353
|
+
//#region ../types/dist/sleep-DBKu2-U5.mjs
|
|
5354
5354
|
/**
|
|
5355
5355
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5356
5356
|
* window to float samples (D455).
|
|
@@ -7313,13 +7313,30 @@ new Set([
|
|
|
7313
7313
|
"scene",
|
|
7314
7314
|
"motion",
|
|
7315
7315
|
"object",
|
|
7316
|
-
"audio"
|
|
7316
|
+
"audio",
|
|
7317
|
+
"mosaic"
|
|
7317
7318
|
]);
|
|
7318
|
-
|
|
7319
|
+
/**
|
|
7320
|
+
* The owner types that are event tables, in the order the event-media resolver
|
|
7321
|
+
* should consider them. Exported so a consumer asking "is this key an event?"
|
|
7322
|
+
* does not re-spell the list and drift from it.
|
|
7323
|
+
*/
|
|
7324
|
+
var EVENT_OWNER_TYPES = [
|
|
7319
7325
|
"motion",
|
|
7320
7326
|
"object",
|
|
7321
7327
|
"audio"
|
|
7322
|
-
]
|
|
7328
|
+
];
|
|
7329
|
+
/**
|
|
7330
|
+
* The same list as a Zod enum, for the cap inputs that must NAME the table
|
|
7331
|
+
* (D482: `getEventMedia` / `listEventMedia` take an owner, and an owner is
|
|
7332
|
+
* `(table, id)`).
|
|
7333
|
+
*
|
|
7334
|
+
* Built FROM {@link EVENT_OWNER_TYPES} rather than re-spelled: a fourth event
|
|
7335
|
+
* table would otherwise be accepted by the codec and refused at the door, with
|
|
7336
|
+
* nothing failing until a caller asked.
|
|
7337
|
+
*/
|
|
7338
|
+
var EventOwnerTypeSchema = _enum(EVENT_OWNER_TYPES);
|
|
7339
|
+
new Set(EVENT_OWNER_TYPES);
|
|
7323
7340
|
var EncodeProfileSchema = object({
|
|
7324
7341
|
video: object({
|
|
7325
7342
|
codec: _enum([
|
|
@@ -7358,7 +7375,23 @@ var EncodeProfileSchema = object({
|
|
|
7358
7375
|
"zerolatency",
|
|
7359
7376
|
"film",
|
|
7360
7377
|
"animation"
|
|
7361
|
-
]).optional()
|
|
7378
|
+
]).optional(),
|
|
7379
|
+
/**
|
|
7380
|
+
* ONE slice per access unit.
|
|
7381
|
+
*
|
|
7382
|
+
* `-tune zerolatency` turns on x264's sliced threads, and a frame then leaves
|
|
7383
|
+
* the encoder as five NAL slices that share one RTP timestamp and carry one
|
|
7384
|
+
* marker bit. A libwebrtc depacketiser sees five frame-starts and one
|
|
7385
|
+
* frame-end per frame: the first pictures render and the video then freezes
|
|
7386
|
+
* for good while the audio, on its own plane, plays on. Measured on this hub
|
|
7387
|
+
* 2026-09-13 against the Echo, and reduced to one slice by this flag alone.
|
|
7388
|
+
*
|
|
7389
|
+
* A NAMED field and not a raw flag, because {@link EgressEncodeSchema} omits
|
|
7390
|
+
* `outputArgs` on purpose: an opaque array is part of the sharing key, so two
|
|
7391
|
+
* consumers meaning the same thing spelled differently would stop sharing one
|
|
7392
|
+
* child. Absent means "whatever the encoder does" — today's behaviour.
|
|
7393
|
+
*/
|
|
7394
|
+
singleSlicePerFrame: boolean().optional()
|
|
7362
7395
|
}),
|
|
7363
7396
|
audio: union([literal("passthrough"), object({
|
|
7364
7397
|
codec: _enum([
|
|
@@ -7408,7 +7441,7 @@ var BASE_LIVE_EGRESS_PROFILE = {
|
|
|
7408
7441
|
audio: "passthrough"
|
|
7409
7442
|
};
|
|
7410
7443
|
({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
|
|
7411
|
-
({ ...BASE_LIVE_EGRESS_PROFILE });
|
|
7444
|
+
({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
|
|
7412
7445
|
/**
|
|
7413
7446
|
* Deep wiring healthcheck — snapshot of active reachability probes across
|
|
7414
7447
|
* every declared capability + widget of every installed plugin, on every
|
|
@@ -12416,6 +12449,16 @@ method(object({
|
|
|
12416
12449
|
filter: QueryFilterSchema.optional(),
|
|
12417
12450
|
columns: array(string()).readonly().optional()
|
|
12418
12451
|
}), array(SettingsRecordSchema).readonly()), method(object({
|
|
12452
|
+
namespace: string().optional(),
|
|
12453
|
+
collection: string(),
|
|
12454
|
+
/** Declared columns identifying the slot; must be covered by a UNIQUE
|
|
12455
|
+
* index on the collection. Never empty. */
|
|
12456
|
+
conflict: array(string()).readonly(),
|
|
12457
|
+
record: BulkRecordSchema
|
|
12458
|
+
}), object({
|
|
12459
|
+
/** The id the row HAS: assigned by SQLite on an insert, or the existing
|
|
12460
|
+
* row's own id on an update. */
|
|
12461
|
+
id: union([string(), number()]) }), { kind: "mutation" }), method(object({
|
|
12419
12462
|
namespace: string().optional(),
|
|
12420
12463
|
collection: string(),
|
|
12421
12464
|
record: object({
|
|
@@ -12550,6 +12593,14 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
|
|
|
12550
12593
|
id: union([string(), number()]) }), {
|
|
12551
12594
|
kind: "mutation",
|
|
12552
12595
|
auth: "admin"
|
|
12596
|
+
}), method(object({
|
|
12597
|
+
namespace: string().optional(),
|
|
12598
|
+
collection: string(),
|
|
12599
|
+
conflict: array(string()).readonly(),
|
|
12600
|
+
record: BulkRecordSchema
|
|
12601
|
+
}), object({ id: union([string(), number()]) }), {
|
|
12602
|
+
kind: "mutation",
|
|
12603
|
+
auth: "admin"
|
|
12553
12604
|
}), method(object({
|
|
12554
12605
|
namespace: string().optional(),
|
|
12555
12606
|
collection: string(),
|
|
@@ -18847,8 +18898,8 @@ var TrackPositionSchema = object({
|
|
|
18847
18898
|
var TrackSnapshotSchema = object({
|
|
18848
18899
|
timestamp: number(),
|
|
18849
18900
|
position: TrackPositionSchema,
|
|
18850
|
-
/**
|
|
18851
|
-
|
|
18901
|
+
/** The snapshot's media row id (D482); resolve via `listTrackMedia({ trackId })`. */
|
|
18902
|
+
mediaId: number().int()
|
|
18852
18903
|
});
|
|
18853
18904
|
/**
|
|
18854
18905
|
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
@@ -19452,14 +19503,14 @@ var ObjectEventSchema = object({
|
|
|
19452
19503
|
* pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
|
|
19453
19504
|
frameWidth: number().optional(),
|
|
19454
19505
|
frameHeight: number().optional(),
|
|
19455
|
-
/**
|
|
19456
|
-
|
|
19457
|
-
/** Design B:
|
|
19506
|
+
/** Media row id of the crop attached to this event (if any) — D482. */
|
|
19507
|
+
mediaId: number().int().optional(),
|
|
19508
|
+
/** Design B: media row id of the track's native-resolution key frame (the
|
|
19458
19509
|
* best-detection full frame). Resolve via the event-media data-plane
|
|
19459
|
-
* (`/addon/<addonId>/event-media/<
|
|
19510
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`) for a detail view that
|
|
19460
19511
|
* draws `bbox` over the native frame. Absent on legacy rows / non-decoded
|
|
19461
|
-
* sources — consumers fall back to `
|
|
19462
|
-
|
|
19512
|
+
* sources — consumers fall back to `mediaId` (the tight crop). */
|
|
19513
|
+
keyFrameMediaId: number().int().optional(),
|
|
19463
19514
|
/** Populated by B5 (recording playback URL for this event). */
|
|
19464
19515
|
mediaUrl: string().optional(),
|
|
19465
19516
|
/** The parent track's key-event importance [0,1], propagated to every object
|
|
@@ -19509,7 +19560,7 @@ var MediaFileKindEnum = _enum([
|
|
|
19509
19560
|
* hub-main's heap on the way past — for an `<img>` that would have cached it.
|
|
19510
19561
|
*
|
|
19511
19562
|
* `url` points at the `event-media` data plane
|
|
19512
|
-
* (`/addon/<addonId>/event-media/<
|
|
19563
|
+
* (`/addon/<addonId>/event-media/m/<mediaId>` — D482), which serves the same blob
|
|
19513
19564
|
* with an ETag and `Cache-Control: immutable`, honours conditional GETs, can
|
|
19514
19565
|
* render a `?variant=thumb`, and streams. The hub gate in front of it requires
|
|
19515
19566
|
* a bearer or the session cookie (`access: 'authenticated'`), so the bytes are
|
|
@@ -19517,10 +19568,13 @@ var MediaFileKindEnum = _enum([
|
|
|
19517
19568
|
* `data-plane-access.ts` for the rule and the one gap it does not close
|
|
19518
19569
|
* (per-device scoping).
|
|
19519
19570
|
*
|
|
19520
|
-
* The URL is built from the row's
|
|
19521
|
-
*
|
|
19571
|
+
* The URL is built from the row's own id, which since D482 says nothing about
|
|
19572
|
+
* the row's owner or kind — and that is the point. The published `kind` is not
|
|
19573
|
+
* the stored one (a track's face/plate crop is stored as `crop` under
|
|
19522
19574
|
* `('face'|'plate', '<prefix>-<trackId>')` and published as
|
|
19523
|
-
* `faceCrop`/`plateCrop
|
|
19575
|
+
* `faceCrop`/`plateCrop`), and under the old composite key the URL had to be
|
|
19576
|
+
* taken from `row.key` verbatim or it 404'd exactly those two rows. An id
|
|
19577
|
+
* cannot be mis-reconstructed, because there is nothing in it to reconstruct.
|
|
19524
19578
|
*
|
|
19525
19579
|
* ## `base64` is TRANSITIONAL and is going away
|
|
19526
19580
|
*
|
|
@@ -19533,7 +19587,19 @@ var MediaFileKindEnum = _enum([
|
|
|
19533
19587
|
* `analytics-query-facade.ts`; nothing else reads it.
|
|
19534
19588
|
*/
|
|
19535
19589
|
var MediaFileSchema = object({
|
|
19536
|
-
|
|
19590
|
+
/**
|
|
19591
|
+
* The media row's OWN id — the rowid SQLite assigned it (D482).
|
|
19592
|
+
*
|
|
19593
|
+
* It used to be the row's composite key, `<ownerType>:<ownerId>:<fileKind>
|
|
19594
|
+
* [:<timestampMs>]`, which embedded a FOREIGN id. D474 made event ids
|
|
19595
|
+
* per-table rowid aliases, so `object:101314` and `motion:101314` are two
|
|
19596
|
+
* different rows that spell the same number, and a track whose
|
|
19597
|
+
* `bestEventId` was an object event was served a motion event's snapshot —
|
|
19598
|
+
* a night-time thumbnail on an afternoon track, with no error anywhere. A
|
|
19599
|
+
* surrogate id cannot name the wrong row's owner, because it names no owner
|
|
19600
|
+
* at all.
|
|
19601
|
+
*/
|
|
19602
|
+
mediaId: number().int(),
|
|
19537
19603
|
kind: MediaFileKindEnum,
|
|
19538
19604
|
sizeBytes: number(),
|
|
19539
19605
|
timestamp: number()
|
|
@@ -19641,7 +19707,7 @@ var RetrainTrackSchema = object({
|
|
|
19641
19707
|
});
|
|
19642
19708
|
/** A frame the picker may offer — an index row, no blob was read to produce it. */
|
|
19643
19709
|
var RetrainFrameCandidateSchema = object({
|
|
19644
|
-
|
|
19710
|
+
mediaId: number().int(),
|
|
19645
19711
|
kind: MediaFileKindEnum,
|
|
19646
19712
|
timestamp: number(),
|
|
19647
19713
|
sizeBytes: number().int(),
|
|
@@ -19655,7 +19721,7 @@ var RetrainFrameSchema = object({
|
|
|
19655
19721
|
deviceId: number(),
|
|
19656
19722
|
trackId: string(),
|
|
19657
19723
|
/** Provenance only. It may already point at nothing — that is expected. */
|
|
19658
|
-
|
|
19724
|
+
sourceMediaId: number().int(),
|
|
19659
19725
|
sourceKind: MediaFileKindEnum,
|
|
19660
19726
|
sizeBytes: number().int(),
|
|
19661
19727
|
width: number().int(),
|
|
@@ -19671,7 +19737,7 @@ var RetrainCopyRefusalSchema = _enum([
|
|
|
19671
19737
|
var RetrainFrameSelectionSchema = object({
|
|
19672
19738
|
copied: array(RetrainFrameSchema).readonly(),
|
|
19673
19739
|
refused: array(object({
|
|
19674
|
-
|
|
19740
|
+
sourceMediaId: number().int(),
|
|
19675
19741
|
reason: RetrainCopyRefusalSchema
|
|
19676
19742
|
})).readonly()
|
|
19677
19743
|
});
|
|
@@ -19679,7 +19745,7 @@ var RetrainFrameListSchema = object({
|
|
|
19679
19745
|
candidates: array(RetrainFrameCandidateSchema).readonly(),
|
|
19680
19746
|
copies: array(RetrainFrameSchema).readonly(),
|
|
19681
19747
|
/** What the page pre-selects — the native key frame when one survives. */
|
|
19682
|
-
|
|
19748
|
+
autoPickMediaId: number().int().optional()
|
|
19683
19749
|
});
|
|
19684
19750
|
/** What the operator asked the assist to look for. */
|
|
19685
19751
|
var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
|
|
@@ -19774,9 +19840,11 @@ var RecentTracksQueryInput = object({
|
|
|
19774
19840
|
});
|
|
19775
19841
|
/**
|
|
19776
19842
|
* A Summary (D359): the per-camera session envelope that references tracks.
|
|
19777
|
-
* `
|
|
19778
|
-
* served by the event-media plane
|
|
19779
|
-
* member visible has been materialised
|
|
19843
|
+
* `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
|
|
19844
|
+
* 'summary'`, served by the event-media plane at `/m/<id>`), null until the
|
|
19845
|
+
* first frame with a member visible has been materialised (D482 — it was the
|
|
19846
|
+
* row's composite key, which embedded the owner and could name another table's
|
|
19847
|
+
* row once event ids became per-table rowids).
|
|
19780
19848
|
*/
|
|
19781
19849
|
var SummarySchema = object({
|
|
19782
19850
|
id: string(),
|
|
@@ -19785,19 +19853,115 @@ var SummarySchema = object({
|
|
|
19785
19853
|
lastActiveAt: number(),
|
|
19786
19854
|
sealedAt: number().nullable(),
|
|
19787
19855
|
memberCount: number().int().nonnegative(),
|
|
19788
|
-
|
|
19856
|
+
groupShotMediaId: number().int().nullable()
|
|
19789
19857
|
});
|
|
19790
19858
|
var SummariesQueryInput = object({
|
|
19791
19859
|
deviceIds: array(number()).min(1),
|
|
19792
19860
|
since: number().optional(),
|
|
19793
19861
|
until: number().optional(),
|
|
19794
|
-
limit: number().int().min(1).max(200).default(50)
|
|
19862
|
+
limit: number().int().min(1).max(200).default(50),
|
|
19863
|
+
/** The same member-wise filter {@link listRecentSummaries} takes — one
|
|
19864
|
+
* meaning of "dog" on every summary surface. */
|
|
19865
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
19795
19866
|
});
|
|
19796
|
-
var SummariesPageSchema = object({ summaries: array(SummarySchema).readonly() });
|
|
19797
19867
|
var SummaryDetailSchema = object({
|
|
19798
19868
|
summary: SummarySchema,
|
|
19799
|
-
/**
|
|
19800
|
-
|
|
19869
|
+
/** Members in absorption order, oldest join first. */
|
|
19870
|
+
members: array(object({
|
|
19871
|
+
trackId: string(),
|
|
19872
|
+
/**
|
|
19873
|
+
* The track's class at the time it JOINED, or `null` when it was unresolved
|
|
19874
|
+
* and the track no longer exists to fill it.
|
|
19875
|
+
*
|
|
19876
|
+
* The join, not the latest opinion: class voting can re-decide a track's
|
|
19877
|
+
* class afterwards, and a group's composition is the history of who came
|
|
19878
|
+
* together. A consumer counts these to badge a thumbnail — "two people and a
|
|
19879
|
+
* dog" — rather than being handed a second, denormalised tally that would
|
|
19880
|
+
* drift from the members it claims to describe.
|
|
19881
|
+
*/
|
|
19882
|
+
className: string().nullable(),
|
|
19883
|
+
/** `primary` is the one member that carries the group's identity. */
|
|
19884
|
+
role: _enum([
|
|
19885
|
+
"primary",
|
|
19886
|
+
"sibling",
|
|
19887
|
+
"child"
|
|
19888
|
+
]).nullable(),
|
|
19889
|
+
joinedAt: number(),
|
|
19890
|
+
/** Tier 1 — the sub-class (`dog`, `van`), resolved from the member's track
|
|
19891
|
+
* at read time. Absent when nothing resolved, never an empty string. */
|
|
19892
|
+
label: string().optional(),
|
|
19893
|
+
/** Tier 2 — the instance: a person's name, a plate. Absent when the pipeline
|
|
19894
|
+
* recognised nobody, and absent for a member whose track has been pruned —
|
|
19895
|
+
* a thumbnail that names the wrong person is worse than one naming nobody. */
|
|
19896
|
+
subLabel: string().optional()
|
|
19897
|
+
})).readonly()
|
|
19898
|
+
});
|
|
19899
|
+
/**
|
|
19900
|
+
* What a LIST of groups carries: the envelope plus what it is MADE OF.
|
|
19901
|
+
*
|
|
19902
|
+
* Coarse on purpose — the operator's rule is "only the rough data on the list,
|
|
19903
|
+
* we extend when we notice we need more". Enough to draw the card ("two people
|
|
19904
|
+
* and a dog") and no more. The MEMBERS, their names and the per-member links
|
|
19905
|
+
* are on {@link getSummary}: shipping every member of every group so a client
|
|
19906
|
+
* can count them turns a page of two hundred groups into a thousand records to
|
|
19907
|
+
* draw two hundred badges.
|
|
19908
|
+
*/
|
|
19909
|
+
var SummaryListItemSchema = object({
|
|
19910
|
+
summary: SummarySchema,
|
|
19911
|
+
/** Class counts, most numerous first; `className: null` is a member whose
|
|
19912
|
+
* class never resolved, counted so the counts add up to `memberCount`. */
|
|
19913
|
+
classes: array(object({
|
|
19914
|
+
className: string().nullable(),
|
|
19915
|
+
count: number().int().positive()
|
|
19916
|
+
})).readonly()
|
|
19917
|
+
});
|
|
19918
|
+
var SummariesPageSchema = object({ summaries: array(SummaryListItemSchema).readonly() });
|
|
19919
|
+
/**
|
|
19920
|
+
* The paged feed, deliberately the SAME shape as {@link RecentTracksQueryInput}.
|
|
19921
|
+
*
|
|
19922
|
+
* The reel on the cameras page and the Events gallery both ride a cursor, so a
|
|
19923
|
+
* summaries feed that could only answer "the last N for these cameras"
|
|
19924
|
+
* (`listSummaries`) would make groups available in the timeline and nowhere
|
|
19925
|
+
* else. Two feeds with different ordering contracts would be two ideas of what
|
|
19926
|
+
* "newest" means, on one screen.
|
|
19927
|
+
*/
|
|
19928
|
+
var RecentSummariesQueryInput = object({
|
|
19929
|
+
/** Devices to merge. An empty array yields an empty page. */
|
|
19930
|
+
deviceIds: array(number()),
|
|
19931
|
+
/** Window lower bound on `lastActiveAt` (inclusive). */
|
|
19932
|
+
since: number().optional(),
|
|
19933
|
+
/** Window upper bound on `lastActiveAt` (inclusive). */
|
|
19934
|
+
until: number().optional(),
|
|
19935
|
+
limit: number().int().min(1).max(500).default(100),
|
|
19936
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`. */
|
|
19937
|
+
cursor: string().optional(),
|
|
19938
|
+
/**
|
|
19939
|
+
* Restrict to these classes — THE SAME FIELD `listRecentTracks` takes, and
|
|
19940
|
+
* deliberately the same name: the events filter tree emits one list of ticked
|
|
19941
|
+
* taxonomy nodes, and a summaries feed that called it something else would
|
|
19942
|
+
* make the operator's one filter component produce two shapes.
|
|
19943
|
+
*
|
|
19944
|
+
* A question about the MEMBERS: a group matches when ANY of them does. "Show
|
|
19945
|
+
* me the arrivals with a dog" has to return the group of four people who had
|
|
19946
|
+
* one with them; a filter on the group's own fields could only ever answer
|
|
19947
|
+
* about its primary.
|
|
19948
|
+
*
|
|
19949
|
+
* Matched against all THREE tiers of a member — the class (`animal`), the
|
|
19950
|
+
* sub-class (`dog`) and the instance (a name, a plate) — because which tier a
|
|
19951
|
+
* ticked node lives on is the taxonomy's business, not the caller's. `dog` is
|
|
19952
|
+
* an event kind in the tree and a tier-1 label on an `animal` track; a filter
|
|
19953
|
+
* that read only the class would answer "animal" and never "dog".
|
|
19954
|
+
*
|
|
19955
|
+
* ABSENT or EMPTY means no filter — absent is not a selection of none.
|
|
19956
|
+
*/
|
|
19957
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
19958
|
+
});
|
|
19959
|
+
var RecentSummariesPageSchema = object({
|
|
19960
|
+
/** Ordered by (`lastActiveAt` DESC, id DESC). Same light item as
|
|
19961
|
+
* {@link listSummaries} — one list shape, so a card renders the same
|
|
19962
|
+
* whichever feed drew it. */
|
|
19963
|
+
summaries: array(SummaryListItemSchema).readonly(),
|
|
19964
|
+
nextCursor: string().nullable()
|
|
19801
19965
|
});
|
|
19802
19966
|
var RecentTracksPageSchema = object({
|
|
19803
19967
|
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
@@ -20211,7 +20375,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20211
20375
|
classes: array(string()).optional(),
|
|
20212
20376
|
/** See {@link ExcludeSourcesDoc}. */
|
|
20213
20377
|
excludeSources: array(TrackSourceSchema).optional()
|
|
20214
|
-
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
20378
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(RecentSummariesQueryInput, RecentSummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
20215
20379
|
kind: "mutation",
|
|
20216
20380
|
auth: "admin"
|
|
20217
20381
|
}), 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({
|
|
@@ -20339,7 +20503,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20339
20503
|
}), method(object({
|
|
20340
20504
|
deviceId: number(),
|
|
20341
20505
|
trackId: string(),
|
|
20342
|
-
|
|
20506
|
+
mediaIds: array(number().int()).min(1)
|
|
20343
20507
|
}), RetrainFrameSelectionSchema, {
|
|
20344
20508
|
kind: "mutation",
|
|
20345
20509
|
auth: "admin"
|
|
@@ -20407,7 +20571,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20407
20571
|
kind: "query",
|
|
20408
20572
|
auth: "admin"
|
|
20409
20573
|
}), method(object({
|
|
20410
|
-
|
|
20574
|
+
/** Which of the three event tables owns the row. */
|
|
20575
|
+
ownerType: EventOwnerTypeSchema,
|
|
20576
|
+
/** The event's rowid in that table (D474: an event id is a number). */
|
|
20577
|
+
eventId: number().int(),
|
|
20411
20578
|
kind: MediaFileKindEnum.optional(),
|
|
20412
20579
|
deviceId: number()
|
|
20413
20580
|
}), array(MediaFileSchema).readonly()), method(object({
|
|
@@ -20418,7 +20585,8 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20418
20585
|
trackId: string(),
|
|
20419
20586
|
deviceId: number()
|
|
20420
20587
|
}), array(MediaFileInfoSchema).readonly()), method(object({
|
|
20421
|
-
|
|
20588
|
+
ownerType: EventOwnerTypeSchema,
|
|
20589
|
+
eventId: number().int(),
|
|
20422
20590
|
deviceId: number()
|
|
20423
20591
|
}), array(MediaFileInfoSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
|
|
20424
20592
|
kind: "mutation",
|
|
@@ -24985,8 +25153,8 @@ var IdentitySchema = object({
|
|
|
24985
25153
|
id: string(),
|
|
24986
25154
|
name: string(),
|
|
24987
25155
|
sampleCount: number().int().nonnegative(),
|
|
24988
|
-
|
|
24989
|
-
/** Inline base64 of the cover sample's crop, resolved from `
|
|
25156
|
+
coverMediaId: number().int().optional(),
|
|
25157
|
+
/** Inline base64 of the cover sample's crop, resolved from `coverMediaId`.
|
|
24990
25158
|
* Lets the UI render the person's face avatar instead of a placeholder icon. */
|
|
24991
25159
|
coverBase64: string().optional()
|
|
24992
25160
|
});
|
|
@@ -25012,8 +25180,8 @@ var IdentitySampleAuditRowSchema = object({
|
|
|
25012
25180
|
enrolledAt: number().int(),
|
|
25013
25181
|
deviceId: number().int().optional(),
|
|
25014
25182
|
source: _enum(["detected", "photo"]),
|
|
25015
|
-
/** The enrolled crop's media
|
|
25016
|
-
|
|
25183
|
+
/** The enrolled crop's media row id, so the panel can show the evidence. */
|
|
25184
|
+
mediaId: number().int().optional(),
|
|
25017
25185
|
/**
|
|
25018
25186
|
* False = the sample is stamped with a DIFFERENT face model, and a cosine
|
|
25019
25187
|
* across feature spaces is a well-formed float with no meaning. Every number
|
|
@@ -25082,15 +25250,15 @@ var FaceInfoSchema = object({
|
|
|
25082
25250
|
*/
|
|
25083
25251
|
cropUrl: string().optional(),
|
|
25084
25252
|
/** Design B: the face bbox (pixel space) on the key frame — lets a detail
|
|
25085
|
-
* view draw the box over the native `
|
|
25253
|
+
* view draw the box over the native `keyFrameMediaId` frame. Absent on
|
|
25086
25254
|
* legacy rows written before design B. */
|
|
25087
25255
|
faceBbox: BoundingBoxSchema.optional(),
|
|
25088
25256
|
/** Design B: MediaStore key of the track's native-resolution key frame.
|
|
25089
25257
|
* Fetch the native JPEG via the event-media data-plane
|
|
25090
|
-
* (`/addon/<addonId>/event-media/<
|
|
25258
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`). Absent when the
|
|
25091
25259
|
* track produced no key frame (e.g. native/onboard source) — the UI falls
|
|
25092
25260
|
* back to the inline `base64` face crop. */
|
|
25093
|
-
|
|
25261
|
+
keyFrameMediaId: number().int().optional(),
|
|
25094
25262
|
/** Winning identity-match cosine (0..1) for this face's track, when an
|
|
25095
25263
|
* identity was auto-confirmed. Lets the UI surface WHY a face was assigned
|
|
25096
25264
|
* (confidence badge / low-confidence audit). Absent on legacy rows and on
|
|
@@ -25159,11 +25327,14 @@ var FaceClusterSchema = object({
|
|
|
25159
25327
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
25160
25328
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
25161
25329
|
*
|
|
25162
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
25163
|
-
* media
|
|
25330
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
25331
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
25332
|
+
* access decision.
|
|
25164
25333
|
*/
|
|
25165
25334
|
var MediaFileLiteSchema$1 = object({
|
|
25166
|
-
|
|
25335
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
25336
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
25337
|
+
mediaId: number().int(),
|
|
25167
25338
|
kind: string(),
|
|
25168
25339
|
url: string(),
|
|
25169
25340
|
sizeBytes: number(),
|
|
@@ -25180,7 +25351,7 @@ method(object({
|
|
|
25180
25351
|
* covers inline, ~10 KB of base64 per row, on a query this UI mounts
|
|
25181
25352
|
* four times and the viewer holds at `staleTime: 30_000`.
|
|
25182
25353
|
*
|
|
25183
|
-
* Nothing loses its avatar: `
|
|
25354
|
+
* Nothing loses its avatar: `coverMediaId` is already on every row and
|
|
25184
25355
|
* the `event-media` plane serves that key `immutable` with an ETag.
|
|
25185
25356
|
*
|
|
25186
25357
|
* **This is an INPUT field, so it does not reach the addon until the
|
|
@@ -27648,8 +27819,8 @@ var VehicleSchema = object({
|
|
|
27648
27819
|
id: string(),
|
|
27649
27820
|
name: string(),
|
|
27650
27821
|
sampleCount: number().int().nonnegative(),
|
|
27651
|
-
|
|
27652
|
-
/** Inline base64 of the cover sample's plate crop, resolved from `
|
|
27822
|
+
coverMediaId: number().int().optional(),
|
|
27823
|
+
/** Inline base64 of the cover sample's plate crop, resolved from `coverMediaId`. */
|
|
27653
27824
|
coverBase64: string().optional()
|
|
27654
27825
|
});
|
|
27655
27826
|
var VehicleSampleInfoSchema = object({
|
|
@@ -27682,7 +27853,7 @@ var PlateInfoSchema = object({
|
|
|
27682
27853
|
/** keyFrame parity: the plate bbox (pixel space) on the native key frame. */
|
|
27683
27854
|
plateBbox: BoundingBoxSchema.optional(),
|
|
27684
27855
|
/** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
|
|
27685
|
-
|
|
27856
|
+
keyFrameMediaId: number().int().optional(),
|
|
27686
27857
|
base64: string().optional(),
|
|
27687
27858
|
/**
|
|
27688
27859
|
* Same crop as a data-plane URL, always present when the plate has a stored
|
|
@@ -27703,11 +27874,14 @@ var PlateInfoSchema = object({
|
|
|
27703
27874
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
27704
27875
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
27705
27876
|
*
|
|
27706
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
27707
|
-
* media
|
|
27877
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
27878
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
27879
|
+
* access decision.
|
|
27708
27880
|
*/
|
|
27709
27881
|
var MediaFileLiteSchema = object({
|
|
27710
|
-
|
|
27882
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
27883
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
27884
|
+
mediaId: number().int(),
|
|
27711
27885
|
kind: string(),
|
|
27712
27886
|
url: string(),
|
|
27713
27887
|
sizeBytes: number(),
|
|
@@ -27766,7 +27940,7 @@ method(object({
|
|
|
27766
27940
|
}), method(object({
|
|
27767
27941
|
/** Inline {@link VehicleSchema.coverBase64} on every row. Default
|
|
27768
27942
|
* `false` — the vehicle twin of `faceGallery.listIdentities`'s
|
|
27769
|
-
* option; `
|
|
27943
|
+
* option; `coverMediaId` + the `event-media` plane carry the picture.
|
|
27770
27944
|
* INPUT field: stripped by the hub router until the train ships, which
|
|
27771
27945
|
* resolves to `false` and is exactly the intended default. */
|
|
27772
27946
|
includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
|
|
@@ -29132,7 +29306,14 @@ var SceneReferenceSchema = object({
|
|
|
29132
29306
|
modelId: string(),
|
|
29133
29307
|
condition: SceneConditionSchema,
|
|
29134
29308
|
capturedAt: number(),
|
|
29135
|
-
|
|
29309
|
+
/**
|
|
29310
|
+
* The reference thumbnail's media ROW id (D482).
|
|
29311
|
+
*
|
|
29312
|
+
* The name already said `mediaId` while the value was the row's composite
|
|
29313
|
+
* key — a leftover that read as done and was not. It is the row's own id
|
|
29314
|
+
* now, addressed at `/addon/<addonId>/event-media/m/<id>`.
|
|
29315
|
+
*/
|
|
29316
|
+
thumbnailMediaId: number().int().optional(),
|
|
29136
29317
|
/** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
|
|
29137
29318
|
* anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
|
|
29138
29319
|
* normalized rect frame a different piece of world, and the scene would
|
|
@@ -29946,7 +30127,29 @@ var LoggingSettingsPatchSchema = object({
|
|
|
29946
30127
|
* disarmed the channels it did not mention would make the Levels page and
|
|
29947
30128
|
* the Diagnostics page fight over the same value.
|
|
29948
30129
|
*/
|
|
29949
|
-
channels: array(LogChannelWindowPatchSchema).readonly().optional()
|
|
30130
|
+
channels: array(LogChannelWindowPatchSchema).readonly().optional(),
|
|
30131
|
+
/**
|
|
30132
|
+
* How many days the analytics OPS LOG is kept — the audit trail of what
|
|
30133
|
+
* retention actually deleted.
|
|
30134
|
+
*
|
|
30135
|
+
* It lives HERE, on the logging document, and not on the analytics addon's
|
|
30136
|
+
* settings form, on the operator's instruction: every other log-ish window in
|
|
30137
|
+
* this system is configured through this one document, and a retention audit
|
|
30138
|
+
* configured somewhere else is a second place to look when the question is
|
|
30139
|
+
* "what happened to my data".
|
|
30140
|
+
*
|
|
30141
|
+
* That placement has a cost worth stating: this document ships in the
|
|
30142
|
+
* framework closure, so this knob needs a published `@camstack/server` while
|
|
30143
|
+
* the four windows beside it (D485) reach a node on `camstack deploy`.
|
|
30144
|
+
*
|
|
30145
|
+
* `retention-model.ts` argued this one must NOT follow a device window,
|
|
30146
|
+
* because the audit trail is the history of the SWEEP and not of the camera.
|
|
30147
|
+
* That argument stands and is untouched — what changes is that 30 days stops
|
|
30148
|
+
* being a constant nobody can reach. `0` keeps it forever. The floor is 1 day
|
|
30149
|
+
* rather than 0-as-delete: an audit log truncated to nothing is precisely the
|
|
30150
|
+
* state in which the next 9.5 GiB leak cannot be explained.
|
|
30151
|
+
*/
|
|
30152
|
+
opsLogRetentionDays: number().int().min(0).max(3650).optional()
|
|
29950
30153
|
});
|
|
29951
30154
|
/**
|
|
29952
30155
|
* Which LAYER of the hierarchy is addressed. Absent = the cluster layer.
|
|
@@ -30019,6 +30222,14 @@ var LoggingSettingsStateSchema = object({
|
|
|
30019
30222
|
channels: array(LogChannelDescriptorSchema).readonly(),
|
|
30020
30223
|
/** The channels ARMED right now, each with its deadline. */
|
|
30021
30224
|
activeChannels: array(LogChannelWindowStateSchema).readonly(),
|
|
30225
|
+
/**
|
|
30226
|
+
* The ops-log window in days, as it is in force. `0` = kept forever.
|
|
30227
|
+
*
|
|
30228
|
+
* Reported rather than left to the caller's memory of what it wrote: this is
|
|
30229
|
+
* the value the analytics sweep will actually use, and an operator asking how
|
|
30230
|
+
* long their audit trail lives should not have to infer it from a default.
|
|
30231
|
+
*/
|
|
30232
|
+
opsLogRetentionDays: number().int().min(0),
|
|
30022
30233
|
persisted: boolean()
|
|
30023
30234
|
});
|
|
30024
30235
|
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(), {
|
|
@@ -30580,7 +30791,7 @@ var StationaryObjectSchema = object({
|
|
|
30580
30791
|
/** Enrichment label carried from the source track (identity / plate). */
|
|
30581
30792
|
label: string().optional(),
|
|
30582
30793
|
/** Native-resolution key-frame media key for the parked object's best image. */
|
|
30583
|
-
|
|
30794
|
+
keyFrameMediaId: number().int().optional()
|
|
30584
30795
|
});
|
|
30585
30796
|
var CameraOccupancySnapshotSchema = object({
|
|
30586
30797
|
/** Frame timestamp of the inference result that produced this snapshot. */
|
|
@@ -32562,6 +32773,12 @@ Object.freeze({
|
|
|
32562
32773
|
addonId: null,
|
|
32563
32774
|
access: "create"
|
|
32564
32775
|
},
|
|
32776
|
+
"dataStoreProvider.upsert": {
|
|
32777
|
+
capName: "data-store-provider",
|
|
32778
|
+
capScope: "system",
|
|
32779
|
+
addonId: null,
|
|
32780
|
+
access: "create"
|
|
32781
|
+
},
|
|
32565
32782
|
"dayNight.getOptions": {
|
|
32566
32783
|
capName: "day-night",
|
|
32567
32784
|
capScope: "device",
|
|
@@ -34998,6 +35215,12 @@ Object.freeze({
|
|
|
34998
35215
|
addonId: null,
|
|
34999
35216
|
access: "view"
|
|
35000
35217
|
},
|
|
35218
|
+
"pipelineAnalytics.listRecentSummaries": {
|
|
35219
|
+
capName: "pipeline-analytics",
|
|
35220
|
+
capScope: "device",
|
|
35221
|
+
addonId: null,
|
|
35222
|
+
access: "view"
|
|
35223
|
+
},
|
|
35001
35224
|
"pipelineAnalytics.listRecentTracks": {
|
|
35002
35225
|
capName: "pipeline-analytics",
|
|
35003
35226
|
capScope: "device",
|
|
@@ -36426,6 +36649,12 @@ Object.freeze({
|
|
|
36426
36649
|
addonId: null,
|
|
36427
36650
|
access: "create"
|
|
36428
36651
|
},
|
|
36652
|
+
"settingsStore.upsert": {
|
|
36653
|
+
capName: "settings-store",
|
|
36654
|
+
capScope: "system",
|
|
36655
|
+
addonId: null,
|
|
36656
|
+
access: "create"
|
|
36657
|
+
},
|
|
36429
36658
|
"smtpProvider.getStatus": {
|
|
36430
36659
|
capName: "smtp-provider",
|
|
36431
36660
|
capScope: "system",
|
|
@@ -38819,6 +39048,11 @@ Object.freeze({
|
|
|
38819
39048
|
form: "single",
|
|
38820
39049
|
optional: true
|
|
38821
39050
|
}],
|
|
39051
|
+
"pipelineAnalytics.listRecentSummaries": [{
|
|
39052
|
+
name: "deviceIds",
|
|
39053
|
+
form: "array",
|
|
39054
|
+
optional: false
|
|
39055
|
+
}],
|
|
38822
39056
|
"pipelineAnalytics.listRecentTracks": [{
|
|
38823
39057
|
name: "deviceIds",
|
|
38824
39058
|
form: "array",
|