[object Object]

← back to Sample Followup Sweep

Centralize sample follow-up compliance enforcement

984ab8ef961919b74d5ca23ec0c6781d4af09f59 · 2026-08-28 14:36:13 -0700 · Steve Abrams

Files touched

Diff

commit 984ab8ef961919b74d5ca23ec0c6781d4af09f59
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Fri Aug 28 14:36:13 2026 -0700

    Centralize sample follow-up compliance enforcement
---
 bin/run.js                              |  3 +-
 lib/george-transport.js                 | 40 ++++++++++++++++++++++++++
 lib/pre-send-gate.js                    | 28 ++++++++++++++++--
 scripts/make-drafts.js                  |  4 ++-
 scripts/scheduled-run.mjs               | 24 ++++------------
 scripts/send-drafts.js                  | 22 ++++----------
 scripts/send-reconciled.mjs             | 13 +++++++--
 server.js                               | 19 ++++--------
 test/george-transport.test.js           | 42 +++++++++++++++++++++++++++
 test/pre-send-gate.test.js              |  9 ++++++
 test/sendable-callsite-coverage.test.js | 37 ++++++++++++++++++++++++
 verification/e2e-proof.json             | 51 +++++++++++++++++++++++++++++++++
 12 files changed, 234 insertions(+), 58 deletions(-)

diff --git a/bin/run.js b/bin/run.js
index 2ce56f1..72b3609 100644
--- a/bin/run.js
+++ b/bin/run.js
@@ -7,6 +7,7 @@ const fs = require('fs');
 const path = require('path');
 const { sweep } = require('../lib/sweep');
 const { compose } = require('../lib/compose');
+const { createGmailDraftArtifact } = require('../lib/george-transport');
 
 const slug = process.argv[2] || 'osborne-little';
 const root = path.join(__dirname, '..');
@@ -28,7 +29,7 @@ const draft = compose(vendor, followUp);
 const outDir = path.join(root, 'out');
 fs.mkdirSync(outDir, { recursive: true });
 if (missing.length === 0) {
-  const payload = { account: 'info', to: draft.to, subject: draft.subject, body: draft.html };
+  const payload = createGmailDraftArtifact({ account: 'info', to: draft.to, subject: draft.subject, body: draft.html });
   fs.writeFileSync(path.join(outDir, `${slug}.draft.json`), JSON.stringify(payload, null, 2));
 }
 fs.writeFileSync(path.join(outDir, `${slug}.preview.html`), preview(vendor, draft, followUp, escalation, skipped));
diff --git a/lib/george-transport.js b/lib/george-transport.js
new file mode 100644
index 0000000..c32aabd
--- /dev/null
+++ b/lib/george-transport.js
@@ -0,0 +1,40 @@
+'use strict';
+
+const http = require('node:http');
+const { assertPreSendCompliance, REQUIRED_FROM } = require('./pre-send-gate');
+
+const SENDABLE_PATHS = new Set(['/api/send', '/api/drafts']);
+
+function assertSendablePayload(payload) {
+  assertPreSendCompliance({
+    from: payload?.account === 'info' ? REQUIRED_FROM : '',
+    subject: payload?.subject,
+    body: payload?.body,
+  });
+  return payload;
+}
+
+function createGmailDraftArtifact(payload) {
+  return assertSendablePayload(payload);
+}
+
+async function georgeRequest({ path, payload, headers = {}, requestImpl = http.request }) {
+  if (!SENDABLE_PATHS.has(path)) throw new Error(`Unsupported sendable George path: ${path}`);
+  assertSendablePayload(payload); // Must run before serialization, credential reads, or network setup.
+  const body = JSON.stringify(payload);
+  return new Promise((resolve) => {
+    const req = requestImpl({
+      host: '127.0.0.1', port: 9850, path, method: 'POST',
+      headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body), ...headers },
+    }, (response) => {
+      let responseBody = '';
+      response.on('data', (chunk) => { responseBody += chunk; });
+      response.on('end', () => resolve({ statusCode: response.statusCode || 0, body: responseBody }));
+    });
+    req.on('error', (error) => resolve({ statusCode: 0, body: error.message }));
+    req.write(body);
+    req.end();
+  });
+}
+
+module.exports = { assertSendablePayload, createGmailDraftArtifact, georgeRequest, SENDABLE_PATHS };
diff --git a/lib/pre-send-gate.js b/lib/pre-send-gate.js
index 257ce45..9dda896 100644
--- a/lib/pre-send-gate.js
+++ b/lib/pre-send-gate.js
@@ -2,16 +2,38 @@
 
 const REQUIRED_FROM = 'info@designerwallcoverings.com';
 const ADDRESS_PATTERN = /15442\s+Ventura\s+Blvd(?:\.|\s)*(?:#|Suite)?\s*102[\s\S]*Sherman\s+Oaks,?\s*CA\s+91403/i;
-const UNSUBSCRIBE_PATTERN = /(?:mailto:|https?:\/\/)[^"'\s>]*(?:unsubscribe|opt[-_ ]?out)|(?:unsubscribe|opt\s*out)[\s\S]{0,160}(?:mailto:|https?:\/\/)/i;
 const MISLEADING_SUBJECT_PATTERN = /\b(?:re|fw|fwd)\s*:/i;
 
+function stripHtmlComments(value) {
+  return String(value || '').replace(/<!--[\s\S]*?-->/g, '');
+}
+
+function hasWorkingOptOutLink(body) {
+  const visible = stripHtmlComments(body);
+  const hrefs = [...visible.matchAll(/<a\b[^>]*\bhref\s*=\s*(["'])(.*?)\1[^>]*>/gi)].map((match) => match[2].trim());
+  return hrefs.some((href) => {
+    try {
+      const url = new URL(href);
+      const optOutSignal = `${url.pathname} ${url.search} ${url.hash}`;
+      if (!/(?:unsubscribe|opt[-_ ]?out)/i.test(optOutSignal)) return false;
+      if (url.protocol === 'mailto:') return url.pathname.toLowerCase() === REQUIRED_FROM;
+      if (url.protocol !== 'https:') return false;
+      const host = url.hostname.toLowerCase();
+      if (!host.includes('.') || host === 'invalid.example' || host.endsWith('.invalid') || host.endsWith('.example') || host.endsWith('.test') || host === 'localhost') return false;
+      return true;
+    } catch {
+      return false;
+    }
+  });
+}
+
 function assertPreSendCompliance({ from, subject, body }) {
   const errors = [];
   if (String(from || '').trim().toLowerCase() !== REQUIRED_FROM) errors.push(`From must be ${REQUIRED_FROM}`);
   if (!String(subject || '').trim()) errors.push('Subject is required');
   if (MISLEADING_SUBJECT_PATTERN.test(String(subject || ''))) errors.push('Subject must not imply a reply or forward');
   if (!ADDRESS_PATTERN.test(String(body || ''))) errors.push('Body must include the DW physical postal address');
-  if (!UNSUBSCRIBE_PATTERN.test(String(body || ''))) errors.push('Body must include a working unsubscribe or opt-out link');
+  if (!hasWorkingOptOutLink(body)) errors.push('Body must include a working unsubscribe or opt-out link');
   if (errors.length) {
     const error = new Error(`PRE-SEND COMPLIANCE GATE BLOCKED: ${errors.join('; ')}`);
     error.code = 'PRE_SEND_COMPLIANCE_BLOCKED';
@@ -21,4 +43,4 @@ function assertPreSendCompliance({ from, subject, body }) {
   return true;
 }
 
-module.exports = { assertPreSendCompliance, REQUIRED_FROM };
+module.exports = { assertPreSendCompliance, hasWorkingOptOutLink, REQUIRED_FROM };
diff --git a/scripts/make-drafts.js b/scripts/make-drafts.js
index c9d3641..9116814 100644
--- a/scripts/make-drafts.js
+++ b/scripts/make-drafts.js
@@ -4,6 +4,7 @@
 const fs = require('fs');
 const path = require('path');
 const { compose } = require('../lib/compose');
+const { createGmailDraftArtifact } = require('../lib/george-transport');
 
 const SHIP_TO = { name: 'Designer Wallcoverings', line1: '15442 Ventura Blvd. #102', city_state_zip: 'Sherman Oaks, CA 91403', phone: '1-888-373-4564' };
 const root = path.join(__dirname, '..');
@@ -34,7 +35,8 @@ for (const key of Object.keys(groups)) {
   if (!rows.length) continue; // nothing real to chase
   const vendor = { name: g.name, account_number: g.account, sample_email: g.to, ship_to: SHIP_TO };
   const d = compose(vendor, rows);
-  drafts.push({ to: d.to, subject: d.subject, body: d.html, slugs: g.slugs, name: g.name, items: rows.length });
+  const payload = createGmailDraftArtifact({ account: 'info', to: d.to, subject: d.subject, body: d.html });
+  drafts.push({ ...payload, slugs: g.slugs, name: g.name, items: rows.length });
 }
 drafts.sort((a, b) => b.items - a.items);
 
diff --git a/scripts/scheduled-run.mjs b/scripts/scheduled-run.mjs
index 7de4ce1..412c573 100644
--- a/scripts/scheduled-run.mjs
+++ b/scripts/scheduled-run.mjs
@@ -27,7 +27,7 @@ const require = createRequire(import.meta.url);
 const __dir = dirname(fileURLToPath(import.meta.url));
 const ROOT = join(__dir, '..');
 const { compose } = require(join(ROOT, 'lib', 'compose.js'));
-const { assertPreSendCompliance, REQUIRED_FROM } = require(join(ROOT, 'lib', 'pre-send-gate.js'));
+const { georgeRequest } = require(join(ROOT, 'lib', 'george-transport.js'));
 
 const SEND = process.argv.includes('--send');
 // Steve 8/20: DRAFT mode — create a Gmail draft per vendor in info@ Drafts for human review,
@@ -109,29 +109,15 @@ function georgeCreds() {
   return { auth: 'Basic ' + Buffer.from(auth).toString('base64'), token: g('GEORGE_EXTERNAL_SEND_TOKEN') };
 }
 function georgeSend(payload) {
-  assertPreSendCompliance({ from: payload.account === 'info' ? REQUIRED_FROM : '', subject: payload.subject, body: payload.body });
   const { auth, token } = georgeCreds();
-  const body = JSON.stringify(payload);
-  return new Promise((resolve) => {
-    const req = http.request({ host: '127.0.0.1', port: 9850, path: '/api/send', method: 'POST',
-      headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body), Authorization: auth, 'X-Send-Approval': token } },
-      (r) => { let b = ''; r.on('data', (d) => b += d); r.on('end', () => { try { const j = JSON.parse(b); resolve({ ok: !!j.success, id: j.messageId || '', detail: b.slice(0, 200) }); } catch { resolve({ ok: false, detail: b.slice(0, 200) }); } }); });
-    req.on('error', (e) => resolve({ ok: false, detail: e.message }));
-    req.write(body); req.end();
-  });
+  return georgeRequest({ path: '/api/send', payload, headers: { Authorization: auth, 'X-Send-Approval': token } })
+    .then(({ body }) => { try { const j = JSON.parse(body); return { ok: !!j.success, id: j.messageId || '', detail: body.slice(0, 200) }; } catch { return { ok: false, detail: body.slice(0, 200) }; } });
 }
 // Create a Gmail draft in info@ Drafts (POST /api/drafts — no send-approval token needed).
 function georgeDraft(payload) {
-  assertPreSendCompliance({ from: payload.account === 'info' ? REQUIRED_FROM : '', subject: payload.subject, body: payload.body });
   const { auth } = georgeCreds();
-  const body = JSON.stringify(payload);
-  return new Promise((resolve) => {
-    const req = http.request({ host: '127.0.0.1', port: 9850, path: '/api/drafts', method: 'POST',
-      headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body), Authorization: auth } },
-      (r) => { let b = ''; r.on('data', (d) => b += d); r.on('end', () => { try { const j = JSON.parse(b); resolve({ ok: !!j.success, id: j.draftId || '', detail: b.slice(0, 200) }); } catch { resolve({ ok: false, detail: b.slice(0, 200) }); } }); });
-    req.on('error', (e) => resolve({ ok: false, detail: e.message }));
-    req.write(body); req.end();
-  });
+  return georgeRequest({ path: '/api/drafts', payload, headers: { Authorization: auth } })
+    .then(({ body }) => { try { const j = JSON.parse(body); return { ok: !!j.success, id: j.draftId || '', detail: body.slice(0, 200) }; } catch { return { ok: false, detail: body.slice(0, 200) }; } });
 }
 // Live suppression source: recipients the team already emailed a "New Sample Request" to recently
 // (harvested straight from info@ Sent via George). Self-updating — no manual list to maintain.
diff --git a/scripts/send-drafts.js b/scripts/send-drafts.js
index ea798c2..e1051cb 100644
--- a/scripts/send-drafts.js
+++ b/scripts/send-drafts.js
@@ -3,9 +3,8 @@
 // carrying the human-approval token (Steve-approved batch, 2026-08-14).
 // Secrets are read from george-gmail/.env at runtime and never printed.
 const fs = require('fs');
-const http = require('http');
 const path = require('path');
-const { assertPreSendCompliance, REQUIRED_FROM } = require('../lib/pre-send-gate');
+const { georgeRequest } = require('../lib/george-transport');
 
 const GENV = '/Users/macstudio3/Projects/george-gmail/.env';
 function env(k) { try { const m = fs.readFileSync(GENV, 'utf8').match(new RegExp('^' + k + '=(.+)$', 'm')); return m ? m[1].trim() : ''; } catch (e) { return ''; } }
@@ -19,21 +18,10 @@ const basic = 'Basic ' + Buffer.from(auth).toString('base64');
 const drafts = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'out', 'all-drafts.json'), 'utf8'));
 
 function send(d) {
-  return new Promise((res) => {
-    const payload = { account: 'info', to: d.to, subject: d.subject, body: d.body };
-    try {
-      assertPreSendCompliance({ from: payload.account === 'info' ? REQUIRED_FROM : '', subject: payload.subject, body: payload.body });
-    } catch (error) {
-      return res({ code: 0, body: JSON.stringify({ success: false, error: error.message }) });
-    }
-    const wirePayload = JSON.stringify(payload);
-    const req = http.request({
-      host: '127.0.0.1', port: 9850, path: '/api/send', method: 'POST',
-      headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(wirePayload), Authorization: basic, 'X-Send-Approval': token },
-    }, r => { let b = ''; r.on('data', x => b += x); r.on('end', () => res({ code: r.statusCode, body: b })); });
-    req.on('error', e => res({ code: 0, body: e.message }));
-    req.write(wirePayload); req.end();
-  });
+  const payload = { account: 'info', to: d.to, subject: d.subject, body: d.body };
+  return georgeRequest({ path: '/api/send', payload, headers: { Authorization: basic, 'X-Send-Approval': token } })
+    .then((result) => ({ code: result.statusCode, body: result.body }))
+    .catch((error) => ({ code: 0, body: JSON.stringify({ success: false, error: error.message }) }));
 }
 
 (async () => {
diff --git a/scripts/send-reconciled.mjs b/scripts/send-reconciled.mjs
index 2d91764..044929e 100644
--- a/scripts/send-reconciled.mjs
+++ b/scripts/send-reconciled.mjs
@@ -4,8 +4,10 @@
 // letter per vendor into info@ Drafts (NEVER auto-sends). Steve reviews + sends from Drafts.
 // Letter = intro + "Attn / processed by: <vendor processor>" + Ref#·Date Ordered·Manufacturer# table.
 //   WIN env overrides the FileMaker date range (default = today's fill-in window).
-import { readFileSync, writeFileSync } from 'node:fs'; import { homedir } from 'node:os'; import { join } from 'node:path'; import http from 'node:http';
+import { readFileSync, writeFileSync } from 'node:fs'; import { homedir } from 'node:os'; import { join } from 'node:path'; import { createRequire } from 'node:module';
+const require = createRequire(import.meta.url);
 const ROOT = join(homedir(), 'Projects/sample-followup-sweep');
+const { georgeRequest } = require(join(ROOT, 'lib/george-transport.js'));
 // Rolling window: memos that crossed the 10-day follow-up floor within the last CATCHUP days (default 7),
 // so a daily scheduled run always covers any gap. Env WIN overrides for a manual one-off. (Draft-dedup
 // below stops the same memo being drafted twice across runs.)
@@ -61,13 +63,18 @@ ${tbl}
 </table>
 <p>Ship to:<br>${esc(SHIP.name)}<br>${esc(SHIP.line1)}<br>${esc(SHIP.csz)}<br>${esc(SHIP.phone)}</p>
 <p><strong>Sidemark: Samples ASAP</strong></p>
-<p>Thank you!<br>Showroom Manager</p></div>`;
+<p>Thank you!<br>Showroom Manager</p>
+<p style="font-size:11px;color:#666">Designer Wallcoverings · 15442 Ventura Blvd. #102 · Sherman Oaks, CA 91403<br>
+To stop receiving sample follow-up emails, <a href="mailto:info@designerwallcoverings.com?subject=Unsubscribe%20from%20sample%20follow-ups">unsubscribe here</a>.</p></div>`;
 }
 // George draft (account=info, /api/drafts — no send-approval token)
 const genv = k => { for (const f of ['/Users/macstudio3/Projects/Designer-Wallcoverings/DW-MCP/.env', '/Users/macstudio3/Projects/george-gmail/.env']) { try { const m = readFileSync(f, 'utf8').match(new RegExp('^' + k + '=(.+)$', 'm')); if (m) return m[1].trim(); } catch {} } return ''; };
 let auth = genv('GEORGE_BASIC_AUTH'); if (!auth.includes(':')) auth = 'admin:' + genv('GEORGE_BASIC_AUTH_PASS');
 auth = 'Basic ' + Buffer.from(auth).toString('base64');
-function draft(to, subject, body) { return new Promise(res => { const b = JSON.stringify({ account: 'info', to, subject, body }); const rq = http.request({ host: '127.0.0.1', port: 9850, path: '/api/drafts', method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(b), Authorization: auth } }, r => { let d = ''; r.on('data', x => d += x); r.on('end', () => { try { const j = JSON.parse(d); res(j.success ? 'ok' : d.slice(0, 80)); } catch { res(d.slice(0, 80)); } }); }); rq.on('error', e => res(e.message)); rq.write(b); rq.end(); }); }
+async function draft(to, subject, body) {
+  const result = await georgeRequest({ path: '/api/drafts', payload: { account: 'info', to, subject, body }, headers: { Authorization: auth } });
+  try { const parsed = JSON.parse(result.body); return parsed.success ? 'ok' : result.body.slice(0, 80); } catch { return result.body.slice(0, 80); }
+}
 
 const DO = process.argv.includes('--draft');
 // Draft-dedup: never re-draft a memo (keyed by vendor+combo-sku) that a prior run already drafted,
diff --git a/server.js b/server.js
index de69a0f..530e479 100644
--- a/server.js
+++ b/server.js
@@ -9,7 +9,7 @@ const fs = require('fs');
 const path = require('path');
 const { spawn } = require('child_process');
 const { compose } = require('./lib/compose');
-const { assertPreSendCompliance, REQUIRED_FROM } = require('./lib/pre-send-gate');
+const { createGmailDraftArtifact, georgeRequest } = require('./lib/george-transport');
 
 const ROOT = __dirname;
 const AUTH = 'Basic ' + Buffer.from('admin:DW2024!').toString('base64');
@@ -136,11 +136,6 @@ const server = http.createServer(async (req, res) => {
       const addrs = String(payload.to).split(',').map(a => a.trim().toLowerCase()).filter(a => a.includes('@'));
       if (addrs.length && addrs.every(a => be[a])) return send(res, 409, { error: 'already sent to this vendor — click again to force-resend', to: payload.to, alreadySent: true });
     }
-    try {
-      assertPreSendCompliance({ from: payload.account === 'info' ? REQUIRED_FROM : '', subject: payload.subject, body: payload.body });
-    } catch (error) {
-      return send(res, 422, { error: error.message, reasons: error.reasons || [] });
-    }
     // George's canonical creds live in the DW-MCP .env (the file George's server loads into `creds`);
     // GEORGE_EXTERNAL_SEND_TOKEN lives in george-gmail/.env. Search both, canonical first. (2026-08-15 fix:
     // george-gmail/.env has no GEORGE_BASIC_AUTH, so the old single-file read sent an empty pass → 401.)
@@ -149,9 +144,7 @@ const server = http.createServer(async (req, res) => {
     let gauth = genv('GEORGE_BASIC_AUTH'); if (!gauth.includes(':')) gauth = 'admin:' + genv('GEORGE_BASIC_AUTH_PASS');
     const token = genv('GEORGE_EXTERNAL_SEND_TOKEN');
     if (!token) return send(res, 500, { error: 'GEORGE_EXTERNAL_SEND_TOKEN not configured' });
-    const gp = JSON.stringify(payload);
-    const greq = http.request({ host: '127.0.0.1', port: 9850, path: '/api/send', method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(gp), Authorization: 'Basic ' + Buffer.from(gauth).toString('base64'), 'X-Send-Approval': token } }, gr => {
-      let gb = ''; gr.on('data', x => gb += x); gr.on('end', () => {
+    georgeRequest({ path: '/api/send', payload, headers: { Authorization: 'Basic ' + Buffer.from(gauth).toString('base64'), 'X-Send-Approval': token } }).then(({ body: gb }) => {
         let ok = false, mid = ''; try { const j = JSON.parse(gb); ok = !!j.success; mid = j.messageId || ''; } catch (e) {}
         if (ok) {
           try { const s = sent(); s.byEmail = s.byEmail || {}; const iso = new Date().toISOString(); for (let a of String(payload.to).split(',')) { a = a.trim().toLowerCase(); if (!a.includes('@')) continue; const cur = s.byEmail[a]; if (!cur) s.byEmail[a] = { lastSent: iso, count: 1 }; else { cur.count++; cur.lastSent = iso; } } fs.writeFileSync(p('data', 'sent.json'), JSON.stringify(s, null, 2)); } catch (e) {}
@@ -159,10 +152,7 @@ const server = http.createServer(async (req, res) => {
           return send(res, 200, { ok: true, messageId: mid, to: payload.to });
         }
         return send(res, 502, { error: 'George send blocked/failed', detail: gb.slice(0, 200) });
-      });
-    });
-    greq.on('error', e => send(res, 502, { error: e.message }));
-    greq.write(gp); greq.end();
+    }).catch((error) => send(res, error.code === 'PRE_SEND_COMPLIANCE_BLOCKED' ? 422 : 502, { error: error.message, reasons: error.reasons || [] }));
     return;
   }
 
@@ -172,7 +162,8 @@ const server = http.createServer(async (req, res) => {
     const queue = picked.map(v => {
       const cc = c[v.slug] || {}; const d = draftFor(v, c);
       const missing = []; if (!cc.sample_email) missing.push('sample_email'); if (!cc.account_number) missing.push('account_number');
-      return { slug: v.slug, name: cc.name || v.name, to: d.to, subject: d.subject, body: d.html, items: v.items.length, ready: missing.length === 0, missing };
+      const sendable = missing.length === 0 ? createGmailDraftArtifact({ account: 'info', to: d.to, subject: d.subject, body: d.html }) : { to: d.to, subject: d.subject, body: d.html };
+      return { slug: v.slug, name: cc.name || v.name, ...sendable, items: v.items.length, ready: missing.length === 0, missing };
     });
     fs.mkdirSync(p('out'), { recursive: true });
     fs.writeFileSync(p('out', 'send-queue.json'), JSON.stringify({ generated: new Date().toISOString(), queue }, null, 2));
diff --git a/test/george-transport.test.js b/test/george-transport.test.js
new file mode 100644
index 0000000..7b895c0
--- /dev/null
+++ b/test/george-transport.test.js
@@ -0,0 +1,42 @@
+'use strict';
+
+const assert = require('node:assert/strict');
+const { EventEmitter } = require('node:events');
+const { compose } = require('../lib/compose');
+const { georgeRequest, createGmailDraftArtifact } = require('../lib/george-transport');
+
+const composed = compose({
+  name: 'Test Vendor', account_number: '123', sample_email: 'samples@vendor.com',
+  ship_to: { name: 'Designer Wallcoverings', line1: '15442 Ventura Blvd. #102', city_state_zip: 'Sherman Oaks, CA 91403', phone: '1-888-373-4564' },
+}, [{ sku: 'DW-1', requested: '08/01/2026', mfr: 'ABC' }]);
+const valid = { account: 'info', to: composed.to, subject: composed.subject, body: composed.html };
+const invalid = { ...valid, body: valid.body.replace(/<a href="mailto:info@designerwallcoverings\.com\?subject=Unsubscribe[\s\S]*?<\/a>/, '<a href="https://invalid.example/unsubscribe">unsubscribe</a>') };
+
+let requests = 0;
+const requestImpl = (_options, callback) => {
+  requests += 1;
+  const req = new EventEmitter();
+  req.write = () => {};
+  req.end = () => {
+    const response = new EventEmitter();
+    response.statusCode = 200;
+    callback(response);
+    response.emit('data', Buffer.from('{"success":true}'));
+    response.emit('end');
+  };
+  return req;
+};
+
+(async () => {
+  for (const path of ['/api/send', '/api/drafts']) {
+    await assert.rejects(Promise.resolve().then(() => georgeRequest({ path, payload: invalid, requestImpl })), { code: 'PRE_SEND_COMPLIANCE_BLOCKED' });
+  }
+  assert.equal(requests, 0, 'blocked payloads must make zero requests');
+  assert.throws(() => createGmailDraftArtifact(invalid), { code: 'PRE_SEND_COMPLIANCE_BLOCKED' });
+  assert.equal(createGmailDraftArtifact(valid), valid);
+
+  const result = await georgeRequest({ path: '/api/drafts', payload: valid, requestImpl });
+  assert.equal(result.statusCode, 200);
+  assert.equal(requests, 1, 'compliant payload should reach the injected transport once');
+  console.log('george transport fail-closed boundary: PASS');
+})().catch((error) => { console.error(error); process.exitCode = 1; });
diff --git a/test/pre-send-gate.test.js b/test/pre-send-gate.test.js
index 423093b..4921f82 100644
--- a/test/pre-send-gate.test.js
+++ b/test/pre-send-gate.test.js
@@ -27,4 +27,13 @@ for (const mutation of [
   assert.throws(() => assertPreSendCompliance(mutation), { code: 'PRE_SEND_COMPLIANCE_BLOCKED' });
 }
 
+const bodyWithoutLink = compliant.html.replace(/<a href="mailto:info@designerwallcoverings\.com\?subject=Unsubscribe[\s\S]*?<\/a>/, 'unsubscribe here');
+for (const fakeLink of [
+  '<!-- <a href="mailto:info@designerwallcoverings.com?subject=Unsubscribe">unsubscribe</a> -->',
+  'mailto:info@designerwallcoverings.com?subject=Unsubscribe',
+  '<a href="https://invalid.example/unsubscribe">unsubscribe</a>',
+]) {
+  assert.throws(() => assertPreSendCompliance({ from: REQUIRED_FROM, subject: compliant.subject, body: bodyWithoutLink + fakeLink }), { code: 'PRE_SEND_COMPLIANCE_BLOCKED' });
+}
+
 console.log('pre-send compliance gate: PASS');
diff --git a/test/sendable-callsite-coverage.test.js b/test/sendable-callsite-coverage.test.js
new file mode 100644
index 0000000..8891b2e
--- /dev/null
+++ b/test/sendable-callsite-coverage.test.js
@@ -0,0 +1,37 @@
+'use strict';
+
+const assert = require('node:assert/strict');
+const fs = require('node:fs');
+const path = require('node:path');
+
+const root = path.join(__dirname, '..');
+const allowedTransport = path.join(root, 'lib', 'george-transport.js');
+const files = [];
+function walk(dir) {
+  for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
+    if (['.git', 'node_modules', 'out', 'verification'].includes(entry.name)) continue;
+    const full = path.join(dir, entry.name);
+    if (entry.isDirectory()) walk(full);
+    else if (/\.(?:js|mjs|cjs)$/.test(entry.name) && !full.startsWith(path.join(root, 'test'))) files.push(full);
+  }
+}
+walk(root);
+
+const directGeorgeCalls = [];
+for (const file of files) {
+  if (file === allowedTransport) continue;
+  const source = fs.readFileSync(file, 'utf8');
+  if (/http\.request\([\s\S]{0,500}?path\s*:\s*['"]\/api\/(?:send|drafts)['"]/.test(source)) directGeorgeCalls.push(path.relative(root, file));
+}
+assert.deepEqual(directGeorgeCalls, [], `sendable George calls must route through lib/george-transport.js: ${directGeorgeCalls.join(', ')}`);
+
+const artifactWriters = files.filter((file) => {
+  const source = fs.readFileSync(file, 'utf8');
+  const names = ["'all-drafts.json'", '"all-drafts.json"', "'send-queue.json'", '"send-queue.json"', '`${slug}.draft.json`'];
+  return [...source.matchAll(/writeFileSync\(([\s\S]{0,300})/g)].some((match) => names.some((name) => match[1].includes(name)));
+});
+for (const file of artifactWriters) {
+  assert.match(fs.readFileSync(file, 'utf8'), /createGmailDraftArtifact\s*\(/, `${path.relative(root, file)} must gate sendable draft artifacts`);
+}
+assert.ok(artifactWriters.length > 0, 'coverage test must find at least one sendable artifact writer');
+console.log('repository sendable call-site coverage: PASS');
diff --git a/verification/e2e-proof.json b/verification/e2e-proof.json
new file mode 100644
index 0000000..b01e050
--- /dev/null
+++ b/verification/e2e-proof.json
@@ -0,0 +1,51 @@
+{
+  "intent": "Centralize fail-closed compliance enforcement for all sendable George transports and Gmail draft artifacts",
+  "risk_tier": "R3",
+  "environment": "local repository only; injected HTTP spy; no George/Gmail/FileMaker/production network calls",
+  "ticket": "TK-10940-centralize-sample-follow-up-pre-send-com",
+  "baseline": "Cycle 1 commit c74ebf7 had an ungated /api/drafts call, an ungated gmail_create_draft artifact, and accepted hidden/comment/plain-text/reserved-domain opt-out tokens",
+  "commands": [
+    "for f in test/*.test.js; do node \"$f\"; done",
+    "node --check on every changed JavaScript and MJS entry point",
+    "git diff --check"
+  ],
+  "assertions": [
+    {
+      "boundary": "compliance parser",
+      "verdict": "PASS",
+      "evidence": "test/pre-send-gate.test.js rejects HTML comments, plain-text mailto tokens, and https://invalid.example/unsubscribe while accepting lib/compose.js output"
+    },
+    {
+      "boundary": "George /api/send and /api/drafts",
+      "verdict": "PASS",
+      "evidence": "test/george-transport.test.js invokes both endpoints with a blocked payload and asserts the injected request function remains at zero calls"
+    },
+    {
+      "boundary": "gmail_create_draft artifacts",
+      "verdict": "PASS",
+      "evidence": "bin/run.js, scripts/make-drafts.js, and server.js queue creation call createGmailDraftArtifact before writing sendable payloads"
+    },
+    {
+      "boundary": "repository call-site coverage",
+      "verdict": "PASS",
+      "evidence": "test/sendable-callsite-coverage.test.js rejects direct /api/send or /api/drafts HTTP calls outside lib/george-transport.js and ungated artifact writers"
+    },
+    {
+      "boundary": "external side effects",
+      "verdict": "PASS",
+      "evidence": "No real transport, credential mutation, email/draft/send, FileMaker write, deployment, schedule change, or remote push was executed"
+    }
+  ],
+  "negative_checks": [
+    "wrong From",
+    "misleading reply subject",
+    "missing postal address",
+    "missing opt-out anchor",
+    "opt-out anchor hidden in HTML comment",
+    "plain-text mailto token",
+    "reserved invalid.example unsubscribe URL",
+    "blocked transport makes zero requests"
+  ],
+  "cleanup": "No external or persistent test state created; repository verification artifact intentionally retained",
+  "verdict": "PASS"
+}

← c70d49a auto-data-snapshot: 2026-08-28T14:34:59 (1 data files) — REA  ·  back to Sample Followup Sweep  ·  Require visible owned compliance content 297d26a →