[object Object]

← back to Ventura Claw

no breakins: pull plaintext creds from login banner, add PUT /api/admin/users/:id/password rotation endpoint

817b756eaef46276ab95a7582a00e5b44527fb4a · 2026-05-06 12:11:31 -0700 · Steve

Files touched

Diff

commit 817b756eaef46276ab95a7582a00e5b44527fb4a
Author: Steve <steve@designerwallcoverings.com>
Date:   Wed May 6 12:11:31 2026 -0700

    no breakins: pull plaintext creds from login banner, add PUT /api/admin/users/:id/password rotation endpoint
---
 server/public/login.html |  3 +--
 server/server.js         | 15 +++++++++++++++
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/server/public/login.html b/server/public/login.html
index 289bf77..6314a84 100644
--- a/server/public/login.html
+++ b/server/public/login.html
@@ -40,8 +40,7 @@
   </form>
   <p style="font-family:var(--mono);font-size:10px;letter-spacing:.08em;color:var(--ink-mute);margin-top:32px;line-height:1.7;border-top:1px solid var(--rule);padding-top:20px">
     All 56 connectors pre-wired. After login your chat is connected and ready.<br>
-    <span style="color:var(--ink-faint)">Demo · admin@venturaclaw.com / admin</span><br>
-    <span style="color:var(--ink-faint)">Demo · demo@venturaclaw.com / demo</span>
+    <span style="color:var(--ink-faint)">Access by invite — contact <a href="mailto:steve@designerwallcoverings.com" style="color:inherit;text-decoration:underline">steve@designerwallcoverings.com</a> to request credentials.</span>
   </p>
 </div>
 </main>
diff --git a/server/server.js b/server/server.js
index 4424bd2..9f78c1f 100644
--- a/server/server.js
+++ b/server/server.js
@@ -1966,6 +1966,21 @@ app.delete("/api/admin/users/:id", requireAdmin, (req, res) => {
   res.json({ ok: true, removed: before - users.length });
 });
 
+// Password rotation — admin must be authenticated; can rotate own or others.
+// Body: { password: "new-strong-value" } (min 12 chars).
+// Stored as bcrypt hash; old hash is irrecoverable. Audit-logged.
+app.put("/api/admin/users/:id/password", requireAdmin, (req, res) => {
+  const id = String(req.params.id);
+  const u = users.find(x => String(x.id) === id);
+  if (!u) return res.status(404).json({ error: "user_not_found" });
+  const pw = (req.body && typeof req.body.password === "string") ? req.body.password : "";
+  if (pw.length < 12) return res.status(400).json({ error: "password_too_short", min: 12 });
+  u.password = bcrypt.hashSync(pw, 10);
+  save("users", users);
+  logEvent({ kind: "password_rotated", by: req.session.email, target: u.email });
+  res.json({ ok: true });
+});
+
 // (duplicate /api/audit removed — earlier route at line ~346 with limit + total is canonical)
 
 // Branded 404 — catches anything no other handler matched. Must come last,

← e175bc9 Add ElevenLabs as a VenturaClaw connector  ·  back to Ventura Claw  ·  sync-tokens: strip hardcoded password fallback (was leaked i 37b29cb →