@camstack/addon-provider-rtsp 1.1.20 → 1.1.22

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.
Files changed (3) hide show
  1. package/dist/addon.js +541 -95
  2. package/dist/addon.mjs +541 -95
  3. package/package.json +1 -1
package/dist/addon.mjs CHANGED
@@ -4642,7 +4642,7 @@ function preprocess(fn, schema) {
4642
4642
  });
4643
4643
  }
4644
4644
  //#endregion
4645
- //#region ../types/dist/sleep-Cc14_yxc.mjs
4645
+ //#region ../types/dist/sleep-Baang_XW.mjs
4646
4646
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4647
4647
  EventCategory["SystemBoot"] = "system.boot";
4648
4648
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -5363,10 +5363,6 @@ function hydrateField(field, values) {
5363
5363
  };
5364
5364
  }
5365
5365
  const rawValue = storedValue !== void 0 ? storedValue : defaultValue !== void 0 ? defaultValue : null;
5366
- if (field.type === "password") return {
5367
- ...field,
5368
- value: ""
5369
- };
5370
5366
  const value = field.type === "textarea" && field.isJson && rawValue !== null && typeof rawValue === "object" ? JSON.stringify(rawValue, null, 2) : rawValue;
5371
5367
  return {
5372
5368
  ...field,
@@ -6750,10 +6746,25 @@ function method(input, output, options) {
6750
6746
  timeoutMs: options?.timeoutMs
6751
6747
  };
6752
6748
  }
6749
+ /**
6750
+ * A wrapper/system-only method: served exclusively by the cap's system-level
6751
+ * provider (`InferProvider`), and OPTIONAL on `InferNativeProvider` so per-device
6752
+ * driver natives don't stub out a wrapper concern (e.g. a cross-device cache
6753
+ * overview). The `systemOnly: true` literal is what `InferNativeProvider` keys on.
6754
+ */
6755
+ function systemMethod(input, output, options) {
6756
+ return {
6757
+ ...method(input, output, options),
6758
+ systemOnly: true
6759
+ };
6760
+ }
6753
6761
  /** Shorthand to define an event schema */
6754
6762
  function event(data) {
6755
6763
  return { data };
6756
6764
  }
6765
+ var StaticDirOutputSchema$1 = object({ staticDir: string() });
6766
+ var VersionOutputSchema$1 = object({ version: string() });
6767
+ method(_void(), StaticDirOutputSchema$1), method(_void(), VersionOutputSchema$1);
6757
6768
  var StaticDirOutputSchema = object({ staticDir: string() });
6758
6769
  var VersionOutputSchema = object({ version: string() });
6759
6770
  method(_void(), StaticDirOutputSchema), method(_void(), VersionOutputSchema);
@@ -11673,7 +11684,7 @@ var BoundingBoxSchema = object({
11673
11684
  w: number(),
11674
11685
  h: number()
11675
11686
  });
11676
- var SpatialDetectionSchema = object({
11687
+ object({
11677
11688
  class: string(),
11678
11689
  originalClass: string(),
11679
11690
  score: number(),
@@ -11848,6 +11859,7 @@ var PipelineAddonSchemaSchema = object({
11848
11859
  defaultModelId: string(),
11849
11860
  defaultModelIdByFormat: record(string(), string()).optional(),
11850
11861
  enabledByDefault: boolean().optional(),
11862
+ backfillIntoExistingOverrides: boolean().optional(),
11851
11863
  defaultConfidence: number(),
11852
11864
  group: string().optional(),
11853
11865
  configSchema: array(ConfigFieldBridge).readonly().optional()
@@ -11864,11 +11876,6 @@ var PipelineSchemaSchema = object({
11864
11876
  selectedEngine: PipelineEngineChoiceSchema,
11865
11877
  slots: array(PipelineSlotSchemaSchema).readonly()
11866
11878
  });
11867
- var DetectorOutputSchema = object({
11868
- detections: array(SpatialDetectionSchema).readonly(),
11869
- inferenceMs: number(),
11870
- modelId: string()
11871
- });
11872
11879
  var EngineProvisioningSchema = object({
11873
11880
  runtimeId: _enum([
11874
11881
  "onnx",
@@ -11993,7 +12000,7 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
11993
12000
  auth: "admin"
11994
12001
  }), method(object({ nodeId: string() }), object({
11995
12002
  success: literal(true),
11996
- regeneratedModelId: string().nullable()
12003
+ clearedDevices: number()
11997
12004
  }), {
11998
12005
  kind: "mutation",
11999
12006
  auth: "admin"
@@ -12014,10 +12021,6 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
12014
12021
  modelId: string(),
12015
12022
  format: ModelFormatSchema$1
12016
12023
  }), object({ success: literal(true) }), { kind: "mutation" }), method(object({
12017
- addonId: string(),
12018
- frame: FrameInputSchema,
12019
- config: record(string(), unknown()).optional()
12020
- }), DetectorOutputSchema), method(object({
12021
12024
  engine: PipelineEngineChoiceSchema.optional(),
12022
12025
  steps: array(PipelineStepInputSchema).min(1),
12023
12026
  frame: FrameInputSchema.optional(),
@@ -12038,7 +12041,15 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
12038
12041
  image: _instanceof(Uint8Array).optional(),
12039
12042
  referenceImage: string().optional(),
12040
12043
  deviceId: number().optional(),
12041
- sessionId: string().optional()
12044
+ sessionId: string().optional(),
12045
+ /**
12046
+ * Execution plane. 'full' (default) runs the whole tree — benchmark,
12047
+ * reference-image, and detail-subtree calls. 'frame' is the live
12048
+ * per-frame dispatch: ONLY root-plane steps run; crop children
12049
+ * (inputClasses ≠ null) are skipped and served per-track via
12050
+ * pipelineRunner.runDetailSubtree (two-plane design).
12051
+ */
12052
+ plane: _enum(["full", "frame"]).optional()
12042
12053
  }), PipelineRunResultBridge, { kind: "mutation" }), method(object({
12043
12054
  engine: PipelineEngineChoiceSchema.optional(),
12044
12055
  steps: array(PipelineStepInputSchema).min(1),
@@ -12196,6 +12207,47 @@ var zonesCapability = {
12196
12207
  runtimeState: object({ zones: array(ZoneSchema).readonly() })
12197
12208
  };
12198
12209
  /**
12210
+ * A bounding box in NORMALIZED [0,1] frame coordinates for `getNativeCrop`. The
12211
+ * decode worker resolves it against the RETAINED native frame's real pixel dims,
12212
+ * so the caller supplies only the detection-res bbox divided by the detection
12213
+ * dims — no native resolution to plumb.
12214
+ */
12215
+ var NativeCropBboxSchema = object({
12216
+ x: number(),
12217
+ y: number(),
12218
+ w: number(),
12219
+ h: number()
12220
+ });
12221
+ /** Result of a best-effort native-resolution crop (`getNativeCrop`). */
12222
+ var NativeCropResultSchema = object({
12223
+ /** Packed rgb (24-bit) pixels of the crop. */
12224
+ bytes: _instanceof(Uint8Array),
12225
+ width: number().int().positive(),
12226
+ height: number().int().positive()
12227
+ });
12228
+ /** Parent detection context passed to `runDetailSubtree` — the crop's
12229
+ * originating detection, in FRAME-space coordinates. Reuses
12230
+ * `NativeCropBboxSchema`'s `{x,y,w,h}` shape (same numeric fields; here
12231
+ * the coordinates are frame-space rather than getNativeCrop's
12232
+ * normalized [0,1] convention). */
12233
+ var DetailParentSchema = object({
12234
+ bbox: NativeCropBboxSchema,
12235
+ className: string()
12236
+ });
12237
+ /** One child-step result from `runDetailSubtree` — an embedding, label,
12238
+ * or refined detection produced by running the crop-subtree on a
12239
+ * single tracked detection. */
12240
+ var DetailResultSchema = object({
12241
+ stepId: string(),
12242
+ className: string(),
12243
+ score: number(),
12244
+ /** FRAME-space bbox (already mapped back from crop space). */
12245
+ bbox: NativeCropBboxSchema.optional(),
12246
+ embedding: string().optional(),
12247
+ label: string().optional(),
12248
+ alignedCropJpeg: string().optional()
12249
+ });
12250
+ /**
12199
12251
  * Per-camera tunable ranges + defaults. Single source of truth used
12200
12252
  * by both the Zod data schema (validation + default fallback) and
12201
12253
  * the device settings UI (slider min/max/step). Touch one place and
@@ -12451,7 +12503,17 @@ var RunnerLocalMetricsSchema = object({
12451
12503
  avgInferenceTimeMs: number(),
12452
12504
  queueDepth: number()
12453
12505
  });
12454
- 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());
12506
+ 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({
12507
+ handle: FrameHandleSchema,
12508
+ bbox: NativeCropBboxSchema,
12509
+ maxWidth: number().int().positive().optional()
12510
+ }), NativeCropResultSchema.nullable()), method(object({
12511
+ deviceId: number(),
12512
+ frameHandle: FrameHandleSchema.optional(),
12513
+ cropJpeg: string().optional(),
12514
+ parent: DetailParentSchema,
12515
+ steps: array(string()).optional()
12516
+ }), object({ details: array(DetailResultSchema) }).nullable(), { kind: "mutation" });
12455
12517
  /**
12456
12518
  * Hardware / firmware motion sensor cap — binary detected state plus
12457
12519
  * a timestamp of the last observation. Distinct from
@@ -15382,7 +15444,9 @@ var AddonPageDeclarationSchema$1 = object({
15382
15444
  icon: string(),
15383
15445
  path: string(),
15384
15446
  remoteName: string(),
15385
- bundle: string()
15447
+ bundle: string(),
15448
+ section: string().optional(),
15449
+ sectionLabel: string().optional()
15386
15450
  });
15387
15451
  var AddonPageInfoSchema = object({
15388
15452
  addonId: string(),
@@ -15422,7 +15486,18 @@ var AddonPageDeclarationSchema = object({
15422
15486
  * the static-file route can compute an mtime-based cache-buster URL
15423
15487
  * without a separate filesystem stat.
15424
15488
  */
15425
- bundle: string()
15489
+ bundle: string(),
15490
+ /**
15491
+ * Sidebar section this page docks into. Well-known ids: `'detection'`,
15492
+ * `'cluster'`, `'administration'` — the page renders inside that group.
15493
+ * Any OTHER string creates (or joins) a custom section rendered after
15494
+ * the built-in groups; its label comes from `sectionLabel` (first
15495
+ * declaration wins), falling back to the id. Absent → the legacy
15496
+ * "Addon Pages" group.
15497
+ */
15498
+ section: string().optional(),
15499
+ /** Display label for a CUSTOM `section` id (ignored for well-known ids). */
15500
+ sectionLabel: string().optional()
15426
15501
  });
15427
15502
  method(_void(), array(AddonPageDeclarationSchema).readonly());
15428
15503
  var AddonHttpRouteSchema = object({
@@ -15638,6 +15713,17 @@ var WidgetMetadataSchema = object({
15638
15713
  deviceContext: boolean().default(false),
15639
15714
  integrationContext: boolean().default(false)
15640
15715
  }),
15716
+ /**
15717
+ * Loadable BEFORE authentication. The normal widget registry listing
15718
+ * (`addon-widgets.listWidgets`) is auth-gated, so a pre-auth surface
15719
+ * (the login page) cannot discover a widget through it. A widget that
15720
+ * declares `preAuth: true` marks itself as safe to mount on a pre-auth
15721
+ * screen — it is surfaced through the PUBLIC `auth.listLoginMethods`
15722
+ * login-method contribution channel (see `login-method.cap.ts`) rather
15723
+ * than the authenticated registry, and its bundle is served by the
15724
+ * public `/api/addon-widgets/:addonId/*` static route. Defaults false.
15725
+ */
15726
+ preAuth: boolean().optional().default(false),
15641
15727
  /** Dashboard placement HINTS (operator can override per instance). */
15642
15728
  defaultSize: WidgetSizeEnum.default("md"),
15643
15729
  allowedSizes: array(WidgetSizeEnum).readonly().default([
@@ -15939,6 +16025,66 @@ method(object({
15939
16025
  password: string()
15940
16026
  }), AuthResultSchema.nullable(), { kind: "mutation" }), method(object({ state: string() }), string()), method(record(string(), string()), AuthResultSchema, { kind: "mutation" }), method(object({ token: string() }), AuthResultSchema.nullable());
15941
16027
  /**
16028
+ * `login-method` — collection cap through which auth addons contribute
16029
+ * their pre-auth login surfaces to the login page. This is the SINGLE,
16030
+ * generic mechanism that supersedes the dead `auth.listProviders` reader:
16031
+ * every auth addon (OIDC, magic-link, WebAuthn/passkey) registers a
16032
+ * `login-method` provider and the PUBLIC `auth.listLoginMethods`
16033
+ * procedure aggregates them for the unauthenticated login page.
16034
+ *
16035
+ * A contribution is a discriminated union on `kind`:
16036
+ *
16037
+ * - `redirect` — a declarative button. The login page renders a generic
16038
+ * button that navigates to `startUrl` (an addon-owned HTTP route).
16039
+ * Covers OIDC (`/addon/auth-oidc/<id>/start`) and magic-link with
16040
+ * ZERO shell-side JS. A future SSO addon plugs in the same way — the
16041
+ * login page needs NO change.
16042
+ *
16043
+ * - `widget` — a Module-Federation widget the login page mounts (via
16044
+ * `loadRemoteBundle`) for an in-page ceremony. Covers the passkey
16045
+ * login ceremony, which must run `@simplewebauthn/browser` INSIDE the
16046
+ * addon bundle. The referenced widget also declares `preAuth: true` in
16047
+ * its `addon-widgets-source` catalog entry. `auth.listLoginMethods`
16048
+ * stamps a public `bundleUrl` from `addonId` + `bundle`.
16049
+ *
16050
+ * Every contribution carries a `stage`:
16051
+ * - `primary` — shown on the first credentials screen (OIDC /
16052
+ * magic-link buttons; a future usernameless passkey).
16053
+ * - `second-factor` — shown AFTER the password leg, gated on the
16054
+ * returned `factors` (passkey-as-2FA today).
16055
+ *
16056
+ * `mount: skip` — the cap is read server-side by the core auth router
16057
+ * (`registry.getCollection('login-method')`), never mounted as its own
16058
+ * tRPC router.
16059
+ */
16060
+ /** When a login method renders in the two-phase login flow. */
16061
+ var LoginStageEnum = _enum(["primary", "second-factor"]);
16062
+ /** One login-method contribution — redirect button OR pre-auth widget. */
16063
+ var LoginMethodContributionSchema = discriminatedUnion("kind", [object({
16064
+ kind: literal("redirect"),
16065
+ /** Stable id within the login-method set (e.g. `auth-oidc/google`). */
16066
+ id: string(),
16067
+ /** Operator-facing button label. */
16068
+ label: string(),
16069
+ /** lucide-react icon name. */
16070
+ icon: string().optional(),
16071
+ /** Addon-owned HTTP route the button navigates to (GET). */
16072
+ startUrl: string(),
16073
+ stage: LoginStageEnum
16074
+ }), object({
16075
+ kind: literal("widget"),
16076
+ /** Stable id within the login-method set (e.g. `auth-webauthn/passkey-login`). */
16077
+ id: string(),
16078
+ /** Owning addon id — drives the public bundle URL + the MF namespace. */
16079
+ addonId: string(),
16080
+ /** Bundle filename inside the addon's dist dir (`remoteEntry.js`). */
16081
+ bundle: string(),
16082
+ /** MF remote descriptor — `{ remoteName, exposedModule, componentKey }`. */
16083
+ remote: WidgetRemoteSchema,
16084
+ stage: LoginStageEnum
16085
+ })]);
16086
+ method(_void(), array(LoginMethodContributionSchema).readonly());
16087
+ /**
15942
16088
  * Orchestrator-side destination metadata. The orchestrator computes
15943
16089
  * `id = <addonId>:<subId>` from its provider lookup so consumers
15944
16090
  * (admin UI, restore flow) see one canonical key.
@@ -18042,7 +18188,17 @@ var TrackSchema = object({
18042
18188
  /** Cumulative normalized distance travelled (0..1 units = full frame width). */
18043
18189
  totalDistance: number(),
18044
18190
  state: TrackStateSchema,
18045
- active: boolean()
18191
+ active: boolean(),
18192
+ /** Deterministic key-event importance score in [0,1] (server-computed at
18193
+ * track expiry, recomputed on late label). Absent on legacy rows written
18194
+ * before scoring shipped — consumers degrade to absence / compute-on-read. */
18195
+ importance: number().optional(),
18196
+ /** Id of the track's highest-confidence ObjectEvent (its representative
18197
+ * "best" frame). Absent when the track produced no object events. */
18198
+ bestEventId: string().optional(),
18199
+ /** Tag of the importance sub-signal that dominated the score
18200
+ * (identity|dwell|proximity|class|confidence|travel|zone). */
18201
+ importanceReason: string().optional()
18046
18202
  });
18047
18203
  var BaseEventFields = {
18048
18204
  id: string(),
@@ -18107,8 +18263,18 @@ var ObjectEventSchema = object({
18107
18263
  frameHeight: number().optional(),
18108
18264
  /** MediaStore key for the crop attached to this event (if any). */
18109
18265
  mediaKey: string().optional(),
18266
+ /** Design B: MediaStore key of the track's native-resolution key frame (the
18267
+ * best-detection full frame). Resolve via the event-media data-plane
18268
+ * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`) for a detail view that
18269
+ * draws `bbox` over the native frame. Absent on legacy rows / non-decoded
18270
+ * sources — consumers fall back to `mediaKey` (the tight crop). */
18271
+ keyFrameMediaKey: string().optional(),
18110
18272
  /** Populated by B5 (recording playback URL for this event). */
18111
- mediaUrl: string().optional()
18273
+ mediaUrl: string().optional(),
18274
+ /** The parent track's key-event importance [0,1], propagated to every object
18275
+ * event of the track (so an event row can be sorted by importance without a
18276
+ * track join). Absent on legacy rows / before the track was scored. */
18277
+ importance: number().optional()
18112
18278
  });
18113
18279
  var AudioEventSchema = object({
18114
18280
  ...BaseEventFields,
@@ -18132,7 +18298,8 @@ var MediaFileKindEnum = _enum([
18132
18298
  "fullFrame",
18133
18299
  "fullFrameBoxed",
18134
18300
  "faceCrop",
18135
- "plateCrop"
18301
+ "plateCrop",
18302
+ "keyFrame"
18136
18303
  ]);
18137
18304
  var MediaFileSchema = object({
18138
18305
  key: string(),
@@ -18153,6 +18320,32 @@ var DeviceEventQueryInput = object({
18153
18320
  projection: _enum(["full", "slim"]).optional()
18154
18321
  });
18155
18322
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
18323
+ var KeyEventQueryInput = object({
18324
+ deviceId: number(),
18325
+ /** Window lower bound (track firstSeen ≥ since). */
18326
+ since: number(),
18327
+ /** Window upper bound (track firstSeen ≤ until). */
18328
+ until: number(),
18329
+ limit: number().int().min(1).max(200).default(50),
18330
+ /** Drop tracks scoring below this importance. */
18331
+ minImportance: number().min(0).max(1).optional(),
18332
+ /** Restrict to a single class (e.g. 'person'). */
18333
+ classFilter: string().optional()
18334
+ });
18335
+ var KeyEventSchema = object({
18336
+ /** The representative event id (the track's best ObjectEvent, else its trackId). */
18337
+ id: string(),
18338
+ trackId: string(),
18339
+ /** Track start time (firstSeen). */
18340
+ timestamp: number(),
18341
+ className: string(),
18342
+ label: string().optional(),
18343
+ importance: number(),
18344
+ /** Highest-confidence ObjectEvent id for the track (empty when none). */
18345
+ bestEventId: string(),
18346
+ /** Track lifetime in ms (lastSeen - firstSeen). */
18347
+ windowMs: number().optional()
18348
+ });
18156
18349
  var TrackedDetectionSchema = object({
18157
18350
  trackId: string(),
18158
18351
  className: string(),
@@ -18182,7 +18375,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
18182
18375
  }), array(TrackSchema).readonly()), method(object({ deviceId: number() }), _void(), {
18183
18376
  kind: "mutation",
18184
18377
  auth: "admin"
18185
- }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({
18378
+ }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
18186
18379
  deviceId: number(),
18187
18380
  since: number(),
18188
18381
  until: number(),
@@ -18256,7 +18449,12 @@ var AgentPipelineSettingsSchema = object({
18256
18449
  detectWeight: number().positive().optional(),
18257
18450
  /** Node is eligible to run the detection pipeline (decode + inference). */
18258
18451
  detect: boolean().optional(),
18259
- /** Node is eligible to host decoder sessions. */
18452
+ /**
18453
+ * DEPRECATED AND IGNORED. Decode is always co-located with its frame
18454
+ * consumer, so decode eligibility IS detect eligibility. Kept optional in
18455
+ * the schema ONLY so persisted stores written before the removal still
18456
+ * parse — no code reads it and no write path emits it.
18457
+ */
18260
18458
  decode: boolean().optional(),
18261
18459
  /** Node is eligible to run audio-analyzer sessions. */
18262
18460
  audio: boolean().optional(),
@@ -18317,25 +18515,6 @@ var PipelineAssignmentSchema = object({
18317
18515
  assignedAt: number()
18318
18516
  });
18319
18517
  /**
18320
- * Decoder placement record. Symmetric to `PipelineAssignmentSchema` but for
18321
- * the decoder-node placement domain (`balanceDecoder` decision: manual pin
18322
- * → co-located with pipeline → capacity).
18323
- */
18324
- var DecoderAssignmentSchema = object({
18325
- deviceId: number(),
18326
- /** Moleculer node id of the decoder provider currently responsible for this camera. */
18327
- decoderNodeId: string(),
18328
- /** True when the assignment was set manually via `assignDecoder`, false when chosen by the balancer. */
18329
- pinned: boolean(),
18330
- /** Why this assignment was made — useful for debugging the decoder balancer. */
18331
- reason: _enum([
18332
- "manual",
18333
- "co-located",
18334
- "capacity",
18335
- "hardware-affinity"
18336
- ])
18337
- });
18338
- /**
18339
18518
  * Per-agent load summary surfaced to the load balancer + dashboards.
18340
18519
  * Aggregated from each runner's `getLocalLoad` cap call.
18341
18520
  */
@@ -18541,15 +18720,6 @@ method(object({
18541
18720
  }), method(_void(), IngestOwnerSchema), method(object({
18542
18721
  deviceId: number(),
18543
18722
  nodeId: string()
18544
- }), _void(), {
18545
- kind: "mutation",
18546
- auth: "admin"
18547
- }), method(object({ deviceId: number() }), _void(), {
18548
- kind: "mutation",
18549
- auth: "admin"
18550
- }), method(_void(), array(DecoderAssignmentSchema).readonly()), method(object({
18551
- deviceId: number(),
18552
- nodeId: string()
18553
18723
  }), object({ success: literal(true) }), {
18554
18724
  kind: "mutation",
18555
18725
  auth: "admin"
@@ -18568,10 +18738,7 @@ method(object({
18568
18738
  nodeId: string(),
18569
18739
  pinned: boolean(),
18570
18740
  assignedAt: number()
18571
- }))), method(object({
18572
- deviceId: number(),
18573
- pipelineNodeId: string().optional()
18574
- }), DecoderAssignmentSchema), method(object({ agentNodeId: string() }), AgentPipelineSettingsSchema.nullable()), method(_void(), array(object({
18741
+ }))), method(object({ agentNodeId: string() }), AgentPipelineSettingsSchema.nullable()), method(_void(), array(object({
18575
18742
  nodeId: string(),
18576
18743
  settings: AgentPipelineSettingsSchema
18577
18744
  })).readonly()), method(object({
@@ -18601,7 +18768,6 @@ method(object({
18601
18768
  }), method(object({
18602
18769
  agentNodeId: string(),
18603
18770
  detect: boolean().nullable().optional(),
18604
- decode: boolean().nullable().optional(),
18605
18771
  audio: boolean().nullable().optional(),
18606
18772
  ingest: boolean().nullable().optional()
18607
18773
  }), object({ success: literal(true) }), {
@@ -18613,6 +18779,15 @@ method(object({
18613
18779
  }), object({ success: literal(true) }), {
18614
18780
  kind: "mutation",
18615
18781
  auth: "admin"
18782
+ }), method(object({ agentNodeId: string() }), object({
18783
+ success: literal(true),
18784
+ /** Hardware-aware default detection model now in effect on the node (null when unresolvable). */
18785
+ effectiveModelId: string().nullable(),
18786
+ /** Number of cameras whose node-scoped overrides were cleared. */
18787
+ clearedCameraOverrides: number()
18788
+ }), {
18789
+ kind: "mutation",
18790
+ auth: "admin"
18616
18791
  }), method(object({ deviceId: number() }), CameraPipelineSettingsSchema.nullable()), method(object({
18617
18792
  deviceId: number(),
18618
18793
  addonId: string(),
@@ -18658,6 +18833,131 @@ method(object({
18658
18833
  auth: "admin"
18659
18834
  });
18660
18835
  /**
18836
+ * server-management — per-NODE singleton capability for a node's ROOT
18837
+ * package lifecycle (runtime-updatable node packages, phase 2: hub + docker
18838
+ * agents).
18839
+ *
18840
+ * Each node's root package (`@camstack/server` on the hub, `@camstack/agent`
18841
+ * on agents) carries the whole software stack in its npm dep tree, so ONE
18842
+ * version describes the node. Updates install into
18843
+ * `<dataDir>/server-root/versions/<v>/` and apply on restart via the baked
18844
+ * starter (probation boot + auto-rollback to N-1).
18845
+ *
18846
+ * Providers:
18847
+ * - HUB: `ServerUpdateService` behind the `server-provided` mount
18848
+ * (`buildServerProviders` in trpc.router.ts) — the default target for
18849
+ * unpinned calls.
18850
+ * - AGENT: `AgentUpdateService` registered by the agent bootstrap under
18851
+ * the synthetic `agent-runtime` addonId and declared in the agent's
18852
+ * `$hub.registerNode` manifest.
18853
+ *
18854
+ * Node routing: singleton caps get the codegen/runtime-builder `nodeId`
18855
+ * injection on every method — `input.nodeId` (or `nodePin(nodeId)` from the
18856
+ * SDK) routes the call to that node's provider via the standard remote
18857
+ * proxy (`createCapabilityProxy` → `$agent-cap-fwd` → the agent's
18858
+ * in-process provider lookup). No `nodeId` → the hub's own provider.
18859
+ *
18860
+ * Spec: docs/superpowers/specs/2026-07-12-runtime-updatable-node-packages-design.md
18861
+ */
18862
+ /**
18863
+ * Where the running hub's code was loaded from:
18864
+ * - `workspace` — dev checkout (tsx / workspace dist); the starter defers to
18865
+ * plain resolution and runtime updates are refused.
18866
+ * - `baked` — the immutable image seed closure (no data-dir root active).
18867
+ * - `data-root` — the runtime-updatable `<dataDir>/server-root` closure.
18868
+ */
18869
+ var ServerBootModeSchema = _enum([
18870
+ "workspace",
18871
+ "baked",
18872
+ "data-root"
18873
+ ]);
18874
+ /**
18875
+ * Update lifecycle state:
18876
+ * - `idle` / `checking` / `staging` — steady / in-flight registry work.
18877
+ * - `pending-restart` — a version is staged and the node has NOT yet
18878
+ * restarted onto it (still running the OLD version).
18879
+ * - `awaiting-confirmation` — the node HAS restarted onto the staged version
18880
+ * (it is the active probation boot) and is waiting to confirm boot-health.
18881
+ * Apply/rollback are refused in this state and the node must NOT be
18882
+ * manually restarted, or the probation boot auto-rolls-back.
18883
+ */
18884
+ var ServerUpdateStateSchema = _enum([
18885
+ "idle",
18886
+ "checking",
18887
+ "staging",
18888
+ "pending-restart",
18889
+ "awaiting-confirmation"
18890
+ ]);
18891
+ var ServerRollbackInfoSchema = object({
18892
+ /** The version that failed (or was manually rolled back). */
18893
+ fromVersion: string(),
18894
+ /** The version rolled back to; null = the baked seed. */
18895
+ toVersion: string().nullable(),
18896
+ atMs: number(),
18897
+ reason: string()
18898
+ });
18899
+ var ServerPackageStatusSchema = object({
18900
+ /** Root package name (`@camstack/server` on the hub). */
18901
+ packageName: string(),
18902
+ /** Version of the code the running process ACTUALLY loaded. */
18903
+ runningVersion: string().nullable(),
18904
+ /** Node.js runtime version the node's process runs on (`process.versions.node`). */
18905
+ nodeRuntimeVersion: string().nullable(),
18906
+ /** Active data-dir root version; null when booted from seed/workspace. */
18907
+ activeVersion: string().nullable(),
18908
+ /** N-1 version kept for rollback; null when no previous version exists. */
18909
+ previousVersion: string().nullable(),
18910
+ /** Version of the immutable baked seed closure (image fallback). */
18911
+ seedVersion: string().nullable(),
18912
+ /** Latest registry version from the most recent check (null = never checked). */
18913
+ latestVersion: string().nullable(),
18914
+ updateAvailable: boolean(),
18915
+ bootMode: ServerBootModeSchema,
18916
+ updateState: ServerUpdateStateSchema,
18917
+ /** Version staged + awaiting its probation boot, when one is pending. */
18918
+ pendingVersion: string().nullable(),
18919
+ /** Set when the last freshly-activated version failed its boot health-check. */
18920
+ rolledBack: ServerRollbackInfoSchema.nullable(),
18921
+ /**
18922
+ * True when `server-root/state.json` EXISTS but is unreadable/corrupt — the
18923
+ * hub is running from the baked seed (or workspace) while installed data-dir
18924
+ * versions are being IGNORED. Surfaced as a warning in the UI.
18925
+ */
18926
+ stateFileCorrupt: boolean(),
18927
+ lastCheckedAtMs: number().nullable()
18928
+ });
18929
+ var ServerUpdateCheckResultSchema = object({
18930
+ packageName: string(),
18931
+ runningVersion: string().nullable(),
18932
+ latestVersion: string().nullable(),
18933
+ updateAvailable: boolean(),
18934
+ checkedAtMs: number(),
18935
+ /** Non-null when the registry lookup failed (offline, bad registry, …). */
18936
+ error: string().nullable()
18937
+ });
18938
+ var ServerUpdateActionResultSchema = object({
18939
+ accepted: boolean(),
18940
+ targetVersion: string().nullable(),
18941
+ /** True when a graceful restart was scheduled to apply the change. */
18942
+ restarting: boolean(),
18943
+ message: string()
18944
+ });
18945
+ method(_void(), ServerPackageStatusSchema, { auth: "admin" }), method(_void(), ServerUpdateCheckResultSchema, {
18946
+ kind: "mutation",
18947
+ auth: "admin"
18948
+ }), method(object({
18949
+ /** Explicit target version; omitted = latest from the registry. */
18950
+ version: string().optional() }), ServerUpdateActionResultSchema, {
18951
+ kind: "mutation",
18952
+ auth: "admin"
18953
+ }), method(_void(), ServerUpdateActionResultSchema, {
18954
+ kind: "mutation",
18955
+ auth: "admin"
18956
+ }), method(_void(), ServerUpdateActionResultSchema, {
18957
+ kind: "mutation",
18958
+ auth: "admin"
18959
+ });
18960
+ /**
18661
18961
  * Query filter for settings-store collections.
18662
18962
  */
18663
18963
  var QueryFilterSchema = object({
@@ -18879,7 +19179,20 @@ var snapshotCapability = {
18879
19179
  invalidateCache: method(object({ deviceId: number() }), _void(), {
18880
19180
  kind: "mutation",
18881
19181
  auth: "admin"
18882
- })
19182
+ }),
19183
+ /**
19184
+ * Cache-only batch overview — answers from the wrapper's in-memory cache in
19185
+ * O(n) and NEVER triggers a capture. Lets a grid skip requesting images for
19186
+ * devices that never produced a frame, and gives it an ETag per device for
19187
+ * conditional (304-able) image fetches. `lastCapturedAt`/`cacheAgeMs`/`etag`
19188
+ * are null for a device with no cached frame.
19189
+ */
19190
+ getSnapshotOverview: systemMethod(object({ deviceIds: array(number()).min(1).max(200) }), array(object({
19191
+ deviceId: number(),
19192
+ lastCapturedAt: number().nullable(),
19193
+ cacheAgeMs: number().nullable(),
19194
+ etag: string().nullable()
19195
+ })))
18883
19196
  },
18884
19197
  status: {
18885
19198
  schema: SnapshotStatusSchema,
@@ -19136,10 +19449,32 @@ method(_void(), array(TurnServerSchema).readonly());
19136
19449
  * b. `finishAuthentication({userId, response})` → server verifies
19137
19450
  * the assertion, bumps the credential counter, returns ok.
19138
19451
  *
19452
+ * 2b. Usernameless (discoverable-credential) authentication — the
19453
+ * passkey IS the primary factor, no password leg:
19454
+ * a. `beginDiscoverableAuthentication({})` → assertion options with
19455
+ * EMPTY `allowCredentials` (the browser offers every resident
19456
+ * passkey it holds for this RP) + `userVerification: 'required'`
19457
+ * (the passkey replaces both factors, so UV is mandatory).
19458
+ * The challenge is stored server-side, NOT bound to any user.
19459
+ * b. `finishDiscoverableAuthentication({response})` → the provider
19460
+ * resolves the credential by the response's credential id,
19461
+ * verifies the assertion against the stored challenge + that
19462
+ * credential's public key/counter, and returns the OWNING
19463
+ * `userId` — the caller (core auth router) mints the session.
19464
+ *
19139
19465
  * 3. Management:
19140
19466
  * - `listPasskeys({userId})` — enumerate user's enrolled credentials.
19141
19467
  * - `removePasskey({userId, credentialId})` — revoke one credential.
19142
19468
  *
19469
+ * 4. Second-factor preference (opt-in, default OFF):
19470
+ * Enrolling a passkey only enables passkey-FIRST sign-in. It is
19471
+ * demanded as a second factor after a password login ONLY when the
19472
+ * user explicitly opts in via `setSecondFactorPreference`.
19473
+ * - `getSecondFactorPreference({userId})` → `{ enabled }` (missing
19474
+ * row ⇒ `enabled: false`).
19475
+ * - `setSecondFactorPreference({userId, enabled})` — persisted by
19476
+ * the providing addon beside its credentials.
19477
+ *
19143
19478
  * Challenges are short-lived (5 min, in-memory). The cap is internal —
19144
19479
  * the admin-ui composes the begin/finish round-trip and never exposes
19145
19480
  * the cap to non-admins.
@@ -19182,6 +19517,17 @@ method(object({
19182
19517
  }), object({ verified: boolean() }), {
19183
19518
  kind: "mutation",
19184
19519
  access: "view"
19520
+ }), method(object({}), object({ optionsJSON: record(string(), unknown()) }), {
19521
+ kind: "mutation",
19522
+ access: "view"
19523
+ }), method(object({
19524
+ /** AuthenticationResponseJSON from the browser. */
19525
+ response: record(string(), unknown()) }), object({
19526
+ verified: boolean(),
19527
+ userId: string().nullable()
19528
+ }), {
19529
+ kind: "mutation",
19530
+ access: "view"
19185
19531
  }), method(object({ userId: string() }), array(PasskeySummarySchema), { auth: "admin" }), method(object({
19186
19532
  userId: string(),
19187
19533
  credentialId: string()
@@ -19189,6 +19535,13 @@ method(object({
19189
19535
  kind: "mutation",
19190
19536
  auth: "admin",
19191
19537
  access: "delete"
19538
+ }), method(object({ userId: string() }), object({ enabled: boolean() }), { auth: "admin" }), method(object({
19539
+ userId: string(),
19540
+ enabled: boolean()
19541
+ }), object({ success: literal(true) }), {
19542
+ kind: "mutation",
19543
+ auth: "admin",
19544
+ access: "create"
19192
19545
  });
19193
19546
  /**
19194
19547
  * `videoclips` — the unified, navigable-clip surface for a camera.
@@ -19990,7 +20343,17 @@ var FaceInfoSchema = object({
19990
20343
  recognizedIdentityId: string().optional(),
19991
20344
  identityName: string().optional(),
19992
20345
  assigned: boolean(),
19993
- base64: string().optional()
20346
+ base64: string().optional(),
20347
+ /** Design B: the face bbox (pixel space) on the key frame — lets a detail
20348
+ * view draw the box over the native `keyFrameMediaKey` frame. Absent on
20349
+ * legacy rows written before design B. */
20350
+ faceBbox: BoundingBoxSchema.optional(),
20351
+ /** Design B: MediaStore key of the track's native-resolution key frame.
20352
+ * Fetch the native JPEG via the event-media data-plane
20353
+ * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`). Absent when the
20354
+ * track produced no key frame (e.g. native/onboard source) — the UI falls
20355
+ * back to the inline `base64` face crop. */
20356
+ keyFrameMediaKey: string().optional()
19994
20357
  });
19995
20358
  var FaceFilterEnum = _enum([
19996
20359
  "unassigned",
@@ -20687,6 +21050,16 @@ var TopologyCategorySchema = object({
20687
21050
  healthy: number(),
20688
21051
  addons: array(TopologyCategoryAddonSchema).readonly()
20689
21052
  });
21053
+ /**
21054
+ * The node's runtime-updatable ROOT package (`@camstack/server` on the hub,
21055
+ * `@camstack/agent` on agents) as reported by its `registerNode` manifest —
21056
+ * version visibility for the Server management surface. Nullable: offline
21057
+ * rows and pre-phase-2 nodes report none.
21058
+ */
21059
+ var TopologyRootPackageSchema = object({
21060
+ name: string(),
21061
+ version: string()
21062
+ });
20690
21063
  var TopologyNodeSchema = object({
20691
21064
  id: string(),
20692
21065
  name: string(),
@@ -20710,7 +21083,8 @@ var TopologyNodeSchema = object({
20710
21083
  status: string()
20711
21084
  })).readonly(),
20712
21085
  processes: array(TopologyProcessSchema).readonly(),
20713
- categories: array(TopologyCategorySchema).readonly()
21086
+ categories: array(TopologyCategorySchema).readonly(),
21087
+ rootPackage: TopologyRootPackageSchema.nullable()
20714
21088
  });
20715
21089
  var CapUsageEdgeSchema = object({
20716
21090
  callerAddonId: string(),
@@ -23523,6 +23897,12 @@ Object.freeze({
23523
23897
  addonId: null,
23524
23898
  access: "create"
23525
23899
  },
23900
+ "loginMethod.getLoginMethods": {
23901
+ capName: "login-method",
23902
+ capScope: "system",
23903
+ addonId: null,
23904
+ access: "view"
23905
+ },
23526
23906
  "mediaPlayer.next": {
23527
23907
  capName: "media-player",
23528
23908
  capScope: "device",
@@ -24105,6 +24485,12 @@ Object.freeze({
24105
24485
  addonId: null,
24106
24486
  access: "view"
24107
24487
  },
24488
+ "pipelineAnalytics.getKeyEvents": {
24489
+ capName: "pipeline-analytics",
24490
+ capScope: "device",
24491
+ addonId: null,
24492
+ access: "view"
24493
+ },
24108
24494
  "pipelineAnalytics.getMotionEvents": {
24109
24495
  capName: "pipeline-analytics",
24110
24496
  capScope: "device",
@@ -24153,23 +24539,23 @@ Object.freeze({
24153
24539
  addonId: null,
24154
24540
  access: "create"
24155
24541
  },
24156
- "pipelineExecutor.deleteModel": {
24542
+ "pipelineExecutor.clearDeviceOverrides": {
24157
24543
  capName: "pipeline-executor",
24158
24544
  capScope: "system",
24159
24545
  addonId: null,
24160
24546
  access: "delete"
24161
24547
  },
24162
- "pipelineExecutor.deleteTemplate": {
24548
+ "pipelineExecutor.deleteModel": {
24163
24549
  capName: "pipeline-executor",
24164
24550
  capScope: "system",
24165
24551
  addonId: null,
24166
24552
  access: "delete"
24167
24553
  },
24168
- "pipelineExecutor.detect": {
24554
+ "pipelineExecutor.deleteTemplate": {
24169
24555
  capName: "pipeline-executor",
24170
24556
  capScope: "system",
24171
24557
  addonId: null,
24172
- access: "view"
24558
+ access: "delete"
24173
24559
  },
24174
24560
  "pipelineExecutor.downloadModel": {
24175
24561
  capName: "pipeline-executor",
@@ -24315,12 +24701,6 @@ Object.freeze({
24315
24701
  addonId: null,
24316
24702
  access: "create"
24317
24703
  },
24318
- "pipelineExecutor.resetToDefault": {
24319
- capName: "pipeline-executor",
24320
- capScope: "system",
24321
- addonId: null,
24322
- access: "delete"
24323
- },
24324
24704
  "pipelineExecutor.runAudioTest": {
24325
24705
  capName: "pipeline-executor",
24326
24706
  capScope: "system",
@@ -24381,12 +24761,6 @@ Object.freeze({
24381
24761
  addonId: null,
24382
24762
  access: "create"
24383
24763
  },
24384
- "pipelineOrchestrator.assignDecoder": {
24385
- capName: "pipeline-orchestrator",
24386
- capScope: "system",
24387
- addonId: null,
24388
- access: "create"
24389
- },
24390
24764
  "pipelineOrchestrator.assignPipeline": {
24391
24765
  capName: "pipeline-orchestrator",
24392
24766
  capScope: "system",
@@ -24465,18 +24839,6 @@ Object.freeze({
24465
24839
  addonId: null,
24466
24840
  access: "view"
24467
24841
  },
24468
- "pipelineOrchestrator.getDecoderAssignment": {
24469
- capName: "pipeline-orchestrator",
24470
- capScope: "system",
24471
- addonId: null,
24472
- access: "view"
24473
- },
24474
- "pipelineOrchestrator.getDecoderAssignments": {
24475
- capName: "pipeline-orchestrator",
24476
- capScope: "system",
24477
- addonId: null,
24478
- access: "view"
24479
- },
24480
24842
  "pipelineOrchestrator.getGlobalMetrics": {
24481
24843
  capName: "pipeline-orchestrator",
24482
24844
  capScope: "system",
@@ -24525,6 +24887,12 @@ Object.freeze({
24525
24887
  addonId: null,
24526
24888
  access: "delete"
24527
24889
  },
24890
+ "pipelineOrchestrator.resetNodePipelineDefaults": {
24891
+ capName: "pipeline-orchestrator",
24892
+ capScope: "system",
24893
+ addonId: null,
24894
+ access: "delete"
24895
+ },
24528
24896
  "pipelineOrchestrator.resolvePipeline": {
24529
24897
  capName: "pipeline-orchestrator",
24530
24898
  capScope: "system",
@@ -24597,12 +24965,6 @@ Object.freeze({
24597
24965
  addonId: null,
24598
24966
  access: "create"
24599
24967
  },
24600
- "pipelineOrchestrator.unassignDecoder": {
24601
- capName: "pipeline-orchestrator",
24602
- capScope: "system",
24603
- addonId: null,
24604
- access: "create"
24605
- },
24606
24968
  "pipelineOrchestrator.unassignPipeline": {
24607
24969
  capName: "pipeline-orchestrator",
24608
24970
  capScope: "system",
@@ -24657,12 +25019,24 @@ Object.freeze({
24657
25019
  addonId: null,
24658
25020
  access: "view"
24659
25021
  },
25022
+ "pipelineRunner.getNativeCrop": {
25023
+ capName: "pipeline-runner",
25024
+ capScope: "system",
25025
+ addonId: null,
25026
+ access: "view"
25027
+ },
24660
25028
  "pipelineRunner.reportMotion": {
24661
25029
  capName: "pipeline-runner",
24662
25030
  capScope: "system",
24663
25031
  addonId: null,
24664
25032
  access: "create"
24665
25033
  },
25034
+ "pipelineRunner.runDetailSubtree": {
25035
+ capName: "pipeline-runner",
25036
+ capScope: "system",
25037
+ addonId: null,
25038
+ access: "create"
25039
+ },
24666
25040
  "plateGallery.correctPlateText": {
24667
25041
  capName: "plate-gallery",
24668
25042
  capScope: "system",
@@ -24909,6 +25283,36 @@ Object.freeze({
24909
25283
  addonId: null,
24910
25284
  access: "create"
24911
25285
  },
25286
+ "serverManagement.applyServerUpdate": {
25287
+ capName: "server-management",
25288
+ capScope: "system",
25289
+ addonId: null,
25290
+ access: "create"
25291
+ },
25292
+ "serverManagement.checkServerUpdate": {
25293
+ capName: "server-management",
25294
+ capScope: "system",
25295
+ addonId: null,
25296
+ access: "create"
25297
+ },
25298
+ "serverManagement.getServerPackageStatus": {
25299
+ capName: "server-management",
25300
+ capScope: "system",
25301
+ addonId: null,
25302
+ access: "view"
25303
+ },
25304
+ "serverManagement.restartServer": {
25305
+ capName: "server-management",
25306
+ capScope: "system",
25307
+ addonId: null,
25308
+ access: "create"
25309
+ },
25310
+ "serverManagement.rollbackServerUpdate": {
25311
+ capName: "server-management",
25312
+ capScope: "system",
25313
+ addonId: null,
25314
+ access: "create"
25315
+ },
24912
25316
  "settingsStore.count": {
24913
25317
  capName: "settings-store",
24914
25318
  capScope: "system",
@@ -24993,6 +25397,12 @@ Object.freeze({
24993
25397
  addonId: null,
24994
25398
  access: "view"
24995
25399
  },
25400
+ "snapshot.getSnapshotOverview": {
25401
+ capName: "snapshot",
25402
+ capScope: "device",
25403
+ addonId: null,
25404
+ access: "view"
25405
+ },
24996
25406
  "snapshot.invalidateCache": {
24997
25407
  capName: "snapshot",
24998
25408
  capScope: "device",
@@ -25671,6 +26081,12 @@ Object.freeze({
25671
26081
  addonId: null,
25672
26082
  access: "view"
25673
26083
  },
26084
+ "userPasskeys.beginDiscoverableAuthentication": {
26085
+ capName: "user-passkeys",
26086
+ capScope: "system",
26087
+ addonId: null,
26088
+ access: "view"
26089
+ },
25674
26090
  "userPasskeys.beginRegistration": {
25675
26091
  capName: "user-passkeys",
25676
26092
  capScope: "system",
@@ -25683,12 +26099,24 @@ Object.freeze({
25683
26099
  addonId: null,
25684
26100
  access: "view"
25685
26101
  },
26102
+ "userPasskeys.finishDiscoverableAuthentication": {
26103
+ capName: "user-passkeys",
26104
+ capScope: "system",
26105
+ addonId: null,
26106
+ access: "view"
26107
+ },
25686
26108
  "userPasskeys.finishRegistration": {
25687
26109
  capName: "user-passkeys",
25688
26110
  capScope: "system",
25689
26111
  addonId: null,
25690
26112
  access: "create"
25691
26113
  },
26114
+ "userPasskeys.getSecondFactorPreference": {
26115
+ capName: "user-passkeys",
26116
+ capScope: "system",
26117
+ addonId: null,
26118
+ access: "view"
26119
+ },
25692
26120
  "userPasskeys.listPasskeys": {
25693
26121
  capName: "user-passkeys",
25694
26122
  capScope: "system",
@@ -25701,6 +26129,12 @@ Object.freeze({
25701
26129
  addonId: null,
25702
26130
  access: "delete"
25703
26131
  },
26132
+ "userPasskeys.setSecondFactorPreference": {
26133
+ capName: "user-passkeys",
26134
+ capScope: "system",
26135
+ addonId: null,
26136
+ access: "create"
26137
+ },
25704
26138
  "vacuumControl.locate": {
25705
26139
  capName: "vacuum-control",
25706
26140
  capScope: "device",
@@ -25773,6 +26207,18 @@ Object.freeze({
25773
26207
  addonId: null,
25774
26208
  access: "view"
25775
26209
  },
26210
+ "viewerUi.getStaticDir": {
26211
+ capName: "viewer-ui",
26212
+ capScope: "system",
26213
+ addonId: null,
26214
+ access: "view"
26215
+ },
26216
+ "viewerUi.getVersion": {
26217
+ capName: "viewer-ui",
26218
+ capScope: "system",
26219
+ addonId: null,
26220
+ access: "view"
26221
+ },
25776
26222
  "waterHeater.setAway": {
25777
26223
  capName: "water-heater",
25778
26224
  capScope: "device",