[object Object]

← back to Hollywood Import

generator forward-fix revised to DTD-C: HW-<deterministic opaque hash of Momentum number>; raw number internal-only; collision-guarded; kill-switch frozen

3844a4f6e534471764dfc95262b32a0a2057d8c2 · 2026-08-17 17:12:06 -0700 · steve

Files touched

Diff

commit 3844a4f6e534471764dfc95262b32a0a2057d8c2
Author: steve <steve@designerwallcoverings.com>
Date:   Mon Aug 17 17:12:06 2026 -0700

    generator forward-fix revised to DTD-C: HW-<deterministic opaque hash of Momentum number>; raw number internal-only; collision-guarded; kill-switch frozen
---
 momentum-feed/assign-sku.mjs | 24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/momentum-feed/assign-sku.mjs b/momentum-feed/assign-sku.mjs
index e41e3e1..39f9fdf 100644
--- a/momentum-feed/assign-sku.mjs
+++ b/momentum-feed/assign-sku.mjs
@@ -18,6 +18,7 @@ const COMMIT = process.argv.includes('--commit');
 // `number` / manufacturer_sku, not a minted DW code). The kill-switch halts
 // the daily drip; this guard also blocks a direct `--commit` re-mint.
 import { existsSync } from 'node:fs';
+import { createHash } from 'node:crypto';
 if (COMMIT && existsSync(`${process.env.HOME}/.dw-fixer-stop`)) {
   console.error('[assign-sku] BLOCKED: ~/.dw-fixer-stop present. DWHD minting is FROZEN (brand-as-vendor bug, TK-10634). Remove the kill-switch only after the real-code redesign.');
   process.exit(3);
@@ -58,12 +59,17 @@ function buildPool(need, used) {
 async function main() {
   const used = (await pool.query(`SELECT DISTINCT pl_city_name c FROM momentum_colorways WHERE pl_city_name IS NOT NULL`))
     .rows.map(r => r.c).filter(Boolean);
-  // --- FORWARD-FIX (DTD-B, 2026-08-17): mint a Hollywood PRIVATE-LABEL code from the REAL
-  // Momentum number, NOT a sequential DW-vendor DWHD mint. The prefix is the private-label
-  // wrapper (Hollywood), the number is the product's real identity; the raw number is ALSO
-  // kept internal in manufacturer_sku. NEVER the bare number customer-facing ("always pl
-  // momentum"), NEVER a sequential mint divorced from the product. Prefix is configurable. ---
+  // --- FORWARD-FIX (DTD verdict C, 2026-08-17): the customer-facing SKU = Hollywood prefix +
+  // a DETERMINISTIC, OPAQUE transform of the real Momentum number — NOT the raw number and
+  // NOT a stateful sequential mint. Why C over "HW-<raw number>": the variant SKU propagates
+  // to the Google/Meta merchant feed, order emails, packing slips, and CSV/EDI exports, so a
+  // raw Momentum number there is one prefix-strip from a momentumco.com lookup = a private-
+  // label LEAK ("always pl momentum"). The hash is deterministic (same number → same code,
+  // idempotent, no counter to drift like DWHD) AND opaque (competitor-safe). The RAW number
+  // stays ONLY in the internal manufacturer_sku metafield. Prefix + hash length configurable.
   const PL_PREFIX = process.env.HW_PL_PREFIX || 'HW';
+  const HASH_LEN = Number(process.env.HW_HASH_LEN || 12); // hex chars; 12 = 48 bits ≈ collision-free at catalog scale (guarded below)
+  const plSku = num => `${PL_PREFIX}-${createHash('sha256').update(String(num)).digest('hex').slice(0, HASH_LEN).toUpperCase()}`;
   // Deterministic order: WC before Acoustic, then pattern, then colorway.
   const { rows } = await pool.query(
     `SELECT id, pattern_name, color_name, color_number, category, momentum_sku FROM momentum_colorways
@@ -76,12 +82,12 @@ async function main() {
   if (pool2.length < patterns.length) throw new Error(`pool short: ${pool2.length} < ${patterns.length}`);
   const cityOf = new Map(patterns.map((p, i) => [p, pool2[i]]));
 
-  const plan = codeable.map(r => ({ id: r.id, dw_sku: `${PL_PREFIX}-${r.momentum_sku}`, city: cityOf.get(r.pattern_name),
+  const plan = codeable.map(r => ({ id: r.id, dw_sku: plSku(r.momentum_sku), city: cityOf.get(r.pattern_name),
     pattern: r.pattern_name, color: r.color_name, cat: r.category, mfr: r.momentum_sku }));
-  // collision guard: a real number appearing twice would collide (must be unique)
+  // collision guard: fail loud if the opaque transform ever collides (raise HW_HASH_LEN)
   const codes = plan.map(p => p.dw_sku);
-  if (new Set(codes).size !== codes.length) throw new Error('duplicate momentum_sku → SKU collision; aborting');
-  console.log(`assign-sku (forward-fix ${PL_PREFIX}-<number>): ${plan.length} colorways / ${patterns.length} patterns. SKIPPED ${noNumber.length} with no momentum_sku (need real number).`);
+  if (new Set(codes).size !== codes.length) throw new Error('opaque-SKU hash collision → raise HW_HASH_LEN; aborting');
+  console.log(`assign-sku (forward-fix ${PL_PREFIX}-<opaque hash>): ${plan.length} colorways / ${patterns.length} patterns. SKIPPED ${noNumber.length} with no momentum_sku. Raw number stays in manufacturer_sku only.`);
   console.log('  samples:'); plan.slice(0, 4).forEach(p => console.log(`    ${p.dw_sku}  ${p.cat}  "${p.pattern}" / ${p.color}  → ${p.city}`));
 
   if (!COMMIT) { console.log('DRY-RUN — re-run with --commit to write.'); await pool.end(); return; }

← 61c9a76 TK-10634 generator forward-fix (DTD-B): mint HW-<real moment  ·  back to Hollywood Import  ·  TK-10679: add ^DWHD/DWHW2 SKU-shape guard to hollywood-creat f7109e8 →