/** * The recurrence gate celilo#626 asks for, at the layer it can actually be * asserted: feed the check a public record that diverges from where the fleet * really is, and it must say so. * * Every check celilo had answered "healthy" for the nine days five public * names were dark. This is the one that could not have. */ import { describe, expect, test } from 'bun:test'; import { type IngressObservation, type PublicDnsEvidence, type PublicDnsProbe, type PublicResolution, auditPublicDns, } from './public-dns'; const FLEET_INGRESS = '71.36.123.107'; /** The address the fleet moved off, and kept publishing for nine days. */ const DEAD_ADDRESS = '71.36.112.98'; const LONG_AGO = new Date('2026-08-01T00:00:00Z'); const NOW = new Date('2026-08-06T00:00:00Z'); function probe(options: { ingress?: IngressObservation; answers?: Record; fallback?: PublicResolution; }): PublicDnsProbe { return { resolver: '1.1.1.1', echoService: 'https://echo.example', async observeIngress() { return options.ingress ?? { kind: 'observed', ip: FLEET_INGRESS }; }, async resolve(fqdn) { return ( options.answers?.[fqdn] ?? options.fallback ?? { kind: 'answer', ip: FLEET_INGRESS, ttlSeconds: 180 } ); }, }; } function declared(fqdn: string, lastAssertedAt = LONG_AGO) { return { fqdn, companion: false, lastAssertedAt }; } describe('auditPublicDns', () => { test('a record pointing at an address the fleet no longer holds is a finding', async () => { const findings = await auditPublicDns({ records: [declared('apt.celilo.computer')], probe: probe({ answers: { 'apt.celilo.computer': { kind: 'answer', ip: DEAD_ADDRESS, ttlSeconds: 180 }, }, }), now: NOW, }); expect(findings.length).toBe(1); expect(findings[0].code).toBe('public_dns_stale'); expect(findings[0].subject).toBe('apt.celilo.computer'); // The finding has to name both addresses; "DNS is wrong" is not actionable. expect(findings[0].message).toContain(DEAD_ADDRESS); expect(findings[0].message).toContain(FLEET_INGRESS); }); test('a record that agrees with the fleet is silent', async () => { const findings = await auditPublicDns({ records: [declared('git.celilo.computer')], probe: probe({}), now: NOW, }); expect(findings).toEqual([]); }); // ── Hysteresis: propagation is not a fault ──────────────────────────────── test('divergence inside the record TTL is propagation, not a finding', async () => { const assertedSecondsAgo = 60; const findings = await auditPublicDns({ records: [ declared('git.celilo.computer', new Date(NOW.getTime() - assertedSecondsAgo * 1000)), ], probe: probe({ answers: { 'git.celilo.computer': { kind: 'answer', ip: DEAD_ADDRESS, ttlSeconds: 180 }, }, }), now: NOW, }); // An ISP re-lease produces exactly this for up to one TTL. Alerting here // would page on every re-lease, and a check nobody trusts is not a check. expect(findings).toEqual([]); }); test('the same divergence once the TTL has elapsed IS a finding', async () => { const findings = await auditPublicDns({ records: [declared('git.celilo.computer', new Date(NOW.getTime() - 181 * 1000))], probe: probe({ answers: { 'git.celilo.computer': { kind: 'answer', ip: DEAD_ADDRESS, ttlSeconds: 180 }, }, }), now: NOW, }); expect(findings.map((f) => f.code)).toEqual(['public_dns_stale']); }); // ── Missing evidence is louder than absent evidence ─────────────────────── test('one undetermined run stays quiet', async () => { const findings = await auditPublicDns({ records: [declared('git.celilo.computer')], probe: probe({ ingress: { kind: 'undetermined', reason: 'ECONNREFUSED' } }), now: NOW, }); expect(findings).toEqual([]); }); test('consecutive undetermined runs become their own finding', async () => { let evidence: PublicDnsEvidence[] = []; const run = () => auditPublicDns({ records: [declared('git.celilo.computer')], probe: probe({ ingress: { kind: 'undetermined', reason: 'ECONNREFUSED' } }), evidence, saveEvidence: (next) => { evidence = next; }, now: NOW, }); expect(await run()).toEqual([]); expect(await run()).toEqual([]); const findings = await run(); expect(findings.map((f) => f.code)).toEqual(['public_dns_unverifiable']); // Distinguishable from "the site is unreachable" — this says nothing is // currently checking, which is the state the outage hid behind. expect(findings[0].message).toContain('unverifiable'); // D7: "could not tell" is unmeasured, not drift. It must stop the verdict // at UNKNOWN, never render as an ordinary divergence. expect(findings[0].severity).toBe('unmeasured'); }); test('a run that obtained evidence resets the count', async () => { let evidence: PublicDnsEvidence[] = []; const save = (next: PublicDnsEvidence[]) => { evidence = next; }; const args = (ingress?: IngressObservation) => ({ records: [declared('git.celilo.computer')], probe: probe({ ingress }), evidence, saveEvidence: save, now: NOW, }); await auditPublicDns(args({ kind: 'undetermined', reason: 'ECONNREFUSED' })); await auditPublicDns(args({ kind: 'undetermined', reason: 'ECONNREFUSED' })); await auditPublicDns(args()); expect(evidence).toEqual([]); expect(await auditPublicDns(args({ kind: 'undetermined', reason: 'ECONNREFUSED' }))).toEqual( [], ); }); // ── Companions: best effort must not mean silent ────────────────────────── test('an unclaimed companion is reported with the manual registrar step', async () => { const findings = await auditPublicDns({ records: [{ fqdn: 'www.peterbanka.org', companion: true, lastAssertedAt: LONG_AGO }], probe: probe({ // The parked placeholder Namecheap keeps serving after reporting // ErrCount 0 for an update it never applied (design.md D3). answers: { 'www.peterbanka.org': { kind: 'answer', ip: '1.2.23.4', ttlSeconds: 1799 } }, }), now: NOW, }); expect(findings.map((f) => f.code)).toEqual(['public_dns_companion_unclaimed']); expect(findings[0].remediation).toContain('Dynamic DNS'); }); test('a name with no public record at all is a finding', async () => { const findings = await auditPublicDns({ records: [declared('nexus.lunacycle.net')], probe: probe({ fallback: { kind: 'no_record' } }), now: NOW, }); expect(findings.map((f) => f.code)).toEqual(['public_dns_missing']); }); test('a name the resolver will not answer for is unmeasured once it stops being a blip (D7)', async () => { const args = () => ({ records: [declared('nexus.lunacycle.net')], probe: probe({ answers: { 'nexus.lunacycle.net': { kind: 'undetermined' as const, reason: 'timeout' } }, }), undeterminedThreshold: 1, now: NOW, }); const findings = await auditPublicDns(args()); expect(findings.map((f) => f.code)).toEqual(['public_dns_unverifiable']); // The resolver did not answer, so the truth about this name is unknown — // not fine, not broken. It must stop the verdict at UNKNOWN. expect(findings[0].severity).toBe('unmeasured'); }); test('an empty ledger never touches the network', async () => { const findings = await auditPublicDns({ records: [], probe: { resolver: 'x', echoService: 'y', observeIngress() { throw new Error('probed with nothing to check'); }, resolve() { throw new Error('probed with nothing to check'); }, }, now: NOW, }); expect(findings).toEqual([]); }); });