@camstack/addon-remote-storage 1.2.48 → 1.2.50

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-BOy-Ilbo.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-BKw72Pim.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-BOy-Ilbo.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-BKw72Pim.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
@@ -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()
@@ -15480,6 +15558,8 @@ var NcSystemEventKindSchema = _enum([
15480
15558
  "device-offline",
15481
15559
  "device-disabled",
15482
15560
  "device-enabled",
15561
+ "device-battery-low",
15562
+ "device-battery-normal",
15483
15563
  "stream-online",
15484
15564
  "stream-offline",
15485
15565
  "node-online",
@@ -18698,46 +18778,6 @@ var RecentTracksPageSchema = object({
18698
18778
  /** Cursor for the next page, or null when this page is the last. */
18699
18779
  nextCursor: string().nullable()
18700
18780
  });
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
18781
  var KEY_EVENTS_DEFAULT_LIMIT = 50;
18742
18782
  var KEY_EVENTS_MAX_LIMIT = 200;
18743
18783
  var KeyEventQueryInput = object({
@@ -18841,9 +18881,7 @@ var TrackCascadeCountsSchema = object({
18841
18881
  /** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
18842
18882
  plates: number().int(),
18843
18883
  /** 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()
18884
+ embeddings: number().int()
18847
18885
  });
18848
18886
  /** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
18849
18887
  var DiskReconcileCountsSchema = object({
@@ -19013,6 +19051,47 @@ var RebuildStatusSchema = object({
19013
19051
  /** Present when the pass ended by throwing. */
19014
19052
  error: string().nullable()
19015
19053
  });
19054
+ /**
19055
+ * Acknowledgement that a debug-media reclaim STARTED.
19056
+ *
19057
+ * The pass is paced at ~2 MB/s over a standing 100 GB — tens of minutes — so
19058
+ * it runs detached and this returns immediately. Awaiting it is how the
19059
+ * `addons.custom` door hit the 60 s UDS deadline while the walk carried on
19060
+ * with no status. Poll {@link pipelineAnalyticsCapability.methods.getMediaReclaimStatus}.
19061
+ */
19062
+ var MediaReclaimStartResultSchema = object({
19063
+ started: boolean(),
19064
+ /** True when a pass was already running; the new request is ignored. */
19065
+ alreadyRunning: boolean()
19066
+ });
19067
+ var MediaReclaimInputSchema = object({
19068
+ mode: _enum(["report", "reclaim"]).default("report"),
19069
+ scopes: array(_enum(["motion-still", "track-filmstrip"])).min(1).optional(),
19070
+ deviceIds: array(number().int()).min(1).optional(),
19071
+ restart: boolean().optional(),
19072
+ pageSize: number().int().min(50).max(5e3).optional(),
19073
+ maxRowsPerDevice: number().int().min(1).max(5e5).optional(),
19074
+ maxReclaimPerDevice: number().int().min(1).max(5e5).optional(),
19075
+ maxBytesPerRun: number().int().min(1).optional(),
19076
+ budgetMinutes: number().int().min(1).max(720).optional(),
19077
+ throttleBytesPerSec: number().int().min(64 * 1024).optional(),
19078
+ graceMinutes: number().int().min(1).max(10080).optional()
19079
+ });
19080
+ var MediaReclaimStatusSchema = object({
19081
+ running: boolean(),
19082
+ mode: _enum(["report", "reclaim"]).nullable(),
19083
+ totalExamined: number(),
19084
+ totalEligible: number(),
19085
+ totalReclaimed: number(),
19086
+ totalBytesReclaimed: number(),
19087
+ totalRefused: number(),
19088
+ /** Device+scope windows finished in this pass. */
19089
+ devicesDone: number(),
19090
+ complete: boolean().nullable(),
19091
+ startedAtMs: number().nullable(),
19092
+ finishedAtMs: number().nullable(),
19093
+ error: string().nullable()
19094
+ });
19016
19095
  var ReplayFrameInputSchema = object({
19017
19096
  timestamp: number(),
19018
19097
  frame: PipelineRunResultBridge
@@ -19051,10 +19130,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19051
19130
  * stationary registry). Default false: the timeline lists passages,
19052
19131
  * not parking records (operator decision, 2026-08-15). */
19053
19132
  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(), {
19133
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
19058
19134
  kind: "mutation",
19059
19135
  auth: "admin"
19060
19136
  }), 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 +19230,12 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19154
19230
  }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
19155
19231
  kind: "query",
19156
19232
  auth: "admin"
19233
+ }), method(MediaReclaimInputSchema, MediaReclaimStartResultSchema, {
19234
+ kind: "mutation",
19235
+ auth: "admin"
19236
+ }), method(object({}), MediaReclaimStatusSchema, {
19237
+ kind: "query",
19238
+ auth: "admin"
19157
19239
  }), method(object({ deviceIds: array(number()).optional() }), TrainingExportSummarySchema, {
19158
19240
  kind: "query",
19159
19241
  auth: "admin"
@@ -21124,7 +21206,13 @@ method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin"
21124
21206
  }), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
21125
21207
  kind: "mutation",
21126
21208
  auth: "admin"
21127
- });
21209
+ }), method(StorageCleanupInputSchema, object({ jobId: string() }), {
21210
+ kind: "mutation",
21211
+ auth: "admin"
21212
+ }), method(StorageCleanupStatusInputSchema, StorageCleanupJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
21213
+ kind: "mutation",
21214
+ auth: "admin"
21215
+ }), method(object({}), array(StorageMigrationJobSchema).readonly(), { auth: "admin" });
21128
21216
  var ProviderInfoSchema = discriminatedUnion("shouldSaveDiskSpace", [object({
21129
21217
  providerId: string().min(1),
21130
21218
  displayName: string().min(1),
@@ -26562,6 +26650,33 @@ var RecordingRebalanceInputSchema = object({
26562
26650
  minMoveGb: number().min(0).optional()
26563
26651
  });
26564
26652
  /**
26653
+ * Operator-facing placement of one camera onto a recordings location.
26654
+ *
26655
+ * `pinLocationId` is the operator instruction: a location id, or `null` for
26656
+ * Auto (the planner may move this camera). `locationId` is where high/mid
26657
+ * currently write — the plan, which may disagree with the pin when Auto.
26658
+ */
26659
+ var RecordingDevicePlacementSchema = object({
26660
+ deviceId: number().int(),
26661
+ profile: string(),
26662
+ locationId: string()
26663
+ });
26664
+ var RecordingDevicePinSchema = object({
26665
+ deviceId: number().int(),
26666
+ /** Recordings-class location this camera is pinned to. */
26667
+ locationId: string()
26668
+ });
26669
+ var RecordingPlacementViewSchema = object({
26670
+ assignments: array(RecordingDevicePlacementSchema),
26671
+ pins: array(RecordingDevicePinSchema),
26672
+ defaultLocations: record(string(), string())
26673
+ });
26674
+ var RecordingSetDevicePlacementInputSchema = object({
26675
+ deviceId: number().int(),
26676
+ /** `null` = Auto. Otherwise a `recordings:*` location id. */
26677
+ locationId: string().nullable()
26678
+ });
26679
+ /**
26565
26680
  * Result of locating footage at a wall-clock instant for one device/profile.
26566
26681
  * `segment` carries the covering segment's window; `gap` reports the forward
26567
26682
  * nearest covered edge (`null` past the end of footage / when none exists)
@@ -26787,6 +26902,12 @@ method(object({
26787
26902
  }), method(RecordingRebalanceInputSchema, RecordingRebalancePlanSchema, {
26788
26903
  kind: "mutation",
26789
26904
  auth: "admin"
26905
+ }), method(object({}), RecordingPlacementViewSchema, {
26906
+ kind: "query",
26907
+ auth: "admin"
26908
+ }), method(RecordingSetDevicePlacementInputSchema, object({ ok: literal(true) }), {
26909
+ kind: "mutation",
26910
+ auth: "admin"
26790
26911
  });
26791
26912
  /**
26792
26913
  * `recording-export` cap — render a footage time range into a single downloadable
@@ -30157,6 +30278,12 @@ Object.freeze({
30157
30278
  addonId: null,
30158
30279
  access: "delete"
30159
30280
  },
30281
+ "deviceManager.renameLocation": {
30282
+ capName: "device-manager",
30283
+ capScope: "system",
30284
+ addonId: null,
30285
+ access: "create"
30286
+ },
30160
30287
  "deviceManager.runDeviceAction": {
30161
30288
  capName: "device-manager",
30162
30289
  capScope: "system",
@@ -31849,19 +31976,19 @@ Object.freeze({
31849
31976
  addonId: null,
31850
31977
  access: "view"
31851
31978
  },
31852
- "pipelineAnalytics.getGroup": {
31979
+ "pipelineAnalytics.getKeyEvents": {
31853
31980
  capName: "pipeline-analytics",
31854
31981
  capScope: "device",
31855
31982
  addonId: null,
31856
31983
  access: "view"
31857
31984
  },
31858
- "pipelineAnalytics.getKeyEvents": {
31985
+ "pipelineAnalytics.getKeyEventsBatch": {
31859
31986
  capName: "pipeline-analytics",
31860
31987
  capScope: "device",
31861
31988
  addonId: null,
31862
31989
  access: "view"
31863
31990
  },
31864
- "pipelineAnalytics.getKeyEventsBatch": {
31991
+ "pipelineAnalytics.getMediaReclaimStatus": {
31865
31992
  capName: "pipeline-analytics",
31866
31993
  capScope: "device",
31867
31994
  addonId: null,
@@ -31951,12 +32078,6 @@ Object.freeze({
31951
32078
  addonId: null,
31952
32079
  access: "view"
31953
32080
  },
31954
- "pipelineAnalytics.listGroups": {
31955
- capName: "pipeline-analytics",
31956
- capScope: "device",
31957
- addonId: null,
31958
- access: "view"
31959
- },
31960
32081
  "pipelineAnalytics.listOpsLog": {
31961
32082
  capName: "pipeline-analytics",
31962
32083
  capScope: "device",
@@ -32041,6 +32162,12 @@ Object.freeze({
32041
32162
  addonId: null,
32042
32163
  access: "create"
32043
32164
  },
32165
+ "pipelineAnalytics.reclaimDebugMedia": {
32166
+ capName: "pipeline-analytics",
32167
+ capScope: "device",
32168
+ addonId: null,
32169
+ access: "create"
32170
+ },
32044
32171
  "pipelineAnalytics.reconcileFromDisk": {
32045
32172
  capName: "pipeline-analytics",
32046
32173
  capScope: "device",
@@ -32965,6 +33092,12 @@ Object.freeze({
32965
33092
  addonId: null,
32966
33093
  access: "view"
32967
33094
  },
33095
+ "recording.getPlacement": {
33096
+ capName: "recording",
33097
+ capScope: "system",
33098
+ addonId: null,
33099
+ access: "view"
33100
+ },
32968
33101
  "recording.getPlaybackManifest": {
32969
33102
  capName: "recording",
32970
33103
  capScope: "system",
@@ -33091,6 +33224,12 @@ Object.freeze({
33091
33224
  addonId: null,
33092
33225
  access: "create"
33093
33226
  },
33227
+ "recording.setDevicePlacement": {
33228
+ capName: "recording",
33229
+ capScope: "system",
33230
+ addonId: null,
33231
+ access: "create"
33232
+ },
33094
33233
  "recording.startStorageMigrationMove": {
33095
33234
  capName: "recording",
33096
33235
  capScope: "system",
@@ -33535,12 +33674,36 @@ Object.freeze({
33535
33674
  addonId: null,
33536
33675
  access: "create"
33537
33676
  },
33677
+ "storageMigration.cleanupCancel": {
33678
+ capName: "storage-migration",
33679
+ capScope: "system",
33680
+ addonId: null,
33681
+ access: "create"
33682
+ },
33683
+ "storageMigration.cleanupStart": {
33684
+ capName: "storage-migration",
33685
+ capScope: "system",
33686
+ addonId: null,
33687
+ access: "create"
33688
+ },
33689
+ "storageMigration.cleanupStatus": {
33690
+ capName: "storage-migration",
33691
+ capScope: "system",
33692
+ addonId: null,
33693
+ access: "view"
33694
+ },
33538
33695
  "storageMigration.drain": {
33539
33696
  capName: "storage-migration",
33540
33697
  capScope: "system",
33541
33698
  addonId: null,
33542
33699
  access: "create"
33543
33700
  },
33701
+ "storageMigration.history": {
33702
+ capName: "storage-migration",
33703
+ capScope: "system",
33704
+ addonId: null,
33705
+ access: "view"
33706
+ },
33544
33707
  "storageMigration.movers": {
33545
33708
  capName: "storage-migration",
33546
33709
  capScope: "system",
@@ -35537,11 +35700,6 @@ Object.freeze({
35537
35700
  form: "single",
35538
35701
  optional: true
35539
35702
  }],
35540
- "pipelineAnalytics.getGroup": [{
35541
- name: "deviceId",
35542
- form: "single",
35543
- optional: false
35544
- }],
35545
35703
  "pipelineAnalytics.getKeyEvents": [{
35546
35704
  name: "deviceId",
35547
35705
  form: "single",
@@ -35607,11 +35765,6 @@ Object.freeze({
35607
35765
  form: "single",
35608
35766
  optional: false
35609
35767
  }],
35610
- "pipelineAnalytics.listGroups": [{
35611
- name: "deviceIds",
35612
- form: "array",
35613
- optional: false
35614
- }],
35615
35768
  "pipelineAnalytics.listOpsLog": [{
35616
35769
  name: "deviceId",
35617
35770
  form: "single",
@@ -35657,6 +35810,11 @@ Object.freeze({
35657
35810
  form: "single",
35658
35811
  optional: true
35659
35812
  }],
35813
+ "pipelineAnalytics.reclaimDebugMedia": [{
35814
+ name: "deviceIds",
35815
+ form: "array",
35816
+ optional: true
35817
+ }],
35660
35818
  "pipelineAnalytics.reconcileFromDisk": [{
35661
35819
  name: "deviceId",
35662
35820
  form: "single",
@@ -36022,6 +36180,11 @@ Object.freeze({
36022
36180
  form: "single",
36023
36181
  optional: false
36024
36182
  }],
36183
+ "recording.setDevicePlacement": [{
36184
+ name: "deviceId",
36185
+ form: "single",
36186
+ optional: false
36187
+ }],
36025
36188
  "recording.startStorageMigrationMove": [{
36026
36189
  name: "deviceId",
36027
36190
  form: "single",
@@ -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()
@@ -15503,6 +15581,8 @@ var NcSystemEventKindSchema = _enum([
15503
15581
  "device-offline",
15504
15582
  "device-disabled",
15505
15583
  "device-enabled",
15584
+ "device-battery-low",
15585
+ "device-battery-normal",
15506
15586
  "stream-online",
15507
15587
  "stream-offline",
15508
15588
  "node-online",
@@ -18721,46 +18801,6 @@ var RecentTracksPageSchema = object({
18721
18801
  /** Cursor for the next page, or null when this page is the last. */
18722
18802
  nextCursor: string().nullable()
18723
18803
  });
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
18804
  var KEY_EVENTS_DEFAULT_LIMIT = 50;
18765
18805
  var KEY_EVENTS_MAX_LIMIT = 200;
18766
18806
  var KeyEventQueryInput = object({
@@ -18864,9 +18904,7 @@ var TrackCascadeCountsSchema = object({
18864
18904
  /** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
18865
18905
  plates: number().int(),
18866
18906
  /** 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()
18907
+ embeddings: number().int()
18870
18908
  });
18871
18909
  /** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
18872
18910
  var DiskReconcileCountsSchema = object({
@@ -19036,6 +19074,47 @@ var RebuildStatusSchema = object({
19036
19074
  /** Present when the pass ended by throwing. */
19037
19075
  error: string().nullable()
19038
19076
  });
19077
+ /**
19078
+ * Acknowledgement that a debug-media reclaim STARTED.
19079
+ *
19080
+ * The pass is paced at ~2 MB/s over a standing 100 GB — tens of minutes — so
19081
+ * it runs detached and this returns immediately. Awaiting it is how the
19082
+ * `addons.custom` door hit the 60 s UDS deadline while the walk carried on
19083
+ * with no status. Poll {@link pipelineAnalyticsCapability.methods.getMediaReclaimStatus}.
19084
+ */
19085
+ var MediaReclaimStartResultSchema = object({
19086
+ started: boolean(),
19087
+ /** True when a pass was already running; the new request is ignored. */
19088
+ alreadyRunning: boolean()
19089
+ });
19090
+ var MediaReclaimInputSchema = object({
19091
+ mode: _enum(["report", "reclaim"]).default("report"),
19092
+ scopes: array(_enum(["motion-still", "track-filmstrip"])).min(1).optional(),
19093
+ deviceIds: array(number().int()).min(1).optional(),
19094
+ restart: boolean().optional(),
19095
+ pageSize: number().int().min(50).max(5e3).optional(),
19096
+ maxRowsPerDevice: number().int().min(1).max(5e5).optional(),
19097
+ maxReclaimPerDevice: number().int().min(1).max(5e5).optional(),
19098
+ maxBytesPerRun: number().int().min(1).optional(),
19099
+ budgetMinutes: number().int().min(1).max(720).optional(),
19100
+ throttleBytesPerSec: number().int().min(64 * 1024).optional(),
19101
+ graceMinutes: number().int().min(1).max(10080).optional()
19102
+ });
19103
+ var MediaReclaimStatusSchema = object({
19104
+ running: boolean(),
19105
+ mode: _enum(["report", "reclaim"]).nullable(),
19106
+ totalExamined: number(),
19107
+ totalEligible: number(),
19108
+ totalReclaimed: number(),
19109
+ totalBytesReclaimed: number(),
19110
+ totalRefused: number(),
19111
+ /** Device+scope windows finished in this pass. */
19112
+ devicesDone: number(),
19113
+ complete: boolean().nullable(),
19114
+ startedAtMs: number().nullable(),
19115
+ finishedAtMs: number().nullable(),
19116
+ error: string().nullable()
19117
+ });
19039
19118
  var ReplayFrameInputSchema = object({
19040
19119
  timestamp: number(),
19041
19120
  frame: PipelineRunResultBridge
@@ -19074,10 +19153,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19074
19153
  * stationary registry). Default false: the timeline lists passages,
19075
19154
  * not parking records (operator decision, 2026-08-15). */
19076
19155
  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(), {
19156
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
19081
19157
  kind: "mutation",
19082
19158
  auth: "admin"
19083
19159
  }), 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 +19253,12 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19177
19253
  }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
19178
19254
  kind: "query",
19179
19255
  auth: "admin"
19256
+ }), method(MediaReclaimInputSchema, MediaReclaimStartResultSchema, {
19257
+ kind: "mutation",
19258
+ auth: "admin"
19259
+ }), method(object({}), MediaReclaimStatusSchema, {
19260
+ kind: "query",
19261
+ auth: "admin"
19180
19262
  }), method(object({ deviceIds: array(number()).optional() }), TrainingExportSummarySchema, {
19181
19263
  kind: "query",
19182
19264
  auth: "admin"
@@ -21147,7 +21229,13 @@ method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin"
21147
21229
  }), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
21148
21230
  kind: "mutation",
21149
21231
  auth: "admin"
21150
- });
21232
+ }), method(StorageCleanupInputSchema, object({ jobId: string() }), {
21233
+ kind: "mutation",
21234
+ auth: "admin"
21235
+ }), method(StorageCleanupStatusInputSchema, StorageCleanupJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
21236
+ kind: "mutation",
21237
+ auth: "admin"
21238
+ }), method(object({}), array(StorageMigrationJobSchema).readonly(), { auth: "admin" });
21151
21239
  var ProviderInfoSchema = discriminatedUnion("shouldSaveDiskSpace", [object({
21152
21240
  providerId: string().min(1),
21153
21241
  displayName: string().min(1),
@@ -26585,6 +26673,33 @@ var RecordingRebalanceInputSchema = object({
26585
26673
  minMoveGb: number().min(0).optional()
26586
26674
  });
26587
26675
  /**
26676
+ * Operator-facing placement of one camera onto a recordings location.
26677
+ *
26678
+ * `pinLocationId` is the operator instruction: a location id, or `null` for
26679
+ * Auto (the planner may move this camera). `locationId` is where high/mid
26680
+ * currently write — the plan, which may disagree with the pin when Auto.
26681
+ */
26682
+ var RecordingDevicePlacementSchema = object({
26683
+ deviceId: number().int(),
26684
+ profile: string(),
26685
+ locationId: string()
26686
+ });
26687
+ var RecordingDevicePinSchema = object({
26688
+ deviceId: number().int(),
26689
+ /** Recordings-class location this camera is pinned to. */
26690
+ locationId: string()
26691
+ });
26692
+ var RecordingPlacementViewSchema = object({
26693
+ assignments: array(RecordingDevicePlacementSchema),
26694
+ pins: array(RecordingDevicePinSchema),
26695
+ defaultLocations: record(string(), string())
26696
+ });
26697
+ var RecordingSetDevicePlacementInputSchema = object({
26698
+ deviceId: number().int(),
26699
+ /** `null` = Auto. Otherwise a `recordings:*` location id. */
26700
+ locationId: string().nullable()
26701
+ });
26702
+ /**
26588
26703
  * Result of locating footage at a wall-clock instant for one device/profile.
26589
26704
  * `segment` carries the covering segment's window; `gap` reports the forward
26590
26705
  * nearest covered edge (`null` past the end of footage / when none exists)
@@ -26810,6 +26925,12 @@ method(object({
26810
26925
  }), method(RecordingRebalanceInputSchema, RecordingRebalancePlanSchema, {
26811
26926
  kind: "mutation",
26812
26927
  auth: "admin"
26928
+ }), method(object({}), RecordingPlacementViewSchema, {
26929
+ kind: "query",
26930
+ auth: "admin"
26931
+ }), method(RecordingSetDevicePlacementInputSchema, object({ ok: literal(true) }), {
26932
+ kind: "mutation",
26933
+ auth: "admin"
26813
26934
  });
26814
26935
  /**
26815
26936
  * `recording-export` cap — render a footage time range into a single downloadable
@@ -30180,6 +30301,12 @@ Object.freeze({
30180
30301
  addonId: null,
30181
30302
  access: "delete"
30182
30303
  },
30304
+ "deviceManager.renameLocation": {
30305
+ capName: "device-manager",
30306
+ capScope: "system",
30307
+ addonId: null,
30308
+ access: "create"
30309
+ },
30183
30310
  "deviceManager.runDeviceAction": {
30184
30311
  capName: "device-manager",
30185
30312
  capScope: "system",
@@ -31872,19 +31999,19 @@ Object.freeze({
31872
31999
  addonId: null,
31873
32000
  access: "view"
31874
32001
  },
31875
- "pipelineAnalytics.getGroup": {
32002
+ "pipelineAnalytics.getKeyEvents": {
31876
32003
  capName: "pipeline-analytics",
31877
32004
  capScope: "device",
31878
32005
  addonId: null,
31879
32006
  access: "view"
31880
32007
  },
31881
- "pipelineAnalytics.getKeyEvents": {
32008
+ "pipelineAnalytics.getKeyEventsBatch": {
31882
32009
  capName: "pipeline-analytics",
31883
32010
  capScope: "device",
31884
32011
  addonId: null,
31885
32012
  access: "view"
31886
32013
  },
31887
- "pipelineAnalytics.getKeyEventsBatch": {
32014
+ "pipelineAnalytics.getMediaReclaimStatus": {
31888
32015
  capName: "pipeline-analytics",
31889
32016
  capScope: "device",
31890
32017
  addonId: null,
@@ -31974,12 +32101,6 @@ Object.freeze({
31974
32101
  addonId: null,
31975
32102
  access: "view"
31976
32103
  },
31977
- "pipelineAnalytics.listGroups": {
31978
- capName: "pipeline-analytics",
31979
- capScope: "device",
31980
- addonId: null,
31981
- access: "view"
31982
- },
31983
32104
  "pipelineAnalytics.listOpsLog": {
31984
32105
  capName: "pipeline-analytics",
31985
32106
  capScope: "device",
@@ -32064,6 +32185,12 @@ Object.freeze({
32064
32185
  addonId: null,
32065
32186
  access: "create"
32066
32187
  },
32188
+ "pipelineAnalytics.reclaimDebugMedia": {
32189
+ capName: "pipeline-analytics",
32190
+ capScope: "device",
32191
+ addonId: null,
32192
+ access: "create"
32193
+ },
32067
32194
  "pipelineAnalytics.reconcileFromDisk": {
32068
32195
  capName: "pipeline-analytics",
32069
32196
  capScope: "device",
@@ -32988,6 +33115,12 @@ Object.freeze({
32988
33115
  addonId: null,
32989
33116
  access: "view"
32990
33117
  },
33118
+ "recording.getPlacement": {
33119
+ capName: "recording",
33120
+ capScope: "system",
33121
+ addonId: null,
33122
+ access: "view"
33123
+ },
32991
33124
  "recording.getPlaybackManifest": {
32992
33125
  capName: "recording",
32993
33126
  capScope: "system",
@@ -33114,6 +33247,12 @@ Object.freeze({
33114
33247
  addonId: null,
33115
33248
  access: "create"
33116
33249
  },
33250
+ "recording.setDevicePlacement": {
33251
+ capName: "recording",
33252
+ capScope: "system",
33253
+ addonId: null,
33254
+ access: "create"
33255
+ },
33117
33256
  "recording.startStorageMigrationMove": {
33118
33257
  capName: "recording",
33119
33258
  capScope: "system",
@@ -33558,12 +33697,36 @@ Object.freeze({
33558
33697
  addonId: null,
33559
33698
  access: "create"
33560
33699
  },
33700
+ "storageMigration.cleanupCancel": {
33701
+ capName: "storage-migration",
33702
+ capScope: "system",
33703
+ addonId: null,
33704
+ access: "create"
33705
+ },
33706
+ "storageMigration.cleanupStart": {
33707
+ capName: "storage-migration",
33708
+ capScope: "system",
33709
+ addonId: null,
33710
+ access: "create"
33711
+ },
33712
+ "storageMigration.cleanupStatus": {
33713
+ capName: "storage-migration",
33714
+ capScope: "system",
33715
+ addonId: null,
33716
+ access: "view"
33717
+ },
33561
33718
  "storageMigration.drain": {
33562
33719
  capName: "storage-migration",
33563
33720
  capScope: "system",
33564
33721
  addonId: null,
33565
33722
  access: "create"
33566
33723
  },
33724
+ "storageMigration.history": {
33725
+ capName: "storage-migration",
33726
+ capScope: "system",
33727
+ addonId: null,
33728
+ access: "view"
33729
+ },
33567
33730
  "storageMigration.movers": {
33568
33731
  capName: "storage-migration",
33569
33732
  capScope: "system",
@@ -35560,11 +35723,6 @@ Object.freeze({
35560
35723
  form: "single",
35561
35724
  optional: true
35562
35725
  }],
35563
- "pipelineAnalytics.getGroup": [{
35564
- name: "deviceId",
35565
- form: "single",
35566
- optional: false
35567
- }],
35568
35726
  "pipelineAnalytics.getKeyEvents": [{
35569
35727
  name: "deviceId",
35570
35728
  form: "single",
@@ -35630,11 +35788,6 @@ Object.freeze({
35630
35788
  form: "single",
35631
35789
  optional: false
35632
35790
  }],
35633
- "pipelineAnalytics.listGroups": [{
35634
- name: "deviceIds",
35635
- form: "array",
35636
- optional: false
35637
- }],
35638
35791
  "pipelineAnalytics.listOpsLog": [{
35639
35792
  name: "deviceId",
35640
35793
  form: "single",
@@ -35680,6 +35833,11 @@ Object.freeze({
35680
35833
  form: "single",
35681
35834
  optional: true
35682
35835
  }],
35836
+ "pipelineAnalytics.reclaimDebugMedia": [{
35837
+ name: "deviceIds",
35838
+ form: "array",
35839
+ optional: true
35840
+ }],
35683
35841
  "pipelineAnalytics.reconcileFromDisk": [{
35684
35842
  name: "deviceId",
35685
35843
  form: "single",
@@ -36045,6 +36203,11 @@ Object.freeze({
36045
36203
  form: "single",
36046
36204
  optional: false
36047
36205
  }],
36206
+ "recording.setDevicePlacement": [{
36207
+ name: "deviceId",
36208
+ form: "single",
36209
+ optional: false
36210
+ }],
36048
36211
  "recording.startStorageMigrationMove": [{
36049
36212
  name: "deviceId",
36050
36213
  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-BOy-Ilbo.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-BKw72Pim.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-BOy-Ilbo.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-BKw72Pim.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.50",
4
4
  "description": "Remote storage providers (SFTP, S3, WebDAV, SMB) — unifies remote backends behind the storage-provider cap",
5
5
  "keywords": [
6
6
  "camstack",