camstack 1.2.20 → 1.2.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -23509,9 +23509,9 @@ var require_zod = __commonJS({
23509
23509
  }
23510
23510
  });
23511
23511
 
23512
- // ../system/dist/dist-DWZce90k.js
23513
- var require_dist_DWZce90k = __commonJS({
23514
- "../system/dist/dist-DWZce90k.js"(exports) {
23512
+ // ../system/dist/dist-cINpngi1.js
23513
+ var require_dist_cINpngi1 = __commonJS({
23514
+ "../system/dist/dist-cINpngi1.js"(exports) {
23515
23515
  "use strict";
23516
23516
  var zod = require_zod();
23517
23517
  var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
@@ -25865,19 +25865,85 @@ var require_dist_DWZce90k = __commonJS({
25865
25865
  finishedAt: zod.z.number().nullable(),
25866
25866
  error: zod.z.string().nullable()
25867
25867
  });
25868
+ var RelocateFootageClassSchema = zod.z.enum(["recordings", "recordingsLow"]);
25868
25869
  var RelocateFootageInputSchema = zod.z.object({
25869
- deviceId: zod.z.number().optional(),
25870
25870
  fromLocationId: zod.z.string(),
25871
25871
  toLocationId: zod.z.string(),
25872
25872
  entities: zod.z.array(zod.z.enum(["segments"])).optional(),
25873
+ /** Limits relocation to the logical profile class. Omit only for the
25874
+ * pre-orchestration compatibility path. */
25875
+ footageClass: RelocateFootageClassSchema.optional(),
25873
25876
  /** Copy throttle in MB/s (default 40) — the drain is a background chore,
25874
25877
  * never allowed to starve live writers. */
25875
25878
  throttleMbps: zod.z.number().min(1).max(1e3).optional()
25876
25879
  });
25877
- var RelocateMediaInputSchema = zod.z.object({
25878
- deviceId: zod.z.number().optional(),
25880
+ var StorageMigrationLeaseInputSchema = zod.z.object({ leaseId: zod.z.string().min(1) });
25881
+ var StorageMigrationFootageMoveInputSchema = RelocateFootageInputSchema.extend({ leaseId: zod.z.string().min(1) });
25882
+ var StorageMigrationMediaMoveInputSchema = zod.z.object({
25879
25883
  toLocationId: zod.z.string(),
25880
25884
  throttleMbps: zod.z.number().min(1).max(1e3).optional()
25885
+ }).extend({ leaseId: zod.z.string().min(1) });
25886
+ var StorageMigrationClassSchema = zod.z.enum([
25887
+ "recordings",
25888
+ "recordingsLow",
25889
+ "eventMedia"
25890
+ ]);
25891
+ var StorageMigrationDestinationsSchema = zod.z.object({
25892
+ recordings: zod.z.string().min(1).optional(),
25893
+ recordingsLow: zod.z.string().min(1).optional(),
25894
+ eventMedia: zod.z.string().min(1).optional()
25895
+ }).refine((value) => Object.keys(value).length > 0, { message: "select at least one storage class" });
25896
+ var StorageMigrationInputSchema = zod.z.object({
25897
+ destinations: StorageMigrationDestinationsSchema,
25898
+ throttleMbps: zod.z.number().min(1).max(1e3).optional()
25899
+ });
25900
+ var StorageMigrationPhaseSchema = zod.z.enum([
25901
+ "planning",
25902
+ "pausing",
25903
+ "moving",
25904
+ "verifying",
25905
+ "repointing",
25906
+ "refreshing",
25907
+ "resuming",
25908
+ "done",
25909
+ "failed",
25910
+ "cancelled"
25911
+ ]);
25912
+ var StorageMigrationParticipantSchema = zod.z.enum([
25913
+ "pipeline",
25914
+ "recorder",
25915
+ "analytics"
25916
+ ]);
25917
+ var StorageMigrationMoveSchema = zod.z.object({
25918
+ storageClass: StorageMigrationClassSchema,
25919
+ fromLocationId: zod.z.string(),
25920
+ toLocationId: zod.z.string(),
25921
+ moverJobId: zod.z.string().nullable(),
25922
+ state: RelocateJobStateSchema.nullable(),
25923
+ error: zod.z.string().nullable()
25924
+ });
25925
+ var StorageMigrationJobSchema = zod.z.object({
25926
+ jobId: zod.z.string(),
25927
+ phase: StorageMigrationPhaseSchema,
25928
+ destinations: StorageMigrationDestinationsSchema,
25929
+ throttleMbps: zod.z.number(),
25930
+ moves: zod.z.array(StorageMigrationMoveSchema),
25931
+ pauseLeaseId: zod.z.string().nullable(),
25932
+ pausedParticipants: zod.z.array(StorageMigrationParticipantSchema),
25933
+ repointed: zod.z.boolean(),
25934
+ cancelRequested: zod.z.boolean(),
25935
+ startedAt: zod.z.number(),
25936
+ updatedAt: zod.z.number(),
25937
+ finishedAt: zod.z.number().nullable(),
25938
+ error: zod.z.string().nullable()
25939
+ });
25940
+ var StorageMigrationPlanSchema = zod.z.object({
25941
+ destinations: StorageMigrationDestinationsSchema,
25942
+ moves: zod.z.array(zod.z.object({
25943
+ storageClass: StorageMigrationClassSchema,
25944
+ fromLocationId: zod.z.string(),
25945
+ toLocationId: zod.z.string()
25946
+ }))
25881
25947
  });
25882
25948
  var StorageLocationTypeSchema = zod.z.string().regex(/^[a-z][a-zA-Z0-9-]*$/);
25883
25949
  var StorageLocationSchema = zod.z.object({
@@ -34497,20 +34563,28 @@ var require_dist_DWZce90k = __commonJS({
34497
34563
  }),
34498
34564
  /** The events ops-log rows (newest-first), optionally scoped to one camera.
34499
34565
  * Backed by a declared pipeline-analytics SQLite collection. */
34500
- /**
34501
- * Move event-media blobs onto `toLocationId` (entity-routing spec Phase
34502
- * 4): per-row copy → stamp row.locationId delete old blob. Rows already
34503
- * at the target are skipped, so a re-run resumes. Single-flight.
34504
- */
34505
- relocateMedia: method(RelocateMediaInputSchema, zod.z.object({ jobId: zod.z.string() }), {
34566
+ /** Internal migration-participant lease. It drains active MediaStore
34567
+ * writes and refuses new ones without changing analytics bindings. */
34568
+ pauseForStorageMigration: method(StorageMigrationLeaseInputSchema, zod.z.object({ paused: zod.z.literal(true) }), {
34506
34569
  kind: "mutation",
34507
34570
  auth: "admin"
34508
34571
  }),
34509
- getMediaRelocateStatus: method(zod.z.object({}), zod.z.array(RelocateJobSchema).readonly(), {
34510
- kind: "query",
34572
+ resumeForStorageMigration: method(StorageMigrationLeaseInputSchema, zod.z.object({ resumed: zod.z.literal(true) }), {
34573
+ kind: "mutation",
34574
+ auth: "admin"
34575
+ }),
34576
+ /** Drops cached location roots after the storage coordinator repoints a
34577
+ * default so future event-media writes use the new root. */
34578
+ refreshStorageLocationsForMigration: method(StorageMigrationLeaseInputSchema, zod.z.object({ refreshed: zod.z.literal(true) }), {
34579
+ kind: "mutation",
34511
34580
  auth: "admin"
34512
34581
  }),
34513
- cancelMediaRelocate: method(zod.z.object({ jobId: zod.z.string() }), zod.z.object({ cancelled: zod.z.boolean() }), {
34582
+ startStorageMigrationMove: method(StorageMigrationMediaMoveInputSchema, zod.z.object({ jobId: zod.z.string() }), {
34583
+ kind: "mutation",
34584
+ auth: "admin"
34585
+ }),
34586
+ getStorageMigrationMoveStatus: method(zod.z.object({ jobId: zod.z.string() }), RelocateJobSchema.nullable(), { auth: "admin" }),
34587
+ cancelStorageMigrationMove: method(zod.z.object({ jobId: zod.z.string() }), zod.z.object({ cancelled: zod.z.boolean() }), {
34514
34588
  kind: "mutation",
34515
34589
  auth: "admin"
34516
34590
  }),
@@ -36303,6 +36377,16 @@ var require_dist_DWZce90k = __commonJS({
36303
36377
  nodeIdMode: "data",
36304
36378
  exposesDeviceSettings: true,
36305
36379
  methods: {
36380
+ /** Internal storage-migration participant lease. While held, dispatch
36381
+ * requests are accepted as pending but no new runner attachment starts. */
36382
+ pauseForStorageMigration: method(StorageMigrationLeaseInputSchema, zod.z.object({ paused: zod.z.literal(true) }), {
36383
+ kind: "mutation",
36384
+ auth: "admin"
36385
+ }),
36386
+ resumeForStorageMigration: method(StorageMigrationLeaseInputSchema, zod.z.object({ resumed: zod.z.literal(true) }), {
36387
+ kind: "mutation",
36388
+ auth: "admin"
36389
+ }),
36306
36390
  /**
36307
36391
  * Pin a camera's pipeline to a specific agent (L1 affinity).
36308
36392
  * The orchestrator re-evaluates the assignment immediately and persists
@@ -37295,6 +37379,23 @@ var require_dist_DWZce90k = __commonJS({
37295
37379
  }), EvictResultSchema, { kind: "mutation" })
37296
37380
  }
37297
37381
  };
37382
+ var storageMigrationCapability = {
37383
+ name: "storage-migration",
37384
+ scope: "system",
37385
+ mode: "singleton",
37386
+ methods: {
37387
+ plan: method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin" }),
37388
+ start: method(StorageMigrationInputSchema, zod.z.object({ jobId: zod.z.string() }), {
37389
+ kind: "mutation",
37390
+ auth: "admin"
37391
+ }),
37392
+ status: method(zod.z.object({ jobId: zod.z.string().optional() }), StorageMigrationJobSchema.nullable(), { auth: "admin" }),
37393
+ cancel: method(zod.z.object({ jobId: zod.z.string() }), zod.z.object({ cancelled: zod.z.boolean() }), {
37394
+ kind: "mutation",
37395
+ auth: "admin"
37396
+ })
37397
+ }
37398
+ };
37298
37399
  var ProviderInfoSchema = zod.z.discriminatedUnion("shouldSaveDiskSpace", [zod.z.object({
37299
37400
  providerId: zod.z.string().min(1),
37300
37401
  displayName: zod.z.string().min(1),
@@ -37409,6 +37510,24 @@ var require_dist_DWZce90k = __commonJS({
37409
37510
  label: zod.z.string(),
37410
37511
  description: zod.z.string().optional()
37411
37512
  });
37513
+ var TerminalInstanceInfoSchema = zod.z.object({
37514
+ instanceId: zod.z.string(),
37515
+ cameraStableId: zod.z.string(),
37516
+ nodeId: zod.z.string(),
37517
+ profileId: zod.z.string(),
37518
+ profileLabel: zod.z.string(),
37519
+ name: zod.z.string(),
37520
+ enabled: zod.z.boolean()
37521
+ });
37522
+ var TerminalLegacyCameraSchema = zod.z.object({
37523
+ stableId: zod.z.string(),
37524
+ nodeId: zod.z.string(),
37525
+ profileId: zod.z.string(),
37526
+ profileLabel: zod.z.string(),
37527
+ name: zod.z.string(),
37528
+ /** Only legacy monitor cameras can retain their historic stable identity. */
37529
+ adoptable: zod.z.boolean()
37530
+ });
37412
37531
  var TerminalOutputEventSchema = zod.z.discriminatedUnion("kind", [zod.z.object({
37413
37532
  seq: zod.z.number().int().positive(),
37414
37533
  kind: zod.z.literal("data"),
@@ -37432,6 +37551,37 @@ var require_dist_DWZce90k = __commonJS({
37432
37551
  methods: {
37433
37552
  /** Pre-declared profiles the operator may open. */
37434
37553
  listProfiles: method(zod.z.void(), zod.z.array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
37554
+ /** Explicit durable Terminal instances, managed centrally on the hub. */
37555
+ listInstances: method(zod.z.void(), zod.z.array(TerminalInstanceInfoSchema).readonly(), { auth: "admin" }),
37556
+ createInstance: method(zod.z.object({
37557
+ targetNodeId: zod.z.string().min(1),
37558
+ profileId: zod.z.string().min(1),
37559
+ name: zod.z.string().trim().min(1).max(160).optional()
37560
+ }), TerminalInstanceInfoSchema, {
37561
+ kind: "mutation",
37562
+ auth: "admin"
37563
+ }),
37564
+ deleteInstance: method(zod.z.object({ instanceId: zod.z.string().min(1) }), zod.z.void(), {
37565
+ kind: "mutation",
37566
+ auth: "admin"
37567
+ }),
37568
+ setInstanceEnabled: method(zod.z.object({
37569
+ instanceId: zod.z.string().min(1),
37570
+ enabled: zod.z.boolean()
37571
+ }), TerminalInstanceInfoSchema, {
37572
+ kind: "mutation",
37573
+ auth: "admin"
37574
+ }),
37575
+ /** Existing automatic cameras are shown for explicit migration only. */
37576
+ listLegacyCameras: method(zod.z.void(), zod.z.array(TerminalLegacyCameraSchema).readonly(), { auth: "admin" }),
37577
+ /** Explicitly adopt one legacy monitor camera, retaining its stable id. */
37578
+ adoptLegacyMonitor: method(zod.z.object({
37579
+ stableId: zod.z.string().min(1),
37580
+ name: zod.z.string().trim().min(1).max(160).optional()
37581
+ }), TerminalInstanceInfoSchema, {
37582
+ kind: "mutation",
37583
+ auth: "admin"
37584
+ }),
37435
37585
  /** Live sessions currently hosted by the provider. */
37436
37586
  listSessions: method(zod.z.void(), zod.z.array(TerminalSessionInfoSchema).readonly(), { auth: "admin" }),
37437
37587
  /**
@@ -37463,7 +37613,13 @@ var require_dist_DWZce90k = __commonJS({
37463
37613
  pullOutput: method(zod.z.object({
37464
37614
  sessionId: zod.z.string(),
37465
37615
  afterSeq: zod.z.number().int().nonnegative(),
37466
- waitMs: zod.z.number().int().min(0).max(2e3).default(0)
37616
+ waitMs: zod.z.number().int().min(0).max(2e3).default(0),
37617
+ /**
37618
+ * Wait when a just-opened session has no output yet. Kept opt-in so a
37619
+ * browser's initial repaint remains immediate; the camera snapshot
37620
+ * relay uses it to avoid encoding a blank startup frame.
37621
+ */
37622
+ waitForOutput: zod.z.boolean().optional()
37467
37623
  }), TerminalOutputBatchSchema, {
37468
37624
  kind: "mutation",
37469
37625
  auth: "admin",
@@ -39843,6 +39999,7 @@ var require_dist_DWZce90k = __commonJS({
39843
39999
  var FaceFilterEnum = zod.z.enum([
39844
40000
  "unassigned",
39845
40001
  "recognized",
40002
+ "identified",
39846
40003
  "all"
39847
40004
  ]);
39848
40005
  var MediaFileLiteSchema$1 = zod.z.object({
@@ -39882,6 +40039,8 @@ var require_dist_DWZce90k = __commonJS({
39882
40039
  auth: "admin"
39883
40040
  }),
39884
40041
  listRecentFaces: method(zod.z.object({
40042
+ /** Restrict to one camera. Absent keeps the cluster-wide gallery view. */
40043
+ deviceId: zod.z.number().int().optional(),
39885
40044
  limit: zod.z.number().int().positive().optional(),
39886
40045
  filter: FaceFilterEnum.optional(),
39887
40046
  /**
@@ -41958,6 +42117,10 @@ var require_dist_DWZce90k = __commonJS({
41958
42117
  capName: zod.z.string().min(1).max(64),
41959
42118
  /** Dot path inside the slice, e.g. `detected`, `value`, `mode`. */
41960
42119
  valuePath: zod.z.string().min(1).max(64)
42120
+ }),
42121
+ zod.z.object({
42122
+ kind: zod.z.literal("latest-recognition"),
42123
+ recognition: zod.z.enum(["person", "plate"])
41961
42124
  })
41962
42125
  ]);
41963
42126
  var OsdSlotBindingSchema = zod.z.object({
@@ -42084,6 +42247,21 @@ var require_dist_DWZce90k = __commonJS({
42084
42247
  auth: "admin"
42085
42248
  }),
42086
42249
  /**
42250
+ * Replace one camera's binding configuration from another. Writable source
42251
+ * slots are mapped by ordinal onto writable target slots so different
42252
+ * provider slot ids do not make the copied configuration disappear.
42253
+ */
42254
+ copyDeviceConfiguration: method(zod.z.object({
42255
+ sourceDeviceId: zod.z.number().int(),
42256
+ targetDeviceId: zod.z.number().int()
42257
+ }), zod.z.object({
42258
+ copied: zod.z.number().int().nonnegative(),
42259
+ skipped: zod.z.number().int().nonnegative()
42260
+ }), {
42261
+ kind: "mutation",
42262
+ auth: "admin"
42263
+ }),
42264
+ /**
42087
42265
  * Render without writing. `binding` overrides the stored one so an
42088
42266
  * editor can preview an unsaved change. Mutation kind only to carry
42089
42267
  * the binding object safely; no side effects.
@@ -43168,12 +43346,6 @@ var require_dist_DWZce90k = __commonJS({
43168
43346
  auth: "admin"
43169
43347
  }),
43170
43348
  /**
43171
- * Move footage (recorded segments) from one recordings location to
43172
- * another — the drain workflow's mover (entity-routing spec Phase 4).
43173
- * Throttled copy → size-verify → delete source → index refresh; resumable
43174
- * by construction (copy-if-absent). Single-flight: one job at a time.
43175
- */
43176
- /**
43177
43349
  * Render a short GIF from recorded footage around `aroundMs` (low profile,
43178
43350
  * palette-free ffmpeg gif). Synchronous — the window is a few seconds of
43179
43351
  * `low`, rendering in ~1-2s. Built for notification attachments: the
@@ -43225,16 +43397,28 @@ var require_dist_DWZce90k = __commonJS({
43225
43397
  kind: "mutation",
43226
43398
  auth: "admin"
43227
43399
  }),
43228
- relocateFootage: method(RelocateFootageInputSchema, zod.z.object({ jobId: zod.z.string() }), {
43400
+ /** Internal migration-participant lease. Blocks new recorder attaches and
43401
+ * waits for writers to exit while their watchers index final segments. */
43402
+ pauseForStorageMigration: method(StorageMigrationLeaseInputSchema, zod.z.object({ paused: zod.z.literal(true) }), {
43229
43403
  kind: "mutation",
43230
43404
  auth: "admin"
43231
43405
  }),
43232
- /** Every known relocate job (in-RAM, newest-first). */
43233
- getRelocateStatus: method(zod.z.object({}), zod.z.array(RelocateJobSchema).readonly(), {
43234
- kind: "query",
43406
+ resumeForStorageMigration: method(StorageMigrationLeaseInputSchema, zod.z.object({ resumed: zod.z.literal(true) }), {
43407
+ kind: "mutation",
43235
43408
  auth: "admin"
43236
43409
  }),
43237
- cancelRelocate: method(zod.z.object({ jobId: zod.z.string() }), zod.z.object({ cancelled: zod.z.boolean() }), {
43410
+ /** Re-resolve location roots after the coordinator changes defaults. */
43411
+ refreshStorageLocationsForMigration: method(StorageMigrationLeaseInputSchema, zod.z.object({ refreshed: zod.z.literal(true) }), {
43412
+ kind: "mutation",
43413
+ auth: "admin"
43414
+ }),
43415
+ /** Internal mover, callable only by the storage-migration coordinator. */
43416
+ startStorageMigrationMove: method(StorageMigrationFootageMoveInputSchema, zod.z.object({ jobId: zod.z.string() }), {
43417
+ kind: "mutation",
43418
+ auth: "admin"
43419
+ }),
43420
+ getStorageMigrationMoveStatus: method(zod.z.object({ jobId: zod.z.string() }), RelocateJobSchema.nullable(), { auth: "admin" }),
43421
+ cancelStorageMigrationMove: method(zod.z.object({ jobId: zod.z.string() }), zod.z.object({ cancelled: zod.z.boolean() }), {
43238
43422
  kind: "mutation",
43239
43423
  auth: "admin"
43240
43424
  })
@@ -45313,6 +45497,7 @@ var require_dist_DWZce90k = __commonJS({
45313
45497
  ssoBridgeCapability,
45314
45498
  storageCapability,
45315
45499
  storageEvictableCapability,
45500
+ storageMigrationCapability,
45316
45501
  storageProviderCapability,
45317
45502
  streamBrokerCapability,
45318
45503
  streamCatalogCapability,
@@ -48239,6 +48424,12 @@ var require_dist_DWZce90k = __commonJS({
48239
48424
  addonId: null,
48240
48425
  access: "delete"
48241
48426
  },
48427
+ "osdManager.copyDeviceConfiguration": {
48428
+ capName: "osd-manager",
48429
+ capScope: "system",
48430
+ addonId: null,
48431
+ access: "create"
48432
+ },
48242
48433
  "osdManager.getConditionSupport": {
48243
48434
  capName: "osd-manager",
48244
48435
  capScope: "system",
@@ -48335,7 +48526,7 @@ var require_dist_DWZce90k = __commonJS({
48335
48526
  addonId: null,
48336
48527
  access: "create"
48337
48528
  },
48338
- "pipelineAnalytics.cancelMediaRelocate": {
48529
+ "pipelineAnalytics.cancelStorageMigrationMove": {
48339
48530
  capName: "pipeline-analytics",
48340
48531
  capScope: "device",
48341
48532
  addonId: null,
@@ -48407,12 +48598,6 @@ var require_dist_DWZce90k = __commonJS({
48407
48598
  addonId: null,
48408
48599
  access: "view"
48409
48600
  },
48410
- "pipelineAnalytics.getMediaRelocateStatus": {
48411
- capName: "pipeline-analytics",
48412
- capScope: "device",
48413
- addonId: null,
48414
- access: "view"
48415
- },
48416
48601
  "pipelineAnalytics.getMotionEvents": {
48417
48602
  capName: "pipeline-analytics",
48418
48603
  capScope: "device",
@@ -48449,6 +48634,12 @@ var require_dist_DWZce90k = __commonJS({
48449
48634
  addonId: null,
48450
48635
  access: "view"
48451
48636
  },
48637
+ "pipelineAnalytics.getStorageMigrationMoveStatus": {
48638
+ capName: "pipeline-analytics",
48639
+ capScope: "device",
48640
+ addonId: null,
48641
+ access: "view"
48642
+ },
48452
48643
  "pipelineAnalytics.getTrack": {
48453
48644
  capName: "pipeline-analytics",
48454
48645
  capScope: "device",
@@ -48527,6 +48718,12 @@ var require_dist_DWZce90k = __commonJS({
48527
48718
  addonId: null,
48528
48719
  access: "view"
48529
48720
  },
48721
+ "pipelineAnalytics.pauseForStorageMigration": {
48722
+ capName: "pipeline-analytics",
48723
+ capScope: "device",
48724
+ addonId: null,
48725
+ access: "create"
48726
+ },
48530
48727
  "pipelineAnalytics.proposeRetrainAnnotations": {
48531
48728
  capName: "pipeline-analytics",
48532
48729
  capScope: "device",
@@ -48557,7 +48754,7 @@ var require_dist_DWZce90k = __commonJS({
48557
48754
  addonId: null,
48558
48755
  access: "create"
48559
48756
  },
48560
- "pipelineAnalytics.relocateMedia": {
48757
+ "pipelineAnalytics.refreshStorageLocationsForMigration": {
48561
48758
  capName: "pipeline-analytics",
48562
48759
  capScope: "device",
48563
48760
  addonId: null,
@@ -48569,6 +48766,12 @@ var require_dist_DWZce90k = __commonJS({
48569
48766
  addonId: null,
48570
48767
  access: "create"
48571
48768
  },
48769
+ "pipelineAnalytics.resumeForStorageMigration": {
48770
+ capName: "pipeline-analytics",
48771
+ capScope: "device",
48772
+ addonId: null,
48773
+ access: "create"
48774
+ },
48572
48775
  "pipelineAnalytics.saveRetrainAnnotations": {
48573
48776
  capName: "pipeline-analytics",
48574
48777
  capScope: "device",
@@ -48593,6 +48796,12 @@ var require_dist_DWZce90k = __commonJS({
48593
48796
  addonId: null,
48594
48797
  access: "create"
48595
48798
  },
48799
+ "pipelineAnalytics.startStorageMigrationMove": {
48800
+ capName: "pipeline-analytics",
48801
+ capScope: "device",
48802
+ addonId: null,
48803
+ access: "create"
48804
+ },
48596
48805
  "pipelineAnalytics.wipeAllAnalytics": {
48597
48806
  capName: "pipeline-analytics",
48598
48807
  capScope: "device",
@@ -48959,6 +49168,12 @@ var require_dist_DWZce90k = __commonJS({
48959
49168
  addonId: null,
48960
49169
  access: "view"
48961
49170
  },
49171
+ "pipelineOrchestrator.pauseForStorageMigration": {
49172
+ capName: "pipeline-orchestrator",
49173
+ capScope: "system",
49174
+ addonId: null,
49175
+ access: "create"
49176
+ },
48962
49177
  "pipelineOrchestrator.rebalance": {
48963
49178
  capName: "pipeline-orchestrator",
48964
49179
  capScope: "system",
@@ -48983,6 +49198,12 @@ var require_dist_DWZce90k = __commonJS({
48983
49198
  addonId: null,
48984
49199
  access: "view"
48985
49200
  },
49201
+ "pipelineOrchestrator.resumeForStorageMigration": {
49202
+ capName: "pipeline-orchestrator",
49203
+ capScope: "system",
49204
+ addonId: null,
49205
+ access: "create"
49206
+ },
48986
49207
  "pipelineOrchestrator.saveTemplate": {
48987
49208
  capName: "pipeline-orchestrator",
48988
49209
  capScope: "system",
@@ -49379,7 +49600,7 @@ var require_dist_DWZce90k = __commonJS({
49379
49600
  addonId: null,
49380
49601
  access: "create"
49381
49602
  },
49382
- "recording.cancelRelocate": {
49603
+ "recording.cancelStorageMigrationMove": {
49383
49604
  capName: "recording",
49384
49605
  capScope: "system",
49385
49606
  addonId: null,
@@ -49415,7 +49636,7 @@ var require_dist_DWZce90k = __commonJS({
49415
49636
  addonId: null,
49416
49637
  access: "view"
49417
49638
  },
49418
- "recording.getRelocateStatus": {
49639
+ "recording.getStorageMigrationMoveStatus": {
49419
49640
  capName: "recording",
49420
49641
  capScope: "system",
49421
49642
  addonId: null,
@@ -49439,6 +49660,12 @@ var require_dist_DWZce90k = __commonJS({
49439
49660
  addonId: null,
49440
49661
  access: "view"
49441
49662
  },
49663
+ "recording.pauseForStorageMigration": {
49664
+ capName: "recording",
49665
+ capScope: "system",
49666
+ addonId: null,
49667
+ access: "create"
49668
+ },
49442
49669
  "recording.pruneFootage": {
49443
49670
  capName: "recording",
49444
49671
  capScope: "system",
@@ -49457,7 +49684,7 @@ var require_dist_DWZce90k = __commonJS({
49457
49684
  addonId: null,
49458
49685
  access: "view"
49459
49686
  },
49460
- "recording.relocateFootage": {
49687
+ "recording.refreshStorageLocationsForMigration": {
49461
49688
  capName: "recording",
49462
49689
  capScope: "system",
49463
49690
  addonId: null,
@@ -49481,12 +49708,24 @@ var require_dist_DWZce90k = __commonJS({
49481
49708
  addonId: null,
49482
49709
  access: "create"
49483
49710
  },
49711
+ "recording.resumeForStorageMigration": {
49712
+ capName: "recording",
49713
+ capScope: "system",
49714
+ addonId: null,
49715
+ access: "create"
49716
+ },
49484
49717
  "recording.setDeviceConfig": {
49485
49718
  capName: "recording",
49486
49719
  capScope: "system",
49487
49720
  addonId: null,
49488
49721
  access: "create"
49489
49722
  },
49723
+ "recording.startStorageMigrationMove": {
49724
+ capName: "recording",
49725
+ capScope: "system",
49726
+ addonId: null,
49727
+ access: "create"
49728
+ },
49490
49729
  "recordingExport.cancelExport": {
49491
49730
  capName: "recordingExport",
49492
49731
  capScope: "system",
@@ -49877,6 +50116,30 @@ var require_dist_DWZce90k = __commonJS({
49877
50116
  addonId: null,
49878
50117
  access: "view"
49879
50118
  },
50119
+ "storageMigration.cancel": {
50120
+ capName: "storage-migration",
50121
+ capScope: "system",
50122
+ addonId: null,
50123
+ access: "create"
50124
+ },
50125
+ "storageMigration.plan": {
50126
+ capName: "storage-migration",
50127
+ capScope: "system",
50128
+ addonId: null,
50129
+ access: "view"
50130
+ },
50131
+ "storageMigration.start": {
50132
+ capName: "storage-migration",
50133
+ capScope: "system",
50134
+ addonId: null,
50135
+ access: "create"
50136
+ },
50137
+ "storageMigration.status": {
50138
+ capName: "storage-migration",
50139
+ capScope: "system",
50140
+ addonId: null,
50141
+ access: "view"
50142
+ },
49880
50143
  "storageProvider.abortUpload": {
49881
50144
  capName: "storage-provider",
49882
50145
  capScope: "system",
@@ -50255,12 +50518,42 @@ var require_dist_DWZce90k = __commonJS({
50255
50518
  addonId: null,
50256
50519
  access: "create"
50257
50520
  },
50521
+ "terminalSession.adoptLegacyMonitor": {
50522
+ capName: "terminal-session",
50523
+ capScope: "system",
50524
+ addonId: null,
50525
+ access: "create"
50526
+ },
50258
50527
  "terminalSession.close": {
50259
50528
  capName: "terminal-session",
50260
50529
  capScope: "system",
50261
50530
  addonId: null,
50262
50531
  access: "create"
50263
50532
  },
50533
+ "terminalSession.createInstance": {
50534
+ capName: "terminal-session",
50535
+ capScope: "system",
50536
+ addonId: null,
50537
+ access: "create"
50538
+ },
50539
+ "terminalSession.deleteInstance": {
50540
+ capName: "terminal-session",
50541
+ capScope: "system",
50542
+ addonId: null,
50543
+ access: "delete"
50544
+ },
50545
+ "terminalSession.listInstances": {
50546
+ capName: "terminal-session",
50547
+ capScope: "system",
50548
+ addonId: null,
50549
+ access: "view"
50550
+ },
50551
+ "terminalSession.listLegacyCameras": {
50552
+ capName: "terminal-session",
50553
+ capScope: "system",
50554
+ addonId: null,
50555
+ access: "view"
50556
+ },
50264
50557
  "terminalSession.listProfiles": {
50265
50558
  capName: "terminal-session",
50266
50559
  capScope: "system",
@@ -50291,6 +50584,12 @@ var require_dist_DWZce90k = __commonJS({
50291
50584
  addonId: null,
50292
50585
  access: "create"
50293
50586
  },
50587
+ "terminalSession.setInstanceEnabled": {
50588
+ capName: "terminal-session",
50589
+ capScope: "system",
50590
+ addonId: null,
50591
+ access: "create"
50592
+ },
50294
50593
  "terminalSession.writeInput": {
50295
50594
  capName: "terminal-session",
50296
50595
  capScope: "system",
@@ -51199,6 +51498,12 @@ var require_dist_DWZce90k = __commonJS({
51199
51498
  return StorageLocationTypeSchema;
51200
51499
  }
51201
51500
  });
51501
+ Object.defineProperty(exports, "StorageMigrationJobSchema", {
51502
+ enumerable: true,
51503
+ get: function() {
51504
+ return StorageMigrationJobSchema;
51505
+ }
51506
+ });
51202
51507
  Object.defineProperty(exports, "UserRecordSchema", {
51203
51508
  enumerable: true,
51204
51509
  get: function() {
@@ -51583,6 +51888,12 @@ var require_dist_DWZce90k = __commonJS({
51583
51888
  return storageCapability;
51584
51889
  }
51585
51890
  });
51891
+ Object.defineProperty(exports, "storageMigrationCapability", {
51892
+ enumerable: true,
51893
+ get: function() {
51894
+ return storageMigrationCapability;
51895
+ }
51896
+ });
51586
51897
  Object.defineProperty(exports, "storageProviderCapability", {
51587
51898
  enumerable: true,
51588
51899
  get: function() {
@@ -51625,7 +51936,7 @@ var require_alerts_addon = __commonJS({
51625
51936
  [Symbol.toStringTag]: { value: "Module" }
51626
51937
  });
51627
51938
  require_chunk_Cek0wNdY();
51628
- var require_dist10 = require_dist_DWZce90k();
51939
+ var require_dist10 = require_dist_cINpngi1();
51629
51940
  function selectExpired(alerts, cutoffMs) {
51630
51941
  return alerts.filter((a) => a.createdAt < cutoffMs).sort((a, b) => a.createdAt - b.createdAt).map((a) => a.id);
51631
51942
  }
@@ -52438,7 +52749,7 @@ var require_console_logging = __commonJS({
52438
52749
  [Symbol.toStringTag]: { value: "Module" }
52439
52750
  });
52440
52751
  require_chunk_Cek0wNdY();
52441
- var require_dist10 = require_dist_DWZce90k();
52752
+ var require_dist10 = require_dist_cINpngi1();
52442
52753
  var require_formatter = require_formatter_DqAKDlvN();
52443
52754
  var LEVEL_RANK = {
52444
52755
  debug: 0,
@@ -52532,7 +52843,7 @@ var require_core_blocks_addon = __commonJS({
52532
52843
  "use strict";
52533
52844
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
52534
52845
  var require_chunk = require_chunk_Cek0wNdY();
52535
- var require_dist10 = require_dist_DWZce90k();
52846
+ var require_dist10 = require_dist_cINpngi1();
52536
52847
  var node_crypto = __require("crypto");
52537
52848
  var node_fs_promises = __require("fs/promises");
52538
52849
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -55230,7 +55541,7 @@ var require_device_manager_addon = __commonJS({
55230
55541
  [Symbol.toStringTag]: { value: "Module" }
55231
55542
  });
55232
55543
  require_chunk_Cek0wNdY();
55233
- var require_dist10 = require_dist_DWZce90k();
55544
+ var require_dist10 = require_dist_cINpngi1();
55234
55545
  var node_crypto = __require("crypto");
55235
55546
  var _camstack_types_node = require_node();
55236
55547
  var JOB_HISTORY = 20;
@@ -59086,7 +59397,7 @@ var require_hub_forwarder = __commonJS({
59086
59397
  [Symbol.toStringTag]: { value: "Module" }
59087
59398
  });
59088
59399
  require_chunk_Cek0wNdY();
59089
- var require_dist10 = require_dist_DWZce90k();
59400
+ var require_dist10 = require_dist_cINpngi1();
59090
59401
  var require_formatter = require_formatter_DqAKDlvN();
59091
59402
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
59092
59403
  var HubForwarderDestination = class {
@@ -59223,7 +59534,7 @@ var require_liveness_monitor_addon = __commonJS({
59223
59534
  "use strict";
59224
59535
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
59225
59536
  require_chunk_Cek0wNdY();
59226
- var require_dist10 = require_dist_DWZce90k();
59537
+ var require_dist10 = require_dist_cINpngi1();
59227
59538
  var NO_DEVICES = "liveness:no-devices";
59228
59539
  var ALL_OFFLINE = "liveness:all-devices-offline";
59229
59540
  var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
@@ -59413,7 +59724,7 @@ var require_local_auth_addon = __commonJS({
59413
59724
  [Symbol.toStringTag]: { value: "Module" }
59414
59725
  });
59415
59726
  var require_chunk = require_chunk_Cek0wNdY();
59416
- var require_dist10 = require_dist_DWZce90k();
59727
+ var require_dist10 = require_dist_cINpngi1();
59417
59728
  var node_crypto = __require("crypto");
59418
59729
  node_crypto = require_chunk.__toESM(node_crypto);
59419
59730
  var crypto$1 = __require("crypto");
@@ -67097,7 +67408,7 @@ var require_loki_logging = __commonJS({
67097
67408
  [Symbol.toStringTag]: { value: "Module" }
67098
67409
  });
67099
67410
  require_chunk_Cek0wNdY();
67100
- var require_dist10 = require_dist_DWZce90k();
67411
+ var require_dist10 = require_dist_cINpngi1();
67101
67412
  function sanitizeLabelName(raw) {
67102
67413
  const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
67103
67414
  return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
@@ -67662,7 +67973,7 @@ var require_native_metrics_addon = __commonJS({
67662
67973
  [Symbol.toStringTag]: { value: "Module" }
67663
67974
  });
67664
67975
  var require_chunk = require_chunk_Cek0wNdY();
67665
- var require_dist10 = require_dist_DWZce90k();
67976
+ var require_dist10 = require_dist_cINpngi1();
67666
67977
  var node_child_process = __require("child_process");
67667
67978
  var node_util = __require("util");
67668
67979
  var node_os = __require("os");
@@ -68604,7 +68915,7 @@ var require_filesystem_storage_addon = __commonJS({
68604
68915
  [Symbol.toStringTag]: { value: "Module" }
68605
68916
  });
68606
68917
  var require_chunk = require_chunk_Cek0wNdY();
68607
- var require_dist10 = require_dist_DWZce90k();
68918
+ var require_dist10 = require_dist_cINpngi1();
68608
68919
  var node_crypto = __require("crypto");
68609
68920
  var node_fs_promises = __require("fs/promises");
68610
68921
  var node_path = __require("path");
@@ -69717,7 +70028,7 @@ var require_sqlite_settings_addon = __commonJS({
69717
70028
  [Symbol.toStringTag]: { value: "Module" }
69718
70029
  });
69719
70030
  var require_chunk = require_chunk_Cek0wNdY();
69720
- var require_dist10 = require_dist_DWZce90k();
70031
+ var require_dist10 = require_dist_cINpngi1();
69721
70032
  var node_crypto = __require("crypto");
69722
70033
  var node_fs = __require("fs");
69723
70034
  var node_module = __require("module");
@@ -71232,7 +71543,8 @@ var require_storage_orchestrator_addon = __commonJS({
71232
71543
  [Symbol.toStringTag]: { value: "Module" }
71233
71544
  });
71234
71545
  var require_chunk = require_chunk_Cek0wNdY();
71235
- var require_dist10 = require_dist_DWZce90k();
71546
+ var require_dist10 = require_dist_cINpngi1();
71547
+ var node_crypto = __require("crypto");
71236
71548
  var node_fs_promises = __require("fs/promises");
71237
71549
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
71238
71550
  var node_path = __require("path");
@@ -71463,6 +71775,53 @@ var require_storage_orchestrator_addon = __commonJS({
71463
71775
  return null;
71464
71776
  }
71465
71777
  /**
71778
+ * Repoint several logical defaults as one in-memory commit. The migration
71779
+ * coordinator persists its `repointing` phase before calling this method, so
71780
+ * a process crash during the backing-store writes is recovered by replaying
71781
+ * the same idempotent target set before anyone resumes writers.
71782
+ */
71783
+ async setDefaultLocations(targetByType) {
71784
+ if (targetByType.size === 0) return;
71785
+ const now = Date.now();
71786
+ const nextById = new Map(this.locations);
71787
+ const touched = /* @__PURE__ */ new Map();
71788
+ for (const [type, targetId] of targetByType) {
71789
+ const target = nextById.get(targetId);
71790
+ if (!target) throw new Error(`Storage location "${targetId}" not found`);
71791
+ if (target.type !== type) throw new Error(`Storage location "${targetId}" is type "${target.type}", expected "${type}"`);
71792
+ for (const [id, location] of nextById) {
71793
+ if (location.type !== type) continue;
71794
+ const isDefault = id === targetId;
71795
+ if (location.isDefault === isDefault) continue;
71796
+ const updated = {
71797
+ ...location,
71798
+ isDefault,
71799
+ updatedAt: now
71800
+ };
71801
+ nextById.set(id, updated);
71802
+ touched.set(id, updated);
71803
+ }
71804
+ }
71805
+ if (this.locationStore) {
71806
+ const previous = /* @__PURE__ */ new Map();
71807
+ for (const id of touched.keys()) {
71808
+ const location = this.locations.get(id);
71809
+ if (location) previous.set(id, location);
71810
+ }
71811
+ try {
71812
+ for (const location of touched.values()) await this.locationStore.upsert(location);
71813
+ } catch (err) {
71814
+ for (const location of previous.values()) try {
71815
+ await this.locationStore.upsert(location);
71816
+ } catch {
71817
+ }
71818
+ throw err;
71819
+ }
71820
+ }
71821
+ this.locations.clear();
71822
+ for (const [id, location] of nextById) this.locations.set(id, location);
71823
+ }
71824
+ /**
71466
71825
  * Insert or update a location. If `isDefault: true`, atomically
71467
71826
  * demotes any other default for the same type — operators always see
71468
71827
  * exactly one default per type.
@@ -72095,6 +72454,349 @@ var require_storage_orchestrator_addon = __commonJS({
72095
72454
  return reclaimedAny;
72096
72455
  }
72097
72456
  };
72457
+ var STORAGE_CLASSES = [
72458
+ "recordings",
72459
+ "recordingsLow",
72460
+ "eventMedia"
72461
+ ];
72462
+ var PARTICIPANTS = [
72463
+ "pipeline",
72464
+ "recorder",
72465
+ "analytics"
72466
+ ];
72467
+ var REVERSE_PARTICIPANTS = [
72468
+ "analytics",
72469
+ "recorder",
72470
+ "pipeline"
72471
+ ];
72472
+ var StorageMigrationCoordinator = class {
72473
+ deps;
72474
+ active = null;
72475
+ runPromise = null;
72476
+ startReserved = false;
72477
+ constructor(deps) {
72478
+ this.deps = deps;
72479
+ }
72480
+ async plan(input) {
72481
+ const moves = [];
72482
+ for (const storageClass of STORAGE_CLASSES) {
72483
+ const targetId = input.destinations[storageClass];
72484
+ if (targetId === void 0) continue;
72485
+ const source = this.deps.locations.getDefaultLocation(storageClass);
72486
+ if (!source) throw new Error(`No default storage location for "${storageClass}"`);
72487
+ const target = this.deps.locations.getLocationById(targetId);
72488
+ if (!target) throw new Error(`Storage location "${targetId}" not found`);
72489
+ if (target.type !== storageClass) throw new Error(`Storage location "${targetId}" is type "${target.type}", expected "${storageClass}"`);
72490
+ if (source.id === target.id) throw new Error(`Storage location "${targetId}" is already the "${storageClass}" default`);
72491
+ moves.push({
72492
+ storageClass,
72493
+ fromLocationId: source.id,
72494
+ toLocationId: target.id,
72495
+ moverJobId: null,
72496
+ state: null,
72497
+ error: null
72498
+ });
72499
+ }
72500
+ if (moves.length === 0) throw new Error("select at least one storage class");
72501
+ return {
72502
+ destinations: input.destinations,
72503
+ moves: moves.map(({ storageClass, fromLocationId, toLocationId }) => ({
72504
+ storageClass,
72505
+ fromLocationId,
72506
+ toLocationId
72507
+ }))
72508
+ };
72509
+ }
72510
+ async start(input) {
72511
+ if (this.startReserved) throw new Error("storage migration is already active");
72512
+ this.startReserved = true;
72513
+ try {
72514
+ const existing = await this.status();
72515
+ if (existing && isTerminal(existing) && existing.pausedParticipants.length > 0) {
72516
+ await this.releaseAfterTerminal(existing);
72517
+ await this.persist(existing);
72518
+ if (existing.pausedParticipants.length > 0) throw new Error(`storage migration ${existing.jobId} still holds maintenance leases`);
72519
+ }
72520
+ if (existing && !isTerminal(existing)) throw new Error(`storage migration is already active (${existing.jobId})`);
72521
+ const plan = await this.plan(input);
72522
+ const now = this.deps.now();
72523
+ const job = {
72524
+ jobId: this.deps.newId(),
72525
+ phase: "planning",
72526
+ destinations: input.destinations,
72527
+ throttleMbps: input.throttleMbps ?? 40,
72528
+ moves: plan.moves.map((move) => ({
72529
+ ...move,
72530
+ moverJobId: null,
72531
+ state: null,
72532
+ error: null
72533
+ })),
72534
+ pauseLeaseId: null,
72535
+ pausedParticipants: [],
72536
+ repointed: false,
72537
+ cancelRequested: false,
72538
+ startedAt: now,
72539
+ updatedAt: now,
72540
+ finishedAt: null,
72541
+ error: null
72542
+ };
72543
+ this.active = job;
72544
+ await this.persist(job);
72545
+ this.runPromise = this.run(job);
72546
+ this.runPromise;
72547
+ return job.jobId;
72548
+ } finally {
72549
+ this.startReserved = false;
72550
+ }
72551
+ }
72552
+ async status(jobId) {
72553
+ const job = this.active ?? await this.deps.state.get();
72554
+ if (jobId !== void 0 && job?.jobId !== jobId) return null;
72555
+ return job;
72556
+ }
72557
+ async cancel(jobId) {
72558
+ const job = await this.status(jobId);
72559
+ if (!job || isTerminal(job) || job.repointed) return false;
72560
+ job.cancelRequested = true;
72561
+ await this.persist(job);
72562
+ await Promise.all(job.moves.filter((move) => move.moverJobId !== null).map((move) => this.cancelMove(move)));
72563
+ return true;
72564
+ }
72565
+ /** Boot recovery resumes a durable unfinished state. A missing in-memory
72566
+ * child mover is recreated from the same copy-if-absent input. */
72567
+ async recover() {
72568
+ const job = await this.deps.state.get();
72569
+ if (!job) return;
72570
+ if (job.cancelRequested) {
72571
+ await Promise.all(job.moves.filter((move) => move.moverJobId !== null).map((move) => this.cancelMove(move)));
72572
+ await this.waitForMoves(job);
72573
+ await this.releaseAfterTerminal(job);
72574
+ job.phase = "cancelled";
72575
+ job.finishedAt ??= this.deps.now();
72576
+ await this.persist(job);
72577
+ return;
72578
+ }
72579
+ if (isTerminal(job)) {
72580
+ if (job.pausedParticipants.length > 0) {
72581
+ await this.releaseAfterTerminal(job);
72582
+ await this.persist(job);
72583
+ }
72584
+ return;
72585
+ }
72586
+ this.active = job;
72587
+ job.pauseLeaseId ??= this.deps.newId();
72588
+ if (job.repointed && job.phase === "resuming") job.phase = "refreshing";
72589
+ await this.persist(job);
72590
+ try {
72591
+ await this.pauseParticipants(job, true);
72592
+ } catch (err) {
72593
+ job.error = err instanceof Error ? err.message : String(err);
72594
+ await this.persist(job);
72595
+ return;
72596
+ }
72597
+ if (this.runPromise === null) {
72598
+ this.runPromise = this.run(job);
72599
+ this.runPromise;
72600
+ }
72601
+ }
72602
+ async run(job) {
72603
+ try {
72604
+ if (job.phase === "planning") await this.setPhase(job, "pausing");
72605
+ if (job.phase === "pausing") {
72606
+ job.pauseLeaseId ??= job.jobId;
72607
+ await this.pauseParticipants(job);
72608
+ if (job.cancelRequested) return this.finishCancelled(job);
72609
+ await this.setPhase(job, "moving");
72610
+ }
72611
+ if (job.phase === "moving") {
72612
+ await this.startOrResumeMoves(job);
72613
+ await this.waitForMoves(job);
72614
+ if (job.cancelRequested) return this.finishCancelled(job);
72615
+ await this.setPhase(job, "verifying");
72616
+ }
72617
+ if (job.phase === "verifying") {
72618
+ await this.verifyMoves(job);
72619
+ if (job.cancelRequested) return this.finishCancelled(job);
72620
+ await this.setPhase(job, "repointing");
72621
+ }
72622
+ if (job.phase === "repointing") {
72623
+ const targets = new Map(job.moves.map((move) => [move.storageClass, move.toLocationId]));
72624
+ await this.deps.locations.setDefaultLocations(targets);
72625
+ job.repointed = true;
72626
+ await this.setPhase(job, "refreshing");
72627
+ }
72628
+ if (job.phase === "refreshing") {
72629
+ const leaseId = requireLease(job);
72630
+ if (job.moves.some((move) => move.storageClass !== "eventMedia")) await this.deps.participants.recorder.refresh(leaseId);
72631
+ if (job.moves.some((move) => move.storageClass === "eventMedia")) await this.deps.participants.analytics.refresh(leaseId);
72632
+ await this.setPhase(job, "resuming");
72633
+ }
72634
+ if (job.phase === "resuming") {
72635
+ await this.resumeParticipants(job);
72636
+ await this.setPhase(job, "done");
72637
+ }
72638
+ } catch (err) {
72639
+ job.error = err instanceof Error ? err.message : String(err);
72640
+ if (job.repointed) {
72641
+ job.phase = "refreshing";
72642
+ job.finishedAt = null;
72643
+ await this.persist(job);
72644
+ return;
72645
+ }
72646
+ job.phase = "failed";
72647
+ job.finishedAt = this.deps.now();
72648
+ await this.releaseAfterTerminal(job);
72649
+ await this.persist(job);
72650
+ } finally {
72651
+ if (isTerminal(job)) {
72652
+ await this.releaseAfterTerminal(job);
72653
+ this.active = job;
72654
+ }
72655
+ this.runPromise = null;
72656
+ }
72657
+ }
72658
+ async pauseParticipants(job, reacquire = false) {
72659
+ const leaseId = requireLease(job);
72660
+ for (const name of PARTICIPANTS) {
72661
+ if (job.cancelRequested) return;
72662
+ if (!reacquire && job.pausedParticipants.includes(name)) continue;
72663
+ await this.participant(name).pause(leaseId);
72664
+ if (!job.pausedParticipants.includes(name)) job.pausedParticipants.push(name);
72665
+ await this.persist(job);
72666
+ }
72667
+ }
72668
+ async resumeParticipants(job) {
72669
+ const leaseId = requireLease(job);
72670
+ for (const name of REVERSE_PARTICIPANTS) {
72671
+ if (!job.pausedParticipants.includes(name)) continue;
72672
+ await this.participant(name).resume(leaseId);
72673
+ job.pausedParticipants = job.pausedParticipants.filter((participant) => participant !== name);
72674
+ await this.persist(job);
72675
+ }
72676
+ }
72677
+ async releaseAfterTerminal(job) {
72678
+ if (job.pauseLeaseId === null) return;
72679
+ for (const name of REVERSE_PARTICIPANTS) {
72680
+ if (!job.pausedParticipants.includes(name)) continue;
72681
+ try {
72682
+ await this.participant(name).resume(job.pauseLeaseId);
72683
+ job.pausedParticipants = job.pausedParticipants.filter((participant) => participant !== name);
72684
+ await this.persist(job);
72685
+ } catch {
72686
+ }
72687
+ }
72688
+ }
72689
+ async startOrResumeMoves(job) {
72690
+ if (job.cancelRequested) return;
72691
+ const mediaMove = job.moves.find((move) => move.storageClass === "eventMedia");
72692
+ if (mediaMove?.moverJobId === null) {
72693
+ mediaMove.moverJobId = await this.startMove(job, mediaMove);
72694
+ await this.persist(job);
72695
+ }
72696
+ const footageMoves = job.moves.filter((move) => move.storageClass !== "eventMedia");
72697
+ for (let index = 0; index < footageMoves.length; index++) {
72698
+ const move = footageMoves[index];
72699
+ if (move.moverJobId !== null) continue;
72700
+ if (!footageMoves.slice(0, index).every((predecessor) => predecessor.state === "done")) return;
72701
+ move.moverJobId = await this.startMove(job, move);
72702
+ await this.persist(job);
72703
+ return;
72704
+ }
72705
+ }
72706
+ async waitForMoves(job) {
72707
+ const sleep = this.deps.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
72708
+ const pollMs = this.deps.pollMs ?? 250;
72709
+ for (; ; ) {
72710
+ if (!job.cancelRequested) await this.startOrResumeMoves(job);
72711
+ let complete = true;
72712
+ for (const [index, move] of job.moves.entries()) {
72713
+ if (job.cancelRequested && move.moverJobId === null) continue;
72714
+ if (move.storageClass !== "eventMedia" && job.moves.slice(0, index).filter((predecessor) => predecessor.storageClass !== "eventMedia").some((predecessor) => predecessor.state !== "done")) {
72715
+ complete = false;
72716
+ continue;
72717
+ }
72718
+ if (move.moverJobId === null) {
72719
+ if (!job.cancelRequested) complete = false;
72720
+ continue;
72721
+ }
72722
+ const status = await this.moveStatus(move);
72723
+ if (status === null) {
72724
+ if (job.cancelRequested) {
72725
+ move.state = "cancelled";
72726
+ continue;
72727
+ }
72728
+ move.moverJobId = await this.startMove(job, move);
72729
+ move.state = "running";
72730
+ await this.persist(job);
72731
+ complete = false;
72732
+ continue;
72733
+ }
72734
+ move.state = status.state;
72735
+ move.error = status.error;
72736
+ if (status.state === "failed") throw new Error(move.error ?? `${move.storageClass} move failed`);
72737
+ if (status.state === "cancelled") {
72738
+ job.cancelRequested = true;
72739
+ continue;
72740
+ }
72741
+ if (status.state !== "done") complete = false;
72742
+ }
72743
+ await this.persist(job);
72744
+ if (complete) return;
72745
+ await sleep(pollMs);
72746
+ }
72747
+ }
72748
+ async verifyMoves(job) {
72749
+ for (const move of job.moves) if (move.state !== "done") throw new Error(`${move.storageClass} move did not complete verification`);
72750
+ }
72751
+ async startMove(job, move) {
72752
+ if (move.storageClass === "eventMedia") return (await this.deps.participants.analytics.startMove({
72753
+ toLocationId: move.toLocationId,
72754
+ throttleMbps: job.throttleMbps,
72755
+ leaseId: requireLease(job)
72756
+ })).jobId;
72757
+ return (await this.deps.participants.recorder.startMove({
72758
+ fromLocationId: move.fromLocationId,
72759
+ toLocationId: move.toLocationId,
72760
+ footageClass: move.storageClass,
72761
+ throttleMbps: job.throttleMbps,
72762
+ leaseId: requireLease(job)
72763
+ })).jobId;
72764
+ }
72765
+ async moveStatus(move) {
72766
+ if (move.moverJobId === null) return null;
72767
+ return move.storageClass === "eventMedia" ? this.deps.participants.analytics.getMove(move.moverJobId) : this.deps.participants.recorder.getMove(move.moverJobId);
72768
+ }
72769
+ async cancelMove(move) {
72770
+ if (move.moverJobId === null) return;
72771
+ if (move.storageClass === "eventMedia") await this.deps.participants.analytics.cancelMove(move.moverJobId);
72772
+ else await this.deps.participants.recorder.cancelMove(move.moverJobId);
72773
+ }
72774
+ participant(name) {
72775
+ return this.deps.participants[name];
72776
+ }
72777
+ async setPhase(job, phase) {
72778
+ job.phase = phase;
72779
+ if (isTerminal(job)) job.finishedAt = this.deps.now();
72780
+ await this.persist(job);
72781
+ }
72782
+ async finishCancelled(job) {
72783
+ job.phase = "cancelled";
72784
+ job.finishedAt = this.deps.now();
72785
+ await this.releaseAfterTerminal(job);
72786
+ await this.persist(job);
72787
+ }
72788
+ async persist(job) {
72789
+ job.updatedAt = this.deps.now();
72790
+ await this.deps.state.set(job);
72791
+ }
72792
+ };
72793
+ function requireLease(job) {
72794
+ if (job.pauseLeaseId === null) throw new Error("storage migration has no maintenance lease");
72795
+ return job.pauseLeaseId;
72796
+ }
72797
+ function isTerminal(job) {
72798
+ return job.phase === "done" || job.phase === "failed" || job.phase === "cancelled";
72799
+ }
72098
72800
  var STORAGE_PROVIDER_CAP_NAME = "storage-provider";
72099
72801
  var DATA_STORE_PROVIDER_CAP_NAME = "data-store-provider";
72100
72802
  var STORAGE_EVICTABLE_CAP_NAME = "storage-evictable";
@@ -72106,6 +72808,7 @@ var require_storage_orchestrator_addon = __commonJS({
72106
72808
  pressureManager = null;
72107
72809
  pressureTimer = null;
72108
72810
  pressureSweepInFlight = false;
72811
+ migration = null;
72109
72812
  /**
72110
72813
  * Cached `providerId → nodeLocal` snapshot (SP1). Backs the orchestrator's
72111
72814
  * synchronous `NodeLocalResolver` — `getProviderInfo()` is async, so we
@@ -72299,6 +73002,57 @@ var require_storage_orchestrator_addon = __commonJS({
72299
73002
  }
72300
73003
  }
72301
73004
  };
73005
+ const migration = new StorageMigrationCoordinator({
73006
+ locations: service,
73007
+ state: this.state("storage-migration", require_dist10.StorageMigrationJobSchema.nullable(), null),
73008
+ participants: {
73009
+ pipeline: {
73010
+ pause: async (leaseId) => {
73011
+ await this.ctx.api.pipelineOrchestrator.pauseForStorageMigration.mutate({ leaseId });
73012
+ },
73013
+ resume: async (leaseId) => {
73014
+ await this.ctx.api.pipelineOrchestrator.resumeForStorageMigration.mutate({ leaseId });
73015
+ }
73016
+ },
73017
+ recorder: {
73018
+ pause: async (leaseId) => {
73019
+ await this.ctx.api.recording.pauseForStorageMigration.mutate({ leaseId });
73020
+ },
73021
+ resume: async (leaseId) => {
73022
+ await this.ctx.api.recording.resumeForStorageMigration.mutate({ leaseId });
73023
+ },
73024
+ startMove: (input) => this.ctx.api.recording.startStorageMigrationMove.mutate(input),
73025
+ getMove: (jobId) => this.ctx.api.recording.getStorageMigrationMoveStatus.query({ jobId }),
73026
+ cancelMove: async (jobId) => (await this.ctx.api.recording.cancelStorageMigrationMove.mutate({ jobId })).cancelled,
73027
+ refresh: async (leaseId) => {
73028
+ await this.ctx.api.recording.refreshStorageLocationsForMigration.mutate({ leaseId });
73029
+ }
73030
+ },
73031
+ analytics: {
73032
+ pause: async (leaseId) => {
73033
+ await this.ctx.api.pipelineAnalytics.pauseForStorageMigration.mutate({ leaseId });
73034
+ },
73035
+ resume: async (leaseId) => {
73036
+ await this.ctx.api.pipelineAnalytics.resumeForStorageMigration.mutate({ leaseId });
73037
+ },
73038
+ startMove: (input) => this.ctx.api.pipelineAnalytics.startStorageMigrationMove.mutate(input),
73039
+ getMove: (jobId) => this.ctx.api.pipelineAnalytics.getStorageMigrationMoveStatus.query({ jobId }),
73040
+ cancelMove: async (jobId) => (await this.ctx.api.pipelineAnalytics.cancelStorageMigrationMove.mutate({ jobId })).cancelled,
73041
+ refresh: async (leaseId) => {
73042
+ await this.ctx.api.pipelineAnalytics.refreshStorageLocationsForMigration.mutate({ leaseId });
73043
+ }
73044
+ }
73045
+ },
73046
+ now: () => Date.now(),
73047
+ newId: () => (0, node_crypto.randomUUID)()
73048
+ });
73049
+ this.migration = migration;
73050
+ const migrationProvider = {
73051
+ plan: (input) => migration.plan(input),
73052
+ start: async (input) => ({ jobId: await migration.start(input) }),
73053
+ status: ({ jobId }) => migration.status(jobId),
73054
+ cancel: async ({ jobId }) => ({ cancelled: await migration.cancel(jobId) })
73055
+ };
72302
73056
  await this.seedFromDeclarations();
72303
73057
  const eventBus = this.ctx.eventBus;
72304
73058
  if (eventBus) {
@@ -72323,13 +73077,20 @@ var require_storage_orchestrator_addon = __commonJS({
72323
73077
  this.runPressureSweep();
72324
73078
  }, PRESSURE_SWEEP_INTERVAL_MS);
72325
73079
  this.ctx.logger.info("Storage orchestrator initialized");
72326
- return [{
72327
- capability: require_dist10.storageCapability,
72328
- provider
72329
- }, {
72330
- capability: require_dist10.settingsStoreCapability,
72331
- provider: createDataStoreDispatch(getEngines)
72332
- }];
73080
+ return [
73081
+ {
73082
+ capability: require_dist10.storageCapability,
73083
+ provider
73084
+ },
73085
+ {
73086
+ capability: require_dist10.storageMigrationCapability,
73087
+ provider: migrationProvider
73088
+ },
73089
+ {
73090
+ capability: require_dist10.settingsStoreCapability,
73091
+ provider: createDataStoreDispatch(getEngines)
73092
+ }
73093
+ ];
72333
73094
  }
72334
73095
  async onShutdown() {
72335
73096
  for (const dispose of this.seedSubscriptionDisposers) try {
@@ -72344,6 +73105,10 @@ var require_storage_orchestrator_addon = __commonJS({
72344
73105
  this.pressureManager = null;
72345
73106
  this.service?.clearSessions();
72346
73107
  this.service = null;
73108
+ this.migration = null;
73109
+ }
73110
+ async onHubReachable() {
73111
+ await this.migration?.recover();
72347
73112
  }
72348
73113
  /**
72349
73114
  * Resolve the live engine from the capability registry and wrap it in a
@@ -72566,6 +73331,7 @@ var require_storage_orchestrator_addon = __commonJS({
72566
73331
  }
72567
73332
  };
72568
73333
  exports.SqliteLocationStore = SqliteLocationStore;
73334
+ exports.StorageMigrationCoordinator = StorageMigrationCoordinator;
72569
73335
  exports.StorageOrchestratorAddon = StorageOrchestratorAddon;
72570
73336
  exports.default = StorageOrchestratorAddon;
72571
73337
  exports.StorageOrchestratorService = StorageOrchestratorService;
@@ -72583,6 +73349,7 @@ var require_storage_orchestrator = __commonJS({
72583
73349
  require_chunk_Cek0wNdY();
72584
73350
  var require_builtins_storage_orchestrator_storage_orchestrator_addon = require_storage_orchestrator_addon();
72585
73351
  exports.SqliteLocationStore = require_builtins_storage_orchestrator_storage_orchestrator_addon.SqliteLocationStore;
73352
+ exports.StorageMigrationCoordinator = require_builtins_storage_orchestrator_storage_orchestrator_addon.StorageMigrationCoordinator;
72586
73353
  exports.StorageOrchestratorAddon = require_builtins_storage_orchestrator_storage_orchestrator_addon.StorageOrchestratorAddon;
72587
73354
  exports.StorageOrchestratorService = require_builtins_storage_orchestrator_storage_orchestrator_addon.StorageOrchestratorService;
72588
73355
  exports.default = require_builtins_storage_orchestrator_storage_orchestrator_addon.StorageOrchestratorAddon;
@@ -72598,7 +73365,7 @@ var require_system_config_addon = __commonJS({
72598
73365
  [Symbol.toStringTag]: { value: "Module" }
72599
73366
  });
72600
73367
  require_chunk_Cek0wNdY();
72601
- var require_dist10 = require_dist_DWZce90k();
73368
+ var require_dist10 = require_dist_cINpngi1();
72602
73369
  var SECTION_TITLES = {
72603
73370
  server: "Server",
72604
73371
  auth: "Authentication"
@@ -90659,7 +91426,7 @@ var require_winston_logging = __commonJS({
90659
91426
  [Symbol.toStringTag]: { value: "Module" }
90660
91427
  });
90661
91428
  var require_chunk = require_chunk_Cek0wNdY();
90662
- var require_dist10 = require_dist_DWZce90k();
91429
+ var require_dist10 = require_dist_cINpngi1();
90663
91430
  var require_formatter = require_formatter_DqAKDlvN();
90664
91431
  var node_path = __require("path");
90665
91432
  node_path = require_chunk.__toESM(node_path);
@@ -91810,9 +92577,9 @@ var require_event_category_DxZbWydC = __commonJS({
91810
92577
  }
91811
92578
  });
91812
92579
 
91813
- // ../types/dist/sleep-EX1-qUVR.js
91814
- var require_sleep_EX1_qUVR = __commonJS({
91815
- "../types/dist/sleep-EX1-qUVR.js"(exports) {
92580
+ // ../types/dist/sleep-BszXLEvP.js
92581
+ var require_sleep_BszXLEvP = __commonJS({
92582
+ "../types/dist/sleep-BszXLEvP.js"(exports) {
91816
92583
  "use strict";
91817
92584
  var require_event_category = require_event_category_DxZbWydC();
91818
92585
  var zod = require_zod();
@@ -94287,9 +95054,12 @@ var require_sleep_EX1_qUVR = __commonJS({
94287
95054
  getEventStoreFootprint: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getEventStoreFootprint", "query", input),
94288
95055
  pruneEvents: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "pruneEvents", "mutation", input),
94289
95056
  deleteDeviceEvents: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "deleteDeviceEvents", "mutation", input),
94290
- relocateMedia: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "relocateMedia", "mutation", input),
94291
- getMediaRelocateStatus: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getMediaRelocateStatus", "query", input),
94292
- cancelMediaRelocate: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "cancelMediaRelocate", "mutation", input),
95057
+ pauseForStorageMigration: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "pauseForStorageMigration", "mutation", input),
95058
+ resumeForStorageMigration: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "resumeForStorageMigration", "mutation", input),
95059
+ refreshStorageLocationsForMigration: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "refreshStorageLocationsForMigration", "mutation", input),
95060
+ startStorageMigrationMove: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "startStorageMigrationMove", "mutation", input),
95061
+ getStorageMigrationMoveStatus: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getStorageMigrationMoveStatus", "query", input),
95062
+ cancelStorageMigrationMove: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "cancelStorageMigrationMove", "mutation", input),
94293
95063
  listOpsLog: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "listOpsLog", "query", input),
94294
95064
  getTrainingExportSummary: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getTrainingExportSummary", "query", input),
94295
95065
  getTrainingExportUrl: (input) => dispatch("pipeline-analytics", "pipelineAnalytics", "getTrainingExportUrl", "query", input),
@@ -94507,7 +95277,10 @@ var require_sleep_EX1_qUVR = __commonJS({
94507
95277
  getCapSlice: (input) => dispatchSystem("deviceState", "getCapSlice", "query", input),
94508
95278
  setCapSlice: (input) => dispatchSystem("deviceState", "setCapSlice", "mutation", input)
94509
95279
  },
94510
- faceGallery: { getFaceByTrack: (input) => dispatchSystem("faceGallery", "getFaceByTrack", "query", input) },
95280
+ faceGallery: {
95281
+ listRecentFaces: (input) => dispatchSystem("faceGallery", "listRecentFaces", "query", input),
95282
+ getFaceByTrack: (input) => dispatchSystem("faceGallery", "getFaceByTrack", "query", input)
95283
+ },
94511
95284
  networkQuality: {
94512
95285
  getDeviceStats: (input) => dispatchSystem("networkQuality", "getDeviceStats", "query", input),
94513
95286
  reportClientStats: (input) => dispatchSystem("networkQuality", "reportClientStats", "mutation", input)
@@ -95222,7 +95995,7 @@ var require_addon = __commonJS({
95222
95995
  "use strict";
95223
95996
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
95224
95997
  var require_event_category = require_event_category_DxZbWydC();
95225
- var require_sleep = require_sleep_EX1_qUVR();
95998
+ var require_sleep = require_sleep_BszXLEvP();
95226
95999
  var require_err_msg = require_err_msg_COpsHMw2();
95227
96000
  var COLLECTION_ARRAY_METHODS = Object.freeze({
95228
96001
  "addon-pages-source": ["listPages"],
@@ -112628,7 +113401,7 @@ var require_dist3 = __commonJS({
112628
113401
  "use strict";
112629
113402
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
112630
113403
  var require_chunk = require_chunk_Cek0wNdY();
112631
- var require_dist10 = require_dist_DWZce90k();
113404
+ var require_dist10 = require_dist_cINpngi1();
112632
113405
  var require_builtins_alerts_alerts_addon = require_alerts_addon();
112633
113406
  require_alerts();
112634
113407
  var require_formatter = require_formatter_DqAKDlvN();
@@ -231516,7 +232289,7 @@ var require_dist9 = __commonJS({
231516
232289
  "use strict";
231517
232290
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
231518
232291
  var require_event_category = require_event_category_DxZbWydC();
231519
- var require_sleep = require_sleep_EX1_qUVR();
232292
+ var require_sleep = require_sleep_BszXLEvP();
231520
232293
  var require_canonical_hash = require_canonical_hash_DNV8S5ET();
231521
232294
  var require_enums2 = require_enums();
231522
232295
  var require_err_msg = require_err_msg_COpsHMw2();
@@ -232528,20 +233301,87 @@ var require_dist9 = __commonJS({
232528
233301
  finishedAt: zod.z.number().nullable(),
232529
233302
  error: zod.z.string().nullable()
232530
233303
  });
233304
+ var RelocateFootageClassSchema = zod.z.enum(["recordings", "recordingsLow"]);
232531
233305
  var RelocateFootageInputSchema = zod.z.object({
232532
- deviceId: zod.z.number().optional(),
232533
233306
  fromLocationId: zod.z.string(),
232534
233307
  toLocationId: zod.z.string(),
232535
233308
  entities: zod.z.array(zod.z.enum(["segments"])).optional(),
233309
+ /** Limits relocation to the logical profile class. Omit only for the
233310
+ * pre-orchestration compatibility path. */
233311
+ footageClass: RelocateFootageClassSchema.optional(),
232536
233312
  /** Copy throttle in MB/s (default 40) — the drain is a background chore,
232537
233313
  * never allowed to starve live writers. */
232538
233314
  throttleMbps: zod.z.number().min(1).max(1e3).optional()
232539
233315
  });
233316
+ var StorageMigrationLeaseInputSchema = zod.z.object({ leaseId: zod.z.string().min(1) });
233317
+ var StorageMigrationFootageMoveInputSchema = RelocateFootageInputSchema.extend({ leaseId: zod.z.string().min(1) });
232540
233318
  var RelocateMediaInputSchema = zod.z.object({
232541
- deviceId: zod.z.number().optional(),
232542
233319
  toLocationId: zod.z.string(),
232543
233320
  throttleMbps: zod.z.number().min(1).max(1e3).optional()
232544
233321
  });
233322
+ var StorageMigrationMediaMoveInputSchema = RelocateMediaInputSchema.extend({ leaseId: zod.z.string().min(1) });
233323
+ var StorageMigrationClassSchema = zod.z.enum([
233324
+ "recordings",
233325
+ "recordingsLow",
233326
+ "eventMedia"
233327
+ ]);
233328
+ var StorageMigrationDestinationsSchema = zod.z.object({
233329
+ recordings: zod.z.string().min(1).optional(),
233330
+ recordingsLow: zod.z.string().min(1).optional(),
233331
+ eventMedia: zod.z.string().min(1).optional()
233332
+ }).refine((value) => Object.keys(value).length > 0, { message: "select at least one storage class" });
233333
+ var StorageMigrationInputSchema = zod.z.object({
233334
+ destinations: StorageMigrationDestinationsSchema,
233335
+ throttleMbps: zod.z.number().min(1).max(1e3).optional()
233336
+ });
233337
+ var StorageMigrationPhaseSchema = zod.z.enum([
233338
+ "planning",
233339
+ "pausing",
233340
+ "moving",
233341
+ "verifying",
233342
+ "repointing",
233343
+ "refreshing",
233344
+ "resuming",
233345
+ "done",
233346
+ "failed",
233347
+ "cancelled"
233348
+ ]);
233349
+ var StorageMigrationParticipantSchema = zod.z.enum([
233350
+ "pipeline",
233351
+ "recorder",
233352
+ "analytics"
233353
+ ]);
233354
+ var StorageMigrationMoveSchema = zod.z.object({
233355
+ storageClass: StorageMigrationClassSchema,
233356
+ fromLocationId: zod.z.string(),
233357
+ toLocationId: zod.z.string(),
233358
+ moverJobId: zod.z.string().nullable(),
233359
+ state: RelocateJobStateSchema.nullable(),
233360
+ error: zod.z.string().nullable()
233361
+ });
233362
+ var StorageMigrationJobSchema = zod.z.object({
233363
+ jobId: zod.z.string(),
233364
+ phase: StorageMigrationPhaseSchema,
233365
+ destinations: StorageMigrationDestinationsSchema,
233366
+ throttleMbps: zod.z.number(),
233367
+ moves: zod.z.array(StorageMigrationMoveSchema),
233368
+ pauseLeaseId: zod.z.string().nullable(),
233369
+ pausedParticipants: zod.z.array(StorageMigrationParticipantSchema),
233370
+ repointed: zod.z.boolean(),
233371
+ cancelRequested: zod.z.boolean(),
233372
+ startedAt: zod.z.number(),
233373
+ updatedAt: zod.z.number(),
233374
+ finishedAt: zod.z.number().nullable(),
233375
+ error: zod.z.string().nullable()
233376
+ });
233377
+ var StorageMigrationPlanSchema = zod.z.object({
233378
+ destinations: StorageMigrationDestinationsSchema,
233379
+ moves: zod.z.array(zod.z.object({
233380
+ storageClass: StorageMigrationClassSchema,
233381
+ fromLocationId: zod.z.string(),
233382
+ toLocationId: zod.z.string()
233383
+ }))
233384
+ });
232545
233385
  var SUB_DETECTION_TYPES = ["face", "plate"];
232546
233386
  var RECOGNITION_TYPES = [
232547
233387
  "face",
@@ -242957,20 +243797,28 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
242957
243797
  }),
242958
243798
  /** The events ops-log rows (newest-first), optionally scoped to one camera.
242959
243799
  * Backed by a declared pipeline-analytics SQLite collection. */
242960
- /**
242961
- * Move event-media blobs onto `toLocationId` (entity-routing spec Phase
242962
- * 4): per-row copy → stamp row.locationId delete old blob. Rows already
242963
- * at the target are skipped, so a re-run resumes. Single-flight.
242964
- */
242965
- relocateMedia: require_sleep.method(RelocateMediaInputSchema, zod.z.object({ jobId: zod.z.string() }), {
243800
+ /** Internal migration-participant lease. It drains active MediaStore
243801
+ * writes and refuses new ones without changing analytics bindings. */
243802
+ pauseForStorageMigration: require_sleep.method(StorageMigrationLeaseInputSchema, zod.z.object({ paused: zod.z.literal(true) }), {
242966
243803
  kind: "mutation",
242967
243804
  auth: "admin"
242968
243805
  }),
242969
- getMediaRelocateStatus: require_sleep.method(zod.z.object({}), zod.z.array(RelocateJobSchema).readonly(), {
242970
- kind: "query",
243806
+ resumeForStorageMigration: require_sleep.method(StorageMigrationLeaseInputSchema, zod.z.object({ resumed: zod.z.literal(true) }), {
243807
+ kind: "mutation",
243808
+ auth: "admin"
243809
+ }),
243810
+ /** Drops cached location roots after the storage coordinator repoints a
243811
+ * default so future event-media writes use the new root. */
243812
+ refreshStorageLocationsForMigration: require_sleep.method(StorageMigrationLeaseInputSchema, zod.z.object({ refreshed: zod.z.literal(true) }), {
243813
+ kind: "mutation",
242971
243814
  auth: "admin"
242972
243815
  }),
242973
- cancelMediaRelocate: require_sleep.method(zod.z.object({ jobId: zod.z.string() }), zod.z.object({ cancelled: zod.z.boolean() }), {
243816
+ startStorageMigrationMove: require_sleep.method(StorageMigrationMediaMoveInputSchema, zod.z.object({ jobId: zod.z.string() }), {
243817
+ kind: "mutation",
243818
+ auth: "admin"
243819
+ }),
243820
+ getStorageMigrationMoveStatus: require_sleep.method(zod.z.object({ jobId: zod.z.string() }), RelocateJobSchema.nullable(), { auth: "admin" }),
243821
+ cancelStorageMigrationMove: require_sleep.method(zod.z.object({ jobId: zod.z.string() }), zod.z.object({ cancelled: zod.z.boolean() }), {
242974
243822
  kind: "mutation",
242975
243823
  auth: "admin"
242976
243824
  }),
@@ -244887,6 +245735,16 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
244887
245735
  nodeIdMode: "data",
244888
245736
  exposesDeviceSettings: true,
244889
245737
  methods: {
245738
+ /** Internal storage-migration participant lease. While held, dispatch
245739
+ * requests are accepted as pending but no new runner attachment starts. */
245740
+ pauseForStorageMigration: require_sleep.method(StorageMigrationLeaseInputSchema, zod.z.object({ paused: zod.z.literal(true) }), {
245741
+ kind: "mutation",
245742
+ auth: "admin"
245743
+ }),
245744
+ resumeForStorageMigration: require_sleep.method(StorageMigrationLeaseInputSchema, zod.z.object({ resumed: zod.z.literal(true) }), {
245745
+ kind: "mutation",
245746
+ auth: "admin"
245747
+ }),
244890
245748
  /**
244891
245749
  * Pin a camera's pipeline to a specific agent (L1 affinity).
244892
245750
  * The orchestrator re-evaluates the assignment immediately and persists
@@ -245899,6 +246757,23 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
245899
246757
  }), EvictResultSchema, { kind: "mutation" })
245900
246758
  }
245901
246759
  };
246760
+ var storageMigrationCapability = {
246761
+ name: "storage-migration",
246762
+ scope: "system",
246763
+ mode: "singleton",
246764
+ methods: {
246765
+ plan: require_sleep.method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin" }),
246766
+ start: require_sleep.method(StorageMigrationInputSchema, zod.z.object({ jobId: zod.z.string() }), {
246767
+ kind: "mutation",
246768
+ auth: "admin"
246769
+ }),
246770
+ status: require_sleep.method(zod.z.object({ jobId: zod.z.string().optional() }), StorageMigrationJobSchema.nullable(), { auth: "admin" }),
246771
+ cancel: require_sleep.method(zod.z.object({ jobId: zod.z.string() }), zod.z.object({ cancelled: zod.z.boolean() }), {
246772
+ kind: "mutation",
246773
+ auth: "admin"
246774
+ })
246775
+ }
246776
+ };
245902
246777
  var ProviderInfoSchema = zod.z.discriminatedUnion("shouldSaveDiskSpace", [zod.z.object({
245903
246778
  providerId: zod.z.string().min(1),
245904
246779
  displayName: zod.z.string().min(1),
@@ -246013,6 +246888,24 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
246013
246888
  label: zod.z.string(),
246014
246889
  description: zod.z.string().optional()
246015
246890
  });
246891
+ var TerminalInstanceInfoSchema = zod.z.object({
246892
+ instanceId: zod.z.string(),
246893
+ cameraStableId: zod.z.string(),
246894
+ nodeId: zod.z.string(),
246895
+ profileId: zod.z.string(),
246896
+ profileLabel: zod.z.string(),
246897
+ name: zod.z.string(),
246898
+ enabled: zod.z.boolean()
246899
+ });
246900
+ var TerminalLegacyCameraSchema = zod.z.object({
246901
+ stableId: zod.z.string(),
246902
+ nodeId: zod.z.string(),
246903
+ profileId: zod.z.string(),
246904
+ profileLabel: zod.z.string(),
246905
+ name: zod.z.string(),
246906
+ /** Only legacy monitor cameras can retain their historic stable identity. */
246907
+ adoptable: zod.z.boolean()
246908
+ });
246016
246909
  var TerminalOutputEventSchema = zod.z.discriminatedUnion("kind", [zod.z.object({
246017
246910
  seq: zod.z.number().int().positive(),
246018
246911
  kind: zod.z.literal("data"),
@@ -246036,6 +246929,37 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
246036
246929
  methods: {
246037
246930
  /** Pre-declared profiles the operator may open. */
246038
246931
  listProfiles: require_sleep.method(zod.z.void(), zod.z.array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
246932
+ /** Explicit durable Terminal instances, managed centrally on the hub. */
246933
+ listInstances: require_sleep.method(zod.z.void(), zod.z.array(TerminalInstanceInfoSchema).readonly(), { auth: "admin" }),
246934
+ createInstance: require_sleep.method(zod.z.object({
246935
+ targetNodeId: zod.z.string().min(1),
246936
+ profileId: zod.z.string().min(1),
246937
+ name: zod.z.string().trim().min(1).max(160).optional()
246938
+ }), TerminalInstanceInfoSchema, {
246939
+ kind: "mutation",
246940
+ auth: "admin"
246941
+ }),
246942
+ deleteInstance: require_sleep.method(zod.z.object({ instanceId: zod.z.string().min(1) }), zod.z.void(), {
246943
+ kind: "mutation",
246944
+ auth: "admin"
246945
+ }),
246946
+ setInstanceEnabled: require_sleep.method(zod.z.object({
246947
+ instanceId: zod.z.string().min(1),
246948
+ enabled: zod.z.boolean()
246949
+ }), TerminalInstanceInfoSchema, {
246950
+ kind: "mutation",
246951
+ auth: "admin"
246952
+ }),
246953
+ /** Existing automatic cameras are shown for explicit migration only. */
246954
+ listLegacyCameras: require_sleep.method(zod.z.void(), zod.z.array(TerminalLegacyCameraSchema).readonly(), { auth: "admin" }),
246955
+ /** Explicitly adopt one legacy monitor camera, retaining its stable id. */
246956
+ adoptLegacyMonitor: require_sleep.method(zod.z.object({
246957
+ stableId: zod.z.string().min(1),
246958
+ name: zod.z.string().trim().min(1).max(160).optional()
246959
+ }), TerminalInstanceInfoSchema, {
246960
+ kind: "mutation",
246961
+ auth: "admin"
246962
+ }),
246039
246963
  /** Live sessions currently hosted by the provider. */
246040
246964
  listSessions: require_sleep.method(zod.z.void(), zod.z.array(TerminalSessionInfoSchema).readonly(), { auth: "admin" }),
246041
246965
  /**
@@ -246067,7 +246991,13 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
246067
246991
  pullOutput: require_sleep.method(zod.z.object({
246068
246992
  sessionId: zod.z.string(),
246069
246993
  afterSeq: zod.z.number().int().nonnegative(),
246070
- waitMs: zod.z.number().int().min(0).max(2e3).default(0)
246994
+ waitMs: zod.z.number().int().min(0).max(2e3).default(0),
246995
+ /**
246996
+ * Wait when a just-opened session has no output yet. Kept opt-in so a
246997
+ * browser's initial repaint remains immediate; the camera snapshot
246998
+ * relay uses it to avoid encoding a blank startup frame.
246999
+ */
247000
+ waitForOutput: zod.z.boolean().optional()
246071
247001
  }), TerminalOutputBatchSchema, {
246072
247002
  kind: "mutation",
246073
247003
  auth: "admin",
@@ -248448,6 +249378,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
248448
249378
  var FaceFilterEnum = zod.z.enum([
248449
249379
  "unassigned",
248450
249380
  "recognized",
249381
+ "identified",
248451
249382
  "all"
248452
249383
  ]);
248453
249384
  var MediaFileLiteSchema$1 = zod.z.object({
@@ -248487,6 +249418,8 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
248487
249418
  auth: "admin"
248488
249419
  }),
248489
249420
  listRecentFaces: require_sleep.method(zod.z.object({
249421
+ /** Restrict to one camera. Absent keeps the cluster-wide gallery view. */
249422
+ deviceId: zod.z.number().int().optional(),
248490
249423
  limit: zod.z.number().int().positive().optional(),
248491
249424
  filter: FaceFilterEnum.optional(),
248492
249425
  /**
@@ -250563,6 +251496,10 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
250563
251496
  capName: zod.z.string().min(1).max(64),
250564
251497
  /** Dot path inside the slice, e.g. `detected`, `value`, `mode`. */
250565
251498
  valuePath: zod.z.string().min(1).max(64)
251499
+ }),
251500
+ zod.z.object({
251501
+ kind: zod.z.literal("latest-recognition"),
251502
+ recognition: zod.z.enum(["person", "plate"])
250566
251503
  })
250567
251504
  ]);
250568
251505
  var OsdSlotBindingSchema = zod.z.object({
@@ -250689,6 +251626,21 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
250689
251626
  auth: "admin"
250690
251627
  }),
250691
251628
  /**
251629
+ * Replace one camera's binding configuration from another. Writable source
251630
+ * slots are mapped by ordinal onto writable target slots so different
251631
+ * provider slot ids do not make the copied configuration disappear.
251632
+ */
251633
+ copyDeviceConfiguration: require_sleep.method(zod.z.object({
251634
+ sourceDeviceId: zod.z.number().int(),
251635
+ targetDeviceId: zod.z.number().int()
251636
+ }), zod.z.object({
251637
+ copied: zod.z.number().int().nonnegative(),
251638
+ skipped: zod.z.number().int().nonnegative()
251639
+ }), {
251640
+ kind: "mutation",
251641
+ auth: "admin"
251642
+ }),
251643
+ /**
250692
251644
  * Render without writing. `binding` overrides the stored one so an
250693
251645
  * editor can preview an unsaved change. Mutation kind only to carry
250694
251646
  * the binding object safely; no side effects.
@@ -251779,12 +252731,6 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
251779
252731
  auth: "admin"
251780
252732
  }),
251781
252733
  /**
251782
- * Move footage (recorded segments) from one recordings location to
251783
- * another — the drain workflow's mover (entity-routing spec Phase 4).
251784
- * Throttled copy → size-verify → delete source → index refresh; resumable
251785
- * by construction (copy-if-absent). Single-flight: one job at a time.
251786
- */
251787
- /**
251788
252734
  * Render a short GIF from recorded footage around `aroundMs` (low profile,
251789
252735
  * palette-free ffmpeg gif). Synchronous — the window is a few seconds of
251790
252736
  * `low`, rendering in ~1-2s. Built for notification attachments: the
@@ -251836,16 +252782,28 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
251836
252782
  kind: "mutation",
251837
252783
  auth: "admin"
251838
252784
  }),
251839
- relocateFootage: require_sleep.method(RelocateFootageInputSchema, zod.z.object({ jobId: zod.z.string() }), {
252785
+ /** Internal migration-participant lease. Blocks new recorder attaches and
252786
+ * waits for writers to exit while their watchers index final segments. */
252787
+ pauseForStorageMigration: require_sleep.method(StorageMigrationLeaseInputSchema, zod.z.object({ paused: zod.z.literal(true) }), {
251840
252788
  kind: "mutation",
251841
252789
  auth: "admin"
251842
252790
  }),
251843
- /** Every known relocate job (in-RAM, newest-first). */
251844
- getRelocateStatus: require_sleep.method(zod.z.object({}), zod.z.array(RelocateJobSchema).readonly(), {
251845
- kind: "query",
252791
+ resumeForStorageMigration: require_sleep.method(StorageMigrationLeaseInputSchema, zod.z.object({ resumed: zod.z.literal(true) }), {
252792
+ kind: "mutation",
251846
252793
  auth: "admin"
251847
252794
  }),
251848
- cancelRelocate: require_sleep.method(zod.z.object({ jobId: zod.z.string() }), zod.z.object({ cancelled: zod.z.boolean() }), {
252795
+ /** Re-resolve location roots after the coordinator changes defaults. */
252796
+ refreshStorageLocationsForMigration: require_sleep.method(StorageMigrationLeaseInputSchema, zod.z.object({ refreshed: zod.z.literal(true) }), {
252797
+ kind: "mutation",
252798
+ auth: "admin"
252799
+ }),
252800
+ /** Internal mover, callable only by the storage-migration coordinator. */
252801
+ startStorageMigrationMove: require_sleep.method(StorageMigrationFootageMoveInputSchema, zod.z.object({ jobId: zod.z.string() }), {
252802
+ kind: "mutation",
252803
+ auth: "admin"
252804
+ }),
252805
+ getStorageMigrationMoveStatus: require_sleep.method(zod.z.object({ jobId: zod.z.string() }), RelocateJobSchema.nullable(), { auth: "admin" }),
252806
+ cancelStorageMigrationMove: require_sleep.method(zod.z.object({ jobId: zod.z.string() }), zod.z.object({ cancelled: zod.z.boolean() }), {
251849
252807
  kind: "mutation",
251850
252808
  auth: "admin"
251851
252809
  })
@@ -256016,6 +256974,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
256016
256974
  ssoBridge: "sso-bridge",
256017
256975
  storage: "storage",
256018
256976
  storageEvictable: "storage-evictable",
256977
+ storageMigration: "storage-migration",
256019
256978
  storageProvider: "storage-provider",
256020
256979
  streamBroker: "stream-broker",
256021
256980
  streamCatalog: "stream-catalog",
@@ -256532,6 +257491,10 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
256532
257491
  key: "storageEvictable",
256533
257492
  name: "storage-evictable"
256534
257493
  },
257494
+ {
257495
+ key: "storageMigration",
257496
+ name: "storage-migration"
257497
+ },
256535
257498
  {
256536
257499
  key: "storageProvider",
256537
257500
  name: "storage-provider"
@@ -256760,6 +257723,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
256760
257723
  ssoBridgeCapability,
256761
257724
  storageCapability,
256762
257725
  storageEvictableCapability,
257726
+ storageMigrationCapability,
256763
257727
  storageProviderCapability,
256764
257728
  streamBrokerCapability,
256765
257729
  streamCatalogCapability,
@@ -259686,6 +260650,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
259686
260650
  addonId: null,
259687
260651
  access: "delete"
259688
260652
  },
260653
+ "osdManager.copyDeviceConfiguration": {
260654
+ capName: "osd-manager",
260655
+ capScope: "system",
260656
+ addonId: null,
260657
+ access: "create"
260658
+ },
259689
260659
  "osdManager.getConditionSupport": {
259690
260660
  capName: "osd-manager",
259691
260661
  capScope: "system",
@@ -259782,7 +260752,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
259782
260752
  addonId: null,
259783
260753
  access: "create"
259784
260754
  },
259785
- "pipelineAnalytics.cancelMediaRelocate": {
260755
+ "pipelineAnalytics.cancelStorageMigrationMove": {
259786
260756
  capName: "pipeline-analytics",
259787
260757
  capScope: "device",
259788
260758
  addonId: null,
@@ -259854,12 +260824,6 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
259854
260824
  addonId: null,
259855
260825
  access: "view"
259856
260826
  },
259857
- "pipelineAnalytics.getMediaRelocateStatus": {
259858
- capName: "pipeline-analytics",
259859
- capScope: "device",
259860
- addonId: null,
259861
- access: "view"
259862
- },
259863
260827
  "pipelineAnalytics.getMotionEvents": {
259864
260828
  capName: "pipeline-analytics",
259865
260829
  capScope: "device",
@@ -259896,6 +260860,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
259896
260860
  addonId: null,
259897
260861
  access: "view"
259898
260862
  },
260863
+ "pipelineAnalytics.getStorageMigrationMoveStatus": {
260864
+ capName: "pipeline-analytics",
260865
+ capScope: "device",
260866
+ addonId: null,
260867
+ access: "view"
260868
+ },
259899
260869
  "pipelineAnalytics.getTrack": {
259900
260870
  capName: "pipeline-analytics",
259901
260871
  capScope: "device",
@@ -259974,6 +260944,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
259974
260944
  addonId: null,
259975
260945
  access: "view"
259976
260946
  },
260947
+ "pipelineAnalytics.pauseForStorageMigration": {
260948
+ capName: "pipeline-analytics",
260949
+ capScope: "device",
260950
+ addonId: null,
260951
+ access: "create"
260952
+ },
259977
260953
  "pipelineAnalytics.proposeRetrainAnnotations": {
259978
260954
  capName: "pipeline-analytics",
259979
260955
  capScope: "device",
@@ -260004,7 +260980,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
260004
260980
  addonId: null,
260005
260981
  access: "create"
260006
260982
  },
260007
- "pipelineAnalytics.relocateMedia": {
260983
+ "pipelineAnalytics.refreshStorageLocationsForMigration": {
260008
260984
  capName: "pipeline-analytics",
260009
260985
  capScope: "device",
260010
260986
  addonId: null,
@@ -260016,6 +260992,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
260016
260992
  addonId: null,
260017
260993
  access: "create"
260018
260994
  },
260995
+ "pipelineAnalytics.resumeForStorageMigration": {
260996
+ capName: "pipeline-analytics",
260997
+ capScope: "device",
260998
+ addonId: null,
260999
+ access: "create"
261000
+ },
260019
261001
  "pipelineAnalytics.saveRetrainAnnotations": {
260020
261002
  capName: "pipeline-analytics",
260021
261003
  capScope: "device",
@@ -260040,6 +261022,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
260040
261022
  addonId: null,
260041
261023
  access: "create"
260042
261024
  },
261025
+ "pipelineAnalytics.startStorageMigrationMove": {
261026
+ capName: "pipeline-analytics",
261027
+ capScope: "device",
261028
+ addonId: null,
261029
+ access: "create"
261030
+ },
260043
261031
  "pipelineAnalytics.wipeAllAnalytics": {
260044
261032
  capName: "pipeline-analytics",
260045
261033
  capScope: "device",
@@ -260406,6 +261394,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
260406
261394
  addonId: null,
260407
261395
  access: "view"
260408
261396
  },
261397
+ "pipelineOrchestrator.pauseForStorageMigration": {
261398
+ capName: "pipeline-orchestrator",
261399
+ capScope: "system",
261400
+ addonId: null,
261401
+ access: "create"
261402
+ },
260409
261403
  "pipelineOrchestrator.rebalance": {
260410
261404
  capName: "pipeline-orchestrator",
260411
261405
  capScope: "system",
@@ -260430,6 +261424,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
260430
261424
  addonId: null,
260431
261425
  access: "view"
260432
261426
  },
261427
+ "pipelineOrchestrator.resumeForStorageMigration": {
261428
+ capName: "pipeline-orchestrator",
261429
+ capScope: "system",
261430
+ addonId: null,
261431
+ access: "create"
261432
+ },
260433
261433
  "pipelineOrchestrator.saveTemplate": {
260434
261434
  capName: "pipeline-orchestrator",
260435
261435
  capScope: "system",
@@ -260826,7 +261826,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
260826
261826
  addonId: null,
260827
261827
  access: "create"
260828
261828
  },
260829
- "recording.cancelRelocate": {
261829
+ "recording.cancelStorageMigrationMove": {
260830
261830
  capName: "recording",
260831
261831
  capScope: "system",
260832
261832
  addonId: null,
@@ -260862,7 +261862,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
260862
261862
  addonId: null,
260863
261863
  access: "view"
260864
261864
  },
260865
- "recording.getRelocateStatus": {
261865
+ "recording.getStorageMigrationMoveStatus": {
260866
261866
  capName: "recording",
260867
261867
  capScope: "system",
260868
261868
  addonId: null,
@@ -260886,6 +261886,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
260886
261886
  addonId: null,
260887
261887
  access: "view"
260888
261888
  },
261889
+ "recording.pauseForStorageMigration": {
261890
+ capName: "recording",
261891
+ capScope: "system",
261892
+ addonId: null,
261893
+ access: "create"
261894
+ },
260889
261895
  "recording.pruneFootage": {
260890
261896
  capName: "recording",
260891
261897
  capScope: "system",
@@ -260904,7 +261910,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
260904
261910
  addonId: null,
260905
261911
  access: "view"
260906
261912
  },
260907
- "recording.relocateFootage": {
261913
+ "recording.refreshStorageLocationsForMigration": {
260908
261914
  capName: "recording",
260909
261915
  capScope: "system",
260910
261916
  addonId: null,
@@ -260928,12 +261934,24 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
260928
261934
  addonId: null,
260929
261935
  access: "create"
260930
261936
  },
261937
+ "recording.resumeForStorageMigration": {
261938
+ capName: "recording",
261939
+ capScope: "system",
261940
+ addonId: null,
261941
+ access: "create"
261942
+ },
260931
261943
  "recording.setDeviceConfig": {
260932
261944
  capName: "recording",
260933
261945
  capScope: "system",
260934
261946
  addonId: null,
260935
261947
  access: "create"
260936
261948
  },
261949
+ "recording.startStorageMigrationMove": {
261950
+ capName: "recording",
261951
+ capScope: "system",
261952
+ addonId: null,
261953
+ access: "create"
261954
+ },
260937
261955
  "recordingExport.cancelExport": {
260938
261956
  capName: "recordingExport",
260939
261957
  capScope: "system",
@@ -261324,6 +262342,30 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
261324
262342
  addonId: null,
261325
262343
  access: "view"
261326
262344
  },
262345
+ "storageMigration.cancel": {
262346
+ capName: "storage-migration",
262347
+ capScope: "system",
262348
+ addonId: null,
262349
+ access: "create"
262350
+ },
262351
+ "storageMigration.plan": {
262352
+ capName: "storage-migration",
262353
+ capScope: "system",
262354
+ addonId: null,
262355
+ access: "view"
262356
+ },
262357
+ "storageMigration.start": {
262358
+ capName: "storage-migration",
262359
+ capScope: "system",
262360
+ addonId: null,
262361
+ access: "create"
262362
+ },
262363
+ "storageMigration.status": {
262364
+ capName: "storage-migration",
262365
+ capScope: "system",
262366
+ addonId: null,
262367
+ access: "view"
262368
+ },
261327
262369
  "storageProvider.abortUpload": {
261328
262370
  capName: "storage-provider",
261329
262371
  capScope: "system",
@@ -261702,12 +262744,42 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
261702
262744
  addonId: null,
261703
262745
  access: "create"
261704
262746
  },
262747
+ "terminalSession.adoptLegacyMonitor": {
262748
+ capName: "terminal-session",
262749
+ capScope: "system",
262750
+ addonId: null,
262751
+ access: "create"
262752
+ },
261705
262753
  "terminalSession.close": {
261706
262754
  capName: "terminal-session",
261707
262755
  capScope: "system",
261708
262756
  addonId: null,
261709
262757
  access: "create"
261710
262758
  },
262759
+ "terminalSession.createInstance": {
262760
+ capName: "terminal-session",
262761
+ capScope: "system",
262762
+ addonId: null,
262763
+ access: "create"
262764
+ },
262765
+ "terminalSession.deleteInstance": {
262766
+ capName: "terminal-session",
262767
+ capScope: "system",
262768
+ addonId: null,
262769
+ access: "delete"
262770
+ },
262771
+ "terminalSession.listInstances": {
262772
+ capName: "terminal-session",
262773
+ capScope: "system",
262774
+ addonId: null,
262775
+ access: "view"
262776
+ },
262777
+ "terminalSession.listLegacyCameras": {
262778
+ capName: "terminal-session",
262779
+ capScope: "system",
262780
+ addonId: null,
262781
+ access: "view"
262782
+ },
261711
262783
  "terminalSession.listProfiles": {
261712
262784
  capName: "terminal-session",
261713
262785
  capScope: "system",
@@ -261738,6 +262810,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
261738
262810
  addonId: null,
261739
262811
  access: "create"
261740
262812
  },
262813
+ "terminalSession.setInstanceEnabled": {
262814
+ capName: "terminal-session",
262815
+ capScope: "system",
262816
+ addonId: null,
262817
+ access: "create"
262818
+ },
261741
262819
  "terminalSession.writeInput": {
261742
262820
  capName: "terminal-session",
261743
262821
  capScope: "system",
@@ -262338,6 +263416,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
262338
263416
  "sso-bridge",
262339
263417
  "storage",
262340
263418
  "storage-evictable",
263419
+ "storage-migration",
262341
263420
  "storage-provider",
262342
263421
  "stream-broker",
262343
263422
  "stream-catalog",
@@ -262476,6 +263555,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
262476
263555
  "sso-bridge",
262477
263556
  "storage",
262478
263557
  "storage-evictable",
263558
+ "storage-migration",
262479
263559
  "storage-provider",
262480
263560
  "stream-broker",
262481
263561
  "system",
@@ -262785,7 +263865,6 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
262785
263865
  deleteIdentity: (input) => dispatch("faceGallery", "deleteIdentity", "mutation", input),
262786
263866
  listIdentitySamples: (input) => dispatch("faceGallery", "listIdentitySamples", "query", input),
262787
263867
  removeSample: (input) => dispatch("faceGallery", "removeSample", "mutation", input),
262788
- listRecentFaces: (input) => dispatch("faceGallery", "listRecentFaces", "query", input),
262789
263868
  getFaceMedia: (input) => dispatch("faceGallery", "getFaceMedia", "query", input),
262790
263869
  assignFace: (input) => dispatch("faceGallery", "assignFace", "mutation", input),
262791
263870
  unassignFace: (input) => dispatch("faceGallery", "unassignFace", "mutation", input),
@@ -262903,7 +263982,10 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
262903
263982
  deleteTarget: (input) => dispatch("notificationOutput", "deleteTarget", "mutation", input),
262904
263983
  setTargetEnabled: (input) => dispatch("notificationOutput", "setTargetEnabled", "mutation", input)
262905
263984
  },
262906
- osdManager: { getConditionSupport: (input) => dispatch("osdManager", "getConditionSupport", "query", input) },
263985
+ osdManager: {
263986
+ getConditionSupport: (input) => dispatch("osdManager", "getConditionSupport", "query", input),
263987
+ copyDeviceConfiguration: (input) => dispatch("osdManager", "copyDeviceConfiguration", "mutation", input)
263988
+ },
262907
263989
  pipelineExecutor: {
262908
263990
  getAvailableEngines: (input) => dispatch("pipelineExecutor", "getAvailableEngines", "query", input),
262909
263991
  getSelectedEngine: (input) => dispatch("pipelineExecutor", "getSelectedEngine", "query", input),
@@ -262941,6 +264023,8 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
262941
264023
  getDetectionConfigSchema: (input) => dispatch("pipelineExecutor", "getDetectionConfigSchema", "query", input)
262942
264024
  },
262943
264025
  pipelineOrchestrator: {
264026
+ pauseForStorageMigration: (input) => dispatch("pipelineOrchestrator", "pauseForStorageMigration", "mutation", input),
264027
+ resumeForStorageMigration: (input) => dispatch("pipelineOrchestrator", "resumeForStorageMigration", "mutation", input),
262944
264028
  rebalance: (input) => dispatch("pipelineOrchestrator", "rebalance", "mutation", input),
262945
264029
  getPipelineAssignments: (input) => dispatch("pipelineOrchestrator", "getPipelineAssignments", "query", input),
262946
264030
  getAgentLoad: (input) => dispatch("pipelineOrchestrator", "getAgentLoad", "query", input),
@@ -262995,9 +264079,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
262995
264079
  recording: {
262996
264080
  getStorageUsage: (input) => dispatch("recording", "getStorageUsage", "query", input),
262997
264081
  listOpsLog: (input) => dispatch("recording", "listOpsLog", "query", input),
262998
- relocateFootage: (input) => dispatch("recording", "relocateFootage", "mutation", input),
262999
- getRelocateStatus: (input) => dispatch("recording", "getRelocateStatus", "query", input),
263000
- cancelRelocate: (input) => dispatch("recording", "cancelRelocate", "mutation", input)
264082
+ pauseForStorageMigration: (input) => dispatch("recording", "pauseForStorageMigration", "mutation", input),
264083
+ resumeForStorageMigration: (input) => dispatch("recording", "resumeForStorageMigration", "mutation", input),
264084
+ refreshStorageLocationsForMigration: (input) => dispatch("recording", "refreshStorageLocationsForMigration", "mutation", input),
264085
+ startStorageMigrationMove: (input) => dispatch("recording", "startStorageMigrationMove", "mutation", input),
264086
+ getStorageMigrationMoveStatus: (input) => dispatch("recording", "getStorageMigrationMoveStatus", "query", input),
264087
+ cancelStorageMigrationMove: (input) => dispatch("recording", "cancelStorageMigrationMove", "mutation", input)
263001
264088
  },
263002
264089
  recordingExport: {
263003
264090
  getExport: (input) => dispatch("recordingExport", "getExport", "query", input),
@@ -263050,6 +264137,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
263050
264137
  listProviders: (input) => dispatch("storage", "listProviders", "query", input),
263051
264138
  testConfig: (input) => dispatch("storage", "testConfig", "query", input)
263052
264139
  },
264140
+ storageMigration: {
264141
+ plan: (input) => dispatch("storageMigration", "plan", "query", input),
264142
+ start: (input) => dispatch("storageMigration", "start", "mutation", input),
264143
+ status: (input) => dispatch("storageMigration", "status", "query", input),
264144
+ cancel: (input) => dispatch("storageMigration", "cancel", "mutation", input)
264145
+ },
263053
264146
  streamBroker: {
263054
264147
  fetchEventMedia: (input) => dispatch("streamBroker", "fetchEventMedia", "mutation", input),
263055
264148
  listAllCameraStreams: (input) => dispatch("streamBroker", "listAllCameraStreams", "query", input),
@@ -263089,6 +264182,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
263089
264182
  },
263090
264183
  terminalSession: {
263091
264184
  listProfiles: (input) => dispatch("terminalSession", "listProfiles", "query", input),
264185
+ listInstances: (input) => dispatch("terminalSession", "listInstances", "query", input),
264186
+ createInstance: (input) => dispatch("terminalSession", "createInstance", "mutation", input),
264187
+ deleteInstance: (input) => dispatch("terminalSession", "deleteInstance", "mutation", input),
264188
+ setInstanceEnabled: (input) => dispatch("terminalSession", "setInstanceEnabled", "mutation", input),
264189
+ listLegacyCameras: (input) => dispatch("terminalSession", "listLegacyCameras", "query", input),
264190
+ adoptLegacyMonitor: (input) => dispatch("terminalSession", "adoptLegacyMonitor", "mutation", input),
263092
264191
  listSessions: (input) => dispatch("terminalSession", "listSessions", "query", input),
263093
264192
  openSession: (input) => dispatch("terminalSession", "openSession", "mutation", input),
263094
264193
  resize: (input) => dispatch("terminalSession", "resize", "mutation", input),
@@ -265292,6 +266391,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
265292
266391
  exports.RecordingTriggersSchema = RecordingTriggersSchema;
265293
266392
  exports.RecordingWeekdaySchema = RecordingWeekdaySchema;
265294
266393
  exports.RedirectLoginMethodSchema = RedirectLoginMethodSchema;
266394
+ exports.RelocateFootageClassSchema = RelocateFootageClassSchema;
265295
266395
  exports.RelocateFootageInputSchema = RelocateFootageInputSchema;
265296
266396
  exports.RelocateJobSchema = RelocateJobSchema;
265297
266397
  exports.RelocateJobStateSchema = RelocateJobStateSchema;
@@ -265379,6 +266479,17 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
265379
266479
  exports.StorageLocationRefSchema = StorageLocationRefSchema;
265380
266480
  exports.StorageLocationSchema = StorageLocationSchema;
265381
266481
  exports.StorageLocationTypeSchema = StorageLocationTypeSchema;
266482
+ exports.StorageMigrationClassSchema = StorageMigrationClassSchema;
266483
+ exports.StorageMigrationDestinationsSchema = StorageMigrationDestinationsSchema;
266484
+ exports.StorageMigrationFootageMoveInputSchema = StorageMigrationFootageMoveInputSchema;
266485
+ exports.StorageMigrationInputSchema = StorageMigrationInputSchema;
266486
+ exports.StorageMigrationJobSchema = StorageMigrationJobSchema;
266487
+ exports.StorageMigrationLeaseInputSchema = StorageMigrationLeaseInputSchema;
266488
+ exports.StorageMigrationMediaMoveInputSchema = StorageMigrationMediaMoveInputSchema;
266489
+ exports.StorageMigrationMoveSchema = StorageMigrationMoveSchema;
266490
+ exports.StorageMigrationParticipantSchema = StorageMigrationParticipantSchema;
266491
+ exports.StorageMigrationPhaseSchema = StorageMigrationPhaseSchema;
266492
+ exports.StorageMigrationPlanSchema = StorageMigrationPlanSchema;
265382
266493
  exports.StorageProviderInfoSchema = ProviderInfoSchema;
265383
266494
  exports.StorageReadChunkInputSchema = ReadChunkInputSchema;
265384
266495
  exports.StorageTestLocationResultSchema = TestLocationResultSchema;
@@ -265412,6 +266523,8 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
265412
266523
  exports.TargetKindSchema = TargetKindSchema;
265413
266524
  exports.TargetSchema = TargetSchema;
265414
266525
  exports.TemperatureSensorStatusSchema = TemperatureSensorStatusSchema;
266526
+ exports.TerminalInstanceInfoSchema = TerminalInstanceInfoSchema;
266527
+ exports.TerminalLegacyCameraSchema = TerminalLegacyCameraSchema;
265415
266528
  exports.TerminalOutputBatchSchema = TerminalOutputBatchSchema;
265416
266529
  exports.TerminalOutputEventSchema = TerminalOutputEventSchema;
265417
266530
  exports.TerminalProfileInfoSchema = TerminalProfileInfoSchema;
@@ -265797,6 +266910,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
265797
266910
  exports.stateVocabularyFor = stateVocabularyFor;
265798
266911
  exports.storageCapability = storageCapability;
265799
266912
  exports.storageEvictableCapability = storageEvictableCapability;
266913
+ exports.storageMigrationCapability = storageMigrationCapability;
265800
266914
  exports.storageProviderCapability = storageProviderCapability;
265801
266915
  exports.streamBrokerCapability = streamBrokerCapability;
265802
266916
  exports.streamCatalogCapability = streamCatalogCapability;