@cryptiklemur/lattice 5.1.0 → 5.2.0
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.
- package/dist/server/daemon.js +13 -3
- package/dist/server/index.js +66 -0
- package/dist/server/tls.js +17 -2
- package/package.json +1 -1
package/dist/server/daemon.js
CHANGED
|
@@ -404,12 +404,22 @@ export async function startDaemon(portOverride, tlsOverride) {
|
|
|
404
404
|
cert: readFileSync(certs.cert),
|
|
405
405
|
key: readFileSync(certs.key),
|
|
406
406
|
};
|
|
407
|
-
log.server("TLS enabled");
|
|
407
|
+
log.server("TLS enabled (cert: %s)", certs.cert);
|
|
408
408
|
}
|
|
409
409
|
catch (err) {
|
|
410
410
|
console.error("[lattice] Failed to load TLS certs, falling back to HTTP:", err);
|
|
411
411
|
}
|
|
412
412
|
}
|
|
413
|
+
if (tlsOptions) {
|
|
414
|
+
var certsDir = join(getLatticeHome(), "certs");
|
|
415
|
+
log.server("TLS cert: %s", join(certsDir, "cert.pem"));
|
|
416
|
+
log.server("To trust the self-signed cert:");
|
|
417
|
+
log.server(" Linux: sudo cp %s /usr/local/share/ca-certificates/lattice.crt && sudo update-ca-certificates", join(certsDir, "cert.pem"));
|
|
418
|
+
log.server(" macOS: sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain %s", join(certsDir, "cert.pem"));
|
|
419
|
+
log.server(" Or use Tailscale HTTPS (no trust needed):");
|
|
420
|
+
log.server(" tailscale cert $(tailscale status --json | jq -r '.Self.DNSName' | sed 's/\\.$//')");
|
|
421
|
+
log.server(" Then copy: cp <hostname>.crt %s && cp <hostname>.key %s", join(certsDir, "cert.pem"), join(certsDir, "key.pem"));
|
|
422
|
+
}
|
|
413
423
|
var protocol = tlsOptions ? "https" : "http";
|
|
414
424
|
var httpServer = tlsOptions
|
|
415
425
|
? createHttpsServer(tlsOptions, app)
|
|
@@ -428,11 +438,11 @@ export async function startDaemon(portOverride, tlsOverride) {
|
|
|
428
438
|
log.server("Vite dev server attached (middleware mode, HMR on same port)");
|
|
429
439
|
}
|
|
430
440
|
else if (clientDir && existsSync(clientDir)) {
|
|
431
|
-
app.use(express.static(clientDir));
|
|
441
|
+
app.use(express.static(clientDir, { dotfiles: "allow" }));
|
|
432
442
|
app.get("/{*path}", function (_req, res) {
|
|
433
443
|
var indexPath = join(clientDir, "index.html");
|
|
434
444
|
if (existsSync(indexPath)) {
|
|
435
|
-
res.sendFile(indexPath);
|
|
445
|
+
res.sendFile(indexPath, { dotfiles: "allow" });
|
|
436
446
|
}
|
|
437
447
|
else {
|
|
438
448
|
res.status(404).send("Not found");
|
package/dist/server/index.js
CHANGED
|
@@ -141,6 +141,9 @@ switch (command) {
|
|
|
141
141
|
case "config":
|
|
142
142
|
runConfigInfo();
|
|
143
143
|
break;
|
|
144
|
+
case "setup-tls":
|
|
145
|
+
await runSetupTls();
|
|
146
|
+
break;
|
|
144
147
|
case "help":
|
|
145
148
|
case "--help":
|
|
146
149
|
case "-h":
|
|
@@ -269,6 +272,7 @@ function runHelp() {
|
|
|
269
272
|
console.log(" logs Tail the daemon log");
|
|
270
273
|
console.log(" open Open the UI in the browser");
|
|
271
274
|
console.log(" config Show configuration paths and settings");
|
|
275
|
+
console.log(" setup-tls Set up HTTPS (Tailscale or self-signed)");
|
|
272
276
|
console.log(" help Show this help message");
|
|
273
277
|
console.log("");
|
|
274
278
|
console.log(" Options:");
|
|
@@ -281,6 +285,68 @@ function runHelp() {
|
|
|
281
285
|
console.log(" DEBUG Enable debug logging (e.g. DEBUG=lattice:*)");
|
|
282
286
|
console.log("");
|
|
283
287
|
}
|
|
288
|
+
async function runSetupTls() {
|
|
289
|
+
var { execSync: exec } = await import("node:child_process");
|
|
290
|
+
var certsDir = join(getLatticeHome(), "certs");
|
|
291
|
+
var certPath = join(certsDir, "cert.pem");
|
|
292
|
+
var keyPath = join(certsDir, "key.pem");
|
|
293
|
+
console.log("[lattice] TLS Setup");
|
|
294
|
+
console.log("");
|
|
295
|
+
var hasTailscale = false;
|
|
296
|
+
try {
|
|
297
|
+
exec("tailscale version", { stdio: "ignore" });
|
|
298
|
+
hasTailscale = true;
|
|
299
|
+
}
|
|
300
|
+
catch { }
|
|
301
|
+
if (hasTailscale) {
|
|
302
|
+
console.log(" Tailscale detected. To use trusted Tailscale HTTPS certs:");
|
|
303
|
+
console.log("");
|
|
304
|
+
try {
|
|
305
|
+
var dnsName = exec("tailscale status --json", { encoding: "utf-8" });
|
|
306
|
+
var hostname = JSON.parse(dnsName).Self.DNSName.replace(/\.$/, "");
|
|
307
|
+
console.log(" 1. Generate cert:");
|
|
308
|
+
console.log(" sudo tailscale cert --cert-file " + certPath + " --key-file " + keyPath + " " + hostname);
|
|
309
|
+
console.log("");
|
|
310
|
+
console.log(" 2. Enable TLS and restart:");
|
|
311
|
+
console.log(" lattice restart --tls");
|
|
312
|
+
console.log("");
|
|
313
|
+
console.log(" 3. Access at:");
|
|
314
|
+
console.log(" https://" + hostname + ":" + loadConfig().port);
|
|
315
|
+
}
|
|
316
|
+
catch {
|
|
317
|
+
console.log(" 1. Run: sudo tailscale cert --cert-file " + certPath + " --key-file " + keyPath + " <your-hostname>.ts.net");
|
|
318
|
+
console.log(" 2. Run: lattice restart --tls");
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
console.log(" Tailscale not found. Using self-signed certificate.");
|
|
323
|
+
console.log("");
|
|
324
|
+
}
|
|
325
|
+
console.log("");
|
|
326
|
+
console.log(" ── Self-signed certificate ──");
|
|
327
|
+
console.log("");
|
|
328
|
+
if (existsSync(certPath)) {
|
|
329
|
+
console.log(" Cert exists: " + certPath);
|
|
330
|
+
console.log(" To regenerate: rm -rf " + certsDir + " && lattice restart --tls");
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
console.log(" No cert yet. Run 'lattice restart --tls' to auto-generate one.");
|
|
334
|
+
}
|
|
335
|
+
console.log("");
|
|
336
|
+
console.log(" To trust the self-signed cert (removes browser warnings):");
|
|
337
|
+
console.log("");
|
|
338
|
+
console.log(" Linux:");
|
|
339
|
+
console.log(" sudo cp " + certPath + " /usr/local/share/ca-certificates/lattice.crt");
|
|
340
|
+
console.log(" sudo update-ca-certificates");
|
|
341
|
+
console.log("");
|
|
342
|
+
console.log(" macOS:");
|
|
343
|
+
console.log(" sudo security add-trusted-cert -d -r trustRoot \\");
|
|
344
|
+
console.log(" -k /Library/Keychains/System.keychain " + certPath);
|
|
345
|
+
console.log("");
|
|
346
|
+
console.log(" Windows (PowerShell as admin):");
|
|
347
|
+
console.log(" Import-Certificate -FilePath " + certPath + " -CertStoreLocation Cert:\\LocalMachine\\Root");
|
|
348
|
+
console.log("");
|
|
349
|
+
}
|
|
284
350
|
async function runRestart() {
|
|
285
351
|
var pid = readPid();
|
|
286
352
|
if (pid !== null && isDaemonRunning(pid)) {
|
package/dist/server/tls.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { existsSync, mkdirSync } from "node:fs";
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { spawnSync } from "node:child_process";
|
|
4
|
+
import { networkInterfaces } from "node:os";
|
|
4
5
|
import { getLatticeHome } from "./config.js";
|
|
5
6
|
export function getCertsDir() {
|
|
6
7
|
var certsDir = join(getLatticeHome(), "certs");
|
|
@@ -33,6 +34,20 @@ export function ensureCerts() {
|
|
|
33
34
|
return { cert: certPath, key: keyPath };
|
|
34
35
|
}
|
|
35
36
|
console.log("[lattice] Generating self-signed TLS certificate...");
|
|
37
|
+
var sans = ["DNS:lattice", "DNS:localhost", "IP:127.0.0.1", "IP:::1"];
|
|
38
|
+
var ifaces = networkInterfaces();
|
|
39
|
+
for (var name in ifaces) {
|
|
40
|
+
var addrs = ifaces[name];
|
|
41
|
+
if (!addrs)
|
|
42
|
+
continue;
|
|
43
|
+
for (var i = 0; i < addrs.length; i++) {
|
|
44
|
+
if (!addrs[i].internal) {
|
|
45
|
+
sans.push("IP:" + addrs[i].address);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
var extFile = join(certsDir, "openssl-san.cnf");
|
|
50
|
+
writeFileSync(extFile, "[req]\ndistinguished_name=dn\nx509_extensions=v3\nprompt=no\n[dn]\nCN=lattice\n[v3]\nsubjectAltName=" + sans.join(",") + "\n");
|
|
36
51
|
var result = spawnSync("openssl", [
|
|
37
52
|
"req", "-x509",
|
|
38
53
|
"-newkey", "rsa:2048",
|
|
@@ -40,7 +55,7 @@ export function ensureCerts() {
|
|
|
40
55
|
"-out", certPath,
|
|
41
56
|
"-days", "365",
|
|
42
57
|
"-nodes",
|
|
43
|
-
"-
|
|
58
|
+
"-config", extFile,
|
|
44
59
|
], { encoding: "utf-8" });
|
|
45
60
|
if (result.status !== 0) {
|
|
46
61
|
throw new Error("[lattice] Failed to generate TLS certificates: " + (result.stderr || result.error?.message || "unknown error"));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cryptiklemur/lattice",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.2.0",
|
|
4
4
|
"description": "Multi-machine agentic dashboard for Claude Code. Monitor sessions, manage MCP servers and skills, orchestrate across mesh-networked nodes.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Aaron Scherer <me@aaronscherer.me>",
|