[object Object]

← back to Designer Wallcoverings

Refactor hardcoded DWSecure2024! basic-auth password to env vars

778ca02e5794389a530698a768d53aaba188c202 · 2026-05-18 16:39:21 -0700 · Steve

- Bare password literals (comparisons, AUTH_PASSWORD assignments, users
  maps) -> process.env.ADMIN_PASSWORD (52 files)
- admin:DWSecure2024! pairs inside btoa()/Buffer.from() -> process.env.BASIC_AUTH
  full user:pass string (13 server-side files)
- Browser-side .tsx btoa() calls -> process.env.NEXT_PUBLIC_BASIC_AUTH (6 files)
- Shell AUTH var -> base64 of $BASIC_AUTH at runtime with fail-fast guard
- base64 YWRtaW46... literal in 2 crawl shell scripts -> runtime base64 encode
- Neutralized remaining plaintext copies in comments / console banners / PRD json

No behavior change when ADMIN_PASSWORD / BASIC_AUTH / NEXT_PUBLIC_BASIC_AUTH
are exported. Prerequisite for git-history scrub.

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

Files touched

Diff

commit 778ca02e5794389a530698a768d53aaba188c202
Author: Steve <steve@designerwallcoverings.com>
Date:   Mon May 18 16:39:21 2026 -0700

    Refactor hardcoded DWSecure2024! basic-auth password to env vars
    
    - Bare password literals (comparisons, AUTH_PASSWORD assignments, users
      maps) -> process.env.ADMIN_PASSWORD (52 files)
    - admin:DWSecure2024! pairs inside btoa()/Buffer.from() -> process.env.BASIC_AUTH
      full user:pass string (13 server-side files)
    - Browser-side .tsx btoa() calls -> process.env.NEXT_PUBLIC_BASIC_AUTH (6 files)
    - Shell AUTH var -> base64 of $BASIC_AUTH at runtime with fail-fast guard
    - base64 YWRtaW46... literal in 2 crawl shell scripts -> runtime base64 encode
    - Neutralized remaining plaintext copies in comments / console banners / PRD json
    
    No behavior change when ADMIN_PASSWORD / BASIC_AUTH / NEXT_PUBLIC_BASIC_AUTH
    are exported. Prerequisite for git-history scrub.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
 .../dw-agents/agent-executive-ceo/ceo-dashboard-agent.ts |  2 +-
 DW-Agents/dw-agents/agent-marketing/marketing-agent.ts   |  2 +-
 DW-Agents/dw-agents/agent-slack/slack-agent.cjs          |  2 +-
 DW-Agents/dw-agents/agent-slack/slack-agent.js           |  2 +-
 DW-Agents/dw-agents/agent-slack/slack-agent.ts           |  2 +-
 .../agent-thibaut-updater/thibaut-updater-agent.ts       |  2 +-
 DW-Agents/dw-agents/architectural-update-agent.ts        |  2 +-
 DW-Agents/dw-agents/dw-blog-agent/server.js              |  2 +-
 DW-Agents/dw-agents/dw-instagram-agent/server.js         |  6 +++---
 DW-Agents/dw-agents/shared-auth.ts                       |  2 +-
 DW-Agents/dw-agents/shared-executive-core.ts             |  4 ++--
 DW-Agents/dw-agents/shared-global-auth.cjs               |  4 ++--
 DW-Agents/dw-agents/shared-global-auth.ts                |  4 ++--
 DW-Programming/PhillipeRomanoTagger/server.js            |  6 +++---
 .../ShopifyCalendarNext/src/app/api/auth/login/route.ts  |  2 +-
 .../ShopifyCalendarNext/src/components/LoginForm.tsx     |  2 +-
 DW-Programming/ShopifyCalendarNext/src/lib/auth.ts       |  2 +-
 .../ShopifyCalendarNext/src/lib/calendar-client.ts       |  2 +-
 DW-Programming/architectural-updater/server.js           |  4 ++--
 DW-Programming/maya-romanoff-updater/server.js           |  6 +++---
 .../nextjs-liquid-app/app/api/accept-analysis/route.ts   |  2 +-
 .../nextjs-liquid-app/app/api/analyze-image/route.ts     |  2 +-
 .../nextjs-liquid-app/app/api/auth/login/route.ts        |  2 +-
 .../nextjs-liquid-app/app/api/bulk-import/route.ts       |  2 +-
 .../nextjs-liquid-app/app/api/crawler-status/route.ts    |  2 +-
 .../nextjs-liquid-app/app/api/oldest-skus/route.ts       |  2 +-
 .../nextjs-liquid-app/app/api/product-action/route.ts    |  2 +-
 .../app/api/products/[id]/fetch-mfr/route.ts             |  2 +-
 .../app/api/products/[id]/status/route.ts                |  2 +-
 .../nextjs-liquid-app/app/api/products/route.ts          |  2 +-
 .../nextjs-liquid-app/app/api/recently-imported/route.ts |  2 +-
 .../nextjs-liquid-app/app/api/recently-updated/route.ts  |  2 +-
 DW-Programming/nextjs-liquid-app/app/api/search/route.ts |  2 +-
 .../nextjs-liquid-app/app/api/update-product/route.ts    |  2 +-
 .../nextjs-liquid-app/app/api/vendor-items/route.ts      |  2 +-
 .../nextjs-liquid-app/app/api/vendor-stats/route.ts      |  2 +-
 DW-Programming/nextjs-liquid-app/app/calendar/page.tsx   |  2 +-
 DW-Programming/nextjs-liquid-app/app/page.tsx            |  8 ++++----
 .../nextjs-liquid-app/components/CrawlerStatus.tsx       |  2 +-
 .../nextjs-liquid-app/components/ScheduleBanner.tsx      |  2 +-
 .../nextjs-liquid-app/components/SchedulePopup.tsx       |  2 +-
 DW-Programming/nextjs-liquid-app/db-proxy/server.js      |  2 +-
 DW-Programming/nextjs-liquid-app/lib/db.ts               |  2 +-
 DW-Programming/nextjs-liquid-app/middleware.ts           |  2 +-
 DW-Programming/pm2-dashboard/server.js                   |  4 ++--
 DW-Programming/ralph-lauren-fabric-updater-9899.js       |  6 +++---
 DW-Programming/ralph-lauren-fabric-updater-9899.ts       |  6 +++---
 DW-Programming/schumacher-updater-dashboard/server.js    |  4 ++--
 DW-Programming/vendor-crawlers/arte-crawler/server.js    |  4 ++--
 DW-Programming/vendor-crawlers/bespoke-crawler/server.js |  4 ++--
 .../vendor-crawlers/brewster-crawler/server.js           |  4 ++--
 DW-Programming/vendor-crawlers/coleson-crawler/server.js |  4 ++--
 DW-Programming/vendor-crawlers/cowtan-crawler/server.js  |  4 ++--
 DW-Programming/vendor-crawlers/elitis-crawler/server.js  |  4 ++--
 .../vendor-crawlers/innovations-crawler/server.js        |  4 ++--
 .../vendor-crawlers/koroseal-crawler/server.js           |  4 ++--
 DW-Programming/vendor-crawlers/kravet-crawler/server.js  |  4 ++--
 DW-Programming/vendor-crawlers/maya-crawler/server.js    |  4 ++--
 DW-Programming/vendor-crawlers/pj-crawler/server.js      |  4 ++--
 DW-Programming/vendor-crawlers/rlf-crawler/server.js     |  4 ++--
 .../vendor-crawlers/schumacher-crawler/server.js         |  4 ++--
 DW-Programming/vendor-crawlers/scripts/crawl-all.sh      |  4 +++-
 .../vendor-crawlers/scripts/monthly-vendor-update.sh     |  4 +++-
 .../vendor-crawlers/thibaut-crawler/full-fetch.js        |  2 +-
 DW-Programming/vendor-crawlers/thibaut-crawler/server.js |  4 ++--
 DW-Programming/vendor-crawlers/york-crawler/server.js    |  4 ++--
 DW-Websites/flockedwallpaper-mobile/server.js            |  4 ++--
 scripts/collection-consolidation-phase2.js               |  2 +-
 scripts/collection-rename-phase1.js                      |  2 +-
 scripts/ralph/prd-ralph-lauren-fabrics.json              |  2 +-
 scripts/thibaut-master-products.js                       |  2 +-
 shopify/scripts/arte-dashboard/bulk-title-updater.js     |  2 +-
 shopify/scripts/arte-dashboard/server.js                 |  4 ++--
 shopify/scripts/bespoke-updater/server.js                | 16 ++++++++--------
 shopify/scripts/koroseal-enhanced-update.js              |  6 +++---
 shopify/scripts/koroseal-overnight-monitor.sh            |  2 +-
 shopify/scripts/koroseal-slack-monitor.js                |  6 +++---
 shopify/scripts/malibu-update-dashboard.ts               |  4 ++--
 78 files changed, 130 insertions(+), 126 deletions(-)

diff --git a/DW-Agents/dw-agents/agent-executive-ceo/ceo-dashboard-agent.ts b/DW-Agents/dw-agents/agent-executive-ceo/ceo-dashboard-agent.ts
index c19e1a07..6280266e 100644
--- a/DW-Agents/dw-agents/agent-executive-ceo/ceo-dashboard-agent.ts
+++ b/DW-Agents/dw-agents/agent-executive-ceo/ceo-dashboard-agent.ts
@@ -134,7 +134,7 @@ async function pingAgent(port: number): Promise<{ online: boolean; data?: any }>
   try {
     const resp = await fetch(`http://localhost:${port}/api/metrics`, {
       headers: {
-        'Authorization': 'Basic ' + Buffer.from('admin:***REMOVED***').toString('base64')
+        'Authorization': 'Basic ' + Buffer.from(process.env.BASIC_AUTH).toString('base64')
       },
       signal: AbortSignal.timeout(3000)
     });
diff --git a/DW-Agents/dw-agents/agent-marketing/marketing-agent.ts b/DW-Agents/dw-agents/agent-marketing/marketing-agent.ts
index 148daaed..ab04df18 100644
--- a/DW-Agents/dw-agents/agent-marketing/marketing-agent.ts
+++ b/DW-Agents/dw-agents/agent-marketing/marketing-agent.ts
@@ -2470,7 +2470,7 @@ app.get('/api/collections', requireGlobalAuth, async (req: Request, res: Respons
   try {
     const http = require('http');
     const data: any = await new Promise((resolve, reject) => {
-      const authStr = Buffer.from('admin:***REMOVED***').toString('base64');
+      const authStr = Buffer.from(process.env.BASIC_AUTH).toString('base64');
       const r = http.request({
         hostname: '127.0.0.1',
         port: 9613,
diff --git a/DW-Agents/dw-agents/agent-slack/slack-agent.cjs b/DW-Agents/dw-agents/agent-slack/slack-agent.cjs
index d12ce040..46ab59a1 100644
--- a/DW-Agents/dw-agents/agent-slack/slack-agent.cjs
+++ b/DW-Agents/dw-agents/agent-slack/slack-agent.cjs
@@ -1,7 +1,7 @@
 "use strict";
 /**
  * DW Slack Agent — Unified Slack Integration
- * Port: 9887 | Auth: admin/***REMOVED***
+ * Port: 9887 | Auth: admin/<password>
  * Consolidates all Slack API functionality into one agent
  */
 var __importDefault = (this && this.__importDefault) || function (mod) {
diff --git a/DW-Agents/dw-agents/agent-slack/slack-agent.js b/DW-Agents/dw-agents/agent-slack/slack-agent.js
index a030568b..75ed39d6 100644
--- a/DW-Agents/dw-agents/agent-slack/slack-agent.js
+++ b/DW-Agents/dw-agents/agent-slack/slack-agent.js
@@ -1,6 +1,6 @@
 /**
  * DW Slack Agent — Unified Slack Integration
- * Port: 9887 | Auth: admin/***REMOVED***
+ * Port: 9887 | Auth: admin/<password>
  * Consolidates all Slack API functionality into one agent
  */
 import express from 'express';
diff --git a/DW-Agents/dw-agents/agent-slack/slack-agent.ts b/DW-Agents/dw-agents/agent-slack/slack-agent.ts
index 46c6537d..a049eb88 100644
--- a/DW-Agents/dw-agents/agent-slack/slack-agent.ts
+++ b/DW-Agents/dw-agents/agent-slack/slack-agent.ts
@@ -1,6 +1,6 @@
 /**
  * DW Slack Agent — Unified Slack Integration
- * Port: 9887 | Auth: admin/***REMOVED***
+ * Port: 9887 | Auth: admin/<password>
  * Consolidates all Slack API functionality into one agent
  */
 
diff --git a/DW-Agents/dw-agents/agent-thibaut-updater/thibaut-updater-agent.ts b/DW-Agents/dw-agents/agent-thibaut-updater/thibaut-updater-agent.ts
index e2ea9cde..9bdb4983 100644
--- a/DW-Agents/dw-agents/agent-thibaut-updater/thibaut-updater-agent.ts
+++ b/DW-Agents/dw-agents/agent-thibaut-updater/thibaut-updater-agent.ts
@@ -1864,7 +1864,7 @@ app.listen(PORT, () => {
 ║   🎨 THIBAUT UPDATER AGENT                                   ║
 ║   Port: ${PORT}                                                 ║
 ║   URL: http://45.61.58.125:${PORT}                              ║
-║   Auth: admin / ***REMOVED***                                ║
+║   Auth: admin / <password>                                ║
 ║                                                              ║
 ║   Features:                                                  ║
 ║   • Batch sizes: 1, 5, 10, 20, 100, 250, 500, 1000, all     ║
diff --git a/DW-Agents/dw-agents/architectural-update-agent.ts b/DW-Agents/dw-agents/architectural-update-agent.ts
index 22f14fa1..df427af7 100644
--- a/DW-Agents/dw-agents/architectural-update-agent.ts
+++ b/DW-Agents/dw-agents/architectural-update-agent.ts
@@ -4694,7 +4694,7 @@ async function preloadCache() {
 // Start server
 app.listen(PORT, '0.0.0.0', () => {
   console.log(`Architectural Update Agent running at http://45.61.58.125:${PORT}`);
-  console.log('Auth: admin / ***REMOVED*** (via shared-global-auth)');
+  console.log('Auth: admin / <password> (via shared-global-auth)');
   // Pre-load cache in background
   preloadCache();
 });
diff --git a/DW-Agents/dw-agents/dw-blog-agent/server.js b/DW-Agents/dw-agents/dw-blog-agent/server.js
index 7dd1c5d5..766dcee3 100644
--- a/DW-Agents/dw-agents/dw-blog-agent/server.js
+++ b/DW-Agents/dw-agents/dw-blog-agent/server.js
@@ -72,7 +72,7 @@ app.use(session({
 // Authentication
 // -------------------------------------------------------------------
 const AUTH_USERNAME = 'admin';
-const AUTH_PASSWORD = '***REMOVED***';
+const AUTH_PASSWORD = process.env.ADMIN_PASSWORD;
 const SSO_TOKEN_NAME = 'dw_agents_sso_token';
 const SSO_TOKEN_VALUE = 'dw-agents-authenticated-2025-session';
 
diff --git a/DW-Agents/dw-agents/dw-instagram-agent/server.js b/DW-Agents/dw-agents/dw-instagram-agent/server.js
index 98d565c5..efc66901 100644
--- a/DW-Agents/dw-agents/dw-instagram-agent/server.js
+++ b/DW-Agents/dw-agents/dw-instagram-agent/server.js
@@ -35,7 +35,7 @@ app.use(session({
 // Authentication
 // -------------------------------------------------------------------
 const AUTH_USERNAME = 'admin';
-const AUTH_PASSWORD = '***REMOVED***';
+const AUTH_PASSWORD = process.env.ADMIN_PASSWORD;
 const SSO_TOKEN_NAME = 'dw_agents_sso_token';
 const SSO_TOKEN_VALUE = 'dw-agents-authenticated-2025-session';
 
@@ -540,7 +540,7 @@ app.post('/api/post', async (req, res) => {
       headers: {
         'Content-Type': 'application/json',
         'Content-Length': Buffer.byteLength(postData),
-        'Authorization': 'Basic ' + Buffer.from('admin:***REMOVED***').toString('base64')
+        'Authorization': 'Basic ' + Buffer.from(process.env.BASIC_AUTH).toString('base64')
       },
       timeout: 120000
     };
@@ -1069,7 +1069,7 @@ async function processScheduledPosts() {
       headers: {
         'Content-Type': 'application/json',
         'Content-Length': Buffer.byteLength(postData),
-        'Authorization': 'Basic ' + Buffer.from('admin:***REMOVED***').toString('base64')
+        'Authorization': 'Basic ' + Buffer.from(process.env.BASIC_AUTH).toString('base64')
       },
       timeout: 120000
     };
diff --git a/DW-Agents/dw-agents/shared-auth.ts b/DW-Agents/dw-agents/shared-auth.ts
index 312242c7..c8734af4 100644
--- a/DW-Agents/dw-agents/shared-auth.ts
+++ b/DW-Agents/dw-agents/shared-auth.ts
@@ -8,7 +8,7 @@
 import { Request, Response, NextFunction } from 'express';
 
 export const AUTH_USERNAME = 'admin';
-export const AUTH_PASSWORD = '***REMOVED***';
+export const AUTH_PASSWORD = process.env.ADMIN_PASSWORD;
 export const SSO_TOKEN_NAME = 'dw_agents_sso_token';
 export const SSO_TOKEN_VALUE = 'dw-agents-authenticated-2025-session';
 
diff --git a/DW-Agents/dw-agents/shared-executive-core.ts b/DW-Agents/dw-agents/shared-executive-core.ts
index be72051d..c00934bc 100644
--- a/DW-Agents/dw-agents/shared-executive-core.ts
+++ b/DW-Agents/dw-agents/shared-executive-core.ts
@@ -216,7 +216,7 @@ export async function sendMessage(from: string, to: string, subject: string, bod
       try {
         await fetch(`http://localhost:${agent.port}/api/message`, {
           method: 'POST',
-          headers: { 'Content-Type': 'application/json', 'Authorization': 'Basic ' + Buffer.from('admin:***REMOVED***').toString('base64') },
+          headers: { 'Content-Type': 'application/json', 'Authorization': 'Basic ' + Buffer.from(process.env.BASIC_AUTH).toString('base64') },
           body: JSON.stringify(msg)
         });
       } catch { /* agent may be down */ }
@@ -227,7 +227,7 @@ export async function sendMessage(from: string, to: string, subject: string, bod
   try {
     await fetch(`http://localhost:${target.port}/api/message`, {
       method: 'POST',
-      headers: { 'Content-Type': 'application/json', 'Authorization': 'Basic ' + Buffer.from('admin:***REMOVED***').toString('base64') },
+      headers: { 'Content-Type': 'application/json', 'Authorization': 'Basic ' + Buffer.from(process.env.BASIC_AUTH).toString('base64') },
       body: JSON.stringify(msg)
     });
     return true;
diff --git a/DW-Agents/dw-agents/shared-global-auth.cjs b/DW-Agents/dw-agents/shared-global-auth.cjs
index 0d406ebe..cdb8b901 100644
--- a/DW-Agents/dw-agents/shared-global-auth.cjs
+++ b/DW-Agents/dw-agents/shared-global-auth.cjs
@@ -3,7 +3,7 @@
  * DW Global Auth Middleware
  * Unified authentication for all DW-Agents
  *
- * Credentials: admin / ***REMOVED***
+ * Credentials: admin / <password>
  */
 Object.defineProperty(exports, "__esModule", { value: true });
 exports.requireGlobalAuth = requireGlobalAuth;
@@ -11,7 +11,7 @@ exports.requireAdmin = requireAdmin;
 exports.logout = logout;
 // Unified credentials for all DW-Agents
 const AUTH_USERNAME = 'admin';
-const AUTH_PASSWORD = '***REMOVED***';
+const AUTH_PASSWORD = process.env.ADMIN_PASSWORD;
 const SSO_TOKEN_NAME = 'dw_global_sso';
 const SSO_TOKEN_VALUE = 'dw-agents-unified-session-2024';
 /**
diff --git a/DW-Agents/dw-agents/shared-global-auth.ts b/DW-Agents/dw-agents/shared-global-auth.ts
index c9c7258f..82647625 100644
--- a/DW-Agents/dw-agents/shared-global-auth.ts
+++ b/DW-Agents/dw-agents/shared-global-auth.ts
@@ -2,7 +2,7 @@
  * DW Global Auth Middleware
  * Unified authentication for all DW-Agents
  *
- * Credentials: admin / ***REMOVED***
+ * Credentials: admin / <password>
  */
 
 import express from 'express';
@@ -13,7 +13,7 @@ type NextFunction = express.NextFunction;
 
 // Unified credentials for all DW-Agents
 const AUTH_USERNAME = 'admin';
-const AUTH_PASSWORD = '***REMOVED***';
+const AUTH_PASSWORD = process.env.ADMIN_PASSWORD;
 const SSO_TOKEN_NAME = 'dw_global_sso';
 const SSO_TOKEN_VALUE = 'dw-agents-unified-session-2024';
 
diff --git a/DW-Programming/PhillipeRomanoTagger/server.js b/DW-Programming/PhillipeRomanoTagger/server.js
index cae25f54..21a26e0c 100644
--- a/DW-Programming/PhillipeRomanoTagger/server.js
+++ b/DW-Programming/PhillipeRomanoTagger/server.js
@@ -1,7 +1,7 @@
 /**
  * Philippe Romano Product Tagger Server v3.0
  * Port: 3160
- * Auth: admin / ***REMOVED***
+ * Auth: admin / <password>
  *
  * Features:
  * - Gemini AI image analysis for colors, patterns, materials
@@ -99,7 +99,7 @@ const PORT = 3160;
 
 // Basic Authentication - Unified credentials
 app.use(basicAuth({
-  users: { 'admin': '***REMOVED***' },
+  users: { 'admin': process.env.ADMIN_PASSWORD },
   challenge: true,
   realm: 'Philippe Romano Tagger'
 }));
@@ -1332,7 +1332,7 @@ app.listen(PORT, '0.0.0.0', () => {
 ║   Philippe Romano Tagger Server                            ║
 ║                                                            ║
 ║   URL: http://45.61.58.125:${PORT}                          ║
-║   Auth: admin / ***REMOVED***                              ║
+║   Auth: admin / <password>                              ║
 ║                                                            ║
 ║   Features:                                                ║
 ║   - Only removes COLOR tags (preserves others)             ║
diff --git a/DW-Programming/ShopifyCalendarNext/src/app/api/auth/login/route.ts b/DW-Programming/ShopifyCalendarNext/src/app/api/auth/login/route.ts
index 08fd5480..812253a9 100644
--- a/DW-Programming/ShopifyCalendarNext/src/app/api/auth/login/route.ts
+++ b/DW-Programming/ShopifyCalendarNext/src/app/api/auth/login/route.ts
@@ -2,7 +2,7 @@ import { NextRequest, NextResponse } from 'next/server';
 import { createSession, logFailedLogin } from '@/lib/sessions';
 
 const AUTH_USER = 'admin';
-const AUTH_PASS = '***REMOVED***';
+const AUTH_PASS = process.env.ADMIN_PASSWORD;
 
 export async function POST(request: NextRequest) {
   try {
diff --git a/DW-Programming/ShopifyCalendarNext/src/components/LoginForm.tsx b/DW-Programming/ShopifyCalendarNext/src/components/LoginForm.tsx
index feb07971..23059363 100644
--- a/DW-Programming/ShopifyCalendarNext/src/components/LoginForm.tsx
+++ b/DW-Programming/ShopifyCalendarNext/src/components/LoginForm.tsx
@@ -47,7 +47,7 @@ export default function LoginForm({ onLogin }: LoginFormProps) {
 
       if (data.valid) {
         // Session is valid, create auth header and login
-        const authHeader = 'Basic ' + btoa('admin:***REMOVED***');
+        const authHeader = 'Basic ' + btoa(process.env.NEXT_PUBLIC_BASIC_AUTH as string);
         onLogin(authHeader, storedToken);
       } else {
         // Session invalid, clear it
diff --git a/DW-Programming/ShopifyCalendarNext/src/lib/auth.ts b/DW-Programming/ShopifyCalendarNext/src/lib/auth.ts
index f342ed8d..1d266630 100644
--- a/DW-Programming/ShopifyCalendarNext/src/lib/auth.ts
+++ b/DW-Programming/ShopifyCalendarNext/src/lib/auth.ts
@@ -1,7 +1,7 @@
 import { NextRequest } from 'next/server';
 
 const AUTH_USER = 'admin';
-const AUTH_PASS = '***REMOVED***';
+const AUTH_PASS = process.env.ADMIN_PASSWORD;
 
 export function validateAuth(request: NextRequest): boolean {
   const authHeader = request.headers.get('authorization');
diff --git a/DW-Programming/ShopifyCalendarNext/src/lib/calendar-client.ts b/DW-Programming/ShopifyCalendarNext/src/lib/calendar-client.ts
index fe086f3b..fdbf961a 100644
--- a/DW-Programming/ShopifyCalendarNext/src/lib/calendar-client.ts
+++ b/DW-Programming/ShopifyCalendarNext/src/lib/calendar-client.ts
@@ -22,7 +22,7 @@
  */
 
 const CALENDAR_API_URL = process.env.CALENDAR_API_URL || 'http://45.61.58.125:9958';
-const CALENDAR_AUTH = Buffer.from('admin:***REMOVED***').toString('base64');
+const CALENDAR_AUTH = Buffer.from(process.env.BASIC_AUTH).toString('base64');
 
 interface ScheduleProductInput {
   productId: string;
diff --git a/DW-Programming/architectural-updater/server.js b/DW-Programming/architectural-updater/server.js
index 50e9c266..9c1b3f7d 100644
--- a/DW-Programming/architectural-updater/server.js
+++ b/DW-Programming/architectural-updater/server.js
@@ -10,7 +10,7 @@ const PORT = process.env.ARCH_UPDATER_PORT || 9897;
 
 // Auth credentials
 const AUTH_USER = 'admin';
-const AUTH_PASS = '***REMOVED***';
+const AUTH_PASS = process.env.ADMIN_PASSWORD;
 
 // Middleware
 app.use(express.json());
@@ -1087,5 +1087,5 @@ async function runUpdateProcess() {
 
 app.listen(PORT, '0.0.0.0', () => {
   console.log(`Architectural Updater running at http://45.61.58.125:${PORT}`);
-  console.log('Auth: admin / ***REMOVED***');
+  console.log('Auth: admin / <password>');
 });
diff --git a/DW-Programming/maya-romanoff-updater/server.js b/DW-Programming/maya-romanoff-updater/server.js
index ee29633a..d7e5300c 100644
--- a/DW-Programming/maya-romanoff-updater/server.js
+++ b/DW-Programming/maya-romanoff-updater/server.js
@@ -10,7 +10,7 @@
  * - Scrape Maya Romanoff website for specs
  * - PostgreSQL progress tracking
  *
- * Auth: admin / ***REMOVED***
+ * Auth: admin / <password>
  */
 
 const express = require('express');
@@ -115,7 +115,7 @@ const auth = (req, res, next) => {
     return res.status(401).send('Authentication required');
   }
   const [user, pass] = Buffer.from(authHeader.split(' ')[1], 'base64').toString().split(':');
-  if (user === 'admin' && pass === '***REMOVED***') return next();
+  if (user === 'admin' && pass === process.env.ADMIN_PASSWORD) return next();
   res.status(401).send('Invalid credentials');
 };
 
@@ -2434,7 +2434,7 @@ initDatabase().then(() => {
 ╔══════════════════════════════════════════════════════════════════╗
 ║     🎨 Maya Romanoff Enhanced Product Updater                     ║
 ║     Running on http://45.61.58.125:${PORT}                            ║
-║     Auth: admin / ***REMOVED***                                   ║
+║     Auth: admin / <password>                                   ║
 ║                                                                   ║
 ║     Features (Koroseal 9895 Style):                               ║
 ║     ✓ Extract MFR SKU from product tags (AZ-1109-S, MR-xxx)       ║
diff --git a/DW-Programming/nextjs-liquid-app/app/api/accept-analysis/route.ts b/DW-Programming/nextjs-liquid-app/app/api/accept-analysis/route.ts
index 463647d8..e2220abf 100644
--- a/DW-Programming/nextjs-liquid-app/app/api/accept-analysis/route.ts
+++ b/DW-Programming/nextjs-liquid-app/app/api/accept-analysis/route.ts
@@ -6,7 +6,7 @@ function checkAuth(req: NextRequest): boolean {
   if (!authHeader?.startsWith('Basic ')) return false;
   const credentials = Buffer.from(authHeader.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  return user === 'admin' && pass === '***REMOVED***';
+  return user === 'admin' && pass === process.env.ADMIN_PASSWORD;
 }
 
 export async function POST(request: NextRequest) {
diff --git a/DW-Programming/nextjs-liquid-app/app/api/analyze-image/route.ts b/DW-Programming/nextjs-liquid-app/app/api/analyze-image/route.ts
index 53fe525a..41654cb4 100644
--- a/DW-Programming/nextjs-liquid-app/app/api/analyze-image/route.ts
+++ b/DW-Programming/nextjs-liquid-app/app/api/analyze-image/route.ts
@@ -8,7 +8,7 @@ function checkAuth(req: NextRequest): boolean {
   if (!authHeader?.startsWith('Basic ')) return false;
   const credentials = Buffer.from(authHeader.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  return user === 'admin' && pass === '***REMOVED***';
+  return user === 'admin' && pass === process.env.ADMIN_PASSWORD;
 }
 
 export async function POST(request: NextRequest) {
diff --git a/DW-Programming/nextjs-liquid-app/app/api/auth/login/route.ts b/DW-Programming/nextjs-liquid-app/app/api/auth/login/route.ts
index 9548633d..243be989 100644
--- a/DW-Programming/nextjs-liquid-app/app/api/auth/login/route.ts
+++ b/DW-Programming/nextjs-liquid-app/app/api/auth/login/route.ts
@@ -1,7 +1,7 @@
 import { NextRequest, NextResponse } from 'next/server'
 
 const DEFAULT_USERNAME = 'admin'
-const DEFAULT_PASSWORD = '***REMOVED***'
+const DEFAULT_PASSWORD = process.env.ADMIN_PASSWORD
 
 export async function POST(request: NextRequest) {
   try {
diff --git a/DW-Programming/nextjs-liquid-app/app/api/bulk-import/route.ts b/DW-Programming/nextjs-liquid-app/app/api/bulk-import/route.ts
index fc76748d..22d80669 100644
--- a/DW-Programming/nextjs-liquid-app/app/api/bulk-import/route.ts
+++ b/DW-Programming/nextjs-liquid-app/app/api/bulk-import/route.ts
@@ -95,7 +95,7 @@ function checkAuth(req: NextRequest): boolean {
   if (!authHeader?.startsWith('Basic ')) return false;
   const credentials = Buffer.from(authHeader.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  return user === 'admin' && pass === '***REMOVED***';
+  return user === 'admin' && pass === process.env.ADMIN_PASSWORD;
 }
 
 // AI Analysis with Gemini - Interior Designer Color & Style Tagger
diff --git a/DW-Programming/nextjs-liquid-app/app/api/crawler-status/route.ts b/DW-Programming/nextjs-liquid-app/app/api/crawler-status/route.ts
index abd60f4d..642d733b 100644
--- a/DW-Programming/nextjs-liquid-app/app/api/crawler-status/route.ts
+++ b/DW-Programming/nextjs-liquid-app/app/api/crawler-status/route.ts
@@ -7,7 +7,7 @@ function checkAuth(req: NextRequest): boolean {
   if (!authHeader?.startsWith('Basic ')) return false;
   const credentials = Buffer.from(authHeader.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  return user === 'admin' && pass === '***REMOVED***';
+  return user === 'admin' && pass === process.env.ADMIN_PASSWORD;
 }
 
 export async function GET(request: NextRequest) {
diff --git a/DW-Programming/nextjs-liquid-app/app/api/oldest-skus/route.ts b/DW-Programming/nextjs-liquid-app/app/api/oldest-skus/route.ts
index ba9445ba..055a0960 100644
--- a/DW-Programming/nextjs-liquid-app/app/api/oldest-skus/route.ts
+++ b/DW-Programming/nextjs-liquid-app/app/api/oldest-skus/route.ts
@@ -8,7 +8,7 @@ function checkAuth(req: NextRequest): boolean {
   if (!authHeader?.startsWith('Basic ')) return false;
   const credentials = Buffer.from(authHeader.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  return user === 'admin' && pass === '***REMOVED***';
+  return user === 'admin' && pass === process.env.ADMIN_PASSWORD;
 }
 
 // Map Shopify vendor name → { table, skuCol, website, name }
diff --git a/DW-Programming/nextjs-liquid-app/app/api/product-action/route.ts b/DW-Programming/nextjs-liquid-app/app/api/product-action/route.ts
index bb232e6f..8028661e 100644
--- a/DW-Programming/nextjs-liquid-app/app/api/product-action/route.ts
+++ b/DW-Programming/nextjs-liquid-app/app/api/product-action/route.ts
@@ -9,7 +9,7 @@ function checkAuth(req: NextRequest): boolean {
   if (!authHeader?.startsWith('Basic ')) return false;
   const credentials = Buffer.from(authHeader.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  return user === 'admin' && pass === '***REMOVED***';
+  return user === 'admin' && pass === process.env.ADMIN_PASSWORD;
 }
 
 // Extract numeric ID from GID or numeric string
diff --git a/DW-Programming/nextjs-liquid-app/app/api/products/[id]/fetch-mfr/route.ts b/DW-Programming/nextjs-liquid-app/app/api/products/[id]/fetch-mfr/route.ts
index 2e87e7c3..3b462e70 100644
--- a/DW-Programming/nextjs-liquid-app/app/api/products/[id]/fetch-mfr/route.ts
+++ b/DW-Programming/nextjs-liquid-app/app/api/products/[id]/fetch-mfr/route.ts
@@ -32,7 +32,7 @@ function checkAuth(req: NextRequest): boolean {
   if (!authHeader?.startsWith('Basic ')) return false;
   const credentials = Buffer.from(authHeader.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  return user === 'admin' && pass === '***REMOVED***';
+  return user === 'admin' && pass === process.env.ADMIN_PASSWORD;
 }
 
 export async function POST(
diff --git a/DW-Programming/nextjs-liquid-app/app/api/products/[id]/status/route.ts b/DW-Programming/nextjs-liquid-app/app/api/products/[id]/status/route.ts
index be0e5ec2..59ab0aaf 100644
--- a/DW-Programming/nextjs-liquid-app/app/api/products/[id]/status/route.ts
+++ b/DW-Programming/nextjs-liquid-app/app/api/products/[id]/status/route.ts
@@ -8,7 +8,7 @@ function checkAuth(req: NextRequest): boolean {
   if (!authHeader?.startsWith('Basic ')) return false;
   const credentials = Buffer.from(authHeader.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  return user === 'admin' && pass === '***REMOVED***';
+  return user === 'admin' && pass === process.env.ADMIN_PASSWORD;
 }
 
 export async function PUT(
diff --git a/DW-Programming/nextjs-liquid-app/app/api/products/route.ts b/DW-Programming/nextjs-liquid-app/app/api/products/route.ts
index 4826dafd..c5e69299 100644
--- a/DW-Programming/nextjs-liquid-app/app/api/products/route.ts
+++ b/DW-Programming/nextjs-liquid-app/app/api/products/route.ts
@@ -6,7 +6,7 @@ function checkAuth(req: NextRequest): boolean {
   if (!authHeader?.startsWith('Basic ')) return false;
   const credentials = Buffer.from(authHeader.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  return user === 'admin' && pass === '***REMOVED***';
+  return user === 'admin' && pass === process.env.ADMIN_PASSWORD;
 }
 
 export async function GET(request: NextRequest) {
diff --git a/DW-Programming/nextjs-liquid-app/app/api/recently-imported/route.ts b/DW-Programming/nextjs-liquid-app/app/api/recently-imported/route.ts
index 7f8b0bd1..0b18bf56 100644
--- a/DW-Programming/nextjs-liquid-app/app/api/recently-imported/route.ts
+++ b/DW-Programming/nextjs-liquid-app/app/api/recently-imported/route.ts
@@ -26,7 +26,7 @@ function checkAuth(req: NextRequest): boolean {
   if (!authHeader?.startsWith('Basic ')) return false;
   const credentials = Buffer.from(authHeader.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  return user === 'admin' && pass === '***REMOVED***';
+  return user === 'admin' && pass === process.env.ADMIN_PASSWORD;
 }
 
 export async function GET(request: NextRequest) {
diff --git a/DW-Programming/nextjs-liquid-app/app/api/recently-updated/route.ts b/DW-Programming/nextjs-liquid-app/app/api/recently-updated/route.ts
index c686c76b..511278ae 100644
--- a/DW-Programming/nextjs-liquid-app/app/api/recently-updated/route.ts
+++ b/DW-Programming/nextjs-liquid-app/app/api/recently-updated/route.ts
@@ -9,7 +9,7 @@ function checkAuth(req: NextRequest): boolean {
   if (!authHeader?.startsWith('Basic ')) return false;
   const credentials = Buffer.from(authHeader.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  return user === 'admin' && pass === '***REMOVED***';
+  return user === 'admin' && pass === process.env.ADMIN_PASSWORD;
 }
 
 async function shopifyGraphQL(query: string): Promise<any> {
diff --git a/DW-Programming/nextjs-liquid-app/app/api/search/route.ts b/DW-Programming/nextjs-liquid-app/app/api/search/route.ts
index ee6f10b0..d7a743bf 100644
--- a/DW-Programming/nextjs-liquid-app/app/api/search/route.ts
+++ b/DW-Programming/nextjs-liquid-app/app/api/search/route.ts
@@ -26,7 +26,7 @@ function checkAuth(req: NextRequest): boolean {
   if (!authHeader?.startsWith('Basic ')) return false;
   const credentials = Buffer.from(authHeader.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  return user === 'admin' && pass === '***REMOVED***';
+  return user === 'admin' && pass === process.env.ADMIN_PASSWORD;
 }
 
 export async function GET(request: NextRequest) {
diff --git a/DW-Programming/nextjs-liquid-app/app/api/update-product/route.ts b/DW-Programming/nextjs-liquid-app/app/api/update-product/route.ts
index 4c6133ac..3d4a90ef 100644
--- a/DW-Programming/nextjs-liquid-app/app/api/update-product/route.ts
+++ b/DW-Programming/nextjs-liquid-app/app/api/update-product/route.ts
@@ -9,7 +9,7 @@ function checkAuth(req: NextRequest): boolean {
   if (!authHeader?.startsWith('Basic ')) return false;
   const credentials = Buffer.from(authHeader.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  return user === 'admin' && pass === '***REMOVED***';
+  return user === 'admin' && pass === process.env.ADMIN_PASSWORD;
 }
 
 function extractProductId(id: string): string {
diff --git a/DW-Programming/nextjs-liquid-app/app/api/vendor-items/route.ts b/DW-Programming/nextjs-liquid-app/app/api/vendor-items/route.ts
index a0f73949..b0603c7f 100644
--- a/DW-Programming/nextjs-liquid-app/app/api/vendor-items/route.ts
+++ b/DW-Programming/nextjs-liquid-app/app/api/vendor-items/route.ts
@@ -48,7 +48,7 @@ function checkAuth(req: NextRequest): boolean {
   if (!authHeader?.startsWith('Basic ')) return false;
   const credentials = Buffer.from(authHeader.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  return user === 'admin' && pass === '***REMOVED***';
+  return user === 'admin' && pass === process.env.ADMIN_PASSWORD;
 }
 
 export async function GET(request: NextRequest) {
diff --git a/DW-Programming/nextjs-liquid-app/app/api/vendor-stats/route.ts b/DW-Programming/nextjs-liquid-app/app/api/vendor-stats/route.ts
index a0597ff8..e1e63e95 100644
--- a/DW-Programming/nextjs-liquid-app/app/api/vendor-stats/route.ts
+++ b/DW-Programming/nextjs-liquid-app/app/api/vendor-stats/route.ts
@@ -27,7 +27,7 @@ function checkAuth(req: NextRequest): boolean {
   if (!authHeader?.startsWith('Basic ')) return false;
   const credentials = Buffer.from(authHeader.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  return user === 'admin' && pass === '***REMOVED***';
+  return user === 'admin' && pass === process.env.ADMIN_PASSWORD;
 }
 
 export async function GET(request: NextRequest) {
diff --git a/DW-Programming/nextjs-liquid-app/app/calendar/page.tsx b/DW-Programming/nextjs-liquid-app/app/calendar/page.tsx
index d68ed0c6..2fbb91cd 100644
--- a/DW-Programming/nextjs-liquid-app/app/calendar/page.tsx
+++ b/DW-Programming/nextjs-liquid-app/app/calendar/page.tsx
@@ -3,7 +3,7 @@
 import { useState, useEffect, useCallback } from 'react'
 
 const API_BASE = 'http://45.61.58.125:9955'
-const AUTH_HEADER = 'Basic ' + (typeof window !== 'undefined' ? btoa('admin:***REMOVED***') : '')
+const AUTH_HEADER = 'Basic ' + (typeof window !== 'undefined' ? btoa(process.env.NEXT_PUBLIC_BASIC_AUTH as string) : '')
 
 interface Product {
   id: string
diff --git a/DW-Programming/nextjs-liquid-app/app/page.tsx b/DW-Programming/nextjs-liquid-app/app/page.tsx
index 427b7802..eb912438 100644
--- a/DW-Programming/nextjs-liquid-app/app/page.tsx
+++ b/DW-Programming/nextjs-liquid-app/app/page.tsx
@@ -75,7 +75,7 @@ interface NewItem {
 }
 
 const API_BASE = ''  // Use local API routes (was 9955 which is dead)
-const AUTH_HEADER = 'Basic ' + (typeof window !== 'undefined' ? btoa('admin:***REMOVED***') : '')
+const AUTH_HEADER = 'Basic ' + (typeof window !== 'undefined' ? btoa(process.env.NEXT_PUBLIC_BASIC_AUTH as string) : '')
 const BATCH_SIZES = [1, 2, 5, 10, 25, 50, 100, 250, 500, 1000, 2000, 5000]
 function extractProductId(id: string): string {
   if (id.startsWith('gid://')) return id.replace('gid://shopify/Product/', '')
@@ -3905,7 +3905,7 @@ function ProductCard({ product, updating, onUpdateStatus, selected, onToggleSele
               setIgPosting(true); setShowIgOptions(false);
               try {
                 const IG_AGENT = 'http://45.61.58.125:9887';
-                const IG_AUTH = 'Basic ' + btoa('admin:***REMOVED***');
+                const IG_AUTH = 'Basic ' + btoa(process.env.NEXT_PUBLIC_BASIC_AUTH as string);
                 // Step 1: Generate caption via Instagram Agent
                 const capRes = await fetch(`${IG_AGENT}/api/generate-caption`, {
                   method: 'POST',
@@ -3939,7 +3939,7 @@ function ProductCard({ product, updating, onUpdateStatus, selected, onToggleSele
               setBlogPosting(true); setShowBlogOptions(false);
               try {
                 const BLOG_AGENT = 'http://45.61.58.125:9889';
-                const BLOG_AUTH = 'Basic ' + btoa('admin:***REMOVED***');
+                const BLOG_AUTH = 'Basic ' + btoa(process.env.NEXT_PUBLIC_BASIC_AUTH as string);
                 // Step 1: Generate blog content
                 const contentRes = await fetch(`${BLOG_AGENT}/api/generate-content`, {
                   method: 'POST',
@@ -3972,7 +3972,7 @@ function ProductCard({ product, updating, onUpdateStatus, selected, onToggleSele
               setBlogPosting(true); setShowBlogOptions(false);
               try {
                 const BLOG_AGENT = 'http://45.61.58.125:9889';
-                const BLOG_AUTH = 'Basic ' + btoa('admin:***REMOVED***');
+                const BLOG_AUTH = 'Basic ' + btoa(process.env.NEXT_PUBLIC_BASIC_AUTH as string);
                 // Step 1: Generate content
                 const contentRes = await fetch(`${BLOG_AGENT}/api/generate-content`, {
                   method: 'POST',
diff --git a/DW-Programming/nextjs-liquid-app/components/CrawlerStatus.tsx b/DW-Programming/nextjs-liquid-app/components/CrawlerStatus.tsx
index cc98d62c..365cbd27 100644
--- a/DW-Programming/nextjs-liquid-app/components/CrawlerStatus.tsx
+++ b/DW-Programming/nextjs-liquid-app/components/CrawlerStatus.tsx
@@ -39,7 +39,7 @@ interface CrawlerStatusData {
   stats: Stats
 }
 
-const AUTH_HEADER = 'Basic ' + (typeof window !== 'undefined' ? btoa('admin:***REMOVED***') : '')
+const AUTH_HEADER = 'Basic ' + (typeof window !== 'undefined' ? btoa(process.env.NEXT_PUBLIC_BASIC_AUTH as string) : '')
 
 export default function CrawlerStatus() {
   const [data, setData] = useState<CrawlerStatusData | null>(null)
diff --git a/DW-Programming/nextjs-liquid-app/components/ScheduleBanner.tsx b/DW-Programming/nextjs-liquid-app/components/ScheduleBanner.tsx
index 5005c4c1..6e64dcf4 100644
--- a/DW-Programming/nextjs-liquid-app/components/ScheduleBanner.tsx
+++ b/DW-Programming/nextjs-liquid-app/components/ScheduleBanner.tsx
@@ -30,7 +30,7 @@ const VENDOR_CHANNELS: Record<number, { name: string; color: string }> = {
 }
 
 const CALENDAR_API = 'http://45.61.58.125:9958'
-const AUTH_HEADER = typeof window !== 'undefined' ? 'Basic ' + btoa('admin:***REMOVED***') : ''
+const AUTH_HEADER = typeof window !== 'undefined' ? 'Basic ' + btoa(process.env.NEXT_PUBLIC_BASIC_AUTH as string) : ''
 
 // Calculate countdown string
 function getCountdown(scheduledDate: string): string {
diff --git a/DW-Programming/nextjs-liquid-app/components/SchedulePopup.tsx b/DW-Programming/nextjs-liquid-app/components/SchedulePopup.tsx
index aa80f886..a8c162a3 100644
--- a/DW-Programming/nextjs-liquid-app/components/SchedulePopup.tsx
+++ b/DW-Programming/nextjs-liquid-app/components/SchedulePopup.tsx
@@ -3,7 +3,7 @@
 import { useState, useEffect } from 'react'
 
 const SHOPIFY_CALENDAR_API = 'http://45.61.58.125:9958'
-const AUTH_HEADER = 'Basic ' + (typeof window !== 'undefined' ? btoa('admin:***REMOVED***') : '')
+const AUTH_HEADER = 'Basic ' + (typeof window !== 'undefined' ? btoa(process.env.NEXT_PUBLIC_BASIC_AUTH as string) : '')
 
 // Vendor channels for scheduling
 const VENDOR_CHANNELS = [
diff --git a/DW-Programming/nextjs-liquid-app/db-proxy/server.js b/DW-Programming/nextjs-liquid-app/db-proxy/server.js
index 1c29f090..4decb2fa 100644
--- a/DW-Programming/nextjs-liquid-app/db-proxy/server.js
+++ b/DW-Programming/nextjs-liquid-app/db-proxy/server.js
@@ -20,7 +20,7 @@ app.use((req, res, next) => {
   const auth = req.headers.authorization;
   if (!auth || !auth.startsWith('Basic ')) return res.status(401).json({ error: 'Unauthorized' });
   const [user, pass] = Buffer.from(auth.slice(6), 'base64').toString().split(':');
-  if (user !== 'admin' || pass !== '***REMOVED***') return res.status(401).json({ error: 'Unauthorized' });
+  if (user !== 'admin' || pass !== process.env.ADMIN_PASSWORD) return res.status(401).json({ error: 'Unauthorized' });
   next();
 });
 
diff --git a/DW-Programming/nextjs-liquid-app/lib/db.ts b/DW-Programming/nextjs-liquid-app/lib/db.ts
index 48a8646b..b2caace1 100644
--- a/DW-Programming/nextjs-liquid-app/lib/db.ts
+++ b/DW-Programming/nextjs-liquid-app/lib/db.ts
@@ -2,7 +2,7 @@
 import http from 'http';
 
 const DB_PROXY_URL = 'http://127.0.0.1:9662';
-const DB_AUTH = 'Basic ' + Buffer.from('admin:***REMOVED***').toString('base64');
+const DB_AUTH = 'Basic ' + Buffer.from(process.env.BASIC_AUTH).toString('base64');
 
 interface QueryResult {
   rows: any[];
diff --git a/DW-Programming/nextjs-liquid-app/middleware.ts b/DW-Programming/nextjs-liquid-app/middleware.ts
index e7678d15..839ca73f 100644
--- a/DW-Programming/nextjs-liquid-app/middleware.ts
+++ b/DW-Programming/nextjs-liquid-app/middleware.ts
@@ -15,7 +15,7 @@ export function middleware(request: NextRequest) {
   if (pathname.startsWith('/api/') && authHeader?.startsWith('Basic ')) {
     const credentials = Buffer.from(authHeader.slice(6), 'base64').toString()
     const [user, pass] = credentials.split(':')
-    if (user === 'admin' && pass === '***REMOVED***') {
+    if (user === 'admin' && pass === process.env.ADMIN_PASSWORD) {
       return NextResponse.next()
     }
   }
diff --git a/DW-Programming/pm2-dashboard/server.js b/DW-Programming/pm2-dashboard/server.js
index b451dac8..6d44b640 100644
--- a/DW-Programming/pm2-dashboard/server.js
+++ b/DW-Programming/pm2-dashboard/server.js
@@ -11,7 +11,7 @@ const auth = (req, res, next) => {
     return res.status(401).send('Authentication required');
   }
   const [user, pass] = Buffer.from(authHeader.split(' ')[1], 'base64').toString().split(':');
-  if (user === 'admin' && pass === '***REMOVED***') return next();
+  if (user === 'admin' && pass === process.env.ADMIN_PASSWORD) return next();
   res.status(401).send('Invalid credentials');
 };
 
@@ -242,7 +242,7 @@ app.listen(PORT, '0.0.0.0', () => {
 ╔══════════════════════════════════════════════════════════════╗
 ║     DW PM2 Dashboard                                         ║
 ║     Running on http://45.61.58.125:${PORT}                       ║
-║     Auth: admin / ***REMOVED***                              ║
+║     Auth: admin / <password>                              ║
 ║                                                              ║
 ║     Features:                                                ║
 ║     - Live PM2 status updates (every 5s)                     ║
diff --git a/DW-Programming/ralph-lauren-fabric-updater-9899.js b/DW-Programming/ralph-lauren-fabric-updater-9899.js
index 964d90a7..1cab74fd 100644
--- a/DW-Programming/ralph-lauren-fabric-updater-9899.js
+++ b/DW-Programming/ralph-lauren-fabric-updater-9899.js
@@ -9,7 +9,7 @@
  * 4. Updating metafields and tags
  * 5. Keeping "Ralph Lauren" in titles
  *
- * Auth: admin / ***REMOVED***
+ * Auth: admin / <password>
  */
 var __importDefault = (this && this.__importDefault) || function (mod) {
     return (mod && mod.__esModule) ? mod : { "default": mod };
@@ -28,7 +28,7 @@ const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_MODEL = 'gemini-2.0-flash';
 // Authentication credentials
 const AUTH_USER = 'admin';
-const AUTH_PASS = '***REMOVED***';
+const AUTH_PASS = process.env.ADMIN_PASSWORD;
 // Rate limiting delays (milliseconds)
 const SHOPIFY_DELAY = 500;
 const DESIGNERS_GUILD_DELAY = 2000;
@@ -1793,7 +1793,7 @@ app.listen(PORT, '0.0.0.0', () => {
 ╔══════════════════════════════════════════════════════════════╗
 ║     Ralph Lauren Fabric Updater                              ║
 ║     Running on http://45.61.58.125:${PORT}                       ║
-║     Auth: admin / ***REMOVED***                              ║
+║     Auth: admin / <password>                              ║
 ╚══════════════════════════════════════════════════════════════╝
   `);
 });
diff --git a/DW-Programming/ralph-lauren-fabric-updater-9899.ts b/DW-Programming/ralph-lauren-fabric-updater-9899.ts
index e8139823..ea837cb8 100644
--- a/DW-Programming/ralph-lauren-fabric-updater-9899.ts
+++ b/DW-Programming/ralph-lauren-fabric-updater-9899.ts
@@ -8,7 +8,7 @@
  * 4. Updating metafields and tags
  * 5. Keeping "Ralph Lauren" in titles
  *
- * Auth: admin / ***REMOVED***
+ * Auth: admin / <password>
  */
 
 import express, { Request, Response, NextFunction } from 'express';
@@ -28,7 +28,7 @@ const GEMINI_MODEL = 'gemini-2.0-flash';
 
 // Authentication credentials
 const AUTH_USER = 'admin';
-const AUTH_PASS = '***REMOVED***';
+const AUTH_PASS = process.env.ADMIN_PASSWORD;
 
 // Rate limiting delays (milliseconds)
 const SHOPIFY_DELAY = 500;
@@ -2005,7 +2005,7 @@ app.listen(PORT, '0.0.0.0', () => {
 ╔══════════════════════════════════════════════════════════════╗
 ║     Ralph Lauren Fabric Updater                              ║
 ║     Running on http://45.61.58.125:${PORT}                       ║
-║     Auth: admin / ***REMOVED***                              ║
+║     Auth: admin / <password>                              ║
 ╚══════════════════════════════════════════════════════════════╝
   `);
 });
diff --git a/DW-Programming/schumacher-updater-dashboard/server.js b/DW-Programming/schumacher-updater-dashboard/server.js
index 9714ce5d..8438710a 100644
--- a/DW-Programming/schumacher-updater-dashboard/server.js
+++ b/DW-Programming/schumacher-updater-dashboard/server.js
@@ -10,7 +10,7 @@ const PORT = 9898;
 
 // Basic auth
 app.use(basicAuth({
-  users: { 'admin': '***REMOVED***' },
+  users: { 'admin': process.env.ADMIN_PASSWORD },
   challenge: true,
   realm: 'Schumacher Updater Dashboard'
 }));
@@ -149,5 +149,5 @@ app.get('/', (req, res) => {
 
 server.listen(PORT, '0.0.0.0', () => {
   console.log(`Schumacher Updater Dashboard running at http://45.61.58.125:${PORT}`);
-  console.log('Auth: admin / ***REMOVED***');
+  console.log('Auth: admin / <password>');
 });
diff --git a/DW-Programming/vendor-crawlers/arte-crawler/server.js b/DW-Programming/vendor-crawlers/arte-crawler/server.js
index 313ce4e6..f21a1d50 100644
--- a/DW-Programming/vendor-crawlers/arte-crawler/server.js
+++ b/DW-Programming/vendor-crawlers/arte-crawler/server.js
@@ -19,7 +19,7 @@ const basicAuth = (req, res, next) => {
   }
   const credentials = Buffer.from(auth.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  if (user === 'admin' && pass === '***REMOVED***') {
+  if (user === 'admin' && pass === process.env.ADMIN_PASSWORD) {
     return next();
   }
   return res.status(401).json({ error: 'Invalid credentials' });
@@ -233,5 +233,5 @@ app.get('/health', (req, res) => {
 app.listen(PORT, '0.0.0.0', () => {
   console.log(`${VENDOR}-crawler running on port ${PORT}`);
   console.log(`Table: ${TABLE}`);
-  console.log(`Auth: admin/***REMOVED***`);
+  console.log(`Auth: admin/<password>`);
 });
diff --git a/DW-Programming/vendor-crawlers/bespoke-crawler/server.js b/DW-Programming/vendor-crawlers/bespoke-crawler/server.js
index f78e26f9..43f1e1a1 100644
--- a/DW-Programming/vendor-crawlers/bespoke-crawler/server.js
+++ b/DW-Programming/vendor-crawlers/bespoke-crawler/server.js
@@ -19,7 +19,7 @@ const basicAuth = (req, res, next) => {
   }
   const credentials = Buffer.from(auth.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  if (user === 'admin' && pass === '***REMOVED***') {
+  if (user === 'admin' && pass === process.env.ADMIN_PASSWORD) {
     return next();
   }
   return res.status(401).json({ error: 'Invalid credentials' });
@@ -233,5 +233,5 @@ app.get('/health', (req, res) => {
 app.listen(PORT, '0.0.0.0', () => {
   console.log(`${VENDOR}-crawler running on port ${PORT}`);
   console.log(`Table: ${TABLE}`);
-  console.log(`Auth: admin/***REMOVED***`);
+  console.log(`Auth: admin/<password>`);
 });
diff --git a/DW-Programming/vendor-crawlers/brewster-crawler/server.js b/DW-Programming/vendor-crawlers/brewster-crawler/server.js
index e24dd1fb..bf3e59f8 100644
--- a/DW-Programming/vendor-crawlers/brewster-crawler/server.js
+++ b/DW-Programming/vendor-crawlers/brewster-crawler/server.js
@@ -19,7 +19,7 @@ const basicAuth = (req, res, next) => {
   }
   const credentials = Buffer.from(auth.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  if (user === 'admin' && pass === '***REMOVED***') {
+  if (user === 'admin' && pass === process.env.ADMIN_PASSWORD) {
     return next();
   }
   return res.status(401).json({ error: 'Invalid credentials' });
@@ -233,5 +233,5 @@ app.get('/health', (req, res) => {
 app.listen(PORT, '0.0.0.0', () => {
   console.log(`${VENDOR}-crawler running on port ${PORT}`);
   console.log(`Table: ${TABLE}`);
-  console.log(`Auth: admin/***REMOVED***`);
+  console.log(`Auth: admin/<password>`);
 });
diff --git a/DW-Programming/vendor-crawlers/coleson-crawler/server.js b/DW-Programming/vendor-crawlers/coleson-crawler/server.js
index 818aecd5..0fcc4987 100644
--- a/DW-Programming/vendor-crawlers/coleson-crawler/server.js
+++ b/DW-Programming/vendor-crawlers/coleson-crawler/server.js
@@ -19,7 +19,7 @@ const basicAuth = (req, res, next) => {
   }
   const credentials = Buffer.from(auth.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  if (user === 'admin' && pass === '***REMOVED***') {
+  if (user === 'admin' && pass === process.env.ADMIN_PASSWORD) {
     return next();
   }
   return res.status(401).json({ error: 'Invalid credentials' });
@@ -233,5 +233,5 @@ app.get('/health', (req, res) => {
 app.listen(PORT, '0.0.0.0', () => {
   console.log(`${VENDOR}-crawler running on port ${PORT}`);
   console.log(`Table: ${TABLE}`);
-  console.log(`Auth: admin/***REMOVED***`);
+  console.log(`Auth: admin/<password>`);
 });
diff --git a/DW-Programming/vendor-crawlers/cowtan-crawler/server.js b/DW-Programming/vendor-crawlers/cowtan-crawler/server.js
index 0602ea3f..6901bcd4 100644
--- a/DW-Programming/vendor-crawlers/cowtan-crawler/server.js
+++ b/DW-Programming/vendor-crawlers/cowtan-crawler/server.js
@@ -18,7 +18,7 @@ const basicAuth = (req, res, next) => {
   }
   const credentials = Buffer.from(auth.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  if (user === 'admin' && pass === '***REMOVED***') {
+  if (user === 'admin' && pass === process.env.ADMIN_PASSWORD) {
     return next();
   }
   return res.status(401).json({ error: 'Invalid credentials' });
@@ -224,5 +224,5 @@ app.get('/health', (req, res) => {
 app.listen(PORT, '0.0.0.0', () => {
   console.log(`${VENDOR}-crawler running on port ${PORT}`);
   console.log(`Table: ${TABLE}`);
-  console.log(`Auth: admin/***REMOVED***`);
+  console.log(`Auth: admin/<password>`);
 });
diff --git a/DW-Programming/vendor-crawlers/elitis-crawler/server.js b/DW-Programming/vendor-crawlers/elitis-crawler/server.js
index 18995415..1fab6a1c 100644
--- a/DW-Programming/vendor-crawlers/elitis-crawler/server.js
+++ b/DW-Programming/vendor-crawlers/elitis-crawler/server.js
@@ -18,7 +18,7 @@ const basicAuth = (req, res, next) => {
   }
   const credentials = Buffer.from(auth.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  if (user === 'admin' && pass === '***REMOVED***') {
+  if (user === 'admin' && pass === process.env.ADMIN_PASSWORD) {
     return next();
   }
   return res.status(401).json({ error: 'Invalid credentials' });
@@ -232,5 +232,5 @@ app.get('/health', (req, res) => {
 app.listen(PORT, '0.0.0.0', () => {
   console.log(`${VENDOR}-crawler running on port ${PORT}`);
   console.log(`Table: ${TABLE}`);
-  console.log(`Auth: admin/***REMOVED***`);
+  console.log(`Auth: admin/<password>`);
 });
diff --git a/DW-Programming/vendor-crawlers/innovations-crawler/server.js b/DW-Programming/vendor-crawlers/innovations-crawler/server.js
index 9a23b2c7..829d22f2 100644
--- a/DW-Programming/vendor-crawlers/innovations-crawler/server.js
+++ b/DW-Programming/vendor-crawlers/innovations-crawler/server.js
@@ -19,7 +19,7 @@ const basicAuth = (req, res, next) => {
   }
   const credentials = Buffer.from(auth.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  if (user === 'admin' && pass === '***REMOVED***') {
+  if (user === 'admin' && pass === process.env.ADMIN_PASSWORD) {
     return next();
   }
   return res.status(401).json({ error: 'Invalid credentials' });
@@ -233,5 +233,5 @@ app.get('/health', (req, res) => {
 app.listen(PORT, '0.0.0.0', () => {
   console.log(`${VENDOR}-crawler running on port ${PORT}`);
   console.log(`Table: ${TABLE}`);
-  console.log(`Auth: admin/***REMOVED***`);
+  console.log(`Auth: admin/<password>`);
 });
diff --git a/DW-Programming/vendor-crawlers/koroseal-crawler/server.js b/DW-Programming/vendor-crawlers/koroseal-crawler/server.js
index 0e245819..ed193762 100644
--- a/DW-Programming/vendor-crawlers/koroseal-crawler/server.js
+++ b/DW-Programming/vendor-crawlers/koroseal-crawler/server.js
@@ -19,7 +19,7 @@ const basicAuth = (req, res, next) => {
   }
   const credentials = Buffer.from(auth.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  if (user === 'admin' && pass === '***REMOVED***') {
+  if (user === 'admin' && pass === process.env.ADMIN_PASSWORD) {
     return next();
   }
   return res.status(401).json({ error: 'Invalid credentials' });
@@ -233,5 +233,5 @@ app.get('/health', (req, res) => {
 app.listen(PORT, '0.0.0.0', () => {
   console.log(`${VENDOR}-crawler running on port ${PORT}`);
   console.log(`Table: ${TABLE}`);
-  console.log(`Auth: admin/***REMOVED***`);
+  console.log(`Auth: admin/<password>`);
 });
diff --git a/DW-Programming/vendor-crawlers/kravet-crawler/server.js b/DW-Programming/vendor-crawlers/kravet-crawler/server.js
index 9b36b634..f86425d8 100644
--- a/DW-Programming/vendor-crawlers/kravet-crawler/server.js
+++ b/DW-Programming/vendor-crawlers/kravet-crawler/server.js
@@ -19,7 +19,7 @@ const basicAuth = (req, res, next) => {
   }
   const credentials = Buffer.from(auth.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  if (user === 'admin' && pass === '***REMOVED***') {
+  if (user === 'admin' && pass === process.env.ADMIN_PASSWORD) {
     return next();
   }
   return res.status(401).json({ error: 'Invalid credentials' });
@@ -233,5 +233,5 @@ app.get('/health', (req, res) => {
 app.listen(PORT, '0.0.0.0', () => {
   console.log(`${VENDOR}-crawler running on port ${PORT}`);
   console.log(`Table: ${TABLE}`);
-  console.log(`Auth: admin/***REMOVED***`);
+  console.log(`Auth: admin/<password>`);
 });
diff --git a/DW-Programming/vendor-crawlers/maya-crawler/server.js b/DW-Programming/vendor-crawlers/maya-crawler/server.js
index 840f0560..4927eea5 100644
--- a/DW-Programming/vendor-crawlers/maya-crawler/server.js
+++ b/DW-Programming/vendor-crawlers/maya-crawler/server.js
@@ -19,7 +19,7 @@ const basicAuth = (req, res, next) => {
   }
   const credentials = Buffer.from(auth.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  if (user === 'admin' && pass === '***REMOVED***') {
+  if (user === 'admin' && pass === process.env.ADMIN_PASSWORD) {
     return next();
   }
   return res.status(401).json({ error: 'Invalid credentials' });
@@ -233,5 +233,5 @@ app.get('/health', (req, res) => {
 app.listen(PORT, '0.0.0.0', () => {
   console.log(`${VENDOR}-crawler running on port ${PORT}`);
   console.log(`Table: ${TABLE}`);
-  console.log(`Auth: admin/***REMOVED***`);
+  console.log(`Auth: admin/<password>`);
 });
diff --git a/DW-Programming/vendor-crawlers/pj-crawler/server.js b/DW-Programming/vendor-crawlers/pj-crawler/server.js
index 6964f73b..1b8165b5 100644
--- a/DW-Programming/vendor-crawlers/pj-crawler/server.js
+++ b/DW-Programming/vendor-crawlers/pj-crawler/server.js
@@ -19,7 +19,7 @@ const basicAuth = (req, res, next) => {
   }
   const credentials = Buffer.from(auth.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  if (user === 'admin' && pass === '***REMOVED***') {
+  if (user === 'admin' && pass === process.env.ADMIN_PASSWORD) {
     return next();
   }
   return res.status(401).json({ error: 'Invalid credentials' });
@@ -233,5 +233,5 @@ app.get('/health', (req, res) => {
 app.listen(PORT, '0.0.0.0', () => {
   console.log(`${VENDOR}-crawler running on port ${PORT}`);
   console.log(`Table: ${TABLE}`);
-  console.log(`Auth: admin/***REMOVED***`);
+  console.log(`Auth: admin/<password>`);
 });
diff --git a/DW-Programming/vendor-crawlers/rlf-crawler/server.js b/DW-Programming/vendor-crawlers/rlf-crawler/server.js
index 75b9a98a..e70b5325 100644
--- a/DW-Programming/vendor-crawlers/rlf-crawler/server.js
+++ b/DW-Programming/vendor-crawlers/rlf-crawler/server.js
@@ -19,7 +19,7 @@ const basicAuth = (req, res, next) => {
   }
   const credentials = Buffer.from(auth.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  if (user === 'admin' && pass === '***REMOVED***') {
+  if (user === 'admin' && pass === process.env.ADMIN_PASSWORD) {
     return next();
   }
   return res.status(401).json({ error: 'Invalid credentials' });
@@ -233,5 +233,5 @@ app.get('/health', (req, res) => {
 app.listen(PORT, '0.0.0.0', () => {
   console.log(`${VENDOR}-crawler running on port ${PORT}`);
   console.log(`Table: ${TABLE}`);
-  console.log(`Auth: admin/***REMOVED***`);
+  console.log(`Auth: admin/<password>`);
 });
diff --git a/DW-Programming/vendor-crawlers/schumacher-crawler/server.js b/DW-Programming/vendor-crawlers/schumacher-crawler/server.js
index 225ac801..c7ca0c81 100644
--- a/DW-Programming/vendor-crawlers/schumacher-crawler/server.js
+++ b/DW-Programming/vendor-crawlers/schumacher-crawler/server.js
@@ -19,7 +19,7 @@ const basicAuth = (req, res, next) => {
   }
   const credentials = Buffer.from(auth.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  if (user === 'admin' && pass === '***REMOVED***') {
+  if (user === 'admin' && pass === process.env.ADMIN_PASSWORD) {
     return next();
   }
   return res.status(401).json({ error: 'Invalid credentials' });
@@ -233,5 +233,5 @@ app.get('/health', (req, res) => {
 app.listen(PORT, '0.0.0.0', () => {
   console.log(`${VENDOR}-crawler running on port ${PORT}`);
   console.log(`Table: ${TABLE}`);
-  console.log(`Auth: admin/***REMOVED***`);
+  console.log(`Auth: admin/<password>`);
 });
diff --git a/DW-Programming/vendor-crawlers/scripts/crawl-all.sh b/DW-Programming/vendor-crawlers/scripts/crawl-all.sh
index 11e7b568..47ac7f31 100755
--- a/DW-Programming/vendor-crawlers/scripts/crawl-all.sh
+++ b/DW-Programming/vendor-crawlers/scripts/crawl-all.sh
@@ -18,7 +18,9 @@ mkdir -p "$LOG_DIR"
 MODE="${1:-weekly}"
 TIMESTAMP=$(date +%Y-%m-%d_%H%M)
 LOG_FILE="$LOG_DIR/crawl-all-${MODE}-${TIMESTAMP}.log"
-AUTH="***REMOVED***"  # admin:***REMOVED***
+# BASIC_AUTH must be exported as "user:pass" (see secrets-manager). Base64-encoded at runtime.
+: "${BASIC_AUTH:?BASIC_AUTH not set — export user:pass before running}"
+AUTH=$(printf '%s' "$BASIC_AUTH" | base64)
 
 # Slack webhook for #claude-to-steve
 SLACK_WEBHOOK="${SLACK_WEBHOOK_URL}"
diff --git a/DW-Programming/vendor-crawlers/scripts/monthly-vendor-update.sh b/DW-Programming/vendor-crawlers/scripts/monthly-vendor-update.sh
index db82f567..a1a863d3 100755
--- a/DW-Programming/vendor-crawlers/scripts/monthly-vendor-update.sh
+++ b/DW-Programming/vendor-crawlers/scripts/monthly-vendor-update.sh
@@ -16,7 +16,9 @@ mkdir -p "$LOG_DIR"
 
 TIMESTAMP=$(date +%Y-%m-%d_%H%M)
 LOG_FILE="$LOG_DIR/monthly-update-$TIMESTAMP.log"
-AUTH="***REMOVED***"  # admin:***REMOVED***
+# BASIC_AUTH must be exported as "user:pass" (see secrets-manager). Base64-encoded at runtime.
+: "${BASIC_AUTH:?BASIC_AUTH not set — export user:pass before running}"
+AUTH=$(printf '%s' "$BASIC_AUTH" | base64)
 
 # Slack webhook for #claude-to-steve
 SLACK_WEBHOOK="${SLACK_WEBHOOK_URL}"
diff --git a/DW-Programming/vendor-crawlers/thibaut-crawler/full-fetch.js b/DW-Programming/vendor-crawlers/thibaut-crawler/full-fetch.js
index db803728..59230f91 100644
--- a/DW-Programming/vendor-crawlers/thibaut-crawler/full-fetch.js
+++ b/DW-Programming/vendor-crawlers/thibaut-crawler/full-fetch.js
@@ -10,7 +10,7 @@ const fetch = require('node-fetch');
 const { Pool } = require('pg');
 
 const CRAWLER_API = 'http://localhost:9966';
-const AUTH = 'Basic ' + Buffer.from('admin:***REMOVED***').toString('base64');
+const AUTH = 'Basic ' + Buffer.from(process.env.BASIC_AUTH).toString('base64');
 const BASE_URL = 'https://www.thibautdesign.com';
 const CATEGORY_URL = 'https://www.thibautdesign.com/category/wallcoverings';
 
diff --git a/DW-Programming/vendor-crawlers/thibaut-crawler/server.js b/DW-Programming/vendor-crawlers/thibaut-crawler/server.js
index 9a8c0b4c..9df63e29 100644
--- a/DW-Programming/vendor-crawlers/thibaut-crawler/server.js
+++ b/DW-Programming/vendor-crawlers/thibaut-crawler/server.js
@@ -19,7 +19,7 @@ const basicAuth = (req, res, next) => {
   }
   const credentials = Buffer.from(auth.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  if (user === 'admin' && pass === '***REMOVED***') {
+  if (user === 'admin' && pass === process.env.ADMIN_PASSWORD) {
     return next();
   }
   return res.status(401).json({ error: 'Invalid credentials' });
@@ -233,5 +233,5 @@ app.get('/health', (req, res) => {
 app.listen(PORT, '0.0.0.0', () => {
   console.log(`${VENDOR}-crawler running on port ${PORT}`);
   console.log(`Table: ${TABLE}`);
-  console.log(`Auth: admin/***REMOVED***`);
+  console.log(`Auth: admin/<password>`);
 });
diff --git a/DW-Programming/vendor-crawlers/york-crawler/server.js b/DW-Programming/vendor-crawlers/york-crawler/server.js
index c81f3a54..b97caa98 100644
--- a/DW-Programming/vendor-crawlers/york-crawler/server.js
+++ b/DW-Programming/vendor-crawlers/york-crawler/server.js
@@ -19,7 +19,7 @@ const basicAuth = (req, res, next) => {
   }
   const credentials = Buffer.from(auth.slice(6), 'base64').toString();
   const [user, pass] = credentials.split(':');
-  if (user === 'admin' && pass === '***REMOVED***') {
+  if (user === 'admin' && pass === process.env.ADMIN_PASSWORD) {
     return next();
   }
   return res.status(401).json({ error: 'Invalid credentials' });
@@ -233,5 +233,5 @@ app.get('/health', (req, res) => {
 app.listen(PORT, '0.0.0.0', () => {
   console.log(`${VENDOR}-crawler running on port ${PORT}`);
   console.log(`Table: ${TABLE}`);
-  console.log(`Auth: admin/***REMOVED***`);
+  console.log(`Auth: admin/<password>`);
 });
diff --git a/DW-Websites/flockedwallpaper-mobile/server.js b/DW-Websites/flockedwallpaper-mobile/server.js
index 204492e4..17f92a6d 100644
--- a/DW-Websites/flockedwallpaper-mobile/server.js
+++ b/DW-Websites/flockedwallpaper-mobile/server.js
@@ -4,7 +4,7 @@ const path = require('path');
 const crypto = require('crypto');
 
 const PORT = process.env.PORT || 8888;
-const AUTH_PASS = '***REMOVED***';
+const AUTH_PASS = process.env.ADMIN_PASSWORD;
 const SESSION_SECRET = crypto.randomBytes(32).toString('hex');
 const sessions = new Set();
 
@@ -147,5 +147,5 @@ function serveFile(filePath, ext, res) {
 server.listen(PORT, '0.0.0.0', () => {
     console.log(`FlockedWallpaper Mobile running on port ${PORT}`);
     console.log(`  URL: http://45.61.58.125:${PORT}/`);
-    console.log(`  Auth: Cookie-based (password: ***REMOVED***)`);
+    console.log(`  Auth: Cookie-based (password: <password>)`);
 });
diff --git a/scripts/collection-consolidation-phase2.js b/scripts/collection-consolidation-phase2.js
index 61bc3e9c..49ca4710 100644
--- a/scripts/collection-consolidation-phase2.js
+++ b/scripts/collection-consolidation-phase2.js
@@ -14,7 +14,7 @@ const REDIRECT_TOKEN = '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';
 const PRODUCT_TOKEN = process.env.SHOPIFY_ADMIN_TOKEN;
 const API_VERSION = '2024-07';
 const COLLECTIONS_API = 'http://localhost:9501/api/collections';
-const AUTH = Buffer.from('admin:***REMOVED***').toString('base64');
+const AUTH = Buffer.from(process.env.BASIC_AUTH).toString('base64');
 const RATE_LIMIT_MS = 650;
 const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
diff --git a/scripts/collection-rename-phase1.js b/scripts/collection-rename-phase1.js
index 4bd8c5b7..dc7e243c 100644
--- a/scripts/collection-rename-phase1.js
+++ b/scripts/collection-rename-phase1.js
@@ -1,7 +1,7 @@
 #!/usr/bin/env node
 // Collection Consolidation Phase 1: Remove vendor collection suffixes
 const API = 'http://localhost:9501';
-const AUTH = 'Basic ' + Buffer.from('admin:***REMOVED***').toString('base64');
+const AUTH = 'Basic ' + Buffer.from(process.env.BASIC_AUTH).toString('base64');
 
 const SUFFIXES = [
   ' Wallpaper and Fabrics',
diff --git a/scripts/ralph/prd-ralph-lauren-fabrics.json b/scripts/ralph/prd-ralph-lauren-fabrics.json
index e52be424..1d4b8e49 100644
--- a/scripts/ralph/prd-ralph-lauren-fabrics.json
+++ b/scripts/ralph/prd-ralph-lauren-fabrics.json
@@ -116,7 +116,7 @@
         "Displays real-time progress (current product, percentage)",
         "Shows recent updates log with success/failure status",
         "Lists products without MFR# for manual review",
-        "Uses unified authentication (admin / ***REMOVED***)",
+        "Uses unified authentication (admin / <ADMIN_PASSWORD>)",
         "Verify in browser",
         "Typecheck passes"
       ],
diff --git a/scripts/thibaut-master-products.js b/scripts/thibaut-master-products.js
index 0d9347e4..0a9f7847 100644
--- a/scripts/thibaut-master-products.js
+++ b/scripts/thibaut-master-products.js
@@ -10,7 +10,7 @@ const pool = new Pool({
 // Basic auth
 app.use((req, res, next) => {
   const auth = req.headers.authorization;
-  if (!auth || auth !== 'Basic ' + Buffer.from('admin:***REMOVED***').toString('base64')) {
+  if (!auth || auth !== 'Basic ' + Buffer.from(process.env.BASIC_AUTH).toString('base64')) {
     res.setHeader('WWW-Authenticate', 'Basic realm="DW"');
     return res.status(401).send('Auth required');
   }
diff --git a/shopify/scripts/arte-dashboard/bulk-title-updater.js b/shopify/scripts/arte-dashboard/bulk-title-updater.js
index c0e06161..d2755ef5 100755
--- a/shopify/scripts/arte-dashboard/bulk-title-updater.js
+++ b/shopify/scripts/arte-dashboard/bulk-title-updater.js
@@ -16,7 +16,7 @@ const pool = new Pool({
 });
 
 const DASHBOARD_URL = 'http://45.61.58.125:9955';
-const AUTH = 'Basic ' + Buffer.from('admin:***REMOVED***').toString('base64');
+const AUTH = 'Basic ' + Buffer.from(process.env.BASIC_AUTH).toString('base64');
 
 // Shopify GraphQL
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
diff --git a/shopify/scripts/arte-dashboard/server.js b/shopify/scripts/arte-dashboard/server.js
index 3edeb8c7..364dcabd 100644
--- a/shopify/scripts/arte-dashboard/server.js
+++ b/shopify/scripts/arte-dashboard/server.js
@@ -7,7 +7,7 @@
  * - Separate sections for Products, Murals, New SKUs
  * - Scrape arte-international.com for product data
  * - Log to PostgreSQL
- * - Auth: admin / ***REMOVED***
+ * - Auth: admin / <password>
  */
 
 const express = require('express');
@@ -19,7 +19,7 @@ const PORT = 9955;
 
 // Auth credentials
 const AUTH_USER = 'admin';
-const AUTH_PASS = '***REMOVED***';
+const AUTH_PASS = process.env.ADMIN_PASSWORD;
 
 // Shopify config
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
diff --git a/shopify/scripts/bespoke-updater/server.js b/shopify/scripts/bespoke-updater/server.js
index 7bb43be1..8d487f5d 100644
--- a/shopify/scripts/bespoke-updater/server.js
+++ b/shopify/scripts/bespoke-updater/server.js
@@ -9,7 +9,7 @@
  * - Batch update functionality
  * - Architecture-focused terminology
  *
- * Auth: admin / ***REMOVED***
+ * Auth: admin / <password>
  */
 
 const express = require('express');
@@ -52,7 +52,7 @@ function basicAuth(req, res, next) {
   }
   const credentials = Buffer.from(auth.split(' ')[1], 'base64').toString();
   const [username, password] = credentials.split(':');
-  if (username === 'admin' && password === '***REMOVED***') {
+  if (username === 'admin' && password === process.env.ADMIN_PASSWORD) {
     return next();
   }
   res.setHeader('WWW-Authenticate', 'Basic realm="Bespoke Updater"');
@@ -1555,7 +1555,7 @@ app.get('/', (req, res) => {
 
         // Fetch ALL launches (no channel filter)
         const res = await fetch(\`\${CALENDAR_API_URL}/api/launches?start=\${startStr}&end=\${endStr}\`, {
-          headers: { 'Authorization': 'Basic ' + btoa('admin:***REMOVED***') }
+          headers: { 'Authorization': 'Basic ' + btoa(process.env.BASIC_AUTH) }
         });
 
         if (!res.ok) throw new Error('Failed to fetch launches');
@@ -1629,7 +1629,7 @@ app.get('/', (req, res) => {
 
         // Only fetch DW Bespoke launches (channel 9)
         const res = await fetch(\`\${CALENDAR_API_URL}/api/launches?start=\${startStr}&end=\${endStr}&channelId=9\`, {
-          headers: { 'Authorization': 'Basic ' + btoa('admin:***REMOVED***') }
+          headers: { 'Authorization': 'Basic ' + btoa(process.env.BASIC_AUTH) }
         });
 
         if (!res.ok) {
@@ -1707,7 +1707,7 @@ app.get('/', (req, res) => {
         const endStr = now.toISOString();
 
         const res = await fetch(\`\${CALENDAR_API_URL}/api/launches?start=\${startStr}&end=\${endStr}&status=activated\`, {
-          headers: { 'Authorization': 'Basic ' + btoa('admin:***REMOVED***') }
+          headers: { 'Authorization': 'Basic ' + btoa(process.env.BASIC_AUTH) }
         });
 
         if (!res.ok) throw new Error('Failed to fetch launched products');
@@ -1958,7 +1958,7 @@ app.post('/api/products/:id/schedule', async (req, res) => {
       method: 'POST',
       headers: {
         'Content-Type': 'application/json',
-        'Authorization': 'Basic ' + Buffer.from('admin:***REMOVED***').toString('base64')
+        'Authorization': 'Basic ' + Buffer.from(process.env.BASIC_AUTH).toString('base64')
       },
       body: JSON.stringify({
         productId: id,
@@ -2014,7 +2014,7 @@ app.get('/api/scheduled', async (req, res) => {
     // Fetch from ShopifyCalendar
     const calendarResponse = await fetch('http://127.0.0.1:9958/api/launches?channelId=9', {
       headers: {
-        'Authorization': 'Basic ' + Buffer.from('admin:***REMOVED***').toString('base64')
+        'Authorization': 'Basic ' + Buffer.from(process.env.BASIC_AUTH).toString('base64')
       }
     });
     const data = await calendarResponse.json();
@@ -2536,7 +2536,7 @@ async function start() {
   await initDatabase();
   app.listen(PORT, '0.0.0.0', () => {
     console.log(`🏛️ Bespoke Updater running at http://45.61.58.125:${PORT}`);
-    console.log('Auth: admin / ***REMOVED***');
+    console.log('Auth: admin / <password>');
   });
 }
 
diff --git a/shopify/scripts/koroseal-enhanced-update.js b/shopify/scripts/koroseal-enhanced-update.js
index ffffbbe4..3fe54358 100644
--- a/shopify/scripts/koroseal-enhanced-update.js
+++ b/shopify/scripts/koroseal-enhanced-update.js
@@ -15,7 +15,7 @@
  * - Inventory: 2026 units, Sample price: $4.25
  * - Koroseal spec scraping
  *
- * Auth: admin / ***REMOVED***
+ * Auth: admin / <password>
  */
 var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
     if (k2 === undefined) k2 = k;
@@ -67,7 +67,7 @@ const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_MODEL = 'gemini-2.0-flash';
 // Authentication credentials
 const AUTH_USER = 'admin';
-const AUTH_PASS = '***REMOVED***';
+const AUTH_PASS = process.env.ADMIN_PASSWORD;
 // Rate limiting delays (milliseconds)
 const SHOPIFY_DELAY = 500;
 const KOROSEAL_DELAY = 2000;
@@ -2153,7 +2153,7 @@ app.listen(PORT, '0.0.0.0', () => {
 ╔══════════════════════════════════════════════════════════════╗
 ║     Koroseal Enhanced Product Updater                        ║
 ║     Running on http://45.61.58.125:${PORT}                       ║
-║     Auth: admin / ***REMOVED***                              ║
+║     Auth: admin / <password>                              ║
 ╚══════════════════════════════════════════════════════════════╝
   `);
 });
diff --git a/shopify/scripts/koroseal-overnight-monitor.sh b/shopify/scripts/koroseal-overnight-monitor.sh
index e7d8471a..b0bf6312 100755
--- a/shopify/scripts/koroseal-overnight-monitor.sh
+++ b/shopify/scripts/koroseal-overnight-monitor.sh
@@ -5,7 +5,7 @@
 LOG_FILE="/tmp/koroseal-overnight.log"
 SHOPIFY_STORE="designer-laboratory-sandbox.myshopify.com"
 SHOPIFY_TOKEN="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"
-AUTH="admin:***REMOVED***"
+AUTH="$BASIC_AUTH"
 API_URL="http://45.61.58.125:9895"
 
 log() {
diff --git a/shopify/scripts/koroseal-slack-monitor.js b/shopify/scripts/koroseal-slack-monitor.js
index 968b804d..ad344a41 100644
--- a/shopify/scripts/koroseal-slack-monitor.js
+++ b/shopify/scripts/koroseal-slack-monitor.js
@@ -49,7 +49,7 @@ function fetchStats() {
       path: '/api/stats',
       method: 'GET',
       headers: {
-        'Authorization': 'Basic ' + Buffer.from('admin:***REMOVED***').toString('base64')
+        'Authorization': 'Basic ' + Buffer.from(process.env.BASIC_AUTH).toString('base64')
       }
     };
 
@@ -80,7 +80,7 @@ function restartUpdate() {
       path: '/api/batch-size',
       method: 'POST',
       headers: {
-        'Authorization': 'Basic ' + Buffer.from('admin:***REMOVED***').toString('base64'),
+        'Authorization': 'Basic ' + Buffer.from(process.env.BASIC_AUTH).toString('base64'),
         'Content-Type': 'application/json',
         'Content-Length': postData.length
       }
@@ -92,7 +92,7 @@ function restartUpdate() {
         path: '/api/start',
         method: 'POST',
         headers: {
-          'Authorization': 'Basic ' + Buffer.from('admin:***REMOVED***').toString('base64')
+          'Authorization': 'Basic ' + Buffer.from(process.env.BASIC_AUTH).toString('base64')
         }
       }, (res) => {
         let data = '';
diff --git a/shopify/scripts/malibu-update-dashboard.ts b/shopify/scripts/malibu-update-dashboard.ts
index 45975399..00074826 100644
--- a/shopify/scripts/malibu-update-dashboard.ts
+++ b/shopify/scripts/malibu-update-dashboard.ts
@@ -2,7 +2,7 @@
 /**
  * Malibu Update Progress Dashboard
  * Port: 9896
- * Auth: admin / ***REMOVED***
+ * Auth: admin / <password>
  */
 
 import * as http from 'http';
@@ -12,7 +12,7 @@ import { spawn, ChildProcess } from 'child_process';
 
 const PORT = 9896;
 const AUTH_USER = 'admin';
-const AUTH_PASS = '***REMOVED***';
+const AUTH_PASS = process.env.ADMIN_PASSWORD;
 const PROGRESS_FILE = '/root/Projects/Designer-Wallcoverings/shopify/scripts/malibu-update-progress.json';
 const LOG_FILE = '/root/Projects/Designer-Wallcoverings/shopify/scripts/malibu-update.log';
 

← ad11ae9c Refactor hardcoded Shopify Admin token to process.env.SHOPIF  ·  back to Designer Wallcoverings  ·  scrub last plaintext basic-auth password from progress doc + f3c52e53 →