[object Object]

← back to Dw Signup Fulfillment

TK-11120: real-customer click proof — verify confirms + tags with zero input (PASS)

64b3102ffa32f18150da36bb7483e5c0f256fa5d · 2026-09-02 14:13:40 -0700 · Steve Abrams

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017j4qS38tWq21qYdjxMcFTy

Files touched

Diff

commit 64b3102ffa32f18150da36bb7483e5c0f256fa5d
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed Sep 2 14:13:40 2026 -0700

    TK-11120: real-customer click proof — verify confirms + tags with zero input (PASS)
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_017j4qS38tWq21qYdjxMcFTy
---
 verification/tk11120/prove-real-customer.js | 55 +++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)

diff --git a/verification/tk11120/prove-real-customer.js b/verification/tk11120/prove-real-customer.js
new file mode 100644
index 0000000..68aa732
--- /dev/null
+++ b/verification/tk11120/prove-real-customer.js
@@ -0,0 +1,55 @@
+'use strict';
+// TK-11120 — end-to-end proof that a REAL customer clicking the corrected verify link is
+// confirmed with ZERO user input. Creates a throwaway Shopify customer, hits the LIVE
+// /verify HTTP endpoint with a real token, asserts "Email confirmed" + the verified-sample
+// tag lands, then DELETES the throwaway customer. Reversible + self-cleaning.
+const http = require('http');
+const https = require('https');
+const config = require('./../../lib/config');
+const verify = require('./../../lib/verify');
+
+const SHOP = config.SHOP_DOMAIN, VER = config.SHOPIFY_API_VERSION, TOK = config.SHOPIFY_FULFILLMENT_TOKEN;
+function shopify(method, path, body) {
+  return new Promise((resolve) => {
+    const data = body ? JSON.stringify(body) : null;
+    const req = https.request({ hostname: SHOP, path: `/admin/api/${VER}/${path}`, method,
+      headers: { 'X-Shopify-Access-Token': TOK, 'Content-Type': 'application/json', ...(data ? { 'Content-Length': Buffer.byteLength(data) } : {}) } },
+      res => { let d = ''; res.on('data', c => d += c); res.on('end', () => { let j = null; try { j = JSON.parse(d); } catch {} resolve({ status: res.statusCode, json: j }); }); });
+    req.on('error', e => resolve({ status: 0, error: e.message })); if (data) req.write(data); req.end();
+  });
+}
+const PUBLIC = (process.env.PUBLIC_URL || 'https://signup.designerwallcoverings.com').replace(/\/+$/, '');
+function getVerify(path) {
+  return new Promise((resolve) => { https.get(PUBLIC + path, res => { let d = ''; res.on('data', c => d += c); res.on('end', () => resolve({ status: res.statusCode, body: d })); }).on('error', e => resolve({ status: 0, error: e.message })); });
+}
+
+(async () => {
+  const email = `steve+tk11120-realcust-${Date.now()}@designerwallcoverings.com`;
+  console.log('1) creating throwaway Shopify customer:', email);
+  const c = await shopify('POST', 'customers.json', { customer: { email, first_name: 'RealTest', verified_email: true } });
+  const cust = c.json && c.json.customer;
+  if (!cust || !cust.id) { console.log('   CREATE FAILED', c.status, JSON.stringify(c.json)); process.exit(1); }
+  const id = cust.id; console.log('   created id=', id);
+  let pass = false, tags = '';
+  try {
+    const token = verify.mintToken({ email, customerId: String(id) });
+    console.log('2) clicking /verify (no sign-in, no form) ...');
+    const r = await getVerify(`/verify?token=${encodeURIComponent(token)}`);
+    const confirmed = /Email confirmed/i.test(r.body);
+    const attachFail = /couldn.t attach/i.test(r.body);
+    const h1 = (r.body.match(/<h1[^>]*>([^<]*)<\/h1>/) || [])[1] || '';
+    const msg = (r.body.match(/<p style="color:#4b5563[^"]*">([^<]*)<\/p>/) || [])[1] || '';
+    console.log('   HTTP', r.status, '| H1:', JSON.stringify(h1), '| MSG:', JSON.stringify(msg).slice(0, 160));
+    console.log('   "Email confirmed":', confirmed, '| "couldn\'t attach":', attachFail);
+    const g = await shopify('GET', `customers/${id}.json`);
+    tags = (g.json && g.json.customer && g.json.customer.tags) || '';
+    const tagged = tags.toLowerCase().includes(config.VERIFIED_TAG.toLowerCase());
+    console.log('3) customer tags now:', JSON.stringify(tags), '| has', config.VERIFIED_TAG + ':', tagged);
+    pass = confirmed && tagged && !attachFail;
+  } finally {
+    const d = await shopify('DELETE', `customers/${id}.json`);
+    console.log('4) deleted throwaway customer id=', id, '→ status', d.status);
+  }
+  console.log(pass ? '\n✅ PASS — real customer click confirms + tags, zero user input.' : '\n❌ FAIL — see above.');
+  process.exit(pass ? 0 : 1);
+})().catch(e => { console.error('ERR', e.message); process.exit(1); });

← e288df7 auto-data-snapshot: 2026-09-02T14:03:59 (1 data files) — ver  ·  back to Dw Signup Fulfillment  ·  TK-11120: retail-only 5-sample apology resend (--force, --re 0b127cf →