@camstack/system 1.2.481 → 1.2.483

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.
Files changed (109) hide show
  1. package/dist/addon-runner.js +2 -2
  2. package/dist/addon-runner.mjs +2 -2
  3. package/dist/{agent-https-o3X-jkS7.js → agent-https-CHZpVx3I.js} +1 -1
  4. package/dist/{agent-https-doVPSeiy.mjs → agent-https-NP141VCW.mjs} +1 -1
  5. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  6. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  7. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  8. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  9. package/dist/builtins/alerts/alerts.addon.js +3 -3
  10. package/dist/builtins/alerts/alerts.addon.mjs +3 -3
  11. package/dist/builtins/alerts/device-label.d.ts +2 -2
  12. package/dist/builtins/autotrack/index.js +1 -1
  13. package/dist/builtins/autotrack/index.mjs +1 -1
  14. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +2 -2
  15. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2 -2
  16. package/dist/builtins/calendars/calendars.addon.js +1 -1
  17. package/dist/builtins/calendars/calendars.addon.mjs +1 -1
  18. package/dist/builtins/camera-grid/acquire-retry.d.ts +1 -1
  19. package/dist/builtins/camera-grid/addon.d.ts +2 -2
  20. package/dist/builtins/camera-grid/grid-profiles.d.ts +1 -1
  21. package/dist/builtins/camera-grid/grid-sentry-sources.d.ts +1 -1
  22. package/dist/builtins/camera-grid/index.js +3 -3
  23. package/dist/builtins/camera-grid/index.mjs +3 -3
  24. package/dist/builtins/composer/composer.addon.js +4 -4
  25. package/dist/builtins/composer/composer.addon.mjs +4 -4
  26. package/dist/builtins/composer/existing-target.d.ts +1 -1
  27. package/dist/builtins/composer/own-field-reads.d.ts +1 -1
  28. package/dist/builtins/console-logging/index.js +2 -2
  29. package/dist/builtins/console-logging/index.mjs +2 -2
  30. package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
  31. package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
  32. package/dist/builtins/device-history/device-history.addon.js +2 -2
  33. package/dist/builtins/device-history/device-history.addon.mjs +2 -2
  34. package/dist/builtins/device-manager/device-aggregation.d.ts +1 -1
  35. package/dist/builtins/device-manager/device-bindings-store.d.ts +3 -3
  36. package/dist/builtins/device-manager/device-manager.addon.js +9 -9
  37. package/dist/builtins/device-manager/device-manager.addon.mjs +9 -9
  38. package/dist/builtins/device-manager/device-meta-types.d.ts +2 -2
  39. package/dist/builtins/device-manager/device-online-fallback.d.ts +1 -1
  40. package/dist/builtins/hub-forwarder/index.js +2 -2
  41. package/dist/builtins/hub-forwarder/index.mjs +2 -2
  42. package/dist/builtins/keychain/index.js +3 -3
  43. package/dist/builtins/keychain/index.mjs +3 -3
  44. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  45. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  46. package/dist/builtins/local-auth/local-auth.addon.js +2 -2
  47. package/dist/builtins/local-auth/local-auth.addon.mjs +2 -2
  48. package/dist/builtins/local-network/local-network.addon.js +2 -2
  49. package/dist/builtins/local-network/local-network.addon.mjs +2 -2
  50. package/dist/builtins/loki-logging/index.js +1 -1
  51. package/dist/builtins/loki-logging/index.mjs +1 -1
  52. package/dist/builtins/native-metrics/native-metrics.addon.d.ts +1 -1
  53. package/dist/builtins/native-metrics/native-metrics.addon.js +3 -3
  54. package/dist/builtins/native-metrics/native-metrics.addon.mjs +3 -3
  55. package/dist/builtins/native-metrics/thread-cpu-sampler.d.ts +1 -1
  56. package/dist/builtins/platform-probe/index.js +1 -1
  57. package/dist/builtins/platform-probe/index.mjs +1 -1
  58. package/dist/builtins/record-entries/index.js +1 -1
  59. package/dist/builtins/record-entries/index.mjs +1 -1
  60. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  61. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  62. package/dist/builtins/snapshot/index.js +1 -1
  63. package/dist/builtins/snapshot/index.mjs +1 -1
  64. package/dist/builtins/snapshot/snapshot-fatigue.d.ts +1 -1
  65. package/dist/builtins/snapshot/snapshot-link-url.d.ts +1 -1
  66. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  67. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  68. package/dist/builtins/sqlite-storage/filter-compiler.d.ts +1 -1
  69. package/dist/builtins/sqlite-storage/index.js +1 -1
  70. package/dist/builtins/sqlite-storage/index.mjs +1 -1
  71. package/dist/builtins/sqlite-storage/prefix-range.d.ts +2 -2
  72. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +2 -2
  73. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +2 -2
  74. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  75. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  76. package/dist/builtins/system-config/system-config.addon.js +3 -3
  77. package/dist/builtins/system-config/system-config.addon.mjs +280 -280
  78. package/dist/builtins/winston-logging/index.js +2 -2
  79. package/dist/builtins/winston-logging/index.mjs +2 -2
  80. package/dist/{composition-sources-BrDtOpfE.mjs → composition-sources-CC13wGKL.mjs} +1 -1
  81. package/dist/{composition-sources-BmhhDWIc.js → composition-sources-CQxrCexr.js} +1 -1
  82. package/dist/{constants-BVJrLycr.js → constants-Bt0NFXDm.js} +1 -1
  83. package/dist/{constants-xuLNi4a2.mjs → constants-DMB-ex5z.mjs} +1 -1
  84. package/dist/{device-ca-DgLZPn5R.js → device-ca-CSLMfr4Q.js} +1 -1
  85. package/dist/{device-ca-DKOZSFED.mjs → device-ca-HQKcvofS.mjs} +1 -1
  86. package/dist/{dist--v3KMKa1.js → dist-2gZWO597.js} +2215 -241
  87. package/dist/{dist-BIJXQo_j.mjs → dist-DvKEKSap.mjs} +2215 -241
  88. package/dist/file-host-worker.js +1 -1
  89. package/dist/file-host-worker.mjs +1 -1
  90. package/dist/{formatter-B7qW8bPJ.mjs → formatter-DkYZ4LXp.mjs} +1 -1
  91. package/dist/{formatter-DqAKDlvN.js → formatter-xbxeV4GD.js} +1 -1
  92. package/dist/{hub-mdns-ciao-C3NJsOvK.js → hub-mdns-ciao-Bs3cn9C1.js} +2 -2
  93. package/dist/{hub-mdns-ciao-DMFXIlMY.mjs → hub-mdns-ciao-CVf6mxIZ.mjs} +2 -2
  94. package/dist/index.js +131 -17
  95. package/dist/index.mjs +129 -18
  96. package/dist/kernel/addon-installer.d.ts +25 -5
  97. package/dist/kernel/addon-version-policy.d.ts +26 -0
  98. package/dist/kernel/heap-watch.d.ts +1 -1
  99. package/dist/kernel/index.d.ts +2 -0
  100. package/dist/kernel/moleculer/trpc-links.d.ts +1 -1
  101. package/dist/kernel/transport/socket-channel.d.ts +1 -1
  102. package/dist/logging/formatter.d.ts +1 -1
  103. package/dist/{restore-archive-DAEsvFY6.mjs → restore-archive-EFYeCdrG.mjs} +78 -78
  104. package/dist/{restore-archive-DpkdAuFf.js → restore-archive-_mgadWlk.js} +1 -1
  105. package/dist/{retention-DbunrLR4.mjs → retention-FFJW3-3P.mjs} +1 -1
  106. package/dist/{retention-C71dNCIh.js → retention-qugQGYuY.js} +1 -1
  107. package/dist/{wal-maintenance-CsGk4kYn.js → wal-maintenance-DbUC_wdC.js} +0 -0
  108. package/dist/{wal-maintenance-DYAJwPWu.mjs → wal-maintenance-TCW_esAc.mjs} +0 -0
  109. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  require("./chunk-Cek0wNdY.js");
2
- const require_wal_maintenance = require("./wal-maintenance-CsGk4kYn.js");
2
+ const require_wal_maintenance = require("./wal-maintenance-DbUC_wdC.js");
3
3
  let node_worker_threads = require("node:worker_threads");
4
4
  //#region src/builtins/sqlite-storage/file-host-worker.ts
5
5
  /**
@@ -1,4 +1,4 @@
1
- import { C as RecordsEngine, D as callVector, E as callRecords, O as controlTargetOf, T as callData, _ as collectTransferables, a as WalMaintenance, b as isFileHostWorkerData, h as serializeError, l as SqliteSettingsBackend, o as createVectorIndex, s as vectorProviderOf, w as callControl, x as trustInput, y as isFileHostRequest } from "./wal-maintenance-DYAJwPWu.mjs";
1
+ import { C as RecordsEngine, D as callVector, E as callRecords, O as controlTargetOf, T as callData, _ as collectTransferables, a as WalMaintenance, b as isFileHostWorkerData, h as serializeError, l as SqliteSettingsBackend, o as createVectorIndex, s as vectorProviderOf, w as callControl, x as trustInput, y as isFileHostRequest } from "./wal-maintenance-TCW_esAc.mjs";
2
2
  import { parentPort, threadId, workerData } from "node:worker_threads";
3
3
  //#region src/builtins/sqlite-storage/file-host-worker.ts
4
4
  /**
@@ -81,7 +81,7 @@ function buildBrand(entry) {
81
81
  /**
82
82
  * Build the optional device-context bracket. Returns `null` when the
83
83
  * line doesn't carry a device tag — renders as just the brand + message
84
- * without the second bracket. With a device tag: `salone` / `#42`.
84
+ * without the second bracket. With a device tag: `hall` / `#42`.
85
85
  */
86
86
  function buildDeviceContext(entry) {
87
87
  return resolveDevice(entry.tags);
@@ -81,7 +81,7 @@ function buildBrand(entry) {
81
81
  /**
82
82
  * Build the optional device-context bracket. Returns `null` when the
83
83
  * line doesn't carry a device tag — renders as just the brand + message
84
- * without the second bracket. With a device tag: `salone` / `#42`.
84
+ * without the second bracket. With a device tag: `hall` / `#42`.
85
85
  */
86
86
  function buildDeviceContext(entry) {
87
87
  return resolveDevice(entry.tags);
@@ -1,7 +1,7 @@
1
1
  const require_chunk = require("./chunk-Cek0wNdY.js");
2
- const require_dist = require("./dist--v3KMKa1.js");
2
+ const require_dist = require("./dist-2gZWO597.js");
3
3
  const require_x509_es = require("./x509.es-WtnRNyYS.js");
4
- const require_agent_https = require("./agent-https-o3X-jkS7.js");
4
+ const require_agent_https = require("./agent-https-CHZpVx3I.js");
5
5
  let node_crypto = require("node:crypto");
6
6
  let _camstack_types_node = require("@camstack/types/node");
7
7
  let node_fs_promises = require("node:fs/promises");
@@ -1,7 +1,7 @@
1
1
  import { o as __toESM } from "./chunk-CNf5ZN-e.mjs";
2
- import { Da as userError } from "./dist-BIJXQo_j.mjs";
2
+ import { Da as userError } from "./dist-DvKEKSap.mjs";
3
3
  import { f as X509Certificate$1 } from "./x509.es-BRiJgOvu.mjs";
4
- import { D as reasonRequiresNewCa, E as evaluateExistingCert, F as readNameConstraints, N as permitsIdentity, _ as issueLeaf, b as collectCertIdentity, g as generateCa, j as isConstrainedCa, v as loadCa, y as localCaCommonName } from "./agent-https-doVPSeiy.mjs";
4
+ import { D as reasonRequiresNewCa, E as evaluateExistingCert, F as readNameConstraints, N as permitsIdentity, _ as issueLeaf, b as collectCertIdentity, g as generateCa, j as isConstrainedCa, v as loadCa, y as localCaCommonName } from "./agent-https-NP141VCW.mjs";
5
5
  import { X509Certificate, createPrivateKey } from "node:crypto";
6
6
  import { writeOwnerOnlyFileSync } from "@camstack/types/node";
7
7
  import { mkdir, writeFile } from "node:fs/promises";
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("./chunk-Cek0wNdY.js");
3
- const require_dist = require("./dist--v3KMKa1.js");
4
- const require_device_ca = require("./device-ca-DgLZPn5R.js");
3
+ const require_dist = require("./dist-2gZWO597.js");
4
+ const require_device_ca = require("./device-ca-CSLMfr4Q.js");
5
5
  const require_read_all_rows$1 = require("./read-all-rows-CVoO1ONM.js");
6
6
  const require_builtins_alerts_alerts_addon = require("./builtins/alerts/alerts.addon.js");
7
7
  require("./builtins/alerts/index.js");
@@ -9,7 +9,7 @@ const require_builtins_calendars_calendars_addon = require("./builtins/calendars
9
9
  require("./builtins/calendars/index.js");
10
10
  const require_builtins_composer_composer_addon = require("./builtins/composer/composer.addon.js");
11
11
  require("./builtins/composer/index.js");
12
- const require_formatter = require("./formatter-DqAKDlvN.js");
12
+ const require_formatter = require("./formatter-xbxeV4GD.js");
13
13
  const require_builtins_console_logging_index = require("./builtins/console-logging/index.js");
14
14
  const require_prefix_walk = require("./prefix-walk-Dv6MLZlM.js");
15
15
  const require_builtins_core_blocks_core_blocks_addon = require("./builtins/core-blocks/core-blocks.addon.js");
@@ -26,21 +26,21 @@ const require_builtins_loki_logging_index = require("./builtins/loki-logging/ind
26
26
  const require_builtins_native_metrics_native_metrics_addon = require("./builtins/native-metrics/native-metrics.addon.js");
27
27
  const require_builtins_device_history_device_history_addon = require("./builtins/device-history/device-history.addon.js");
28
28
  const require_builtins_sqlite_storage_filesystem_storage_addon = require("./builtins/sqlite-storage/filesystem-storage.addon.js");
29
- const require_wal_maintenance = require("./wal-maintenance-CsGk4kYn.js");
29
+ const require_wal_maintenance = require("./wal-maintenance-DbUC_wdC.js");
30
30
  const require_builtins_sqlite_storage_sqlite_settings_addon = require("./builtins/sqlite-storage/sqlite-settings.addon.js");
31
31
  const require_builtins_sqlite_storage_index = require("./builtins/sqlite-storage/index.js");
32
32
  const require_builtins_storage_orchestrator_storage_orchestrator_addon = require("./builtins/storage-orchestrator/storage-orchestrator.addon.js");
33
33
  require("./builtins/storage-orchestrator/index.js");
34
- const require_agent_https = require("./agent-https-o3X-jkS7.js");
35
- const require_constants = require("./constants-BVJrLycr.js");
34
+ const require_agent_https = require("./agent-https-CHZpVx3I.js");
35
+ const require_constants = require("./constants-Bt0NFXDm.js");
36
36
  const require_builtins_system_config_system_config_addon = require("./builtins/system-config/system-config.addon.js");
37
37
  require("./builtins/system-config/index.js");
38
38
  const require_builtins_winston_logging_index = require("./builtins/winston-logging/index.js");
39
39
  const require_custom_action_registry = require("./custom-action-registry-MRyes5j0.js");
40
- const require_hub_mdns_ciao = require("./hub-mdns-ciao-C3NJsOvK.js");
40
+ const require_hub_mdns_ciao = require("./hub-mdns-ciao-Bs3cn9C1.js");
41
41
  const require_platform_key_source = require("./platform-key-source-Di7HrlGR.js");
42
42
  const require_resource_monitor = require("./resource-monitor-mio9dSCT.js");
43
- const require_restore_archive = require("./restore-archive-DpkdAuFf.js");
43
+ const require_restore_archive = require("./restore-archive-_mgadWlk.js");
44
44
  const require_coral_accelerators = require("./coral-accelerators-BSVsBVzt.js");
45
45
  let zod = require("zod");
46
46
  let node_crypto = require("node:crypto");
@@ -7528,6 +7528,34 @@ var AddonManifest = class {
7528
7528
  }
7529
7529
  };
7530
7530
  //#endregion
7531
+ //#region src/kernel/addon-version-policy.ts
7532
+ /**
7533
+ * Which version an installed addon should be running (D942).
7534
+ *
7535
+ * The hub's target is the registry dist-tag `latest`. An agent's target is
7536
+ * the hub's installed version — never the registry, and never "strictly
7537
+ * newer". A missing target is an unreadable authority: a failed read changes
7538
+ * nothing (D49), including never a move downward because the registry or the
7539
+ * hub could not be asked.
7540
+ */
7541
+ var ADDON_VERSION_REASON_REGISTRY_LATEST = "installed version differs from registry latest";
7542
+ var ADDON_VERSION_REASON_HUB = "agent follows the hub installed version";
7543
+ /**
7544
+ * Move when `installed` is not `target`. `target === null` (or empty) means
7545
+ * the authority could not be read — keep whatever is installed.
7546
+ * `installed === null` with a known target is a first install of that target.
7547
+ */
7548
+ function decideAddonVersionMove(installed, target, reason) {
7549
+ if (target === null || target.length === 0) return { move: false };
7550
+ if (installed !== null && installed === target) return { move: false };
7551
+ return {
7552
+ move: true,
7553
+ from: installed ?? "absent",
7554
+ to: target,
7555
+ reason
7556
+ };
7557
+ }
7558
+ //#endregion
7531
7559
  //#region src/kernel/deps/closure-dedupe.ts
7532
7560
  /**
7533
7561
  * Closure dedupe — stop copying into every addon the libraries the server
@@ -8282,6 +8310,25 @@ function readPackageJson(pkgJsonPath) {
8282
8310
  function shouldSkipClosureProvidedSeed(packageName, isResolvable) {
8283
8311
  return packageName === "@camstack/system" && isResolvable;
8284
8312
  }
8313
+ /** How long a boot-time `dist-tags.latest` read may take before it is "unreadable". */
8314
+ var REGISTRY_LATEST_TIMEOUT_MS = 15e3;
8315
+ function readInstalledPackageVersion(addonDir) {
8316
+ try {
8317
+ const raw = JSON.parse(node_fs.readFileSync(node_path.join(addonDir, "package.json"), "utf-8"));
8318
+ if (raw === null || typeof raw !== "object") return null;
8319
+ const version = Reflect.get(raw, "version");
8320
+ return typeof version === "string" && version.length > 0 ? version : null;
8321
+ } catch {
8322
+ return null;
8323
+ }
8324
+ }
8325
+ function distTagLatest(body) {
8326
+ if (body === null || typeof body !== "object") return null;
8327
+ const tags = Reflect.get(body, "dist-tags");
8328
+ if (tags === null || typeof tags !== "object") return null;
8329
+ const latest = Reflect.get(tags, "latest");
8330
+ return typeof latest === "string" && latest.length > 0 ? latest : null;
8331
+ }
8285
8332
  /** Minimal no-op logger for default parameter */
8286
8333
  var noopLogger = {
8287
8334
  debug() {},
@@ -8315,7 +8362,7 @@ var STAGING_RESIDUE_MIN_AGE_MS = 30 * 6e4;
8315
8362
  * npm error path …/.staging/install-14820-2026-08-07T12-28-28-875Z/package/package.json
8316
8363
  *
8317
8364
  * which the propagation then reported as `runtime dependency install failed`.
8318
- * Observed on the Mac desktop agent and on little-unraid on 2026-08-07.
8365
+ * Observed on the Mac desktop agent and on agent-a on 2026-08-07.
8319
8366
  *
8320
8367
  * So a sweep only removes what cannot be live: not a tree this process is
8321
8368
  * building, and not one young enough to belong to anybody's in-flight install.
@@ -8332,6 +8379,7 @@ var AddonInstaller = class AddonInstaller {
8332
8379
  isPackageResolvable;
8333
8380
  /** Test seam — production resolves via `CAMSTACK_FRAMEWORK_DIR`. */
8334
8381
  closureNodeModulesDir;
8382
+ resolveLatestVersionOverride;
8335
8383
  /**
8336
8384
  * Central manifest of installed addons. Tracks version + source +
8337
8385
  * timestamps + last-backup pointer per package, written atomically
@@ -8354,6 +8402,7 @@ var AddonInstaller = class AddonInstaller {
8354
8402
  this.manifest = new AddonManifest(config.addonsDir);
8355
8403
  this.isPackageResolvable = config.isPackageResolvable;
8356
8404
  this.closureNodeModulesDir = config.closureNodeModulesDir;
8405
+ this.resolveLatestVersionOverride = config.resolveLatestVersion;
8357
8406
  if (config.installSource) this.installSource = config.installSource;
8358
8407
  else this.installSource = "npm";
8359
8408
  }
@@ -8467,10 +8516,13 @@ var AddonInstaller = class AddonInstaller {
8467
8516
  * defaults to npm in production.
8468
8517
  *
8469
8518
  * There is no version argument and there is deliberately no pin: the system is
8470
- * addons-agnostic and `latest` is the whole contract at first boot (operator,
8471
- * 2026-08-13). A copy already under the addon root is never replaced either —
8472
- * bootstrap is seed-only, and overwriting a deployed bundle would be an
8473
- * un-deploy ([D90](../../../../docs/decisions/adr-0090.md)).
8519
+ * addons-agnostic and `latest` is the whole contract (operator, 2026-08-13,
8520
+ * restated 2026-10-25 — D942). A copy already under the addon root is left
8521
+ * alone when this installer is not on the npm source (a workspace or a
8522
+ * bundled desktop seed) and when the package is the closure-provided
8523
+ * `@camstack/system` (a copy there would shadow the closure). Every other
8524
+ * required addon already on disk is moved to registry `latest` when that
8525
+ * tag differs, higher or lower. An unreadable registry changes nothing.
8474
8526
  *
8475
8527
  * @param packages — optional custom package list (default: REQUIRED_PACKAGES)
8476
8528
  */
@@ -8486,7 +8538,16 @@ var AddonInstaller = class AddonInstaller {
8486
8538
  for (const packageName of pkgList) {
8487
8539
  const addonDir = node_path.join(this.addonsDir, packageName);
8488
8540
  if (node_fs.existsSync(node_path.join(addonDir, "package.json"))) {
8489
- this.logger.debug(`${packageName} — already installed, skipping`);
8541
+ if (this.installSource !== "npm" || shouldSkipClosureProvidedSeed(packageName, this.isResolvableFromClosure(packageName))) {
8542
+ this.logger.debug(`${packageName} — already installed, skipping`);
8543
+ continue;
8544
+ }
8545
+ try {
8546
+ await this.followInstalledAddonToLatest(packageName, addonDir);
8547
+ } catch (err) {
8548
+ const msg = require_dist.errMsg(err);
8549
+ this.logger.error(`Failed to move ${packageName} to registry latest`, { meta: { error: msg } });
8550
+ }
8490
8551
  continue;
8491
8552
  }
8492
8553
  if (shouldSkipClosureProvidedSeed(packageName, this.isResolvableFromClosure(packageName))) {
@@ -8511,6 +8572,56 @@ var AddonInstaller = class AddonInstaller {
8511
8572
  }
8512
8573
  }
8513
8574
  /**
8575
+ * Move an already-installed required addon to registry `latest` when the
8576
+ * installed version differs. `applyUpdate` keeps the previous tree as a
8577
+ * backup and restores it if the install throws. A null latest (registry
8578
+ * down, or no tag) leaves the copy where it is.
8579
+ */
8580
+ async followInstalledAddonToLatest(packageName, addonDir) {
8581
+ const installedVersion = readInstalledPackageVersion(addonDir);
8582
+ const decision = decideAddonVersionMove(installedVersion, await this.readRegistryLatest(packageName), ADDON_VERSION_REASON_REGISTRY_LATEST);
8583
+ if (!decision.move) {
8584
+ this.logger.debug(`${packageName} — installed copy matches registry latest, or the registry could not be read`);
8585
+ return;
8586
+ }
8587
+ this.logger.info(`${packageName} — moving ${decision.from} → ${decision.to}: ${decision.reason}`, { meta: {
8588
+ from: decision.from,
8589
+ to: decision.to,
8590
+ reason: decision.reason
8591
+ } });
8592
+ if (this.manifest.get(packageName) == null) this.manifest.upsert(packageName, {
8593
+ version: installedVersion ?? "0.0.0",
8594
+ source: "npm"
8595
+ });
8596
+ await this.applyUpdate(packageName, decision.to);
8597
+ }
8598
+ /** `dist-tags.latest`, or `null` when the registry cannot be read. */
8599
+ async readRegistryLatest(packageName) {
8600
+ if (this.resolveLatestVersionOverride) try {
8601
+ return await this.resolveLatestVersionOverride(packageName);
8602
+ } catch (err) {
8603
+ this.logger.warn(`${packageName} — registry unreadable, leaving the installed copy`, { meta: { error: require_dist.errMsg(err) } });
8604
+ return null;
8605
+ }
8606
+ return this.fetchRegistryLatest(packageName);
8607
+ }
8608
+ async fetchRegistryLatest(packageName) {
8609
+ const metadataUrl = `${(this.registry ?? "https://registry.npmjs.org").replace(/\/+$/, "")}/${encodeURIComponent(packageName).replace(/^%40/, "@")}`;
8610
+ try {
8611
+ const metadataRes = await fetch(metadataUrl, { signal: AbortSignal.timeout(REGISTRY_LATEST_TIMEOUT_MS) });
8612
+ if (!metadataRes.ok) {
8613
+ this.logger.warn(`${packageName} — registry answered ${metadataRes.status}, leaving the installed copy`);
8614
+ return null;
8615
+ }
8616
+ const latest = distTagLatest(await metadataRes.json());
8617
+ if (latest === null) this.logger.warn(`${packageName} — registry returned no dist-tags.latest, leaving the installed copy`);
8618
+ return latest;
8619
+ } catch (err) {
8620
+ this.logger.warn(`${packageName} — registry unreadable, leaving the installed copy`, { meta: { error: require_dist.errMsg(err) } });
8621
+ return null;
8622
+ }
8623
+ }
8624
+ /**
8514
8625
  * Reconcile the install manifest against the addons actually present on
8515
8626
  * disk: register seeded addons, correct a version that disagrees with the
8516
8627
  * installed `package.json`, and drop entries naming a directory that does
@@ -9725,7 +9836,7 @@ function isDirEntry(entry, parentDir) {
9725
9836
  *
9726
9837
  * Measured 2026-08-07/08 on the live cluster:
9727
9838
  *
9728
- * little-unraid `@camstack/system.bak-pre-unshadow` — no package.json left,
9839
+ * agent-a `@camstack/system.bak-pre-unshadow` — no package.json left,
9729
9840
  * so not loadable, but the agent main process held five live
9730
9841
  * mappings of `better_sqlite3.node` out of it (D87).
9731
9842
  * macmini `@camstack/system.bak-pre-1272-1786129145` — still declares
@@ -19325,7 +19436,7 @@ var SocketChannel = class {
19325
19436
  * `res` frame, or the socket's `close` (which drains `pending`) — so a peer
19326
19437
  * that receives the request and then neither answers nor closes leaves the
19327
19438
  * caller pending forever. That is a wedged handler, or a half-open socket
19328
- * after a child died without a clean teardown, and it is how camera 615 spent
19439
+ * after a child died without a clean teardown, and it is how camera 101 spent
19329
19440
  * 30+ minutes with every inference permit held by a call that was never
19330
19441
  * coming back.
19331
19442
  */
@@ -22303,7 +22414,7 @@ function buildLinkChain(target, localResolver, hookup) {
22303
22414
  /**
22304
22415
  * Can libva initialise the VA driver on this node's render node? (D926)
22305
22416
  *
22306
- * Measured 2026-10-23 (intel-1.2.509, hub + little-unraid): Intel's iHD 25.2.4
22417
+ * Measured 2026-10-23 (intel-1.2.509, hub + agent-a): Intel's iHD 25.2.4
22307
22418
  * exports only `__vaDriverInit_1_22`, the container's Ubuntu libva 2.20 looks
22308
22419
  * for `_1_20`, and `vaInitialize` failed — while the resolver kept offering
22309
22420
  * `qsv, vaapi`. Every session tried, failed and fell back to software: 722
@@ -27769,6 +27880,8 @@ function resetCatalogRegistryForTests() {
27769
27880
  shared = null;
27770
27881
  }
27771
27882
  //#endregion
27883
+ exports.ADDON_VERSION_REASON_HUB = ADDON_VERSION_REASON_HUB;
27884
+ exports.ADDON_VERSION_REASON_REGISTRY_LATEST = ADDON_VERSION_REASON_REGISTRY_LATEST;
27772
27885
  exports.AGENT_CAP_FWD_ACTION = AGENT_CAP_FWD_ACTION;
27773
27886
  exports.AGENT_CAP_FWD_SERVICE = AGENT_CAP_FWD_SERVICE;
27774
27887
  exports.AGENT_DASHBOARD_ORIGINS_FIELD = require_builtins_system_config_system_config_addon.AGENT_DASHBOARD_ORIGINS_FIELD;
@@ -28115,6 +28228,7 @@ exports.createUdsLogger = createUdsLogger;
28115
28228
  exports.createUdsLoggerWithControl = createUdsLoggerWithControl;
28116
28229
  exports.createV8Reclaimer = createV8Reclaimer;
28117
28230
  exports.currentBrokerTransporter = currentBrokerTransporter;
28231
+ exports.decideAddonVersionMove = decideAddonVersionMove;
28118
28232
  exports.deleteModelFromDisk = require_custom_action_registry.deleteModelFromDisk;
28119
28233
  exports.deriveAgentListenPort = deriveAgentListenPort;
28120
28234
  exports.describeCsr = require_builtins_system_config_system_config_addon.describeCsr;