@camstack/addon-remote-storage 1.2.48 → 1.2.49

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.
package/dist/s3.addon.js CHANGED
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_shared = require("./shared-Bwt_Ye8T.js");
5
+ const require_shared = require("./shared-BAungtYx.js");
6
6
  let node_stream = require("node:stream");
7
7
  let _aws_sdk_client_s3 = require("@aws-sdk/client-s3");
8
8
  let _aws_sdk_lib_storage = require("@aws-sdk/lib-storage");
package/dist/s3.addon.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { c as BaseAddon, i as rearmIdleAbort, n as getOptionalBasePath, o as scheduleIdleAbort, s as storageProviderCapability, t as createSessionId } from "./shared-CQEWmUcA.mjs";
1
+ import { c as BaseAddon, i as rearmIdleAbort, n as getOptionalBasePath, o as scheduleIdleAbort, s as storageProviderCapability, t as createSessionId } from "./shared-Da9FHywp.mjs";
2
2
  import { PassThrough } from "node:stream";
3
3
  import { DeleteObjectCommand, GetObjectCommand, HeadBucketCommand, HeadObjectCommand, ListObjectsV2Command, PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
4
4
  import { Upload } from "@aws-sdk/lib-storage";
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_shared = require("./shared-Bwt_Ye8T.js");
5
+ const require_shared = require("./shared-BAungtYx.js");
6
6
  let ssh2 = require("ssh2");
7
7
  let node_path = require("node:path");
8
8
  node_path = require_shared.__toESM(node_path);
@@ -1,4 +1,4 @@
1
- import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-CQEWmUcA.mjs";
1
+ import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-Da9FHywp.mjs";
2
2
  import { Client } from "ssh2";
3
3
  import * as path from "node:path";
4
4
  //#region src/providers/sftp/sftp-config-schema.ts
@@ -8104,6 +8104,13 @@ var MediaRelocateModeSchema = _enum([
8104
8104
  ]);
8105
8105
  var RelocateMediaInputSchema = object({
8106
8106
  toLocationId: string(),
8107
+ /**
8108
+ * Restrict the pass to rows currently on this location. Omitted / `'*'` =
8109
+ * every row that is not already on `toLocationId` (the historical
8110
+ * behaviour). A named source is what a from→to migration needs: without it
8111
+ * "move events off disk 2" also emptied disk 1.
8112
+ */
8113
+ fromLocationId: string().optional(),
8107
8114
  throttleMbps: number().min(1).max(1e3).optional(),
8108
8115
  /** Omitted = `move`, the pre-existing behaviour. */
8109
8116
  mode: MediaRelocateModeSchema.optional()
@@ -8171,6 +8178,19 @@ var StorageMigrationDestinationsSchema = object({
8171
8178
  galleryMedia: string().min(1).optional()
8172
8179
  }).refine((value) => Object.keys(value).length > 0, { message: "select at least one storage class" });
8173
8180
  /**
8181
+ * Optional named source per class. Omitted = the class's current default
8182
+ * (the historical behaviour). A named source that is NOT the default is a
8183
+ * drain of that disk: bytes move, the default stays, and the source is
8184
+ * disabled when the move finishes.
8185
+ */
8186
+ var StorageMigrationSourcesSchema = object({
8187
+ recordings: string().min(1).optional(),
8188
+ recordingsLow: string().min(1).optional(),
8189
+ eventMedia: string().min(1).optional(),
8190
+ backups: string().min(1).optional(),
8191
+ galleryMedia: string().min(1).optional()
8192
+ }).optional();
8193
+ /**
8174
8194
  * How a migration sequences the cutover against the byte move.
8175
8195
  *
8176
8196
  * - `blocking` — the historical order: pause, move every byte, repoint,
@@ -8192,6 +8212,8 @@ var StorageMigrationModeSchema = _enum(["blocking", "nonBlocking"]);
8192
8212
  /** Shared input for planning and starting an orchestrated storage migration. */
8193
8213
  var StorageMigrationInputSchema = object({
8194
8214
  destinations: StorageMigrationDestinationsSchema,
8215
+ /** Omitted = each class's current default. */
8216
+ sources: StorageMigrationSourcesSchema,
8195
8217
  throttleMbps: number().min(1).max(1e3).optional(),
8196
8218
  /** Omitted = `blocking`, which stays the default. */
8197
8219
  mode: StorageMigrationModeSchema.optional()
@@ -8271,6 +8293,13 @@ var StorageMigrationMoveSchema = object({
8271
8293
  storageClass: StorageMigrationClassSchema,
8272
8294
  fromLocationId: string(),
8273
8295
  toLocationId: string(),
8296
+ /**
8297
+ * True when `from` was NOT the class default at plan time. The move still
8298
+ * copies bytes, but the default is left alone and the source is disabled
8299
+ * once the copy verifies. Absent on jobs planned before this field existed
8300
+ * — those jobs always repointed, which is `false`.
8301
+ */
8302
+ freezeSource: boolean().optional(),
8274
8303
  moverJobId: string().nullable(),
8275
8304
  state: RelocateJobStateSchema.nullable(),
8276
8305
  error: string().nullable(),
@@ -8284,6 +8313,7 @@ var StorageMigrationJobSchema = object({
8284
8313
  * can tell a seconds-long cutover from a thirty-hour one. */
8285
8314
  mode: StorageMigrationModeSchema,
8286
8315
  destinations: StorageMigrationDestinationsSchema,
8316
+ sources: StorageMigrationSourcesSchema,
8287
8317
  throttleMbps: number(),
8288
8318
  moves: array(StorageMigrationMoveSchema),
8289
8319
  pauseLeaseId: string().nullable(),
@@ -8309,6 +8339,7 @@ var StorageMigrationFindingSchema = object({
8309
8339
  });
8310
8340
  var StorageMigrationPlanSchema = object({
8311
8341
  destinations: StorageMigrationDestinationsSchema,
8342
+ sources: StorageMigrationSourcesSchema,
8312
8343
  /** The mode this plan was built for. A plan is only valid for its mode: the
8313
8344
  * `eventMedia` seal gate and the single-cardinality refusal both depend on
8314
8345
  * it. */
@@ -8316,7 +8347,8 @@ var StorageMigrationPlanSchema = object({
8316
8347
  moves: array(object({
8317
8348
  storageClass: StorageMigrationClassSchema,
8318
8349
  fromLocationId: string(),
8319
- toLocationId: string()
8350
+ toLocationId: string(),
8351
+ freezeSource: boolean().optional()
8320
8352
  })),
8321
8353
  findings: array(StorageMigrationFindingSchema)
8322
8354
  });
@@ -8494,10 +8526,51 @@ var LedgerWalkReportSchema = object({
8494
8526
  var RelocatableMediaCountSchema = object({ rows: number().int().nonnegative() }).nullable();
8495
8527
  var RelocatableMediaCountInputSchema = object({
8496
8528
  toLocationId: string().min(1),
8529
+ /** Restrict the count to one source; omitted / `'*'` = every non-target row. */
8530
+ fromLocationId: string().optional(),
8497
8531
  /** Omitted = `move`. */
8498
8532
  mode: MediaRelocateModeSchema.optional()
8499
8533
  });
8500
8534
  /**
8535
+ * Operator cleanup of leftover analytics rows, optional debug media, and
8536
+ * ghost ledger entries on frozen footage locations.
8537
+ *
8538
+ * A pass is tens of minutes on a standing backlog. The hub method RETURNS
8539
+ * `{ jobId }` immediately; progress is `cleanupStatus`. Awaiting the work
8540
+ * is how `addons.custom` hit the 60 s UDS deadline while reclaim continued
8541
+ * with no operator-visible status.
8542
+ */
8543
+ var StorageCleanupPhaseSchema = _enum([
8544
+ "orphans",
8545
+ "debug-media",
8546
+ "ghost-ledger",
8547
+ "done",
8548
+ "failed",
8549
+ "cancelled"
8550
+ ]);
8551
+ var StorageCleanupInputSchema = object({
8552
+ /** Also walk motion stills / track filmstrips. Off by default. */
8553
+ includeDebugMedia: boolean().optional() });
8554
+ var StorageCleanupJobSchema = object({
8555
+ jobId: string(),
8556
+ phase: StorageCleanupPhaseSchema,
8557
+ includeDebugMedia: boolean(),
8558
+ orphansReclaimed: number().int().nonnegative(),
8559
+ orphanBytesReclaimed: number().int().nonnegative(),
8560
+ debugMediaReclaimed: number().int().nonnegative(),
8561
+ debugMediaBytesReclaimed: number().int().nonnegative(),
8562
+ ghostsForgotten: number().int().nonnegative(),
8563
+ ghostBytesForgotten: number().int().nonnegative(),
8564
+ /** Short operator-facing line: current collection, pass, or location. */
8565
+ detail: string().nullable(),
8566
+ cancelRequested: boolean(),
8567
+ startedAt: number(),
8568
+ updatedAt: number(),
8569
+ finishedAt: number().nullable(),
8570
+ error: string().nullable()
8571
+ });
8572
+ var StorageCleanupStatusInputSchema = object({ jobId: string().optional() });
8573
+ /**
8501
8574
  * `StorageLocationType` — an addon-declared id that identifies the *kind* of
8502
8575
  * storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
8503
8576
  * so the persisted record schema and the consumer-facing cap can both consume it
@@ -8525,11 +8598,10 @@ var StorageLocationTypeSchema = string().regex(/^[a-z][a-zA-Z0-9-]*$/);
8525
8598
  * The default location for a type uses `id === <type>:default` by
8526
8599
  * convention (the bare type ref like `'backups'` resolves to it).
8527
8600
  *
8528
- * `isSystem: true` marks a location as orchestrator-seeded and
8529
- * undeletable. The bootstrap-installed defaults (one per type) carry
8530
- * this flag; operator-added locations don't. Editing the config of
8531
- * a system location is allowed (path migration, provider swap) but
8532
- * deleting it is rejected at the cap level.
8601
+ * `isSystem` is a legacy persisted flag. Seed still creates the initial
8602
+ * `<type>:default` locations; the flag is no longer a lock, a badge, or a
8603
+ * prune selector. New writes leave it false. Deletion is gated on uniqueness
8604
+ * / last-enabled, not on this bit.
8533
8605
  */
8534
8606
  var StorageLocationSchema = object({
8535
8607
  id: string().regex(/^[a-z][a-zA-Z0-9-]*:[a-zA-Z0-9-]+$/),
@@ -12791,6 +12863,12 @@ method(object({
12791
12863
  }), _void(), {
12792
12864
  kind: "mutation",
12793
12865
  auth: "admin"
12866
+ }), method(object({
12867
+ from: string(),
12868
+ to: string()
12869
+ }), object({ moved: number() }), {
12870
+ kind: "mutation",
12871
+ auth: "admin"
12794
12872
  }), method(object({
12795
12873
  deviceId: number(),
12796
12874
  disabled: boolean()
@@ -18721,46 +18799,6 @@ var RecentTracksPageSchema = object({
18721
18799
  /** Cursor for the next page, or null when this page is the last. */
18722
18800
  nextCursor: string().nullable()
18723
18801
  });
18724
- var LIST_GROUPS_DEFAULT_LIMIT = 40;
18725
- var LIST_GROUPS_MAX_LIMIT = 100;
18726
- var AnalyticsGroupRecordSchema = object({
18727
- id: string(),
18728
- deviceId: number().int(),
18729
- openedAt: number().int(),
18730
- closedAt: number().int(),
18731
- timestamp: number().int(),
18732
- memberCount: number().int(),
18733
- memberTrackIds: array(string()).readonly(),
18734
- className: string(),
18735
- classes: array(string()).readonly(),
18736
- /** Relative event-media path, or null when the group has no picture yet. */
18737
- mediaUrl: string().nullable(),
18738
- singleton: boolean()
18739
- });
18740
- var AnalyticsGroupMemberSchema = object({
18741
- trackId: string(),
18742
- deviceId: number().int(),
18743
- className: string(),
18744
- firstSeen: number().int(),
18745
- lastSeen: number().int(),
18746
- mediaUrl: string().nullable()
18747
- });
18748
- var AnalyticsGroupDetailSchema = AnalyticsGroupRecordSchema.extend({ members: array(AnalyticsGroupMemberSchema).readonly() });
18749
- var ListGroupsQueryInput = object({
18750
- /** Devices to merge. An empty array yields `{ groups: [], nextCursor: null }`. */
18751
- deviceIds: array(number()),
18752
- /** Window lower bound on `closedAt` (inclusive). */
18753
- since: number().optional(),
18754
- /** Window upper bound on `openedAt` (inclusive). */
18755
- until: number().optional(),
18756
- limit: number().int().min(1).max(LIST_GROUPS_MAX_LIMIT).default(LIST_GROUPS_DEFAULT_LIMIT),
18757
- /** Opaque continuation cursor from a previous page's `nextCursor`. */
18758
- cursor: string().optional()
18759
- });
18760
- var ListGroupsPageSchema = object({
18761
- groups: array(AnalyticsGroupRecordSchema).readonly(),
18762
- nextCursor: string().nullable()
18763
- });
18764
18802
  var KEY_EVENTS_DEFAULT_LIMIT = 50;
18765
18803
  var KEY_EVENTS_MAX_LIMIT = 200;
18766
18804
  var KeyEventQueryInput = object({
@@ -18864,9 +18902,7 @@ var TrackCascadeCountsSchema = object({
18864
18902
  /** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
18865
18903
  plates: number().int(),
18866
18904
  /** Per-track CLIP search vectors removed (best-effort). */
18867
- embeddings: number().int(),
18868
- /** Group membership + group rows removed with their last member (best-effort). */
18869
- groups: number().int()
18905
+ embeddings: number().int()
18870
18906
  });
18871
18907
  /** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
18872
18908
  var DiskReconcileCountsSchema = object({
@@ -19036,6 +19072,47 @@ var RebuildStatusSchema = object({
19036
19072
  /** Present when the pass ended by throwing. */
19037
19073
  error: string().nullable()
19038
19074
  });
19075
+ /**
19076
+ * Acknowledgement that a debug-media reclaim STARTED.
19077
+ *
19078
+ * The pass is paced at ~2 MB/s over a standing 100 GB — tens of minutes — so
19079
+ * it runs detached and this returns immediately. Awaiting it is how the
19080
+ * `addons.custom` door hit the 60 s UDS deadline while the walk carried on
19081
+ * with no status. Poll {@link pipelineAnalyticsCapability.methods.getMediaReclaimStatus}.
19082
+ */
19083
+ var MediaReclaimStartResultSchema = object({
19084
+ started: boolean(),
19085
+ /** True when a pass was already running; the new request is ignored. */
19086
+ alreadyRunning: boolean()
19087
+ });
19088
+ var MediaReclaimInputSchema = object({
19089
+ mode: _enum(["report", "reclaim"]).default("report"),
19090
+ scopes: array(_enum(["motion-still", "track-filmstrip"])).min(1).optional(),
19091
+ deviceIds: array(number().int()).min(1).optional(),
19092
+ restart: boolean().optional(),
19093
+ pageSize: number().int().min(50).max(5e3).optional(),
19094
+ maxRowsPerDevice: number().int().min(1).max(5e5).optional(),
19095
+ maxReclaimPerDevice: number().int().min(1).max(5e5).optional(),
19096
+ maxBytesPerRun: number().int().min(1).optional(),
19097
+ budgetMinutes: number().int().min(1).max(720).optional(),
19098
+ throttleBytesPerSec: number().int().min(64 * 1024).optional(),
19099
+ graceMinutes: number().int().min(1).max(10080).optional()
19100
+ });
19101
+ var MediaReclaimStatusSchema = object({
19102
+ running: boolean(),
19103
+ mode: _enum(["report", "reclaim"]).nullable(),
19104
+ totalExamined: number(),
19105
+ totalEligible: number(),
19106
+ totalReclaimed: number(),
19107
+ totalBytesReclaimed: number(),
19108
+ totalRefused: number(),
19109
+ /** Device+scope windows finished in this pass. */
19110
+ devicesDone: number(),
19111
+ complete: boolean().nullable(),
19112
+ startedAtMs: number().nullable(),
19113
+ finishedAtMs: number().nullable(),
19114
+ error: string().nullable()
19115
+ });
19039
19116
  var ReplayFrameInputSchema = object({
19040
19117
  timestamp: number(),
19041
19118
  frame: PipelineRunResultBridge
@@ -19074,10 +19151,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19074
19151
  * stationary registry). Default false: the timeline lists passages,
19075
19152
  * not parking records (operator decision, 2026-08-15). */
19076
19153
  includeStationary: boolean().optional()
19077
- }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(ListGroupsQueryInput, ListGroupsPageSchema), method(object({
19078
- deviceId: number(),
19079
- groupId: string().min(1)
19080
- }), AnalyticsGroupDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
19154
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
19081
19155
  kind: "mutation",
19082
19156
  auth: "admin"
19083
19157
  }), 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({
@@ -19177,6 +19251,12 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19177
19251
  }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
19178
19252
  kind: "query",
19179
19253
  auth: "admin"
19254
+ }), method(MediaReclaimInputSchema, MediaReclaimStartResultSchema, {
19255
+ kind: "mutation",
19256
+ auth: "admin"
19257
+ }), method(object({}), MediaReclaimStatusSchema, {
19258
+ kind: "query",
19259
+ auth: "admin"
19180
19260
  }), method(object({ deviceIds: array(number()).optional() }), TrainingExportSummarySchema, {
19181
19261
  kind: "query",
19182
19262
  auth: "admin"
@@ -21147,7 +21227,13 @@ method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin"
21147
21227
  }), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
21148
21228
  kind: "mutation",
21149
21229
  auth: "admin"
21150
- });
21230
+ }), method(StorageCleanupInputSchema, object({ jobId: string() }), {
21231
+ kind: "mutation",
21232
+ auth: "admin"
21233
+ }), method(StorageCleanupStatusInputSchema, StorageCleanupJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
21234
+ kind: "mutation",
21235
+ auth: "admin"
21236
+ }), method(object({}), array(StorageMigrationJobSchema).readonly(), { auth: "admin" });
21151
21237
  var ProviderInfoSchema = discriminatedUnion("shouldSaveDiskSpace", [object({
21152
21238
  providerId: string().min(1),
21153
21239
  displayName: string().min(1),
@@ -26585,6 +26671,33 @@ var RecordingRebalanceInputSchema = object({
26585
26671
  minMoveGb: number().min(0).optional()
26586
26672
  });
26587
26673
  /**
26674
+ * Operator-facing placement of one camera onto a recordings location.
26675
+ *
26676
+ * `pinLocationId` is the operator instruction: a location id, or `null` for
26677
+ * Auto (the planner may move this camera). `locationId` is where high/mid
26678
+ * currently write — the plan, which may disagree with the pin when Auto.
26679
+ */
26680
+ var RecordingDevicePlacementSchema = object({
26681
+ deviceId: number().int(),
26682
+ profile: string(),
26683
+ locationId: string()
26684
+ });
26685
+ var RecordingDevicePinSchema = object({
26686
+ deviceId: number().int(),
26687
+ /** Recordings-class location this camera is pinned to. */
26688
+ locationId: string()
26689
+ });
26690
+ var RecordingPlacementViewSchema = object({
26691
+ assignments: array(RecordingDevicePlacementSchema),
26692
+ pins: array(RecordingDevicePinSchema),
26693
+ defaultLocations: record(string(), string())
26694
+ });
26695
+ var RecordingSetDevicePlacementInputSchema = object({
26696
+ deviceId: number().int(),
26697
+ /** `null` = Auto. Otherwise a `recordings:*` location id. */
26698
+ locationId: string().nullable()
26699
+ });
26700
+ /**
26588
26701
  * Result of locating footage at a wall-clock instant for one device/profile.
26589
26702
  * `segment` carries the covering segment's window; `gap` reports the forward
26590
26703
  * nearest covered edge (`null` past the end of footage / when none exists)
@@ -26810,6 +26923,12 @@ method(object({
26810
26923
  }), method(RecordingRebalanceInputSchema, RecordingRebalancePlanSchema, {
26811
26924
  kind: "mutation",
26812
26925
  auth: "admin"
26926
+ }), method(object({}), RecordingPlacementViewSchema, {
26927
+ kind: "query",
26928
+ auth: "admin"
26929
+ }), method(RecordingSetDevicePlacementInputSchema, object({ ok: literal(true) }), {
26930
+ kind: "mutation",
26931
+ auth: "admin"
26813
26932
  });
26814
26933
  /**
26815
26934
  * `recording-export` cap — render a footage time range into a single downloadable
@@ -30180,6 +30299,12 @@ Object.freeze({
30180
30299
  addonId: null,
30181
30300
  access: "delete"
30182
30301
  },
30302
+ "deviceManager.renameLocation": {
30303
+ capName: "device-manager",
30304
+ capScope: "system",
30305
+ addonId: null,
30306
+ access: "create"
30307
+ },
30183
30308
  "deviceManager.runDeviceAction": {
30184
30309
  capName: "device-manager",
30185
30310
  capScope: "system",
@@ -31872,19 +31997,19 @@ Object.freeze({
31872
31997
  addonId: null,
31873
31998
  access: "view"
31874
31999
  },
31875
- "pipelineAnalytics.getGroup": {
32000
+ "pipelineAnalytics.getKeyEvents": {
31876
32001
  capName: "pipeline-analytics",
31877
32002
  capScope: "device",
31878
32003
  addonId: null,
31879
32004
  access: "view"
31880
32005
  },
31881
- "pipelineAnalytics.getKeyEvents": {
32006
+ "pipelineAnalytics.getKeyEventsBatch": {
31882
32007
  capName: "pipeline-analytics",
31883
32008
  capScope: "device",
31884
32009
  addonId: null,
31885
32010
  access: "view"
31886
32011
  },
31887
- "pipelineAnalytics.getKeyEventsBatch": {
32012
+ "pipelineAnalytics.getMediaReclaimStatus": {
31888
32013
  capName: "pipeline-analytics",
31889
32014
  capScope: "device",
31890
32015
  addonId: null,
@@ -31974,12 +32099,6 @@ Object.freeze({
31974
32099
  addonId: null,
31975
32100
  access: "view"
31976
32101
  },
31977
- "pipelineAnalytics.listGroups": {
31978
- capName: "pipeline-analytics",
31979
- capScope: "device",
31980
- addonId: null,
31981
- access: "view"
31982
- },
31983
32102
  "pipelineAnalytics.listOpsLog": {
31984
32103
  capName: "pipeline-analytics",
31985
32104
  capScope: "device",
@@ -32064,6 +32183,12 @@ Object.freeze({
32064
32183
  addonId: null,
32065
32184
  access: "create"
32066
32185
  },
32186
+ "pipelineAnalytics.reclaimDebugMedia": {
32187
+ capName: "pipeline-analytics",
32188
+ capScope: "device",
32189
+ addonId: null,
32190
+ access: "create"
32191
+ },
32067
32192
  "pipelineAnalytics.reconcileFromDisk": {
32068
32193
  capName: "pipeline-analytics",
32069
32194
  capScope: "device",
@@ -32988,6 +33113,12 @@ Object.freeze({
32988
33113
  addonId: null,
32989
33114
  access: "view"
32990
33115
  },
33116
+ "recording.getPlacement": {
33117
+ capName: "recording",
33118
+ capScope: "system",
33119
+ addonId: null,
33120
+ access: "view"
33121
+ },
32991
33122
  "recording.getPlaybackManifest": {
32992
33123
  capName: "recording",
32993
33124
  capScope: "system",
@@ -33114,6 +33245,12 @@ Object.freeze({
33114
33245
  addonId: null,
33115
33246
  access: "create"
33116
33247
  },
33248
+ "recording.setDevicePlacement": {
33249
+ capName: "recording",
33250
+ capScope: "system",
33251
+ addonId: null,
33252
+ access: "create"
33253
+ },
33117
33254
  "recording.startStorageMigrationMove": {
33118
33255
  capName: "recording",
33119
33256
  capScope: "system",
@@ -33558,12 +33695,36 @@ Object.freeze({
33558
33695
  addonId: null,
33559
33696
  access: "create"
33560
33697
  },
33698
+ "storageMigration.cleanupCancel": {
33699
+ capName: "storage-migration",
33700
+ capScope: "system",
33701
+ addonId: null,
33702
+ access: "create"
33703
+ },
33704
+ "storageMigration.cleanupStart": {
33705
+ capName: "storage-migration",
33706
+ capScope: "system",
33707
+ addonId: null,
33708
+ access: "create"
33709
+ },
33710
+ "storageMigration.cleanupStatus": {
33711
+ capName: "storage-migration",
33712
+ capScope: "system",
33713
+ addonId: null,
33714
+ access: "view"
33715
+ },
33561
33716
  "storageMigration.drain": {
33562
33717
  capName: "storage-migration",
33563
33718
  capScope: "system",
33564
33719
  addonId: null,
33565
33720
  access: "create"
33566
33721
  },
33722
+ "storageMigration.history": {
33723
+ capName: "storage-migration",
33724
+ capScope: "system",
33725
+ addonId: null,
33726
+ access: "view"
33727
+ },
33567
33728
  "storageMigration.movers": {
33568
33729
  capName: "storage-migration",
33569
33730
  capScope: "system",
@@ -35560,11 +35721,6 @@ Object.freeze({
35560
35721
  form: "single",
35561
35722
  optional: true
35562
35723
  }],
35563
- "pipelineAnalytics.getGroup": [{
35564
- name: "deviceId",
35565
- form: "single",
35566
- optional: false
35567
- }],
35568
35724
  "pipelineAnalytics.getKeyEvents": [{
35569
35725
  name: "deviceId",
35570
35726
  form: "single",
@@ -35630,11 +35786,6 @@ Object.freeze({
35630
35786
  form: "single",
35631
35787
  optional: false
35632
35788
  }],
35633
- "pipelineAnalytics.listGroups": [{
35634
- name: "deviceIds",
35635
- form: "array",
35636
- optional: false
35637
- }],
35638
35789
  "pipelineAnalytics.listOpsLog": [{
35639
35790
  name: "deviceId",
35640
35791
  form: "single",
@@ -35680,6 +35831,11 @@ Object.freeze({
35680
35831
  form: "single",
35681
35832
  optional: true
35682
35833
  }],
35834
+ "pipelineAnalytics.reclaimDebugMedia": [{
35835
+ name: "deviceIds",
35836
+ form: "array",
35837
+ optional: true
35838
+ }],
35683
35839
  "pipelineAnalytics.reconcileFromDisk": [{
35684
35840
  name: "deviceId",
35685
35841
  form: "single",
@@ -36045,6 +36201,11 @@ Object.freeze({
36045
36201
  form: "single",
36046
36202
  optional: false
36047
36203
  }],
36204
+ "recording.setDevicePlacement": [{
36205
+ name: "deviceId",
36206
+ form: "single",
36207
+ optional: false
36208
+ }],
36048
36209
  "recording.startStorageMigrationMove": [{
36049
36210
  name: "deviceId",
36050
36211
  form: "single",
@@ -8081,6 +8081,13 @@ var MediaRelocateModeSchema = _enum([
8081
8081
  ]);
8082
8082
  var RelocateMediaInputSchema = object({
8083
8083
  toLocationId: string(),
8084
+ /**
8085
+ * Restrict the pass to rows currently on this location. Omitted / `'*'` =
8086
+ * every row that is not already on `toLocationId` (the historical
8087
+ * behaviour). A named source is what a from→to migration needs: without it
8088
+ * "move events off disk 2" also emptied disk 1.
8089
+ */
8090
+ fromLocationId: string().optional(),
8084
8091
  throttleMbps: number().min(1).max(1e3).optional(),
8085
8092
  /** Omitted = `move`, the pre-existing behaviour. */
8086
8093
  mode: MediaRelocateModeSchema.optional()
@@ -8148,6 +8155,19 @@ var StorageMigrationDestinationsSchema = object({
8148
8155
  galleryMedia: string().min(1).optional()
8149
8156
  }).refine((value) => Object.keys(value).length > 0, { message: "select at least one storage class" });
8150
8157
  /**
8158
+ * Optional named source per class. Omitted = the class's current default
8159
+ * (the historical behaviour). A named source that is NOT the default is a
8160
+ * drain of that disk: bytes move, the default stays, and the source is
8161
+ * disabled when the move finishes.
8162
+ */
8163
+ var StorageMigrationSourcesSchema = object({
8164
+ recordings: string().min(1).optional(),
8165
+ recordingsLow: string().min(1).optional(),
8166
+ eventMedia: string().min(1).optional(),
8167
+ backups: string().min(1).optional(),
8168
+ galleryMedia: string().min(1).optional()
8169
+ }).optional();
8170
+ /**
8151
8171
  * How a migration sequences the cutover against the byte move.
8152
8172
  *
8153
8173
  * - `blocking` — the historical order: pause, move every byte, repoint,
@@ -8169,6 +8189,8 @@ var StorageMigrationModeSchema = _enum(["blocking", "nonBlocking"]);
8169
8189
  /** Shared input for planning and starting an orchestrated storage migration. */
8170
8190
  var StorageMigrationInputSchema = object({
8171
8191
  destinations: StorageMigrationDestinationsSchema,
8192
+ /** Omitted = each class's current default. */
8193
+ sources: StorageMigrationSourcesSchema,
8172
8194
  throttleMbps: number().min(1).max(1e3).optional(),
8173
8195
  /** Omitted = `blocking`, which stays the default. */
8174
8196
  mode: StorageMigrationModeSchema.optional()
@@ -8248,6 +8270,13 @@ var StorageMigrationMoveSchema = object({
8248
8270
  storageClass: StorageMigrationClassSchema,
8249
8271
  fromLocationId: string(),
8250
8272
  toLocationId: string(),
8273
+ /**
8274
+ * True when `from` was NOT the class default at plan time. The move still
8275
+ * copies bytes, but the default is left alone and the source is disabled
8276
+ * once the copy verifies. Absent on jobs planned before this field existed
8277
+ * — those jobs always repointed, which is `false`.
8278
+ */
8279
+ freezeSource: boolean().optional(),
8251
8280
  moverJobId: string().nullable(),
8252
8281
  state: RelocateJobStateSchema.nullable(),
8253
8282
  error: string().nullable(),
@@ -8261,6 +8290,7 @@ var StorageMigrationJobSchema = object({
8261
8290
  * can tell a seconds-long cutover from a thirty-hour one. */
8262
8291
  mode: StorageMigrationModeSchema,
8263
8292
  destinations: StorageMigrationDestinationsSchema,
8293
+ sources: StorageMigrationSourcesSchema,
8264
8294
  throttleMbps: number(),
8265
8295
  moves: array(StorageMigrationMoveSchema),
8266
8296
  pauseLeaseId: string().nullable(),
@@ -8286,6 +8316,7 @@ var StorageMigrationFindingSchema = object({
8286
8316
  });
8287
8317
  var StorageMigrationPlanSchema = object({
8288
8318
  destinations: StorageMigrationDestinationsSchema,
8319
+ sources: StorageMigrationSourcesSchema,
8289
8320
  /** The mode this plan was built for. A plan is only valid for its mode: the
8290
8321
  * `eventMedia` seal gate and the single-cardinality refusal both depend on
8291
8322
  * it. */
@@ -8293,7 +8324,8 @@ var StorageMigrationPlanSchema = object({
8293
8324
  moves: array(object({
8294
8325
  storageClass: StorageMigrationClassSchema,
8295
8326
  fromLocationId: string(),
8296
- toLocationId: string()
8327
+ toLocationId: string(),
8328
+ freezeSource: boolean().optional()
8297
8329
  })),
8298
8330
  findings: array(StorageMigrationFindingSchema)
8299
8331
  });
@@ -8471,10 +8503,51 @@ var LedgerWalkReportSchema = object({
8471
8503
  var RelocatableMediaCountSchema = object({ rows: number().int().nonnegative() }).nullable();
8472
8504
  var RelocatableMediaCountInputSchema = object({
8473
8505
  toLocationId: string().min(1),
8506
+ /** Restrict the count to one source; omitted / `'*'` = every non-target row. */
8507
+ fromLocationId: string().optional(),
8474
8508
  /** Omitted = `move`. */
8475
8509
  mode: MediaRelocateModeSchema.optional()
8476
8510
  });
8477
8511
  /**
8512
+ * Operator cleanup of leftover analytics rows, optional debug media, and
8513
+ * ghost ledger entries on frozen footage locations.
8514
+ *
8515
+ * A pass is tens of minutes on a standing backlog. The hub method RETURNS
8516
+ * `{ jobId }` immediately; progress is `cleanupStatus`. Awaiting the work
8517
+ * is how `addons.custom` hit the 60 s UDS deadline while reclaim continued
8518
+ * with no operator-visible status.
8519
+ */
8520
+ var StorageCleanupPhaseSchema = _enum([
8521
+ "orphans",
8522
+ "debug-media",
8523
+ "ghost-ledger",
8524
+ "done",
8525
+ "failed",
8526
+ "cancelled"
8527
+ ]);
8528
+ var StorageCleanupInputSchema = object({
8529
+ /** Also walk motion stills / track filmstrips. Off by default. */
8530
+ includeDebugMedia: boolean().optional() });
8531
+ var StorageCleanupJobSchema = object({
8532
+ jobId: string(),
8533
+ phase: StorageCleanupPhaseSchema,
8534
+ includeDebugMedia: boolean(),
8535
+ orphansReclaimed: number().int().nonnegative(),
8536
+ orphanBytesReclaimed: number().int().nonnegative(),
8537
+ debugMediaReclaimed: number().int().nonnegative(),
8538
+ debugMediaBytesReclaimed: number().int().nonnegative(),
8539
+ ghostsForgotten: number().int().nonnegative(),
8540
+ ghostBytesForgotten: number().int().nonnegative(),
8541
+ /** Short operator-facing line: current collection, pass, or location. */
8542
+ detail: string().nullable(),
8543
+ cancelRequested: boolean(),
8544
+ startedAt: number(),
8545
+ updatedAt: number(),
8546
+ finishedAt: number().nullable(),
8547
+ error: string().nullable()
8548
+ });
8549
+ var StorageCleanupStatusInputSchema = object({ jobId: string().optional() });
8550
+ /**
8478
8551
  * `StorageLocationType` — an addon-declared id that identifies the *kind* of
8479
8552
  * storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
8480
8553
  * so the persisted record schema and the consumer-facing cap can both consume it
@@ -8502,11 +8575,10 @@ var StorageLocationTypeSchema = string().regex(/^[a-z][a-zA-Z0-9-]*$/);
8502
8575
  * The default location for a type uses `id === <type>:default` by
8503
8576
  * convention (the bare type ref like `'backups'` resolves to it).
8504
8577
  *
8505
- * `isSystem: true` marks a location as orchestrator-seeded and
8506
- * undeletable. The bootstrap-installed defaults (one per type) carry
8507
- * this flag; operator-added locations don't. Editing the config of
8508
- * a system location is allowed (path migration, provider swap) but
8509
- * deleting it is rejected at the cap level.
8578
+ * `isSystem` is a legacy persisted flag. Seed still creates the initial
8579
+ * `<type>:default` locations; the flag is no longer a lock, a badge, or a
8580
+ * prune selector. New writes leave it false. Deletion is gated on uniqueness
8581
+ * / last-enabled, not on this bit.
8510
8582
  */
8511
8583
  var StorageLocationSchema = object({
8512
8584
  id: string().regex(/^[a-z][a-zA-Z0-9-]*:[a-zA-Z0-9-]+$/),
@@ -12768,6 +12840,12 @@ method(object({
12768
12840
  }), _void(), {
12769
12841
  kind: "mutation",
12770
12842
  auth: "admin"
12843
+ }), method(object({
12844
+ from: string(),
12845
+ to: string()
12846
+ }), object({ moved: number() }), {
12847
+ kind: "mutation",
12848
+ auth: "admin"
12771
12849
  }), method(object({
12772
12850
  deviceId: number(),
12773
12851
  disabled: boolean()
@@ -18698,46 +18776,6 @@ var RecentTracksPageSchema = object({
18698
18776
  /** Cursor for the next page, or null when this page is the last. */
18699
18777
  nextCursor: string().nullable()
18700
18778
  });
18701
- var LIST_GROUPS_DEFAULT_LIMIT = 40;
18702
- var LIST_GROUPS_MAX_LIMIT = 100;
18703
- var AnalyticsGroupRecordSchema = object({
18704
- id: string(),
18705
- deviceId: number().int(),
18706
- openedAt: number().int(),
18707
- closedAt: number().int(),
18708
- timestamp: number().int(),
18709
- memberCount: number().int(),
18710
- memberTrackIds: array(string()).readonly(),
18711
- className: string(),
18712
- classes: array(string()).readonly(),
18713
- /** Relative event-media path, or null when the group has no picture yet. */
18714
- mediaUrl: string().nullable(),
18715
- singleton: boolean()
18716
- });
18717
- var AnalyticsGroupMemberSchema = object({
18718
- trackId: string(),
18719
- deviceId: number().int(),
18720
- className: string(),
18721
- firstSeen: number().int(),
18722
- lastSeen: number().int(),
18723
- mediaUrl: string().nullable()
18724
- });
18725
- var AnalyticsGroupDetailSchema = AnalyticsGroupRecordSchema.extend({ members: array(AnalyticsGroupMemberSchema).readonly() });
18726
- var ListGroupsQueryInput = object({
18727
- /** Devices to merge. An empty array yields `{ groups: [], nextCursor: null }`. */
18728
- deviceIds: array(number()),
18729
- /** Window lower bound on `closedAt` (inclusive). */
18730
- since: number().optional(),
18731
- /** Window upper bound on `openedAt` (inclusive). */
18732
- until: number().optional(),
18733
- limit: number().int().min(1).max(LIST_GROUPS_MAX_LIMIT).default(LIST_GROUPS_DEFAULT_LIMIT),
18734
- /** Opaque continuation cursor from a previous page's `nextCursor`. */
18735
- cursor: string().optional()
18736
- });
18737
- var ListGroupsPageSchema = object({
18738
- groups: array(AnalyticsGroupRecordSchema).readonly(),
18739
- nextCursor: string().nullable()
18740
- });
18741
18779
  var KEY_EVENTS_DEFAULT_LIMIT = 50;
18742
18780
  var KEY_EVENTS_MAX_LIMIT = 200;
18743
18781
  var KeyEventQueryInput = object({
@@ -18841,9 +18879,7 @@ var TrackCascadeCountsSchema = object({
18841
18879
  /** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
18842
18880
  plates: number().int(),
18843
18881
  /** Per-track CLIP search vectors removed (best-effort). */
18844
- embeddings: number().int(),
18845
- /** Group membership + group rows removed with their last member (best-effort). */
18846
- groups: number().int()
18882
+ embeddings: number().int()
18847
18883
  });
18848
18884
  /** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
18849
18885
  var DiskReconcileCountsSchema = object({
@@ -19013,6 +19049,47 @@ var RebuildStatusSchema = object({
19013
19049
  /** Present when the pass ended by throwing. */
19014
19050
  error: string().nullable()
19015
19051
  });
19052
+ /**
19053
+ * Acknowledgement that a debug-media reclaim STARTED.
19054
+ *
19055
+ * The pass is paced at ~2 MB/s over a standing 100 GB — tens of minutes — so
19056
+ * it runs detached and this returns immediately. Awaiting it is how the
19057
+ * `addons.custom` door hit the 60 s UDS deadline while the walk carried on
19058
+ * with no status. Poll {@link pipelineAnalyticsCapability.methods.getMediaReclaimStatus}.
19059
+ */
19060
+ var MediaReclaimStartResultSchema = object({
19061
+ started: boolean(),
19062
+ /** True when a pass was already running; the new request is ignored. */
19063
+ alreadyRunning: boolean()
19064
+ });
19065
+ var MediaReclaimInputSchema = object({
19066
+ mode: _enum(["report", "reclaim"]).default("report"),
19067
+ scopes: array(_enum(["motion-still", "track-filmstrip"])).min(1).optional(),
19068
+ deviceIds: array(number().int()).min(1).optional(),
19069
+ restart: boolean().optional(),
19070
+ pageSize: number().int().min(50).max(5e3).optional(),
19071
+ maxRowsPerDevice: number().int().min(1).max(5e5).optional(),
19072
+ maxReclaimPerDevice: number().int().min(1).max(5e5).optional(),
19073
+ maxBytesPerRun: number().int().min(1).optional(),
19074
+ budgetMinutes: number().int().min(1).max(720).optional(),
19075
+ throttleBytesPerSec: number().int().min(64 * 1024).optional(),
19076
+ graceMinutes: number().int().min(1).max(10080).optional()
19077
+ });
19078
+ var MediaReclaimStatusSchema = object({
19079
+ running: boolean(),
19080
+ mode: _enum(["report", "reclaim"]).nullable(),
19081
+ totalExamined: number(),
19082
+ totalEligible: number(),
19083
+ totalReclaimed: number(),
19084
+ totalBytesReclaimed: number(),
19085
+ totalRefused: number(),
19086
+ /** Device+scope windows finished in this pass. */
19087
+ devicesDone: number(),
19088
+ complete: boolean().nullable(),
19089
+ startedAtMs: number().nullable(),
19090
+ finishedAtMs: number().nullable(),
19091
+ error: string().nullable()
19092
+ });
19016
19093
  var ReplayFrameInputSchema = object({
19017
19094
  timestamp: number(),
19018
19095
  frame: PipelineRunResultBridge
@@ -19051,10 +19128,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19051
19128
  * stationary registry). Default false: the timeline lists passages,
19052
19129
  * not parking records (operator decision, 2026-08-15). */
19053
19130
  includeStationary: boolean().optional()
19054
- }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(ListGroupsQueryInput, ListGroupsPageSchema), method(object({
19055
- deviceId: number(),
19056
- groupId: string().min(1)
19057
- }), AnalyticsGroupDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
19131
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
19058
19132
  kind: "mutation",
19059
19133
  auth: "admin"
19060
19134
  }), 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({
@@ -19154,6 +19228,12 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19154
19228
  }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
19155
19229
  kind: "query",
19156
19230
  auth: "admin"
19231
+ }), method(MediaReclaimInputSchema, MediaReclaimStartResultSchema, {
19232
+ kind: "mutation",
19233
+ auth: "admin"
19234
+ }), method(object({}), MediaReclaimStatusSchema, {
19235
+ kind: "query",
19236
+ auth: "admin"
19157
19237
  }), method(object({ deviceIds: array(number()).optional() }), TrainingExportSummarySchema, {
19158
19238
  kind: "query",
19159
19239
  auth: "admin"
@@ -21124,7 +21204,13 @@ method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin"
21124
21204
  }), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
21125
21205
  kind: "mutation",
21126
21206
  auth: "admin"
21127
- });
21207
+ }), method(StorageCleanupInputSchema, object({ jobId: string() }), {
21208
+ kind: "mutation",
21209
+ auth: "admin"
21210
+ }), method(StorageCleanupStatusInputSchema, StorageCleanupJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
21211
+ kind: "mutation",
21212
+ auth: "admin"
21213
+ }), method(object({}), array(StorageMigrationJobSchema).readonly(), { auth: "admin" });
21128
21214
  var ProviderInfoSchema = discriminatedUnion("shouldSaveDiskSpace", [object({
21129
21215
  providerId: string().min(1),
21130
21216
  displayName: string().min(1),
@@ -26562,6 +26648,33 @@ var RecordingRebalanceInputSchema = object({
26562
26648
  minMoveGb: number().min(0).optional()
26563
26649
  });
26564
26650
  /**
26651
+ * Operator-facing placement of one camera onto a recordings location.
26652
+ *
26653
+ * `pinLocationId` is the operator instruction: a location id, or `null` for
26654
+ * Auto (the planner may move this camera). `locationId` is where high/mid
26655
+ * currently write — the plan, which may disagree with the pin when Auto.
26656
+ */
26657
+ var RecordingDevicePlacementSchema = object({
26658
+ deviceId: number().int(),
26659
+ profile: string(),
26660
+ locationId: string()
26661
+ });
26662
+ var RecordingDevicePinSchema = object({
26663
+ deviceId: number().int(),
26664
+ /** Recordings-class location this camera is pinned to. */
26665
+ locationId: string()
26666
+ });
26667
+ var RecordingPlacementViewSchema = object({
26668
+ assignments: array(RecordingDevicePlacementSchema),
26669
+ pins: array(RecordingDevicePinSchema),
26670
+ defaultLocations: record(string(), string())
26671
+ });
26672
+ var RecordingSetDevicePlacementInputSchema = object({
26673
+ deviceId: number().int(),
26674
+ /** `null` = Auto. Otherwise a `recordings:*` location id. */
26675
+ locationId: string().nullable()
26676
+ });
26677
+ /**
26565
26678
  * Result of locating footage at a wall-clock instant for one device/profile.
26566
26679
  * `segment` carries the covering segment's window; `gap` reports the forward
26567
26680
  * nearest covered edge (`null` past the end of footage / when none exists)
@@ -26787,6 +26900,12 @@ method(object({
26787
26900
  }), method(RecordingRebalanceInputSchema, RecordingRebalancePlanSchema, {
26788
26901
  kind: "mutation",
26789
26902
  auth: "admin"
26903
+ }), method(object({}), RecordingPlacementViewSchema, {
26904
+ kind: "query",
26905
+ auth: "admin"
26906
+ }), method(RecordingSetDevicePlacementInputSchema, object({ ok: literal(true) }), {
26907
+ kind: "mutation",
26908
+ auth: "admin"
26790
26909
  });
26791
26910
  /**
26792
26911
  * `recording-export` cap — render a footage time range into a single downloadable
@@ -30157,6 +30276,12 @@ Object.freeze({
30157
30276
  addonId: null,
30158
30277
  access: "delete"
30159
30278
  },
30279
+ "deviceManager.renameLocation": {
30280
+ capName: "device-manager",
30281
+ capScope: "system",
30282
+ addonId: null,
30283
+ access: "create"
30284
+ },
30160
30285
  "deviceManager.runDeviceAction": {
30161
30286
  capName: "device-manager",
30162
30287
  capScope: "system",
@@ -31849,19 +31974,19 @@ Object.freeze({
31849
31974
  addonId: null,
31850
31975
  access: "view"
31851
31976
  },
31852
- "pipelineAnalytics.getGroup": {
31977
+ "pipelineAnalytics.getKeyEvents": {
31853
31978
  capName: "pipeline-analytics",
31854
31979
  capScope: "device",
31855
31980
  addonId: null,
31856
31981
  access: "view"
31857
31982
  },
31858
- "pipelineAnalytics.getKeyEvents": {
31983
+ "pipelineAnalytics.getKeyEventsBatch": {
31859
31984
  capName: "pipeline-analytics",
31860
31985
  capScope: "device",
31861
31986
  addonId: null,
31862
31987
  access: "view"
31863
31988
  },
31864
- "pipelineAnalytics.getKeyEventsBatch": {
31989
+ "pipelineAnalytics.getMediaReclaimStatus": {
31865
31990
  capName: "pipeline-analytics",
31866
31991
  capScope: "device",
31867
31992
  addonId: null,
@@ -31951,12 +32076,6 @@ Object.freeze({
31951
32076
  addonId: null,
31952
32077
  access: "view"
31953
32078
  },
31954
- "pipelineAnalytics.listGroups": {
31955
- capName: "pipeline-analytics",
31956
- capScope: "device",
31957
- addonId: null,
31958
- access: "view"
31959
- },
31960
32079
  "pipelineAnalytics.listOpsLog": {
31961
32080
  capName: "pipeline-analytics",
31962
32081
  capScope: "device",
@@ -32041,6 +32160,12 @@ Object.freeze({
32041
32160
  addonId: null,
32042
32161
  access: "create"
32043
32162
  },
32163
+ "pipelineAnalytics.reclaimDebugMedia": {
32164
+ capName: "pipeline-analytics",
32165
+ capScope: "device",
32166
+ addonId: null,
32167
+ access: "create"
32168
+ },
32044
32169
  "pipelineAnalytics.reconcileFromDisk": {
32045
32170
  capName: "pipeline-analytics",
32046
32171
  capScope: "device",
@@ -32965,6 +33090,12 @@ Object.freeze({
32965
33090
  addonId: null,
32966
33091
  access: "view"
32967
33092
  },
33093
+ "recording.getPlacement": {
33094
+ capName: "recording",
33095
+ capScope: "system",
33096
+ addonId: null,
33097
+ access: "view"
33098
+ },
32968
33099
  "recording.getPlaybackManifest": {
32969
33100
  capName: "recording",
32970
33101
  capScope: "system",
@@ -33091,6 +33222,12 @@ Object.freeze({
33091
33222
  addonId: null,
33092
33223
  access: "create"
33093
33224
  },
33225
+ "recording.setDevicePlacement": {
33226
+ capName: "recording",
33227
+ capScope: "system",
33228
+ addonId: null,
33229
+ access: "create"
33230
+ },
33094
33231
  "recording.startStorageMigrationMove": {
33095
33232
  capName: "recording",
33096
33233
  capScope: "system",
@@ -33535,12 +33672,36 @@ Object.freeze({
33535
33672
  addonId: null,
33536
33673
  access: "create"
33537
33674
  },
33675
+ "storageMigration.cleanupCancel": {
33676
+ capName: "storage-migration",
33677
+ capScope: "system",
33678
+ addonId: null,
33679
+ access: "create"
33680
+ },
33681
+ "storageMigration.cleanupStart": {
33682
+ capName: "storage-migration",
33683
+ capScope: "system",
33684
+ addonId: null,
33685
+ access: "create"
33686
+ },
33687
+ "storageMigration.cleanupStatus": {
33688
+ capName: "storage-migration",
33689
+ capScope: "system",
33690
+ addonId: null,
33691
+ access: "view"
33692
+ },
33538
33693
  "storageMigration.drain": {
33539
33694
  capName: "storage-migration",
33540
33695
  capScope: "system",
33541
33696
  addonId: null,
33542
33697
  access: "create"
33543
33698
  },
33699
+ "storageMigration.history": {
33700
+ capName: "storage-migration",
33701
+ capScope: "system",
33702
+ addonId: null,
33703
+ access: "view"
33704
+ },
33544
33705
  "storageMigration.movers": {
33545
33706
  capName: "storage-migration",
33546
33707
  capScope: "system",
@@ -35537,11 +35698,6 @@ Object.freeze({
35537
35698
  form: "single",
35538
35699
  optional: true
35539
35700
  }],
35540
- "pipelineAnalytics.getGroup": [{
35541
- name: "deviceId",
35542
- form: "single",
35543
- optional: false
35544
- }],
35545
35701
  "pipelineAnalytics.getKeyEvents": [{
35546
35702
  name: "deviceId",
35547
35703
  form: "single",
@@ -35607,11 +35763,6 @@ Object.freeze({
35607
35763
  form: "single",
35608
35764
  optional: false
35609
35765
  }],
35610
- "pipelineAnalytics.listGroups": [{
35611
- name: "deviceIds",
35612
- form: "array",
35613
- optional: false
35614
- }],
35615
35766
  "pipelineAnalytics.listOpsLog": [{
35616
35767
  name: "deviceId",
35617
35768
  form: "single",
@@ -35657,6 +35808,11 @@ Object.freeze({
35657
35808
  form: "single",
35658
35809
  optional: true
35659
35810
  }],
35811
+ "pipelineAnalytics.reclaimDebugMedia": [{
35812
+ name: "deviceIds",
35813
+ form: "array",
35814
+ optional: true
35815
+ }],
35660
35816
  "pipelineAnalytics.reconcileFromDisk": [{
35661
35817
  name: "deviceId",
35662
35818
  form: "single",
@@ -36022,6 +36178,11 @@ Object.freeze({
36022
36178
  form: "single",
36023
36179
  optional: false
36024
36180
  }],
36181
+ "recording.setDevicePlacement": [{
36182
+ name: "deviceId",
36183
+ form: "single",
36184
+ optional: false
36185
+ }],
36025
36186
  "recording.startStorageMigrationMove": [{
36026
36187
  name: "deviceId",
36027
36188
  form: "single",
package/dist/smb.addon.js CHANGED
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_shared = require("./shared-Bwt_Ye8T.js");
5
+ const require_shared = require("./shared-BAungtYx.js");
6
6
  let node_crypto = require("node:crypto");
7
7
  let node_path = require("node:path");
8
8
  node_path = require_shared.__toESM(node_path);
@@ -1,4 +1,4 @@
1
- import { c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, s as storageProviderCapability } from "./shared-CQEWmUcA.mjs";
1
+ import { c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, s as storageProviderCapability } from "./shared-Da9FHywp.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import * as path from "node:path";
4
4
  import * as fsp from "node:fs/promises";
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_shared = require("./shared-Bwt_Ye8T.js");
5
+ const require_shared = require("./shared-BAungtYx.js");
6
6
  let node_stream = require("node:stream");
7
7
  let webdav = require("webdav");
8
8
  //#region src/providers/webdav/webdav-config-schema.ts
@@ -1,4 +1,4 @@
1
- import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-CQEWmUcA.mjs";
1
+ import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-Da9FHywp.mjs";
2
2
  import { PassThrough } from "node:stream";
3
3
  import { AuthType, createClient } from "webdav";
4
4
  //#region src/providers/webdav/webdav-config-schema.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-remote-storage",
3
- "version": "1.2.48",
3
+ "version": "1.2.49",
4
4
  "description": "Remote storage providers (SFTP, S3, WebDAV, SMB) — unifies remote backends behind the storage-provider cap",
5
5
  "keywords": [
6
6
  "camstack",