@lifeaitools/clauth 1.5.6 → 1.5.7

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.
@@ -739,6 +739,7 @@ function dashboardHtml(port, whitelist, isStaged = false) {
739
739
  <button class="btn-add" onclick="toggleAddService()">+ Add Service</button>
740
740
  <button class="btn-check" id="check-btn" onclick="checkAll()">⬤ Check All</button>
741
741
  <button class="btn-lock" onclick="lockVault()">🔒 Lock</button>
742
+ <button class="btn-stop" onclick="restartDaemon()" style="background:#1a2e1a;border:1px solid #166534;color:#86efac" title="Restart daemon — keeps vault unlocked">↺ Restart</button>
742
743
  <button class="btn-stop" onclick="stopDaemon()" style="background:#7f1d1d;border:1px solid #991b1b;color:#fca5a5" title="Stop daemon — password required on next start">⏹ Stop</button>
743
744
  <button class="btn-cancel" style="margin-left:auto" onclick="toggleChangePw()">Change Password</button>
744
745
  </div>
@@ -1131,6 +1132,17 @@ async function makeLive() {
1131
1132
  }
1132
1133
  }
1133
1134
 
1135
+ // ── Restart daemon (keeps boot.key — vault stays unlocked) ──
1136
+ async function restartDaemon() {
1137
+ if (!confirm("Restart the daemon?\\n\\nThe vault will stay unlocked (boot.key kept).")) return;
1138
+ const btn = document.querySelector('[onclick="restartDaemon()"]');
1139
+ if (btn) { btn.disabled = true; btn.textContent = "↺ Restarting…"; }
1140
+ try {
1141
+ await fetch(BASE + "/restart", { method: "POST" });
1142
+ } catch {}
1143
+ document.getElementById("main-view").innerHTML = '<div style="text-align:center;padding:80px 20px"><div style="font-size:3rem;margin-bottom:16px">↺</div><div style="font-size:1.1rem;color:#86efac">Restarting…</div><div style="font-size:.85rem;color:#64748b;margin-top:8px">Page will reload automatically.</div></div>';
1144
+ }
1145
+
1134
1146
  // ── Stop daemon (user-initiated — clears boot.key, requires password on restart) ──
1135
1147
  async function stopDaemon() {
1136
1148
  if (!confirm("Stop the daemon?\\n\\nCredentials will need to be re-entered on next start.")) return;
@@ -3272,6 +3284,28 @@ function createServer(initPassword, whitelist, port, tunnelHostnameInit = null,
3272
3284
  return ok(res, { status: tunnelStatus });
3273
3285
  }
3274
3286
 
3287
+ // POST /restart — spawn fresh process then exit (keeps boot.key, vault stays unlocked)
3288
+ if (method === "POST" && reqPath === "/restart") {
3289
+ ok(res, { ok: true, message: "restarting" });
3290
+ const { spawn } = await import("child_process");
3291
+ const cliEntry = path.resolve(__dirname, "../index.js");
3292
+ const childArgs = [cliEntry, "serve", "start", "--port", String(port)];
3293
+ if (password) childArgs.push("--pw", password);
3294
+ if (whitelist) childArgs.push("--services", whitelist.join(","));
3295
+ if (tunnelHostname) childArgs.push("--tunnel", tunnelHostname);
3296
+ const out = fs.openSync(LOG_FILE, "a");
3297
+ const child = spawn(process.execPath, childArgs, {
3298
+ detached: true,
3299
+ stdio: ["ignore", out, out],
3300
+ env: { ...process.env, __CLAUTH_DAEMON: "1" },
3301
+ });
3302
+ child.unref();
3303
+ stopTunnel();
3304
+ removePid();
3305
+ setTimeout(() => process.exit(0), 300);
3306
+ return;
3307
+ }
3308
+
3275
3309
  // GET|POST /shutdown (for daemon stop — programmatic, keeps boot.key)
3276
3310
  // Accept POST as well — older scripts and curl default to POST
3277
3311
  if ((method === "GET" || method === "POST") && reqPath === "/shutdown") {
@@ -4287,7 +4321,7 @@ function createServer(initPassword, whitelist, port, tunnelHostnameInit = null,
4287
4321
  // Don't count browser noise, MCP discovery probes, or OAuth probes as auth failures
4288
4322
  const isBenign = reqPath.startsWith("/.well-known/") || [
4289
4323
  "/favicon.ico", "/robots.txt", "/apple-touch-icon.png", "/apple-touch-icon-precomposed.png",
4290
- "/sse", "/mcp", "/message", "/register", "/authorize", "/token", "/shutdown",
4324
+ "/sse", "/mcp", "/message", "/register", "/authorize", "/token", "/shutdown", "/restart",
4291
4325
  ].includes(reqPath);
4292
4326
  if (isBenign) {
4293
4327
  res.writeHead(404, { "Content-Type": "application/json", ...CORS });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifeaitools/clauth",
3
- "version": "1.5.6",
3
+ "version": "1.5.7",
4
4
  "description": "Hardware-bound credential vault for the LIFEAI infrastructure stack",
5
5
  "type": "module",
6
6
  "bin": {