[object Object]

← back to Nationalrealestate

usre: scoped Basic-auth credential for the shareable Contractors browse page

ac61383a465b50fba05611de8f548f80578492ed · 2026-08-12 11:50:28 -0700 · Steve Abrams

CONTRACTORS_USER/CONTRACTORS_PASS (.env) grants access to /contractors* +
/api/contractors + shared nav chrome ONLY — never usre admin (deals/parcels/
listings/markets). Env-driven (no secret in source); no-op if unset. Verified
locally: admin=all-access, cx-cred=200 on contractors + 401 on /deals.html,
no-auth=401.

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

Files touched

Diff

commit ac61383a465b50fba05611de8f548f80578492ed
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed Aug 12 11:50:28 2026 -0700

    usre: scoped Basic-auth credential for the shareable Contractors browse page
    
    CONTRACTORS_USER/CONTRACTORS_PASS (.env) grants access to /contractors* +
    /api/contractors + shared nav chrome ONLY — never usre admin (deals/parcels/
    listings/markets). Env-driven (no secret in source); no-op if unset. Verified
    locally: admin=all-access, cx-cred=200 on contractors + 401 on /deals.html,
    no-auth=401.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 src/server/index.ts | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/src/server/index.ts b/src/server/index.ts
index 73e14aa..5137d8a 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -35,8 +35,25 @@ const AUTH_PAIRS = [
   'Scott:Russia1980',
 ].concat((process.env.BASIC_AUTH_EXTRA || '').split(',').map((s) => s.trim()).filter(Boolean));
 const ACCEPTED = new Set(AUTH_PAIRS.map((p) => 'Basic ' + Buffer.from(p).toString('base64')));
+
+// Dedicated, SCOPED credential for the shareable Contractors browse page.
+// Set CONTRACTORS_USER + CONTRACTORS_PASS in .env to enable. This login grants
+// access to /contractors* + /api/contractors + the shared nav chrome ONLY — it
+// can never reach the rest of usre admin (deals, parcels, listings, market data).
+// If the env vars are unset, behavior is identical to before (no new access).
+const CONTRACTOR_TOKEN =
+  process.env.CONTRACTORS_USER && process.env.CONTRACTORS_PASS
+    ? 'Basic ' +
+      Buffer.from(`${process.env.CONTRACTORS_USER}:${process.env.CONTRACTORS_PASS}`).toString('base64')
+    : null;
+const CONTRACTOR_ASSETS = new Set(['/contractors', '/contractors.html', '/nav-drawer.css', '/nav-drawer.js']);
+const contractorScopeAllows = (p: string) =>
+  CONTRACTOR_ASSETS.has(p) || p.startsWith('/contractors/') || p.startsWith('/api/contractors');
+
 app.use((req, res, next) => {
-  if (ACCEPTED.has(req.headers.authorization || '')) return next();
+  const auth = req.headers.authorization || '';
+  if (ACCEPTED.has(auth)) return next(); // full usre logins → everywhere
+  if (CONTRACTOR_TOKEN && auth === CONTRACTOR_TOKEN && contractorScopeAllows(req.path)) return next(); // scoped
   res.set('WWW-Authenticate', 'Basic realm="USRealEstate", charset="UTF-8"');
   return res.status(401).send('Authentication required');
 });

← ca8f556 ca_contractors: recon script + v0.18.0 (session close, TK-10  ·  back to Nationalrealestate  ·  scripts: safe usre contractor code deploy (backup+smoke+roll 095c0c2 →