@lensmcp/cluster 1.16.14 → 1.16.15

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.
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../../../../libs/cluster/src/executors/gateway/runtime/server.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAkB,qBAAqB,EAAsB,MAAM,SAAS,CAAC;AAkDxH,wBAAsB,YAAY,CAChC,OAAO,EAAE,qBAAqB,EAC9B,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,CAAC,CAqNxB"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../../../../libs/cluster/src/executors/gateway/runtime/server.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAkB,qBAAqB,EAAsB,MAAM,SAAS,CAAC;AAkDxH,wBAAsB,YAAY,CAChC,OAAO,EAAE,qBAAqB,EAC9B,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,CAAC,CA0OxB"}
@@ -140,6 +140,10 @@ async function startGateway(options, context) {
140
140
  // REGISTERS its fragment here instead of fighting for :443, and the daemon HOSTS its services (spawns
141
141
  // them, model A) + its dashboard (planning/multi-workspace-gateway.md P3). Harmless for a lone gateway.
142
142
  const dashboardReapers = new Map();
143
+ // Assigned after the TLS servers are built (below) — re-mints the gateway cert with the CURRENT route
144
+ // hosts and hot-swaps it, so a workspace that registers AFTER boot gets its hostnames into the cert SANs
145
+ // (otherwise the browser sees ERR_CERT_COMMON_NAME_INVALID for the new workspace's hosts).
146
+ let refreshCert = () => { };
143
147
  let controlServer;
144
148
  try {
145
149
  controlServer = (0, control_1.startControlServer)({
@@ -151,10 +155,12 @@ async function startGateway(options, context) {
151
155
  const reap = lens.hostWorkspaceDashboard(fragment);
152
156
  if (reap)
153
157
  dashboardReapers.set(fragment.wsKey, reap);
158
+ refreshCert(); // the new workspace's hosts must join the gateway cert SANs
154
159
  },
155
160
  onUnregister: (fragment) => {
156
161
  dashboardReapers.get(fragment.wsKey)?.();
157
162
  dashboardReapers.delete(fragment.wsKey);
163
+ refreshCert();
158
164
  },
159
165
  });
160
166
  }
@@ -214,12 +220,15 @@ async function startGateway(options, context) {
214
220
  // --- TLS + listeners --------------------------------------------------------
215
221
  let pem;
216
222
  let caPath;
223
+ let mintCert;
217
224
  if (https) {
218
225
  // eslint-disable-next-line @typescript-eslint/no-require-imports
219
226
  const basicSsl = require('../../../basic-ssl');
220
227
  const cacheDir = (0, service_keys_1.gatewayCacheDir)(context.root);
221
- const hosts = routes.map((r) => r.host).filter((h) => !!h);
222
- pem = basicSsl.getCertificateSync(cacheDir, 'gateway', hosts);
228
+ // SANs = the CURRENT route hosts. `rt.routes` is rebuilt live on register, so a re-mint (refreshCert
229
+ // below) automatically includes a newly-registered workspace's hostnames.
230
+ mintCert = () => basicSsl.getCertificateSync(cacheDir, 'gateway', rt.routes.map((r) => r.host).filter((h) => !!h));
231
+ pem = mintCert();
223
232
  caPath = basicSsl.caCertPath(cacheDir);
224
233
  }
225
234
  const servers = [];
@@ -253,6 +262,18 @@ async function startGateway(options, context) {
253
262
  });
254
263
  servers.push(server);
255
264
  }
265
+ // Now that the TLS servers exist, wire the live cert refresh: on a workspace register/unregister the
266
+ // control endpoint calls this to re-mint the gateway cert with the CURRENT route hosts and hot-swap it
267
+ // into every HTTP/2 secure server (setSecureContext), so a dynamically-registered workspace's hostnames
268
+ // are covered (no ERR_CERT_COMMON_NAME_INVALID).
269
+ if (mintCert) {
270
+ refreshCert = () => {
271
+ const fresh = mintCert();
272
+ for (const s of servers) {
273
+ s.setSecureContext?.({ key: fresh, cert: fresh });
274
+ }
275
+ };
276
+ }
256
277
  console.log('[gateway] Routes:');
257
278
  for (const r of routes) {
258
279
  const dest = r.pool ? `pods@${r.pool.dir}` : r.target;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lensmcp/cluster",
3
- "version": "1.16.14",
3
+ "version": "1.16.15",
4
4
  "description": "Run your Nx workspace as a local production cluster: pods on unix sockets with true HMR, one https gateway with per-project domains, scale-from-zero, autoscale, idle-kill, local-CA TLS — observed by the LensMCP lens.",
5
5
  "main": "./index.js",
6
6
  "types": "./index.d.ts",
@@ -65,8 +65,8 @@
65
65
  }
66
66
  },
67
67
  "dependencies": {
68
- "@lensmcp/node-instrumentation": "1.16.14",
69
- "@lensmcp/nx-plugin": "1.16.14",
68
+ "@lensmcp/node-instrumentation": "1.16.15",
69
+ "@lensmcp/nx-plugin": "1.16.15",
70
70
  "fork-ts-checker-webpack-plugin": "^9.0.0",
71
71
  "glob": "^11.0.0",
72
72
  "http-proxy": "^1.18.0",