// Private-Network Signal Providers (v3)
// Typed features for cx-private-network-v3 — a PUBLIC web page reaching into the
// user's local network (localhost, RFC1918 private IPs, link-local). This is the
// DNS-rebinding / local-network-pivoting / router-admin-probing class. The dead
// private-network detector was a stub; this implements it properly.
//
// Channel 'url'; evaluated per outbound request. Target: { url, initiatorPublic }.
// The load-bearing FP gate is initiatorPublic — a dev page on localhost or an
// intranet app on 10.x talking to its own network is normal and is NOT flagged;
// only a PUBLIC origin reaching into private space is suspicious.

function hostType(host) {
  if (!host) return 'public';
  let h = host.toLowerCase().replace(/^\[/, '').replace(/\]$/, ''); // strip ipv6 brackets
  if (h === 'localhost' || h === '0.0.0.0' || h === '::1') return 'localhost';
  if (/^127\./.test(h)) return 'localhost';
  if (/^10\./.test(h)) return 'private';
  if (/^192\.168\./.test(h)) return 'private';
  if (/^172\.(1[6-9]|2[0-9]|3[01])\./.test(h)) return 'private';
  if (/^169\.254\./.test(h)) return 'linklocal';
  if (/^(fe80:|fc[0-9a-f]{2}:|fd[0-9a-f]{2}:)/.test(h)) return 'private'; // ipv6 link/unique-local
  return 'public';
}

// Exported so the background can compute initiatorPublic from details.initiator.
export function isPublicHost(host) {
  return hostType(host) === 'public';
}

/**
 * @param {import('../../core/signal-provider.js').SignalProviderRegistry} registry
 */
export function registerPrivateNetworkSignals(registry) {
  // ── url.lan_probe ─────────────────────────────
  // A public page requesting an RFC1918 / link-local private IP — router / IoT /
  // internal-service probing. Almost never legitimate.
  registry.register('url', 'lan_probe', (target) => {
    if (!target.initiatorPublic) return { value: false };
    let host = ''; try { host = new URL(target.url).hostname; } catch { return { value: false }; }
    const t = hostType(host);
    if (t === 'private' || t === 'linklocal') {
      return { value: true, metadata: { host, kind: t } };
    }
    return { value: false };
  }, { returnType: 'boolean', scope: 'frame', description: 'Public page requesting a private/link-local IP' });

  // ── url.localhost_probe ───────────────────────
  // A public page requesting localhost / 127.x. Lower confidence than lan_probe —
  // a few legit local agents exist (hardware-wallet bridges, desktop apps) — but
  // it's still the classic local-service-probing vector.
  registry.register('url', 'localhost_probe', (target) => {
    if (!target.initiatorPublic) return { value: false };
    let host = ''; try { host = new URL(target.url).hostname; } catch { return { value: false }; }
    if (hostType(host) === 'localhost') {
      return { value: true, metadata: { host } };
    }
    return { value: false };
  }, { returnType: 'boolean', scope: 'frame', description: 'Public page requesting localhost / 127.x' });
}
