{"slug":"dw-domain-fleet","total":57,"limit":100,"offset":0,"since":null,"commits":[{"hash":"2cb23f3","date":"2026-07-27 20:04:24 -0700","author":"Steve Abrams","subject":"migrate GoDaddy auth → Bearer PAT (TK-10 key rotation); sso-key fallback retained","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"7b1c304","date":"2026-07-06 17:57:08 -0700","author":"Steve Abrams","subject":"Square fleet card images (aspect-ratio 1/1)","body":""},{"hash":"4936c4d","date":"2026-06-20 09:49:29 -0700","author":"Steve Abrams","subject":"Add Tier-A promo-banner desktop verification screenshot from prior run","body":""},{"hash":"e0e0d83","date":"2026-06-19 16:30:48 -0700","author":"Steve","subject":"Tier A promo strip: text-only rotating 'New · <product> →' new-arrivals banner across the 44 multitenant DW sites (promoStrip() in render.js, per-site cfg.promoBanner default on); verified live on carmelwallpaper","body":"Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>"},{"hash":"1b277d8","date":"2026-06-09 13:09:37 -0700","author":"Steve Abrams","subject":"snapshot before task-52 verification (standalone hero allocation data drift)","body":""},{"hash":"45f2fce","date":"2026-06-03 21:24:36 -0700","author":"Steve","subject":"fix(fleet): route scrubTags through canonical isVendorTag + extend scrubVendor denylist — kills dwf vendor tag-chip + slug leaks (Anna French, Christian Lacroix, Ralph Lauren, AS Creation, Gaston Y Daniela, etc); verified 0 vendor names in barwallpaper DOM across 3267 products","body":""},{"hash":"bd7303f","date":"2026-06-03 14:14:34 -0700","author":"Steve Abrams","subject":"Vendor-neutral image proxy: render emits /img/<token>, server.js streams CDN bytes (closed proxy + LRU). Kills image_url vendor-name leak in card/PDP/hero/JSON-LD. DTD-A. Proven local: 0 leaks, /img 200.","body":""},{"hash":"7c6386c","date":"2026-06-01 15:33:14 -0700","author":"Steve Abrams","subject":"Per-site catalog extras overlay (data/extras/<slug>.json) — site-exclusive products w/ buy_url, no flagship-store write, survives pull-catalog. For asseeninla LA-toile line.","body":""},{"hash":"251f908","date":"2026-06-01 14:26:45 -0700","author":"Steve Abrams","subject":"fleet-heroes: fix spurious exit-1 in deploy mode + dedup by slug (don't re-churn same-site www+repo pairs)","body":""},{"hash":"6c986ea","date":"2026-06-01 14:24:17 -0700","author":"Steve Abrams","subject":"fleet-heroes: open DW fleet registry viewer (:9774) on launch (FLEET_HEROES_NO_OPEN to suppress)","body":""},{"hash":"addb71d","date":"2026-06-01 14:19:32 -0700","author":"Steve Abrams","subject":"Add fleet-heroes.sh driver: repeatable fleet-wide hero refresh + global dedupe (report-only default, --deploy gated, batched reload)","body":""},{"hash":"c069168","date":"2026-06-01 14:17:07 -0700","author":"Steve Abrams","subject":"fix: app.set('trust proxy', 1) — resolves ERR_ERL_UNEXPECTED_X_FORWARDED_FOR across all 9 dwf-* apps behind nginx","body":""},{"hash":"10970b9","date":"2026-06-01 13:53:56 -0700","author":"Steve Abrams","subject":"Standalone hero apply + size-vetted retry scripts (prod-side); de-collide 2 content-site lead heroes","body":""},{"hash":"d7527ba","date":"2026-06-01 13:46:50 -0700","author":"Steve Abrams","subject":"Standalone sister-site unique hero allocation (59 sites, 0 dup, 0 generic-overlap)","body":"59 standalone storefronts served only 14 distinct static hero-bg.jpg files (31\nshared one 1.9MB template image). scripts/gen-standalone-heroes.js assigns each\na unique, clean, niche-relevant catalog image, disjoint from the 344 generic\nheroes and each other. Deploy replaces the 51 duplicate-cluster files; 8\nalready-unique heroes preserved."},{"hash":"5d250af","date":"2026-06-01 13:38:43 -0700","author":"Steve Abrams","subject":"Honor prior bleachfriendly drop (domain not renewing): remove re-added config, regen 43-site manifest","body":"Reverts the accidental re-add in 79bf34f. bleachfriendly.com serves a static\nhero and its domain is lapsing per 8b660a0; it does not belong in the rotating\nhero fleet. Prod's live 43 active template sites are already verified unique."},{"hash":"79bf34f","date":"2026-06-01 13:38:06 -0700","author":"Steve Abrams","subject":"Add bleachfriendly to fleet config + regen 44-site hero manifest (352/352 unique)","body":""},{"hash":"52573cc","date":"2026-06-01 13:32:38 -0700","author":"Steve Abrams","subject":"Unique clean heroes per site: global disjoint hero-allocation manifest","body":"Every generic-fleet site previously derived its hero from the same\nnewest-niche slice; thin-niche sites fell back to the shared all-wallcovering\npool, so 18+ sites rendered the identical lead image (43 sites used only 67\nunique images across 344 hero slots).\n\nscripts/gen-hero-allocation.js now precomputes data/hero-allocation.json — a\nglobally-disjoint, niche-relevant, clean (https, non-swatch) set of 8 heroes\nper site, distinct base patterns within each rotation. server.js reads it.\nResult: 344/344 hero slots unique, zero cross-site duplicates."},{"hash":"8b660a0","date":"2026-06-01 13:24:27 -0700","author":"Steve Abrams","subject":"drop bleachfriendly from fleet (domain not renewing): remove gen-configs spec+name, manifest entry, pm2 app, site config + local nginx conf","body":""},{"hash":"3b76655","date":"2026-05-31 21:20:13 -0700","author":"Steve Abrams","subject":"audit: read-only all-sites vendor-href leak re-verify — fleet STILL leaks (259, a85eb02 undeployed); 3 standalones clean","body":""},{"hash":"7fd25ca","date":"2026-05-31 13:34:25 -0700","author":"Steve Abrams","subject":"audit: standalone storefronts outbound-href vendor leak (cdm/carmel/ntw all leak via buy-CTA+anchor, deploy Steve-gated)","body":""},{"hash":"a85eb02","date":"2026-05-31 13:22:11 -0700","author":"Steve Abrams","subject":"render: route PDP buy CTA + main-store anchor + canonical through clean slug (kills vendor-handle DOM leak)","body":""},{"hash":"49997ea","date":"2026-05-31 08:42:46 -0700","author":"steve","subject":"Add sort <select> + density control bar to dwf homepage Featured grid (standing-rule compliance, client-side sort, shared localStorage with /catalog)","body":""},{"hash":"55a7f0b","date":"2026-05-31 06:39:20 -0700","author":"Steve Abrams","subject":"Add 2026-05-31 read-only vendor-leak re-verify: slug/chip scrub holds 0; outbound DW-store href leaks 594 across 43 sites","body":""},{"hash":"1bdbba0","date":"2026-05-30 08:27:08 -0700","author":"Steve","subject":"scrubVendor: optional inter-token separator ([^a-z0-9]*) catches no-separator handle spellings (wolfgordon, gpjbaker) + add 'g p j baker' per-initial variant + collapse mid-handle residue. Closes the 936 wolfgordon URL-slug leaks (#3 morning digest). Export scrubVendor for tests","body":""},{"hash":"0ac4d91","date":"2026-05-30 08:16:50 -0700","author":"Steve Abrams","subject":"render.js productSlug: guard both slug returns with hasVendorToken() — closes the 936 residual URL-slug leaks (935 wolfgordon + 1 gpjbaker) the separator-requiring scrubVendor regex missed on CONCATENATED handle spellings (wolfgordonwallcovering) + per-initial splits (g-p-j-baker). Falls back to clean scrubbed-sku/hash slug. Normal products unaffected; route still dual-key resolves old URLs.","body":"Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"5aee355","date":"2026-05-29 23:05:19 -0700","author":"Steve","subject":"Close C: 'A is enough' (Steve 2026-05-29). Source handle rename rejected — blind detection can't tell vendor 'Harlequin' from 'harlequin' pattern / house-brand products; would corrupt live canonical URLs. Shipped render-time scrub (A) is the fix","body":""},{"hash":"56504de","date":"2026-05-29 22:42:17 -0700","author":"Steve Abrams","subject":"render.js+server.js: eliminate data-handle/data-sku DOM vendor leak via clean-slug + /buy/:slug server-side redirect (DTD verdict B), reconciled on top of verdict-A slug-cleaning","body":"data-handle + data-sku now carry the vendor-free productSlug instead of the raw\nShopify handle; the quick-view buy-sample CTA links to the fleet's own /buy/:slug\nroute, which resolves the real handle server-side and 302-redirects to the DW\nstore — so the raw vendor-laden handle never reaches the rendered DOM. Folds in\nthe parallel session's productSlug \\s+ re-hyphenate refinement (verdict A). Closed\nredirect: target host hardcoded, slug validated, 404 on miss.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>"},{"hash":"a2b73c4","date":"2026-05-29 22:38:51 -0700","author":"Steve","subject":"Park C (vendor handle source-rename) plan — DTD verdict A's durable follow-up; gated, awaiting Steve go on a Shopify+dw_unified handle migration","body":""},{"hash":"52a5b40","date":"2026-05-29 22:34:09 -0700","author":"Steve","subject":"render.js productSlug: when the whole handle is a vendor name (e.g. brunschwig-fils), fall back to scrubbed-sku or a deterministic hash slug instead of the raw handle — closes the last 4 URL leaks (DTD verdict A)","body":""},{"hash":"9450ca4","date":"2026-05-29 22:30:31 -0700","author":"Steve","subject":"render.js scrubVendor: fix regex builder (split on non-alnum + drop empty tokens — was mangling 'brunschwig & fils' → '-fils' residue) + add slug variants cole-son/caroline-cecil/clarke-clarke/morris-co so /product hrefs are fully vendor-clean (DTD verdict A)","body":""},{"hash":"09c24d7","date":"2026-05-29 22:24:44 -0700","author":"Steve","subject":"render.js: scrubVendor() removes vendor names from displayed title + card-meta sku + /product slug + productPage h1/sku (fleet vendor-leak fix, 2026-05-29 audit). Link-safe: data-handle/data-sku raw, route resolves clean-slug OR raw-handle, DW-store CTA uses raw handle","body":""},{"hash":"ee30c6a","date":"2026-05-29 17:05:00 -0700","author":"Steve Abrams","subject":"fix: strip 3rd-party vendor tokens from product slug/handle in fleet UI (redactVendorSlug) — closes the slug-level vendor leak across the dwf fleet that the 2026-05-28 chip scrub missed; route-safe (server.js resolves via productSlug(x)===key + real-handle fallback)","body":""},{"hash":"34fbe0e","date":"2026-05-29 13:13:47 -0700","author":"Steve Abrams","subject":"fix(fleet pdp): toggle hidden until ?theme=N opt-in","body":"Prior version always set data-page-theme attribute even for default\nvisitors, defeating the gate. Now: no opt-in → attribute unset, toggle\ndisplay:none. Opt-in via URL or localStorage → attribute set, toggle\nbecomes inline-flex."},{"hash":"453b000","date":"2026-05-29 13:10:52 -0700","author":"Steve Abrams","subject":"feat(fleet pdp): theme1/theme2 toggle via ?theme=N query-param gate","body":"Adds the same theme1/theme2 preview surface to all 44 dwf-* product pages\nvia the shared productPage() template. Since dw-domain-fleet has no admin\nauth, gate is by URL query param (?theme=2 → flip to theme2, persisted\nin localStorage 'wallco-page-theme'). Toggle UI is hidden until theme2\nmode is active so default visitors see vanilla theme1."},{"hash":"661cbec","date":"2026-05-28 17:46:37 -0700","author":"Steve Abrams","subject":"shared/render.js: scrub head-baked vendor from product titles (audit 2026-05-28 task#53 addendum). scrubTags closed the tag-chip leak; titles like 'Versace 4 Metallic Wallcovering' still leaked the vendor via card-title + data-title (→ quick-view modal title + aria-label) + productPage <h1>/<title>/og:title. Add scrubTitleLead() (denylist-driven leading-vendor stripper, mirrors stripLeadVendor in _shared/api-vendor-redact.js but on THIS file's VENDORS_DENYLIST so chip+title stay on one list) + displayTitle() helper used by both card() and productPage() so the two derivations stay identical. House-brand-led names preserved; empty/generic remainder falls back to 'Designer Wallcovering'. CANARY-verified on designermagnetics.com (526 products): /catalog + /product visible-text vendor hits 0 (was: Versace in card-title+data-title), 0 empty/mangled titles, house brand preserved 67x. NOT DEPLOYED — follow-up tick fans out deploy + fleet-wide rendered-DOM re-verify per drift-aware plan.","body":""},{"hash":"82e0968","date":"2026-05-28 16:58:20 -0700","author":"Steve Abrams","subject":"shared/render.js: scrub vendor names from tag-chips fleet-wide (closes audit 2026-05-28 task#53 HIGH finding). Add scrubTags() helper with 47-vendor denylist (mirrors _shared/sku-redact.js + adds Kravet, de Gournay, Romo, Farrow & Ball, Colefax & Fowler, Sanderson, Morris & Co, Osborne & Little — all surfaced by the audit or missing from the prior denylist). Apply at both leak points: card data-tags attribute (feeds quick-view modal chips) + productPage <span> chip strip. Verified: 7 audit-leaked vendors filtered (Brunschwig & Fils, Kravet, Schumacher, Maya Romanoff, Lee Jofa, de Gournay, Romo), house brands preserved (Designer Wallcoverings, Hollywood). NOT YET DEPLOYED — awaiting Steve sign-off + drift-aware deploy plan.","body":""},{"hash":"af735a7","date":"2026-05-28 16:55:24 -0700","author":"Steve Abrams","subject":"shared/render.js: reconcile prod drift — pull equalize toolbar markup (ctl-sort + ctl-density flex wrappers + space-between + range/search flex constraints) back into Mac2 source after directly-on-prod shipping earlier today. Mac2's card-hover-effect (aa83057) preserved untouched. Hashes now align on the equalize feature; only card-hover (4 CSS + 1 HTML line) remains Mac2-ahead.","body":""},{"hash":"aa83057","date":"2026-05-28 10:54:51 -0700","author":"Steve Abrams","subject":"shared/render.js: universal hover-preview — stamp --card-bg on card-img inline style + ::after pseudo-element shows 3×3 tile-repeat of the same image on :hover (reveals the seamless pattern structure). One edit applies to all 44 sister sites in dw-domain-fleet/sites/ on next restart. prefers-reduced-motion guarded.","body":"Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"},{"hash":"1e6fa79","date":"2026-05-19 21:50:31 -0700","author":"SteveStudio2","subject":"catalog: hydrate sort dropdown + density slider from localStorage before first paint","body":"Density already read its saved value but the apply() races the initial --cols:5\nemitted in CSS, so users with a saved density saw a brief flash. Add a clear\n\"before first paint\" comment to lock the ordering.\n\nSort dropdown was write-only — change events persisted to localStorage but a\nfresh /catalog visit always rendered with the server's selected=\"newest\". Now,\nwhen the URL has no ?sort= override, the dropdown hydrates from localStorage\n(validated against the known option set) so the user's last choice surfaces.\nThe form still posts ?sort=<value> on next change so the server-rendered list\nmatches what the dropdown shows. Pure client-side; catalog query, sortProducts,\nand product resolution untouched.\n\nFleet-wide change since render.js is the shared template for all 44 sites.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"},{"hash":"febdfbc","date":"2026-05-19 21:49:16 -0700","author":"SteveStudio2","subject":"chore: broaden .gitignore — snapshot/editor cruft (*.bak, *.orig, *.rej, *.swp, *~, *.pre-*)","body":"Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"},{"hash":"46abc9e","date":"2026-05-19 11:22:25 -0700","author":"SteveStudio2","subject":"feat: clean fleet /product/ slugs — productSlug() strips 'wallpaper'; handle kept verbatim for Shopify canonical+sample; dual-key route resolves old+new URLs","body":""},{"hash":"5004030","date":"2026-05-19 11:12:51 -0700","author":"SteveStudio2","subject":"fix: restore lost pattern name on 4 William Morris products (Fruit | William Morris)","body":""},{"hash":"2481a30","date":"2026-05-19 09:24:08 -0700","author":"SteveStudio2","subject":"fix: theme toggle occluded by hamburger (now fixed-position z-101 left of menu); blank-title fallback to SKU for malformed catalog rows","body":"Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"},{"hash":"d0f30c2","date":"2026-05-19 09:10:23 -0700","author":"SteveStudio2","subject":"DNS cutover batches 4-5 complete (idx 27-43): 44/44 fleet HTTPS verified","body":""},{"hash":"8b73567","date":"2026-05-19 08:57:26 -0700","author":"SteveStudio2","subject":"DNS cutover batch 5 (idx 36-43): 8/8 live HTTPS 200 — fleet cutover complete 44/44","body":""},{"hash":"26f2aef","date":"2026-05-19 08:51:30 -0700","author":"SteveStudio2","subject":"Add /info page, trim navpanel to 4 items, sun/moon theme toggle","body":"TASK 1: New per-site /info page (infoPage in shared/render.js + /info\nroute in server.js) — Memo Samples, Trade Program, Shipping & Lead\nTimes, FAQ. cfg-driven, no vendor names, no banned 'wallpaper' word,\nrel=canonical to the site's own /info.\n\nTASK 2: Navpanel now exactly 4 items — Designs, About, Info, Contact.\n\nTASK 3: Theme toggle shows a sun in light mode, moon in dark mode —\nboth SVGs in the button, swapped via CSS keyed on html[data-theme=dark],\nno JS change so it survives the anti-flash inline script.\n\nVerified: node -c passes both files; grassclothwallcovering booted on\n:10999 — /, /info, /about, /catalog all 200; /info renders all 4\nsections; nav shows the 4 items; no 'wallpaper' in /info copy.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"},{"hash":"40eaabd","date":"2026-05-19 08:51:16 -0700","author":"SteveStudio2","subject":"DNS cutover batch 4 (idx 27-35): 9/9 live HTTPS 200","body":""},{"hash":"1e65c59","date":"2026-05-19 08:39:03 -0700","author":"SteveStudio2","subject":"DNS cutover batch 3 (idx 18-26): SSL+HTTPS verified","body":""},{"hash":"cfc34cd","date":"2026-05-19 08:31:08 -0700","author":"SteveStudio2","subject":"DNS cutover batch 3 (idx 18-26): 9/9 live HTTPS 200","body":""},{"hash":"f84402b","date":"2026-05-19 08:10:42 -0700","author":"SteveStudio2","subject":"DNS cutover batch 2 (idx 9-17): 9/9 live HTTPS 200","body":""},{"hash":"42bb3e2","date":"2026-05-19 08:01:37 -0700","author":"SteveStudio2","subject":"DNS cutover batch 1 (idx 0-8): 9/9 live HTTPS 200 + nginx blocker resolved","body":""},{"hash":"b9e4a69","date":"2026-05-19 07:53:45 -0700","author":"SteveStudio2","subject":"fleet: DEPLOY+SMOKE phase — 44/44 deployed to Kamatera, all online ports 10001-10044, 44/44 origin smoke pass; log nginx typo-redirect-1800wallcoverings conflict blocker","body":""},{"hash":"b57956d","date":"2026-05-18 20:54:23 -0700","author":"SteveStudio2","subject":"fleet: STEP 2 — re-port fleet-44 to 10001-10044 (clear collision with sister sites on 9901-9944); regenerate ecosystem + nginx + sync site config ports; 44/44 boot-test pass","body":""},{"hash":"2186562","date":"2026-05-18 20:44:10 -0700","author":"SteveStudio2","subject":"fleet: SCOPE CORRECTION 66→44 (dtd Option B split) — 22 domains stay 301 redirects; add asseeninmovies; product pages with rel=canonical→main store + per-site title/meta; crawlable card links","body":""},{"hash":"32e95f9","date":"2026-05-18 20:38:37 -0700","author":"Steve","subject":"fleet: DNS cutover + SSL + deploy scripts, PROGRESS.md","body":""},{"hash":"d1bbf07","date":"2026-05-18 20:37:01 -0700","author":"Steve","subject":"fleet: explicit display-name overrides, ecosystem + nginx generators, boot-test (65/65 pass)","body":""},{"hash":"fb983c1","date":"2026-05-18 20:34:01 -0700","author":"Steve","subject":"dw-domain-fleet: shared parameterized microsite server + 65 site configs; grasscloth exemplar verified locally","body":""}]}