← back to Sample Followup Sweep
test/sent-stamp-heartbeat.test.js
106 lines
'use strict';
// TK-12351: dead-letter heartbeat + vid-keyed pull-forward. Negative tests: each check must go RED
// on its injected fault. No FM, no network, no fs.
const assert = require('node:assert/strict');
const path = require('node:path');
const { pathToFileURL } = require('node:url');
(async () => {
const core = await import(pathToFileURL(path.join(__dirname, '../scripts/sent-stamp-core.mjs')).href);
const DAY = 86400e3;
const NOW = new Date(2026, 8, 26, 9, 0, 0).getTime();
const at = daysAgo => String(NOW - daysAgo * DAY);
const base = { now: NOW, searchDays: 21, nearDays: 5 };
// ── (a) heartbeat ──────────────────────────────────────────────────────────────────────────
const msgs = [
{ id: 'fresh', to: 'a@v.com', internalDate: at(2) },
{ id: 'old-done', to: 'b@v.com', internalDate: at(19) },
{ id: 'old-stuck', to: 'Lin <samples@lincrusta.com>', internalDate: at(18) }, // 3d left
];
const clean = { fresh: { stamped: 1, failed: 0 }, 'old-done': { stamped: 2, failed: 0 }, 'old-stuck': { stamped: 1, failed: 0 } };
const hbClean = core.buildHeartbeat({ ...base, ledger: clean, msgs });
assert.equal(hbClean.verdict, 'PASS', 'clean → PASS');
assert.equal(hbClean.status, 'PASS');
assert.deepEqual(hbClean.population, { sends_seen: 3, terminal: 3, non_terminal: 0, unprocessed: 0, ledger_entries: 3 });
console.log('(a1) PASS — clean ledger → PASS, population carried beside observed');
const stuck = { ...clean, 'old-stuck': { vids: ['LIN'], stamped: 0, failed: 0, attempts: 40, to: 'samples@lincrusta.com' } };
const hbStuck = core.buildHeartbeat({ ...base, ledger: stuck, msgs });
assert.equal(hbStuck.verdict, 'WARN', 'near-expiry non-terminal → WARN');
assert.equal(hbStuck.near_expiry.length, 1);
assert.equal(hbStuck.near_expiry[0].id, 'old-stuck');
assert.equal(hbStuck.near_expiry[0].state, 'stamped:0');
assert.equal(hbStuck.near_expiry[0].days_left, 3);
assert.equal(hbStuck.near_expiry[0].sent_on, '09/08/2026');
// a non-terminal entry with plenty of runway is NOT a dead-letter warning (no nagging on normal retries)
const young = { ...clean, fresh: { skip: 'no vid for recipient' } };
assert.equal(core.buildHeartbeat({ ...base, ledger: young, msgs }).verdict, 'PASS', 'non-terminal with 19d left is not near expiry');
console.log('(a2) PASS — non-terminal within 5d of aging out → WARN; far from expiry stays PASS');
const hbSearchErr = core.buildHeartbeat({ ...base, ledger: clean, msgs, searchErr: 'HTTP 502' });
assert.equal(hbSearchErr.verdict, 'WARN', 'search error must never be PASS');
assert.match(hbSearchErr.not_measured.join(), /HTTP 502/);
assert.equal(core.buildHeartbeat({ ...base, ledger: clean, msgs, searchErr: 'truncated at 10 pages' }).verdict, 'WARN');
assert.equal(core.buildHeartbeat({ ...base, ledger: {}, msgs: [] }).verdict, 'WARN', '0 of 0 is NOT-MEASURED, not PASS');
assert.equal(core.buildHeartbeat({ ...base, ledger: clean, msgs, results: [{ id: 'x', failed: 1 }] }).verdict, 'WARN', 'FM lookup error → WARN');
assert.equal(core.buildHeartbeat({ ...base, ledger: clean, msgs, results: [{ id: 'x', bodyFailed: true }] }).verdict, 'WARN', 'body fetch fail → WARN');
assert.equal(core.buildHeartbeat({ ...base, ledger: clean, msgs: [...msgs, { id: 'e', error: 'fetch-failed' }] }).verdict, 'WARN', 'metadata fail → WARN');
assert.equal(core.buildHeartbeat({ ...base, ledger: clean, msgs, ledgerErr: 'Unexpected token' }).verdict, 'WARN', 'unreadable ledger → WARN');
// transient-miss grace: a partial pass right after a FULL measure is not a finding; a persistent one is
const partial = { ...base, ledger: clean, msgs, results: [{ id: 'x', bodyFailed: true }] };
assert.equal(core.buildHeartbeat({ ...partial, lastFullMeasureAt: NOW - 60e3 }).verdict, 'PASS', 'lone transient miss inside grace');
assert.equal(core.buildHeartbeat({ ...partial, lastFullMeasureAt: NOW - 31 * 60e3 }).verdict, 'WARN', 'no full measure for >30 min → WARN');
assert.equal(core.buildHeartbeat({ ...base, ledger: clean, msgs, searchErr: 'HTTP 500', lastFullMeasureAt: NOW - 31 * 60e3 }).verdict, 'WARN');
assert.equal(core.buildHeartbeat({ ...base, ledger: {}, msgs: [], lastFullMeasureAt: NOW - 60e3 }).verdict, 'WARN', 'empty population gets no grace');
assert.equal(core.buildHeartbeat({ ...base, ledger: clean, msgs, ledgerErr: 'bad', lastFullMeasureAt: NOW - 60e3 }).verdict, 'WARN', 'unreadable ledger gets no grace');
assert.equal(core.buildHeartbeat({ ...partial, lastFullMeasureAt: NOW - 60e3, ledger: stuck }).verdict, 'WARN', 'grace never hides a near-expiry finding');
assert.equal(core.buildHeartbeat({ ...base, ledger: clean, msgs, results: [{ id: 'x', failed: 1 }], lastFullMeasureAt: NOW - 60e3 }).verdict, 'WARN', 'FileMaker errors get no grace');
assert.equal(hbClean.full_measure, true); assert.equal(hbClean.last_full_measure_at, new Date(NOW).toISOString());
console.log('(a3) PASS — unmeasured (search error / truncated / empty / FM error / body / metadata / ledger) → WARN, never PASS');
// just-aged-out unresolved entry (no longer returned by the search) → WARN; undated legacy / long-gone → no nag
const expired = { ...clean, gone: { skip: 'no vid for recipient', sent_on: core.fmt(new Date(NOW - 23 * DAY)) } };
const hbExp = core.buildHeartbeat({ ...base, ledger: expired, msgs });
assert.equal(hbExp.verdict, 'WARN'); assert.equal(hbExp.recently_expired[0].id, 'gone');
assert.equal(core.buildHeartbeat({ ...base, ledger: expired, msgs, searchErr: 'x' }).recently_expired.length, 0, 'incomplete search cannot claim expiry');
const ancient = { ...clean, legacy: { stamped: 0 }, long: { skip: 'x', sent_on: '06/01/2026' } };
assert.equal(core.buildHeartbeat({ ...base, ledger: ancient, msgs }).verdict, 'PASS', 'decays: undated/long-expired entries do not pin amber forever');
console.log('(a4) PASS — aged out unresolved in last 7d → WARN; decays after');
const hbFail = core.failHeartbeat('boom', NOW);
assert.equal(hbFail.verdict, 'FAIL'); assert.equal(hbFail.status, 'FAIL');
console.log('(a5) PASS — a pass that threw → FAIL');
// skips now carry sent_on so they can be aged after leaving the search
const rs = await core.runPass({ msgs: [{ id: 'u', to: 'x@nowhere.example', internalDate: at(4) }], ledger: {}, now: NOW, dry: false, retrySecs: 900, minAgeDays: 10, maxAgeDays: 60,
deps: { emailVid: {}, getBody: async () => '', stamp: async () => ({ stamped: [] }) } });
assert.equal(rs.ledger.u.sent_on, core.fmt(new Date(NOW - 4 * DAY)));
// ── (b) vid-keyed pull-forward (Lincrusta: sample_email ≠ main_email, one vendor) ──────────
const ev = core.buildEmailVid([{ slug: 'lincrusta', vid: 'LIN' }], { lincrusta: { sample_email: 'samples@lincrusta.com', main_email: 'info@lincrusta.com' } });
const older = { id: 'old', to: 'Samples <samples@lincrusta.com>', internalDate: at(13) };
const newer = { id: 'new', to: 'info@lincrusta.com', internalDate: at(2) };
const led = { old: { vids: ['LIN'], stamped: 0, last_try: new Date(NOW - 60e3).toISOString() } }; // older is in backoff
const order = [];
await core.runPass({ msgs: [newer, older], ledger: led, now: NOW, dry: false, retrySecs: 900, minAgeDays: 10, maxAgeDays: 60,
deps: { emailVid: ev, getBody: async id => id, stamp: async (v, body, w, sentOn) => { order.push(`${body}@${sentOn}`); return { stamped: [] }; } } });
assert.deepEqual(order, [`old@${core.fmt(new Date(NOW - 13 * DAY))}`, `new@${core.fmt(new Date(NOW - 2 * DAY))}`],
'older send to a DIFFERENT address of the same vid must run first and own the chase date');
// unrelated vendor in backoff is NOT pulled forward
const ev2 = core.buildEmailVid([{ slug: 'lincrusta', vid: 'LIN' }, { slug: 'k', vid: 'KRA' }], { lincrusta: { main_email: 'info@lincrusta.com' }, k: { sample_email: 'k@kravet.com' } });
const order2 = [];
await core.runPass({ msgs: [{ id: 'new', to: 'info@lincrusta.com', internalDate: at(2) }, { id: 'kold', to: 'k@kravet.com', internalDate: at(13) }],
ledger: { kold: { vids: ['KRA'], stamped: 0, last_try: new Date(NOW - 60e3).toISOString() } }, now: NOW, dry: false, retrySecs: 900, minAgeDays: 10, maxAgeDays: 60,
deps: { emailVid: ev2, getBody: async id => id, stamp: async (v, body) => { order2.push(body); return { stamped: [] }; } } });
assert.deepEqual(order2, ['new'], 'a different vendor in backoff stays in backoff');
// address fallback when nothing resolves: same unmapped address still pulls forward (reaches the skip path)
const r3 = await core.runPass({ msgs: [{ id: 'n', to: 'z@x.example', internalDate: at(2) }, { id: 'o', to: 'Z <z@x.example>', internalDate: at(13) }],
ledger: { o: { skip: 'no vid for recipient', last_try: new Date(NOW - 60e3).toISOString() } }, now: NOW, dry: false, retrySecs: 900, minAgeDays: 10, maxAgeDays: 60,
deps: { emailVid: {}, getBody: async () => '', stamp: async () => ({ stamped: [] }) } });
assert.equal(r3.results.find(x => x.id === 'o')?.why, 'retry-ahead-of-newer', 'address fallback keeps unmapped pull-forward');
console.log('(b) PASS — pull-forward keyed on resolved vid (Lincrusta alias), unrelated vendor untouched, address fallback kept');
console.log('sent-stamp-heartbeat: ALL PASS');
})().catch(e => { console.error('FAIL:', e.message); process.exit(1); });