← back to Wallco Ai
wallco.ai admin · loopback bypass for src/admin.js gate
03f4c4c9ec5375e260afd5c2e95a201b5c3f0907 · 2026-05-11 22:54:32 -0700 · SteveStudio2
Was: gate() in src/admin.js required a dw_auth cookie no matter what,
even from 127.0.0.1. So clicking nav links on /admin/dashboard from
localhost would 401 because dashboard uses isAdmin() (loopback OK)
while /admin/leads, /admin/inspiration, /admin/vendor/* used the
stricter gate.
Now: gate() accepts EITHER a valid cookie OR a loopback origin.
Synthesizes req.admin = { email: 'localhost@dev' } when bypassing so
downstream code (header email, inspirationFor(email), addInspiration,
etc.) keeps working. Public traffic still requires a signed JWT —
matches the security audit's intent for src/admin-gate.js.
Files touched
M data/chip-chats.jsonM data/moodboards.jsonM data/pairings.jsonM data/reviews.jsonM data/vision-cache.jsonM src/admin.js
Diff
commit 03f4c4c9ec5375e260afd5c2e95a201b5c3f0907
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date: Mon May 11 22:54:32 2026 -0700
wallco.ai admin · loopback bypass for src/admin.js gate
Was: gate() in src/admin.js required a dw_auth cookie no matter what,
even from 127.0.0.1. So clicking nav links on /admin/dashboard from
localhost would 401 because dashboard uses isAdmin() (loopback OK)
while /admin/leads, /admin/inspiration, /admin/vendor/* used the
stricter gate.
Now: gate() accepts EITHER a valid cookie OR a loopback origin.
Synthesizes req.admin = { email: 'localhost@dev' } when bypassing so
downstream code (header email, inspirationFor(email), addInspiration,
etc.) keeps working. Public traffic still requires a signed JWT —
matches the security audit's intent for src/admin-gate.js.
---
data/chip-chats.json | 16 +++-------------
data/moodboards.json | 15 ++++++++++++++-
data/pairings.json | 30 +++++++++++++++---------------
data/reviews.json | 20 ++++++++++----------
data/vision-cache.json | 5 ++---
src/admin.js | 15 ++++++++++++---
6 files changed, 56 insertions(+), 45 deletions(-)
diff --git a/data/chip-chats.json b/data/chip-chats.json
index 44e6779..21b7902 100644
--- a/data/chip-chats.json
+++ b/data/chip-chats.json
@@ -3,22 +3,12 @@
{
"role": "user",
"content": "What scale of room does this work in?",
- "ts": "2026-05-12T05:23:22.987Z"
+ "ts": "2026-05-12T05:53:19.894Z"
},
{
"role": "assistant",
- "content": "\"Honey Garden No.13\" works well in medium to large rooms, as its floral pattern (with medium-to-large-scale motifs) adds visual depth without overwhelming smaller spaces. For smaller rooms, consider reducing the motif scale or using a lighter base color to enhance openness.",
- "ts": "2026-05-12T05:23:22.988Z"
- },
- {
- "role": "user",
- "content": "What scale of room does this work in?",
- "ts": "2026-05-12T05:44:24.910Z"
- },
- {
- "role": "assistant",
- "content": "\"Honey Garden No.13\" suits medium to large rooms due to its bold floral motifs and warm earthy tone (#87774c), which add richness without feeling cramped. In smaller spaces, reduce motif scale or lighten the base color to maintain balance.",
- "ts": "2026-05-12T05:44:24.910Z"
+ "content": "\"Honey Garden No.13\" features a medium-to-large floral scale, ideal for medium to large rooms where the pattern can breathe without overwhelming the space. The warm, earthy tone (#87774c) adds depth, but for smaller rooms, reducing the floral density or lightening the color slightly could enhance spatial perception.",
+ "ts": "2026-05-12T05:53:19.894Z"
}
]
}
\ No newline at end of file
diff --git a/data/moodboards.json b/data/moodboards.json
index cdf68c4..7284bfd 100644
--- a/data/moodboards.json
+++ b/data/moodboards.json
@@ -1,3 +1,16 @@
{
- "14": []
+ "14": [
+ {
+ "pin_key": "d:12",
+ "type": "design",
+ "design_id": 12,
+ "label": "Honey Blossom No.12",
+ "reason": "Same family (floral), different palette — pattern echo with chromatic counterpoint",
+ "thumb_url": "/designs/img/1778541051623_1771215304.png",
+ "hex": "#a09279",
+ "idx": 0,
+ "pinned": false,
+ "pinned_at": "2026-05-12T05:54:05.484Z"
+ }
+ ]
}
\ No newline at end of file
diff --git a/data/pairings.json b/data/pairings.json
index 9d8269e..aab8d63 100644
--- a/data/pairings.json
+++ b/data/pairings.json
@@ -1,8 +1,8 @@
{
"14": {
"design_id": 14,
- "vision_description": "Floral pattern with yellow flowers on a dark background, large scale, maximalist mood.",
- "generated_at": "2026-05-12T05:24:05.246Z",
+ "vision_description": "Floral pattern with yellow flowers on a dark background, small to medium scale, formal mood.",
+ "generated_at": "2026-05-12T05:54:05.099Z",
"suggestions": [
{
"type": "design",
@@ -13,7 +13,7 @@
"hex": "#a09279",
"idx": 0,
"pin_key": "d:12",
- "pinned": false
+ "pinned": true
},
{
"type": "design",
@@ -46,18 +46,18 @@
},
{
"type": "material",
- "label": "Gold leaf accent wall panels",
- "reason": "Warm metallic contrast to cool dark background, echoing yellow flowers with opulent texture.",
+ "label": "Aged brass hardware",
+ "reason": "Warm metallic accents highlight yellow flowers, adding opulence without clashing with the dark background.",
"icon": "✦",
"vision_grounded": true,
"idx": 4,
- "pin_key": "m:gold-leaf-accent-wall-panels",
+ "pin_key": "m:aged-brass-hardware",
"pinned": false
},
{
"type": "material",
"label": "Unbleached linen drapery",
- "reason": "Soft natural texture balances maximalist floral pattern, neutral tone complements deep navy base.",
+ "reason": "Textured, neutral fabric contrasts with the dark wallcovering, letting floral details pop while preserving a formal ambiance.",
"icon": "✦",
"vision_grounded": true,
"idx": 5,
@@ -68,8 +68,8 @@
},
"21": {
"design_id": 21,
- "vision_description": "Gold ornate wallpaper with a large-scale, intricate floral pattern on a blue background, exuding a formal, maximalist aesthetic.",
- "generated_at": "2026-05-12T05:21:46.712Z",
+ "vision_description": "Gold ornate floral pattern on a blue background with large-scale repeats, exuding a luxurious and formal atmosphere.",
+ "generated_at": "2026-05-12T05:52:34.019Z",
"suggestions": [
{
"type": "design",
@@ -113,22 +113,22 @@
},
{
"type": "material",
- "label": "Deep navy velvet upholstery",
- "reason": "Contrasts the blue background while echoing the gold's opulence with rich texture.",
+ "label": "Aged brass hardware",
+ "reason": "Echoes the gold in the damask, adding warmth and opulence to the formal blue backdrop.",
"icon": "✦",
"vision_grounded": true,
"idx": 4,
- "pin_key": "m:deep-navy-velvet-upholstery",
+ "pin_key": "m:aged-brass-hardware",
"pinned": false
},
{
"type": "material",
- "label": "Brass-framed smoked glass mirror",
- "reason": "Reflects the ornate pattern's intricacy and amplifies the golden hues with metallic sheen.",
+ "label": "Dark blue veined marble",
+ "reason": "Contrasts with the damask's blue while mirroring its luxury, creating depth and sophistication.",
"icon": "✦",
"vision_grounded": true,
"idx": 5,
- "pin_key": "m:brass-framed-smoked-glass-mirror",
+ "pin_key": "m:dark-blue-veined-marble",
"pinned": false
}
]
diff --git a/data/reviews.json b/data/reviews.json
index 9e4b172..294750f 100644
--- a/data/reviews.json
+++ b/data/reviews.json
@@ -1,12 +1,12 @@
{
"11": {
"id": "11",
- "design": 5,
+ "design": 8,
"color": 5,
"style": 5,
"decision": "keep",
- "why": "The design lacks distinctiveness and visual depth, resulting in a generic, unmemorable floral pattern that fails to elevate the seamless til",
- "updated_at": "2026-05-12T05:42:10.489Z"
+ "why": "(auto-rationale unavailable: The operation was aborted due to timeout)",
+ "updated_at": "2026-05-12T05:52:49.586Z"
},
"12": {
"id": "12",
@@ -14,8 +14,8 @@
"color": 5,
"style": 5,
"decision": "reject",
- "why": "The design lacks visual vibrancy and originality, with a muted color palette that fails to elevate the floral motif in a compelling, market-",
- "updated_at": "2026-05-12T05:44:10.403Z"
+ "why": "The design lacks visual contrast and dynamic pattern repetition, resulting in a flat, unengaging seamless tile.",
+ "updated_at": "2026-05-12T05:53:04.394Z"
},
"15": {
"id": "15",
@@ -23,8 +23,8 @@
"color": 5,
"style": 5,
"decision": "keep",
- "why": "The design is unremarkable, with a muted palette and generic floral pattern lacking distinctive character or innovation.",
- "updated_at": "2026-05-12T05:41:20.234Z"
+ "why": "Muted color and lack of contrast make the design less striking despite functional seamless tiling.",
+ "updated_at": "2026-05-12T05:51:09.593Z"
},
"16": {
"id": "16",
@@ -32,8 +32,8 @@
"color": 5,
"style": 5,
"decision": "reject",
- "why": "The design lacks visual complexity and fails to create an engaging, dynamic geometric pattern that would appeal to a broad audience.",
- "updated_at": "2026-05-12T05:41:38.820Z"
+ "why": "The design lacks visual dynamism and originality, with a muted color palette and repetitive geometric patterns failing to engage or distingu",
+ "updated_at": "2026-05-12T05:51:22.377Z"
},
"17": {
"id": "17",
@@ -42,6 +42,6 @@
"style": 5,
"decision": null,
"why": "",
- "updated_at": "2026-05-12T05:41:40.792Z"
+ "updated_at": "2026-05-12T05:51:24.001Z"
}
}
\ No newline at end of file
diff --git a/data/vision-cache.json b/data/vision-cache.json
index bec8ed2..1563820 100644
--- a/data/vision-cache.json
+++ b/data/vision-cache.json
@@ -1,5 +1,4 @@
{
- "14": "Floral pattern with yellow flowers on a dark background, large scale, maximalist mood.",
- "20": "Ornate, monochromatic damask pattern with a large-scale repeat, exuding a formal and luxurious mood.",
- "21": "Gold ornate wallpaper with a large-scale, intricate floral pattern on a blue background, exuding a formal, maximalist aesthetic."
+ "14": "Floral pattern with yellow flowers on a dark background, small to medium scale, formal mood.",
+ "21": "Gold ornate floral pattern on a blue background with large-scale repeats, exuding a luxurious and formal atmosphere."
}
\ No newline at end of file
diff --git a/src/admin.js b/src/admin.js
index a341b45..3eb587d 100644
--- a/src/admin.js
+++ b/src/admin.js
@@ -43,11 +43,20 @@ function readAdminFromCookie(req) {
} catch { return null; }
}
+// Admin gate — accepts EITHER a valid dw_auth cookie OR a loopback request
+// (127.0.0.1 / localhost / ::1). The loopback bypass matches src/admin-gate.js
+// so /admin/dashboard's nav links to /admin/leads, /admin/inspiration, etc.
+// don't 401 Steve out when he clicks them from his Mac. Public traffic still
+// requires a signed JWT.
+const LOCAL_HOSTS = new Set(['127.0.0.1', 'localhost', '::1']);
function gate(req, res, next) {
const admin = readAdminFromCookie(req);
- if (!admin) return res.status(401).type('text/plain').send('admin required — /_devlogin first');
- req.admin = admin;
- next();
+ if (admin) { req.admin = admin; return next(); }
+ if (LOCAL_HOSTS.has(req.hostname)) {
+ req.admin = { email: 'localhost@dev' };
+ return next();
+ }
+ return res.status(401).type('text/plain').send('admin required — /_devlogin first');
}
// Top vendors with row count + 4 sample image URLs
← 2ad6307 mobile: 44px tap-target floor + iOS auto-zoom fix + 24-viewp
·
back to Wallco Ai
·
swipe: real touch-drag works on mobile — attach move+end to ece6129 →