@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.
- package/AUTHORING.md +92 -13
- package/CHANGELOG.md +10 -0
- package/dist/config/loader.d.ts +19 -0
- package/dist/config/loader.js +59 -28
- package/dist/define.js +20 -1
- package/dist/error-resolution.d.ts +2 -0
- package/dist/error-resolution.js +90 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/native-egress-policy.d.ts +1 -0
- package/dist/native-egress-policy.js +34 -21
- package/dist/native-ipv4.d.ts +22 -0
- package/dist/native-ipv4.js +98 -0
- package/dist/provider.d.ts +2 -2
- package/dist/provider.js +1 -1
- package/dist/runtime/native-network.d.ts +43 -7
- package/dist/runtime/native-network.js +567 -110
- package/dist/runtime/proxy-nodemaven.d.ts +7 -0
- package/dist/runtime/proxy-nodemaven.js +5 -5
- package/dist/server/serve.js +76 -100
- package/dist/types.d.ts +9 -2
- package/dist/types.js +1 -0
- package/package.json +1 -1
- package/src/config/loader.ts +110 -18
- package/src/define.ts +33 -0
- package/src/error-resolution.ts +91 -0
- package/src/index.ts +6 -0
- package/src/native-egress-policy.ts +39 -33
- package/src/native-ipv4.ts +118 -0
- package/src/provider.ts +6 -0
- package/src/runtime/native-network.ts +734 -131
- package/src/runtime/proxy-nodemaven.ts +13 -5
- package/src/server/serve.ts +118 -98
- package/src/types.ts +11 -2
|
@@ -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
|
|
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
|
|
102
|
-
if (!
|
|
89
|
+
const canonical = canonicalizeEgressHost(value);
|
|
90
|
+
if (!canonical.ok)
|
|
103
91
|
fail(`${fieldPath} must be a non-empty hostname`);
|
|
104
|
-
return
|
|
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 =
|
|
177
|
-
|
|
178
|
-
|
|
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
|
+
}
|
package/dist/provider.d.ts
CHANGED
|
@@ -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,
|
|
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) =>
|
|
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
|
|
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;
|