@camstack/addon-mqtt-broker 1.2.99 → 1.2.101
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/mqtt-broker.addon.js +292 -58
- package/dist/mqtt-broker.addon.mjs +292 -58
- package/package.json +1 -1
|
@@ -44,7 +44,7 @@ let crypto$10 = __toESM(crypto$1, 1);
|
|
|
44
44
|
crypto$1 = __toESM(crypto$1);
|
|
45
45
|
let node_fs = require("node:fs");
|
|
46
46
|
let node_path = require("node:path");
|
|
47
|
-
//#region ../types/dist/event-category-
|
|
47
|
+
//#region ../types/dist/event-category-ZyX6jcse.mjs
|
|
48
48
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
49
49
|
EventCategory["SystemBoot"] = "system.boot";
|
|
50
50
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -605,7 +605,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
605
605
|
* a package zone — a newly-appeared stationary object of a package class
|
|
606
606
|
* that cleared the class / zone / dwell / size gates. Payload:
|
|
607
607
|
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
608
|
-
* entryId, className, zoneIds,
|
|
608
|
+
* entryId, className, zoneIds, keyFrameMediaId?, bbox, timestamp }`.
|
|
609
609
|
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
610
610
|
* this bus topic drives notifier rules + live UI. See
|
|
611
611
|
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
@@ -5391,7 +5391,7 @@ var ZodIssueCode = {
|
|
|
5391
5391
|
var ZodFirstPartyTypeKind;
|
|
5392
5392
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5393
5393
|
//#endregion
|
|
5394
|
-
//#region ../types/dist/sleep-
|
|
5394
|
+
//#region ../types/dist/sleep-DBKu2-U5.mjs
|
|
5395
5395
|
/**
|
|
5396
5396
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5397
5397
|
* window to float samples (D455).
|
|
@@ -7342,13 +7342,30 @@ new Set([
|
|
|
7342
7342
|
"scene",
|
|
7343
7343
|
"motion",
|
|
7344
7344
|
"object",
|
|
7345
|
-
"audio"
|
|
7345
|
+
"audio",
|
|
7346
|
+
"mosaic"
|
|
7346
7347
|
]);
|
|
7347
|
-
|
|
7348
|
+
/**
|
|
7349
|
+
* The owner types that are event tables, in the order the event-media resolver
|
|
7350
|
+
* should consider them. Exported so a consumer asking "is this key an event?"
|
|
7351
|
+
* does not re-spell the list and drift from it.
|
|
7352
|
+
*/
|
|
7353
|
+
var EVENT_OWNER_TYPES = [
|
|
7348
7354
|
"motion",
|
|
7349
7355
|
"object",
|
|
7350
7356
|
"audio"
|
|
7351
|
-
]
|
|
7357
|
+
];
|
|
7358
|
+
/**
|
|
7359
|
+
* The same list as a Zod enum, for the cap inputs that must NAME the table
|
|
7360
|
+
* (D482: `getEventMedia` / `listEventMedia` take an owner, and an owner is
|
|
7361
|
+
* `(table, id)`).
|
|
7362
|
+
*
|
|
7363
|
+
* Built FROM {@link EVENT_OWNER_TYPES} rather than re-spelled: a fourth event
|
|
7364
|
+
* table would otherwise be accepted by the codec and refused at the door, with
|
|
7365
|
+
* nothing failing until a caller asked.
|
|
7366
|
+
*/
|
|
7367
|
+
var EventOwnerTypeSchema = _enum(EVENT_OWNER_TYPES);
|
|
7368
|
+
new Set(EVENT_OWNER_TYPES);
|
|
7352
7369
|
var EncodeProfileSchema = object({
|
|
7353
7370
|
video: object({
|
|
7354
7371
|
codec: _enum([
|
|
@@ -7387,7 +7404,23 @@ var EncodeProfileSchema = object({
|
|
|
7387
7404
|
"zerolatency",
|
|
7388
7405
|
"film",
|
|
7389
7406
|
"animation"
|
|
7390
|
-
]).optional()
|
|
7407
|
+
]).optional(),
|
|
7408
|
+
/**
|
|
7409
|
+
* ONE slice per access unit.
|
|
7410
|
+
*
|
|
7411
|
+
* `-tune zerolatency` turns on x264's sliced threads, and a frame then leaves
|
|
7412
|
+
* the encoder as five NAL slices that share one RTP timestamp and carry one
|
|
7413
|
+
* marker bit. A libwebrtc depacketiser sees five frame-starts and one
|
|
7414
|
+
* frame-end per frame: the first pictures render and the video then freezes
|
|
7415
|
+
* for good while the audio, on its own plane, plays on. Measured on this hub
|
|
7416
|
+
* 2026-09-13 against the Echo, and reduced to one slice by this flag alone.
|
|
7417
|
+
*
|
|
7418
|
+
* A NAMED field and not a raw flag, because {@link EgressEncodeSchema} omits
|
|
7419
|
+
* `outputArgs` on purpose: an opaque array is part of the sharing key, so two
|
|
7420
|
+
* consumers meaning the same thing spelled differently would stop sharing one
|
|
7421
|
+
* child. Absent means "whatever the encoder does" — today's behaviour.
|
|
7422
|
+
*/
|
|
7423
|
+
singleSlicePerFrame: boolean().optional()
|
|
7391
7424
|
}),
|
|
7392
7425
|
audio: union([literal("passthrough"), object({
|
|
7393
7426
|
codec: _enum([
|
|
@@ -7437,7 +7470,7 @@ var BASE_LIVE_EGRESS_PROFILE = {
|
|
|
7437
7470
|
audio: "passthrough"
|
|
7438
7471
|
};
|
|
7439
7472
|
({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
|
|
7440
|
-
({ ...BASE_LIVE_EGRESS_PROFILE });
|
|
7473
|
+
({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
|
|
7441
7474
|
/**
|
|
7442
7475
|
* Deep wiring healthcheck — snapshot of active reachability probes across
|
|
7443
7476
|
* every declared capability + widget of every installed plugin, on every
|
|
@@ -12494,6 +12527,16 @@ method(object({
|
|
|
12494
12527
|
filter: QueryFilterSchema.optional(),
|
|
12495
12528
|
columns: array(string()).readonly().optional()
|
|
12496
12529
|
}), array(SettingsRecordSchema).readonly()), method(object({
|
|
12530
|
+
namespace: string().optional(),
|
|
12531
|
+
collection: string(),
|
|
12532
|
+
/** Declared columns identifying the slot; must be covered by a UNIQUE
|
|
12533
|
+
* index on the collection. Never empty. */
|
|
12534
|
+
conflict: array(string()).readonly(),
|
|
12535
|
+
record: BulkRecordSchema
|
|
12536
|
+
}), object({
|
|
12537
|
+
/** The id the row HAS: assigned by SQLite on an insert, or the existing
|
|
12538
|
+
* row's own id on an update. */
|
|
12539
|
+
id: union([string(), number()]) }), { kind: "mutation" }), method(object({
|
|
12497
12540
|
namespace: string().optional(),
|
|
12498
12541
|
collection: string(),
|
|
12499
12542
|
record: object({
|
|
@@ -12628,6 +12671,14 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
|
|
|
12628
12671
|
id: union([string(), number()]) }), {
|
|
12629
12672
|
kind: "mutation",
|
|
12630
12673
|
auth: "admin"
|
|
12674
|
+
}), method(object({
|
|
12675
|
+
namespace: string().optional(),
|
|
12676
|
+
collection: string(),
|
|
12677
|
+
conflict: array(string()).readonly(),
|
|
12678
|
+
record: BulkRecordSchema
|
|
12679
|
+
}), object({ id: union([string(), number()]) }), {
|
|
12680
|
+
kind: "mutation",
|
|
12681
|
+
auth: "admin"
|
|
12631
12682
|
}), method(object({
|
|
12632
12683
|
namespace: string().optional(),
|
|
12633
12684
|
collection: string(),
|
|
@@ -18863,8 +18914,8 @@ var TrackPositionSchema = object({
|
|
|
18863
18914
|
var TrackSnapshotSchema = object({
|
|
18864
18915
|
timestamp: number(),
|
|
18865
18916
|
position: TrackPositionSchema,
|
|
18866
|
-
/**
|
|
18867
|
-
|
|
18917
|
+
/** The snapshot's media row id (D482); resolve via `listTrackMedia({ trackId })`. */
|
|
18918
|
+
mediaId: number().int()
|
|
18868
18919
|
});
|
|
18869
18920
|
/**
|
|
18870
18921
|
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
@@ -19468,14 +19519,14 @@ var ObjectEventSchema = object({
|
|
|
19468
19519
|
* pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
|
|
19469
19520
|
frameWidth: number().optional(),
|
|
19470
19521
|
frameHeight: number().optional(),
|
|
19471
|
-
/**
|
|
19472
|
-
|
|
19473
|
-
/** Design B:
|
|
19522
|
+
/** Media row id of the crop attached to this event (if any) — D482. */
|
|
19523
|
+
mediaId: number().int().optional(),
|
|
19524
|
+
/** Design B: media row id of the track's native-resolution key frame (the
|
|
19474
19525
|
* best-detection full frame). Resolve via the event-media data-plane
|
|
19475
|
-
* (`/addon/<addonId>/event-media/<
|
|
19526
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`) for a detail view that
|
|
19476
19527
|
* draws `bbox` over the native frame. Absent on legacy rows / non-decoded
|
|
19477
|
-
* sources — consumers fall back to `
|
|
19478
|
-
|
|
19528
|
+
* sources — consumers fall back to `mediaId` (the tight crop). */
|
|
19529
|
+
keyFrameMediaId: number().int().optional(),
|
|
19479
19530
|
/** Populated by B5 (recording playback URL for this event). */
|
|
19480
19531
|
mediaUrl: string().optional(),
|
|
19481
19532
|
/** The parent track's key-event importance [0,1], propagated to every object
|
|
@@ -19525,7 +19576,7 @@ var MediaFileKindEnum = _enum([
|
|
|
19525
19576
|
* hub-main's heap on the way past — for an `<img>` that would have cached it.
|
|
19526
19577
|
*
|
|
19527
19578
|
* `url` points at the `event-media` data plane
|
|
19528
|
-
* (`/addon/<addonId>/event-media/<
|
|
19579
|
+
* (`/addon/<addonId>/event-media/m/<mediaId>` — D482), which serves the same blob
|
|
19529
19580
|
* with an ETag and `Cache-Control: immutable`, honours conditional GETs, can
|
|
19530
19581
|
* render a `?variant=thumb`, and streams. The hub gate in front of it requires
|
|
19531
19582
|
* a bearer or the session cookie (`access: 'authenticated'`), so the bytes are
|
|
@@ -19533,10 +19584,13 @@ var MediaFileKindEnum = _enum([
|
|
|
19533
19584
|
* `data-plane-access.ts` for the rule and the one gap it does not close
|
|
19534
19585
|
* (per-device scoping).
|
|
19535
19586
|
*
|
|
19536
|
-
* The URL is built from the row's
|
|
19537
|
-
*
|
|
19587
|
+
* The URL is built from the row's own id, which since D482 says nothing about
|
|
19588
|
+
* the row's owner or kind — and that is the point. The published `kind` is not
|
|
19589
|
+
* the stored one (a track's face/plate crop is stored as `crop` under
|
|
19538
19590
|
* `('face'|'plate', '<prefix>-<trackId>')` and published as
|
|
19539
|
-
* `faceCrop`/`plateCrop
|
|
19591
|
+
* `faceCrop`/`plateCrop`), and under the old composite key the URL had to be
|
|
19592
|
+
* taken from `row.key` verbatim or it 404'd exactly those two rows. An id
|
|
19593
|
+
* cannot be mis-reconstructed, because there is nothing in it to reconstruct.
|
|
19540
19594
|
*
|
|
19541
19595
|
* ## `base64` is TRANSITIONAL and is going away
|
|
19542
19596
|
*
|
|
@@ -19549,7 +19603,19 @@ var MediaFileKindEnum = _enum([
|
|
|
19549
19603
|
* `analytics-query-facade.ts`; nothing else reads it.
|
|
19550
19604
|
*/
|
|
19551
19605
|
var MediaFileSchema = object({
|
|
19552
|
-
|
|
19606
|
+
/**
|
|
19607
|
+
* The media row's OWN id — the rowid SQLite assigned it (D482).
|
|
19608
|
+
*
|
|
19609
|
+
* It used to be the row's composite key, `<ownerType>:<ownerId>:<fileKind>
|
|
19610
|
+
* [:<timestampMs>]`, which embedded a FOREIGN id. D474 made event ids
|
|
19611
|
+
* per-table rowid aliases, so `object:101314` and `motion:101314` are two
|
|
19612
|
+
* different rows that spell the same number, and a track whose
|
|
19613
|
+
* `bestEventId` was an object event was served a motion event's snapshot —
|
|
19614
|
+
* a night-time thumbnail on an afternoon track, with no error anywhere. A
|
|
19615
|
+
* surrogate id cannot name the wrong row's owner, because it names no owner
|
|
19616
|
+
* at all.
|
|
19617
|
+
*/
|
|
19618
|
+
mediaId: number().int(),
|
|
19553
19619
|
kind: MediaFileKindEnum,
|
|
19554
19620
|
sizeBytes: number(),
|
|
19555
19621
|
timestamp: number()
|
|
@@ -19657,7 +19723,7 @@ var RetrainTrackSchema = object({
|
|
|
19657
19723
|
});
|
|
19658
19724
|
/** A frame the picker may offer — an index row, no blob was read to produce it. */
|
|
19659
19725
|
var RetrainFrameCandidateSchema = object({
|
|
19660
|
-
|
|
19726
|
+
mediaId: number().int(),
|
|
19661
19727
|
kind: MediaFileKindEnum,
|
|
19662
19728
|
timestamp: number(),
|
|
19663
19729
|
sizeBytes: number().int(),
|
|
@@ -19671,7 +19737,7 @@ var RetrainFrameSchema = object({
|
|
|
19671
19737
|
deviceId: number(),
|
|
19672
19738
|
trackId: string(),
|
|
19673
19739
|
/** Provenance only. It may already point at nothing — that is expected. */
|
|
19674
|
-
|
|
19740
|
+
sourceMediaId: number().int(),
|
|
19675
19741
|
sourceKind: MediaFileKindEnum,
|
|
19676
19742
|
sizeBytes: number().int(),
|
|
19677
19743
|
width: number().int(),
|
|
@@ -19687,7 +19753,7 @@ var RetrainCopyRefusalSchema = _enum([
|
|
|
19687
19753
|
var RetrainFrameSelectionSchema = object({
|
|
19688
19754
|
copied: array(RetrainFrameSchema).readonly(),
|
|
19689
19755
|
refused: array(object({
|
|
19690
|
-
|
|
19756
|
+
sourceMediaId: number().int(),
|
|
19691
19757
|
reason: RetrainCopyRefusalSchema
|
|
19692
19758
|
})).readonly()
|
|
19693
19759
|
});
|
|
@@ -19695,7 +19761,7 @@ var RetrainFrameListSchema = object({
|
|
|
19695
19761
|
candidates: array(RetrainFrameCandidateSchema).readonly(),
|
|
19696
19762
|
copies: array(RetrainFrameSchema).readonly(),
|
|
19697
19763
|
/** What the page pre-selects — the native key frame when one survives. */
|
|
19698
|
-
|
|
19764
|
+
autoPickMediaId: number().int().optional()
|
|
19699
19765
|
});
|
|
19700
19766
|
/** What the operator asked the assist to look for. */
|
|
19701
19767
|
var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
|
|
@@ -19790,9 +19856,11 @@ var RecentTracksQueryInput = object({
|
|
|
19790
19856
|
});
|
|
19791
19857
|
/**
|
|
19792
19858
|
* A Summary (D359): the per-camera session envelope that references tracks.
|
|
19793
|
-
* `
|
|
19794
|
-
* served by the event-media plane
|
|
19795
|
-
* member visible has been materialised
|
|
19859
|
+
* `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
|
|
19860
|
+
* 'summary'`, served by the event-media plane at `/m/<id>`), null until the
|
|
19861
|
+
* first frame with a member visible has been materialised (D482 — it was the
|
|
19862
|
+
* row's composite key, which embedded the owner and could name another table's
|
|
19863
|
+
* row once event ids became per-table rowids).
|
|
19796
19864
|
*/
|
|
19797
19865
|
var SummarySchema = object({
|
|
19798
19866
|
id: string(),
|
|
@@ -19801,19 +19869,115 @@ var SummarySchema = object({
|
|
|
19801
19869
|
lastActiveAt: number(),
|
|
19802
19870
|
sealedAt: number().nullable(),
|
|
19803
19871
|
memberCount: number().int().nonnegative(),
|
|
19804
|
-
|
|
19872
|
+
groupShotMediaId: number().int().nullable()
|
|
19805
19873
|
});
|
|
19806
19874
|
var SummariesQueryInput = object({
|
|
19807
19875
|
deviceIds: array(number()).min(1),
|
|
19808
19876
|
since: number().optional(),
|
|
19809
19877
|
until: number().optional(),
|
|
19810
|
-
limit: number().int().min(1).max(200).default(50)
|
|
19878
|
+
limit: number().int().min(1).max(200).default(50),
|
|
19879
|
+
/** The same member-wise filter {@link listRecentSummaries} takes — one
|
|
19880
|
+
* meaning of "dog" on every summary surface. */
|
|
19881
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
19811
19882
|
});
|
|
19812
|
-
var SummariesPageSchema = object({ summaries: array(SummarySchema).readonly() });
|
|
19813
19883
|
var SummaryDetailSchema = object({
|
|
19814
19884
|
summary: SummarySchema,
|
|
19815
|
-
/**
|
|
19816
|
-
|
|
19885
|
+
/** Members in absorption order, oldest join first. */
|
|
19886
|
+
members: array(object({
|
|
19887
|
+
trackId: string(),
|
|
19888
|
+
/**
|
|
19889
|
+
* The track's class at the time it JOINED, or `null` when it was unresolved
|
|
19890
|
+
* and the track no longer exists to fill it.
|
|
19891
|
+
*
|
|
19892
|
+
* The join, not the latest opinion: class voting can re-decide a track's
|
|
19893
|
+
* class afterwards, and a group's composition is the history of who came
|
|
19894
|
+
* together. A consumer counts these to badge a thumbnail — "two people and a
|
|
19895
|
+
* dog" — rather than being handed a second, denormalised tally that would
|
|
19896
|
+
* drift from the members it claims to describe.
|
|
19897
|
+
*/
|
|
19898
|
+
className: string().nullable(),
|
|
19899
|
+
/** `primary` is the one member that carries the group's identity. */
|
|
19900
|
+
role: _enum([
|
|
19901
|
+
"primary",
|
|
19902
|
+
"sibling",
|
|
19903
|
+
"child"
|
|
19904
|
+
]).nullable(),
|
|
19905
|
+
joinedAt: number(),
|
|
19906
|
+
/** Tier 1 — the sub-class (`dog`, `van`), resolved from the member's track
|
|
19907
|
+
* at read time. Absent when nothing resolved, never an empty string. */
|
|
19908
|
+
label: string().optional(),
|
|
19909
|
+
/** Tier 2 — the instance: a person's name, a plate. Absent when the pipeline
|
|
19910
|
+
* recognised nobody, and absent for a member whose track has been pruned —
|
|
19911
|
+
* a thumbnail that names the wrong person is worse than one naming nobody. */
|
|
19912
|
+
subLabel: string().optional()
|
|
19913
|
+
})).readonly()
|
|
19914
|
+
});
|
|
19915
|
+
/**
|
|
19916
|
+
* What a LIST of groups carries: the envelope plus what it is MADE OF.
|
|
19917
|
+
*
|
|
19918
|
+
* Coarse on purpose — the operator's rule is "only the rough data on the list,
|
|
19919
|
+
* we extend when we notice we need more". Enough to draw the card ("two people
|
|
19920
|
+
* and a dog") and no more. The MEMBERS, their names and the per-member links
|
|
19921
|
+
* are on {@link getSummary}: shipping every member of every group so a client
|
|
19922
|
+
* can count them turns a page of two hundred groups into a thousand records to
|
|
19923
|
+
* draw two hundred badges.
|
|
19924
|
+
*/
|
|
19925
|
+
var SummaryListItemSchema = object({
|
|
19926
|
+
summary: SummarySchema,
|
|
19927
|
+
/** Class counts, most numerous first; `className: null` is a member whose
|
|
19928
|
+
* class never resolved, counted so the counts add up to `memberCount`. */
|
|
19929
|
+
classes: array(object({
|
|
19930
|
+
className: string().nullable(),
|
|
19931
|
+
count: number().int().positive()
|
|
19932
|
+
})).readonly()
|
|
19933
|
+
});
|
|
19934
|
+
var SummariesPageSchema = object({ summaries: array(SummaryListItemSchema).readonly() });
|
|
19935
|
+
/**
|
|
19936
|
+
* The paged feed, deliberately the SAME shape as {@link RecentTracksQueryInput}.
|
|
19937
|
+
*
|
|
19938
|
+
* The reel on the cameras page and the Events gallery both ride a cursor, so a
|
|
19939
|
+
* summaries feed that could only answer "the last N for these cameras"
|
|
19940
|
+
* (`listSummaries`) would make groups available in the timeline and nowhere
|
|
19941
|
+
* else. Two feeds with different ordering contracts would be two ideas of what
|
|
19942
|
+
* "newest" means, on one screen.
|
|
19943
|
+
*/
|
|
19944
|
+
var RecentSummariesQueryInput = object({
|
|
19945
|
+
/** Devices to merge. An empty array yields an empty page. */
|
|
19946
|
+
deviceIds: array(number()),
|
|
19947
|
+
/** Window lower bound on `lastActiveAt` (inclusive). */
|
|
19948
|
+
since: number().optional(),
|
|
19949
|
+
/** Window upper bound on `lastActiveAt` (inclusive). */
|
|
19950
|
+
until: number().optional(),
|
|
19951
|
+
limit: number().int().min(1).max(500).default(100),
|
|
19952
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`. */
|
|
19953
|
+
cursor: string().optional(),
|
|
19954
|
+
/**
|
|
19955
|
+
* Restrict to these classes — THE SAME FIELD `listRecentTracks` takes, and
|
|
19956
|
+
* deliberately the same name: the events filter tree emits one list of ticked
|
|
19957
|
+
* taxonomy nodes, and a summaries feed that called it something else would
|
|
19958
|
+
* make the operator's one filter component produce two shapes.
|
|
19959
|
+
*
|
|
19960
|
+
* A question about the MEMBERS: a group matches when ANY of them does. "Show
|
|
19961
|
+
* me the arrivals with a dog" has to return the group of four people who had
|
|
19962
|
+
* one with them; a filter on the group's own fields could only ever answer
|
|
19963
|
+
* about its primary.
|
|
19964
|
+
*
|
|
19965
|
+
* Matched against all THREE tiers of a member — the class (`animal`), the
|
|
19966
|
+
* sub-class (`dog`) and the instance (a name, a plate) — because which tier a
|
|
19967
|
+
* ticked node lives on is the taxonomy's business, not the caller's. `dog` is
|
|
19968
|
+
* an event kind in the tree and a tier-1 label on an `animal` track; a filter
|
|
19969
|
+
* that read only the class would answer "animal" and never "dog".
|
|
19970
|
+
*
|
|
19971
|
+
* ABSENT or EMPTY means no filter — absent is not a selection of none.
|
|
19972
|
+
*/
|
|
19973
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
19974
|
+
});
|
|
19975
|
+
var RecentSummariesPageSchema = object({
|
|
19976
|
+
/** Ordered by (`lastActiveAt` DESC, id DESC). Same light item as
|
|
19977
|
+
* {@link listSummaries} — one list shape, so a card renders the same
|
|
19978
|
+
* whichever feed drew it. */
|
|
19979
|
+
summaries: array(SummaryListItemSchema).readonly(),
|
|
19980
|
+
nextCursor: string().nullable()
|
|
19817
19981
|
});
|
|
19818
19982
|
var RecentTracksPageSchema = object({
|
|
19819
19983
|
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
@@ -20227,7 +20391,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20227
20391
|
classes: array(string()).optional(),
|
|
20228
20392
|
/** See {@link ExcludeSourcesDoc}. */
|
|
20229
20393
|
excludeSources: array(TrackSourceSchema).optional()
|
|
20230
|
-
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
20394
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(RecentSummariesQueryInput, RecentSummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
20231
20395
|
kind: "mutation",
|
|
20232
20396
|
auth: "admin"
|
|
20233
20397
|
}), 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({
|
|
@@ -20355,7 +20519,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20355
20519
|
}), method(object({
|
|
20356
20520
|
deviceId: number(),
|
|
20357
20521
|
trackId: string(),
|
|
20358
|
-
|
|
20522
|
+
mediaIds: array(number().int()).min(1)
|
|
20359
20523
|
}), RetrainFrameSelectionSchema, {
|
|
20360
20524
|
kind: "mutation",
|
|
20361
20525
|
auth: "admin"
|
|
@@ -20423,7 +20587,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20423
20587
|
kind: "query",
|
|
20424
20588
|
auth: "admin"
|
|
20425
20589
|
}), method(object({
|
|
20426
|
-
|
|
20590
|
+
/** Which of the three event tables owns the row. */
|
|
20591
|
+
ownerType: EventOwnerTypeSchema,
|
|
20592
|
+
/** The event's rowid in that table (D474: an event id is a number). */
|
|
20593
|
+
eventId: number().int(),
|
|
20427
20594
|
kind: MediaFileKindEnum.optional(),
|
|
20428
20595
|
deviceId: number()
|
|
20429
20596
|
}), array(MediaFileSchema).readonly()), method(object({
|
|
@@ -20434,7 +20601,8 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20434
20601
|
trackId: string(),
|
|
20435
20602
|
deviceId: number()
|
|
20436
20603
|
}), array(MediaFileInfoSchema).readonly()), method(object({
|
|
20437
|
-
|
|
20604
|
+
ownerType: EventOwnerTypeSchema,
|
|
20605
|
+
eventId: number().int(),
|
|
20438
20606
|
deviceId: number()
|
|
20439
20607
|
}), array(MediaFileInfoSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
|
|
20440
20608
|
kind: "mutation",
|
|
@@ -24897,8 +25065,8 @@ var IdentitySchema = object({
|
|
|
24897
25065
|
id: string(),
|
|
24898
25066
|
name: string(),
|
|
24899
25067
|
sampleCount: number().int().nonnegative(),
|
|
24900
|
-
|
|
24901
|
-
/** Inline base64 of the cover sample's crop, resolved from `
|
|
25068
|
+
coverMediaId: number().int().optional(),
|
|
25069
|
+
/** Inline base64 of the cover sample's crop, resolved from `coverMediaId`.
|
|
24902
25070
|
* Lets the UI render the person's face avatar instead of a placeholder icon. */
|
|
24903
25071
|
coverBase64: string().optional()
|
|
24904
25072
|
});
|
|
@@ -24924,8 +25092,8 @@ var IdentitySampleAuditRowSchema = object({
|
|
|
24924
25092
|
enrolledAt: number().int(),
|
|
24925
25093
|
deviceId: number().int().optional(),
|
|
24926
25094
|
source: _enum(["detected", "photo"]),
|
|
24927
|
-
/** The enrolled crop's media
|
|
24928
|
-
|
|
25095
|
+
/** The enrolled crop's media row id, so the panel can show the evidence. */
|
|
25096
|
+
mediaId: number().int().optional(),
|
|
24929
25097
|
/**
|
|
24930
25098
|
* False = the sample is stamped with a DIFFERENT face model, and a cosine
|
|
24931
25099
|
* across feature spaces is a well-formed float with no meaning. Every number
|
|
@@ -24994,15 +25162,15 @@ var FaceInfoSchema = object({
|
|
|
24994
25162
|
*/
|
|
24995
25163
|
cropUrl: string().optional(),
|
|
24996
25164
|
/** Design B: the face bbox (pixel space) on the key frame — lets a detail
|
|
24997
|
-
* view draw the box over the native `
|
|
25165
|
+
* view draw the box over the native `keyFrameMediaId` frame. Absent on
|
|
24998
25166
|
* legacy rows written before design B. */
|
|
24999
25167
|
faceBbox: BoundingBoxSchema.optional(),
|
|
25000
25168
|
/** Design B: MediaStore key of the track's native-resolution key frame.
|
|
25001
25169
|
* Fetch the native JPEG via the event-media data-plane
|
|
25002
|
-
* (`/addon/<addonId>/event-media/<
|
|
25170
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`). Absent when the
|
|
25003
25171
|
* track produced no key frame (e.g. native/onboard source) — the UI falls
|
|
25004
25172
|
* back to the inline `base64` face crop. */
|
|
25005
|
-
|
|
25173
|
+
keyFrameMediaId: number().int().optional(),
|
|
25006
25174
|
/** Winning identity-match cosine (0..1) for this face's track, when an
|
|
25007
25175
|
* identity was auto-confirmed. Lets the UI surface WHY a face was assigned
|
|
25008
25176
|
* (confidence badge / low-confidence audit). Absent on legacy rows and on
|
|
@@ -25071,11 +25239,14 @@ var FaceClusterSchema = object({
|
|
|
25071
25239
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
25072
25240
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
25073
25241
|
*
|
|
25074
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
25075
|
-
* media
|
|
25242
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
25243
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
25244
|
+
* access decision.
|
|
25076
25245
|
*/
|
|
25077
25246
|
var MediaFileLiteSchema$1 = object({
|
|
25078
|
-
|
|
25247
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
25248
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
25249
|
+
mediaId: number().int(),
|
|
25079
25250
|
kind: string(),
|
|
25080
25251
|
url: string(),
|
|
25081
25252
|
sizeBytes: number(),
|
|
@@ -25092,7 +25263,7 @@ method(object({
|
|
|
25092
25263
|
* covers inline, ~10 KB of base64 per row, on a query this UI mounts
|
|
25093
25264
|
* four times and the viewer holds at `staleTime: 30_000`.
|
|
25094
25265
|
*
|
|
25095
|
-
* Nothing loses its avatar: `
|
|
25266
|
+
* Nothing loses its avatar: `coverMediaId` is already on every row and
|
|
25096
25267
|
* the `event-media` plane serves that key `immutable` with an ETag.
|
|
25097
25268
|
*
|
|
25098
25269
|
* **This is an INPUT field, so it does not reach the addon until the
|
|
@@ -27560,8 +27731,8 @@ var VehicleSchema = object({
|
|
|
27560
27731
|
id: string(),
|
|
27561
27732
|
name: string(),
|
|
27562
27733
|
sampleCount: number().int().nonnegative(),
|
|
27563
|
-
|
|
27564
|
-
/** Inline base64 of the cover sample's plate crop, resolved from `
|
|
27734
|
+
coverMediaId: number().int().optional(),
|
|
27735
|
+
/** Inline base64 of the cover sample's plate crop, resolved from `coverMediaId`. */
|
|
27565
27736
|
coverBase64: string().optional()
|
|
27566
27737
|
});
|
|
27567
27738
|
var VehicleSampleInfoSchema = object({
|
|
@@ -27594,7 +27765,7 @@ var PlateInfoSchema = object({
|
|
|
27594
27765
|
/** keyFrame parity: the plate bbox (pixel space) on the native key frame. */
|
|
27595
27766
|
plateBbox: BoundingBoxSchema.optional(),
|
|
27596
27767
|
/** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
|
|
27597
|
-
|
|
27768
|
+
keyFrameMediaId: number().int().optional(),
|
|
27598
27769
|
base64: string().optional(),
|
|
27599
27770
|
/**
|
|
27600
27771
|
* Same crop as a data-plane URL, always present when the plate has a stored
|
|
@@ -27615,11 +27786,14 @@ var PlateInfoSchema = object({
|
|
|
27615
27786
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
27616
27787
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
27617
27788
|
*
|
|
27618
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
27619
|
-
* media
|
|
27789
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
27790
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
27791
|
+
* access decision.
|
|
27620
27792
|
*/
|
|
27621
27793
|
var MediaFileLiteSchema = object({
|
|
27622
|
-
|
|
27794
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
27795
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
27796
|
+
mediaId: number().int(),
|
|
27623
27797
|
kind: string(),
|
|
27624
27798
|
url: string(),
|
|
27625
27799
|
sizeBytes: number(),
|
|
@@ -27678,7 +27852,7 @@ method(object({
|
|
|
27678
27852
|
}), method(object({
|
|
27679
27853
|
/** Inline {@link VehicleSchema.coverBase64} on every row. Default
|
|
27680
27854
|
* `false` — the vehicle twin of `faceGallery.listIdentities`'s
|
|
27681
|
-
* option; `
|
|
27855
|
+
* option; `coverMediaId` + the `event-media` plane carry the picture.
|
|
27682
27856
|
* INPUT field: stripped by the hub router until the train ships, which
|
|
27683
27857
|
* resolves to `false` and is exactly the intended default. */
|
|
27684
27858
|
includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
|
|
@@ -29002,7 +29176,14 @@ var SceneReferenceSchema = object({
|
|
|
29002
29176
|
modelId: string(),
|
|
29003
29177
|
condition: SceneConditionSchema,
|
|
29004
29178
|
capturedAt: number(),
|
|
29005
|
-
|
|
29179
|
+
/**
|
|
29180
|
+
* The reference thumbnail's media ROW id (D482).
|
|
29181
|
+
*
|
|
29182
|
+
* The name already said `mediaId` while the value was the row's composite
|
|
29183
|
+
* key — a leftover that read as done and was not. It is the row's own id
|
|
29184
|
+
* now, addressed at `/addon/<addonId>/event-media/m/<id>`.
|
|
29185
|
+
*/
|
|
29186
|
+
thumbnailMediaId: number().int().optional(),
|
|
29006
29187
|
/** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
|
|
29007
29188
|
* anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
|
|
29008
29189
|
* normalized rect frame a different piece of world, and the scene would
|
|
@@ -29816,7 +29997,29 @@ var LoggingSettingsPatchSchema = object({
|
|
|
29816
29997
|
* disarmed the channels it did not mention would make the Levels page and
|
|
29817
29998
|
* the Diagnostics page fight over the same value.
|
|
29818
29999
|
*/
|
|
29819
|
-
channels: array(LogChannelWindowPatchSchema).readonly().optional()
|
|
30000
|
+
channels: array(LogChannelWindowPatchSchema).readonly().optional(),
|
|
30001
|
+
/**
|
|
30002
|
+
* How many days the analytics OPS LOG is kept — the audit trail of what
|
|
30003
|
+
* retention actually deleted.
|
|
30004
|
+
*
|
|
30005
|
+
* It lives HERE, on the logging document, and not on the analytics addon's
|
|
30006
|
+
* settings form, on the operator's instruction: every other log-ish window in
|
|
30007
|
+
* this system is configured through this one document, and a retention audit
|
|
30008
|
+
* configured somewhere else is a second place to look when the question is
|
|
30009
|
+
* "what happened to my data".
|
|
30010
|
+
*
|
|
30011
|
+
* That placement has a cost worth stating: this document ships in the
|
|
30012
|
+
* framework closure, so this knob needs a published `@camstack/server` while
|
|
30013
|
+
* the four windows beside it (D485) reach a node on `camstack deploy`.
|
|
30014
|
+
*
|
|
30015
|
+
* `retention-model.ts` argued this one must NOT follow a device window,
|
|
30016
|
+
* because the audit trail is the history of the SWEEP and not of the camera.
|
|
30017
|
+
* That argument stands and is untouched — what changes is that 30 days stops
|
|
30018
|
+
* being a constant nobody can reach. `0` keeps it forever. The floor is 1 day
|
|
30019
|
+
* rather than 0-as-delete: an audit log truncated to nothing is precisely the
|
|
30020
|
+
* state in which the next 9.5 GiB leak cannot be explained.
|
|
30021
|
+
*/
|
|
30022
|
+
opsLogRetentionDays: number().int().min(0).max(3650).optional()
|
|
29820
30023
|
});
|
|
29821
30024
|
/**
|
|
29822
30025
|
* Which LAYER of the hierarchy is addressed. Absent = the cluster layer.
|
|
@@ -29889,6 +30092,14 @@ var LoggingSettingsStateSchema = object({
|
|
|
29889
30092
|
channels: array(LogChannelDescriptorSchema).readonly(),
|
|
29890
30093
|
/** The channels ARMED right now, each with its deadline. */
|
|
29891
30094
|
activeChannels: array(LogChannelWindowStateSchema).readonly(),
|
|
30095
|
+
/**
|
|
30096
|
+
* The ops-log window in days, as it is in force. `0` = kept forever.
|
|
30097
|
+
*
|
|
30098
|
+
* Reported rather than left to the caller's memory of what it wrote: this is
|
|
30099
|
+
* the value the analytics sweep will actually use, and an operator asking how
|
|
30100
|
+
* long their audit trail lives should not have to infer it from a default.
|
|
30101
|
+
*/
|
|
30102
|
+
opsLogRetentionDays: number().int().min(0),
|
|
29892
30103
|
persisted: boolean()
|
|
29893
30104
|
});
|
|
29894
30105
|
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(), {
|
|
@@ -30450,7 +30661,7 @@ var StationaryObjectSchema = object({
|
|
|
30450
30661
|
/** Enrichment label carried from the source track (identity / plate). */
|
|
30451
30662
|
label: string().optional(),
|
|
30452
30663
|
/** Native-resolution key-frame media key for the parked object's best image. */
|
|
30453
|
-
|
|
30664
|
+
keyFrameMediaId: number().int().optional()
|
|
30454
30665
|
});
|
|
30455
30666
|
var CameraOccupancySnapshotSchema = object({
|
|
30456
30667
|
/** Frame timestamp of the inference result that produced this snapshot. */
|
|
@@ -31606,6 +31817,12 @@ Object.freeze({
|
|
|
31606
31817
|
addonId: null,
|
|
31607
31818
|
access: "create"
|
|
31608
31819
|
},
|
|
31820
|
+
"dataStoreProvider.upsert": {
|
|
31821
|
+
capName: "data-store-provider",
|
|
31822
|
+
capScope: "system",
|
|
31823
|
+
addonId: null,
|
|
31824
|
+
access: "create"
|
|
31825
|
+
},
|
|
31609
31826
|
"dayNight.getOptions": {
|
|
31610
31827
|
capName: "day-night",
|
|
31611
31828
|
capScope: "device",
|
|
@@ -34042,6 +34259,12 @@ Object.freeze({
|
|
|
34042
34259
|
addonId: null,
|
|
34043
34260
|
access: "view"
|
|
34044
34261
|
},
|
|
34262
|
+
"pipelineAnalytics.listRecentSummaries": {
|
|
34263
|
+
capName: "pipeline-analytics",
|
|
34264
|
+
capScope: "device",
|
|
34265
|
+
addonId: null,
|
|
34266
|
+
access: "view"
|
|
34267
|
+
},
|
|
34045
34268
|
"pipelineAnalytics.listRecentTracks": {
|
|
34046
34269
|
capName: "pipeline-analytics",
|
|
34047
34270
|
capScope: "device",
|
|
@@ -35470,6 +35693,12 @@ Object.freeze({
|
|
|
35470
35693
|
addonId: null,
|
|
35471
35694
|
access: "create"
|
|
35472
35695
|
},
|
|
35696
|
+
"settingsStore.upsert": {
|
|
35697
|
+
capName: "settings-store",
|
|
35698
|
+
capScope: "system",
|
|
35699
|
+
addonId: null,
|
|
35700
|
+
access: "create"
|
|
35701
|
+
},
|
|
35473
35702
|
"smtpProvider.getStatus": {
|
|
35474
35703
|
capName: "smtp-provider",
|
|
35475
35704
|
capScope: "system",
|
|
@@ -37863,6 +38092,11 @@ Object.freeze({
|
|
|
37863
38092
|
form: "single",
|
|
37864
38093
|
optional: true
|
|
37865
38094
|
}],
|
|
38095
|
+
"pipelineAnalytics.listRecentSummaries": [{
|
|
38096
|
+
name: "deviceIds",
|
|
38097
|
+
form: "array",
|
|
38098
|
+
optional: false
|
|
38099
|
+
}],
|
|
37866
38100
|
"pipelineAnalytics.listRecentTracks": [{
|
|
37867
38101
|
name: "deviceIds",
|
|
37868
38102
|
form: "array",
|
|
@@ -39,7 +39,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
39
39
|
var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
40
40
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
41
41
|
//#endregion
|
|
42
|
-
//#region ../types/dist/event-category-
|
|
42
|
+
//#region ../types/dist/event-category-ZyX6jcse.mjs
|
|
43
43
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
44
44
|
EventCategory["SystemBoot"] = "system.boot";
|
|
45
45
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -600,7 +600,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
600
600
|
* a package zone — a newly-appeared stationary object of a package class
|
|
601
601
|
* that cleared the class / zone / dwell / size gates. Payload:
|
|
602
602
|
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
603
|
-
* entryId, className, zoneIds,
|
|
603
|
+
* entryId, className, zoneIds, keyFrameMediaId?, bbox, timestamp }`.
|
|
604
604
|
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
605
605
|
* this bus topic drives notifier rules + live UI. See
|
|
606
606
|
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
@@ -5386,7 +5386,7 @@ var ZodIssueCode = {
|
|
|
5386
5386
|
var ZodFirstPartyTypeKind;
|
|
5387
5387
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5388
5388
|
//#endregion
|
|
5389
|
-
//#region ../types/dist/sleep-
|
|
5389
|
+
//#region ../types/dist/sleep-DBKu2-U5.mjs
|
|
5390
5390
|
/**
|
|
5391
5391
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5392
5392
|
* window to float samples (D455).
|
|
@@ -7337,13 +7337,30 @@ new Set([
|
|
|
7337
7337
|
"scene",
|
|
7338
7338
|
"motion",
|
|
7339
7339
|
"object",
|
|
7340
|
-
"audio"
|
|
7340
|
+
"audio",
|
|
7341
|
+
"mosaic"
|
|
7341
7342
|
]);
|
|
7342
|
-
|
|
7343
|
+
/**
|
|
7344
|
+
* The owner types that are event tables, in the order the event-media resolver
|
|
7345
|
+
* should consider them. Exported so a consumer asking "is this key an event?"
|
|
7346
|
+
* does not re-spell the list and drift from it.
|
|
7347
|
+
*/
|
|
7348
|
+
var EVENT_OWNER_TYPES = [
|
|
7343
7349
|
"motion",
|
|
7344
7350
|
"object",
|
|
7345
7351
|
"audio"
|
|
7346
|
-
]
|
|
7352
|
+
];
|
|
7353
|
+
/**
|
|
7354
|
+
* The same list as a Zod enum, for the cap inputs that must NAME the table
|
|
7355
|
+
* (D482: `getEventMedia` / `listEventMedia` take an owner, and an owner is
|
|
7356
|
+
* `(table, id)`).
|
|
7357
|
+
*
|
|
7358
|
+
* Built FROM {@link EVENT_OWNER_TYPES} rather than re-spelled: a fourth event
|
|
7359
|
+
* table would otherwise be accepted by the codec and refused at the door, with
|
|
7360
|
+
* nothing failing until a caller asked.
|
|
7361
|
+
*/
|
|
7362
|
+
var EventOwnerTypeSchema = _enum(EVENT_OWNER_TYPES);
|
|
7363
|
+
new Set(EVENT_OWNER_TYPES);
|
|
7347
7364
|
var EncodeProfileSchema = object({
|
|
7348
7365
|
video: object({
|
|
7349
7366
|
codec: _enum([
|
|
@@ -7382,7 +7399,23 @@ var EncodeProfileSchema = object({
|
|
|
7382
7399
|
"zerolatency",
|
|
7383
7400
|
"film",
|
|
7384
7401
|
"animation"
|
|
7385
|
-
]).optional()
|
|
7402
|
+
]).optional(),
|
|
7403
|
+
/**
|
|
7404
|
+
* ONE slice per access unit.
|
|
7405
|
+
*
|
|
7406
|
+
* `-tune zerolatency` turns on x264's sliced threads, and a frame then leaves
|
|
7407
|
+
* the encoder as five NAL slices that share one RTP timestamp and carry one
|
|
7408
|
+
* marker bit. A libwebrtc depacketiser sees five frame-starts and one
|
|
7409
|
+
* frame-end per frame: the first pictures render and the video then freezes
|
|
7410
|
+
* for good while the audio, on its own plane, plays on. Measured on this hub
|
|
7411
|
+
* 2026-09-13 against the Echo, and reduced to one slice by this flag alone.
|
|
7412
|
+
*
|
|
7413
|
+
* A NAMED field and not a raw flag, because {@link EgressEncodeSchema} omits
|
|
7414
|
+
* `outputArgs` on purpose: an opaque array is part of the sharing key, so two
|
|
7415
|
+
* consumers meaning the same thing spelled differently would stop sharing one
|
|
7416
|
+
* child. Absent means "whatever the encoder does" — today's behaviour.
|
|
7417
|
+
*/
|
|
7418
|
+
singleSlicePerFrame: boolean().optional()
|
|
7386
7419
|
}),
|
|
7387
7420
|
audio: union([literal("passthrough"), object({
|
|
7388
7421
|
codec: _enum([
|
|
@@ -7432,7 +7465,7 @@ var BASE_LIVE_EGRESS_PROFILE = {
|
|
|
7432
7465
|
audio: "passthrough"
|
|
7433
7466
|
};
|
|
7434
7467
|
({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
|
|
7435
|
-
({ ...BASE_LIVE_EGRESS_PROFILE });
|
|
7468
|
+
({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
|
|
7436
7469
|
/**
|
|
7437
7470
|
* Deep wiring healthcheck — snapshot of active reachability probes across
|
|
7438
7471
|
* every declared capability + widget of every installed plugin, on every
|
|
@@ -12489,6 +12522,16 @@ method(object({
|
|
|
12489
12522
|
filter: QueryFilterSchema.optional(),
|
|
12490
12523
|
columns: array(string()).readonly().optional()
|
|
12491
12524
|
}), array(SettingsRecordSchema).readonly()), method(object({
|
|
12525
|
+
namespace: string().optional(),
|
|
12526
|
+
collection: string(),
|
|
12527
|
+
/** Declared columns identifying the slot; must be covered by a UNIQUE
|
|
12528
|
+
* index on the collection. Never empty. */
|
|
12529
|
+
conflict: array(string()).readonly(),
|
|
12530
|
+
record: BulkRecordSchema
|
|
12531
|
+
}), object({
|
|
12532
|
+
/** The id the row HAS: assigned by SQLite on an insert, or the existing
|
|
12533
|
+
* row's own id on an update. */
|
|
12534
|
+
id: union([string(), number()]) }), { kind: "mutation" }), method(object({
|
|
12492
12535
|
namespace: string().optional(),
|
|
12493
12536
|
collection: string(),
|
|
12494
12537
|
record: object({
|
|
@@ -12623,6 +12666,14 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
|
|
|
12623
12666
|
id: union([string(), number()]) }), {
|
|
12624
12667
|
kind: "mutation",
|
|
12625
12668
|
auth: "admin"
|
|
12669
|
+
}), method(object({
|
|
12670
|
+
namespace: string().optional(),
|
|
12671
|
+
collection: string(),
|
|
12672
|
+
conflict: array(string()).readonly(),
|
|
12673
|
+
record: BulkRecordSchema
|
|
12674
|
+
}), object({ id: union([string(), number()]) }), {
|
|
12675
|
+
kind: "mutation",
|
|
12676
|
+
auth: "admin"
|
|
12626
12677
|
}), method(object({
|
|
12627
12678
|
namespace: string().optional(),
|
|
12628
12679
|
collection: string(),
|
|
@@ -18858,8 +18909,8 @@ var TrackPositionSchema = object({
|
|
|
18858
18909
|
var TrackSnapshotSchema = object({
|
|
18859
18910
|
timestamp: number(),
|
|
18860
18911
|
position: TrackPositionSchema,
|
|
18861
|
-
/**
|
|
18862
|
-
|
|
18912
|
+
/** The snapshot's media row id (D482); resolve via `listTrackMedia({ trackId })`. */
|
|
18913
|
+
mediaId: number().int()
|
|
18863
18914
|
});
|
|
18864
18915
|
/**
|
|
18865
18916
|
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
@@ -19463,14 +19514,14 @@ var ObjectEventSchema = object({
|
|
|
19463
19514
|
* pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
|
|
19464
19515
|
frameWidth: number().optional(),
|
|
19465
19516
|
frameHeight: number().optional(),
|
|
19466
|
-
/**
|
|
19467
|
-
|
|
19468
|
-
/** Design B:
|
|
19517
|
+
/** Media row id of the crop attached to this event (if any) — D482. */
|
|
19518
|
+
mediaId: number().int().optional(),
|
|
19519
|
+
/** Design B: media row id of the track's native-resolution key frame (the
|
|
19469
19520
|
* best-detection full frame). Resolve via the event-media data-plane
|
|
19470
|
-
* (`/addon/<addonId>/event-media/<
|
|
19521
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`) for a detail view that
|
|
19471
19522
|
* draws `bbox` over the native frame. Absent on legacy rows / non-decoded
|
|
19472
|
-
* sources — consumers fall back to `
|
|
19473
|
-
|
|
19523
|
+
* sources — consumers fall back to `mediaId` (the tight crop). */
|
|
19524
|
+
keyFrameMediaId: number().int().optional(),
|
|
19474
19525
|
/** Populated by B5 (recording playback URL for this event). */
|
|
19475
19526
|
mediaUrl: string().optional(),
|
|
19476
19527
|
/** The parent track's key-event importance [0,1], propagated to every object
|
|
@@ -19520,7 +19571,7 @@ var MediaFileKindEnum = _enum([
|
|
|
19520
19571
|
* hub-main's heap on the way past — for an `<img>` that would have cached it.
|
|
19521
19572
|
*
|
|
19522
19573
|
* `url` points at the `event-media` data plane
|
|
19523
|
-
* (`/addon/<addonId>/event-media/<
|
|
19574
|
+
* (`/addon/<addonId>/event-media/m/<mediaId>` — D482), which serves the same blob
|
|
19524
19575
|
* with an ETag and `Cache-Control: immutable`, honours conditional GETs, can
|
|
19525
19576
|
* render a `?variant=thumb`, and streams. The hub gate in front of it requires
|
|
19526
19577
|
* a bearer or the session cookie (`access: 'authenticated'`), so the bytes are
|
|
@@ -19528,10 +19579,13 @@ var MediaFileKindEnum = _enum([
|
|
|
19528
19579
|
* `data-plane-access.ts` for the rule and the one gap it does not close
|
|
19529
19580
|
* (per-device scoping).
|
|
19530
19581
|
*
|
|
19531
|
-
* The URL is built from the row's
|
|
19532
|
-
*
|
|
19582
|
+
* The URL is built from the row's own id, which since D482 says nothing about
|
|
19583
|
+
* the row's owner or kind — and that is the point. The published `kind` is not
|
|
19584
|
+
* the stored one (a track's face/plate crop is stored as `crop` under
|
|
19533
19585
|
* `('face'|'plate', '<prefix>-<trackId>')` and published as
|
|
19534
|
-
* `faceCrop`/`plateCrop
|
|
19586
|
+
* `faceCrop`/`plateCrop`), and under the old composite key the URL had to be
|
|
19587
|
+
* taken from `row.key` verbatim or it 404'd exactly those two rows. An id
|
|
19588
|
+
* cannot be mis-reconstructed, because there is nothing in it to reconstruct.
|
|
19535
19589
|
*
|
|
19536
19590
|
* ## `base64` is TRANSITIONAL and is going away
|
|
19537
19591
|
*
|
|
@@ -19544,7 +19598,19 @@ var MediaFileKindEnum = _enum([
|
|
|
19544
19598
|
* `analytics-query-facade.ts`; nothing else reads it.
|
|
19545
19599
|
*/
|
|
19546
19600
|
var MediaFileSchema = object({
|
|
19547
|
-
|
|
19601
|
+
/**
|
|
19602
|
+
* The media row's OWN id — the rowid SQLite assigned it (D482).
|
|
19603
|
+
*
|
|
19604
|
+
* It used to be the row's composite key, `<ownerType>:<ownerId>:<fileKind>
|
|
19605
|
+
* [:<timestampMs>]`, which embedded a FOREIGN id. D474 made event ids
|
|
19606
|
+
* per-table rowid aliases, so `object:101314` and `motion:101314` are two
|
|
19607
|
+
* different rows that spell the same number, and a track whose
|
|
19608
|
+
* `bestEventId` was an object event was served a motion event's snapshot —
|
|
19609
|
+
* a night-time thumbnail on an afternoon track, with no error anywhere. A
|
|
19610
|
+
* surrogate id cannot name the wrong row's owner, because it names no owner
|
|
19611
|
+
* at all.
|
|
19612
|
+
*/
|
|
19613
|
+
mediaId: number().int(),
|
|
19548
19614
|
kind: MediaFileKindEnum,
|
|
19549
19615
|
sizeBytes: number(),
|
|
19550
19616
|
timestamp: number()
|
|
@@ -19652,7 +19718,7 @@ var RetrainTrackSchema = object({
|
|
|
19652
19718
|
});
|
|
19653
19719
|
/** A frame the picker may offer — an index row, no blob was read to produce it. */
|
|
19654
19720
|
var RetrainFrameCandidateSchema = object({
|
|
19655
|
-
|
|
19721
|
+
mediaId: number().int(),
|
|
19656
19722
|
kind: MediaFileKindEnum,
|
|
19657
19723
|
timestamp: number(),
|
|
19658
19724
|
sizeBytes: number().int(),
|
|
@@ -19666,7 +19732,7 @@ var RetrainFrameSchema = object({
|
|
|
19666
19732
|
deviceId: number(),
|
|
19667
19733
|
trackId: string(),
|
|
19668
19734
|
/** Provenance only. It may already point at nothing — that is expected. */
|
|
19669
|
-
|
|
19735
|
+
sourceMediaId: number().int(),
|
|
19670
19736
|
sourceKind: MediaFileKindEnum,
|
|
19671
19737
|
sizeBytes: number().int(),
|
|
19672
19738
|
width: number().int(),
|
|
@@ -19682,7 +19748,7 @@ var RetrainCopyRefusalSchema = _enum([
|
|
|
19682
19748
|
var RetrainFrameSelectionSchema = object({
|
|
19683
19749
|
copied: array(RetrainFrameSchema).readonly(),
|
|
19684
19750
|
refused: array(object({
|
|
19685
|
-
|
|
19751
|
+
sourceMediaId: number().int(),
|
|
19686
19752
|
reason: RetrainCopyRefusalSchema
|
|
19687
19753
|
})).readonly()
|
|
19688
19754
|
});
|
|
@@ -19690,7 +19756,7 @@ var RetrainFrameListSchema = object({
|
|
|
19690
19756
|
candidates: array(RetrainFrameCandidateSchema).readonly(),
|
|
19691
19757
|
copies: array(RetrainFrameSchema).readonly(),
|
|
19692
19758
|
/** What the page pre-selects — the native key frame when one survives. */
|
|
19693
|
-
|
|
19759
|
+
autoPickMediaId: number().int().optional()
|
|
19694
19760
|
});
|
|
19695
19761
|
/** What the operator asked the assist to look for. */
|
|
19696
19762
|
var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
|
|
@@ -19785,9 +19851,11 @@ var RecentTracksQueryInput = object({
|
|
|
19785
19851
|
});
|
|
19786
19852
|
/**
|
|
19787
19853
|
* A Summary (D359): the per-camera session envelope that references tracks.
|
|
19788
|
-
* `
|
|
19789
|
-
* served by the event-media plane
|
|
19790
|
-
* member visible has been materialised
|
|
19854
|
+
* `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
|
|
19855
|
+
* 'summary'`, served by the event-media plane at `/m/<id>`), null until the
|
|
19856
|
+
* first frame with a member visible has been materialised (D482 — it was the
|
|
19857
|
+
* row's composite key, which embedded the owner and could name another table's
|
|
19858
|
+
* row once event ids became per-table rowids).
|
|
19791
19859
|
*/
|
|
19792
19860
|
var SummarySchema = object({
|
|
19793
19861
|
id: string(),
|
|
@@ -19796,19 +19864,115 @@ var SummarySchema = object({
|
|
|
19796
19864
|
lastActiveAt: number(),
|
|
19797
19865
|
sealedAt: number().nullable(),
|
|
19798
19866
|
memberCount: number().int().nonnegative(),
|
|
19799
|
-
|
|
19867
|
+
groupShotMediaId: number().int().nullable()
|
|
19800
19868
|
});
|
|
19801
19869
|
var SummariesQueryInput = object({
|
|
19802
19870
|
deviceIds: array(number()).min(1),
|
|
19803
19871
|
since: number().optional(),
|
|
19804
19872
|
until: number().optional(),
|
|
19805
|
-
limit: number().int().min(1).max(200).default(50)
|
|
19873
|
+
limit: number().int().min(1).max(200).default(50),
|
|
19874
|
+
/** The same member-wise filter {@link listRecentSummaries} takes — one
|
|
19875
|
+
* meaning of "dog" on every summary surface. */
|
|
19876
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
19806
19877
|
});
|
|
19807
|
-
var SummariesPageSchema = object({ summaries: array(SummarySchema).readonly() });
|
|
19808
19878
|
var SummaryDetailSchema = object({
|
|
19809
19879
|
summary: SummarySchema,
|
|
19810
|
-
/**
|
|
19811
|
-
|
|
19880
|
+
/** Members in absorption order, oldest join first. */
|
|
19881
|
+
members: array(object({
|
|
19882
|
+
trackId: string(),
|
|
19883
|
+
/**
|
|
19884
|
+
* The track's class at the time it JOINED, or `null` when it was unresolved
|
|
19885
|
+
* and the track no longer exists to fill it.
|
|
19886
|
+
*
|
|
19887
|
+
* The join, not the latest opinion: class voting can re-decide a track's
|
|
19888
|
+
* class afterwards, and a group's composition is the history of who came
|
|
19889
|
+
* together. A consumer counts these to badge a thumbnail — "two people and a
|
|
19890
|
+
* dog" — rather than being handed a second, denormalised tally that would
|
|
19891
|
+
* drift from the members it claims to describe.
|
|
19892
|
+
*/
|
|
19893
|
+
className: string().nullable(),
|
|
19894
|
+
/** `primary` is the one member that carries the group's identity. */
|
|
19895
|
+
role: _enum([
|
|
19896
|
+
"primary",
|
|
19897
|
+
"sibling",
|
|
19898
|
+
"child"
|
|
19899
|
+
]).nullable(),
|
|
19900
|
+
joinedAt: number(),
|
|
19901
|
+
/** Tier 1 — the sub-class (`dog`, `van`), resolved from the member's track
|
|
19902
|
+
* at read time. Absent when nothing resolved, never an empty string. */
|
|
19903
|
+
label: string().optional(),
|
|
19904
|
+
/** Tier 2 — the instance: a person's name, a plate. Absent when the pipeline
|
|
19905
|
+
* recognised nobody, and absent for a member whose track has been pruned —
|
|
19906
|
+
* a thumbnail that names the wrong person is worse than one naming nobody. */
|
|
19907
|
+
subLabel: string().optional()
|
|
19908
|
+
})).readonly()
|
|
19909
|
+
});
|
|
19910
|
+
/**
|
|
19911
|
+
* What a LIST of groups carries: the envelope plus what it is MADE OF.
|
|
19912
|
+
*
|
|
19913
|
+
* Coarse on purpose — the operator's rule is "only the rough data on the list,
|
|
19914
|
+
* we extend when we notice we need more". Enough to draw the card ("two people
|
|
19915
|
+
* and a dog") and no more. The MEMBERS, their names and the per-member links
|
|
19916
|
+
* are on {@link getSummary}: shipping every member of every group so a client
|
|
19917
|
+
* can count them turns a page of two hundred groups into a thousand records to
|
|
19918
|
+
* draw two hundred badges.
|
|
19919
|
+
*/
|
|
19920
|
+
var SummaryListItemSchema = object({
|
|
19921
|
+
summary: SummarySchema,
|
|
19922
|
+
/** Class counts, most numerous first; `className: null` is a member whose
|
|
19923
|
+
* class never resolved, counted so the counts add up to `memberCount`. */
|
|
19924
|
+
classes: array(object({
|
|
19925
|
+
className: string().nullable(),
|
|
19926
|
+
count: number().int().positive()
|
|
19927
|
+
})).readonly()
|
|
19928
|
+
});
|
|
19929
|
+
var SummariesPageSchema = object({ summaries: array(SummaryListItemSchema).readonly() });
|
|
19930
|
+
/**
|
|
19931
|
+
* The paged feed, deliberately the SAME shape as {@link RecentTracksQueryInput}.
|
|
19932
|
+
*
|
|
19933
|
+
* The reel on the cameras page and the Events gallery both ride a cursor, so a
|
|
19934
|
+
* summaries feed that could only answer "the last N for these cameras"
|
|
19935
|
+
* (`listSummaries`) would make groups available in the timeline and nowhere
|
|
19936
|
+
* else. Two feeds with different ordering contracts would be two ideas of what
|
|
19937
|
+
* "newest" means, on one screen.
|
|
19938
|
+
*/
|
|
19939
|
+
var RecentSummariesQueryInput = object({
|
|
19940
|
+
/** Devices to merge. An empty array yields an empty page. */
|
|
19941
|
+
deviceIds: array(number()),
|
|
19942
|
+
/** Window lower bound on `lastActiveAt` (inclusive). */
|
|
19943
|
+
since: number().optional(),
|
|
19944
|
+
/** Window upper bound on `lastActiveAt` (inclusive). */
|
|
19945
|
+
until: number().optional(),
|
|
19946
|
+
limit: number().int().min(1).max(500).default(100),
|
|
19947
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`. */
|
|
19948
|
+
cursor: string().optional(),
|
|
19949
|
+
/**
|
|
19950
|
+
* Restrict to these classes — THE SAME FIELD `listRecentTracks` takes, and
|
|
19951
|
+
* deliberately the same name: the events filter tree emits one list of ticked
|
|
19952
|
+
* taxonomy nodes, and a summaries feed that called it something else would
|
|
19953
|
+
* make the operator's one filter component produce two shapes.
|
|
19954
|
+
*
|
|
19955
|
+
* A question about the MEMBERS: a group matches when ANY of them does. "Show
|
|
19956
|
+
* me the arrivals with a dog" has to return the group of four people who had
|
|
19957
|
+
* one with them; a filter on the group's own fields could only ever answer
|
|
19958
|
+
* about its primary.
|
|
19959
|
+
*
|
|
19960
|
+
* Matched against all THREE tiers of a member — the class (`animal`), the
|
|
19961
|
+
* sub-class (`dog`) and the instance (a name, a plate) — because which tier a
|
|
19962
|
+
* ticked node lives on is the taxonomy's business, not the caller's. `dog` is
|
|
19963
|
+
* an event kind in the tree and a tier-1 label on an `animal` track; a filter
|
|
19964
|
+
* that read only the class would answer "animal" and never "dog".
|
|
19965
|
+
*
|
|
19966
|
+
* ABSENT or EMPTY means no filter — absent is not a selection of none.
|
|
19967
|
+
*/
|
|
19968
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
19969
|
+
});
|
|
19970
|
+
var RecentSummariesPageSchema = object({
|
|
19971
|
+
/** Ordered by (`lastActiveAt` DESC, id DESC). Same light item as
|
|
19972
|
+
* {@link listSummaries} — one list shape, so a card renders the same
|
|
19973
|
+
* whichever feed drew it. */
|
|
19974
|
+
summaries: array(SummaryListItemSchema).readonly(),
|
|
19975
|
+
nextCursor: string().nullable()
|
|
19812
19976
|
});
|
|
19813
19977
|
var RecentTracksPageSchema = object({
|
|
19814
19978
|
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
@@ -20222,7 +20386,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20222
20386
|
classes: array(string()).optional(),
|
|
20223
20387
|
/** See {@link ExcludeSourcesDoc}. */
|
|
20224
20388
|
excludeSources: array(TrackSourceSchema).optional()
|
|
20225
|
-
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
20389
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(RecentSummariesQueryInput, RecentSummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
20226
20390
|
kind: "mutation",
|
|
20227
20391
|
auth: "admin"
|
|
20228
20392
|
}), 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({
|
|
@@ -20350,7 +20514,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20350
20514
|
}), method(object({
|
|
20351
20515
|
deviceId: number(),
|
|
20352
20516
|
trackId: string(),
|
|
20353
|
-
|
|
20517
|
+
mediaIds: array(number().int()).min(1)
|
|
20354
20518
|
}), RetrainFrameSelectionSchema, {
|
|
20355
20519
|
kind: "mutation",
|
|
20356
20520
|
auth: "admin"
|
|
@@ -20418,7 +20582,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20418
20582
|
kind: "query",
|
|
20419
20583
|
auth: "admin"
|
|
20420
20584
|
}), method(object({
|
|
20421
|
-
|
|
20585
|
+
/** Which of the three event tables owns the row. */
|
|
20586
|
+
ownerType: EventOwnerTypeSchema,
|
|
20587
|
+
/** The event's rowid in that table (D474: an event id is a number). */
|
|
20588
|
+
eventId: number().int(),
|
|
20422
20589
|
kind: MediaFileKindEnum.optional(),
|
|
20423
20590
|
deviceId: number()
|
|
20424
20591
|
}), array(MediaFileSchema).readonly()), method(object({
|
|
@@ -20429,7 +20596,8 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20429
20596
|
trackId: string(),
|
|
20430
20597
|
deviceId: number()
|
|
20431
20598
|
}), array(MediaFileInfoSchema).readonly()), method(object({
|
|
20432
|
-
|
|
20599
|
+
ownerType: EventOwnerTypeSchema,
|
|
20600
|
+
eventId: number().int(),
|
|
20433
20601
|
deviceId: number()
|
|
20434
20602
|
}), array(MediaFileInfoSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
|
|
20435
20603
|
kind: "mutation",
|
|
@@ -24892,8 +25060,8 @@ var IdentitySchema = object({
|
|
|
24892
25060
|
id: string(),
|
|
24893
25061
|
name: string(),
|
|
24894
25062
|
sampleCount: number().int().nonnegative(),
|
|
24895
|
-
|
|
24896
|
-
/** Inline base64 of the cover sample's crop, resolved from `
|
|
25063
|
+
coverMediaId: number().int().optional(),
|
|
25064
|
+
/** Inline base64 of the cover sample's crop, resolved from `coverMediaId`.
|
|
24897
25065
|
* Lets the UI render the person's face avatar instead of a placeholder icon. */
|
|
24898
25066
|
coverBase64: string().optional()
|
|
24899
25067
|
});
|
|
@@ -24919,8 +25087,8 @@ var IdentitySampleAuditRowSchema = object({
|
|
|
24919
25087
|
enrolledAt: number().int(),
|
|
24920
25088
|
deviceId: number().int().optional(),
|
|
24921
25089
|
source: _enum(["detected", "photo"]),
|
|
24922
|
-
/** The enrolled crop's media
|
|
24923
|
-
|
|
25090
|
+
/** The enrolled crop's media row id, so the panel can show the evidence. */
|
|
25091
|
+
mediaId: number().int().optional(),
|
|
24924
25092
|
/**
|
|
24925
25093
|
* False = the sample is stamped with a DIFFERENT face model, and a cosine
|
|
24926
25094
|
* across feature spaces is a well-formed float with no meaning. Every number
|
|
@@ -24989,15 +25157,15 @@ var FaceInfoSchema = object({
|
|
|
24989
25157
|
*/
|
|
24990
25158
|
cropUrl: string().optional(),
|
|
24991
25159
|
/** Design B: the face bbox (pixel space) on the key frame — lets a detail
|
|
24992
|
-
* view draw the box over the native `
|
|
25160
|
+
* view draw the box over the native `keyFrameMediaId` frame. Absent on
|
|
24993
25161
|
* legacy rows written before design B. */
|
|
24994
25162
|
faceBbox: BoundingBoxSchema.optional(),
|
|
24995
25163
|
/** Design B: MediaStore key of the track's native-resolution key frame.
|
|
24996
25164
|
* Fetch the native JPEG via the event-media data-plane
|
|
24997
|
-
* (`/addon/<addonId>/event-media/<
|
|
25165
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`). Absent when the
|
|
24998
25166
|
* track produced no key frame (e.g. native/onboard source) — the UI falls
|
|
24999
25167
|
* back to the inline `base64` face crop. */
|
|
25000
|
-
|
|
25168
|
+
keyFrameMediaId: number().int().optional(),
|
|
25001
25169
|
/** Winning identity-match cosine (0..1) for this face's track, when an
|
|
25002
25170
|
* identity was auto-confirmed. Lets the UI surface WHY a face was assigned
|
|
25003
25171
|
* (confidence badge / low-confidence audit). Absent on legacy rows and on
|
|
@@ -25066,11 +25234,14 @@ var FaceClusterSchema = object({
|
|
|
25066
25234
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
25067
25235
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
25068
25236
|
*
|
|
25069
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
25070
|
-
* media
|
|
25237
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
25238
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
25239
|
+
* access decision.
|
|
25071
25240
|
*/
|
|
25072
25241
|
var MediaFileLiteSchema$1 = object({
|
|
25073
|
-
|
|
25242
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
25243
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
25244
|
+
mediaId: number().int(),
|
|
25074
25245
|
kind: string(),
|
|
25075
25246
|
url: string(),
|
|
25076
25247
|
sizeBytes: number(),
|
|
@@ -25087,7 +25258,7 @@ method(object({
|
|
|
25087
25258
|
* covers inline, ~10 KB of base64 per row, on a query this UI mounts
|
|
25088
25259
|
* four times and the viewer holds at `staleTime: 30_000`.
|
|
25089
25260
|
*
|
|
25090
|
-
* Nothing loses its avatar: `
|
|
25261
|
+
* Nothing loses its avatar: `coverMediaId` is already on every row and
|
|
25091
25262
|
* the `event-media` plane serves that key `immutable` with an ETag.
|
|
25092
25263
|
*
|
|
25093
25264
|
* **This is an INPUT field, so it does not reach the addon until the
|
|
@@ -27555,8 +27726,8 @@ var VehicleSchema = object({
|
|
|
27555
27726
|
id: string(),
|
|
27556
27727
|
name: string(),
|
|
27557
27728
|
sampleCount: number().int().nonnegative(),
|
|
27558
|
-
|
|
27559
|
-
/** Inline base64 of the cover sample's plate crop, resolved from `
|
|
27729
|
+
coverMediaId: number().int().optional(),
|
|
27730
|
+
/** Inline base64 of the cover sample's plate crop, resolved from `coverMediaId`. */
|
|
27560
27731
|
coverBase64: string().optional()
|
|
27561
27732
|
});
|
|
27562
27733
|
var VehicleSampleInfoSchema = object({
|
|
@@ -27589,7 +27760,7 @@ var PlateInfoSchema = object({
|
|
|
27589
27760
|
/** keyFrame parity: the plate bbox (pixel space) on the native key frame. */
|
|
27590
27761
|
plateBbox: BoundingBoxSchema.optional(),
|
|
27591
27762
|
/** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
|
|
27592
|
-
|
|
27763
|
+
keyFrameMediaId: number().int().optional(),
|
|
27593
27764
|
base64: string().optional(),
|
|
27594
27765
|
/**
|
|
27595
27766
|
* Same crop as a data-plane URL, always present when the plate has a stored
|
|
@@ -27610,11 +27781,14 @@ var PlateInfoSchema = object({
|
|
|
27610
27781
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
27611
27782
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
27612
27783
|
*
|
|
27613
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
27614
|
-
* media
|
|
27784
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
27785
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
27786
|
+
* access decision.
|
|
27615
27787
|
*/
|
|
27616
27788
|
var MediaFileLiteSchema = object({
|
|
27617
|
-
|
|
27789
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
27790
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
27791
|
+
mediaId: number().int(),
|
|
27618
27792
|
kind: string(),
|
|
27619
27793
|
url: string(),
|
|
27620
27794
|
sizeBytes: number(),
|
|
@@ -27673,7 +27847,7 @@ method(object({
|
|
|
27673
27847
|
}), method(object({
|
|
27674
27848
|
/** Inline {@link VehicleSchema.coverBase64} on every row. Default
|
|
27675
27849
|
* `false` — the vehicle twin of `faceGallery.listIdentities`'s
|
|
27676
|
-
* option; `
|
|
27850
|
+
* option; `coverMediaId` + the `event-media` plane carry the picture.
|
|
27677
27851
|
* INPUT field: stripped by the hub router until the train ships, which
|
|
27678
27852
|
* resolves to `false` and is exactly the intended default. */
|
|
27679
27853
|
includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
|
|
@@ -28997,7 +29171,14 @@ var SceneReferenceSchema = object({
|
|
|
28997
29171
|
modelId: string(),
|
|
28998
29172
|
condition: SceneConditionSchema,
|
|
28999
29173
|
capturedAt: number(),
|
|
29000
|
-
|
|
29174
|
+
/**
|
|
29175
|
+
* The reference thumbnail's media ROW id (D482).
|
|
29176
|
+
*
|
|
29177
|
+
* The name already said `mediaId` while the value was the row's composite
|
|
29178
|
+
* key — a leftover that read as done and was not. It is the row's own id
|
|
29179
|
+
* now, addressed at `/addon/<addonId>/event-media/m/<id>`.
|
|
29180
|
+
*/
|
|
29181
|
+
thumbnailMediaId: number().int().optional(),
|
|
29001
29182
|
/** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
|
|
29002
29183
|
* anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
|
|
29003
29184
|
* normalized rect frame a different piece of world, and the scene would
|
|
@@ -29811,7 +29992,29 @@ var LoggingSettingsPatchSchema = object({
|
|
|
29811
29992
|
* disarmed the channels it did not mention would make the Levels page and
|
|
29812
29993
|
* the Diagnostics page fight over the same value.
|
|
29813
29994
|
*/
|
|
29814
|
-
channels: array(LogChannelWindowPatchSchema).readonly().optional()
|
|
29995
|
+
channels: array(LogChannelWindowPatchSchema).readonly().optional(),
|
|
29996
|
+
/**
|
|
29997
|
+
* How many days the analytics OPS LOG is kept — the audit trail of what
|
|
29998
|
+
* retention actually deleted.
|
|
29999
|
+
*
|
|
30000
|
+
* It lives HERE, on the logging document, and not on the analytics addon's
|
|
30001
|
+
* settings form, on the operator's instruction: every other log-ish window in
|
|
30002
|
+
* this system is configured through this one document, and a retention audit
|
|
30003
|
+
* configured somewhere else is a second place to look when the question is
|
|
30004
|
+
* "what happened to my data".
|
|
30005
|
+
*
|
|
30006
|
+
* That placement has a cost worth stating: this document ships in the
|
|
30007
|
+
* framework closure, so this knob needs a published `@camstack/server` while
|
|
30008
|
+
* the four windows beside it (D485) reach a node on `camstack deploy`.
|
|
30009
|
+
*
|
|
30010
|
+
* `retention-model.ts` argued this one must NOT follow a device window,
|
|
30011
|
+
* because the audit trail is the history of the SWEEP and not of the camera.
|
|
30012
|
+
* That argument stands and is untouched — what changes is that 30 days stops
|
|
30013
|
+
* being a constant nobody can reach. `0` keeps it forever. The floor is 1 day
|
|
30014
|
+
* rather than 0-as-delete: an audit log truncated to nothing is precisely the
|
|
30015
|
+
* state in which the next 9.5 GiB leak cannot be explained.
|
|
30016
|
+
*/
|
|
30017
|
+
opsLogRetentionDays: number().int().min(0).max(3650).optional()
|
|
29815
30018
|
});
|
|
29816
30019
|
/**
|
|
29817
30020
|
* Which LAYER of the hierarchy is addressed. Absent = the cluster layer.
|
|
@@ -29884,6 +30087,14 @@ var LoggingSettingsStateSchema = object({
|
|
|
29884
30087
|
channels: array(LogChannelDescriptorSchema).readonly(),
|
|
29885
30088
|
/** The channels ARMED right now, each with its deadline. */
|
|
29886
30089
|
activeChannels: array(LogChannelWindowStateSchema).readonly(),
|
|
30090
|
+
/**
|
|
30091
|
+
* The ops-log window in days, as it is in force. `0` = kept forever.
|
|
30092
|
+
*
|
|
30093
|
+
* Reported rather than left to the caller's memory of what it wrote: this is
|
|
30094
|
+
* the value the analytics sweep will actually use, and an operator asking how
|
|
30095
|
+
* long their audit trail lives should not have to infer it from a default.
|
|
30096
|
+
*/
|
|
30097
|
+
opsLogRetentionDays: number().int().min(0),
|
|
29887
30098
|
persisted: boolean()
|
|
29888
30099
|
});
|
|
29889
30100
|
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(), {
|
|
@@ -30445,7 +30656,7 @@ var StationaryObjectSchema = object({
|
|
|
30445
30656
|
/** Enrichment label carried from the source track (identity / plate). */
|
|
30446
30657
|
label: string().optional(),
|
|
30447
30658
|
/** Native-resolution key-frame media key for the parked object's best image. */
|
|
30448
|
-
|
|
30659
|
+
keyFrameMediaId: number().int().optional()
|
|
30449
30660
|
});
|
|
30450
30661
|
var CameraOccupancySnapshotSchema = object({
|
|
30451
30662
|
/** Frame timestamp of the inference result that produced this snapshot. */
|
|
@@ -31601,6 +31812,12 @@ Object.freeze({
|
|
|
31601
31812
|
addonId: null,
|
|
31602
31813
|
access: "create"
|
|
31603
31814
|
},
|
|
31815
|
+
"dataStoreProvider.upsert": {
|
|
31816
|
+
capName: "data-store-provider",
|
|
31817
|
+
capScope: "system",
|
|
31818
|
+
addonId: null,
|
|
31819
|
+
access: "create"
|
|
31820
|
+
},
|
|
31604
31821
|
"dayNight.getOptions": {
|
|
31605
31822
|
capName: "day-night",
|
|
31606
31823
|
capScope: "device",
|
|
@@ -34037,6 +34254,12 @@ Object.freeze({
|
|
|
34037
34254
|
addonId: null,
|
|
34038
34255
|
access: "view"
|
|
34039
34256
|
},
|
|
34257
|
+
"pipelineAnalytics.listRecentSummaries": {
|
|
34258
|
+
capName: "pipeline-analytics",
|
|
34259
|
+
capScope: "device",
|
|
34260
|
+
addonId: null,
|
|
34261
|
+
access: "view"
|
|
34262
|
+
},
|
|
34040
34263
|
"pipelineAnalytics.listRecentTracks": {
|
|
34041
34264
|
capName: "pipeline-analytics",
|
|
34042
34265
|
capScope: "device",
|
|
@@ -35465,6 +35688,12 @@ Object.freeze({
|
|
|
35465
35688
|
addonId: null,
|
|
35466
35689
|
access: "create"
|
|
35467
35690
|
},
|
|
35691
|
+
"settingsStore.upsert": {
|
|
35692
|
+
capName: "settings-store",
|
|
35693
|
+
capScope: "system",
|
|
35694
|
+
addonId: null,
|
|
35695
|
+
access: "create"
|
|
35696
|
+
},
|
|
35468
35697
|
"smtpProvider.getStatus": {
|
|
35469
35698
|
capName: "smtp-provider",
|
|
35470
35699
|
capScope: "system",
|
|
@@ -37858,6 +38087,11 @@ Object.freeze({
|
|
|
37858
38087
|
form: "single",
|
|
37859
38088
|
optional: true
|
|
37860
38089
|
}],
|
|
38090
|
+
"pipelineAnalytics.listRecentSummaries": [{
|
|
38091
|
+
name: "deviceIds",
|
|
38092
|
+
form: "array",
|
|
38093
|
+
optional: false
|
|
38094
|
+
}],
|
|
37861
38095
|
"pipelineAnalytics.listRecentTracks": [{
|
|
37862
38096
|
name: "deviceIds",
|
|
37863
38097
|
form: "array",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-mqtt-broker",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.101",
|
|
4
4
|
"description": "MQTT broker registry addon for CamStack — manages external broker entries + an optional embedded aedes broker. Consumers spin up their own `mqtt.js` clients via the `mqtt-broker` cap.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|