/**
 * SSRF-safe outbound fetch wrapper.
 *
 * The monitor strategies (http/tcp/ping) call `resolveAndValidate` before
 * connecting and then connect to the validated IP directly (see
 * `src/lib/monitor-strategies/http.strategy.ts`). Outbound *notifications*
 * (webhook channel, Telegram, PagerDuty, Teams) and the synthetic-test
 * runner go through this helper.
 *
 * As of PR-33 (EA-2) `safeOutboundFetch` delegates to `pinnedFetch`, which
 * closes the DNS-rebinding TOCTOU window. The previous implementation
 * resolved the hostname, validated it, then handed the URL to `fetch()` —
 * which performed its OWN DNS lookup, allowing a malicious resolver to
 * return a safe IP on validation and a private IP on connect. Pinned
 * fetch performs a single resolution and connects to that exact IP with
 * TLS SNI + Host header preserved for the original hostname.
 */
import { pinnedFetch } from './pinned-fetch';

export interface SafeFetchOptions {
    /** Wall-clock timeout in milliseconds. Default 10_000. */
    timeoutMs?: number;
    /**
     * Hard-coded allow-list of hostnames that bypass the SSRF guard.
     * Use only for vendor SaaS endpoints whose hostnames the operator
     * cannot influence (e.g. 'api.telegram.org').
     */
    allowedHosts?: string[];
    /** Allow private IPs. Honors env.ALLOW_PRIVATE_NETWORK by default. */
    allowPrivate?: boolean;
    /** Allow loopback / ULA. Honors env.ALLOW_LOOPBACK_PROBES by default. */
    allowLoopback?: boolean;
}

export async function safeOutboundFetch(
    input: string | URL,
    init: RequestInit = {},
    opts: SafeFetchOptions = {},
): Promise<Response> {
    return pinnedFetch(input, init, opts);
}
