import { describe, expect, test } from 'bun:test'; import type { TransportReadStatus } from '../alerting/read-records'; import { auditTransportReads } from './transport-reads'; const NOW = new Date('2026-08-01T12:00:00Z'); const STALE_AFTER = 30 * 60_000; const ago = (ms: number) => new Date(NOW.getTime() - ms).toISOString(); function status(over: Partial | null): TransportReadStatus { return { transportModuleId: 'signal', last: over === null ? null : { at: ago(0), outcome: 'received', messages: 0, lastSuccessAt: ago(0), ...over }, }; } const run = (statuses: TransportReadStatus[]) => auditTransportReads({ statuses, now: NOW, staleAfterMs: STALE_AFTER }); describe('auditTransportReads', () => { test('a transport read successfully just now is not a finding', async () => { expect(await run([status({})])).toEqual([]); }); // THE case this check exists for. Six tokens were issued and zero consumed // over a week, and nothing anywhere was red (#501). test('a transport not read successfully for hours is drift', async () => { const findings = await run([ status({ at: ago(60_000), outcome: 'failed', error: 'refused', lastSuccessAt: ago(3 * 3600_000), }), ]); expect(findings).toHaveLength(1); expect(findings[0]).toMatchObject({ category: 'transport_reads', code: 'transport_reads_stale', severity: 'drift', subject: 'signal', }); expect(findings[0].message).toContain('3h ago'); }); // The decision that makes staleness safe to page on: an EMPTY read is a // success, so a quiet transport keeps refreshing lastSuccessAt. If empty // reads counted as failure this check would page on every quiet afternoon // and be switched off within a week. test('a quiet transport — successful reads, zero messages — is NOT stale', async () => { const findings = await run([ status({ at: ago(0), outcome: 'received', messages: 0, lastSuccessAt: ago(0) }), ]); expect(findings).toEqual([]); }); test('a transport that has never succeeded is drift, even if attempts are recent', async () => { const findings = await run([ status({ at: ago(0), outcome: 'failed', error: 'connection refused', lastSuccessAt: undefined, }), ]); expect(findings[0]).toMatchObject({ code: 'transport_never_read', severity: 'drift' }); expect(findings[0].details).toContain('connection refused'); }); test('a transport with no record at all is drift, not silently fine', async () => { const findings = await run([status(null)]); expect(findings[0]).toMatchObject({ code: 'transport_never_polled', severity: 'drift' }); }); // A transport with no `receive` is working as designed. Paging about it // would be paging about a healthy system, which teaches operators to ignore // the check. test('a unidirectional transport is never a finding', async () => { const findings = await run([ status({ at: ago(10 * 3600_000), outcome: 'unidirectional', lastSuccessAt: undefined }), ]); expect(findings).toEqual([]); }); test('just inside the threshold is not yet drift', async () => { expect(await run([status({ lastSuccessAt: ago(STALE_AFTER - 1_000) })])).toEqual([]); }); test('just outside the threshold is drift', async () => { const findings = await run([status({ lastSuccessAt: ago(STALE_AFTER + 1_000) })]); expect(findings).toHaveLength(1); }); // The remediation must point at something that does not consume the queue. // `celilo alerts poll` would READ, and a suggestion that eats the operator's // acknowledgement is worse than no suggestion (#541). test('a stale finding sends you to the journal, not to a read', async () => { const findings = await run([status({ lastSuccessAt: ago(3 * 3600_000) })]); expect(findings[0].remediation).toBe('celilo module journal signal'); }); test('each transport is judged on its own record', async () => { const findings = await run([ { transportModuleId: 'signal', last: status({}).last }, { transportModuleId: 'sms', last: status({ lastSuccessAt: ago(9 * 3600_000) }).last }, ]); expect(findings).toHaveLength(1); expect(findings[0].subject).toBe('sms'); }); });