@camstack/addon-remote-storage 1.2.24 → 1.2.26

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-CAxkUIT8.js");
5
+ const require_shared = require("./shared-UN8idVfB.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-CMeaUSWI.mjs";
1
+ import { c as BaseAddon, i as rearmIdleAbort, n as getOptionalBasePath, o as scheduleIdleAbort, s as storageProviderCapability, t as createSessionId } from "./shared-BwialOVX.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-CAxkUIT8.js");
5
+ const require_shared = require("./shared-UN8idVfB.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-CMeaUSWI.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-BwialOVX.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
@@ -1,6 +1,6 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import * as path from "node:path";
3
- //#region ../types/dist/event-category-XfKNtfCc.mjs
3
+ //#region ../types/dist/event-category-CIa_iT6b.mjs
4
4
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
5
5
  EventCategory["SystemBoot"] = "system.boot";
6
6
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -16,6 +16,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
16
16
  */
17
17
  EventCategory["SystemRestartCompleted"] = "system.restart-completed";
18
18
  /**
19
+ * The hub reissued its own TLS certificate at boot (`ensureTlsCert`).
20
+ * Emitted only when the material on disk actually changed, so an
21
+ * operator who trusted the old certificate by hand is told rather than
22
+ * discovering it as a browser error. Payload `TlsCertChangedPayload`.
23
+ *
24
+ * Rule: docs/decisions/adr-0227-*.md
25
+ */
26
+ EventCategory["SystemTlsCertChanged"] = "system.tls-cert-changed";
27
+ /**
19
28
  * A newer addon or server-root package version was found by the
20
29
  * authoritative registry check. Emitted once when any observed
21
30
  * `latestVersion` changes (or a package/node first appears behind);
@@ -7996,6 +8005,15 @@ var LabelDefinitionSchema = object({
7996
8005
  description: string().optional(),
7997
8006
  icon: string().optional()
7998
8007
  });
8008
+ var ClassMapDefinitionSchema = object({
8009
+ mapping: record(string(), _enum([
8010
+ "person",
8011
+ "vehicle",
8012
+ "animal",
8013
+ "package"
8014
+ ])),
8015
+ preserveOriginal: boolean()
8016
+ });
7999
8017
  var MODEL_FORMATS = [
8000
8018
  "onnx",
8001
8019
  "coreml",
@@ -8174,7 +8192,13 @@ var ModelCatalogEntrySchema = object({
8174
8192
  * `id` stays the source of truth for resolution/download/persistence; grouping
8175
8193
  * is a presentation overlay resolved back to an `id`.
8176
8194
  */
8177
- group: ModelVariantGroupSchema.optional()
8195
+ group: ModelVariantGroupSchema.optional(),
8196
+ /**
8197
+ * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
8198
+ * applies (Frigate / COCO public catalog). Set on a custom model whose raw
8199
+ * labels already ARE the CamStack macros (Scrypted identity map).
8200
+ */
8201
+ classMap: ClassMapDefinitionSchema.optional()
8178
8202
  });
8179
8203
  var ConvertTargetSchema = discriminatedUnion("format", [object({
8180
8204
  format: literal("openvino"),
@@ -8203,7 +8227,8 @@ var ModelConvertMetadataSchema = object({
8203
8227
  "ocr",
8204
8228
  "segmentation"
8205
8229
  ]),
8206
- faceAlignment: boolean().optional()
8230
+ faceAlignment: boolean().optional(),
8231
+ classMap: ClassMapDefinitionSchema.optional()
8207
8232
  });
8208
8233
  var ConvertResultSchema = object({
8209
8234
  entry: ModelCatalogEntrySchema,
@@ -17194,6 +17219,33 @@ var NativeCropRefSchema = object({
17194
17219
  h: number()
17195
17220
  })
17196
17221
  });
17222
+ object({
17223
+ crop: object({
17224
+ left: number(),
17225
+ top: number(),
17226
+ width: number().positive(),
17227
+ height: number().positive()
17228
+ }).optional(),
17229
+ content: object({
17230
+ width: number().int().positive(),
17231
+ height: number().int().positive()
17232
+ }),
17233
+ fit: _enum(["stretch", "contain"]),
17234
+ format: _enum([
17235
+ "rgb",
17236
+ "gray",
17237
+ "jpeg"
17238
+ ])
17239
+ });
17240
+ var FrameRefSchema = object({
17241
+ registryId: string().min(1),
17242
+ id: string().min(1),
17243
+ width: number().int().positive(),
17244
+ height: number().int().positive(),
17245
+ format: _enum(["rgb", "gray"]),
17246
+ timestamp: number(),
17247
+ capturedAt: number().optional()
17248
+ });
17197
17249
  var ModelFormatSchema$1 = _enum([
17198
17250
  "onnx",
17199
17251
  "coreml",
@@ -17438,6 +17490,12 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
17438
17490
  steps: array(PipelineStepInputSchema).min(1),
17439
17491
  frame: FrameInputSchema.optional(),
17440
17492
  /**
17493
+ * Process-local lazy frame. Valid only when caller and provider resolve
17494
+ * in the same execution-group process; split/cross-node callers use
17495
+ * `frame`/`image` inline compatibility instead.
17496
+ */
17497
+ frameRef: FrameRefSchema.optional(),
17498
+ /**
17441
17499
  * CB5 shm passthrough — a `FrameHandle` naming the same ring slot
17442
17500
  * the decoded pixels live in. One more member of the one-of
17443
17501
  * frame/frameHandle/image/imageBase64/referenceImage group.
@@ -17693,7 +17751,10 @@ var NativeCropResultSchema = object({
17693
17751
  * Which source served this crop, so a quality-sensitive consumer (the native
17694
17752
  * `keyFrame`) can reject a degraded fallback:
17695
17753
  * - `native` — cut from the decode worker's retained NATIVE surface (the
17696
- * quality path).
17754
+ * quality path). A subject-tile serve is also native-resolution and stays
17755
+ * `native` here: the public enum cannot name `tile` without a breaking cap
17756
+ * change. Runner telemetry distinguishes lease vs tile via `source` on the
17757
+ * internal crop result (`nativeHits` vs `tileHits`).
17697
17758
  * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
17698
17759
  * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
17699
17760
  * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
@@ -18184,12 +18245,41 @@ var RunnerLocalLoadSchema = object({
18184
18245
  * legacy `OrchestratorMetricsSchema` shape so existing dashboards keep
18185
18246
  * working unchanged when they switch to reading from the runner cap.
18186
18247
  */
18248
+ var FrameLazyCountersSchema = object({
18249
+ framesDecoded: number(),
18250
+ framesAdmitted: number(),
18251
+ framesDroppedPixelFree: number(),
18252
+ viewsMaterialized: number(),
18253
+ viewsSkipped: number(),
18254
+ workerToRunnerBytes: number(),
18255
+ runnerToPoolRawBytes: number(),
18256
+ runnerToPoolJpegBytes: number(),
18257
+ onDemandFullFrameRequests: number(),
18258
+ onDemandCropRequests: number(),
18259
+ nativeHits: number(),
18260
+ nativeMisses: number(),
18261
+ tileHits: number(),
18262
+ tileMisses: number(),
18263
+ fallbackHits: number(),
18264
+ fallbackMisses: number(),
18265
+ retainedWritesAvoided: number(),
18266
+ residentRefs: number(),
18267
+ residentBytes: number(),
18268
+ releases: number(),
18269
+ evictions: number(),
18270
+ staleMisses: number()
18271
+ });
18272
+ var FrameLazyMetricsSchema = object({
18273
+ node: FrameLazyCountersSchema,
18274
+ cameras: array(FrameLazyCountersSchema.extend({ deviceId: number() }))
18275
+ });
18187
18276
  var RunnerLocalMetricsSchema = object({
18188
18277
  nodeId: string(),
18189
18278
  activeCameras: number(),
18190
18279
  throttledCameras: number(),
18191
18280
  avgInferenceTimeMs: number(),
18192
- queueDepth: number()
18281
+ queueDepth: number(),
18282
+ frameLazy: FrameLazyMetricsSchema.optional()
18193
18283
  });
18194
18284
  method(RunnerCameraConfigSchema, object({ success: literal(true) }), { kind: "mutation" }), method(object({ deviceId: number() }), object({ success: literal(true) }), { kind: "mutation" }), method(ReportMotionInputSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), RunnerLocalLoadSchema), method(_void(), RunnerLocalMetricsSchema), method(object({ deviceId: number() }), CameraMetricsSchema.nullable()), method(_void(), array(CameraMetricsWithDeviceIdSchema).readonly()), method(_void(), array(number()).readonly()), method(object({
18195
18285
  handle: FrameHandleSchema,
@@ -19534,6 +19624,9 @@ var storageProviderCapability = {
19534
19624
  endDownload: method(EndDownloadInputSchema, _void(), { kind: "mutation" })
19535
19625
  }
19536
19626
  };
19627
+ /** Profile-exported FormBuilder schema. Shape is ConfigUISchema at the UI. */
19628
+ var ProfileSettingsSchemaBridge = unknown().nullable();
19629
+ var ProfileSettingsBagSchema = record(string(), unknown());
19537
19630
  /**
19538
19631
  * A live terminal session hosted by the provider addon. Output and input do
19539
19632
  * NOT flow through the capability — they use the addon data plane
@@ -19563,7 +19656,14 @@ var TerminalSessionInfoSchema = object({
19563
19656
  var TerminalProfileInfoSchema = object({
19564
19657
  profileId: string(),
19565
19658
  label: string(),
19566
- description: string().optional()
19659
+ description: string().optional(),
19660
+ /** Spawn defaults the instance form copies on create. */
19661
+ executable: string().optional(),
19662
+ args: array(string()).readonly().optional(),
19663
+ cwd: string().optional(),
19664
+ environment: array(string()).readonly().optional(),
19665
+ /** ConfigUISchema for instance knobs, or null when the profile has none. */
19666
+ settingsSchema: ProfileSettingsSchemaBridge.optional()
19567
19667
  });
19568
19668
  /**
19569
19669
  * A durable operator-created Terminal instance. Profiles are templates; only
@@ -19576,7 +19676,12 @@ var TerminalInstanceInfoSchema = object({
19576
19676
  profileId: string(),
19577
19677
  profileLabel: string(),
19578
19678
  name: string(),
19579
- enabled: boolean()
19679
+ enabled: boolean(),
19680
+ executable: string(),
19681
+ args: array(string()).readonly(),
19682
+ cwd: string(),
19683
+ environment: array(string()).readonly(),
19684
+ profileSettings: ProfileSettingsBagSchema
19580
19685
  });
19581
19686
  var TerminalLegacyCameraSchema = object({
19582
19687
  stableId: string(),
@@ -19606,7 +19711,23 @@ var TerminalOutputBatchSchema = object({
19606
19711
  method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }), method(_void(), array(TerminalInstanceInfoSchema).readonly(), { auth: "admin" }), method(object({
19607
19712
  targetNodeId: string().min(1),
19608
19713
  profileId: string().min(1),
19609
- name: string().trim().min(1).max(160).optional()
19714
+ name: string().trim().min(1).max(160).optional(),
19715
+ executable: string().max(1024).optional(),
19716
+ args: array(string().max(2048)).max(64).optional(),
19717
+ cwd: string().max(1024).optional(),
19718
+ environment: array(string().max(4096)).max(64).optional(),
19719
+ profileSettings: ProfileSettingsBagSchema.optional()
19720
+ }), TerminalInstanceInfoSchema, {
19721
+ kind: "mutation",
19722
+ auth: "admin"
19723
+ }), method(object({
19724
+ instanceId: string().min(1),
19725
+ name: string().trim().min(1).max(160).optional(),
19726
+ executable: string().max(1024).optional(),
19727
+ args: array(string().max(2048)).max(64).optional(),
19728
+ cwd: string().max(1024).optional(),
19729
+ environment: array(string().max(4096)).max(64).optional(),
19730
+ profileSettings: ProfileSettingsBagSchema.optional()
19610
19731
  }), TerminalInstanceInfoSchema, {
19611
19732
  kind: "mutation",
19612
19733
  auth: "admin"
@@ -19628,7 +19749,11 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
19628
19749
  }), method(_void(), array(TerminalSessionInfoSchema).readonly(), { auth: "admin" }), method(object({
19629
19750
  profileId: string(),
19630
19751
  cols: number().int().positive(),
19631
- rows: number().int().positive()
19752
+ rows: number().int().positive(),
19753
+ executable: string().max(1024).optional(),
19754
+ args: array(string().max(2048)).max(64).optional(),
19755
+ cwd: string().max(1024).optional(),
19756
+ environment: array(string().max(4096)).max(64).optional()
19632
19757
  }), TerminalSessionInfoSchema, {
19633
19758
  kind: "mutation",
19634
19759
  auth: "admin"
@@ -22410,10 +22535,10 @@ DeviceType.LawnMower, method(object({ deviceId: number().int().nonnegative() }),
22410
22535
  *
22411
22536
  * • The SDK (mobile / web client) consumes `getConnectionEndpoints()`
22412
22537
  * to receive an ordered list of candidate base URLs it should race
22413
- * on connect — LAN IPv4 first (lowest latency when on same network),
22414
- * then public hostname (if a tunnel is up), then IPv6. The SDK can
22415
- * race them with short timeouts and stick with the winner for the
22416
- * session.
22538
+ * on connect — LAN IPv4 and stable LAN IPv6 first (lowest latency
22539
+ * when on the same network), then public hostname (if a tunnel is
22540
+ * up). The SDK can race them with short timeouts and stick with the
22541
+ * winner for the session.
22417
22542
  *
22418
22543
  * Why hub-only: agents are not directly addressable by the operator's
22419
22544
  * clients — they reverse-connect to the hub. Exposing their interfaces
@@ -22568,6 +22693,17 @@ var NotificationEndpointSchema = object({
22568
22693
  /** What the ranking currently resolves to (null when nothing is reachable). */
22569
22694
  resolved: string().nullable()
22570
22695
  });
22696
+ /**
22697
+ * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
22698
+ * AUTO (every LAN IPv4 + the public tunnel). `resolved` is what that choice
22699
+ * currently expands to, so the UI can show the effective set either way.
22700
+ */
22701
+ var ViewerEndpointsSchema = object({
22702
+ /** The operator's explicit race set, or empty for AUTO. */
22703
+ baseUrls: array(string()).readonly(),
22704
+ /** What the ranking currently resolves to (may be empty if nothing is up). */
22705
+ resolved: array(string()).readonly()
22706
+ });
22571
22707
  var AllowedAddressesSchema = object({
22572
22708
  /**
22573
22709
  * Allowlist of interface addresses operators have explicitly opted
@@ -22576,6 +22712,20 @@ var AllowedAddressesSchema = object({
22576
22712
  * Network Addresses admin page and persisted by the addon.
22577
22713
  */
22578
22714
  addresses: array(string()).readonly() });
22715
+ var TlsStatusSchema = object({
22716
+ mode: _enum([
22717
+ "generated",
22718
+ "uploaded",
22719
+ "disabled"
22720
+ ]),
22721
+ leafFingerprintSha256: string().nullable(),
22722
+ caFingerprintSha256: string().nullable(),
22723
+ validTo: string().nullable(),
22724
+ sans: array(string()),
22725
+ caCertPem: string().nullable(),
22726
+ reissueError: string().nullable(),
22727
+ restartRequired: boolean()
22728
+ });
22579
22729
  method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
22580
22730
  /**
22581
22731
  * LEGACY HINT — do not send from new code. Kept optional so clients
@@ -22585,17 +22735,31 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
22585
22735
  */
22586
22736
  port: number().int().min(1).max(65535).optional(),
22587
22737
  /** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
22588
- * candidate. Default `true`. */
22738
+ * candidate. Default `false` — loopback is not a client route. */
22589
22739
  includeLoopback: boolean().optional(),
22590
- /** Skip IPv6 entries. Some legacy clients can't parse them.
22591
- * Default `false`. */
22740
+ /** Skip IPv6 entries. Default `false` the palette includes stable
22741
+ * LAN IPv6 (ICE/WebRTC uses dual-stack regardless). Pass `true` to
22742
+ * hide them. The viewer HTTP/WS race is `getViewerEndpoints`. */
22592
22743
  ipv4Only: boolean().optional(),
22593
22744
  /** Scheme to emit for LAN/loopback URLs. Default `'http'`.
22594
22745
  * Pass `'https'` when the caller is itself loaded over HTTPS
22595
22746
  * to avoid mixed-content blocks in the browser. The public
22596
22747
  * tunnel always emits `https://` regardless. */
22597
22748
  scheme: _enum(["http", "https"]).optional()
22598
- }), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" });
22749
+ }), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), ViewerEndpointsSchema), method(object({ baseUrls: array(string()).readonly() }), ViewerEndpointsSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" }), method(_void(), TlsStatusSchema), method(object({ reason: string().optional() }), TlsStatusSchema, {
22750
+ kind: "mutation",
22751
+ auth: "admin"
22752
+ }), method(object({
22753
+ certPem: string().min(1),
22754
+ keyPem: string().min(1),
22755
+ caPem: string().optional()
22756
+ }), TlsStatusSchema, {
22757
+ kind: "mutation",
22758
+ auth: "admin"
22759
+ }), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
22760
+ kind: "mutation",
22761
+ auth: "admin"
22762
+ });
22599
22763
  object({
22600
22764
  /** Lifecycle state of the lock. `jammed` means the motor reported
22601
22765
  * failure to reach the target — operator intervention required. */
@@ -28358,6 +28522,12 @@ Object.freeze({
28358
28522
  addonId: null,
28359
28523
  access: "create"
28360
28524
  },
28525
+ "localNetwork.downloadCa": {
28526
+ capName: "local-network",
28527
+ capScope: "system",
28528
+ addonId: null,
28529
+ access: "view"
28530
+ },
28361
28531
  "localNetwork.getAllowedAddresses": {
28362
28532
  capName: "local-network",
28363
28533
  capScope: "system",
@@ -28382,18 +28552,42 @@ Object.freeze({
28382
28552
  addonId: null,
28383
28553
  access: "view"
28384
28554
  },
28555
+ "localNetwork.getTlsStatus": {
28556
+ capName: "local-network",
28557
+ capScope: "system",
28558
+ addonId: null,
28559
+ access: "view"
28560
+ },
28561
+ "localNetwork.getViewerEndpoints": {
28562
+ capName: "local-network",
28563
+ capScope: "system",
28564
+ addonId: null,
28565
+ access: "view"
28566
+ },
28385
28567
  "localNetwork.list": {
28386
28568
  capName: "local-network",
28387
28569
  capScope: "system",
28388
28570
  addonId: null,
28389
28571
  access: "view"
28390
28572
  },
28573
+ "localNetwork.regenerateCertificate": {
28574
+ capName: "local-network",
28575
+ capScope: "system",
28576
+ addonId: null,
28577
+ access: "create"
28578
+ },
28391
28579
  "localNetwork.resetAllowlistToBestMatch": {
28392
28580
  capName: "local-network",
28393
28581
  capScope: "system",
28394
28582
  addonId: null,
28395
28583
  access: "delete"
28396
28584
  },
28585
+ "localNetwork.revertToGeneratedCertificate": {
28586
+ capName: "local-network",
28587
+ capScope: "system",
28588
+ addonId: null,
28589
+ access: "create"
28590
+ },
28397
28591
  "localNetwork.setAllowedAddresses": {
28398
28592
  capName: "local-network",
28399
28593
  capScope: "system",
@@ -28406,6 +28600,18 @@ Object.freeze({
28406
28600
  addonId: null,
28407
28601
  access: "create"
28408
28602
  },
28603
+ "localNetwork.setViewerEndpoints": {
28604
+ capName: "local-network",
28605
+ capScope: "system",
28606
+ addonId: null,
28607
+ access: "create"
28608
+ },
28609
+ "localNetwork.uploadCertificate": {
28610
+ capName: "local-network",
28611
+ capScope: "system",
28612
+ addonId: null,
28613
+ access: "create"
28614
+ },
28409
28615
  "lockControl.lock": {
28410
28616
  capName: "lock-control",
28411
28617
  capScope: "device",
@@ -31286,6 +31492,12 @@ Object.freeze({
31286
31492
  addonId: null,
31287
31493
  access: "create"
31288
31494
  },
31495
+ "terminalSession.updateInstance": {
31496
+ capName: "terminal-session",
31497
+ capScope: "system",
31498
+ addonId: null,
31499
+ access: "create"
31500
+ },
31289
31501
  "terminalSession.writeInput": {
31290
31502
  capName: "terminal-session",
31291
31503
  capScope: "system",
@@ -33773,6 +33985,35 @@ Object.freeze(Object.fromEntries([{
33773
33985
  }]
33774
33986
  }].map((s) => [s.stepId, s.defaultModelId])));
33775
33987
  string().min(1);
33988
+ var CLUSTER_STEP_SETTING_FIELDS = [{
33989
+ stepId: "face-embedding",
33990
+ key: "minLandmarkFaceSize",
33991
+ label: "Min face size for recognition (detection px)",
33992
+ description: "Refuse to embed a face smaller than this IN THE DETECTION FRAME. Applies to every node — the enrolled gallery is one index, and two admission floors would fill it from two policies. 0 disables the gate.",
33993
+ type: "slider",
33994
+ min: 0,
33995
+ max: 64,
33996
+ step: 2,
33997
+ default: 24
33998
+ }];
33999
+ function clusterStepSettingKey(stepId, fieldKey) {
34000
+ return `clusterStepSetting:${stepId}:${fieldKey}`;
34001
+ }
34002
+ var ClusterSettingNumberSchema = number().finite();
34003
+ function readClusterStepSettings(config) {
34004
+ const out = {};
34005
+ for (const field of CLUSTER_STEP_SETTING_FIELDS) {
34006
+ const parsed = ClusterSettingNumberSchema.safeParse(config[clusterStepSettingKey(field.stepId, field.key)]);
34007
+ const value = parsed.success ? parsed.data : field.default;
34008
+ const existing = out[field.stepId] ?? {};
34009
+ out[field.stepId] = {
34010
+ ...existing,
34011
+ [field.key]: value
34012
+ };
34013
+ }
34014
+ return out;
34015
+ }
34016
+ readClusterStepSettings({});
33776
34017
  object({
33777
34018
  /**
33778
34019
  * Fraction of the box's own size added on EACH side before cutting.
@@ -23,7 +23,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
23
  let node_crypto = require("node:crypto");
24
24
  let node_path = require("node:path");
25
25
  node_path = __toESM(node_path);
26
- //#region ../types/dist/event-category-XfKNtfCc.mjs
26
+ //#region ../types/dist/event-category-CIa_iT6b.mjs
27
27
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
28
28
  EventCategory["SystemBoot"] = "system.boot";
29
29
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -39,6 +39,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
39
39
  */
40
40
  EventCategory["SystemRestartCompleted"] = "system.restart-completed";
41
41
  /**
42
+ * The hub reissued its own TLS certificate at boot (`ensureTlsCert`).
43
+ * Emitted only when the material on disk actually changed, so an
44
+ * operator who trusted the old certificate by hand is told rather than
45
+ * discovering it as a browser error. Payload `TlsCertChangedPayload`.
46
+ *
47
+ * Rule: docs/decisions/adr-0227-*.md
48
+ */
49
+ EventCategory["SystemTlsCertChanged"] = "system.tls-cert-changed";
50
+ /**
42
51
  * A newer addon or server-root package version was found by the
43
52
  * authoritative registry check. Emitted once when any observed
44
53
  * `latestVersion` changes (or a package/node first appears behind);
@@ -8019,6 +8028,15 @@ var LabelDefinitionSchema = object({
8019
8028
  description: string().optional(),
8020
8029
  icon: string().optional()
8021
8030
  });
8031
+ var ClassMapDefinitionSchema = object({
8032
+ mapping: record(string(), _enum([
8033
+ "person",
8034
+ "vehicle",
8035
+ "animal",
8036
+ "package"
8037
+ ])),
8038
+ preserveOriginal: boolean()
8039
+ });
8022
8040
  var MODEL_FORMATS = [
8023
8041
  "onnx",
8024
8042
  "coreml",
@@ -8197,7 +8215,13 @@ var ModelCatalogEntrySchema = object({
8197
8215
  * `id` stays the source of truth for resolution/download/persistence; grouping
8198
8216
  * is a presentation overlay resolved back to an `id`.
8199
8217
  */
8200
- group: ModelVariantGroupSchema.optional()
8218
+ group: ModelVariantGroupSchema.optional(),
8219
+ /**
8220
+ * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
8221
+ * applies (Frigate / COCO public catalog). Set on a custom model whose raw
8222
+ * labels already ARE the CamStack macros (Scrypted identity map).
8223
+ */
8224
+ classMap: ClassMapDefinitionSchema.optional()
8201
8225
  });
8202
8226
  var ConvertTargetSchema = discriminatedUnion("format", [object({
8203
8227
  format: literal("openvino"),
@@ -8226,7 +8250,8 @@ var ModelConvertMetadataSchema = object({
8226
8250
  "ocr",
8227
8251
  "segmentation"
8228
8252
  ]),
8229
- faceAlignment: boolean().optional()
8253
+ faceAlignment: boolean().optional(),
8254
+ classMap: ClassMapDefinitionSchema.optional()
8230
8255
  });
8231
8256
  var ConvertResultSchema = object({
8232
8257
  entry: ModelCatalogEntrySchema,
@@ -17217,6 +17242,33 @@ var NativeCropRefSchema = object({
17217
17242
  h: number()
17218
17243
  })
17219
17244
  });
17245
+ object({
17246
+ crop: object({
17247
+ left: number(),
17248
+ top: number(),
17249
+ width: number().positive(),
17250
+ height: number().positive()
17251
+ }).optional(),
17252
+ content: object({
17253
+ width: number().int().positive(),
17254
+ height: number().int().positive()
17255
+ }),
17256
+ fit: _enum(["stretch", "contain"]),
17257
+ format: _enum([
17258
+ "rgb",
17259
+ "gray",
17260
+ "jpeg"
17261
+ ])
17262
+ });
17263
+ var FrameRefSchema = object({
17264
+ registryId: string().min(1),
17265
+ id: string().min(1),
17266
+ width: number().int().positive(),
17267
+ height: number().int().positive(),
17268
+ format: _enum(["rgb", "gray"]),
17269
+ timestamp: number(),
17270
+ capturedAt: number().optional()
17271
+ });
17220
17272
  var ModelFormatSchema$1 = _enum([
17221
17273
  "onnx",
17222
17274
  "coreml",
@@ -17461,6 +17513,12 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
17461
17513
  steps: array(PipelineStepInputSchema).min(1),
17462
17514
  frame: FrameInputSchema.optional(),
17463
17515
  /**
17516
+ * Process-local lazy frame. Valid only when caller and provider resolve
17517
+ * in the same execution-group process; split/cross-node callers use
17518
+ * `frame`/`image` inline compatibility instead.
17519
+ */
17520
+ frameRef: FrameRefSchema.optional(),
17521
+ /**
17464
17522
  * CB5 shm passthrough — a `FrameHandle` naming the same ring slot
17465
17523
  * the decoded pixels live in. One more member of the one-of
17466
17524
  * frame/frameHandle/image/imageBase64/referenceImage group.
@@ -17716,7 +17774,10 @@ var NativeCropResultSchema = object({
17716
17774
  * Which source served this crop, so a quality-sensitive consumer (the native
17717
17775
  * `keyFrame`) can reject a degraded fallback:
17718
17776
  * - `native` — cut from the decode worker's retained NATIVE surface (the
17719
- * quality path).
17777
+ * quality path). A subject-tile serve is also native-resolution and stays
17778
+ * `native` here: the public enum cannot name `tile` without a breaking cap
17779
+ * change. Runner telemetry distinguishes lease vs tile via `source` on the
17780
+ * internal crop result (`nativeHits` vs `tileHits`).
17720
17781
  * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
17721
17782
  * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
17722
17783
  * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
@@ -18207,12 +18268,41 @@ var RunnerLocalLoadSchema = object({
18207
18268
  * legacy `OrchestratorMetricsSchema` shape so existing dashboards keep
18208
18269
  * working unchanged when they switch to reading from the runner cap.
18209
18270
  */
18271
+ var FrameLazyCountersSchema = object({
18272
+ framesDecoded: number(),
18273
+ framesAdmitted: number(),
18274
+ framesDroppedPixelFree: number(),
18275
+ viewsMaterialized: number(),
18276
+ viewsSkipped: number(),
18277
+ workerToRunnerBytes: number(),
18278
+ runnerToPoolRawBytes: number(),
18279
+ runnerToPoolJpegBytes: number(),
18280
+ onDemandFullFrameRequests: number(),
18281
+ onDemandCropRequests: number(),
18282
+ nativeHits: number(),
18283
+ nativeMisses: number(),
18284
+ tileHits: number(),
18285
+ tileMisses: number(),
18286
+ fallbackHits: number(),
18287
+ fallbackMisses: number(),
18288
+ retainedWritesAvoided: number(),
18289
+ residentRefs: number(),
18290
+ residentBytes: number(),
18291
+ releases: number(),
18292
+ evictions: number(),
18293
+ staleMisses: number()
18294
+ });
18295
+ var FrameLazyMetricsSchema = object({
18296
+ node: FrameLazyCountersSchema,
18297
+ cameras: array(FrameLazyCountersSchema.extend({ deviceId: number() }))
18298
+ });
18210
18299
  var RunnerLocalMetricsSchema = object({
18211
18300
  nodeId: string(),
18212
18301
  activeCameras: number(),
18213
18302
  throttledCameras: number(),
18214
18303
  avgInferenceTimeMs: number(),
18215
- queueDepth: number()
18304
+ queueDepth: number(),
18305
+ frameLazy: FrameLazyMetricsSchema.optional()
18216
18306
  });
18217
18307
  method(RunnerCameraConfigSchema, object({ success: literal(true) }), { kind: "mutation" }), method(object({ deviceId: number() }), object({ success: literal(true) }), { kind: "mutation" }), method(ReportMotionInputSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), RunnerLocalLoadSchema), method(_void(), RunnerLocalMetricsSchema), method(object({ deviceId: number() }), CameraMetricsSchema.nullable()), method(_void(), array(CameraMetricsWithDeviceIdSchema).readonly()), method(_void(), array(number()).readonly()), method(object({
18218
18308
  handle: FrameHandleSchema,
@@ -19557,6 +19647,9 @@ var storageProviderCapability = {
19557
19647
  endDownload: method(EndDownloadInputSchema, _void(), { kind: "mutation" })
19558
19648
  }
19559
19649
  };
19650
+ /** Profile-exported FormBuilder schema. Shape is ConfigUISchema at the UI. */
19651
+ var ProfileSettingsSchemaBridge = unknown().nullable();
19652
+ var ProfileSettingsBagSchema = record(string(), unknown());
19560
19653
  /**
19561
19654
  * A live terminal session hosted by the provider addon. Output and input do
19562
19655
  * NOT flow through the capability — they use the addon data plane
@@ -19586,7 +19679,14 @@ var TerminalSessionInfoSchema = object({
19586
19679
  var TerminalProfileInfoSchema = object({
19587
19680
  profileId: string(),
19588
19681
  label: string(),
19589
- description: string().optional()
19682
+ description: string().optional(),
19683
+ /** Spawn defaults the instance form copies on create. */
19684
+ executable: string().optional(),
19685
+ args: array(string()).readonly().optional(),
19686
+ cwd: string().optional(),
19687
+ environment: array(string()).readonly().optional(),
19688
+ /** ConfigUISchema for instance knobs, or null when the profile has none. */
19689
+ settingsSchema: ProfileSettingsSchemaBridge.optional()
19590
19690
  });
19591
19691
  /**
19592
19692
  * A durable operator-created Terminal instance. Profiles are templates; only
@@ -19599,7 +19699,12 @@ var TerminalInstanceInfoSchema = object({
19599
19699
  profileId: string(),
19600
19700
  profileLabel: string(),
19601
19701
  name: string(),
19602
- enabled: boolean()
19702
+ enabled: boolean(),
19703
+ executable: string(),
19704
+ args: array(string()).readonly(),
19705
+ cwd: string(),
19706
+ environment: array(string()).readonly(),
19707
+ profileSettings: ProfileSettingsBagSchema
19603
19708
  });
19604
19709
  var TerminalLegacyCameraSchema = object({
19605
19710
  stableId: string(),
@@ -19629,7 +19734,23 @@ var TerminalOutputBatchSchema = object({
19629
19734
  method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }), method(_void(), array(TerminalInstanceInfoSchema).readonly(), { auth: "admin" }), method(object({
19630
19735
  targetNodeId: string().min(1),
19631
19736
  profileId: string().min(1),
19632
- name: string().trim().min(1).max(160).optional()
19737
+ name: string().trim().min(1).max(160).optional(),
19738
+ executable: string().max(1024).optional(),
19739
+ args: array(string().max(2048)).max(64).optional(),
19740
+ cwd: string().max(1024).optional(),
19741
+ environment: array(string().max(4096)).max(64).optional(),
19742
+ profileSettings: ProfileSettingsBagSchema.optional()
19743
+ }), TerminalInstanceInfoSchema, {
19744
+ kind: "mutation",
19745
+ auth: "admin"
19746
+ }), method(object({
19747
+ instanceId: string().min(1),
19748
+ name: string().trim().min(1).max(160).optional(),
19749
+ executable: string().max(1024).optional(),
19750
+ args: array(string().max(2048)).max(64).optional(),
19751
+ cwd: string().max(1024).optional(),
19752
+ environment: array(string().max(4096)).max(64).optional(),
19753
+ profileSettings: ProfileSettingsBagSchema.optional()
19633
19754
  }), TerminalInstanceInfoSchema, {
19634
19755
  kind: "mutation",
19635
19756
  auth: "admin"
@@ -19651,7 +19772,11 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
19651
19772
  }), method(_void(), array(TerminalSessionInfoSchema).readonly(), { auth: "admin" }), method(object({
19652
19773
  profileId: string(),
19653
19774
  cols: number().int().positive(),
19654
- rows: number().int().positive()
19775
+ rows: number().int().positive(),
19776
+ executable: string().max(1024).optional(),
19777
+ args: array(string().max(2048)).max(64).optional(),
19778
+ cwd: string().max(1024).optional(),
19779
+ environment: array(string().max(4096)).max(64).optional()
19655
19780
  }), TerminalSessionInfoSchema, {
19656
19781
  kind: "mutation",
19657
19782
  auth: "admin"
@@ -22433,10 +22558,10 @@ DeviceType.LawnMower, method(object({ deviceId: number().int().nonnegative() }),
22433
22558
  *
22434
22559
  * • The SDK (mobile / web client) consumes `getConnectionEndpoints()`
22435
22560
  * to receive an ordered list of candidate base URLs it should race
22436
- * on connect — LAN IPv4 first (lowest latency when on same network),
22437
- * then public hostname (if a tunnel is up), then IPv6. The SDK can
22438
- * race them with short timeouts and stick with the winner for the
22439
- * session.
22561
+ * on connect — LAN IPv4 and stable LAN IPv6 first (lowest latency
22562
+ * when on the same network), then public hostname (if a tunnel is
22563
+ * up). The SDK can race them with short timeouts and stick with the
22564
+ * winner for the session.
22440
22565
  *
22441
22566
  * Why hub-only: agents are not directly addressable by the operator's
22442
22567
  * clients — they reverse-connect to the hub. Exposing their interfaces
@@ -22591,6 +22716,17 @@ var NotificationEndpointSchema = object({
22591
22716
  /** What the ranking currently resolves to (null when nothing is reachable). */
22592
22717
  resolved: string().nullable()
22593
22718
  });
22719
+ /**
22720
+ * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
22721
+ * AUTO (every LAN IPv4 + the public tunnel). `resolved` is what that choice
22722
+ * currently expands to, so the UI can show the effective set either way.
22723
+ */
22724
+ var ViewerEndpointsSchema = object({
22725
+ /** The operator's explicit race set, or empty for AUTO. */
22726
+ baseUrls: array(string()).readonly(),
22727
+ /** What the ranking currently resolves to (may be empty if nothing is up). */
22728
+ resolved: array(string()).readonly()
22729
+ });
22594
22730
  var AllowedAddressesSchema = object({
22595
22731
  /**
22596
22732
  * Allowlist of interface addresses operators have explicitly opted
@@ -22599,6 +22735,20 @@ var AllowedAddressesSchema = object({
22599
22735
  * Network Addresses admin page and persisted by the addon.
22600
22736
  */
22601
22737
  addresses: array(string()).readonly() });
22738
+ var TlsStatusSchema = object({
22739
+ mode: _enum([
22740
+ "generated",
22741
+ "uploaded",
22742
+ "disabled"
22743
+ ]),
22744
+ leafFingerprintSha256: string().nullable(),
22745
+ caFingerprintSha256: string().nullable(),
22746
+ validTo: string().nullable(),
22747
+ sans: array(string()),
22748
+ caCertPem: string().nullable(),
22749
+ reissueError: string().nullable(),
22750
+ restartRequired: boolean()
22751
+ });
22602
22752
  method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
22603
22753
  /**
22604
22754
  * LEGACY HINT — do not send from new code. Kept optional so clients
@@ -22608,17 +22758,31 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
22608
22758
  */
22609
22759
  port: number().int().min(1).max(65535).optional(),
22610
22760
  /** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
22611
- * candidate. Default `true`. */
22761
+ * candidate. Default `false` — loopback is not a client route. */
22612
22762
  includeLoopback: boolean().optional(),
22613
- /** Skip IPv6 entries. Some legacy clients can't parse them.
22614
- * Default `false`. */
22763
+ /** Skip IPv6 entries. Default `false` the palette includes stable
22764
+ * LAN IPv6 (ICE/WebRTC uses dual-stack regardless). Pass `true` to
22765
+ * hide them. The viewer HTTP/WS race is `getViewerEndpoints`. */
22615
22766
  ipv4Only: boolean().optional(),
22616
22767
  /** Scheme to emit for LAN/loopback URLs. Default `'http'`.
22617
22768
  * Pass `'https'` when the caller is itself loaded over HTTPS
22618
22769
  * to avoid mixed-content blocks in the browser. The public
22619
22770
  * tunnel always emits `https://` regardless. */
22620
22771
  scheme: _enum(["http", "https"]).optional()
22621
- }), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" });
22772
+ }), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), ViewerEndpointsSchema), method(object({ baseUrls: array(string()).readonly() }), ViewerEndpointsSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" }), method(_void(), TlsStatusSchema), method(object({ reason: string().optional() }), TlsStatusSchema, {
22773
+ kind: "mutation",
22774
+ auth: "admin"
22775
+ }), method(object({
22776
+ certPem: string().min(1),
22777
+ keyPem: string().min(1),
22778
+ caPem: string().optional()
22779
+ }), TlsStatusSchema, {
22780
+ kind: "mutation",
22781
+ auth: "admin"
22782
+ }), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
22783
+ kind: "mutation",
22784
+ auth: "admin"
22785
+ });
22622
22786
  object({
22623
22787
  /** Lifecycle state of the lock. `jammed` means the motor reported
22624
22788
  * failure to reach the target — operator intervention required. */
@@ -28381,6 +28545,12 @@ Object.freeze({
28381
28545
  addonId: null,
28382
28546
  access: "create"
28383
28547
  },
28548
+ "localNetwork.downloadCa": {
28549
+ capName: "local-network",
28550
+ capScope: "system",
28551
+ addonId: null,
28552
+ access: "view"
28553
+ },
28384
28554
  "localNetwork.getAllowedAddresses": {
28385
28555
  capName: "local-network",
28386
28556
  capScope: "system",
@@ -28405,18 +28575,42 @@ Object.freeze({
28405
28575
  addonId: null,
28406
28576
  access: "view"
28407
28577
  },
28578
+ "localNetwork.getTlsStatus": {
28579
+ capName: "local-network",
28580
+ capScope: "system",
28581
+ addonId: null,
28582
+ access: "view"
28583
+ },
28584
+ "localNetwork.getViewerEndpoints": {
28585
+ capName: "local-network",
28586
+ capScope: "system",
28587
+ addonId: null,
28588
+ access: "view"
28589
+ },
28408
28590
  "localNetwork.list": {
28409
28591
  capName: "local-network",
28410
28592
  capScope: "system",
28411
28593
  addonId: null,
28412
28594
  access: "view"
28413
28595
  },
28596
+ "localNetwork.regenerateCertificate": {
28597
+ capName: "local-network",
28598
+ capScope: "system",
28599
+ addonId: null,
28600
+ access: "create"
28601
+ },
28414
28602
  "localNetwork.resetAllowlistToBestMatch": {
28415
28603
  capName: "local-network",
28416
28604
  capScope: "system",
28417
28605
  addonId: null,
28418
28606
  access: "delete"
28419
28607
  },
28608
+ "localNetwork.revertToGeneratedCertificate": {
28609
+ capName: "local-network",
28610
+ capScope: "system",
28611
+ addonId: null,
28612
+ access: "create"
28613
+ },
28420
28614
  "localNetwork.setAllowedAddresses": {
28421
28615
  capName: "local-network",
28422
28616
  capScope: "system",
@@ -28429,6 +28623,18 @@ Object.freeze({
28429
28623
  addonId: null,
28430
28624
  access: "create"
28431
28625
  },
28626
+ "localNetwork.setViewerEndpoints": {
28627
+ capName: "local-network",
28628
+ capScope: "system",
28629
+ addonId: null,
28630
+ access: "create"
28631
+ },
28632
+ "localNetwork.uploadCertificate": {
28633
+ capName: "local-network",
28634
+ capScope: "system",
28635
+ addonId: null,
28636
+ access: "create"
28637
+ },
28432
28638
  "lockControl.lock": {
28433
28639
  capName: "lock-control",
28434
28640
  capScope: "device",
@@ -31309,6 +31515,12 @@ Object.freeze({
31309
31515
  addonId: null,
31310
31516
  access: "create"
31311
31517
  },
31518
+ "terminalSession.updateInstance": {
31519
+ capName: "terminal-session",
31520
+ capScope: "system",
31521
+ addonId: null,
31522
+ access: "create"
31523
+ },
31312
31524
  "terminalSession.writeInput": {
31313
31525
  capName: "terminal-session",
31314
31526
  capScope: "system",
@@ -33796,6 +34008,35 @@ Object.freeze(Object.fromEntries([{
33796
34008
  }]
33797
34009
  }].map((s) => [s.stepId, s.defaultModelId])));
33798
34010
  string().min(1);
34011
+ var CLUSTER_STEP_SETTING_FIELDS = [{
34012
+ stepId: "face-embedding",
34013
+ key: "minLandmarkFaceSize",
34014
+ label: "Min face size for recognition (detection px)",
34015
+ description: "Refuse to embed a face smaller than this IN THE DETECTION FRAME. Applies to every node — the enrolled gallery is one index, and two admission floors would fill it from two policies. 0 disables the gate.",
34016
+ type: "slider",
34017
+ min: 0,
34018
+ max: 64,
34019
+ step: 2,
34020
+ default: 24
34021
+ }];
34022
+ function clusterStepSettingKey(stepId, fieldKey) {
34023
+ return `clusterStepSetting:${stepId}:${fieldKey}`;
34024
+ }
34025
+ var ClusterSettingNumberSchema = number().finite();
34026
+ function readClusterStepSettings(config) {
34027
+ const out = {};
34028
+ for (const field of CLUSTER_STEP_SETTING_FIELDS) {
34029
+ const parsed = ClusterSettingNumberSchema.safeParse(config[clusterStepSettingKey(field.stepId, field.key)]);
34030
+ const value = parsed.success ? parsed.data : field.default;
34031
+ const existing = out[field.stepId] ?? {};
34032
+ out[field.stepId] = {
34033
+ ...existing,
34034
+ [field.key]: value
34035
+ };
34036
+ }
34037
+ return out;
34038
+ }
34039
+ readClusterStepSettings({});
33799
34040
  object({
33800
34041
  /**
33801
34042
  * Fraction of the box's own size added on EACH side before cutting.
@@ -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-CAxkUIT8.js");
5
+ const require_shared = require("./shared-UN8idVfB.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-CMeaUSWI.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-BwialOVX.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.24",
3
+ "version": "1.2.26",
4
4
  "description": "Remote storage providers (SFTP, S3, WebDAV) — unifies remote backends behind the storage-provider cap",
5
5
  "keywords": [
6
6
  "camstack",