@camstack/system 1.2.22 → 1.2.23

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 (60) hide show
  1. package/dist/addon-runner.js +1 -1
  2. package/dist/addon-runner.mjs +1 -1
  3. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  4. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  5. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  6. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  7. package/dist/builtins/alerts/alerts.addon.js +1 -1
  8. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  9. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.d.ts +0 -9
  10. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -40
  11. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -40
  12. package/dist/builtins/console-logging/index.js +1 -1
  13. package/dist/builtins/console-logging/index.mjs +1 -1
  14. package/dist/builtins/device-manager/device-manager.addon.js +1 -1
  15. package/dist/builtins/device-manager/device-manager.addon.mjs +1 -1
  16. package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
  17. package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
  18. package/dist/builtins/hub-forwarder/index.js +1 -1
  19. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  20. package/dist/builtins/local-auth/local-auth.addon.js +1 -1
  21. package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
  22. package/dist/builtins/local-network/local-network.addon.d.ts +16 -0
  23. package/dist/builtins/local-network/local-network.addon.js +30 -2
  24. package/dist/builtins/local-network/local-network.addon.mjs +30 -2
  25. package/dist/builtins/loki-logging/index.js +34 -12
  26. package/dist/builtins/loki-logging/index.mjs +34 -12
  27. package/dist/builtins/loki-logging/loki-logging.addon.d.ts +19 -0
  28. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  29. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  30. package/dist/builtins/platform-probe/index.js +1 -1
  31. package/dist/builtins/platform-probe/index.mjs +1 -1
  32. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  33. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  34. package/dist/builtins/snapshot/index.js +1 -1
  35. package/dist/builtins/snapshot/index.mjs +1 -1
  36. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  37. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  38. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +1 -1
  39. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +1 -1
  40. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +7 -0
  41. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +108 -4
  42. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +108 -4
  43. package/dist/builtins/storage-orchestrator/storage-orchestrator.service.d.ts +11 -1
  44. package/dist/builtins/storage-orchestrator/storage-pressure-manager.d.ts +5 -0
  45. package/dist/builtins/system-config/system-config.addon.js +1 -1
  46. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  47. package/dist/builtins/winston-logging/index.js +1 -1
  48. package/dist/builtins/winston-logging/index.mjs +1 -1
  49. package/dist/{dist-C9_XdXl5.mjs → dist-CIek6F9X.mjs} +436 -72
  50. package/dist/{dist-j49ewCPY.js → dist-CS0pdC8l.js} +436 -72
  51. package/dist/index.js +58 -8
  52. package/dist/index.mjs +58 -8
  53. package/dist/kernel/capability-registry.d.ts +9 -0
  54. package/dist/kernel/transport/local-child-registry.d.ts +18 -0
  55. package/dist/kernel/transport/parent-unowned-call.d.ts +22 -0
  56. package/dist/logging/log-manager.d.ts +32 -1
  57. package/dist/logging/partitioned-log-buffer.d.ts +15 -3
  58. package/dist/{manifest-python-deps-B30qVAuW.mjs → manifest-python-deps-57PA4rHm.mjs} +15 -6
  59. package/dist/{manifest-python-deps-CnRW2Utv.js → manifest-python-deps-CqDPWqEE.js} +14 -5
  60. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  const require_chunk = require("./chunk-Cek0wNdY.js");
2
- const require_manifest_python_deps = require("./manifest-python-deps-CnRW2Utv.js");
2
+ const require_manifest_python_deps = require("./manifest-python-deps-CqDPWqEE.js");
3
3
  const require_custom_action_registry = require("./custom-action-registry-jY0NOZK8.js");
4
4
  let node_fs = require("node:fs");
5
5
  node_fs = require_chunk.__toESM(node_fs);
@@ -1,4 +1,4 @@
1
- import { Ct as resolveAddonClass, I as createUdsLoggerWithControl, L as LocalChildClient, at as setWorkerNativeCapsChangeListener, bt as installManifestNativeDeps, i as createUdsAddonContext, nt as getWorkerNativeCapProvider, rt as getWorkerNativeCapSnapshot, st as validateProviderRegistrations, t as installManifestPythonDeps } from "./manifest-python-deps-B30qVAuW.mjs";
1
+ import { Ct as resolveAddonClass, I as createUdsLoggerWithControl, L as LocalChildClient, at as setWorkerNativeCapsChangeListener, bt as installManifestNativeDeps, i as createUdsAddonContext, nt as getWorkerNativeCapProvider, rt as getWorkerNativeCapSnapshot, st as validateProviderRegistrations, t as installManifestPythonDeps } from "./manifest-python-deps-57PA4rHm.mjs";
2
2
  import { t as CustomActionRegistry } from "./custom-action-registry-F__gp_VX.mjs";
3
3
  import { register } from "node:module";
4
4
  import * as fs from "node:fs";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-j49ewCPY.js");
6
+ const require_dist = require("../../dist-CS0pdC8l.js");
7
7
  const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
8
8
  let node_fs = require("node:fs");
9
9
  node_fs = require_chunk.__toESM(node_fs);
@@ -1,4 +1,4 @@
1
- import { at as BaseAddon, it as errMsg, jt as EventCategory, p as addonPagesCapability } from "../../dist-C9_XdXl5.mjs";
1
+ import { at as BaseAddon, it as errMsg, jt as EventCategory, p as addonPagesCapability } from "../../dist-CIek6F9X.mjs";
2
2
  import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
3
3
  import * as fs from "node:fs";
4
4
  import * as path$1 from "node:path";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-j49ewCPY.js");
6
+ const require_dist = require("../../dist-CS0pdC8l.js");
7
7
  const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
8
8
  let node_fs = require("node:fs");
9
9
  node_fs = require_chunk.__toESM(node_fs);
@@ -1,4 +1,4 @@
1
- import { at as BaseAddon, h as addonWidgetsCapability, it as errMsg, jt as EventCategory } from "../../dist-C9_XdXl5.mjs";
1
+ import { at as BaseAddon, h as addonWidgetsCapability, it as errMsg, jt as EventCategory } from "../../dist-CIek6F9X.mjs";
2
2
  import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
3
3
  import * as fs from "node:fs";
4
4
  import * as path$1 from "node:path";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-j49ewCPY.js");
6
+ const require_dist = require("../../dist-CS0pdC8l.js");
7
7
  //#region src/builtins/alerts/alerts.addon.ts
8
8
  var CATEGORY_MAPPINGS = {
9
9
  "addon.crashed": {
@@ -1,4 +1,4 @@
1
- import { at as BaseAddon, g as alertsCapability, it as errMsg, jt as EventCategory, n as AlertSchema, vt as createEvent } from "../../dist-C9_XdXl5.mjs";
1
+ import { at as BaseAddon, g as alertsCapability, it as errMsg, jt as EventCategory, n as AlertSchema, vt as createEvent } from "../../dist-CIek6F9X.mjs";
2
2
  //#region src/builtins/alerts/alerts.addon.ts
3
3
  var CATEGORY_MAPPINGS = {
4
4
  "addon.crashed": {
@@ -149,15 +149,6 @@ export declare class BackupOrchestratorAddon extends BaseAddon<Record<string, ne
149
149
  private listSchedules;
150
150
  private upsertSchedule;
151
151
  private deleteSchedule;
152
- /**
153
- * One-shot migration: pre-schedule installs carried the cron on each
154
- * `BackupDestinationPolicy`. When the schedule table is empty but
155
- * policies with crons exist, mint one schedule per cron'd destination
156
- * so existing scheduled backups keep firing after the redesign. The
157
- * legacy per-location cron is left intact but the scheduler no longer
158
- * reads it, so no double-fire.
159
- */
160
- private migrateLegacyCronToSchedules;
161
152
  private resolveScheduleService;
162
153
  private resolvePolicyService;
163
154
  /**
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-j49ewCPY.js");
6
+ const require_dist = require("../../dist-CS0pdC8l.js");
7
7
  let node_fs = require("node:fs");
8
8
  let node_fs$1 = require_chunk.__toESM(node_fs, 1);
9
9
  node_fs = require_chunk.__toESM(node_fs);
@@ -4815,7 +4815,6 @@ var BackupOrchestratorAddon = class extends require_dist.BaseAddon {
4815
4815
  this.schedules = this.resolveScheduleService();
4816
4816
  if (this.schedules) try {
4817
4817
  await this.schedules.initialize();
4818
- await this.migrateLegacyCronToSchedules();
4819
4818
  } catch (err) {
4820
4819
  this.ctx.logger.error("backup-orchestrator: schedule table init failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
4821
4820
  this.schedules = null;
@@ -5449,44 +5448,6 @@ var BackupOrchestratorAddon = class extends require_dist.BaseAddon {
5449
5448
  if (!this.schedules) return;
5450
5449
  await this.schedules.delete(input.id);
5451
5450
  }
5452
- /**
5453
- * One-shot migration: pre-schedule installs carried the cron on each
5454
- * `BackupDestinationPolicy`. When the schedule table is empty but
5455
- * policies with crons exist, mint one schedule per cron'd destination
5456
- * so existing scheduled backups keep firing after the redesign. The
5457
- * legacy per-location cron is left intact but the scheduler no longer
5458
- * reads it, so no double-fire.
5459
- */
5460
- async migrateLegacyCronToSchedules() {
5461
- if (!this.schedules || !this.policies) return;
5462
- if ((await this.schedules.list()).length > 0) return;
5463
- const cronned = (await this.policies.list()).filter((p) => p.cron && p.cron.trim().length > 0);
5464
- if (cronned.length === 0) return;
5465
- for (const p of cronned) {
5466
- const schedule = {
5467
- id: (0, node_crypto.randomUUID)(),
5468
- label: p.label ?? p.locationId,
5469
- cron: p.cron ?? "",
5470
- enabled: p.enabled,
5471
- locationIds: [p.locationId],
5472
- retentionCount: p.retentionCount,
5473
- ...p.lastRunAt !== void 0 ? { lastRunAt: p.lastRunAt } : {}
5474
- };
5475
- try {
5476
- await this.schedules.upsert(schedule);
5477
- this.ctx.logger.info("Migrated legacy per-location cron to schedule", { meta: {
5478
- locationId: p.locationId,
5479
- scheduleId: schedule.id,
5480
- cron: schedule.cron
5481
- } });
5482
- } catch (err) {
5483
- this.ctx.logger.warn("Legacy cron migration failed for destination", { meta: {
5484
- locationId: p.locationId,
5485
- error: err instanceof Error ? err.message : String(err)
5486
- } });
5487
- }
5488
- }
5489
- }
5490
5451
  resolveScheduleService() {
5491
5452
  const reg = this.ctx.kernel.capabilityRegistry;
5492
5453
  if (!reg) return null;
@@ -1,4 +1,4 @@
1
- import { at as BaseAddon, jt as EventCategory, y as backupCapability } from "../../dist-C9_XdXl5.mjs";
1
+ import { at as BaseAddon, jt as EventCategory, y as backupCapability } from "../../dist-CIek6F9X.mjs";
2
2
  import * as fs from "node:fs";
3
3
  import Kt from "node:fs";
4
4
  import * as path$1 from "node:path";
@@ -4800,7 +4800,6 @@ var BackupOrchestratorAddon = class extends BaseAddon {
4800
4800
  this.schedules = this.resolveScheduleService();
4801
4801
  if (this.schedules) try {
4802
4802
  await this.schedules.initialize();
4803
- await this.migrateLegacyCronToSchedules();
4804
4803
  } catch (err) {
4805
4804
  this.ctx.logger.error("backup-orchestrator: schedule table init failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
4806
4805
  this.schedules = null;
@@ -5434,44 +5433,6 @@ var BackupOrchestratorAddon = class extends BaseAddon {
5434
5433
  if (!this.schedules) return;
5435
5434
  await this.schedules.delete(input.id);
5436
5435
  }
5437
- /**
5438
- * One-shot migration: pre-schedule installs carried the cron on each
5439
- * `BackupDestinationPolicy`. When the schedule table is empty but
5440
- * policies with crons exist, mint one schedule per cron'd destination
5441
- * so existing scheduled backups keep firing after the redesign. The
5442
- * legacy per-location cron is left intact but the scheduler no longer
5443
- * reads it, so no double-fire.
5444
- */
5445
- async migrateLegacyCronToSchedules() {
5446
- if (!this.schedules || !this.policies) return;
5447
- if ((await this.schedules.list()).length > 0) return;
5448
- const cronned = (await this.policies.list()).filter((p) => p.cron && p.cron.trim().length > 0);
5449
- if (cronned.length === 0) return;
5450
- for (const p of cronned) {
5451
- const schedule = {
5452
- id: randomUUID(),
5453
- label: p.label ?? p.locationId,
5454
- cron: p.cron ?? "",
5455
- enabled: p.enabled,
5456
- locationIds: [p.locationId],
5457
- retentionCount: p.retentionCount,
5458
- ...p.lastRunAt !== void 0 ? { lastRunAt: p.lastRunAt } : {}
5459
- };
5460
- try {
5461
- await this.schedules.upsert(schedule);
5462
- this.ctx.logger.info("Migrated legacy per-location cron to schedule", { meta: {
5463
- locationId: p.locationId,
5464
- scheduleId: schedule.id,
5465
- cron: schedule.cron
5466
- } });
5467
- } catch (err) {
5468
- this.ctx.logger.warn("Legacy cron migration failed for destination", { meta: {
5469
- locationId: p.locationId,
5470
- error: err instanceof Error ? err.message : String(err)
5471
- } });
5472
- }
5473
- }
5474
- }
5475
5436
  resolveScheduleService() {
5476
5437
  const reg = this.ctx.kernel.capabilityRegistry;
5477
5438
  if (!reg) return null;
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-j49ewCPY.js");
6
+ const require_dist = require("../../dist-CS0pdC8l.js");
7
7
  const require_formatter = require("../../formatter-DqAKDlvN.js");
8
8
  //#region src/builtins/console-logging/console-destination.ts
9
9
  var LEVEL_RANK = {
@@ -1,4 +1,4 @@
1
- import { at as BaseAddon, z as logDestinationCapability } from "../../dist-C9_XdXl5.mjs";
1
+ import { at as BaseAddon, z as logDestinationCapability } from "../../dist-CIek6F9X.mjs";
2
2
  import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
3
3
  //#region src/builtins/console-logging/console-destination.ts
4
4
  var LEVEL_RANK = {
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-j49ewCPY.js");
6
+ const require_dist = require("../../dist-CS0pdC8l.js");
7
7
  let _camstack_types_node = require("@camstack/types/node");
8
8
  let zod = require("zod");
9
9
  let node_crypto = require("node:crypto");
@@ -1,4 +1,4 @@
1
- import { At as sleep, C as deviceStatusCapability, Ct as isDeviceConfigCap, D as enumerateSchemaFields, E as enumerateItemArrayFields, G as parseStreamParamsFormPatch, O as evaluateLinkExpression, S as deviceStateCapability, U as normalizeUnit, Y as setByPath, _ as applyTransform, a as CAP_NAMES_WITH_STATUS, at as BaseAddon, b as buildStreamParamsConfigSchema, dt as DeviceType, it as errMsg, j as getByPath, jt as EventCategory, l as STREAM_PROFILE_META, lt as DeviceFeature, mt as WELL_KNOWN_TAB_MAP, o as DeviceStatusSchema, rt as validateExpressionSource, t as ALL_CAPABILITY_DEFINITIONS, tt as toExpressionValue, ut as DeviceRole, x as deviceManagerCapability } from "../../dist-C9_XdXl5.mjs";
1
+ import { At as sleep, C as deviceStatusCapability, Ct as isDeviceConfigCap, D as enumerateSchemaFields, E as enumerateItemArrayFields, G as parseStreamParamsFormPatch, O as evaluateLinkExpression, S as deviceStateCapability, U as normalizeUnit, Y as setByPath, _ as applyTransform, a as CAP_NAMES_WITH_STATUS, at as BaseAddon, b as buildStreamParamsConfigSchema, dt as DeviceType, it as errMsg, j as getByPath, jt as EventCategory, l as STREAM_PROFILE_META, lt as DeviceFeature, mt as WELL_KNOWN_TAB_MAP, o as DeviceStatusSchema, rt as validateExpressionSource, t as ALL_CAPABILITY_DEFINITIONS, tt as toExpressionValue, ut as DeviceRole, x as deviceManagerCapability } from "../../dist-CIek6F9X.mjs";
2
2
  import { canonicalDeviceFingerprint } from "@camstack/types/node";
3
3
  import { z } from "zod";
4
4
  import { randomUUID } from "node:crypto";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-j49ewCPY.js");
6
+ const require_dist = require("../../dist-CS0pdC8l.js");
7
7
  //#region src/builtins/doorbell/trigger-engine.ts
8
8
  /**
9
9
  * Pure trigger logic for the virtual-doorbell builtin — edge detection over
@@ -1,4 +1,4 @@
1
- import { at as BaseAddon, dt as DeviceType, it as errMsg, jt as EventCategory, vt as createEvent, w as doorbellCapability } from "../../dist-C9_XdXl5.mjs";
1
+ import { at as BaseAddon, dt as DeviceType, it as errMsg, jt as EventCategory, vt as createEvent, w as doorbellCapability } from "../../dist-CIek6F9X.mjs";
2
2
  //#region src/builtins/doorbell/trigger-engine.ts
3
3
  /**
4
4
  * Pure trigger logic for the virtual-doorbell builtin — edge detection over
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-j49ewCPY.js");
6
+ const require_dist = require("../../dist-CS0pdC8l.js");
7
7
  const require_formatter = require("../../formatter-DqAKDlvN.js");
8
8
  //#region src/builtins/hub-forwarder/hub-forwarder-destination.ts
9
9
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
@@ -1,4 +1,4 @@
1
- import { at as BaseAddon, z as logDestinationCapability } from "../../dist-C9_XdXl5.mjs";
1
+ import { at as BaseAddon, z as logDestinationCapability } from "../../dist-CIek6F9X.mjs";
2
2
  import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
3
3
  //#region src/builtins/hub-forwarder/hub-forwarder-destination.ts
4
4
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-j49ewCPY.js");
6
+ const require_dist = require("../../dist-CS0pdC8l.js");
7
7
  let node_crypto = require("node:crypto");
8
8
  node_crypto = require_chunk.__toESM(node_crypto);
9
9
  let crypto$1 = require("crypto");
@@ -1,5 +1,5 @@
1
1
  import { i as __require, o as __toESM, t as __commonJSMin } from "../../chunk-CNf5ZN-e.mjs";
2
- import { at as BaseAddon, f as UserRecordSchema, nt as userManagementCapability, r as ApiKeyRecordSchema, u as ScopedTokenSchema, v as authProviderCapability } from "../../dist-C9_XdXl5.mjs";
2
+ import { at as BaseAddon, f as UserRecordSchema, nt as userManagementCapability, r as ApiKeyRecordSchema, u as ScopedTokenSchema, v as authProviderCapability } from "../../dist-CIek6F9X.mjs";
3
3
  import * as crypto$1 from "node:crypto";
4
4
  import { randomUUID } from "node:crypto";
5
5
  import nodeCrypto from "crypto";
@@ -20,6 +20,14 @@ interface LocalNetworkConfig {
20
20
  * with LAN/Wi-Fi addresses) from "operator explicitly cleared the
21
21
  * allowlist" (true + empty → respect operator's choice). */
22
22
  readonly bootSeeded: boolean;
23
+ /**
24
+ * The endpoint outbound artifacts (notification attachment links, deep
25
+ * links) must be addressed by. Empty = AUTO: the first public candidate,
26
+ * never loopback. Stored VERBATIM rather than as an index into the candidate
27
+ * list — interfaces come and go, and an index would silently re-point at a
28
+ * different address after a reboot.
29
+ */
30
+ readonly notificationBaseUrl: string;
23
31
  }
24
32
  export declare class LocalNetworkAddon extends BaseAddon<LocalNetworkConfig> {
25
33
  private pollTimer;
@@ -35,6 +43,14 @@ export declare class LocalNetworkAddon extends BaseAddon<LocalNetworkConfig> {
35
43
  */
36
44
  private meshEndpoint;
37
45
  constructor();
46
+ /**
47
+ * What AUTO currently resolves to for outbound artifact links: the first
48
+ * PUBLIC candidate, never loopback and never a LAN address — a link is
49
+ * opened on someone's phone, off this network, possibly hours later.
50
+ * `null` when nothing public is reachable (the caller then ships bytes only
51
+ * rather than a link that 404s).
52
+ */
53
+ private resolveNotificationEndpoint;
38
54
  protected onInitialize(): Promise<ProviderRegistration[]>;
39
55
  protected onShutdown(): Promise<void>;
40
56
  /**
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("../../chunk-Cek0wNdY.js");
3
- const require_dist = require("../../dist-j49ewCPY.js");
3
+ const require_dist = require("../../dist-CS0pdC8l.js");
4
4
  let node_os = require("node:os");
5
5
  node_os = require_chunk.__toESM(node_os);
6
6
  //#region src/builtins/local-network/local-network.addon.ts
@@ -44,9 +44,25 @@ var LocalNetworkAddon = class extends require_dist.BaseAddon {
44
44
  constructor() {
45
45
  super({
46
46
  allowedAddresses: [],
47
- bootSeeded: false
47
+ bootSeeded: false,
48
+ notificationBaseUrl: ""
48
49
  });
49
50
  }
51
+ /**
52
+ * What AUTO currently resolves to for outbound artifact links: the first
53
+ * PUBLIC candidate, never loopback and never a LAN address — a link is
54
+ * opened on someone's phone, off this network, possibly hours later.
55
+ * `null` when nothing public is reachable (the caller then ships bytes only
56
+ * rather than a link that 404s).
57
+ */
58
+ resolveNotificationEndpoint() {
59
+ const explicit = this.config.notificationBaseUrl;
60
+ if (explicit !== "") return explicit;
61
+ if (this.publicHostname !== "") return `https://${this.publicHostname}`;
62
+ const mesh = this.meshEndpoint;
63
+ if (mesh !== null && mesh.host !== "") return `https://${mesh.host}:${mesh.port}`;
64
+ return null;
65
+ }
50
66
  async onInitialize() {
51
67
  if (!this.config.bootSeeded) {
52
68
  const seed = autoSeedAllowlist(this.enumerate());
@@ -71,6 +87,18 @@ var LocalNetworkAddon = class extends require_dist.BaseAddon {
71
87
  await this.reconcileMeshEndpoint();
72
88
  return { endpoints: buildEndpoints(interfaces, input.port, includeLoopback, ipv4Only, this.publicHostname, scheme, this.meshEndpoint) };
73
89
  },
90
+ getNotificationEndpoint: async () => ({
91
+ baseUrl: this.config.notificationBaseUrl === "" ? null : this.config.notificationBaseUrl,
92
+ resolved: this.resolveNotificationEndpoint()
93
+ }),
94
+ setNotificationEndpoint: async ({ baseUrl }) => {
95
+ await this.updateGlobalSettings({ notificationBaseUrl: baseUrl ?? "" });
96
+ this.ctx.logger.info("local-network: notification endpoint set", { meta: { baseUrl: baseUrl ?? "(auto)" } });
97
+ return {
98
+ baseUrl: baseUrl === "" ? null : baseUrl,
99
+ resolved: this.resolveNotificationEndpoint()
100
+ };
101
+ },
74
102
  getAllowedAddresses: async () => ({ addresses: this.config.allowedAddresses }),
75
103
  resetAllowlistToBestMatch: async () => {
76
104
  const seed = autoSeedAllowlist(this.enumerate());
@@ -1,4 +1,4 @@
1
- import { R as localNetworkCapability, at as BaseAddon, jt as EventCategory } from "../../dist-C9_XdXl5.mjs";
1
+ import { R as localNetworkCapability, at as BaseAddon, jt as EventCategory } from "../../dist-CIek6F9X.mjs";
2
2
  import * as os from "node:os";
3
3
  //#region src/builtins/local-network/local-network.addon.ts
4
4
  /**
@@ -41,9 +41,25 @@ var LocalNetworkAddon = class extends BaseAddon {
41
41
  constructor() {
42
42
  super({
43
43
  allowedAddresses: [],
44
- bootSeeded: false
44
+ bootSeeded: false,
45
+ notificationBaseUrl: ""
45
46
  });
46
47
  }
48
+ /**
49
+ * What AUTO currently resolves to for outbound artifact links: the first
50
+ * PUBLIC candidate, never loopback and never a LAN address — a link is
51
+ * opened on someone's phone, off this network, possibly hours later.
52
+ * `null` when nothing public is reachable (the caller then ships bytes only
53
+ * rather than a link that 404s).
54
+ */
55
+ resolveNotificationEndpoint() {
56
+ const explicit = this.config.notificationBaseUrl;
57
+ if (explicit !== "") return explicit;
58
+ if (this.publicHostname !== "") return `https://${this.publicHostname}`;
59
+ const mesh = this.meshEndpoint;
60
+ if (mesh !== null && mesh.host !== "") return `https://${mesh.host}:${mesh.port}`;
61
+ return null;
62
+ }
47
63
  async onInitialize() {
48
64
  if (!this.config.bootSeeded) {
49
65
  const seed = autoSeedAllowlist(this.enumerate());
@@ -68,6 +84,18 @@ var LocalNetworkAddon = class extends BaseAddon {
68
84
  await this.reconcileMeshEndpoint();
69
85
  return { endpoints: buildEndpoints(interfaces, input.port, includeLoopback, ipv4Only, this.publicHostname, scheme, this.meshEndpoint) };
70
86
  },
87
+ getNotificationEndpoint: async () => ({
88
+ baseUrl: this.config.notificationBaseUrl === "" ? null : this.config.notificationBaseUrl,
89
+ resolved: this.resolveNotificationEndpoint()
90
+ }),
91
+ setNotificationEndpoint: async ({ baseUrl }) => {
92
+ await this.updateGlobalSettings({ notificationBaseUrl: baseUrl ?? "" });
93
+ this.ctx.logger.info("local-network: notification endpoint set", { meta: { baseUrl: baseUrl ?? "(auto)" } });
94
+ return {
95
+ baseUrl: baseUrl === "" ? null : baseUrl,
96
+ resolved: this.resolveNotificationEndpoint()
97
+ };
98
+ },
71
99
  getAllowedAddresses: async () => ({ addresses: this.config.allowedAddresses }),
72
100
  resetAllowlistToBestMatch: async () => {
73
101
  const seed = autoSeedAllowlist(this.enumerate());
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-j49ewCPY.js");
6
+ const require_dist = require("../../dist-CS0pdC8l.js");
7
7
  //#region src/builtins/loki-logging/loki-payload.ts
8
8
  /**
9
9
  * Loki rejects a label name that is not a valid Prometheus label
@@ -295,7 +295,8 @@ var LokiDestination = class {
295
295
  //#endregion
296
296
  //#region src/builtins/loki-logging/loki-logging.addon.ts
297
297
  var DEFAULTS = {
298
- enabled: false,
298
+ enabled: true,
299
+ migratedEnabled: false,
299
300
  url: "",
300
301
  job: "camstack",
301
302
  level: "info",
@@ -315,12 +316,39 @@ var LokiLoggingAddon = class extends require_dist.BaseAddon {
315
316
  async onInitialize() {
316
317
  this.destination = new LokiDestination();
317
318
  await this.destination.initialize(this.destinationConfig());
318
- this.ctx.logger.info(this.config.enabled && this.config.url.length > 0 ? `Loki logging initialized → ${this.config.url}` : "Loki logging registered but inactive (set a URL and enable it)");
319
+ this.ctx.logger.info(this.config.url.length > 0 ? `Loki logging initialized → ${this.config.url}` : "Loki logging registered but inactive (no URL set)");
320
+ await this.migrateRetiredEnabledFlag();
319
321
  return [{
320
322
  capability: require_dist.logDestinationCapability,
321
323
  provider: this.destination
322
324
  }];
323
325
  }
326
+ /**
327
+ * ONE-SHOT: carry a stored `enabled: false` over to the orchestrator's
328
+ * per-destination toggle, then never look at the flag again.
329
+ *
330
+ * Without this, retiring the private setting would silently RE-ENABLE Loki
331
+ * for every operator who had turned it off — shipping their logs to a host
332
+ * they may no longer control. Best-effort: if the toggle call fails the
333
+ * migration is simply retried next boot (the flag is only cleared on
334
+ * success).
335
+ */
336
+ async migrateRetiredEnabledFlag() {
337
+ if (this.config.migratedEnabled) return;
338
+ try {
339
+ if (!this.config.enabled) {
340
+ await this.ctx.api.addons.setCapabilityProviderEnabled.mutate({
341
+ capName: "log-destination",
342
+ addonId: this.ctx.id,
343
+ enabled: false
344
+ });
345
+ this.ctx.logger.info("Loki logging: the retired `enabled: false` setting was carried over to the per-destination toggle — re-enable it there if you want Loki shipping again.");
346
+ }
347
+ await this.updateGlobalSettings({ migratedEnabled: true });
348
+ } catch (err) {
349
+ this.ctx.logger.warn("Loki logging: enablement migration deferred to next boot", { meta: { error: err instanceof Error ? err.message : String(err) } });
350
+ }
351
+ }
324
352
  async onShutdown() {
325
353
  await this.destination?.shutdown();
326
354
  this.destination = null;
@@ -334,7 +362,7 @@ var LokiLoggingAddon = class extends require_dist.BaseAddon {
334
362
  */
335
363
  async onConfigChanged() {
336
364
  await this.destination?.reconfigure(this.destinationConfig());
337
- this.ctx.logger.info(this.config.enabled && this.config.url.length > 0 ? `Loki logging reconfigured → ${this.config.url}` : "Loki logging now inactive (disabled or no URL)");
365
+ this.ctx.logger.info(this.config.url.length > 0 ? `Loki logging reconfigured → ${this.config.url}` : "Loki logging now inactive (no URL)");
338
366
  }
339
367
  /**
340
368
  * `node` is a Loki LABEL, so it must be the node's real identity and must not
@@ -350,6 +378,7 @@ var LokiLoggingAddon = class extends require_dist.BaseAddon {
350
378
  destinationConfig() {
351
379
  return {
352
380
  ...this.config,
381
+ enabled: true,
353
382
  node: this.ctx.kernel.localNodeId ?? "hub"
354
383
  };
355
384
  }
@@ -361,16 +390,9 @@ var LokiLoggingAddon = class extends require_dist.BaseAddon {
361
390
  return this.schema({ sections: [{
362
391
  id: "loki-logging",
363
392
  title: "Loki",
364
- description: "Ship this node’s logs to a Grafana Loki instance. Independent of the rotated-file and console destinations enabling this does not disable those.",
393
+ description: "Ship this node’s logs to a Grafana Loki instance. Independent of the rotated-file and console destinations. Turn it on or off with the Enable/Disable control on this destination the same one every other destination uses.",
365
394
  columns: 2,
366
395
  fields: [
367
- this.field({
368
- type: "boolean",
369
- key: "enabled",
370
- label: "Enabled",
371
- description: "Off by default. Needs a URL below to do anything.",
372
- default: false
373
- }),
374
396
  this.field({
375
397
  type: "text",
376
398
  key: "url",
@@ -1,4 +1,4 @@
1
- import { at as BaseAddon, z as logDestinationCapability } from "../../dist-C9_XdXl5.mjs";
1
+ import { at as BaseAddon, z as logDestinationCapability } from "../../dist-CIek6F9X.mjs";
2
2
  //#region src/builtins/loki-logging/loki-payload.ts
3
3
  /**
4
4
  * Loki rejects a label name that is not a valid Prometheus label
@@ -290,7 +290,8 @@ var LokiDestination = class {
290
290
  //#endregion
291
291
  //#region src/builtins/loki-logging/loki-logging.addon.ts
292
292
  var DEFAULTS = {
293
- enabled: false,
293
+ enabled: true,
294
+ migratedEnabled: false,
294
295
  url: "",
295
296
  job: "camstack",
296
297
  level: "info",
@@ -310,12 +311,39 @@ var LokiLoggingAddon = class extends BaseAddon {
310
311
  async onInitialize() {
311
312
  this.destination = new LokiDestination();
312
313
  await this.destination.initialize(this.destinationConfig());
313
- this.ctx.logger.info(this.config.enabled && this.config.url.length > 0 ? `Loki logging initialized → ${this.config.url}` : "Loki logging registered but inactive (set a URL and enable it)");
314
+ this.ctx.logger.info(this.config.url.length > 0 ? `Loki logging initialized → ${this.config.url}` : "Loki logging registered but inactive (no URL set)");
315
+ await this.migrateRetiredEnabledFlag();
314
316
  return [{
315
317
  capability: logDestinationCapability,
316
318
  provider: this.destination
317
319
  }];
318
320
  }
321
+ /**
322
+ * ONE-SHOT: carry a stored `enabled: false` over to the orchestrator's
323
+ * per-destination toggle, then never look at the flag again.
324
+ *
325
+ * Without this, retiring the private setting would silently RE-ENABLE Loki
326
+ * for every operator who had turned it off — shipping their logs to a host
327
+ * they may no longer control. Best-effort: if the toggle call fails the
328
+ * migration is simply retried next boot (the flag is only cleared on
329
+ * success).
330
+ */
331
+ async migrateRetiredEnabledFlag() {
332
+ if (this.config.migratedEnabled) return;
333
+ try {
334
+ if (!this.config.enabled) {
335
+ await this.ctx.api.addons.setCapabilityProviderEnabled.mutate({
336
+ capName: "log-destination",
337
+ addonId: this.ctx.id,
338
+ enabled: false
339
+ });
340
+ this.ctx.logger.info("Loki logging: the retired `enabled: false` setting was carried over to the per-destination toggle — re-enable it there if you want Loki shipping again.");
341
+ }
342
+ await this.updateGlobalSettings({ migratedEnabled: true });
343
+ } catch (err) {
344
+ this.ctx.logger.warn("Loki logging: enablement migration deferred to next boot", { meta: { error: err instanceof Error ? err.message : String(err) } });
345
+ }
346
+ }
319
347
  async onShutdown() {
320
348
  await this.destination?.shutdown();
321
349
  this.destination = null;
@@ -329,7 +357,7 @@ var LokiLoggingAddon = class extends BaseAddon {
329
357
  */
330
358
  async onConfigChanged() {
331
359
  await this.destination?.reconfigure(this.destinationConfig());
332
- this.ctx.logger.info(this.config.enabled && this.config.url.length > 0 ? `Loki logging reconfigured → ${this.config.url}` : "Loki logging now inactive (disabled or no URL)");
360
+ this.ctx.logger.info(this.config.url.length > 0 ? `Loki logging reconfigured → ${this.config.url}` : "Loki logging now inactive (no URL)");
333
361
  }
334
362
  /**
335
363
  * `node` is a Loki LABEL, so it must be the node's real identity and must not
@@ -345,6 +373,7 @@ var LokiLoggingAddon = class extends BaseAddon {
345
373
  destinationConfig() {
346
374
  return {
347
375
  ...this.config,
376
+ enabled: true,
348
377
  node: this.ctx.kernel.localNodeId ?? "hub"
349
378
  };
350
379
  }
@@ -356,16 +385,9 @@ var LokiLoggingAddon = class extends BaseAddon {
356
385
  return this.schema({ sections: [{
357
386
  id: "loki-logging",
358
387
  title: "Loki",
359
- description: "Ship this node’s logs to a Grafana Loki instance. Independent of the rotated-file and console destinations enabling this does not disable those.",
388
+ description: "Ship this node’s logs to a Grafana Loki instance. Independent of the rotated-file and console destinations. Turn it on or off with the Enable/Disable control on this destination the same one every other destination uses.",
360
389
  columns: 2,
361
390
  fields: [
362
- this.field({
363
- type: "boolean",
364
- key: "enabled",
365
- label: "Enabled",
366
- description: "Off by default. Needs a URL below to do anything.",
367
- default: false
368
- }),
369
391
  this.field({
370
392
  type: "text",
371
393
  key: "url",