@camstack/addon-export-google 0.1.13 → 0.1.14

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.
@@ -8289,6 +8289,13 @@ var MediaRelocateModeSchema = _enum([
8289
8289
  ]);
8290
8290
  var RelocateMediaInputSchema = object({
8291
8291
  toLocationId: string(),
8292
+ /**
8293
+ * Restrict the pass to rows currently on this location. Omitted / `'*'` =
8294
+ * every row that is not already on `toLocationId` (the historical
8295
+ * behaviour). A named source is what a from→to migration needs: without it
8296
+ * "move events off disk 2" also emptied disk 1.
8297
+ */
8298
+ fromLocationId: string().optional(),
8292
8299
  throttleMbps: number().min(1).max(1e3).optional(),
8293
8300
  /** Omitted = `move`, the pre-existing behaviour. */
8294
8301
  mode: MediaRelocateModeSchema.optional()
@@ -8356,6 +8363,19 @@ var StorageMigrationDestinationsSchema = object({
8356
8363
  galleryMedia: string().min(1).optional()
8357
8364
  }).refine((value) => Object.keys(value).length > 0, { message: "select at least one storage class" });
8358
8365
  /**
8366
+ * Optional named source per class. Omitted = the class's current default
8367
+ * (the historical behaviour). A named source that is NOT the default is a
8368
+ * drain of that disk: bytes move, the default stays, and the source is
8369
+ * disabled when the move finishes.
8370
+ */
8371
+ var StorageMigrationSourcesSchema = object({
8372
+ recordings: string().min(1).optional(),
8373
+ recordingsLow: string().min(1).optional(),
8374
+ eventMedia: string().min(1).optional(),
8375
+ backups: string().min(1).optional(),
8376
+ galleryMedia: string().min(1).optional()
8377
+ }).optional();
8378
+ /**
8359
8379
  * How a migration sequences the cutover against the byte move.
8360
8380
  *
8361
8381
  * - `blocking` — the historical order: pause, move every byte, repoint,
@@ -8377,6 +8397,8 @@ var StorageMigrationModeSchema = _enum(["blocking", "nonBlocking"]);
8377
8397
  /** Shared input for planning and starting an orchestrated storage migration. */
8378
8398
  var StorageMigrationInputSchema = object({
8379
8399
  destinations: StorageMigrationDestinationsSchema,
8400
+ /** Omitted = each class's current default. */
8401
+ sources: StorageMigrationSourcesSchema,
8380
8402
  throttleMbps: number().min(1).max(1e3).optional(),
8381
8403
  /** Omitted = `blocking`, which stays the default. */
8382
8404
  mode: StorageMigrationModeSchema.optional()
@@ -8456,6 +8478,13 @@ var StorageMigrationMoveSchema = object({
8456
8478
  storageClass: StorageMigrationClassSchema,
8457
8479
  fromLocationId: string(),
8458
8480
  toLocationId: string(),
8481
+ /**
8482
+ * True when `from` was NOT the class default at plan time. The move still
8483
+ * copies bytes, but the default is left alone and the source is disabled
8484
+ * once the copy verifies. Absent on jobs planned before this field existed
8485
+ * — those jobs always repointed, which is `false`.
8486
+ */
8487
+ freezeSource: boolean().optional(),
8459
8488
  moverJobId: string().nullable(),
8460
8489
  state: RelocateJobStateSchema.nullable(),
8461
8490
  error: string().nullable(),
@@ -8469,6 +8498,7 @@ var StorageMigrationJobSchema = object({
8469
8498
  * can tell a seconds-long cutover from a thirty-hour one. */
8470
8499
  mode: StorageMigrationModeSchema,
8471
8500
  destinations: StorageMigrationDestinationsSchema,
8501
+ sources: StorageMigrationSourcesSchema,
8472
8502
  throttleMbps: number(),
8473
8503
  moves: array(StorageMigrationMoveSchema),
8474
8504
  pauseLeaseId: string().nullable(),
@@ -8494,6 +8524,7 @@ var StorageMigrationFindingSchema = object({
8494
8524
  });
8495
8525
  var StorageMigrationPlanSchema = object({
8496
8526
  destinations: StorageMigrationDestinationsSchema,
8527
+ sources: StorageMigrationSourcesSchema,
8497
8528
  /** The mode this plan was built for. A plan is only valid for its mode: the
8498
8529
  * `eventMedia` seal gate and the single-cardinality refusal both depend on
8499
8530
  * it. */
@@ -8501,7 +8532,8 @@ var StorageMigrationPlanSchema = object({
8501
8532
  moves: array(object({
8502
8533
  storageClass: StorageMigrationClassSchema,
8503
8534
  fromLocationId: string(),
8504
- toLocationId: string()
8535
+ toLocationId: string(),
8536
+ freezeSource: boolean().optional()
8505
8537
  })),
8506
8538
  findings: array(StorageMigrationFindingSchema)
8507
8539
  });
@@ -8679,10 +8711,51 @@ var LedgerWalkReportSchema = object({
8679
8711
  var RelocatableMediaCountSchema = object({ rows: number().int().nonnegative() }).nullable();
8680
8712
  var RelocatableMediaCountInputSchema = object({
8681
8713
  toLocationId: string().min(1),
8714
+ /** Restrict the count to one source; omitted / `'*'` = every non-target row. */
8715
+ fromLocationId: string().optional(),
8682
8716
  /** Omitted = `move`. */
8683
8717
  mode: MediaRelocateModeSchema.optional()
8684
8718
  });
8685
8719
  /**
8720
+ * Operator cleanup of leftover analytics rows, optional debug media, and
8721
+ * ghost ledger entries on frozen footage locations.
8722
+ *
8723
+ * A pass is tens of minutes on a standing backlog. The hub method RETURNS
8724
+ * `{ jobId }` immediately; progress is `cleanupStatus`. Awaiting the work
8725
+ * is how `addons.custom` hit the 60 s UDS deadline while reclaim continued
8726
+ * with no operator-visible status.
8727
+ */
8728
+ var StorageCleanupPhaseSchema = _enum([
8729
+ "orphans",
8730
+ "debug-media",
8731
+ "ghost-ledger",
8732
+ "done",
8733
+ "failed",
8734
+ "cancelled"
8735
+ ]);
8736
+ var StorageCleanupInputSchema = object({
8737
+ /** Also walk motion stills / track filmstrips. Off by default. */
8738
+ includeDebugMedia: boolean().optional() });
8739
+ var StorageCleanupJobSchema = object({
8740
+ jobId: string(),
8741
+ phase: StorageCleanupPhaseSchema,
8742
+ includeDebugMedia: boolean(),
8743
+ orphansReclaimed: number().int().nonnegative(),
8744
+ orphanBytesReclaimed: number().int().nonnegative(),
8745
+ debugMediaReclaimed: number().int().nonnegative(),
8746
+ debugMediaBytesReclaimed: number().int().nonnegative(),
8747
+ ghostsForgotten: number().int().nonnegative(),
8748
+ ghostBytesForgotten: number().int().nonnegative(),
8749
+ /** Short operator-facing line: current collection, pass, or location. */
8750
+ detail: string().nullable(),
8751
+ cancelRequested: boolean(),
8752
+ startedAt: number(),
8753
+ updatedAt: number(),
8754
+ finishedAt: number().nullable(),
8755
+ error: string().nullable()
8756
+ });
8757
+ var StorageCleanupStatusInputSchema = object({ jobId: string().optional() });
8758
+ /**
8686
8759
  * `StorageLocationType` — an addon-declared id that identifies the *kind* of
8687
8760
  * storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
8688
8761
  * so the persisted record schema and the consumer-facing cap can both consume it
@@ -8710,11 +8783,10 @@ var StorageLocationTypeSchema = string().regex(/^[a-z][a-zA-Z0-9-]*$/);
8710
8783
  * The default location for a type uses `id === <type>:default` by
8711
8784
  * convention (the bare type ref like `'backups'` resolves to it).
8712
8785
  *
8713
- * `isSystem: true` marks a location as orchestrator-seeded and
8714
- * undeletable. The bootstrap-installed defaults (one per type) carry
8715
- * this flag; operator-added locations don't. Editing the config of
8716
- * a system location is allowed (path migration, provider swap) but
8717
- * deleting it is rejected at the cap level.
8786
+ * `isSystem` is a legacy persisted flag. Seed still creates the initial
8787
+ * `<type>:default` locations; the flag is no longer a lock, a badge, or a
8788
+ * prune selector. New writes leave it false. Deletion is gated on uniqueness
8789
+ * / last-enabled, not on this bit.
8718
8790
  */
8719
8791
  var StorageLocationSchema = object({
8720
8792
  id: string().regex(/^[a-z][a-zA-Z0-9-]*:[a-zA-Z0-9-]+$/),
@@ -13049,6 +13121,12 @@ method(object({
13049
13121
  }), _void(), {
13050
13122
  kind: "mutation",
13051
13123
  auth: "admin"
13124
+ }), method(object({
13125
+ from: string(),
13126
+ to: string()
13127
+ }), object({ moved: number() }), {
13128
+ kind: "mutation",
13129
+ auth: "admin"
13052
13130
  }), method(object({
13053
13131
  deviceId: number(),
13054
13132
  disabled: boolean()
@@ -18995,46 +19073,6 @@ var RecentTracksPageSchema = object({
18995
19073
  /** Cursor for the next page, or null when this page is the last. */
18996
19074
  nextCursor: string().nullable()
18997
19075
  });
18998
- var LIST_GROUPS_DEFAULT_LIMIT = 40;
18999
- var LIST_GROUPS_MAX_LIMIT = 100;
19000
- var AnalyticsGroupRecordSchema = object({
19001
- id: string(),
19002
- deviceId: number().int(),
19003
- openedAt: number().int(),
19004
- closedAt: number().int(),
19005
- timestamp: number().int(),
19006
- memberCount: number().int(),
19007
- memberTrackIds: array(string()).readonly(),
19008
- className: string(),
19009
- classes: array(string()).readonly(),
19010
- /** Relative event-media path, or null when the group has no picture yet. */
19011
- mediaUrl: string().nullable(),
19012
- singleton: boolean()
19013
- });
19014
- var AnalyticsGroupMemberSchema = object({
19015
- trackId: string(),
19016
- deviceId: number().int(),
19017
- className: string(),
19018
- firstSeen: number().int(),
19019
- lastSeen: number().int(),
19020
- mediaUrl: string().nullable()
19021
- });
19022
- var AnalyticsGroupDetailSchema = AnalyticsGroupRecordSchema.extend({ members: array(AnalyticsGroupMemberSchema).readonly() });
19023
- var ListGroupsQueryInput = object({
19024
- /** Devices to merge. An empty array yields `{ groups: [], nextCursor: null }`. */
19025
- deviceIds: array(number()),
19026
- /** Window lower bound on `closedAt` (inclusive). */
19027
- since: number().optional(),
19028
- /** Window upper bound on `openedAt` (inclusive). */
19029
- until: number().optional(),
19030
- limit: number().int().min(1).max(LIST_GROUPS_MAX_LIMIT).default(LIST_GROUPS_DEFAULT_LIMIT),
19031
- /** Opaque continuation cursor from a previous page's `nextCursor`. */
19032
- cursor: string().optional()
19033
- });
19034
- var ListGroupsPageSchema = object({
19035
- groups: array(AnalyticsGroupRecordSchema).readonly(),
19036
- nextCursor: string().nullable()
19037
- });
19038
19076
  var KEY_EVENTS_DEFAULT_LIMIT = 50;
19039
19077
  var KEY_EVENTS_MAX_LIMIT = 200;
19040
19078
  var KeyEventQueryInput = object({
@@ -19138,9 +19176,7 @@ var TrackCascadeCountsSchema = object({
19138
19176
  /** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
19139
19177
  plates: number().int(),
19140
19178
  /** Per-track CLIP search vectors removed (best-effort). */
19141
- embeddings: number().int(),
19142
- /** Group membership + group rows removed with their last member (best-effort). */
19143
- groups: number().int()
19179
+ embeddings: number().int()
19144
19180
  });
19145
19181
  /** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
19146
19182
  var DiskReconcileCountsSchema = object({
@@ -19310,6 +19346,47 @@ var RebuildStatusSchema = object({
19310
19346
  /** Present when the pass ended by throwing. */
19311
19347
  error: string().nullable()
19312
19348
  });
19349
+ /**
19350
+ * Acknowledgement that a debug-media reclaim STARTED.
19351
+ *
19352
+ * The pass is paced at ~2 MB/s over a standing 100 GB — tens of minutes — so
19353
+ * it runs detached and this returns immediately. Awaiting it is how the
19354
+ * `addons.custom` door hit the 60 s UDS deadline while the walk carried on
19355
+ * with no status. Poll {@link pipelineAnalyticsCapability.methods.getMediaReclaimStatus}.
19356
+ */
19357
+ var MediaReclaimStartResultSchema = object({
19358
+ started: boolean(),
19359
+ /** True when a pass was already running; the new request is ignored. */
19360
+ alreadyRunning: boolean()
19361
+ });
19362
+ var MediaReclaimInputSchema = object({
19363
+ mode: _enum(["report", "reclaim"]).default("report"),
19364
+ scopes: array(_enum(["motion-still", "track-filmstrip"])).min(1).optional(),
19365
+ deviceIds: array(number().int()).min(1).optional(),
19366
+ restart: boolean().optional(),
19367
+ pageSize: number().int().min(50).max(5e3).optional(),
19368
+ maxRowsPerDevice: number().int().min(1).max(5e5).optional(),
19369
+ maxReclaimPerDevice: number().int().min(1).max(5e5).optional(),
19370
+ maxBytesPerRun: number().int().min(1).optional(),
19371
+ budgetMinutes: number().int().min(1).max(720).optional(),
19372
+ throttleBytesPerSec: number().int().min(64 * 1024).optional(),
19373
+ graceMinutes: number().int().min(1).max(10080).optional()
19374
+ });
19375
+ var MediaReclaimStatusSchema = object({
19376
+ running: boolean(),
19377
+ mode: _enum(["report", "reclaim"]).nullable(),
19378
+ totalExamined: number(),
19379
+ totalEligible: number(),
19380
+ totalReclaimed: number(),
19381
+ totalBytesReclaimed: number(),
19382
+ totalRefused: number(),
19383
+ /** Device+scope windows finished in this pass. */
19384
+ devicesDone: number(),
19385
+ complete: boolean().nullable(),
19386
+ startedAtMs: number().nullable(),
19387
+ finishedAtMs: number().nullable(),
19388
+ error: string().nullable()
19389
+ });
19313
19390
  var ReplayFrameInputSchema = object({
19314
19391
  timestamp: number(),
19315
19392
  frame: PipelineRunResultBridge
@@ -19348,10 +19425,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19348
19425
  * stationary registry). Default false: the timeline lists passages,
19349
19426
  * not parking records (operator decision, 2026-08-15). */
19350
19427
  includeStationary: boolean().optional()
19351
- }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(ListGroupsQueryInput, ListGroupsPageSchema), method(object({
19352
- deviceId: number(),
19353
- groupId: string().min(1)
19354
- }), AnalyticsGroupDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
19428
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
19355
19429
  kind: "mutation",
19356
19430
  auth: "admin"
19357
19431
  }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(EventKindsForDeviceSchema).readonly()), method(object({
@@ -19451,6 +19525,12 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19451
19525
  }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
19452
19526
  kind: "query",
19453
19527
  auth: "admin"
19528
+ }), method(MediaReclaimInputSchema, MediaReclaimStartResultSchema, {
19529
+ kind: "mutation",
19530
+ auth: "admin"
19531
+ }), method(object({}), MediaReclaimStatusSchema, {
19532
+ kind: "query",
19533
+ auth: "admin"
19454
19534
  }), method(object({ deviceIds: array(number()).optional() }), TrainingExportSummarySchema, {
19455
19535
  kind: "query",
19456
19536
  auth: "admin"
@@ -21421,7 +21501,13 @@ method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin"
21421
21501
  }), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
21422
21502
  kind: "mutation",
21423
21503
  auth: "admin"
21424
- });
21504
+ }), method(StorageCleanupInputSchema, object({ jobId: string() }), {
21505
+ kind: "mutation",
21506
+ auth: "admin"
21507
+ }), method(StorageCleanupStatusInputSchema, StorageCleanupJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
21508
+ kind: "mutation",
21509
+ auth: "admin"
21510
+ }), method(object({}), array(StorageMigrationJobSchema).readonly(), { auth: "admin" });
21425
21511
  var ProviderInfoSchema = discriminatedUnion("shouldSaveDiskSpace", [object({
21426
21512
  providerId: string().min(1),
21427
21513
  displayName: string().min(1),
@@ -26811,6 +26897,33 @@ var RecordingRebalanceInputSchema = object({
26811
26897
  minMoveGb: number().min(0).optional()
26812
26898
  });
26813
26899
  /**
26900
+ * Operator-facing placement of one camera onto a recordings location.
26901
+ *
26902
+ * `pinLocationId` is the operator instruction: a location id, or `null` for
26903
+ * Auto (the planner may move this camera). `locationId` is where high/mid
26904
+ * currently write — the plan, which may disagree with the pin when Auto.
26905
+ */
26906
+ var RecordingDevicePlacementSchema = object({
26907
+ deviceId: number().int(),
26908
+ profile: string(),
26909
+ locationId: string()
26910
+ });
26911
+ var RecordingDevicePinSchema = object({
26912
+ deviceId: number().int(),
26913
+ /** Recordings-class location this camera is pinned to. */
26914
+ locationId: string()
26915
+ });
26916
+ var RecordingPlacementViewSchema = object({
26917
+ assignments: array(RecordingDevicePlacementSchema),
26918
+ pins: array(RecordingDevicePinSchema),
26919
+ defaultLocations: record(string(), string())
26920
+ });
26921
+ var RecordingSetDevicePlacementInputSchema = object({
26922
+ deviceId: number().int(),
26923
+ /** `null` = Auto. Otherwise a `recordings:*` location id. */
26924
+ locationId: string().nullable()
26925
+ });
26926
+ /**
26814
26927
  * Result of locating footage at a wall-clock instant for one device/profile.
26815
26928
  * `segment` carries the covering segment's window; `gap` reports the forward
26816
26929
  * nearest covered edge (`null` past the end of footage / when none exists)
@@ -27036,6 +27149,12 @@ method(object({
27036
27149
  }), method(RecordingRebalanceInputSchema, RecordingRebalancePlanSchema, {
27037
27150
  kind: "mutation",
27038
27151
  auth: "admin"
27152
+ }), method(object({}), RecordingPlacementViewSchema, {
27153
+ kind: "query",
27154
+ auth: "admin"
27155
+ }), method(RecordingSetDevicePlacementInputSchema, object({ ok: literal(true) }), {
27156
+ kind: "mutation",
27157
+ auth: "admin"
27039
27158
  });
27040
27159
  /**
27041
27160
  * `recording-export` cap — render a footage time range into a single downloadable
@@ -30413,6 +30532,12 @@ Object.freeze({
30413
30532
  addonId: null,
30414
30533
  access: "delete"
30415
30534
  },
30535
+ "deviceManager.renameLocation": {
30536
+ capName: "device-manager",
30537
+ capScope: "system",
30538
+ addonId: null,
30539
+ access: "create"
30540
+ },
30416
30541
  "deviceManager.runDeviceAction": {
30417
30542
  capName: "device-manager",
30418
30543
  capScope: "system",
@@ -32105,19 +32230,19 @@ Object.freeze({
32105
32230
  addonId: null,
32106
32231
  access: "view"
32107
32232
  },
32108
- "pipelineAnalytics.getGroup": {
32233
+ "pipelineAnalytics.getKeyEvents": {
32109
32234
  capName: "pipeline-analytics",
32110
32235
  capScope: "device",
32111
32236
  addonId: null,
32112
32237
  access: "view"
32113
32238
  },
32114
- "pipelineAnalytics.getKeyEvents": {
32239
+ "pipelineAnalytics.getKeyEventsBatch": {
32115
32240
  capName: "pipeline-analytics",
32116
32241
  capScope: "device",
32117
32242
  addonId: null,
32118
32243
  access: "view"
32119
32244
  },
32120
- "pipelineAnalytics.getKeyEventsBatch": {
32245
+ "pipelineAnalytics.getMediaReclaimStatus": {
32121
32246
  capName: "pipeline-analytics",
32122
32247
  capScope: "device",
32123
32248
  addonId: null,
@@ -32207,12 +32332,6 @@ Object.freeze({
32207
32332
  addonId: null,
32208
32333
  access: "view"
32209
32334
  },
32210
- "pipelineAnalytics.listGroups": {
32211
- capName: "pipeline-analytics",
32212
- capScope: "device",
32213
- addonId: null,
32214
- access: "view"
32215
- },
32216
32335
  "pipelineAnalytics.listOpsLog": {
32217
32336
  capName: "pipeline-analytics",
32218
32337
  capScope: "device",
@@ -32297,6 +32416,12 @@ Object.freeze({
32297
32416
  addonId: null,
32298
32417
  access: "create"
32299
32418
  },
32419
+ "pipelineAnalytics.reclaimDebugMedia": {
32420
+ capName: "pipeline-analytics",
32421
+ capScope: "device",
32422
+ addonId: null,
32423
+ access: "create"
32424
+ },
32300
32425
  "pipelineAnalytics.reconcileFromDisk": {
32301
32426
  capName: "pipeline-analytics",
32302
32427
  capScope: "device",
@@ -33221,6 +33346,12 @@ Object.freeze({
33221
33346
  addonId: null,
33222
33347
  access: "view"
33223
33348
  },
33349
+ "recording.getPlacement": {
33350
+ capName: "recording",
33351
+ capScope: "system",
33352
+ addonId: null,
33353
+ access: "view"
33354
+ },
33224
33355
  "recording.getPlaybackManifest": {
33225
33356
  capName: "recording",
33226
33357
  capScope: "system",
@@ -33347,6 +33478,12 @@ Object.freeze({
33347
33478
  addonId: null,
33348
33479
  access: "create"
33349
33480
  },
33481
+ "recording.setDevicePlacement": {
33482
+ capName: "recording",
33483
+ capScope: "system",
33484
+ addonId: null,
33485
+ access: "create"
33486
+ },
33350
33487
  "recording.startStorageMigrationMove": {
33351
33488
  capName: "recording",
33352
33489
  capScope: "system",
@@ -33791,12 +33928,36 @@ Object.freeze({
33791
33928
  addonId: null,
33792
33929
  access: "create"
33793
33930
  },
33931
+ "storageMigration.cleanupCancel": {
33932
+ capName: "storage-migration",
33933
+ capScope: "system",
33934
+ addonId: null,
33935
+ access: "create"
33936
+ },
33937
+ "storageMigration.cleanupStart": {
33938
+ capName: "storage-migration",
33939
+ capScope: "system",
33940
+ addonId: null,
33941
+ access: "create"
33942
+ },
33943
+ "storageMigration.cleanupStatus": {
33944
+ capName: "storage-migration",
33945
+ capScope: "system",
33946
+ addonId: null,
33947
+ access: "view"
33948
+ },
33794
33949
  "storageMigration.drain": {
33795
33950
  capName: "storage-migration",
33796
33951
  capScope: "system",
33797
33952
  addonId: null,
33798
33953
  access: "create"
33799
33954
  },
33955
+ "storageMigration.history": {
33956
+ capName: "storage-migration",
33957
+ capScope: "system",
33958
+ addonId: null,
33959
+ access: "view"
33960
+ },
33800
33961
  "storageMigration.movers": {
33801
33962
  capName: "storage-migration",
33802
33963
  capScope: "system",
@@ -35793,11 +35954,6 @@ Object.freeze({
35793
35954
  form: "single",
35794
35955
  optional: true
35795
35956
  }],
35796
- "pipelineAnalytics.getGroup": [{
35797
- name: "deviceId",
35798
- form: "single",
35799
- optional: false
35800
- }],
35801
35957
  "pipelineAnalytics.getKeyEvents": [{
35802
35958
  name: "deviceId",
35803
35959
  form: "single",
@@ -35863,11 +36019,6 @@ Object.freeze({
35863
36019
  form: "single",
35864
36020
  optional: false
35865
36021
  }],
35866
- "pipelineAnalytics.listGroups": [{
35867
- name: "deviceIds",
35868
- form: "array",
35869
- optional: false
35870
- }],
35871
36022
  "pipelineAnalytics.listOpsLog": [{
35872
36023
  name: "deviceId",
35873
36024
  form: "single",
@@ -35913,6 +36064,11 @@ Object.freeze({
35913
36064
  form: "single",
35914
36065
  optional: true
35915
36066
  }],
36067
+ "pipelineAnalytics.reclaimDebugMedia": [{
36068
+ name: "deviceIds",
36069
+ form: "array",
36070
+ optional: true
36071
+ }],
35916
36072
  "pipelineAnalytics.reconcileFromDisk": [{
35917
36073
  name: "deviceId",
35918
36074
  form: "single",
@@ -36278,6 +36434,11 @@ Object.freeze({
36278
36434
  form: "single",
36279
36435
  optional: false
36280
36436
  }],
36437
+ "recording.setDevicePlacement": [{
36438
+ name: "deviceId",
36439
+ form: "single",
36440
+ optional: false
36441
+ }],
36281
36442
  "recording.startStorageMigrationMove": [{
36282
36443
  name: "deviceId",
36283
36444
  form: "single",
@@ -8285,6 +8285,13 @@ var MediaRelocateModeSchema = _enum([
8285
8285
  ]);
8286
8286
  var RelocateMediaInputSchema = object({
8287
8287
  toLocationId: string(),
8288
+ /**
8289
+ * Restrict the pass to rows currently on this location. Omitted / `'*'` =
8290
+ * every row that is not already on `toLocationId` (the historical
8291
+ * behaviour). A named source is what a from→to migration needs: without it
8292
+ * "move events off disk 2" also emptied disk 1.
8293
+ */
8294
+ fromLocationId: string().optional(),
8288
8295
  throttleMbps: number().min(1).max(1e3).optional(),
8289
8296
  /** Omitted = `move`, the pre-existing behaviour. */
8290
8297
  mode: MediaRelocateModeSchema.optional()
@@ -8352,6 +8359,19 @@ var StorageMigrationDestinationsSchema = object({
8352
8359
  galleryMedia: string().min(1).optional()
8353
8360
  }).refine((value) => Object.keys(value).length > 0, { message: "select at least one storage class" });
8354
8361
  /**
8362
+ * Optional named source per class. Omitted = the class's current default
8363
+ * (the historical behaviour). A named source that is NOT the default is a
8364
+ * drain of that disk: bytes move, the default stays, and the source is
8365
+ * disabled when the move finishes.
8366
+ */
8367
+ var StorageMigrationSourcesSchema = object({
8368
+ recordings: string().min(1).optional(),
8369
+ recordingsLow: string().min(1).optional(),
8370
+ eventMedia: string().min(1).optional(),
8371
+ backups: string().min(1).optional(),
8372
+ galleryMedia: string().min(1).optional()
8373
+ }).optional();
8374
+ /**
8355
8375
  * How a migration sequences the cutover against the byte move.
8356
8376
  *
8357
8377
  * - `blocking` — the historical order: pause, move every byte, repoint,
@@ -8373,6 +8393,8 @@ var StorageMigrationModeSchema = _enum(["blocking", "nonBlocking"]);
8373
8393
  /** Shared input for planning and starting an orchestrated storage migration. */
8374
8394
  var StorageMigrationInputSchema = object({
8375
8395
  destinations: StorageMigrationDestinationsSchema,
8396
+ /** Omitted = each class's current default. */
8397
+ sources: StorageMigrationSourcesSchema,
8376
8398
  throttleMbps: number().min(1).max(1e3).optional(),
8377
8399
  /** Omitted = `blocking`, which stays the default. */
8378
8400
  mode: StorageMigrationModeSchema.optional()
@@ -8452,6 +8474,13 @@ var StorageMigrationMoveSchema = object({
8452
8474
  storageClass: StorageMigrationClassSchema,
8453
8475
  fromLocationId: string(),
8454
8476
  toLocationId: string(),
8477
+ /**
8478
+ * True when `from` was NOT the class default at plan time. The move still
8479
+ * copies bytes, but the default is left alone and the source is disabled
8480
+ * once the copy verifies. Absent on jobs planned before this field existed
8481
+ * — those jobs always repointed, which is `false`.
8482
+ */
8483
+ freezeSource: boolean().optional(),
8455
8484
  moverJobId: string().nullable(),
8456
8485
  state: RelocateJobStateSchema.nullable(),
8457
8486
  error: string().nullable(),
@@ -8465,6 +8494,7 @@ var StorageMigrationJobSchema = object({
8465
8494
  * can tell a seconds-long cutover from a thirty-hour one. */
8466
8495
  mode: StorageMigrationModeSchema,
8467
8496
  destinations: StorageMigrationDestinationsSchema,
8497
+ sources: StorageMigrationSourcesSchema,
8468
8498
  throttleMbps: number(),
8469
8499
  moves: array(StorageMigrationMoveSchema),
8470
8500
  pauseLeaseId: string().nullable(),
@@ -8490,6 +8520,7 @@ var StorageMigrationFindingSchema = object({
8490
8520
  });
8491
8521
  var StorageMigrationPlanSchema = object({
8492
8522
  destinations: StorageMigrationDestinationsSchema,
8523
+ sources: StorageMigrationSourcesSchema,
8493
8524
  /** The mode this plan was built for. A plan is only valid for its mode: the
8494
8525
  * `eventMedia` seal gate and the single-cardinality refusal both depend on
8495
8526
  * it. */
@@ -8497,7 +8528,8 @@ var StorageMigrationPlanSchema = object({
8497
8528
  moves: array(object({
8498
8529
  storageClass: StorageMigrationClassSchema,
8499
8530
  fromLocationId: string(),
8500
- toLocationId: string()
8531
+ toLocationId: string(),
8532
+ freezeSource: boolean().optional()
8501
8533
  })),
8502
8534
  findings: array(StorageMigrationFindingSchema)
8503
8535
  });
@@ -8675,10 +8707,51 @@ var LedgerWalkReportSchema = object({
8675
8707
  var RelocatableMediaCountSchema = object({ rows: number().int().nonnegative() }).nullable();
8676
8708
  var RelocatableMediaCountInputSchema = object({
8677
8709
  toLocationId: string().min(1),
8710
+ /** Restrict the count to one source; omitted / `'*'` = every non-target row. */
8711
+ fromLocationId: string().optional(),
8678
8712
  /** Omitted = `move`. */
8679
8713
  mode: MediaRelocateModeSchema.optional()
8680
8714
  });
8681
8715
  /**
8716
+ * Operator cleanup of leftover analytics rows, optional debug media, and
8717
+ * ghost ledger entries on frozen footage locations.
8718
+ *
8719
+ * A pass is tens of minutes on a standing backlog. The hub method RETURNS
8720
+ * `{ jobId }` immediately; progress is `cleanupStatus`. Awaiting the work
8721
+ * is how `addons.custom` hit the 60 s UDS deadline while reclaim continued
8722
+ * with no operator-visible status.
8723
+ */
8724
+ var StorageCleanupPhaseSchema = _enum([
8725
+ "orphans",
8726
+ "debug-media",
8727
+ "ghost-ledger",
8728
+ "done",
8729
+ "failed",
8730
+ "cancelled"
8731
+ ]);
8732
+ var StorageCleanupInputSchema = object({
8733
+ /** Also walk motion stills / track filmstrips. Off by default. */
8734
+ includeDebugMedia: boolean().optional() });
8735
+ var StorageCleanupJobSchema = object({
8736
+ jobId: string(),
8737
+ phase: StorageCleanupPhaseSchema,
8738
+ includeDebugMedia: boolean(),
8739
+ orphansReclaimed: number().int().nonnegative(),
8740
+ orphanBytesReclaimed: number().int().nonnegative(),
8741
+ debugMediaReclaimed: number().int().nonnegative(),
8742
+ debugMediaBytesReclaimed: number().int().nonnegative(),
8743
+ ghostsForgotten: number().int().nonnegative(),
8744
+ ghostBytesForgotten: number().int().nonnegative(),
8745
+ /** Short operator-facing line: current collection, pass, or location. */
8746
+ detail: string().nullable(),
8747
+ cancelRequested: boolean(),
8748
+ startedAt: number(),
8749
+ updatedAt: number(),
8750
+ finishedAt: number().nullable(),
8751
+ error: string().nullable()
8752
+ });
8753
+ var StorageCleanupStatusInputSchema = object({ jobId: string().optional() });
8754
+ /**
8682
8755
  * `StorageLocationType` — an addon-declared id that identifies the *kind* of
8683
8756
  * storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
8684
8757
  * so the persisted record schema and the consumer-facing cap can both consume it
@@ -8706,11 +8779,10 @@ var StorageLocationTypeSchema = string().regex(/^[a-z][a-zA-Z0-9-]*$/);
8706
8779
  * The default location for a type uses `id === <type>:default` by
8707
8780
  * convention (the bare type ref like `'backups'` resolves to it).
8708
8781
  *
8709
- * `isSystem: true` marks a location as orchestrator-seeded and
8710
- * undeletable. The bootstrap-installed defaults (one per type) carry
8711
- * this flag; operator-added locations don't. Editing the config of
8712
- * a system location is allowed (path migration, provider swap) but
8713
- * deleting it is rejected at the cap level.
8782
+ * `isSystem` is a legacy persisted flag. Seed still creates the initial
8783
+ * `<type>:default` locations; the flag is no longer a lock, a badge, or a
8784
+ * prune selector. New writes leave it false. Deletion is gated on uniqueness
8785
+ * / last-enabled, not on this bit.
8714
8786
  */
8715
8787
  var StorageLocationSchema = object({
8716
8788
  id: string().regex(/^[a-z][a-zA-Z0-9-]*:[a-zA-Z0-9-]+$/),
@@ -13045,6 +13117,12 @@ method(object({
13045
13117
  }), _void(), {
13046
13118
  kind: "mutation",
13047
13119
  auth: "admin"
13120
+ }), method(object({
13121
+ from: string(),
13122
+ to: string()
13123
+ }), object({ moved: number() }), {
13124
+ kind: "mutation",
13125
+ auth: "admin"
13048
13126
  }), method(object({
13049
13127
  deviceId: number(),
13050
13128
  disabled: boolean()
@@ -18991,46 +19069,6 @@ var RecentTracksPageSchema = object({
18991
19069
  /** Cursor for the next page, or null when this page is the last. */
18992
19070
  nextCursor: string().nullable()
18993
19071
  });
18994
- var LIST_GROUPS_DEFAULT_LIMIT = 40;
18995
- var LIST_GROUPS_MAX_LIMIT = 100;
18996
- var AnalyticsGroupRecordSchema = object({
18997
- id: string(),
18998
- deviceId: number().int(),
18999
- openedAt: number().int(),
19000
- closedAt: number().int(),
19001
- timestamp: number().int(),
19002
- memberCount: number().int(),
19003
- memberTrackIds: array(string()).readonly(),
19004
- className: string(),
19005
- classes: array(string()).readonly(),
19006
- /** Relative event-media path, or null when the group has no picture yet. */
19007
- mediaUrl: string().nullable(),
19008
- singleton: boolean()
19009
- });
19010
- var AnalyticsGroupMemberSchema = object({
19011
- trackId: string(),
19012
- deviceId: number().int(),
19013
- className: string(),
19014
- firstSeen: number().int(),
19015
- lastSeen: number().int(),
19016
- mediaUrl: string().nullable()
19017
- });
19018
- var AnalyticsGroupDetailSchema = AnalyticsGroupRecordSchema.extend({ members: array(AnalyticsGroupMemberSchema).readonly() });
19019
- var ListGroupsQueryInput = object({
19020
- /** Devices to merge. An empty array yields `{ groups: [], nextCursor: null }`. */
19021
- deviceIds: array(number()),
19022
- /** Window lower bound on `closedAt` (inclusive). */
19023
- since: number().optional(),
19024
- /** Window upper bound on `openedAt` (inclusive). */
19025
- until: number().optional(),
19026
- limit: number().int().min(1).max(LIST_GROUPS_MAX_LIMIT).default(LIST_GROUPS_DEFAULT_LIMIT),
19027
- /** Opaque continuation cursor from a previous page's `nextCursor`. */
19028
- cursor: string().optional()
19029
- });
19030
- var ListGroupsPageSchema = object({
19031
- groups: array(AnalyticsGroupRecordSchema).readonly(),
19032
- nextCursor: string().nullable()
19033
- });
19034
19072
  var KEY_EVENTS_DEFAULT_LIMIT = 50;
19035
19073
  var KEY_EVENTS_MAX_LIMIT = 200;
19036
19074
  var KeyEventQueryInput = object({
@@ -19134,9 +19172,7 @@ var TrackCascadeCountsSchema = object({
19134
19172
  /** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
19135
19173
  plates: number().int(),
19136
19174
  /** Per-track CLIP search vectors removed (best-effort). */
19137
- embeddings: number().int(),
19138
- /** Group membership + group rows removed with their last member (best-effort). */
19139
- groups: number().int()
19175
+ embeddings: number().int()
19140
19176
  });
19141
19177
  /** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
19142
19178
  var DiskReconcileCountsSchema = object({
@@ -19306,6 +19342,47 @@ var RebuildStatusSchema = object({
19306
19342
  /** Present when the pass ended by throwing. */
19307
19343
  error: string().nullable()
19308
19344
  });
19345
+ /**
19346
+ * Acknowledgement that a debug-media reclaim STARTED.
19347
+ *
19348
+ * The pass is paced at ~2 MB/s over a standing 100 GB — tens of minutes — so
19349
+ * it runs detached and this returns immediately. Awaiting it is how the
19350
+ * `addons.custom` door hit the 60 s UDS deadline while the walk carried on
19351
+ * with no status. Poll {@link pipelineAnalyticsCapability.methods.getMediaReclaimStatus}.
19352
+ */
19353
+ var MediaReclaimStartResultSchema = object({
19354
+ started: boolean(),
19355
+ /** True when a pass was already running; the new request is ignored. */
19356
+ alreadyRunning: boolean()
19357
+ });
19358
+ var MediaReclaimInputSchema = object({
19359
+ mode: _enum(["report", "reclaim"]).default("report"),
19360
+ scopes: array(_enum(["motion-still", "track-filmstrip"])).min(1).optional(),
19361
+ deviceIds: array(number().int()).min(1).optional(),
19362
+ restart: boolean().optional(),
19363
+ pageSize: number().int().min(50).max(5e3).optional(),
19364
+ maxRowsPerDevice: number().int().min(1).max(5e5).optional(),
19365
+ maxReclaimPerDevice: number().int().min(1).max(5e5).optional(),
19366
+ maxBytesPerRun: number().int().min(1).optional(),
19367
+ budgetMinutes: number().int().min(1).max(720).optional(),
19368
+ throttleBytesPerSec: number().int().min(64 * 1024).optional(),
19369
+ graceMinutes: number().int().min(1).max(10080).optional()
19370
+ });
19371
+ var MediaReclaimStatusSchema = object({
19372
+ running: boolean(),
19373
+ mode: _enum(["report", "reclaim"]).nullable(),
19374
+ totalExamined: number(),
19375
+ totalEligible: number(),
19376
+ totalReclaimed: number(),
19377
+ totalBytesReclaimed: number(),
19378
+ totalRefused: number(),
19379
+ /** Device+scope windows finished in this pass. */
19380
+ devicesDone: number(),
19381
+ complete: boolean().nullable(),
19382
+ startedAtMs: number().nullable(),
19383
+ finishedAtMs: number().nullable(),
19384
+ error: string().nullable()
19385
+ });
19309
19386
  var ReplayFrameInputSchema = object({
19310
19387
  timestamp: number(),
19311
19388
  frame: PipelineRunResultBridge
@@ -19344,10 +19421,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19344
19421
  * stationary registry). Default false: the timeline lists passages,
19345
19422
  * not parking records (operator decision, 2026-08-15). */
19346
19423
  includeStationary: boolean().optional()
19347
- }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(ListGroupsQueryInput, ListGroupsPageSchema), method(object({
19348
- deviceId: number(),
19349
- groupId: string().min(1)
19350
- }), AnalyticsGroupDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
19424
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
19351
19425
  kind: "mutation",
19352
19426
  auth: "admin"
19353
19427
  }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(EventKindsForDeviceSchema).readonly()), method(object({
@@ -19447,6 +19521,12 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19447
19521
  }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
19448
19522
  kind: "query",
19449
19523
  auth: "admin"
19524
+ }), method(MediaReclaimInputSchema, MediaReclaimStartResultSchema, {
19525
+ kind: "mutation",
19526
+ auth: "admin"
19527
+ }), method(object({}), MediaReclaimStatusSchema, {
19528
+ kind: "query",
19529
+ auth: "admin"
19450
19530
  }), method(object({ deviceIds: array(number()).optional() }), TrainingExportSummarySchema, {
19451
19531
  kind: "query",
19452
19532
  auth: "admin"
@@ -21417,7 +21497,13 @@ method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin"
21417
21497
  }), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
21418
21498
  kind: "mutation",
21419
21499
  auth: "admin"
21420
- });
21500
+ }), method(StorageCleanupInputSchema, object({ jobId: string() }), {
21501
+ kind: "mutation",
21502
+ auth: "admin"
21503
+ }), method(StorageCleanupStatusInputSchema, StorageCleanupJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
21504
+ kind: "mutation",
21505
+ auth: "admin"
21506
+ }), method(object({}), array(StorageMigrationJobSchema).readonly(), { auth: "admin" });
21421
21507
  var ProviderInfoSchema = discriminatedUnion("shouldSaveDiskSpace", [object({
21422
21508
  providerId: string().min(1),
21423
21509
  displayName: string().min(1),
@@ -26807,6 +26893,33 @@ var RecordingRebalanceInputSchema = object({
26807
26893
  minMoveGb: number().min(0).optional()
26808
26894
  });
26809
26895
  /**
26896
+ * Operator-facing placement of one camera onto a recordings location.
26897
+ *
26898
+ * `pinLocationId` is the operator instruction: a location id, or `null` for
26899
+ * Auto (the planner may move this camera). `locationId` is where high/mid
26900
+ * currently write — the plan, which may disagree with the pin when Auto.
26901
+ */
26902
+ var RecordingDevicePlacementSchema = object({
26903
+ deviceId: number().int(),
26904
+ profile: string(),
26905
+ locationId: string()
26906
+ });
26907
+ var RecordingDevicePinSchema = object({
26908
+ deviceId: number().int(),
26909
+ /** Recordings-class location this camera is pinned to. */
26910
+ locationId: string()
26911
+ });
26912
+ var RecordingPlacementViewSchema = object({
26913
+ assignments: array(RecordingDevicePlacementSchema),
26914
+ pins: array(RecordingDevicePinSchema),
26915
+ defaultLocations: record(string(), string())
26916
+ });
26917
+ var RecordingSetDevicePlacementInputSchema = object({
26918
+ deviceId: number().int(),
26919
+ /** `null` = Auto. Otherwise a `recordings:*` location id. */
26920
+ locationId: string().nullable()
26921
+ });
26922
+ /**
26810
26923
  * Result of locating footage at a wall-clock instant for one device/profile.
26811
26924
  * `segment` carries the covering segment's window; `gap` reports the forward
26812
26925
  * nearest covered edge (`null` past the end of footage / when none exists)
@@ -27032,6 +27145,12 @@ method(object({
27032
27145
  }), method(RecordingRebalanceInputSchema, RecordingRebalancePlanSchema, {
27033
27146
  kind: "mutation",
27034
27147
  auth: "admin"
27148
+ }), method(object({}), RecordingPlacementViewSchema, {
27149
+ kind: "query",
27150
+ auth: "admin"
27151
+ }), method(RecordingSetDevicePlacementInputSchema, object({ ok: literal(true) }), {
27152
+ kind: "mutation",
27153
+ auth: "admin"
27035
27154
  });
27036
27155
  /**
27037
27156
  * `recording-export` cap — render a footage time range into a single downloadable
@@ -30409,6 +30528,12 @@ Object.freeze({
30409
30528
  addonId: null,
30410
30529
  access: "delete"
30411
30530
  },
30531
+ "deviceManager.renameLocation": {
30532
+ capName: "device-manager",
30533
+ capScope: "system",
30534
+ addonId: null,
30535
+ access: "create"
30536
+ },
30412
30537
  "deviceManager.runDeviceAction": {
30413
30538
  capName: "device-manager",
30414
30539
  capScope: "system",
@@ -32101,19 +32226,19 @@ Object.freeze({
32101
32226
  addonId: null,
32102
32227
  access: "view"
32103
32228
  },
32104
- "pipelineAnalytics.getGroup": {
32229
+ "pipelineAnalytics.getKeyEvents": {
32105
32230
  capName: "pipeline-analytics",
32106
32231
  capScope: "device",
32107
32232
  addonId: null,
32108
32233
  access: "view"
32109
32234
  },
32110
- "pipelineAnalytics.getKeyEvents": {
32235
+ "pipelineAnalytics.getKeyEventsBatch": {
32111
32236
  capName: "pipeline-analytics",
32112
32237
  capScope: "device",
32113
32238
  addonId: null,
32114
32239
  access: "view"
32115
32240
  },
32116
- "pipelineAnalytics.getKeyEventsBatch": {
32241
+ "pipelineAnalytics.getMediaReclaimStatus": {
32117
32242
  capName: "pipeline-analytics",
32118
32243
  capScope: "device",
32119
32244
  addonId: null,
@@ -32203,12 +32328,6 @@ Object.freeze({
32203
32328
  addonId: null,
32204
32329
  access: "view"
32205
32330
  },
32206
- "pipelineAnalytics.listGroups": {
32207
- capName: "pipeline-analytics",
32208
- capScope: "device",
32209
- addonId: null,
32210
- access: "view"
32211
- },
32212
32331
  "pipelineAnalytics.listOpsLog": {
32213
32332
  capName: "pipeline-analytics",
32214
32333
  capScope: "device",
@@ -32293,6 +32412,12 @@ Object.freeze({
32293
32412
  addonId: null,
32294
32413
  access: "create"
32295
32414
  },
32415
+ "pipelineAnalytics.reclaimDebugMedia": {
32416
+ capName: "pipeline-analytics",
32417
+ capScope: "device",
32418
+ addonId: null,
32419
+ access: "create"
32420
+ },
32296
32421
  "pipelineAnalytics.reconcileFromDisk": {
32297
32422
  capName: "pipeline-analytics",
32298
32423
  capScope: "device",
@@ -33217,6 +33342,12 @@ Object.freeze({
33217
33342
  addonId: null,
33218
33343
  access: "view"
33219
33344
  },
33345
+ "recording.getPlacement": {
33346
+ capName: "recording",
33347
+ capScope: "system",
33348
+ addonId: null,
33349
+ access: "view"
33350
+ },
33220
33351
  "recording.getPlaybackManifest": {
33221
33352
  capName: "recording",
33222
33353
  capScope: "system",
@@ -33343,6 +33474,12 @@ Object.freeze({
33343
33474
  addonId: null,
33344
33475
  access: "create"
33345
33476
  },
33477
+ "recording.setDevicePlacement": {
33478
+ capName: "recording",
33479
+ capScope: "system",
33480
+ addonId: null,
33481
+ access: "create"
33482
+ },
33346
33483
  "recording.startStorageMigrationMove": {
33347
33484
  capName: "recording",
33348
33485
  capScope: "system",
@@ -33787,12 +33924,36 @@ Object.freeze({
33787
33924
  addonId: null,
33788
33925
  access: "create"
33789
33926
  },
33927
+ "storageMigration.cleanupCancel": {
33928
+ capName: "storage-migration",
33929
+ capScope: "system",
33930
+ addonId: null,
33931
+ access: "create"
33932
+ },
33933
+ "storageMigration.cleanupStart": {
33934
+ capName: "storage-migration",
33935
+ capScope: "system",
33936
+ addonId: null,
33937
+ access: "create"
33938
+ },
33939
+ "storageMigration.cleanupStatus": {
33940
+ capName: "storage-migration",
33941
+ capScope: "system",
33942
+ addonId: null,
33943
+ access: "view"
33944
+ },
33790
33945
  "storageMigration.drain": {
33791
33946
  capName: "storage-migration",
33792
33947
  capScope: "system",
33793
33948
  addonId: null,
33794
33949
  access: "create"
33795
33950
  },
33951
+ "storageMigration.history": {
33952
+ capName: "storage-migration",
33953
+ capScope: "system",
33954
+ addonId: null,
33955
+ access: "view"
33956
+ },
33796
33957
  "storageMigration.movers": {
33797
33958
  capName: "storage-migration",
33798
33959
  capScope: "system",
@@ -35789,11 +35950,6 @@ Object.freeze({
35789
35950
  form: "single",
35790
35951
  optional: true
35791
35952
  }],
35792
- "pipelineAnalytics.getGroup": [{
35793
- name: "deviceId",
35794
- form: "single",
35795
- optional: false
35796
- }],
35797
35953
  "pipelineAnalytics.getKeyEvents": [{
35798
35954
  name: "deviceId",
35799
35955
  form: "single",
@@ -35859,11 +36015,6 @@ Object.freeze({
35859
36015
  form: "single",
35860
36016
  optional: false
35861
36017
  }],
35862
- "pipelineAnalytics.listGroups": [{
35863
- name: "deviceIds",
35864
- form: "array",
35865
- optional: false
35866
- }],
35867
36018
  "pipelineAnalytics.listOpsLog": [{
35868
36019
  name: "deviceId",
35869
36020
  form: "single",
@@ -35909,6 +36060,11 @@ Object.freeze({
35909
36060
  form: "single",
35910
36061
  optional: true
35911
36062
  }],
36063
+ "pipelineAnalytics.reclaimDebugMedia": [{
36064
+ name: "deviceIds",
36065
+ form: "array",
36066
+ optional: true
36067
+ }],
35912
36068
  "pipelineAnalytics.reconcileFromDisk": [{
35913
36069
  name: "deviceId",
35914
36070
  form: "single",
@@ -36274,6 +36430,11 @@ Object.freeze({
36274
36430
  form: "single",
36275
36431
  optional: false
36276
36432
  }],
36433
+ "recording.setDevicePlacement": [{
36434
+ name: "deviceId",
36435
+ form: "single",
36436
+ optional: false
36437
+ }],
36277
36438
  "recording.startStorageMigrationMove": [{
36278
36439
  name: "deviceId",
36279
36440
  form: "single",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-export-google",
3
- "version": "0.1.13",
3
+ "version": "0.1.14",
4
4
  "description": "Google Home export — hub-side smart-home fulfillment (SYNC / QUERY / EXECUTE / DISCONNECT) for the non-camera fleet, served over the hub's own OAuth account link. No Google credential is stored, sent or required.",
5
5
  "keywords": [
6
6
  "camstack",