@camstack/addon-export-alexa 1.2.33 → 1.2.35

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.
@@ -5801,6 +5801,13 @@ var BaseAddon = class {
5801
5801
  _readinessGeneration = typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2, 14);
5802
5802
  /** Capability names this addon registered at init — used to emit matching `down` events on shutdown. */
5803
5803
  _registeredCapNames = [];
5804
+ /**
5805
+ * True only after `readAddonStore` actually answered. Constructor
5806
+ * defaults look like stored config when the store is down — a forked
5807
+ * addon that auto-starts from those defaults (cloudflare-tunnel quick
5808
+ * mode, 2026-08-25) is not "the operator chose this".
5809
+ */
5810
+ settingsStoreReady = false;
5804
5811
  /** Default config values. Provided via constructor. */
5805
5812
  defaults;
5806
5813
  constructor(defaults) {
@@ -6201,7 +6208,9 @@ var BaseAddon = class {
6201
6208
  ];
6202
6209
  let lastErr;
6203
6210
  for (let attempt = 0; attempt <= delaysMs.length; attempt++) try {
6204
- return await settings.readAddonStore() ?? {};
6211
+ const stored = await settings.readAddonStore() ?? {};
6212
+ this.settingsStoreReady = true;
6213
+ return stored;
6205
6214
  } catch (err) {
6206
6215
  lastErr = err;
6207
6216
  const msg = err instanceof Error ? err.message : String(err);
@@ -6209,6 +6218,7 @@ var BaseAddon = class {
6209
6218
  if (attempt === delaysMs.length) break;
6210
6219
  await new Promise((r) => setTimeout(r, delaysMs[attempt]));
6211
6220
  }
6221
+ this.settingsStoreReady = false;
6212
6222
  this._ctx?.logger?.warn?.("readAddonStore: settings-store unavailable after retries — using defaults", { meta: { error: lastErr instanceof Error ? lastErr.message : String(lastErr) } });
6213
6223
  return {};
6214
6224
  }
@@ -6620,7 +6630,7 @@ function method(input, output, options) {
6620
6630
  input,
6621
6631
  output,
6622
6632
  kind: options?.kind ?? "query",
6623
- auth: options?.auth ?? "protected",
6633
+ ...options?.auth !== void 0 ? { auth: options.auth } : {},
6624
6634
  ...options?.access !== void 0 ? { access: options.access } : {},
6625
6635
  ...options?.caller !== void 0 ? { caller: options.caller } : {},
6626
6636
  timeoutMs: options?.timeoutMs
@@ -6640,7 +6650,7 @@ function systemMethod(input, output, options) {
6640
6650
  }
6641
6651
  var StaticDirOutputSchema$1 = object({ staticDir: string() });
6642
6652
  var VersionOutputSchema$1 = object({ version: string() });
6643
- method(_void(), StaticDirOutputSchema$1), method(_void(), VersionOutputSchema$1);
6653
+ method(_void(), StaticDirOutputSchema$1, { auth: "admin" }), method(_void(), VersionOutputSchema$1, { auth: "admin" });
6644
6654
  var DeviceType = /* @__PURE__ */ function(DeviceType) {
6645
6655
  DeviceType["Camera"] = "camera";
6646
6656
  DeviceType["Hub"] = "hub";
@@ -6961,7 +6971,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
6961
6971
  }({});
6962
6972
  var StaticDirOutputSchema = object({ staticDir: string() });
6963
6973
  var VersionOutputSchema = object({ version: string() });
6964
- method(_void(), StaticDirOutputSchema), method(_void(), VersionOutputSchema);
6974
+ method(_void(), StaticDirOutputSchema, { auth: "admin" }), method(_void(), VersionOutputSchema, { auth: "admin" });
6965
6975
  /**
6966
6976
  * device-ops — device-scoped cap that unifies the per-IDevice operations
6967
6977
  * previously routed through the `.device-ops` Moleculer bridge service.
@@ -7732,24 +7742,6 @@ var RecordingRetentionSchema = object({
7732
7742
  maxSizeGb: number().min(0).optional()
7733
7743
  });
7734
7744
  /**
7735
- * Scrub-thumbnail fidelity preset — the single per-camera selector bundling the
7736
- * sprite tile RESOLUTION + JPEG QUALITY the recorder packs timeline-scrub
7737
- * previews at. Five graduated steps; absent on a config = `standard` (the
7738
- * shipped default, matching `sheet-geometry`/`sheet-composer`).
7739
- *
7740
- * Existing sheets are IMMUTABLE — a changed preset applies to NEW windows only.
7741
- * Each window's index sidecar carries its own tile dims, so a camera whose
7742
- * preset changed over time renders every historical window at the dims it was
7743
- * written with.
7744
- */
7745
- var ScrubThumbnailPresetSchema = _enum([
7746
- "minimal",
7747
- "low",
7748
- "standard",
7749
- "high",
7750
- "max"
7751
- ]);
7752
- /**
7753
7745
  * The full per-camera recording intent — the wire shape of a RecordingTarget.
7754
7746
  *
7755
7747
  * `bands` is the ONLY authored recording intent: what to record, when, and on
@@ -7757,7 +7749,11 @@ var ScrubThumbnailPresetSchema = _enum([
7757
7749
  * other field is a storage knob (profiles, segment length, retention, scrub).
7758
7750
  *
7759
7751
  * STRICT on purpose: the legacy authoring surface (`schedule`/`schedules`/
7760
- * `triggers`/`preBufferSec`/`postBufferSec`/`rules`) was retired 2026-07-30.
7752
+ * `triggers`/`preBufferSec`/`postBufferSec`/`rules`) was retired 2026-07-30,
7753
+ * and `scrubThumbnails` — a five-step fidelity knob for a sprite tier that was
7754
+ * deleted on 2026-07-24 and had ZERO consumers in the recorder — on 2026-08-25
7755
+ * (D62: a switch that writes a store nobody reads is worse than no switch).
7756
+ * Stored rows keep loading: the READ schema is `.strip()` (config-store.ts).
7761
7757
  * A stale caller must fail loudly — silently stripping its legacy intent would
7762
7758
  * persist a band-less config, i.e. silently stop recording the camera.
7763
7759
  */
@@ -7780,14 +7776,7 @@ var RecordingConfigSchema = object({
7780
7776
  * "off" is the absence of a covering band, never a band value.
7781
7777
  */
7782
7778
  bands: array(RecordingBandSchema).default([]),
7783
- retention: RecordingRetentionSchema.optional(),
7784
- /**
7785
- * Per-camera scrub-thumbnail fidelity preset (resolution + JPEG quality for
7786
- * timeline-scrub sprite previews). Absent = `standard`. Applies to NEW
7787
- * windows only — existing sheets are immutable, and each window's index
7788
- * carries its own tile dims so mixed-preset history renders correctly.
7789
- */
7790
- scrubThumbnails: ScrubThumbnailPresetSchema.optional()
7779
+ retention: RecordingRetentionSchema.optional()
7791
7780
  }).strict();
7792
7781
  /**
7793
7782
  * Entity-relocation job state (storage entity-routing spec, Phase 4).
@@ -7863,10 +7852,11 @@ var RelocateFootageInputSchema = object({
7863
7852
  * `RecordingConfig.enabled` or camera wrapper bindings. */
7864
7853
  var StorageMigrationLeaseInputSchema = object({ leaseId: string().min(1) });
7865
7854
  var StorageMigrationFootageMoveInputSchema = RelocateFootageInputSchema.extend({ leaseId: string().min(1) });
7866
- var StorageMigrationMediaMoveInputSchema = object({
7855
+ var RelocateMediaInputSchema = object({
7867
7856
  toLocationId: string(),
7868
7857
  throttleMbps: number().min(1).max(1e3).optional()
7869
- }).extend({ leaseId: string().min(1) });
7858
+ });
7859
+ var StorageMigrationMediaMoveInputSchema = RelocateMediaInputSchema.extend({ leaseId: string().min(1) });
7870
7860
  /** The independently selectable logical storage classes. `recordings`
7871
7861
  * encompasses the high and mid segment profiles; `recordingsLow` is low
7872
7862
  * segments; `eventMedia` is post-analysis blobs. */
@@ -8215,7 +8205,26 @@ var LabelDefinitionSchema = object({
8215
8205
  description: string().optional(),
8216
8206
  icon: string().optional()
8217
8207
  });
8218
- var ClassMapDefinitionSchema = object({
8208
+ /**
8209
+ * Wire schema for a per-model CATALOG classMap override
8210
+ * (`ModelCatalogEntry.classMap` / `ModelConvertMetadata.classMap`) —
8211
+ * restricted to {@link CLASS_MAP_MACRO_TARGETS}, the only macros the
8212
+ * detection pipeline executor actually routes.
8213
+ *
8214
+ * This is deliberately a DIFFERENT, narrower shape than the general-purpose
8215
+ * `ClassMapDefinition` interface above (e.g. `IDetectionAddon.getClassMap()`
8216
+ * and the audio `YAMNET_TO_MACRO` catalog both use macro targets outside this
8217
+ * enum) — the two used to share the name `ClassMapDefinition`/
8218
+ * `ClassMapDefinitionSchema`, which made the schema-type-twin guard
8219
+ * (`scripts/check-schema-type-twins.ts`) flag them as a duplicated shape. They
8220
+ * are not: it is two different concepts colliding on a name. Keep this type
8221
+ * under its own name rather than reusing `ClassMapDefinition` — reusing it
8222
+ * would either narrow every `ClassMapDefinition` consumer to the four
8223
+ * detection macros (breaking `YAMNET_TO_MACRO`) or drop the validation this
8224
+ * schema exists for (see the "rejects a classMap whose target is not a
8225
+ * detection macro" test in `model-catalog-schema.test.ts`).
8226
+ */
8227
+ var DetectionCatalogClassMapSchema = object({
8219
8228
  mapping: record(string(), _enum([
8220
8229
  "person",
8221
8230
  "vehicle",
@@ -8307,6 +8316,12 @@ var ModelVariantGroupSchema = object({
8307
8316
  */
8308
8317
  resolution: number().int().positive().optional()
8309
8318
  });
8319
+ var ModelProviderIdSchema = _enum([
8320
+ "camstack",
8321
+ "frigate",
8322
+ "scrypted",
8323
+ "custom"
8324
+ ]);
8310
8325
  var ModelCatalogEntrySchema = object({
8311
8326
  id: string(),
8312
8327
  name: string(),
@@ -8404,11 +8419,17 @@ var ModelCatalogEntrySchema = object({
8404
8419
  */
8405
8420
  group: ModelVariantGroupSchema.optional(),
8406
8421
  /**
8422
+ * Catalog source for the pipeline stepper's provider-first picker. Absent on
8423
+ * built-in CamStack entries (treated as `camstack`) and on registry rows
8424
+ * persisted before this field existed (`inferModelProvider` fills those).
8425
+ */
8426
+ provider: ModelProviderIdSchema.optional(),
8427
+ /**
8407
8428
  * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
8408
8429
  * applies (Frigate / COCO public catalog). Set on a custom model whose raw
8409
8430
  * labels already ARE the CamStack macros (Scrypted identity map).
8410
8431
  */
8411
- classMap: ClassMapDefinitionSchema.optional()
8432
+ classMap: DetectionCatalogClassMapSchema.optional()
8412
8433
  });
8413
8434
  var ConvertTargetSchema = discriminatedUnion("format", [object({
8414
8435
  format: literal("openvino"),
@@ -8438,7 +8459,7 @@ var ModelConvertMetadataSchema = object({
8438
8459
  "segmentation"
8439
8460
  ]),
8440
8461
  faceAlignment: boolean().optional(),
8441
- classMap: ClassMapDefinitionSchema.optional()
8462
+ classMap: DetectionCatalogClassMapSchema.optional()
8442
8463
  });
8443
8464
  var ConvertResultSchema = object({
8444
8465
  entry: ModelCatalogEntrySchema,
@@ -9308,7 +9329,7 @@ var AddonPageDeclarationSchema = object({
9308
9329
  /** Display label for a CUSTOM `section` id (ignored for well-known ids). */
9309
9330
  sectionLabel: string().optional()
9310
9331
  });
9311
- method(_void(), array(AddonPageDeclarationSchema).readonly());
9332
+ method(_void(), array(AddonPageDeclarationSchema).readonly(), { auth: "admin" });
9312
9333
  var AddonHttpRouteSchema = object({
9313
9334
  method: _enum([
9314
9335
  "GET",
@@ -9562,7 +9583,7 @@ var WidgetMetadataSchema = object({
9562
9583
  defaultColumns: number().int().min(1).max(12).default(6),
9563
9584
  defaultRows: number().int().min(1).max(12).default(1)
9564
9585
  });
9565
- method(_void(), array(WidgetMetadataSchema).readonly());
9586
+ method(_void(), array(WidgetMetadataSchema).readonly(), { auth: "admin" });
9566
9587
  /**
9567
9588
  * `addon-widgets` — system-scoped singleton aggregator cap. Public-facing
9568
9589
  * surface that admin-ui consumes through `useAddonWidgetsListWidgets()`.
@@ -11106,7 +11127,7 @@ var CustomModelDescriptorSchema = object({
11106
11127
  stepId: string(),
11107
11128
  entry: ModelCatalogEntrySchema
11108
11129
  });
11109
- method(_void(), array(CustomModelDescriptorSchema).readonly());
11130
+ method(_void(), array(CustomModelDescriptorSchema).readonly(), { auth: "admin" });
11110
11131
  /**
11111
11132
  * Query filter for settings-store collections.
11112
11133
  */
@@ -11193,7 +11214,8 @@ method(object({
11193
11214
  }), _void(), { kind: "mutation" }), method(object({
11194
11215
  namespace: string().optional(),
11195
11216
  collection: string(),
11196
- filter: QueryFilterSchema.optional()
11217
+ filter: QueryFilterSchema.optional(),
11218
+ columns: array(string()).readonly().optional()
11197
11219
  }), array(SettingsRecordSchema).readonly()), method(object({
11198
11220
  namespace: string().optional(),
11199
11221
  collection: string(),
@@ -11256,46 +11278,87 @@ var EngineInfoSchema = object({
11256
11278
  kind: _enum(["relational", "vector"]),
11257
11279
  displayName: string()
11258
11280
  });
11259
- method(_void(), EngineInfoSchema), method(object({
11281
+ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
11260
11282
  namespace: string().optional(),
11261
11283
  collection: string(),
11262
11284
  key: string()
11263
- }), unknown()), method(object({
11285
+ }), unknown(), { auth: "admin" }), method(object({
11264
11286
  namespace: string().optional(),
11265
11287
  collection: string(),
11266
11288
  key: string(),
11267
11289
  value: unknown()
11268
- }), _void(), { kind: "mutation" }), method(object({
11290
+ }), _void(), {
11291
+ kind: "mutation",
11292
+ auth: "admin"
11293
+ }), method(object({
11269
11294
  namespace: string().optional(),
11270
11295
  collection: string(),
11271
- filter: QueryFilterSchema.optional()
11272
- }), array(SettingsRecordSchema).readonly()), method(object({
11296
+ filter: QueryFilterSchema.optional(),
11297
+ /**
11298
+ * SQL-level column projection — MUST mirror `settings-store.query`.
11299
+ *
11300
+ * ⚠ An earlier version of this comment blamed Zod stripping, and that
11301
+ * was wrong — corrected 2026-08-26 after the hop map
11302
+ * (`docs/design/2026-08-26-mappa-hop-argomenti.md`) traced the path.
11303
+ * There is **no Zod parse at all** between the door and the engine: the
11304
+ * dispatcher forwards the payload verbatim and UDS carries it whole. A
11305
+ * field declared here reaches `SqliteSettingsBackend` either way.
11306
+ *
11307
+ * What actually lost `columns` was the THIRD declaration of this shape:
11308
+ * `SettingsQueryInput` in `interfaces/storage.ts`, a hand-written TS
11309
+ * interface the engine destructures from. The field existed on both
11310
+ * schemas and the engine still never read it, because nothing checks a
11311
+ * registered provider against `InferProvider<cap>` —
11312
+ * `ProviderRegistration.provider` is typed `object`.
11313
+ *
11314
+ * It is declared here anyway, and must stay in step with
11315
+ * `settings-store.query`: a caller reading only the cap definitions has
11316
+ * to be able to see that this call carries a projection.
11317
+ * `data-door-schema-parity.spec.ts` keeps the two aligned.
11318
+ */
11319
+ columns: array(string()).readonly().optional()
11320
+ }), array(SettingsRecordSchema).readonly(), { auth: "admin" }), method(object({
11273
11321
  namespace: string().optional(),
11274
11322
  collection: string(),
11275
11323
  record: SettingsRecordSchema
11276
- }), _void(), { kind: "mutation" }), method(object({
11324
+ }), _void(), {
11325
+ kind: "mutation",
11326
+ auth: "admin"
11327
+ }), method(object({
11277
11328
  namespace: string().optional(),
11278
11329
  collection: string(),
11279
11330
  id: string(),
11280
11331
  data: record(string(), unknown())
11281
- }), _void(), { kind: "mutation" }), method(object({
11332
+ }), _void(), {
11333
+ kind: "mutation",
11334
+ auth: "admin"
11335
+ }), method(object({
11282
11336
  namespace: string().optional(),
11283
11337
  collection: string(),
11284
11338
  key: string()
11285
- }), _void(), { kind: "mutation" }), method(object({
11339
+ }), _void(), {
11340
+ kind: "mutation",
11341
+ auth: "admin"
11342
+ }), method(object({
11286
11343
  namespace: string().optional(),
11287
11344
  collection: string(),
11288
11345
  filter: MutationFilterSchema
11289
- }), object({ deleted: number().int() }), { kind: "mutation" }), method(object({
11346
+ }), object({ deleted: number().int() }), {
11347
+ kind: "mutation",
11348
+ auth: "admin"
11349
+ }), method(object({
11290
11350
  namespace: string().optional(),
11291
11351
  collection: string(),
11292
11352
  filter: MutationFilterSchema,
11293
11353
  data: record(string(), unknown())
11294
- }), object({ updated: number().int() }), { kind: "mutation" }), method(object({
11354
+ }), object({ updated: number().int() }), {
11355
+ kind: "mutation",
11356
+ auth: "admin"
11357
+ }), method(object({
11295
11358
  namespace: string().optional(),
11296
11359
  collection: string(),
11297
11360
  filter: QueryFilterSchema.optional()
11298
- }), number()), method(object({
11361
+ }), number(), { auth: "admin" }), method(object({
11299
11362
  namespace: string().optional(),
11300
11363
  collection: string(),
11301
11364
  field: string(),
@@ -11305,15 +11368,18 @@ method(_void(), EngineInfoSchema), method(object({
11305
11368
  }), array(object({
11306
11369
  bucket: number().int(),
11307
11370
  count: number().int()
11308
- })).readonly()), method(object({
11371
+ })).readonly(), { auth: "admin" }), method(object({
11309
11372
  namespace: string().optional(),
11310
11373
  collection: string()
11311
- }), boolean()), method(object({
11374
+ }), boolean(), { auth: "admin" }), method(object({
11312
11375
  namespace: string().optional(),
11313
11376
  collection: string(),
11314
11377
  columns: array(CollectionColumnSchema).readonly(),
11315
11378
  indexes: array(CollectionIndexSchema).readonly().optional()
11316
- }), _void(), { kind: "mutation" });
11379
+ }), _void(), {
11380
+ kind: "mutation",
11381
+ auth: "admin"
11382
+ });
11317
11383
  /**
11318
11384
  * shm ring usage stats for a `frameSink: 'shm'` decoder session —
11319
11385
  * exposed via `decoder.getShmStats` so downstream consumers can
@@ -12004,6 +12070,27 @@ var LinkedDeviceSchema = object({
12004
12070
  features: array(string()),
12005
12071
  producesTrackedEvents: boolean().optional()
12006
12072
  });
12073
+ /** One camera's resolved linked set, tagged with the camera it belongs to.
12074
+ * The batch answer needs the tag; the single-device answer already has it
12075
+ * from the input, which is why `getLinkedDevices` keeps the untagged shape. */
12076
+ var LinkedDevicesForDeviceSchema = object({
12077
+ deviceId: number(),
12078
+ mode: LinkedDevicesModeSchema,
12079
+ devices: array(LinkedDeviceSchema)
12080
+ });
12081
+ /** One device's binding map — the shape `getBindings`, `getBindingsBatch` and
12082
+ * `getAllBindings` all answer in. Declared once: three copies of the same
12083
+ * object literal is exactly how the three drift apart. */
12084
+ var DeviceBindingsForDeviceSchema = object({
12085
+ deviceId: number(),
12086
+ entries: array(object({
12087
+ capName: string(),
12088
+ kind: _enum(["native", "wrapped"]),
12089
+ providerAddonId: string(),
12090
+ providerNodeId: string(),
12091
+ nativeAddonId: string()
12092
+ }))
12093
+ });
12007
12094
  var SavedDeviceRowSchema = object({
12008
12095
  /** Numeric id reserved at allocateDeviceId time. */
12009
12096
  id: number(),
@@ -12229,11 +12316,25 @@ method(object({
12229
12316
  projection: _enum(["full", "slim"]).optional(),
12230
12317
  /** Return only camera devices. Filtering server-side instead of
12231
12318
  * shipping 293 rows to find 12. */
12232
- isCamera: boolean().optional()
12319
+ isCamera: boolean().optional(),
12320
+ /**
12321
+ * Return only these device ids. For the caller that already KNOWS the
12322
+ * handful it wants and needs a field the id-bearing answer does not
12323
+ * carry — the viewer's linked-devices panel joins `type` and `online`
12324
+ * onto ~8 linked ids and, unfiltered, dragged the fleet across to do
12325
+ * it: 433 KB slim / 958 KB full for 967 devices, on a query that
12326
+ * refetches on the reconcile interval, on a phone.
12327
+ *
12328
+ * Safe to send at a hub that predates it: Zod STRIPS unknown input
12329
+ * keys rather than rejecting them (verified against the live hub
12330
+ * 2026-08-25 — 967 rows came back), so an old hub answers exactly what
12331
+ * it answers today and the caller filters as it already does.
12332
+ */
12333
+ deviceIds: array(number()).optional()
12233
12334
  }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), object({
12234
12335
  mode: LinkedDevicesModeSchema,
12235
12336
  devices: array(LinkedDeviceSchema)
12236
- })), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
12337
+ })), method(object({ deviceIds: array(number()) }), array(LinkedDevicesForDeviceSchema)), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
12237
12338
  deviceId: number(),
12238
12339
  values: record(string(), unknown())
12239
12340
  }), object({ success: literal(true) }), {
@@ -12260,25 +12361,7 @@ method(object({
12260
12361
  }), method(object({ deviceId: number() }), array(StreamProbeResultSchema), {
12261
12362
  kind: "mutation",
12262
12363
  auth: "admin"
12263
- }), method(object({ deviceId: number() }), object({
12264
- deviceId: number(),
12265
- entries: array(object({
12266
- capName: string(),
12267
- kind: _enum(["native", "wrapped"]),
12268
- providerAddonId: string(),
12269
- providerNodeId: string(),
12270
- nativeAddonId: string()
12271
- }))
12272
- })), method(object({}), array(object({
12273
- deviceId: number(),
12274
- entries: array(object({
12275
- capName: string(),
12276
- kind: _enum(["native", "wrapped"]),
12277
- providerAddonId: string(),
12278
- providerNodeId: string(),
12279
- nativeAddonId: string()
12280
- }))
12281
- }))), method(object({
12364
+ }), method(object({ deviceId: number() }), DeviceBindingsForDeviceSchema), method(object({ deviceIds: array(number()) }), array(DeviceBindingsForDeviceSchema)), method(object({}), array(DeviceBindingsForDeviceSchema)), method(object({
12282
12365
  deviceId: number(),
12283
12366
  capName: string(),
12284
12367
  wrapperAddonId: string(),
@@ -12449,7 +12532,7 @@ method(object({
12449
12532
  crop: _instanceof(Uint8Array),
12450
12533
  width: number(),
12451
12534
  height: number()
12452
- }), EmbeddingResultSchema), method(object({ text: string() }), EmbeddingResultSchema), method(_void(), EmbeddingInfoSchema);
12535
+ }), EmbeddingResultSchema, { auth: "admin" }), method(object({ text: string() }), EmbeddingResultSchema, { auth: "admin" }), method(_void(), EmbeddingInfoSchema, { auth: "admin" });
12453
12536
  /**
12454
12537
  * filesystem-browse — per-node capability for browsing the node's local
12455
12538
  * filesystem. Reads are unconfined (whole filesystem, from `/` down); WRITES
@@ -12742,19 +12825,22 @@ method(LlmGenerateBaseInputSchema.extend({
12742
12825
  runtime: ManagedRuntimeConfigSchema,
12743
12826
  /** The managed profile's timeout, threaded by the hub provider. */
12744
12827
  timeoutMs: number().int().positive().optional()
12745
- }), LlmGenerateResultSchema, { kind: "mutation" }), method(object({ runtime: ManagedRuntimeConfigSchema }), LlmRuntimeStatusSchema, {
12828
+ }), LlmGenerateResultSchema, {
12829
+ kind: "mutation",
12830
+ auth: "admin"
12831
+ }), method(object({ runtime: ManagedRuntimeConfigSchema }), LlmRuntimeStatusSchema, {
12746
12832
  kind: "mutation",
12747
12833
  auth: "admin"
12748
12834
  }), method(object({}), _void(), {
12749
12835
  kind: "mutation",
12750
12836
  auth: "admin"
12751
- }), method(object({}), LlmRuntimeStatusSchema), method(object({ model: ManagedModelRefSchema }), _void(), {
12837
+ }), method(object({}), LlmRuntimeStatusSchema, { auth: "admin" }), method(object({ model: ManagedModelRefSchema }), _void(), {
12752
12838
  kind: "mutation",
12753
12839
  auth: "admin"
12754
12840
  }), method(object({ file: string() }), _void(), {
12755
12841
  kind: "mutation",
12756
12842
  auth: "admin"
12757
- }), method(object({}), array(LlmNodeModelSchema)), method(object({}), LlmRuntimeDiskUsageSchema);
12843
+ }), method(object({}), array(LlmNodeModelSchema), { auth: "admin" }), method(object({}), LlmRuntimeDiskUsageSchema, { auth: "admin" });
12758
12844
  /**
12759
12845
  * `llm` — consumer-facing LLM surface (spec §1-§3). Collection-mode: array
12760
12846
  * methods concat-fan across providers; single-row methods route to ONE
@@ -14650,12 +14736,15 @@ var NcOccupancyConditionSchema = object({
14650
14736
  * there is no second switch that can disagree with the first and every rule
14651
14737
  * authored before the decision migrates for free (`audioModeOf`):
14652
14738
  *
14653
- * - **LABEL mode — `labels` present.** The rule fires on the FIRST frame the
14654
- * classifier labels with one of them. No window, no percentage:
14655
- * `hitPercent` and `samplingSeconds` are ignored, and the rule's own
14656
- * `throttle` cooldown is the only brake. The per-label confidence floor is
14657
- * the analyzer's (`classificationMinScore`, per device) — a label only
14658
- * reaches this condition if the classifier was already confident enough.
14739
+ * - **LABEL mode — `labels` present.** The rule fires when `confirmHits`
14740
+ * labelled frames land inside `confirmWindowSec` (default 2 in 5 s).
14741
+ * `hitPercent` and `samplingSeconds` are still ignored — a percentage of
14742
+ * frames is the wrong question for a classifier that labels 1–3 frames
14743
+ * per episode. The count window is the brake that drops a single-frame
14744
+ * false positive; the rule's own `throttle` cooldown is the other. The
14745
+ * per-label confidence floor is the analyzer's (`classificationMinScore`,
14746
+ * per device) — a label only reaches this condition if the classifier was
14747
+ * already confident enough. `confirmHits: 1` restores first-frame fire.
14659
14748
  * - **LEVEL mode — `dbThreshold` present, no labels.** The sampling window IS
14660
14749
  * the condition: at least `hitPercent`% of the samples over
14661
14750
  * `samplingSeconds` must be at or above `dbThreshold` dBFS (see
@@ -14682,14 +14771,22 @@ var NcOccupancyConditionSchema = object({
14682
14771
  * an operator who typed `dog` mean the same thing.
14683
14772
  */
14684
14773
  var NcAudioConditionSchema = object({
14685
- /** LABEL MODE: audio macro labels. Present ⇒ fires on the first labelled frame. */
14774
+ /** LABEL MODE: audio macro labels. Present ⇒ count-in-window confirm. */
14686
14775
  labels: array(string().min(1)).min(1).optional(),
14687
14776
  /** LEVEL MODE: floor in dBFS (negative-going, `0` = full scale). */
14688
14777
  dbThreshold: number().min(-96).max(0).optional(),
14689
14778
  /** LEVEL MODE ONLY: percentage of the window's samples that must be hits (1–100). */
14690
14779
  hitPercent: number().int().min(1).max(100).default(60),
14691
14780
  /** LEVEL MODE ONLY: length of the sampling window in seconds. */
14692
- samplingSeconds: number().int().min(1).max(300).default(10)
14781
+ samplingSeconds: number().int().min(1).max(300).default(10),
14782
+ /**
14783
+ * LABEL MODE: how many labelled frames must land inside
14784
+ * {@link NcAudioConditionSchema.shape.confirmWindowSec} before dispatch.
14785
+ * Absent ⇒ 2 (the matcher default). `1` is first-frame fire.
14786
+ */
14787
+ confirmHits: number().int().min(1).max(20).optional(),
14788
+ /** LABEL MODE: the window those frames must share, in seconds. Absent ⇒ 5. */
14789
+ confirmWindowSec: number().int().min(1).max(60).optional()
14693
14790
  });
14694
14791
  /**
14695
14792
  * Which zone-crossing DIRECTION a rule accepts (`ObjectEvent.zoneCrossing`).
@@ -16221,7 +16318,17 @@ var oauthIntegrationCapability = {
16221
16318
  scope: "system",
16222
16319
  mode: "collection",
16223
16320
  internal: true,
16224
- methods: { getDescriptor: method(_void(), OauthIntegrationDescriptorSchema) }
16321
+ methods: {
16322
+ /**
16323
+ * `internal: true` did not gate the mount (see the 2026-08-26 note on
16324
+ * `data-store-provider`) — `getDescriptor` was reachable on the AppRouter
16325
+ * by ANY authenticated session at the default `auth: 'protected'`. The
16326
+ * real caller is `/api/oauth2/authorize` and `/api/oauth2/integrations`
16327
+ * (`oauth2-routes.ts`), which resolve the provider directly off the
16328
+ * capability registry — never through tRPC. `auth: 'admin'` closes the
16329
+ * tRPC surface without touching that path.
16330
+ */
16331
+ getDescriptor: method(_void(), OauthIntegrationDescriptorSchema, { auth: "admin" }) }
16225
16332
  };
16226
16333
  /**
16227
16334
  * pipeline-analytics — device-scoped wrapper cap. Refines raw
@@ -17069,6 +17176,46 @@ var RecentTracksPageSchema = object({
17069
17176
  /** Cursor for the next page, or null when this page is the last. */
17070
17177
  nextCursor: string().nullable()
17071
17178
  });
17179
+ var LIST_GROUPS_DEFAULT_LIMIT = 40;
17180
+ var LIST_GROUPS_MAX_LIMIT = 100;
17181
+ var AnalyticsGroupRecordSchema = object({
17182
+ id: string(),
17183
+ deviceId: number().int(),
17184
+ openedAt: number().int(),
17185
+ closedAt: number().int(),
17186
+ timestamp: number().int(),
17187
+ memberCount: number().int(),
17188
+ memberTrackIds: array(string()).readonly(),
17189
+ className: string(),
17190
+ classes: array(string()).readonly(),
17191
+ /** Relative event-media path, or null when the group has no picture yet. */
17192
+ mediaUrl: string().nullable(),
17193
+ singleton: boolean()
17194
+ });
17195
+ var AnalyticsGroupMemberSchema = object({
17196
+ trackId: string(),
17197
+ deviceId: number().int(),
17198
+ className: string(),
17199
+ firstSeen: number().int(),
17200
+ lastSeen: number().int(),
17201
+ mediaUrl: string().nullable()
17202
+ });
17203
+ var AnalyticsGroupDetailSchema = AnalyticsGroupRecordSchema.extend({ members: array(AnalyticsGroupMemberSchema).readonly() });
17204
+ var ListGroupsQueryInput = object({
17205
+ /** Devices to merge. An empty array yields `{ groups: [], nextCursor: null }`. */
17206
+ deviceIds: array(number()),
17207
+ /** Window lower bound on `closedAt` (inclusive). */
17208
+ since: number().optional(),
17209
+ /** Window upper bound on `openedAt` (inclusive). */
17210
+ until: number().optional(),
17211
+ limit: number().int().min(1).max(LIST_GROUPS_MAX_LIMIT).default(LIST_GROUPS_DEFAULT_LIMIT),
17212
+ /** Opaque continuation cursor from a previous page's `nextCursor`. */
17213
+ cursor: string().optional()
17214
+ });
17215
+ var ListGroupsPageSchema = object({
17216
+ groups: array(AnalyticsGroupRecordSchema).readonly(),
17217
+ nextCursor: string().nullable()
17218
+ });
17072
17219
  var KeyEventQueryInput = object({
17073
17220
  deviceId: number(),
17074
17221
  /** Window lower bound (track firstSeen ≥ since). */
@@ -17144,7 +17291,9 @@ var TrackCascadeCountsSchema = object({
17144
17291
  /** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
17145
17292
  plates: number().int(),
17146
17293
  /** Per-track CLIP search vectors removed (best-effort). */
17147
- embeddings: number().int()
17294
+ embeddings: number().int(),
17295
+ /** Group membership + group rows removed with their last member (best-effort). */
17296
+ groups: number().int()
17148
17297
  });
17149
17298
  /** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
17150
17299
  var DiskReconcileCountsSchema = object({
@@ -17290,7 +17439,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
17290
17439
  * stationary registry). Default false: the timeline lists passages,
17291
17440
  * not parking records (operator decision, 2026-08-15). */
17292
17441
  includeStationary: boolean().optional()
17293
- }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
17442
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(ListGroupsQueryInput, ListGroupsPageSchema), method(object({
17443
+ deviceId: number(),
17444
+ groupId: string().min(1)
17445
+ }), AnalyticsGroupDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
17294
17446
  kind: "mutation",
17295
17447
  auth: "admin"
17296
17448
  }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(EventKindsForDeviceSchema).readonly()), method(object({
@@ -17372,6 +17524,15 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
17372
17524
  }), method(object({ jobId: string() }), RelocateJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
17373
17525
  kind: "mutation",
17374
17526
  auth: "admin"
17527
+ }), method(RelocateMediaInputSchema, object({ jobId: string() }), {
17528
+ kind: "mutation",
17529
+ auth: "admin"
17530
+ }), method(object({}), array(RelocateJobSchema).readonly(), {
17531
+ kind: "query",
17532
+ auth: "admin"
17533
+ }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
17534
+ kind: "mutation",
17535
+ auth: "admin"
17375
17536
  }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
17376
17537
  kind: "query",
17377
17538
  auth: "admin"
@@ -17526,6 +17687,11 @@ object({
17526
17687
  "jpeg"
17527
17688
  ])
17528
17689
  });
17690
+ /**
17691
+ * Process-local frame identity. It is serializable so it can ride an in-process
17692
+ * capability call, but `registryId` deliberately prevents resolution in any
17693
+ * other process or execution group.
17694
+ */
17529
17695
  var FrameRefSchema = object({
17530
17696
  registryId: string().min(1),
17531
17697
  id: string().min(1),
@@ -17600,7 +17766,8 @@ var PipelineModelOptionSchema = object({
17600
17766
  sizeMB: number()
17601
17767
  })),
17602
17768
  group: ModelVariantGroupSchema.optional(),
17603
- legacy: boolean().optional()
17769
+ legacy: boolean().optional(),
17770
+ provider: ModelProviderIdSchema.optional()
17604
17771
  });
17605
17772
  var ConfigFieldBridge = custom();
17606
17773
  var PipelineAddonSchemaSchema = object({
@@ -19690,7 +19857,7 @@ method(object({
19690
19857
  * linking rather than produce an eternal token.
19691
19858
  */
19692
19859
  ttlSec: union([number().int().positive(), literal("never")]).optional()
19693
- }), object({ token: string() })), method(object({ token: string() }), SsoBridgeClaimsSchema.nullable());
19860
+ }), object({ token: string() }), { auth: "admin" }), method(object({ token: string() }), SsoBridgeClaimsSchema.nullable(), { auth: "admin" });
19694
19861
  var ProviderListEntrySchema = discriminatedUnion("shouldSaveDiskSpace", [object({
19695
19862
  providerId: string().min(1),
19696
19863
  displayName: string().min(1),
@@ -19785,10 +19952,13 @@ var EvictResultSchema = object({
19785
19952
  /** True when the provider has nothing left it is willing to drop on this location. */
19786
19953
  exhausted: boolean()
19787
19954
  });
19788
- method(object({ locationId: string() }), EvictableUsageSchema), method(object({
19955
+ method(object({ locationId: string() }), EvictableUsageSchema, { auth: "admin" }), method(object({
19789
19956
  locationId: string(),
19790
19957
  targetBytes: number().int().positive()
19791
- }), EvictResultSchema, { kind: "mutation" });
19958
+ }), EvictResultSchema, {
19959
+ kind: "mutation",
19960
+ auth: "admin"
19961
+ });
19792
19962
  method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin" }), method(StorageMigrationInputSchema, object({ jobId: string() }), {
19793
19963
  kind: "mutation",
19794
19964
  auth: "admin"
@@ -19848,26 +20018,50 @@ var ReadChunkInputSchema = object({
19848
20018
  length: number()
19849
20019
  });
19850
20020
  var EndDownloadInputSchema = object({ downloadId: string() });
19851
- method(_void(), ProviderInfoSchema), method(object({ config: record(string(), unknown()) }), TestLocationResultSchema, { auth: "admin" }), method(object({
20021
+ method(_void(), ProviderInfoSchema, { auth: "admin" }), method(object({ config: record(string(), unknown()) }), TestLocationResultSchema, { auth: "admin" }), method(object({
19852
20022
  location: StorageLocationSchema,
19853
20023
  relativePath: string()
19854
- }), string()), method(object({
20024
+ }), string(), { auth: "admin" }), method(object({
19855
20025
  location: StorageLocationSchema,
19856
20026
  relativePath: string(),
19857
20027
  data: _instanceof(Uint8Array)
19858
- }), _void(), { kind: "mutation" }), method(object({
20028
+ }), _void(), {
20029
+ kind: "mutation",
20030
+ auth: "admin"
20031
+ }), method(object({
19859
20032
  location: StorageLocationSchema,
19860
20033
  relativePath: string()
19861
- }), _instanceof(Uint8Array)), method(object({
20034
+ }), _instanceof(Uint8Array), { auth: "admin" }), method(object({
19862
20035
  location: StorageLocationSchema,
19863
20036
  relativePath: string()
19864
- }), boolean()), method(object({
20037
+ }), boolean(), { auth: "admin" }), method(object({
19865
20038
  location: StorageLocationSchema,
19866
20039
  prefix: string().optional()
19867
- }), array(string()).readonly()), method(object({
20040
+ }), array(string()).readonly(), { auth: "admin" }), method(object({
19868
20041
  location: StorageLocationSchema,
19869
20042
  relativePath: string()
19870
- }), _void(), { kind: "mutation" }), method(object({ location: StorageLocationSchema }), number().nullable()), method(BeginUploadInputSchema, BeginUploadResultSchema, { kind: "mutation" }), method(WriteChunkInputSchema, _void(), { kind: "mutation" }), method(FinalizeUploadInputSchema, _void(), { kind: "mutation" }), method(AbortUploadInputSchema, _void(), { kind: "mutation" }), method(BeginDownloadInputSchema, BeginDownloadResultSchema, { kind: "mutation" }), method(ReadChunkInputSchema, _instanceof(Uint8Array)), method(EndDownloadInputSchema, _void(), { kind: "mutation" });
20043
+ }), _void(), {
20044
+ kind: "mutation",
20045
+ auth: "admin"
20046
+ }), method(object({ location: StorageLocationSchema }), number().nullable(), { auth: "admin" }), method(BeginUploadInputSchema, BeginUploadResultSchema, {
20047
+ kind: "mutation",
20048
+ auth: "admin"
20049
+ }), method(WriteChunkInputSchema, _void(), {
20050
+ kind: "mutation",
20051
+ auth: "admin"
20052
+ }), method(FinalizeUploadInputSchema, _void(), {
20053
+ kind: "mutation",
20054
+ auth: "admin"
20055
+ }), method(AbortUploadInputSchema, _void(), {
20056
+ kind: "mutation",
20057
+ auth: "admin"
20058
+ }), method(BeginDownloadInputSchema, BeginDownloadResultSchema, {
20059
+ kind: "mutation",
20060
+ auth: "admin"
20061
+ }), method(ReadChunkInputSchema, _instanceof(Uint8Array), { auth: "admin" }), method(EndDownloadInputSchema, _void(), {
20062
+ kind: "mutation",
20063
+ auth: "admin"
20064
+ });
19871
20065
  /** Profile-exported FormBuilder schema. Shape is ConfigUISchema at the UI. */
19872
20066
  var ProfileSettingsSchemaBridge = unknown().nullable();
19873
20067
  var ProfileSettingsBagSchema = record(string(), unknown());
@@ -20125,7 +20319,8 @@ method(object({
20125
20319
  access: "create"
20126
20320
  }), method(object({ userId: string().optional() }), object({ optionsJSON: record(string(), unknown()) }), {
20127
20321
  kind: "mutation",
20128
- access: "view"
20322
+ access: "view",
20323
+ auth: "admin"
20129
20324
  }), method(object({
20130
20325
  /** Required — the user the assertion belongs to (verified). */
20131
20326
  userId: string(),
@@ -20133,10 +20328,12 @@ method(object({
20133
20328
  response: record(string(), unknown())
20134
20329
  }), object({ verified: boolean() }), {
20135
20330
  kind: "mutation",
20136
- access: "view"
20331
+ access: "view",
20332
+ auth: "admin"
20137
20333
  }), method(object({}), object({ optionsJSON: record(string(), unknown()) }), {
20138
20334
  kind: "mutation",
20139
- access: "view"
20335
+ access: "view",
20336
+ auth: "admin"
20140
20337
  }), method(object({
20141
20338
  /** AuthenticationResponseJSON from the browser. */
20142
20339
  response: record(string(), unknown()) }), object({
@@ -20144,7 +20341,8 @@ response: record(string(), unknown()) }), object({
20144
20341
  userId: string().nullable()
20145
20342
  }), {
20146
20343
  kind: "mutation",
20147
- access: "view"
20344
+ access: "view",
20345
+ auth: "admin"
20148
20346
  }), method(object({ userId: string() }), array(PasskeySummarySchema), { auth: "admin" }), method(object({
20149
20347
  userId: string(),
20150
20348
  credentialId: string()
@@ -20316,7 +20514,19 @@ var VectorStatsResultSchema = object({
20316
20514
  /** False when the backend ranks approximately. */
20317
20515
  exact: boolean()
20318
20516
  });
20319
- method(VectorDeclareIndexInputSchema, _void(), { kind: "mutation" }), method(VectorUpsertInputSchema, VectorUpsertResultSchema, { kind: "mutation" }), method(VectorQueryInputSchema, VectorQueryResultSchema), method(VectorGetInputSchema, VectorGetResultSchema), method(VectorDeleteInputSchema, VectorDeleteResultSchema, { kind: "mutation" }), method(VectorDeleteByFilterInputSchema, VectorDeleteResultSchema, { kind: "mutation" }), method(VectorStatsInputSchema, VectorStatsResultSchema);
20517
+ method(VectorDeclareIndexInputSchema, _void(), {
20518
+ kind: "mutation",
20519
+ auth: "admin"
20520
+ }), method(VectorUpsertInputSchema, VectorUpsertResultSchema, {
20521
+ kind: "mutation",
20522
+ auth: "admin"
20523
+ }), method(VectorQueryInputSchema, VectorQueryResultSchema, { auth: "admin" }), method(VectorGetInputSchema, VectorGetResultSchema, { auth: "admin" }), method(VectorDeleteInputSchema, VectorDeleteResultSchema, {
20524
+ kind: "mutation",
20525
+ auth: "admin"
20526
+ }), method(VectorDeleteByFilterInputSchema, VectorDeleteResultSchema, {
20527
+ kind: "mutation",
20528
+ auth: "admin"
20529
+ }), method(VectorStatsInputSchema, VectorStatsResultSchema, { auth: "admin" });
20320
20530
  var ClipSchema = object({
20321
20531
  /** Opaque, provider-namespaced id. The default provider encodes the time
20322
20532
  * window so `getClipPlayback` is self-contained (no event re-query). */
@@ -22039,7 +22249,27 @@ var MediaFileLiteSchema$1 = object({
22039
22249
  sizeBytes: number(),
22040
22250
  timestamp: number()
22041
22251
  });
22042
- method(_void(), array(IdentitySchema).readonly()), method(object({ name: string().min(1) }), IdentitySchema, {
22252
+ method(object({
22253
+ /**
22254
+ * Inline {@link IdentitySchema.coverBase64} on every row.
22255
+ *
22256
+ * Default `false`, the same inversion `listRecentFaces` and
22257
+ * `listPlates` took on 2026-08-25 (see `include-crops-default.ts` for
22258
+ * why the burden belongs on the caller that WANTS the bytes). Measured
22259
+ * on the live hub the same day: four identities cost 40,979 B with the
22260
+ * covers inline, ~10 KB of base64 per row, on a query this UI mounts
22261
+ * four times and the viewer holds at `staleTime: 30_000`.
22262
+ *
22263
+ * Nothing loses its avatar: `coverMediaKey` is already on every row and
22264
+ * the `event-media` plane serves that key `immutable` with an ETag.
22265
+ *
22266
+ * **This is an INPUT field, so it does not reach the addon until the
22267
+ * next train** — the hub router validates cap inputs against its own
22268
+ * compiled Zod and strips a key it does not know. Until then the
22269
+ * provider sees `undefined`, which resolves to `false`: the cheap shape
22270
+ * is what ships, and the opt-in becomes reachable when the train lands.
22271
+ */
22272
+ includeCrops: boolean().optional() }).optional(), array(IdentitySchema).readonly()), method(object({ name: string().min(1) }), IdentitySchema, {
22043
22273
  kind: "mutation",
22044
22274
  auth: "admin"
22045
22275
  }), method(object({
@@ -24184,7 +24414,14 @@ var PlateInfoSchema = object({
24184
24414
  plateBbox: BoundingBoxSchema.optional(),
24185
24415
  /** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
24186
24416
  keyFrameMediaKey: string().optional(),
24187
- base64: string().optional()
24417
+ base64: string().optional(),
24418
+ /**
24419
+ * Same crop as a data-plane URL, always present when the plate has a stored
24420
+ * crop. `getPlateByTrack` returns this and never inlines JPEG; `listPlates`
24421
+ * and `searchPlates` inline the crop only when their `includeCrops` input is
24422
+ * left at its `true` default.
24423
+ */
24424
+ cropUrl: string().optional()
24188
24425
  });
24189
24426
  var MediaFileLiteSchema = object({
24190
24427
  key: string(),
@@ -24202,14 +24439,34 @@ var PlateClusterSchema = object({
24202
24439
  });
24203
24440
  method(object({
24204
24441
  deviceId: number().int().optional(),
24205
- limit: number().int().positive().optional()
24442
+ limit: number().int().positive().optional(),
24443
+ /**
24444
+ * Inline the base64 crop on every row. Default `true` — the existing
24445
+ * behaviour, kept so no caller breaks.
24446
+ *
24447
+ * Set `false` once the caller renders {@link PlateInfo.cropUrl}.
24448
+ * Measured on the live hub at the 500 rows the Plates view asks for:
24449
+ * 879,403 B and 27.7 s with the crops inline, against a few KiB of
24450
+ * metadata without them — and the browser then caches the images.
24451
+ *
24452
+ * This is the plate twin of `faceGallery.listRecentFaces`'s option;
24453
+ * plates were the one gallery list left without it.
24454
+ *
24455
+ * **This is an INPUT field, so it does not reach the addon until the
24456
+ * next train.** The hub router validates cap inputs against its own
24457
+ * compiled Zod and strips a key it does not know. Until the train
24458
+ * ships, sending `false` is harmless and keeps the crops inline.
24459
+ */
24460
+ includeCrops: boolean().optional()
24206
24461
  }).optional(), array(PlateInfoSchema).readonly()), method(object({
24207
24462
  deviceId: number().int(),
24208
24463
  trackId: string()
24209
24464
  }), PlateInfoSchema.nullable()), method(object({ plateId: string() }), array(MediaFileLiteSchema).readonly()), method(object({
24210
24465
  text: string().min(1),
24211
24466
  maxDistance: number().int().min(0).optional(),
24212
- limit: number().int().positive().optional()
24467
+ limit: number().int().positive().optional(),
24468
+ /** See `listPlates.includeCrops`. Default `true`. */
24469
+ includeCrops: boolean().optional()
24213
24470
  }), array(PlateInfoSchema).readonly()), method(object({
24214
24471
  maxDistance: number().int().min(0).optional(),
24215
24472
  minClusterSize: number().int().min(2).optional(),
@@ -24223,7 +24480,13 @@ method(object({
24223
24480
  }), method(object({ plateId: string() }), _void(), {
24224
24481
  kind: "mutation",
24225
24482
  auth: "admin"
24226
- }), method(_void(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
24483
+ }), method(object({
24484
+ /** Inline {@link VehicleSchema.coverBase64} on every row. Default
24485
+ * `false` — the vehicle twin of `faceGallery.listIdentities`'s
24486
+ * option; `coverMediaKey` + the `event-media` plane carry the picture.
24487
+ * INPUT field: stripped by the hub router until the train ships, which
24488
+ * resolves to `false` and is exactly the intended default. */
24489
+ includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
24227
24490
  kind: "mutation",
24228
24491
  auth: "admin"
24229
24492
  }), method(object({
@@ -27824,6 +28087,12 @@ Object.freeze({
27824
28087
  addonId: null,
27825
28088
  access: "view"
27826
28089
  },
28090
+ "deviceManager.getBindingsBatch": {
28091
+ capName: "device-manager",
28092
+ capScope: "system",
28093
+ addonId: null,
28094
+ access: "view"
28095
+ },
27827
28096
  "deviceManager.getChildren": {
27828
28097
  capName: "device-manager",
27829
28098
  capScope: "system",
@@ -27884,6 +28153,12 @@ Object.freeze({
27884
28153
  addonId: null,
27885
28154
  access: "view"
27886
28155
  },
28156
+ "deviceManager.getLinkedDevicesBatch": {
28157
+ capName: "device-manager",
28158
+ capScope: "system",
28159
+ addonId: null,
28160
+ access: "view"
28161
+ },
27887
28162
  "deviceManager.getRoleDisplayDefaults": {
27888
28163
  capName: "device-manager",
27889
28164
  capScope: "system",
@@ -29588,6 +29863,12 @@ Object.freeze({
29588
29863
  addonId: null,
29589
29864
  access: "create"
29590
29865
  },
29866
+ "pipelineAnalytics.cancelRelocateMedia": {
29867
+ capName: "pipeline-analytics",
29868
+ capScope: "device",
29869
+ addonId: null,
29870
+ access: "create"
29871
+ },
29591
29872
  "pipelineAnalytics.cancelStorageMigrationMove": {
29592
29873
  capName: "pipeline-analytics",
29593
29874
  capScope: "device",
@@ -29654,6 +29935,12 @@ Object.freeze({
29654
29935
  addonId: null,
29655
29936
  access: "view"
29656
29937
  },
29938
+ "pipelineAnalytics.getGroup": {
29939
+ capName: "pipeline-analytics",
29940
+ capScope: "device",
29941
+ addonId: null,
29942
+ access: "view"
29943
+ },
29657
29944
  "pipelineAnalytics.getKeyEvents": {
29658
29945
  capName: "pipeline-analytics",
29659
29946
  capScope: "device",
@@ -29738,6 +30025,12 @@ Object.freeze({
29738
30025
  addonId: null,
29739
30026
  access: "view"
29740
30027
  },
30028
+ "pipelineAnalytics.listGroups": {
30029
+ capName: "pipeline-analytics",
30030
+ capScope: "device",
30031
+ addonId: null,
30032
+ access: "view"
30033
+ },
29741
30034
  "pipelineAnalytics.listOpsLog": {
29742
30035
  capName: "pipeline-analytics",
29743
30036
  capScope: "device",
@@ -29750,6 +30043,12 @@ Object.freeze({
29750
30043
  addonId: null,
29751
30044
  access: "view"
29752
30045
  },
30046
+ "pipelineAnalytics.listRelocateMediaJobs": {
30047
+ capName: "pipeline-analytics",
30048
+ capScope: "device",
30049
+ addonId: null,
30050
+ access: "view"
30051
+ },
29753
30052
  "pipelineAnalytics.listRetrainAnnotations": {
29754
30053
  capName: "pipeline-analytics",
29755
30054
  capScope: "device",
@@ -29828,6 +30127,12 @@ Object.freeze({
29828
30127
  addonId: null,
29829
30128
  access: "create"
29830
30129
  },
30130
+ "pipelineAnalytics.relocateMedia": {
30131
+ capName: "pipeline-analytics",
30132
+ capScope: "device",
30133
+ addonId: null,
30134
+ access: "create"
30135
+ },
29831
30136
  "pipelineAnalytics.restageRetrainTrack": {
29832
30137
  capName: "pipeline-analytics",
29833
30138
  capScope: "device",
@@ -32519,6 +32824,11 @@ Object.freeze({
32519
32824
  form: "single",
32520
32825
  optional: false
32521
32826
  }],
32827
+ "deviceManager.getBindingsBatch": [{
32828
+ name: "deviceIds",
32829
+ form: "array",
32830
+ optional: false
32831
+ }],
32522
32832
  "deviceManager.getChildren": [{
32523
32833
  name: "parentDeviceId",
32524
32834
  form: "single",
@@ -32564,6 +32874,11 @@ Object.freeze({
32564
32874
  form: "single",
32565
32875
  optional: false
32566
32876
  }],
32877
+ "deviceManager.getLinkedDevicesBatch": [{
32878
+ name: "deviceIds",
32879
+ form: "array",
32880
+ optional: false
32881
+ }],
32567
32882
  "deviceManager.getSettingsSchema": [{
32568
32883
  name: "deviceId",
32569
32884
  form: "single",
@@ -32584,6 +32899,11 @@ Object.freeze({
32584
32899
  form: "single",
32585
32900
  optional: false
32586
32901
  }],
32902
+ "deviceManager.listAll": [{
32903
+ name: "deviceIds",
32904
+ form: "array",
32905
+ optional: true
32906
+ }],
32587
32907
  "deviceManager.loadConfig": [{
32588
32908
  name: "deviceId",
32589
32909
  form: "single",
@@ -33157,6 +33477,11 @@ Object.freeze({
33157
33477
  form: "single",
33158
33478
  optional: false
33159
33479
  }],
33480
+ "pipelineAnalytics.getGroup": [{
33481
+ name: "deviceId",
33482
+ form: "single",
33483
+ optional: false
33484
+ }],
33160
33485
  "pipelineAnalytics.getKeyEvents": [{
33161
33486
  name: "deviceId",
33162
33487
  form: "single",
@@ -33212,6 +33537,11 @@ Object.freeze({
33212
33537
  form: "array",
33213
33538
  optional: false
33214
33539
  }],
33540
+ "pipelineAnalytics.listGroups": [{
33541
+ name: "deviceIds",
33542
+ form: "array",
33543
+ optional: false
33544
+ }],
33215
33545
  "pipelineAnalytics.listOpsLog": [{
33216
33546
  name: "deviceId",
33217
33547
  form: "single",