@camstack/system 1.2.433 → 1.2.435

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 (87) hide show
  1. package/dist/{agent-https-DtRU9A7I.mjs → agent-https-B8lKYVtU.mjs} +34 -6
  2. package/dist/{agent-https-CHZTxK-q.js → agent-https-BZIwS4xF.js} +34 -6
  3. package/dist/auth/device-ca.d.ts +0 -10
  4. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  5. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  6. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  7. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  8. package/dist/builtins/alerts/alerts.addon.js +1 -1
  9. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  10. package/dist/builtins/autotrack/index.js +1 -1
  11. package/dist/builtins/autotrack/index.mjs +1 -1
  12. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +2 -2
  13. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2 -2
  14. package/dist/builtins/calendars/calendars.addon.js +1 -1
  15. package/dist/builtins/calendars/calendars.addon.mjs +1 -1
  16. package/dist/builtins/camera-grid/index.js +1 -1
  17. package/dist/builtins/camera-grid/index.mjs +1 -1
  18. package/dist/builtins/composer/composer.addon.js +2 -2
  19. package/dist/builtins/composer/composer.addon.mjs +2 -2
  20. package/dist/builtins/console-logging/index.js +1 -1
  21. package/dist/builtins/console-logging/index.mjs +1 -1
  22. package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
  23. package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
  24. package/dist/builtins/device-manager/device-manager.addon.js +2 -2
  25. package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
  26. package/dist/builtins/hub-forwarder/index.js +1 -1
  27. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  28. package/dist/builtins/keychain/index.js +3 -3
  29. package/dist/builtins/keychain/index.mjs +3 -3
  30. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  31. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  32. package/dist/builtins/local-auth/local-auth.addon.js +9 -4
  33. package/dist/builtins/local-auth/local-auth.addon.mjs +9 -4
  34. package/dist/builtins/local-network/address-book.d.ts +13 -0
  35. package/dist/builtins/local-network/local-network.addon.d.ts +4 -2
  36. package/dist/builtins/local-network/local-network.addon.js +78 -22
  37. package/dist/builtins/local-network/local-network.addon.mjs +78 -22
  38. package/dist/builtins/loki-logging/index.js +1 -1
  39. package/dist/builtins/loki-logging/index.mjs +1 -1
  40. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  41. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  42. package/dist/builtins/platform-probe/index.js +1 -1
  43. package/dist/builtins/platform-probe/index.mjs +1 -1
  44. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  45. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  46. package/dist/builtins/snapshot/index.js +1 -1
  47. package/dist/builtins/snapshot/index.mjs +1 -1
  48. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  49. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  50. package/dist/builtins/sqlite-storage/index.js +1 -1
  51. package/dist/builtins/sqlite-storage/index.mjs +1 -1
  52. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +3 -3
  53. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +3 -3
  54. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  55. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  56. package/dist/builtins/system-config/system-config.addon.js +23 -8
  57. package/dist/builtins/system-config/system-config.addon.mjs +23 -8
  58. package/dist/builtins/winston-logging/index.js +1 -1
  59. package/dist/builtins/winston-logging/index.mjs +1 -1
  60. package/dist/{composition-sources-BgJWQMjr.js → composition-sources-Cm42mgbv.js} +1 -1
  61. package/dist/{composition-sources-8-cpAt1c.mjs → composition-sources-_7W2Ly9s.mjs} +1 -1
  62. package/dist/{constants-Ah3T_KAW.js → constants-DL87WgeN.js} +1 -1
  63. package/dist/{constants-Cg9ve13y.mjs → constants-DoiTA134.mjs} +1 -1
  64. package/dist/{device-ca-DUrcTW5h.mjs → device-ca-B6YJZus6.mjs} +17 -6
  65. package/dist/{device-ca-NNP4Jz0P.js → device-ca-WXuKc8AX.js} +17 -6
  66. package/dist/{dist-DJnlnL7P.mjs → dist-Bz4_y8Xy.mjs} +80 -11
  67. package/dist/{dist-C6Yvfhpq.js → dist-CnUtkSwN.js} +91 -10
  68. package/dist/file-host-worker.js +1 -1
  69. package/dist/file-host-worker.mjs +1 -1
  70. package/dist/{hub-mdns-ciao-B50jAU5C.js → hub-mdns-ciao-CBLvq2oj.js} +2 -2
  71. package/dist/{hub-mdns-ciao-8_Ed1Za5.mjs → hub-mdns-ciao-DJRwtlA8.mjs} +2 -2
  72. package/dist/index.js +7 -7
  73. package/dist/index.mjs +7 -7
  74. package/dist/kernel/moleculer/mesh-mtls/mesh-ca.d.ts +0 -9
  75. package/dist/{lib-B_R6sPC3.mjs → lib-BeGzVQcd.mjs} +1 -1
  76. package/dist/{lib-DOJ5yyWA.js → lib-NNxHSOIE.js} +1 -1
  77. package/dist/{restore-archive-DqPaRjjY.js → restore-archive-BNoFLAg8.js} +1 -1
  78. package/dist/{restore-archive-C3_rzOCx.mjs → restore-archive-DJYuznWP.mjs} +1 -1
  79. package/dist/{retired-settings-keys-CAWHWDwy.mjs → retired-settings-keys-9nA85bwT.mjs} +1 -1
  80. package/dist/{retired-settings-keys-DJBQkZok.js → retired-settings-keys-CO3RqsDw.js} +1 -1
  81. package/dist/tls/cert-backdate.d.ts +10 -0
  82. package/dist/tls/cert-issue.d.ts +0 -20
  83. package/dist/{wal-maintenance-CPLvZbzA.js → wal-maintenance-D3gwRj1B.js} +0 -0
  84. package/dist/{wal-maintenance-Bc38yI3r.mjs → wal-maintenance-DLrbapzi.mjs} +0 -0
  85. package/dist/{x509.es-CAjSsrkk.mjs → x509.es-CDvj67p1.mjs} +14 -1
  86. package/dist/{x509.es-Dzl0BbmG.js → x509.es-r7Ht1thA.js} +19 -0
  87. package/package.json +1 -1
@@ -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-C6Yvfhpq.js");
4
- const require_hub_mdns_ciao = require("../../hub-mdns-ciao-B50jAU5C.js");
3
+ const require_dist = require("../../dist-CnUtkSwN.js");
4
+ const require_hub_mdns_ciao = require("../../hub-mdns-ciao-CBLvq2oj.js");
5
5
  let zod = require("zod");
6
6
  let node_net = require("node:net");
7
7
  let node_os = require("node:os");
@@ -192,6 +192,48 @@ function withAppConnectionCustomEndpoints(detected, state) {
192
192
  const extra = state.custom.filter((c) => wanted.has(c.baseUrl) && !known.has(c.baseUrl)).map(customEndpoint);
193
193
  return [...detected, ...extra];
194
194
  }
195
+ /** Where a twin sorts relative to its plain-HTTP row: straight after it. */
196
+ var HTTPS_TWIN_PRIORITY_STEP = .5;
197
+ /**
198
+ * The HTTPS counterpart of every LAN address advertised over plain HTTP
199
+ * (D859): `http://<lan>:<httpPort>` gains `https://<lan>:<httpsPort>`, the hub's
200
+ * TLS listener, as its own row straight after it. The twin is an ordinary
201
+ * detected LAN row — ticked, unticked and flagged like any other, on by default
202
+ * (a LAN row is an automatic app connection). A phone that does not trust the
203
+ * hub's local CA fails that candidate in the race it already runs; one that
204
+ * does reaches it. Only the app-connection palette and the table carry twins:
205
+ * the palette `internal` and `publicEndpoint` resolve over never does, so those
206
+ * roles keep their answer. Rows already on https (LAN HTTP off), the public
207
+ * tunnel, the mesh, custom addresses and loopback have no twin.
208
+ */
209
+ function withLanHttpsCounterparts(palette, httpsPort) {
210
+ const known = new Set(palette.map((e) => e.baseUrl));
211
+ const out = [];
212
+ for (const endpoint of palette) {
213
+ out.push(endpoint);
214
+ if (endpoint.kind !== "lan-ipv4" && endpoint.kind !== "lan-ipv6") continue;
215
+ const twin = httpsTwinOf(endpoint, httpsPort);
216
+ if (twin === null || known.has(twin.baseUrl)) continue;
217
+ known.add(twin.baseUrl);
218
+ out.push(twin);
219
+ }
220
+ return out;
221
+ }
222
+ function httpsTwinOf(endpoint, httpsPort) {
223
+ let parsed;
224
+ try {
225
+ parsed = new URL(endpoint.baseUrl);
226
+ } catch {
227
+ return null;
228
+ }
229
+ if (parsed.protocol !== "http:") return null;
230
+ return {
231
+ ...endpoint,
232
+ label: `${endpoint.label} (HTTPS)`,
233
+ baseUrl: `https://${parsed.hostname}:${httpsPort}`,
234
+ priority: endpoint.priority + HTTPS_TWIN_PRIORITY_STEP
235
+ };
236
+ }
195
237
  /** Every role's answer — the resolvers from `@camstack/types`, nothing else. */
196
238
  function resolveRoles(state, appPalette, httpsPalette) {
197
239
  return require_dist.resolveHubAddressRoles(withAppConnectionCustomEndpoints(appPalette, state), httpsPalette, state.flags);
@@ -566,6 +608,8 @@ var LocalNetworkAddon = class extends require_dist.BaseAddon {
566
608
  /** Optional public hostname tracked from `NetworkTunnelStarted`/
567
609
  * `Stopped` events on the bus. */
568
610
  publicHostname = "";
611
+ /** False for a Quick tunnel: shown in the palette, never picked automatically (D860). */
612
+ publicHostnameStable = true;
569
613
  /**
570
614
  * Mesh-reachable endpoint (Tailscale MagicDNS / 100.x), learned from
571
615
  * the `MeshNetworkChanged` event-tail and refreshed by a pull-reconcile
@@ -597,9 +641,13 @@ var LocalNetworkAddon = class extends require_dist.BaseAddon {
597
641
  async palettes() {
598
642
  const port = (await this.resolveAdvertisedListenPort(null)).port;
599
643
  await this.reconcileMeshEndpoint();
644
+ const http = this.endpointsNow(false, false, "http", port);
645
+ const https = this.endpointsNow(false, false, "https", port);
600
646
  return {
601
- http: this.endpointsNow(false, false, "http", port),
602
- https: this.endpointsNow(false, false, "https", port)
647
+ http,
648
+ https,
649
+ httpWithTwins: withLanHttpsCounterparts(http, port),
650
+ httpsWithTwins: withLanHttpsCounterparts(https, port)
603
651
  };
604
652
  }
605
653
  /** The stored address book, normalised against what is detected now. */
@@ -612,11 +660,11 @@ var LocalNetworkAddon = class extends require_dist.BaseAddon {
612
660
  }
613
661
  /** `getAddresses`: the Addresses table and every role's answer. */
614
662
  async addressBook(scheme) {
615
- const { http, https } = await this.palettes();
616
- const state = this.addressState([...http, ...https]);
663
+ const { http, https, httpWithTwins, httpsWithTwins } = await this.palettes();
664
+ const state = this.addressState([...httpWithTwins, ...httpsWithTwins]);
617
665
  const httpsPort = (await this.resolveAdvertisedListenPort(null)).port;
618
666
  return buildAddressBook(state, {
619
- rowsPalette: scheme === "http" ? http : https,
667
+ rowsPalette: scheme === "http" ? httpWithTwins : httpsWithTwins,
620
668
  httpsPalette: https,
621
669
  appLink: appLinkEndpoint(),
622
670
  appLinkHub: require_dist.pickAppLinkHub(https),
@@ -628,8 +676,8 @@ var LocalNetworkAddon = class extends require_dist.BaseAddon {
628
676
  * naming an address in no row becomes a custom address in the same write).
629
677
  */
630
678
  async changeAddressBook(change) {
631
- const { http, https } = await this.palettes();
632
- const detected = [...http, ...https];
679
+ const { httpWithTwins, httpsWithTwins } = await this.palettes();
680
+ const detected = [...httpWithTwins, ...httpsWithTwins];
633
681
  const detectedUrls = new Set(detected.map((e) => e.baseUrl));
634
682
  const changed = change(this.addressState(detected), {
635
683
  detectedUrls,
@@ -708,7 +756,7 @@ var LocalNetworkAddon = class extends require_dist.BaseAddon {
708
756
  */
709
757
  async buildAdvertisedEndpoints(includeLoopback, ipv4Only, scheme, httpsPort) {
710
758
  await this.reconcileMeshEndpoint();
711
- const detected = this.endpointsNow(includeLoopback, ipv4Only, scheme, httpsPort);
759
+ const detected = withLanHttpsCounterparts(this.endpointsNow(includeLoopback, ipv4Only, scheme, httpsPort), httpsPort);
712
760
  return withAppConnectionCustomEndpoints(detected, this.addressState(detected));
713
761
  }
714
762
  /**
@@ -737,7 +785,7 @@ var LocalNetworkAddon = class extends require_dist.BaseAddon {
737
785
  httpPort: this.resolvedHttpPort(),
738
786
  httpsPort,
739
787
  localHostname: this.config.localHostname || null
740
- } : null);
788
+ } : null, this.publicHostnameStable);
741
789
  }
742
790
  async onInitialize() {
743
791
  if (!this.config.bootSeeded) {
@@ -870,11 +918,14 @@ var LocalNetworkAddon = class extends require_dist.BaseAddon {
870
918
  }, ALLOWLIST_RECONCILE_INTERVAL_MS);
871
919
  this.allowlistTimer.unref?.();
872
920
  this.ctx.eventBus?.subscribe({ category: require_dist.EventCategory.NetworkTunnelStarted }, (event) => {
873
- const data = event.data ?? {};
874
- if (typeof data.url === "string") try {
875
- const hostname = new URL(data.url).hostname;
876
- if (hostname && !hostname.endsWith(".placeholder") && !hostname.startsWith("pending.")) this.setPublicHostname(hostname);
877
- } catch {}
921
+ const parsed = require_dist.NetworkTunnelStartedDataSchema.safeParse(event.data ?? {});
922
+ if (parsed.success) {
923
+ const data = parsed.data;
924
+ try {
925
+ const hostname = new URL(data.url).hostname;
926
+ if (hostname && !hostname.endsWith(".placeholder") && !hostname.startsWith("pending.")) this.setPublicHostname(hostname, data.stable !== false);
927
+ } catch {}
928
+ }
878
929
  });
879
930
  this.ctx.eventBus?.subscribe({ category: require_dist.EventCategory.NetworkTunnelStopped }, () => this.setPublicHostname(""));
880
931
  this.ctx.eventBus?.subscribe({ category: require_dist.EventCategory.MeshNetworkChanged }, (event) => {
@@ -985,10 +1036,14 @@ var LocalNetworkAddon = class extends require_dist.BaseAddon {
985
1036
  * `onInitialize`. This setter exists for tests + future direct
986
1037
  * callers; cleared by passing an empty string.
987
1038
  */
988
- setPublicHostname(hostname) {
989
- if (this.publicHostname === hostname) return;
1039
+ setPublicHostname(hostname, stable = true) {
1040
+ if (this.publicHostname === hostname && this.publicHostnameStable === stable) return;
990
1041
  this.publicHostname = hostname;
991
- this.ctx.logger.info("local-network: public hostname updated", { meta: { hostname: hostname || "(cleared)" } });
1042
+ this.publicHostnameStable = stable;
1043
+ this.ctx.logger.info("local-network: public hostname updated", { meta: {
1044
+ hostname: hostname || "(cleared)",
1045
+ stable
1046
+ } });
992
1047
  }
993
1048
  /**
994
1049
  * Replace the cached mesh endpoint. Set from the `MeshNetworkChanged`
@@ -1317,7 +1372,7 @@ function appLinkEndpoint() {
1317
1372
  priority: -1
1318
1373
  };
1319
1374
  }
1320
- function buildEndpoints(interfaces, port, includeLoopback, ipv4Only, publicHostname, scheme = "http", meshEndpoint = null, lanHttp = null) {
1375
+ function buildEndpoints(interfaces, port, includeLoopback, ipv4Only, publicHostname, scheme = "http", meshEndpoint = null, lanHttp = null, publicHostnameStable = true) {
1321
1376
  const out = [];
1322
1377
  let priority = 0;
1323
1378
  const preferred = pickPreferred(interfaces);
@@ -1360,13 +1415,14 @@ function buildEndpoints(interfaces, port, includeLoopback, ipv4Only, publicHostn
1360
1415
  emit(iface, "lan-ipv6", `${formatKind(iface.kind)} — ${iface.name} (IPv6)`, `${lanScheme}://[${iface.address}]:${lanPort}`, 10 + priority++);
1361
1416
  }
1362
1417
  if (publicHostname) out.push({
1363
- label: "Public tunnel",
1418
+ label: publicHostnameStable ? "Public tunnel" : "Public tunnel (temporary address)",
1364
1419
  baseUrl: `https://${publicHostname}`,
1365
1420
  kind: "public",
1366
1421
  interfaceKind: "public",
1367
1422
  plausible: true,
1368
1423
  plausibleReason: "",
1369
- priority: 100
1424
+ priority: 100,
1425
+ ...publicHostnameStable ? {} : { stable: false }
1370
1426
  });
1371
1427
  if (meshEndpoint && meshEndpoint.host) out.push({
1372
1428
  label: "Mesh (Tailscale)",
@@ -1,5 +1,5 @@
1
- import { Fn as resolveNotificationTapAddress, Kt as isAppLinkBase, M as HUB_MDNS_SERVICE_TYPE, Mn as resolveHubAddressRoles, N as HUB_MDNS_TXT_KEYS, On as resolveAppConnections, Qn as validateCustomAddress, Yt as isDefaultAppConnectionEndpoint, an as localNetworkCapability, di as EventCategory, dt as checkRoleAddress, l as CAMSTACK_APP_LINK_ORIGIN, xn as pickAppLinkHub, yr as BaseAddon } from "../../dist-DJnlnL7P.mjs";
2
- import { C as DEFAULT_LAN_HTTP_PORT, O as readLanHttpState, T as applyLanHttp, a as storeUploadedCertificate, b as ensureTlsCert, d as servedHttpsLeafFingerprint, g as readTlsMode, h as readTlsAccessStatus, i as revertToGeneratedCertificate, m as readExtraSans, n as applyCertificateToListener, r as regenerateCertificate, t as createCiaoPublisher, v as writeExtraSans } from "../../hub-mdns-ciao-8_Ed1Za5.mjs";
1
+ import { An as resolveAppConnections, B as NetworkTunnelStartedDataSchema, Cn as pickAppLinkHub, Jt as isAppLinkBase, Ln as resolveNotificationTapAddress, M as HUB_MDNS_SERVICE_TYPE, N as HUB_MDNS_TXT_KEYS, Pn as resolveHubAddressRoles, Zt as isDefaultAppConnectionEndpoint, er as validateCustomAddress, l as CAMSTACK_APP_LINK_ORIGIN, pi as EventCategory, pt as checkRoleAddress, sn as localNetworkCapability, xr as BaseAddon } from "../../dist-Bz4_y8Xy.mjs";
2
+ import { C as DEFAULT_LAN_HTTP_PORT, O as readLanHttpState, T as applyLanHttp, a as storeUploadedCertificate, b as ensureTlsCert, d as servedHttpsLeafFingerprint, g as readTlsMode, h as readTlsAccessStatus, i as revertToGeneratedCertificate, m as readExtraSans, n as applyCertificateToListener, r as regenerateCertificate, t as createCiaoPublisher, v as writeExtraSans } from "../../hub-mdns-ciao-DJRwtlA8.mjs";
3
3
  import { z } from "zod";
4
4
  import { isIP } from "node:net";
5
5
  import * as os from "node:os";
@@ -189,6 +189,48 @@ function withAppConnectionCustomEndpoints(detected, state) {
189
189
  const extra = state.custom.filter((c) => wanted.has(c.baseUrl) && !known.has(c.baseUrl)).map(customEndpoint);
190
190
  return [...detected, ...extra];
191
191
  }
192
+ /** Where a twin sorts relative to its plain-HTTP row: straight after it. */
193
+ var HTTPS_TWIN_PRIORITY_STEP = .5;
194
+ /**
195
+ * The HTTPS counterpart of every LAN address advertised over plain HTTP
196
+ * (D859): `http://<lan>:<httpPort>` gains `https://<lan>:<httpsPort>`, the hub's
197
+ * TLS listener, as its own row straight after it. The twin is an ordinary
198
+ * detected LAN row — ticked, unticked and flagged like any other, on by default
199
+ * (a LAN row is an automatic app connection). A phone that does not trust the
200
+ * hub's local CA fails that candidate in the race it already runs; one that
201
+ * does reaches it. Only the app-connection palette and the table carry twins:
202
+ * the palette `internal` and `publicEndpoint` resolve over never does, so those
203
+ * roles keep their answer. Rows already on https (LAN HTTP off), the public
204
+ * tunnel, the mesh, custom addresses and loopback have no twin.
205
+ */
206
+ function withLanHttpsCounterparts(palette, httpsPort) {
207
+ const known = new Set(palette.map((e) => e.baseUrl));
208
+ const out = [];
209
+ for (const endpoint of palette) {
210
+ out.push(endpoint);
211
+ if (endpoint.kind !== "lan-ipv4" && endpoint.kind !== "lan-ipv6") continue;
212
+ const twin = httpsTwinOf(endpoint, httpsPort);
213
+ if (twin === null || known.has(twin.baseUrl)) continue;
214
+ known.add(twin.baseUrl);
215
+ out.push(twin);
216
+ }
217
+ return out;
218
+ }
219
+ function httpsTwinOf(endpoint, httpsPort) {
220
+ let parsed;
221
+ try {
222
+ parsed = new URL(endpoint.baseUrl);
223
+ } catch {
224
+ return null;
225
+ }
226
+ if (parsed.protocol !== "http:") return null;
227
+ return {
228
+ ...endpoint,
229
+ label: `${endpoint.label} (HTTPS)`,
230
+ baseUrl: `https://${parsed.hostname}:${httpsPort}`,
231
+ priority: endpoint.priority + HTTPS_TWIN_PRIORITY_STEP
232
+ };
233
+ }
192
234
  /** Every role's answer — the resolvers from `@camstack/types`, nothing else. */
193
235
  function resolveRoles(state, appPalette, httpsPalette) {
194
236
  return resolveHubAddressRoles(withAppConnectionCustomEndpoints(appPalette, state), httpsPalette, state.flags);
@@ -563,6 +605,8 @@ var LocalNetworkAddon = class extends BaseAddon {
563
605
  /** Optional public hostname tracked from `NetworkTunnelStarted`/
564
606
  * `Stopped` events on the bus. */
565
607
  publicHostname = "";
608
+ /** False for a Quick tunnel: shown in the palette, never picked automatically (D860). */
609
+ publicHostnameStable = true;
566
610
  /**
567
611
  * Mesh-reachable endpoint (Tailscale MagicDNS / 100.x), learned from
568
612
  * the `MeshNetworkChanged` event-tail and refreshed by a pull-reconcile
@@ -594,9 +638,13 @@ var LocalNetworkAddon = class extends BaseAddon {
594
638
  async palettes() {
595
639
  const port = (await this.resolveAdvertisedListenPort(null)).port;
596
640
  await this.reconcileMeshEndpoint();
641
+ const http = this.endpointsNow(false, false, "http", port);
642
+ const https = this.endpointsNow(false, false, "https", port);
597
643
  return {
598
- http: this.endpointsNow(false, false, "http", port),
599
- https: this.endpointsNow(false, false, "https", port)
644
+ http,
645
+ https,
646
+ httpWithTwins: withLanHttpsCounterparts(http, port),
647
+ httpsWithTwins: withLanHttpsCounterparts(https, port)
600
648
  };
601
649
  }
602
650
  /** The stored address book, normalised against what is detected now. */
@@ -609,11 +657,11 @@ var LocalNetworkAddon = class extends BaseAddon {
609
657
  }
610
658
  /** `getAddresses`: the Addresses table and every role's answer. */
611
659
  async addressBook(scheme) {
612
- const { http, https } = await this.palettes();
613
- const state = this.addressState([...http, ...https]);
660
+ const { http, https, httpWithTwins, httpsWithTwins } = await this.palettes();
661
+ const state = this.addressState([...httpWithTwins, ...httpsWithTwins]);
614
662
  const httpsPort = (await this.resolveAdvertisedListenPort(null)).port;
615
663
  return buildAddressBook(state, {
616
- rowsPalette: scheme === "http" ? http : https,
664
+ rowsPalette: scheme === "http" ? httpWithTwins : httpsWithTwins,
617
665
  httpsPalette: https,
618
666
  appLink: appLinkEndpoint(),
619
667
  appLinkHub: pickAppLinkHub(https),
@@ -625,8 +673,8 @@ var LocalNetworkAddon = class extends BaseAddon {
625
673
  * naming an address in no row becomes a custom address in the same write).
626
674
  */
627
675
  async changeAddressBook(change) {
628
- const { http, https } = await this.palettes();
629
- const detected = [...http, ...https];
676
+ const { httpWithTwins, httpsWithTwins } = await this.palettes();
677
+ const detected = [...httpWithTwins, ...httpsWithTwins];
630
678
  const detectedUrls = new Set(detected.map((e) => e.baseUrl));
631
679
  const changed = change(this.addressState(detected), {
632
680
  detectedUrls,
@@ -705,7 +753,7 @@ var LocalNetworkAddon = class extends BaseAddon {
705
753
  */
706
754
  async buildAdvertisedEndpoints(includeLoopback, ipv4Only, scheme, httpsPort) {
707
755
  await this.reconcileMeshEndpoint();
708
- const detected = this.endpointsNow(includeLoopback, ipv4Only, scheme, httpsPort);
756
+ const detected = withLanHttpsCounterparts(this.endpointsNow(includeLoopback, ipv4Only, scheme, httpsPort), httpsPort);
709
757
  return withAppConnectionCustomEndpoints(detected, this.addressState(detected));
710
758
  }
711
759
  /**
@@ -734,7 +782,7 @@ var LocalNetworkAddon = class extends BaseAddon {
734
782
  httpPort: this.resolvedHttpPort(),
735
783
  httpsPort,
736
784
  localHostname: this.config.localHostname || null
737
- } : null);
785
+ } : null, this.publicHostnameStable);
738
786
  }
739
787
  async onInitialize() {
740
788
  if (!this.config.bootSeeded) {
@@ -867,11 +915,14 @@ var LocalNetworkAddon = class extends BaseAddon {
867
915
  }, ALLOWLIST_RECONCILE_INTERVAL_MS);
868
916
  this.allowlistTimer.unref?.();
869
917
  this.ctx.eventBus?.subscribe({ category: EventCategory.NetworkTunnelStarted }, (event) => {
870
- const data = event.data ?? {};
871
- if (typeof data.url === "string") try {
872
- const hostname = new URL(data.url).hostname;
873
- if (hostname && !hostname.endsWith(".placeholder") && !hostname.startsWith("pending.")) this.setPublicHostname(hostname);
874
- } catch {}
918
+ const parsed = NetworkTunnelStartedDataSchema.safeParse(event.data ?? {});
919
+ if (parsed.success) {
920
+ const data = parsed.data;
921
+ try {
922
+ const hostname = new URL(data.url).hostname;
923
+ if (hostname && !hostname.endsWith(".placeholder") && !hostname.startsWith("pending.")) this.setPublicHostname(hostname, data.stable !== false);
924
+ } catch {}
925
+ }
875
926
  });
876
927
  this.ctx.eventBus?.subscribe({ category: EventCategory.NetworkTunnelStopped }, () => this.setPublicHostname(""));
877
928
  this.ctx.eventBus?.subscribe({ category: EventCategory.MeshNetworkChanged }, (event) => {
@@ -982,10 +1033,14 @@ var LocalNetworkAddon = class extends BaseAddon {
982
1033
  * `onInitialize`. This setter exists for tests + future direct
983
1034
  * callers; cleared by passing an empty string.
984
1035
  */
985
- setPublicHostname(hostname) {
986
- if (this.publicHostname === hostname) return;
1036
+ setPublicHostname(hostname, stable = true) {
1037
+ if (this.publicHostname === hostname && this.publicHostnameStable === stable) return;
987
1038
  this.publicHostname = hostname;
988
- this.ctx.logger.info("local-network: public hostname updated", { meta: { hostname: hostname || "(cleared)" } });
1039
+ this.publicHostnameStable = stable;
1040
+ this.ctx.logger.info("local-network: public hostname updated", { meta: {
1041
+ hostname: hostname || "(cleared)",
1042
+ stable
1043
+ } });
989
1044
  }
990
1045
  /**
991
1046
  * Replace the cached mesh endpoint. Set from the `MeshNetworkChanged`
@@ -1314,7 +1369,7 @@ function appLinkEndpoint() {
1314
1369
  priority: -1
1315
1370
  };
1316
1371
  }
1317
- function buildEndpoints(interfaces, port, includeLoopback, ipv4Only, publicHostname, scheme = "http", meshEndpoint = null, lanHttp = null) {
1372
+ function buildEndpoints(interfaces, port, includeLoopback, ipv4Only, publicHostname, scheme = "http", meshEndpoint = null, lanHttp = null, publicHostnameStable = true) {
1318
1373
  const out = [];
1319
1374
  let priority = 0;
1320
1375
  const preferred = pickPreferred(interfaces);
@@ -1357,13 +1412,14 @@ function buildEndpoints(interfaces, port, includeLoopback, ipv4Only, publicHostn
1357
1412
  emit(iface, "lan-ipv6", `${formatKind(iface.kind)} — ${iface.name} (IPv6)`, `${lanScheme}://[${iface.address}]:${lanPort}`, 10 + priority++);
1358
1413
  }
1359
1414
  if (publicHostname) out.push({
1360
- label: "Public tunnel",
1415
+ label: publicHostnameStable ? "Public tunnel" : "Public tunnel (temporary address)",
1361
1416
  baseUrl: `https://${publicHostname}`,
1362
1417
  kind: "public",
1363
1418
  interfaceKind: "public",
1364
1419
  plausible: true,
1365
1420
  plausibleReason: "",
1366
- priority: 100
1421
+ priority: 100,
1422
+ ...publicHostnameStable ? {} : { stable: false }
1367
1423
  });
1368
1424
  if (meshEndpoint && meshEndpoint.host) out.push({
1369
1425
  label: "Mesh (Tailscale)",
@@ -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-C6Yvfhpq.js");
6
+ const require_dist = require("../../dist-CnUtkSwN.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
@@ -1,4 +1,4 @@
1
- import { sn as logDestinationCapability, yr as BaseAddon } from "../../dist-DJnlnL7P.mjs";
1
+ import { ln as logDestinationCapability, xr as BaseAddon } from "../../dist-Bz4_y8Xy.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
@@ -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-C6Yvfhpq.js");
6
+ const require_dist = require("../../dist-CnUtkSwN.js");
7
7
  let node_fs_promises = require("node:fs/promises");
8
8
  let node_os = require("node:os");
9
9
  node_os = require_chunk.__toESM(node_os);
@@ -1,4 +1,4 @@
1
- import { En as reducePoints, Fr as createEvent, Ht as foldSnapshotByFunction, di as EventCategory, kn as resolveBucketMs, pn as metricsProviderCapability, vr as errMsg, yr as BaseAddon } from "../../dist-DJnlnL7P.mjs";
1
+ import { Lr as createEvent, On as reducePoints, Wt as foldSnapshotByFunction, br as errMsg, hn as metricsProviderCapability, jn as resolveBucketMs, pi as EventCategory, xr as BaseAddon } from "../../dist-Bz4_y8Xy.mjs";
2
2
  import { access, readFile, readdir } from "node:fs/promises";
3
3
  import * as os from "node:os";
4
4
  import { platform } from "node:os";
@@ -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-C6Yvfhpq.js");
6
+ const require_dist = require("../../dist-CnUtkSwN.js");
7
7
  let node_os = require("node:os");
8
8
  node_os = require_chunk.__toESM(node_os);
9
9
  let node_fs = require("node:fs");
@@ -1,5 +1,5 @@
1
1
  import { o as __toESM, r as __exportAll } from "../../chunk-CNf5ZN-e.mjs";
2
- import { Cn as platformProbeCapability, Nt as enumerateInferenceDevices, di as EventCategory, vr as errMsg, yr as BaseAddon, zn as scoreRuntimes, zr as emitReadiness } from "../../dist-DJnlnL7P.mjs";
2
+ import { Ft as enumerateInferenceDevices, Tn as platformProbeCapability, Vn as scoreRuntimes, Vr as emitReadiness, br as errMsg, pi as EventCategory, xr as BaseAddon } from "../../dist-Bz4_y8Xy.mjs";
3
3
  import * as os from "node:os";
4
4
  import * as fs from "node:fs";
5
5
  import { execFile } from "node:child_process";
@@ -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-C6Yvfhpq.js");
6
+ const require_dist = require("../../dist-CnUtkSwN.js");
7
7
  //#region src/builtins/remote-access-orchestrator/enabled-providers-reconcile.ts
8
8
  /**
9
9
  * Reconcile the durable `enabledProviders` set against authoritative
@@ -1,4 +1,4 @@
1
- import { di as EventCategory, yr as BaseAddon } from "../../dist-DJnlnL7P.mjs";
1
+ import { pi as EventCategory, xr as BaseAddon } from "../../dist-Bz4_y8Xy.mjs";
2
2
  //#region src/builtins/remote-access-orchestrator/enabled-providers-reconcile.ts
3
3
  /**
4
4
  * Reconcile the durable `enabledProviders` set against authoritative
@@ -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-C6Yvfhpq.js");
6
+ const require_dist = require("../../dist-CnUtkSwN.js");
7
7
  const require_snapshot_courtesy = require("../../snapshot-courtesy-D_C5-nC0.js");
8
8
  let zod = require("zod");
9
9
  let node_crypto = require("node:crypto");
@@ -1,4 +1,4 @@
1
- import { Et as deriveBatteryPresence, Hn as snapshotCapability, Jn as streamQualityLabel, Xr as nodePin, _r as DeviceType, di as EventCategory, fn as memoizePinnedFfmpeg, hr as DeviceFeature, nt as bareAddonId, rt as batteryCapability, s as BatteryStatusSchema, vr as errMsg, yr as BaseAddon } from "../../dist-DJnlnL7P.mjs";
1
+ import { Ot as deriveBatteryPresence, Qr as nodePin, Wn as snapshotCapability, Xn as streamQualityLabel, _r as DeviceFeature, at as batteryCapability, br as errMsg, it as bareAddonId, mn as memoizePinnedFfmpeg, pi as EventCategory, s as BatteryStatusSchema, xr as BaseAddon, yr as DeviceType } from "../../dist-Bz4_y8Xy.mjs";
2
2
  import { i as renderCourtesyOverlayJpeg, n as courtesyCacheKey, r as renderCourtesyJpeg } from "../../snapshot-courtesy-CyFs1M3I.mjs";
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
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-C6Yvfhpq.js");
6
+ const require_dist = require("../../dist-CnUtkSwN.js");
7
7
  let node_crypto = require("node:crypto");
8
8
  let node_fs_promises = require("node:fs/promises");
9
9
  let node_path = require("node:path");
@@ -1,4 +1,4 @@
1
- import { Kn as storageProviderCapability, Vt as filesystemBrowseCapability, yr as BaseAddon } from "../../dist-DJnlnL7P.mjs";
1
+ import { Jn as storageProviderCapability, Ut as filesystemBrowseCapability, xr as BaseAddon } from "../../dist-Bz4_y8Xy.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { mkdir, readdir, realpath, statfs } from "node:fs/promises";
4
4
  import * as path$1 from "node:path";
@@ -4,7 +4,7 @@ Object.defineProperties(exports, {
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
6
  const require_builtins_sqlite_storage_filesystem_storage_addon = require("./filesystem-storage.addon.js");
7
- const require_wal_maintenance = require("../../wal-maintenance-CPLvZbzA.js");
7
+ const require_wal_maintenance = require("../../wal-maintenance-D3gwRj1B.js");
8
8
  const require_builtins_sqlite_storage_sqlite_settings_addon = require("./sqlite-settings.addon.js");
9
9
  //#region src/builtins/sqlite-storage/config-store.ts
10
10
  var ConfigStore = class {
@@ -1,5 +1,5 @@
1
1
  import { FilesystemStorageAddon, t as FilesystemStorageProvider } from "./filesystem-storage.addon.mjs";
2
- import { A as SQLITE_PAGE_CACHE_CEILING_KIB, B as sqliteEngineStorm, D as SQLITE_JOURNAL_SIZE_LIMIT_BYTES, F as SQLITE_PROFILE_REPORT_FLOOR_MS, I as SQLITE_PROFILE_REPORT_INTERVAL_MS, L as SQLITE_PROFILE_TOP_N, M as sqliteMmapSizeFor, N as sqlitePageCacheKibFor, O as SQLITE_MMAP_CEILING_BYTES, P as SQLITE_ENGINE_STORM_WALL_SHARE, R as SQLITE_SLOW_CALL_MS, a as WalMaintenance, c as SqliteSettingsBackend, i as WAL_MAINTENANCE_INTERVAL_MS, j as SQLITE_PAGE_CACHE_FLOOR_KIB, k as SQLITE_MMAP_FLOOR_BYTES, n as WAL_HIGH_WATER_BYTES, r as WAL_IDLE_QUIET_MS, t as WAL_CHECKPOINT_BUSY_TIMEOUT_MS, z as SqliteOpProfiler } from "../../wal-maintenance-Bc38yI3r.mjs";
2
+ import { A as SQLITE_PAGE_CACHE_CEILING_KIB, B as sqliteEngineStorm, D as SQLITE_JOURNAL_SIZE_LIMIT_BYTES, F as SQLITE_PROFILE_REPORT_FLOOR_MS, I as SQLITE_PROFILE_REPORT_INTERVAL_MS, L as SQLITE_PROFILE_TOP_N, M as sqliteMmapSizeFor, N as sqlitePageCacheKibFor, O as SQLITE_MMAP_CEILING_BYTES, P as SQLITE_ENGINE_STORM_WALL_SHARE, R as SQLITE_SLOW_CALL_MS, a as WalMaintenance, c as SqliteSettingsBackend, i as WAL_MAINTENANCE_INTERVAL_MS, j as SQLITE_PAGE_CACHE_FLOOR_KIB, k as SQLITE_MMAP_FLOOR_BYTES, n as WAL_HIGH_WATER_BYTES, r as WAL_IDLE_QUIET_MS, t as WAL_CHECKPOINT_BUSY_TIMEOUT_MS, z as SqliteOpProfiler } from "../../wal-maintenance-DLrbapzi.mjs";
3
3
  import { SqliteSettingsAddon } from "./sqlite-settings.addon.mjs";
4
4
  //#region src/builtins/sqlite-storage/config-store.ts
5
5
  var ConfigStore = class {
@@ -3,9 +3,9 @@ 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-C6Yvfhpq.js");
7
- const require_retired_settings_keys = require("../../retired-settings-keys-DJBQkZok.js");
8
- const require_wal_maintenance = require("../../wal-maintenance-CPLvZbzA.js");
6
+ const require_dist = require("../../dist-CnUtkSwN.js");
7
+ const require_retired_settings_keys = require("../../retired-settings-keys-CO3RqsDw.js");
8
+ const require_wal_maintenance = require("../../wal-maintenance-D3gwRj1B.js");
9
9
  const require_sqlite_snapshot_protocol = require("../../sqlite-snapshot-protocol-B9OndqZv.js");
10
10
  const require_wal_checkpoint_policy = require("../../wal-checkpoint-policy-d2z2qPqx.js");
11
11
  let node_fs_promises = require("node:fs/promises");
@@ -1,6 +1,6 @@
1
- import { St as databaseSnapshotCapability, _ as DATABASE_SNAPSHOT_PARTIAL_SUFFIX, b as DATA_STORE_DATABASES, nt as bareAddonId, tr as vectorStoreCapability, v as DATABASE_SNAPSHOT_SUFFIX, vr as errMsg, wr as RUNTIME_DEFAULTS, xt as dataStoreProviderCapability, y as DATABASE_SNAPSHOT_TIMEOUT_MS, yr as BaseAddon } from "../../dist-DJnlnL7P.mjs";
2
- import { r as retiredKeyStoreOf, t as purgeRetiredSettingsKeys } from "../../retired-settings-keys-CAWHWDwy.mjs";
3
- import { C as callControl, E as controlTargetOf, S as trustResult, T as callVector, _ as collectTransferables, a as WalMaintenance, c as SqliteSettingsBackend, d as CrossDatabaseTransactError, f as DatabaseBusyError, m as rehydrateError, o as createVectorIndex, p as DuplicatePlacementError, s as vectorProviderOf, u as CollectionPlacementError, v as isFileHostMessage, w as callData } from "../../wal-maintenance-Bc38yI3r.mjs";
1
+ import { Ct as dataStoreProviderCapability, Er as RUNTIME_DEFAULTS, _ as DATABASE_SNAPSHOT_PARTIAL_SUFFIX, b as DATA_STORE_DATABASES, br as errMsg, it as bareAddonId, rr as vectorStoreCapability, v as DATABASE_SNAPSHOT_SUFFIX, wt as databaseSnapshotCapability, xr as BaseAddon, y as DATABASE_SNAPSHOT_TIMEOUT_MS } from "../../dist-Bz4_y8Xy.mjs";
2
+ import { r as retiredKeyStoreOf, t as purgeRetiredSettingsKeys } from "../../retired-settings-keys-9nA85bwT.mjs";
3
+ import { C as callControl, E as controlTargetOf, S as trustResult, T as callVector, _ as collectTransferables, a as WalMaintenance, c as SqliteSettingsBackend, d as CrossDatabaseTransactError, f as DatabaseBusyError, m as rehydrateError, o as createVectorIndex, p as DuplicatePlacementError, s as vectorProviderOf, u as CollectionPlacementError, v as isFileHostMessage, w as callData } from "../../wal-maintenance-DLrbapzi.mjs";
4
4
  import { r as isSnapshotWorkerMessage } from "../../sqlite-snapshot-protocol-2QaTouWV.mjs";
5
5
  import { a as isWorkerMessage, t as WAL_CHECKPOINT_LARGE_PASS_FRAMES } from "../../wal-checkpoint-policy-BahrTtyD.mjs";
6
6
  import { createRequire } from "node:module";
@@ -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-C6Yvfhpq.js");
6
+ const require_dist = require("../../dist-CnUtkSwN.js");
7
7
  let zod = require("zod");
8
8
  let node_crypto = require("node:crypto");
9
9
  let _camstack_types_node = require("@camstack/types/node");
@@ -1,4 +1,4 @@
1
- import { Bn as settingsStoreCapability, Cr as REDACTED_SECRET, G as StorageCleanupJobSchema, Gt as gbToBytes, I as LegacyStorageLocationDefaultSchema, J as StorageMigrationJobSchema, K as StorageLocationModeSchema, Lt as evictionPolicyOfLocation, Nn as resolveLocationMode, Nr as collectSecretConfigKeys, Qr as parseJsonObject, Un as storageCapability, Wn as storageMigrationCapability, Xt as isLocationEnabled, ai as secretTreeFromPaths, di as EventCategory, dn as mayWriteToLocation, mn as modeMayWrite, nr as withLocationMode, q as StorageLocationTypeSchema, qr as isSecretMarker, ri as resolveSecretMarkers, rn as legacyModeOf, ui as transformSecretWrite, un as mayReadLocation, yr as BaseAddon } from "../../dist-DJnlnL7P.mjs";
1
+ import { Fn as resolveLocationMode, Fr as collectSecretConfigKeys, Gn as storageCapability, Hn as settingsStoreCapability, I as LegacyStorageLocationDefaultSchema, J as StorageLocationModeSchema, Kn as storageMigrationCapability, Qt as isLocationEnabled, Tr as REDACTED_SECRET, X as StorageMigrationJobSchema, Y as StorageLocationTypeSchema, Yr as isSecretMarker, ai as resolveSecretMarkers, an as legacyModeOf, ei as parseJsonObject, fi as transformSecretWrite, fn as mayReadLocation, gn as modeMayWrite, ir as withLocationMode, pi as EventCategory, pn as mayWriteToLocation, q as StorageCleanupJobSchema, qt as gbToBytes, si as secretTreeFromPaths, xr as BaseAddon, zt as evictionPolicyOfLocation } from "../../dist-Bz4_y8Xy.mjs";
2
2
  import { z } from "zod";
3
3
  import { randomUUID } from "node:crypto";
4
4
  import { containsOrEquals, physicalRootOf } from "@camstack/types/node";
@@ -3,11 +3,11 @@ 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-C6Yvfhpq.js");
6
+ const require_dist = require("../../dist-CnUtkSwN.js");
7
7
  const require_safe_buffer$1 = require("../../safe-buffer-D3aoa-7X.js");
8
- const require_x509_es = require("../../x509.es-Dzl0BbmG.js");
9
- const require_agent_https = require("../../agent-https-CHZTxK-q.js");
10
- const require_constants$8 = require("../../constants-Ah3T_KAW.js");
8
+ const require_x509_es = require("../../x509.es-r7Ht1thA.js");
9
+ const require_agent_https = require("../../agent-https-BZIwS4xF.js");
10
+ const require_constants$8 = require("../../constants-DL87WgeN.js");
11
11
  const require_src$1 = require("../../src-CnAqG6EF.js");
12
12
  let zod = require("zod");
13
13
  let node_crypto = require("node:crypto");
@@ -408,6 +408,15 @@ function parsePayloadEs256(value) {
408
408
  }
409
409
  //#endregion
410
410
  //#region src/kernel/moleculer/mesh-mtls/mesh-ca.ts
411
+ /**
412
+ * Hub mesh CA — EC P-256, key in the keychain, cert in `cluster.meshCa`.
413
+ *
414
+ * Distinct from the HTTPS local CA (`tls/cert-issue.ts`, RSA): the mesh CA
415
+ * signs node leaves (CN = nodeID) and join-token JWS (ES256). Issuance uses
416
+ * `@peculiar/x509` over WebCrypto — same library the HTTPS path already uses
417
+ * (installed `1.14.3`; registry latest at adoption time was `2.1.0` — stay on
418
+ * the pinned range already shipping).
419
+ */
411
420
  require_x509_es.cryptoProvider.set(node_crypto.webcrypto);
412
421
  var MS_PER_DAY = 864e5;
413
422
  /** Key generation — EC P-256 (plan). WebCrypto DOM names are not in @types/node. */
@@ -458,7 +467,7 @@ async function generateMeshCa(now = /* @__PURE__ */ new Date()) {
458
467
  const cert = await require_x509_es.X509CertificateGenerator.createSelfSigned({
459
468
  serialNumber: freshSerial(),
460
469
  name: `CN=${require_constants$8.MESH_CA_COMMON_NAME}`,
461
- notBefore: now,
470
+ notBefore: require_x509_es.backdatedNotBefore(now),
462
471
  notAfter: new Date(now.getTime() + require_constants$8.MESH_CA_VALIDITY_DAYS * MS_PER_DAY),
463
472
  keys,
464
473
  signingAlgorithm: MESH_SIGNING_ALGORITHM,
@@ -509,7 +518,7 @@ async function issueMeshLeafFromCsr(ca, csrPem, opts = {}) {
509
518
  serialNumber,
510
519
  subject: `CN=${cn}`,
511
520
  issuer: ca.cert.subject,
512
- notBefore: now,
521
+ notBefore: require_x509_es.backdatedNotBefore(now),
513
522
  notAfter,
514
523
  publicKey: csr.publicKey,
515
524
  signingKey: ca.privateKey,
@@ -88439,12 +88448,18 @@ function isHttpUrl(value) {
88439
88448
  return false;
88440
88449
  }
88441
88450
  }
88442
- /** The hub CA must be a self-signed CA certificate, valid now. */
88451
+ /**
88452
+ * Clock skew tolerated between the hub that minted a CA and this agent. X.509 dates have
88453
+ * one-second resolution and a fresh CA's notBefore is the hub's "now", so an agent whose clock
88454
+ * is even a moment behind would otherwise refuse a brand-new CA. Same bound as the offer `iat`.
88455
+ */
88456
+ var CA_CLOCK_SKEW_MS = 6e4;
88457
+ /** The hub CA must be a self-signed CA certificate, valid now (give or take the skew). */
88443
88458
  function readCaCertificate(pem, nowMs) {
88444
88459
  try {
88445
88460
  const cert = new node_crypto.X509Certificate(pem);
88446
88461
  if (!cert.ca || !cert.verify(cert.publicKey)) return null;
88447
- if (Date.parse(cert.validTo) <= nowMs || Date.parse(cert.validFrom) > nowMs) return null;
88462
+ if (Date.parse(cert.validTo) <= nowMs || Date.parse(cert.validFrom) > nowMs + CA_CLOCK_SKEW_MS) return null;
88448
88463
  return cert;
88449
88464
  } catch {
88450
88465
  return null;