@camstack/addon-provider-wyze 0.2.31 → 0.2.33

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 +431 -111
  2. package/dist/addon.mjs +431 -111
  3. package/package.json +1 -1
package/dist/addon.mjs CHANGED
@@ -5812,6 +5812,13 @@ var BaseAddon = class {
5812
5812
  _readinessGeneration = typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2, 14);
5813
5813
  /** Capability names this addon registered at init — used to emit matching `down` events on shutdown. */
5814
5814
  _registeredCapNames = [];
5815
+ /**
5816
+ * True only after `readAddonStore` actually answered. Constructor
5817
+ * defaults look like stored config when the store is down — a forked
5818
+ * addon that auto-starts from those defaults (cloudflare-tunnel quick
5819
+ * mode, 2026-08-25) is not "the operator chose this".
5820
+ */
5821
+ settingsStoreReady = false;
5815
5822
  /** Default config values. Provided via constructor. */
5816
5823
  defaults;
5817
5824
  constructor(defaults) {
@@ -6212,7 +6219,9 @@ var BaseAddon = class {
6212
6219
  ];
6213
6220
  let lastErr;
6214
6221
  for (let attempt = 0; attempt <= delaysMs.length; attempt++) try {
6215
- return await settings.readAddonStore() ?? {};
6222
+ const stored = await settings.readAddonStore() ?? {};
6223
+ this.settingsStoreReady = true;
6224
+ return stored;
6216
6225
  } catch (err) {
6217
6226
  lastErr = err;
6218
6227
  const msg = err instanceof Error ? err.message : String(err);
@@ -6220,6 +6229,7 @@ var BaseAddon = class {
6220
6229
  if (attempt === delaysMs.length) break;
6221
6230
  await new Promise((r) => setTimeout(r, delaysMs[attempt]));
6222
6231
  }
6232
+ this.settingsStoreReady = false;
6223
6233
  this._ctx?.logger?.warn?.("readAddonStore: settings-store unavailable after retries — using defaults", { meta: { error: lastErr instanceof Error ? lastErr.message : String(lastErr) } });
6224
6234
  return {};
6225
6235
  }
@@ -6631,7 +6641,7 @@ function method(input, output, options) {
6631
6641
  input,
6632
6642
  output,
6633
6643
  kind: options?.kind ?? "query",
6634
- auth: options?.auth ?? "protected",
6644
+ ...options?.auth !== void 0 ? { auth: options.auth } : {},
6635
6645
  ...options?.access !== void 0 ? { access: options.access } : {},
6636
6646
  ...options?.caller !== void 0 ? { caller: options.caller } : {},
6637
6647
  timeoutMs: options?.timeoutMs
@@ -6655,7 +6665,7 @@ function event(data) {
6655
6665
  }
6656
6666
  var StaticDirOutputSchema$1 = object({ staticDir: string() });
6657
6667
  var VersionOutputSchema$1 = object({ version: string() });
6658
- method(_void(), StaticDirOutputSchema$1), method(_void(), VersionOutputSchema$1);
6668
+ method(_void(), StaticDirOutputSchema$1, { auth: "admin" }), method(_void(), VersionOutputSchema$1, { auth: "admin" });
6659
6669
  var DeviceType = /* @__PURE__ */ function(DeviceType) {
6660
6670
  DeviceType["Camera"] = "camera";
6661
6671
  DeviceType["Hub"] = "hub";
@@ -6976,7 +6986,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
6976
6986
  }({});
6977
6987
  var StaticDirOutputSchema = object({ staticDir: string() });
6978
6988
  var VersionOutputSchema = object({ version: string() });
6979
- method(_void(), StaticDirOutputSchema), method(_void(), VersionOutputSchema);
6989
+ method(_void(), StaticDirOutputSchema, { auth: "admin" }), method(_void(), VersionOutputSchema, { auth: "admin" });
6980
6990
  /**
6981
6991
  * device-ops — device-scoped cap that unifies the per-IDevice operations
6982
6992
  * previously routed through the `.device-ops` Moleculer bridge service.
@@ -7602,24 +7612,6 @@ var RecordingRetentionSchema = object({
7602
7612
  maxSizeGb: number().min(0).optional()
7603
7613
  });
7604
7614
  /**
7605
- * Scrub-thumbnail fidelity preset — the single per-camera selector bundling the
7606
- * sprite tile RESOLUTION + JPEG QUALITY the recorder packs timeline-scrub
7607
- * previews at. Five graduated steps; absent on a config = `standard` (the
7608
- * shipped default, matching `sheet-geometry`/`sheet-composer`).
7609
- *
7610
- * Existing sheets are IMMUTABLE — a changed preset applies to NEW windows only.
7611
- * Each window's index sidecar carries its own tile dims, so a camera whose
7612
- * preset changed over time renders every historical window at the dims it was
7613
- * written with.
7614
- */
7615
- var ScrubThumbnailPresetSchema = _enum([
7616
- "minimal",
7617
- "low",
7618
- "standard",
7619
- "high",
7620
- "max"
7621
- ]);
7622
- /**
7623
7615
  * The full per-camera recording intent — the wire shape of a RecordingTarget.
7624
7616
  *
7625
7617
  * `bands` is the ONLY authored recording intent: what to record, when, and on
@@ -7627,7 +7619,11 @@ var ScrubThumbnailPresetSchema = _enum([
7627
7619
  * other field is a storage knob (profiles, segment length, retention, scrub).
7628
7620
  *
7629
7621
  * STRICT on purpose: the legacy authoring surface (`schedule`/`schedules`/
7630
- * `triggers`/`preBufferSec`/`postBufferSec`/`rules`) was retired 2026-07-30.
7622
+ * `triggers`/`preBufferSec`/`postBufferSec`/`rules`) was retired 2026-07-30,
7623
+ * and `scrubThumbnails` — a five-step fidelity knob for a sprite tier that was
7624
+ * deleted on 2026-07-24 and had ZERO consumers in the recorder — on 2026-08-25
7625
+ * (D62: a switch that writes a store nobody reads is worse than no switch).
7626
+ * Stored rows keep loading: the READ schema is `.strip()` (config-store.ts).
7631
7627
  * A stale caller must fail loudly — silently stripping its legacy intent would
7632
7628
  * persist a band-less config, i.e. silently stop recording the camera.
7633
7629
  */
@@ -7650,14 +7646,7 @@ var RecordingConfigSchema = object({
7650
7646
  * "off" is the absence of a covering band, never a band value.
7651
7647
  */
7652
7648
  bands: array(RecordingBandSchema).default([]),
7653
- retention: RecordingRetentionSchema.optional(),
7654
- /**
7655
- * Per-camera scrub-thumbnail fidelity preset (resolution + JPEG quality for
7656
- * timeline-scrub sprite previews). Absent = `standard`. Applies to NEW
7657
- * windows only — existing sheets are immutable, and each window's index
7658
- * carries its own tile dims so mixed-preset history renders correctly.
7659
- */
7660
- scrubThumbnails: ScrubThumbnailPresetSchema.optional()
7649
+ retention: RecordingRetentionSchema.optional()
7661
7650
  }).strict();
7662
7651
  /**
7663
7652
  * Entity-relocation job state (storage entity-routing spec, Phase 4).
@@ -7733,10 +7722,11 @@ var RelocateFootageInputSchema = object({
7733
7722
  * `RecordingConfig.enabled` or camera wrapper bindings. */
7734
7723
  var StorageMigrationLeaseInputSchema = object({ leaseId: string().min(1) });
7735
7724
  var StorageMigrationFootageMoveInputSchema = RelocateFootageInputSchema.extend({ leaseId: string().min(1) });
7736
- var StorageMigrationMediaMoveInputSchema = object({
7725
+ var RelocateMediaInputSchema = object({
7737
7726
  toLocationId: string(),
7738
7727
  throttleMbps: number().min(1).max(1e3).optional()
7739
- }).extend({ leaseId: string().min(1) });
7728
+ });
7729
+ var StorageMigrationMediaMoveInputSchema = RelocateMediaInputSchema.extend({ leaseId: string().min(1) });
7740
7730
  /** The independently selectable logical storage classes. `recordings`
7741
7731
  * encompasses the high and mid segment profiles; `recordingsLow` is low
7742
7732
  * segments; `eventMedia` is post-analysis blobs. */
@@ -8031,7 +8021,26 @@ var LabelDefinitionSchema = object({
8031
8021
  description: string().optional(),
8032
8022
  icon: string().optional()
8033
8023
  });
8034
- var ClassMapDefinitionSchema = object({
8024
+ /**
8025
+ * Wire schema for a per-model CATALOG classMap override
8026
+ * (`ModelCatalogEntry.classMap` / `ModelConvertMetadata.classMap`) —
8027
+ * restricted to {@link CLASS_MAP_MACRO_TARGETS}, the only macros the
8028
+ * detection pipeline executor actually routes.
8029
+ *
8030
+ * This is deliberately a DIFFERENT, narrower shape than the general-purpose
8031
+ * `ClassMapDefinition` interface above (e.g. `IDetectionAddon.getClassMap()`
8032
+ * and the audio `YAMNET_TO_MACRO` catalog both use macro targets outside this
8033
+ * enum) — the two used to share the name `ClassMapDefinition`/
8034
+ * `ClassMapDefinitionSchema`, which made the schema-type-twin guard
8035
+ * (`scripts/check-schema-type-twins.ts`) flag them as a duplicated shape. They
8036
+ * are not: it is two different concepts colliding on a name. Keep this type
8037
+ * under its own name rather than reusing `ClassMapDefinition` — reusing it
8038
+ * would either narrow every `ClassMapDefinition` consumer to the four
8039
+ * detection macros (breaking `YAMNET_TO_MACRO`) or drop the validation this
8040
+ * schema exists for (see the "rejects a classMap whose target is not a
8041
+ * detection macro" test in `model-catalog-schema.test.ts`).
8042
+ */
8043
+ var DetectionCatalogClassMapSchema = object({
8035
8044
  mapping: record(string(), _enum([
8036
8045
  "person",
8037
8046
  "vehicle",
@@ -8123,6 +8132,12 @@ var ModelVariantGroupSchema = object({
8123
8132
  */
8124
8133
  resolution: number().int().positive().optional()
8125
8134
  });
8135
+ var ModelProviderIdSchema = _enum([
8136
+ "camstack",
8137
+ "frigate",
8138
+ "scrypted",
8139
+ "custom"
8140
+ ]);
8126
8141
  var ModelCatalogEntrySchema = object({
8127
8142
  id: string(),
8128
8143
  name: string(),
@@ -8220,11 +8235,17 @@ var ModelCatalogEntrySchema = object({
8220
8235
  */
8221
8236
  group: ModelVariantGroupSchema.optional(),
8222
8237
  /**
8238
+ * Catalog source for the pipeline stepper's provider-first picker. Absent on
8239
+ * built-in CamStack entries (treated as `camstack`) and on registry rows
8240
+ * persisted before this field existed (`inferModelProvider` fills those).
8241
+ */
8242
+ provider: ModelProviderIdSchema.optional(),
8243
+ /**
8223
8244
  * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
8224
8245
  * applies (Frigate / COCO public catalog). Set on a custom model whose raw
8225
8246
  * labels already ARE the CamStack macros (Scrypted identity map).
8226
8247
  */
8227
- classMap: ClassMapDefinitionSchema.optional()
8248
+ classMap: DetectionCatalogClassMapSchema.optional()
8228
8249
  });
8229
8250
  var ConvertTargetSchema = discriminatedUnion("format", [object({
8230
8251
  format: literal("openvino"),
@@ -8254,7 +8275,7 @@ var ModelConvertMetadataSchema = object({
8254
8275
  "segmentation"
8255
8276
  ]),
8256
8277
  faceAlignment: boolean().optional(),
8257
- classMap: ClassMapDefinitionSchema.optional()
8278
+ classMap: DetectionCatalogClassMapSchema.optional()
8258
8279
  });
8259
8280
  var ConvertResultSchema = object({
8260
8281
  entry: ModelCatalogEntrySchema,
@@ -9117,7 +9138,7 @@ var AddonPageDeclarationSchema = object({
9117
9138
  /** Display label for a CUSTOM `section` id (ignored for well-known ids). */
9118
9139
  sectionLabel: string().optional()
9119
9140
  });
9120
- method(_void(), array(AddonPageDeclarationSchema).readonly());
9141
+ method(_void(), array(AddonPageDeclarationSchema).readonly(), { auth: "admin" });
9121
9142
  var AddonHttpRouteSchema = object({
9122
9143
  method: _enum([
9123
9144
  "GET",
@@ -9352,7 +9373,7 @@ var WidgetMetadataSchema = object({
9352
9373
  defaultColumns: number().int().min(1).max(12).default(6),
9353
9374
  defaultRows: number().int().min(1).max(12).default(1)
9354
9375
  });
9355
- method(_void(), array(WidgetMetadataSchema).readonly());
9376
+ method(_void(), array(WidgetMetadataSchema).readonly(), { auth: "admin" });
9356
9377
  /**
9357
9378
  * `addon-widgets` — system-scoped singleton aggregator cap. Public-facing
9358
9379
  * surface that admin-ui consumes through `useAddonWidgetsListWidgets()`.
@@ -10976,7 +10997,7 @@ var CustomModelDescriptorSchema = object({
10976
10997
  stepId: string(),
10977
10998
  entry: ModelCatalogEntrySchema
10978
10999
  });
10979
- method(_void(), array(CustomModelDescriptorSchema).readonly());
11000
+ method(_void(), array(CustomModelDescriptorSchema).readonly(), { auth: "admin" });
10980
11001
  /**
10981
11002
  * Query filter for settings-store collections.
10982
11003
  */
@@ -11063,7 +11084,8 @@ method(object({
11063
11084
  }), _void(), { kind: "mutation" }), method(object({
11064
11085
  namespace: string().optional(),
11065
11086
  collection: string(),
11066
- filter: QueryFilterSchema.optional()
11087
+ filter: QueryFilterSchema.optional(),
11088
+ columns: array(string()).readonly().optional()
11067
11089
  }), array(SettingsRecordSchema).readonly()), method(object({
11068
11090
  namespace: string().optional(),
11069
11091
  collection: string(),
@@ -11126,46 +11148,87 @@ var EngineInfoSchema = object({
11126
11148
  kind: _enum(["relational", "vector"]),
11127
11149
  displayName: string()
11128
11150
  });
11129
- method(_void(), EngineInfoSchema), method(object({
11151
+ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
11130
11152
  namespace: string().optional(),
11131
11153
  collection: string(),
11132
11154
  key: string()
11133
- }), unknown()), method(object({
11155
+ }), unknown(), { auth: "admin" }), method(object({
11134
11156
  namespace: string().optional(),
11135
11157
  collection: string(),
11136
11158
  key: string(),
11137
11159
  value: unknown()
11138
- }), _void(), { kind: "mutation" }), method(object({
11160
+ }), _void(), {
11161
+ kind: "mutation",
11162
+ auth: "admin"
11163
+ }), method(object({
11139
11164
  namespace: string().optional(),
11140
11165
  collection: string(),
11141
- filter: QueryFilterSchema.optional()
11142
- }), array(SettingsRecordSchema).readonly()), method(object({
11166
+ filter: QueryFilterSchema.optional(),
11167
+ /**
11168
+ * SQL-level column projection — MUST mirror `settings-store.query`.
11169
+ *
11170
+ * ⚠ An earlier version of this comment blamed Zod stripping, and that
11171
+ * was wrong — corrected 2026-08-26 after the hop map
11172
+ * (`docs/design/2026-08-26-mappa-hop-argomenti.md`) traced the path.
11173
+ * There is **no Zod parse at all** between the door and the engine: the
11174
+ * dispatcher forwards the payload verbatim and UDS carries it whole. A
11175
+ * field declared here reaches `SqliteSettingsBackend` either way.
11176
+ *
11177
+ * What actually lost `columns` was the THIRD declaration of this shape:
11178
+ * `SettingsQueryInput` in `interfaces/storage.ts`, a hand-written TS
11179
+ * interface the engine destructures from. The field existed on both
11180
+ * schemas and the engine still never read it, because nothing checks a
11181
+ * registered provider against `InferProvider<cap>` —
11182
+ * `ProviderRegistration.provider` is typed `object`.
11183
+ *
11184
+ * It is declared here anyway, and must stay in step with
11185
+ * `settings-store.query`: a caller reading only the cap definitions has
11186
+ * to be able to see that this call carries a projection.
11187
+ * `data-door-schema-parity.spec.ts` keeps the two aligned.
11188
+ */
11189
+ columns: array(string()).readonly().optional()
11190
+ }), array(SettingsRecordSchema).readonly(), { auth: "admin" }), method(object({
11143
11191
  namespace: string().optional(),
11144
11192
  collection: string(),
11145
11193
  record: SettingsRecordSchema
11146
- }), _void(), { kind: "mutation" }), method(object({
11194
+ }), _void(), {
11195
+ kind: "mutation",
11196
+ auth: "admin"
11197
+ }), method(object({
11147
11198
  namespace: string().optional(),
11148
11199
  collection: string(),
11149
11200
  id: string(),
11150
11201
  data: record(string(), unknown())
11151
- }), _void(), { kind: "mutation" }), method(object({
11202
+ }), _void(), {
11203
+ kind: "mutation",
11204
+ auth: "admin"
11205
+ }), method(object({
11152
11206
  namespace: string().optional(),
11153
11207
  collection: string(),
11154
11208
  key: string()
11155
- }), _void(), { kind: "mutation" }), method(object({
11209
+ }), _void(), {
11210
+ kind: "mutation",
11211
+ auth: "admin"
11212
+ }), method(object({
11156
11213
  namespace: string().optional(),
11157
11214
  collection: string(),
11158
11215
  filter: MutationFilterSchema
11159
- }), object({ deleted: number().int() }), { kind: "mutation" }), method(object({
11216
+ }), object({ deleted: number().int() }), {
11217
+ kind: "mutation",
11218
+ auth: "admin"
11219
+ }), method(object({
11160
11220
  namespace: string().optional(),
11161
11221
  collection: string(),
11162
11222
  filter: MutationFilterSchema,
11163
11223
  data: record(string(), unknown())
11164
- }), object({ updated: number().int() }), { kind: "mutation" }), method(object({
11224
+ }), object({ updated: number().int() }), {
11225
+ kind: "mutation",
11226
+ auth: "admin"
11227
+ }), method(object({
11165
11228
  namespace: string().optional(),
11166
11229
  collection: string(),
11167
11230
  filter: QueryFilterSchema.optional()
11168
- }), number()), method(object({
11231
+ }), number(), { auth: "admin" }), method(object({
11169
11232
  namespace: string().optional(),
11170
11233
  collection: string(),
11171
11234
  field: string(),
@@ -11175,15 +11238,18 @@ method(_void(), EngineInfoSchema), method(object({
11175
11238
  }), array(object({
11176
11239
  bucket: number().int(),
11177
11240
  count: number().int()
11178
- })).readonly()), method(object({
11241
+ })).readonly(), { auth: "admin" }), method(object({
11179
11242
  namespace: string().optional(),
11180
11243
  collection: string()
11181
- }), boolean()), method(object({
11244
+ }), boolean(), { auth: "admin" }), method(object({
11182
11245
  namespace: string().optional(),
11183
11246
  collection: string(),
11184
11247
  columns: array(CollectionColumnSchema).readonly(),
11185
11248
  indexes: array(CollectionIndexSchema).readonly().optional()
11186
- }), _void(), { kind: "mutation" });
11249
+ }), _void(), {
11250
+ kind: "mutation",
11251
+ auth: "admin"
11252
+ });
11187
11253
  /**
11188
11254
  * shm ring usage stats for a `frameSink: 'shm'` decoder session —
11189
11255
  * exposed via `decoder.getShmStats` so downstream consumers can
@@ -12028,6 +12094,27 @@ var LinkedDeviceSchema = object({
12028
12094
  features: array(string()),
12029
12095
  producesTrackedEvents: boolean().optional()
12030
12096
  });
12097
+ /** One camera's resolved linked set, tagged with the camera it belongs to.
12098
+ * The batch answer needs the tag; the single-device answer already has it
12099
+ * from the input, which is why `getLinkedDevices` keeps the untagged shape. */
12100
+ var LinkedDevicesForDeviceSchema = object({
12101
+ deviceId: number(),
12102
+ mode: LinkedDevicesModeSchema,
12103
+ devices: array(LinkedDeviceSchema)
12104
+ });
12105
+ /** One device's binding map — the shape `getBindings`, `getBindingsBatch` and
12106
+ * `getAllBindings` all answer in. Declared once: three copies of the same
12107
+ * object literal is exactly how the three drift apart. */
12108
+ var DeviceBindingsForDeviceSchema = object({
12109
+ deviceId: number(),
12110
+ entries: array(object({
12111
+ capName: string(),
12112
+ kind: _enum(["native", "wrapped"]),
12113
+ providerAddonId: string(),
12114
+ providerNodeId: string(),
12115
+ nativeAddonId: string()
12116
+ }))
12117
+ });
12031
12118
  var SavedDeviceRowSchema = object({
12032
12119
  /** Numeric id reserved at allocateDeviceId time. */
12033
12120
  id: number(),
@@ -12253,11 +12340,25 @@ method(object({
12253
12340
  projection: _enum(["full", "slim"]).optional(),
12254
12341
  /** Return only camera devices. Filtering server-side instead of
12255
12342
  * shipping 293 rows to find 12. */
12256
- isCamera: boolean().optional()
12343
+ isCamera: boolean().optional(),
12344
+ /**
12345
+ * Return only these device ids. For the caller that already KNOWS the
12346
+ * handful it wants and needs a field the id-bearing answer does not
12347
+ * carry — the viewer's linked-devices panel joins `type` and `online`
12348
+ * onto ~8 linked ids and, unfiltered, dragged the fleet across to do
12349
+ * it: 433 KB slim / 958 KB full for 967 devices, on a query that
12350
+ * refetches on the reconcile interval, on a phone.
12351
+ *
12352
+ * Safe to send at a hub that predates it: Zod STRIPS unknown input
12353
+ * keys rather than rejecting them (verified against the live hub
12354
+ * 2026-08-25 — 967 rows came back), so an old hub answers exactly what
12355
+ * it answers today and the caller filters as it already does.
12356
+ */
12357
+ deviceIds: array(number()).optional()
12257
12358
  }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), object({
12258
12359
  mode: LinkedDevicesModeSchema,
12259
12360
  devices: array(LinkedDeviceSchema)
12260
- })), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
12361
+ })), 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({
12261
12362
  deviceId: number(),
12262
12363
  values: record(string(), unknown())
12263
12364
  }), object({ success: literal(true) }), {
@@ -12284,25 +12385,7 @@ method(object({
12284
12385
  }), method(object({ deviceId: number() }), array(StreamProbeResultSchema), {
12285
12386
  kind: "mutation",
12286
12387
  auth: "admin"
12287
- }), method(object({ deviceId: number() }), object({
12288
- deviceId: number(),
12289
- entries: array(object({
12290
- capName: string(),
12291
- kind: _enum(["native", "wrapped"]),
12292
- providerAddonId: string(),
12293
- providerNodeId: string(),
12294
- nativeAddonId: string()
12295
- }))
12296
- })), method(object({}), array(object({
12297
- deviceId: number(),
12298
- entries: array(object({
12299
- capName: string(),
12300
- kind: _enum(["native", "wrapped"]),
12301
- providerAddonId: string(),
12302
- providerNodeId: string(),
12303
- nativeAddonId: string()
12304
- }))
12305
- }))), method(object({
12388
+ }), method(object({ deviceId: number() }), DeviceBindingsForDeviceSchema), method(object({ deviceIds: array(number()) }), array(DeviceBindingsForDeviceSchema)), method(object({}), array(DeviceBindingsForDeviceSchema)), method(object({
12306
12389
  deviceId: number(),
12307
12390
  capName: string(),
12308
12391
  wrapperAddonId: string(),
@@ -12473,7 +12556,7 @@ method(object({
12473
12556
  crop: _instanceof(Uint8Array),
12474
12557
  width: number(),
12475
12558
  height: number()
12476
- }), EmbeddingResultSchema), method(object({ text: string() }), EmbeddingResultSchema), method(_void(), EmbeddingInfoSchema);
12559
+ }), EmbeddingResultSchema, { auth: "admin" }), method(object({ text: string() }), EmbeddingResultSchema, { auth: "admin" }), method(_void(), EmbeddingInfoSchema, { auth: "admin" });
12477
12560
  /**
12478
12561
  * filesystem-browse — per-node capability for browsing the node's local
12479
12562
  * filesystem. Reads are unconfined (whole filesystem, from `/` down); WRITES
@@ -12766,19 +12849,22 @@ method(LlmGenerateBaseInputSchema.extend({
12766
12849
  runtime: ManagedRuntimeConfigSchema,
12767
12850
  /** The managed profile's timeout, threaded by the hub provider. */
12768
12851
  timeoutMs: number().int().positive().optional()
12769
- }), LlmGenerateResultSchema, { kind: "mutation" }), method(object({ runtime: ManagedRuntimeConfigSchema }), LlmRuntimeStatusSchema, {
12852
+ }), LlmGenerateResultSchema, {
12853
+ kind: "mutation",
12854
+ auth: "admin"
12855
+ }), method(object({ runtime: ManagedRuntimeConfigSchema }), LlmRuntimeStatusSchema, {
12770
12856
  kind: "mutation",
12771
12857
  auth: "admin"
12772
12858
  }), method(object({}), _void(), {
12773
12859
  kind: "mutation",
12774
12860
  auth: "admin"
12775
- }), method(object({}), LlmRuntimeStatusSchema), method(object({ model: ManagedModelRefSchema }), _void(), {
12861
+ }), method(object({}), LlmRuntimeStatusSchema, { auth: "admin" }), method(object({ model: ManagedModelRefSchema }), _void(), {
12776
12862
  kind: "mutation",
12777
12863
  auth: "admin"
12778
12864
  }), method(object({ file: string() }), _void(), {
12779
12865
  kind: "mutation",
12780
12866
  auth: "admin"
12781
- }), method(object({}), array(LlmNodeModelSchema)), method(object({}), LlmRuntimeDiskUsageSchema);
12867
+ }), method(object({}), array(LlmNodeModelSchema), { auth: "admin" }), method(object({}), LlmRuntimeDiskUsageSchema, { auth: "admin" });
12782
12868
  /**
12783
12869
  * `llm` — consumer-facing LLM surface (spec §1-§3). Collection-mode: array
12784
12870
  * methods concat-fan across providers; single-row methods route to ONE
@@ -14712,12 +14798,15 @@ var NcOccupancyConditionSchema = object({
14712
14798
  * there is no second switch that can disagree with the first and every rule
14713
14799
  * authored before the decision migrates for free (`audioModeOf`):
14714
14800
  *
14715
- * - **LABEL mode — `labels` present.** The rule fires on the FIRST frame the
14716
- * classifier labels with one of them. No window, no percentage:
14717
- * `hitPercent` and `samplingSeconds` are ignored, and the rule's own
14718
- * `throttle` cooldown is the only brake. The per-label confidence floor is
14719
- * the analyzer's (`classificationMinScore`, per device) — a label only
14720
- * reaches this condition if the classifier was already confident enough.
14801
+ * - **LABEL mode — `labels` present.** The rule fires when `confirmHits`
14802
+ * labelled frames land inside `confirmWindowSec` (default 2 in 5 s).
14803
+ * `hitPercent` and `samplingSeconds` are still ignored — a percentage of
14804
+ * frames is the wrong question for a classifier that labels 1–3 frames
14805
+ * per episode. The count window is the brake that drops a single-frame
14806
+ * false positive; the rule's own `throttle` cooldown is the other. The
14807
+ * per-label confidence floor is the analyzer's (`classificationMinScore`,
14808
+ * per device) — a label only reaches this condition if the classifier was
14809
+ * already confident enough. `confirmHits: 1` restores first-frame fire.
14721
14810
  * - **LEVEL mode — `dbThreshold` present, no labels.** The sampling window IS
14722
14811
  * the condition: at least `hitPercent`% of the samples over
14723
14812
  * `samplingSeconds` must be at or above `dbThreshold` dBFS (see
@@ -14744,14 +14833,22 @@ var NcOccupancyConditionSchema = object({
14744
14833
  * an operator who typed `dog` mean the same thing.
14745
14834
  */
14746
14835
  var NcAudioConditionSchema = object({
14747
- /** LABEL MODE: audio macro labels. Present ⇒ fires on the first labelled frame. */
14836
+ /** LABEL MODE: audio macro labels. Present ⇒ count-in-window confirm. */
14748
14837
  labels: array(string().min(1)).min(1).optional(),
14749
14838
  /** LEVEL MODE: floor in dBFS (negative-going, `0` = full scale). */
14750
14839
  dbThreshold: number().min(-96).max(0).optional(),
14751
14840
  /** LEVEL MODE ONLY: percentage of the window's samples that must be hits (1–100). */
14752
14841
  hitPercent: number().int().min(1).max(100).default(60),
14753
14842
  /** LEVEL MODE ONLY: length of the sampling window in seconds. */
14754
- samplingSeconds: number().int().min(1).max(300).default(10)
14843
+ samplingSeconds: number().int().min(1).max(300).default(10),
14844
+ /**
14845
+ * LABEL MODE: how many labelled frames must land inside
14846
+ * {@link NcAudioConditionSchema.shape.confirmWindowSec} before dispatch.
14847
+ * Absent ⇒ 2 (the matcher default). `1` is first-frame fire.
14848
+ */
14849
+ confirmHits: number().int().min(1).max(20).optional(),
14850
+ /** LABEL MODE: the window those frames must share, in seconds. Absent ⇒ 5. */
14851
+ confirmWindowSec: number().int().min(1).max(60).optional()
14755
14852
  });
14756
14853
  /**
14757
14854
  * Which zone-crossing DIRECTION a rule accepts (`ObjectEvent.zoneCrossing`).
@@ -16278,7 +16375,7 @@ var OauthIntegrationDescriptorSchema = object({
16278
16375
  */
16279
16376
  refreshTokenTtlSec: union([number().int().positive(), literal("never")]).optional()
16280
16377
  });
16281
- method(_void(), OauthIntegrationDescriptorSchema);
16378
+ method(_void(), OauthIntegrationDescriptorSchema, { auth: "admin" });
16282
16379
  /**
16283
16380
  * pipeline-analytics — device-scoped wrapper cap. Refines raw
16284
16381
  * per-frame detections emitted by the pipeline runner into tracked
@@ -17125,6 +17222,46 @@ var RecentTracksPageSchema = object({
17125
17222
  /** Cursor for the next page, or null when this page is the last. */
17126
17223
  nextCursor: string().nullable()
17127
17224
  });
17225
+ var LIST_GROUPS_DEFAULT_LIMIT = 40;
17226
+ var LIST_GROUPS_MAX_LIMIT = 100;
17227
+ var AnalyticsGroupRecordSchema = object({
17228
+ id: string(),
17229
+ deviceId: number().int(),
17230
+ openedAt: number().int(),
17231
+ closedAt: number().int(),
17232
+ timestamp: number().int(),
17233
+ memberCount: number().int(),
17234
+ memberTrackIds: array(string()).readonly(),
17235
+ className: string(),
17236
+ classes: array(string()).readonly(),
17237
+ /** Relative event-media path, or null when the group has no picture yet. */
17238
+ mediaUrl: string().nullable(),
17239
+ singleton: boolean()
17240
+ });
17241
+ var AnalyticsGroupMemberSchema = object({
17242
+ trackId: string(),
17243
+ deviceId: number().int(),
17244
+ className: string(),
17245
+ firstSeen: number().int(),
17246
+ lastSeen: number().int(),
17247
+ mediaUrl: string().nullable()
17248
+ });
17249
+ var AnalyticsGroupDetailSchema = AnalyticsGroupRecordSchema.extend({ members: array(AnalyticsGroupMemberSchema).readonly() });
17250
+ var ListGroupsQueryInput = object({
17251
+ /** Devices to merge. An empty array yields `{ groups: [], nextCursor: null }`. */
17252
+ deviceIds: array(number()),
17253
+ /** Window lower bound on `closedAt` (inclusive). */
17254
+ since: number().optional(),
17255
+ /** Window upper bound on `openedAt` (inclusive). */
17256
+ until: number().optional(),
17257
+ limit: number().int().min(1).max(LIST_GROUPS_MAX_LIMIT).default(LIST_GROUPS_DEFAULT_LIMIT),
17258
+ /** Opaque continuation cursor from a previous page's `nextCursor`. */
17259
+ cursor: string().optional()
17260
+ });
17261
+ var ListGroupsPageSchema = object({
17262
+ groups: array(AnalyticsGroupRecordSchema).readonly(),
17263
+ nextCursor: string().nullable()
17264
+ });
17128
17265
  var KeyEventQueryInput = object({
17129
17266
  deviceId: number(),
17130
17267
  /** Window lower bound (track firstSeen ≥ since). */
@@ -17200,7 +17337,9 @@ var TrackCascadeCountsSchema = object({
17200
17337
  /** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
17201
17338
  plates: number().int(),
17202
17339
  /** Per-track CLIP search vectors removed (best-effort). */
17203
- embeddings: number().int()
17340
+ embeddings: number().int(),
17341
+ /** Group membership + group rows removed with their last member (best-effort). */
17342
+ groups: number().int()
17204
17343
  });
17205
17344
  /** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
17206
17345
  var DiskReconcileCountsSchema = object({
@@ -17346,7 +17485,10 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
17346
17485
  * stationary registry). Default false: the timeline lists passages,
17347
17486
  * not parking records (operator decision, 2026-08-15). */
17348
17487
  includeStationary: boolean().optional()
17349
- }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
17488
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(ListGroupsQueryInput, ListGroupsPageSchema), method(object({
17489
+ deviceId: number(),
17490
+ groupId: string().min(1)
17491
+ }), AnalyticsGroupDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
17350
17492
  kind: "mutation",
17351
17493
  auth: "admin"
17352
17494
  }), 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({
@@ -17428,6 +17570,15 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
17428
17570
  }), method(object({ jobId: string() }), RelocateJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
17429
17571
  kind: "mutation",
17430
17572
  auth: "admin"
17573
+ }), method(RelocateMediaInputSchema, object({ jobId: string() }), {
17574
+ kind: "mutation",
17575
+ auth: "admin"
17576
+ }), method(object({}), array(RelocateJobSchema).readonly(), {
17577
+ kind: "query",
17578
+ auth: "admin"
17579
+ }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
17580
+ kind: "mutation",
17581
+ auth: "admin"
17431
17582
  }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
17432
17583
  kind: "query",
17433
17584
  auth: "admin"
@@ -17582,6 +17733,11 @@ object({
17582
17733
  "jpeg"
17583
17734
  ])
17584
17735
  });
17736
+ /**
17737
+ * Process-local frame identity. It is serializable so it can ride an in-process
17738
+ * capability call, but `registryId` deliberately prevents resolution in any
17739
+ * other process or execution group.
17740
+ */
17585
17741
  var FrameRefSchema = object({
17586
17742
  registryId: string().min(1),
17587
17743
  id: string().min(1),
@@ -17656,7 +17812,8 @@ var PipelineModelOptionSchema = object({
17656
17812
  sizeMB: number()
17657
17813
  })),
17658
17814
  group: ModelVariantGroupSchema.optional(),
17659
- legacy: boolean().optional()
17815
+ legacy: boolean().optional(),
17816
+ provider: ModelProviderIdSchema.optional()
17660
17817
  });
17661
17818
  var ConfigFieldBridge = custom();
17662
17819
  var PipelineAddonSchemaSchema = object({
@@ -19890,7 +20047,7 @@ method(object({
19890
20047
  * linking rather than produce an eternal token.
19891
20048
  */
19892
20049
  ttlSec: union([number().int().positive(), literal("never")]).optional()
19893
- }), object({ token: string() })), method(object({ token: string() }), SsoBridgeClaimsSchema.nullable());
20050
+ }), object({ token: string() }), { auth: "admin" }), method(object({ token: string() }), SsoBridgeClaimsSchema.nullable(), { auth: "admin" });
19894
20051
  var ProviderListEntrySchema = discriminatedUnion("shouldSaveDiskSpace", [object({
19895
20052
  providerId: string().min(1),
19896
20053
  displayName: string().min(1),
@@ -19985,10 +20142,13 @@ var EvictResultSchema = object({
19985
20142
  /** True when the provider has nothing left it is willing to drop on this location. */
19986
20143
  exhausted: boolean()
19987
20144
  });
19988
- method(object({ locationId: string() }), EvictableUsageSchema), method(object({
20145
+ method(object({ locationId: string() }), EvictableUsageSchema, { auth: "admin" }), method(object({
19989
20146
  locationId: string(),
19990
20147
  targetBytes: number().int().positive()
19991
- }), EvictResultSchema, { kind: "mutation" });
20148
+ }), EvictResultSchema, {
20149
+ kind: "mutation",
20150
+ auth: "admin"
20151
+ });
19992
20152
  method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin" }), method(StorageMigrationInputSchema, object({ jobId: string() }), {
19993
20153
  kind: "mutation",
19994
20154
  auth: "admin"
@@ -20048,26 +20208,50 @@ var ReadChunkInputSchema = object({
20048
20208
  length: number()
20049
20209
  });
20050
20210
  var EndDownloadInputSchema = object({ downloadId: string() });
20051
- method(_void(), ProviderInfoSchema), method(object({ config: record(string(), unknown()) }), TestLocationResultSchema, { auth: "admin" }), method(object({
20211
+ method(_void(), ProviderInfoSchema, { auth: "admin" }), method(object({ config: record(string(), unknown()) }), TestLocationResultSchema, { auth: "admin" }), method(object({
20052
20212
  location: StorageLocationSchema,
20053
20213
  relativePath: string()
20054
- }), string()), method(object({
20214
+ }), string(), { auth: "admin" }), method(object({
20055
20215
  location: StorageLocationSchema,
20056
20216
  relativePath: string(),
20057
20217
  data: _instanceof(Uint8Array)
20058
- }), _void(), { kind: "mutation" }), method(object({
20218
+ }), _void(), {
20219
+ kind: "mutation",
20220
+ auth: "admin"
20221
+ }), method(object({
20059
20222
  location: StorageLocationSchema,
20060
20223
  relativePath: string()
20061
- }), _instanceof(Uint8Array)), method(object({
20224
+ }), _instanceof(Uint8Array), { auth: "admin" }), method(object({
20062
20225
  location: StorageLocationSchema,
20063
20226
  relativePath: string()
20064
- }), boolean()), method(object({
20227
+ }), boolean(), { auth: "admin" }), method(object({
20065
20228
  location: StorageLocationSchema,
20066
20229
  prefix: string().optional()
20067
- }), array(string()).readonly()), method(object({
20230
+ }), array(string()).readonly(), { auth: "admin" }), method(object({
20068
20231
  location: StorageLocationSchema,
20069
20232
  relativePath: string()
20070
- }), _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" });
20233
+ }), _void(), {
20234
+ kind: "mutation",
20235
+ auth: "admin"
20236
+ }), method(object({ location: StorageLocationSchema }), number().nullable(), { auth: "admin" }), method(BeginUploadInputSchema, BeginUploadResultSchema, {
20237
+ kind: "mutation",
20238
+ auth: "admin"
20239
+ }), method(WriteChunkInputSchema, _void(), {
20240
+ kind: "mutation",
20241
+ auth: "admin"
20242
+ }), method(FinalizeUploadInputSchema, _void(), {
20243
+ kind: "mutation",
20244
+ auth: "admin"
20245
+ }), method(AbortUploadInputSchema, _void(), {
20246
+ kind: "mutation",
20247
+ auth: "admin"
20248
+ }), method(BeginDownloadInputSchema, BeginDownloadResultSchema, {
20249
+ kind: "mutation",
20250
+ auth: "admin"
20251
+ }), method(ReadChunkInputSchema, _instanceof(Uint8Array), { auth: "admin" }), method(EndDownloadInputSchema, _void(), {
20252
+ kind: "mutation",
20253
+ auth: "admin"
20254
+ });
20071
20255
  /** Profile-exported FormBuilder schema. Shape is ConfigUISchema at the UI. */
20072
20256
  var ProfileSettingsSchemaBridge = unknown().nullable();
20073
20257
  var ProfileSettingsBagSchema = record(string(), unknown());
@@ -20325,7 +20509,8 @@ method(object({
20325
20509
  access: "create"
20326
20510
  }), method(object({ userId: string().optional() }), object({ optionsJSON: record(string(), unknown()) }), {
20327
20511
  kind: "mutation",
20328
- access: "view"
20512
+ access: "view",
20513
+ auth: "admin"
20329
20514
  }), method(object({
20330
20515
  /** Required — the user the assertion belongs to (verified). */
20331
20516
  userId: string(),
@@ -20333,10 +20518,12 @@ method(object({
20333
20518
  response: record(string(), unknown())
20334
20519
  }), object({ verified: boolean() }), {
20335
20520
  kind: "mutation",
20336
- access: "view"
20521
+ access: "view",
20522
+ auth: "admin"
20337
20523
  }), method(object({}), object({ optionsJSON: record(string(), unknown()) }), {
20338
20524
  kind: "mutation",
20339
- access: "view"
20525
+ access: "view",
20526
+ auth: "admin"
20340
20527
  }), method(object({
20341
20528
  /** AuthenticationResponseJSON from the browser. */
20342
20529
  response: record(string(), unknown()) }), object({
@@ -20344,7 +20531,8 @@ response: record(string(), unknown()) }), object({
20344
20531
  userId: string().nullable()
20345
20532
  }), {
20346
20533
  kind: "mutation",
20347
- access: "view"
20534
+ access: "view",
20535
+ auth: "admin"
20348
20536
  }), method(object({ userId: string() }), array(PasskeySummarySchema), { auth: "admin" }), method(object({
20349
20537
  userId: string(),
20350
20538
  credentialId: string()
@@ -20516,7 +20704,19 @@ var VectorStatsResultSchema = object({
20516
20704
  /** False when the backend ranks approximately. */
20517
20705
  exact: boolean()
20518
20706
  });
20519
- 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);
20707
+ method(VectorDeclareIndexInputSchema, _void(), {
20708
+ kind: "mutation",
20709
+ auth: "admin"
20710
+ }), method(VectorUpsertInputSchema, VectorUpsertResultSchema, {
20711
+ kind: "mutation",
20712
+ auth: "admin"
20713
+ }), method(VectorQueryInputSchema, VectorQueryResultSchema, { auth: "admin" }), method(VectorGetInputSchema, VectorGetResultSchema, { auth: "admin" }), method(VectorDeleteInputSchema, VectorDeleteResultSchema, {
20714
+ kind: "mutation",
20715
+ auth: "admin"
20716
+ }), method(VectorDeleteByFilterInputSchema, VectorDeleteResultSchema, {
20717
+ kind: "mutation",
20718
+ auth: "admin"
20719
+ }), method(VectorStatsInputSchema, VectorStatsResultSchema, { auth: "admin" });
20520
20720
  var ClipSchema = object({
20521
20721
  /** Opaque, provider-namespaced id. The default provider encodes the time
20522
20722
  * window so `getClipPlayback` is self-contained (no event re-query). */
@@ -22977,7 +23177,27 @@ var MediaFileLiteSchema$1 = object({
22977
23177
  sizeBytes: number(),
22978
23178
  timestamp: number()
22979
23179
  });
22980
- method(_void(), array(IdentitySchema).readonly()), method(object({ name: string().min(1) }), IdentitySchema, {
23180
+ method(object({
23181
+ /**
23182
+ * Inline {@link IdentitySchema.coverBase64} on every row.
23183
+ *
23184
+ * Default `false`, the same inversion `listRecentFaces` and
23185
+ * `listPlates` took on 2026-08-25 (see `include-crops-default.ts` for
23186
+ * why the burden belongs on the caller that WANTS the bytes). Measured
23187
+ * on the live hub the same day: four identities cost 40,979 B with the
23188
+ * covers inline, ~10 KB of base64 per row, on a query this UI mounts
23189
+ * four times and the viewer holds at `staleTime: 30_000`.
23190
+ *
23191
+ * Nothing loses its avatar: `coverMediaKey` is already on every row and
23192
+ * the `event-media` plane serves that key `immutable` with an ETag.
23193
+ *
23194
+ * **This is an INPUT field, so it does not reach the addon until the
23195
+ * next train** — the hub router validates cap inputs against its own
23196
+ * compiled Zod and strips a key it does not know. Until then the
23197
+ * provider sees `undefined`, which resolves to `false`: the cheap shape
23198
+ * is what ships, and the opt-in becomes reachable when the train lands.
23199
+ */
23200
+ includeCrops: boolean().optional() }).optional(), array(IdentitySchema).readonly()), method(object({ name: string().min(1) }), IdentitySchema, {
22981
23201
  kind: "mutation",
22982
23202
  auth: "admin"
22983
23203
  }), method(object({
@@ -25865,7 +26085,14 @@ var PlateInfoSchema = object({
25865
26085
  plateBbox: BoundingBoxSchema.optional(),
25866
26086
  /** keyFrame parity: MediaStore key of the track's native-resolution key frame. */
25867
26087
  keyFrameMediaKey: string().optional(),
25868
- base64: string().optional()
26088
+ base64: string().optional(),
26089
+ /**
26090
+ * Same crop as a data-plane URL, always present when the plate has a stored
26091
+ * crop. `getPlateByTrack` returns this and never inlines JPEG; `listPlates`
26092
+ * and `searchPlates` inline the crop only when their `includeCrops` input is
26093
+ * left at its `true` default.
26094
+ */
26095
+ cropUrl: string().optional()
25869
26096
  });
25870
26097
  var MediaFileLiteSchema = object({
25871
26098
  key: string(),
@@ -25883,14 +26110,34 @@ var PlateClusterSchema = object({
25883
26110
  });
25884
26111
  method(object({
25885
26112
  deviceId: number().int().optional(),
25886
- limit: number().int().positive().optional()
26113
+ limit: number().int().positive().optional(),
26114
+ /**
26115
+ * Inline the base64 crop on every row. Default `true` — the existing
26116
+ * behaviour, kept so no caller breaks.
26117
+ *
26118
+ * Set `false` once the caller renders {@link PlateInfo.cropUrl}.
26119
+ * Measured on the live hub at the 500 rows the Plates view asks for:
26120
+ * 879,403 B and 27.7 s with the crops inline, against a few KiB of
26121
+ * metadata without them — and the browser then caches the images.
26122
+ *
26123
+ * This is the plate twin of `faceGallery.listRecentFaces`'s option;
26124
+ * plates were the one gallery list left without it.
26125
+ *
26126
+ * **This is an INPUT field, so it does not reach the addon until the
26127
+ * next train.** The hub router validates cap inputs against its own
26128
+ * compiled Zod and strips a key it does not know. Until the train
26129
+ * ships, sending `false` is harmless and keeps the crops inline.
26130
+ */
26131
+ includeCrops: boolean().optional()
25887
26132
  }).optional(), array(PlateInfoSchema).readonly()), method(object({
25888
26133
  deviceId: number().int(),
25889
26134
  trackId: string()
25890
26135
  }), PlateInfoSchema.nullable()), method(object({ plateId: string() }), array(MediaFileLiteSchema).readonly()), method(object({
25891
26136
  text: string().min(1),
25892
26137
  maxDistance: number().int().min(0).optional(),
25893
- limit: number().int().positive().optional()
26138
+ limit: number().int().positive().optional(),
26139
+ /** See `listPlates.includeCrops`. Default `true`. */
26140
+ includeCrops: boolean().optional()
25894
26141
  }), array(PlateInfoSchema).readonly()), method(object({
25895
26142
  maxDistance: number().int().min(0).optional(),
25896
26143
  minClusterSize: number().int().min(2).optional(),
@@ -25904,7 +26151,13 @@ method(object({
25904
26151
  }), method(object({ plateId: string() }), _void(), {
25905
26152
  kind: "mutation",
25906
26153
  auth: "admin"
25907
- }), method(_void(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
26154
+ }), method(object({
26155
+ /** Inline {@link VehicleSchema.coverBase64} on every row. Default
26156
+ * `false` — the vehicle twin of `faceGallery.listIdentities`'s
26157
+ * option; `coverMediaKey` + the `event-media` plane carry the picture.
26158
+ * INPUT field: stripped by the hub router until the train ships, which
26159
+ * resolves to `false` and is exactly the intended default. */
26160
+ includeCrops: boolean().optional() }).optional(), array(VehicleSchema).readonly()), method(object({ name: string().min(1) }), VehicleSchema, {
25908
26161
  kind: "mutation",
25909
26162
  auth: "admin"
25910
26163
  }), method(object({
@@ -31389,6 +31642,12 @@ Object.freeze({
31389
31642
  addonId: null,
31390
31643
  access: "view"
31391
31644
  },
31645
+ "deviceManager.getBindingsBatch": {
31646
+ capName: "device-manager",
31647
+ capScope: "system",
31648
+ addonId: null,
31649
+ access: "view"
31650
+ },
31392
31651
  "deviceManager.getChildren": {
31393
31652
  capName: "device-manager",
31394
31653
  capScope: "system",
@@ -31449,6 +31708,12 @@ Object.freeze({
31449
31708
  addonId: null,
31450
31709
  access: "view"
31451
31710
  },
31711
+ "deviceManager.getLinkedDevicesBatch": {
31712
+ capName: "device-manager",
31713
+ capScope: "system",
31714
+ addonId: null,
31715
+ access: "view"
31716
+ },
31452
31717
  "deviceManager.getRoleDisplayDefaults": {
31453
31718
  capName: "device-manager",
31454
31719
  capScope: "system",
@@ -33153,6 +33418,12 @@ Object.freeze({
33153
33418
  addonId: null,
33154
33419
  access: "create"
33155
33420
  },
33421
+ "pipelineAnalytics.cancelRelocateMedia": {
33422
+ capName: "pipeline-analytics",
33423
+ capScope: "device",
33424
+ addonId: null,
33425
+ access: "create"
33426
+ },
33156
33427
  "pipelineAnalytics.cancelStorageMigrationMove": {
33157
33428
  capName: "pipeline-analytics",
33158
33429
  capScope: "device",
@@ -33219,6 +33490,12 @@ Object.freeze({
33219
33490
  addonId: null,
33220
33491
  access: "view"
33221
33492
  },
33493
+ "pipelineAnalytics.getGroup": {
33494
+ capName: "pipeline-analytics",
33495
+ capScope: "device",
33496
+ addonId: null,
33497
+ access: "view"
33498
+ },
33222
33499
  "pipelineAnalytics.getKeyEvents": {
33223
33500
  capName: "pipeline-analytics",
33224
33501
  capScope: "device",
@@ -33303,6 +33580,12 @@ Object.freeze({
33303
33580
  addonId: null,
33304
33581
  access: "view"
33305
33582
  },
33583
+ "pipelineAnalytics.listGroups": {
33584
+ capName: "pipeline-analytics",
33585
+ capScope: "device",
33586
+ addonId: null,
33587
+ access: "view"
33588
+ },
33306
33589
  "pipelineAnalytics.listOpsLog": {
33307
33590
  capName: "pipeline-analytics",
33308
33591
  capScope: "device",
@@ -33315,6 +33598,12 @@ Object.freeze({
33315
33598
  addonId: null,
33316
33599
  access: "view"
33317
33600
  },
33601
+ "pipelineAnalytics.listRelocateMediaJobs": {
33602
+ capName: "pipeline-analytics",
33603
+ capScope: "device",
33604
+ addonId: null,
33605
+ access: "view"
33606
+ },
33318
33607
  "pipelineAnalytics.listRetrainAnnotations": {
33319
33608
  capName: "pipeline-analytics",
33320
33609
  capScope: "device",
@@ -33393,6 +33682,12 @@ Object.freeze({
33393
33682
  addonId: null,
33394
33683
  access: "create"
33395
33684
  },
33685
+ "pipelineAnalytics.relocateMedia": {
33686
+ capName: "pipeline-analytics",
33687
+ capScope: "device",
33688
+ addonId: null,
33689
+ access: "create"
33690
+ },
33396
33691
  "pipelineAnalytics.restageRetrainTrack": {
33397
33692
  capName: "pipeline-analytics",
33398
33693
  capScope: "device",
@@ -36084,6 +36379,11 @@ Object.freeze({
36084
36379
  form: "single",
36085
36380
  optional: false
36086
36381
  }],
36382
+ "deviceManager.getBindingsBatch": [{
36383
+ name: "deviceIds",
36384
+ form: "array",
36385
+ optional: false
36386
+ }],
36087
36387
  "deviceManager.getChildren": [{
36088
36388
  name: "parentDeviceId",
36089
36389
  form: "single",
@@ -36129,6 +36429,11 @@ Object.freeze({
36129
36429
  form: "single",
36130
36430
  optional: false
36131
36431
  }],
36432
+ "deviceManager.getLinkedDevicesBatch": [{
36433
+ name: "deviceIds",
36434
+ form: "array",
36435
+ optional: false
36436
+ }],
36132
36437
  "deviceManager.getSettingsSchema": [{
36133
36438
  name: "deviceId",
36134
36439
  form: "single",
@@ -36149,6 +36454,11 @@ Object.freeze({
36149
36454
  form: "single",
36150
36455
  optional: false
36151
36456
  }],
36457
+ "deviceManager.listAll": [{
36458
+ name: "deviceIds",
36459
+ form: "array",
36460
+ optional: true
36461
+ }],
36152
36462
  "deviceManager.loadConfig": [{
36153
36463
  name: "deviceId",
36154
36464
  form: "single",
@@ -36722,6 +37032,11 @@ Object.freeze({
36722
37032
  form: "single",
36723
37033
  optional: false
36724
37034
  }],
37035
+ "pipelineAnalytics.getGroup": [{
37036
+ name: "deviceId",
37037
+ form: "single",
37038
+ optional: false
37039
+ }],
36725
37040
  "pipelineAnalytics.getKeyEvents": [{
36726
37041
  name: "deviceId",
36727
37042
  form: "single",
@@ -36777,6 +37092,11 @@ Object.freeze({
36777
37092
  form: "array",
36778
37093
  optional: false
36779
37094
  }],
37095
+ "pipelineAnalytics.listGroups": [{
37096
+ name: "deviceIds",
37097
+ form: "array",
37098
+ optional: false
37099
+ }],
36780
37100
  "pipelineAnalytics.listOpsLog": [{
36781
37101
  name: "deviceId",
36782
37102
  form: "single",