← back to Tk10630 Sku Suffix Canary

leak-audit.mjs.bak

53 lines

// Full-surface private-label LEAK audit for the Hollywood line. READ-ONLY.
// Flags any customer-facing (and known leak-prone) surface exposing the forbidden
// upstream names: "Versa", "Versa Designed Surfaces", "Momentum".
import { gql } from './shopify.mjs';
import { writeFileSync } from 'node:fs';

const LEAK = /versa|momentum/i;
const PAGE = `query($c:String){
  products(first:40, query:"vendor:\\"Hollywood Wallcoverings\\"", after:$c){
    pageInfo{ hasNextPage endCursor }
    nodes{
      id handle title status vendor productType tags bodyHtml
      images(first:5){ nodes{ altText src } }
      grade:  metafield(namespace:"dwc", key:"grade_collection"){ value }
      rv:     metafield(namespace:"dwc", key:"real_vendor"){ value }
      instpdf:metafield(namespace:"dwc", key:"installation_pdf"){ value }
      collections(first:10){ nodes{ title } }
    }
  }
}`;
const sleep = ms => new Promise(r => setTimeout(r, ms));

// per-surface counters (customer-facing surfaces first, then leak-prone metafields)
const surf = { handle: 0, title: 0, tags: 0, bodyHtml: 0, image_alt: 0, image_src: 0, productType: 0, collection: 0, vendor: 0,
  mf_grade_collection: 0, mf_real_vendor: 0, mf_installation_pdf: 0 };
const CUSTOMER_FACING = ['handle', 'title', 'tags', 'bodyHtml', 'image_alt', 'image_src', 'productType', 'collection', 'vendor'];
let scanned = 0, anyLeak = 0, activeLeak = 0, cursor = null;
const leakers = new Set(), activeLeakers = new Set(); const examples = {};

function hit(k, p) { surf[k]++; if (!examples[k]) examples[k] = `${p.handle} (${p.status})`; }

while (true) {
  let res;
  for (let a = 0; ; a++) { try { res = await gql(PAGE, { cursor }); break; }
    catch (e) { if (/THROTTLED/i.test(e.message) && a < 8) { await sleep(2000 * (a + 1)); continue; } throw e; } }
  for (const p of res.data.products.nodes) {
    scanned++;
    let leaked = false;
    const flag = (k, v) => { if (LEAK.test(v || '')) { hit(k, p); if (CUSTOMER_FACING.includes(k)) leaked = true; } };
    flag('handle', p.handle); flag('title', p.title); flag('vendor', p.vendor);
    flag('productType', p.productType); flag('tags', (p.tags || []).join(' ')); flag('bodyHtml', p.bodyHtml);
    for (const im of p.images.nodes) { flag('image_alt', im.altText); flag('image_src', decodeURIComponent(im.src || '')); }
    for (const c of p.collections.nodes) flag('collection', c.title);
    flag('mf_grade_collection', p.grade?.value); flag('mf_real_vendor', p.rv?.value); flag('mf_installation_pdf', p.instpdf?.value);
    if (leaked) { anyLeak++; leakers.add(p.handle); if (p.status === 'ACTIVE') { activeLeak++; activeLeakers.add(p.handle); } }
  }
  if (!res.data.products.pageInfo.hasNextPage) break;
  cursor = res.data.products.pageInfo.endCursor;
  if (scanned % 800 === 0) process.stderr.write(`  ...${scanned} scanned, ${anyLeak} customer-facing leakers\n`);
}
writeFileSync('leak-audit-result.json', JSON.stringify({ scanned, anyLeak, activeLeak, surf, examples }, null, 2));
console.log(JSON.stringify({ scanned, customer_facing_leakers: anyLeak, active_customer_facing_leakers: activeLeak, by_surface: surf, examples }, null, 2));