[object Object]

← back to Wallco Ai

styleguides.wallco.ai → admin-only; revert public metering on batch/recolor

5b012f979ce9b625bb7abc78fdc97973d3718fa1 · 2026-06-01 12:33:14 -0700 · Steve Abrams

Files touched

Diff

commit 5b012f979ce9b625bb7abc78fdc97973d3718fa1
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Mon Jun 1 12:33:14 2026 -0700

    styleguides.wallco.ai → admin-only; revert public metering on batch/recolor
---
 server.js | 43 ++++++++++++++-----------------------------
 1 file changed, 14 insertions(+), 29 deletions(-)

diff --git a/server.js b/server.js
index 5f07e71..d895997 100644
--- a/server.js
+++ b/server.js
@@ -1174,17 +1174,18 @@ setInterval(() => load(true), 30000);
 // check as a CRITICAL bypass (anyone could mint a token with {role:"admin"}).
 const { isAdmin, requireAdmin } = require('./src/admin-gate');
 
-// ── Style Guides — Brand Selector (PUBLIC, metered) ────────────────────────
+// ── Style Guides — Brand Selector (ADMIN-ONLY) ─────────────────────────────
 // A curated picker of fashion + wallcovering houses whose palettes/signatures
 // seed the generative pipeline. Three live actions on the page:
 //   • Generate  → POST /api/generator/batch (new SDXL designs in the houses' look)
 //   • Apply     → POST /api/design/:id/recolor (restyle an existing studio design)
 //   • Export    → portable style-guide JSON / Figma block (client-side)
-// Open to the public (Steve 2026-06-01 "give user all abilities") but METERED:
-// every non-admin visitor gets SG_IMAGE_CAP paid renders per rolling 24h,
-// keyed by client IP. Generate counts its batch size; Recolor counts 1 each.
-// Admins (cookie / ?admin / localhost) are unlimited. The cap protects the
-// Replicate/Gemini bill from open-internet abuse.
+// Admin-only for now (Steve 2026-06-01 — "styleguides.wallco.ai is for admin
+// accounts for now"). The public-metering experiment is reverted: the page and
+// its recolor action gate on isAdmin, and batch is back to its original public
+// uncapped behavior. The sg* quota helpers below are kept dormant so the page's
+// quota poll still answers cleanly (admins → unlimited) and re-enabling public
+// access later is a one-line flip, not a rewrite.
 const SG_IMAGE_CAP = 5;
 const SG_WINDOW_MS = 24 * 60 * 60 * 1000;
 const _sgQuota = new Map(); // ip -> { used, resetAt }
@@ -1205,26 +1206,23 @@ function sgConsume(req, k) { sgBudget(req).entry.used += Math.max(0, k | 0); }
 // the public here does NOT open it on the main storefront PDPs (those stay 404
 // for non-admins). batch is already public, so it's capped for everyone non-admin.
 function fromSG(req) { return String(req.headers['x-sg'] || '') === '1'; }
-// Recolor gate: admin → unlimited; styleguides public within budget → allow;
-// anyone else → 404 (storefront recolor stays admin-only as before).
+// Recolor gate: admin-only (Steve 2026-06-01 — styleguides reverted to
+// admin-only, so recolor goes back to its original admin-only behavior).
 function sgRecolorGate(req, res, next) {
   if (isAdmin(req)) return next();
-  if (fromSG(req)) {
-    if (sgBudget(req).remaining <= 0) {
-      return res.status(429).json({ ok: false, error: `Free limit reached — ${SG_IMAGE_CAP} images per day. Come back tomorrow.` });
-    }
-    return next();
-  }
   return res.status(404).type('html').send('<h1>404</h1>');
 }
 
 app.get('/', (req, res, next) => {
   if (/^styleguides\./i.test(req.hostname || '')) {
+    // Admin-only for now (Steve 2026-06-01). Non-admins get a 404 so the
+    // subdomain doesn't even advertise that the styleguides page exists.
+    if (!isAdmin(req)) return res.status(404).type('html').send('<h1>404</h1>');
     return res.sendFile(path.join(__dirname, 'public', 'admin', 'styleguides.html'));
   }
   next();
 });
-app.get('/admin/styleguides', (req, res) => {
+app.get('/admin/styleguides', requireAdmin, (req, res) => {
   res.sendFile(path.join(__dirname, 'public', 'admin', 'styleguides.html'));
 });
 app.get('/api/styleguides/quota', (req, res) => {
@@ -21289,15 +21287,6 @@ app.post('/api/generator/batch', (req, res) => {
   // Clamp the requested count to a sane 1–50 so a fat-fingered number can't
   // spawn a runaway render job.
   let n = Math.max(1, Math.min(50, parseInt(req.body && req.body.n, 10) || 1));
-  // Public metering (Steve 2026-06-01): non-admin callers get SG_IMAGE_CAP
-  // paid renders / 24h per IP. Clamp n to what's left; refuse when exhausted.
-  if (!isAdmin(req)) {
-    const b = sgBudget(req);
-    if (b.remaining <= 0) {
-      return res.status(429).json({ ok: false, error: `Free limit reached — ${SG_IMAGE_CAP} images per day. Come back tomorrow.`, remaining: 0, cap: SG_IMAGE_CAP });
-    }
-    n = Math.min(n, b.remaining);
-  }
 
   // Build the prompt (one prompt drives the whole batch; each render gets its
   // own random seed so the N outputs are siblings, not duplicates).
@@ -21376,11 +21365,8 @@ app.post('/api/generator/batch', (req, res) => {
       } catch {}
     });
 
-    // Charge the public budget for the renders we just kicked off.
-    if (!isAdmin(req)) sgConsume(req, n);
     // Respond immediately — the batch renders in the background.
     res.json({ ok: true, run_id: runId, count: n, status: 'running', prompt,
-               remaining: isAdmin(req) ? null : sgBudget(req).remaining,
                note: `Rendering ${n} design${n>1?'s':''} in the background — watch the Recent Runs list. Safe to close this tab.` });
   } catch (e) { res.status(500).json({ ok:false, error: e.message }); }
 });
@@ -24042,8 +24028,7 @@ app.post('/api/design/:id/recolor', sgRecolorGate, express.json(), async (req, r
       tags: baseTags,
     });
 
-    if (!isAdmin(req)) sgConsume(req, 1);
-    res.json({ ok: true, parent_id: id, new_id: newId, new_image_url: '/designs/img/' + filename, hue: hueKey, elapsed_s: elapsed, remaining: isAdmin(req) ? null : sgBudget(req).remaining });
+    res.json({ ok: true, parent_id: id, new_id: newId, new_image_url: '/designs/img/' + filename, hue: hueKey, elapsed_s: elapsed });
   } catch (e) {
     res.status(500).json({ ok: false, error: e.message });
   }

← 55c9073 batch-regen driver: 4-gate (seam+color+concept+settlement-OK  ·  back to Wallco Ai  ·  feat(admin): side-by-side prompt-vs-image A/B rating surface 2070bb0 →