@@ -12,7 +12,11 @@ import { toError } from '@sim/utils/errors'
1212import { HttpProxyAgent } from 'http-proxy-agent'
1313import { HttpsProxyAgent } from 'https-proxy-agent'
1414import { Agent , type Dispatcher , type RequestInit as UndiciRequestInit } from 'undici/index.js'
15- import { requireDirectOutboundTransport } from '@/lib/core/network/context.server'
15+ import { isOutboundRoutingEnabled } from '@/lib/core/network/config.server'
16+ import {
17+ requireDirectOutboundTransport ,
18+ resolveCurrentOutboundRoute ,
19+ } from '@/lib/core/network/context.server'
1620import { OutboundRoutingError } from '@/lib/core/network/routing'
1721import {
1822 createOutboundTransport ,
@@ -976,6 +980,24 @@ export function createSsrfGuardedFetchWithDispatcher(options: {
976980 }
977981}
978982
983+ let providerFetch : ReturnType < typeof createSsrfGuardedFetchWithDispatcher > | undefined
984+
985+ /**
986+ * Fetch for external provider calls. Unconfigured deployments preserve native behavior.
987+ * Required gateways use the shared guarded transport and its organization-separated pools.
988+ * User-controlled configured endpoints retain their explicit provenance-aware fetch factory.
989+ */
990+ export async function outboundFetch (
991+ input : RequestInfo | URL ,
992+ init ?: RequestInit
993+ ) : Promise < Response > {
994+ if ( ! isOutboundRoutingEnabled ( ) ) return fetch ( input , init )
995+ const route = await resolveCurrentOutboundRoute ( )
996+ if ( route . kind === 'direct' ) return fetch ( input , init )
997+ providerFetch ??= createSsrfGuardedFetchWithDispatcher ( { profile : 'contentFetch' } )
998+ return providerFetch . fetch ( input , init )
999+ }
1000+
9791001/**
9801002 * Builds a standard `fetch`-compatible function that pins every outbound
9811003 * connection to `resolvedIP`, preventing DNS-rebinding (TOCTOU) between URL
0 commit comments