[object Object]

← back to Dw Signup Fulfillment

prove TK-11114 signup email remediation end to end

e393474b1cf1ee418e0bdcca2177507ec4e914ce · 2026-09-02 11:35:29 -0700 · Steve Abrams

Files touched

Diff

commit e393474b1cf1ee418e0bdcca2177507ec4e914ce
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed Sep 2 11:35:29 2026 -0700

    prove TK-11114 signup email remediation end to end
---
 verification/tk11114-remediation/A2A-HANDOFF.md | 12 +++++++
 verification/tk11114-remediation/E2E-PROOF.md   | 38 ++++++++++++++++++++++
 verification/tk11114-remediation/r4.js          | 43 +++++++++++++++++++++++++
 3 files changed, 93 insertions(+)

diff --git a/verification/tk11114-remediation/A2A-HANDOFF.md b/verification/tk11114-remediation/A2A-HANDOFF.md
new file mode 100644
index 0000000..52f6830
--- /dev/null
+++ b/verification/tk11114-remediation/A2A-HANDOFF.md
@@ -0,0 +1,12 @@
+# TK-11114 A2A handoff — iterm remediation → `/root`
+
+Status: **PASS / ready for finalization**
+
+- Owner lane: `iterm-tk11114-george-repair`
+- Delegation chain: `/root → iterm-tk11114-george-repair` (depth 1)
+- Accountable finalizer: `/root`
+- Gates preserved: yes
+
+The isolated worker produced the sanitized before-state and rollback map, identified the stale PM2 George credential override, deployed the approved files, and restarted only the named service. The finalizer independently corrected privacy logging, verified tests, restored the registered webhook token after restart drift, and executed the controlled R4 journey.
+
+Independent finalizer assertions are recorded in `E2E-PROOF.md`. Controlled customer cleanup completed (DELETE 200 → GET 404). No further action remains under TK-11114; customer backfill remains separately gated and was not performed.
diff --git a/verification/tk11114-remediation/E2E-PROOF.md b/verification/tk11114-remediation/E2E-PROOF.md
new file mode 100644
index 0000000..65982c8
--- /dev/null
+++ b/verification/tk11114-remediation/E2E-PROOF.md
@@ -0,0 +1,38 @@
+# TK-11114 remediation — R4 E2E proof
+
+Status: **PASS** · 2026-09-02 · finalizer `/root`
+
+## Root cause and repair
+
+- The existing `customers/create` webhook was valid; no webhook was created or deleted.
+- PM2 injected a stale `GEORGE_BASIC_AUTH` override (`sha8 bd3d134d`) instead of George's authoritative on-host credential (`sha8 29398480`).
+- Production `lib/email.js` also lagged local HEAD and omitted `message_class: transactional`.
+- Deployed current `lib/email.js` and `lib/verify.js`, including credential/customer-safe status logging.
+- Restarted only `dw-signup-fulfillment`. Removed the stale George override and restored the existing Shopify-registered webhook token after `--update-env` initially selected the stale secrets-master value.
+
+No secret values are recorded in this evidence.
+
+## Boundary assertions
+
+| Boundary | Evidence | Verdict |
+|---|---|---|
+| Build identity | Production hashes equal local HEAD `9e5aa29` for `lib/email.js` and `lib/verify.js` | PASS |
+| Service health | `dw-signup-fulfillment` online after bounded restart | PASS |
+| Credential resolution | Stale PM2 Basic-auth override absent; authoritative George file fallback active | PASS |
+| Webhook auth negative | Invalid URL token returned HTTP 401 | PASS |
+| Controlled customer | One Steve-owned `+dwgolive` customer created, id `8412255387699` | PASS |
+| Handler correlation | Production log: `customers/create id=8412255387699` | PASS |
+| Automatic delivery | Production log: `source=retail-verify status=200`; George mailbox contains exactly one matching message | PASS |
+| UTF-8 content | Subject preserved the gift emoji and typographic dash | PASS |
+| Verify click | Bearer URL handled without disclosure; URL hash `dc408a21`; HTTP 200 with success body | PASS |
+| Persisted entitlement | `verified-sample` tag, `custom.sample_verified=true`, and `custom.sample_verify_sent=true` | PASS |
+| Replay idempotency | Second controlled delivery returned `skipped: already_sent`; mailbox verify-message count remained 1 | PASS |
+| Cleanup | Customer DELETE 200, subsequent GET 404 | PASS |
+
+## Scope and residuals
+
+- No backfill/list send, DNS, spend, remote push, webhook creation/deletion, or other Shopify/dw_unified write occurred.
+- No other PM2 service was intentionally restarted.
+- Native Shopify delivery was not observed for the Admin-API-created test customer during the wait window, so the existing registered webhook was deterministically replayed with that exact customer ID. This proves the production webhook handler → George → verify → tag journey, while keeping the native-emission distinction explicit.
+- Unrelated untracked helper files were not modified or committed.
+
diff --git a/verification/tk11114-remediation/r4.js b/verification/tk11114-remediation/r4.js
new file mode 100644
index 0000000..3bffee1
--- /dev/null
+++ b/verification/tk11114-remediation/r4.js
@@ -0,0 +1,43 @@
+'use strict';
+// TK-11114 R4 helper — controlled LIVE Shopify ops for the ONE approved +dwgolive test.
+// LIVE by design: DRY_RUN forced 0 so the customers/create webhook actually fires.
+// Subcommands: create | get <id> | delete <id>
+process.env.DRY_RUN = '0';
+const path = require('path');
+const shopify = require(path.join(__dirname, '..', '..', 'lib', 'shopify'));
+const config = require(path.join(__dirname, '..', '..', 'lib', 'config'));
+
+async function createCustomer() {
+  const ts = new Date().toISOString().replace(/[:.]/g, '-');
+  const email = `steve+dwgolive-tk11114-${Date.now()}@designerwallcoverings.com`;
+  const body = { customer: { email, first_name: 'DW GoLive', last_name: 'TK11114 Test', tags: 'tk11114-test', verified_email: true } };
+  const r = await shopify.request('POST', '/customers.json', body);
+  const c = r && r.json && r.json.customer;
+  if (!r.ok || !c || !c.id) { console.log(JSON.stringify({ ok: false, status: r.status, json: r.json })); process.exit(1); }
+  console.log(JSON.stringify({ ok: true, id: c.id, email: c.email, created_at: c.created_at, tags: c.tags }, null, 2));
+}
+async function getCustomer(id) {
+  const r = await shopify.getCustomer(id);
+  const c = r && r.json && r.json.customer;
+  let mf = null;
+  try { mf = await shopify.getCustomerMetafield(id, 'custom', 'sample_verified'); } catch (e) {}
+  let sentFlag = null;
+  try { sentFlag = await shopify.getCustomerMetafield(id, 'custom', 'sample_verify_sent'); } catch (e) {}
+  console.log(JSON.stringify({ ok: r.ok, status: r.status, id: c && c.id, email: c && c.email, tags: c && c.tags, verified_metafield: mf, sample_verify_sent: sentFlag }, null, 2));
+}
+async function deleteCustomer(id) {
+  const r = await shopify.request('DELETE', `/customers/${id}.json`, undefined);
+  console.log(JSON.stringify({ ok: r.ok, status: r.status, id }));
+  // confirm 404
+  const g = await shopify.getCustomer(id);
+  console.log(JSON.stringify({ verify_deleted: true, get_status: g.status }));
+}
+
+const [cmd, arg] = process.argv.slice(2);
+if (!config.SHOPIFY_FULFILLMENT_TOKEN) { console.log(JSON.stringify({ ok: false, error: 'no fulfillment token resolved' })); process.exit(1); }
+(async () => {
+  if (cmd === 'create') return createCustomer();
+  if (cmd === 'get') return getCustomer(arg);
+  if (cmd === 'delete') return deleteCustomer(arg);
+  console.log('usage: node r4.js create|get <id>|delete <id>'); process.exit(2);
+})().catch(e => { console.error('r4 error:', e.message); process.exit(1); });

← e8c174a auto-data-snapshot: 2026-09-02T11:28:31 (2 data files) — arm  ·  back to Dw Signup Fulfillment  ·  TK-11114: reconcile deploy paste — supersede stale webhook F 7963d0a →