← back to Tk10630 Sku Suffix Canary
leak-audit.mjs
56 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:100, query:"vendor:\\"Hollywood Wallcoverings\\"", after:$c){
pageInfo{ hasNextPage endCursor }
nodes{
id handle title status vendor productType tags
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(' '));
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;
const next = res.data.products.pageInfo.endCursor;
if (next === cursor) { process.stderr.write('CURSOR STUCK — breaking\n'); break; } // anti-loop guard
cursor = next;
if (scanned > 8000) { process.stderr.write(`SAFETY BREAK at ${scanned} (exceeds product count)\n`); break; }
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));