camstack 1.2.85 → 1.2.87

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.
@@ -20364,7 +20364,26 @@ var DiscoveryCandidateSchema = external_exports.object({
20364
20364
  * identity ahead of adoption. Rendering metadata (unit, precision)
20365
20365
  * flows live through the cap STATUS SLICE after adoption.
20366
20366
  */
20367
- sourceInfo: SourceInfoSchema.optional()
20367
+ sourceInfo: SourceInfoSchema.optional(),
20368
+ /**
20369
+ * Set when this candidate is a device the provider ALREADY owns.
20370
+ *
20371
+ * A scan cannot generally produce the identity a device was onboarded under
20372
+ * (Reolink keys on `mac-<mac>`, learned at adopt time), so a stableId
20373
+ * comparison never matches and an owned device looks addable. Re-adopting one
20374
+ * overwrites its config with scan-derived values — that is how a Home Hub's
20375
+ * Baichuan port was overwritten with its ONVIF port, taking the hub and its
20376
+ * three child cameras offline for four hours.
20377
+ *
20378
+ * A provider that can recognise its own devices says so here. Absent means
20379
+ * "not recognised", which is not the same as "known to be new" — a provider
20380
+ * that cannot tell simply never sets it.
20381
+ */
20382
+ alreadyOnboarded: external_exports.boolean().optional(),
20383
+ /** Numeric id of the device this candidate was matched to. Set with `alreadyOnboarded`. */
20384
+ onboardedDeviceId: external_exports.number().optional(),
20385
+ /** Operator-facing name of the matched device, so the UI can say WHICH one it is. */
20386
+ onboardedName: external_exports.string().optional()
20368
20387
  });
20369
20388
  var DeviceSummarySchema = external_exports.object({
20370
20389
  id: external_exports.number(),
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runDiscover
4
- } from "./chunk-Y3OL5WYZ.js";
4
+ } from "./chunk-I6O2CHPR.js";
5
5
  import "./chunk-LMMQX4CK.js";
6
6
 
7
7
  // src/cli.ts
@@ -38,7 +38,7 @@ async function runServe(args) {
38
38
  ...typeof values.data === "string" ? { data: values.data } : {}
39
39
  };
40
40
  Object.assign(process.env, buildServeEnv(opts));
41
- await import("./launcher-6T2UFXIG.js");
41
+ await import("./launcher-3OHBVI43.js");
42
42
  }
43
43
 
44
44
  // src/commands/agent.ts
@@ -83,7 +83,7 @@ async function runAgent(args) {
83
83
  ...typeof values.port === "string" ? { port: values.port } : {}
84
84
  };
85
85
  Object.assign(process.env, buildAgentEnv(opts));
86
- await import("./launcher-6T2UFXIG.js");
86
+ await import("./launcher-3OHBVI43.js");
87
87
  }
88
88
 
89
89
  // src/commands/setup.ts
@@ -1130,7 +1130,7 @@ function isUnknown(_value) {
1130
1130
  return true;
1131
1131
  }
1132
1132
  async function resolveServerInteractive(presetNamespace) {
1133
- const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-PPTEAP5N.js");
1133
+ const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-LZJPQBVA.js");
1134
1134
  if (presetNamespace) {
1135
1135
  const spinner4 = clack.spinner();
1136
1136
  spinner4.start(`Discovering hub on LAN (namespace "${presetNamespace}")`);
@@ -5,7 +5,7 @@ import {
5
5
  filterHubNodes,
6
6
  resolveHubFromDiscovered,
7
7
  runDiscover
8
- } from "./chunk-Y3OL5WYZ.js";
8
+ } from "./chunk-I6O2CHPR.js";
9
9
  import "./chunk-LMMQX4CK.js";
10
10
  export {
11
11
  DEFAULT_HUB_HTTPS_PORT,
@@ -23633,9 +23633,9 @@ var require_zod = __commonJS({
23633
23633
  }
23634
23634
  });
23635
23635
 
23636
- // ../system/dist/dist-whe0b4_3.js
23637
- var require_dist_whe0b4_3 = __commonJS({
23638
- "../system/dist/dist-whe0b4_3.js"(exports) {
23636
+ // ../system/dist/dist-D8VIyu_0.js
23637
+ var require_dist_D8VIyu_0 = __commonJS({
23638
+ "../system/dist/dist-D8VIyu_0.js"(exports) {
23639
23639
  "use strict";
23640
23640
  var zod = require_zod();
23641
23641
  var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
@@ -31077,7 +31077,26 @@ var require_dist_whe0b4_3 = __commonJS({
31077
31077
  * identity ahead of adoption. Rendering metadata (unit, precision)
31078
31078
  * flows live through the cap STATUS SLICE after adoption.
31079
31079
  */
31080
- sourceInfo: SourceInfoSchema.optional()
31080
+ sourceInfo: SourceInfoSchema.optional(),
31081
+ /**
31082
+ * Set when this candidate is a device the provider ALREADY owns.
31083
+ *
31084
+ * A scan cannot generally produce the identity a device was onboarded under
31085
+ * (Reolink keys on `mac-<mac>`, learned at adopt time), so a stableId
31086
+ * comparison never matches and an owned device looks addable. Re-adopting one
31087
+ * overwrites its config with scan-derived values — that is how a Home Hub's
31088
+ * Baichuan port was overwritten with its ONVIF port, taking the hub and its
31089
+ * three child cameras offline for four hours.
31090
+ *
31091
+ * A provider that can recognise its own devices says so here. Absent means
31092
+ * "not recognised", which is not the same as "known to be new" — a provider
31093
+ * that cannot tell simply never sets it.
31094
+ */
31095
+ alreadyOnboarded: zod.z.boolean().optional(),
31096
+ /** Numeric id of the device this candidate was matched to. Set with `alreadyOnboarded`. */
31097
+ onboardedDeviceId: zod.z.number().optional(),
31098
+ /** Operator-facing name of the matched device, so the UI can say WHICH one it is. */
31099
+ onboardedName: zod.z.string().optional()
31081
31100
  });
31082
31101
  var DeviceSummarySchema = zod.z.object({
31083
31102
  id: zod.z.number(),
@@ -60042,7 +60061,7 @@ var require_alerts_addon = __commonJS({
60042
60061
  [Symbol.toStringTag]: { value: "Module" }
60043
60062
  });
60044
60063
  require_chunk_Cek0wNdY();
60045
- var require_dist10 = require_dist_whe0b4_3();
60064
+ var require_dist10 = require_dist_D8VIyu_0();
60046
60065
  function selectExpired(alerts, cutoffMs) {
60047
60066
  return alerts.filter((a) => a.createdAt < cutoffMs).sort((a, b) => a.createdAt - b.createdAt).map((a) => a.id);
60048
60067
  }
@@ -60861,7 +60880,7 @@ var require_console_logging = __commonJS({
60861
60880
  [Symbol.toStringTag]: { value: "Module" }
60862
60881
  });
60863
60882
  require_chunk_Cek0wNdY();
60864
- var require_dist10 = require_dist_whe0b4_3();
60883
+ var require_dist10 = require_dist_D8VIyu_0();
60865
60884
  var require_formatter = require_formatter_DqAKDlvN();
60866
60885
  var LEVEL_RANK = {
60867
60886
  debug: 0,
@@ -60955,7 +60974,7 @@ var require_core_blocks_addon = __commonJS({
60955
60974
  "use strict";
60956
60975
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
60957
60976
  var require_chunk = require_chunk_Cek0wNdY();
60958
- var require_dist10 = require_dist_whe0b4_3();
60977
+ var require_dist10 = require_dist_D8VIyu_0();
60959
60978
  var node_crypto = __require("crypto");
60960
60979
  var node_fs_promises = __require("fs/promises");
60961
60980
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -61852,11 +61871,11 @@ var require_core_blocks = __commonJS({
61852
61871
  }
61853
61872
  });
61854
61873
 
61855
- // ../system/dist/retired-settings-keys-BdvmiaK7.js
61856
- var require_retired_settings_keys_BdvmiaK7 = __commonJS({
61857
- "../system/dist/retired-settings-keys-BdvmiaK7.js"(exports) {
61874
+ // ../system/dist/retired-settings-keys-wakiINPT.js
61875
+ var require_retired_settings_keys_wakiINPT = __commonJS({
61876
+ "../system/dist/retired-settings-keys-wakiINPT.js"(exports) {
61858
61877
  "use strict";
61859
- var require_dist10 = require_dist_whe0b4_3();
61878
+ var require_dist10 = require_dist_D8VIyu_0();
61860
61879
  function settingsStoreIsAuthoritativeHere(env) {
61861
61880
  const raw = (env["CAMSTACK_ROLE"] ?? "").trim().toLowerCase();
61862
61881
  return raw === "" || raw === "hub";
@@ -64070,8 +64089,8 @@ var require_device_manager_addon = __commonJS({
64070
64089
  [Symbol.toStringTag]: { value: "Module" }
64071
64090
  });
64072
64091
  require_chunk_Cek0wNdY();
64073
- var require_dist10 = require_dist_whe0b4_3();
64074
- var require_retired_settings_keys = require_retired_settings_keys_BdvmiaK7();
64092
+ var require_dist10 = require_dist_D8VIyu_0();
64093
+ var require_retired_settings_keys = require_retired_settings_keys_wakiINPT();
64075
64094
  var node_crypto = __require("crypto");
64076
64095
  var _camstack_types_node = require_node();
64077
64096
  var JOB_HISTORY = 20;
@@ -65547,7 +65566,10 @@ var require_device_manager_addon = __commonJS({
65547
65566
  stableId: d.stableId,
65548
65567
  type: d.type,
65549
65568
  suggestedName: d.suggestedName,
65550
- prefilledConfig: d.prefilledConfig
65569
+ prefilledConfig: d.prefilledConfig,
65570
+ ...d.alreadyOnboarded === true ? { alreadyOnboarded: true } : {},
65571
+ ...d.onboardedDeviceId !== void 0 ? { onboardedDeviceId: d.onboardedDeviceId } : {},
65572
+ ...d.onboardedName !== void 0 ? { onboardedName: d.onboardedName } : {}
65551
65573
  }));
65552
65574
  }
65553
65575
  async function adoptDevice(pctx, input) {
@@ -69340,7 +69362,7 @@ var require_hub_forwarder = __commonJS({
69340
69362
  [Symbol.toStringTag]: { value: "Module" }
69341
69363
  });
69342
69364
  require_chunk_Cek0wNdY();
69343
- var require_dist10 = require_dist_whe0b4_3();
69365
+ var require_dist10 = require_dist_D8VIyu_0();
69344
69366
  var require_formatter = require_formatter_DqAKDlvN();
69345
69367
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
69346
69368
  var HubForwarderDestination = class {
@@ -69477,7 +69499,7 @@ var require_liveness_monitor_addon = __commonJS({
69477
69499
  "use strict";
69478
69500
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
69479
69501
  require_chunk_Cek0wNdY();
69480
- var require_dist10 = require_dist_whe0b4_3();
69502
+ var require_dist10 = require_dist_D8VIyu_0();
69481
69503
  var NO_DEVICES = "liveness:no-devices";
69482
69504
  var ALL_OFFLINE = "liveness:all-devices-offline";
69483
69505
  var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
@@ -69667,7 +69689,7 @@ var require_local_auth_addon = __commonJS({
69667
69689
  [Symbol.toStringTag]: { value: "Module" }
69668
69690
  });
69669
69691
  var require_chunk = require_chunk_Cek0wNdY();
69670
- var require_dist10 = require_dist_whe0b4_3();
69692
+ var require_dist10 = require_dist_D8VIyu_0();
69671
69693
  var node_crypto = __require("crypto");
69672
69694
  node_crypto = require_chunk.__toESM(node_crypto);
69673
69695
  var crypto$1 = __require("crypto");
@@ -77480,7 +77502,7 @@ var require_loki_logging = __commonJS({
77480
77502
  [Symbol.toStringTag]: { value: "Module" }
77481
77503
  });
77482
77504
  require_chunk_Cek0wNdY();
77483
- var require_dist10 = require_dist_whe0b4_3();
77505
+ var require_dist10 = require_dist_D8VIyu_0();
77484
77506
  function sanitizeLabelName(raw) {
77485
77507
  const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
77486
77508
  return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
@@ -78045,7 +78067,7 @@ var require_native_metrics_addon = __commonJS({
78045
78067
  [Symbol.toStringTag]: { value: "Module" }
78046
78068
  });
78047
78069
  var require_chunk = require_chunk_Cek0wNdY();
78048
- var require_dist10 = require_dist_whe0b4_3();
78070
+ var require_dist10 = require_dist_D8VIyu_0();
78049
78071
  var node_fs_promises = __require("fs/promises");
78050
78072
  var node_child_process = __require("child_process");
78051
78073
  var node_util = __require("util");
@@ -80629,7 +80651,7 @@ var require_filesystem_storage_addon = __commonJS({
80629
80651
  [Symbol.toStringTag]: { value: "Module" }
80630
80652
  });
80631
80653
  var require_chunk = require_chunk_Cek0wNdY();
80632
- var require_dist10 = require_dist_whe0b4_3();
80654
+ var require_dist10 = require_dist_D8VIyu_0();
80633
80655
  var node_crypto = __require("crypto");
80634
80656
  var node_fs_promises = __require("fs/promises");
80635
80657
  var node_path = __require("path");
@@ -81745,8 +81767,8 @@ var require_sqlite_settings_addon = __commonJS({
81745
81767
  [Symbol.toStringTag]: { value: "Module" }
81746
81768
  });
81747
81769
  var require_chunk = require_chunk_Cek0wNdY();
81748
- var require_dist10 = require_dist_whe0b4_3();
81749
- var require_retired_settings_keys = require_retired_settings_keys_BdvmiaK7();
81770
+ var require_dist10 = require_dist_D8VIyu_0();
81771
+ var require_retired_settings_keys = require_retired_settings_keys_wakiINPT();
81750
81772
  var node_crypto = __require("crypto");
81751
81773
  var node_fs = __require("fs");
81752
81774
  var node_module = __require("module");
@@ -84236,7 +84258,7 @@ var require_storage_orchestrator_addon = __commonJS({
84236
84258
  [Symbol.toStringTag]: { value: "Module" }
84237
84259
  });
84238
84260
  var require_chunk = require_chunk_Cek0wNdY();
84239
- var require_dist10 = require_dist_whe0b4_3();
84261
+ var require_dist10 = require_dist_D8VIyu_0();
84240
84262
  var require_hub_cap_forward = require_hub_cap_forward_DmHNjbB0();
84241
84263
  var zod = require_zod();
84242
84264
  var node_crypto = __require("crypto");
@@ -87187,7 +87209,7 @@ var require_system_config_addon = __commonJS({
87187
87209
  [Symbol.toStringTag]: { value: "Module" }
87188
87210
  });
87189
87211
  require_chunk_Cek0wNdY();
87190
- var require_dist10 = require_dist_whe0b4_3();
87212
+ var require_dist10 = require_dist_D8VIyu_0();
87191
87213
  var SECTION_TITLES = {
87192
87214
  server: "Server",
87193
87215
  auth: "Authentication"
@@ -105248,7 +105270,7 @@ var require_winston_logging = __commonJS({
105248
105270
  [Symbol.toStringTag]: { value: "Module" }
105249
105271
  });
105250
105272
  var require_chunk = require_chunk_Cek0wNdY();
105251
- var require_dist10 = require_dist_whe0b4_3();
105273
+ var require_dist10 = require_dist_D8VIyu_0();
105252
105274
  var require_formatter = require_formatter_DqAKDlvN();
105253
105275
  var node_path = __require("path");
105254
105276
  node_path = require_chunk.__toESM(node_path);
@@ -117750,12 +117772,12 @@ var require_dist2 = __commonJS({
117750
117772
  }
117751
117773
  });
117752
117774
 
117753
- // ../system/dist/manifest-system-deps-y5vZBO6q.js
117754
- var require_manifest_system_deps_y5vZBO6q = __commonJS({
117755
- "../system/dist/manifest-system-deps-y5vZBO6q.js"(exports) {
117775
+ // ../system/dist/manifest-system-deps-BbP419V1.js
117776
+ var require_manifest_system_deps_BbP419V1 = __commonJS({
117777
+ "../system/dist/manifest-system-deps-BbP419V1.js"(exports) {
117756
117778
  "use strict";
117757
117779
  var require_chunk = require_chunk_Cek0wNdY();
117758
- require_dist_whe0b4_3();
117780
+ require_dist_D8VIyu_0();
117759
117781
  require_hub_cap_forward_DmHNjbB0();
117760
117782
  var node_crypto = __require("crypto");
117761
117783
  node_crypto = require_chunk.__toESM(node_crypto);
@@ -129822,7 +129844,7 @@ var require_dist3 = __commonJS({
129822
129844
  "use strict";
129823
129845
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
129824
129846
  var require_chunk = require_chunk_Cek0wNdY();
129825
- var require_dist10 = require_dist_whe0b4_3();
129847
+ var require_dist10 = require_dist_D8VIyu_0();
129826
129848
  var require_builtins_alerts_alerts_addon = require_alerts_addon();
129827
129849
  require_alerts();
129828
129850
  var require_formatter = require_formatter_DqAKDlvN();
@@ -129849,7 +129871,7 @@ var require_dist3 = __commonJS({
129849
129871
  var require_builtins_winston_logging_index = require_winston_logging();
129850
129872
  var require_file_data_plane = require_file_data_plane_DO8KbxCe();
129851
129873
  var require_tls$1 = require_tls_BxQlomxd();
129852
- var require_manifest_system_deps = require_manifest_system_deps_y5vZBO6q();
129874
+ var require_manifest_system_deps = require_manifest_system_deps_BbP419V1();
129853
129875
  var require_resource_monitor = require_resource_monitor_CdnzxBLP();
129854
129876
  var require_custom_action_registry = require_custom_action_registry_jY0NOZK8();
129855
129877
  var zod = require_zod();
@@ -218247,7 +218269,26 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
218247
218269
  * identity ahead of adoption. Rendering metadata (unit, precision)
218248
218270
  * flows live through the cap STATUS SLICE after adoption.
218249
218271
  */
218250
- sourceInfo: SourceInfoSchema.optional()
218272
+ sourceInfo: SourceInfoSchema.optional(),
218273
+ /**
218274
+ * Set when this candidate is a device the provider ALREADY owns.
218275
+ *
218276
+ * A scan cannot generally produce the identity a device was onboarded under
218277
+ * (Reolink keys on `mac-<mac>`, learned at adopt time), so a stableId
218278
+ * comparison never matches and an owned device looks addable. Re-adopting one
218279
+ * overwrites its config with scan-derived values — that is how a Home Hub's
218280
+ * Baichuan port was overwritten with its ONVIF port, taking the hub and its
218281
+ * three child cameras offline for four hours.
218282
+ *
218283
+ * A provider that can recognise its own devices says so here. Absent means
218284
+ * "not recognised", which is not the same as "known to be new" — a provider
218285
+ * that cannot tell simply never sets it.
218286
+ */
218287
+ alreadyOnboarded: zod.z.boolean().optional(),
218288
+ /** Numeric id of the device this candidate was matched to. Set with `alreadyOnboarded`. */
218289
+ onboardedDeviceId: zod.z.number().optional(),
218290
+ /** Operator-facing name of the matched device, so the UI can say WHICH one it is. */
218291
+ onboardedName: zod.z.string().optional()
218251
218292
  });
218252
218293
  var DeviceSummarySchema = zod.z.object({
218253
218294
  id: zod.z.number(),
@@ -239772,6 +239813,23 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
239772
239813
  * failed — logged at ERROR with `tags.deviceId` and surfaced via
239773
239814
  * `getStatus().error`.
239774
239815
  */
239816
+ /**
239817
+ * Repair a row's PERSISTED config blob immediately before it is restored.
239818
+ * Default: no-op — most providers have nothing to heal.
239819
+ *
239820
+ * This exists because a restored device self-hydrates from the DB: `create()`
239821
+ * passes `{}` and `BaseDevice` parses the stored blob against the device
239822
+ * schema. A blob that lost a REQUIRED field therefore fails restore forever,
239823
+ * and no later pass revisits it — a hub-adopted Reolink camera whose blob had
239824
+ * been emptied failed all four bounded attempts against fields
239825
+ * (`host`, `password`) it inherits from its parent and never dials itself.
239826
+ *
239827
+ * Implementations get every saved row, so a child can read its parent's blob.
239828
+ * A heal that throws is treated like any other restore failure: retried under
239829
+ * the bound, then reported — never swallowed.
239830
+ */
239831
+ async healSavedConfig(_saved, _allSaved) {
239832
+ }
239775
239833
  async onRestoreDevices(savedDevices) {
239776
239834
  const restored = /* @__PURE__ */ new Set();
239777
239835
  const failures = [];
@@ -239780,6 +239838,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
239780
239838
  const Class = this.deviceClasses[saved.type];
239781
239839
  if (!Class) throw new Error(`no device class registered for type "${saved.type}"`);
239782
239840
  if (saved.parentDeviceId !== null && !restored.has(saved.parentDeviceId)) throw new Error(`parent device ${saved.parentDeviceId} not restored`);
239841
+ await this.healSavedConfig(saved, savedDevices);
239783
239842
  await this.ctx.kernel.devices.create(saved.stableId, Class, {}, saved.parentDeviceId);
239784
239843
  restored.add(saved.id);
239785
239844
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "camstack",
3
- "version": "1.2.85",
3
+ "version": "1.2.87",
4
4
  "description": "CLI tool for managing and running CamStack server",
5
5
  "keywords": [
6
6
  "camstack",