@camstack/addon-export-hap 1.2.60 → 1.2.61

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.
@@ -8762,6 +8762,13 @@ var MediaRelocateModeSchema = _enum([
8762
8762
  ]);
8763
8763
  var RelocateMediaInputSchema = object({
8764
8764
  toLocationId: string(),
8765
+ /**
8766
+ * Restrict the pass to rows currently on this location. Omitted / `'*'` =
8767
+ * every row that is not already on `toLocationId` (the historical
8768
+ * behaviour). A named source is what a from→to migration needs: without it
8769
+ * "move events off disk 2" also emptied disk 1.
8770
+ */
8771
+ fromLocationId: string().optional(),
8765
8772
  throttleMbps: number().min(1).max(1e3).optional(),
8766
8773
  /** Omitted = `move`, the pre-existing behaviour. */
8767
8774
  mode: MediaRelocateModeSchema.optional()
@@ -8829,6 +8836,19 @@ var StorageMigrationDestinationsSchema = object({
8829
8836
  galleryMedia: string().min(1).optional()
8830
8837
  }).refine((value) => Object.keys(value).length > 0, { message: "select at least one storage class" });
8831
8838
  /**
8839
+ * Optional named source per class. Omitted = the class's current default
8840
+ * (the historical behaviour). A named source that is NOT the default is a
8841
+ * drain of that disk: bytes move, the default stays, and the source is
8842
+ * disabled when the move finishes.
8843
+ */
8844
+ var StorageMigrationSourcesSchema = object({
8845
+ recordings: string().min(1).optional(),
8846
+ recordingsLow: string().min(1).optional(),
8847
+ eventMedia: string().min(1).optional(),
8848
+ backups: string().min(1).optional(),
8849
+ galleryMedia: string().min(1).optional()
8850
+ }).optional();
8851
+ /**
8832
8852
  * How a migration sequences the cutover against the byte move.
8833
8853
  *
8834
8854
  * - `blocking` — the historical order: pause, move every byte, repoint,
@@ -8850,6 +8870,8 @@ var StorageMigrationModeSchema = _enum(["blocking", "nonBlocking"]);
8850
8870
  /** Shared input for planning and starting an orchestrated storage migration. */
8851
8871
  var StorageMigrationInputSchema = object({
8852
8872
  destinations: StorageMigrationDestinationsSchema,
8873
+ /** Omitted = each class's current default. */
8874
+ sources: StorageMigrationSourcesSchema,
8853
8875
  throttleMbps: number().min(1).max(1e3).optional(),
8854
8876
  /** Omitted = `blocking`, which stays the default. */
8855
8877
  mode: StorageMigrationModeSchema.optional()
@@ -8929,6 +8951,13 @@ var StorageMigrationMoveSchema = object({
8929
8951
  storageClass: StorageMigrationClassSchema,
8930
8952
  fromLocationId: string(),
8931
8953
  toLocationId: string(),
8954
+ /**
8955
+ * True when `from` was NOT the class default at plan time. The move still
8956
+ * copies bytes, but the default is left alone and the source is disabled
8957
+ * once the copy verifies. Absent on jobs planned before this field existed
8958
+ * — those jobs always repointed, which is `false`.
8959
+ */
8960
+ freezeSource: boolean().optional(),
8932
8961
  moverJobId: string().nullable(),
8933
8962
  state: RelocateJobStateSchema.nullable(),
8934
8963
  error: string().nullable(),
@@ -8942,6 +8971,7 @@ var StorageMigrationJobSchema = object({
8942
8971
  * can tell a seconds-long cutover from a thirty-hour one. */
8943
8972
  mode: StorageMigrationModeSchema,
8944
8973
  destinations: StorageMigrationDestinationsSchema,
8974
+ sources: StorageMigrationSourcesSchema,
8945
8975
  throttleMbps: number(),
8946
8976
  moves: array(StorageMigrationMoveSchema),
8947
8977
  pauseLeaseId: string().nullable(),
@@ -8967,6 +8997,7 @@ var StorageMigrationFindingSchema = object({
8967
8997
  });
8968
8998
  var StorageMigrationPlanSchema = object({
8969
8999
  destinations: StorageMigrationDestinationsSchema,
9000
+ sources: StorageMigrationSourcesSchema,
8970
9001
  /** The mode this plan was built for. A plan is only valid for its mode: the
8971
9002
  * `eventMedia` seal gate and the single-cardinality refusal both depend on
8972
9003
  * it. */
@@ -8974,7 +9005,8 @@ var StorageMigrationPlanSchema = object({
8974
9005
  moves: array(object({
8975
9006
  storageClass: StorageMigrationClassSchema,
8976
9007
  fromLocationId: string(),
8977
- toLocationId: string()
9008
+ toLocationId: string(),
9009
+ freezeSource: boolean().optional()
8978
9010
  })),
8979
9011
  findings: array(StorageMigrationFindingSchema)
8980
9012
  });
@@ -9152,10 +9184,51 @@ var LedgerWalkReportSchema = object({
9152
9184
  var RelocatableMediaCountSchema = object({ rows: number().int().nonnegative() }).nullable();
9153
9185
  var RelocatableMediaCountInputSchema = object({
9154
9186
  toLocationId: string().min(1),
9187
+ /** Restrict the count to one source; omitted / `'*'` = every non-target row. */
9188
+ fromLocationId: string().optional(),
9155
9189
  /** Omitted = `move`. */
9156
9190
  mode: MediaRelocateModeSchema.optional()
9157
9191
  });
9158
9192
  /**
9193
+ * Operator cleanup of leftover analytics rows, optional debug media, and
9194
+ * ghost ledger entries on frozen footage locations.
9195
+ *
9196
+ * A pass is tens of minutes on a standing backlog. The hub method RETURNS
9197
+ * `{ jobId }` immediately; progress is `cleanupStatus`. Awaiting the work
9198
+ * is how `addons.custom` hit the 60 s UDS deadline while reclaim continued
9199
+ * with no operator-visible status.
9200
+ */
9201
+ var StorageCleanupPhaseSchema = _enum([
9202
+ "orphans",
9203
+ "debug-media",
9204
+ "ghost-ledger",
9205
+ "done",
9206
+ "failed",
9207
+ "cancelled"
9208
+ ]);
9209
+ var StorageCleanupInputSchema = object({
9210
+ /** Also walk motion stills / track filmstrips. Off by default. */
9211
+ includeDebugMedia: boolean().optional() });
9212
+ var StorageCleanupJobSchema = object({
9213
+ jobId: string(),
9214
+ phase: StorageCleanupPhaseSchema,
9215
+ includeDebugMedia: boolean(),
9216
+ orphansReclaimed: number().int().nonnegative(),
9217
+ orphanBytesReclaimed: number().int().nonnegative(),
9218
+ debugMediaReclaimed: number().int().nonnegative(),
9219
+ debugMediaBytesReclaimed: number().int().nonnegative(),
9220
+ ghostsForgotten: number().int().nonnegative(),
9221
+ ghostBytesForgotten: number().int().nonnegative(),
9222
+ /** Short operator-facing line: current collection, pass, or location. */
9223
+ detail: string().nullable(),
9224
+ cancelRequested: boolean(),
9225
+ startedAt: number(),
9226
+ updatedAt: number(),
9227
+ finishedAt: number().nullable(),
9228
+ error: string().nullable()
9229
+ });
9230
+ var StorageCleanupStatusInputSchema = object({ jobId: string().optional() });
9231
+ /**
9159
9232
  * `StorageLocationType` — an addon-declared id that identifies the *kind* of
9160
9233
  * storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
9161
9234
  * so the persisted record schema and the consumer-facing cap can both consume it
@@ -9183,11 +9256,10 @@ var StorageLocationTypeSchema = string().regex(/^[a-z][a-zA-Z0-9-]*$/);
9183
9256
  * The default location for a type uses `id === <type>:default` by
9184
9257
  * convention (the bare type ref like `'backups'` resolves to it).
9185
9258
  *
9186
- * `isSystem: true` marks a location as orchestrator-seeded and
9187
- * undeletable. The bootstrap-installed defaults (one per type) carry
9188
- * this flag; operator-added locations don't. Editing the config of
9189
- * a system location is allowed (path migration, provider swap) but
9190
- * deleting it is rejected at the cap level.
9259
+ * `isSystem` is a legacy persisted flag. Seed still creates the initial
9260
+ * `<type>:default` locations; the flag is no longer a lock, a badge, or a
9261
+ * prune selector. New writes leave it false. Deletion is gated on uniqueness
9262
+ * / last-enabled, not on this bit.
9191
9263
  */
9192
9264
  var StorageLocationSchema = object({
9193
9265
  id: string().regex(/^[a-z][a-zA-Z0-9-]*:[a-zA-Z0-9-]+$/),
@@ -13584,6 +13656,12 @@ method(object({
13584
13656
  }), _void(), {
13585
13657
  kind: "mutation",
13586
13658
  auth: "admin"
13659
+ }), method(object({
13660
+ from: string(),
13661
+ to: string()
13662
+ }), object({ moved: number() }), {
13663
+ kind: "mutation",
13664
+ auth: "admin"
13587
13665
  }), method(object({
13588
13666
  deviceId: number(),
13589
13667
  disabled: boolean()
@@ -19514,46 +19592,6 @@ var RecentTracksPageSchema = object({
19514
19592
  /** Cursor for the next page, or null when this page is the last. */
19515
19593
  nextCursor: string().nullable()
19516
19594
  });
19517
- var LIST_GROUPS_DEFAULT_LIMIT = 40;
19518
- var LIST_GROUPS_MAX_LIMIT = 100;
19519
- var AnalyticsGroupRecordSchema = object({
19520
- id: string(),
19521
- deviceId: number().int(),
19522
- openedAt: number().int(),
19523
- closedAt: number().int(),
19524
- timestamp: number().int(),
19525
- memberCount: number().int(),
19526
- memberTrackIds: array(string()).readonly(),
19527
- className: string(),
19528
- classes: array(string()).readonly(),
19529
- /** Relative event-media path, or null when the group has no picture yet. */
19530
- mediaUrl: string().nullable(),
19531
- singleton: boolean()
19532
- });
19533
- var AnalyticsGroupMemberSchema = object({
19534
- trackId: string(),
19535
- deviceId: number().int(),
19536
- className: string(),
19537
- firstSeen: number().int(),
19538
- lastSeen: number().int(),
19539
- mediaUrl: string().nullable()
19540
- });
19541
- var AnalyticsGroupDetailSchema = AnalyticsGroupRecordSchema.extend({ members: array(AnalyticsGroupMemberSchema).readonly() });
19542
- var ListGroupsQueryInput = object({
19543
- /** Devices to merge. An empty array yields `{ groups: [], nextCursor: null }`. */
19544
- deviceIds: array(number()),
19545
- /** Window lower bound on `closedAt` (inclusive). */
19546
- since: number().optional(),
19547
- /** Window upper bound on `openedAt` (inclusive). */
19548
- until: number().optional(),
19549
- limit: number().int().min(1).max(LIST_GROUPS_MAX_LIMIT).default(LIST_GROUPS_DEFAULT_LIMIT),
19550
- /** Opaque continuation cursor from a previous page's `nextCursor`. */
19551
- cursor: string().optional()
19552
- });
19553
- var ListGroupsPageSchema = object({
19554
- groups: array(AnalyticsGroupRecordSchema).readonly(),
19555
- nextCursor: string().nullable()
19556
- });
19557
19595
  var KEY_EVENTS_DEFAULT_LIMIT = 50;
19558
19596
  var KEY_EVENTS_MAX_LIMIT = 200;
19559
19597
  var KeyEventQueryInput = object({
@@ -19657,9 +19695,7 @@ var TrackCascadeCountsSchema = object({
19657
19695
  /** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
19658
19696
  plates: number().int(),
19659
19697
  /** Per-track CLIP search vectors removed (best-effort). */
19660
- embeddings: number().int(),
19661
- /** Group membership + group rows removed with their last member (best-effort). */
19662
- groups: number().int()
19698
+ embeddings: number().int()
19663
19699
  });
19664
19700
  /** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
19665
19701
  var DiskReconcileCountsSchema = object({
@@ -19829,6 +19865,47 @@ var RebuildStatusSchema = object({
19829
19865
  /** Present when the pass ended by throwing. */
19830
19866
  error: string().nullable()
19831
19867
  });
19868
+ /**
19869
+ * Acknowledgement that a debug-media reclaim STARTED.
19870
+ *
19871
+ * The pass is paced at ~2 MB/s over a standing 100 GB — tens of minutes — so
19872
+ * it runs detached and this returns immediately. Awaiting it is how the
19873
+ * `addons.custom` door hit the 60 s UDS deadline while the walk carried on
19874
+ * with no status. Poll {@link pipelineAnalyticsCapability.methods.getMediaReclaimStatus}.
19875
+ */
19876
+ var MediaReclaimStartResultSchema = object({
19877
+ started: boolean(),
19878
+ /** True when a pass was already running; the new request is ignored. */
19879
+ alreadyRunning: boolean()
19880
+ });
19881
+ var MediaReclaimInputSchema = object({
19882
+ mode: _enum(["report", "reclaim"]).default("report"),
19883
+ scopes: array(_enum(["motion-still", "track-filmstrip"])).min(1).optional(),
19884
+ deviceIds: array(number().int()).min(1).optional(),
19885
+ restart: boolean().optional(),
19886
+ pageSize: number().int().min(50).max(5e3).optional(),
19887
+ maxRowsPerDevice: number().int().min(1).max(5e5).optional(),
19888
+ maxReclaimPerDevice: number().int().min(1).max(5e5).optional(),
19889
+ maxBytesPerRun: number().int().min(1).optional(),
19890
+ budgetMinutes: number().int().min(1).max(720).optional(),
19891
+ throttleBytesPerSec: number().int().min(64 * 1024).optional(),
19892
+ graceMinutes: number().int().min(1).max(10080).optional()
19893
+ });
19894
+ var MediaReclaimStatusSchema = object({
19895
+ running: boolean(),
19896
+ mode: _enum(["report", "reclaim"]).nullable(),
19897
+ totalExamined: number(),
19898
+ totalEligible: number(),
19899
+ totalReclaimed: number(),
19900
+ totalBytesReclaimed: number(),
19901
+ totalRefused: number(),
19902
+ /** Device+scope windows finished in this pass. */
19903
+ devicesDone: number(),
19904
+ complete: boolean().nullable(),
19905
+ startedAtMs: number().nullable(),
19906
+ finishedAtMs: number().nullable(),
19907
+ error: string().nullable()
19908
+ });
19832
19909
  var ReplayFrameInputSchema = object({
19833
19910
  timestamp: number(),
19834
19911
  frame: PipelineRunResultBridge
@@ -19867,10 +19944,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19867
19944
  * stationary registry). Default false: the timeline lists passages,
19868
19945
  * not parking records (operator decision, 2026-08-15). */
19869
19946
  includeStationary: boolean().optional()
19870
- }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(ListGroupsQueryInput, ListGroupsPageSchema), method(object({
19871
- deviceId: number(),
19872
- groupId: string().min(1)
19873
- }), AnalyticsGroupDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
19947
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
19874
19948
  kind: "mutation",
19875
19949
  auth: "admin"
19876
19950
  }), 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({
@@ -19970,6 +20044,12 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19970
20044
  }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
19971
20045
  kind: "query",
19972
20046
  auth: "admin"
20047
+ }), method(MediaReclaimInputSchema, MediaReclaimStartResultSchema, {
20048
+ kind: "mutation",
20049
+ auth: "admin"
20050
+ }), method(object({}), MediaReclaimStatusSchema, {
20051
+ kind: "query",
20052
+ auth: "admin"
19973
20053
  }), method(object({ deviceIds: array(number()).optional() }), TrainingExportSummarySchema, {
19974
20054
  kind: "query",
19975
20055
  auth: "admin"
@@ -21940,7 +22020,13 @@ method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin"
21940
22020
  }), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
21941
22021
  kind: "mutation",
21942
22022
  auth: "admin"
21943
- });
22023
+ }), method(StorageCleanupInputSchema, object({ jobId: string() }), {
22024
+ kind: "mutation",
22025
+ auth: "admin"
22026
+ }), method(StorageCleanupStatusInputSchema, StorageCleanupJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
22027
+ kind: "mutation",
22028
+ auth: "admin"
22029
+ }), method(object({}), array(StorageMigrationJobSchema).readonly(), { auth: "admin" });
21944
22030
  var ProviderInfoSchema = discriminatedUnion("shouldSaveDiskSpace", [object({
21945
22031
  providerId: string().min(1),
21946
22032
  displayName: string().min(1),
@@ -27366,6 +27452,33 @@ var RecordingRebalanceInputSchema = object({
27366
27452
  minMoveGb: number().min(0).optional()
27367
27453
  });
27368
27454
  /**
27455
+ * Operator-facing placement of one camera onto a recordings location.
27456
+ *
27457
+ * `pinLocationId` is the operator instruction: a location id, or `null` for
27458
+ * Auto (the planner may move this camera). `locationId` is where high/mid
27459
+ * currently write — the plan, which may disagree with the pin when Auto.
27460
+ */
27461
+ var RecordingDevicePlacementSchema = object({
27462
+ deviceId: number().int(),
27463
+ profile: string(),
27464
+ locationId: string()
27465
+ });
27466
+ var RecordingDevicePinSchema = object({
27467
+ deviceId: number().int(),
27468
+ /** Recordings-class location this camera is pinned to. */
27469
+ locationId: string()
27470
+ });
27471
+ var RecordingPlacementViewSchema = object({
27472
+ assignments: array(RecordingDevicePlacementSchema),
27473
+ pins: array(RecordingDevicePinSchema),
27474
+ defaultLocations: record(string(), string())
27475
+ });
27476
+ var RecordingSetDevicePlacementInputSchema = object({
27477
+ deviceId: number().int(),
27478
+ /** `null` = Auto. Otherwise a `recordings:*` location id. */
27479
+ locationId: string().nullable()
27480
+ });
27481
+ /**
27369
27482
  * Result of locating footage at a wall-clock instant for one device/profile.
27370
27483
  * `segment` carries the covering segment's window; `gap` reports the forward
27371
27484
  * nearest covered edge (`null` past the end of footage / when none exists)
@@ -27591,6 +27704,12 @@ method(object({
27591
27704
  }), method(RecordingRebalanceInputSchema, RecordingRebalancePlanSchema, {
27592
27705
  kind: "mutation",
27593
27706
  auth: "admin"
27707
+ }), method(object({}), RecordingPlacementViewSchema, {
27708
+ kind: "query",
27709
+ auth: "admin"
27710
+ }), method(RecordingSetDevicePlacementInputSchema, object({ ok: literal(true) }), {
27711
+ kind: "mutation",
27712
+ auth: "admin"
27594
27713
  });
27595
27714
  /**
27596
27715
  * `recording-export` cap — render a footage time range into a single downloadable
@@ -30986,6 +31105,12 @@ Object.freeze({
30986
31105
  addonId: null,
30987
31106
  access: "delete"
30988
31107
  },
31108
+ "deviceManager.renameLocation": {
31109
+ capName: "device-manager",
31110
+ capScope: "system",
31111
+ addonId: null,
31112
+ access: "create"
31113
+ },
30989
31114
  "deviceManager.runDeviceAction": {
30990
31115
  capName: "device-manager",
30991
31116
  capScope: "system",
@@ -32678,19 +32803,19 @@ Object.freeze({
32678
32803
  addonId: null,
32679
32804
  access: "view"
32680
32805
  },
32681
- "pipelineAnalytics.getGroup": {
32806
+ "pipelineAnalytics.getKeyEvents": {
32682
32807
  capName: "pipeline-analytics",
32683
32808
  capScope: "device",
32684
32809
  addonId: null,
32685
32810
  access: "view"
32686
32811
  },
32687
- "pipelineAnalytics.getKeyEvents": {
32812
+ "pipelineAnalytics.getKeyEventsBatch": {
32688
32813
  capName: "pipeline-analytics",
32689
32814
  capScope: "device",
32690
32815
  addonId: null,
32691
32816
  access: "view"
32692
32817
  },
32693
- "pipelineAnalytics.getKeyEventsBatch": {
32818
+ "pipelineAnalytics.getMediaReclaimStatus": {
32694
32819
  capName: "pipeline-analytics",
32695
32820
  capScope: "device",
32696
32821
  addonId: null,
@@ -32780,12 +32905,6 @@ Object.freeze({
32780
32905
  addonId: null,
32781
32906
  access: "view"
32782
32907
  },
32783
- "pipelineAnalytics.listGroups": {
32784
- capName: "pipeline-analytics",
32785
- capScope: "device",
32786
- addonId: null,
32787
- access: "view"
32788
- },
32789
32908
  "pipelineAnalytics.listOpsLog": {
32790
32909
  capName: "pipeline-analytics",
32791
32910
  capScope: "device",
@@ -32870,6 +32989,12 @@ Object.freeze({
32870
32989
  addonId: null,
32871
32990
  access: "create"
32872
32991
  },
32992
+ "pipelineAnalytics.reclaimDebugMedia": {
32993
+ capName: "pipeline-analytics",
32994
+ capScope: "device",
32995
+ addonId: null,
32996
+ access: "create"
32997
+ },
32873
32998
  "pipelineAnalytics.reconcileFromDisk": {
32874
32999
  capName: "pipeline-analytics",
32875
33000
  capScope: "device",
@@ -33794,6 +33919,12 @@ Object.freeze({
33794
33919
  addonId: null,
33795
33920
  access: "view"
33796
33921
  },
33922
+ "recording.getPlacement": {
33923
+ capName: "recording",
33924
+ capScope: "system",
33925
+ addonId: null,
33926
+ access: "view"
33927
+ },
33797
33928
  "recording.getPlaybackManifest": {
33798
33929
  capName: "recording",
33799
33930
  capScope: "system",
@@ -33920,6 +34051,12 @@ Object.freeze({
33920
34051
  addonId: null,
33921
34052
  access: "create"
33922
34053
  },
34054
+ "recording.setDevicePlacement": {
34055
+ capName: "recording",
34056
+ capScope: "system",
34057
+ addonId: null,
34058
+ access: "create"
34059
+ },
33923
34060
  "recording.startStorageMigrationMove": {
33924
34061
  capName: "recording",
33925
34062
  capScope: "system",
@@ -34364,12 +34501,36 @@ Object.freeze({
34364
34501
  addonId: null,
34365
34502
  access: "create"
34366
34503
  },
34504
+ "storageMigration.cleanupCancel": {
34505
+ capName: "storage-migration",
34506
+ capScope: "system",
34507
+ addonId: null,
34508
+ access: "create"
34509
+ },
34510
+ "storageMigration.cleanupStart": {
34511
+ capName: "storage-migration",
34512
+ capScope: "system",
34513
+ addonId: null,
34514
+ access: "create"
34515
+ },
34516
+ "storageMigration.cleanupStatus": {
34517
+ capName: "storage-migration",
34518
+ capScope: "system",
34519
+ addonId: null,
34520
+ access: "view"
34521
+ },
34367
34522
  "storageMigration.drain": {
34368
34523
  capName: "storage-migration",
34369
34524
  capScope: "system",
34370
34525
  addonId: null,
34371
34526
  access: "create"
34372
34527
  },
34528
+ "storageMigration.history": {
34529
+ capName: "storage-migration",
34530
+ capScope: "system",
34531
+ addonId: null,
34532
+ access: "view"
34533
+ },
34373
34534
  "storageMigration.movers": {
34374
34535
  capName: "storage-migration",
34375
34536
  capScope: "system",
@@ -36366,11 +36527,6 @@ Object.freeze({
36366
36527
  form: "single",
36367
36528
  optional: true
36368
36529
  }],
36369
- "pipelineAnalytics.getGroup": [{
36370
- name: "deviceId",
36371
- form: "single",
36372
- optional: false
36373
- }],
36374
36530
  "pipelineAnalytics.getKeyEvents": [{
36375
36531
  name: "deviceId",
36376
36532
  form: "single",
@@ -36436,11 +36592,6 @@ Object.freeze({
36436
36592
  form: "single",
36437
36593
  optional: false
36438
36594
  }],
36439
- "pipelineAnalytics.listGroups": [{
36440
- name: "deviceIds",
36441
- form: "array",
36442
- optional: false
36443
- }],
36444
36595
  "pipelineAnalytics.listOpsLog": [{
36445
36596
  name: "deviceId",
36446
36597
  form: "single",
@@ -36486,6 +36637,11 @@ Object.freeze({
36486
36637
  form: "single",
36487
36638
  optional: true
36488
36639
  }],
36640
+ "pipelineAnalytics.reclaimDebugMedia": [{
36641
+ name: "deviceIds",
36642
+ form: "array",
36643
+ optional: true
36644
+ }],
36489
36645
  "pipelineAnalytics.reconcileFromDisk": [{
36490
36646
  name: "deviceId",
36491
36647
  form: "single",
@@ -36851,6 +37007,11 @@ Object.freeze({
36851
37007
  form: "single",
36852
37008
  optional: false
36853
37009
  }],
37010
+ "recording.setDevicePlacement": [{
37011
+ name: "deviceId",
37012
+ form: "single",
37013
+ optional: false
37014
+ }],
36854
37015
  "recording.startStorageMigrationMove": [{
36855
37016
  name: "deviceId",
36856
37017
  form: "single",
@@ -8750,6 +8750,13 @@ var MediaRelocateModeSchema = _enum([
8750
8750
  ]);
8751
8751
  var RelocateMediaInputSchema = object({
8752
8752
  toLocationId: string(),
8753
+ /**
8754
+ * Restrict the pass to rows currently on this location. Omitted / `'*'` =
8755
+ * every row that is not already on `toLocationId` (the historical
8756
+ * behaviour). A named source is what a from→to migration needs: without it
8757
+ * "move events off disk 2" also emptied disk 1.
8758
+ */
8759
+ fromLocationId: string().optional(),
8753
8760
  throttleMbps: number().min(1).max(1e3).optional(),
8754
8761
  /** Omitted = `move`, the pre-existing behaviour. */
8755
8762
  mode: MediaRelocateModeSchema.optional()
@@ -8817,6 +8824,19 @@ var StorageMigrationDestinationsSchema = object({
8817
8824
  galleryMedia: string().min(1).optional()
8818
8825
  }).refine((value) => Object.keys(value).length > 0, { message: "select at least one storage class" });
8819
8826
  /**
8827
+ * Optional named source per class. Omitted = the class's current default
8828
+ * (the historical behaviour). A named source that is NOT the default is a
8829
+ * drain of that disk: bytes move, the default stays, and the source is
8830
+ * disabled when the move finishes.
8831
+ */
8832
+ var StorageMigrationSourcesSchema = object({
8833
+ recordings: string().min(1).optional(),
8834
+ recordingsLow: string().min(1).optional(),
8835
+ eventMedia: string().min(1).optional(),
8836
+ backups: string().min(1).optional(),
8837
+ galleryMedia: string().min(1).optional()
8838
+ }).optional();
8839
+ /**
8820
8840
  * How a migration sequences the cutover against the byte move.
8821
8841
  *
8822
8842
  * - `blocking` — the historical order: pause, move every byte, repoint,
@@ -8838,6 +8858,8 @@ var StorageMigrationModeSchema = _enum(["blocking", "nonBlocking"]);
8838
8858
  /** Shared input for planning and starting an orchestrated storage migration. */
8839
8859
  var StorageMigrationInputSchema = object({
8840
8860
  destinations: StorageMigrationDestinationsSchema,
8861
+ /** Omitted = each class's current default. */
8862
+ sources: StorageMigrationSourcesSchema,
8841
8863
  throttleMbps: number().min(1).max(1e3).optional(),
8842
8864
  /** Omitted = `blocking`, which stays the default. */
8843
8865
  mode: StorageMigrationModeSchema.optional()
@@ -8917,6 +8939,13 @@ var StorageMigrationMoveSchema = object({
8917
8939
  storageClass: StorageMigrationClassSchema,
8918
8940
  fromLocationId: string(),
8919
8941
  toLocationId: string(),
8942
+ /**
8943
+ * True when `from` was NOT the class default at plan time. The move still
8944
+ * copies bytes, but the default is left alone and the source is disabled
8945
+ * once the copy verifies. Absent on jobs planned before this field existed
8946
+ * — those jobs always repointed, which is `false`.
8947
+ */
8948
+ freezeSource: boolean().optional(),
8920
8949
  moverJobId: string().nullable(),
8921
8950
  state: RelocateJobStateSchema.nullable(),
8922
8951
  error: string().nullable(),
@@ -8930,6 +8959,7 @@ var StorageMigrationJobSchema = object({
8930
8959
  * can tell a seconds-long cutover from a thirty-hour one. */
8931
8960
  mode: StorageMigrationModeSchema,
8932
8961
  destinations: StorageMigrationDestinationsSchema,
8962
+ sources: StorageMigrationSourcesSchema,
8933
8963
  throttleMbps: number(),
8934
8964
  moves: array(StorageMigrationMoveSchema),
8935
8965
  pauseLeaseId: string().nullable(),
@@ -8955,6 +8985,7 @@ var StorageMigrationFindingSchema = object({
8955
8985
  });
8956
8986
  var StorageMigrationPlanSchema = object({
8957
8987
  destinations: StorageMigrationDestinationsSchema,
8988
+ sources: StorageMigrationSourcesSchema,
8958
8989
  /** The mode this plan was built for. A plan is only valid for its mode: the
8959
8990
  * `eventMedia` seal gate and the single-cardinality refusal both depend on
8960
8991
  * it. */
@@ -8962,7 +8993,8 @@ var StorageMigrationPlanSchema = object({
8962
8993
  moves: array(object({
8963
8994
  storageClass: StorageMigrationClassSchema,
8964
8995
  fromLocationId: string(),
8965
- toLocationId: string()
8996
+ toLocationId: string(),
8997
+ freezeSource: boolean().optional()
8966
8998
  })),
8967
8999
  findings: array(StorageMigrationFindingSchema)
8968
9000
  });
@@ -9140,10 +9172,51 @@ var LedgerWalkReportSchema = object({
9140
9172
  var RelocatableMediaCountSchema = object({ rows: number().int().nonnegative() }).nullable();
9141
9173
  var RelocatableMediaCountInputSchema = object({
9142
9174
  toLocationId: string().min(1),
9175
+ /** Restrict the count to one source; omitted / `'*'` = every non-target row. */
9176
+ fromLocationId: string().optional(),
9143
9177
  /** Omitted = `move`. */
9144
9178
  mode: MediaRelocateModeSchema.optional()
9145
9179
  });
9146
9180
  /**
9181
+ * Operator cleanup of leftover analytics rows, optional debug media, and
9182
+ * ghost ledger entries on frozen footage locations.
9183
+ *
9184
+ * A pass is tens of minutes on a standing backlog. The hub method RETURNS
9185
+ * `{ jobId }` immediately; progress is `cleanupStatus`. Awaiting the work
9186
+ * is how `addons.custom` hit the 60 s UDS deadline while reclaim continued
9187
+ * with no operator-visible status.
9188
+ */
9189
+ var StorageCleanupPhaseSchema = _enum([
9190
+ "orphans",
9191
+ "debug-media",
9192
+ "ghost-ledger",
9193
+ "done",
9194
+ "failed",
9195
+ "cancelled"
9196
+ ]);
9197
+ var StorageCleanupInputSchema = object({
9198
+ /** Also walk motion stills / track filmstrips. Off by default. */
9199
+ includeDebugMedia: boolean().optional() });
9200
+ var StorageCleanupJobSchema = object({
9201
+ jobId: string(),
9202
+ phase: StorageCleanupPhaseSchema,
9203
+ includeDebugMedia: boolean(),
9204
+ orphansReclaimed: number().int().nonnegative(),
9205
+ orphanBytesReclaimed: number().int().nonnegative(),
9206
+ debugMediaReclaimed: number().int().nonnegative(),
9207
+ debugMediaBytesReclaimed: number().int().nonnegative(),
9208
+ ghostsForgotten: number().int().nonnegative(),
9209
+ ghostBytesForgotten: number().int().nonnegative(),
9210
+ /** Short operator-facing line: current collection, pass, or location. */
9211
+ detail: string().nullable(),
9212
+ cancelRequested: boolean(),
9213
+ startedAt: number(),
9214
+ updatedAt: number(),
9215
+ finishedAt: number().nullable(),
9216
+ error: string().nullable()
9217
+ });
9218
+ var StorageCleanupStatusInputSchema = object({ jobId: string().optional() });
9219
+ /**
9147
9220
  * `StorageLocationType` — an addon-declared id that identifies the *kind* of
9148
9221
  * storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
9149
9222
  * so the persisted record schema and the consumer-facing cap can both consume it
@@ -9171,11 +9244,10 @@ var StorageLocationTypeSchema = string().regex(/^[a-z][a-zA-Z0-9-]*$/);
9171
9244
  * The default location for a type uses `id === <type>:default` by
9172
9245
  * convention (the bare type ref like `'backups'` resolves to it).
9173
9246
  *
9174
- * `isSystem: true` marks a location as orchestrator-seeded and
9175
- * undeletable. The bootstrap-installed defaults (one per type) carry
9176
- * this flag; operator-added locations don't. Editing the config of
9177
- * a system location is allowed (path migration, provider swap) but
9178
- * deleting it is rejected at the cap level.
9247
+ * `isSystem` is a legacy persisted flag. Seed still creates the initial
9248
+ * `<type>:default` locations; the flag is no longer a lock, a badge, or a
9249
+ * prune selector. New writes leave it false. Deletion is gated on uniqueness
9250
+ * / last-enabled, not on this bit.
9179
9251
  */
9180
9252
  var StorageLocationSchema = object({
9181
9253
  id: string().regex(/^[a-z][a-zA-Z0-9-]*:[a-zA-Z0-9-]+$/),
@@ -13572,6 +13644,12 @@ method(object({
13572
13644
  }), _void(), {
13573
13645
  kind: "mutation",
13574
13646
  auth: "admin"
13647
+ }), method(object({
13648
+ from: string(),
13649
+ to: string()
13650
+ }), object({ moved: number() }), {
13651
+ kind: "mutation",
13652
+ auth: "admin"
13575
13653
  }), method(object({
13576
13654
  deviceId: number(),
13577
13655
  disabled: boolean()
@@ -19502,46 +19580,6 @@ var RecentTracksPageSchema = object({
19502
19580
  /** Cursor for the next page, or null when this page is the last. */
19503
19581
  nextCursor: string().nullable()
19504
19582
  });
19505
- var LIST_GROUPS_DEFAULT_LIMIT = 40;
19506
- var LIST_GROUPS_MAX_LIMIT = 100;
19507
- var AnalyticsGroupRecordSchema = object({
19508
- id: string(),
19509
- deviceId: number().int(),
19510
- openedAt: number().int(),
19511
- closedAt: number().int(),
19512
- timestamp: number().int(),
19513
- memberCount: number().int(),
19514
- memberTrackIds: array(string()).readonly(),
19515
- className: string(),
19516
- classes: array(string()).readonly(),
19517
- /** Relative event-media path, or null when the group has no picture yet. */
19518
- mediaUrl: string().nullable(),
19519
- singleton: boolean()
19520
- });
19521
- var AnalyticsGroupMemberSchema = object({
19522
- trackId: string(),
19523
- deviceId: number().int(),
19524
- className: string(),
19525
- firstSeen: number().int(),
19526
- lastSeen: number().int(),
19527
- mediaUrl: string().nullable()
19528
- });
19529
- var AnalyticsGroupDetailSchema = AnalyticsGroupRecordSchema.extend({ members: array(AnalyticsGroupMemberSchema).readonly() });
19530
- var ListGroupsQueryInput = object({
19531
- /** Devices to merge. An empty array yields `{ groups: [], nextCursor: null }`. */
19532
- deviceIds: array(number()),
19533
- /** Window lower bound on `closedAt` (inclusive). */
19534
- since: number().optional(),
19535
- /** Window upper bound on `openedAt` (inclusive). */
19536
- until: number().optional(),
19537
- limit: number().int().min(1).max(LIST_GROUPS_MAX_LIMIT).default(LIST_GROUPS_DEFAULT_LIMIT),
19538
- /** Opaque continuation cursor from a previous page's `nextCursor`. */
19539
- cursor: string().optional()
19540
- });
19541
- var ListGroupsPageSchema = object({
19542
- groups: array(AnalyticsGroupRecordSchema).readonly(),
19543
- nextCursor: string().nullable()
19544
- });
19545
19583
  var KEY_EVENTS_DEFAULT_LIMIT = 50;
19546
19584
  var KEY_EVENTS_MAX_LIMIT = 200;
19547
19585
  var KeyEventQueryInput = object({
@@ -19645,9 +19683,7 @@ var TrackCascadeCountsSchema = object({
19645
19683
  /** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
19646
19684
  plates: number().int(),
19647
19685
  /** Per-track CLIP search vectors removed (best-effort). */
19648
- embeddings: number().int(),
19649
- /** Group membership + group rows removed with their last member (best-effort). */
19650
- groups: number().int()
19686
+ embeddings: number().int()
19651
19687
  });
19652
19688
  /** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
19653
19689
  var DiskReconcileCountsSchema = object({
@@ -19817,6 +19853,47 @@ var RebuildStatusSchema = object({
19817
19853
  /** Present when the pass ended by throwing. */
19818
19854
  error: string().nullable()
19819
19855
  });
19856
+ /**
19857
+ * Acknowledgement that a debug-media reclaim STARTED.
19858
+ *
19859
+ * The pass is paced at ~2 MB/s over a standing 100 GB — tens of minutes — so
19860
+ * it runs detached and this returns immediately. Awaiting it is how the
19861
+ * `addons.custom` door hit the 60 s UDS deadline while the walk carried on
19862
+ * with no status. Poll {@link pipelineAnalyticsCapability.methods.getMediaReclaimStatus}.
19863
+ */
19864
+ var MediaReclaimStartResultSchema = object({
19865
+ started: boolean(),
19866
+ /** True when a pass was already running; the new request is ignored. */
19867
+ alreadyRunning: boolean()
19868
+ });
19869
+ var MediaReclaimInputSchema = object({
19870
+ mode: _enum(["report", "reclaim"]).default("report"),
19871
+ scopes: array(_enum(["motion-still", "track-filmstrip"])).min(1).optional(),
19872
+ deviceIds: array(number().int()).min(1).optional(),
19873
+ restart: boolean().optional(),
19874
+ pageSize: number().int().min(50).max(5e3).optional(),
19875
+ maxRowsPerDevice: number().int().min(1).max(5e5).optional(),
19876
+ maxReclaimPerDevice: number().int().min(1).max(5e5).optional(),
19877
+ maxBytesPerRun: number().int().min(1).optional(),
19878
+ budgetMinutes: number().int().min(1).max(720).optional(),
19879
+ throttleBytesPerSec: number().int().min(64 * 1024).optional(),
19880
+ graceMinutes: number().int().min(1).max(10080).optional()
19881
+ });
19882
+ var MediaReclaimStatusSchema = object({
19883
+ running: boolean(),
19884
+ mode: _enum(["report", "reclaim"]).nullable(),
19885
+ totalExamined: number(),
19886
+ totalEligible: number(),
19887
+ totalReclaimed: number(),
19888
+ totalBytesReclaimed: number(),
19889
+ totalRefused: number(),
19890
+ /** Device+scope windows finished in this pass. */
19891
+ devicesDone: number(),
19892
+ complete: boolean().nullable(),
19893
+ startedAtMs: number().nullable(),
19894
+ finishedAtMs: number().nullable(),
19895
+ error: string().nullable()
19896
+ });
19820
19897
  var ReplayFrameInputSchema = object({
19821
19898
  timestamp: number(),
19822
19899
  frame: PipelineRunResultBridge
@@ -19855,10 +19932,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19855
19932
  * stationary registry). Default false: the timeline lists passages,
19856
19933
  * not parking records (operator decision, 2026-08-15). */
19857
19934
  includeStationary: boolean().optional()
19858
- }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(ListGroupsQueryInput, ListGroupsPageSchema), method(object({
19859
- deviceId: number(),
19860
- groupId: string().min(1)
19861
- }), AnalyticsGroupDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
19935
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
19862
19936
  kind: "mutation",
19863
19937
  auth: "admin"
19864
19938
  }), 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({
@@ -19958,6 +20032,12 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19958
20032
  }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
19959
20033
  kind: "query",
19960
20034
  auth: "admin"
20035
+ }), method(MediaReclaimInputSchema, MediaReclaimStartResultSchema, {
20036
+ kind: "mutation",
20037
+ auth: "admin"
20038
+ }), method(object({}), MediaReclaimStatusSchema, {
20039
+ kind: "query",
20040
+ auth: "admin"
19961
20041
  }), method(object({ deviceIds: array(number()).optional() }), TrainingExportSummarySchema, {
19962
20042
  kind: "query",
19963
20043
  auth: "admin"
@@ -21928,7 +22008,13 @@ method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin"
21928
22008
  }), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
21929
22009
  kind: "mutation",
21930
22010
  auth: "admin"
21931
- });
22011
+ }), method(StorageCleanupInputSchema, object({ jobId: string() }), {
22012
+ kind: "mutation",
22013
+ auth: "admin"
22014
+ }), method(StorageCleanupStatusInputSchema, StorageCleanupJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
22015
+ kind: "mutation",
22016
+ auth: "admin"
22017
+ }), method(object({}), array(StorageMigrationJobSchema).readonly(), { auth: "admin" });
21932
22018
  var ProviderInfoSchema = discriminatedUnion("shouldSaveDiskSpace", [object({
21933
22019
  providerId: string().min(1),
21934
22020
  displayName: string().min(1),
@@ -27354,6 +27440,33 @@ var RecordingRebalanceInputSchema = object({
27354
27440
  minMoveGb: number().min(0).optional()
27355
27441
  });
27356
27442
  /**
27443
+ * Operator-facing placement of one camera onto a recordings location.
27444
+ *
27445
+ * `pinLocationId` is the operator instruction: a location id, or `null` for
27446
+ * Auto (the planner may move this camera). `locationId` is where high/mid
27447
+ * currently write — the plan, which may disagree with the pin when Auto.
27448
+ */
27449
+ var RecordingDevicePlacementSchema = object({
27450
+ deviceId: number().int(),
27451
+ profile: string(),
27452
+ locationId: string()
27453
+ });
27454
+ var RecordingDevicePinSchema = object({
27455
+ deviceId: number().int(),
27456
+ /** Recordings-class location this camera is pinned to. */
27457
+ locationId: string()
27458
+ });
27459
+ var RecordingPlacementViewSchema = object({
27460
+ assignments: array(RecordingDevicePlacementSchema),
27461
+ pins: array(RecordingDevicePinSchema),
27462
+ defaultLocations: record(string(), string())
27463
+ });
27464
+ var RecordingSetDevicePlacementInputSchema = object({
27465
+ deviceId: number().int(),
27466
+ /** `null` = Auto. Otherwise a `recordings:*` location id. */
27467
+ locationId: string().nullable()
27468
+ });
27469
+ /**
27357
27470
  * Result of locating footage at a wall-clock instant for one device/profile.
27358
27471
  * `segment` carries the covering segment's window; `gap` reports the forward
27359
27472
  * nearest covered edge (`null` past the end of footage / when none exists)
@@ -27579,6 +27692,12 @@ method(object({
27579
27692
  }), method(RecordingRebalanceInputSchema, RecordingRebalancePlanSchema, {
27580
27693
  kind: "mutation",
27581
27694
  auth: "admin"
27695
+ }), method(object({}), RecordingPlacementViewSchema, {
27696
+ kind: "query",
27697
+ auth: "admin"
27698
+ }), method(RecordingSetDevicePlacementInputSchema, object({ ok: literal(true) }), {
27699
+ kind: "mutation",
27700
+ auth: "admin"
27582
27701
  });
27583
27702
  /**
27584
27703
  * `recording-export` cap — render a footage time range into a single downloadable
@@ -30974,6 +31093,12 @@ Object.freeze({
30974
31093
  addonId: null,
30975
31094
  access: "delete"
30976
31095
  },
31096
+ "deviceManager.renameLocation": {
31097
+ capName: "device-manager",
31098
+ capScope: "system",
31099
+ addonId: null,
31100
+ access: "create"
31101
+ },
30977
31102
  "deviceManager.runDeviceAction": {
30978
31103
  capName: "device-manager",
30979
31104
  capScope: "system",
@@ -32666,19 +32791,19 @@ Object.freeze({
32666
32791
  addonId: null,
32667
32792
  access: "view"
32668
32793
  },
32669
- "pipelineAnalytics.getGroup": {
32794
+ "pipelineAnalytics.getKeyEvents": {
32670
32795
  capName: "pipeline-analytics",
32671
32796
  capScope: "device",
32672
32797
  addonId: null,
32673
32798
  access: "view"
32674
32799
  },
32675
- "pipelineAnalytics.getKeyEvents": {
32800
+ "pipelineAnalytics.getKeyEventsBatch": {
32676
32801
  capName: "pipeline-analytics",
32677
32802
  capScope: "device",
32678
32803
  addonId: null,
32679
32804
  access: "view"
32680
32805
  },
32681
- "pipelineAnalytics.getKeyEventsBatch": {
32806
+ "pipelineAnalytics.getMediaReclaimStatus": {
32682
32807
  capName: "pipeline-analytics",
32683
32808
  capScope: "device",
32684
32809
  addonId: null,
@@ -32768,12 +32893,6 @@ Object.freeze({
32768
32893
  addonId: null,
32769
32894
  access: "view"
32770
32895
  },
32771
- "pipelineAnalytics.listGroups": {
32772
- capName: "pipeline-analytics",
32773
- capScope: "device",
32774
- addonId: null,
32775
- access: "view"
32776
- },
32777
32896
  "pipelineAnalytics.listOpsLog": {
32778
32897
  capName: "pipeline-analytics",
32779
32898
  capScope: "device",
@@ -32858,6 +32977,12 @@ Object.freeze({
32858
32977
  addonId: null,
32859
32978
  access: "create"
32860
32979
  },
32980
+ "pipelineAnalytics.reclaimDebugMedia": {
32981
+ capName: "pipeline-analytics",
32982
+ capScope: "device",
32983
+ addonId: null,
32984
+ access: "create"
32985
+ },
32861
32986
  "pipelineAnalytics.reconcileFromDisk": {
32862
32987
  capName: "pipeline-analytics",
32863
32988
  capScope: "device",
@@ -33782,6 +33907,12 @@ Object.freeze({
33782
33907
  addonId: null,
33783
33908
  access: "view"
33784
33909
  },
33910
+ "recording.getPlacement": {
33911
+ capName: "recording",
33912
+ capScope: "system",
33913
+ addonId: null,
33914
+ access: "view"
33915
+ },
33785
33916
  "recording.getPlaybackManifest": {
33786
33917
  capName: "recording",
33787
33918
  capScope: "system",
@@ -33908,6 +34039,12 @@ Object.freeze({
33908
34039
  addonId: null,
33909
34040
  access: "create"
33910
34041
  },
34042
+ "recording.setDevicePlacement": {
34043
+ capName: "recording",
34044
+ capScope: "system",
34045
+ addonId: null,
34046
+ access: "create"
34047
+ },
33911
34048
  "recording.startStorageMigrationMove": {
33912
34049
  capName: "recording",
33913
34050
  capScope: "system",
@@ -34352,12 +34489,36 @@ Object.freeze({
34352
34489
  addonId: null,
34353
34490
  access: "create"
34354
34491
  },
34492
+ "storageMigration.cleanupCancel": {
34493
+ capName: "storage-migration",
34494
+ capScope: "system",
34495
+ addonId: null,
34496
+ access: "create"
34497
+ },
34498
+ "storageMigration.cleanupStart": {
34499
+ capName: "storage-migration",
34500
+ capScope: "system",
34501
+ addonId: null,
34502
+ access: "create"
34503
+ },
34504
+ "storageMigration.cleanupStatus": {
34505
+ capName: "storage-migration",
34506
+ capScope: "system",
34507
+ addonId: null,
34508
+ access: "view"
34509
+ },
34355
34510
  "storageMigration.drain": {
34356
34511
  capName: "storage-migration",
34357
34512
  capScope: "system",
34358
34513
  addonId: null,
34359
34514
  access: "create"
34360
34515
  },
34516
+ "storageMigration.history": {
34517
+ capName: "storage-migration",
34518
+ capScope: "system",
34519
+ addonId: null,
34520
+ access: "view"
34521
+ },
34361
34522
  "storageMigration.movers": {
34362
34523
  capName: "storage-migration",
34363
34524
  capScope: "system",
@@ -36354,11 +36515,6 @@ Object.freeze({
36354
36515
  form: "single",
36355
36516
  optional: true
36356
36517
  }],
36357
- "pipelineAnalytics.getGroup": [{
36358
- name: "deviceId",
36359
- form: "single",
36360
- optional: false
36361
- }],
36362
36518
  "pipelineAnalytics.getKeyEvents": [{
36363
36519
  name: "deviceId",
36364
36520
  form: "single",
@@ -36424,11 +36580,6 @@ Object.freeze({
36424
36580
  form: "single",
36425
36581
  optional: false
36426
36582
  }],
36427
- "pipelineAnalytics.listGroups": [{
36428
- name: "deviceIds",
36429
- form: "array",
36430
- optional: false
36431
- }],
36432
36583
  "pipelineAnalytics.listOpsLog": [{
36433
36584
  name: "deviceId",
36434
36585
  form: "single",
@@ -36474,6 +36625,11 @@ Object.freeze({
36474
36625
  form: "single",
36475
36626
  optional: true
36476
36627
  }],
36628
+ "pipelineAnalytics.reclaimDebugMedia": [{
36629
+ name: "deviceIds",
36630
+ form: "array",
36631
+ optional: true
36632
+ }],
36477
36633
  "pipelineAnalytics.reconcileFromDisk": [{
36478
36634
  name: "deviceId",
36479
36635
  form: "single",
@@ -36839,6 +36995,11 @@ Object.freeze({
36839
36995
  form: "single",
36840
36996
  optional: false
36841
36997
  }],
36998
+ "recording.setDevicePlacement": [{
36999
+ name: "deviceId",
37000
+ form: "single",
37001
+ optional: false
37002
+ }],
36842
37003
  "recording.startStorageMigrationMove": [{
36843
37004
  name: "deviceId",
36844
37005
  form: "single",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-export-hap",
3
- "version": "1.2.60",
3
+ "version": "1.2.61",
4
4
  "description": "HomeKit (HAP) exporter for CamStack devices. Publishes each exposed device as its own HomeKit accessory: cameras and doorbells with SRTP streaming, HomeKit Secure Video, motion, two-way audio, PTZ and battery; switches, lights, locks and sensors through a capability→service table.",
5
5
  "keywords": [
6
6
  "camstack",