@camstack/addon-export-hap 1.1.20 → 1.1.21

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.
@@ -4664,7 +4664,7 @@ function _instanceof(cls, params = {}) {
4664
4664
  return inst;
4665
4665
  }
4666
4666
  //#endregion
4667
- //#region ../types/dist/sleep-DJaTV2D7.mjs
4667
+ //#region ../types/dist/sleep-BC9Yqte7.mjs
4668
4668
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4669
4669
  EventCategory["SystemBoot"] = "system.boot";
4670
4670
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -6768,6 +6768,18 @@ function method(input, output, options) {
6768
6768
  timeoutMs: options?.timeoutMs
6769
6769
  };
6770
6770
  }
6771
+ /**
6772
+ * A wrapper/system-only method: served exclusively by the cap's system-level
6773
+ * provider (`InferProvider`), and OPTIONAL on `InferNativeProvider` so per-device
6774
+ * driver natives don't stub out a wrapper concern (e.g. a cross-device cache
6775
+ * overview). The `systemOnly: true` literal is what `InferNativeProvider` keys on.
6776
+ */
6777
+ function systemMethod(input, output, options) {
6778
+ return {
6779
+ ...method(input, output, options),
6780
+ systemOnly: true
6781
+ };
6782
+ }
6771
6783
  var StaticDirOutputSchema$1 = object({ staticDir: string() });
6772
6784
  var VersionOutputSchema$1 = object({ version: string() });
6773
6785
  method(_void(), StaticDirOutputSchema$1), method(_void(), VersionOutputSchema$1);
@@ -10560,6 +10572,7 @@ var PipelineAddonSchemaSchema = object({
10560
10572
  defaultModelId: string(),
10561
10573
  defaultModelIdByFormat: record(string(), string()).optional(),
10562
10574
  enabledByDefault: boolean().optional(),
10575
+ backfillIntoExistingOverrides: boolean().optional(),
10563
10576
  defaultConfidence: number(),
10564
10577
  group: string().optional(),
10565
10578
  configSchema: array(ConfigFieldBridge).readonly().optional()
@@ -10866,6 +10879,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(ZoneSchema).read
10866
10879
  auth: "admin"
10867
10880
  }), object({ zones: array(ZoneSchema).readonly() });
10868
10881
  /**
10882
+ * A bounding box in NORMALIZED [0,1] frame coordinates for `getNativeCrop`. The
10883
+ * decode worker resolves it against the RETAINED native frame's real pixel dims,
10884
+ * so the caller supplies only the detection-res bbox divided by the detection
10885
+ * dims — no native resolution to plumb.
10886
+ */
10887
+ var NativeCropBboxSchema = object({
10888
+ x: number(),
10889
+ y: number(),
10890
+ w: number(),
10891
+ h: number()
10892
+ });
10893
+ /** Result of a best-effort native-resolution crop (`getNativeCrop`). */
10894
+ var NativeCropResultSchema = object({
10895
+ /** Packed rgb (24-bit) pixels of the crop. */
10896
+ bytes: _instanceof(Uint8Array),
10897
+ width: number().int().positive(),
10898
+ height: number().int().positive()
10899
+ });
10900
+ /**
10869
10901
  * Per-camera tunable ranges + defaults. Single source of truth used
10870
10902
  * by both the Zod data schema (validation + default fallback) and
10871
10903
  * the device settings UI (slider min/max/step). Touch one place and
@@ -11121,7 +11153,11 @@ var RunnerLocalMetricsSchema = object({
11121
11153
  avgInferenceTimeMs: number(),
11122
11154
  queueDepth: number()
11123
11155
  });
11124
- 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());
11156
+ 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({
11157
+ handle: FrameHandleSchema,
11158
+ bbox: NativeCropBboxSchema,
11159
+ maxWidth: number().int().positive().optional()
11160
+ }), NativeCropResultSchema.nullable());
11125
11161
  object({
11126
11162
  detected: boolean(),
11127
11163
  /** Ms epoch of the last detected-true observation. Null if never detected. */
@@ -15184,7 +15220,17 @@ var TrackSchema = object({
15184
15220
  /** Cumulative normalized distance travelled (0..1 units = full frame width). */
15185
15221
  totalDistance: number(),
15186
15222
  state: TrackStateSchema,
15187
- active: boolean()
15223
+ active: boolean(),
15224
+ /** Deterministic key-event importance score in [0,1] (server-computed at
15225
+ * track expiry, recomputed on late label). Absent on legacy rows written
15226
+ * before scoring shipped — consumers degrade to absence / compute-on-read. */
15227
+ importance: number().optional(),
15228
+ /** Id of the track's highest-confidence ObjectEvent (its representative
15229
+ * "best" frame). Absent when the track produced no object events. */
15230
+ bestEventId: string().optional(),
15231
+ /** Tag of the importance sub-signal that dominated the score
15232
+ * (identity|dwell|proximity|class|confidence|travel|zone). */
15233
+ importanceReason: string().optional()
15188
15234
  });
15189
15235
  var BaseEventFields = {
15190
15236
  id: string(),
@@ -15249,8 +15295,18 @@ var ObjectEventSchema = object({
15249
15295
  frameHeight: number().optional(),
15250
15296
  /** MediaStore key for the crop attached to this event (if any). */
15251
15297
  mediaKey: string().optional(),
15298
+ /** Design B: MediaStore key of the track's native-resolution key frame (the
15299
+ * best-detection full frame). Resolve via the event-media data-plane
15300
+ * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`) for a detail view that
15301
+ * draws `bbox` over the native frame. Absent on legacy rows / non-decoded
15302
+ * sources — consumers fall back to `mediaKey` (the tight crop). */
15303
+ keyFrameMediaKey: string().optional(),
15252
15304
  /** Populated by B5 (recording playback URL for this event). */
15253
- mediaUrl: string().optional()
15305
+ mediaUrl: string().optional(),
15306
+ /** The parent track's key-event importance [0,1], propagated to every object
15307
+ * event of the track (so an event row can be sorted by importance without a
15308
+ * track join). Absent on legacy rows / before the track was scored. */
15309
+ importance: number().optional()
15254
15310
  });
15255
15311
  var AudioEventSchema = object({
15256
15312
  ...BaseEventFields,
@@ -15274,7 +15330,8 @@ var MediaFileKindEnum = _enum([
15274
15330
  "fullFrame",
15275
15331
  "fullFrameBoxed",
15276
15332
  "faceCrop",
15277
- "plateCrop"
15333
+ "plateCrop",
15334
+ "keyFrame"
15278
15335
  ]);
15279
15336
  var MediaFileSchema = object({
15280
15337
  key: string(),
@@ -15295,6 +15352,32 @@ var DeviceEventQueryInput = object({
15295
15352
  projection: _enum(["full", "slim"]).optional()
15296
15353
  });
15297
15354
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
15355
+ var KeyEventQueryInput = object({
15356
+ deviceId: number(),
15357
+ /** Window lower bound (track firstSeen ≥ since). */
15358
+ since: number(),
15359
+ /** Window upper bound (track firstSeen ≤ until). */
15360
+ until: number(),
15361
+ limit: number().int().min(1).max(200).default(50),
15362
+ /** Drop tracks scoring below this importance. */
15363
+ minImportance: number().min(0).max(1).optional(),
15364
+ /** Restrict to a single class (e.g. 'person'). */
15365
+ classFilter: string().optional()
15366
+ });
15367
+ var KeyEventSchema = object({
15368
+ /** The representative event id (the track's best ObjectEvent, else its trackId). */
15369
+ id: string(),
15370
+ trackId: string(),
15371
+ /** Track start time (firstSeen). */
15372
+ timestamp: number(),
15373
+ className: string(),
15374
+ label: string().optional(),
15375
+ importance: number(),
15376
+ /** Highest-confidence ObjectEvent id for the track (empty when none). */
15377
+ bestEventId: string(),
15378
+ /** Track lifetime in ms (lastSeen - firstSeen). */
15379
+ windowMs: number().optional()
15380
+ });
15298
15381
  var TrackedDetectionSchema = object({
15299
15382
  trackId: string(),
15300
15383
  className: string(),
@@ -15324,7 +15407,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
15324
15407
  }), array(TrackSchema).readonly()), method(object({ deviceId: number() }), _void(), {
15325
15408
  kind: "mutation",
15326
15409
  auth: "admin"
15327
- }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({
15410
+ }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
15328
15411
  deviceId: number(),
15329
15412
  since: number(),
15330
15413
  until: number(),
@@ -16091,7 +16174,12 @@ DeviceType.Camera, method(object({
16091
16174
  }), SnapshotImageSchema.nullable()), method(object({ deviceId: number() }), _void(), {
16092
16175
  kind: "mutation",
16093
16176
  auth: "admin"
16094
- });
16177
+ }), systemMethod(object({ deviceIds: array(number()).min(1).max(200) }), array(object({
16178
+ deviceId: number(),
16179
+ lastCapturedAt: number().nullable(),
16180
+ cacheAgeMs: number().nullable(),
16181
+ etag: string().nullable()
16182
+ })));
16095
16183
  /**
16096
16184
  * `sso-bridge` — internal hub-only cap that lets SSO-style auth
16097
16185
  * providers (OIDC, SAML, magic-link, …) mint an HMAC-signed token
@@ -16342,10 +16430,32 @@ method(_void(), array(TurnServerSchema).readonly());
16342
16430
  * b. `finishAuthentication({userId, response})` → server verifies
16343
16431
  * the assertion, bumps the credential counter, returns ok.
16344
16432
  *
16433
+ * 2b. Usernameless (discoverable-credential) authentication — the
16434
+ * passkey IS the primary factor, no password leg:
16435
+ * a. `beginDiscoverableAuthentication({})` → assertion options with
16436
+ * EMPTY `allowCredentials` (the browser offers every resident
16437
+ * passkey it holds for this RP) + `userVerification: 'required'`
16438
+ * (the passkey replaces both factors, so UV is mandatory).
16439
+ * The challenge is stored server-side, NOT bound to any user.
16440
+ * b. `finishDiscoverableAuthentication({response})` → the provider
16441
+ * resolves the credential by the response's credential id,
16442
+ * verifies the assertion against the stored challenge + that
16443
+ * credential's public key/counter, and returns the OWNING
16444
+ * `userId` — the caller (core auth router) mints the session.
16445
+ *
16345
16446
  * 3. Management:
16346
16447
  * - `listPasskeys({userId})` — enumerate user's enrolled credentials.
16347
16448
  * - `removePasskey({userId, credentialId})` — revoke one credential.
16348
16449
  *
16450
+ * 4. Second-factor preference (opt-in, default OFF):
16451
+ * Enrolling a passkey only enables passkey-FIRST sign-in. It is
16452
+ * demanded as a second factor after a password login ONLY when the
16453
+ * user explicitly opts in via `setSecondFactorPreference`.
16454
+ * - `getSecondFactorPreference({userId})` → `{ enabled }` (missing
16455
+ * row ⇒ `enabled: false`).
16456
+ * - `setSecondFactorPreference({userId, enabled})` — persisted by
16457
+ * the providing addon beside its credentials.
16458
+ *
16349
16459
  * Challenges are short-lived (5 min, in-memory). The cap is internal —
16350
16460
  * the admin-ui composes the begin/finish round-trip and never exposes
16351
16461
  * the cap to non-admins.
@@ -16388,6 +16498,17 @@ method(object({
16388
16498
  }), object({ verified: boolean() }), {
16389
16499
  kind: "mutation",
16390
16500
  access: "view"
16501
+ }), method(object({}), object({ optionsJSON: record(string(), unknown()) }), {
16502
+ kind: "mutation",
16503
+ access: "view"
16504
+ }), method(object({
16505
+ /** AuthenticationResponseJSON from the browser. */
16506
+ response: record(string(), unknown()) }), object({
16507
+ verified: boolean(),
16508
+ userId: string().nullable()
16509
+ }), {
16510
+ kind: "mutation",
16511
+ access: "view"
16391
16512
  }), method(object({ userId: string() }), array(PasskeySummarySchema), { auth: "admin" }), method(object({
16392
16513
  userId: string(),
16393
16514
  credentialId: string()
@@ -16395,6 +16516,13 @@ method(object({
16395
16516
  kind: "mutation",
16396
16517
  auth: "admin",
16397
16518
  access: "delete"
16519
+ }), method(object({ userId: string() }), object({ enabled: boolean() }), { auth: "admin" }), method(object({
16520
+ userId: string(),
16521
+ enabled: boolean()
16522
+ }), object({ success: literal(true) }), {
16523
+ kind: "mutation",
16524
+ auth: "admin",
16525
+ access: "create"
16398
16526
  });
16399
16527
  /**
16400
16528
  * `videoclips` — the unified, navigable-clip surface for a camera.
@@ -17196,7 +17324,17 @@ var FaceInfoSchema = object({
17196
17324
  recognizedIdentityId: string().optional(),
17197
17325
  identityName: string().optional(),
17198
17326
  assigned: boolean(),
17199
- base64: string().optional()
17327
+ base64: string().optional(),
17328
+ /** Design B: the face bbox (pixel space) on the key frame — lets a detail
17329
+ * view draw the box over the native `keyFrameMediaKey` frame. Absent on
17330
+ * legacy rows written before design B. */
17331
+ faceBbox: BoundingBoxSchema.optional(),
17332
+ /** Design B: MediaStore key of the track's native-resolution key frame.
17333
+ * Fetch the native JPEG via the event-media data-plane
17334
+ * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`). Absent when the
17335
+ * track produced no key frame (e.g. native/onboard source) — the UI falls
17336
+ * back to the inline `base64` face crop. */
17337
+ keyFrameMediaKey: string().optional()
17200
17338
  });
17201
17339
  var FaceFilterEnum = _enum([
17202
17340
  "unassigned",
@@ -21315,6 +21453,12 @@ Object.freeze({
21315
21453
  addonId: null,
21316
21454
  access: "view"
21317
21455
  },
21456
+ "pipelineAnalytics.getKeyEvents": {
21457
+ capName: "pipeline-analytics",
21458
+ capScope: "device",
21459
+ addonId: null,
21460
+ access: "view"
21461
+ },
21318
21462
  "pipelineAnalytics.getMotionEvents": {
21319
21463
  capName: "pipeline-analytics",
21320
21464
  capScope: "device",
@@ -21843,6 +21987,12 @@ Object.freeze({
21843
21987
  addonId: null,
21844
21988
  access: "view"
21845
21989
  },
21990
+ "pipelineRunner.getNativeCrop": {
21991
+ capName: "pipeline-runner",
21992
+ capScope: "system",
21993
+ addonId: null,
21994
+ access: "view"
21995
+ },
21846
21996
  "pipelineRunner.reportMotion": {
21847
21997
  capName: "pipeline-runner",
21848
21998
  capScope: "system",
@@ -22209,6 +22359,12 @@ Object.freeze({
22209
22359
  addonId: null,
22210
22360
  access: "view"
22211
22361
  },
22362
+ "snapshot.getSnapshotOverview": {
22363
+ capName: "snapshot",
22364
+ capScope: "device",
22365
+ addonId: null,
22366
+ access: "view"
22367
+ },
22212
22368
  "snapshot.invalidateCache": {
22213
22369
  capName: "snapshot",
22214
22370
  capScope: "device",
@@ -22887,6 +23043,12 @@ Object.freeze({
22887
23043
  addonId: null,
22888
23044
  access: "view"
22889
23045
  },
23046
+ "userPasskeys.beginDiscoverableAuthentication": {
23047
+ capName: "user-passkeys",
23048
+ capScope: "system",
23049
+ addonId: null,
23050
+ access: "view"
23051
+ },
22890
23052
  "userPasskeys.beginRegistration": {
22891
23053
  capName: "user-passkeys",
22892
23054
  capScope: "system",
@@ -22899,12 +23061,24 @@ Object.freeze({
22899
23061
  addonId: null,
22900
23062
  access: "view"
22901
23063
  },
23064
+ "userPasskeys.finishDiscoverableAuthentication": {
23065
+ capName: "user-passkeys",
23066
+ capScope: "system",
23067
+ addonId: null,
23068
+ access: "view"
23069
+ },
22902
23070
  "userPasskeys.finishRegistration": {
22903
23071
  capName: "user-passkeys",
22904
23072
  capScope: "system",
22905
23073
  addonId: null,
22906
23074
  access: "create"
22907
23075
  },
23076
+ "userPasskeys.getSecondFactorPreference": {
23077
+ capName: "user-passkeys",
23078
+ capScope: "system",
23079
+ addonId: null,
23080
+ access: "view"
23081
+ },
22908
23082
  "userPasskeys.listPasskeys": {
22909
23083
  capName: "user-passkeys",
22910
23084
  capScope: "system",
@@ -22917,6 +23091,12 @@ Object.freeze({
22917
23091
  addonId: null,
22918
23092
  access: "delete"
22919
23093
  },
23094
+ "userPasskeys.setSecondFactorPreference": {
23095
+ capName: "user-passkeys",
23096
+ capScope: "system",
23097
+ addonId: null,
23098
+ access: "create"
23099
+ },
22920
23100
  "vacuumControl.locate": {
22921
23101
  capName: "vacuum-control",
22922
23102
  capScope: "device",
@@ -4639,7 +4639,7 @@ function _instanceof(cls, params = {}) {
4639
4639
  return inst;
4640
4640
  }
4641
4641
  //#endregion
4642
- //#region ../types/dist/sleep-DJaTV2D7.mjs
4642
+ //#region ../types/dist/sleep-BC9Yqte7.mjs
4643
4643
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4644
4644
  EventCategory["SystemBoot"] = "system.boot";
4645
4645
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -6743,6 +6743,18 @@ function method(input, output, options) {
6743
6743
  timeoutMs: options?.timeoutMs
6744
6744
  };
6745
6745
  }
6746
+ /**
6747
+ * A wrapper/system-only method: served exclusively by the cap's system-level
6748
+ * provider (`InferProvider`), and OPTIONAL on `InferNativeProvider` so per-device
6749
+ * driver natives don't stub out a wrapper concern (e.g. a cross-device cache
6750
+ * overview). The `systemOnly: true` literal is what `InferNativeProvider` keys on.
6751
+ */
6752
+ function systemMethod(input, output, options) {
6753
+ return {
6754
+ ...method(input, output, options),
6755
+ systemOnly: true
6756
+ };
6757
+ }
6746
6758
  var StaticDirOutputSchema$1 = object({ staticDir: string() });
6747
6759
  var VersionOutputSchema$1 = object({ version: string() });
6748
6760
  method(_void(), StaticDirOutputSchema$1), method(_void(), VersionOutputSchema$1);
@@ -10535,6 +10547,7 @@ var PipelineAddonSchemaSchema = object({
10535
10547
  defaultModelId: string(),
10536
10548
  defaultModelIdByFormat: record(string(), string()).optional(),
10537
10549
  enabledByDefault: boolean().optional(),
10550
+ backfillIntoExistingOverrides: boolean().optional(),
10538
10551
  defaultConfidence: number(),
10539
10552
  group: string().optional(),
10540
10553
  configSchema: array(ConfigFieldBridge).readonly().optional()
@@ -10841,6 +10854,25 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(ZoneSchema).read
10841
10854
  auth: "admin"
10842
10855
  }), object({ zones: array(ZoneSchema).readonly() });
10843
10856
  /**
10857
+ * A bounding box in NORMALIZED [0,1] frame coordinates for `getNativeCrop`. The
10858
+ * decode worker resolves it against the RETAINED native frame's real pixel dims,
10859
+ * so the caller supplies only the detection-res bbox divided by the detection
10860
+ * dims — no native resolution to plumb.
10861
+ */
10862
+ var NativeCropBboxSchema = object({
10863
+ x: number(),
10864
+ y: number(),
10865
+ w: number(),
10866
+ h: number()
10867
+ });
10868
+ /** Result of a best-effort native-resolution crop (`getNativeCrop`). */
10869
+ var NativeCropResultSchema = object({
10870
+ /** Packed rgb (24-bit) pixels of the crop. */
10871
+ bytes: _instanceof(Uint8Array),
10872
+ width: number().int().positive(),
10873
+ height: number().int().positive()
10874
+ });
10875
+ /**
10844
10876
  * Per-camera tunable ranges + defaults. Single source of truth used
10845
10877
  * by both the Zod data schema (validation + default fallback) and
10846
10878
  * the device settings UI (slider min/max/step). Touch one place and
@@ -11096,7 +11128,11 @@ var RunnerLocalMetricsSchema = object({
11096
11128
  avgInferenceTimeMs: number(),
11097
11129
  queueDepth: number()
11098
11130
  });
11099
- 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());
11131
+ 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({
11132
+ handle: FrameHandleSchema,
11133
+ bbox: NativeCropBboxSchema,
11134
+ maxWidth: number().int().positive().optional()
11135
+ }), NativeCropResultSchema.nullable());
11100
11136
  object({
11101
11137
  detected: boolean(),
11102
11138
  /** Ms epoch of the last detected-true observation. Null if never detected. */
@@ -15159,7 +15195,17 @@ var TrackSchema = object({
15159
15195
  /** Cumulative normalized distance travelled (0..1 units = full frame width). */
15160
15196
  totalDistance: number(),
15161
15197
  state: TrackStateSchema,
15162
- active: boolean()
15198
+ active: boolean(),
15199
+ /** Deterministic key-event importance score in [0,1] (server-computed at
15200
+ * track expiry, recomputed on late label). Absent on legacy rows written
15201
+ * before scoring shipped — consumers degrade to absence / compute-on-read. */
15202
+ importance: number().optional(),
15203
+ /** Id of the track's highest-confidence ObjectEvent (its representative
15204
+ * "best" frame). Absent when the track produced no object events. */
15205
+ bestEventId: string().optional(),
15206
+ /** Tag of the importance sub-signal that dominated the score
15207
+ * (identity|dwell|proximity|class|confidence|travel|zone). */
15208
+ importanceReason: string().optional()
15163
15209
  });
15164
15210
  var BaseEventFields = {
15165
15211
  id: string(),
@@ -15224,8 +15270,18 @@ var ObjectEventSchema = object({
15224
15270
  frameHeight: number().optional(),
15225
15271
  /** MediaStore key for the crop attached to this event (if any). */
15226
15272
  mediaKey: string().optional(),
15273
+ /** Design B: MediaStore key of the track's native-resolution key frame (the
15274
+ * best-detection full frame). Resolve via the event-media data-plane
15275
+ * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`) for a detail view that
15276
+ * draws `bbox` over the native frame. Absent on legacy rows / non-decoded
15277
+ * sources — consumers fall back to `mediaKey` (the tight crop). */
15278
+ keyFrameMediaKey: string().optional(),
15227
15279
  /** Populated by B5 (recording playback URL for this event). */
15228
- mediaUrl: string().optional()
15280
+ mediaUrl: string().optional(),
15281
+ /** The parent track's key-event importance [0,1], propagated to every object
15282
+ * event of the track (so an event row can be sorted by importance without a
15283
+ * track join). Absent on legacy rows / before the track was scored. */
15284
+ importance: number().optional()
15229
15285
  });
15230
15286
  var AudioEventSchema = object({
15231
15287
  ...BaseEventFields,
@@ -15249,7 +15305,8 @@ var MediaFileKindEnum = _enum([
15249
15305
  "fullFrame",
15250
15306
  "fullFrameBoxed",
15251
15307
  "faceCrop",
15252
- "plateCrop"
15308
+ "plateCrop",
15309
+ "keyFrame"
15253
15310
  ]);
15254
15311
  var MediaFileSchema = object({
15255
15312
  key: string(),
@@ -15270,6 +15327,32 @@ var DeviceEventQueryInput = object({
15270
15327
  projection: _enum(["full", "slim"]).optional()
15271
15328
  });
15272
15329
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
15330
+ var KeyEventQueryInput = object({
15331
+ deviceId: number(),
15332
+ /** Window lower bound (track firstSeen ≥ since). */
15333
+ since: number(),
15334
+ /** Window upper bound (track firstSeen ≤ until). */
15335
+ until: number(),
15336
+ limit: number().int().min(1).max(200).default(50),
15337
+ /** Drop tracks scoring below this importance. */
15338
+ minImportance: number().min(0).max(1).optional(),
15339
+ /** Restrict to a single class (e.g. 'person'). */
15340
+ classFilter: string().optional()
15341
+ });
15342
+ var KeyEventSchema = object({
15343
+ /** The representative event id (the track's best ObjectEvent, else its trackId). */
15344
+ id: string(),
15345
+ trackId: string(),
15346
+ /** Track start time (firstSeen). */
15347
+ timestamp: number(),
15348
+ className: string(),
15349
+ label: string().optional(),
15350
+ importance: number(),
15351
+ /** Highest-confidence ObjectEvent id for the track (empty when none). */
15352
+ bestEventId: string(),
15353
+ /** Track lifetime in ms (lastSeen - firstSeen). */
15354
+ windowMs: number().optional()
15355
+ });
15273
15356
  var TrackedDetectionSchema = object({
15274
15357
  trackId: string(),
15275
15358
  className: string(),
@@ -15299,7 +15382,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
15299
15382
  }), array(TrackSchema).readonly()), method(object({ deviceId: number() }), _void(), {
15300
15383
  kind: "mutation",
15301
15384
  auth: "admin"
15302
- }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({
15385
+ }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
15303
15386
  deviceId: number(),
15304
15387
  since: number(),
15305
15388
  until: number(),
@@ -16066,7 +16149,12 @@ DeviceType.Camera, method(object({
16066
16149
  }), SnapshotImageSchema.nullable()), method(object({ deviceId: number() }), _void(), {
16067
16150
  kind: "mutation",
16068
16151
  auth: "admin"
16069
- });
16152
+ }), systemMethod(object({ deviceIds: array(number()).min(1).max(200) }), array(object({
16153
+ deviceId: number(),
16154
+ lastCapturedAt: number().nullable(),
16155
+ cacheAgeMs: number().nullable(),
16156
+ etag: string().nullable()
16157
+ })));
16070
16158
  /**
16071
16159
  * `sso-bridge` — internal hub-only cap that lets SSO-style auth
16072
16160
  * providers (OIDC, SAML, magic-link, …) mint an HMAC-signed token
@@ -16317,10 +16405,32 @@ method(_void(), array(TurnServerSchema).readonly());
16317
16405
  * b. `finishAuthentication({userId, response})` → server verifies
16318
16406
  * the assertion, bumps the credential counter, returns ok.
16319
16407
  *
16408
+ * 2b. Usernameless (discoverable-credential) authentication — the
16409
+ * passkey IS the primary factor, no password leg:
16410
+ * a. `beginDiscoverableAuthentication({})` → assertion options with
16411
+ * EMPTY `allowCredentials` (the browser offers every resident
16412
+ * passkey it holds for this RP) + `userVerification: 'required'`
16413
+ * (the passkey replaces both factors, so UV is mandatory).
16414
+ * The challenge is stored server-side, NOT bound to any user.
16415
+ * b. `finishDiscoverableAuthentication({response})` → the provider
16416
+ * resolves the credential by the response's credential id,
16417
+ * verifies the assertion against the stored challenge + that
16418
+ * credential's public key/counter, and returns the OWNING
16419
+ * `userId` — the caller (core auth router) mints the session.
16420
+ *
16320
16421
  * 3. Management:
16321
16422
  * - `listPasskeys({userId})` — enumerate user's enrolled credentials.
16322
16423
  * - `removePasskey({userId, credentialId})` — revoke one credential.
16323
16424
  *
16425
+ * 4. Second-factor preference (opt-in, default OFF):
16426
+ * Enrolling a passkey only enables passkey-FIRST sign-in. It is
16427
+ * demanded as a second factor after a password login ONLY when the
16428
+ * user explicitly opts in via `setSecondFactorPreference`.
16429
+ * - `getSecondFactorPreference({userId})` → `{ enabled }` (missing
16430
+ * row ⇒ `enabled: false`).
16431
+ * - `setSecondFactorPreference({userId, enabled})` — persisted by
16432
+ * the providing addon beside its credentials.
16433
+ *
16324
16434
  * Challenges are short-lived (5 min, in-memory). The cap is internal —
16325
16435
  * the admin-ui composes the begin/finish round-trip and never exposes
16326
16436
  * the cap to non-admins.
@@ -16363,6 +16473,17 @@ method(object({
16363
16473
  }), object({ verified: boolean() }), {
16364
16474
  kind: "mutation",
16365
16475
  access: "view"
16476
+ }), method(object({}), object({ optionsJSON: record(string(), unknown()) }), {
16477
+ kind: "mutation",
16478
+ access: "view"
16479
+ }), method(object({
16480
+ /** AuthenticationResponseJSON from the browser. */
16481
+ response: record(string(), unknown()) }), object({
16482
+ verified: boolean(),
16483
+ userId: string().nullable()
16484
+ }), {
16485
+ kind: "mutation",
16486
+ access: "view"
16366
16487
  }), method(object({ userId: string() }), array(PasskeySummarySchema), { auth: "admin" }), method(object({
16367
16488
  userId: string(),
16368
16489
  credentialId: string()
@@ -16370,6 +16491,13 @@ method(object({
16370
16491
  kind: "mutation",
16371
16492
  auth: "admin",
16372
16493
  access: "delete"
16494
+ }), method(object({ userId: string() }), object({ enabled: boolean() }), { auth: "admin" }), method(object({
16495
+ userId: string(),
16496
+ enabled: boolean()
16497
+ }), object({ success: literal(true) }), {
16498
+ kind: "mutation",
16499
+ auth: "admin",
16500
+ access: "create"
16373
16501
  });
16374
16502
  /**
16375
16503
  * `videoclips` — the unified, navigable-clip surface for a camera.
@@ -17171,7 +17299,17 @@ var FaceInfoSchema = object({
17171
17299
  recognizedIdentityId: string().optional(),
17172
17300
  identityName: string().optional(),
17173
17301
  assigned: boolean(),
17174
- base64: string().optional()
17302
+ base64: string().optional(),
17303
+ /** Design B: the face bbox (pixel space) on the key frame — lets a detail
17304
+ * view draw the box over the native `keyFrameMediaKey` frame. Absent on
17305
+ * legacy rows written before design B. */
17306
+ faceBbox: BoundingBoxSchema.optional(),
17307
+ /** Design B: MediaStore key of the track's native-resolution key frame.
17308
+ * Fetch the native JPEG via the event-media data-plane
17309
+ * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`). Absent when the
17310
+ * track produced no key frame (e.g. native/onboard source) — the UI falls
17311
+ * back to the inline `base64` face crop. */
17312
+ keyFrameMediaKey: string().optional()
17175
17313
  });
17176
17314
  var FaceFilterEnum = _enum([
17177
17315
  "unassigned",
@@ -21290,6 +21428,12 @@ Object.freeze({
21290
21428
  addonId: null,
21291
21429
  access: "view"
21292
21430
  },
21431
+ "pipelineAnalytics.getKeyEvents": {
21432
+ capName: "pipeline-analytics",
21433
+ capScope: "device",
21434
+ addonId: null,
21435
+ access: "view"
21436
+ },
21293
21437
  "pipelineAnalytics.getMotionEvents": {
21294
21438
  capName: "pipeline-analytics",
21295
21439
  capScope: "device",
@@ -21818,6 +21962,12 @@ Object.freeze({
21818
21962
  addonId: null,
21819
21963
  access: "view"
21820
21964
  },
21965
+ "pipelineRunner.getNativeCrop": {
21966
+ capName: "pipeline-runner",
21967
+ capScope: "system",
21968
+ addonId: null,
21969
+ access: "view"
21970
+ },
21821
21971
  "pipelineRunner.reportMotion": {
21822
21972
  capName: "pipeline-runner",
21823
21973
  capScope: "system",
@@ -22184,6 +22334,12 @@ Object.freeze({
22184
22334
  addonId: null,
22185
22335
  access: "view"
22186
22336
  },
22337
+ "snapshot.getSnapshotOverview": {
22338
+ capName: "snapshot",
22339
+ capScope: "device",
22340
+ addonId: null,
22341
+ access: "view"
22342
+ },
22187
22343
  "snapshot.invalidateCache": {
22188
22344
  capName: "snapshot",
22189
22345
  capScope: "device",
@@ -22862,6 +23018,12 @@ Object.freeze({
22862
23018
  addonId: null,
22863
23019
  access: "view"
22864
23020
  },
23021
+ "userPasskeys.beginDiscoverableAuthentication": {
23022
+ capName: "user-passkeys",
23023
+ capScope: "system",
23024
+ addonId: null,
23025
+ access: "view"
23026
+ },
22865
23027
  "userPasskeys.beginRegistration": {
22866
23028
  capName: "user-passkeys",
22867
23029
  capScope: "system",
@@ -22874,12 +23036,24 @@ Object.freeze({
22874
23036
  addonId: null,
22875
23037
  access: "view"
22876
23038
  },
23039
+ "userPasskeys.finishDiscoverableAuthentication": {
23040
+ capName: "user-passkeys",
23041
+ capScope: "system",
23042
+ addonId: null,
23043
+ access: "view"
23044
+ },
22877
23045
  "userPasskeys.finishRegistration": {
22878
23046
  capName: "user-passkeys",
22879
23047
  capScope: "system",
22880
23048
  addonId: null,
22881
23049
  access: "create"
22882
23050
  },
23051
+ "userPasskeys.getSecondFactorPreference": {
23052
+ capName: "user-passkeys",
23053
+ capScope: "system",
23054
+ addonId: null,
23055
+ access: "view"
23056
+ },
22883
23057
  "userPasskeys.listPasskeys": {
22884
23058
  capName: "user-passkeys",
22885
23059
  capScope: "system",
@@ -22892,6 +23066,12 @@ Object.freeze({
22892
23066
  addonId: null,
22893
23067
  access: "delete"
22894
23068
  },
23069
+ "userPasskeys.setSecondFactorPreference": {
23070
+ capName: "user-passkeys",
23071
+ capScope: "system",
23072
+ addonId: null,
23073
+ access: "create"
23074
+ },
22895
23075
  "vacuumControl.locate": {
22896
23076
  capName: "vacuum-control",
22897
23077
  capScope: "device",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-export-hap",
3
- "version": "1.1.20",
3
+ "version": "1.1.21",
4
4
  "description": "HomeKit (HAP) bridge exporter for CamStack devices. Publishes a bridged accessory per exposed device — MotionSensor in this MVP; Camera/Doorbell/Switch/Light follow.",
5
5
  "keywords": [
6
6
  "camstack",