[object Object]

← back to Commercialrealestate

CRCP gate: multi-credential auth (CRCP_EXTRA_USERS) — add steve to main :9911

9bbc69347588c942e0881af5cbdf178eb930db04 · 2026-08-19 12:40:17 -0700 · Steve Abrams

Accept the primary CRCP_USER/CRCP_PASS plus an optional comma-separated
CRCP_EXTRA_USERS list so multiple people share one instance. Cookie check now
matches any accepted cred's token. Backward-compatible (no extras = old single
cred). Main :9911 launchd plist gets CRCP_EXTRA_USERS=steve:jef215 so steve logs
in alongside admin/DW2024!.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit 9bbc69347588c942e0881af5cbdf178eb930db04
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed Aug 19 12:40:17 2026 -0700

    CRCP gate: multi-credential auth (CRCP_EXTRA_USERS) — add steve to main :9911
    
    Accept the primary CRCP_USER/CRCP_PASS plus an optional comma-separated
    CRCP_EXTRA_USERS list so multiple people share one instance. Cookie check now
    matches any accepted cred's token. Backward-compatible (no extras = old single
    cred). Main :9911 launchd plist gets CRCP_EXTRA_USERS=steve:jef215 so steve logs
    in alongside admin/DW2024!.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 scripts/serve.js | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/scripts/serve.js b/scripts/serve.js
index 773dd38..e88dea6 100644
--- a/scripts/serve.js
+++ b/scripts/serve.js
@@ -53,19 +53,30 @@ const AUTH_PASS = process.env.CRCP_PASS || 'DW2024!';
 // automatically, and accept that cookie as an alternative to the header. Token is a stable
 // non-reversible hash of the creds (never the plaintext password), so it survives restarts.
 const crypto = require('crypto');
-const AUTH_TOKEN = crypto.createHash('sha256').update(AUTH_USER + ':' + AUTH_PASS).digest('hex');
+// Multi-credential gate (2026-08-19): accept the primary CRCP_USER/CRCP_PASS PLUS an optional
+// comma-separated CRCP_EXTRA_USERS list ("steve:jef215,foo:bar") so more than one person can log
+// into the same instance. Backward-compatible: with no extras this is exactly the old single cred.
+const GATE_CREDS = [[AUTH_USER, AUTH_PASS]];
+(process.env.CRCP_EXTRA_USERS || '').split(',').map(s => s.trim()).filter(Boolean).forEach(pair => {
+  const i = pair.indexOf(':'); if (i > 0) GATE_CREDS.push([pair.slice(0, i), pair.slice(i + 1)]);
+});
+const tokenOf = (u, p) => crypto.createHash('sha256').update(u + ':' + p).digest('hex');
+const AUTH_TOKEN = tokenOf(AUTH_USER, AUTH_PASS);           // primary cred's token (kept for compatibility)
+const AUTH_TOKENS = new Set(GATE_CREDS.map(([u, p]) => tokenOf(u, p))); // every accepted cred's cookie token
 app.get('/healthz', (req, res) => res.type('text').send('ok'));
 app.use((req, res, next) => {
   // 1) session cookie set after a prior successful Basic auth (fixes URL-creds subresource 401s)
   const cookies = req.headers.cookie || '';
-  if (cookies.split(/;\s*/).some(c => c === 'crcp_auth=' + AUTH_TOKEN)) return next();
+  const ck = cookies.split(/;\s*/).find(c => c.startsWith('crcp_auth='));
+  if (ck && AUTH_TOKENS.has(ck.slice('crcp_auth='.length))) return next();
   // 2) the standard Authorization header (Basic-auth dialog, curl, or the navigation request)
   const hdr = req.headers.authorization || '';
   const [scheme, encoded] = hdr.split(' ');
   if (scheme === 'Basic' && encoded) {
     const [u, ...rest] = Buffer.from(encoded, 'base64').toString().split(':');
-    if (u === AUTH_USER && rest.join(':') === AUTH_PASS) {
-      res.cookie('crcp_auth', AUTH_TOKEN, { httpOnly: true, sameSite: 'Lax', path: '/', maxAge: 30 * 24 * 3600 * 1000 });
+    const p = rest.join(':');
+    if (GATE_CREDS.some(([cu, cp]) => cu === u && cp === p)) {
+      res.cookie('crcp_auth', tokenOf(u, p), { httpOnly: true, sameSite: 'Lax', path: '/', maxAge: 30 * 24 * 3600 * 1000 });
       return next();
     }
   }

← c6ab3e8 gitignore data/sfr-notes.json (per-user runtime notes)  ·  back to Commercialrealestate  ·  Daily valley-pools refresh now pushes the fresh snapshot to 036e4b5 →