← back to Rentv Adintel

test/compliance.test.js

145 lines

'use strict';
/**
 * Tests for the compliance guards (spec §6, §32).
 * Modules under test are being written concurrently by teammates, so each is
 * imported DEFENSIVELY and the relevant test t.skip()s when the module is
 * absent — `node --test` must never hard-crash on a missing file.
 *
 * Pure-function level only: no DB, no live network. The fetch-guard cases we
 * assert (LinkedIn hosts, literal private/metadata/loopback IPs) all reject
 * BEFORE any DNS resolution, so these stay offline and deterministic.
 */

const test = require('node:test');
const assert = require('node:assert');

function tryRequire(p) {
  try {
    return require(p);
  } catch (_e) {
    return null;
  }
}

const fetchGuard = tryRequire('../lib/compliance/fetch-guard');
const noInferredEmail = tryRequire('../lib/compliance/no-inferred-email');
const sourcePolicy = tryRequire('../lib/compliance/source-policy');

// --------------------------------------------------------------------------
// fetch-guard — assertFetchAllowed / isBlockedIp (§6.4, §32)
// --------------------------------------------------------------------------

test('assertFetchAllowed throws for a LinkedIn profile URL', async (t) => {
  if (!fetchGuard || !fetchGuard.assertFetchAllowed) return t.skip('fetch-guard not present yet');
  await assert.rejects(
    () => fetchGuard.assertFetchAllowed('https://www.linkedin.com/in/x'),
    /linkedin/i
  );
});

test('assertFetchAllowed throws for the cloud metadata IP 169.254.169.254', async (t) => {
  if (!fetchGuard || !fetchGuard.assertFetchAllowed) return t.skip('fetch-guard not present yet');
  await assert.rejects(() => fetchGuard.assertFetchAllowed('http://169.254.169.254/'));
});

test('assertFetchAllowed throws for loopback 127.0.0.1', async (t) => {
  if (!fetchGuard || !fetchGuard.assertFetchAllowed) return t.skip('fetch-guard not present yet');
  await assert.rejects(() => fetchGuard.assertFetchAllowed('http://127.0.0.1/'));
});

test('isBlockedIp flags private/loopback/metadata ranges, allows a public IP', (t) => {
  if (!fetchGuard || !fetchGuard.isBlockedIp) return t.skip('isBlockedIp not present yet');
  const { isBlockedIp } = fetchGuard;
  assert.strictEqual(isBlockedIp('169.254.169.254'), true); // metadata / link-local
  assert.strictEqual(isBlockedIp('127.0.0.1'), true); // loopback
  assert.strictEqual(isBlockedIp('10.0.0.5'), true); // private
  assert.strictEqual(isBlockedIp('192.168.1.1'), true); // private
  assert.strictEqual(isBlockedIp('::1'), true); // IPv6 loopback
  assert.strictEqual(isBlockedIp('8.8.8.8'), false); // public — allowed
});

// --------------------------------------------------------------------------
// source-policy — validateSourcePolicy (§6.2)
// --------------------------------------------------------------------------

test('validateSourcePolicy rejects an automated costar.com policy', (t) => {
  if (!sourcePolicy || !sourcePolicy.validateSourcePolicy) return t.skip('source-policy not present yet');
  const result = sourcePolicy.validateSourcePolicy({
    sourceKey: 'costar',
    displayName: 'CoStar',
    baseUrl: 'https://www.costar.com',
    accessMethod: 'first_party_public_web',
    allowsAutomatedAccess: true,
    enabled: true,
  });
  assert.strictEqual(result.valid, false);
  assert.ok(Array.isArray(result.errors) && result.errors.length > 0);
});

test('validateSourcePolicy accepts a permitted first-party public source', (t) => {
  if (!sourcePolicy || !sourcePolicy.validateSourcePolicy) return t.skip('source-policy not present yet');
  const result = sourcePolicy.validateSourcePolicy({
    sourceKey: 'rentv',
    displayName: 'RENTV public pages',
    baseUrl: 'https://www.rentv.com',
    accessMethod: 'first_party_public_web',
    allowsAutomatedAccess: true,
    maxRequestsPerMinute: 6,
    enabled: true,
  });
  assert.strictEqual(result.valid, true, JSON.stringify(result.errors));
});

test('validateSourcePolicy rejects an automated linkedin.com policy', (t) => {
  if (!sourcePolicy || !sourcePolicy.validateSourcePolicy) return t.skip('source-policy not present yet');
  const result = sourcePolicy.validateSourcePolicy({
    sourceKey: 'li',
    displayName: 'LinkedIn',
    baseUrl: 'https://www.linkedin.com',
    accessMethod: 'first_party_public_web',
    allowsAutomatedAccess: true,
    enabled: true,
  });
  assert.strictEqual(result.valid, false);
});

// --------------------------------------------------------------------------
// no-inferred-email — assertContactEvidence (§6.8, §6.9, §6.11)
// --------------------------------------------------------------------------

test('assertContactEvidence throws for an empty contact', (t) => {
  if (!noInferredEmail || !noInferredEmail.assertContactEvidence) return t.skip('no-inferred-email not present yet');
  assert.throws(() => noInferredEmail.assertContactEvidence({}));
});

test('assertContactEvidence throws without source_evidence_id', (t) => {
  if (!noInferredEmail || !noInferredEmail.assertContactEvidence) return t.skip('no-inferred-email not present yet');
  assert.throws(() => noInferredEmail.assertContactEvidence({ explicitly_public: true }));
});

test('assertContactEvidence throws when not explicitly_public', (t) => {
  if (!noInferredEmail || !noInferredEmail.assertContactEvidence) return t.skip('no-inferred-email not present yet');
  assert.throws(() => noInferredEmail.assertContactEvidence({ source_evidence_id: 'x' }));
});

test('assertContactEvidence passes for an explicitly-public, evidenced contact', (t) => {
  if (!noInferredEmail || !noInferredEmail.assertContactEvidence) return t.skip('no-inferred-email not present yet');
  assert.strictEqual(
    noInferredEmail.assertContactEvidence({ source_evidence_id: 'x', explicitly_public: true }),
    true
  );
});

test('looksLikePatternEmail flags a first.last@domain permutation', (t) => {
  if (!noInferredEmail || !noInferredEmail.looksLikePatternEmail) return t.skip('looksLikePatternEmail not present yet');
  assert.strictEqual(
    noInferredEmail.looksLikePatternEmail('jane.smith@acme.com', 'Jane Smith', 'acme.com'),
    true
  );
  // A genuinely-published generic mailbox is not a name permutation.
  assert.strictEqual(
    noInferredEmail.looksLikePatternEmail('media@acme.com', 'Jane Smith', 'acme.com'),
    false
  );
});