@camstack/addon-smtp-nodemailer 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/smtp.addon.js +292 -58
- package/dist/smtp.addon.mjs +292 -58
- package/package.json +1 -1
package/dist/smtp.addon.js
CHANGED
|
@@ -36,7 +36,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
36
36
|
}) : target, mod));
|
|
37
37
|
var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
38
38
|
//#endregion
|
|
39
|
-
//#region ../types/dist/event-category-
|
|
39
|
+
//#region ../types/dist/event-category-ZyX6jcse.mjs
|
|
40
40
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
41
41
|
EventCategory["SystemBoot"] = "system.boot";
|
|
42
42
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -597,7 +597,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
597
597
|
* a package zone — a newly-appeared stationary object of a package class
|
|
598
598
|
* that cleared the class / zone / dwell / size gates. Payload:
|
|
599
599
|
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
600
|
-
* entryId, className, zoneIds,
|
|
600
|
+
* entryId, className, zoneIds, keyFrameMediaId?, bbox, timestamp }`.
|
|
601
601
|
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
602
602
|
* this bus topic drives notifier rules + live UI. See
|
|
603
603
|
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
@@ -5383,7 +5383,7 @@ var ZodIssueCode = {
|
|
|
5383
5383
|
var ZodFirstPartyTypeKind;
|
|
5384
5384
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5385
5385
|
//#endregion
|
|
5386
|
-
//#region ../types/dist/sleep-
|
|
5386
|
+
//#region ../types/dist/sleep-DBKu2-U5.mjs
|
|
5387
5387
|
/**
|
|
5388
5388
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5389
5389
|
* window to float samples (D455).
|
|
@@ -7334,13 +7334,30 @@ new Set([
|
|
|
7334
7334
|
"scene",
|
|
7335
7335
|
"motion",
|
|
7336
7336
|
"object",
|
|
7337
|
-
"audio"
|
|
7337
|
+
"audio",
|
|
7338
|
+
"mosaic"
|
|
7338
7339
|
]);
|
|
7339
|
-
|
|
7340
|
+
/**
|
|
7341
|
+
* The owner types that are event tables, in the order the event-media resolver
|
|
7342
|
+
* should consider them. Exported so a consumer asking "is this key an event?"
|
|
7343
|
+
* does not re-spell the list and drift from it.
|
|
7344
|
+
*/
|
|
7345
|
+
var EVENT_OWNER_TYPES = [
|
|
7340
7346
|
"motion",
|
|
7341
7347
|
"object",
|
|
7342
7348
|
"audio"
|
|
7343
|
-
]
|
|
7349
|
+
];
|
|
7350
|
+
/**
|
|
7351
|
+
* The same list as a Zod enum, for the cap inputs that must NAME the table
|
|
7352
|
+
* (D482: `getEventMedia` / `listEventMedia` take an owner, and an owner is
|
|
7353
|
+
* `(table, id)`).
|
|
7354
|
+
*
|
|
7355
|
+
* Built FROM {@link EVENT_OWNER_TYPES} rather than re-spelled: a fourth event
|
|
7356
|
+
* table would otherwise be accepted by the codec and refused at the door, with
|
|
7357
|
+
* nothing failing until a caller asked.
|
|
7358
|
+
*/
|
|
7359
|
+
var EventOwnerTypeSchema = _enum(EVENT_OWNER_TYPES);
|
|
7360
|
+
new Set(EVENT_OWNER_TYPES);
|
|
7344
7361
|
var EncodeProfileSchema = object({
|
|
7345
7362
|
video: object({
|
|
7346
7363
|
codec: _enum([
|
|
@@ -7379,7 +7396,23 @@ var EncodeProfileSchema = object({
|
|
|
7379
7396
|
"zerolatency",
|
|
7380
7397
|
"film",
|
|
7381
7398
|
"animation"
|
|
7382
|
-
]).optional()
|
|
7399
|
+
]).optional(),
|
|
7400
|
+
/**
|
|
7401
|
+
* ONE slice per access unit.
|
|
7402
|
+
*
|
|
7403
|
+
* `-tune zerolatency` turns on x264's sliced threads, and a frame then leaves
|
|
7404
|
+
* the encoder as five NAL slices that share one RTP timestamp and carry one
|
|
7405
|
+
* marker bit. A libwebrtc depacketiser sees five frame-starts and one
|
|
7406
|
+
* frame-end per frame: the first pictures render and the video then freezes
|
|
7407
|
+
* for good while the audio, on its own plane, plays on. Measured on this hub
|
|
7408
|
+
* 2026-09-13 against the Echo, and reduced to one slice by this flag alone.
|
|
7409
|
+
*
|
|
7410
|
+
* A NAMED field and not a raw flag, because {@link EgressEncodeSchema} omits
|
|
7411
|
+
* `outputArgs` on purpose: an opaque array is part of the sharing key, so two
|
|
7412
|
+
* consumers meaning the same thing spelled differently would stop sharing one
|
|
7413
|
+
* child. Absent means "whatever the encoder does" — today's behaviour.
|
|
7414
|
+
*/
|
|
7415
|
+
singleSlicePerFrame: boolean().optional()
|
|
7383
7416
|
}),
|
|
7384
7417
|
audio: union([literal("passthrough"), object({
|
|
7385
7418
|
codec: _enum([
|
|
@@ -7429,7 +7462,7 @@ var BASE_LIVE_EGRESS_PROFILE = {
|
|
|
7429
7462
|
audio: "passthrough"
|
|
7430
7463
|
};
|
|
7431
7464
|
({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
|
|
7432
|
-
({ ...BASE_LIVE_EGRESS_PROFILE });
|
|
7465
|
+
({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
|
|
7433
7466
|
/**
|
|
7434
7467
|
* Deep wiring healthcheck — snapshot of active reachability probes across
|
|
7435
7468
|
* every declared capability + widget of every installed plugin, on every
|
|
@@ -12437,6 +12470,16 @@ method(object({
|
|
|
12437
12470
|
filter: QueryFilterSchema.optional(),
|
|
12438
12471
|
columns: array(string()).readonly().optional()
|
|
12439
12472
|
}), array(SettingsRecordSchema).readonly()), method(object({
|
|
12473
|
+
namespace: string().optional(),
|
|
12474
|
+
collection: string(),
|
|
12475
|
+
/** Declared columns identifying the slot; must be covered by a UNIQUE
|
|
12476
|
+
* index on the collection. Never empty. */
|
|
12477
|
+
conflict: array(string()).readonly(),
|
|
12478
|
+
record: BulkRecordSchema
|
|
12479
|
+
}), object({
|
|
12480
|
+
/** The id the row HAS: assigned by SQLite on an insert, or the existing
|
|
12481
|
+
* row's own id on an update. */
|
|
12482
|
+
id: union([string(), number()]) }), { kind: "mutation" }), method(object({
|
|
12440
12483
|
namespace: string().optional(),
|
|
12441
12484
|
collection: string(),
|
|
12442
12485
|
record: object({
|
|
@@ -12571,6 +12614,14 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
|
|
|
12571
12614
|
id: union([string(), number()]) }), {
|
|
12572
12615
|
kind: "mutation",
|
|
12573
12616
|
auth: "admin"
|
|
12617
|
+
}), method(object({
|
|
12618
|
+
namespace: string().optional(),
|
|
12619
|
+
collection: string(),
|
|
12620
|
+
conflict: array(string()).readonly(),
|
|
12621
|
+
record: BulkRecordSchema
|
|
12622
|
+
}), object({ id: union([string(), number()]) }), {
|
|
12623
|
+
kind: "mutation",
|
|
12624
|
+
auth: "admin"
|
|
12574
12625
|
}), method(object({
|
|
12575
12626
|
namespace: string().optional(),
|
|
12576
12627
|
collection: string(),
|
|
@@ -18787,8 +18838,8 @@ var TrackPositionSchema = object({
|
|
|
18787
18838
|
var TrackSnapshotSchema = object({
|
|
18788
18839
|
timestamp: number(),
|
|
18789
18840
|
position: TrackPositionSchema,
|
|
18790
|
-
/**
|
|
18791
|
-
|
|
18841
|
+
/** The snapshot's media row id (D482); resolve via `listTrackMedia({ trackId })`. */
|
|
18842
|
+
mediaId: number().int()
|
|
18792
18843
|
});
|
|
18793
18844
|
/**
|
|
18794
18845
|
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
@@ -19392,14 +19443,14 @@ var ObjectEventSchema = object({
|
|
|
19392
19443
|
* pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
|
|
19393
19444
|
frameWidth: number().optional(),
|
|
19394
19445
|
frameHeight: number().optional(),
|
|
19395
|
-
/**
|
|
19396
|
-
|
|
19397
|
-
/** Design B:
|
|
19446
|
+
/** Media row id of the crop attached to this event (if any) — D482. */
|
|
19447
|
+
mediaId: number().int().optional(),
|
|
19448
|
+
/** Design B: media row id of the track's native-resolution key frame (the
|
|
19398
19449
|
* best-detection full frame). Resolve via the event-media data-plane
|
|
19399
|
-
* (`/addon/<addonId>/event-media/<
|
|
19450
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`) for a detail view that
|
|
19400
19451
|
* draws `bbox` over the native frame. Absent on legacy rows / non-decoded
|
|
19401
|
-
* sources — consumers fall back to `
|
|
19402
|
-
|
|
19452
|
+
* sources — consumers fall back to `mediaId` (the tight crop). */
|
|
19453
|
+
keyFrameMediaId: number().int().optional(),
|
|
19403
19454
|
/** Populated by B5 (recording playback URL for this event). */
|
|
19404
19455
|
mediaUrl: string().optional(),
|
|
19405
19456
|
/** The parent track's key-event importance [0,1], propagated to every object
|
|
@@ -19449,7 +19500,7 @@ var MediaFileKindEnum = _enum([
|
|
|
19449
19500
|
* hub-main's heap on the way past — for an `<img>` that would have cached it.
|
|
19450
19501
|
*
|
|
19451
19502
|
* `url` points at the `event-media` data plane
|
|
19452
|
-
* (`/addon/<addonId>/event-media/<
|
|
19503
|
+
* (`/addon/<addonId>/event-media/m/<mediaId>` — D482), which serves the same blob
|
|
19453
19504
|
* with an ETag and `Cache-Control: immutable`, honours conditional GETs, can
|
|
19454
19505
|
* render a `?variant=thumb`, and streams. The hub gate in front of it requires
|
|
19455
19506
|
* a bearer or the session cookie (`access: 'authenticated'`), so the bytes are
|
|
@@ -19457,10 +19508,13 @@ var MediaFileKindEnum = _enum([
|
|
|
19457
19508
|
* `data-plane-access.ts` for the rule and the one gap it does not close
|
|
19458
19509
|
* (per-device scoping).
|
|
19459
19510
|
*
|
|
19460
|
-
* The URL is built from the row's
|
|
19461
|
-
*
|
|
19511
|
+
* The URL is built from the row's own id, which since D482 says nothing about
|
|
19512
|
+
* the row's owner or kind — and that is the point. The published `kind` is not
|
|
19513
|
+
* the stored one (a track's face/plate crop is stored as `crop` under
|
|
19462
19514
|
* `('face'|'plate', '<prefix>-<trackId>')` and published as
|
|
19463
|
-
* `faceCrop`/`plateCrop
|
|
19515
|
+
* `faceCrop`/`plateCrop`), and under the old composite key the URL had to be
|
|
19516
|
+
* taken from `row.key` verbatim or it 404'd exactly those two rows. An id
|
|
19517
|
+
* cannot be mis-reconstructed, because there is nothing in it to reconstruct.
|
|
19464
19518
|
*
|
|
19465
19519
|
* ## `base64` is TRANSITIONAL and is going away
|
|
19466
19520
|
*
|
|
@@ -19473,7 +19527,19 @@ var MediaFileKindEnum = _enum([
|
|
|
19473
19527
|
* `analytics-query-facade.ts`; nothing else reads it.
|
|
19474
19528
|
*/
|
|
19475
19529
|
var MediaFileSchema = object({
|
|
19476
|
-
|
|
19530
|
+
/**
|
|
19531
|
+
* The media row's OWN id — the rowid SQLite assigned it (D482).
|
|
19532
|
+
*
|
|
19533
|
+
* It used to be the row's composite key, `<ownerType>:<ownerId>:<fileKind>
|
|
19534
|
+
* [:<timestampMs>]`, which embedded a FOREIGN id. D474 made event ids
|
|
19535
|
+
* per-table rowid aliases, so `object:101314` and `motion:101314` are two
|
|
19536
|
+
* different rows that spell the same number, and a track whose
|
|
19537
|
+
* `bestEventId` was an object event was served a motion event's snapshot —
|
|
19538
|
+
* a night-time thumbnail on an afternoon track, with no error anywhere. A
|
|
19539
|
+
* surrogate id cannot name the wrong row's owner, because it names no owner
|
|
19540
|
+
* at all.
|
|
19541
|
+
*/
|
|
19542
|
+
mediaId: number().int(),
|
|
19477
19543
|
kind: MediaFileKindEnum,
|
|
19478
19544
|
sizeBytes: number(),
|
|
19479
19545
|
timestamp: number()
|
|
@@ -19581,7 +19647,7 @@ var RetrainTrackSchema = object({
|
|
|
19581
19647
|
});
|
|
19582
19648
|
/** A frame the picker may offer — an index row, no blob was read to produce it. */
|
|
19583
19649
|
var RetrainFrameCandidateSchema = object({
|
|
19584
|
-
|
|
19650
|
+
mediaId: number().int(),
|
|
19585
19651
|
kind: MediaFileKindEnum,
|
|
19586
19652
|
timestamp: number(),
|
|
19587
19653
|
sizeBytes: number().int(),
|
|
@@ -19595,7 +19661,7 @@ var RetrainFrameSchema = object({
|
|
|
19595
19661
|
deviceId: number(),
|
|
19596
19662
|
trackId: string(),
|
|
19597
19663
|
/** Provenance only. It may already point at nothing — that is expected. */
|
|
19598
|
-
|
|
19664
|
+
sourceMediaId: number().int(),
|
|
19599
19665
|
sourceKind: MediaFileKindEnum,
|
|
19600
19666
|
sizeBytes: number().int(),
|
|
19601
19667
|
width: number().int(),
|
|
@@ -19611,7 +19677,7 @@ var RetrainCopyRefusalSchema = _enum([
|
|
|
19611
19677
|
var RetrainFrameSelectionSchema = object({
|
|
19612
19678
|
copied: array(RetrainFrameSchema).readonly(),
|
|
19613
19679
|
refused: array(object({
|
|
19614
|
-
|
|
19680
|
+
sourceMediaId: number().int(),
|
|
19615
19681
|
reason: RetrainCopyRefusalSchema
|
|
19616
19682
|
})).readonly()
|
|
19617
19683
|
});
|
|
@@ -19619,7 +19685,7 @@ var RetrainFrameListSchema = object({
|
|
|
19619
19685
|
candidates: array(RetrainFrameCandidateSchema).readonly(),
|
|
19620
19686
|
copies: array(RetrainFrameSchema).readonly(),
|
|
19621
19687
|
/** What the page pre-selects — the native key frame when one survives. */
|
|
19622
|
-
|
|
19688
|
+
autoPickMediaId: number().int().optional()
|
|
19623
19689
|
});
|
|
19624
19690
|
/** What the operator asked the assist to look for. */
|
|
19625
19691
|
var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
|
|
@@ -19714,9 +19780,11 @@ var RecentTracksQueryInput = object({
|
|
|
19714
19780
|
});
|
|
19715
19781
|
/**
|
|
19716
19782
|
* A Summary (D359): the per-camera session envelope that references tracks.
|
|
19717
|
-
* `
|
|
19718
|
-
* served by the event-media plane
|
|
19719
|
-
* member visible has been materialised
|
|
19783
|
+
* `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
|
|
19784
|
+
* 'summary'`, served by the event-media plane at `/m/<id>`), null until the
|
|
19785
|
+
* first frame with a member visible has been materialised (D482 — it was the
|
|
19786
|
+
* row's composite key, which embedded the owner and could name another table's
|
|
19787
|
+
* row once event ids became per-table rowids).
|
|
19720
19788
|
*/
|
|
19721
19789
|
var SummarySchema = object({
|
|
19722
19790
|
id: string(),
|
|
@@ -19725,19 +19793,115 @@ var SummarySchema = object({
|
|
|
19725
19793
|
lastActiveAt: number(),
|
|
19726
19794
|
sealedAt: number().nullable(),
|
|
19727
19795
|
memberCount: number().int().nonnegative(),
|
|
19728
|
-
|
|
19796
|
+
groupShotMediaId: number().int().nullable()
|
|
19729
19797
|
});
|
|
19730
19798
|
var SummariesQueryInput = object({
|
|
19731
19799
|
deviceIds: array(number()).min(1),
|
|
19732
19800
|
since: number().optional(),
|
|
19733
19801
|
until: number().optional(),
|
|
19734
|
-
limit: number().int().min(1).max(200).default(50)
|
|
19802
|
+
limit: number().int().min(1).max(200).default(50),
|
|
19803
|
+
/** The same member-wise filter {@link listRecentSummaries} takes — one
|
|
19804
|
+
* meaning of "dog" on every summary surface. */
|
|
19805
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
19735
19806
|
});
|
|
19736
|
-
var SummariesPageSchema = object({ summaries: array(SummarySchema).readonly() });
|
|
19737
19807
|
var SummaryDetailSchema = object({
|
|
19738
19808
|
summary: SummarySchema,
|
|
19739
|
-
/**
|
|
19740
|
-
|
|
19809
|
+
/** Members in absorption order, oldest join first. */
|
|
19810
|
+
members: array(object({
|
|
19811
|
+
trackId: string(),
|
|
19812
|
+
/**
|
|
19813
|
+
* The track's class at the time it JOINED, or `null` when it was unresolved
|
|
19814
|
+
* and the track no longer exists to fill it.
|
|
19815
|
+
*
|
|
19816
|
+
* The join, not the latest opinion: class voting can re-decide a track's
|
|
19817
|
+
* class afterwards, and a group's composition is the history of who came
|
|
19818
|
+
* together. A consumer counts these to badge a thumbnail — "two people and a
|
|
19819
|
+
* dog" — rather than being handed a second, denormalised tally that would
|
|
19820
|
+
* drift from the members it claims to describe.
|
|
19821
|
+
*/
|
|
19822
|
+
className: string().nullable(),
|
|
19823
|
+
/** `primary` is the one member that carries the group's identity. */
|
|
19824
|
+
role: _enum([
|
|
19825
|
+
"primary",
|
|
19826
|
+
"sibling",
|
|
19827
|
+
"child"
|
|
19828
|
+
]).nullable(),
|
|
19829
|
+
joinedAt: number(),
|
|
19830
|
+
/** Tier 1 — the sub-class (`dog`, `van`), resolved from the member's track
|
|
19831
|
+
* at read time. Absent when nothing resolved, never an empty string. */
|
|
19832
|
+
label: string().optional(),
|
|
19833
|
+
/** Tier 2 — the instance: a person's name, a plate. Absent when the pipeline
|
|
19834
|
+
* recognised nobody, and absent for a member whose track has been pruned —
|
|
19835
|
+
* a thumbnail that names the wrong person is worse than one naming nobody. */
|
|
19836
|
+
subLabel: string().optional()
|
|
19837
|
+
})).readonly()
|
|
19838
|
+
});
|
|
19839
|
+
/**
|
|
19840
|
+
* What a LIST of groups carries: the envelope plus what it is MADE OF.
|
|
19841
|
+
*
|
|
19842
|
+
* Coarse on purpose — the operator's rule is "only the rough data on the list,
|
|
19843
|
+
* we extend when we notice we need more". Enough to draw the card ("two people
|
|
19844
|
+
* and a dog") and no more. The MEMBERS, their names and the per-member links
|
|
19845
|
+
* are on {@link getSummary}: shipping every member of every group so a client
|
|
19846
|
+
* can count them turns a page of two hundred groups into a thousand records to
|
|
19847
|
+
* draw two hundred badges.
|
|
19848
|
+
*/
|
|
19849
|
+
var SummaryListItemSchema = object({
|
|
19850
|
+
summary: SummarySchema,
|
|
19851
|
+
/** Class counts, most numerous first; `className: null` is a member whose
|
|
19852
|
+
* class never resolved, counted so the counts add up to `memberCount`. */
|
|
19853
|
+
classes: array(object({
|
|
19854
|
+
className: string().nullable(),
|
|
19855
|
+
count: number().int().positive()
|
|
19856
|
+
})).readonly()
|
|
19857
|
+
});
|
|
19858
|
+
var SummariesPageSchema = object({ summaries: array(SummaryListItemSchema).readonly() });
|
|
19859
|
+
/**
|
|
19860
|
+
* The paged feed, deliberately the SAME shape as {@link RecentTracksQueryInput}.
|
|
19861
|
+
*
|
|
19862
|
+
* The reel on the cameras page and the Events gallery both ride a cursor, so a
|
|
19863
|
+
* summaries feed that could only answer "the last N for these cameras"
|
|
19864
|
+
* (`listSummaries`) would make groups available in the timeline and nowhere
|
|
19865
|
+
* else. Two feeds with different ordering contracts would be two ideas of what
|
|
19866
|
+
* "newest" means, on one screen.
|
|
19867
|
+
*/
|
|
19868
|
+
var RecentSummariesQueryInput = object({
|
|
19869
|
+
/** Devices to merge. An empty array yields an empty page. */
|
|
19870
|
+
deviceIds: array(number()),
|
|
19871
|
+
/** Window lower bound on `lastActiveAt` (inclusive). */
|
|
19872
|
+
since: number().optional(),
|
|
19873
|
+
/** Window upper bound on `lastActiveAt` (inclusive). */
|
|
19874
|
+
until: number().optional(),
|
|
19875
|
+
limit: number().int().min(1).max(500).default(100),
|
|
19876
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`. */
|
|
19877
|
+
cursor: string().optional(),
|
|
19878
|
+
/**
|
|
19879
|
+
* Restrict to these classes — THE SAME FIELD `listRecentTracks` takes, and
|
|
19880
|
+
* deliberately the same name: the events filter tree emits one list of ticked
|
|
19881
|
+
* taxonomy nodes, and a summaries feed that called it something else would
|
|
19882
|
+
* make the operator's one filter component produce two shapes.
|
|
19883
|
+
*
|
|
19884
|
+
* A question about the MEMBERS: a group matches when ANY of them does. "Show
|
|
19885
|
+
* me the arrivals with a dog" has to return the group of four people who had
|
|
19886
|
+
* one with them; a filter on the group's own fields could only ever answer
|
|
19887
|
+
* about its primary.
|
|
19888
|
+
*
|
|
19889
|
+
* Matched against all THREE tiers of a member — the class (`animal`), the
|
|
19890
|
+
* sub-class (`dog`) and the instance (a name, a plate) — because which tier a
|
|
19891
|
+
* ticked node lives on is the taxonomy's business, not the caller's. `dog` is
|
|
19892
|
+
* an event kind in the tree and a tier-1 label on an `animal` track; a filter
|
|
19893
|
+
* that read only the class would answer "animal" and never "dog".
|
|
19894
|
+
*
|
|
19895
|
+
* ABSENT or EMPTY means no filter — absent is not a selection of none.
|
|
19896
|
+
*/
|
|
19897
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
19898
|
+
});
|
|
19899
|
+
var RecentSummariesPageSchema = object({
|
|
19900
|
+
/** Ordered by (`lastActiveAt` DESC, id DESC). Same light item as
|
|
19901
|
+
* {@link listSummaries} — one list shape, so a card renders the same
|
|
19902
|
+
* whichever feed drew it. */
|
|
19903
|
+
summaries: array(SummaryListItemSchema).readonly(),
|
|
19904
|
+
nextCursor: string().nullable()
|
|
19741
19905
|
});
|
|
19742
19906
|
var RecentTracksPageSchema = object({
|
|
19743
19907
|
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
@@ -20151,7 +20315,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20151
20315
|
classes: array(string()).optional(),
|
|
20152
20316
|
/** See {@link ExcludeSourcesDoc}. */
|
|
20153
20317
|
excludeSources: array(TrackSourceSchema).optional()
|
|
20154
|
-
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
20318
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(RecentSummariesQueryInput, RecentSummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
20155
20319
|
kind: "mutation",
|
|
20156
20320
|
auth: "admin"
|
|
20157
20321
|
}), 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({
|
|
@@ -20279,7 +20443,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20279
20443
|
}), method(object({
|
|
20280
20444
|
deviceId: number(),
|
|
20281
20445
|
trackId: string(),
|
|
20282
|
-
|
|
20446
|
+
mediaIds: array(number().int()).min(1)
|
|
20283
20447
|
}), RetrainFrameSelectionSchema, {
|
|
20284
20448
|
kind: "mutation",
|
|
20285
20449
|
auth: "admin"
|
|
@@ -20347,7 +20511,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20347
20511
|
kind: "query",
|
|
20348
20512
|
auth: "admin"
|
|
20349
20513
|
}), method(object({
|
|
20350
|
-
|
|
20514
|
+
/** Which of the three event tables owns the row. */
|
|
20515
|
+
ownerType: EventOwnerTypeSchema,
|
|
20516
|
+
/** The event's rowid in that table (D474: an event id is a number). */
|
|
20517
|
+
eventId: number().int(),
|
|
20351
20518
|
kind: MediaFileKindEnum.optional(),
|
|
20352
20519
|
deviceId: number()
|
|
20353
20520
|
}), array(MediaFileSchema).readonly()), method(object({
|
|
@@ -20358,7 +20525,8 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20358
20525
|
trackId: string(),
|
|
20359
20526
|
deviceId: number()
|
|
20360
20527
|
}), array(MediaFileInfoSchema).readonly()), method(object({
|
|
20361
|
-
|
|
20528
|
+
ownerType: EventOwnerTypeSchema,
|
|
20529
|
+
eventId: number().int(),
|
|
20362
20530
|
deviceId: number()
|
|
20363
20531
|
}), array(MediaFileInfoSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
|
|
20364
20532
|
kind: "mutation",
|
|
@@ -24834,8 +25002,8 @@ var IdentitySchema = object({
|
|
|
24834
25002
|
id: string(),
|
|
24835
25003
|
name: string(),
|
|
24836
25004
|
sampleCount: number().int().nonnegative(),
|
|
24837
|
-
|
|
24838
|
-
/** Inline base64 of the cover sample's crop, resolved from `
|
|
25005
|
+
coverMediaId: number().int().optional(),
|
|
25006
|
+
/** Inline base64 of the cover sample's crop, resolved from `coverMediaId`.
|
|
24839
25007
|
* Lets the UI render the person's face avatar instead of a placeholder icon. */
|
|
24840
25008
|
coverBase64: string().optional()
|
|
24841
25009
|
});
|
|
@@ -24861,8 +25029,8 @@ var IdentitySampleAuditRowSchema = object({
|
|
|
24861
25029
|
enrolledAt: number().int(),
|
|
24862
25030
|
deviceId: number().int().optional(),
|
|
24863
25031
|
source: _enum(["detected", "photo"]),
|
|
24864
|
-
/** The enrolled crop's media
|
|
24865
|
-
|
|
25032
|
+
/** The enrolled crop's media row id, so the panel can show the evidence. */
|
|
25033
|
+
mediaId: number().int().optional(),
|
|
24866
25034
|
/**
|
|
24867
25035
|
* False = the sample is stamped with a DIFFERENT face model, and a cosine
|
|
24868
25036
|
* across feature spaces is a well-formed float with no meaning. Every number
|
|
@@ -24931,15 +25099,15 @@ var FaceInfoSchema = object({
|
|
|
24931
25099
|
*/
|
|
24932
25100
|
cropUrl: string().optional(),
|
|
24933
25101
|
/** Design B: the face bbox (pixel space) on the key frame — lets a detail
|
|
24934
|
-
* view draw the box over the native `
|
|
25102
|
+
* view draw the box over the native `keyFrameMediaId` frame. Absent on
|
|
24935
25103
|
* legacy rows written before design B. */
|
|
24936
25104
|
faceBbox: BoundingBoxSchema.optional(),
|
|
24937
25105
|
/** Design B: MediaStore key of the track's native-resolution key frame.
|
|
24938
25106
|
* Fetch the native JPEG via the event-media data-plane
|
|
24939
|
-
* (`/addon/<addonId>/event-media/<
|
|
25107
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`). Absent when the
|
|
24940
25108
|
* track produced no key frame (e.g. native/onboard source) — the UI falls
|
|
24941
25109
|
* back to the inline `base64` face crop. */
|
|
24942
|
-
|
|
25110
|
+
keyFrameMediaId: number().int().optional(),
|
|
24943
25111
|
/** Winning identity-match cosine (0..1) for this face's track, when an
|
|
24944
25112
|
* identity was auto-confirmed. Lets the UI surface WHY a face was assigned
|
|
24945
25113
|
* (confidence badge / low-confidence audit). Absent on legacy rows and on
|
|
@@ -25008,11 +25176,14 @@ var FaceClusterSchema = object({
|
|
|
25008
25176
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
25009
25177
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
25010
25178
|
*
|
|
25011
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
25012
|
-
* media
|
|
25179
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
25180
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
25181
|
+
* access decision.
|
|
25013
25182
|
*/
|
|
25014
25183
|
var MediaFileLiteSchema$1 = object({
|
|
25015
|
-
|
|
25184
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
25185
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
25186
|
+
mediaId: number().int(),
|
|
25016
25187
|
kind: string(),
|
|
25017
25188
|
url: string(),
|
|
25018
25189
|
sizeBytes: number(),
|
|
@@ -25029,7 +25200,7 @@ method(object({
|
|
|
25029
25200
|
* covers inline, ~10 KB of base64 per row, on a query this UI mounts
|
|
25030
25201
|
* four times and the viewer holds at `staleTime: 30_000`.
|
|
25031
25202
|
*
|
|
25032
|
-
* Nothing loses its avatar: `
|
|
25203
|
+
* Nothing loses its avatar: `coverMediaId` is already on every row and
|
|
25033
25204
|
* the `event-media` plane serves that key `immutable` with an ETag.
|
|
25034
25205
|
*
|
|
25035
25206
|
* **This is an INPUT field, so it does not reach the addon until the
|
|
@@ -27497,8 +27668,8 @@ var VehicleSchema = object({
|
|
|
27497
27668
|
id: string(),
|
|
27498
27669
|
name: string(),
|
|
27499
27670
|
sampleCount: number().int().nonnegative(),
|
|
27500
|
-
|
|
27501
|
-
/** Inline base64 of the cover sample's plate crop, resolved from `
|
|
27671
|
+
coverMediaId: number().int().optional(),
|
|
27672
|
+
/** Inline base64 of the cover sample's plate crop, resolved from `coverMediaId`. */
|
|
27502
27673
|
coverBase64: string().optional()
|
|
27503
27674
|
});
|
|
27504
27675
|
var VehicleSampleInfoSchema = object({
|
|
@@ -27531,7 +27702,7 @@ var PlateInfoSchema = object({
|
|
|
27531
27702
|
/** keyFrame parity: the plate bbox (pixel space) on the native key frame. */
|
|
27532
27703
|
plateBbox: BoundingBoxSchema.optional(),
|
|
27533
27704
|
/** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
|
|
27534
|
-
|
|
27705
|
+
keyFrameMediaId: number().int().optional(),
|
|
27535
27706
|
base64: string().optional(),
|
|
27536
27707
|
/**
|
|
27537
27708
|
* Same crop as a data-plane URL, always present when the plate has a stored
|
|
@@ -27552,11 +27723,14 @@ var PlateInfoSchema = object({
|
|
|
27552
27723
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
27553
27724
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
27554
27725
|
*
|
|
27555
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
27556
|
-
* media
|
|
27726
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
27727
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
27728
|
+
* access decision.
|
|
27557
27729
|
*/
|
|
27558
27730
|
var MediaFileLiteSchema = object({
|
|
27559
|
-
|
|
27731
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
27732
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
27733
|
+
mediaId: number().int(),
|
|
27560
27734
|
kind: string(),
|
|
27561
27735
|
url: string(),
|
|
27562
27736
|
sizeBytes: number(),
|
|
@@ -27615,7 +27789,7 @@ method(object({
|
|
|
27615
27789
|
}), method(object({
|
|
27616
27790
|
/** Inline {@link VehicleSchema.coverBase64} on every row. Default
|
|
27617
27791
|
* `false` — the vehicle twin of `faceGallery.listIdentities`'s
|
|
27618
|
-
* option; `
|
|
27792
|
+
* option; `coverMediaId` + the `event-media` plane carry the picture.
|
|
27619
27793
|
* INPUT field: stripped by the hub router until the train ships, which
|
|
27620
27794
|
* resolves to `false` and is exactly the intended default. */
|
|
27621
27795
|
includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
|
|
@@ -28939,7 +29113,14 @@ var SceneReferenceSchema = object({
|
|
|
28939
29113
|
modelId: string(),
|
|
28940
29114
|
condition: SceneConditionSchema,
|
|
28941
29115
|
capturedAt: number(),
|
|
28942
|
-
|
|
29116
|
+
/**
|
|
29117
|
+
* The reference thumbnail's media ROW id (D482).
|
|
29118
|
+
*
|
|
29119
|
+
* The name already said `mediaId` while the value was the row's composite
|
|
29120
|
+
* key — a leftover that read as done and was not. It is the row's own id
|
|
29121
|
+
* now, addressed at `/addon/<addonId>/event-media/m/<id>`.
|
|
29122
|
+
*/
|
|
29123
|
+
thumbnailMediaId: number().int().optional(),
|
|
28943
29124
|
/** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
|
|
28944
29125
|
* anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
|
|
28945
29126
|
* normalized rect frame a different piece of world, and the scene would
|
|
@@ -29753,7 +29934,29 @@ var LoggingSettingsPatchSchema = object({
|
|
|
29753
29934
|
* disarmed the channels it did not mention would make the Levels page and
|
|
29754
29935
|
* the Diagnostics page fight over the same value.
|
|
29755
29936
|
*/
|
|
29756
|
-
channels: array(LogChannelWindowPatchSchema).readonly().optional()
|
|
29937
|
+
channels: array(LogChannelWindowPatchSchema).readonly().optional(),
|
|
29938
|
+
/**
|
|
29939
|
+
* How many days the analytics OPS LOG is kept — the audit trail of what
|
|
29940
|
+
* retention actually deleted.
|
|
29941
|
+
*
|
|
29942
|
+
* It lives HERE, on the logging document, and not on the analytics addon's
|
|
29943
|
+
* settings form, on the operator's instruction: every other log-ish window in
|
|
29944
|
+
* this system is configured through this one document, and a retention audit
|
|
29945
|
+
* configured somewhere else is a second place to look when the question is
|
|
29946
|
+
* "what happened to my data".
|
|
29947
|
+
*
|
|
29948
|
+
* That placement has a cost worth stating: this document ships in the
|
|
29949
|
+
* framework closure, so this knob needs a published `@camstack/server` while
|
|
29950
|
+
* the four windows beside it (D485) reach a node on `camstack deploy`.
|
|
29951
|
+
*
|
|
29952
|
+
* `retention-model.ts` argued this one must NOT follow a device window,
|
|
29953
|
+
* because the audit trail is the history of the SWEEP and not of the camera.
|
|
29954
|
+
* That argument stands and is untouched — what changes is that 30 days stops
|
|
29955
|
+
* being a constant nobody can reach. `0` keeps it forever. The floor is 1 day
|
|
29956
|
+
* rather than 0-as-delete: an audit log truncated to nothing is precisely the
|
|
29957
|
+
* state in which the next 9.5 GiB leak cannot be explained.
|
|
29958
|
+
*/
|
|
29959
|
+
opsLogRetentionDays: number().int().min(0).max(3650).optional()
|
|
29757
29960
|
});
|
|
29758
29961
|
/**
|
|
29759
29962
|
* Which LAYER of the hierarchy is addressed. Absent = the cluster layer.
|
|
@@ -29826,6 +30029,14 @@ var LoggingSettingsStateSchema = object({
|
|
|
29826
30029
|
channels: array(LogChannelDescriptorSchema).readonly(),
|
|
29827
30030
|
/** The channels ARMED right now, each with its deadline. */
|
|
29828
30031
|
activeChannels: array(LogChannelWindowStateSchema).readonly(),
|
|
30032
|
+
/**
|
|
30033
|
+
* The ops-log window in days, as it is in force. `0` = kept forever.
|
|
30034
|
+
*
|
|
30035
|
+
* Reported rather than left to the caller's memory of what it wrote: this is
|
|
30036
|
+
* the value the analytics sweep will actually use, and an operator asking how
|
|
30037
|
+
* long their audit trail lives should not have to infer it from a default.
|
|
30038
|
+
*/
|
|
30039
|
+
opsLogRetentionDays: number().int().min(0),
|
|
29829
30040
|
persisted: boolean()
|
|
29830
30041
|
});
|
|
29831
30042
|
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(), {
|
|
@@ -30387,7 +30598,7 @@ var StationaryObjectSchema = object({
|
|
|
30387
30598
|
/** Enrichment label carried from the source track (identity / plate). */
|
|
30388
30599
|
label: string().optional(),
|
|
30389
30600
|
/** Native-resolution key-frame media key for the parked object's best image. */
|
|
30390
|
-
|
|
30601
|
+
keyFrameMediaId: number().int().optional()
|
|
30391
30602
|
});
|
|
30392
30603
|
var CameraOccupancySnapshotSchema = object({
|
|
30393
30604
|
/** Frame timestamp of the inference result that produced this snapshot. */
|
|
@@ -31543,6 +31754,12 @@ Object.freeze({
|
|
|
31543
31754
|
addonId: null,
|
|
31544
31755
|
access: "create"
|
|
31545
31756
|
},
|
|
31757
|
+
"dataStoreProvider.upsert": {
|
|
31758
|
+
capName: "data-store-provider",
|
|
31759
|
+
capScope: "system",
|
|
31760
|
+
addonId: null,
|
|
31761
|
+
access: "create"
|
|
31762
|
+
},
|
|
31546
31763
|
"dayNight.getOptions": {
|
|
31547
31764
|
capName: "day-night",
|
|
31548
31765
|
capScope: "device",
|
|
@@ -33979,6 +34196,12 @@ Object.freeze({
|
|
|
33979
34196
|
addonId: null,
|
|
33980
34197
|
access: "view"
|
|
33981
34198
|
},
|
|
34199
|
+
"pipelineAnalytics.listRecentSummaries": {
|
|
34200
|
+
capName: "pipeline-analytics",
|
|
34201
|
+
capScope: "device",
|
|
34202
|
+
addonId: null,
|
|
34203
|
+
access: "view"
|
|
34204
|
+
},
|
|
33982
34205
|
"pipelineAnalytics.listRecentTracks": {
|
|
33983
34206
|
capName: "pipeline-analytics",
|
|
33984
34207
|
capScope: "device",
|
|
@@ -35407,6 +35630,12 @@ Object.freeze({
|
|
|
35407
35630
|
addonId: null,
|
|
35408
35631
|
access: "create"
|
|
35409
35632
|
},
|
|
35633
|
+
"settingsStore.upsert": {
|
|
35634
|
+
capName: "settings-store",
|
|
35635
|
+
capScope: "system",
|
|
35636
|
+
addonId: null,
|
|
35637
|
+
access: "create"
|
|
35638
|
+
},
|
|
35410
35639
|
"smtpProvider.getStatus": {
|
|
35411
35640
|
capName: "smtp-provider",
|
|
35412
35641
|
capScope: "system",
|
|
@@ -37800,6 +38029,11 @@ Object.freeze({
|
|
|
37800
38029
|
form: "single",
|
|
37801
38030
|
optional: true
|
|
37802
38031
|
}],
|
|
38032
|
+
"pipelineAnalytics.listRecentSummaries": [{
|
|
38033
|
+
name: "deviceIds",
|
|
38034
|
+
form: "array",
|
|
38035
|
+
optional: false
|
|
38036
|
+
}],
|
|
37803
38037
|
"pipelineAnalytics.listRecentTracks": [{
|
|
37804
38038
|
name: "deviceIds",
|
|
37805
38039
|
form: "array",
|
package/dist/smtp.addon.mjs
CHANGED
|
@@ -34,7 +34,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
34
34
|
var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
35
35
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
36
36
|
//#endregion
|
|
37
|
-
//#region ../types/dist/event-category-
|
|
37
|
+
//#region ../types/dist/event-category-ZyX6jcse.mjs
|
|
38
38
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
39
39
|
EventCategory["SystemBoot"] = "system.boot";
|
|
40
40
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -595,7 +595,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
595
595
|
* a package zone — a newly-appeared stationary object of a package class
|
|
596
596
|
* that cleared the class / zone / dwell / size gates. Payload:
|
|
597
597
|
* `PipelineAnalyticsPackageDeliveredPayload` carrying `{ deviceId,
|
|
598
|
-
* entryId, className, zoneIds,
|
|
598
|
+
* entryId, className, zoneIds, keyFrameMediaId?, bbox, timestamp }`.
|
|
599
599
|
* Telemetry (D8): the durable record is the `package-events` store row;
|
|
600
600
|
* this bus topic drives notifier rules + live UI. See
|
|
601
601
|
* docs/superpowers/specs/2026-07-17-package-zones-design.md §5.1.
|
|
@@ -5381,7 +5381,7 @@ var ZodIssueCode = {
|
|
|
5381
5381
|
var ZodFirstPartyTypeKind;
|
|
5382
5382
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5383
5383
|
//#endregion
|
|
5384
|
-
//#region ../types/dist/sleep-
|
|
5384
|
+
//#region ../types/dist/sleep-DBKu2-U5.mjs
|
|
5385
5385
|
/**
|
|
5386
5386
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5387
5387
|
* window to float samples (D455).
|
|
@@ -7332,13 +7332,30 @@ new Set([
|
|
|
7332
7332
|
"scene",
|
|
7333
7333
|
"motion",
|
|
7334
7334
|
"object",
|
|
7335
|
-
"audio"
|
|
7335
|
+
"audio",
|
|
7336
|
+
"mosaic"
|
|
7336
7337
|
]);
|
|
7337
|
-
|
|
7338
|
+
/**
|
|
7339
|
+
* The owner types that are event tables, in the order the event-media resolver
|
|
7340
|
+
* should consider them. Exported so a consumer asking "is this key an event?"
|
|
7341
|
+
* does not re-spell the list and drift from it.
|
|
7342
|
+
*/
|
|
7343
|
+
var EVENT_OWNER_TYPES = [
|
|
7338
7344
|
"motion",
|
|
7339
7345
|
"object",
|
|
7340
7346
|
"audio"
|
|
7341
|
-
]
|
|
7347
|
+
];
|
|
7348
|
+
/**
|
|
7349
|
+
* The same list as a Zod enum, for the cap inputs that must NAME the table
|
|
7350
|
+
* (D482: `getEventMedia` / `listEventMedia` take an owner, and an owner is
|
|
7351
|
+
* `(table, id)`).
|
|
7352
|
+
*
|
|
7353
|
+
* Built FROM {@link EVENT_OWNER_TYPES} rather than re-spelled: a fourth event
|
|
7354
|
+
* table would otherwise be accepted by the codec and refused at the door, with
|
|
7355
|
+
* nothing failing until a caller asked.
|
|
7356
|
+
*/
|
|
7357
|
+
var EventOwnerTypeSchema = _enum(EVENT_OWNER_TYPES);
|
|
7358
|
+
new Set(EVENT_OWNER_TYPES);
|
|
7342
7359
|
var EncodeProfileSchema = object({
|
|
7343
7360
|
video: object({
|
|
7344
7361
|
codec: _enum([
|
|
@@ -7377,7 +7394,23 @@ var EncodeProfileSchema = object({
|
|
|
7377
7394
|
"zerolatency",
|
|
7378
7395
|
"film",
|
|
7379
7396
|
"animation"
|
|
7380
|
-
]).optional()
|
|
7397
|
+
]).optional(),
|
|
7398
|
+
/**
|
|
7399
|
+
* ONE slice per access unit.
|
|
7400
|
+
*
|
|
7401
|
+
* `-tune zerolatency` turns on x264's sliced threads, and a frame then leaves
|
|
7402
|
+
* the encoder as five NAL slices that share one RTP timestamp and carry one
|
|
7403
|
+
* marker bit. A libwebrtc depacketiser sees five frame-starts and one
|
|
7404
|
+
* frame-end per frame: the first pictures render and the video then freezes
|
|
7405
|
+
* for good while the audio, on its own plane, plays on. Measured on this hub
|
|
7406
|
+
* 2026-09-13 against the Echo, and reduced to one slice by this flag alone.
|
|
7407
|
+
*
|
|
7408
|
+
* A NAMED field and not a raw flag, because {@link EgressEncodeSchema} omits
|
|
7409
|
+
* `outputArgs` on purpose: an opaque array is part of the sharing key, so two
|
|
7410
|
+
* consumers meaning the same thing spelled differently would stop sharing one
|
|
7411
|
+
* child. Absent means "whatever the encoder does" — today's behaviour.
|
|
7412
|
+
*/
|
|
7413
|
+
singleSlicePerFrame: boolean().optional()
|
|
7381
7414
|
}),
|
|
7382
7415
|
audio: union([literal("passthrough"), object({
|
|
7383
7416
|
codec: _enum([
|
|
@@ -7427,7 +7460,7 @@ var BASE_LIVE_EGRESS_PROFILE = {
|
|
|
7427
7460
|
audio: "passthrough"
|
|
7428
7461
|
};
|
|
7429
7462
|
({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
|
|
7430
|
-
({ ...BASE_LIVE_EGRESS_PROFILE });
|
|
7463
|
+
({ ...BASE_LIVE_EGRESS_PROFILE }), { ...BASE_LIVE_EGRESS_PROFILE.video };
|
|
7431
7464
|
/**
|
|
7432
7465
|
* Deep wiring healthcheck — snapshot of active reachability probes across
|
|
7433
7466
|
* every declared capability + widget of every installed plugin, on every
|
|
@@ -12435,6 +12468,16 @@ method(object({
|
|
|
12435
12468
|
filter: QueryFilterSchema.optional(),
|
|
12436
12469
|
columns: array(string()).readonly().optional()
|
|
12437
12470
|
}), array(SettingsRecordSchema).readonly()), method(object({
|
|
12471
|
+
namespace: string().optional(),
|
|
12472
|
+
collection: string(),
|
|
12473
|
+
/** Declared columns identifying the slot; must be covered by a UNIQUE
|
|
12474
|
+
* index on the collection. Never empty. */
|
|
12475
|
+
conflict: array(string()).readonly(),
|
|
12476
|
+
record: BulkRecordSchema
|
|
12477
|
+
}), object({
|
|
12478
|
+
/** The id the row HAS: assigned by SQLite on an insert, or the existing
|
|
12479
|
+
* row's own id on an update. */
|
|
12480
|
+
id: union([string(), number()]) }), { kind: "mutation" }), method(object({
|
|
12438
12481
|
namespace: string().optional(),
|
|
12439
12482
|
collection: string(),
|
|
12440
12483
|
record: object({
|
|
@@ -12569,6 +12612,14 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
|
|
|
12569
12612
|
id: union([string(), number()]) }), {
|
|
12570
12613
|
kind: "mutation",
|
|
12571
12614
|
auth: "admin"
|
|
12615
|
+
}), method(object({
|
|
12616
|
+
namespace: string().optional(),
|
|
12617
|
+
collection: string(),
|
|
12618
|
+
conflict: array(string()).readonly(),
|
|
12619
|
+
record: BulkRecordSchema
|
|
12620
|
+
}), object({ id: union([string(), number()]) }), {
|
|
12621
|
+
kind: "mutation",
|
|
12622
|
+
auth: "admin"
|
|
12572
12623
|
}), method(object({
|
|
12573
12624
|
namespace: string().optional(),
|
|
12574
12625
|
collection: string(),
|
|
@@ -18785,8 +18836,8 @@ var TrackPositionSchema = object({
|
|
|
18785
18836
|
var TrackSnapshotSchema = object({
|
|
18786
18837
|
timestamp: number(),
|
|
18787
18838
|
position: TrackPositionSchema,
|
|
18788
|
-
/**
|
|
18789
|
-
|
|
18839
|
+
/** The snapshot's media row id (D482); resolve via `listTrackMedia({ trackId })`. */
|
|
18840
|
+
mediaId: number().int()
|
|
18790
18841
|
});
|
|
18791
18842
|
/**
|
|
18792
18843
|
* Normalized 0..1 trajectory envelope (min/max over every position bbox,
|
|
@@ -19390,14 +19441,14 @@ var ObjectEventSchema = object({
|
|
|
19390
19441
|
* pixel-space `bbox` onto a displayed image. Omitted in slim projection. */
|
|
19391
19442
|
frameWidth: number().optional(),
|
|
19392
19443
|
frameHeight: number().optional(),
|
|
19393
|
-
/**
|
|
19394
|
-
|
|
19395
|
-
/** Design B:
|
|
19444
|
+
/** Media row id of the crop attached to this event (if any) — D482. */
|
|
19445
|
+
mediaId: number().int().optional(),
|
|
19446
|
+
/** Design B: media row id of the track's native-resolution key frame (the
|
|
19396
19447
|
* best-detection full frame). Resolve via the event-media data-plane
|
|
19397
|
-
* (`/addon/<addonId>/event-media/<
|
|
19448
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`) for a detail view that
|
|
19398
19449
|
* draws `bbox` over the native frame. Absent on legacy rows / non-decoded
|
|
19399
|
-
* sources — consumers fall back to `
|
|
19400
|
-
|
|
19450
|
+
* sources — consumers fall back to `mediaId` (the tight crop). */
|
|
19451
|
+
keyFrameMediaId: number().int().optional(),
|
|
19401
19452
|
/** Populated by B5 (recording playback URL for this event). */
|
|
19402
19453
|
mediaUrl: string().optional(),
|
|
19403
19454
|
/** The parent track's key-event importance [0,1], propagated to every object
|
|
@@ -19447,7 +19498,7 @@ var MediaFileKindEnum = _enum([
|
|
|
19447
19498
|
* hub-main's heap on the way past — for an `<img>` that would have cached it.
|
|
19448
19499
|
*
|
|
19449
19500
|
* `url` points at the `event-media` data plane
|
|
19450
|
-
* (`/addon/<addonId>/event-media/<
|
|
19501
|
+
* (`/addon/<addonId>/event-media/m/<mediaId>` — D482), which serves the same blob
|
|
19451
19502
|
* with an ETag and `Cache-Control: immutable`, honours conditional GETs, can
|
|
19452
19503
|
* render a `?variant=thumb`, and streams. The hub gate in front of it requires
|
|
19453
19504
|
* a bearer or the session cookie (`access: 'authenticated'`), so the bytes are
|
|
@@ -19455,10 +19506,13 @@ var MediaFileKindEnum = _enum([
|
|
|
19455
19506
|
* `data-plane-access.ts` for the rule and the one gap it does not close
|
|
19456
19507
|
* (per-device scoping).
|
|
19457
19508
|
*
|
|
19458
|
-
* The URL is built from the row's
|
|
19459
|
-
*
|
|
19509
|
+
* The URL is built from the row's own id, which since D482 says nothing about
|
|
19510
|
+
* the row's owner or kind — and that is the point. The published `kind` is not
|
|
19511
|
+
* the stored one (a track's face/plate crop is stored as `crop` under
|
|
19460
19512
|
* `('face'|'plate', '<prefix>-<trackId>')` and published as
|
|
19461
|
-
* `faceCrop`/`plateCrop
|
|
19513
|
+
* `faceCrop`/`plateCrop`), and under the old composite key the URL had to be
|
|
19514
|
+
* taken from `row.key` verbatim or it 404'd exactly those two rows. An id
|
|
19515
|
+
* cannot be mis-reconstructed, because there is nothing in it to reconstruct.
|
|
19462
19516
|
*
|
|
19463
19517
|
* ## `base64` is TRANSITIONAL and is going away
|
|
19464
19518
|
*
|
|
@@ -19471,7 +19525,19 @@ var MediaFileKindEnum = _enum([
|
|
|
19471
19525
|
* `analytics-query-facade.ts`; nothing else reads it.
|
|
19472
19526
|
*/
|
|
19473
19527
|
var MediaFileSchema = object({
|
|
19474
|
-
|
|
19528
|
+
/**
|
|
19529
|
+
* The media row's OWN id — the rowid SQLite assigned it (D482).
|
|
19530
|
+
*
|
|
19531
|
+
* It used to be the row's composite key, `<ownerType>:<ownerId>:<fileKind>
|
|
19532
|
+
* [:<timestampMs>]`, which embedded a FOREIGN id. D474 made event ids
|
|
19533
|
+
* per-table rowid aliases, so `object:101314` and `motion:101314` are two
|
|
19534
|
+
* different rows that spell the same number, and a track whose
|
|
19535
|
+
* `bestEventId` was an object event was served a motion event's snapshot —
|
|
19536
|
+
* a night-time thumbnail on an afternoon track, with no error anywhere. A
|
|
19537
|
+
* surrogate id cannot name the wrong row's owner, because it names no owner
|
|
19538
|
+
* at all.
|
|
19539
|
+
*/
|
|
19540
|
+
mediaId: number().int(),
|
|
19475
19541
|
kind: MediaFileKindEnum,
|
|
19476
19542
|
sizeBytes: number(),
|
|
19477
19543
|
timestamp: number()
|
|
@@ -19579,7 +19645,7 @@ var RetrainTrackSchema = object({
|
|
|
19579
19645
|
});
|
|
19580
19646
|
/** A frame the picker may offer — an index row, no blob was read to produce it. */
|
|
19581
19647
|
var RetrainFrameCandidateSchema = object({
|
|
19582
|
-
|
|
19648
|
+
mediaId: number().int(),
|
|
19583
19649
|
kind: MediaFileKindEnum,
|
|
19584
19650
|
timestamp: number(),
|
|
19585
19651
|
sizeBytes: number().int(),
|
|
@@ -19593,7 +19659,7 @@ var RetrainFrameSchema = object({
|
|
|
19593
19659
|
deviceId: number(),
|
|
19594
19660
|
trackId: string(),
|
|
19595
19661
|
/** Provenance only. It may already point at nothing — that is expected. */
|
|
19596
|
-
|
|
19662
|
+
sourceMediaId: number().int(),
|
|
19597
19663
|
sourceKind: MediaFileKindEnum,
|
|
19598
19664
|
sizeBytes: number().int(),
|
|
19599
19665
|
width: number().int(),
|
|
@@ -19609,7 +19675,7 @@ var RetrainCopyRefusalSchema = _enum([
|
|
|
19609
19675
|
var RetrainFrameSelectionSchema = object({
|
|
19610
19676
|
copied: array(RetrainFrameSchema).readonly(),
|
|
19611
19677
|
refused: array(object({
|
|
19612
|
-
|
|
19678
|
+
sourceMediaId: number().int(),
|
|
19613
19679
|
reason: RetrainCopyRefusalSchema
|
|
19614
19680
|
})).readonly()
|
|
19615
19681
|
});
|
|
@@ -19617,7 +19683,7 @@ var RetrainFrameListSchema = object({
|
|
|
19617
19683
|
candidates: array(RetrainFrameCandidateSchema).readonly(),
|
|
19618
19684
|
copies: array(RetrainFrameSchema).readonly(),
|
|
19619
19685
|
/** What the page pre-selects — the native key frame when one survives. */
|
|
19620
|
-
|
|
19686
|
+
autoPickMediaId: number().int().optional()
|
|
19621
19687
|
});
|
|
19622
19688
|
/** What the operator asked the assist to look for. */
|
|
19623
19689
|
var RetrainAssistSubjectSchema = discriminatedUnion("kind", [object({
|
|
@@ -19712,9 +19778,11 @@ var RecentTracksQueryInput = object({
|
|
|
19712
19778
|
});
|
|
19713
19779
|
/**
|
|
19714
19780
|
* A Summary (D359): the per-camera session envelope that references tracks.
|
|
19715
|
-
* `
|
|
19716
|
-
* served by the event-media plane
|
|
19717
|
-
* member visible has been materialised
|
|
19781
|
+
* `groupShotMediaId` is the media ROW id of its group shot (`ownerKind:
|
|
19782
|
+
* 'summary'`, served by the event-media plane at `/m/<id>`), null until the
|
|
19783
|
+
* first frame with a member visible has been materialised (D482 — it was the
|
|
19784
|
+
* row's composite key, which embedded the owner and could name another table's
|
|
19785
|
+
* row once event ids became per-table rowids).
|
|
19718
19786
|
*/
|
|
19719
19787
|
var SummarySchema = object({
|
|
19720
19788
|
id: string(),
|
|
@@ -19723,19 +19791,115 @@ var SummarySchema = object({
|
|
|
19723
19791
|
lastActiveAt: number(),
|
|
19724
19792
|
sealedAt: number().nullable(),
|
|
19725
19793
|
memberCount: number().int().nonnegative(),
|
|
19726
|
-
|
|
19794
|
+
groupShotMediaId: number().int().nullable()
|
|
19727
19795
|
});
|
|
19728
19796
|
var SummariesQueryInput = object({
|
|
19729
19797
|
deviceIds: array(number()).min(1),
|
|
19730
19798
|
since: number().optional(),
|
|
19731
19799
|
until: number().optional(),
|
|
19732
|
-
limit: number().int().min(1).max(200).default(50)
|
|
19800
|
+
limit: number().int().min(1).max(200).default(50),
|
|
19801
|
+
/** The same member-wise filter {@link listRecentSummaries} takes — one
|
|
19802
|
+
* meaning of "dog" on every summary surface. */
|
|
19803
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
19733
19804
|
});
|
|
19734
|
-
var SummariesPageSchema = object({ summaries: array(SummarySchema).readonly() });
|
|
19735
19805
|
var SummaryDetailSchema = object({
|
|
19736
19806
|
summary: SummarySchema,
|
|
19737
|
-
/**
|
|
19738
|
-
|
|
19807
|
+
/** Members in absorption order, oldest join first. */
|
|
19808
|
+
members: array(object({
|
|
19809
|
+
trackId: string(),
|
|
19810
|
+
/**
|
|
19811
|
+
* The track's class at the time it JOINED, or `null` when it was unresolved
|
|
19812
|
+
* and the track no longer exists to fill it.
|
|
19813
|
+
*
|
|
19814
|
+
* The join, not the latest opinion: class voting can re-decide a track's
|
|
19815
|
+
* class afterwards, and a group's composition is the history of who came
|
|
19816
|
+
* together. A consumer counts these to badge a thumbnail — "two people and a
|
|
19817
|
+
* dog" — rather than being handed a second, denormalised tally that would
|
|
19818
|
+
* drift from the members it claims to describe.
|
|
19819
|
+
*/
|
|
19820
|
+
className: string().nullable(),
|
|
19821
|
+
/** `primary` is the one member that carries the group's identity. */
|
|
19822
|
+
role: _enum([
|
|
19823
|
+
"primary",
|
|
19824
|
+
"sibling",
|
|
19825
|
+
"child"
|
|
19826
|
+
]).nullable(),
|
|
19827
|
+
joinedAt: number(),
|
|
19828
|
+
/** Tier 1 — the sub-class (`dog`, `van`), resolved from the member's track
|
|
19829
|
+
* at read time. Absent when nothing resolved, never an empty string. */
|
|
19830
|
+
label: string().optional(),
|
|
19831
|
+
/** Tier 2 — the instance: a person's name, a plate. Absent when the pipeline
|
|
19832
|
+
* recognised nobody, and absent for a member whose track has been pruned —
|
|
19833
|
+
* a thumbnail that names the wrong person is worse than one naming nobody. */
|
|
19834
|
+
subLabel: string().optional()
|
|
19835
|
+
})).readonly()
|
|
19836
|
+
});
|
|
19837
|
+
/**
|
|
19838
|
+
* What a LIST of groups carries: the envelope plus what it is MADE OF.
|
|
19839
|
+
*
|
|
19840
|
+
* Coarse on purpose — the operator's rule is "only the rough data on the list,
|
|
19841
|
+
* we extend when we notice we need more". Enough to draw the card ("two people
|
|
19842
|
+
* and a dog") and no more. The MEMBERS, their names and the per-member links
|
|
19843
|
+
* are on {@link getSummary}: shipping every member of every group so a client
|
|
19844
|
+
* can count them turns a page of two hundred groups into a thousand records to
|
|
19845
|
+
* draw two hundred badges.
|
|
19846
|
+
*/
|
|
19847
|
+
var SummaryListItemSchema = object({
|
|
19848
|
+
summary: SummarySchema,
|
|
19849
|
+
/** Class counts, most numerous first; `className: null` is a member whose
|
|
19850
|
+
* class never resolved, counted so the counts add up to `memberCount`. */
|
|
19851
|
+
classes: array(object({
|
|
19852
|
+
className: string().nullable(),
|
|
19853
|
+
count: number().int().positive()
|
|
19854
|
+
})).readonly()
|
|
19855
|
+
});
|
|
19856
|
+
var SummariesPageSchema = object({ summaries: array(SummaryListItemSchema).readonly() });
|
|
19857
|
+
/**
|
|
19858
|
+
* The paged feed, deliberately the SAME shape as {@link RecentTracksQueryInput}.
|
|
19859
|
+
*
|
|
19860
|
+
* The reel on the cameras page and the Events gallery both ride a cursor, so a
|
|
19861
|
+
* summaries feed that could only answer "the last N for these cameras"
|
|
19862
|
+
* (`listSummaries`) would make groups available in the timeline and nowhere
|
|
19863
|
+
* else. Two feeds with different ordering contracts would be two ideas of what
|
|
19864
|
+
* "newest" means, on one screen.
|
|
19865
|
+
*/
|
|
19866
|
+
var RecentSummariesQueryInput = object({
|
|
19867
|
+
/** Devices to merge. An empty array yields an empty page. */
|
|
19868
|
+
deviceIds: array(number()),
|
|
19869
|
+
/** Window lower bound on `lastActiveAt` (inclusive). */
|
|
19870
|
+
since: number().optional(),
|
|
19871
|
+
/** Window upper bound on `lastActiveAt` (inclusive). */
|
|
19872
|
+
until: number().optional(),
|
|
19873
|
+
limit: number().int().min(1).max(500).default(100),
|
|
19874
|
+
/** Opaque continuation cursor from a previous page's `nextCursor`. */
|
|
19875
|
+
cursor: string().optional(),
|
|
19876
|
+
/**
|
|
19877
|
+
* Restrict to these classes — THE SAME FIELD `listRecentTracks` takes, and
|
|
19878
|
+
* deliberately the same name: the events filter tree emits one list of ticked
|
|
19879
|
+
* taxonomy nodes, and a summaries feed that called it something else would
|
|
19880
|
+
* make the operator's one filter component produce two shapes.
|
|
19881
|
+
*
|
|
19882
|
+
* A question about the MEMBERS: a group matches when ANY of them does. "Show
|
|
19883
|
+
* me the arrivals with a dog" has to return the group of four people who had
|
|
19884
|
+
* one with them; a filter on the group's own fields could only ever answer
|
|
19885
|
+
* about its primary.
|
|
19886
|
+
*
|
|
19887
|
+
* Matched against all THREE tiers of a member — the class (`animal`), the
|
|
19888
|
+
* sub-class (`dog`) and the instance (a name, a plate) — because which tier a
|
|
19889
|
+
* ticked node lives on is the taxonomy's business, not the caller's. `dog` is
|
|
19890
|
+
* an event kind in the tree and a tier-1 label on an `animal` track; a filter
|
|
19891
|
+
* that read only the class would answer "animal" and never "dog".
|
|
19892
|
+
*
|
|
19893
|
+
* ABSENT or EMPTY means no filter — absent is not a selection of none.
|
|
19894
|
+
*/
|
|
19895
|
+
classes: array(string().min(1).max(60)).max(40).optional()
|
|
19896
|
+
});
|
|
19897
|
+
var RecentSummariesPageSchema = object({
|
|
19898
|
+
/** Ordered by (`lastActiveAt` DESC, id DESC). Same light item as
|
|
19899
|
+
* {@link listSummaries} — one list shape, so a card renders the same
|
|
19900
|
+
* whichever feed drew it. */
|
|
19901
|
+
summaries: array(SummaryListItemSchema).readonly(),
|
|
19902
|
+
nextCursor: string().nullable()
|
|
19739
19903
|
});
|
|
19740
19904
|
var RecentTracksPageSchema = object({
|
|
19741
19905
|
/** Merged page, ordered by (`lastSeen` DESC, `trackId` DESC). */
|
|
@@ -20149,7 +20313,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20149
20313
|
classes: array(string()).optional(),
|
|
20150
20314
|
/** See {@link ExcludeSourcesDoc}. */
|
|
20151
20315
|
excludeSources: array(TrackSourceSchema).optional()
|
|
20152
|
-
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
20316
|
+
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(SummariesQueryInput, SummariesPageSchema), method(RecentSummariesQueryInput, RecentSummariesPageSchema), method(object({ id: string() }), SummaryDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
|
|
20153
20317
|
kind: "mutation",
|
|
20154
20318
|
auth: "admin"
|
|
20155
20319
|
}), 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({
|
|
@@ -20277,7 +20441,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20277
20441
|
}), method(object({
|
|
20278
20442
|
deviceId: number(),
|
|
20279
20443
|
trackId: string(),
|
|
20280
|
-
|
|
20444
|
+
mediaIds: array(number().int()).min(1)
|
|
20281
20445
|
}), RetrainFrameSelectionSchema, {
|
|
20282
20446
|
kind: "mutation",
|
|
20283
20447
|
auth: "admin"
|
|
@@ -20345,7 +20509,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20345
20509
|
kind: "query",
|
|
20346
20510
|
auth: "admin"
|
|
20347
20511
|
}), method(object({
|
|
20348
|
-
|
|
20512
|
+
/** Which of the three event tables owns the row. */
|
|
20513
|
+
ownerType: EventOwnerTypeSchema,
|
|
20514
|
+
/** The event's rowid in that table (D474: an event id is a number). */
|
|
20515
|
+
eventId: number().int(),
|
|
20349
20516
|
kind: MediaFileKindEnum.optional(),
|
|
20350
20517
|
deviceId: number()
|
|
20351
20518
|
}), array(MediaFileSchema).readonly()), method(object({
|
|
@@ -20356,7 +20523,8 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
20356
20523
|
trackId: string(),
|
|
20357
20524
|
deviceId: number()
|
|
20358
20525
|
}), array(MediaFileInfoSchema).readonly()), method(object({
|
|
20359
|
-
|
|
20526
|
+
ownerType: EventOwnerTypeSchema,
|
|
20527
|
+
eventId: number().int(),
|
|
20360
20528
|
deviceId: number()
|
|
20361
20529
|
}), array(MediaFileInfoSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), method(object({}), WipeObjectEmbeddingsResultSchema, {
|
|
20362
20530
|
kind: "mutation",
|
|
@@ -24832,8 +25000,8 @@ var IdentitySchema = object({
|
|
|
24832
25000
|
id: string(),
|
|
24833
25001
|
name: string(),
|
|
24834
25002
|
sampleCount: number().int().nonnegative(),
|
|
24835
|
-
|
|
24836
|
-
/** Inline base64 of the cover sample's crop, resolved from `
|
|
25003
|
+
coverMediaId: number().int().optional(),
|
|
25004
|
+
/** Inline base64 of the cover sample's crop, resolved from `coverMediaId`.
|
|
24837
25005
|
* Lets the UI render the person's face avatar instead of a placeholder icon. */
|
|
24838
25006
|
coverBase64: string().optional()
|
|
24839
25007
|
});
|
|
@@ -24859,8 +25027,8 @@ var IdentitySampleAuditRowSchema = object({
|
|
|
24859
25027
|
enrolledAt: number().int(),
|
|
24860
25028
|
deviceId: number().int().optional(),
|
|
24861
25029
|
source: _enum(["detected", "photo"]),
|
|
24862
|
-
/** The enrolled crop's media
|
|
24863
|
-
|
|
25030
|
+
/** The enrolled crop's media row id, so the panel can show the evidence. */
|
|
25031
|
+
mediaId: number().int().optional(),
|
|
24864
25032
|
/**
|
|
24865
25033
|
* False = the sample is stamped with a DIFFERENT face model, and a cosine
|
|
24866
25034
|
* across feature spaces is a well-formed float with no meaning. Every number
|
|
@@ -24929,15 +25097,15 @@ var FaceInfoSchema = object({
|
|
|
24929
25097
|
*/
|
|
24930
25098
|
cropUrl: string().optional(),
|
|
24931
25099
|
/** Design B: the face bbox (pixel space) on the key frame — lets a detail
|
|
24932
|
-
* view draw the box over the native `
|
|
25100
|
+
* view draw the box over the native `keyFrameMediaId` frame. Absent on
|
|
24933
25101
|
* legacy rows written before design B. */
|
|
24934
25102
|
faceBbox: BoundingBoxSchema.optional(),
|
|
24935
25103
|
/** Design B: MediaStore key of the track's native-resolution key frame.
|
|
24936
25104
|
* Fetch the native JPEG via the event-media data-plane
|
|
24937
|
-
* (`/addon/<addonId>/event-media/<
|
|
25105
|
+
* (`/addon/<addonId>/event-media/m/<keyFrameMediaId>`). Absent when the
|
|
24938
25106
|
* track produced no key frame (e.g. native/onboard source) — the UI falls
|
|
24939
25107
|
* back to the inline `base64` face crop. */
|
|
24940
|
-
|
|
25108
|
+
keyFrameMediaId: number().int().optional(),
|
|
24941
25109
|
/** Winning identity-match cosine (0..1) for this face's track, when an
|
|
24942
25110
|
* identity was auto-confirmed. Lets the UI surface WHY a face was assigned
|
|
24943
25111
|
* (confidence badge / low-confidence audit). Absent on legacy rows and on
|
|
@@ -25006,11 +25174,14 @@ var FaceClusterSchema = object({
|
|
|
25006
25174
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
25007
25175
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
25008
25176
|
*
|
|
25009
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
25010
|
-
* media
|
|
25177
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
25178
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
25179
|
+
* access decision.
|
|
25011
25180
|
*/
|
|
25012
25181
|
var MediaFileLiteSchema$1 = object({
|
|
25013
|
-
|
|
25182
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
25183
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
25184
|
+
mediaId: number().int(),
|
|
25014
25185
|
kind: string(),
|
|
25015
25186
|
url: string(),
|
|
25016
25187
|
sizeBytes: number(),
|
|
@@ -25027,7 +25198,7 @@ method(object({
|
|
|
25027
25198
|
* covers inline, ~10 KB of base64 per row, on a query this UI mounts
|
|
25028
25199
|
* four times and the viewer holds at `staleTime: 30_000`.
|
|
25029
25200
|
*
|
|
25030
|
-
* Nothing loses its avatar: `
|
|
25201
|
+
* Nothing loses its avatar: `coverMediaId` is already on every row and
|
|
25031
25202
|
* the `event-media` plane serves that key `immutable` with an ETag.
|
|
25032
25203
|
*
|
|
25033
25204
|
* **This is an INPUT field, so it does not reach the addon until the
|
|
@@ -27495,8 +27666,8 @@ var VehicleSchema = object({
|
|
|
27495
27666
|
id: string(),
|
|
27496
27667
|
name: string(),
|
|
27497
27668
|
sampleCount: number().int().nonnegative(),
|
|
27498
|
-
|
|
27499
|
-
/** Inline base64 of the cover sample's plate crop, resolved from `
|
|
27669
|
+
coverMediaId: number().int().optional(),
|
|
27670
|
+
/** Inline base64 of the cover sample's plate crop, resolved from `coverMediaId`. */
|
|
27500
27671
|
coverBase64: string().optional()
|
|
27501
27672
|
});
|
|
27502
27673
|
var VehicleSampleInfoSchema = object({
|
|
@@ -27529,7 +27700,7 @@ var PlateInfoSchema = object({
|
|
|
27529
27700
|
/** keyFrame parity: the plate bbox (pixel space) on the native key frame. */
|
|
27530
27701
|
plateBbox: BoundingBoxSchema.optional(),
|
|
27531
27702
|
/** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
|
|
27532
|
-
|
|
27703
|
+
keyFrameMediaId: number().int().optional(),
|
|
27533
27704
|
base64: string().optional(),
|
|
27534
27705
|
/**
|
|
27535
27706
|
* Same crop as a data-plane URL, always present when the plate has a stored
|
|
@@ -27550,11 +27721,14 @@ var PlateInfoSchema = object({
|
|
|
27550
27721
|
* `data:image/jpeg;base64,…` from a row whose `key` sat right beside it, in a
|
|
27551
27722
|
* dialog already rendering its key FRAME from the `event-media` plane.
|
|
27552
27723
|
*
|
|
27553
|
-
* `url` is `/addon/<addonId>/event-media/<
|
|
27554
|
-
* media
|
|
27724
|
+
* `url` is `/addon/<addonId>/event-media/m/<mediaId>` (D482). The plane
|
|
27725
|
+
* resolves a media row by its own id, so this needed no new plane and no new
|
|
27726
|
+
* access decision.
|
|
27555
27727
|
*/
|
|
27556
27728
|
var MediaFileLiteSchema = object({
|
|
27557
|
-
|
|
27729
|
+
/** The media row's own id — the same address `MediaFileRef.mediaId` carries
|
|
27730
|
+
* (D482). It was the row's composite key, which embedded the owner. */
|
|
27731
|
+
mediaId: number().int(),
|
|
27558
27732
|
kind: string(),
|
|
27559
27733
|
url: string(),
|
|
27560
27734
|
sizeBytes: number(),
|
|
@@ -27613,7 +27787,7 @@ method(object({
|
|
|
27613
27787
|
}), method(object({
|
|
27614
27788
|
/** Inline {@link VehicleSchema.coverBase64} on every row. Default
|
|
27615
27789
|
* `false` — the vehicle twin of `faceGallery.listIdentities`'s
|
|
27616
|
-
* option; `
|
|
27790
|
+
* option; `coverMediaId` + the `event-media` plane carry the picture.
|
|
27617
27791
|
* INPUT field: stripped by the hub router until the train ships, which
|
|
27618
27792
|
* resolves to `false` and is exactly the intended default. */
|
|
27619
27793
|
includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
|
|
@@ -28937,7 +29111,14 @@ var SceneReferenceSchema = object({
|
|
|
28937
29111
|
modelId: string(),
|
|
28938
29112
|
condition: SceneConditionSchema,
|
|
28939
29113
|
capturedAt: number(),
|
|
28940
|
-
|
|
29114
|
+
/**
|
|
29115
|
+
* The reference thumbnail's media ROW id (D482).
|
|
29116
|
+
*
|
|
29117
|
+
* The name already said `mediaId` while the value was the row's composite
|
|
29118
|
+
* key — a leftover that read as done and was not. It is the row's own id
|
|
29119
|
+
* now, addressed at `/addon/<addonId>/event-media/m/<id>`.
|
|
29120
|
+
*/
|
|
29121
|
+
thumbnailMediaId: number().int().optional(),
|
|
28941
29122
|
/** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
|
|
28942
29123
|
* anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
|
|
28943
29124
|
* normalized rect frame a different piece of world, and the scene would
|
|
@@ -29751,7 +29932,29 @@ var LoggingSettingsPatchSchema = object({
|
|
|
29751
29932
|
* disarmed the channels it did not mention would make the Levels page and
|
|
29752
29933
|
* the Diagnostics page fight over the same value.
|
|
29753
29934
|
*/
|
|
29754
|
-
channels: array(LogChannelWindowPatchSchema).readonly().optional()
|
|
29935
|
+
channels: array(LogChannelWindowPatchSchema).readonly().optional(),
|
|
29936
|
+
/**
|
|
29937
|
+
* How many days the analytics OPS LOG is kept — the audit trail of what
|
|
29938
|
+
* retention actually deleted.
|
|
29939
|
+
*
|
|
29940
|
+
* It lives HERE, on the logging document, and not on the analytics addon's
|
|
29941
|
+
* settings form, on the operator's instruction: every other log-ish window in
|
|
29942
|
+
* this system is configured through this one document, and a retention audit
|
|
29943
|
+
* configured somewhere else is a second place to look when the question is
|
|
29944
|
+
* "what happened to my data".
|
|
29945
|
+
*
|
|
29946
|
+
* That placement has a cost worth stating: this document ships in the
|
|
29947
|
+
* framework closure, so this knob needs a published `@camstack/server` while
|
|
29948
|
+
* the four windows beside it (D485) reach a node on `camstack deploy`.
|
|
29949
|
+
*
|
|
29950
|
+
* `retention-model.ts` argued this one must NOT follow a device window,
|
|
29951
|
+
* because the audit trail is the history of the SWEEP and not of the camera.
|
|
29952
|
+
* That argument stands and is untouched — what changes is that 30 days stops
|
|
29953
|
+
* being a constant nobody can reach. `0` keeps it forever. The floor is 1 day
|
|
29954
|
+
* rather than 0-as-delete: an audit log truncated to nothing is precisely the
|
|
29955
|
+
* state in which the next 9.5 GiB leak cannot be explained.
|
|
29956
|
+
*/
|
|
29957
|
+
opsLogRetentionDays: number().int().min(0).max(3650).optional()
|
|
29755
29958
|
});
|
|
29756
29959
|
/**
|
|
29757
29960
|
* Which LAYER of the hierarchy is addressed. Absent = the cluster layer.
|
|
@@ -29824,6 +30027,14 @@ var LoggingSettingsStateSchema = object({
|
|
|
29824
30027
|
channels: array(LogChannelDescriptorSchema).readonly(),
|
|
29825
30028
|
/** The channels ARMED right now, each with its deadline. */
|
|
29826
30029
|
activeChannels: array(LogChannelWindowStateSchema).readonly(),
|
|
30030
|
+
/**
|
|
30031
|
+
* The ops-log window in days, as it is in force. `0` = kept forever.
|
|
30032
|
+
*
|
|
30033
|
+
* Reported rather than left to the caller's memory of what it wrote: this is
|
|
30034
|
+
* the value the analytics sweep will actually use, and an operator asking how
|
|
30035
|
+
* long their audit trail lives should not have to infer it from a default.
|
|
30036
|
+
*/
|
|
30037
|
+
opsLogRetentionDays: number().int().min(0),
|
|
29827
30038
|
persisted: boolean()
|
|
29828
30039
|
});
|
|
29829
30040
|
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(), {
|
|
@@ -30385,7 +30596,7 @@ var StationaryObjectSchema = object({
|
|
|
30385
30596
|
/** Enrichment label carried from the source track (identity / plate). */
|
|
30386
30597
|
label: string().optional(),
|
|
30387
30598
|
/** Native-resolution key-frame media key for the parked object's best image. */
|
|
30388
|
-
|
|
30599
|
+
keyFrameMediaId: number().int().optional()
|
|
30389
30600
|
});
|
|
30390
30601
|
var CameraOccupancySnapshotSchema = object({
|
|
30391
30602
|
/** Frame timestamp of the inference result that produced this snapshot. */
|
|
@@ -31541,6 +31752,12 @@ Object.freeze({
|
|
|
31541
31752
|
addonId: null,
|
|
31542
31753
|
access: "create"
|
|
31543
31754
|
},
|
|
31755
|
+
"dataStoreProvider.upsert": {
|
|
31756
|
+
capName: "data-store-provider",
|
|
31757
|
+
capScope: "system",
|
|
31758
|
+
addonId: null,
|
|
31759
|
+
access: "create"
|
|
31760
|
+
},
|
|
31544
31761
|
"dayNight.getOptions": {
|
|
31545
31762
|
capName: "day-night",
|
|
31546
31763
|
capScope: "device",
|
|
@@ -33977,6 +34194,12 @@ Object.freeze({
|
|
|
33977
34194
|
addonId: null,
|
|
33978
34195
|
access: "view"
|
|
33979
34196
|
},
|
|
34197
|
+
"pipelineAnalytics.listRecentSummaries": {
|
|
34198
|
+
capName: "pipeline-analytics",
|
|
34199
|
+
capScope: "device",
|
|
34200
|
+
addonId: null,
|
|
34201
|
+
access: "view"
|
|
34202
|
+
},
|
|
33980
34203
|
"pipelineAnalytics.listRecentTracks": {
|
|
33981
34204
|
capName: "pipeline-analytics",
|
|
33982
34205
|
capScope: "device",
|
|
@@ -35405,6 +35628,12 @@ Object.freeze({
|
|
|
35405
35628
|
addonId: null,
|
|
35406
35629
|
access: "create"
|
|
35407
35630
|
},
|
|
35631
|
+
"settingsStore.upsert": {
|
|
35632
|
+
capName: "settings-store",
|
|
35633
|
+
capScope: "system",
|
|
35634
|
+
addonId: null,
|
|
35635
|
+
access: "create"
|
|
35636
|
+
},
|
|
35408
35637
|
"smtpProvider.getStatus": {
|
|
35409
35638
|
capName: "smtp-provider",
|
|
35410
35639
|
capScope: "system",
|
|
@@ -37798,6 +38027,11 @@ Object.freeze({
|
|
|
37798
38027
|
form: "single",
|
|
37799
38028
|
optional: true
|
|
37800
38029
|
}],
|
|
38030
|
+
"pipelineAnalytics.listRecentSummaries": [{
|
|
38031
|
+
name: "deviceIds",
|
|
38032
|
+
form: "array",
|
|
38033
|
+
optional: false
|
|
38034
|
+
}],
|
|
37801
38035
|
"pipelineAnalytics.listRecentTracks": [{
|
|
37802
38036
|
name: "deviceIds",
|
|
37803
38037
|
form: "array",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-smtp-nodemailer",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.100",
|
|
4
4
|
"description": "SMTP email provider addon for CamStack — wraps `nodemailer` and registers a `smtp-provider` cap collection entry. Used by magic-link login + notifier addons.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|