@camstack/addon-provider-rtsp 1.2.83 → 1.2.85

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/addon.js CHANGED
@@ -18802,11 +18802,30 @@ var SensorEventSchema = object({
18802
18802
  value: record(string(), unknown()).nullable(),
18803
18803
  timestamp: number()
18804
18804
  });
18805
+ /**
18806
+ * One stored sighting on a track's trajectory.
18807
+ *
18808
+ * The array these live in is returned in TIME order (D399) — it is APPENDED in
18809
+ * arrival order, and the two detector passes interleave, so a consumer must not
18810
+ * assume the two are the same on a row written by an older build.
18811
+ */
18805
18812
  var TrackPositionSchema = object({
18806
18813
  x: number(),
18807
18814
  y: number(),
18808
18815
  timestamp: number(),
18809
- bbox: BoundingBoxSchema
18816
+ bbox: BoundingBoxSchema,
18817
+ /**
18818
+ * Which detector pass measured this box (D399): `frame` is the full-frame
18819
+ * pass on the analysis raster, `recovery` is the native-resolution
18820
+ * small-subject second pass (D377/D378). Both write into one array, and until
18821
+ * this field existed the only way to tell them apart was that full-frame boxes
18822
+ * are exact multiples of 1.2 while recovery boxes are full-precision floats.
18823
+ * Absent on rows written before D399.
18824
+ */
18825
+ source: _enum(["frame", "recovery"]).optional(),
18826
+ /** Detection score of this box, so a position can be weighed and not only
18827
+ * plotted. Absent on rows written before D399. */
18828
+ score: number().optional()
18810
18829
  });
18811
18830
  var TrackSnapshotSchema = object({
18812
18831
  timestamp: number(),
@@ -19206,14 +19225,25 @@ var TrackSchema = object({
19206
19225
  */
19207
19226
  hasRider: boolean().optional(),
19208
19227
  /**
19209
- * WHY this track ended without a NATIVE best-shot tile
19210
- * ([D276](../decisions/adr-0276-a-stand-in-tile-is-provisional-and-a-close-says-why.md)) —
19228
+ * WHY this track ended without a NATIVE best-shot FRAME
19229
+ * ([D276](../decisions/adr-0276-a-stand-in-tile-is-provisional-and-a-close-says-why.md),
19230
+ * widened by [D400](../decisions/adr-0400-the-picture-is-judged-on-what-is-delivered.md)) —
19211
19231
  * a composed token line (`no-key-frame capture=keyframe:native-missx4`,
19212
- * `derive-returned-null tile=standin`, …) written at close and CLEARED by
19213
- * the late-keyFrame upgrade when a native tile lands after all. The
19214
- * operator-facing answer to "perché manca l'immagine?" on a track whose
19232
+ * `derive-returned-null tile=standin`,
19233
+ * `native-tile tile=native no-key-frame-at-close`, …) written at close and
19234
+ * CLEARED by the late-keyFrame upgrade when a native tile lands after all.
19235
+ * The operator-facing answer to "perché manca l'immagine?" on a track whose
19215
19236
  * tile is a face/plate stand-in, a raster crop, or an icon.
19216
19237
  *
19238
+ * **`no-key-frame-at-close` (D400).** The line used to be written ONLY when
19239
+ * the TILE ranked below native, so a track whose thumbnail landed natively
19240
+ * while its key frame missed carried no reason at all — three of the four
19241
+ * `MISSING_KEYFRAME` tracks in the 2026-09-07 operator audit were exactly
19242
+ * that shape, and their "niente ultimo" had no cause anywhere on the row.
19243
+ * The key frame is the head of a cascade (`keyFrame ⇒ keyFrameSmall ⇒ the
19244
+ * lastFrame copy source`), so its absence is now on this line whatever the
19245
+ * tile ended up being.
19246
+ *
19217
19247
  * **Absent ≠ "missed silently"**: a row written before the column, a hub
19218
19248
  * that predates the field, and every track whose tile landed native all
19219
19249
  * omit it. Render nothing when absent.
@@ -25389,6 +25419,59 @@ var IdentitySampleInfoSchema = object({
25389
25419
  deviceId: number().int().optional(),
25390
25420
  base64: string().optional()
25391
25421
  });
25422
+ /**
25423
+ * One enrolled sample, judged against the gallery it lives in.
25424
+ *
25425
+ * The gallery is the one input to recognition nobody re-reads: a sample
25426
+ * enrolled from the wrong face keeps voting forever, and because the matches it
25427
+ * pulls then look confident, nobody goes back. The 2026-09-08 audit found
25428
+ * exactly one such pair on this cluster — a sample scoring 0.61 against three
25429
+ * samples of ANOTHER person, enrolled from the same camera in the same minute,
25430
+ * where every other cross-identity pair sits under 0.50.
25431
+ */
25432
+ var IdentitySampleAuditRowSchema = object({
25433
+ sampleId: string(),
25434
+ enrolledAt: number().int(),
25435
+ deviceId: number().int().optional(),
25436
+ source: _enum(["detected", "photo"]),
25437
+ /** The enrolled crop's media key, so the panel can show the evidence. */
25438
+ mediaKey: string().optional(),
25439
+ /**
25440
+ * False = the sample is stamped with a DIFFERENT face model, and a cosine
25441
+ * across feature spaces is a well-formed float with no meaning. Every number
25442
+ * below then says nothing — it must read as "cannot say", never as an
25443
+ * accusation and never as a clean bill: this list ends in a Remove button.
25444
+ */
25445
+ comparable: boolean(),
25446
+ /** Mean cosine against this person's other samples. Null when there are none
25447
+ * to compare with — never 0, which would read as "opposite". */
25448
+ selfMean: number().nullable(),
25449
+ /** The other person this sample looks most like, when it looks like one.
25450
+ * This is the half that convicts: not looking like yourself can be a hard
25451
+ * angle; looking like someone the gallery can NAME is a mis-enrolment. */
25452
+ bestForeign: object({
25453
+ identityId: string(),
25454
+ name: string(),
25455
+ score: number()
25456
+ }).optional(),
25457
+ /** 0 = nothing to say. Higher = look at this one sooner. */
25458
+ suspicion: number()
25459
+ });
25460
+ var IdentitySampleAuditSchema = object({
25461
+ identityId: string(),
25462
+ name: string(),
25463
+ /** The cluster face model every comparison was made in. */
25464
+ modelId: string(),
25465
+ totalSamples: number().int(),
25466
+ comparableSamples: number().int(),
25467
+ flagged: number().int(),
25468
+ /** The bar `flagged` counts against, so the panel states the RULE and not
25469
+ * only its current result. */
25470
+ flagThreshold: number(),
25471
+ /** Worst first. A row with nothing to say still appears, at the bottom: the
25472
+ * operator asked to see the gallery, not only its accusations. */
25473
+ rows: array(IdentitySampleAuditRowSchema).readonly()
25474
+ });
25392
25475
  var FaceInfoSchema = object({
25393
25476
  faceId: string(),
25394
25477
  deviceId: number().int(),
@@ -25540,7 +25623,7 @@ includeCrops: boolean().optional() }).optional(), array(IdentitySchema).readonly
25540
25623
  }), method(object({ id: string() }), _void(), {
25541
25624
  kind: "mutation",
25542
25625
  auth: "admin"
25543
- }), method(object({ identityId: string() }), array(IdentitySampleInfoSchema).readonly()), method(object({
25626
+ }), method(object({ identityId: string() }), array(IdentitySampleInfoSchema).readonly()), method(object({ identityId: string().min(1) }), IdentitySampleAuditSchema, { auth: "admin" }), method(object({
25544
25627
  identityId: string(),
25545
25628
  sampleId: string()
25546
25629
  }), _void(), {
@@ -36099,6 +36182,12 @@ Object.freeze({
36099
36182
  addonId: null,
36100
36183
  access: "create"
36101
36184
  },
36185
+ "faceGallery.auditIdentitySamples": {
36186
+ capName: "face-gallery",
36187
+ capScope: "system",
36188
+ addonId: null,
36189
+ access: "view"
36190
+ },
36102
36191
  "faceGallery.createIdentity": {
36103
36192
  capName: "face-gallery",
36104
36193
  capScope: "system",
package/dist/addon.mjs CHANGED
@@ -18778,11 +18778,30 @@ var SensorEventSchema = object({
18778
18778
  value: record(string(), unknown()).nullable(),
18779
18779
  timestamp: number()
18780
18780
  });
18781
+ /**
18782
+ * One stored sighting on a track's trajectory.
18783
+ *
18784
+ * The array these live in is returned in TIME order (D399) — it is APPENDED in
18785
+ * arrival order, and the two detector passes interleave, so a consumer must not
18786
+ * assume the two are the same on a row written by an older build.
18787
+ */
18781
18788
  var TrackPositionSchema = object({
18782
18789
  x: number(),
18783
18790
  y: number(),
18784
18791
  timestamp: number(),
18785
- bbox: BoundingBoxSchema
18792
+ bbox: BoundingBoxSchema,
18793
+ /**
18794
+ * Which detector pass measured this box (D399): `frame` is the full-frame
18795
+ * pass on the analysis raster, `recovery` is the native-resolution
18796
+ * small-subject second pass (D377/D378). Both write into one array, and until
18797
+ * this field existed the only way to tell them apart was that full-frame boxes
18798
+ * are exact multiples of 1.2 while recovery boxes are full-precision floats.
18799
+ * Absent on rows written before D399.
18800
+ */
18801
+ source: _enum(["frame", "recovery"]).optional(),
18802
+ /** Detection score of this box, so a position can be weighed and not only
18803
+ * plotted. Absent on rows written before D399. */
18804
+ score: number().optional()
18786
18805
  });
18787
18806
  var TrackSnapshotSchema = object({
18788
18807
  timestamp: number(),
@@ -19182,14 +19201,25 @@ var TrackSchema = object({
19182
19201
  */
19183
19202
  hasRider: boolean().optional(),
19184
19203
  /**
19185
- * WHY this track ended without a NATIVE best-shot tile
19186
- * ([D276](../decisions/adr-0276-a-stand-in-tile-is-provisional-and-a-close-says-why.md)) —
19204
+ * WHY this track ended without a NATIVE best-shot FRAME
19205
+ * ([D276](../decisions/adr-0276-a-stand-in-tile-is-provisional-and-a-close-says-why.md),
19206
+ * widened by [D400](../decisions/adr-0400-the-picture-is-judged-on-what-is-delivered.md)) —
19187
19207
  * a composed token line (`no-key-frame capture=keyframe:native-missx4`,
19188
- * `derive-returned-null tile=standin`, …) written at close and CLEARED by
19189
- * the late-keyFrame upgrade when a native tile lands after all. The
19190
- * operator-facing answer to "perché manca l'immagine?" on a track whose
19208
+ * `derive-returned-null tile=standin`,
19209
+ * `native-tile tile=native no-key-frame-at-close`, …) written at close and
19210
+ * CLEARED by the late-keyFrame upgrade when a native tile lands after all.
19211
+ * The operator-facing answer to "perché manca l'immagine?" on a track whose
19191
19212
  * tile is a face/plate stand-in, a raster crop, or an icon.
19192
19213
  *
19214
+ * **`no-key-frame-at-close` (D400).** The line used to be written ONLY when
19215
+ * the TILE ranked below native, so a track whose thumbnail landed natively
19216
+ * while its key frame missed carried no reason at all — three of the four
19217
+ * `MISSING_KEYFRAME` tracks in the 2026-09-07 operator audit were exactly
19218
+ * that shape, and their "niente ultimo" had no cause anywhere on the row.
19219
+ * The key frame is the head of a cascade (`keyFrame ⇒ keyFrameSmall ⇒ the
19220
+ * lastFrame copy source`), so its absence is now on this line whatever the
19221
+ * tile ended up being.
19222
+ *
19193
19223
  * **Absent ≠ "missed silently"**: a row written before the column, a hub
19194
19224
  * that predates the field, and every track whose tile landed native all
19195
19225
  * omit it. Render nothing when absent.
@@ -25365,6 +25395,59 @@ var IdentitySampleInfoSchema = object({
25365
25395
  deviceId: number().int().optional(),
25366
25396
  base64: string().optional()
25367
25397
  });
25398
+ /**
25399
+ * One enrolled sample, judged against the gallery it lives in.
25400
+ *
25401
+ * The gallery is the one input to recognition nobody re-reads: a sample
25402
+ * enrolled from the wrong face keeps voting forever, and because the matches it
25403
+ * pulls then look confident, nobody goes back. The 2026-09-08 audit found
25404
+ * exactly one such pair on this cluster — a sample scoring 0.61 against three
25405
+ * samples of ANOTHER person, enrolled from the same camera in the same minute,
25406
+ * where every other cross-identity pair sits under 0.50.
25407
+ */
25408
+ var IdentitySampleAuditRowSchema = object({
25409
+ sampleId: string(),
25410
+ enrolledAt: number().int(),
25411
+ deviceId: number().int().optional(),
25412
+ source: _enum(["detected", "photo"]),
25413
+ /** The enrolled crop's media key, so the panel can show the evidence. */
25414
+ mediaKey: string().optional(),
25415
+ /**
25416
+ * False = the sample is stamped with a DIFFERENT face model, and a cosine
25417
+ * across feature spaces is a well-formed float with no meaning. Every number
25418
+ * below then says nothing — it must read as "cannot say", never as an
25419
+ * accusation and never as a clean bill: this list ends in a Remove button.
25420
+ */
25421
+ comparable: boolean(),
25422
+ /** Mean cosine against this person's other samples. Null when there are none
25423
+ * to compare with — never 0, which would read as "opposite". */
25424
+ selfMean: number().nullable(),
25425
+ /** The other person this sample looks most like, when it looks like one.
25426
+ * This is the half that convicts: not looking like yourself can be a hard
25427
+ * angle; looking like someone the gallery can NAME is a mis-enrolment. */
25428
+ bestForeign: object({
25429
+ identityId: string(),
25430
+ name: string(),
25431
+ score: number()
25432
+ }).optional(),
25433
+ /** 0 = nothing to say. Higher = look at this one sooner. */
25434
+ suspicion: number()
25435
+ });
25436
+ var IdentitySampleAuditSchema = object({
25437
+ identityId: string(),
25438
+ name: string(),
25439
+ /** The cluster face model every comparison was made in. */
25440
+ modelId: string(),
25441
+ totalSamples: number().int(),
25442
+ comparableSamples: number().int(),
25443
+ flagged: number().int(),
25444
+ /** The bar `flagged` counts against, so the panel states the RULE and not
25445
+ * only its current result. */
25446
+ flagThreshold: number(),
25447
+ /** Worst first. A row with nothing to say still appears, at the bottom: the
25448
+ * operator asked to see the gallery, not only its accusations. */
25449
+ rows: array(IdentitySampleAuditRowSchema).readonly()
25450
+ });
25368
25451
  var FaceInfoSchema = object({
25369
25452
  faceId: string(),
25370
25453
  deviceId: number().int(),
@@ -25516,7 +25599,7 @@ includeCrops: boolean().optional() }).optional(), array(IdentitySchema).readonly
25516
25599
  }), method(object({ id: string() }), _void(), {
25517
25600
  kind: "mutation",
25518
25601
  auth: "admin"
25519
- }), method(object({ identityId: string() }), array(IdentitySampleInfoSchema).readonly()), method(object({
25602
+ }), method(object({ identityId: string() }), array(IdentitySampleInfoSchema).readonly()), method(object({ identityId: string().min(1) }), IdentitySampleAuditSchema, { auth: "admin" }), method(object({
25520
25603
  identityId: string(),
25521
25604
  sampleId: string()
25522
25605
  }), _void(), {
@@ -36075,6 +36158,12 @@ Object.freeze({
36075
36158
  addonId: null,
36076
36159
  access: "create"
36077
36160
  },
36161
+ "faceGallery.auditIdentitySamples": {
36162
+ capName: "face-gallery",
36163
+ capScope: "system",
36164
+ addonId: null,
36165
+ access: "view"
36166
+ },
36078
36167
  "faceGallery.createIdentity": {
36079
36168
  capName: "face-gallery",
36080
36169
  capScope: "system",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-rtsp",
3
- "version": "1.2.83",
3
+ "version": "1.2.85",
4
4
  "description": "Generic RTSP camera device provider addon for CamStack",
5
5
  "keywords": [
6
6
  "camstack",