@camstack/addon-tailscale 1.2.49 → 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.
@@ -24,7 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  enumerable: true
25
25
  }) : target, mod));
26
26
  //#endregion
27
- const require_dist = require("../dist-Cv-ufJXF.js");
27
+ const require_dist = require("../dist-v7uK6zeq.js");
28
28
  let node_child_process = require("node:child_process");
29
29
  let node_util = require("node:util");
30
30
  let node_fs = require("node:fs");
@@ -1,4 +1,4 @@
1
- import { a as EventCategory, i as BaseAddon, n as networkAccessCapability, r as BOOT_RECOVERY_BACKOFF_MS, t as meshNetworkCapability } from "../dist-8Fi7VglU.mjs";
1
+ import { a as EventCategory, i as BaseAddon, n as networkAccessCapability, r as BOOT_RECOVERY_BACKOFF_MS, t as meshNetworkCapability } from "../dist-CMpgFoPi.mjs";
2
2
  import { execFile, spawn } from "node:child_process";
3
3
  import { promisify } from "node:util";
4
4
  import * as fs from "node:fs";
@@ -8113,6 +8113,13 @@ var MediaRelocateModeSchema = _enum([
8113
8113
  ]);
8114
8114
  var RelocateMediaInputSchema = object({
8115
8115
  toLocationId: string(),
8116
+ /**
8117
+ * Restrict the pass to rows currently on this location. Omitted / `'*'` =
8118
+ * every row that is not already on `toLocationId` (the historical
8119
+ * behaviour). A named source is what a from→to migration needs: without it
8120
+ * "move events off disk 2" also emptied disk 1.
8121
+ */
8122
+ fromLocationId: string().optional(),
8116
8123
  throttleMbps: number().min(1).max(1e3).optional(),
8117
8124
  /** Omitted = `move`, the pre-existing behaviour. */
8118
8125
  mode: MediaRelocateModeSchema.optional()
@@ -8180,6 +8187,19 @@ var StorageMigrationDestinationsSchema = object({
8180
8187
  galleryMedia: string().min(1).optional()
8181
8188
  }).refine((value) => Object.keys(value).length > 0, { message: "select at least one storage class" });
8182
8189
  /**
8190
+ * Optional named source per class. Omitted = the class's current default
8191
+ * (the historical behaviour). A named source that is NOT the default is a
8192
+ * drain of that disk: bytes move, the default stays, and the source is
8193
+ * disabled when the move finishes.
8194
+ */
8195
+ var StorageMigrationSourcesSchema = object({
8196
+ recordings: string().min(1).optional(),
8197
+ recordingsLow: string().min(1).optional(),
8198
+ eventMedia: string().min(1).optional(),
8199
+ backups: string().min(1).optional(),
8200
+ galleryMedia: string().min(1).optional()
8201
+ }).optional();
8202
+ /**
8183
8203
  * How a migration sequences the cutover against the byte move.
8184
8204
  *
8185
8205
  * - `blocking` — the historical order: pause, move every byte, repoint,
@@ -8201,6 +8221,8 @@ var StorageMigrationModeSchema = _enum(["blocking", "nonBlocking"]);
8201
8221
  /** Shared input for planning and starting an orchestrated storage migration. */
8202
8222
  var StorageMigrationInputSchema = object({
8203
8223
  destinations: StorageMigrationDestinationsSchema,
8224
+ /** Omitted = each class's current default. */
8225
+ sources: StorageMigrationSourcesSchema,
8204
8226
  throttleMbps: number().min(1).max(1e3).optional(),
8205
8227
  /** Omitted = `blocking`, which stays the default. */
8206
8228
  mode: StorageMigrationModeSchema.optional()
@@ -8280,6 +8302,13 @@ var StorageMigrationMoveSchema = object({
8280
8302
  storageClass: StorageMigrationClassSchema,
8281
8303
  fromLocationId: string(),
8282
8304
  toLocationId: string(),
8305
+ /**
8306
+ * True when `from` was NOT the class default at plan time. The move still
8307
+ * copies bytes, but the default is left alone and the source is disabled
8308
+ * once the copy verifies. Absent on jobs planned before this field existed
8309
+ * — those jobs always repointed, which is `false`.
8310
+ */
8311
+ freezeSource: boolean().optional(),
8283
8312
  moverJobId: string().nullable(),
8284
8313
  state: RelocateJobStateSchema.nullable(),
8285
8314
  error: string().nullable(),
@@ -8293,6 +8322,7 @@ var StorageMigrationJobSchema = object({
8293
8322
  * can tell a seconds-long cutover from a thirty-hour one. */
8294
8323
  mode: StorageMigrationModeSchema,
8295
8324
  destinations: StorageMigrationDestinationsSchema,
8325
+ sources: StorageMigrationSourcesSchema,
8296
8326
  throttleMbps: number(),
8297
8327
  moves: array(StorageMigrationMoveSchema),
8298
8328
  pauseLeaseId: string().nullable(),
@@ -8318,6 +8348,7 @@ var StorageMigrationFindingSchema = object({
8318
8348
  });
8319
8349
  var StorageMigrationPlanSchema = object({
8320
8350
  destinations: StorageMigrationDestinationsSchema,
8351
+ sources: StorageMigrationSourcesSchema,
8321
8352
  /** The mode this plan was built for. A plan is only valid for its mode: the
8322
8353
  * `eventMedia` seal gate and the single-cardinality refusal both depend on
8323
8354
  * it. */
@@ -8325,7 +8356,8 @@ var StorageMigrationPlanSchema = object({
8325
8356
  moves: array(object({
8326
8357
  storageClass: StorageMigrationClassSchema,
8327
8358
  fromLocationId: string(),
8328
- toLocationId: string()
8359
+ toLocationId: string(),
8360
+ freezeSource: boolean().optional()
8329
8361
  })),
8330
8362
  findings: array(StorageMigrationFindingSchema)
8331
8363
  });
@@ -8503,10 +8535,51 @@ var LedgerWalkReportSchema = object({
8503
8535
  var RelocatableMediaCountSchema = object({ rows: number().int().nonnegative() }).nullable();
8504
8536
  var RelocatableMediaCountInputSchema = object({
8505
8537
  toLocationId: string().min(1),
8538
+ /** Restrict the count to one source; omitted / `'*'` = every non-target row. */
8539
+ fromLocationId: string().optional(),
8506
8540
  /** Omitted = `move`. */
8507
8541
  mode: MediaRelocateModeSchema.optional()
8508
8542
  });
8509
8543
  /**
8544
+ * Operator cleanup of leftover analytics rows, optional debug media, and
8545
+ * ghost ledger entries on frozen footage locations.
8546
+ *
8547
+ * A pass is tens of minutes on a standing backlog. The hub method RETURNS
8548
+ * `{ jobId }` immediately; progress is `cleanupStatus`. Awaiting the work
8549
+ * is how `addons.custom` hit the 60 s UDS deadline while reclaim continued
8550
+ * with no operator-visible status.
8551
+ */
8552
+ var StorageCleanupPhaseSchema = _enum([
8553
+ "orphans",
8554
+ "debug-media",
8555
+ "ghost-ledger",
8556
+ "done",
8557
+ "failed",
8558
+ "cancelled"
8559
+ ]);
8560
+ var StorageCleanupInputSchema = object({
8561
+ /** Also walk motion stills / track filmstrips. Off by default. */
8562
+ includeDebugMedia: boolean().optional() });
8563
+ var StorageCleanupJobSchema = object({
8564
+ jobId: string(),
8565
+ phase: StorageCleanupPhaseSchema,
8566
+ includeDebugMedia: boolean(),
8567
+ orphansReclaimed: number().int().nonnegative(),
8568
+ orphanBytesReclaimed: number().int().nonnegative(),
8569
+ debugMediaReclaimed: number().int().nonnegative(),
8570
+ debugMediaBytesReclaimed: number().int().nonnegative(),
8571
+ ghostsForgotten: number().int().nonnegative(),
8572
+ ghostBytesForgotten: number().int().nonnegative(),
8573
+ /** Short operator-facing line: current collection, pass, or location. */
8574
+ detail: string().nullable(),
8575
+ cancelRequested: boolean(),
8576
+ startedAt: number(),
8577
+ updatedAt: number(),
8578
+ finishedAt: number().nullable(),
8579
+ error: string().nullable()
8580
+ });
8581
+ var StorageCleanupStatusInputSchema = object({ jobId: string().optional() });
8582
+ /**
8510
8583
  * `StorageLocationType` — an addon-declared id that identifies the *kind* of
8511
8584
  * storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
8512
8585
  * so the persisted record schema and the consumer-facing cap can both consume it
@@ -8534,11 +8607,10 @@ var StorageLocationTypeSchema = string().regex(/^[a-z][a-zA-Z0-9-]*$/);
8534
8607
  * The default location for a type uses `id === <type>:default` by
8535
8608
  * convention (the bare type ref like `'backups'` resolves to it).
8536
8609
  *
8537
- * `isSystem: true` marks a location as orchestrator-seeded and
8538
- * undeletable. The bootstrap-installed defaults (one per type) carry
8539
- * this flag; operator-added locations don't. Editing the config of
8540
- * a system location is allowed (path migration, provider swap) but
8541
- * deleting it is rejected at the cap level.
8610
+ * `isSystem` is a legacy persisted flag. Seed still creates the initial
8611
+ * `<type>:default` locations; the flag is no longer a lock, a badge, or a
8612
+ * prune selector. New writes leave it false. Deletion is gated on uniqueness
8613
+ * / last-enabled, not on this bit.
8542
8614
  */
8543
8615
  var StorageLocationSchema = object({
8544
8616
  id: string().regex(/^[a-z][a-zA-Z0-9-]*:[a-zA-Z0-9-]+$/),
@@ -12800,6 +12872,12 @@ method(object({
12800
12872
  }), _void(), {
12801
12873
  kind: "mutation",
12802
12874
  auth: "admin"
12875
+ }), method(object({
12876
+ from: string(),
12877
+ to: string()
12878
+ }), object({ moved: number() }), {
12879
+ kind: "mutation",
12880
+ auth: "admin"
12803
12881
  }), method(object({
12804
12882
  deviceId: number(),
12805
12883
  disabled: boolean()
@@ -18747,46 +18825,6 @@ var RecentTracksPageSchema = object({
18747
18825
  /** Cursor for the next page, or null when this page is the last. */
18748
18826
  nextCursor: string().nullable()
18749
18827
  });
18750
- var LIST_GROUPS_DEFAULT_LIMIT = 40;
18751
- var LIST_GROUPS_MAX_LIMIT = 100;
18752
- var AnalyticsGroupRecordSchema = object({
18753
- id: string(),
18754
- deviceId: number().int(),
18755
- openedAt: number().int(),
18756
- closedAt: number().int(),
18757
- timestamp: number().int(),
18758
- memberCount: number().int(),
18759
- memberTrackIds: array(string()).readonly(),
18760
- className: string(),
18761
- classes: array(string()).readonly(),
18762
- /** Relative event-media path, or null when the group has no picture yet. */
18763
- mediaUrl: string().nullable(),
18764
- singleton: boolean()
18765
- });
18766
- var AnalyticsGroupMemberSchema = object({
18767
- trackId: string(),
18768
- deviceId: number().int(),
18769
- className: string(),
18770
- firstSeen: number().int(),
18771
- lastSeen: number().int(),
18772
- mediaUrl: string().nullable()
18773
- });
18774
- var AnalyticsGroupDetailSchema = AnalyticsGroupRecordSchema.extend({ members: array(AnalyticsGroupMemberSchema).readonly() });
18775
- var ListGroupsQueryInput = object({
18776
- /** Devices to merge. An empty array yields `{ groups: [], nextCursor: null }`. */
18777
- deviceIds: array(number()),
18778
- /** Window lower bound on `closedAt` (inclusive). */
18779
- since: number().optional(),
18780
- /** Window upper bound on `openedAt` (inclusive). */
18781
- until: number().optional(),
18782
- limit: number().int().min(1).max(LIST_GROUPS_MAX_LIMIT).default(LIST_GROUPS_DEFAULT_LIMIT),
18783
- /** Opaque continuation cursor from a previous page's `nextCursor`. */
18784
- cursor: string().optional()
18785
- });
18786
- var ListGroupsPageSchema = object({
18787
- groups: array(AnalyticsGroupRecordSchema).readonly(),
18788
- nextCursor: string().nullable()
18789
- });
18790
18828
  var KEY_EVENTS_DEFAULT_LIMIT = 50;
18791
18829
  var KEY_EVENTS_MAX_LIMIT = 200;
18792
18830
  var KeyEventQueryInput = object({
@@ -18890,9 +18928,7 @@ var TrackCascadeCountsSchema = object({
18890
18928
  /** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
18891
18929
  plates: number().int(),
18892
18930
  /** Per-track CLIP search vectors removed (best-effort). */
18893
- embeddings: number().int(),
18894
- /** Group membership + group rows removed with their last member (best-effort). */
18895
- groups: number().int()
18931
+ embeddings: number().int()
18896
18932
  });
18897
18933
  /** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
18898
18934
  var DiskReconcileCountsSchema = object({
@@ -19062,6 +19098,47 @@ var RebuildStatusSchema = object({
19062
19098
  /** Present when the pass ended by throwing. */
19063
19099
  error: string().nullable()
19064
19100
  });
19101
+ /**
19102
+ * Acknowledgement that a debug-media reclaim STARTED.
19103
+ *
19104
+ * The pass is paced at ~2 MB/s over a standing 100 GB — tens of minutes — so
19105
+ * it runs detached and this returns immediately. Awaiting it is how the
19106
+ * `addons.custom` door hit the 60 s UDS deadline while the walk carried on
19107
+ * with no status. Poll {@link pipelineAnalyticsCapability.methods.getMediaReclaimStatus}.
19108
+ */
19109
+ var MediaReclaimStartResultSchema = object({
19110
+ started: boolean(),
19111
+ /** True when a pass was already running; the new request is ignored. */
19112
+ alreadyRunning: boolean()
19113
+ });
19114
+ var MediaReclaimInputSchema = object({
19115
+ mode: _enum(["report", "reclaim"]).default("report"),
19116
+ scopes: array(_enum(["motion-still", "track-filmstrip"])).min(1).optional(),
19117
+ deviceIds: array(number().int()).min(1).optional(),
19118
+ restart: boolean().optional(),
19119
+ pageSize: number().int().min(50).max(5e3).optional(),
19120
+ maxRowsPerDevice: number().int().min(1).max(5e5).optional(),
19121
+ maxReclaimPerDevice: number().int().min(1).max(5e5).optional(),
19122
+ maxBytesPerRun: number().int().min(1).optional(),
19123
+ budgetMinutes: number().int().min(1).max(720).optional(),
19124
+ throttleBytesPerSec: number().int().min(64 * 1024).optional(),
19125
+ graceMinutes: number().int().min(1).max(10080).optional()
19126
+ });
19127
+ var MediaReclaimStatusSchema = object({
19128
+ running: boolean(),
19129
+ mode: _enum(["report", "reclaim"]).nullable(),
19130
+ totalExamined: number(),
19131
+ totalEligible: number(),
19132
+ totalReclaimed: number(),
19133
+ totalBytesReclaimed: number(),
19134
+ totalRefused: number(),
19135
+ /** Device+scope windows finished in this pass. */
19136
+ devicesDone: number(),
19137
+ complete: boolean().nullable(),
19138
+ startedAtMs: number().nullable(),
19139
+ finishedAtMs: number().nullable(),
19140
+ error: string().nullable()
19141
+ });
19065
19142
  var ReplayFrameInputSchema = object({
19066
19143
  timestamp: number(),
19067
19144
  frame: PipelineRunResultBridge
@@ -19100,10 +19177,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19100
19177
  * stationary registry). Default false: the timeline lists passages,
19101
19178
  * not parking records (operator decision, 2026-08-15). */
19102
19179
  includeStationary: boolean().optional()
19103
- }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(ListGroupsQueryInput, ListGroupsPageSchema), method(object({
19104
- deviceId: number(),
19105
- groupId: string().min(1)
19106
- }), AnalyticsGroupDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
19180
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
19107
19181
  kind: "mutation",
19108
19182
  auth: "admin"
19109
19183
  }), 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({
@@ -19203,6 +19277,12 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19203
19277
  }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
19204
19278
  kind: "query",
19205
19279
  auth: "admin"
19280
+ }), method(MediaReclaimInputSchema, MediaReclaimStartResultSchema, {
19281
+ kind: "mutation",
19282
+ auth: "admin"
19283
+ }), method(object({}), MediaReclaimStatusSchema, {
19284
+ kind: "query",
19285
+ auth: "admin"
19206
19286
  }), method(object({ deviceIds: array(number()).optional() }), TrainingExportSummarySchema, {
19207
19287
  kind: "query",
19208
19288
  auth: "admin"
@@ -21173,7 +21253,13 @@ method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin"
21173
21253
  }), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
21174
21254
  kind: "mutation",
21175
21255
  auth: "admin"
21176
- });
21256
+ }), method(StorageCleanupInputSchema, object({ jobId: string() }), {
21257
+ kind: "mutation",
21258
+ auth: "admin"
21259
+ }), method(StorageCleanupStatusInputSchema, StorageCleanupJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
21260
+ kind: "mutation",
21261
+ auth: "admin"
21262
+ }), method(object({}), array(StorageMigrationJobSchema).readonly(), { auth: "admin" });
21177
21263
  var ProviderInfoSchema = discriminatedUnion("shouldSaveDiskSpace", [object({
21178
21264
  providerId: string().min(1),
21179
21265
  displayName: string().min(1),
@@ -26612,6 +26698,33 @@ var RecordingRebalanceInputSchema = object({
26612
26698
  minMoveGb: number().min(0).optional()
26613
26699
  });
26614
26700
  /**
26701
+ * Operator-facing placement of one camera onto a recordings location.
26702
+ *
26703
+ * `pinLocationId` is the operator instruction: a location id, or `null` for
26704
+ * Auto (the planner may move this camera). `locationId` is where high/mid
26705
+ * currently write — the plan, which may disagree with the pin when Auto.
26706
+ */
26707
+ var RecordingDevicePlacementSchema = object({
26708
+ deviceId: number().int(),
26709
+ profile: string(),
26710
+ locationId: string()
26711
+ });
26712
+ var RecordingDevicePinSchema = object({
26713
+ deviceId: number().int(),
26714
+ /** Recordings-class location this camera is pinned to. */
26715
+ locationId: string()
26716
+ });
26717
+ var RecordingPlacementViewSchema = object({
26718
+ assignments: array(RecordingDevicePlacementSchema),
26719
+ pins: array(RecordingDevicePinSchema),
26720
+ defaultLocations: record(string(), string())
26721
+ });
26722
+ var RecordingSetDevicePlacementInputSchema = object({
26723
+ deviceId: number().int(),
26724
+ /** `null` = Auto. Otherwise a `recordings:*` location id. */
26725
+ locationId: string().nullable()
26726
+ });
26727
+ /**
26615
26728
  * Result of locating footage at a wall-clock instant for one device/profile.
26616
26729
  * `segment` carries the covering segment's window; `gap` reports the forward
26617
26730
  * nearest covered edge (`null` past the end of footage / when none exists)
@@ -26837,6 +26950,12 @@ method(object({
26837
26950
  }), method(RecordingRebalanceInputSchema, RecordingRebalancePlanSchema, {
26838
26951
  kind: "mutation",
26839
26952
  auth: "admin"
26953
+ }), method(object({}), RecordingPlacementViewSchema, {
26954
+ kind: "query",
26955
+ auth: "admin"
26956
+ }), method(RecordingSetDevicePlacementInputSchema, object({ ok: literal(true) }), {
26957
+ kind: "mutation",
26958
+ auth: "admin"
26840
26959
  });
26841
26960
  /**
26842
26961
  * `recording-export` cap — render a footage time range into a single downloadable
@@ -30207,6 +30326,12 @@ Object.freeze({
30207
30326
  addonId: null,
30208
30327
  access: "delete"
30209
30328
  },
30329
+ "deviceManager.renameLocation": {
30330
+ capName: "device-manager",
30331
+ capScope: "system",
30332
+ addonId: null,
30333
+ access: "create"
30334
+ },
30210
30335
  "deviceManager.runDeviceAction": {
30211
30336
  capName: "device-manager",
30212
30337
  capScope: "system",
@@ -31899,19 +32024,19 @@ Object.freeze({
31899
32024
  addonId: null,
31900
32025
  access: "view"
31901
32026
  },
31902
- "pipelineAnalytics.getGroup": {
32027
+ "pipelineAnalytics.getKeyEvents": {
31903
32028
  capName: "pipeline-analytics",
31904
32029
  capScope: "device",
31905
32030
  addonId: null,
31906
32031
  access: "view"
31907
32032
  },
31908
- "pipelineAnalytics.getKeyEvents": {
32033
+ "pipelineAnalytics.getKeyEventsBatch": {
31909
32034
  capName: "pipeline-analytics",
31910
32035
  capScope: "device",
31911
32036
  addonId: null,
31912
32037
  access: "view"
31913
32038
  },
31914
- "pipelineAnalytics.getKeyEventsBatch": {
32039
+ "pipelineAnalytics.getMediaReclaimStatus": {
31915
32040
  capName: "pipeline-analytics",
31916
32041
  capScope: "device",
31917
32042
  addonId: null,
@@ -32001,12 +32126,6 @@ Object.freeze({
32001
32126
  addonId: null,
32002
32127
  access: "view"
32003
32128
  },
32004
- "pipelineAnalytics.listGroups": {
32005
- capName: "pipeline-analytics",
32006
- capScope: "device",
32007
- addonId: null,
32008
- access: "view"
32009
- },
32010
32129
  "pipelineAnalytics.listOpsLog": {
32011
32130
  capName: "pipeline-analytics",
32012
32131
  capScope: "device",
@@ -32091,6 +32210,12 @@ Object.freeze({
32091
32210
  addonId: null,
32092
32211
  access: "create"
32093
32212
  },
32213
+ "pipelineAnalytics.reclaimDebugMedia": {
32214
+ capName: "pipeline-analytics",
32215
+ capScope: "device",
32216
+ addonId: null,
32217
+ access: "create"
32218
+ },
32094
32219
  "pipelineAnalytics.reconcileFromDisk": {
32095
32220
  capName: "pipeline-analytics",
32096
32221
  capScope: "device",
@@ -33015,6 +33140,12 @@ Object.freeze({
33015
33140
  addonId: null,
33016
33141
  access: "view"
33017
33142
  },
33143
+ "recording.getPlacement": {
33144
+ capName: "recording",
33145
+ capScope: "system",
33146
+ addonId: null,
33147
+ access: "view"
33148
+ },
33018
33149
  "recording.getPlaybackManifest": {
33019
33150
  capName: "recording",
33020
33151
  capScope: "system",
@@ -33141,6 +33272,12 @@ Object.freeze({
33141
33272
  addonId: null,
33142
33273
  access: "create"
33143
33274
  },
33275
+ "recording.setDevicePlacement": {
33276
+ capName: "recording",
33277
+ capScope: "system",
33278
+ addonId: null,
33279
+ access: "create"
33280
+ },
33144
33281
  "recording.startStorageMigrationMove": {
33145
33282
  capName: "recording",
33146
33283
  capScope: "system",
@@ -33585,12 +33722,36 @@ Object.freeze({
33585
33722
  addonId: null,
33586
33723
  access: "create"
33587
33724
  },
33725
+ "storageMigration.cleanupCancel": {
33726
+ capName: "storage-migration",
33727
+ capScope: "system",
33728
+ addonId: null,
33729
+ access: "create"
33730
+ },
33731
+ "storageMigration.cleanupStart": {
33732
+ capName: "storage-migration",
33733
+ capScope: "system",
33734
+ addonId: null,
33735
+ access: "create"
33736
+ },
33737
+ "storageMigration.cleanupStatus": {
33738
+ capName: "storage-migration",
33739
+ capScope: "system",
33740
+ addonId: null,
33741
+ access: "view"
33742
+ },
33588
33743
  "storageMigration.drain": {
33589
33744
  capName: "storage-migration",
33590
33745
  capScope: "system",
33591
33746
  addonId: null,
33592
33747
  access: "create"
33593
33748
  },
33749
+ "storageMigration.history": {
33750
+ capName: "storage-migration",
33751
+ capScope: "system",
33752
+ addonId: null,
33753
+ access: "view"
33754
+ },
33594
33755
  "storageMigration.movers": {
33595
33756
  capName: "storage-migration",
33596
33757
  capScope: "system",
@@ -35587,11 +35748,6 @@ Object.freeze({
35587
35748
  form: "single",
35588
35749
  optional: true
35589
35750
  }],
35590
- "pipelineAnalytics.getGroup": [{
35591
- name: "deviceId",
35592
- form: "single",
35593
- optional: false
35594
- }],
35595
35751
  "pipelineAnalytics.getKeyEvents": [{
35596
35752
  name: "deviceId",
35597
35753
  form: "single",
@@ -35657,11 +35813,6 @@ Object.freeze({
35657
35813
  form: "single",
35658
35814
  optional: false
35659
35815
  }],
35660
- "pipelineAnalytics.listGroups": [{
35661
- name: "deviceIds",
35662
- form: "array",
35663
- optional: false
35664
- }],
35665
35816
  "pipelineAnalytics.listOpsLog": [{
35666
35817
  name: "deviceId",
35667
35818
  form: "single",
@@ -35707,6 +35858,11 @@ Object.freeze({
35707
35858
  form: "single",
35708
35859
  optional: true
35709
35860
  }],
35861
+ "pipelineAnalytics.reclaimDebugMedia": [{
35862
+ name: "deviceIds",
35863
+ form: "array",
35864
+ optional: true
35865
+ }],
35710
35866
  "pipelineAnalytics.reconcileFromDisk": [{
35711
35867
  name: "deviceId",
35712
35868
  form: "single",
@@ -36072,6 +36228,11 @@ Object.freeze({
36072
36228
  form: "single",
36073
36229
  optional: false
36074
36230
  }],
36231
+ "recording.setDevicePlacement": [{
36232
+ name: "deviceId",
36233
+ form: "single",
36234
+ optional: false
36235
+ }],
36075
36236
  "recording.startStorageMigrationMove": [{
36076
36237
  name: "deviceId",
36077
36238
  form: "single",
@@ -8113,6 +8113,13 @@ var MediaRelocateModeSchema = _enum([
8113
8113
  ]);
8114
8114
  var RelocateMediaInputSchema = object({
8115
8115
  toLocationId: string(),
8116
+ /**
8117
+ * Restrict the pass to rows currently on this location. Omitted / `'*'` =
8118
+ * every row that is not already on `toLocationId` (the historical
8119
+ * behaviour). A named source is what a from→to migration needs: without it
8120
+ * "move events off disk 2" also emptied disk 1.
8121
+ */
8122
+ fromLocationId: string().optional(),
8116
8123
  throttleMbps: number().min(1).max(1e3).optional(),
8117
8124
  /** Omitted = `move`, the pre-existing behaviour. */
8118
8125
  mode: MediaRelocateModeSchema.optional()
@@ -8180,6 +8187,19 @@ var StorageMigrationDestinationsSchema = object({
8180
8187
  galleryMedia: string().min(1).optional()
8181
8188
  }).refine((value) => Object.keys(value).length > 0, { message: "select at least one storage class" });
8182
8189
  /**
8190
+ * Optional named source per class. Omitted = the class's current default
8191
+ * (the historical behaviour). A named source that is NOT the default is a
8192
+ * drain of that disk: bytes move, the default stays, and the source is
8193
+ * disabled when the move finishes.
8194
+ */
8195
+ var StorageMigrationSourcesSchema = object({
8196
+ recordings: string().min(1).optional(),
8197
+ recordingsLow: string().min(1).optional(),
8198
+ eventMedia: string().min(1).optional(),
8199
+ backups: string().min(1).optional(),
8200
+ galleryMedia: string().min(1).optional()
8201
+ }).optional();
8202
+ /**
8183
8203
  * How a migration sequences the cutover against the byte move.
8184
8204
  *
8185
8205
  * - `blocking` — the historical order: pause, move every byte, repoint,
@@ -8201,6 +8221,8 @@ var StorageMigrationModeSchema = _enum(["blocking", "nonBlocking"]);
8201
8221
  /** Shared input for planning and starting an orchestrated storage migration. */
8202
8222
  var StorageMigrationInputSchema = object({
8203
8223
  destinations: StorageMigrationDestinationsSchema,
8224
+ /** Omitted = each class's current default. */
8225
+ sources: StorageMigrationSourcesSchema,
8204
8226
  throttleMbps: number().min(1).max(1e3).optional(),
8205
8227
  /** Omitted = `blocking`, which stays the default. */
8206
8228
  mode: StorageMigrationModeSchema.optional()
@@ -8280,6 +8302,13 @@ var StorageMigrationMoveSchema = object({
8280
8302
  storageClass: StorageMigrationClassSchema,
8281
8303
  fromLocationId: string(),
8282
8304
  toLocationId: string(),
8305
+ /**
8306
+ * True when `from` was NOT the class default at plan time. The move still
8307
+ * copies bytes, but the default is left alone and the source is disabled
8308
+ * once the copy verifies. Absent on jobs planned before this field existed
8309
+ * — those jobs always repointed, which is `false`.
8310
+ */
8311
+ freezeSource: boolean().optional(),
8283
8312
  moverJobId: string().nullable(),
8284
8313
  state: RelocateJobStateSchema.nullable(),
8285
8314
  error: string().nullable(),
@@ -8293,6 +8322,7 @@ var StorageMigrationJobSchema = object({
8293
8322
  * can tell a seconds-long cutover from a thirty-hour one. */
8294
8323
  mode: StorageMigrationModeSchema,
8295
8324
  destinations: StorageMigrationDestinationsSchema,
8325
+ sources: StorageMigrationSourcesSchema,
8296
8326
  throttleMbps: number(),
8297
8327
  moves: array(StorageMigrationMoveSchema),
8298
8328
  pauseLeaseId: string().nullable(),
@@ -8318,6 +8348,7 @@ var StorageMigrationFindingSchema = object({
8318
8348
  });
8319
8349
  var StorageMigrationPlanSchema = object({
8320
8350
  destinations: StorageMigrationDestinationsSchema,
8351
+ sources: StorageMigrationSourcesSchema,
8321
8352
  /** The mode this plan was built for. A plan is only valid for its mode: the
8322
8353
  * `eventMedia` seal gate and the single-cardinality refusal both depend on
8323
8354
  * it. */
@@ -8325,7 +8356,8 @@ var StorageMigrationPlanSchema = object({
8325
8356
  moves: array(object({
8326
8357
  storageClass: StorageMigrationClassSchema,
8327
8358
  fromLocationId: string(),
8328
- toLocationId: string()
8359
+ toLocationId: string(),
8360
+ freezeSource: boolean().optional()
8329
8361
  })),
8330
8362
  findings: array(StorageMigrationFindingSchema)
8331
8363
  });
@@ -8503,10 +8535,51 @@ var LedgerWalkReportSchema = object({
8503
8535
  var RelocatableMediaCountSchema = object({ rows: number().int().nonnegative() }).nullable();
8504
8536
  var RelocatableMediaCountInputSchema = object({
8505
8537
  toLocationId: string().min(1),
8538
+ /** Restrict the count to one source; omitted / `'*'` = every non-target row. */
8539
+ fromLocationId: string().optional(),
8506
8540
  /** Omitted = `move`. */
8507
8541
  mode: MediaRelocateModeSchema.optional()
8508
8542
  });
8509
8543
  /**
8544
+ * Operator cleanup of leftover analytics rows, optional debug media, and
8545
+ * ghost ledger entries on frozen footage locations.
8546
+ *
8547
+ * A pass is tens of minutes on a standing backlog. The hub method RETURNS
8548
+ * `{ jobId }` immediately; progress is `cleanupStatus`. Awaiting the work
8549
+ * is how `addons.custom` hit the 60 s UDS deadline while reclaim continued
8550
+ * with no operator-visible status.
8551
+ */
8552
+ var StorageCleanupPhaseSchema = _enum([
8553
+ "orphans",
8554
+ "debug-media",
8555
+ "ghost-ledger",
8556
+ "done",
8557
+ "failed",
8558
+ "cancelled"
8559
+ ]);
8560
+ var StorageCleanupInputSchema = object({
8561
+ /** Also walk motion stills / track filmstrips. Off by default. */
8562
+ includeDebugMedia: boolean().optional() });
8563
+ var StorageCleanupJobSchema = object({
8564
+ jobId: string(),
8565
+ phase: StorageCleanupPhaseSchema,
8566
+ includeDebugMedia: boolean(),
8567
+ orphansReclaimed: number().int().nonnegative(),
8568
+ orphanBytesReclaimed: number().int().nonnegative(),
8569
+ debugMediaReclaimed: number().int().nonnegative(),
8570
+ debugMediaBytesReclaimed: number().int().nonnegative(),
8571
+ ghostsForgotten: number().int().nonnegative(),
8572
+ ghostBytesForgotten: number().int().nonnegative(),
8573
+ /** Short operator-facing line: current collection, pass, or location. */
8574
+ detail: string().nullable(),
8575
+ cancelRequested: boolean(),
8576
+ startedAt: number(),
8577
+ updatedAt: number(),
8578
+ finishedAt: number().nullable(),
8579
+ error: string().nullable()
8580
+ });
8581
+ var StorageCleanupStatusInputSchema = object({ jobId: string().optional() });
8582
+ /**
8510
8583
  * `StorageLocationType` — an addon-declared id that identifies the *kind* of
8511
8584
  * storage a location serves. Defined here (not in `capabilities/storage.cap.ts`)
8512
8585
  * so the persisted record schema and the consumer-facing cap can both consume it
@@ -8534,11 +8607,10 @@ var StorageLocationTypeSchema = string().regex(/^[a-z][a-zA-Z0-9-]*$/);
8534
8607
  * The default location for a type uses `id === <type>:default` by
8535
8608
  * convention (the bare type ref like `'backups'` resolves to it).
8536
8609
  *
8537
- * `isSystem: true` marks a location as orchestrator-seeded and
8538
- * undeletable. The bootstrap-installed defaults (one per type) carry
8539
- * this flag; operator-added locations don't. Editing the config of
8540
- * a system location is allowed (path migration, provider swap) but
8541
- * deleting it is rejected at the cap level.
8610
+ * `isSystem` is a legacy persisted flag. Seed still creates the initial
8611
+ * `<type>:default` locations; the flag is no longer a lock, a badge, or a
8612
+ * prune selector. New writes leave it false. Deletion is gated on uniqueness
8613
+ * / last-enabled, not on this bit.
8542
8614
  */
8543
8615
  var StorageLocationSchema = object({
8544
8616
  id: string().regex(/^[a-z][a-zA-Z0-9-]*:[a-zA-Z0-9-]+$/),
@@ -12800,6 +12872,12 @@ method(object({
12800
12872
  }), _void(), {
12801
12873
  kind: "mutation",
12802
12874
  auth: "admin"
12875
+ }), method(object({
12876
+ from: string(),
12877
+ to: string()
12878
+ }), object({ moved: number() }), {
12879
+ kind: "mutation",
12880
+ auth: "admin"
12803
12881
  }), method(object({
12804
12882
  deviceId: number(),
12805
12883
  disabled: boolean()
@@ -18747,46 +18825,6 @@ var RecentTracksPageSchema = object({
18747
18825
  /** Cursor for the next page, or null when this page is the last. */
18748
18826
  nextCursor: string().nullable()
18749
18827
  });
18750
- var LIST_GROUPS_DEFAULT_LIMIT = 40;
18751
- var LIST_GROUPS_MAX_LIMIT = 100;
18752
- var AnalyticsGroupRecordSchema = object({
18753
- id: string(),
18754
- deviceId: number().int(),
18755
- openedAt: number().int(),
18756
- closedAt: number().int(),
18757
- timestamp: number().int(),
18758
- memberCount: number().int(),
18759
- memberTrackIds: array(string()).readonly(),
18760
- className: string(),
18761
- classes: array(string()).readonly(),
18762
- /** Relative event-media path, or null when the group has no picture yet. */
18763
- mediaUrl: string().nullable(),
18764
- singleton: boolean()
18765
- });
18766
- var AnalyticsGroupMemberSchema = object({
18767
- trackId: string(),
18768
- deviceId: number().int(),
18769
- className: string(),
18770
- firstSeen: number().int(),
18771
- lastSeen: number().int(),
18772
- mediaUrl: string().nullable()
18773
- });
18774
- var AnalyticsGroupDetailSchema = AnalyticsGroupRecordSchema.extend({ members: array(AnalyticsGroupMemberSchema).readonly() });
18775
- var ListGroupsQueryInput = object({
18776
- /** Devices to merge. An empty array yields `{ groups: [], nextCursor: null }`. */
18777
- deviceIds: array(number()),
18778
- /** Window lower bound on `closedAt` (inclusive). */
18779
- since: number().optional(),
18780
- /** Window upper bound on `openedAt` (inclusive). */
18781
- until: number().optional(),
18782
- limit: number().int().min(1).max(LIST_GROUPS_MAX_LIMIT).default(LIST_GROUPS_DEFAULT_LIMIT),
18783
- /** Opaque continuation cursor from a previous page's `nextCursor`. */
18784
- cursor: string().optional()
18785
- });
18786
- var ListGroupsPageSchema = object({
18787
- groups: array(AnalyticsGroupRecordSchema).readonly(),
18788
- nextCursor: string().nullable()
18789
- });
18790
18828
  var KEY_EVENTS_DEFAULT_LIMIT = 50;
18791
18829
  var KEY_EVENTS_MAX_LIMIT = 200;
18792
18830
  var KeyEventQueryInput = object({
@@ -18890,9 +18928,7 @@ var TrackCascadeCountsSchema = object({
18890
18928
  /** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
18891
18929
  plates: number().int(),
18892
18930
  /** Per-track CLIP search vectors removed (best-effort). */
18893
- embeddings: number().int(),
18894
- /** Group membership + group rows removed with their last member (best-effort). */
18895
- groups: number().int()
18931
+ embeddings: number().int()
18896
18932
  });
18897
18933
  /** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
18898
18934
  var DiskReconcileCountsSchema = object({
@@ -19062,6 +19098,47 @@ var RebuildStatusSchema = object({
19062
19098
  /** Present when the pass ended by throwing. */
19063
19099
  error: string().nullable()
19064
19100
  });
19101
+ /**
19102
+ * Acknowledgement that a debug-media reclaim STARTED.
19103
+ *
19104
+ * The pass is paced at ~2 MB/s over a standing 100 GB — tens of minutes — so
19105
+ * it runs detached and this returns immediately. Awaiting it is how the
19106
+ * `addons.custom` door hit the 60 s UDS deadline while the walk carried on
19107
+ * with no status. Poll {@link pipelineAnalyticsCapability.methods.getMediaReclaimStatus}.
19108
+ */
19109
+ var MediaReclaimStartResultSchema = object({
19110
+ started: boolean(),
19111
+ /** True when a pass was already running; the new request is ignored. */
19112
+ alreadyRunning: boolean()
19113
+ });
19114
+ var MediaReclaimInputSchema = object({
19115
+ mode: _enum(["report", "reclaim"]).default("report"),
19116
+ scopes: array(_enum(["motion-still", "track-filmstrip"])).min(1).optional(),
19117
+ deviceIds: array(number().int()).min(1).optional(),
19118
+ restart: boolean().optional(),
19119
+ pageSize: number().int().min(50).max(5e3).optional(),
19120
+ maxRowsPerDevice: number().int().min(1).max(5e5).optional(),
19121
+ maxReclaimPerDevice: number().int().min(1).max(5e5).optional(),
19122
+ maxBytesPerRun: number().int().min(1).optional(),
19123
+ budgetMinutes: number().int().min(1).max(720).optional(),
19124
+ throttleBytesPerSec: number().int().min(64 * 1024).optional(),
19125
+ graceMinutes: number().int().min(1).max(10080).optional()
19126
+ });
19127
+ var MediaReclaimStatusSchema = object({
19128
+ running: boolean(),
19129
+ mode: _enum(["report", "reclaim"]).nullable(),
19130
+ totalExamined: number(),
19131
+ totalEligible: number(),
19132
+ totalReclaimed: number(),
19133
+ totalBytesReclaimed: number(),
19134
+ totalRefused: number(),
19135
+ /** Device+scope windows finished in this pass. */
19136
+ devicesDone: number(),
19137
+ complete: boolean().nullable(),
19138
+ startedAtMs: number().nullable(),
19139
+ finishedAtMs: number().nullable(),
19140
+ error: string().nullable()
19141
+ });
19065
19142
  var ReplayFrameInputSchema = object({
19066
19143
  timestamp: number(),
19067
19144
  frame: PipelineRunResultBridge
@@ -19100,10 +19177,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19100
19177
  * stationary registry). Default false: the timeline lists passages,
19101
19178
  * not parking records (operator decision, 2026-08-15). */
19102
19179
  includeStationary: boolean().optional()
19103
- }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(ListGroupsQueryInput, ListGroupsPageSchema), method(object({
19104
- deviceId: number(),
19105
- groupId: string().min(1)
19106
- }), AnalyticsGroupDetailSchema.nullable()), method(object({ deviceId: number() }), _void(), {
19180
+ }), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
19107
19181
  kind: "mutation",
19108
19182
  auth: "admin"
19109
19183
  }), 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({
@@ -19203,6 +19277,12 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
19203
19277
  }), method(OpsLogQueryInputSchema, array(OpsLogEntrySchema).readonly(), {
19204
19278
  kind: "query",
19205
19279
  auth: "admin"
19280
+ }), method(MediaReclaimInputSchema, MediaReclaimStartResultSchema, {
19281
+ kind: "mutation",
19282
+ auth: "admin"
19283
+ }), method(object({}), MediaReclaimStatusSchema, {
19284
+ kind: "query",
19285
+ auth: "admin"
19206
19286
  }), method(object({ deviceIds: array(number()).optional() }), TrainingExportSummarySchema, {
19207
19287
  kind: "query",
19208
19288
  auth: "admin"
@@ -21173,7 +21253,13 @@ method(StorageMigrationInputSchema, StorageMigrationPlanSchema, { auth: "admin"
21173
21253
  }), method(object({}), array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }), method(object({}), array(StorageMigrationResidueSchema).readonly(), { auth: "admin" }), method(StorageMigrationDrainInputSchema, object({ jobId: string() }), {
21174
21254
  kind: "mutation",
21175
21255
  auth: "admin"
21176
- });
21256
+ }), method(StorageCleanupInputSchema, object({ jobId: string() }), {
21257
+ kind: "mutation",
21258
+ auth: "admin"
21259
+ }), method(StorageCleanupStatusInputSchema, StorageCleanupJobSchema.nullable(), { auth: "admin" }), method(object({ jobId: string() }), object({ cancelled: boolean() }), {
21260
+ kind: "mutation",
21261
+ auth: "admin"
21262
+ }), method(object({}), array(StorageMigrationJobSchema).readonly(), { auth: "admin" });
21177
21263
  var ProviderInfoSchema = discriminatedUnion("shouldSaveDiskSpace", [object({
21178
21264
  providerId: string().min(1),
21179
21265
  displayName: string().min(1),
@@ -26612,6 +26698,33 @@ var RecordingRebalanceInputSchema = object({
26612
26698
  minMoveGb: number().min(0).optional()
26613
26699
  });
26614
26700
  /**
26701
+ * Operator-facing placement of one camera onto a recordings location.
26702
+ *
26703
+ * `pinLocationId` is the operator instruction: a location id, or `null` for
26704
+ * Auto (the planner may move this camera). `locationId` is where high/mid
26705
+ * currently write — the plan, which may disagree with the pin when Auto.
26706
+ */
26707
+ var RecordingDevicePlacementSchema = object({
26708
+ deviceId: number().int(),
26709
+ profile: string(),
26710
+ locationId: string()
26711
+ });
26712
+ var RecordingDevicePinSchema = object({
26713
+ deviceId: number().int(),
26714
+ /** Recordings-class location this camera is pinned to. */
26715
+ locationId: string()
26716
+ });
26717
+ var RecordingPlacementViewSchema = object({
26718
+ assignments: array(RecordingDevicePlacementSchema),
26719
+ pins: array(RecordingDevicePinSchema),
26720
+ defaultLocations: record(string(), string())
26721
+ });
26722
+ var RecordingSetDevicePlacementInputSchema = object({
26723
+ deviceId: number().int(),
26724
+ /** `null` = Auto. Otherwise a `recordings:*` location id. */
26725
+ locationId: string().nullable()
26726
+ });
26727
+ /**
26615
26728
  * Result of locating footage at a wall-clock instant for one device/profile.
26616
26729
  * `segment` carries the covering segment's window; `gap` reports the forward
26617
26730
  * nearest covered edge (`null` past the end of footage / when none exists)
@@ -26837,6 +26950,12 @@ method(object({
26837
26950
  }), method(RecordingRebalanceInputSchema, RecordingRebalancePlanSchema, {
26838
26951
  kind: "mutation",
26839
26952
  auth: "admin"
26953
+ }), method(object({}), RecordingPlacementViewSchema, {
26954
+ kind: "query",
26955
+ auth: "admin"
26956
+ }), method(RecordingSetDevicePlacementInputSchema, object({ ok: literal(true) }), {
26957
+ kind: "mutation",
26958
+ auth: "admin"
26840
26959
  });
26841
26960
  /**
26842
26961
  * `recording-export` cap — render a footage time range into a single downloadable
@@ -30207,6 +30326,12 @@ Object.freeze({
30207
30326
  addonId: null,
30208
30327
  access: "delete"
30209
30328
  },
30329
+ "deviceManager.renameLocation": {
30330
+ capName: "device-manager",
30331
+ capScope: "system",
30332
+ addonId: null,
30333
+ access: "create"
30334
+ },
30210
30335
  "deviceManager.runDeviceAction": {
30211
30336
  capName: "device-manager",
30212
30337
  capScope: "system",
@@ -31899,19 +32024,19 @@ Object.freeze({
31899
32024
  addonId: null,
31900
32025
  access: "view"
31901
32026
  },
31902
- "pipelineAnalytics.getGroup": {
32027
+ "pipelineAnalytics.getKeyEvents": {
31903
32028
  capName: "pipeline-analytics",
31904
32029
  capScope: "device",
31905
32030
  addonId: null,
31906
32031
  access: "view"
31907
32032
  },
31908
- "pipelineAnalytics.getKeyEvents": {
32033
+ "pipelineAnalytics.getKeyEventsBatch": {
31909
32034
  capName: "pipeline-analytics",
31910
32035
  capScope: "device",
31911
32036
  addonId: null,
31912
32037
  access: "view"
31913
32038
  },
31914
- "pipelineAnalytics.getKeyEventsBatch": {
32039
+ "pipelineAnalytics.getMediaReclaimStatus": {
31915
32040
  capName: "pipeline-analytics",
31916
32041
  capScope: "device",
31917
32042
  addonId: null,
@@ -32001,12 +32126,6 @@ Object.freeze({
32001
32126
  addonId: null,
32002
32127
  access: "view"
32003
32128
  },
32004
- "pipelineAnalytics.listGroups": {
32005
- capName: "pipeline-analytics",
32006
- capScope: "device",
32007
- addonId: null,
32008
- access: "view"
32009
- },
32010
32129
  "pipelineAnalytics.listOpsLog": {
32011
32130
  capName: "pipeline-analytics",
32012
32131
  capScope: "device",
@@ -32091,6 +32210,12 @@ Object.freeze({
32091
32210
  addonId: null,
32092
32211
  access: "create"
32093
32212
  },
32213
+ "pipelineAnalytics.reclaimDebugMedia": {
32214
+ capName: "pipeline-analytics",
32215
+ capScope: "device",
32216
+ addonId: null,
32217
+ access: "create"
32218
+ },
32094
32219
  "pipelineAnalytics.reconcileFromDisk": {
32095
32220
  capName: "pipeline-analytics",
32096
32221
  capScope: "device",
@@ -33015,6 +33140,12 @@ Object.freeze({
33015
33140
  addonId: null,
33016
33141
  access: "view"
33017
33142
  },
33143
+ "recording.getPlacement": {
33144
+ capName: "recording",
33145
+ capScope: "system",
33146
+ addonId: null,
33147
+ access: "view"
33148
+ },
33018
33149
  "recording.getPlaybackManifest": {
33019
33150
  capName: "recording",
33020
33151
  capScope: "system",
@@ -33141,6 +33272,12 @@ Object.freeze({
33141
33272
  addonId: null,
33142
33273
  access: "create"
33143
33274
  },
33275
+ "recording.setDevicePlacement": {
33276
+ capName: "recording",
33277
+ capScope: "system",
33278
+ addonId: null,
33279
+ access: "create"
33280
+ },
33144
33281
  "recording.startStorageMigrationMove": {
33145
33282
  capName: "recording",
33146
33283
  capScope: "system",
@@ -33585,12 +33722,36 @@ Object.freeze({
33585
33722
  addonId: null,
33586
33723
  access: "create"
33587
33724
  },
33725
+ "storageMigration.cleanupCancel": {
33726
+ capName: "storage-migration",
33727
+ capScope: "system",
33728
+ addonId: null,
33729
+ access: "create"
33730
+ },
33731
+ "storageMigration.cleanupStart": {
33732
+ capName: "storage-migration",
33733
+ capScope: "system",
33734
+ addonId: null,
33735
+ access: "create"
33736
+ },
33737
+ "storageMigration.cleanupStatus": {
33738
+ capName: "storage-migration",
33739
+ capScope: "system",
33740
+ addonId: null,
33741
+ access: "view"
33742
+ },
33588
33743
  "storageMigration.drain": {
33589
33744
  capName: "storage-migration",
33590
33745
  capScope: "system",
33591
33746
  addonId: null,
33592
33747
  access: "create"
33593
33748
  },
33749
+ "storageMigration.history": {
33750
+ capName: "storage-migration",
33751
+ capScope: "system",
33752
+ addonId: null,
33753
+ access: "view"
33754
+ },
33594
33755
  "storageMigration.movers": {
33595
33756
  capName: "storage-migration",
33596
33757
  capScope: "system",
@@ -35587,11 +35748,6 @@ Object.freeze({
35587
35748
  form: "single",
35588
35749
  optional: true
35589
35750
  }],
35590
- "pipelineAnalytics.getGroup": [{
35591
- name: "deviceId",
35592
- form: "single",
35593
- optional: false
35594
- }],
35595
35751
  "pipelineAnalytics.getKeyEvents": [{
35596
35752
  name: "deviceId",
35597
35753
  form: "single",
@@ -35657,11 +35813,6 @@ Object.freeze({
35657
35813
  form: "single",
35658
35814
  optional: false
35659
35815
  }],
35660
- "pipelineAnalytics.listGroups": [{
35661
- name: "deviceIds",
35662
- form: "array",
35663
- optional: false
35664
- }],
35665
35816
  "pipelineAnalytics.listOpsLog": [{
35666
35817
  name: "deviceId",
35667
35818
  form: "single",
@@ -35707,6 +35858,11 @@ Object.freeze({
35707
35858
  form: "single",
35708
35859
  optional: true
35709
35860
  }],
35861
+ "pipelineAnalytics.reclaimDebugMedia": [{
35862
+ name: "deviceIds",
35863
+ form: "array",
35864
+ optional: true
35865
+ }],
35710
35866
  "pipelineAnalytics.reconcileFromDisk": [{
35711
35867
  name: "deviceId",
35712
35868
  form: "single",
@@ -36072,6 +36228,11 @@ Object.freeze({
36072
36228
  form: "single",
36073
36229
  optional: false
36074
36230
  }],
36231
+ "recording.setDevicePlacement": [{
36232
+ name: "deviceId",
36233
+ form: "single",
36234
+ optional: false
36235
+ }],
36075
36236
  "recording.startStorageMigrationMove": [{
36076
36237
  name: "deviceId",
36077
36238
  form: "single",
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-Cv-ufJXF.js");
5
+ const require_dist = require("../dist-v7uK6zeq.js");
6
6
  let node_crypto = require("node:crypto");
7
7
  let node_child_process = require("node:child_process");
8
8
  //#region src/ingress/tailscale-cli.ts
@@ -1,4 +1,4 @@
1
- import { a as EventCategory, i as BaseAddon, n as networkAccessCapability } from "../dist-8Fi7VglU.mjs";
1
+ import { a as EventCategory, i as BaseAddon, n as networkAccessCapability } from "../dist-CMpgFoPi.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { execFile } from "node:child_process";
4
4
  import { promisify } from "node:util";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-tailscale",
3
- "version": "1.2.49",
3
+ "version": "1.2.50",
4
4
  "description": "Tailscale bundle for CamStack — joins the host to a tailnet (client) and exposes the hub via Serve/Funnel (ingress). Multi-entry npm package shipping 2 addons under a single bundle.",
5
5
  "keywords": [
6
6
  "camstack",