← back to Designer Wallcoverings
fix(TK-10965): guard remaining importer inventory-stamp sites (completeness pass)
00ba31fa2e0d19a31fb489155dea216d117358c4 · 2026-08-30 23:41:55 -0700 · Steve
Completeness pass over the 7 remaining unguarded 2026 inventory-stamp sites
found after b83a37b.
Guarded (real sellable stamps, now route through safeStampQuantity):
- shopify/scripts/cadence/remediate-channels-inventory.js — SCAN now fetches
variant price + product tags; a $0/quote-only sellable variant is no longer
pushed to skusToSet (never stamped 2026). Wolf Gordon/LA-Fabrics/Innovations
$0 quote lines were the real risk.
- DW-Programming/ralph-lauren-fabric-updater-9899.js — variants query fetches
title/price + product tags/vendor; the per-variant quantity flows through
safeStampQuantity. RL fabrics are priced (defensive-only) but guarded regardless.
Intentionally UNGUARDED, comment added so a future audit doesn't re-flag:
- shopify/scripts/add-missing-samples-v2.js — stamps the new $4.25 Sample only.
- shopify/scripts/fix-samples-graphql.js — creates the $4.25 Sample only.
No live stamp in code (2026 was a header-comment claim only) — clarifying note added:
- DW-Programming/as-creation-shopify-push.js
- DW-Programming/hollywood-shopify-push.js
- shopify/scripts/wolf-gordon-shopify-push.js
Behavior-preserving for all priced lines. node --check passes on all 7; guard
require() resolves + behaves from both new locations (Node v26 require(esm)).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M DW-Programming/as-creation-shopify-push.jsM DW-Programming/hollywood-shopify-push.jsM DW-Programming/ralph-lauren-fabric-updater-9899.jsM shopify/scripts/add-missing-samples-v2.jsM shopify/scripts/cadence/remediate-channels-inventory.jsM shopify/scripts/fix-samples-graphql.jsM shopify/scripts/wolf-gordon-shopify-push.js
Diff
commit 00ba31fa2e0d19a31fb489155dea216d117358c4
Author: Steve <steve@designerwallcoverings.com>
Date: Sun Aug 30 23:41:55 2026 -0700
fix(TK-10965): guard remaining importer inventory-stamp sites (completeness pass)
Completeness pass over the 7 remaining unguarded 2026 inventory-stamp sites
found after b83a37b.
Guarded (real sellable stamps, now route through safeStampQuantity):
- shopify/scripts/cadence/remediate-channels-inventory.js — SCAN now fetches
variant price + product tags; a $0/quote-only sellable variant is no longer
pushed to skusToSet (never stamped 2026). Wolf Gordon/LA-Fabrics/Innovations
$0 quote lines were the real risk.
- DW-Programming/ralph-lauren-fabric-updater-9899.js — variants query fetches
title/price + product tags/vendor; the per-variant quantity flows through
safeStampQuantity. RL fabrics are priced (defensive-only) but guarded regardless.
Intentionally UNGUARDED, comment added so a future audit doesn't re-flag:
- shopify/scripts/add-missing-samples-v2.js — stamps the new $4.25 Sample only.
- shopify/scripts/fix-samples-graphql.js — creates the $4.25 Sample only.
No live stamp in code (2026 was a header-comment claim only) — clarifying note added:
- DW-Programming/as-creation-shopify-push.js
- DW-Programming/hollywood-shopify-push.js
- shopify/scripts/wolf-gordon-shopify-push.js
Behavior-preserving for all priced lines. node --check passes on all 7; guard
require() resolves + behaves from both new locations (Node v26 require(esm)).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
DW-Programming/as-creation-shopify-push.js | 8 +++++++-
DW-Programming/hollywood-shopify-push.js | 8 +++++++-
DW-Programming/ralph-lauren-fabric-updater-9899.js | 21 +++++++++++++++++++--
shopify/scripts/add-missing-samples-v2.js | 4 ++++
.../cadence/remediate-channels-inventory.js | 14 ++++++++++++--
shopify/scripts/fix-samples-graphql.js | 4 ++++
shopify/scripts/wolf-gordon-shopify-push.js | Bin 22923 -> 23475 bytes
7 files changed, 53 insertions(+), 6 deletions(-)
diff --git a/DW-Programming/as-creation-shopify-push.js b/DW-Programming/as-creation-shopify-push.js
index 98c25c0e..cc6c9cab 100644
--- a/DW-Programming/as-creation-shopify-push.js
+++ b/DW-Programming/as-creation-shopify-push.js
@@ -10,9 +10,15 @@
* Body: 3 sentences from AI description, NO specs
* Sample variant: $4.25, weight 0
* Roll variant: price from DB or $0, weight 2 lbs
- * inventory_quantity: 2026 for all variants
+ * inventory_quantity: 2026 for all variants (documentation only — see TK-10965 note)
* Residential vendor — fire_rating: "Inquire for more Information"
*
+ * TK-10965 note: this "2026" is a DOCUMENTATION claim, not a code stamp. This script
+ * only ENQUEUES productCreate + _launchPadFollowUp jobs (no inventory literal in the
+ * payload — buildVariants sets no inventory_quantity). Inventory is stamped later by
+ * the queue worker / cadence path, which already routes through the inventory-stamp
+ * guard (safeStampQuantity). Nothing to guard here.
+ *
* Usage:
* node as-creation-shopify-push.js # Queue first 25 (Launch Pad batch)
* node as-creation-shopify-push.js --limit 100 # Queue first 100
diff --git a/DW-Programming/hollywood-shopify-push.js b/DW-Programming/hollywood-shopify-push.js
index fbd3e7f7..a97612aa 100644
--- a/DW-Programming/hollywood-shopify-push.js
+++ b/DW-Programming/hollywood-shopify-push.js
@@ -10,7 +10,13 @@
* Body: 3 sentences from AI description, NO specs
* Sample variant: $4.25, weight 0
* Roll variant: $0 (quote model), weight 2 lbs
- * inventory_quantity: 2026 for all variants
+ * inventory_quantity: 2026 for all variants (documentation only — see TK-10965 note)
+ *
+ * TK-10965 note: this "2026" is a DOCUMENTATION claim, not a code stamp. This script
+ * builds a productCreate payload whose buildVariants sets NO inventory_quantity literal
+ * (Sample @ $4.25, roll @ $0.00). Inventory is stamped downstream by the queue worker /
+ * cadence path, which already routes through the inventory-stamp guard. Nothing to
+ * guard here.
*
* Usage:
* node hollywood-shopify-push.js # Queue first 25 (Launch Pad batch)
diff --git a/DW-Programming/ralph-lauren-fabric-updater-9899.js b/DW-Programming/ralph-lauren-fabric-updater-9899.js
index 0fb52a29..d48c4375 100644
--- a/DW-Programming/ralph-lauren-fabric-updater-9899.js
+++ b/DW-Programming/ralph-lauren-fabric-updater-9899.js
@@ -17,6 +17,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
Object.defineProperty(exports, "__esModule", { value: true });
const express_1 = __importDefault(require("express"));
const playwright_1 = require("playwright");
+// TK-10965: never stock a $0/quote-only SELLABLE variant (inventory-stamp guard)
+const { safeStampQuantity } = require("../shopify/scripts/lib/inventory-stamp-guard.mjs");
const app = (0, express_1.default)();
const PORT = 9899;
// Shopify Configuration
@@ -1573,11 +1575,15 @@ async function updateProduct(product, specs, aiAnalysis, needsReview = false //
const variantsQuery = `
query {
product(id: "${product.id}") {
+ tags
+ vendor
variants(first: 10) {
edges {
node {
id
sku
+ title
+ price
inventoryItem {
id
}
@@ -1596,6 +1602,10 @@ async function updateProduct(product, specs, aiAnalysis, needsReview = false //
body: JSON.stringify({ query: variantsQuery }),
});
const variantsData = await variantsResponse.json();
+ const productForGuard = {
+ tags: variantsData.data?.product?.tags || [],
+ vendor: variantsData.data?.product?.vendor || '',
+ };
const variants = variantsData.data?.product?.variants?.edges || [];
// Get location ID
const locationQuery = `query { locations(first: 1) { edges { node { id } } } }`;
@@ -1614,6 +1624,13 @@ async function updateProduct(product, specs, aiAnalysis, needsReview = false //
for (const variant of variants) {
const inventoryItemId = variant.node.inventoryItem?.id;
if (inventoryItemId) {
+ // TK-10965: route the stamp through the guard — a $0/quote-only
+ // SELLABLE variant gets 0 (never positive stock); the Sample and
+ // normal priced variants get 2026 unchanged (behavior-preserving).
+ const stampQty = safeStampQuantity(
+ { title: variant.node.title, price: variant.node.price },
+ productForGuard
+ );
const setInventoryMutation = `
mutation {
inventorySetOnHandQuantities(
@@ -1622,7 +1639,7 @@ async function updateProduct(product, specs, aiAnalysis, needsReview = false //
setQuantities: [{
inventoryItemId: "${inventoryItemId}"
locationId: "${locationId}"
- quantity: 2026
+ quantity: ${stampQty}
}]
}
) {
@@ -1639,7 +1656,7 @@ async function updateProduct(product, specs, aiAnalysis, needsReview = false //
body: JSON.stringify({ query: setInventoryMutation }),
});
await sleep(100);
- console.log(` 📦 Set inventory to 2026 for ${variant.node.sku || 'variant'}`);
+ console.log(` 📦 Set inventory to ${stampQty} for ${variant.node.sku || 'variant'}`);
}
}
}
diff --git a/shopify/scripts/add-missing-samples-v2.js b/shopify/scripts/add-missing-samples-v2.js
index 14575b6a..60d28ec1 100644
--- a/shopify/scripts/add-missing-samples-v2.js
+++ b/shopify/scripts/add-missing-samples-v2.js
@@ -232,6 +232,10 @@ async function scanProducts(progress, args) {
}
// ─── Create ────────────────────────────────────────────────────────────
+// TK-10965: this 2026 stamp is INTENTIONALLY UNGUARDED. It only ever fires on the
+// newly-created $4.25 Sample variant (createMissingVariants passes the Sample's
+// inventory_item_id) — positive Sample stock is by-design. The inventory-stamp guard
+// only zeroes a SELLABLE ($0/quote-only) variant, so it does not apply here.
async function setInventory(inventoryItemId) {
const mutation = `
mutation ($input: InventorySetQuantitiesInput!) {
diff --git a/shopify/scripts/cadence/remediate-channels-inventory.js b/shopify/scripts/cadence/remediate-channels-inventory.js
index 4bc50be7..b2e3bfd6 100644
--- a/shopify/scripts/cadence/remediate-channels-inventory.js
+++ b/shopify/scripts/cadence/remediate-channels-inventory.js
@@ -36,6 +36,7 @@ const RECENT = parseInt(val('--recent', '1000'), 10); // else: last N active pro
const TOTAL_CHANNELS = 13;
const { isInternal } = require('../lib/internal-guard.js'); // never publish an INTERNAL line to sales channels
+const { safeStampQuantity } = require('../lib/inventory-stamp-guard.mjs'); // TK-10965: never stock a $0/quote-only sellable variant
const env = fs.readFileSync(os.homedir() + '/Projects/secrets-manager/.env', 'utf8');
const TOKEN = (env.match(/^SHOPIFY_ADMIN_TOKEN=(.*)$/m) || [])[1].replace(/['"]/g, '').trim();
@@ -121,7 +122,8 @@ async function setInventory2026(skus) {
}
// ---- scan: iterate the cohort, classify each ACTIVE product ----
-const SCAN = `query($q:String!,$cursor:String){products(first:50,query:$q,sortKey:CREATED_AT,reverse:true,after:$cursor){pageInfo{hasNextPage endCursor}edges{node{id title status vendor resourcePublicationsCount{count} variants(first:10){edges{node{sku inventoryQuantity}}}}}}}`;
+// TK-10965: fetch tags + variant price so the sellable stamp routes through safeStampQuantity
+const SCAN = `query($q:String!,$cursor:String){products(first:50,query:$q,sortKey:CREATED_AT,reverse:true,after:$cursor){pageInfo{hasNextPage endCursor}edges{node{id title status vendor tags resourcePublicationsCount{count} variants(first:10){edges{node{sku price inventoryQuantity}}}}}}}`;
(async () => {
if (!TOKEN) { console.error('no SHOPIFY_ADMIN_TOKEN'); process.exit(1); }
@@ -163,7 +165,15 @@ const SCAN = `query($q:String!,$cursor:String){products(first:50,query:$q,sortKe
}
if (!invOk) {
needInv++;
- for (const v of sellable) if (v.sku && v.inventoryQuantity !== 2026) skusToSet.push(v.sku);
+ // TK-10965: only stamp 2026 on a sellable variant the guard says is SAFE.
+ // safeStampQuantity returns 0 for a $0-priced or quote-only/price-suppressed
+ // sellable variant — those must never receive positive stock (would make a
+ // $0 line checkout-orderable). Feed title=sku so the -Sample suffix classifies.
+ for (const v of sellable) {
+ if (!v.sku || v.inventoryQuantity === 2026) continue;
+ const safe = safeStampQuantity({ title: v.sku, price: v.price }, { tags: n.tags, vendor: n.vendor });
+ if (safe === 2026) skusToSet.push(v.sku);
+ }
}
}
cursor = conn.pageInfo.hasNextPage ? conn.pageInfo.endCursor : null;
diff --git a/shopify/scripts/fix-samples-graphql.js b/shopify/scripts/fix-samples-graphql.js
index a8c0d7e8..d71fdc46 100644
--- a/shopify/scripts/fix-samples-graphql.js
+++ b/shopify/scripts/fix-samples-graphql.js
@@ -198,6 +198,10 @@ async function createSampleVariant(productId, optionName, baseSku) {
}
}`;
+ // TK-10965: this 2026 stamp is INTENTIONALLY UNGUARDED — it creates the $4.25
+ // Sample variant only (name: "Sample"), and positive Sample stock is by-design.
+ // The inventory-stamp guard only zeroes a SELLABLE ($0/quote-only) variant, not
+ // the Sample, so it does not apply here.
const variantInput = {
price: "4.25",
optionValues: [{ optionName, name: "Sample" }],
diff --git a/shopify/scripts/wolf-gordon-shopify-push.js b/shopify/scripts/wolf-gordon-shopify-push.js
index c346fdc7..ea74547b 100644
Binary files a/shopify/scripts/wolf-gordon-shopify-push.js and b/shopify/scripts/wolf-gordon-shopify-push.js differ
← b83a37b1 fix(TK-10965): guard importer inventory stamp — never stock
·
back to Designer Wallcoverings
·
auto-data-snapshot: 2026-08-31T00:07:16 (2 data files) — sho db57aff5 →