@camstack/addon-provider-amcrest 0.1.7 → 0.1.8

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
@@ -4633,7 +4633,7 @@ function _instanceof(cls, params = {}) {
4633
4633
  return inst;
4634
4634
  }
4635
4635
  //#endregion
4636
- //#region ../types/dist/sleep-DJaTV2D7.mjs
4636
+ //#region ../types/dist/sleep-BC9Yqte7.mjs
4637
4637
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4638
4638
  EventCategory["SystemBoot"] = "system.boot";
4639
4639
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -6737,6 +6737,18 @@ function method(input, output, options) {
6737
6737
  timeoutMs: options?.timeoutMs
6738
6738
  };
6739
6739
  }
6740
+ /**
6741
+ * A wrapper/system-only method: served exclusively by the cap's system-level
6742
+ * provider (`InferProvider`), and OPTIONAL on `InferNativeProvider` so per-device
6743
+ * driver natives don't stub out a wrapper concern (e.g. a cross-device cache
6744
+ * overview). The `systemOnly: true` literal is what `InferNativeProvider` keys on.
6745
+ */
6746
+ function systemMethod(input, output, options) {
6747
+ return {
6748
+ ...method(input, output, options),
6749
+ systemOnly: true
6750
+ };
6751
+ }
6740
6752
  /** Shorthand to define an event schema */
6741
6753
  function event(data) {
6742
6754
  return { data };
@@ -11830,6 +11842,7 @@ var PipelineAddonSchemaSchema = object({
11830
11842
  defaultModelId: string(),
11831
11843
  defaultModelIdByFormat: record(string(), string()).optional(),
11832
11844
  enabledByDefault: boolean().optional(),
11845
+ backfillIntoExistingOverrides: boolean().optional(),
11833
11846
  defaultConfidence: number(),
11834
11847
  group: string().optional(),
11835
11848
  configSchema: array(ConfigFieldBridge).readonly().optional()
@@ -12169,6 +12182,25 @@ var zonesCapability = {
12169
12182
  runtimeState: object({ zones: array(ZoneSchema).readonly() })
12170
12183
  };
12171
12184
  /**
12185
+ * A bounding box in NORMALIZED [0,1] frame coordinates for `getNativeCrop`. The
12186
+ * decode worker resolves it against the RETAINED native frame's real pixel dims,
12187
+ * so the caller supplies only the detection-res bbox divided by the detection
12188
+ * dims — no native resolution to plumb.
12189
+ */
12190
+ var NativeCropBboxSchema = object({
12191
+ x: number(),
12192
+ y: number(),
12193
+ w: number(),
12194
+ h: number()
12195
+ });
12196
+ /** Result of a best-effort native-resolution crop (`getNativeCrop`). */
12197
+ var NativeCropResultSchema = object({
12198
+ /** Packed rgb (24-bit) pixels of the crop. */
12199
+ bytes: _instanceof(Uint8Array),
12200
+ width: number().int().positive(),
12201
+ height: number().int().positive()
12202
+ });
12203
+ /**
12172
12204
  * Per-camera tunable ranges + defaults. Single source of truth used
12173
12205
  * by both the Zod data schema (validation + default fallback) and
12174
12206
  * the device settings UI (slider min/max/step). Touch one place and
@@ -12424,7 +12456,11 @@ var RunnerLocalMetricsSchema = object({
12424
12456
  avgInferenceTimeMs: number(),
12425
12457
  queueDepth: number()
12426
12458
  });
12427
- method(RunnerCameraConfigSchema, object({ success: literal(true) }), { kind: "mutation" }), method(object({ deviceId: number() }), object({ success: literal(true) }), { kind: "mutation" }), method(ReportMotionInputSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), RunnerLocalLoadSchema), method(_void(), RunnerLocalMetricsSchema), method(object({ deviceId: number() }), CameraMetricsSchema.nullable()), method(_void(), array(CameraMetricsWithDeviceIdSchema).readonly()), method(_void(), array(number()).readonly());
12459
+ method(RunnerCameraConfigSchema, object({ success: literal(true) }), { kind: "mutation" }), method(object({ deviceId: number() }), object({ success: literal(true) }), { kind: "mutation" }), method(ReportMotionInputSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), RunnerLocalLoadSchema), method(_void(), RunnerLocalMetricsSchema), method(object({ deviceId: number() }), CameraMetricsSchema.nullable()), method(_void(), array(CameraMetricsWithDeviceIdSchema).readonly()), method(_void(), array(number()).readonly()), method(object({
12460
+ handle: FrameHandleSchema,
12461
+ bbox: NativeCropBboxSchema,
12462
+ maxWidth: number().int().positive().optional()
12463
+ }), NativeCropResultSchema.nullable());
12428
12464
  /**
12429
12465
  * Hardware / firmware motion sensor cap — binary detected state plus
12430
12466
  * a timestamp of the last observation. Distinct from
@@ -18099,7 +18135,17 @@ var TrackSchema = object({
18099
18135
  /** Cumulative normalized distance travelled (0..1 units = full frame width). */
18100
18136
  totalDistance: number(),
18101
18137
  state: TrackStateSchema,
18102
- active: boolean()
18138
+ active: boolean(),
18139
+ /** Deterministic key-event importance score in [0,1] (server-computed at
18140
+ * track expiry, recomputed on late label). Absent on legacy rows written
18141
+ * before scoring shipped — consumers degrade to absence / compute-on-read. */
18142
+ importance: number().optional(),
18143
+ /** Id of the track's highest-confidence ObjectEvent (its representative
18144
+ * "best" frame). Absent when the track produced no object events. */
18145
+ bestEventId: string().optional(),
18146
+ /** Tag of the importance sub-signal that dominated the score
18147
+ * (identity|dwell|proximity|class|confidence|travel|zone). */
18148
+ importanceReason: string().optional()
18103
18149
  });
18104
18150
  var BaseEventFields = {
18105
18151
  id: string(),
@@ -18164,8 +18210,18 @@ var ObjectEventSchema = object({
18164
18210
  frameHeight: number().optional(),
18165
18211
  /** MediaStore key for the crop attached to this event (if any). */
18166
18212
  mediaKey: string().optional(),
18213
+ /** Design B: MediaStore key of the track's native-resolution key frame (the
18214
+ * best-detection full frame). Resolve via the event-media data-plane
18215
+ * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`) for a detail view that
18216
+ * draws `bbox` over the native frame. Absent on legacy rows / non-decoded
18217
+ * sources — consumers fall back to `mediaKey` (the tight crop). */
18218
+ keyFrameMediaKey: string().optional(),
18167
18219
  /** Populated by B5 (recording playback URL for this event). */
18168
- mediaUrl: string().optional()
18220
+ mediaUrl: string().optional(),
18221
+ /** The parent track's key-event importance [0,1], propagated to every object
18222
+ * event of the track (so an event row can be sorted by importance without a
18223
+ * track join). Absent on legacy rows / before the track was scored. */
18224
+ importance: number().optional()
18169
18225
  });
18170
18226
  var AudioEventSchema = object({
18171
18227
  ...BaseEventFields,
@@ -18189,7 +18245,8 @@ var MediaFileKindEnum = _enum([
18189
18245
  "fullFrame",
18190
18246
  "fullFrameBoxed",
18191
18247
  "faceCrop",
18192
- "plateCrop"
18248
+ "plateCrop",
18249
+ "keyFrame"
18193
18250
  ]);
18194
18251
  var MediaFileSchema = object({
18195
18252
  key: string(),
@@ -18210,6 +18267,32 @@ var DeviceEventQueryInput = object({
18210
18267
  projection: _enum(["full", "slim"]).optional()
18211
18268
  });
18212
18269
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
18270
+ var KeyEventQueryInput = object({
18271
+ deviceId: number(),
18272
+ /** Window lower bound (track firstSeen ≥ since). */
18273
+ since: number(),
18274
+ /** Window upper bound (track firstSeen ≤ until). */
18275
+ until: number(),
18276
+ limit: number().int().min(1).max(200).default(50),
18277
+ /** Drop tracks scoring below this importance. */
18278
+ minImportance: number().min(0).max(1).optional(),
18279
+ /** Restrict to a single class (e.g. 'person'). */
18280
+ classFilter: string().optional()
18281
+ });
18282
+ var KeyEventSchema = object({
18283
+ /** The representative event id (the track's best ObjectEvent, else its trackId). */
18284
+ id: string(),
18285
+ trackId: string(),
18286
+ /** Track start time (firstSeen). */
18287
+ timestamp: number(),
18288
+ className: string(),
18289
+ label: string().optional(),
18290
+ importance: number(),
18291
+ /** Highest-confidence ObjectEvent id for the track (empty when none). */
18292
+ bestEventId: string(),
18293
+ /** Track lifetime in ms (lastSeen - firstSeen). */
18294
+ windowMs: number().optional()
18295
+ });
18213
18296
  var TrackedDetectionSchema = object({
18214
18297
  trackId: string(),
18215
18298
  className: string(),
@@ -18239,7 +18322,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
18239
18322
  }), array(TrackSchema).readonly()), method(object({ deviceId: number() }), _void(), {
18240
18323
  kind: "mutation",
18241
18324
  auth: "admin"
18242
- }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({
18325
+ }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
18243
18326
  deviceId: number(),
18244
18327
  since: number(),
18245
18328
  until: number(),
@@ -19043,7 +19126,20 @@ var snapshotCapability = {
19043
19126
  invalidateCache: method(object({ deviceId: number() }), _void(), {
19044
19127
  kind: "mutation",
19045
19128
  auth: "admin"
19046
- })
19129
+ }),
19130
+ /**
19131
+ * Cache-only batch overview — answers from the wrapper's in-memory cache in
19132
+ * O(n) and NEVER triggers a capture. Lets a grid skip requesting images for
19133
+ * devices that never produced a frame, and gives it an ETag per device for
19134
+ * conditional (304-able) image fetches. `lastCapturedAt`/`cacheAgeMs`/`etag`
19135
+ * are null for a device with no cached frame.
19136
+ */
19137
+ getSnapshotOverview: systemMethod(object({ deviceIds: array(number()).min(1).max(200) }), array(object({
19138
+ deviceId: number(),
19139
+ lastCapturedAt: number().nullable(),
19140
+ cacheAgeMs: number().nullable(),
19141
+ etag: string().nullable()
19142
+ })))
19047
19143
  },
19048
19144
  status: {
19049
19145
  schema: SnapshotStatusSchema,
@@ -19300,10 +19396,32 @@ method(_void(), array(TurnServerSchema).readonly());
19300
19396
  * b. `finishAuthentication({userId, response})` → server verifies
19301
19397
  * the assertion, bumps the credential counter, returns ok.
19302
19398
  *
19399
+ * 2b. Usernameless (discoverable-credential) authentication — the
19400
+ * passkey IS the primary factor, no password leg:
19401
+ * a. `beginDiscoverableAuthentication({})` → assertion options with
19402
+ * EMPTY `allowCredentials` (the browser offers every resident
19403
+ * passkey it holds for this RP) + `userVerification: 'required'`
19404
+ * (the passkey replaces both factors, so UV is mandatory).
19405
+ * The challenge is stored server-side, NOT bound to any user.
19406
+ * b. `finishDiscoverableAuthentication({response})` → the provider
19407
+ * resolves the credential by the response's credential id,
19408
+ * verifies the assertion against the stored challenge + that
19409
+ * credential's public key/counter, and returns the OWNING
19410
+ * `userId` — the caller (core auth router) mints the session.
19411
+ *
19303
19412
  * 3. Management:
19304
19413
  * - `listPasskeys({userId})` — enumerate user's enrolled credentials.
19305
19414
  * - `removePasskey({userId, credentialId})` — revoke one credential.
19306
19415
  *
19416
+ * 4. Second-factor preference (opt-in, default OFF):
19417
+ * Enrolling a passkey only enables passkey-FIRST sign-in. It is
19418
+ * demanded as a second factor after a password login ONLY when the
19419
+ * user explicitly opts in via `setSecondFactorPreference`.
19420
+ * - `getSecondFactorPreference({userId})` → `{ enabled }` (missing
19421
+ * row ⇒ `enabled: false`).
19422
+ * - `setSecondFactorPreference({userId, enabled})` — persisted by
19423
+ * the providing addon beside its credentials.
19424
+ *
19307
19425
  * Challenges are short-lived (5 min, in-memory). The cap is internal —
19308
19426
  * the admin-ui composes the begin/finish round-trip and never exposes
19309
19427
  * the cap to non-admins.
@@ -19346,6 +19464,17 @@ method(object({
19346
19464
  }), object({ verified: boolean() }), {
19347
19465
  kind: "mutation",
19348
19466
  access: "view"
19467
+ }), method(object({}), object({ optionsJSON: record(string(), unknown()) }), {
19468
+ kind: "mutation",
19469
+ access: "view"
19470
+ }), method(object({
19471
+ /** AuthenticationResponseJSON from the browser. */
19472
+ response: record(string(), unknown()) }), object({
19473
+ verified: boolean(),
19474
+ userId: string().nullable()
19475
+ }), {
19476
+ kind: "mutation",
19477
+ access: "view"
19349
19478
  }), method(object({ userId: string() }), array(PasskeySummarySchema), { auth: "admin" }), method(object({
19350
19479
  userId: string(),
19351
19480
  credentialId: string()
@@ -19353,6 +19482,13 @@ method(object({
19353
19482
  kind: "mutation",
19354
19483
  auth: "admin",
19355
19484
  access: "delete"
19485
+ }), method(object({ userId: string() }), object({ enabled: boolean() }), { auth: "admin" }), method(object({
19486
+ userId: string(),
19487
+ enabled: boolean()
19488
+ }), object({ success: literal(true) }), {
19489
+ kind: "mutation",
19490
+ auth: "admin",
19491
+ access: "create"
19356
19492
  });
19357
19493
  /**
19358
19494
  * `videoclips` — the unified, navigable-clip surface for a camera.
@@ -20154,7 +20290,17 @@ var FaceInfoSchema = object({
20154
20290
  recognizedIdentityId: string().optional(),
20155
20291
  identityName: string().optional(),
20156
20292
  assigned: boolean(),
20157
- base64: string().optional()
20293
+ base64: string().optional(),
20294
+ /** Design B: the face bbox (pixel space) on the key frame — lets a detail
20295
+ * view draw the box over the native `keyFrameMediaKey` frame. Absent on
20296
+ * legacy rows written before design B. */
20297
+ faceBbox: BoundingBoxSchema.optional(),
20298
+ /** Design B: MediaStore key of the track's native-resolution key frame.
20299
+ * Fetch the native JPEG via the event-media data-plane
20300
+ * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`). Absent when the
20301
+ * track produced no key frame (e.g. native/onboard source) — the UI falls
20302
+ * back to the inline `base64` face crop. */
20303
+ keyFrameMediaKey: string().optional()
20158
20304
  });
20159
20305
  var FaceFilterEnum = _enum([
20160
20306
  "unassigned",
@@ -24572,6 +24718,12 @@ Object.freeze({
24572
24718
  addonId: null,
24573
24719
  access: "view"
24574
24720
  },
24721
+ "pipelineAnalytics.getKeyEvents": {
24722
+ capName: "pipeline-analytics",
24723
+ capScope: "device",
24724
+ addonId: null,
24725
+ access: "view"
24726
+ },
24575
24727
  "pipelineAnalytics.getMotionEvents": {
24576
24728
  capName: "pipeline-analytics",
24577
24729
  capScope: "device",
@@ -25100,6 +25252,12 @@ Object.freeze({
25100
25252
  addonId: null,
25101
25253
  access: "view"
25102
25254
  },
25255
+ "pipelineRunner.getNativeCrop": {
25256
+ capName: "pipeline-runner",
25257
+ capScope: "system",
25258
+ addonId: null,
25259
+ access: "view"
25260
+ },
25103
25261
  "pipelineRunner.reportMotion": {
25104
25262
  capName: "pipeline-runner",
25105
25263
  capScope: "system",
@@ -25466,6 +25624,12 @@ Object.freeze({
25466
25624
  addonId: null,
25467
25625
  access: "view"
25468
25626
  },
25627
+ "snapshot.getSnapshotOverview": {
25628
+ capName: "snapshot",
25629
+ capScope: "device",
25630
+ addonId: null,
25631
+ access: "view"
25632
+ },
25469
25633
  "snapshot.invalidateCache": {
25470
25634
  capName: "snapshot",
25471
25635
  capScope: "device",
@@ -26144,6 +26308,12 @@ Object.freeze({
26144
26308
  addonId: null,
26145
26309
  access: "view"
26146
26310
  },
26311
+ "userPasskeys.beginDiscoverableAuthentication": {
26312
+ capName: "user-passkeys",
26313
+ capScope: "system",
26314
+ addonId: null,
26315
+ access: "view"
26316
+ },
26147
26317
  "userPasskeys.beginRegistration": {
26148
26318
  capName: "user-passkeys",
26149
26319
  capScope: "system",
@@ -26156,12 +26326,24 @@ Object.freeze({
26156
26326
  addonId: null,
26157
26327
  access: "view"
26158
26328
  },
26329
+ "userPasskeys.finishDiscoverableAuthentication": {
26330
+ capName: "user-passkeys",
26331
+ capScope: "system",
26332
+ addonId: null,
26333
+ access: "view"
26334
+ },
26159
26335
  "userPasskeys.finishRegistration": {
26160
26336
  capName: "user-passkeys",
26161
26337
  capScope: "system",
26162
26338
  addonId: null,
26163
26339
  access: "create"
26164
26340
  },
26341
+ "userPasskeys.getSecondFactorPreference": {
26342
+ capName: "user-passkeys",
26343
+ capScope: "system",
26344
+ addonId: null,
26345
+ access: "view"
26346
+ },
26165
26347
  "userPasskeys.listPasskeys": {
26166
26348
  capName: "user-passkeys",
26167
26349
  capScope: "system",
@@ -26174,6 +26356,12 @@ Object.freeze({
26174
26356
  addonId: null,
26175
26357
  access: "delete"
26176
26358
  },
26359
+ "userPasskeys.setSecondFactorPreference": {
26360
+ capName: "user-passkeys",
26361
+ capScope: "system",
26362
+ addonId: null,
26363
+ access: "create"
26364
+ },
26177
26365
  "vacuumControl.locate": {
26178
26366
  capName: "vacuum-control",
26179
26367
  capScope: "device",
package/dist/addon.mjs CHANGED
@@ -4634,7 +4634,7 @@ function _instanceof(cls, params = {}) {
4634
4634
  return inst;
4635
4635
  }
4636
4636
  //#endregion
4637
- //#region ../types/dist/sleep-DJaTV2D7.mjs
4637
+ //#region ../types/dist/sleep-BC9Yqte7.mjs
4638
4638
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4639
4639
  EventCategory["SystemBoot"] = "system.boot";
4640
4640
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -6738,6 +6738,18 @@ function method(input, output, options) {
6738
6738
  timeoutMs: options?.timeoutMs
6739
6739
  };
6740
6740
  }
6741
+ /**
6742
+ * A wrapper/system-only method: served exclusively by the cap's system-level
6743
+ * provider (`InferProvider`), and OPTIONAL on `InferNativeProvider` so per-device
6744
+ * driver natives don't stub out a wrapper concern (e.g. a cross-device cache
6745
+ * overview). The `systemOnly: true` literal is what `InferNativeProvider` keys on.
6746
+ */
6747
+ function systemMethod(input, output, options) {
6748
+ return {
6749
+ ...method(input, output, options),
6750
+ systemOnly: true
6751
+ };
6752
+ }
6741
6753
  /** Shorthand to define an event schema */
6742
6754
  function event(data) {
6743
6755
  return { data };
@@ -11831,6 +11843,7 @@ var PipelineAddonSchemaSchema = object({
11831
11843
  defaultModelId: string(),
11832
11844
  defaultModelIdByFormat: record(string(), string()).optional(),
11833
11845
  enabledByDefault: boolean().optional(),
11846
+ backfillIntoExistingOverrides: boolean().optional(),
11834
11847
  defaultConfidence: number(),
11835
11848
  group: string().optional(),
11836
11849
  configSchema: array(ConfigFieldBridge).readonly().optional()
@@ -12170,6 +12183,25 @@ var zonesCapability = {
12170
12183
  runtimeState: object({ zones: array(ZoneSchema).readonly() })
12171
12184
  };
12172
12185
  /**
12186
+ * A bounding box in NORMALIZED [0,1] frame coordinates for `getNativeCrop`. The
12187
+ * decode worker resolves it against the RETAINED native frame's real pixel dims,
12188
+ * so the caller supplies only the detection-res bbox divided by the detection
12189
+ * dims — no native resolution to plumb.
12190
+ */
12191
+ var NativeCropBboxSchema = object({
12192
+ x: number(),
12193
+ y: number(),
12194
+ w: number(),
12195
+ h: number()
12196
+ });
12197
+ /** Result of a best-effort native-resolution crop (`getNativeCrop`). */
12198
+ var NativeCropResultSchema = object({
12199
+ /** Packed rgb (24-bit) pixels of the crop. */
12200
+ bytes: _instanceof(Uint8Array),
12201
+ width: number().int().positive(),
12202
+ height: number().int().positive()
12203
+ });
12204
+ /**
12173
12205
  * Per-camera tunable ranges + defaults. Single source of truth used
12174
12206
  * by both the Zod data schema (validation + default fallback) and
12175
12207
  * the device settings UI (slider min/max/step). Touch one place and
@@ -12425,7 +12457,11 @@ var RunnerLocalMetricsSchema = object({
12425
12457
  avgInferenceTimeMs: number(),
12426
12458
  queueDepth: number()
12427
12459
  });
12428
- method(RunnerCameraConfigSchema, object({ success: literal(true) }), { kind: "mutation" }), method(object({ deviceId: number() }), object({ success: literal(true) }), { kind: "mutation" }), method(ReportMotionInputSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), RunnerLocalLoadSchema), method(_void(), RunnerLocalMetricsSchema), method(object({ deviceId: number() }), CameraMetricsSchema.nullable()), method(_void(), array(CameraMetricsWithDeviceIdSchema).readonly()), method(_void(), array(number()).readonly());
12460
+ method(RunnerCameraConfigSchema, object({ success: literal(true) }), { kind: "mutation" }), method(object({ deviceId: number() }), object({ success: literal(true) }), { kind: "mutation" }), method(ReportMotionInputSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), RunnerLocalLoadSchema), method(_void(), RunnerLocalMetricsSchema), method(object({ deviceId: number() }), CameraMetricsSchema.nullable()), method(_void(), array(CameraMetricsWithDeviceIdSchema).readonly()), method(_void(), array(number()).readonly()), method(object({
12461
+ handle: FrameHandleSchema,
12462
+ bbox: NativeCropBboxSchema,
12463
+ maxWidth: number().int().positive().optional()
12464
+ }), NativeCropResultSchema.nullable());
12429
12465
  /**
12430
12466
  * Hardware / firmware motion sensor cap — binary detected state plus
12431
12467
  * a timestamp of the last observation. Distinct from
@@ -18100,7 +18136,17 @@ var TrackSchema = object({
18100
18136
  /** Cumulative normalized distance travelled (0..1 units = full frame width). */
18101
18137
  totalDistance: number(),
18102
18138
  state: TrackStateSchema,
18103
- active: boolean()
18139
+ active: boolean(),
18140
+ /** Deterministic key-event importance score in [0,1] (server-computed at
18141
+ * track expiry, recomputed on late label). Absent on legacy rows written
18142
+ * before scoring shipped — consumers degrade to absence / compute-on-read. */
18143
+ importance: number().optional(),
18144
+ /** Id of the track's highest-confidence ObjectEvent (its representative
18145
+ * "best" frame). Absent when the track produced no object events. */
18146
+ bestEventId: string().optional(),
18147
+ /** Tag of the importance sub-signal that dominated the score
18148
+ * (identity|dwell|proximity|class|confidence|travel|zone). */
18149
+ importanceReason: string().optional()
18104
18150
  });
18105
18151
  var BaseEventFields = {
18106
18152
  id: string(),
@@ -18165,8 +18211,18 @@ var ObjectEventSchema = object({
18165
18211
  frameHeight: number().optional(),
18166
18212
  /** MediaStore key for the crop attached to this event (if any). */
18167
18213
  mediaKey: string().optional(),
18214
+ /** Design B: MediaStore key of the track's native-resolution key frame (the
18215
+ * best-detection full frame). Resolve via the event-media data-plane
18216
+ * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`) for a detail view that
18217
+ * draws `bbox` over the native frame. Absent on legacy rows / non-decoded
18218
+ * sources — consumers fall back to `mediaKey` (the tight crop). */
18219
+ keyFrameMediaKey: string().optional(),
18168
18220
  /** Populated by B5 (recording playback URL for this event). */
18169
- mediaUrl: string().optional()
18221
+ mediaUrl: string().optional(),
18222
+ /** The parent track's key-event importance [0,1], propagated to every object
18223
+ * event of the track (so an event row can be sorted by importance without a
18224
+ * track join). Absent on legacy rows / before the track was scored. */
18225
+ importance: number().optional()
18170
18226
  });
18171
18227
  var AudioEventSchema = object({
18172
18228
  ...BaseEventFields,
@@ -18190,7 +18246,8 @@ var MediaFileKindEnum = _enum([
18190
18246
  "fullFrame",
18191
18247
  "fullFrameBoxed",
18192
18248
  "faceCrop",
18193
- "plateCrop"
18249
+ "plateCrop",
18250
+ "keyFrame"
18194
18251
  ]);
18195
18252
  var MediaFileSchema = object({
18196
18253
  key: string(),
@@ -18211,6 +18268,32 @@ var DeviceEventQueryInput = object({
18211
18268
  projection: _enum(["full", "slim"]).optional()
18212
18269
  });
18213
18270
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
18271
+ var KeyEventQueryInput = object({
18272
+ deviceId: number(),
18273
+ /** Window lower bound (track firstSeen ≥ since). */
18274
+ since: number(),
18275
+ /** Window upper bound (track firstSeen ≤ until). */
18276
+ until: number(),
18277
+ limit: number().int().min(1).max(200).default(50),
18278
+ /** Drop tracks scoring below this importance. */
18279
+ minImportance: number().min(0).max(1).optional(),
18280
+ /** Restrict to a single class (e.g. 'person'). */
18281
+ classFilter: string().optional()
18282
+ });
18283
+ var KeyEventSchema = object({
18284
+ /** The representative event id (the track's best ObjectEvent, else its trackId). */
18285
+ id: string(),
18286
+ trackId: string(),
18287
+ /** Track start time (firstSeen). */
18288
+ timestamp: number(),
18289
+ className: string(),
18290
+ label: string().optional(),
18291
+ importance: number(),
18292
+ /** Highest-confidence ObjectEvent id for the track (empty when none). */
18293
+ bestEventId: string(),
18294
+ /** Track lifetime in ms (lastSeen - firstSeen). */
18295
+ windowMs: number().optional()
18296
+ });
18214
18297
  var TrackedDetectionSchema = object({
18215
18298
  trackId: string(),
18216
18299
  className: string(),
@@ -18240,7 +18323,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
18240
18323
  }), array(TrackSchema).readonly()), method(object({ deviceId: number() }), _void(), {
18241
18324
  kind: "mutation",
18242
18325
  auth: "admin"
18243
- }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({
18326
+ }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
18244
18327
  deviceId: number(),
18245
18328
  since: number(),
18246
18329
  until: number(),
@@ -19044,7 +19127,20 @@ var snapshotCapability = {
19044
19127
  invalidateCache: method(object({ deviceId: number() }), _void(), {
19045
19128
  kind: "mutation",
19046
19129
  auth: "admin"
19047
- })
19130
+ }),
19131
+ /**
19132
+ * Cache-only batch overview — answers from the wrapper's in-memory cache in
19133
+ * O(n) and NEVER triggers a capture. Lets a grid skip requesting images for
19134
+ * devices that never produced a frame, and gives it an ETag per device for
19135
+ * conditional (304-able) image fetches. `lastCapturedAt`/`cacheAgeMs`/`etag`
19136
+ * are null for a device with no cached frame.
19137
+ */
19138
+ getSnapshotOverview: systemMethod(object({ deviceIds: array(number()).min(1).max(200) }), array(object({
19139
+ deviceId: number(),
19140
+ lastCapturedAt: number().nullable(),
19141
+ cacheAgeMs: number().nullable(),
19142
+ etag: string().nullable()
19143
+ })))
19048
19144
  },
19049
19145
  status: {
19050
19146
  schema: SnapshotStatusSchema,
@@ -19301,10 +19397,32 @@ method(_void(), array(TurnServerSchema).readonly());
19301
19397
  * b. `finishAuthentication({userId, response})` → server verifies
19302
19398
  * the assertion, bumps the credential counter, returns ok.
19303
19399
  *
19400
+ * 2b. Usernameless (discoverable-credential) authentication — the
19401
+ * passkey IS the primary factor, no password leg:
19402
+ * a. `beginDiscoverableAuthentication({})` → assertion options with
19403
+ * EMPTY `allowCredentials` (the browser offers every resident
19404
+ * passkey it holds for this RP) + `userVerification: 'required'`
19405
+ * (the passkey replaces both factors, so UV is mandatory).
19406
+ * The challenge is stored server-side, NOT bound to any user.
19407
+ * b. `finishDiscoverableAuthentication({response})` → the provider
19408
+ * resolves the credential by the response's credential id,
19409
+ * verifies the assertion against the stored challenge + that
19410
+ * credential's public key/counter, and returns the OWNING
19411
+ * `userId` — the caller (core auth router) mints the session.
19412
+ *
19304
19413
  * 3. Management:
19305
19414
  * - `listPasskeys({userId})` — enumerate user's enrolled credentials.
19306
19415
  * - `removePasskey({userId, credentialId})` — revoke one credential.
19307
19416
  *
19417
+ * 4. Second-factor preference (opt-in, default OFF):
19418
+ * Enrolling a passkey only enables passkey-FIRST sign-in. It is
19419
+ * demanded as a second factor after a password login ONLY when the
19420
+ * user explicitly opts in via `setSecondFactorPreference`.
19421
+ * - `getSecondFactorPreference({userId})` → `{ enabled }` (missing
19422
+ * row ⇒ `enabled: false`).
19423
+ * - `setSecondFactorPreference({userId, enabled})` — persisted by
19424
+ * the providing addon beside its credentials.
19425
+ *
19308
19426
  * Challenges are short-lived (5 min, in-memory). The cap is internal —
19309
19427
  * the admin-ui composes the begin/finish round-trip and never exposes
19310
19428
  * the cap to non-admins.
@@ -19347,6 +19465,17 @@ method(object({
19347
19465
  }), object({ verified: boolean() }), {
19348
19466
  kind: "mutation",
19349
19467
  access: "view"
19468
+ }), method(object({}), object({ optionsJSON: record(string(), unknown()) }), {
19469
+ kind: "mutation",
19470
+ access: "view"
19471
+ }), method(object({
19472
+ /** AuthenticationResponseJSON from the browser. */
19473
+ response: record(string(), unknown()) }), object({
19474
+ verified: boolean(),
19475
+ userId: string().nullable()
19476
+ }), {
19477
+ kind: "mutation",
19478
+ access: "view"
19350
19479
  }), method(object({ userId: string() }), array(PasskeySummarySchema), { auth: "admin" }), method(object({
19351
19480
  userId: string(),
19352
19481
  credentialId: string()
@@ -19354,6 +19483,13 @@ method(object({
19354
19483
  kind: "mutation",
19355
19484
  auth: "admin",
19356
19485
  access: "delete"
19486
+ }), method(object({ userId: string() }), object({ enabled: boolean() }), { auth: "admin" }), method(object({
19487
+ userId: string(),
19488
+ enabled: boolean()
19489
+ }), object({ success: literal(true) }), {
19490
+ kind: "mutation",
19491
+ auth: "admin",
19492
+ access: "create"
19357
19493
  });
19358
19494
  /**
19359
19495
  * `videoclips` — the unified, navigable-clip surface for a camera.
@@ -20155,7 +20291,17 @@ var FaceInfoSchema = object({
20155
20291
  recognizedIdentityId: string().optional(),
20156
20292
  identityName: string().optional(),
20157
20293
  assigned: boolean(),
20158
- base64: string().optional()
20294
+ base64: string().optional(),
20295
+ /** Design B: the face bbox (pixel space) on the key frame — lets a detail
20296
+ * view draw the box over the native `keyFrameMediaKey` frame. Absent on
20297
+ * legacy rows written before design B. */
20298
+ faceBbox: BoundingBoxSchema.optional(),
20299
+ /** Design B: MediaStore key of the track's native-resolution key frame.
20300
+ * Fetch the native JPEG via the event-media data-plane
20301
+ * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`). Absent when the
20302
+ * track produced no key frame (e.g. native/onboard source) — the UI falls
20303
+ * back to the inline `base64` face crop. */
20304
+ keyFrameMediaKey: string().optional()
20159
20305
  });
20160
20306
  var FaceFilterEnum = _enum([
20161
20307
  "unassigned",
@@ -24573,6 +24719,12 @@ Object.freeze({
24573
24719
  addonId: null,
24574
24720
  access: "view"
24575
24721
  },
24722
+ "pipelineAnalytics.getKeyEvents": {
24723
+ capName: "pipeline-analytics",
24724
+ capScope: "device",
24725
+ addonId: null,
24726
+ access: "view"
24727
+ },
24576
24728
  "pipelineAnalytics.getMotionEvents": {
24577
24729
  capName: "pipeline-analytics",
24578
24730
  capScope: "device",
@@ -25101,6 +25253,12 @@ Object.freeze({
25101
25253
  addonId: null,
25102
25254
  access: "view"
25103
25255
  },
25256
+ "pipelineRunner.getNativeCrop": {
25257
+ capName: "pipeline-runner",
25258
+ capScope: "system",
25259
+ addonId: null,
25260
+ access: "view"
25261
+ },
25104
25262
  "pipelineRunner.reportMotion": {
25105
25263
  capName: "pipeline-runner",
25106
25264
  capScope: "system",
@@ -25467,6 +25625,12 @@ Object.freeze({
25467
25625
  addonId: null,
25468
25626
  access: "view"
25469
25627
  },
25628
+ "snapshot.getSnapshotOverview": {
25629
+ capName: "snapshot",
25630
+ capScope: "device",
25631
+ addonId: null,
25632
+ access: "view"
25633
+ },
25470
25634
  "snapshot.invalidateCache": {
25471
25635
  capName: "snapshot",
25472
25636
  capScope: "device",
@@ -26145,6 +26309,12 @@ Object.freeze({
26145
26309
  addonId: null,
26146
26310
  access: "view"
26147
26311
  },
26312
+ "userPasskeys.beginDiscoverableAuthentication": {
26313
+ capName: "user-passkeys",
26314
+ capScope: "system",
26315
+ addonId: null,
26316
+ access: "view"
26317
+ },
26148
26318
  "userPasskeys.beginRegistration": {
26149
26319
  capName: "user-passkeys",
26150
26320
  capScope: "system",
@@ -26157,12 +26327,24 @@ Object.freeze({
26157
26327
  addonId: null,
26158
26328
  access: "view"
26159
26329
  },
26330
+ "userPasskeys.finishDiscoverableAuthentication": {
26331
+ capName: "user-passkeys",
26332
+ capScope: "system",
26333
+ addonId: null,
26334
+ access: "view"
26335
+ },
26160
26336
  "userPasskeys.finishRegistration": {
26161
26337
  capName: "user-passkeys",
26162
26338
  capScope: "system",
26163
26339
  addonId: null,
26164
26340
  access: "create"
26165
26341
  },
26342
+ "userPasskeys.getSecondFactorPreference": {
26343
+ capName: "user-passkeys",
26344
+ capScope: "system",
26345
+ addonId: null,
26346
+ access: "view"
26347
+ },
26166
26348
  "userPasskeys.listPasskeys": {
26167
26349
  capName: "user-passkeys",
26168
26350
  capScope: "system",
@@ -26175,6 +26357,12 @@ Object.freeze({
26175
26357
  addonId: null,
26176
26358
  access: "delete"
26177
26359
  },
26360
+ "userPasskeys.setSecondFactorPreference": {
26361
+ capName: "user-passkeys",
26362
+ capScope: "system",
26363
+ addonId: null,
26364
+ access: "create"
26365
+ },
26178
26366
  "vacuumControl.locate": {
26179
26367
  capName: "vacuum-control",
26180
26368
  capScope: "device",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-amcrest",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Amcrest/Dahua camera device provider addon for CamStack — Dahua CGI over HTTP(S) with digest auth (snapshot, RTSP catalog, PTZ, image/day-night config)",
5
5
  "keywords": [
6
6
  "camstack",