@apifuse/provider-sdk 2.2.0-beta.14 → 2.2.0-beta.16
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 +52 -13
- package/CHANGELOG.md +11 -0
- package/dist/define.js +29 -1
- package/dist/error-resolution.d.ts +2 -0
- package/dist/error-resolution.js +90 -0
- package/dist/errors.d.ts +12 -0
- package/dist/errors.js +19 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/native-egress-policy.d.ts +27 -0
- package/dist/native-egress-policy.js +225 -0
- package/dist/provider.d.ts +3 -3
- package/dist/provider.js +2 -2
- package/dist/runtime/http.js +189 -9
- package/dist/runtime/native-network.d.ts +39 -4
- package/dist/runtime/native-network.js +365 -20
- package/dist/runtime/redirects.d.ts +29 -0
- package/dist/runtime/redirects.js +36 -0
- package/dist/runtime/stealth.js +16 -44
- package/dist/server/serve.js +105 -94
- package/dist/testing/run.js +32 -13
- package/dist/types.d.ts +26 -3
- package/dist/types.js +1 -0
- package/package.json +1 -1
- package/src/define.ts +44 -0
- package/src/error-resolution.ts +91 -0
- package/src/errors.ts +28 -0
- package/src/index.ts +7 -0
- package/src/native-egress-policy.ts +285 -0
- package/src/provider.ts +8 -0
- package/src/runtime/http.ts +217 -9
- package/src/runtime/native-network.ts +474 -22
- package/src/runtime/redirects.ts +66 -0
- package/src/runtime/stealth.ts +20 -47
- package/src/server/serve.ts +141 -92
- package/src/testing/run.ts +39 -14
- package/src/types.ts +37 -3
package/dist/provider.js
CHANGED
|
@@ -2,9 +2,9 @@ export { AuthAbortError, credentialsAuthChallenge, createAuthFlowHelpers, define
|
|
|
2
2
|
export { createFormCeremony } from "./ceremonies/index.js";
|
|
3
3
|
export { assertFreshProviderChoiceIssuedAt, createProviderChoiceToken, ProviderChoiceTokenError, parseProviderChoiceToken, } from "./choice-token.js";
|
|
4
4
|
export { centered, delayed, defineHealthJourney, defineOperation, defineProvider, defineSmsOtpMatcher, every, } from "./define.js";
|
|
5
|
-
export { AuthError, isProviderError, isSessionExpiredError, isTransportError, ProviderError, SessionExpiredError, TransportError, ValidationError, } from "./errors.js";
|
|
5
|
+
export { AuthError, HttpRedirectError, isProviderError, isSessionExpiredError, isTransportError, ProviderError, SessionExpiredError, TransportError, ValidationError, } from "./errors.js";
|
|
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, NativeIdleTimeoutError, NativeNetworkError, NativeProxyExpiredError, resolveNativeGatewayProxy, } from "./runtime/native-network.js";
|
|
9
|
+
export { createNativeNetworkClient, deriveNativeCredentialAffinityKey, NativeEgressGrantExpiredError, NativeEgressNotDeclaredError, NativeIdleTimeoutError, NativeNetworkError, NativeProxyExpiredError, resolveNativeGatewayProxy, } from "./runtime/native-network.js";
|
|
10
10
|
export { HttpRetryAfterPolicy, HttpRetryDelayStrategy, HttpRetryJitter, HttpRetryPreset, HttpRetryUnsafeMethodPolicy, } from "./types.js";
|
package/dist/runtime/http.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { policyRotatesTransportVendorChain, resolvePolicyTransportAttemptCap, resolveProxyConfigAsync, } from "../config/loader.js";
|
|
2
|
-
import { ProviderError, TransportError } from "../errors.js";
|
|
2
|
+
import { HttpRedirectError, ProviderError, TransportError } from "../errors.js";
|
|
3
3
|
import { parseSseStream, readableBytes, readableLines, readableTextChunks } from "../stream.js";
|
|
4
4
|
import { computeProxyAttemptIndex, computeProxyTransportRetryDelayMs, createDefaultProxyTransportRetryOptions, isProxyTransportRetryMethod, normalizeProxyTransportRetryOptions, proxyTransportRetryErrorCode, proxyTransportRetryErrorStatus, shouldRetryProxyTransportAttempt, validateUnsafeProxyTransportRetryMethods, } from "./proxy-retry-policy.js";
|
|
5
|
+
import { evaluateRedirectHop, isRedirectStatus, resolveRedirectUrl } from "./redirects.js";
|
|
5
6
|
import { normalizeHttpRequestBody, redactSensitiveError, redactSensitiveRequestError, serializeRequestUrl, } from "./request-options.js";
|
|
6
7
|
const DEFAULT_HTTP_BASE_URL = "http://localhost";
|
|
7
8
|
function isHttpStatusOutcome(outcome) {
|
|
@@ -196,6 +197,181 @@ function isAbsoluteUrl(url) {
|
|
|
196
197
|
function resolveHttpUrl(baseUrl, url) {
|
|
197
198
|
return new URL(url, baseUrl ?? DEFAULT_HTTP_BASE_URL).toString();
|
|
198
199
|
}
|
|
200
|
+
const MAX_HTTP_REDIRECT_HOPS = 20;
|
|
201
|
+
const HTTP_REDIRECT_POLICY_FIELDS = new Set(["mode", "maxHops"]);
|
|
202
|
+
const REDIRECT_BODY_HEADERS = new Set([
|
|
203
|
+
"content-encoding",
|
|
204
|
+
"content-language",
|
|
205
|
+
"content-location",
|
|
206
|
+
"content-type",
|
|
207
|
+
]);
|
|
208
|
+
const MALFORMED_REDIRECT_TARGET = "[malformed redirect target]";
|
|
209
|
+
function invalidHttpRedirectPolicy(message, cause) {
|
|
210
|
+
return new TransportError(`Invalid ctx.http redirectPolicy: ${message}`, {
|
|
211
|
+
code: "http_redirect_policy_invalid",
|
|
212
|
+
...(cause ? { cause } : {}),
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
/** Snapshot untrusted caller input synchronously, before proxy resolution or fetch. */
|
|
216
|
+
function normalizeHttpRedirectPolicy(value) {
|
|
217
|
+
if (value === undefined)
|
|
218
|
+
return undefined;
|
|
219
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
220
|
+
throw invalidHttpRedirectPolicy("expected an object");
|
|
221
|
+
}
|
|
222
|
+
try {
|
|
223
|
+
const keys = Reflect.ownKeys(value);
|
|
224
|
+
for (const key of keys) {
|
|
225
|
+
if (typeof key !== "string" || !HTTP_REDIRECT_POLICY_FIELDS.has(key)) {
|
|
226
|
+
throw invalidHttpRedirectPolicy(`unknown field ${String(key)}`);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
for (const field of HTTP_REDIRECT_POLICY_FIELDS) {
|
|
230
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, field);
|
|
231
|
+
if (!descriptor || !("value" in descriptor)) {
|
|
232
|
+
throw invalidHttpRedirectPolicy(`${field} must be an own data property`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
const record = value;
|
|
236
|
+
if (record.mode !== "same-origin") {
|
|
237
|
+
throw invalidHttpRedirectPolicy('mode must be "same-origin"');
|
|
238
|
+
}
|
|
239
|
+
if (typeof record.maxHops !== "number" ||
|
|
240
|
+
!Number.isInteger(record.maxHops) ||
|
|
241
|
+
record.maxHops < 0 ||
|
|
242
|
+
record.maxHops > MAX_HTTP_REDIRECT_HOPS) {
|
|
243
|
+
throw invalidHttpRedirectPolicy(`maxHops must be an integer from 0 to ${MAX_HTTP_REDIRECT_HOPS}`);
|
|
244
|
+
}
|
|
245
|
+
return { mode: "same-origin", maxHops: record.maxHops };
|
|
246
|
+
}
|
|
247
|
+
catch (error) {
|
|
248
|
+
if (error instanceof TransportError)
|
|
249
|
+
throw error;
|
|
250
|
+
throw invalidHttpRedirectPolicy("could not be inspected safely", error instanceof Error ? error : undefined);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
function snapshotHttpRedirectPolicy(options) {
|
|
254
|
+
try {
|
|
255
|
+
return normalizeHttpRedirectPolicy(options.redirectPolicy);
|
|
256
|
+
}
|
|
257
|
+
catch (error) {
|
|
258
|
+
if (error instanceof TransportError)
|
|
259
|
+
throw error;
|
|
260
|
+
throw invalidHttpRedirectPolicy("could not be read safely", error instanceof Error ? error : undefined);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
function withoutRedirectBodyHeaders(headers) {
|
|
264
|
+
const nextHeaders = new Headers(headers);
|
|
265
|
+
for (const name of REDIRECT_BODY_HEADERS)
|
|
266
|
+
nextHeaders.delete(name);
|
|
267
|
+
return nextHeaders;
|
|
268
|
+
}
|
|
269
|
+
function redirectDiagnosticTarget(value) {
|
|
270
|
+
try {
|
|
271
|
+
const parsed = new URL(value);
|
|
272
|
+
// Origin omits URL userinfo. Keeping only origin + path makes diagnostics
|
|
273
|
+
// useful while structurally excluding every query value and fragment,
|
|
274
|
+
// including attacker-chosen keys the provider did not declare sensitive.
|
|
275
|
+
const redactedQuery = parsed.search ? "?[REDACTED]" : "";
|
|
276
|
+
return parsed.origin === "null"
|
|
277
|
+
? `${parsed.protocol}<opaque-target>`
|
|
278
|
+
: `${parsed.origin}${parsed.pathname}${redactedQuery}`;
|
|
279
|
+
}
|
|
280
|
+
catch {
|
|
281
|
+
return MALFORMED_REDIRECT_TARGET;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
function discardRedirectResponseBody(response) {
|
|
285
|
+
try {
|
|
286
|
+
const cancellation = response.body?.cancel();
|
|
287
|
+
if (cancellation)
|
|
288
|
+
void cancellation.catch(() => undefined);
|
|
289
|
+
}
|
|
290
|
+
catch {
|
|
291
|
+
// The redirect decision is security-significant and must not be replaced
|
|
292
|
+
// or delayed by an upstream body's cancellation failure. Cancellation was
|
|
293
|
+
// attempted; redirect evaluation continues without awaiting its completion.
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
async function fetchWithHttpRedirectPolicy(requestUrl, requestInit, policy) {
|
|
297
|
+
if (!policy)
|
|
298
|
+
return fetch(requestUrl, requestInit);
|
|
299
|
+
const initialUrl = new URL(requestUrl);
|
|
300
|
+
if (initialUrl.protocol !== "http:" && initialUrl.protocol !== "https:") {
|
|
301
|
+
throw new TransportError("ctx.http redirectPolicy requires an HTTP(S) origin", {
|
|
302
|
+
code: "transport_invalid_url",
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
const initialOrigin = initialUrl.origin;
|
|
306
|
+
let currentUrl = requestUrl;
|
|
307
|
+
let method = normalizeHttpMethod(requestInit.method ?? "GET");
|
|
308
|
+
let body = requestInit.body;
|
|
309
|
+
let headers = requestInit.headers;
|
|
310
|
+
let followedHops = 0;
|
|
311
|
+
const visitedRequests = new Set([`${method} ${currentUrl}`]);
|
|
312
|
+
while (true) {
|
|
313
|
+
const response = await fetch(currentUrl, {
|
|
314
|
+
...requestInit,
|
|
315
|
+
body,
|
|
316
|
+
headers,
|
|
317
|
+
method,
|
|
318
|
+
redirect: "manual",
|
|
319
|
+
});
|
|
320
|
+
if (!isRedirectStatus(response.status))
|
|
321
|
+
return response;
|
|
322
|
+
const location = response.headers.get("location");
|
|
323
|
+
discardRedirectResponseBody(response);
|
|
324
|
+
let nextUrlString;
|
|
325
|
+
try {
|
|
326
|
+
nextUrlString = resolveRedirectUrl(location || undefined, currentUrl);
|
|
327
|
+
}
|
|
328
|
+
catch {
|
|
329
|
+
const target = MALFORMED_REDIRECT_TARGET;
|
|
330
|
+
throw new HttpRedirectError(`Redirect response has malformed Location target ${target}`, {
|
|
331
|
+
reason: "missing_location",
|
|
332
|
+
target,
|
|
333
|
+
status: response.status,
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
const decision = evaluateRedirectHop({
|
|
337
|
+
status: response.status,
|
|
338
|
+
method,
|
|
339
|
+
nextUrl: nextUrlString,
|
|
340
|
+
shouldStop: nextUrlString ? new URL(nextUrlString).origin !== initialOrigin : false,
|
|
341
|
+
redirectCount: followedHops + 1,
|
|
342
|
+
maxHops: policy.maxHops,
|
|
343
|
+
visitedRequests,
|
|
344
|
+
});
|
|
345
|
+
if (decision.kind === "stop") {
|
|
346
|
+
const target = decision.nextUrl ? redirectDiagnosticTarget(decision.nextUrl) : undefined;
|
|
347
|
+
const message = (() => {
|
|
348
|
+
switch (decision.reason) {
|
|
349
|
+
case "stopped":
|
|
350
|
+
return `Redirect policy refused cross-origin target ${target}`;
|
|
351
|
+
case "max_hops":
|
|
352
|
+
return `Redirect policy reached maxHops before target ${target}`;
|
|
353
|
+
case "loop":
|
|
354
|
+
return `Redirect loop refused target ${target}`;
|
|
355
|
+
case "missing_location":
|
|
356
|
+
return `Redirect response from ${redirectDiagnosticTarget(currentUrl)} is missing Location`;
|
|
357
|
+
}
|
|
358
|
+
})();
|
|
359
|
+
throw new HttpRedirectError(message, {
|
|
360
|
+
reason: decision.reason,
|
|
361
|
+
...(target ? { target } : {}),
|
|
362
|
+
status: response.status,
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
if (decision.nextMethod !== method) {
|
|
366
|
+
body = undefined;
|
|
367
|
+
headers = withoutRedirectBodyHeaders(headers);
|
|
368
|
+
}
|
|
369
|
+
method = decision.nextMethod;
|
|
370
|
+
currentUrl = decision.nextUrl;
|
|
371
|
+
followedHops += 1;
|
|
372
|
+
visitedRequests.add(`${method} ${currentUrl}`);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
199
375
|
async function resolveNativeProxy(options, clientOptions, warn, proxyAttemptOffset = 0) {
|
|
200
376
|
const resolvedProxy = await resolveProxyConfigAsync({
|
|
201
377
|
proxy: options.proxy ?? clientOptions.proxy,
|
|
@@ -271,9 +447,7 @@ async function fetchNativeHttp(baseUrl, url, method, options, clientOptions, war
|
|
|
271
447
|
if (options.body !== undefined) {
|
|
272
448
|
requestInit.body = normalizeNativeFetchBody(options.body);
|
|
273
449
|
}
|
|
274
|
-
const response = await
|
|
275
|
-
...requestInit,
|
|
276
|
-
});
|
|
450
|
+
const response = await fetchWithHttpRedirectPolicy(requestUrl, requestInit, options.redirectPolicy);
|
|
277
451
|
const headers = Object.fromEntries(response.headers.entries());
|
|
278
452
|
if (statusRetryCodes && response.status >= 400) {
|
|
279
453
|
await drainNativeResponseBody(response);
|
|
@@ -325,9 +499,7 @@ async function fetchNativeHttpStream(baseUrl, url, method, options, clientOption
|
|
|
325
499
|
if (options.body !== undefined) {
|
|
326
500
|
requestInit.body = normalizeNativeFetchBody(options.body);
|
|
327
501
|
}
|
|
328
|
-
const response = await
|
|
329
|
-
...requestInit,
|
|
330
|
-
});
|
|
502
|
+
const response = await fetchWithHttpRedirectPolicy(requestUrl, requestInit, options.redirectPolicy);
|
|
331
503
|
if (response.status >= 400 && options.throwOnHttpError !== false) {
|
|
332
504
|
await drainNativeResponseBody(response);
|
|
333
505
|
throw new TransportError(`Upstream request failed with status ${response.status}`, {
|
|
@@ -365,7 +537,11 @@ export function createHttpClient(baseUrl, clientOptions = {}) {
|
|
|
365
537
|
throw new TransportError("ctx.http requires an absolute URL when provider.upstream.baseUrl is not declared", { code: "transport_invalid_url" });
|
|
366
538
|
}
|
|
367
539
|
assertNoHttpTransportOverrides(options);
|
|
368
|
-
const
|
|
540
|
+
const redirectPolicy = snapshotHttpRedirectPolicy(options);
|
|
541
|
+
const headersOptions = {
|
|
542
|
+
...withClientHeaders(options, clientOptions, options.body),
|
|
543
|
+
redirectPolicy,
|
|
544
|
+
};
|
|
369
545
|
const methodName = normalizeHttpMethod(method);
|
|
370
546
|
const explicitRetry = headersOptions.retry !== undefined;
|
|
371
547
|
const retryOptions = normalizeProxyTransportRetryOptions(headersOptions.retry, {
|
|
@@ -543,8 +719,12 @@ export function createHttpClient(baseUrl, clientOptions = {}) {
|
|
|
543
719
|
throw new TransportError("ctx.http requires an absolute URL when provider.upstream.baseUrl is not declared", { code: "transport_invalid_url" });
|
|
544
720
|
}
|
|
545
721
|
assertNoHttpTransportOverrides(options);
|
|
722
|
+
const redirectPolicy = snapshotHttpRedirectPolicy(options);
|
|
546
723
|
return {
|
|
547
|
-
headersOptions:
|
|
724
|
+
headersOptions: {
|
|
725
|
+
...withClientHeaders(options, clientOptions, options.body),
|
|
726
|
+
redirectPolicy,
|
|
727
|
+
},
|
|
548
728
|
methodName: normalizeHttpMethod(method),
|
|
549
729
|
};
|
|
550
730
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Socket } from "node:net";
|
|
2
2
|
import { type TLSSocket } from "node:tls";
|
|
3
3
|
import { TransportError } from "../errors.js";
|
|
4
|
-
import type { NativeNetworkClient, NativeNetworkConnection, NativeNetworkDynamicGrantOptions, NativeNetworkEgressGrant, NativeProxyEgressInfo, ProviderProxyPolicy, ProviderProxyProvider } from "../types.js";
|
|
5
|
-
export type NativeNetworkErrorCode = "native_connection_aborted" | "native_connection_closed" | "native_connection_failed" | "native_connection_idle_timeout" | "native_connection_timeout" | "native_dynamic_egress_unsupported" | "native_proxy_expired" | "native_proxy_invalid";
|
|
4
|
+
import type { NativeNetworkClient, NativeNetworkConnection, NativeNetworkConnectInput, NativeNetworkDynamicGrantOptions, NativeNetworkEgressGrant, NativeProviderConfig, NativeProxyEgressInfo, ProviderProxyPolicy, ProviderProxyProvider } from "../types.js";
|
|
5
|
+
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
6
|
export declare class NativeNetworkError extends TransportError {
|
|
7
7
|
constructor(message: string, code: NativeNetworkErrorCode);
|
|
8
8
|
get code(): NativeNetworkErrorCode;
|
|
@@ -11,6 +11,24 @@ export declare class NativeProxyExpiredError extends NativeNetworkError {
|
|
|
11
11
|
readonly expiresAt: string;
|
|
12
12
|
constructor(expiresAt: string);
|
|
13
13
|
}
|
|
14
|
+
/** Raised before transport setup when a native destination is not authorized. */
|
|
15
|
+
export declare class NativeEgressNotDeclaredError extends NativeNetworkError {
|
|
16
|
+
readonly host: string;
|
|
17
|
+
readonly port: number;
|
|
18
|
+
readonly tls: "required" | "disabled";
|
|
19
|
+
constructor(host: string, port: number, tls: "required" | "disabled");
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Raised when the destination was authorized by a grant whose TTL elapsed and
|
|
23
|
+
* its expiry remains in the client's bounded recent-expiry evidence window.
|
|
24
|
+
*/
|
|
25
|
+
export declare class NativeEgressGrantExpiredError extends NativeNetworkError {
|
|
26
|
+
readonly host: string;
|
|
27
|
+
readonly port: number;
|
|
28
|
+
readonly tls: "required" | "disabled";
|
|
29
|
+
readonly expiresAt: string;
|
|
30
|
+
constructor(host: string, port: number, tls: "required" | "disabled", expiresAt: string);
|
|
31
|
+
}
|
|
14
32
|
/** Raised when an established connection exceeds its opt-in read-idle window. */
|
|
15
33
|
export declare class NativeIdleTimeoutError extends NativeNetworkError {
|
|
16
34
|
constructor();
|
|
@@ -41,7 +59,12 @@ export type NativeNetworkClientOptions = {
|
|
|
41
59
|
readonly gatewaySynthesizers?: readonly NativeGatewayProxySynthesizer[];
|
|
42
60
|
/** Warning-level lifecycle diagnostic sink. */
|
|
43
61
|
readonly warn?: (message: string) => void;
|
|
44
|
-
/**
|
|
62
|
+
/**
|
|
63
|
+
* Provider-declared native egress. Undefined preserves legacy unrestricted
|
|
64
|
+
* behavior; any provided declaration, including an empty object, is enforced.
|
|
65
|
+
*/
|
|
66
|
+
readonly egress?: NonNullable<NativeProviderConfig["network"]>;
|
|
67
|
+
/** Additional deployment authorization layered on top of SDK enforcement. */
|
|
45
68
|
readonly grantTcpEgress?: (input: NativeNetworkDynamicGrantOptions) => NativeNetworkEgressGrant;
|
|
46
69
|
};
|
|
47
70
|
/** Domain-separated, process-independent affinity derived from credential identity. */
|
|
@@ -49,5 +72,17 @@ export declare function deriveNativeCredentialAffinityKey(credentialIdentity: st
|
|
|
49
72
|
/** Resolve the first configured native gateway without invoking an allocator API. */
|
|
50
73
|
export declare function resolveNativeGatewayProxy(input: NativeGatewayProxyResolutionInput): NativeGatewayProxy | undefined;
|
|
51
74
|
export declare function createNativeNetworkConnection(socket: Socket | TLSSocket, proxy: NativeGatewayProxy | undefined, options: NativeNetworkClientOptions, idleTimeoutMs?: number): NativeNetworkConnection;
|
|
52
|
-
|
|
75
|
+
type NativeConnectTls = "required" | "disabled";
|
|
76
|
+
export declare const NATIVE_EGRESS_EXPIRED_EVIDENCE_LIMIT = 256;
|
|
77
|
+
/** Internal canonical snapshot shared by production and SDK transport test doubles. */
|
|
78
|
+
export declare function snapshotNativeConnectInput(input: NativeNetworkConnectInput): NativeNetworkConnectInput;
|
|
79
|
+
/** Internal canonical snapshot shared by production and SDK transport test doubles. */
|
|
80
|
+
export declare function snapshotNativeGrantInput(input: NativeNetworkDynamicGrantOptions): NativeNetworkDynamicGrantOptions;
|
|
81
|
+
/** Internal authorization seam shared by production and SDK transport test doubles. */
|
|
82
|
+
export declare function createNativeEgressAuthorization(options: NativeNetworkClientOptions): {
|
|
83
|
+
assertConnect(input: NativeNetworkConnectInput, tls: NativeConnectTls): void;
|
|
84
|
+
grant(input: NativeNetworkDynamicGrantOptions): NativeNetworkEgressGrant;
|
|
85
|
+
};
|
|
86
|
+
/** Create the SDK byte-stream runtime with provider-declared egress enforcement. */
|
|
53
87
|
export declare function createNativeNetworkClient(options?: NativeNetworkClientOptions): NativeNetworkClient;
|
|
88
|
+
export {};
|