[object Object]

← back to Estimate Instant

Harden roll specs and SKU resolution

062bfadea250b40aa20be14e8178151c8cebd4f8 · 2026-08-28 22:14:29 -0700 · Steve Abrams

Files touched

Diff

commit 062bfadea250b40aa20be14e8178151c8cebd4f8
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Fri Aug 28 22:14:29 2026 -0700

    Harden roll specs and SKU resolution
---
 server.js                       | 28 ++++++++++++++++++++++++----
 test/calculate-coverage.test.js | 39 ++++++++++++++++++++++++++++++++++++++-
 verification/e2e-proof.json     |  4 +++-
 3 files changed, 65 insertions(+), 6 deletions(-)

diff --git a/server.js b/server.js
index b4c9e61..774f1da 100644
--- a/server.js
+++ b/server.js
@@ -165,12 +165,28 @@ function calculateCoverage(input, rolls = loadRolls(), checkout_domain) {
   if (errors.length) return { ok: false, errors };
 
   const key = sku.toUpperCase();
-  const roll = rolls.find((item) =>
-    String(item.sku || '').toUpperCase() === key ||
-    (item.shopify_match === true && String(item.shopify_sku || '').toUpperCase() === key)
-  );
+  const canonicalMatches = rolls.filter((item) => String(item.sku || '').toUpperCase() === key);
+  if (canonicalMatches.length > 1) {
+    return { ok: false, errors: [`Ambiguous local roll specification for SKU ${sku}.`] };
+  }
+  const aliasMatches = canonicalMatches.length === 0
+    ? rolls.filter((item) => item.shopify_match === true && String(item.shopify_sku || '').toUpperCase() === key)
+    : [];
+  if (aliasMatches.length > 1) {
+    return { ok: false, errors: [`Ambiguous matched Shopify SKU ${sku}.`] };
+  }
+  const roll = canonicalMatches[0] || aliasMatches[0];
   if (!roll) return { ok: false, errors: [`No local roll specification found for SKU ${sku}.`] };
 
+  const validPositiveSpec = (value) => typeof value === 'number' && Number.isFinite(value) && value > 0;
+  const validRepeat = typeof roll.pattern_repeat_in === 'number' &&
+    Number.isFinite(roll.pattern_repeat_in) && roll.pattern_repeat_in >= 0;
+  const match = String(roll.match || '').trim().toLowerCase();
+  if (!validPositiveSpec(roll.roll_width_in) || !validPositiveSpec(roll.roll_length_ft) ||
+      !validRepeat || !['random', 'straight', 'half-drop'].includes(match)) {
+    return { ok: false, errors: ['Local roll specification is invalid; verify width, length, repeat, and match.'] };
+  }
+
   const totalWidthIn = roomWidthFt * 12 * numWalls;
   const wallHeightIn = roomHeightFt * 12;
   if (!Number.isFinite(totalWidthIn) || Math.abs(totalWidthIn) > Number.MAX_SAFE_INTEGER || !Number.isFinite(wallHeightIn)) {
@@ -194,6 +210,10 @@ function calculateCoverage(input, rolls = loadRolls(), checkout_domain) {
   if (numericOutputs.some((value) => typeof value !== 'number' || !Number.isFinite(value))) {
     return { ok: false, errors: ['Roll specifications produced a non-finite calculation; verify the product data.'] };
   }
+  if (![result.rollsNeeded, result.totalStrips, result.stripsPerRoll].every(Number.isSafeInteger) ||
+      result.rollsNeeded < 1 || result.totalStrips < 1 || result.stripsPerRoll < 1 || result.cutLengthIn <= 0) {
+    return { ok: false, errors: ['Roll specifications produced an invalid quantity; verify the product data.'] };
+  }
 
   const notes = [
     `Assumes ${numWalls} wall${numWalls === 1 ? '' : 's'} at ${roomWidthFt} ft wide by ${roomHeightFt} ft high.`,
diff --git a/test/calculate-coverage.test.js b/test/calculate-coverage.test.js
index 25937ba..a4ed230 100644
--- a/test/calculate-coverage.test.js
+++ b/test/calculate-coverage.test.js
@@ -78,7 +78,44 @@ test('fails closed when malformed roll data produces non-finite output', () => {
   const broken = { ...roll, roll_width_in: 0 };
   const result = calculateCoverage({ sku: roll.sku, room_width_ft: 10, room_height_ft: 8, num_walls: 1 }, [broken]);
   assert.equal(result.ok, false);
-  assert.match(result.errors.join(' '), /non-finite calculation/i);
+  assert.match(result.errors.join(' '), /roll specification is invalid/i);
+});
+
+test('rejects invalid finite roll specs and unsupported match values', () => {
+  for (const patch of [
+    { roll_width_in: -24 },
+    { roll_length_ft: -30 },
+    { pattern_repeat_in: -1 },
+    { match: 'mystery' },
+  ]) {
+    const result = calculateCoverage(
+      { sku: roll.sku, room_width_ft: 10, room_height_ft: 8, num_walls: 1 },
+      [{ ...roll, ...patch }]
+    );
+    assert.equal(result.ok, false);
+    assert.match(result.errors.join(' '), /roll specification is invalid/i);
+  }
+});
+
+test('prefers an exact canonical SKU and rejects ambiguous aliases', () => {
+  const alias = { ...roll, sku: 'PROTO', shopify_sku: 'COLLIDE', shopify_match: true };
+  const canonical = { ...roll, sku: 'COLLIDE', shopify_sku: 'OTHER', shopify_match: true };
+  const exact = calculateCoverage(
+    { sku: 'COLLIDE', room_width_ft: 10, room_height_ft: 8, num_walls: 1 },
+    [alias, canonical]
+  );
+  assert.equal(exact.ok, true);
+  assert.equal(exact.sku, 'COLLIDE');
+
+  const ambiguous = calculateCoverage(
+    { sku: 'SAME-ALIAS', room_width_ft: 10, room_height_ft: 8, num_walls: 1 },
+    [
+      { ...roll, sku: 'ONE', shopify_sku: 'SAME-ALIAS' },
+      { ...roll, sku: 'TWO', shopify_sku: 'SAME-ALIAS' },
+    ]
+  );
+  assert.equal(ambiguous.ok, false);
+  assert.match(ambiguous.errors.join(' '), /ambiguous matched Shopify SKU/i);
 });
 
 test('rejects missing SKU, invalid dimensions, fractional walls, and unknown SKU', () => {
diff --git a/verification/e2e-proof.json b/verification/e2e-proof.json
index 909c364..fa1437b 100644
--- a/verification/e2e-proof.json
+++ b/verification/e2e-proof.json
@@ -11,7 +11,7 @@
       "verdict": "PASS",
       "boundary": "calculation module",
       "command": "node --test test/calculate-coverage.test.js",
-      "assertions": "7/7 pass: room dimensions map to rolls; exact matched alias works; stand-in aliases fail; prototype pricing is withheld; coercible/oversized inputs and non-finite outputs fail closed"
+      "assertions": "9/9 pass: room dimensions map to rolls; exact canonical SKU outranks aliases; ambiguous and stand-in aliases fail; prototype pricing is withheld; coercible/oversized inputs and invalid roll specs fail closed"
     },
     {
       "verdict": "PASS",
@@ -35,6 +35,8 @@
     "boolean, string, and array dimensions",
     "dimensions beyond documented bounds",
     "false-match Shopify alias",
+    "alias collision with exact canonical SKU and ambiguous aliases",
+    "negative roll width/length/repeat and unsupported match",
     "non-finite estimator output from malformed roll data",
     "empty HTTP payload"
   ],

← 8e0c9d3 Add fail-closed room coverage API  ·  back to Estimate Instant  ·  auto-data-snapshot: 2026-08-28T22:35:10 (2 data files) — REA ef09b11 →