@camstack/addon-tailscale 1.2.25 → 1.2.27

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-B3cBbqzz.js");
27
+ const require_dist = require("../dist-BrkbC1tE.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-cyVteDFT.mjs";
1
+ import { a as EventCategory, i as BaseAddon, n as networkAccessCapability, r as BOOT_RECOVERY_BACKOFF_MS, t as meshNetworkCapability } from "../dist-CovkuhH2.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";
@@ -1,4 +1,4 @@
1
- //#region ../types/dist/event-category-XfKNtfCc.mjs
1
+ //#region ../types/dist/event-category-CIa_iT6b.mjs
2
2
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
3
3
  EventCategory["SystemBoot"] = "system.boot";
4
4
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -14,6 +14,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
14
14
  */
15
15
  EventCategory["SystemRestartCompleted"] = "system.restart-completed";
16
16
  /**
17
+ * The hub reissued its own TLS certificate at boot (`ensureTlsCert`).
18
+ * Emitted only when the material on disk actually changed, so an
19
+ * operator who trusted the old certificate by hand is told rather than
20
+ * discovering it as a browser error. Payload `TlsCertChangedPayload`.
21
+ *
22
+ * Rule: docs/decisions/adr-0227-*.md
23
+ */
24
+ EventCategory["SystemTlsCertChanged"] = "system.tls-cert-changed";
25
+ /**
17
26
  * A newer addon or server-root package version was found by the
18
27
  * authoritative registry check. Emitted once when any observed
19
28
  * `latestVersion` changes (or a package/node first appears behind);
@@ -8028,6 +8037,15 @@ var LabelDefinitionSchema = object({
8028
8037
  description: string().optional(),
8029
8038
  icon: string().optional()
8030
8039
  });
8040
+ var ClassMapDefinitionSchema = object({
8041
+ mapping: record(string(), _enum([
8042
+ "person",
8043
+ "vehicle",
8044
+ "animal",
8045
+ "package"
8046
+ ])),
8047
+ preserveOriginal: boolean()
8048
+ });
8031
8049
  var MODEL_FORMATS = [
8032
8050
  "onnx",
8033
8051
  "coreml",
@@ -8206,7 +8224,13 @@ var ModelCatalogEntrySchema = object({
8206
8224
  * `id` stays the source of truth for resolution/download/persistence; grouping
8207
8225
  * is a presentation overlay resolved back to an `id`.
8208
8226
  */
8209
- group: ModelVariantGroupSchema.optional()
8227
+ group: ModelVariantGroupSchema.optional(),
8228
+ /**
8229
+ * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
8230
+ * applies (Frigate / COCO public catalog). Set on a custom model whose raw
8231
+ * labels already ARE the CamStack macros (Scrypted identity map).
8232
+ */
8233
+ classMap: ClassMapDefinitionSchema.optional()
8210
8234
  });
8211
8235
  var ConvertTargetSchema = discriminatedUnion("format", [object({
8212
8236
  format: literal("openvino"),
@@ -8235,7 +8259,8 @@ var ModelConvertMetadataSchema = object({
8235
8259
  "ocr",
8236
8260
  "segmentation"
8237
8261
  ]),
8238
- faceAlignment: boolean().optional()
8262
+ faceAlignment: boolean().optional(),
8263
+ classMap: ClassMapDefinitionSchema.optional()
8239
8264
  });
8240
8265
  var ConvertResultSchema = object({
8241
8266
  entry: ModelCatalogEntrySchema,
@@ -17243,6 +17268,33 @@ var NativeCropRefSchema = object({
17243
17268
  h: number()
17244
17269
  })
17245
17270
  });
17271
+ object({
17272
+ crop: object({
17273
+ left: number(),
17274
+ top: number(),
17275
+ width: number().positive(),
17276
+ height: number().positive()
17277
+ }).optional(),
17278
+ content: object({
17279
+ width: number().int().positive(),
17280
+ height: number().int().positive()
17281
+ }),
17282
+ fit: _enum(["stretch", "contain"]),
17283
+ format: _enum([
17284
+ "rgb",
17285
+ "gray",
17286
+ "jpeg"
17287
+ ])
17288
+ });
17289
+ var FrameRefSchema = object({
17290
+ registryId: string().min(1),
17291
+ id: string().min(1),
17292
+ width: number().int().positive(),
17293
+ height: number().int().positive(),
17294
+ format: _enum(["rgb", "gray"]),
17295
+ timestamp: number(),
17296
+ capturedAt: number().optional()
17297
+ });
17246
17298
  var ModelFormatSchema$1 = _enum([
17247
17299
  "onnx",
17248
17300
  "coreml",
@@ -17487,6 +17539,12 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
17487
17539
  steps: array(PipelineStepInputSchema).min(1),
17488
17540
  frame: FrameInputSchema.optional(),
17489
17541
  /**
17542
+ * Process-local lazy frame. Valid only when caller and provider resolve
17543
+ * in the same execution-group process; split/cross-node callers use
17544
+ * `frame`/`image` inline compatibility instead.
17545
+ */
17546
+ frameRef: FrameRefSchema.optional(),
17547
+ /**
17490
17548
  * CB5 shm passthrough — a `FrameHandle` naming the same ring slot
17491
17549
  * the decoded pixels live in. One more member of the one-of
17492
17550
  * frame/frameHandle/image/imageBase64/referenceImage group.
@@ -17742,7 +17800,10 @@ var NativeCropResultSchema = object({
17742
17800
  * Which source served this crop, so a quality-sensitive consumer (the native
17743
17801
  * `keyFrame`) can reject a degraded fallback:
17744
17802
  * - `native` — cut from the decode worker's retained NATIVE surface (the
17745
- * quality path).
17803
+ * quality path). A subject-tile serve is also native-resolution and stays
17804
+ * `native` here: the public enum cannot name `tile` without a breaking cap
17805
+ * change. Runner telemetry distinguishes lease vs tile via `source` on the
17806
+ * internal crop result (`nativeHits` vs `tileHits`).
17746
17807
  * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
17747
17808
  * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
17748
17809
  * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
@@ -18233,12 +18294,41 @@ var RunnerLocalLoadSchema = object({
18233
18294
  * legacy `OrchestratorMetricsSchema` shape so existing dashboards keep
18234
18295
  * working unchanged when they switch to reading from the runner cap.
18235
18296
  */
18297
+ var FrameLazyCountersSchema = object({
18298
+ framesDecoded: number(),
18299
+ framesAdmitted: number(),
18300
+ framesDroppedPixelFree: number(),
18301
+ viewsMaterialized: number(),
18302
+ viewsSkipped: number(),
18303
+ workerToRunnerBytes: number(),
18304
+ runnerToPoolRawBytes: number(),
18305
+ runnerToPoolJpegBytes: number(),
18306
+ onDemandFullFrameRequests: number(),
18307
+ onDemandCropRequests: number(),
18308
+ nativeHits: number(),
18309
+ nativeMisses: number(),
18310
+ tileHits: number(),
18311
+ tileMisses: number(),
18312
+ fallbackHits: number(),
18313
+ fallbackMisses: number(),
18314
+ retainedWritesAvoided: number(),
18315
+ residentRefs: number(),
18316
+ residentBytes: number(),
18317
+ releases: number(),
18318
+ evictions: number(),
18319
+ staleMisses: number()
18320
+ });
18321
+ var FrameLazyMetricsSchema = object({
18322
+ node: FrameLazyCountersSchema,
18323
+ cameras: array(FrameLazyCountersSchema.extend({ deviceId: number() }))
18324
+ });
18236
18325
  var RunnerLocalMetricsSchema = object({
18237
18326
  nodeId: string(),
18238
18327
  activeCameras: number(),
18239
18328
  throttledCameras: number(),
18240
18329
  avgInferenceTimeMs: number(),
18241
- queueDepth: number()
18330
+ queueDepth: number(),
18331
+ frameLazy: FrameLazyMetricsSchema.optional()
18242
18332
  });
18243
18333
  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({
18244
18334
  handle: FrameHandleSchema,
@@ -19538,6 +19628,9 @@ method(_void(), ProviderInfoSchema), method(object({ config: record(string(), un
19538
19628
  location: StorageLocationSchema,
19539
19629
  relativePath: string()
19540
19630
  }), _void(), { kind: "mutation" }), method(object({ location: StorageLocationSchema }), number().nullable()), method(BeginUploadInputSchema, BeginUploadResultSchema, { kind: "mutation" }), method(WriteChunkInputSchema, _void(), { kind: "mutation" }), method(FinalizeUploadInputSchema, _void(), { kind: "mutation" }), method(AbortUploadInputSchema, _void(), { kind: "mutation" }), method(BeginDownloadInputSchema, BeginDownloadResultSchema, { kind: "mutation" }), method(ReadChunkInputSchema, _instanceof(Uint8Array)), method(EndDownloadInputSchema, _void(), { kind: "mutation" });
19631
+ /** Profile-exported FormBuilder schema. Shape is ConfigUISchema at the UI. */
19632
+ var ProfileSettingsSchemaBridge = unknown().nullable();
19633
+ var ProfileSettingsBagSchema = record(string(), unknown());
19541
19634
  /**
19542
19635
  * A live terminal session hosted by the provider addon. Output and input do
19543
19636
  * NOT flow through the capability — they use the addon data plane
@@ -19567,7 +19660,14 @@ var TerminalSessionInfoSchema = object({
19567
19660
  var TerminalProfileInfoSchema = object({
19568
19661
  profileId: string(),
19569
19662
  label: string(),
19570
- description: string().optional()
19663
+ description: string().optional(),
19664
+ /** Spawn defaults the instance form copies on create. */
19665
+ executable: string().optional(),
19666
+ args: array(string()).readonly().optional(),
19667
+ cwd: string().optional(),
19668
+ environment: array(string()).readonly().optional(),
19669
+ /** ConfigUISchema for instance knobs, or null when the profile has none. */
19670
+ settingsSchema: ProfileSettingsSchemaBridge.optional()
19571
19671
  });
19572
19672
  /**
19573
19673
  * A durable operator-created Terminal instance. Profiles are templates; only
@@ -19580,7 +19680,12 @@ var TerminalInstanceInfoSchema = object({
19580
19680
  profileId: string(),
19581
19681
  profileLabel: string(),
19582
19682
  name: string(),
19583
- enabled: boolean()
19683
+ enabled: boolean(),
19684
+ executable: string(),
19685
+ args: array(string()).readonly(),
19686
+ cwd: string(),
19687
+ environment: array(string()).readonly(),
19688
+ profileSettings: ProfileSettingsBagSchema
19584
19689
  });
19585
19690
  var TerminalLegacyCameraSchema = object({
19586
19691
  stableId: string(),
@@ -19610,7 +19715,23 @@ var TerminalOutputBatchSchema = object({
19610
19715
  method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }), method(_void(), array(TerminalInstanceInfoSchema).readonly(), { auth: "admin" }), method(object({
19611
19716
  targetNodeId: string().min(1),
19612
19717
  profileId: string().min(1),
19613
- name: string().trim().min(1).max(160).optional()
19718
+ name: string().trim().min(1).max(160).optional(),
19719
+ executable: string().max(1024).optional(),
19720
+ args: array(string().max(2048)).max(64).optional(),
19721
+ cwd: string().max(1024).optional(),
19722
+ environment: array(string().max(4096)).max(64).optional(),
19723
+ profileSettings: ProfileSettingsBagSchema.optional()
19724
+ }), TerminalInstanceInfoSchema, {
19725
+ kind: "mutation",
19726
+ auth: "admin"
19727
+ }), method(object({
19728
+ instanceId: string().min(1),
19729
+ name: string().trim().min(1).max(160).optional(),
19730
+ executable: string().max(1024).optional(),
19731
+ args: array(string().max(2048)).max(64).optional(),
19732
+ cwd: string().max(1024).optional(),
19733
+ environment: array(string().max(4096)).max(64).optional(),
19734
+ profileSettings: ProfileSettingsBagSchema.optional()
19614
19735
  }), TerminalInstanceInfoSchema, {
19615
19736
  kind: "mutation",
19616
19737
  auth: "admin"
@@ -19632,7 +19753,11 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
19632
19753
  }), method(_void(), array(TerminalSessionInfoSchema).readonly(), { auth: "admin" }), method(object({
19633
19754
  profileId: string(),
19634
19755
  cols: number().int().positive(),
19635
- rows: number().int().positive()
19756
+ rows: number().int().positive(),
19757
+ executable: string().max(1024).optional(),
19758
+ args: array(string().max(2048)).max(64).optional(),
19759
+ cwd: string().max(1024).optional(),
19760
+ environment: array(string().max(4096)).max(64).optional()
19636
19761
  }), TerminalSessionInfoSchema, {
19637
19762
  kind: "mutation",
19638
19763
  auth: "admin"
@@ -22414,10 +22539,10 @@ DeviceType.LawnMower, method(object({ deviceId: number().int().nonnegative() }),
22414
22539
  *
22415
22540
  * • The SDK (mobile / web client) consumes `getConnectionEndpoints()`
22416
22541
  * to receive an ordered list of candidate base URLs it should race
22417
- * on connect — LAN IPv4 first (lowest latency when on same network),
22418
- * then public hostname (if a tunnel is up), then IPv6. The SDK can
22419
- * race them with short timeouts and stick with the winner for the
22420
- * session.
22542
+ * on connect — LAN IPv4 and stable LAN IPv6 first (lowest latency
22543
+ * when on the same network), then public hostname (if a tunnel is
22544
+ * up). The SDK can race them with short timeouts and stick with the
22545
+ * winner for the session.
22421
22546
  *
22422
22547
  * Why hub-only: agents are not directly addressable by the operator's
22423
22548
  * clients — they reverse-connect to the hub. Exposing their interfaces
@@ -22572,6 +22697,17 @@ var NotificationEndpointSchema = object({
22572
22697
  /** What the ranking currently resolves to (null when nothing is reachable). */
22573
22698
  resolved: string().nullable()
22574
22699
  });
22700
+ /**
22701
+ * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
22702
+ * AUTO (every LAN IPv4 + the public tunnel). `resolved` is what that choice
22703
+ * currently expands to, so the UI can show the effective set either way.
22704
+ */
22705
+ var ViewerEndpointsSchema = object({
22706
+ /** The operator's explicit race set, or empty for AUTO. */
22707
+ baseUrls: array(string()).readonly(),
22708
+ /** What the ranking currently resolves to (may be empty if nothing is up). */
22709
+ resolved: array(string()).readonly()
22710
+ });
22575
22711
  var AllowedAddressesSchema = object({
22576
22712
  /**
22577
22713
  * Allowlist of interface addresses operators have explicitly opted
@@ -22580,6 +22716,20 @@ var AllowedAddressesSchema = object({
22580
22716
  * Network Addresses admin page and persisted by the addon.
22581
22717
  */
22582
22718
  addresses: array(string()).readonly() });
22719
+ var TlsStatusSchema = object({
22720
+ mode: _enum([
22721
+ "generated",
22722
+ "uploaded",
22723
+ "disabled"
22724
+ ]),
22725
+ leafFingerprintSha256: string().nullable(),
22726
+ caFingerprintSha256: string().nullable(),
22727
+ validTo: string().nullable(),
22728
+ sans: array(string()),
22729
+ caCertPem: string().nullable(),
22730
+ reissueError: string().nullable(),
22731
+ restartRequired: boolean()
22732
+ });
22583
22733
  method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
22584
22734
  /**
22585
22735
  * LEGACY HINT — do not send from new code. Kept optional so clients
@@ -22589,17 +22739,31 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
22589
22739
  */
22590
22740
  port: number().int().min(1).max(65535).optional(),
22591
22741
  /** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
22592
- * candidate. Default `true`. */
22742
+ * candidate. Default `false` — loopback is not a client route. */
22593
22743
  includeLoopback: boolean().optional(),
22594
- /** Skip IPv6 entries. Some legacy clients can't parse them.
22595
- * Default `false`. */
22744
+ /** Skip IPv6 entries. Default `false` the palette includes stable
22745
+ * LAN IPv6 (ICE/WebRTC uses dual-stack regardless). Pass `true` to
22746
+ * hide them. The viewer HTTP/WS race is `getViewerEndpoints`. */
22596
22747
  ipv4Only: boolean().optional(),
22597
22748
  /** Scheme to emit for LAN/loopback URLs. Default `'http'`.
22598
22749
  * Pass `'https'` when the caller is itself loaded over HTTPS
22599
22750
  * to avoid mixed-content blocks in the browser. The public
22600
22751
  * tunnel always emits `https://` regardless. */
22601
22752
  scheme: _enum(["http", "https"]).optional()
22602
- }), 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" });
22753
+ }), 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, {
22754
+ kind: "mutation",
22755
+ auth: "admin"
22756
+ }), method(object({
22757
+ certPem: string().min(1),
22758
+ keyPem: string().min(1),
22759
+ caPem: string().optional()
22760
+ }), TlsStatusSchema, {
22761
+ kind: "mutation",
22762
+ auth: "admin"
22763
+ }), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
22764
+ kind: "mutation",
22765
+ auth: "admin"
22766
+ });
22603
22767
  object({
22604
22768
  /** Lifecycle state of the lock. `jammed` means the motor reported
22605
22769
  * failure to reach the target — operator intervention required. */
@@ -28423,6 +28587,12 @@ Object.freeze({
28423
28587
  addonId: null,
28424
28588
  access: "create"
28425
28589
  },
28590
+ "localNetwork.downloadCa": {
28591
+ capName: "local-network",
28592
+ capScope: "system",
28593
+ addonId: null,
28594
+ access: "view"
28595
+ },
28426
28596
  "localNetwork.getAllowedAddresses": {
28427
28597
  capName: "local-network",
28428
28598
  capScope: "system",
@@ -28447,18 +28617,42 @@ Object.freeze({
28447
28617
  addonId: null,
28448
28618
  access: "view"
28449
28619
  },
28620
+ "localNetwork.getTlsStatus": {
28621
+ capName: "local-network",
28622
+ capScope: "system",
28623
+ addonId: null,
28624
+ access: "view"
28625
+ },
28626
+ "localNetwork.getViewerEndpoints": {
28627
+ capName: "local-network",
28628
+ capScope: "system",
28629
+ addonId: null,
28630
+ access: "view"
28631
+ },
28450
28632
  "localNetwork.list": {
28451
28633
  capName: "local-network",
28452
28634
  capScope: "system",
28453
28635
  addonId: null,
28454
28636
  access: "view"
28455
28637
  },
28638
+ "localNetwork.regenerateCertificate": {
28639
+ capName: "local-network",
28640
+ capScope: "system",
28641
+ addonId: null,
28642
+ access: "create"
28643
+ },
28456
28644
  "localNetwork.resetAllowlistToBestMatch": {
28457
28645
  capName: "local-network",
28458
28646
  capScope: "system",
28459
28647
  addonId: null,
28460
28648
  access: "delete"
28461
28649
  },
28650
+ "localNetwork.revertToGeneratedCertificate": {
28651
+ capName: "local-network",
28652
+ capScope: "system",
28653
+ addonId: null,
28654
+ access: "create"
28655
+ },
28462
28656
  "localNetwork.setAllowedAddresses": {
28463
28657
  capName: "local-network",
28464
28658
  capScope: "system",
@@ -28471,6 +28665,18 @@ Object.freeze({
28471
28665
  addonId: null,
28472
28666
  access: "create"
28473
28667
  },
28668
+ "localNetwork.setViewerEndpoints": {
28669
+ capName: "local-network",
28670
+ capScope: "system",
28671
+ addonId: null,
28672
+ access: "create"
28673
+ },
28674
+ "localNetwork.uploadCertificate": {
28675
+ capName: "local-network",
28676
+ capScope: "system",
28677
+ addonId: null,
28678
+ access: "create"
28679
+ },
28474
28680
  "lockControl.lock": {
28475
28681
  capName: "lock-control",
28476
28682
  capScope: "device",
@@ -31351,6 +31557,12 @@ Object.freeze({
31351
31557
  addonId: null,
31352
31558
  access: "create"
31353
31559
  },
31560
+ "terminalSession.updateInstance": {
31561
+ capName: "terminal-session",
31562
+ capScope: "system",
31563
+ addonId: null,
31564
+ access: "create"
31565
+ },
31354
31566
  "terminalSession.writeInput": {
31355
31567
  capName: "terminal-session",
31356
31568
  capScope: "system",
@@ -33838,6 +34050,35 @@ Object.freeze(Object.fromEntries([{
33838
34050
  }]
33839
34051
  }].map((s) => [s.stepId, s.defaultModelId])));
33840
34052
  string().min(1);
34053
+ var CLUSTER_STEP_SETTING_FIELDS = [{
34054
+ stepId: "face-embedding",
34055
+ key: "minLandmarkFaceSize",
34056
+ label: "Min face size for recognition (detection px)",
34057
+ 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.",
34058
+ type: "slider",
34059
+ min: 0,
34060
+ max: 64,
34061
+ step: 2,
34062
+ default: 24
34063
+ }];
34064
+ function clusterStepSettingKey(stepId, fieldKey) {
34065
+ return `clusterStepSetting:${stepId}:${fieldKey}`;
34066
+ }
34067
+ var ClusterSettingNumberSchema = number().finite();
34068
+ function readClusterStepSettings(config) {
34069
+ const out = {};
34070
+ for (const field of CLUSTER_STEP_SETTING_FIELDS) {
34071
+ const parsed = ClusterSettingNumberSchema.safeParse(config[clusterStepSettingKey(field.stepId, field.key)]);
34072
+ const value = parsed.success ? parsed.data : field.default;
34073
+ const existing = out[field.stepId] ?? {};
34074
+ out[field.stepId] = {
34075
+ ...existing,
34076
+ [field.key]: value
34077
+ };
34078
+ }
34079
+ return out;
34080
+ }
34081
+ readClusterStepSettings({});
33841
34082
  object({
33842
34083
  /**
33843
34084
  * Fraction of the box's own size added on EACH side before cutting.
@@ -1,4 +1,4 @@
1
- //#region ../types/dist/event-category-XfKNtfCc.mjs
1
+ //#region ../types/dist/event-category-CIa_iT6b.mjs
2
2
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
3
3
  EventCategory["SystemBoot"] = "system.boot";
4
4
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -14,6 +14,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
14
14
  */
15
15
  EventCategory["SystemRestartCompleted"] = "system.restart-completed";
16
16
  /**
17
+ * The hub reissued its own TLS certificate at boot (`ensureTlsCert`).
18
+ * Emitted only when the material on disk actually changed, so an
19
+ * operator who trusted the old certificate by hand is told rather than
20
+ * discovering it as a browser error. Payload `TlsCertChangedPayload`.
21
+ *
22
+ * Rule: docs/decisions/adr-0227-*.md
23
+ */
24
+ EventCategory["SystemTlsCertChanged"] = "system.tls-cert-changed";
25
+ /**
17
26
  * A newer addon or server-root package version was found by the
18
27
  * authoritative registry check. Emitted once when any observed
19
28
  * `latestVersion` changes (or a package/node first appears behind);
@@ -8028,6 +8037,15 @@ var LabelDefinitionSchema = object({
8028
8037
  description: string().optional(),
8029
8038
  icon: string().optional()
8030
8039
  });
8040
+ var ClassMapDefinitionSchema = object({
8041
+ mapping: record(string(), _enum([
8042
+ "person",
8043
+ "vehicle",
8044
+ "animal",
8045
+ "package"
8046
+ ])),
8047
+ preserveOriginal: boolean()
8048
+ });
8031
8049
  var MODEL_FORMATS = [
8032
8050
  "onnx",
8033
8051
  "coreml",
@@ -8206,7 +8224,13 @@ var ModelCatalogEntrySchema = object({
8206
8224
  * `id` stays the source of truth for resolution/download/persistence; grouping
8207
8225
  * is a presentation overlay resolved back to an `id`.
8208
8226
  */
8209
- group: ModelVariantGroupSchema.optional()
8227
+ group: ModelVariantGroupSchema.optional(),
8228
+ /**
8229
+ * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
8230
+ * applies (Frigate / COCO public catalog). Set on a custom model whose raw
8231
+ * labels already ARE the CamStack macros (Scrypted identity map).
8232
+ */
8233
+ classMap: ClassMapDefinitionSchema.optional()
8210
8234
  });
8211
8235
  var ConvertTargetSchema = discriminatedUnion("format", [object({
8212
8236
  format: literal("openvino"),
@@ -8235,7 +8259,8 @@ var ModelConvertMetadataSchema = object({
8235
8259
  "ocr",
8236
8260
  "segmentation"
8237
8261
  ]),
8238
- faceAlignment: boolean().optional()
8262
+ faceAlignment: boolean().optional(),
8263
+ classMap: ClassMapDefinitionSchema.optional()
8239
8264
  });
8240
8265
  var ConvertResultSchema = object({
8241
8266
  entry: ModelCatalogEntrySchema,
@@ -17243,6 +17268,33 @@ var NativeCropRefSchema = object({
17243
17268
  h: number()
17244
17269
  })
17245
17270
  });
17271
+ object({
17272
+ crop: object({
17273
+ left: number(),
17274
+ top: number(),
17275
+ width: number().positive(),
17276
+ height: number().positive()
17277
+ }).optional(),
17278
+ content: object({
17279
+ width: number().int().positive(),
17280
+ height: number().int().positive()
17281
+ }),
17282
+ fit: _enum(["stretch", "contain"]),
17283
+ format: _enum([
17284
+ "rgb",
17285
+ "gray",
17286
+ "jpeg"
17287
+ ])
17288
+ });
17289
+ var FrameRefSchema = object({
17290
+ registryId: string().min(1),
17291
+ id: string().min(1),
17292
+ width: number().int().positive(),
17293
+ height: number().int().positive(),
17294
+ format: _enum(["rgb", "gray"]),
17295
+ timestamp: number(),
17296
+ capturedAt: number().optional()
17297
+ });
17246
17298
  var ModelFormatSchema$1 = _enum([
17247
17299
  "onnx",
17248
17300
  "coreml",
@@ -17487,6 +17539,12 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
17487
17539
  steps: array(PipelineStepInputSchema).min(1),
17488
17540
  frame: FrameInputSchema.optional(),
17489
17541
  /**
17542
+ * Process-local lazy frame. Valid only when caller and provider resolve
17543
+ * in the same execution-group process; split/cross-node callers use
17544
+ * `frame`/`image` inline compatibility instead.
17545
+ */
17546
+ frameRef: FrameRefSchema.optional(),
17547
+ /**
17490
17548
  * CB5 shm passthrough — a `FrameHandle` naming the same ring slot
17491
17549
  * the decoded pixels live in. One more member of the one-of
17492
17550
  * frame/frameHandle/image/imageBase64/referenceImage group.
@@ -17742,7 +17800,10 @@ var NativeCropResultSchema = object({
17742
17800
  * Which source served this crop, so a quality-sensitive consumer (the native
17743
17801
  * `keyFrame`) can reject a degraded fallback:
17744
17802
  * - `native` — cut from the decode worker's retained NATIVE surface (the
17745
- * quality path).
17803
+ * quality path). A subject-tile serve is also native-resolution and stays
17804
+ * `native` here: the public enum cannot name `tile` without a breaking cap
17805
+ * change. Runner telemetry distinguishes lease vs tile via `source` on the
17806
+ * internal crop result (`nativeHits` vs `tileHits`).
17746
17807
  * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
17747
17808
  * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
17748
17809
  * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
@@ -18233,12 +18294,41 @@ var RunnerLocalLoadSchema = object({
18233
18294
  * legacy `OrchestratorMetricsSchema` shape so existing dashboards keep
18234
18295
  * working unchanged when they switch to reading from the runner cap.
18235
18296
  */
18297
+ var FrameLazyCountersSchema = object({
18298
+ framesDecoded: number(),
18299
+ framesAdmitted: number(),
18300
+ framesDroppedPixelFree: number(),
18301
+ viewsMaterialized: number(),
18302
+ viewsSkipped: number(),
18303
+ workerToRunnerBytes: number(),
18304
+ runnerToPoolRawBytes: number(),
18305
+ runnerToPoolJpegBytes: number(),
18306
+ onDemandFullFrameRequests: number(),
18307
+ onDemandCropRequests: number(),
18308
+ nativeHits: number(),
18309
+ nativeMisses: number(),
18310
+ tileHits: number(),
18311
+ tileMisses: number(),
18312
+ fallbackHits: number(),
18313
+ fallbackMisses: number(),
18314
+ retainedWritesAvoided: number(),
18315
+ residentRefs: number(),
18316
+ residentBytes: number(),
18317
+ releases: number(),
18318
+ evictions: number(),
18319
+ staleMisses: number()
18320
+ });
18321
+ var FrameLazyMetricsSchema = object({
18322
+ node: FrameLazyCountersSchema,
18323
+ cameras: array(FrameLazyCountersSchema.extend({ deviceId: number() }))
18324
+ });
18236
18325
  var RunnerLocalMetricsSchema = object({
18237
18326
  nodeId: string(),
18238
18327
  activeCameras: number(),
18239
18328
  throttledCameras: number(),
18240
18329
  avgInferenceTimeMs: number(),
18241
- queueDepth: number()
18330
+ queueDepth: number(),
18331
+ frameLazy: FrameLazyMetricsSchema.optional()
18242
18332
  });
18243
18333
  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({
18244
18334
  handle: FrameHandleSchema,
@@ -19538,6 +19628,9 @@ method(_void(), ProviderInfoSchema), method(object({ config: record(string(), un
19538
19628
  location: StorageLocationSchema,
19539
19629
  relativePath: string()
19540
19630
  }), _void(), { kind: "mutation" }), method(object({ location: StorageLocationSchema }), number().nullable()), method(BeginUploadInputSchema, BeginUploadResultSchema, { kind: "mutation" }), method(WriteChunkInputSchema, _void(), { kind: "mutation" }), method(FinalizeUploadInputSchema, _void(), { kind: "mutation" }), method(AbortUploadInputSchema, _void(), { kind: "mutation" }), method(BeginDownloadInputSchema, BeginDownloadResultSchema, { kind: "mutation" }), method(ReadChunkInputSchema, _instanceof(Uint8Array)), method(EndDownloadInputSchema, _void(), { kind: "mutation" });
19631
+ /** Profile-exported FormBuilder schema. Shape is ConfigUISchema at the UI. */
19632
+ var ProfileSettingsSchemaBridge = unknown().nullable();
19633
+ var ProfileSettingsBagSchema = record(string(), unknown());
19541
19634
  /**
19542
19635
  * A live terminal session hosted by the provider addon. Output and input do
19543
19636
  * NOT flow through the capability — they use the addon data plane
@@ -19567,7 +19660,14 @@ var TerminalSessionInfoSchema = object({
19567
19660
  var TerminalProfileInfoSchema = object({
19568
19661
  profileId: string(),
19569
19662
  label: string(),
19570
- description: string().optional()
19663
+ description: string().optional(),
19664
+ /** Spawn defaults the instance form copies on create. */
19665
+ executable: string().optional(),
19666
+ args: array(string()).readonly().optional(),
19667
+ cwd: string().optional(),
19668
+ environment: array(string()).readonly().optional(),
19669
+ /** ConfigUISchema for instance knobs, or null when the profile has none. */
19670
+ settingsSchema: ProfileSettingsSchemaBridge.optional()
19571
19671
  });
19572
19672
  /**
19573
19673
  * A durable operator-created Terminal instance. Profiles are templates; only
@@ -19580,7 +19680,12 @@ var TerminalInstanceInfoSchema = object({
19580
19680
  profileId: string(),
19581
19681
  profileLabel: string(),
19582
19682
  name: string(),
19583
- enabled: boolean()
19683
+ enabled: boolean(),
19684
+ executable: string(),
19685
+ args: array(string()).readonly(),
19686
+ cwd: string(),
19687
+ environment: array(string()).readonly(),
19688
+ profileSettings: ProfileSettingsBagSchema
19584
19689
  });
19585
19690
  var TerminalLegacyCameraSchema = object({
19586
19691
  stableId: string(),
@@ -19610,7 +19715,23 @@ var TerminalOutputBatchSchema = object({
19610
19715
  method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }), method(_void(), array(TerminalInstanceInfoSchema).readonly(), { auth: "admin" }), method(object({
19611
19716
  targetNodeId: string().min(1),
19612
19717
  profileId: string().min(1),
19613
- name: string().trim().min(1).max(160).optional()
19718
+ name: string().trim().min(1).max(160).optional(),
19719
+ executable: string().max(1024).optional(),
19720
+ args: array(string().max(2048)).max(64).optional(),
19721
+ cwd: string().max(1024).optional(),
19722
+ environment: array(string().max(4096)).max(64).optional(),
19723
+ profileSettings: ProfileSettingsBagSchema.optional()
19724
+ }), TerminalInstanceInfoSchema, {
19725
+ kind: "mutation",
19726
+ auth: "admin"
19727
+ }), method(object({
19728
+ instanceId: string().min(1),
19729
+ name: string().trim().min(1).max(160).optional(),
19730
+ executable: string().max(1024).optional(),
19731
+ args: array(string().max(2048)).max(64).optional(),
19732
+ cwd: string().max(1024).optional(),
19733
+ environment: array(string().max(4096)).max(64).optional(),
19734
+ profileSettings: ProfileSettingsBagSchema.optional()
19614
19735
  }), TerminalInstanceInfoSchema, {
19615
19736
  kind: "mutation",
19616
19737
  auth: "admin"
@@ -19632,7 +19753,11 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
19632
19753
  }), method(_void(), array(TerminalSessionInfoSchema).readonly(), { auth: "admin" }), method(object({
19633
19754
  profileId: string(),
19634
19755
  cols: number().int().positive(),
19635
- rows: number().int().positive()
19756
+ rows: number().int().positive(),
19757
+ executable: string().max(1024).optional(),
19758
+ args: array(string().max(2048)).max(64).optional(),
19759
+ cwd: string().max(1024).optional(),
19760
+ environment: array(string().max(4096)).max(64).optional()
19636
19761
  }), TerminalSessionInfoSchema, {
19637
19762
  kind: "mutation",
19638
19763
  auth: "admin"
@@ -22414,10 +22539,10 @@ DeviceType.LawnMower, method(object({ deviceId: number().int().nonnegative() }),
22414
22539
  *
22415
22540
  * • The SDK (mobile / web client) consumes `getConnectionEndpoints()`
22416
22541
  * to receive an ordered list of candidate base URLs it should race
22417
- * on connect — LAN IPv4 first (lowest latency when on same network),
22418
- * then public hostname (if a tunnel is up), then IPv6. The SDK can
22419
- * race them with short timeouts and stick with the winner for the
22420
- * session.
22542
+ * on connect — LAN IPv4 and stable LAN IPv6 first (lowest latency
22543
+ * when on the same network), then public hostname (if a tunnel is
22544
+ * up). The SDK can race them with short timeouts and stick with the
22545
+ * winner for the session.
22421
22546
  *
22422
22547
  * Why hub-only: agents are not directly addressable by the operator's
22423
22548
  * clients — they reverse-connect to the hub. Exposing their interfaces
@@ -22572,6 +22697,17 @@ var NotificationEndpointSchema = object({
22572
22697
  /** What the ranking currently resolves to (null when nothing is reachable). */
22573
22698
  resolved: string().nullable()
22574
22699
  });
22700
+ /**
22701
+ * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
22702
+ * AUTO (every LAN IPv4 + the public tunnel). `resolved` is what that choice
22703
+ * currently expands to, so the UI can show the effective set either way.
22704
+ */
22705
+ var ViewerEndpointsSchema = object({
22706
+ /** The operator's explicit race set, or empty for AUTO. */
22707
+ baseUrls: array(string()).readonly(),
22708
+ /** What the ranking currently resolves to (may be empty if nothing is up). */
22709
+ resolved: array(string()).readonly()
22710
+ });
22575
22711
  var AllowedAddressesSchema = object({
22576
22712
  /**
22577
22713
  * Allowlist of interface addresses operators have explicitly opted
@@ -22580,6 +22716,20 @@ var AllowedAddressesSchema = object({
22580
22716
  * Network Addresses admin page and persisted by the addon.
22581
22717
  */
22582
22718
  addresses: array(string()).readonly() });
22719
+ var TlsStatusSchema = object({
22720
+ mode: _enum([
22721
+ "generated",
22722
+ "uploaded",
22723
+ "disabled"
22724
+ ]),
22725
+ leafFingerprintSha256: string().nullable(),
22726
+ caFingerprintSha256: string().nullable(),
22727
+ validTo: string().nullable(),
22728
+ sans: array(string()),
22729
+ caCertPem: string().nullable(),
22730
+ reissueError: string().nullable(),
22731
+ restartRequired: boolean()
22732
+ });
22583
22733
  method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
22584
22734
  /**
22585
22735
  * LEGACY HINT — do not send from new code. Kept optional so clients
@@ -22589,17 +22739,31 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
22589
22739
  */
22590
22740
  port: number().int().min(1).max(65535).optional(),
22591
22741
  /** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
22592
- * candidate. Default `true`. */
22742
+ * candidate. Default `false` — loopback is not a client route. */
22593
22743
  includeLoopback: boolean().optional(),
22594
- /** Skip IPv6 entries. Some legacy clients can't parse them.
22595
- * Default `false`. */
22744
+ /** Skip IPv6 entries. Default `false` the palette includes stable
22745
+ * LAN IPv6 (ICE/WebRTC uses dual-stack regardless). Pass `true` to
22746
+ * hide them. The viewer HTTP/WS race is `getViewerEndpoints`. */
22596
22747
  ipv4Only: boolean().optional(),
22597
22748
  /** Scheme to emit for LAN/loopback URLs. Default `'http'`.
22598
22749
  * Pass `'https'` when the caller is itself loaded over HTTPS
22599
22750
  * to avoid mixed-content blocks in the browser. The public
22600
22751
  * tunnel always emits `https://` regardless. */
22601
22752
  scheme: _enum(["http", "https"]).optional()
22602
- }), 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" });
22753
+ }), 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, {
22754
+ kind: "mutation",
22755
+ auth: "admin"
22756
+ }), method(object({
22757
+ certPem: string().min(1),
22758
+ keyPem: string().min(1),
22759
+ caPem: string().optional()
22760
+ }), TlsStatusSchema, {
22761
+ kind: "mutation",
22762
+ auth: "admin"
22763
+ }), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
22764
+ kind: "mutation",
22765
+ auth: "admin"
22766
+ });
22603
22767
  object({
22604
22768
  /** Lifecycle state of the lock. `jammed` means the motor reported
22605
22769
  * failure to reach the target — operator intervention required. */
@@ -28423,6 +28587,12 @@ Object.freeze({
28423
28587
  addonId: null,
28424
28588
  access: "create"
28425
28589
  },
28590
+ "localNetwork.downloadCa": {
28591
+ capName: "local-network",
28592
+ capScope: "system",
28593
+ addonId: null,
28594
+ access: "view"
28595
+ },
28426
28596
  "localNetwork.getAllowedAddresses": {
28427
28597
  capName: "local-network",
28428
28598
  capScope: "system",
@@ -28447,18 +28617,42 @@ Object.freeze({
28447
28617
  addonId: null,
28448
28618
  access: "view"
28449
28619
  },
28620
+ "localNetwork.getTlsStatus": {
28621
+ capName: "local-network",
28622
+ capScope: "system",
28623
+ addonId: null,
28624
+ access: "view"
28625
+ },
28626
+ "localNetwork.getViewerEndpoints": {
28627
+ capName: "local-network",
28628
+ capScope: "system",
28629
+ addonId: null,
28630
+ access: "view"
28631
+ },
28450
28632
  "localNetwork.list": {
28451
28633
  capName: "local-network",
28452
28634
  capScope: "system",
28453
28635
  addonId: null,
28454
28636
  access: "view"
28455
28637
  },
28638
+ "localNetwork.regenerateCertificate": {
28639
+ capName: "local-network",
28640
+ capScope: "system",
28641
+ addonId: null,
28642
+ access: "create"
28643
+ },
28456
28644
  "localNetwork.resetAllowlistToBestMatch": {
28457
28645
  capName: "local-network",
28458
28646
  capScope: "system",
28459
28647
  addonId: null,
28460
28648
  access: "delete"
28461
28649
  },
28650
+ "localNetwork.revertToGeneratedCertificate": {
28651
+ capName: "local-network",
28652
+ capScope: "system",
28653
+ addonId: null,
28654
+ access: "create"
28655
+ },
28462
28656
  "localNetwork.setAllowedAddresses": {
28463
28657
  capName: "local-network",
28464
28658
  capScope: "system",
@@ -28471,6 +28665,18 @@ Object.freeze({
28471
28665
  addonId: null,
28472
28666
  access: "create"
28473
28667
  },
28668
+ "localNetwork.setViewerEndpoints": {
28669
+ capName: "local-network",
28670
+ capScope: "system",
28671
+ addonId: null,
28672
+ access: "create"
28673
+ },
28674
+ "localNetwork.uploadCertificate": {
28675
+ capName: "local-network",
28676
+ capScope: "system",
28677
+ addonId: null,
28678
+ access: "create"
28679
+ },
28474
28680
  "lockControl.lock": {
28475
28681
  capName: "lock-control",
28476
28682
  capScope: "device",
@@ -31351,6 +31557,12 @@ Object.freeze({
31351
31557
  addonId: null,
31352
31558
  access: "create"
31353
31559
  },
31560
+ "terminalSession.updateInstance": {
31561
+ capName: "terminal-session",
31562
+ capScope: "system",
31563
+ addonId: null,
31564
+ access: "create"
31565
+ },
31354
31566
  "terminalSession.writeInput": {
31355
31567
  capName: "terminal-session",
31356
31568
  capScope: "system",
@@ -33838,6 +34050,35 @@ Object.freeze(Object.fromEntries([{
33838
34050
  }]
33839
34051
  }].map((s) => [s.stepId, s.defaultModelId])));
33840
34052
  string().min(1);
34053
+ var CLUSTER_STEP_SETTING_FIELDS = [{
34054
+ stepId: "face-embedding",
34055
+ key: "minLandmarkFaceSize",
34056
+ label: "Min face size for recognition (detection px)",
34057
+ 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.",
34058
+ type: "slider",
34059
+ min: 0,
34060
+ max: 64,
34061
+ step: 2,
34062
+ default: 24
34063
+ }];
34064
+ function clusterStepSettingKey(stepId, fieldKey) {
34065
+ return `clusterStepSetting:${stepId}:${fieldKey}`;
34066
+ }
34067
+ var ClusterSettingNumberSchema = number().finite();
34068
+ function readClusterStepSettings(config) {
34069
+ const out = {};
34070
+ for (const field of CLUSTER_STEP_SETTING_FIELDS) {
34071
+ const parsed = ClusterSettingNumberSchema.safeParse(config[clusterStepSettingKey(field.stepId, field.key)]);
34072
+ const value = parsed.success ? parsed.data : field.default;
34073
+ const existing = out[field.stepId] ?? {};
34074
+ out[field.stepId] = {
34075
+ ...existing,
34076
+ [field.key]: value
34077
+ };
34078
+ }
34079
+ return out;
34080
+ }
34081
+ readClusterStepSettings({});
33841
34082
  object({
33842
34083
  /**
33843
34084
  * 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_dist = require("../dist-B3cBbqzz.js");
5
+ const require_dist = require("../dist-BrkbC1tE.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-cyVteDFT.mjs";
1
+ import { a as EventCategory, i as BaseAddon, n as networkAccessCapability } from "../dist-CovkuhH2.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.25",
3
+ "version": "1.2.27",
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",