camstack 1.2.37 → 1.2.38

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.
@@ -14522,7 +14522,7 @@ function date4(params) {
14522
14522
  // ../../node_modules/zod/v4/classic/external.js
14523
14523
  config(en_default());
14524
14524
 
14525
- // ../types/dist/sleep-zMxKWD0M.mjs
14525
+ // ../types/dist/sleep-B8EIZt4h.mjs
14526
14526
  var WELL_KNOWN_TABS = [
14527
14527
  {
14528
14528
  id: "overview",
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runDiscover
4
- } from "./chunk-OR2CMMOE.js";
4
+ } from "./chunk-UYHYTS5M.js";
5
5
  import "./chunk-LMMQX4CK.js";
6
6
 
7
7
  // src/cli.ts
@@ -38,7 +38,7 @@ async function runServe(args) {
38
38
  ...typeof values.data === "string" ? { data: values.data } : {}
39
39
  };
40
40
  Object.assign(process.env, buildServeEnv(opts));
41
- await import("./launcher-6VDFMPM6.js");
41
+ await import("./launcher-SCKDFMNR.js");
42
42
  }
43
43
 
44
44
  // src/commands/agent.ts
@@ -83,7 +83,7 @@ async function runAgent(args) {
83
83
  ...typeof values.port === "string" ? { port: values.port } : {}
84
84
  };
85
85
  Object.assign(process.env, buildAgentEnv(opts));
86
- await import("./launcher-6VDFMPM6.js");
86
+ await import("./launcher-SCKDFMNR.js");
87
87
  }
88
88
 
89
89
  // src/commands/setup.ts
@@ -1130,7 +1130,7 @@ function isUnknown(_value) {
1130
1130
  return true;
1131
1131
  }
1132
1132
  async function resolveServerInteractive(presetNamespace) {
1133
- const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-Y3C7HOBU.js");
1133
+ const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-5NNX7OG3.js");
1134
1134
  if (presetNamespace) {
1135
1135
  const spinner4 = clack.spinner();
1136
1136
  spinner4.start(`Discovering hub on LAN (namespace "${presetNamespace}")`);
@@ -5,7 +5,7 @@ import {
5
5
  filterHubNodes,
6
6
  resolveHubFromDiscovered,
7
7
  runDiscover
8
- } from "./chunk-OR2CMMOE.js";
8
+ } from "./chunk-UYHYTS5M.js";
9
9
  import "./chunk-LMMQX4CK.js";
10
10
  export {
11
11
  DEFAULT_HUB_HTTPS_PORT,
@@ -23631,9 +23631,9 @@ var require_zod = __commonJS({
23631
23631
  }
23632
23632
  });
23633
23633
 
23634
- // ../system/dist/dist-C1Aea3c6.js
23635
- var require_dist_C1Aea3c6 = __commonJS({
23636
- "../system/dist/dist-C1Aea3c6.js"(exports) {
23634
+ // ../system/dist/dist-iAwSA2_f.js
23635
+ var require_dist_iAwSA2_f = __commonJS({
23636
+ "../system/dist/dist-iAwSA2_f.js"(exports) {
23637
23637
  "use strict";
23638
23638
  var zod = require_zod();
23639
23639
  var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
@@ -23641,6 +23641,7 @@ var require_dist_C1Aea3c6 = __commonJS({
23641
23641
  EventCategory2["SystemAddonsReady"] = "system.addons-ready";
23642
23642
  EventCategory2["SystemRestarting"] = "system.restarting";
23643
23643
  EventCategory2["SystemRestartCompleted"] = "system.restart-completed";
23644
+ EventCategory2["SystemTlsCertChanged"] = "system.tls-cert-changed";
23644
23645
  EventCategory2["UpdateAvailable"] = "update.available";
23645
23646
  EventCategory2["SystemReadyState"] = "system.ready-state";
23646
23647
  EventCategory2["AddonStarted"] = "addon.started";
@@ -56255,7 +56256,7 @@ var require_alerts_addon = __commonJS({
56255
56256
  [Symbol.toStringTag]: { value: "Module" }
56256
56257
  });
56257
56258
  require_chunk_Cek0wNdY();
56258
- var require_dist10 = require_dist_C1Aea3c6();
56259
+ var require_dist10 = require_dist_iAwSA2_f();
56259
56260
  function selectExpired(alerts, cutoffMs) {
56260
56261
  return alerts.filter((a) => a.createdAt < cutoffMs).sort((a, b) => a.createdAt - b.createdAt).map((a) => a.id);
56261
56262
  }
@@ -56307,6 +56308,10 @@ var require_alerts_addon = __commonJS({
56307
56308
  severity: "warning",
56308
56309
  titleTemplate: "System restarting"
56309
56310
  },
56311
+ "system.tls-cert-changed": {
56312
+ severity: "warning",
56313
+ titleTemplate: "TLS certificate changed"
56314
+ },
56310
56315
  "device.registered": {
56311
56316
  severity: "info",
56312
56317
  titleTemplate: "Device registered"
@@ -56795,6 +56800,8 @@ var require_alerts_addon = __commonJS({
56795
56800
  return `Storage critical for device "${deviceId ?? "unknown"}"`;
56796
56801
  case "system.boot":
56797
56802
  return `System booted in "${data.mode ?? "unknown"}" mode`;
56803
+ case "system.tls-cert-changed":
56804
+ return data.caRotated === true ? `TLS certificate reissued (${String(data.reason)}) \u2014 the local CA also changed. Re-install ${String(data.caCertPath)} on any device that trusted the old one.` : `TLS certificate reissued (${String(data.reason)}) \u2014 the local CA is unchanged, previously trusted devices keep working.`;
56798
56805
  case "process.crashed":
56799
56806
  return `Process "${processId ?? "unknown"}" crashed`;
56800
56807
  default:
@@ -57068,7 +57075,7 @@ var require_console_logging = __commonJS({
57068
57075
  [Symbol.toStringTag]: { value: "Module" }
57069
57076
  });
57070
57077
  require_chunk_Cek0wNdY();
57071
- var require_dist10 = require_dist_C1Aea3c6();
57078
+ var require_dist10 = require_dist_iAwSA2_f();
57072
57079
  var require_formatter = require_formatter_DqAKDlvN();
57073
57080
  var LEVEL_RANK = {
57074
57081
  debug: 0,
@@ -57162,7 +57169,7 @@ var require_core_blocks_addon = __commonJS({
57162
57169
  "use strict";
57163
57170
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
57164
57171
  var require_chunk = require_chunk_Cek0wNdY();
57165
- var require_dist10 = require_dist_C1Aea3c6();
57172
+ var require_dist10 = require_dist_iAwSA2_f();
57166
57173
  var node_crypto = __require("crypto");
57167
57174
  var node_fs_promises = __require("fs/promises");
57168
57175
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -58059,11 +58066,11 @@ var require_core_blocks = __commonJS({
58059
58066
  }
58060
58067
  });
58061
58068
 
58062
- // ../system/dist/retired-settings-keys-B52KsNz8.js
58063
- var require_retired_settings_keys_B52KsNz8 = __commonJS({
58064
- "../system/dist/retired-settings-keys-B52KsNz8.js"(exports) {
58069
+ // ../system/dist/retired-settings-keys-OfhqQio4.js
58070
+ var require_retired_settings_keys_OfhqQio4 = __commonJS({
58071
+ "../system/dist/retired-settings-keys-OfhqQio4.js"(exports) {
58065
58072
  "use strict";
58066
- var require_dist10 = require_dist_C1Aea3c6();
58073
+ var require_dist10 = require_dist_iAwSA2_f();
58067
58074
  function settingsStoreIsAuthoritativeHere(env) {
58068
58075
  const raw = (env["CAMSTACK_ROLE"] ?? "").trim().toLowerCase();
58069
58076
  return raw === "" || raw === "hub";
@@ -60106,8 +60113,8 @@ var require_device_manager_addon = __commonJS({
60106
60113
  [Symbol.toStringTag]: { value: "Module" }
60107
60114
  });
60108
60115
  require_chunk_Cek0wNdY();
60109
- var require_dist10 = require_dist_C1Aea3c6();
60110
- var require_retired_settings_keys = require_retired_settings_keys_B52KsNz8();
60116
+ var require_dist10 = require_dist_iAwSA2_f();
60117
+ var require_retired_settings_keys = require_retired_settings_keys_OfhqQio4();
60111
60118
  var node_crypto = __require("crypto");
60112
60119
  var _camstack_types_node = require_node();
60113
60120
  var JOB_HISTORY = 20;
@@ -64434,7 +64441,7 @@ var require_hub_forwarder = __commonJS({
64434
64441
  [Symbol.toStringTag]: { value: "Module" }
64435
64442
  });
64436
64443
  require_chunk_Cek0wNdY();
64437
- var require_dist10 = require_dist_C1Aea3c6();
64444
+ var require_dist10 = require_dist_iAwSA2_f();
64438
64445
  var require_formatter = require_formatter_DqAKDlvN();
64439
64446
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
64440
64447
  var HubForwarderDestination = class {
@@ -64571,7 +64578,7 @@ var require_liveness_monitor_addon = __commonJS({
64571
64578
  "use strict";
64572
64579
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
64573
64580
  require_chunk_Cek0wNdY();
64574
- var require_dist10 = require_dist_C1Aea3c6();
64581
+ var require_dist10 = require_dist_iAwSA2_f();
64575
64582
  var NO_DEVICES = "liveness:no-devices";
64576
64583
  var ALL_OFFLINE = "liveness:all-devices-offline";
64577
64584
  var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
@@ -64761,7 +64768,7 @@ var require_local_auth_addon = __commonJS({
64761
64768
  [Symbol.toStringTag]: { value: "Module" }
64762
64769
  });
64763
64770
  var require_chunk = require_chunk_Cek0wNdY();
64764
- var require_dist10 = require_dist_C1Aea3c6();
64771
+ var require_dist10 = require_dist_iAwSA2_f();
64765
64772
  var node_crypto = __require("crypto");
64766
64773
  node_crypto = require_chunk.__toESM(node_crypto);
64767
64774
  var crypto$1 = __require("crypto");
@@ -72445,7 +72452,7 @@ var require_loki_logging = __commonJS({
72445
72452
  [Symbol.toStringTag]: { value: "Module" }
72446
72453
  });
72447
72454
  require_chunk_Cek0wNdY();
72448
- var require_dist10 = require_dist_C1Aea3c6();
72455
+ var require_dist10 = require_dist_iAwSA2_f();
72449
72456
  function sanitizeLabelName(raw) {
72450
72457
  const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
72451
72458
  return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
@@ -73010,7 +73017,7 @@ var require_native_metrics_addon = __commonJS({
73010
73017
  [Symbol.toStringTag]: { value: "Module" }
73011
73018
  });
73012
73019
  var require_chunk = require_chunk_Cek0wNdY();
73013
- var require_dist10 = require_dist_C1Aea3c6();
73020
+ var require_dist10 = require_dist_iAwSA2_f();
73014
73021
  var node_child_process = __require("child_process");
73015
73022
  var node_util = __require("util");
73016
73023
  var node_os = __require("os");
@@ -73952,7 +73959,7 @@ var require_filesystem_storage_addon = __commonJS({
73952
73959
  [Symbol.toStringTag]: { value: "Module" }
73953
73960
  });
73954
73961
  var require_chunk = require_chunk_Cek0wNdY();
73955
- var require_dist10 = require_dist_C1Aea3c6();
73962
+ var require_dist10 = require_dist_iAwSA2_f();
73956
73963
  var node_crypto = __require("crypto");
73957
73964
  var node_fs_promises = __require("fs/promises");
73958
73965
  var node_path = __require("path");
@@ -75068,8 +75075,8 @@ var require_sqlite_settings_addon = __commonJS({
75068
75075
  [Symbol.toStringTag]: { value: "Module" }
75069
75076
  });
75070
75077
  var require_chunk = require_chunk_Cek0wNdY();
75071
- var require_dist10 = require_dist_C1Aea3c6();
75072
- var require_retired_settings_keys = require_retired_settings_keys_B52KsNz8();
75078
+ var require_dist10 = require_dist_iAwSA2_f();
75079
+ var require_retired_settings_keys = require_retired_settings_keys_OfhqQio4();
75073
75080
  var node_crypto = __require("crypto");
75074
75081
  var node_fs = __require("fs");
75075
75082
  var node_module = __require("module");
@@ -76613,7 +76620,7 @@ var require_storage_orchestrator_addon = __commonJS({
76613
76620
  [Symbol.toStringTag]: { value: "Module" }
76614
76621
  });
76615
76622
  var require_chunk = require_chunk_Cek0wNdY();
76616
- var require_dist10 = require_dist_C1Aea3c6();
76623
+ var require_dist10 = require_dist_iAwSA2_f();
76617
76624
  var node_crypto = __require("crypto");
76618
76625
  var node_fs_promises = __require("fs/promises");
76619
76626
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -78492,7 +78499,7 @@ var require_system_config_addon = __commonJS({
78492
78499
  [Symbol.toStringTag]: { value: "Module" }
78493
78500
  });
78494
78501
  require_chunk_Cek0wNdY();
78495
- var require_dist10 = require_dist_C1Aea3c6();
78502
+ var require_dist10 = require_dist_iAwSA2_f();
78496
78503
  var SECTION_TITLES = {
78497
78504
  server: "Server",
78498
78505
  auth: "Authentication"
@@ -96553,7 +96560,7 @@ var require_winston_logging = __commonJS({
96553
96560
  [Symbol.toStringTag]: { value: "Module" }
96554
96561
  });
96555
96562
  var require_chunk = require_chunk_Cek0wNdY();
96556
- var require_dist10 = require_dist_C1Aea3c6();
96563
+ var require_dist10 = require_dist_iAwSA2_f();
96557
96564
  var require_formatter = require_formatter_DqAKDlvN();
96558
96565
  var node_path = __require("path");
96559
96566
  node_path = require_chunk.__toESM(node_path);
@@ -97541,15 +97548,16 @@ var require_file_data_plane_DUHPHa_Y = __commonJS({
97541
97548
  }
97542
97549
  });
97543
97550
 
97544
- // ../types/dist/event-category-CRPORAAz.js
97545
- var require_event_category_CRPORAAz = __commonJS({
97546
- "../types/dist/event-category-CRPORAAz.js"(exports) {
97551
+ // ../types/dist/event-category-EY0GNjV9.js
97552
+ var require_event_category_EY0GNjV9 = __commonJS({
97553
+ "../types/dist/event-category-EY0GNjV9.js"(exports) {
97547
97554
  "use strict";
97548
97555
  var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
97549
97556
  EventCategory2["SystemBoot"] = "system.boot";
97550
97557
  EventCategory2["SystemAddonsReady"] = "system.addons-ready";
97551
97558
  EventCategory2["SystemRestarting"] = "system.restarting";
97552
97559
  EventCategory2["SystemRestartCompleted"] = "system.restart-completed";
97560
+ EventCategory2["SystemTlsCertChanged"] = "system.tls-cert-changed";
97553
97561
  EventCategory2["UpdateAvailable"] = "update.available";
97554
97562
  EventCategory2["SystemReadyState"] = "system.ready-state";
97555
97563
  EventCategory2["AddonStarted"] = "addon.started";
@@ -97707,11 +97715,11 @@ var require_event_category_CRPORAAz = __commonJS({
97707
97715
  }
97708
97716
  });
97709
97717
 
97710
- // ../types/dist/sleep-CMRLJj2e.js
97711
- var require_sleep_CMRLJj2e = __commonJS({
97712
- "../types/dist/sleep-CMRLJj2e.js"(exports) {
97718
+ // ../types/dist/sleep-C2XhJhkd.js
97719
+ var require_sleep_C2XhJhkd = __commonJS({
97720
+ "../types/dist/sleep-C2XhJhkd.js"(exports) {
97713
97721
  "use strict";
97714
- var require_event_category = require_event_category_CRPORAAz();
97722
+ var require_event_category = require_event_category_EY0GNjV9();
97715
97723
  var zod = require_zod();
97716
97724
  var WELL_KNOWN_TABS = [
97717
97725
  {
@@ -101148,8 +101156,8 @@ var require_addon = __commonJS({
101148
101156
  "../types/dist/addon.js"(exports) {
101149
101157
  "use strict";
101150
101158
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
101151
- var require_event_category = require_event_category_CRPORAAz();
101152
- var require_sleep = require_sleep_CMRLJj2e();
101159
+ var require_event_category = require_event_category_EY0GNjV9();
101160
+ var require_sleep = require_sleep_C2XhJhkd();
101153
101161
  var require_err_msg = require_err_msg_COpsHMw2();
101154
101162
  var CAP_INPUT_DEFAULTS = Object.freeze({
101155
101163
  "addons": { "getLogs": { "limit": 100 } },
@@ -108023,9 +108031,9 @@ var require_dist2 = __commonJS({
108023
108031
  }
108024
108032
  });
108025
108033
 
108026
- // ../system/dist/manifest-python-deps-MA_BZGBz.js
108027
- var require_manifest_python_deps_MA_BZGBz = __commonJS({
108028
- "../system/dist/manifest-python-deps-MA_BZGBz.js"(exports) {
108034
+ // ../system/dist/manifest-python-deps-CwBbX4Ut.js
108035
+ var require_manifest_python_deps_CwBbX4Ut = __commonJS({
108036
+ "../system/dist/manifest-python-deps-CwBbX4Ut.js"(exports) {
108029
108037
  "use strict";
108030
108038
  var require_chunk = require_chunk_Cek0wNdY();
108031
108039
  var node_crypto = __require("crypto");
@@ -108046,8 +108054,8 @@ var require_manifest_python_deps_MA_BZGBz = __commonJS({
108046
108054
  var node_vm = __require("vm");
108047
108055
  node_vm = require_chunk.__toESM(node_vm);
108048
108056
  var _camstack_types_addon = require_addon();
108049
- var _trpc_client = require_dist2();
108050
108057
  var node_net = __require("net");
108058
+ var _trpc_client = require_dist2();
108051
108059
  var HEAP_WATCH_INTERVAL_MS = 6e4;
108052
108060
  var HEAP_WATCH_WARN_RATIO = 0.8;
108053
108061
  var HEAP_WATCH_ESCALATE_RATIO = 0.7;
@@ -118829,7 +118837,7 @@ var require_dist3 = __commonJS({
118829
118837
  "use strict";
118830
118838
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
118831
118839
  var require_chunk = require_chunk_Cek0wNdY();
118832
- var require_dist10 = require_dist_C1Aea3c6();
118840
+ var require_dist10 = require_dist_iAwSA2_f();
118833
118841
  var require_builtins_alerts_alerts_addon = require_alerts_addon();
118834
118842
  require_alerts();
118835
118843
  var require_formatter = require_formatter_DqAKDlvN();
@@ -118854,7 +118862,7 @@ var require_dist3 = __commonJS({
118854
118862
  require_system_config();
118855
118863
  var require_builtins_winston_logging_index = require_winston_logging();
118856
118864
  var require_file_data_plane = require_file_data_plane_DUHPHa_Y();
118857
- var require_manifest_python_deps = require_manifest_python_deps_MA_BZGBz();
118865
+ var require_manifest_python_deps = require_manifest_python_deps_CwBbX4Ut();
118858
118866
  var require_resource_monitor = require_resource_monitor_CdnzxBLP();
118859
118867
  var require_custom_action_registry = require_custom_action_registry_jY0NOZK8();
118860
118868
  var zod = require_zod();
@@ -118875,6 +118883,7 @@ var require_dist3 = __commonJS({
118875
118883
  var node_vm = __require("vm");
118876
118884
  node_vm = require_chunk.__toESM(node_vm);
118877
118885
  var _camstack_types_addon = require_addon();
118886
+ var node_net = __require("net");
118878
118887
  var node_url = __require("url");
118879
118888
  var node_events = __require("events");
118880
118889
  var node_stream = __require("stream");
@@ -120639,63 +120648,330 @@ var require_dist3 = __commonJS({
120639
120648
  };
120640
120649
  }
120641
120650
  };
120642
- var execFileAsync$3 = (0, node_util.promisify)(node_child_process.execFile);
120643
- async function ensureTlsCert(dataDir, options) {
120644
- const tlsDir = (0, node_path.join)(dataDir, "tls");
120645
- const certPath = (0, node_path.join)(tlsDir, "camstack.crt");
120646
- const keyPath = (0, node_path.join)(tlsDir, "camstack.key");
120647
- if ((0, node_fs.existsSync)(certPath) && (0, node_fs.existsSync)(keyPath)) try {
120648
- const x509 = new node_crypto.X509Certificate((0, node_fs.readFileSync)(certPath));
120649
- if (new Date(x509.validTo) > /* @__PURE__ */ new Date()) return {
120650
- certPath,
120651
- keyPath,
120652
- generated: false
120653
- };
120651
+ var SERVER_AUTH_OID = "1.3.6.1.5.5.7.3.1";
120652
+ var MAX_LEAF_VALIDITY_DAYS = 397;
120653
+ var LEAF_RENEWAL_WINDOW_DAYS = 30;
120654
+ var CA_VALIDITY_DAYS = 3650;
120655
+ var MS_PER_DAY = 864e5;
120656
+ var REASONS_REQUIRING_NEW_CA = [
120657
+ "missing",
120658
+ "unreadable",
120659
+ "no-local-ca",
120660
+ "ca-expiring"
120661
+ ];
120662
+ function reasonRequiresNewCa(reason) {
120663
+ return REASONS_REQUIRING_NEW_CA.includes(reason);
120664
+ }
120665
+ function parse$1(pem) {
120666
+ try {
120667
+ return new node_crypto.X509Certificate(pem);
120668
+ } catch {
120669
+ return null;
120670
+ }
120671
+ }
120672
+ function daysBetween(from, to) {
120673
+ return (to.getTime() - from.getTime()) / MS_PER_DAY;
120674
+ }
120675
+ function hasServerAuthEku(leaf) {
120676
+ const eku = leaf.keyUsage;
120677
+ return eku !== void 0 && eku.length === 1 && eku[0] === "1.3.6.1.5.5.7.3.1";
120678
+ }
120679
+ function keyMatches(leaf, keyPem) {
120680
+ try {
120681
+ return leaf.checkPrivateKey((0, node_crypto.createPrivateKey)(keyPem));
120654
120682
  } catch {
120683
+ return false;
120655
120684
  }
120656
- (0, node_fs.mkdirSync)(tlsDir, { recursive: true });
120657
- const cn = options?.commonName ?? "camstack.local";
120658
- const validDays = options?.validDays ?? 825;
120659
- const sanDns = /* @__PURE__ */ new Set([
120685
+ }
120686
+ function coversIdentity(leaf, identity) {
120687
+ for (const name2 of identity.requiredDnsNames) if (leaf.checkHost(name2) === void 0) return false;
120688
+ for (const ip of identity.requiredIpAddresses) if (leaf.checkIP(ip) === void 0) return false;
120689
+ return true;
120690
+ }
120691
+ function evaluateExistingCert(input) {
120692
+ const leaf = parse$1(input.chainPem);
120693
+ const ca = parse$1(input.caPem);
120694
+ if (leaf === null || ca === null) return "unreadable";
120695
+ if (daysBetween(input.now, new Date(ca.validTo)) < 427) return "ca-expiring";
120696
+ if (!keyMatches(leaf, input.keyPem)) return "key-mismatch";
120697
+ if (daysBetween(input.now, new Date(leaf.validTo)) < 30) return "expiring";
120698
+ if (!hasServerAuthEku(leaf)) return "missing-server-auth-eku";
120699
+ if (leaf.ca || !leaf.checkIssued(ca) || !leaf.verify(ca.publicKey)) return "not-issued-by-local-ca";
120700
+ if (daysBetween(new Date(leaf.validFrom), new Date(leaf.validTo)) > 398) return "validity-too-long";
120701
+ if (!coversIdentity(leaf, input.identity)) return "san-coverage-gap";
120702
+ return null;
120703
+ }
120704
+ var VOLATILE_INTERFACE_PREFIXES = [
120705
+ "docker",
120706
+ "br-",
120707
+ "veth",
120708
+ "virbr",
120709
+ "cni",
120710
+ "flannel",
120711
+ "tun",
120712
+ "utun",
120713
+ "tap",
120714
+ "wg",
120715
+ "zt",
120716
+ "tailscale",
120717
+ "ppp",
120718
+ "awdl",
120719
+ "llw"
120720
+ ];
120721
+ var DNS_NAME_PATTERN = /^[A-Za-z0-9]([A-Za-z0-9._-]*[A-Za-z0-9])?$/;
120722
+ function isIpv4(value) {
120723
+ return (0, node_net.isIP)(value) === 4;
120724
+ }
120725
+ function isIpv6(value) {
120726
+ return (0, node_net.isIP)(value) === 6;
120727
+ }
120728
+ function isLinkLocal(value) {
120729
+ if (isIpv4(value)) return value.startsWith("169.254.");
120730
+ if (!isIpv6(value)) return false;
120731
+ const firstGroup = value.split(":")[0] ?? "";
120732
+ if (firstGroup === "") return false;
120733
+ const parsed = Number.parseInt(firstGroup, 16);
120734
+ return Number.isFinite(parsed) && (parsed & 65472) === 65152;
120735
+ }
120736
+ function isUniqueLocalIpv6(value) {
120737
+ if (!isIpv6(value)) return false;
120738
+ const firstGroup = value.split(":")[0] ?? "";
120739
+ const parsed = Number.parseInt(firstGroup, 16);
120740
+ return Number.isFinite(parsed) && (parsed & 65024) === 64512;
120741
+ }
120742
+ function isVolatileInterface(name2) {
120743
+ const lower = name2.toLowerCase();
120744
+ return VOLATILE_INTERFACE_PREFIXES.some((prefix) => lower.startsWith(prefix));
120745
+ }
120746
+ function isStableGateAddress(address) {
120747
+ if (isLinkLocal(address)) return false;
120748
+ if (isIpv4(address)) return true;
120749
+ return isUniqueLocalIpv6(address);
120750
+ }
120751
+ function addSan(dns, ips, value) {
120752
+ const trimmed = value.trim();
120753
+ if (trimmed === "") return;
120754
+ if ((0, node_net.isIP)(trimmed) !== 0) {
120755
+ if (!isLinkLocal(trimmed)) ips.add(trimmed);
120756
+ return;
120757
+ }
120758
+ if (DNS_NAME_PATTERN.test(trimmed)) dns.add(trimmed);
120759
+ }
120760
+ function collectCertIdentity(options) {
120761
+ const dnsNames = /* @__PURE__ */ new Set();
120762
+ const ipAddresses = /* @__PURE__ */ new Set(["127.0.0.1", "::1"]);
120763
+ const requiredDnsNames = /* @__PURE__ */ new Set();
120764
+ const requiredIpAddresses = /* @__PURE__ */ new Set(["127.0.0.1"]);
120765
+ for (const name2 of [
120660
120766
  "localhost",
120661
- cn,
120767
+ options.commonName,
120662
120768
  node_os.hostname()
120663
- ]);
120664
- const sanIps = /* @__PURE__ */ new Set(["127.0.0.1", "::1"]);
120665
- const interfaces = node_os.networkInterfaces();
120666
- for (const addrs of Object.values(interfaces)) {
120667
- if (!addrs) continue;
120668
- for (const addr of addrs) if (!addr.internal) sanIps.add(addr.address);
120669
- }
120670
- for (const san of options?.extraSans ?? []) if (san.match(/^\d+\.\d+\.\d+\.\d+$/) || san.includes(":")) sanIps.add(san);
120671
- else sanDns.add(san);
120672
- const sanParts = [];
120673
- for (const dns of sanDns) sanParts.push(`DNS:${dns}`);
120674
- for (const ip of sanIps) sanParts.push(`IP:${ip}`);
120675
- const sanString = sanParts.join(",");
120769
+ ]) {
120770
+ addSan(dnsNames, ipAddresses, name2);
120771
+ addSan(requiredDnsNames, requiredIpAddresses, name2);
120772
+ }
120773
+ for (const [ifaceName, addrs] of Object.entries(node_os.networkInterfaces())) for (const addr of addrs ?? []) {
120774
+ if (addr.internal) continue;
120775
+ if (isLinkLocal(addr.address)) continue;
120776
+ ipAddresses.add(addr.address);
120777
+ if (isVolatileInterface(ifaceName)) continue;
120778
+ if (isStableGateAddress(addr.address)) requiredIpAddresses.add(addr.address);
120779
+ }
120780
+ for (const san of options.extraSans) {
120781
+ addSan(dnsNames, ipAddresses, san);
120782
+ addSan(requiredDnsNames, requiredIpAddresses, san);
120783
+ }
120784
+ return {
120785
+ dnsNames: [...dnsNames],
120786
+ ipAddresses: [...ipAddresses],
120787
+ requiredDnsNames: [...requiredDnsNames],
120788
+ requiredIpAddresses: [...requiredIpAddresses]
120789
+ };
120790
+ }
120791
+ var execFileAsync$3 = (0, node_util.promisify)(node_child_process.execFile);
120792
+ var CA_COMMON_NAME = "CamStack Local CA";
120793
+ function sanValue(identity) {
120794
+ const parts = [];
120795
+ for (const dns of identity.dnsNames) parts.push(`DNS:${dns}`);
120796
+ for (const ip of identity.ipAddresses) if ((0, node_net.isIP)(ip) !== 0) parts.push(`IP:${ip}`);
120797
+ return parts.join(",");
120798
+ }
120799
+ async function generateCa(tmpDir) {
120800
+ const caCertPath = (0, node_path.join)(tmpDir, "ca.crt");
120801
+ const caKeyPath = (0, node_path.join)(tmpDir, "ca.key");
120676
120802
  await execFileAsync$3("openssl", [
120677
120803
  "req",
120678
120804
  "-x509",
120679
120805
  "-newkey",
120680
120806
  "rsa:2048",
120807
+ "-nodes",
120808
+ "-sha256",
120809
+ "-days",
120810
+ String(CA_VALIDITY_DAYS),
120811
+ "-keyout",
120812
+ caKeyPath,
120813
+ "-out",
120814
+ caCertPath,
120815
+ "-subj",
120816
+ `/CN=${CA_COMMON_NAME}`,
120817
+ "-addext",
120818
+ "basicConstraints=critical,CA:TRUE,pathlen:0",
120819
+ "-addext",
120820
+ "keyUsage=critical,keyCertSign,cRLSign",
120821
+ "-addext",
120822
+ "subjectKeyIdentifier=hash"
120823
+ ]);
120824
+ await (0, node_fs_promises.chmod)(caKeyPath, 384);
120825
+ return {
120826
+ caCertPath,
120827
+ caKeyPath
120828
+ };
120829
+ }
120830
+ async function issueLeaf(tmpDir, ca, identity, commonName, validDays) {
120831
+ const keyPath = (0, node_path.join)(tmpDir, "leaf.key");
120832
+ const csrPath = (0, node_path.join)(tmpDir, "leaf.csr");
120833
+ const certPath = (0, node_path.join)(tmpDir, "leaf.crt");
120834
+ const extPath = (0, node_path.join)(tmpDir, "leaf.ext");
120835
+ await (0, node_fs_promises.writeFile)(extPath, [
120836
+ "basicConstraints=critical,CA:FALSE",
120837
+ "keyUsage=critical,digitalSignature,keyEncipherment",
120838
+ "extendedKeyUsage=serverAuth",
120839
+ "subjectKeyIdentifier=hash",
120840
+ "authorityKeyIdentifier=keyid,issuer",
120841
+ `subjectAltName=${sanValue(identity)}`,
120842
+ ""
120843
+ ].join("\n"), "utf-8");
120844
+ await execFileAsync$3("openssl", [
120845
+ "req",
120846
+ "-new",
120847
+ "-newkey",
120848
+ "rsa:2048",
120849
+ "-nodes",
120850
+ "-sha256",
120681
120851
  "-keyout",
120682
120852
  keyPath,
120683
120853
  "-out",
120684
- certPath,
120854
+ csrPath,
120855
+ "-subj",
120856
+ `/CN=${commonName}`
120857
+ ]);
120858
+ await execFileAsync$3("openssl", [
120859
+ "x509",
120860
+ "-req",
120861
+ "-in",
120862
+ csrPath,
120863
+ "-CA",
120864
+ ca.caCertPath,
120865
+ "-CAkey",
120866
+ ca.caKeyPath,
120867
+ "-set_serial",
120868
+ `0x00${(0, node_crypto.randomBytes)(16).toString("hex")}`,
120685
120869
  "-days",
120686
120870
  String(validDays),
120687
- "-nodes",
120688
- "-subj",
120689
- `/CN=${cn}`,
120690
- "-addext",
120691
- `subjectAltName=${sanString}`
120871
+ "-sha256",
120872
+ "-extfile",
120873
+ extPath,
120874
+ "-out",
120875
+ certPath
120692
120876
  ]);
120693
- const { chmod } = await import("fs/promises");
120694
- await chmod(keyPath, 384);
120877
+ await (0, node_fs_promises.chmod)(keyPath, 384);
120878
+ await (0, node_fs_promises.rm)(csrPath, { force: true });
120879
+ await (0, node_fs_promises.rm)(extPath, { force: true });
120695
120880
  return {
120696
120881
  certPath,
120697
- keyPath,
120698
- generated: true
120882
+ keyPath
120883
+ };
120884
+ }
120885
+ var DEFAULT_COMMON_NAME = "camstack.local";
120886
+ async function ensureTlsCert(dataDir, options) {
120887
+ const tlsDir = (0, node_path.join)(dataDir, "tls");
120888
+ const paths = {
120889
+ certPath: (0, node_path.join)(tlsDir, "camstack.crt"),
120890
+ keyPath: (0, node_path.join)(tlsDir, "camstack.key"),
120891
+ caCertPath: (0, node_path.join)(tlsDir, "camstack-ca.crt"),
120892
+ caKeyPath: (0, node_path.join)(tlsDir, "camstack-ca.key")
120893
+ };
120894
+ const commonName = options?.commonName ?? DEFAULT_COMMON_NAME;
120895
+ const validDays = Math.min(options?.validDays ?? 397, 397);
120896
+ const identity = collectCertIdentity({
120897
+ commonName,
120898
+ extraSans: options?.extraSans ?? []
120899
+ });
120900
+ const reason = decideRegeneration(paths, identity);
120901
+ if (reason === null) return describe(paths, false, null, false, null);
120902
+ const previousFingerprint = readFingerprint(paths.certPath);
120903
+ const caRotated = reasonRequiresNewCa(reason);
120904
+ (0, node_fs.mkdirSync)(tlsDir, { recursive: true });
120905
+ await regenerate(paths, identity, commonName, validDays, caRotated);
120906
+ return describe(paths, true, reason, caRotated, previousFingerprint);
120907
+ }
120908
+ function readFingerprint(certPath) {
120909
+ try {
120910
+ return new node_crypto.X509Certificate((0, node_fs.readFileSync)(certPath)).fingerprint256;
120911
+ } catch {
120912
+ return null;
120913
+ }
120914
+ }
120915
+ function decideRegeneration(paths, identity) {
120916
+ if (!(0, node_fs.existsSync)(paths.certPath) || !(0, node_fs.existsSync)(paths.keyPath)) return "missing";
120917
+ if (!(0, node_fs.existsSync)(paths.caCertPath) || !(0, node_fs.existsSync)(paths.caKeyPath)) return "no-local-ca";
120918
+ try {
120919
+ return evaluateExistingCert({
120920
+ chainPem: (0, node_fs.readFileSync)(paths.certPath, "utf-8"),
120921
+ keyPem: (0, node_fs.readFileSync)(paths.keyPath, "utf-8"),
120922
+ caPem: (0, node_fs.readFileSync)(paths.caCertPath, "utf-8"),
120923
+ identity,
120924
+ now: /* @__PURE__ */ new Date()
120925
+ });
120926
+ } catch {
120927
+ return "unreadable";
120928
+ }
120929
+ }
120930
+ async function regenerate(paths, identity, commonName, validDays, newCa) {
120931
+ const scratch = await (0, node_fs_promises.mkdtemp)((0, node_path.join)((0, node_os.tmpdir)(), "camstack-tls-"));
120932
+ try {
120933
+ const ca = newCa ? await generateCa(scratch) : {
120934
+ caCertPath: paths.caCertPath,
120935
+ caKeyPath: paths.caKeyPath
120936
+ };
120937
+ const leaf = await issueLeaf(scratch, ca, identity, commonName, validDays);
120938
+ const chainPath = (0, node_path.join)(scratch, "chain.crt");
120939
+ await (0, node_fs_promises.writeFile)(chainPath, `${(0, node_fs.readFileSync)(leaf.certPath, "utf-8").trimEnd()}
120940
+ ${(0, node_fs.readFileSync)(ca.caCertPath, "utf-8").trimEnd()}
120941
+ `, "utf-8");
120942
+ if (newCa) {
120943
+ await (0, node_fs_promises.copyFile)(ca.caCertPath, `${paths.caCertPath}.new`);
120944
+ await (0, node_fs_promises.copyFile)(ca.caKeyPath, `${paths.caKeyPath}.new`);
120945
+ (0, node_fs.renameSync)(`${paths.caCertPath}.new`, paths.caCertPath);
120946
+ (0, node_fs.renameSync)(`${paths.caKeyPath}.new`, paths.caKeyPath);
120947
+ await (0, node_fs_promises.chmod)(paths.caKeyPath, 384);
120948
+ }
120949
+ await (0, node_fs_promises.copyFile)(leaf.keyPath, `${paths.keyPath}.new`);
120950
+ await (0, node_fs_promises.copyFile)(chainPath, `${paths.certPath}.new`);
120951
+ (0, node_fs.renameSync)(`${paths.keyPath}.new`, paths.keyPath);
120952
+ (0, node_fs.renameSync)(`${paths.certPath}.new`, paths.certPath);
120953
+ await (0, node_fs_promises.chmod)(paths.keyPath, 384);
120954
+ } finally {
120955
+ await (0, node_fs_promises.rm)(scratch, {
120956
+ recursive: true,
120957
+ force: true
120958
+ });
120959
+ }
120960
+ }
120961
+ function describe(paths, generated, reason, caRotated, previousFingerprintSha256) {
120962
+ const leaf = new node_crypto.X509Certificate((0, node_fs.readFileSync)(paths.certPath));
120963
+ const ca = new node_crypto.X509Certificate((0, node_fs.readFileSync)(paths.caCertPath));
120964
+ const san = leaf.subjectAltName ?? "";
120965
+ return {
120966
+ ...paths,
120967
+ generated,
120968
+ reason,
120969
+ caRotated,
120970
+ fingerprintSha256: leaf.fingerprint256,
120971
+ previousFingerprintSha256,
120972
+ caFingerprintSha256: ca.fingerprint256,
120973
+ validTo: new Date(leaf.validTo).toISOString(),
120974
+ sans: san === "" ? [] : san.split(", ")
120699
120975
  };
120700
120976
  }
120701
120977
  function loadTlsCert(certPath, keyPath) {
@@ -198975,6 +199251,8 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
198975
199251
  exports.AlertCenterAddon = require_builtins_alerts_alerts_addon.AlertCenterAddon;
198976
199252
  exports.ApiKeyManager = require_builtins_local_auth_local_auth_addon.ApiKeyManager;
198977
199253
  exports.AuthManager = require_builtins_local_auth_local_auth_addon.AuthManager;
199254
+ exports.CA_COMMON_NAME = CA_COMMON_NAME;
199255
+ exports.CA_VALIDITY_DAYS = CA_VALIDITY_DAYS;
198978
199256
  exports.CLUSTER_SECRET_MISMATCH_TYPE = CLUSTER_SECRET_MISMATCH_TYPE;
198979
199257
  exports.CLUSTER_SECRET_REJECTED_EXIT_CODE = CLUSTER_SECRET_REJECTED_EXIT_CODE;
198980
199258
  exports.CORE_CAP_SERVICE_NAME = CORE_CAP_SERVICE_NAME;
@@ -199021,6 +199299,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
199021
199299
  exports.INFRA_CAPABILITIES = INFRA_CAPABILITIES;
199022
199300
  exports.IntegrationRegistry = IntegrationRegistry;
199023
199301
  exports.JobJournal = JobJournal;
199302
+ exports.LEAF_RENEWAL_WINDOW_DAYS = LEAF_RENEWAL_WINDOW_DAYS;
199024
199303
  exports.LifecycleJobEngine = LifecycleJobEngine;
199025
199304
  exports.LifecycleStateMachine = LifecycleStateMachine;
199026
199305
  exports.LivenessMonitorAddon = require_builtins_liveness_monitor_liveness_monitor_addon.LivenessMonitorAddon;
@@ -199031,6 +199310,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
199031
199310
  exports.LogRingBuffer = LogRingBuffer;
199032
199311
  exports.LokiDestination = require_builtins_loki_logging_index.LokiDestination$1;
199033
199312
  exports.LokiLoggingAddon = require_builtins_loki_logging_index.LokiLoggingAddon$1;
199313
+ exports.MAX_LEAF_VALIDITY_DAYS = MAX_LEAF_VALIDITY_DAYS;
199034
199314
  exports.METHOD_ACCESS_MAP = require_dist10.METHOD_ACCESS_MAP;
199035
199315
  exports.ModelDownloadService = require_file_data_plane.ModelDownloadService;
199036
199316
  exports.NATIVE_PROVIDER_SERVICE_INFIX = require_manifest_python_deps.NATIVE_PROVIDER_SERVICE_INFIX;
@@ -199056,6 +199336,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
199056
199336
  exports.ReadinessTimeoutError = require_dist10.ReadinessTimeoutError;
199057
199337
  exports.ReplEngine = ReplEngine;
199058
199338
  exports.RingBuffer = RingBuffer;
199339
+ exports.SERVER_AUTH_OID = SERVER_AUTH_OID;
199059
199340
  exports.ScopedLogger = ScopedLogger;
199060
199341
  exports.ScopedTokenManager = require_builtins_local_auth_local_auth_addon.ScopedTokenManager;
199061
199342
  exports.SocketChannel = require_manifest_python_deps.SocketChannel;
@@ -199107,6 +199388,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
199107
199388
  exports.clearPendingRestart = clearPendingRestart;
199108
199389
  exports.clusterEventTopic = require_manifest_python_deps.clusterEventTopic;
199109
199390
  exports.clusterSecretMatches = clusterSecretMatches;
199391
+ exports.collectCertIdentity = collectCertIdentity;
199110
199392
  exports.collectModelFiles = require_file_data_plane.collectModelFiles;
199111
199393
  exports.contentTypeFor = require_file_data_plane.contentTypeFor;
199112
199394
  exports.copyDirRecursive = copyDirRecursive;
@@ -199173,6 +199455,7 @@ globstar while`, t, d, e, f, m), this.matchOne(t.slice(d), e.slice(f), s)) retur
199173
199455
  }
199174
199456
  });
199175
199457
  exports.ensureTlsCert = ensureTlsCert;
199458
+ exports.evaluateExistingCert = evaluateExistingCert;
199176
199459
  exports.expandCapMethods = require_dist10.expandCapMethods;
199177
199460
  exports.fetchJson = require_file_data_plane.fetchJson;
199178
199461
  Object.defineProperty(exports, "findInPath", {
@@ -237936,7 +238219,7 @@ var require_enums = __commonJS({
237936
238219
  "../types/dist/enums.js"(exports) {
237937
238220
  "use strict";
237938
238221
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
237939
- var require_event_category = require_event_category_CRPORAAz();
238222
+ var require_event_category = require_event_category_EY0GNjV9();
237940
238223
  var EventSourceType = /* @__PURE__ */ (function(EventSourceType2) {
237941
238224
  EventSourceType2["Addon"] = "addon";
237942
238225
  EventSourceType2["Core"] = "core";
@@ -237956,8 +238239,8 @@ var require_dist9 = __commonJS({
237956
238239
  "../types/dist/index.js"(exports) {
237957
238240
  "use strict";
237958
238241
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
237959
- var require_event_category = require_event_category_CRPORAAz();
237960
- var require_sleep = require_sleep_CMRLJj2e();
238242
+ var require_event_category = require_event_category_EY0GNjV9();
238243
+ var require_sleep = require_sleep_C2XhJhkd();
237961
238244
  var require_canonical_hash = require_canonical_hash_DNV8S5ET();
237962
238245
  var require_enums2 = require_enums();
237963
238246
  var require_err_msg = require_err_msg_COpsHMw2();
@@ -399394,7 +399677,7 @@ var require_post_boot_service = __commonJS({
399394
399677
  return entry.payload;
399395
399678
  }
399396
399679
  async run(context) {
399397
- const { port, host, dataPath, trpcRegistered } = context;
399680
+ const { port, host, dataPath, trpcRegistered, tlsCert } = context;
399398
399681
  this.eventBus.emit({
399399
399682
  id: (0, node_crypto_1.randomUUID)(),
399400
399683
  timestamp: /* @__PURE__ */ new Date(),
@@ -399403,6 +399686,7 @@ var require_post_boot_service = __commonJS({
399403
399686
  data: { port, host, trpcRegistered, dataPath }
399404
399687
  });
399405
399688
  this.emitRestartCompletedIfPending(dataPath);
399689
+ this.emitTlsCertChangedIfReissued(tlsCert);
399406
399690
  await this.reconcileLifecycleJobsIfAny();
399407
399691
  }
399408
399692
  async reconcileLifecycleJobsIfAny() {
@@ -399411,6 +399695,27 @@ var require_post_boot_service = __commonJS({
399411
399695
  this.logger.info("Lifecycle jobs reconciled at boot", { meta: { resumed, failed } });
399412
399696
  }
399413
399697
  }
399698
+ emitTlsCertChangedIfReissued(tlsCert) {
399699
+ if (tlsCert === void 0 || !tlsCert.generated)
399700
+ return;
399701
+ const payload = {
399702
+ reason: tlsCert.reason ?? "unknown",
399703
+ fingerprintSha256: tlsCert.fingerprintSha256,
399704
+ caFingerprintSha256: tlsCert.caFingerprintSha256,
399705
+ caRotated: tlsCert.caRotated,
399706
+ caCertPath: tlsCert.caCertPath,
399707
+ validTo: tlsCert.validTo,
399708
+ sans: tlsCert.sans
399709
+ };
399710
+ this.logger.warn("TLS certificate reissued", { meta: payload });
399711
+ this.eventBus.emit({
399712
+ id: (0, node_crypto_1.randomUUID)(),
399713
+ timestamp: /* @__PURE__ */ new Date(),
399714
+ source: { type: "core", id: "system" },
399715
+ category: types_1.EventCategory.SystemTlsCertChanged,
399716
+ data: payload
399717
+ });
399718
+ }
399414
399719
  emitRestartCompletedIfPending(dataDir) {
399415
399720
  const marker = (0, system_1.readPendingRestart)(dataDir);
399416
399721
  if (marker === null)
@@ -401980,11 +402285,11 @@ var require_boot_config = __commonJS({
401980
402285
  exports.loadBootstrapConfig = loadBootstrapConfig;
401981
402286
  exports.autoGenerateJwtSecret = autoGenerateJwtSecret;
401982
402287
  exports.setupInfra = setupInfra;
402288
+ var node_crypto_1 = __require("crypto");
401983
402289
  var fs = __importStar(__require("fs"));
401984
402290
  var path = __importStar(__require("path"));
401985
- var yaml = __importStar(require_js_yaml());
401986
- var node_crypto_1 = __require("crypto");
401987
402291
  var types_1 = require_dist9();
402292
+ var yaml = __importStar(require_js_yaml());
401988
402293
  var config_schema_1 = require_config_schema();
401989
402294
  var storage_location_manager_1 = require_storage_location_manager();
401990
402295
  var CONFIG_DEFAULTS = {
@@ -402104,6 +402409,7 @@ var require_boot_config = __commonJS({
402104
402409
  console.log(`[Phase2] Location "${name}": ${available ? "OK" : "UNAVAILABLE"} \u2192 ${locPath}`);
402105
402410
  }
402106
402411
  let tlsOptions;
402412
+ let tlsCert;
402107
402413
  if (config.tls.enabled) {
402108
402414
  const core = require_dist3();
402109
402415
  const { ensureTlsCert, loadTlsCert } = core;
@@ -402113,11 +402419,8 @@ var require_boot_config = __commonJS({
402113
402419
  tlsOptions = { key: pair.key, cert: pair.cert };
402114
402420
  } else {
402115
402421
  const tlsResult = await ensureTlsCert(dataPath);
402116
- if (tlsResult.generated) {
402117
- console.log(`[Phase2c] Generated self-signed TLS cert at ${tlsResult.certPath}`);
402118
- } else {
402119
- console.log(`[Phase2c] Using existing TLS cert at ${tlsResult.certPath}`);
402120
- }
402422
+ tlsCert = tlsResult;
402423
+ logTlsCert(tlsResult);
402121
402424
  const pair = loadTlsCert(tlsResult.certPath, tlsResult.keyPath);
402122
402425
  tlsOptions = { key: pair.key, cert: pair.cert };
402123
402426
  }
@@ -402126,9 +402429,20 @@ var require_boot_config = __commonJS({
402126
402429
  bootstrapConfig: config,
402127
402430
  dataPath,
402128
402431
  locationManager,
402129
- tlsOptions
402432
+ tlsOptions,
402433
+ tlsCert
402130
402434
  };
402131
402435
  }
402436
+ function logTlsCert(result) {
402437
+ if (!result.generated) {
402438
+ console.log(`[Phase2c] TLS cert unchanged \u2014 ${result.certPath} (leaf ${result.fingerprintSha256}, valid to ${result.validTo})`);
402439
+ return;
402440
+ }
402441
+ console.log(`[Phase2c] TLS CERTIFICATE REISSUED \u2014 reason=${result.reason}, caRotated=${result.caRotated}`);
402442
+ console.log(`[Phase2c] leaf ${result.previousFingerprintSha256 ?? "(none)"} \u2192 ${result.fingerprintSha256}`);
402443
+ console.log(`[Phase2c] valid to ${result.validTo}, names: ${result.sans.join(", ")}`);
402444
+ console.log(result.caRotated ? `[Phase2c] ACTION REQUIRED: the local CA changed. Install ${result.caCertPath} (SHA-256 ${result.caFingerprintSha256}) on every device that trusted the previous certificate.` : `[Phase2c] Local CA unchanged (${result.caFingerprintSha256}) \u2014 devices that trust ${result.caCertPath} keep working.`);
402445
+ }
402132
402446
  }
402133
402447
  });
402134
402448
 
@@ -409611,7 +409925,7 @@ var require_main4 = __commonJS({
409611
409925
  const configPath = process.env.CONFIG_PATH ?? path.join(process.env.CAMSTACK_DATA ?? path.join(process.cwd(), "camstack-data"), "config.yaml");
409612
409926
  const bootstrapConfig = (0, boot_config_1.loadBootstrapConfig)(configPath);
409613
409927
  const infra = await (0, boot_config_1.setupInfra)(configPath, bootstrapConfig);
409614
- const { dataPath, tlsOptions } = infra;
409928
+ const { dataPath, tlsOptions, tlsCert } = infra;
409615
409929
  const port = infra.bootstrapConfig.server.port;
409616
409930
  const host = infra.bootstrapConfig.server.host;
409617
409931
  const fastifyOpts = tlsOptions ? { https: tlsOptions } : {};
@@ -410360,7 +410674,7 @@ var require_main4 = __commonJS({
410360
410674
  logger.info("CamStack server listening", { meta: { protocol, host, port, trpcRegistered } });
410361
410675
  void Promise.all([resolveAdminUi(), resolveViewerUi()]);
410362
410676
  const postBoot = app.get(post_boot_service_1.PostBootService);
410363
- await postBoot.run({ port, host, dataPath, trpcRegistered });
410677
+ await postBoot.run({ port, host, dataPath, trpcRegistered, tlsCert });
410364
410678
  try {
410365
410679
  const confirm = app.get(server_update_service_1.ServerUpdateService).confirmBootHealthy();
410366
410680
  if (confirm.promoted !== null) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "camstack",
3
- "version": "1.2.37",
3
+ "version": "1.2.38",
4
4
  "description": "CLI tool for managing and running CamStack server",
5
5
  "keywords": [
6
6
  "camstack",