@apifuse/provider-sdk 2.2.0-beta.15 → 2.2.0-beta.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,4 @@
1
+ import { canonicalizeEgressHost, parseIpv4Cidr } from "./native-ipv4.js";
1
2
  const NATIVE_PROVIDER_FIELD_RECORD = {
2
3
  network: true,
3
4
  };
@@ -16,6 +17,7 @@ const NATIVE_DYNAMIC_TCP_RULE_FIELD_RECORD = {
16
17
  sourcePorts: true,
17
18
  sourcePortRanges: true,
18
19
  targetHostSuffixes: true,
20
+ targetIpv4Cidrs: true,
19
21
  targetPorts: true,
20
22
  targetPortRanges: true,
21
23
  tls: true,
@@ -81,27 +83,13 @@ function dataArray(value, fieldPath) {
81
83
  }
82
84
  return result;
83
85
  }
84
- function hasControlCharacter(value) {
85
- for (let index = 0; index < value.length; index += 1) {
86
- const code = value.charCodeAt(index);
87
- if (code <= 31 || code === 127)
88
- return true;
89
- }
90
- return false;
91
- }
92
86
  function host(value, fieldPath, suffix = false) {
93
- if (typeof value !== "string" ||
94
- !value.trim() ||
95
- hasControlCharacter(value) ||
96
- /\s/.test(value) ||
97
- value.includes("://"))
98
- fail(`${fieldPath} must be a non-empty hostname`);
99
- if (value.includes("*"))
87
+ if (typeof value === "string" && value.includes("*"))
100
88
  fail(`${fieldPath} must be an exact ${suffix ? "DNS suffix" : "hostname"}, not a wildcard`);
101
- const normalized = value.trim().toLowerCase().replace(/\.$/, "");
102
- if (!normalized)
89
+ const canonical = canonicalizeEgressHost(value);
90
+ if (!canonical.ok)
103
91
  fail(`${fieldPath} must be a non-empty hostname`);
104
- return normalized;
92
+ return canonical.host;
105
93
  }
106
94
  function port(value, fieldPath) {
107
95
  if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 1 || value > 65_535)
@@ -114,6 +102,25 @@ function ports(value, fieldPath) {
114
102
  function hostSuffixes(value, fieldPath) {
115
103
  return dataArray(value, fieldPath).map((value, index) => host(value, `${fieldPath}[${index}]`, true));
116
104
  }
105
+ function ipv4Cidrs(value, fieldPath) {
106
+ const seen = new Set();
107
+ return dataArray(value, fieldPath).map((value, index) => {
108
+ const cidrPath = `${fieldPath}[${index}]`;
109
+ if (typeof value !== "string")
110
+ fail(`${cidrPath} must be an IPv4 CIDR in a.b.c.d/nn form`);
111
+ const parsed = parseIpv4Cidr(value);
112
+ if (!parsed.ok) {
113
+ if (parsed.reason === "non-canonical-network")
114
+ fail(`${cidrPath} must use the canonical network address with no host bits set`);
115
+ fail(`${cidrPath} must be an IPv4 CIDR in a.b.c.d/nn form`);
116
+ }
117
+ const duplicateKey = `${parsed.network}/${parsed.prefix}`;
118
+ if (seen.has(duplicateKey))
119
+ fail(`${fieldPath} must not contain duplicate CIDRs`);
120
+ seen.add(duplicateKey);
121
+ return value;
122
+ });
123
+ }
117
124
  function ranges(value, fieldPath) {
118
125
  return dataArray(value, fieldPath).map((value, index) => {
119
126
  const rangePath = `${fieldPath}[${index}]`;
@@ -173,9 +180,14 @@ export function parseNativeEgressPolicy(value) {
173
180
  : ranges(rule.sourcePortRanges, `${fieldPath}.sourcePortRanges`);
174
181
  if (sourcePorts.length === 0 && sourcePortRanges.length === 0)
175
182
  fail(`${fieldPath} must declare a non-empty sourcePorts or sourcePortRanges list`);
176
- const targetHostSuffixes = hostSuffixes(rule.targetHostSuffixes, `${fieldPath}.targetHostSuffixes`);
177
- if (targetHostSuffixes.length === 0)
178
- fail(`${fieldPath}.targetHostSuffixes must not be empty`);
183
+ const targetHostSuffixes = rule.targetHostSuffixes === undefined
184
+ ? []
185
+ : hostSuffixes(rule.targetHostSuffixes, `${fieldPath}.targetHostSuffixes`);
186
+ const targetIpv4Cidrs = rule.targetIpv4Cidrs === undefined
187
+ ? []
188
+ : ipv4Cidrs(rule.targetIpv4Cidrs, `${fieldPath}.targetIpv4Cidrs`);
189
+ if (targetHostSuffixes.length === 0 && targetIpv4Cidrs.length === 0)
190
+ fail(`${fieldPath} must declare a non-empty targetHostSuffixes or targetIpv4Cidrs list`);
179
191
  const targetPorts = rule.targetPorts === undefined
180
192
  ? []
181
193
  : ports(rule.targetPorts, `${fieldPath}.targetPorts`);
@@ -190,6 +202,7 @@ export function parseNativeEgressPolicy(value) {
190
202
  sourcePorts,
191
203
  sourcePortRanges,
192
204
  targetHostSuffixes,
205
+ targetIpv4Cidrs,
193
206
  targetPorts,
194
207
  targetPortRanges,
195
208
  tls: tls(rule.tls, `${fieldPath}.tls`),
@@ -0,0 +1,22 @@
1
+ export type EgressHostCanonicalizationFailure = "not-string" | "reserved-delimiter" | "control-character" | "whitespace" | "canonicalization-empty";
2
+ export type EgressHostCanonicalizationResult = {
3
+ readonly ok: true;
4
+ readonly host: string;
5
+ } | {
6
+ readonly ok: false;
7
+ readonly reason: EgressHostCanonicalizationFailure;
8
+ };
9
+ export declare function parseStrictIpv4(value: string): number | undefined;
10
+ export declare function classifyEgressTargetHost(host: string): "ipv4" | "numeric-ambiguous" | "dns";
11
+ export declare function hasReservedEgressHostDelimiter(value: string): boolean;
12
+ export declare function hasEgressHostControlCharacter(value: string): boolean;
13
+ export declare function canonicalizeEgressHost(value: unknown): EgressHostCanonicalizationResult;
14
+ export declare function parseIpv4Cidr(value: string): {
15
+ readonly ok: true;
16
+ readonly network: number;
17
+ readonly prefix: number;
18
+ } | {
19
+ readonly ok: false;
20
+ readonly reason: "malformed" | "non-canonical-network";
21
+ };
22
+ export declare function ipv4InCidr(address: number, cidr: string): boolean;
@@ -0,0 +1,98 @@
1
+ import { domainToASCII } from "node:url";
2
+ const STRICT_IPV4_PATTERN = /^(0|[1-9]\d{0,2})\.(0|[1-9]\d{0,2})\.(0|[1-9]\d{0,2})\.(0|[1-9]\d{0,2})$/;
3
+ const DECIMAL_COMPONENT_PATTERN = /^\d+$/;
4
+ const HEX_COMPONENT_PATTERN = /^0[xX][\da-fA-F]+$/;
5
+ const FORMAT_CONTROL_PATTERN = /\p{Cf}/u;
6
+ const RESERVED_EGRESS_HOST_DELIMITERS = ["/", "\\", "?", "#", "@", "[", "]", " ", "%"];
7
+ export function parseStrictIpv4(value) {
8
+ const match = STRICT_IPV4_PATTERN.exec(value);
9
+ if (!match || match[0] !== value)
10
+ return undefined;
11
+ const [, first, second, third, fourth] = match;
12
+ if (first === undefined || second === undefined || third === undefined || fourth === undefined)
13
+ return undefined;
14
+ const octets = [Number(first), Number(second), Number(third), Number(fourth)];
15
+ if (octets.some((octet) => octet > 255))
16
+ return undefined;
17
+ const [a, b, c, d] = octets;
18
+ if (a === undefined || b === undefined || c === undefined || d === undefined)
19
+ return undefined;
20
+ return (a * 0x1000000 + b * 0x10000 + c * 0x100 + d) >>> 0;
21
+ }
22
+ export function classifyEgressTargetHost(host) {
23
+ if (parseStrictIpv4(host) !== undefined)
24
+ return "ipv4";
25
+ if (host.includes(":"))
26
+ return "numeric-ambiguous";
27
+ const labels = host.split(".");
28
+ if (labels.every((label) => DECIMAL_COMPONENT_PATTERN.exec(label)?.[0] === label ||
29
+ HEX_COMPONENT_PATTERN.exec(label)?.[0] === label))
30
+ return "numeric-ambiguous";
31
+ return "dns";
32
+ }
33
+ export function hasReservedEgressHostDelimiter(value) {
34
+ return RESERVED_EGRESS_HOST_DELIMITERS.some((delimiter) => value.includes(delimiter));
35
+ }
36
+ export function hasEgressHostControlCharacter(value) {
37
+ for (let index = 0; index < value.length; index += 1) {
38
+ const code = value.charCodeAt(index);
39
+ if (code <= 31 || code === 127)
40
+ return true;
41
+ }
42
+ return FORMAT_CONTROL_PATTERN.test(value);
43
+ }
44
+ export function canonicalizeEgressHost(value) {
45
+ if (typeof value !== "string")
46
+ return { ok: false, reason: "not-string" };
47
+ if (hasReservedEgressHostDelimiter(value))
48
+ return { ok: false, reason: "reserved-delimiter" };
49
+ if (hasEgressHostControlCharacter(value))
50
+ return { ok: false, reason: "control-character" };
51
+ if (/\s/u.test(value))
52
+ return { ok: false, reason: "whitespace" };
53
+ const raw = value.trim();
54
+ if (!raw)
55
+ return { ok: false, reason: "canonicalization-empty" };
56
+ // Classify the spelling with one optional root-label dot removed before IDNA.
57
+ // This keeps resolver-numeric ASCII forms from being widened into canonical IPv4.
58
+ const numericCandidate = raw.endsWith(".") ? raw.slice(0, -1) : raw;
59
+ const normalizedNumericCandidate = numericCandidate.toLowerCase();
60
+ if (classifyEgressTargetHost(normalizedNumericCandidate) === "numeric-ambiguous")
61
+ return { ok: true, host: normalizedNumericCandidate };
62
+ let ascii;
63
+ try {
64
+ ascii = domainToASCII(raw).toLowerCase().replace(/\.$/, "");
65
+ }
66
+ catch {
67
+ return { ok: false, reason: "canonicalization-empty" };
68
+ }
69
+ if (!ascii || /^\.+$/.test(ascii))
70
+ return { ok: false, reason: "canonicalization-empty" };
71
+ return { ok: true, host: ascii };
72
+ }
73
+ export function parseIpv4Cidr(value) {
74
+ const separator = value.indexOf("/");
75
+ if (separator <= 0 || separator !== value.lastIndexOf("/"))
76
+ return { ok: false, reason: "malformed" };
77
+ const address = parseStrictIpv4(value.slice(0, separator));
78
+ const prefixText = value.slice(separator + 1);
79
+ const prefix = Number(prefixText);
80
+ if (address === undefined ||
81
+ !Number.isInteger(prefix) ||
82
+ prefix < 0 ||
83
+ prefix > 32 ||
84
+ String(prefix) !== prefixText)
85
+ return { ok: false, reason: "malformed" };
86
+ const mask = prefix === 0 ? 0 : (0xffffffff << (32 - prefix)) >>> 0;
87
+ const network = (address & mask) >>> 0;
88
+ if (address !== network)
89
+ return { ok: false, reason: "non-canonical-network" };
90
+ return { ok: true, network, prefix };
91
+ }
92
+ export function ipv4InCidr(address, cidr) {
93
+ const parsed = parseIpv4Cidr(cidr);
94
+ if (!parsed.ok)
95
+ return false;
96
+ return (parsed.prefix === 0 ||
97
+ address >>> (32 - parsed.prefix) === parsed.network >>> (32 - parsed.prefix));
98
+ }
@@ -7,6 +7,6 @@ export { AuthError, HttpRedirectError, isProviderError, isSessionExpiredError, i
7
7
  export { getProviderLocalePath, providerLocaleKey, qualifyProviderLocaleKey, } from "./i18n/index.js";
8
8
  export { type CreateProviderChoiceContextOptions, createProviderChoiceContext, createTestProviderChoiceContext, PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV, } from "./runtime/choice.js";
9
9
  export { APIFUSE_DESCRIPTION_KEY_META_KEY, APIFUSE_REDACTION_MARKER, APIFUSE_SENSITIVE_KIND_META_KEY, APIFUSE_SENSITIVE_META_KEY, collectSensitivePaths, describeKey, field, fields, isSensitiveSchema, redactPayload, type SensitiveFieldKind, type SensitiveFieldOptions, type SensitivePath, sensitive, z, } from "./schema.js";
10
- export type { AuthAbortData, AuthAbortRetry, AuthFlowTerminalContext, AuthMode, AuthSafeData, AuthSafeJson, FlowContext, HealthCheckAssertionContext, HealthCheckCase, HealthCheckSuite, HealthCheckUnsupported, HealthJourneyDefinition, HealthJourneyEventContext, HealthJourneyManualTriggerPolicy, HealthJourneyRunContext, HealthJourneyRunResult, HealthScheduleRandomization, HttpRedirectFailureReason, HttpRedirectPolicy, HttpRedirectPolicyMode, HttpRetryOptions, HttpRetrySummary, InferSchemaOutput, NativeContext, NativeNetworkClient, NativeNetworkCloseReason, NativeNetworkConnection, NativeNetworkConnectInput, NativeNetworkConnectOptions, NativeNetworkDynamicGrantOptions, NativeNetworkEgressGrant, NativeProviderConfig, NativeProviderContext, NativeProxyDrainHandler, NativeProxyEgressInfo, NativeProxyExpiringEvent, NativeProxyExpiringReason, NativeTcpDynamicEgressRule, NativeTcpEgressGrant, NativeTcpEgressRule, NativeTcpPortRange, NativeTcpTlsMode, NativeTlsConnectOptions, OperationApprovalPolicy, OperationContractMetadata, OperationDefinition, OperationDocMeta, OperationErrorCode, OperationInputExample, OperationLifecycle, OperationObservabilityConfig, OperationObservabilitySensitiveConfig, OperationRelationships, OperationRiskClass, OperationSensitivePath, OperationToolRouterMetadata, OperationTransport, ProviderAccessVisibility, ProviderChoiceBindingOptions, ProviderChoiceContext, ProviderChoiceIssueOptions, ProviderChoiceParseOptions, ProviderContext, ProviderDefinition, ProviderDeploymentOverrides, ProviderFileRef, ProviderFilesContext, ProviderLocale, ProviderLocaleKey, ProviderLocaleKeyInput, ProviderLogoProfile, ProviderProxyPolicy, ProviderPublicConnectionMode, ProviderPublicProfile, ProviderResolvedFile, ProviderRuntimeState, ProviderStateDurationString, ProviderStateNamespace, ProviderSupportLevel, RedirectRunReason, SchemaLike, SmsOtpMatcherDefinition, StandardSchemaV1, StateCasResult, StateNamespaceOptions, StateValue, StateWriteOptions, } from "./types.js";
11
- export { createNativeNetworkClient, deriveNativeCredentialAffinityKey, NativeEgressGrantExpiredError, NativeEgressNotDeclaredError, NativeIdleTimeoutError, NativeNetworkError, NativeProxyExpiredError, resolveNativeGatewayProxy, type NativeGatewayProxy, type NativeGatewayProxyResolutionInput, type NativeGatewayProxySynthesizer, type NativeGatewayProxySynthesisInput, type NativeNetworkClientOptions, type NativeNetworkErrorCode, } from "./runtime/native-network.js";
10
+ export type { AuthAbortData, AuthAbortRetry, AuthFlowTerminalContext, AuthMode, AuthSafeData, AuthSafeJson, FlowContext, HealthCheckAssertionContext, HealthCheckCase, HealthCheckSuite, HealthCheckUnsupported, HealthJourneyDefinition, HealthJourneyEventContext, HealthJourneyManualTriggerPolicy, HealthJourneyRunContext, HealthJourneyRunResult, HealthScheduleRandomization, HttpRedirectFailureReason, HttpRedirectPolicy, HttpRedirectPolicyMode, HttpRetryOptions, HttpRetrySummary, InferSchemaOutput, NativeContext, NativeNetworkClient, NativeNetworkCloseReason, NativeNetworkConnection, NativeNetworkConnectInput, NativeNetworkConnectOptions, NativeNetworkDynamicGrantOptions, NativeNetworkEgressGrant, NativeProviderConfig, NativeProviderContext, NativeProxyDrainHandler, NativeProxyEgressInfo, NativeProxyExpiringEvent, NativeProxyExpiringReason, NativeTcpDynamicEgressRule, NativeTcpEgressGrant, NativeTcpEgressRule, NativeTcpPortRange, NativeTcpTlsMode, NativeTlsConnectOptions, OperationApprovalPolicy, OperationContractMetadata, OperationDefinition, OperationDocMeta, OperationErrorCode, ProviderErrorStatus, OperationInputExample, OperationLifecycle, OperationObservabilityConfig, OperationObservabilitySensitiveConfig, OperationRelationships, OperationRiskClass, OperationSensitivePath, OperationToolRouterMetadata, OperationTransport, ProviderAccessVisibility, ProviderChoiceBindingOptions, ProviderChoiceContext, ProviderChoiceIssueOptions, ProviderChoiceParseOptions, ProviderContext, ProviderDefinition, ProviderDeploymentOverrides, ProviderFileRef, ProviderFilesContext, ProviderLocale, ProviderLocaleKey, ProviderLocaleKeyInput, ProviderLogoProfile, ProviderProxyPolicy, ProviderPublicConnectionMode, ProviderPublicProfile, ProviderResolvedFile, ProviderRuntimeState, ProviderStateDurationString, ProviderStateNamespace, ProviderSupportLevel, RedirectRunReason, SchemaLike, SmsOtpMatcherDefinition, StandardSchemaV1, StateCasResult, StateNamespaceOptions, StateValue, StateWriteOptions, } from "./types.js";
11
+ export { createNativeNetworkClient, createEnvVendorCredentialResolver, deriveNativeCredentialAffinityKey, NativeEgressGrantExpiredError, NativeEgressNotDeclaredError, NativeIdleTimeoutError, NativeNetworkError, NativeProxyExpiredError, resolveNativeGatewayProxy, type NativeGatewayProxy, type NativeGatewayProxyResolutionInput, type NativeGatewayProxySkipReason, type NativeGatewayProxySynthesizer, type NativeGatewayProxySynthesisResult, type NativeGatewayProxySynthesisInput, type NativeNetworkClientOptions, type NativeNetworkErrorCode, type VendorCredentialLookup, type VendorCredentialResolver, } from "./runtime/native-network.js";
12
12
  export { HttpRetryAfterPolicy, HttpRetryDelayStrategy, HttpRetryJitter, HttpRetryPreset, HttpRetryUnsafeMethodPolicy, } from "./types.js";
package/dist/provider.js CHANGED
@@ -6,5 +6,5 @@ export { AuthError, HttpRedirectError, isProviderError, isSessionExpiredError, i
6
6
  export { getProviderLocalePath, providerLocaleKey, qualifyProviderLocaleKey, } from "./i18n/index.js";
7
7
  export { createProviderChoiceContext, createTestProviderChoiceContext, PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV, } from "./runtime/choice.js";
8
8
  export { APIFUSE_DESCRIPTION_KEY_META_KEY, APIFUSE_REDACTION_MARKER, APIFUSE_SENSITIVE_KIND_META_KEY, APIFUSE_SENSITIVE_META_KEY, collectSensitivePaths, describeKey, field, fields, isSensitiveSchema, redactPayload, sensitive, z, } from "./schema.js";
9
- export { createNativeNetworkClient, deriveNativeCredentialAffinityKey, NativeEgressGrantExpiredError, NativeEgressNotDeclaredError, NativeIdleTimeoutError, NativeNetworkError, NativeProxyExpiredError, resolveNativeGatewayProxy, } from "./runtime/native-network.js";
9
+ export { createNativeNetworkClient, createEnvVendorCredentialResolver, deriveNativeCredentialAffinityKey, NativeEgressGrantExpiredError, NativeEgressNotDeclaredError, NativeIdleTimeoutError, NativeNetworkError, NativeProxyExpiredError, resolveNativeGatewayProxy, } from "./runtime/native-network.js";
10
10
  export { HttpRetryAfterPolicy, HttpRetryDelayStrategy, HttpRetryJitter, HttpRetryPreset, HttpRetryUnsafeMethodPolicy, } from "./types.js";
@@ -1,10 +1,11 @@
1
1
  import { Socket } from "node:net";
2
2
  import { type TLSSocket } from "node:tls";
3
+ import { type ProxyProtocol } from "../config/loader.js";
3
4
  import { TransportError } from "../errors.js";
4
- import type { NativeNetworkClient, NativeNetworkConnection, NativeNetworkConnectInput, NativeNetworkDynamicGrantOptions, NativeNetworkEgressGrant, NativeProviderConfig, NativeProxyEgressInfo, ProviderProxyPolicy, ProviderProxyProvider } from "../types.js";
5
+ import type { NativeNetworkClient, NativeNetworkConnectInput, NativeNetworkConnection, NativeNetworkDynamicGrantOptions, NativeNetworkEgressGrant, NativeProviderConfig, NativeProxyEgressInfo, ProviderProxyPolicy, ProviderProxyProvider, EnvContext } from "../types.js";
5
6
  export type NativeNetworkErrorCode = "native_connection_aborted" | "native_connection_closed" | "native_connection_failed" | "native_connection_idle_timeout" | "native_connection_timeout" | "native_egress_authorization_failed" | "native_egress_grant_expired" | "native_egress_grant_invalid" | "native_egress_grant_limit_exceeded" | "native_egress_input_invalid" | "native_egress_not_declared" | "native_egress_policy_invalid" | "native_dynamic_egress_unsupported" | "native_proxy_expired" | "native_proxy_invalid";
6
7
  export declare class NativeNetworkError extends TransportError {
7
- constructor(message: string, code: NativeNetworkErrorCode);
8
+ constructor(message: string, code: NativeNetworkErrorCode, cause?: Error);
8
9
  get code(): NativeNetworkErrorCode;
9
10
  }
10
11
  export declare class NativeProxyExpiredError extends NativeNetworkError {
@@ -13,9 +14,9 @@ export declare class NativeProxyExpiredError extends NativeNetworkError {
13
14
  }
14
15
  /** Raised before transport setup when a native destination is not authorized. */
15
16
  export declare class NativeEgressNotDeclaredError extends NativeNetworkError {
16
- readonly host: string;
17
17
  readonly port: number;
18
18
  readonly tls: "required" | "disabled";
19
+ readonly host: string;
19
20
  constructor(host: string, port: number, tls: "required" | "disabled");
20
21
  }
21
22
  /**
@@ -23,10 +24,10 @@ export declare class NativeEgressNotDeclaredError extends NativeNetworkError {
23
24
  * its expiry remains in the client's bounded recent-expiry evidence window.
24
25
  */
25
26
  export declare class NativeEgressGrantExpiredError extends NativeNetworkError {
26
- readonly host: string;
27
27
  readonly port: number;
28
28
  readonly tls: "required" | "disabled";
29
29
  readonly expiresAt: string;
30
+ readonly host: string;
30
31
  constructor(host: string, port: number, tls: "required" | "disabled", expiresAt: string);
31
32
  }
32
33
  /** Raised when an established connection exceeds its opt-in read-idle window. */
@@ -41,13 +42,42 @@ export type NativeGatewayProxySynthesisInput = {
41
42
  readonly policy: ProviderProxyPolicy;
42
43
  readonly affinityKey?: string;
43
44
  readonly now: number;
45
+ readonly protocol: ProxyProtocol;
46
+ readonly credentials: VendorCredentialResolver;
47
+ };
48
+ export type VendorCredentialLookup = {
49
+ readonly kind: "present";
50
+ readonly values: Readonly<Record<string, string>>;
51
+ } | {
52
+ readonly kind: "absent";
53
+ readonly missing: readonly string[];
54
+ };
55
+ export type VendorCredentialResolver = (vendor: ProviderProxyProvider) => VendorCredentialLookup;
56
+ export type NativeGatewayProxySkipReason = {
57
+ readonly kind: "credentials_absent";
58
+ readonly missing: readonly string[];
59
+ } | {
60
+ readonly kind: "protocol_unsupported";
61
+ readonly protocol: string;
62
+ } | {
63
+ readonly kind: "allocation_failed";
64
+ readonly cause: Error;
65
+ } | {
66
+ readonly kind: "credential_lookup_failed";
67
+ readonly cause: Error;
44
68
  };
69
+ export type NativeGatewayProxySynthesisResult = NativeGatewayProxy | {
70
+ readonly kind: "skipped";
71
+ readonly reason: NativeGatewayProxySkipReason;
72
+ } | undefined;
45
73
  /** A vendor adapter in the ordered native gateway resolution chain. */
46
- export type NativeGatewayProxySynthesizer = (input: NativeGatewayProxySynthesisInput) => NativeGatewayProxy | undefined;
74
+ export type NativeGatewayProxySynthesizer = (input: NativeGatewayProxySynthesisInput) => NativeGatewayProxySynthesisResult | Promise<NativeGatewayProxySynthesisResult>;
47
75
  export type NativeGatewayProxyResolutionInput = {
48
76
  readonly policy: ProviderProxyPolicy;
49
77
  readonly affinityKey?: string;
50
78
  readonly now?: number;
79
+ readonly protocol?: ProxyProtocol;
80
+ readonly credentials?: VendorCredentialResolver;
51
81
  readonly gatewaySynthesizers?: readonly NativeGatewayProxySynthesizer[];
52
82
  };
53
83
  export type NativeNetworkClientOptions = {
@@ -55,6 +85,10 @@ export type NativeNetworkClientOptions = {
55
85
  readonly affinityKey?: string;
56
86
  /** Stable credential/account identity; hashed before vendor synthesis. */
57
87
  readonly credentialIdentity?: string;
88
+ /** Vendor credential lookup; defaults to the process EnvContext. */
89
+ readonly credentials?: VendorCredentialResolver;
90
+ /** Explicit CONNECT/SOCKS5 override; vendors otherwise choose their default. */
91
+ readonly proxyProtocol?: ProxyProtocol;
58
92
  /** Vendor adapters in priority order within each policy vendor slot. */
59
93
  readonly gatewaySynthesizers?: readonly NativeGatewayProxySynthesizer[];
60
94
  /** Warning-level lifecycle diagnostic sink. */
@@ -67,10 +101,12 @@ export type NativeNetworkClientOptions = {
67
101
  /** Additional deployment authorization layered on top of SDK enforcement. */
68
102
  readonly grantTcpEgress?: (input: NativeNetworkDynamicGrantOptions) => NativeNetworkEgressGrant;
69
103
  };
104
+ /** Build a resolver over the SDK's existing injectable environment context. */
105
+ export declare function createEnvVendorCredentialResolver(env?: EnvContext): VendorCredentialResolver;
70
106
  /** Domain-separated, process-independent affinity derived from credential identity. */
71
107
  export declare function deriveNativeCredentialAffinityKey(credentialIdentity: string): string;
72
- /** Resolve the first configured native gateway without invoking an allocator API. */
73
- export declare function resolveNativeGatewayProxy(input: NativeGatewayProxyResolutionInput): NativeGatewayProxy | undefined;
108
+ /** Resolve the first configured native gateway, including allocation vendors. */
109
+ export declare function resolveNativeGatewayProxy(input: NativeGatewayProxyResolutionInput): Promise<NativeGatewayProxy | undefined>;
74
110
  export declare function createNativeNetworkConnection(socket: Socket | TLSSocket, proxy: NativeGatewayProxy | undefined, options: NativeNetworkClientOptions, idleTimeoutMs?: number): NativeNetworkConnection;
75
111
  type NativeConnectTls = "required" | "disabled";
76
112
  export declare const NATIVE_EGRESS_EXPIRED_EVIDENCE_LIMIT = 256;