@lifeaitools/clauth 1.30.7 → 1.30.8

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.
@@ -3167,13 +3167,28 @@ function createServer(initPassword, whitelist, port, tunnelHostnameInit = null,
3167
3167
  "Access-Control-Allow-Methods": "GET, POST, OPTIONS",
3168
3168
  "Access-Control-Allow-Headers": "Content-Type, Authorization, Mcp-Session-Id, mcp-protocol-version, mcp-session-id",
3169
3169
  };
3170
- const NO_BROWSER_CORS = {
3171
- "Access-Control-Allow-Methods": "GET, POST, OPTIONS",
3172
- "Access-Control-Allow-Headers": "Content-Type, Authorization, Mcp-Session-Id, mcp-protocol-version, mcp-session-id",
3173
- };
3174
- const studioDebugRuntime = createStudioDebugRuntime({ port, logFile: LOG_FILE });
3175
-
3176
- // ── MCP SSE session tracking ──────────────────────────────
3170
+ const NO_BROWSER_CORS = {
3171
+ "Access-Control-Allow-Methods": "GET, POST, OPTIONS",
3172
+ "Access-Control-Allow-Headers": "Content-Type, Authorization, Mcp-Session-Id, mcp-protocol-version, mcp-session-id",
3173
+ };
3174
+ const studioDebugRuntime = createStudioDebugRuntime({ port, logFile: LOG_FILE });
3175
+ const isSupervisorPort = port === getSupervisorPort();
3176
+ const supervisorTestNoToken = process.env.CLAUTH_SUPERVISOR_TEST_NO_TOKEN === "1";
3177
+
3178
+ function hasSupervisorWrite(req) {
3179
+ if (validateWriteToken(req, writeSession)) return true;
3180
+ return isSupervisorPort && supervisorTestNoToken;
3181
+ }
3182
+
3183
+ function rejectSupervisorWrite(res) {
3184
+ res.writeHead(403, { "Content-Type": "application/json", ...CORS });
3185
+ return res.end(JSON.stringify({
3186
+ error: "write_token_required",
3187
+ hint: "Unlock clauth writes, or set CLAUTH_SUPERVISOR_TEST_NO_TOKEN=1 for temporary localhost-only supervisor tests.",
3188
+ }));
3189
+ }
3190
+
3191
+ // ── MCP SSE session tracking ──────────────────────────────
3177
3192
  const sseSessions = new Map(); // sessionId → { res, initialized }
3178
3193
  let sseCounter = 0;
3179
3194
 
@@ -3641,19 +3656,13 @@ function createServer(initPassword, whitelist, port, tunnelHostnameInit = null,
3641
3656
  }
3642
3657
 
3643
3658
  if (method === "POST" && reqPath === "/v1/plugins/rescan") {
3644
- if (!validateWriteToken(req, writeSession)) {
3645
- res.writeHead(403, { "Content-Type": "application/json", ...CORS });
3646
- return res.end(JSON.stringify({ error: "write_token_required" }));
3647
- }
3659
+ if (!hasSupervisorWrite(req)) return rejectSupervisorWrite(res);
3648
3660
  return ok(res, discoverPlugins());
3649
3661
  }
3650
3662
 
3651
3663
  const pluginEnableMatch = reqPath.match(/^\/v1\/plugins\/([^/]+)\/(enable|disable|test|promote)$/);
3652
3664
  if (method === "POST" && pluginEnableMatch) {
3653
- if (!validateWriteToken(req, writeSession)) {
3654
- res.writeHead(403, { "Content-Type": "application/json", ...CORS });
3655
- return res.end(JSON.stringify({ error: "write_token_required" }));
3656
- }
3665
+ if (!hasSupervisorWrite(req)) return rejectSupervisorWrite(res);
3657
3666
  const pluginId = decodeURIComponent(pluginEnableMatch[1]);
3658
3667
  const op = pluginEnableMatch[2];
3659
3668
  const result = op === "enable"
@@ -3671,10 +3680,7 @@ function createServer(initPassword, whitelist, port, tunnelHostnameInit = null,
3671
3680
 
3672
3681
  const surfaceActionMatch = reqPath.match(/^\/v1\/surfaces\/([^/]+)\/actions$/);
3673
3682
  if (method === "POST" && surfaceActionMatch) {
3674
- if (!validateWriteToken(req, writeSession)) {
3675
- res.writeHead(403, { "Content-Type": "application/json", ...CORS });
3676
- return res.end(JSON.stringify({ error: "write_token_required" }));
3677
- }
3683
+ if (!hasSupervisorWrite(req)) return rejectSupervisorWrite(res);
3678
3684
  let body;
3679
3685
  try { body = await readBody(req); } catch {
3680
3686
  res.writeHead(400, { "Content-Type": "application/json", ...CORS });
@@ -3695,10 +3701,7 @@ function createServer(initPassword, whitelist, port, tunnelHostnameInit = null,
3695
3701
 
3696
3702
  const tunnelRoutesMatch = reqPath.match(/^\/v1\/tunnels\/([^/]+)\/routes$/);
3697
3703
  if (method === "POST" && tunnelRoutesMatch) {
3698
- if (!validateWriteToken(req, writeSession)) {
3699
- res.writeHead(403, { "Content-Type": "application/json", ...CORS });
3700
- return res.end(JSON.stringify({ error: "write_token_required" }));
3701
- }
3704
+ if (!hasSupervisorWrite(req)) return rejectSupervisorWrite(res);
3702
3705
  let body;
3703
3706
  try { body = await readBody(req); } catch {
3704
3707
  res.writeHead(400, { "Content-Type": "application/json", ...CORS });
@@ -3709,10 +3712,7 @@ function createServer(initPassword, whitelist, port, tunnelHostnameInit = null,
3709
3712
 
3710
3713
  const tunnelRouteDeleteMatch = reqPath.match(/^\/v1\/tunnels\/([^/]+)\/routes\/([^/]+)$/);
3711
3714
  if (method === "DELETE" && tunnelRouteDeleteMatch) {
3712
- if (!validateWriteToken(req, writeSession)) {
3713
- res.writeHead(403, { "Content-Type": "application/json", ...CORS });
3714
- return res.end(JSON.stringify({ error: "write_token_required" }));
3715
- }
3715
+ if (!hasSupervisorWrite(req)) return rejectSupervisorWrite(res);
3716
3716
  return ok(res, removeTunnelRoute(decodeURIComponent(tunnelRouteDeleteMatch[1]), decodeURIComponent(tunnelRouteDeleteMatch[2]), "localhost"));
3717
3717
  }
3718
3718
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifeaitools/clauth",
3
- "version": "1.30.7",
3
+ "version": "1.30.8",
4
4
  "description": "Hardware-bound credential vault for the LIFEAI infrastructure stack",
5
5
  "type": "module",
6
6
  "bin": {
Binary file
Binary file
Binary file