← back to Dw Marketing Reels

scripts/leak-deny.mjs

36 lines

// Single source of truth for the private-label / upstream-vendor LEAK denylist used
// across the reels pipeline (build-reel, build-colorwheel-reel, fetch-new-arrivals,
// scan-leaks). These names must NEVER surface on a public IG/TikTok post or slide card.
//
// SYNCED TO CANONICAL: ~/.claude/skills/dw-leak-scanner/denylist.json is the fleet
// source of truth. When that list changes, mirror it here (and in the rotation-activator
// leak guard). Previously this list was hand-copied into 3 builder files and DRIFTED —
// it was missing `lillian august` (which actually leaked 2026-07-06), `rigo`, `rigowall`.
// Consolidated here 2026-07-27 so a caption/card leak can't slip through one stale copy.
//
// Per-term anchoring mirrors the canonical FP notes:
//   • unambiguous names           → substring match (also catches concatenated handles)
//   • `versa` (Momentum sub-brand) → LEADING boundary: catches "Versa" + "versadesignedsurfaces"
//     yet stays safe on "Adversarial"/"conversation"/"Universal"/"Anniversary"
//   • `rigo`  (RIGO Wallcovering)  → BOTH boundaries: canonical note "Rigoletto etc. don't match"
const PARTS = [
  // unambiguous upstream/private-label names — substring (case-insensitive)
  'greenland', 'wallquest', 'chesapeake', 'nextwall', 'seabrook', 'brewster',
  'momentum', 'desima', 'carlsten', 'yorkwall', 'rigowall',
  'nicolette\\s*mayer', 'york\\s*wall', 'command\\s*54',
  'lillian\\s*august',            // Lillian August (Seabrook/York) → PR coastal; leaked 2026-07-06
  'versa\\s+designed\\s+surfaces',
  'rigo\\s+wallcovering',
  // ambiguous short tokens — anchored per canonical notes
  '\\bversa',                     // leading boundary (standalone + concatenated), FP-safe
  '\\brigo\\b',                   // both boundaries — protect "Rigoletto"
];

export const LEAK_DENY = new RegExp(PARTS.join('|'), 'i');

// True when a private-label name is present anywhere in `s`.
export const isLeak = s => LEAK_DENY.test(String(s || ''));

// True when `s` is non-empty AND carries no leak (the builders' existing `safe()` contract).
export const safe = s => !!s && !LEAK_DENY.test(s);