@camstack/types 1.2.122 → 1.2.124

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/addon.js CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_event_category = require("./event-category-BaEgqJNv.js");
3
- const require_sleep = require("./sleep-DUxF5DdC.js");
3
+ const require_sleep = require("./sleep-CJrvRDlD.js");
4
4
  const require_err_msg = require("./err-msg-COpsHMw2.js");
5
5
  //#region src/generated/cap-input-defaults.ts
6
6
  /**
package/dist/addon.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as EventCategory } from "./event-category-BZL-fdNj.mjs";
2
- import { B as ReadinessRegistry, E as adminUiCapability, L as nodePin, R as readNodePin, St as emitReadiness, T as DeviceType, V as ReadinessTimeoutError, W as scopeKey, _t as DisposerChain, a as asJsonObject, b as deviceOpsCapability, d as BOOT_RECOVERY_BACKOFF_MS, f as DEVICE_SCOPED_CAPS, gt as DATAPLANE_SECRET_HEADER, h as createEventBusSliceSource, j as expandCapMethods, m as createDeviceProxy, p as isDeviceScopedCap, s as asString, t as sleep, u as parseJsonUnknown, vt as BaseAddon, x as viewerUiCapability, yt as normalizeAddonInitResult } from "./sleep-C9C8EoK8.mjs";
2
+ import { B as ReadinessRegistry, E as adminUiCapability, L as nodePin, R as readNodePin, St as emitReadiness, T as DeviceType, V as ReadinessTimeoutError, W as scopeKey, _t as DisposerChain, a as asJsonObject, b as deviceOpsCapability, d as BOOT_RECOVERY_BACKOFF_MS, f as DEVICE_SCOPED_CAPS, gt as DATAPLANE_SECRET_HEADER, h as createEventBusSliceSource, j as expandCapMethods, m as createDeviceProxy, p as isDeviceScopedCap, s as asString, t as sleep, u as parseJsonUnknown, vt as BaseAddon, x as viewerUiCapability, yt as normalizeAddonInitResult } from "./sleep-L5-bG_a_.mjs";
3
3
  import { t as errMsg } from "./err-msg-IQTHeDzc.mjs";
4
4
  //#region src/generated/cap-input-defaults.ts
5
5
  /**
@@ -69,6 +69,33 @@ export declare const intercomCapability: {
69
69
  readonly deviceNative: true;
70
70
  readonly mode: "singleton";
71
71
  readonly deviceTypes: readonly [DeviceType.Camera];
72
+ /**
73
+ * **Auth tier: `protected` on every method — deliberate, and load-bearing.**
74
+ *
75
+ * Talking through a camera is an OPERATE action, not a CONFIGURE one. This
76
+ * cap has no configuration surface at all: all six methods open, feed and
77
+ * close one live audio session against one `deviceId`. That is the same
78
+ * authority as `ptz.move` or `snapshot.getSnapshot`, both `protected` — and
79
+ * the opposite of `ptz.savePreset` / `snapshot.invalidateCache`, which are
80
+ * `admin` because they change what the device IS.
81
+ *
82
+ * `protected` does not mean ungated: `protectedProcedure` runs the
83
+ * `METHOD_ACCESS_MAP` scope check, and every method here is `scope: 'device'`
84
+ * with `access: 'create'` and a `deviceId` in its input. So a caller needs a
85
+ * grant that covers THAT camera at `create` — a `camera-viewer` (`view`
86
+ * only) still cannot talk, and a grant on camera 5 cannot talk through
87
+ * camera 7.
88
+ *
89
+ * Every method was `auth: 'admin'` from the initial commit, which made the
90
+ * cap unreachable by every non-admin principal — `adminProcedure` throws
91
+ * `FORBIDDEN: Admin required` BEFORE the scope check runs, so the scope
92
+ * machinery generated for this cap (`METHOD_ACCESS_MAP`,
93
+ * `DEVICE_SCOPED_CAPS`, `METHOD_DEVICE_SELECTORS`) was complete and dead. The
94
+ * `camera-operator` scope preset has promised "PTZ control, intercom,
95
+ * snapshots" since that same commit; the promise could not be kept. Recorded
96
+ * as D289; `scripts/check-scope-preset-promises.ts` now fails the build if a
97
+ * preset promises a cap no row of that preset can reach.
98
+ */
72
99
  readonly methods: {
73
100
  /**
74
101
  * Open a server-side WebRTC audio-only session. Returns an SDP
@@ -2394,6 +2394,11 @@ export declare const pipelineAnalyticsCapability: {
2394
2394
  readonly startStorageMigrationMove: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
2395
2395
  toLocationId: z.ZodString;
2396
2396
  throttleMbps: z.ZodOptional<z.ZodNumber>;
2397
+ mode: z.ZodOptional<z.ZodEnum<{
2398
+ move: "move";
2399
+ seal: "seal";
2400
+ gallery: "gallery";
2401
+ }>>;
2397
2402
  leaseId: z.ZodString;
2398
2403
  }, z.core.$strip>, z.ZodObject<{
2399
2404
  jobId: z.ZodString;
@@ -2436,9 +2441,29 @@ export declare const pipelineAnalyticsCapability: {
2436
2441
  readonly relocateMedia: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
2437
2442
  toLocationId: z.ZodString;
2438
2443
  throttleMbps: z.ZodOptional<z.ZodNumber>;
2444
+ mode: z.ZodOptional<z.ZodEnum<{
2445
+ move: "move";
2446
+ seal: "seal";
2447
+ gallery: "gallery";
2448
+ }>>;
2439
2449
  }, z.core.$strip>, z.ZodObject<{
2440
2450
  jobId: z.ZodString;
2441
2451
  }, z.core.$strip>, "mutation">;
2452
+ /**
2453
+ * How many media / retrain rows still carry NO `locationId`.
2454
+ *
2455
+ * A NULL row means "wherever `eventMedia` points NOW", so the instant a
2456
+ * repoint moves that pointer every such row reads from the new disk while
2457
+ * its bytes are on the old one — the archive goes dark until a drain
2458
+ * happens to stamp it. This count is what the migration planner's
2459
+ * non-blocking gate reads; `relocateMedia({ mode: 'seal' })` is what drives
2460
+ * it to zero.
2461
+ */
2462
+ readonly countUnstampedEventMedia: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{}, z.core.$strip>, z.ZodObject<{
2463
+ media: z.ZodNumber;
2464
+ retrainFrames: z.ZodNumber;
2465
+ total: z.ZodNumber;
2466
+ }, z.core.$strip>, import("./capability-definition.js").CapabilityMethodKind>;
2442
2467
  /** Every relocate job this addon knows about, newest first (in RAM: the
2443
2468
  * move is resumable, so a lost list costs nothing but the display). */
2444
2469
  readonly listRelocateMediaJobs: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{}, z.core.$strip>, z.ZodReadonly<z.ZodArray<z.ZodObject<{
@@ -15,31 +15,68 @@ export declare const storageMigrationCapability: {
15
15
  recordings: z.ZodOptional<z.ZodString>;
16
16
  recordingsLow: z.ZodOptional<z.ZodString>;
17
17
  eventMedia: z.ZodOptional<z.ZodString>;
18
+ backups: z.ZodOptional<z.ZodString>;
19
+ galleryMedia: z.ZodOptional<z.ZodString>;
18
20
  }, z.core.$strip>;
19
21
  throttleMbps: z.ZodOptional<z.ZodNumber>;
22
+ mode: z.ZodOptional<z.ZodEnum<{
23
+ blocking: "blocking";
24
+ nonBlocking: "nonBlocking";
25
+ }>>;
20
26
  }, z.core.$strip>, z.ZodObject<{
21
27
  destinations: z.ZodObject<{
22
28
  recordings: z.ZodOptional<z.ZodString>;
23
29
  recordingsLow: z.ZodOptional<z.ZodString>;
24
30
  eventMedia: z.ZodOptional<z.ZodString>;
31
+ backups: z.ZodOptional<z.ZodString>;
32
+ galleryMedia: z.ZodOptional<z.ZodString>;
25
33
  }, z.core.$strip>;
34
+ mode: z.ZodEnum<{
35
+ blocking: "blocking";
36
+ nonBlocking: "nonBlocking";
37
+ }>;
26
38
  moves: z.ZodArray<z.ZodObject<{
27
39
  storageClass: z.ZodEnum<{
28
40
  recordings: "recordings";
29
41
  recordingsLow: "recordingsLow";
30
42
  eventMedia: "eventMedia";
43
+ backups: "backups";
44
+ galleryMedia: "galleryMedia";
31
45
  }>;
32
46
  fromLocationId: z.ZodString;
33
47
  toLocationId: z.ZodString;
34
48
  }, z.core.$strip>>;
49
+ findings: z.ZodArray<z.ZodObject<{
50
+ code: z.ZodEnum<{
51
+ sharesDeviceWithSource: "sharesDeviceWithSource";
52
+ deviceIdentityUnknown: "deviceIdentityUnknown";
53
+ unstampedEventMediaRows: "unstampedEventMediaRows";
54
+ blockingOnly: "blockingOnly";
55
+ noMover: "noMover";
56
+ }>;
57
+ storageClass: z.ZodEnum<{
58
+ recordings: "recordings";
59
+ recordingsLow: "recordingsLow";
60
+ eventMedia: "eventMedia";
61
+ backups: "backups";
62
+ galleryMedia: "galleryMedia";
63
+ }>;
64
+ message: z.ZodString;
65
+ }, z.core.$strip>>;
35
66
  }, z.core.$strip>, import("./capability-definition.js").CapabilityMethodKind>;
36
67
  readonly start: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
37
68
  destinations: z.ZodObject<{
38
69
  recordings: z.ZodOptional<z.ZodString>;
39
70
  recordingsLow: z.ZodOptional<z.ZodString>;
40
71
  eventMedia: z.ZodOptional<z.ZodString>;
72
+ backups: z.ZodOptional<z.ZodString>;
73
+ galleryMedia: z.ZodOptional<z.ZodString>;
41
74
  }, z.core.$strip>;
42
75
  throttleMbps: z.ZodOptional<z.ZodNumber>;
76
+ mode: z.ZodOptional<z.ZodEnum<{
77
+ blocking: "blocking";
78
+ nonBlocking: "nonBlocking";
79
+ }>>;
43
80
  }, z.core.$strip>, z.ZodObject<{
44
81
  jobId: z.ZodString;
45
82
  }, z.core.$strip>, "mutation">;
@@ -54,15 +91,23 @@ export declare const storageMigrationCapability: {
54
91
  done: "done";
55
92
  cancelled: "cancelled";
56
93
  planning: "planning";
94
+ sealing: "sealing";
57
95
  pausing: "pausing";
96
+ draining: "draining";
58
97
  repointing: "repointing";
59
98
  refreshing: "refreshing";
60
99
  resuming: "resuming";
61
100
  }>;
101
+ mode: z.ZodEnum<{
102
+ blocking: "blocking";
103
+ nonBlocking: "nonBlocking";
104
+ }>;
62
105
  destinations: z.ZodObject<{
63
106
  recordings: z.ZodOptional<z.ZodString>;
64
107
  recordingsLow: z.ZodOptional<z.ZodString>;
65
108
  eventMedia: z.ZodOptional<z.ZodString>;
109
+ backups: z.ZodOptional<z.ZodString>;
110
+ galleryMedia: z.ZodOptional<z.ZodString>;
66
111
  }, z.core.$strip>;
67
112
  throttleMbps: z.ZodNumber;
68
113
  moves: z.ZodArray<z.ZodObject<{
@@ -70,6 +115,8 @@ export declare const storageMigrationCapability: {
70
115
  recordings: "recordings";
71
116
  recordingsLow: "recordingsLow";
72
117
  eventMedia: "eventMedia";
118
+ backups: "backups";
119
+ galleryMedia: "galleryMedia";
73
120
  }>;
74
121
  fromLocationId: z.ZodString;
75
122
  toLocationId: z.ZodString;
@@ -169,8 +169,23 @@ export declare const storageCapability: {
169
169
  createdAt: z.ZodNumber;
170
170
  updatedAt: z.ZodNumber;
171
171
  }, z.core.$strip>, "mutation">;
172
+ /**
173
+ * Remove a location record. REFUSES a location that still holds data —
174
+ * deleting a drained location whose durable rows still name it is how this
175
+ * hub acquired 2 131 ghost `recordings:high` segments, and playback does
176
+ * not stat, so the operator sees a silent black window rather than an
177
+ * error.
178
+ *
179
+ * `force` exists because the occupancy check is BEST-EFFORT and refuses on
180
+ * "unknown" as well as on "occupied" (a read that fails must not authorise
181
+ * a destruction — D49). A location on a removed disk, on another node, or
182
+ * behind a remote provider answers "unknown" forever, and a refusal an
183
+ * operator cannot override is its own failure mode. `force: true` is
184
+ * logged, loudly, with what the check saw.
185
+ */
172
186
  readonly deleteLocation: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
173
187
  id: z.ZodString;
188
+ force: z.ZodOptional<z.ZodBoolean>;
174
189
  }, z.core.$strip>, z.ZodVoid, "mutation">;
175
190
  readonly testLocation: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
176
191
  id: z.ZodString;
@@ -5121,6 +5121,13 @@ export type AppRouter = TrpcCoreRouter<{
5121
5121
  output: z.infer<typeof pipelineAnalyticsCapability.methods.relocateMedia.output>;
5122
5122
  meta: object;
5123
5123
  }>;
5124
+ countUnstampedEventMedia: TRPCQueryProcedure<{
5125
+ input: {
5126
+ [x: string]: unknown;
5127
+ } & z.input<typeof pipelineAnalyticsCapability.methods.countUnstampedEventMedia.input>;
5128
+ output: z.infer<typeof pipelineAnalyticsCapability.methods.countUnstampedEventMedia.output>;
5129
+ meta: object;
5130
+ }>;
5124
5131
  listRelocateMediaJobs: TRPCQueryProcedure<{
5125
5132
  input: {
5126
5133
  [x: string]: unknown;
@@ -6,7 +6,7 @@
6
6
  * scope+access check inside `protectedProcedure` (see
7
7
  * `server/backend/src/api/trpc/trpc.middleware.ts`).
8
8
  *
9
- * Coverage: 978 method paths across 126 capabilities.
9
+ * Coverage: 979 method paths across 126 capabilities.
10
10
  */
11
11
  import type { CapabilityMethodAccess } from '../capabilities/capability-definition.js';
12
12
  export interface MethodAccessRecord {
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_event_category = require("./event-category-BaEgqJNv.js");
3
- const require_sleep = require("./sleep-DUxF5DdC.js");
3
+ const require_sleep = require("./sleep-CJrvRDlD.js");
4
4
  const require_canonical_hash = require("./canonical-hash-DNV8S5ET.js");
5
5
  const require_enums = require("./enums.js");
6
6
  const require_err_msg = require("./err-msg-COpsHMw2.js");
@@ -2225,18 +2225,61 @@ var RelocateFootageInputSchema = zod.z.object({
2225
2225
  * `RecordingConfig.enabled` or camera wrapper bindings. */
2226
2226
  var StorageMigrationLeaseInputSchema = zod.z.object({ leaseId: zod.z.string().min(1) });
2227
2227
  var StorageMigrationFootageMoveInputSchema = RelocateFootageInputSchema.extend({ leaseId: zod.z.string().min(1) });
2228
+ /**
2229
+ * What a `relocateMedia` pass DOES. One engine, three passes — never a second
2230
+ * mover (the engine already walks both collections with a timestamp cursor and
2231
+ * already has a stamp-without-copy path).
2232
+ *
2233
+ * - `move` — the default and the historical behaviour: event-media and
2234
+ * retrain blobs move to `toLocationId` and their rows are
2235
+ * stamped. The enrolled gallery is skipped (D197).
2236
+ * - `seal` — ROWS ONLY, no bytes. Every row whose `locationId` is NULL is
2237
+ * stamped with `toLocationId`. `toLocationId` here is the id the
2238
+ * bytes ALREADY sit on — today's `eventMedia` default — because
2239
+ * a NULL row means "wherever `eventMedia` points *now*", and the
2240
+ * instant a repoint moves that pointer the row reads from the
2241
+ * new disk while its bytes are on the old one.
2242
+ * - `gallery` — the inverse selection of `move`: ONLY the retention-exempt
2243
+ * (enrolled-gallery) rows, which `move` deliberately skips.
2244
+ * `galleryMedia` is `cardinality: 'single'`, so this pass can
2245
+ * never run beside a live second location: it is stop-the-world
2246
+ * by construction, which is acceptable only because the gallery
2247
+ * is a few KB per enrolled sample.
2248
+ */
2249
+ var MediaRelocateModeSchema = zod.z.enum([
2250
+ "move",
2251
+ "seal",
2252
+ "gallery"
2253
+ ]);
2228
2254
  var RelocateMediaInputSchema = zod.z.object({
2229
2255
  toLocationId: zod.z.string(),
2230
- throttleMbps: zod.z.number().min(1).max(1e3).optional()
2256
+ throttleMbps: zod.z.number().min(1).max(1e3).optional(),
2257
+ /** Omitted = `move`, the pre-existing behaviour. */
2258
+ mode: MediaRelocateModeSchema.optional()
2259
+ });
2260
+ /** How many rows still carry NO `locationId` — the population a repoint would
2261
+ * silently re-aim at a disk that does not hold their bytes. Zero is the only
2262
+ * value that permits a non-blocking `eventMedia` cutover. */
2263
+ var UnstampedEventMediaCountSchema = zod.z.object({
2264
+ media: zod.z.number().int().nonnegative(),
2265
+ retrainFrames: zod.z.number().int().nonnegative(),
2266
+ total: zod.z.number().int().nonnegative()
2231
2267
  });
2232
2268
  var StorageMigrationMediaMoveInputSchema = RelocateMediaInputSchema.extend({ leaseId: zod.z.string().min(1) });
2233
- /** The independently selectable logical storage classes. `recordings`
2234
- * encompasses the high and mid segment profiles; `recordingsLow` is low
2235
- * segments; `eventMedia` is post-analysis blobs. */
2269
+ /** The independently selectable logical storage classes — every class
2270
+ * `storage.listLocationDeclarations` reports, so an operator never meets a
2271
+ * Zod enum error where they should meet an explanation.
2272
+ *
2273
+ * `recordings` encompasses the high and mid segment profiles; `recordingsLow`
2274
+ * is low segments; `eventMedia` is post-analysis blobs; `galleryMedia` is the
2275
+ * enrolled gallery; `backups` is the system backup archive. The last two have
2276
+ * their own rules — see {@link StorageMigrationFindingCodeSchema}. */
2236
2277
  var StorageMigrationClassSchema = zod.z.enum([
2237
2278
  "recordings",
2238
2279
  "recordingsLow",
2239
- "eventMedia"
2280
+ "eventMedia",
2281
+ "backups",
2282
+ "galleryMedia"
2240
2283
  ]);
2241
2284
  /** A destination is always an existing, fully-qualified location id. The
2242
2285
  * migration API intentionally never changes a source location's `basePath`:
@@ -2244,20 +2287,56 @@ var StorageMigrationClassSchema = zod.z.enum([
2244
2287
  var StorageMigrationDestinationsSchema = zod.z.object({
2245
2288
  recordings: zod.z.string().min(1).optional(),
2246
2289
  recordingsLow: zod.z.string().min(1).optional(),
2247
- eventMedia: zod.z.string().min(1).optional()
2290
+ eventMedia: zod.z.string().min(1).optional(),
2291
+ backups: zod.z.string().min(1).optional(),
2292
+ galleryMedia: zod.z.string().min(1).optional()
2248
2293
  }).refine((value) => Object.keys(value).length > 0, { message: "select at least one storage class" });
2294
+ /**
2295
+ * How a migration sequences the cutover against the byte move.
2296
+ *
2297
+ * - `blocking` — the historical order: pause, move every byte, repoint,
2298
+ * resume. Recording is stopped for the whole move. Right
2299
+ * for a small or a cold class, and the only legal mode for
2300
+ * a `cardinality: 'single'` class.
2301
+ * - `nonBlocking` — repoint FIRST, drain behind: seal, pause, repoint,
2302
+ * refresh, resume, then move the past with everything
2303
+ * running. The pause is three bounded instants (a detach +
2304
+ * attach round, a write-gate drain, a lease) instead of one
2305
+ * bounded by bytes. 1.09 TB at 7–14 MB/s is thirty hours of
2306
+ * stopped recording under `blocking`; the same move is
2307
+ * seconds of stopped recording under `nonBlocking`.
2308
+ *
2309
+ * The mode is on the JOB, not only on the input, because `status` is where an
2310
+ * operator finds out which one is running.
2311
+ */
2312
+ var StorageMigrationModeSchema = zod.z.enum(["blocking", "nonBlocking"]);
2249
2313
  /** Shared input for planning and starting an orchestrated storage migration. */
2250
2314
  var StorageMigrationInputSchema = zod.z.object({
2251
2315
  destinations: StorageMigrationDestinationsSchema,
2252
- throttleMbps: zod.z.number().min(1).max(1e3).optional()
2316
+ throttleMbps: zod.z.number().min(1).max(1e3).optional(),
2317
+ /** Omitted = `blocking`, which stays the default. */
2318
+ mode: StorageMigrationModeSchema.optional()
2253
2319
  });
2254
- /** The durable coordinator state machine. The only phase that changes default
2255
- * locations is `repointing`, after every selected mover has completed and been
2256
- * verified. */
2320
+ /**
2321
+ * The durable coordinator state machine.
2322
+ *
2323
+ * `blocking`:
2324
+ * planning → pausing → moving → verifying → repointing → refreshing → resuming → done
2325
+ *
2326
+ * `nonBlocking`:
2327
+ * planning → sealing → pausing → repointing → refreshing → resuming → draining → verifying → done
2328
+ *
2329
+ * Same phases, different order plus two new ones — not a second mover.
2330
+ * `sealing` closes the `eventMedia` NULL-row hole BEFORE anything is paused;
2331
+ * `draining` runs the same movers UNLEASED, after every writer is back up.
2332
+ * `repointing` is still the only phase that changes a default location.
2333
+ */
2257
2334
  var StorageMigrationPhaseSchema = zod.z.enum([
2258
2335
  "planning",
2336
+ "sealing",
2259
2337
  "pausing",
2260
2338
  "moving",
2339
+ "draining",
2261
2340
  "verifying",
2262
2341
  "repointing",
2263
2342
  "refreshing",
@@ -2282,6 +2361,9 @@ var StorageMigrationMoveSchema = zod.z.object({
2282
2361
  var StorageMigrationJobSchema = zod.z.object({
2283
2362
  jobId: zod.z.string(),
2284
2363
  phase: StorageMigrationPhaseSchema,
2364
+ /** Which order this job is running. `status` is the only place an operator
2365
+ * can tell a seconds-long cutover from a thirty-hour one. */
2366
+ mode: StorageMigrationModeSchema,
2285
2367
  destinations: StorageMigrationDestinationsSchema,
2286
2368
  throttleMbps: zod.z.number(),
2287
2369
  moves: zod.z.array(StorageMigrationMoveSchema),
@@ -2294,13 +2376,54 @@ var StorageMigrationJobSchema = zod.z.object({
2294
2376
  finishedAt: zod.z.number().nullable(),
2295
2377
  error: zod.z.string().nullable()
2296
2378
  });
2379
+ /**
2380
+ * What the planner NOTICED but did not refuse.
2381
+ *
2382
+ * A refusal throws — the operator cannot miss it. A finding is the other half:
2383
+ * something true about this plan that changes what the operator should expect,
2384
+ * surfaced where they read it rather than in a document they will not open.
2385
+ *
2386
+ * - `sharesDeviceWithSource` — the destination realpath's to the same place as
2387
+ * the source. The move will be a row re-stamp, not a byte move, and it buys
2388
+ * no redundancy. NOTE: this is PATH identity, not `st_dev` — two distinct
2389
+ * directories on one filesystem are NOT detected. See
2390
+ * `deviceIdentityUnknown`.
2391
+ * - `deviceIdentityUnknown` — a location carries a `nodeId` other than this
2392
+ * one (or has no `basePath`), so its realpath cannot be taken here and the
2393
+ * same-device question was not answered at all. Stated rather than assumed
2394
+ * clear: a check that silently never fires is worse than no check.
2395
+ * - `unstampedEventMediaRows` — how many `eventMedia`/retrain rows still carry
2396
+ * no `locationId`. Non-zero refuses a `nonBlocking` cutover.
2397
+ * - `blockingOnly` — this class is `cardinality: 'single'`, so it can never
2398
+ * span two locations and can only ever be moved stop-the-world.
2399
+ * - `noMover` — the class is selectable and planned, but no addon owns a mover
2400
+ * for it. The migration cannot move its bytes.
2401
+ */
2402
+ var StorageMigrationFindingCodeSchema = zod.z.enum([
2403
+ "sharesDeviceWithSource",
2404
+ "deviceIdentityUnknown",
2405
+ "unstampedEventMediaRows",
2406
+ "blockingOnly",
2407
+ "noMover"
2408
+ ]);
2409
+ var StorageMigrationFindingSchema = zod.z.object({
2410
+ code: StorageMigrationFindingCodeSchema,
2411
+ storageClass: StorageMigrationClassSchema,
2412
+ /** Human-readable, already carrying the ids and counts. */
2413
+ message: zod.z.string()
2414
+ });
2297
2415
  var StorageMigrationPlanSchema = zod.z.object({
2298
2416
  destinations: StorageMigrationDestinationsSchema,
2417
+ /** The mode this plan was built for. A plan is only valid for its mode: the
2418
+ * `eventMedia` seal gate and the single-cardinality refusal both depend on
2419
+ * it. */
2420
+ mode: StorageMigrationModeSchema,
2299
2421
  moves: zod.z.array(zod.z.object({
2300
2422
  storageClass: StorageMigrationClassSchema,
2301
2423
  fromLocationId: zod.z.string(),
2302
2424
  toLocationId: zod.z.string()
2303
- }))
2425
+ })),
2426
+ findings: zod.z.array(StorageMigrationFindingSchema)
2304
2427
  });
2305
2428
  //#endregion
2306
2429
  //#region src/interfaces/server-analysis.ts
@@ -18630,6 +18753,17 @@ var pipelineAnalyticsCapability = {
18630
18753
  kind: "mutation",
18631
18754
  auth: "admin"
18632
18755
  }),
18756
+ /**
18757
+ * How many media / retrain rows still carry NO `locationId`.
18758
+ *
18759
+ * A NULL row means "wherever `eventMedia` points NOW", so the instant a
18760
+ * repoint moves that pointer every such row reads from the new disk while
18761
+ * its bytes are on the old one — the archive goes dark until a drain
18762
+ * happens to stamp it. This count is what the migration planner's
18763
+ * non-blocking gate reads; `relocateMedia({ mode: 'seal' })` is what drives
18764
+ * it to zero.
18765
+ */
18766
+ countUnstampedEventMedia: require_sleep.method(zod.z.object({}), UnstampedEventMediaCountSchema, { auth: "admin" }),
18633
18767
  /** Every relocate job this addon knows about, newest first (in RAM: the
18634
18768
  * move is resumable, so a lost list costs nothing but the display). */
18635
18769
  listRelocateMediaJobs: require_sleep.method(zod.z.object({}), zod.z.array(RelocateJobSchema).readonly(), {
@@ -21702,7 +21836,24 @@ var storageCapability = {
21702
21836
  kind: "mutation",
21703
21837
  auth: "admin"
21704
21838
  }),
21705
- deleteLocation: require_sleep.method(zod.z.object({ id: zod.z.string() }), zod.z.void(), {
21839
+ /**
21840
+ * Remove a location record. REFUSES a location that still holds data —
21841
+ * deleting a drained location whose durable rows still name it is how this
21842
+ * hub acquired 2 131 ghost `recordings:high` segments, and playback does
21843
+ * not stat, so the operator sees a silent black window rather than an
21844
+ * error.
21845
+ *
21846
+ * `force` exists because the occupancy check is BEST-EFFORT and refuses on
21847
+ * "unknown" as well as on "occupied" (a read that fails must not authorise
21848
+ * a destruction — D49). A location on a removed disk, on another node, or
21849
+ * behind a remote provider answers "unknown" forever, and a refusal an
21850
+ * operator cannot override is its own failure mode. `force: true` is
21851
+ * logged, loudly, with what the check saw.
21852
+ */
21853
+ deleteLocation: require_sleep.method(zod.z.object({
21854
+ id: zod.z.string(),
21855
+ force: zod.z.boolean().optional()
21856
+ }), zod.z.void(), {
21706
21857
  kind: "mutation",
21707
21858
  auth: "admin"
21708
21859
  }),
@@ -26657,6 +26808,33 @@ var intercomCapability = {
26657
26808
  deviceNative: true,
26658
26809
  mode: "singleton",
26659
26810
  deviceTypes: [require_sleep.DeviceType.Camera],
26811
+ /**
26812
+ * **Auth tier: `protected` on every method — deliberate, and load-bearing.**
26813
+ *
26814
+ * Talking through a camera is an OPERATE action, not a CONFIGURE one. This
26815
+ * cap has no configuration surface at all: all six methods open, feed and
26816
+ * close one live audio session against one `deviceId`. That is the same
26817
+ * authority as `ptz.move` or `snapshot.getSnapshot`, both `protected` — and
26818
+ * the opposite of `ptz.savePreset` / `snapshot.invalidateCache`, which are
26819
+ * `admin` because they change what the device IS.
26820
+ *
26821
+ * `protected` does not mean ungated: `protectedProcedure` runs the
26822
+ * `METHOD_ACCESS_MAP` scope check, and every method here is `scope: 'device'`
26823
+ * with `access: 'create'` and a `deviceId` in its input. So a caller needs a
26824
+ * grant that covers THAT camera at `create` — a `camera-viewer` (`view`
26825
+ * only) still cannot talk, and a grant on camera 5 cannot talk through
26826
+ * camera 7.
26827
+ *
26828
+ * Every method was `auth: 'admin'` from the initial commit, which made the
26829
+ * cap unreachable by every non-admin principal — `adminProcedure` throws
26830
+ * `FORBIDDEN: Admin required` BEFORE the scope check runs, so the scope
26831
+ * machinery generated for this cap (`METHOD_ACCESS_MAP`,
26832
+ * `DEVICE_SCOPED_CAPS`, `METHOD_DEVICE_SELECTORS`) was complete and dead. The
26833
+ * `camera-operator` scope preset has promised "PTZ control, intercom,
26834
+ * snapshots" since that same commit; the promise could not be kept. Recorded
26835
+ * as D289; `scripts/check-scope-preset-promises.ts` now fails the build if a
26836
+ * preset promises a cap no row of that preset can reach.
26837
+ */
26660
26838
  methods: {
26661
26839
  /**
26662
26840
  * Open a server-side WebRTC audio-only session. Returns an SDP
@@ -26669,7 +26847,7 @@ var intercomCapability = {
26669
26847
  sdpOffer: zod.z.string()
26670
26848
  }), {
26671
26849
  kind: "mutation",
26672
- auth: "admin"
26850
+ auth: "protected"
26673
26851
  }),
26674
26852
  handleAnswer: require_sleep.method(zod.z.object({
26675
26853
  deviceId: zod.z.number(),
@@ -26677,7 +26855,7 @@ var intercomCapability = {
26677
26855
  sdpAnswer: zod.z.string()
26678
26856
  }), zod.z.void(), {
26679
26857
  kind: "mutation",
26680
- auth: "admin"
26858
+ auth: "protected"
26681
26859
  }),
26682
26860
  /** Close explicitly. Server also auto-closes on 30s idle. */
26683
26861
  stopSession: require_sleep.method(zod.z.object({
@@ -26685,7 +26863,7 @@ var intercomCapability = {
26685
26863
  sessionId: zod.z.string()
26686
26864
  }), zod.z.void(), {
26687
26865
  kind: "mutation",
26688
- auth: "admin"
26866
+ auth: "protected"
26689
26867
  }),
26690
26868
  /**
26691
26869
  * Open a raw-PCM talk session (no WebRTC SDP plumbing). Used by
@@ -26698,7 +26876,7 @@ var intercomCapability = {
26698
26876
  */
26699
26877
  startTalkSession: require_sleep.method(zod.z.object({ deviceId: zod.z.number() }), zod.z.object({ sessionId: zod.z.string() }), {
26700
26878
  kind: "mutation",
26701
- auth: "admin"
26879
+ auth: "protected"
26702
26880
  }),
26703
26881
  /**
26704
26882
  * Push one chunk of talk-back audio onto the active talk session.
@@ -26733,12 +26911,12 @@ var intercomCapability = {
26733
26911
  sequenceNumber: zod.z.number().int()
26734
26912
  }), zod.z.object({ accepted: zod.z.boolean() }), {
26735
26913
  kind: "mutation",
26736
- auth: "admin"
26914
+ auth: "protected"
26737
26915
  }),
26738
26916
  /** Close the raw-PCM talk session. Idempotent. */
26739
26917
  endTalkSession: require_sleep.method(zod.z.object({ deviceId: zod.z.number() }), zod.z.void(), {
26740
26918
  kind: "mutation",
26741
- auth: "admin"
26919
+ auth: "protected"
26742
26920
  })
26743
26921
  },
26744
26922
  events: { onStatusChanged: { data: zod.z.object({
@@ -40712,6 +40890,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
40712
40890
  addonId: null,
40713
40891
  access: "create"
40714
40892
  },
40893
+ "pipelineAnalytics.countUnstampedEventMedia": {
40894
+ capName: "pipeline-analytics",
40895
+ capScope: "device",
40896
+ addonId: null,
40897
+ access: "view"
40898
+ },
40715
40899
  "pipelineAnalytics.deleteDeviceEvents": {
40716
40900
  capName: "pipeline-analytics",
40717
40901
  capScope: "device",
@@ -45954,7 +46138,7 @@ var SCOPE_PRESETS = [
45954
46138
  {
45955
46139
  id: "camera-operator",
45956
46140
  label: "Camera operator",
45957
- description: "Everything `camera-viewer` does plus PTZ control, intercom, snapshots and recording start/stop. Cannot delete devices or recordings.",
46141
+ description: "Everything `camera-viewer` does plus live control of every granted camera — PTZ movement, intercom talk-back and on-demand snapshots. Cannot delete devices, and grants nothing on system-scope caps (recording control, users, addons).",
45958
46142
  rows: [{
45959
46143
  type: "category",
45960
46144
  target: "device",
@@ -51077,6 +51261,7 @@ exports.MediaFileSchema = MediaFileSchema;
51077
51261
  exports.MediaPlayerRepeatSchema = MediaPlayerRepeatSchema;
51078
51262
  exports.MediaPlayerStateSchema = MediaPlayerStateSchema;
51079
51263
  exports.MediaPlayerStatusSchema = MediaPlayerStatusSchema;
51264
+ exports.MediaRelocateModeSchema = MediaRelocateModeSchema;
51080
51265
  exports.MeshPeerSchema = MeshPeerSchema;
51081
51266
  exports.MeshStatusSchema = MeshStatusSchema;
51082
51267
  exports.MethodAccessSchema = MethodAccessSchema;
@@ -51454,11 +51639,14 @@ exports.StorageLocationSchema = StorageLocationSchema;
51454
51639
  exports.StorageLocationTypeSchema = StorageLocationTypeSchema;
51455
51640
  exports.StorageMigrationClassSchema = StorageMigrationClassSchema;
51456
51641
  exports.StorageMigrationDestinationsSchema = StorageMigrationDestinationsSchema;
51642
+ exports.StorageMigrationFindingCodeSchema = StorageMigrationFindingCodeSchema;
51643
+ exports.StorageMigrationFindingSchema = StorageMigrationFindingSchema;
51457
51644
  exports.StorageMigrationFootageMoveInputSchema = StorageMigrationFootageMoveInputSchema;
51458
51645
  exports.StorageMigrationInputSchema = StorageMigrationInputSchema;
51459
51646
  exports.StorageMigrationJobSchema = StorageMigrationJobSchema;
51460
51647
  exports.StorageMigrationLeaseInputSchema = StorageMigrationLeaseInputSchema;
51461
51648
  exports.StorageMigrationMediaMoveInputSchema = StorageMigrationMediaMoveInputSchema;
51649
+ exports.StorageMigrationModeSchema = StorageMigrationModeSchema;
51462
51650
  exports.StorageMigrationMoveSchema = StorageMigrationMoveSchema;
51463
51651
  exports.StorageMigrationParticipantSchema = StorageMigrationParticipantSchema;
51464
51652
  exports.StorageMigrationPhaseSchema = StorageMigrationPhaseSchema;
@@ -51534,6 +51722,7 @@ exports.UNATTRIBUTED_BUCKET_KEY = UNATTRIBUTED_BUCKET_KEY;
51534
51722
  exports.UNIT_TABLE = UNIT_TABLE;
51535
51723
  exports.UnifiedBrokerInfoSchema = BrokerInfoSchema$1;
51536
51724
  exports.UnitConversionError = UnitConversionError;
51725
+ exports.UnstampedEventMediaCountSchema = UnstampedEventMediaCountSchema;
51537
51726
  exports.UpdateIntegrationInputSchema = UpdateIntegrationInputSchema;
51538
51727
  exports.UpdateStatusSchema = UpdateStatusSchema;
51539
51728
  exports.UpdateUserInputSchema = UpdateUserInputSchema;