@camstack/addon-smtp-nodemailer 1.1.25 → 1.1.27
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 +511 -2
- package/dist/smtp.addon.mjs +511 -2
- package/package.json +1 -1
package/dist/smtp.addon.js
CHANGED
|
@@ -7365,6 +7365,62 @@ var RecordingConfigSchema = object({
|
|
|
7365
7365
|
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
7366
7366
|
});
|
|
7367
7367
|
/**
|
|
7368
|
+
* Ops-log — the durable, append-only operations audit shared by the
|
|
7369
|
+
* recordings and events management surfaces.
|
|
7370
|
+
*
|
|
7371
|
+
* ONE row shape is reused for both domains so a single "Activity" view can
|
|
7372
|
+
* merge the recorder's DurableState ring (recordings ops-log) and the
|
|
7373
|
+
* pipeline-analytics SQLite collection (events ops-log). Each row records a
|
|
7374
|
+
* management operation, WHY it ran (reason), and its measurable effect
|
|
7375
|
+
* (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
|
|
7376
|
+
* never fail the operation it records.
|
|
7377
|
+
*/
|
|
7378
|
+
/** Which management domain the operation belongs to. */
|
|
7379
|
+
var OpsLogDomainSchema = _enum(["recording", "events"]);
|
|
7380
|
+
/** The kind of management operation performed. */
|
|
7381
|
+
var OpsLogOpSchema = _enum([
|
|
7382
|
+
"prune",
|
|
7383
|
+
"manual-delete",
|
|
7384
|
+
"rescan",
|
|
7385
|
+
"retention-run"
|
|
7386
|
+
]);
|
|
7387
|
+
/** Why the operation ran. */
|
|
7388
|
+
var OpsLogReasonSchema = _enum([
|
|
7389
|
+
"retention",
|
|
7390
|
+
"quota",
|
|
7391
|
+
"manual",
|
|
7392
|
+
"operator"
|
|
7393
|
+
]);
|
|
7394
|
+
/** One audit row, shared verbatim by both domains. */
|
|
7395
|
+
var OpsLogEntrySchema = object({
|
|
7396
|
+
/** Unique row id. */
|
|
7397
|
+
id: string(),
|
|
7398
|
+
/** Epoch ms the operation completed. */
|
|
7399
|
+
at: number(),
|
|
7400
|
+
domain: OpsLogDomainSchema,
|
|
7401
|
+
op: OpsLogOpSchema,
|
|
7402
|
+
reason: OpsLogReasonSchema,
|
|
7403
|
+
/** The camera the op targeted; null for a cluster/global op. */
|
|
7404
|
+
deviceId: number().nullable(),
|
|
7405
|
+
/** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
|
|
7406
|
+
nodeId: string(),
|
|
7407
|
+
/** Buckets / rows deleted (op-specific unit). */
|
|
7408
|
+
itemsAffected: number(),
|
|
7409
|
+
/** Bytes reclaimed by the op (0 when not measurable). */
|
|
7410
|
+
bytesReclaimed: number(),
|
|
7411
|
+
/** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
|
|
7412
|
+
detail: string().nullable(),
|
|
7413
|
+
/** Who/what triggered the op. */
|
|
7414
|
+
actor: string()
|
|
7415
|
+
});
|
|
7416
|
+
/** Shared query input for the per-domain `listOpsLog` cap methods. */
|
|
7417
|
+
var OpsLogQueryInputSchema = object({
|
|
7418
|
+
/** Restrict to a single camera; omit for every row. */
|
|
7419
|
+
deviceId: number().optional(),
|
|
7420
|
+
/** Max rows returned, newest-first. */
|
|
7421
|
+
limit: number().int().min(1).max(1e3).optional()
|
|
7422
|
+
});
|
|
7423
|
+
/**
|
|
7368
7424
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
7369
7425
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
7370
7426
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -7608,6 +7664,160 @@ var EncodeProfileSchema = object({
|
|
|
7608
7664
|
*/
|
|
7609
7665
|
outputArgs: array(string()).optional()
|
|
7610
7666
|
});
|
|
7667
|
+
var COCO_TO_MACRO = {
|
|
7668
|
+
mapping: {
|
|
7669
|
+
person: "person",
|
|
7670
|
+
bicycle: "vehicle",
|
|
7671
|
+
car: "vehicle",
|
|
7672
|
+
motorcycle: "vehicle",
|
|
7673
|
+
airplane: "vehicle",
|
|
7674
|
+
bus: "vehicle",
|
|
7675
|
+
train: "vehicle",
|
|
7676
|
+
truck: "vehicle",
|
|
7677
|
+
boat: "vehicle",
|
|
7678
|
+
bird: "animal",
|
|
7679
|
+
cat: "animal",
|
|
7680
|
+
dog: "animal",
|
|
7681
|
+
horse: "animal",
|
|
7682
|
+
sheep: "animal",
|
|
7683
|
+
cow: "animal",
|
|
7684
|
+
elephant: "animal",
|
|
7685
|
+
bear: "animal",
|
|
7686
|
+
zebra: "animal",
|
|
7687
|
+
giraffe: "animal",
|
|
7688
|
+
suitcase: "package",
|
|
7689
|
+
backpack: "package",
|
|
7690
|
+
handbag: "package"
|
|
7691
|
+
},
|
|
7692
|
+
preserveOriginal: false
|
|
7693
|
+
};
|
|
7694
|
+
var AUDIO_MACRO_LABELS = [
|
|
7695
|
+
{
|
|
7696
|
+
id: "speech",
|
|
7697
|
+
name: "Speech",
|
|
7698
|
+
icon: "🗣️"
|
|
7699
|
+
},
|
|
7700
|
+
{
|
|
7701
|
+
id: "scream",
|
|
7702
|
+
name: "Scream / Shout",
|
|
7703
|
+
icon: "😱"
|
|
7704
|
+
},
|
|
7705
|
+
{
|
|
7706
|
+
id: "crying",
|
|
7707
|
+
name: "Crying / Baby",
|
|
7708
|
+
icon: "😢"
|
|
7709
|
+
},
|
|
7710
|
+
{
|
|
7711
|
+
id: "laughter",
|
|
7712
|
+
name: "Laughter",
|
|
7713
|
+
icon: "😂"
|
|
7714
|
+
},
|
|
7715
|
+
{
|
|
7716
|
+
id: "music",
|
|
7717
|
+
name: "Music",
|
|
7718
|
+
icon: "🎵"
|
|
7719
|
+
},
|
|
7720
|
+
{
|
|
7721
|
+
id: "dog",
|
|
7722
|
+
name: "Dog",
|
|
7723
|
+
icon: "🐕"
|
|
7724
|
+
},
|
|
7725
|
+
{
|
|
7726
|
+
id: "cat",
|
|
7727
|
+
name: "Cat",
|
|
7728
|
+
icon: "🐈"
|
|
7729
|
+
},
|
|
7730
|
+
{
|
|
7731
|
+
id: "bird",
|
|
7732
|
+
name: "Bird",
|
|
7733
|
+
icon: "🐦"
|
|
7734
|
+
},
|
|
7735
|
+
{
|
|
7736
|
+
id: "animal",
|
|
7737
|
+
name: "Animal (other)",
|
|
7738
|
+
icon: "🐾"
|
|
7739
|
+
},
|
|
7740
|
+
{
|
|
7741
|
+
id: "alarm",
|
|
7742
|
+
name: "Alarm / Siren",
|
|
7743
|
+
icon: "🚨"
|
|
7744
|
+
},
|
|
7745
|
+
{
|
|
7746
|
+
id: "doorbell",
|
|
7747
|
+
name: "Doorbell / Knock",
|
|
7748
|
+
icon: "🔔"
|
|
7749
|
+
},
|
|
7750
|
+
{
|
|
7751
|
+
id: "glass_breaking",
|
|
7752
|
+
name: "Glass Breaking",
|
|
7753
|
+
icon: "💥"
|
|
7754
|
+
},
|
|
7755
|
+
{
|
|
7756
|
+
id: "gunshot",
|
|
7757
|
+
name: "Gunshot / Explosion",
|
|
7758
|
+
icon: "💣"
|
|
7759
|
+
},
|
|
7760
|
+
{
|
|
7761
|
+
id: "vehicle",
|
|
7762
|
+
name: "Vehicle",
|
|
7763
|
+
icon: "🚗"
|
|
7764
|
+
},
|
|
7765
|
+
{
|
|
7766
|
+
id: "siren",
|
|
7767
|
+
name: "Emergency Siren",
|
|
7768
|
+
icon: "🚑"
|
|
7769
|
+
},
|
|
7770
|
+
{
|
|
7771
|
+
id: "fire",
|
|
7772
|
+
name: "Fire / Smoke",
|
|
7773
|
+
icon: "🔥"
|
|
7774
|
+
},
|
|
7775
|
+
{
|
|
7776
|
+
id: "water",
|
|
7777
|
+
name: "Water",
|
|
7778
|
+
icon: "💧"
|
|
7779
|
+
},
|
|
7780
|
+
{
|
|
7781
|
+
id: "wind",
|
|
7782
|
+
name: "Wind / Weather",
|
|
7783
|
+
icon: "🌬️"
|
|
7784
|
+
},
|
|
7785
|
+
{
|
|
7786
|
+
id: "door",
|
|
7787
|
+
name: "Door",
|
|
7788
|
+
icon: "🚪"
|
|
7789
|
+
},
|
|
7790
|
+
{
|
|
7791
|
+
id: "footsteps",
|
|
7792
|
+
name: "Footsteps",
|
|
7793
|
+
icon: "👣"
|
|
7794
|
+
},
|
|
7795
|
+
{
|
|
7796
|
+
id: "crowd",
|
|
7797
|
+
name: "Crowd / Chatter",
|
|
7798
|
+
icon: "👥"
|
|
7799
|
+
},
|
|
7800
|
+
{
|
|
7801
|
+
id: "telephone",
|
|
7802
|
+
name: "Telephone",
|
|
7803
|
+
icon: "📞"
|
|
7804
|
+
},
|
|
7805
|
+
{
|
|
7806
|
+
id: "engine",
|
|
7807
|
+
name: "Engine / Motor",
|
|
7808
|
+
icon: "⚙️"
|
|
7809
|
+
},
|
|
7810
|
+
{
|
|
7811
|
+
id: "tools",
|
|
7812
|
+
name: "Tools / Construction",
|
|
7813
|
+
icon: "🔨"
|
|
7814
|
+
},
|
|
7815
|
+
{
|
|
7816
|
+
id: "silence",
|
|
7817
|
+
name: "Silence",
|
|
7818
|
+
icon: "🤫"
|
|
7819
|
+
}
|
|
7820
|
+
];
|
|
7611
7821
|
var YAMNET_TO_MACRO = {
|
|
7612
7822
|
mapping: {
|
|
7613
7823
|
Speech: "speech",
|
|
@@ -7874,6 +8084,125 @@ var _macroLookup = /* @__PURE__ */ new Map();
|
|
|
7874
8084
|
for (const [k, v] of Object.entries(YAMNET_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
|
|
7875
8085
|
for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
|
|
7876
8086
|
/**
|
|
8087
|
+
* Unified event-kind taxonomy — THE single source of truth for
|
|
8088
|
+
* `kind → { parentKind, category, level, color, iconId, labelKey, label,
|
|
8089
|
+
* icon }`.
|
|
8090
|
+
*
|
|
8091
|
+
* This dictionary folds together what used to be scattered across four
|
|
8092
|
+
* copies:
|
|
8093
|
+
* - `capabilities/sensor-event-kinds.ts` (sensor cap colors)
|
|
8094
|
+
* - `addon-post-analysis/.../services/event-kinds.ts`
|
|
8095
|
+
* (MOTION/PERSON/VEHICLE… _COLOR constants)
|
|
8096
|
+
* - `ui-library/composites/detection-colors.ts` (CLASS_COLORS)
|
|
8097
|
+
* - `addon-post-analysis/shared/frame/box-drawer.ts` (DEFAULT_COLOR)
|
|
8098
|
+
* - the COCO / audio class maps (macro ↔ sub relationships)
|
|
8099
|
+
*
|
|
8100
|
+
* The DATA (serializable — color/iconId/labelKey/parentKind) lives here in
|
|
8101
|
+
* `@camstack/types`. The UI-side mapping `iconId → lucide component` and
|
|
8102
|
+
* `labelKey → t()` lives in `@camstack/ui-library`. UIs never hardcode a
|
|
8103
|
+
* color or an icon: they read this dictionary (server descriptors carry the
|
|
8104
|
+
* fields inline; the client resolves color/icon/label from `iconId`/`kind`).
|
|
8105
|
+
*
|
|
8106
|
+
* Two levels only (v1 YAGNI): macro → sub. `person` is a leaf macro.
|
|
8107
|
+
*/
|
|
8108
|
+
var TAXONOMY_COLORS = {
|
|
8109
|
+
motion: "#f59e0b",
|
|
8110
|
+
audio: "#06b6d4",
|
|
8111
|
+
person: "#22c55e",
|
|
8112
|
+
vehicle: "#3b82f6",
|
|
8113
|
+
animal: "#f97316",
|
|
8114
|
+
package: "#a855f7",
|
|
8115
|
+
sensor: "#8b5cf6",
|
|
8116
|
+
control: "#10b981",
|
|
8117
|
+
genericDetection: "#64748b"
|
|
8118
|
+
};
|
|
8119
|
+
var DETECTION_SUB_COLORS = {
|
|
8120
|
+
car: "#f59e0b",
|
|
8121
|
+
truck: "#d97706",
|
|
8122
|
+
bus: "#b45309",
|
|
8123
|
+
motorcycle: "#eab308",
|
|
8124
|
+
bicycle: "#ca8a04",
|
|
8125
|
+
airplane: "#60a5fa",
|
|
8126
|
+
boat: "#2563eb",
|
|
8127
|
+
train: "#1d4ed8",
|
|
8128
|
+
bird: "#14b8a6",
|
|
8129
|
+
dog: "#84cc16",
|
|
8130
|
+
cat: "#f97316",
|
|
8131
|
+
horse: "#a16207",
|
|
8132
|
+
sheep: "#a3a3a3",
|
|
8133
|
+
cow: "#78716c",
|
|
8134
|
+
elephant: "#6b7280",
|
|
8135
|
+
bear: "#7c2d12",
|
|
8136
|
+
zebra: "#404040",
|
|
8137
|
+
giraffe: "#d4a373"
|
|
8138
|
+
};
|
|
8139
|
+
function titleCase(id) {
|
|
8140
|
+
return id.split(/[-_ ]/).filter((p) => p.length > 0).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join(" ");
|
|
8141
|
+
}
|
|
8142
|
+
var entries = /* @__PURE__ */ new Map();
|
|
8143
|
+
function macro(kind, category, color, iconId, label) {
|
|
8144
|
+
entries.set(kind, {
|
|
8145
|
+
kind,
|
|
8146
|
+
parentKind: null,
|
|
8147
|
+
level: "macro",
|
|
8148
|
+
category,
|
|
8149
|
+
color,
|
|
8150
|
+
iconId,
|
|
8151
|
+
labelKey: `eventKind.${kind}`,
|
|
8152
|
+
label
|
|
8153
|
+
});
|
|
8154
|
+
}
|
|
8155
|
+
function sub(kind, parentKind, category, color, iconId, label) {
|
|
8156
|
+
entries.set(kind, {
|
|
8157
|
+
kind,
|
|
8158
|
+
parentKind,
|
|
8159
|
+
level: "sub",
|
|
8160
|
+
category,
|
|
8161
|
+
color,
|
|
8162
|
+
iconId,
|
|
8163
|
+
labelKey: `eventKind.${kind}`,
|
|
8164
|
+
label
|
|
8165
|
+
});
|
|
8166
|
+
}
|
|
8167
|
+
macro("motion", "motion", TAXONOMY_COLORS.motion, "motion", "Motion");
|
|
8168
|
+
macro("audio", "audio", TAXONOMY_COLORS.audio, "audio", "Audio");
|
|
8169
|
+
macro("person", "detection", TAXONOMY_COLORS.person, "person", "Person");
|
|
8170
|
+
macro("vehicle", "detection", TAXONOMY_COLORS.vehicle, "vehicle", "Vehicle");
|
|
8171
|
+
macro("animal", "detection", TAXONOMY_COLORS.animal, "animal", "Animal");
|
|
8172
|
+
macro("package", "package", TAXONOMY_COLORS.package, "package", "Package");
|
|
8173
|
+
macro("sensor", "sensor", TAXONOMY_COLORS.sensor, "sensor", "Sensor");
|
|
8174
|
+
macro("control", "control", TAXONOMY_COLORS.control, "control", "Control");
|
|
8175
|
+
for (const [cocoClass, macroClass] of Object.entries(COCO_TO_MACRO.mapping)) {
|
|
8176
|
+
if (macroClass !== "vehicle" && macroClass !== "animal") continue;
|
|
8177
|
+
if (entries.has(cocoClass)) continue;
|
|
8178
|
+
sub(cocoClass, macroClass, "detection", DETECTION_SUB_COLORS[cocoClass] ?? TAXONOMY_COLORS.genericDetection, cocoClass, titleCase(cocoClass));
|
|
8179
|
+
}
|
|
8180
|
+
sub("package-delivered", "package", "package", TAXONOMY_COLORS.package, "package", "Package delivered");
|
|
8181
|
+
sub("package-picked-up", "package", "package", TAXONOMY_COLORS.package, "package", "Package picked up");
|
|
8182
|
+
sub("contact", "sensor", "sensor", "#f59e0b", "door", "Contact");
|
|
8183
|
+
sub("motion-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "pir", "Motion sensor");
|
|
8184
|
+
sub("smoke", "sensor", "sensor", "#ef4444", "smoke", "Smoke");
|
|
8185
|
+
sub("flood", "sensor", "sensor", "#3b82f6", "water", "Water leak");
|
|
8186
|
+
sub("gas", "sensor", "sensor", "#ef4444", "gas", "Gas");
|
|
8187
|
+
sub("carbon-monoxide", "sensor", "sensor", "#dc2626", "smoke", "Carbon monoxide");
|
|
8188
|
+
sub("vibration", "sensor", "sensor", "#eab308", "vibration", "Vibration");
|
|
8189
|
+
sub("tamper", "sensor", "sensor", "#f97316", "tamper", "Tamper");
|
|
8190
|
+
sub("presence", "sensor", "sensor", "#22c55e", "presence", "Presence");
|
|
8191
|
+
sub("enum-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "generic", "Sensor state");
|
|
8192
|
+
sub("device-event", "sensor", "sensor", "#10b981", "button", "Device event");
|
|
8193
|
+
sub("lock", "control", "control", "#0ea5e9", "lock", "Lock");
|
|
8194
|
+
sub("switch", "control", "control", TAXONOMY_COLORS.control, "switch", "Switch");
|
|
8195
|
+
sub("siren", "control", "control", "#dc2626", "siren", "Siren");
|
|
8196
|
+
sub("button", "control", "control", "#10b981", "button", "Button");
|
|
8197
|
+
sub("doorbell", "control", "control", "#a855f7", "doorbell", "Doorbell");
|
|
8198
|
+
for (const l of AUDIO_MACRO_LABELS) {
|
|
8199
|
+
const kind = `audio-${l.id}`;
|
|
8200
|
+
if (entries.has(kind)) continue;
|
|
8201
|
+
sub(kind, "audio", "audio", TAXONOMY_COLORS.audio, kind, l.name);
|
|
8202
|
+
}
|
|
8203
|
+
/** The complete taxonomy dictionary, keyed by kind. */
|
|
8204
|
+
var EVENT_TAXONOMY = Object.freeze(Object.fromEntries(entries));
|
|
8205
|
+
/**
|
|
7877
8206
|
* Error types for the safe expression engine. Two distinct classes so callers
|
|
7878
8207
|
* can tell a compile-time (grammar) failure from a runtime (evaluation)
|
|
7879
8208
|
* failure — both are non-fatal to the host: read paths degrade to "skip link".
|
|
@@ -15823,17 +16152,30 @@ var EventKindCategorySchema = _enum([
|
|
|
15823
16152
|
"audio",
|
|
15824
16153
|
"detection",
|
|
15825
16154
|
"sensor",
|
|
16155
|
+
"control",
|
|
15826
16156
|
"custom",
|
|
15827
16157
|
"package"
|
|
15828
16158
|
]);
|
|
16159
|
+
/** Taxonomy level — macro (timeline lane) vs sub (events-page leaf). */
|
|
16160
|
+
var EventKindLevelSchema = _enum(["macro", "sub"]);
|
|
15829
16161
|
var EventKindDescriptorSchema = object({
|
|
15830
|
-
/** Stable kind id (e.g. 'motion', '
|
|
16162
|
+
/** Stable kind id (e.g. 'motion', 'vehicle', 'car', 'lock'). */
|
|
15831
16163
|
kind: string(),
|
|
16164
|
+
/** i18n key resolved on the UI side; `label` is the English fallback. */
|
|
16165
|
+
labelKey: string(),
|
|
16166
|
+
/** English fallback label (kept for clients that don't translate). */
|
|
15832
16167
|
label: string(),
|
|
15833
16168
|
/** Hex color for timeline/legend rendering. */
|
|
15834
16169
|
color: string(),
|
|
16170
|
+
/** Dictionary id → lucide component on the UI side. */
|
|
16171
|
+
iconId: string(),
|
|
16172
|
+
/** Legacy closed-vocab glyph — fallback for `iconId`. */
|
|
15835
16173
|
icon: EventKindIconSchema,
|
|
15836
16174
|
category: EventKindCategorySchema,
|
|
16175
|
+
/** Macro parent for this kind ('car' → 'vehicle'); null for a macro. */
|
|
16176
|
+
parentKind: string().nullable(),
|
|
16177
|
+
/** Derived from `parentKind`, explicit for the client tree. */
|
|
16178
|
+
level: EventKindLevelSchema,
|
|
15837
16179
|
/** Which cap + device contributes this kind. For built-ins the camera
|
|
15838
16180
|
* itself; for sensor kinds the LINKED source device. */
|
|
15839
16181
|
source: object({
|
|
@@ -15906,11 +16248,21 @@ var TrackAudioLabelSchema = object({
|
|
|
15906
16248
|
firstAt: number(),
|
|
15907
16249
|
lastAt: number()
|
|
15908
16250
|
});
|
|
16251
|
+
/**
|
|
16252
|
+
* How a track was produced. `pipeline` (default / absent) = the spatial
|
|
16253
|
+
* detection+tracking pipeline. `sensor` = a SYNTHETIC track projected from a
|
|
16254
|
+
* linked sensor/control state change (no positions; carries a snapshot). The
|
|
16255
|
+
* spatial subsystems (tracker association, occupancy count, re-id/embedding,
|
|
16256
|
+
* resurrection) MUST skip `sensor` tracks — they have no bbox trajectory.
|
|
16257
|
+
*/
|
|
16258
|
+
var TrackSourceSchema = _enum(["pipeline", "sensor"]);
|
|
15909
16259
|
var TrackSchema = object({
|
|
15910
16260
|
trackId: string(),
|
|
15911
16261
|
deviceId: number(),
|
|
15912
16262
|
className: string(),
|
|
15913
16263
|
label: string().optional(),
|
|
16264
|
+
/** Track provenance. Absent ⇒ `pipeline` (legacy rows). */
|
|
16265
|
+
source: TrackSourceSchema.optional(),
|
|
15914
16266
|
firstSeen: number(),
|
|
15915
16267
|
lastSeen: number(),
|
|
15916
16268
|
/** Frame-rate position history (subject to maxPositionHistory cap). */
|
|
@@ -16165,6 +16517,26 @@ var TrackCascadeCountsSchema = object({
|
|
|
16165
16517
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
16166
16518
|
embeddings: number().int()
|
|
16167
16519
|
});
|
|
16520
|
+
/** Event-store footprint for one camera. */
|
|
16521
|
+
var EventStoreDeviceFootprintSchema = object({
|
|
16522
|
+
deviceId: number(),
|
|
16523
|
+
/** Persisted event rows (motion + object + audio) for the camera. */
|
|
16524
|
+
rows: number().int(),
|
|
16525
|
+
/** Event-owned media bytes on disk for the camera. */
|
|
16526
|
+
bytes: number().int()
|
|
16527
|
+
});
|
|
16528
|
+
/** Aggregate event-store footprint: global totals + per-camera breakdown. */
|
|
16529
|
+
var EventStoreFootprintSchema = object({
|
|
16530
|
+
totalRows: number().int(),
|
|
16531
|
+
totalBytes: number().int(),
|
|
16532
|
+
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
16533
|
+
});
|
|
16534
|
+
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
16535
|
+
var EventPruneCountsSchema = object({
|
|
16536
|
+
motion: number().int(),
|
|
16537
|
+
object: number().int(),
|
|
16538
|
+
audio: number().int()
|
|
16539
|
+
});
|
|
16168
16540
|
DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
|
|
16169
16541
|
deviceId: number(),
|
|
16170
16542
|
trackId: string()
|
|
@@ -16228,6 +16600,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
16228
16600
|
}), {
|
|
16229
16601
|
kind: "mutation",
|
|
16230
16602
|
auth: "admin"
|
|
16603
|
+
}), method(object({}), EventStoreFootprintSchema, {
|
|
16604
|
+
kind: "query",
|
|
16605
|
+
auth: "admin"
|
|
16606
|
+
}), method(object({
|
|
16607
|
+
olderThanMs: number(),
|
|
16608
|
+
reason: OpsLogReasonSchema.optional()
|
|
16609
|
+
}), EventPruneCountsSchema, {
|
|
16610
|
+
kind: "mutation",
|
|
16611
|
+
auth: "admin"
|
|
16612
|
+
}), method(object({ deviceId: number() }), EventPruneCountsSchema, {
|
|
16613
|
+
kind: "mutation",
|
|
16614
|
+
auth: "admin"
|
|
16615
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
16616
|
+
kind: "query",
|
|
16617
|
+
auth: "admin"
|
|
16231
16618
|
}), method(object({
|
|
16232
16619
|
eventId: string(),
|
|
16233
16620
|
kind: MediaFileKindEnum.optional()
|
|
@@ -16252,6 +16639,76 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
16252
16639
|
eventId: string(),
|
|
16253
16640
|
timestamp: number()
|
|
16254
16641
|
});
|
|
16642
|
+
/**
|
|
16643
|
+
* Cap → event-kind mapping for the SENSOR / CONTROL cap families — the table
|
|
16644
|
+
* `pipeline-analytics.listEventKinds` uses to turn a linked device's bound
|
|
16645
|
+
* caps into per-camera event-kind descriptors.
|
|
16646
|
+
*
|
|
16647
|
+
* The descriptor DATA (color / iconId / labelKey / parentKind / category)
|
|
16648
|
+
* is NOT duplicated here — every entry is derived from the single
|
|
16649
|
+
* `EVENT_TAXONOMY` dictionary (`catalogs/event-taxonomy.ts`). This file owns
|
|
16650
|
+
* ONLY the cap-name → taxonomy-kind mapping. Adding a new eventful sensor /
|
|
16651
|
+
* control cap means adding one line here (and a taxonomy entry); the anti-
|
|
16652
|
+
* drift guard `scripts/check-event-kind-coverage.ts` fails the build if an
|
|
16653
|
+
* eventful cap is missing.
|
|
16654
|
+
*/
|
|
16655
|
+
/** Map a taxonomy `iconId` onto the legacy closed `EventKindIcon` enum. */
|
|
16656
|
+
var LEGACY_ICON = {
|
|
16657
|
+
motion: "motion",
|
|
16658
|
+
audio: "audio",
|
|
16659
|
+
person: "person",
|
|
16660
|
+
vehicle: "vehicle",
|
|
16661
|
+
animal: "animal",
|
|
16662
|
+
package: "package",
|
|
16663
|
+
door: "door",
|
|
16664
|
+
pir: "pir",
|
|
16665
|
+
smoke: "smoke",
|
|
16666
|
+
water: "water",
|
|
16667
|
+
button: "button",
|
|
16668
|
+
generic: "generic",
|
|
16669
|
+
gas: "smoke",
|
|
16670
|
+
vibration: "generic",
|
|
16671
|
+
tamper: "generic",
|
|
16672
|
+
presence: "person",
|
|
16673
|
+
lock: "generic",
|
|
16674
|
+
siren: "generic",
|
|
16675
|
+
switch: "generic",
|
|
16676
|
+
doorbell: "button"
|
|
16677
|
+
};
|
|
16678
|
+
function legacyIcon(iconId) {
|
|
16679
|
+
return LEGACY_ICON[iconId] ?? "generic";
|
|
16680
|
+
}
|
|
16681
|
+
/**
|
|
16682
|
+
* Cap name → taxonomy kind id. Covers EVERY eventful sensor / control cap.
|
|
16683
|
+
* The anti-drift guard cross-checks this against the eventful caps declared
|
|
16684
|
+
* in `packages/types/src/capabilities/*.cap.ts`.
|
|
16685
|
+
*/
|
|
16686
|
+
var CAP_TO_KIND = {
|
|
16687
|
+
contact: "contact",
|
|
16688
|
+
motion: "motion-sensor",
|
|
16689
|
+
smoke: "smoke",
|
|
16690
|
+
flood: "flood",
|
|
16691
|
+
gas: "gas",
|
|
16692
|
+
"carbon-monoxide": "carbon-monoxide",
|
|
16693
|
+
vibration: "vibration",
|
|
16694
|
+
tamper: "tamper",
|
|
16695
|
+
presence: "presence",
|
|
16696
|
+
"enum-sensor": "enum-sensor",
|
|
16697
|
+
"event-emitter": "device-event",
|
|
16698
|
+
"lock-control": "lock",
|
|
16699
|
+
switch: "switch",
|
|
16700
|
+
button: "button",
|
|
16701
|
+
doorbell: "doorbell"
|
|
16702
|
+
};
|
|
16703
|
+
function buildDescriptor(capName, kind) {
|
|
16704
|
+
const t = EVENT_TAXONOMY[kind];
|
|
16705
|
+
if (t === void 0) throw new Error(`EVENT_KIND_BY_CAP: cap '${capName}' maps to unknown taxonomy kind '${kind}'`);
|
|
16706
|
+
return {
|
|
16707
|
+
...t,
|
|
16708
|
+
icon: legacyIcon(t.iconId)
|
|
16709
|
+
};
|
|
16710
|
+
}
|
|
16711
|
+
Object.freeze(Object.fromEntries(Object.entries(CAP_TO_KIND).map(([capName, kind]) => [capName, buildDescriptor(capName, kind)])));
|
|
16255
16712
|
var CameraPipelineConfigSchema = object({
|
|
16256
16713
|
engine: PipelineEngineChoiceSchema.optional(),
|
|
16257
16714
|
steps: array(PipelineStepInputSchema).readonly(),
|
|
@@ -19474,13 +19931,29 @@ method(object({
|
|
|
19474
19931
|
}), method(object({ deviceId: number() }), RecordingStatusSchema, {
|
|
19475
19932
|
kind: "mutation",
|
|
19476
19933
|
auth: "admin"
|
|
19477
|
-
}), method(object({
|
|
19934
|
+
}), method(object({
|
|
19935
|
+
deviceId: number(),
|
|
19936
|
+
reason: OpsLogReasonSchema.optional()
|
|
19937
|
+
}), object({
|
|
19478
19938
|
floorMs: number().nullable(),
|
|
19479
19939
|
deletedBuckets: number().int(),
|
|
19480
19940
|
reclaimedBytes: number().int()
|
|
19481
19941
|
}), {
|
|
19482
19942
|
kind: "mutation",
|
|
19483
19943
|
auth: "admin"
|
|
19944
|
+
}), method(object({
|
|
19945
|
+
deviceId: number(),
|
|
19946
|
+
fromMs: number().optional(),
|
|
19947
|
+
toMs: number().optional()
|
|
19948
|
+
}), object({
|
|
19949
|
+
deletedBuckets: number().int(),
|
|
19950
|
+
reclaimedBytes: number().int()
|
|
19951
|
+
}), {
|
|
19952
|
+
kind: "mutation",
|
|
19953
|
+
auth: "admin"
|
|
19954
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
19955
|
+
kind: "query",
|
|
19956
|
+
auth: "admin"
|
|
19484
19957
|
});
|
|
19485
19958
|
/**
|
|
19486
19959
|
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
@@ -22602,6 +23075,12 @@ Object.freeze({
|
|
|
22602
23075
|
addonId: null,
|
|
22603
23076
|
access: "delete"
|
|
22604
23077
|
},
|
|
23078
|
+
"pipelineAnalytics.deleteDeviceEvents": {
|
|
23079
|
+
capName: "pipeline-analytics",
|
|
23080
|
+
capScope: "device",
|
|
23081
|
+
addonId: null,
|
|
23082
|
+
access: "delete"
|
|
23083
|
+
},
|
|
22605
23084
|
"pipelineAnalytics.deleteTracks": {
|
|
22606
23085
|
capName: "pipeline-analytics",
|
|
22607
23086
|
capScope: "device",
|
|
@@ -22632,6 +23111,12 @@ Object.freeze({
|
|
|
22632
23111
|
addonId: null,
|
|
22633
23112
|
access: "view"
|
|
22634
23113
|
},
|
|
23114
|
+
"pipelineAnalytics.getEventStoreFootprint": {
|
|
23115
|
+
capName: "pipeline-analytics",
|
|
23116
|
+
capScope: "device",
|
|
23117
|
+
addonId: null,
|
|
23118
|
+
access: "view"
|
|
23119
|
+
},
|
|
22635
23120
|
"pipelineAnalytics.getKeyEvents": {
|
|
22636
23121
|
capName: "pipeline-analytics",
|
|
22637
23122
|
capScope: "device",
|
|
@@ -22674,6 +23159,12 @@ Object.freeze({
|
|
|
22674
23159
|
addonId: null,
|
|
22675
23160
|
access: "view"
|
|
22676
23161
|
},
|
|
23162
|
+
"pipelineAnalytics.listOpsLog": {
|
|
23163
|
+
capName: "pipeline-analytics",
|
|
23164
|
+
capScope: "device",
|
|
23165
|
+
addonId: null,
|
|
23166
|
+
access: "view"
|
|
23167
|
+
},
|
|
22677
23168
|
"pipelineAnalytics.listRecentTracks": {
|
|
22678
23169
|
capName: "pipeline-analytics",
|
|
22679
23170
|
capScope: "device",
|
|
@@ -22686,6 +23177,12 @@ Object.freeze({
|
|
|
22686
23177
|
addonId: null,
|
|
22687
23178
|
access: "view"
|
|
22688
23179
|
},
|
|
23180
|
+
"pipelineAnalytics.pruneEvents": {
|
|
23181
|
+
capName: "pipeline-analytics",
|
|
23182
|
+
capScope: "device",
|
|
23183
|
+
addonId: null,
|
|
23184
|
+
access: "create"
|
|
23185
|
+
},
|
|
22689
23186
|
"pipelineAnalytics.pruneEventsBefore": {
|
|
22690
23187
|
capName: "pipeline-analytics",
|
|
22691
23188
|
capScope: "device",
|
|
@@ -23448,6 +23945,12 @@ Object.freeze({
|
|
|
23448
23945
|
addonId: null,
|
|
23449
23946
|
access: "create"
|
|
23450
23947
|
},
|
|
23948
|
+
"recording.deleteFootprint": {
|
|
23949
|
+
capName: "recording",
|
|
23950
|
+
capScope: "system",
|
|
23951
|
+
addonId: null,
|
|
23952
|
+
access: "delete"
|
|
23953
|
+
},
|
|
23451
23954
|
"recording.getAvailability": {
|
|
23452
23955
|
capName: "recording",
|
|
23453
23956
|
capScope: "system",
|
|
@@ -23478,6 +23981,12 @@ Object.freeze({
|
|
|
23478
23981
|
addonId: null,
|
|
23479
23982
|
access: "view"
|
|
23480
23983
|
},
|
|
23984
|
+
"recording.listOpsLog": {
|
|
23985
|
+
capName: "recording",
|
|
23986
|
+
capScope: "system",
|
|
23987
|
+
addonId: null,
|
|
23988
|
+
access: "view"
|
|
23989
|
+
},
|
|
23481
23990
|
"recording.locateSegment": {
|
|
23482
23991
|
capName: "recording",
|
|
23483
23992
|
capScope: "system",
|
package/dist/smtp.addon.mjs
CHANGED
|
@@ -7363,6 +7363,62 @@ var RecordingConfigSchema = object({
|
|
|
7363
7363
|
scrubThumbnails: ScrubThumbnailPresetSchema.optional()
|
|
7364
7364
|
});
|
|
7365
7365
|
/**
|
|
7366
|
+
* Ops-log — the durable, append-only operations audit shared by the
|
|
7367
|
+
* recordings and events management surfaces.
|
|
7368
|
+
*
|
|
7369
|
+
* ONE row shape is reused for both domains so a single "Activity" view can
|
|
7370
|
+
* merge the recorder's DurableState ring (recordings ops-log) and the
|
|
7371
|
+
* pipeline-analytics SQLite collection (events ops-log). Each row records a
|
|
7372
|
+
* management operation, WHY it ran (reason), and its measurable effect
|
|
7373
|
+
* (itemsAffected + bytesReclaimed). Writes are best-effort — a failed log must
|
|
7374
|
+
* never fail the operation it records.
|
|
7375
|
+
*/
|
|
7376
|
+
/** Which management domain the operation belongs to. */
|
|
7377
|
+
var OpsLogDomainSchema = _enum(["recording", "events"]);
|
|
7378
|
+
/** The kind of management operation performed. */
|
|
7379
|
+
var OpsLogOpSchema = _enum([
|
|
7380
|
+
"prune",
|
|
7381
|
+
"manual-delete",
|
|
7382
|
+
"rescan",
|
|
7383
|
+
"retention-run"
|
|
7384
|
+
]);
|
|
7385
|
+
/** Why the operation ran. */
|
|
7386
|
+
var OpsLogReasonSchema = _enum([
|
|
7387
|
+
"retention",
|
|
7388
|
+
"quota",
|
|
7389
|
+
"manual",
|
|
7390
|
+
"operator"
|
|
7391
|
+
]);
|
|
7392
|
+
/** One audit row, shared verbatim by both domains. */
|
|
7393
|
+
var OpsLogEntrySchema = object({
|
|
7394
|
+
/** Unique row id. */
|
|
7395
|
+
id: string(),
|
|
7396
|
+
/** Epoch ms the operation completed. */
|
|
7397
|
+
at: number(),
|
|
7398
|
+
domain: OpsLogDomainSchema,
|
|
7399
|
+
op: OpsLogOpSchema,
|
|
7400
|
+
reason: OpsLogReasonSchema,
|
|
7401
|
+
/** The camera the op targeted; null for a cluster/global op. */
|
|
7402
|
+
deviceId: number().nullable(),
|
|
7403
|
+
/** Node that performed the op (the log carries nodeId — no cross-node aggregation). */
|
|
7404
|
+
nodeId: string(),
|
|
7405
|
+
/** Buckets / rows deleted (op-specific unit). */
|
|
7406
|
+
itemsAffected: number(),
|
|
7407
|
+
/** Bytes reclaimed by the op (0 when not measurable). */
|
|
7408
|
+
bytesReclaimed: number(),
|
|
7409
|
+
/** Free-text detail (e.g. "floor moved to <ts>"); null when none. */
|
|
7410
|
+
detail: string().nullable(),
|
|
7411
|
+
/** Who/what triggered the op. */
|
|
7412
|
+
actor: string()
|
|
7413
|
+
});
|
|
7414
|
+
/** Shared query input for the per-domain `listOpsLog` cap methods. */
|
|
7415
|
+
var OpsLogQueryInputSchema = object({
|
|
7416
|
+
/** Restrict to a single camera; omit for every row. */
|
|
7417
|
+
deviceId: number().optional(),
|
|
7418
|
+
/** Max rows returned, newest-first. */
|
|
7419
|
+
limit: number().int().min(1).max(1e3).optional()
|
|
7420
|
+
});
|
|
7421
|
+
/**
|
|
7366
7422
|
* `StorageLocationType` — an addon-declared id that identifies the *kind* of
|
|
7367
7423
|
* storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
|
|
7368
7424
|
* so the persisted record schema and the consumer-facing cap can both consume it
|
|
@@ -7606,6 +7662,160 @@ var EncodeProfileSchema = object({
|
|
|
7606
7662
|
*/
|
|
7607
7663
|
outputArgs: array(string()).optional()
|
|
7608
7664
|
});
|
|
7665
|
+
var COCO_TO_MACRO = {
|
|
7666
|
+
mapping: {
|
|
7667
|
+
person: "person",
|
|
7668
|
+
bicycle: "vehicle",
|
|
7669
|
+
car: "vehicle",
|
|
7670
|
+
motorcycle: "vehicle",
|
|
7671
|
+
airplane: "vehicle",
|
|
7672
|
+
bus: "vehicle",
|
|
7673
|
+
train: "vehicle",
|
|
7674
|
+
truck: "vehicle",
|
|
7675
|
+
boat: "vehicle",
|
|
7676
|
+
bird: "animal",
|
|
7677
|
+
cat: "animal",
|
|
7678
|
+
dog: "animal",
|
|
7679
|
+
horse: "animal",
|
|
7680
|
+
sheep: "animal",
|
|
7681
|
+
cow: "animal",
|
|
7682
|
+
elephant: "animal",
|
|
7683
|
+
bear: "animal",
|
|
7684
|
+
zebra: "animal",
|
|
7685
|
+
giraffe: "animal",
|
|
7686
|
+
suitcase: "package",
|
|
7687
|
+
backpack: "package",
|
|
7688
|
+
handbag: "package"
|
|
7689
|
+
},
|
|
7690
|
+
preserveOriginal: false
|
|
7691
|
+
};
|
|
7692
|
+
var AUDIO_MACRO_LABELS = [
|
|
7693
|
+
{
|
|
7694
|
+
id: "speech",
|
|
7695
|
+
name: "Speech",
|
|
7696
|
+
icon: "🗣️"
|
|
7697
|
+
},
|
|
7698
|
+
{
|
|
7699
|
+
id: "scream",
|
|
7700
|
+
name: "Scream / Shout",
|
|
7701
|
+
icon: "😱"
|
|
7702
|
+
},
|
|
7703
|
+
{
|
|
7704
|
+
id: "crying",
|
|
7705
|
+
name: "Crying / Baby",
|
|
7706
|
+
icon: "😢"
|
|
7707
|
+
},
|
|
7708
|
+
{
|
|
7709
|
+
id: "laughter",
|
|
7710
|
+
name: "Laughter",
|
|
7711
|
+
icon: "😂"
|
|
7712
|
+
},
|
|
7713
|
+
{
|
|
7714
|
+
id: "music",
|
|
7715
|
+
name: "Music",
|
|
7716
|
+
icon: "🎵"
|
|
7717
|
+
},
|
|
7718
|
+
{
|
|
7719
|
+
id: "dog",
|
|
7720
|
+
name: "Dog",
|
|
7721
|
+
icon: "🐕"
|
|
7722
|
+
},
|
|
7723
|
+
{
|
|
7724
|
+
id: "cat",
|
|
7725
|
+
name: "Cat",
|
|
7726
|
+
icon: "🐈"
|
|
7727
|
+
},
|
|
7728
|
+
{
|
|
7729
|
+
id: "bird",
|
|
7730
|
+
name: "Bird",
|
|
7731
|
+
icon: "🐦"
|
|
7732
|
+
},
|
|
7733
|
+
{
|
|
7734
|
+
id: "animal",
|
|
7735
|
+
name: "Animal (other)",
|
|
7736
|
+
icon: "🐾"
|
|
7737
|
+
},
|
|
7738
|
+
{
|
|
7739
|
+
id: "alarm",
|
|
7740
|
+
name: "Alarm / Siren",
|
|
7741
|
+
icon: "🚨"
|
|
7742
|
+
},
|
|
7743
|
+
{
|
|
7744
|
+
id: "doorbell",
|
|
7745
|
+
name: "Doorbell / Knock",
|
|
7746
|
+
icon: "🔔"
|
|
7747
|
+
},
|
|
7748
|
+
{
|
|
7749
|
+
id: "glass_breaking",
|
|
7750
|
+
name: "Glass Breaking",
|
|
7751
|
+
icon: "💥"
|
|
7752
|
+
},
|
|
7753
|
+
{
|
|
7754
|
+
id: "gunshot",
|
|
7755
|
+
name: "Gunshot / Explosion",
|
|
7756
|
+
icon: "💣"
|
|
7757
|
+
},
|
|
7758
|
+
{
|
|
7759
|
+
id: "vehicle",
|
|
7760
|
+
name: "Vehicle",
|
|
7761
|
+
icon: "🚗"
|
|
7762
|
+
},
|
|
7763
|
+
{
|
|
7764
|
+
id: "siren",
|
|
7765
|
+
name: "Emergency Siren",
|
|
7766
|
+
icon: "🚑"
|
|
7767
|
+
},
|
|
7768
|
+
{
|
|
7769
|
+
id: "fire",
|
|
7770
|
+
name: "Fire / Smoke",
|
|
7771
|
+
icon: "🔥"
|
|
7772
|
+
},
|
|
7773
|
+
{
|
|
7774
|
+
id: "water",
|
|
7775
|
+
name: "Water",
|
|
7776
|
+
icon: "💧"
|
|
7777
|
+
},
|
|
7778
|
+
{
|
|
7779
|
+
id: "wind",
|
|
7780
|
+
name: "Wind / Weather",
|
|
7781
|
+
icon: "🌬️"
|
|
7782
|
+
},
|
|
7783
|
+
{
|
|
7784
|
+
id: "door",
|
|
7785
|
+
name: "Door",
|
|
7786
|
+
icon: "🚪"
|
|
7787
|
+
},
|
|
7788
|
+
{
|
|
7789
|
+
id: "footsteps",
|
|
7790
|
+
name: "Footsteps",
|
|
7791
|
+
icon: "👣"
|
|
7792
|
+
},
|
|
7793
|
+
{
|
|
7794
|
+
id: "crowd",
|
|
7795
|
+
name: "Crowd / Chatter",
|
|
7796
|
+
icon: "👥"
|
|
7797
|
+
},
|
|
7798
|
+
{
|
|
7799
|
+
id: "telephone",
|
|
7800
|
+
name: "Telephone",
|
|
7801
|
+
icon: "📞"
|
|
7802
|
+
},
|
|
7803
|
+
{
|
|
7804
|
+
id: "engine",
|
|
7805
|
+
name: "Engine / Motor",
|
|
7806
|
+
icon: "⚙️"
|
|
7807
|
+
},
|
|
7808
|
+
{
|
|
7809
|
+
id: "tools",
|
|
7810
|
+
name: "Tools / Construction",
|
|
7811
|
+
icon: "🔨"
|
|
7812
|
+
},
|
|
7813
|
+
{
|
|
7814
|
+
id: "silence",
|
|
7815
|
+
name: "Silence",
|
|
7816
|
+
icon: "🤫"
|
|
7817
|
+
}
|
|
7818
|
+
];
|
|
7609
7819
|
var YAMNET_TO_MACRO = {
|
|
7610
7820
|
mapping: {
|
|
7611
7821
|
Speech: "speech",
|
|
@@ -7872,6 +8082,125 @@ var _macroLookup = /* @__PURE__ */ new Map();
|
|
|
7872
8082
|
for (const [k, v] of Object.entries(YAMNET_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
|
|
7873
8083
|
for (const [k, v] of Object.entries(APPLE_SA_TO_MACRO.mapping)) _macroLookup.set(k.toLowerCase(), v);
|
|
7874
8084
|
/**
|
|
8085
|
+
* Unified event-kind taxonomy — THE single source of truth for
|
|
8086
|
+
* `kind → { parentKind, category, level, color, iconId, labelKey, label,
|
|
8087
|
+
* icon }`.
|
|
8088
|
+
*
|
|
8089
|
+
* This dictionary folds together what used to be scattered across four
|
|
8090
|
+
* copies:
|
|
8091
|
+
* - `capabilities/sensor-event-kinds.ts` (sensor cap colors)
|
|
8092
|
+
* - `addon-post-analysis/.../services/event-kinds.ts`
|
|
8093
|
+
* (MOTION/PERSON/VEHICLE… _COLOR constants)
|
|
8094
|
+
* - `ui-library/composites/detection-colors.ts` (CLASS_COLORS)
|
|
8095
|
+
* - `addon-post-analysis/shared/frame/box-drawer.ts` (DEFAULT_COLOR)
|
|
8096
|
+
* - the COCO / audio class maps (macro ↔ sub relationships)
|
|
8097
|
+
*
|
|
8098
|
+
* The DATA (serializable — color/iconId/labelKey/parentKind) lives here in
|
|
8099
|
+
* `@camstack/types`. The UI-side mapping `iconId → lucide component` and
|
|
8100
|
+
* `labelKey → t()` lives in `@camstack/ui-library`. UIs never hardcode a
|
|
8101
|
+
* color or an icon: they read this dictionary (server descriptors carry the
|
|
8102
|
+
* fields inline; the client resolves color/icon/label from `iconId`/`kind`).
|
|
8103
|
+
*
|
|
8104
|
+
* Two levels only (v1 YAGNI): macro → sub. `person` is a leaf macro.
|
|
8105
|
+
*/
|
|
8106
|
+
var TAXONOMY_COLORS = {
|
|
8107
|
+
motion: "#f59e0b",
|
|
8108
|
+
audio: "#06b6d4",
|
|
8109
|
+
person: "#22c55e",
|
|
8110
|
+
vehicle: "#3b82f6",
|
|
8111
|
+
animal: "#f97316",
|
|
8112
|
+
package: "#a855f7",
|
|
8113
|
+
sensor: "#8b5cf6",
|
|
8114
|
+
control: "#10b981",
|
|
8115
|
+
genericDetection: "#64748b"
|
|
8116
|
+
};
|
|
8117
|
+
var DETECTION_SUB_COLORS = {
|
|
8118
|
+
car: "#f59e0b",
|
|
8119
|
+
truck: "#d97706",
|
|
8120
|
+
bus: "#b45309",
|
|
8121
|
+
motorcycle: "#eab308",
|
|
8122
|
+
bicycle: "#ca8a04",
|
|
8123
|
+
airplane: "#60a5fa",
|
|
8124
|
+
boat: "#2563eb",
|
|
8125
|
+
train: "#1d4ed8",
|
|
8126
|
+
bird: "#14b8a6",
|
|
8127
|
+
dog: "#84cc16",
|
|
8128
|
+
cat: "#f97316",
|
|
8129
|
+
horse: "#a16207",
|
|
8130
|
+
sheep: "#a3a3a3",
|
|
8131
|
+
cow: "#78716c",
|
|
8132
|
+
elephant: "#6b7280",
|
|
8133
|
+
bear: "#7c2d12",
|
|
8134
|
+
zebra: "#404040",
|
|
8135
|
+
giraffe: "#d4a373"
|
|
8136
|
+
};
|
|
8137
|
+
function titleCase(id) {
|
|
8138
|
+
return id.split(/[-_ ]/).filter((p) => p.length > 0).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join(" ");
|
|
8139
|
+
}
|
|
8140
|
+
var entries = /* @__PURE__ */ new Map();
|
|
8141
|
+
function macro(kind, category, color, iconId, label) {
|
|
8142
|
+
entries.set(kind, {
|
|
8143
|
+
kind,
|
|
8144
|
+
parentKind: null,
|
|
8145
|
+
level: "macro",
|
|
8146
|
+
category,
|
|
8147
|
+
color,
|
|
8148
|
+
iconId,
|
|
8149
|
+
labelKey: `eventKind.${kind}`,
|
|
8150
|
+
label
|
|
8151
|
+
});
|
|
8152
|
+
}
|
|
8153
|
+
function sub(kind, parentKind, category, color, iconId, label) {
|
|
8154
|
+
entries.set(kind, {
|
|
8155
|
+
kind,
|
|
8156
|
+
parentKind,
|
|
8157
|
+
level: "sub",
|
|
8158
|
+
category,
|
|
8159
|
+
color,
|
|
8160
|
+
iconId,
|
|
8161
|
+
labelKey: `eventKind.${kind}`,
|
|
8162
|
+
label
|
|
8163
|
+
});
|
|
8164
|
+
}
|
|
8165
|
+
macro("motion", "motion", TAXONOMY_COLORS.motion, "motion", "Motion");
|
|
8166
|
+
macro("audio", "audio", TAXONOMY_COLORS.audio, "audio", "Audio");
|
|
8167
|
+
macro("person", "detection", TAXONOMY_COLORS.person, "person", "Person");
|
|
8168
|
+
macro("vehicle", "detection", TAXONOMY_COLORS.vehicle, "vehicle", "Vehicle");
|
|
8169
|
+
macro("animal", "detection", TAXONOMY_COLORS.animal, "animal", "Animal");
|
|
8170
|
+
macro("package", "package", TAXONOMY_COLORS.package, "package", "Package");
|
|
8171
|
+
macro("sensor", "sensor", TAXONOMY_COLORS.sensor, "sensor", "Sensor");
|
|
8172
|
+
macro("control", "control", TAXONOMY_COLORS.control, "control", "Control");
|
|
8173
|
+
for (const [cocoClass, macroClass] of Object.entries(COCO_TO_MACRO.mapping)) {
|
|
8174
|
+
if (macroClass !== "vehicle" && macroClass !== "animal") continue;
|
|
8175
|
+
if (entries.has(cocoClass)) continue;
|
|
8176
|
+
sub(cocoClass, macroClass, "detection", DETECTION_SUB_COLORS[cocoClass] ?? TAXONOMY_COLORS.genericDetection, cocoClass, titleCase(cocoClass));
|
|
8177
|
+
}
|
|
8178
|
+
sub("package-delivered", "package", "package", TAXONOMY_COLORS.package, "package", "Package delivered");
|
|
8179
|
+
sub("package-picked-up", "package", "package", TAXONOMY_COLORS.package, "package", "Package picked up");
|
|
8180
|
+
sub("contact", "sensor", "sensor", "#f59e0b", "door", "Contact");
|
|
8181
|
+
sub("motion-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "pir", "Motion sensor");
|
|
8182
|
+
sub("smoke", "sensor", "sensor", "#ef4444", "smoke", "Smoke");
|
|
8183
|
+
sub("flood", "sensor", "sensor", "#3b82f6", "water", "Water leak");
|
|
8184
|
+
sub("gas", "sensor", "sensor", "#ef4444", "gas", "Gas");
|
|
8185
|
+
sub("carbon-monoxide", "sensor", "sensor", "#dc2626", "smoke", "Carbon monoxide");
|
|
8186
|
+
sub("vibration", "sensor", "sensor", "#eab308", "vibration", "Vibration");
|
|
8187
|
+
sub("tamper", "sensor", "sensor", "#f97316", "tamper", "Tamper");
|
|
8188
|
+
sub("presence", "sensor", "sensor", "#22c55e", "presence", "Presence");
|
|
8189
|
+
sub("enum-sensor", "sensor", "sensor", TAXONOMY_COLORS.sensor, "generic", "Sensor state");
|
|
8190
|
+
sub("device-event", "sensor", "sensor", "#10b981", "button", "Device event");
|
|
8191
|
+
sub("lock", "control", "control", "#0ea5e9", "lock", "Lock");
|
|
8192
|
+
sub("switch", "control", "control", TAXONOMY_COLORS.control, "switch", "Switch");
|
|
8193
|
+
sub("siren", "control", "control", "#dc2626", "siren", "Siren");
|
|
8194
|
+
sub("button", "control", "control", "#10b981", "button", "Button");
|
|
8195
|
+
sub("doorbell", "control", "control", "#a855f7", "doorbell", "Doorbell");
|
|
8196
|
+
for (const l of AUDIO_MACRO_LABELS) {
|
|
8197
|
+
const kind = `audio-${l.id}`;
|
|
8198
|
+
if (entries.has(kind)) continue;
|
|
8199
|
+
sub(kind, "audio", "audio", TAXONOMY_COLORS.audio, kind, l.name);
|
|
8200
|
+
}
|
|
8201
|
+
/** The complete taxonomy dictionary, keyed by kind. */
|
|
8202
|
+
var EVENT_TAXONOMY = Object.freeze(Object.fromEntries(entries));
|
|
8203
|
+
/**
|
|
7875
8204
|
* Error types for the safe expression engine. Two distinct classes so callers
|
|
7876
8205
|
* can tell a compile-time (grammar) failure from a runtime (evaluation)
|
|
7877
8206
|
* failure — both are non-fatal to the host: read paths degrade to "skip link".
|
|
@@ -15821,17 +16150,30 @@ var EventKindCategorySchema = _enum([
|
|
|
15821
16150
|
"audio",
|
|
15822
16151
|
"detection",
|
|
15823
16152
|
"sensor",
|
|
16153
|
+
"control",
|
|
15824
16154
|
"custom",
|
|
15825
16155
|
"package"
|
|
15826
16156
|
]);
|
|
16157
|
+
/** Taxonomy level — macro (timeline lane) vs sub (events-page leaf). */
|
|
16158
|
+
var EventKindLevelSchema = _enum(["macro", "sub"]);
|
|
15827
16159
|
var EventKindDescriptorSchema = object({
|
|
15828
|
-
/** Stable kind id (e.g. 'motion', '
|
|
16160
|
+
/** Stable kind id (e.g. 'motion', 'vehicle', 'car', 'lock'). */
|
|
15829
16161
|
kind: string(),
|
|
16162
|
+
/** i18n key resolved on the UI side; `label` is the English fallback. */
|
|
16163
|
+
labelKey: string(),
|
|
16164
|
+
/** English fallback label (kept for clients that don't translate). */
|
|
15830
16165
|
label: string(),
|
|
15831
16166
|
/** Hex color for timeline/legend rendering. */
|
|
15832
16167
|
color: string(),
|
|
16168
|
+
/** Dictionary id → lucide component on the UI side. */
|
|
16169
|
+
iconId: string(),
|
|
16170
|
+
/** Legacy closed-vocab glyph — fallback for `iconId`. */
|
|
15833
16171
|
icon: EventKindIconSchema,
|
|
15834
16172
|
category: EventKindCategorySchema,
|
|
16173
|
+
/** Macro parent for this kind ('car' → 'vehicle'); null for a macro. */
|
|
16174
|
+
parentKind: string().nullable(),
|
|
16175
|
+
/** Derived from `parentKind`, explicit for the client tree. */
|
|
16176
|
+
level: EventKindLevelSchema,
|
|
15835
16177
|
/** Which cap + device contributes this kind. For built-ins the camera
|
|
15836
16178
|
* itself; for sensor kinds the LINKED source device. */
|
|
15837
16179
|
source: object({
|
|
@@ -15904,11 +16246,21 @@ var TrackAudioLabelSchema = object({
|
|
|
15904
16246
|
firstAt: number(),
|
|
15905
16247
|
lastAt: number()
|
|
15906
16248
|
});
|
|
16249
|
+
/**
|
|
16250
|
+
* How a track was produced. `pipeline` (default / absent) = the spatial
|
|
16251
|
+
* detection+tracking pipeline. `sensor` = a SYNTHETIC track projected from a
|
|
16252
|
+
* linked sensor/control state change (no positions; carries a snapshot). The
|
|
16253
|
+
* spatial subsystems (tracker association, occupancy count, re-id/embedding,
|
|
16254
|
+
* resurrection) MUST skip `sensor` tracks — they have no bbox trajectory.
|
|
16255
|
+
*/
|
|
16256
|
+
var TrackSourceSchema = _enum(["pipeline", "sensor"]);
|
|
15907
16257
|
var TrackSchema = object({
|
|
15908
16258
|
trackId: string(),
|
|
15909
16259
|
deviceId: number(),
|
|
15910
16260
|
className: string(),
|
|
15911
16261
|
label: string().optional(),
|
|
16262
|
+
/** Track provenance. Absent ⇒ `pipeline` (legacy rows). */
|
|
16263
|
+
source: TrackSourceSchema.optional(),
|
|
15912
16264
|
firstSeen: number(),
|
|
15913
16265
|
lastSeen: number(),
|
|
15914
16266
|
/** Frame-rate position history (subject to maxPositionHistory cap). */
|
|
@@ -16163,6 +16515,26 @@ var TrackCascadeCountsSchema = object({
|
|
|
16163
16515
|
/** Per-track CLIP search vectors removed (best-effort). */
|
|
16164
16516
|
embeddings: number().int()
|
|
16165
16517
|
});
|
|
16518
|
+
/** Event-store footprint for one camera. */
|
|
16519
|
+
var EventStoreDeviceFootprintSchema = object({
|
|
16520
|
+
deviceId: number(),
|
|
16521
|
+
/** Persisted event rows (motion + object + audio) for the camera. */
|
|
16522
|
+
rows: number().int(),
|
|
16523
|
+
/** Event-owned media bytes on disk for the camera. */
|
|
16524
|
+
bytes: number().int()
|
|
16525
|
+
});
|
|
16526
|
+
/** Aggregate event-store footprint: global totals + per-camera breakdown. */
|
|
16527
|
+
var EventStoreFootprintSchema = object({
|
|
16528
|
+
totalRows: number().int(),
|
|
16529
|
+
totalBytes: number().int(),
|
|
16530
|
+
devices: array(EventStoreDeviceFootprintSchema).readonly()
|
|
16531
|
+
});
|
|
16532
|
+
/** Per-kind counts returned by the event-prune / device-delete mutations. */
|
|
16533
|
+
var EventPruneCountsSchema = object({
|
|
16534
|
+
motion: number().int(),
|
|
16535
|
+
object: number().int(),
|
|
16536
|
+
audio: number().int()
|
|
16537
|
+
});
|
|
16166
16538
|
DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).readonly()), method(object({
|
|
16167
16539
|
deviceId: number(),
|
|
16168
16540
|
trackId: string()
|
|
@@ -16226,6 +16598,21 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
16226
16598
|
}), {
|
|
16227
16599
|
kind: "mutation",
|
|
16228
16600
|
auth: "admin"
|
|
16601
|
+
}), method(object({}), EventStoreFootprintSchema, {
|
|
16602
|
+
kind: "query",
|
|
16603
|
+
auth: "admin"
|
|
16604
|
+
}), method(object({
|
|
16605
|
+
olderThanMs: number(),
|
|
16606
|
+
reason: OpsLogReasonSchema.optional()
|
|
16607
|
+
}), EventPruneCountsSchema, {
|
|
16608
|
+
kind: "mutation",
|
|
16609
|
+
auth: "admin"
|
|
16610
|
+
}), method(object({ deviceId: number() }), EventPruneCountsSchema, {
|
|
16611
|
+
kind: "mutation",
|
|
16612
|
+
auth: "admin"
|
|
16613
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
16614
|
+
kind: "query",
|
|
16615
|
+
auth: "admin"
|
|
16229
16616
|
}), method(object({
|
|
16230
16617
|
eventId: string(),
|
|
16231
16618
|
kind: MediaFileKindEnum.optional()
|
|
@@ -16250,6 +16637,76 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
16250
16637
|
eventId: string(),
|
|
16251
16638
|
timestamp: number()
|
|
16252
16639
|
});
|
|
16640
|
+
/**
|
|
16641
|
+
* Cap → event-kind mapping for the SENSOR / CONTROL cap families — the table
|
|
16642
|
+
* `pipeline-analytics.listEventKinds` uses to turn a linked device's bound
|
|
16643
|
+
* caps into per-camera event-kind descriptors.
|
|
16644
|
+
*
|
|
16645
|
+
* The descriptor DATA (color / iconId / labelKey / parentKind / category)
|
|
16646
|
+
* is NOT duplicated here — every entry is derived from the single
|
|
16647
|
+
* `EVENT_TAXONOMY` dictionary (`catalogs/event-taxonomy.ts`). This file owns
|
|
16648
|
+
* ONLY the cap-name → taxonomy-kind mapping. Adding a new eventful sensor /
|
|
16649
|
+
* control cap means adding one line here (and a taxonomy entry); the anti-
|
|
16650
|
+
* drift guard `scripts/check-event-kind-coverage.ts` fails the build if an
|
|
16651
|
+
* eventful cap is missing.
|
|
16652
|
+
*/
|
|
16653
|
+
/** Map a taxonomy `iconId` onto the legacy closed `EventKindIcon` enum. */
|
|
16654
|
+
var LEGACY_ICON = {
|
|
16655
|
+
motion: "motion",
|
|
16656
|
+
audio: "audio",
|
|
16657
|
+
person: "person",
|
|
16658
|
+
vehicle: "vehicle",
|
|
16659
|
+
animal: "animal",
|
|
16660
|
+
package: "package",
|
|
16661
|
+
door: "door",
|
|
16662
|
+
pir: "pir",
|
|
16663
|
+
smoke: "smoke",
|
|
16664
|
+
water: "water",
|
|
16665
|
+
button: "button",
|
|
16666
|
+
generic: "generic",
|
|
16667
|
+
gas: "smoke",
|
|
16668
|
+
vibration: "generic",
|
|
16669
|
+
tamper: "generic",
|
|
16670
|
+
presence: "person",
|
|
16671
|
+
lock: "generic",
|
|
16672
|
+
siren: "generic",
|
|
16673
|
+
switch: "generic",
|
|
16674
|
+
doorbell: "button"
|
|
16675
|
+
};
|
|
16676
|
+
function legacyIcon(iconId) {
|
|
16677
|
+
return LEGACY_ICON[iconId] ?? "generic";
|
|
16678
|
+
}
|
|
16679
|
+
/**
|
|
16680
|
+
* Cap name → taxonomy kind id. Covers EVERY eventful sensor / control cap.
|
|
16681
|
+
* The anti-drift guard cross-checks this against the eventful caps declared
|
|
16682
|
+
* in `packages/types/src/capabilities/*.cap.ts`.
|
|
16683
|
+
*/
|
|
16684
|
+
var CAP_TO_KIND = {
|
|
16685
|
+
contact: "contact",
|
|
16686
|
+
motion: "motion-sensor",
|
|
16687
|
+
smoke: "smoke",
|
|
16688
|
+
flood: "flood",
|
|
16689
|
+
gas: "gas",
|
|
16690
|
+
"carbon-monoxide": "carbon-monoxide",
|
|
16691
|
+
vibration: "vibration",
|
|
16692
|
+
tamper: "tamper",
|
|
16693
|
+
presence: "presence",
|
|
16694
|
+
"enum-sensor": "enum-sensor",
|
|
16695
|
+
"event-emitter": "device-event",
|
|
16696
|
+
"lock-control": "lock",
|
|
16697
|
+
switch: "switch",
|
|
16698
|
+
button: "button",
|
|
16699
|
+
doorbell: "doorbell"
|
|
16700
|
+
};
|
|
16701
|
+
function buildDescriptor(capName, kind) {
|
|
16702
|
+
const t = EVENT_TAXONOMY[kind];
|
|
16703
|
+
if (t === void 0) throw new Error(`EVENT_KIND_BY_CAP: cap '${capName}' maps to unknown taxonomy kind '${kind}'`);
|
|
16704
|
+
return {
|
|
16705
|
+
...t,
|
|
16706
|
+
icon: legacyIcon(t.iconId)
|
|
16707
|
+
};
|
|
16708
|
+
}
|
|
16709
|
+
Object.freeze(Object.fromEntries(Object.entries(CAP_TO_KIND).map(([capName, kind]) => [capName, buildDescriptor(capName, kind)])));
|
|
16253
16710
|
var CameraPipelineConfigSchema = object({
|
|
16254
16711
|
engine: PipelineEngineChoiceSchema.optional(),
|
|
16255
16712
|
steps: array(PipelineStepInputSchema).readonly(),
|
|
@@ -19472,13 +19929,29 @@ method(object({
|
|
|
19472
19929
|
}), method(object({ deviceId: number() }), RecordingStatusSchema, {
|
|
19473
19930
|
kind: "mutation",
|
|
19474
19931
|
auth: "admin"
|
|
19475
|
-
}), method(object({
|
|
19932
|
+
}), method(object({
|
|
19933
|
+
deviceId: number(),
|
|
19934
|
+
reason: OpsLogReasonSchema.optional()
|
|
19935
|
+
}), object({
|
|
19476
19936
|
floorMs: number().nullable(),
|
|
19477
19937
|
deletedBuckets: number().int(),
|
|
19478
19938
|
reclaimedBytes: number().int()
|
|
19479
19939
|
}), {
|
|
19480
19940
|
kind: "mutation",
|
|
19481
19941
|
auth: "admin"
|
|
19942
|
+
}), method(object({
|
|
19943
|
+
deviceId: number(),
|
|
19944
|
+
fromMs: number().optional(),
|
|
19945
|
+
toMs: number().optional()
|
|
19946
|
+
}), object({
|
|
19947
|
+
deletedBuckets: number().int(),
|
|
19948
|
+
reclaimedBytes: number().int()
|
|
19949
|
+
}), {
|
|
19950
|
+
kind: "mutation",
|
|
19951
|
+
auth: "admin"
|
|
19952
|
+
}), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
|
|
19953
|
+
kind: "query",
|
|
19954
|
+
auth: "admin"
|
|
19482
19955
|
});
|
|
19483
19956
|
/**
|
|
19484
19957
|
* `recordingExport` cap — render a footage time range into a single downloadable
|
|
@@ -22600,6 +23073,12 @@ Object.freeze({
|
|
|
22600
23073
|
addonId: null,
|
|
22601
23074
|
access: "delete"
|
|
22602
23075
|
},
|
|
23076
|
+
"pipelineAnalytics.deleteDeviceEvents": {
|
|
23077
|
+
capName: "pipeline-analytics",
|
|
23078
|
+
capScope: "device",
|
|
23079
|
+
addonId: null,
|
|
23080
|
+
access: "delete"
|
|
23081
|
+
},
|
|
22603
23082
|
"pipelineAnalytics.deleteTracks": {
|
|
22604
23083
|
capName: "pipeline-analytics",
|
|
22605
23084
|
capScope: "device",
|
|
@@ -22630,6 +23109,12 @@ Object.freeze({
|
|
|
22630
23109
|
addonId: null,
|
|
22631
23110
|
access: "view"
|
|
22632
23111
|
},
|
|
23112
|
+
"pipelineAnalytics.getEventStoreFootprint": {
|
|
23113
|
+
capName: "pipeline-analytics",
|
|
23114
|
+
capScope: "device",
|
|
23115
|
+
addonId: null,
|
|
23116
|
+
access: "view"
|
|
23117
|
+
},
|
|
22633
23118
|
"pipelineAnalytics.getKeyEvents": {
|
|
22634
23119
|
capName: "pipeline-analytics",
|
|
22635
23120
|
capScope: "device",
|
|
@@ -22672,6 +23157,12 @@ Object.freeze({
|
|
|
22672
23157
|
addonId: null,
|
|
22673
23158
|
access: "view"
|
|
22674
23159
|
},
|
|
23160
|
+
"pipelineAnalytics.listOpsLog": {
|
|
23161
|
+
capName: "pipeline-analytics",
|
|
23162
|
+
capScope: "device",
|
|
23163
|
+
addonId: null,
|
|
23164
|
+
access: "view"
|
|
23165
|
+
},
|
|
22675
23166
|
"pipelineAnalytics.listRecentTracks": {
|
|
22676
23167
|
capName: "pipeline-analytics",
|
|
22677
23168
|
capScope: "device",
|
|
@@ -22684,6 +23175,12 @@ Object.freeze({
|
|
|
22684
23175
|
addonId: null,
|
|
22685
23176
|
access: "view"
|
|
22686
23177
|
},
|
|
23178
|
+
"pipelineAnalytics.pruneEvents": {
|
|
23179
|
+
capName: "pipeline-analytics",
|
|
23180
|
+
capScope: "device",
|
|
23181
|
+
addonId: null,
|
|
23182
|
+
access: "create"
|
|
23183
|
+
},
|
|
22687
23184
|
"pipelineAnalytics.pruneEventsBefore": {
|
|
22688
23185
|
capName: "pipeline-analytics",
|
|
22689
23186
|
capScope: "device",
|
|
@@ -23446,6 +23943,12 @@ Object.freeze({
|
|
|
23446
23943
|
addonId: null,
|
|
23447
23944
|
access: "create"
|
|
23448
23945
|
},
|
|
23946
|
+
"recording.deleteFootprint": {
|
|
23947
|
+
capName: "recording",
|
|
23948
|
+
capScope: "system",
|
|
23949
|
+
addonId: null,
|
|
23950
|
+
access: "delete"
|
|
23951
|
+
},
|
|
23449
23952
|
"recording.getAvailability": {
|
|
23450
23953
|
capName: "recording",
|
|
23451
23954
|
capScope: "system",
|
|
@@ -23476,6 +23979,12 @@ Object.freeze({
|
|
|
23476
23979
|
addonId: null,
|
|
23477
23980
|
access: "view"
|
|
23478
23981
|
},
|
|
23982
|
+
"recording.listOpsLog": {
|
|
23983
|
+
capName: "recording",
|
|
23984
|
+
capScope: "system",
|
|
23985
|
+
addonId: null,
|
|
23986
|
+
access: "view"
|
|
23987
|
+
},
|
|
23479
23988
|
"recording.locateSegment": {
|
|
23480
23989
|
capName: "recording",
|
|
23481
23990
|
capScope: "system",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/addon-smtp-nodemailer",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.27",
|
|
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",
|