[object Object]

← back to All Designerwallcoverings

internal category: plug 3 front-facing leaks — build-data.py vendor directory drops internal, /api/vendors+/api/microsites Cache-Control private no-store, microsite external URL suppressed for internal (contrarian FIX-FIRST)

1fa387b0b09ff33127e83ba898bca97f09b91c44 · 2026-07-09 22:29:26 -0700 · steve

Files touched

Diff

commit 1fa387b0b09ff33127e83ba898bca97f09b91c44
Author: steve <steve@designerwallcoverings.com>
Date:   Thu Jul 9 22:29:26 2026 -0700

    internal category: plug 3 front-facing leaks — build-data.py vendor directory drops internal, /api/vendors+/api/microsites Cache-Control private no-store, microsite external URL suppressed for internal (contrarian FIX-FIRST)
---
 scripts/build-data.py | 18 ++++++++++++++++--
 server.js             |  7 ++++---
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/scripts/build-data.py b/scripts/build-data.py
index c04e504..d2c0b5b 100644
--- a/scripts/build-data.py
+++ b/scripts/build-data.py
@@ -84,10 +84,24 @@ def upsert(name, **kw):
             v[k] = val
     return v
 
+# INTERNAL lines — deliberately NEVER front-facing (config/internal-lines.json). Their vendor
+# names are dropped from this front-facing vendor directory, same as BANNED. (Steve 2026-07-09)
+INTERNAL_VENDORS = {"fromental", "gracie", "zuber", "crezana design"}
+for _p in (os.path.join(os.path.dirname(__file__), "..", "..", "Designer-Wallcoverings", "shopify", "config", "internal-lines.json"),
+           "/root/Projects/Designer-Wallcoverings/shopify/config/internal-lines.json"):
+    try:
+        with open(_p) as _f:
+            _j = json.load(_f)
+        if isinstance(_j.get("vendors"), list) and _j["vendors"]:
+            INTERNAL_VENDORS = {str(x).strip().lower() for x in _j["vendors"]}
+        break
+    except Exception:
+        pass
+
 dropped = []
 for row in reg:
     name = display_name(row)
-    if not name or BANNED.search(name):
+    if not name or BANNED.search(name) or name.strip().lower() in INTERNAL_VENDORS:
         dropped.append(row.get("vendor_name"))
         continue
     lv = live_by_name.get(name.lower())
@@ -99,7 +113,7 @@ for row in reg:
 
 # Live store vendors with no registry row still belong in a front-facing directory
 for lname, lv in live_by_name.items():
-    if BANNED.search(lv["vendor"] or ""):
+    if BANNED.search(lv["vendor"] or "") or (lv["vendor"] or "").strip().lower() in INTERNAL_VENDORS:
         dropped.append(lv["vendor"])
         continue
     if lname not in vendors:
diff --git a/server.js b/server.js
index 9d44706..3d27543 100644
--- a/server.js
+++ b/server.js
@@ -581,7 +581,8 @@ function deriveMicrositeRow(p, feed) {
     materials: [...new Set(materials)],
     image_state: primaryImg ? 'Has image' : 'No image',
     // Website = the vendor's own product page when the feed carries an absolute one.
-    url: (typeof (p.productUrl || p.product_url) === 'string' && /^https?:\/\//.test(p.productUrl || p.product_url)) ? (p.productUrl || p.product_url) : null,
+    // INTERNAL lines never emit an external front-facing URL (Steve 2026-07-09).
+    url: (!isInternalRow({ vendor: feed.vendor }) && typeof (p.productUrl || p.product_url) === 'string' && /^https?:\/\//.test(p.productUrl || p.product_url)) ? (p.productUrl || p.product_url) : null,
     internal_url: null,
     // Line Viewer = the vendor's live internal microsite (resolves via the same crawl artifact).
     line_viewer_url: VENDOR_VIEWER.get(slugify(feed.vendor)) || VENDOR_VIEWER.get(feed.slug) || null,
@@ -1183,14 +1184,14 @@ const server = http.createServer((req, res) => {
 
   if (u.pathname === '/api/vendors') { // legacy vendor directory API (vendors.html)
     try {
-      res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'public, max-age=300' });
+      res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'private, no-store' });
       return res.end(loadVendors());
     } catch { res.writeHead(500, { 'Content-Type': 'application/json' }); return res.end('{"error":"data unavailable"}'); }
   }
 
   if (u.pathname === '/api/microsites') {
     try {
-      res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'public, max-age=60' });
+      res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'private, no-store' });
       return res.end(loadMicrosites());
     } catch { res.writeHead(503, { 'Content-Type': 'application/json' }); return res.end('{"error":"crawl snapshot not ready"}'); }
   }

← f37876c auto-save: 2026-07-09T22:12:24 (1 files) — server.js  ·  back to All Designerwallcoverings  ·  auto-save: 2026-07-09T22:42:31 (2 files) — data/vendors.json 301550f →