[object Object]

← back to Norma Platform

feat(set-admin-password): NEW_PW_B64 input to survive shell '!' mangling

db0ecc25c58dd9b1840ae5779423d5832c23dfaa · 2026-08-28 07:22:48 -0700 · Steve Abrams

Files touched

Diff

commit db0ecc25c58dd9b1840ae5779423d5832c23dfaa
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Fri Aug 28 07:22:48 2026 -0700

    feat(set-admin-password): NEW_PW_B64 input to survive shell '!' mangling
---
 scripts/set-admin-password.mjs |  7 ++++++-
 scripts/verify-admin-hash.mjs  | 20 ++++++++++++++++++++
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/scripts/set-admin-password.mjs b/scripts/set-admin-password.mjs
index 2cf2206..2490648 100644
--- a/scripts/set-admin-password.mjs
+++ b/scripts/set-admin-password.mjs
@@ -26,7 +26,12 @@ if (!process.env.DATABASE_URL) {
 }
 
 const username = process.env.TARGET_USER || 'admin';
-const newPw = process.env.NEW_PW || 'DW2024!';
+// Prefer NEW_PW_B64 (base64) so passwords with shell-special chars like '!'
+// can't be mangled by the shell/ssh layers on the way in. Falls back to NEW_PW.
+const newPw = process.env.NEW_PW_B64
+  ? Buffer.from(process.env.NEW_PW_B64, 'base64').toString('utf8')
+  : (process.env.NEW_PW || 'DW2024!');
+console.log(`new password length: ${newPw.length} chars`);
 
 const { Client } = pg;
 const c = new Client({ connectionString: process.env.DATABASE_URL });
diff --git a/scripts/verify-admin-hash.mjs b/scripts/verify-admin-hash.mjs
new file mode 100644
index 0000000..3f81af0
--- /dev/null
+++ b/scripts/verify-admin-hash.mjs
@@ -0,0 +1,20 @@
+#!/usr/bin/env node
+// Read-only: which password does the stored admin hash actually verify against?
+import bcrypt from 'bcryptjs';
+import pg from 'pg';
+const c = new pg.Client({ connectionString: 'postgresql://dw_admin@127.0.0.1:5432/sdcc' });
+await c.connect();
+const r = await c.query(
+  'SELECT username, role, client_type, password_hash FROM tier_credentials WHERE username=$1',
+  ['admin'],
+);
+if (!r.rows.length) { console.log('no admin row'); await c.end(); process.exit(0); }
+const row = r.rows[0];
+console.log(`row: username=${row.username} role=${row.role} client_type=${row.client_type}`);
+console.log(`hash prefix: ${row.password_hash.slice(0, 20)}  (len ${row.password_hash.length})`);
+for (const pw of ['DW2024!', 'DW2024', 'TestPass123!', 'DWSecure2024!']) {
+  let ok = false;
+  try { ok = await bcrypt.compare(pw, row.password_hash); } catch (e) { ok = `ERR:${e.message}`; }
+  console.log(`  compare(${JSON.stringify(pw)}) = ${ok}`);
+}
+await c.end();

← 7c027a1 fix(set-admin-password): read .env.local first, echo DB host  ·  back to Norma Platform  ·  scripts: restore-admin-hash helper (revert a tier_credential 159c3e5 →