← back to Dw Gemini Skip TK11321
Fail closed on malformed activation fields
c4f1747624c2d4fa9a27931a9b01e177358b60cf · 2026-08-28 21:40:54 -0700 · Steve Abrams
Files touched
M lib/five-field-extra.jsM test/five-field-extra.test.jsM verification/e2e-proof.json
Diff
commit c4f1747624c2d4fa9a27931a9b01e177358b60cf
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Fri Aug 28 21:40:54 2026 -0700
Fail closed on malformed activation fields
---
lib/five-field-extra.js | 16 +++++++++++++---
test/five-field-extra.test.js | 25 ++++++++++++++++++++++++-
verification/e2e-proof.json | 8 +++++---
3 files changed, 42 insertions(+), 7 deletions(-)
diff --git a/lib/five-field-extra.js b/lib/five-field-extra.js
index 87548f2..6fd9940 100644
--- a/lib/five-field-extra.js
+++ b/lib/five-field-extra.js
@@ -1,13 +1,23 @@
'use strict';
function fiveFieldExtra(product) {
- const variants = product?.variants?.nodes || [];
- const tags = product?.tags || [];
+ const hasValidVariantsShape = Array.isArray(product?.variants?.nodes);
+ const hasValidTagsShape = Array.isArray(product?.tags);
+ const variants = hasValidVariantsShape ? product.variants.nodes : [];
+ const tags = hasValidTagsShape
+ ? product.tags.map((tag) => String(tag).trim().toLowerCase())
+ : [];
const hasSample = variants.some((variant) => /-sample$/i.test(variant.sku || ''));
const sellable = variants.filter((variant) => !/-sample$/i.test(variant.sku || ''));
- const hasSellablePriced = sellable.some((variant) => Number.parseFloat(variant.price) > 0);
+ const hasSellablePriced = sellable.some((variant) => {
+ if (typeof variant.price !== 'string' || !/^\d+(?:\.\d+)?$/.test(variant.price)) return false;
+ const price = Number(variant.price);
+ return Number.isFinite(price) && price > 0;
+ });
const isQuoteOnly = tags.includes('quotes');
const reasons = [];
+ if (!hasValidVariantsShape) reasons.push('invalid-variants-shape');
+ if (!hasValidTagsShape) reasons.push('invalid-tags-shape');
if (!hasSample) reasons.push('no-sample-variant');
if (!sellable.length && !isQuoteOnly) reasons.push('no-sellable-variant');
if (!hasSellablePriced && !isQuoteOnly) reasons.push('sellable-price-not-gt-0');
diff --git a/test/five-field-extra.test.js b/test/five-field-extra.test.js
index be1ee1b..8e68d11 100644
--- a/test/five-field-extra.test.js
+++ b/test/five-field-extra.test.js
@@ -18,7 +18,7 @@ test('fails closed without a sample', () => {
});
test('rejects missing, zero, malformed, and negative sellable prices', () => {
- for (const price of [undefined, '', '0', 'not-a-price', '-1']) {
+ for (const price of [undefined, '', '0', 'not-a-price', '-1', '125 USD', '1e309']) {
const result = fiveFieldExtra(product([
{ sku: 'DW-100-SAMPLE', price: '5.00' }, { sku: 'DW-100', price },
]));
@@ -27,6 +27,29 @@ test('rejects missing, zero, malformed, and negative sellable prices', () => {
}
});
+test('fails closed on non-array variants and tags with explicit shape reasons', () => {
+ const variants = [{ sku: 'DW-100-SAMPLE', price: '5.00' }, { sku: 'DW-100', price: '125.00' }];
+ const tagsString = fiveFieldExtra({ variants: { nodes: variants }, tags: 'wallpaper' });
+ assert.equal(tagsString.ok, false);
+ assert.ok(tagsString.reasons.includes('invalid-tags-shape'));
+
+ const quoteString = fiveFieldExtra({ variants: { nodes: [variants[0]] }, tags: 'quotes' });
+ assert.equal(quoteString.ok, false);
+ assert.ok(quoteString.reasons.includes('invalid-tags-shape'));
+ assert.ok(quoteString.reasons.includes('no-sellable-variant'));
+ assert.ok(quoteString.reasons.includes('sellable-price-not-gt-0'));
+
+ const variantsString = fiveFieldExtra({ variants: { nodes: 'not-an-array' }, tags: ['quotes', 'wallpaper'] });
+ assert.equal(variantsString.ok, false);
+ assert.ok(variantsString.reasons.includes('invalid-variants-shape'));
+});
+
+test('normalizes valid tag arrays before applying the quote exemption', () => {
+ assert.deepEqual(fiveFieldExtra(product([
+ { sku: 'DW-QUOTE-SAMPLE', price: '5.00' },
+ ], [' Quotes ', 'Wallpaper'])), { ok: true, reasons: [] });
+});
+
test('requires at least two tags', () => {
assert.deepEqual(fiveFieldExtra(product([
{ sku: 'DW-100-SAMPLE', price: '5.00' }, { sku: 'DW-100', price: '125.00' },
diff --git a/verification/e2e-proof.json b/verification/e2e-proof.json
index 308cfff..94399bd 100644
--- a/verification/e2e-proof.json
+++ b/verification/e2e-proof.json
@@ -2,7 +2,7 @@
"intent": "Use one fail-closed five-field invariant check in every local product activation lane before any ACTIVE mutation.",
"risk_tier": "R1 isolated code; live Shopify activation is R4 and was intentionally not invoked",
"environment": "local macOS workspace; zero-network tests",
- "timestamp": "2026-08-29T04:37:05Z",
+ "timestamp": "2026-08-29T04:43:00Z",
"ticket": "TK-10947-unify-five-field-activation-checks-acros",
"precondition": "rotate-activate.js had the full extra invariant set; cmo-activate.js and mdc-activate.js duplicated only sample/tag checks.",
"checks": [
@@ -10,7 +10,7 @@
"verdict": "PASS",
"boundary": "pure validation",
"command": "node --test test/five-field-extra.test.js",
- "assertions": "5/5 pass: normal pass, missing sample rejection, invalid price rejection, tag rejection, quote-only exemption boundaries"
+ "assertions": "7/7 pass: normal pass, missing sample rejection, strict finite-decimal prices, explicit invalid array-shape holds, tag rejection, normalized quote-only exemption boundaries"
},
{
"verdict": "PASS",
@@ -33,7 +33,9 @@
],
"negative_checks": [
"missing sample",
- "missing, blank, zero, malformed, and negative sellable price",
+ "missing, blank, zero, malformed, negative, suffixed, and non-finite sellable price",
+ "non-array variants.nodes and tags shapes",
+ "string tags cannot trigger count or quote-only exemptions",
"fewer than two tags",
"quote-only product without sample"
],
← ee136fc Unify pre-activation five-field checks
·
back to Dw Gemini Skip TK11321
·
rotation-activator: block $4.25 sample-leak price from passi d9e84e1 →