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

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/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # @apifuse/provider-sdk Changelog
2
2
 
3
+ ## 2.2.0-beta.15
4
+
5
+ - Release candidate for main commit b5ebd25e48f6502e4ddb775d4e0a25f5c8276712.
6
+
3
7
  ## 2.2.0-beta.14
4
8
 
5
9
  - Release candidate for main commit 3491acd253ca17b517985e8a618f1c2904a664a9.
@@ -86,6 +90,8 @@
86
90
 
87
91
  ## Unreleased
88
92
 
93
+ - Add an opt-in same-origin redirect hop policy to `ctx.http`, with bounded manual following and typed failures before a refused target is requested.
94
+ - Enforce provider-declared native TCP/TLS egress before proxy or socket setup, with revocable and expiring dynamic grants plus typed authorization failures; providers without a native egress declaration retain legacy behavior.
89
95
  - **Breaking:** Provider error `details` is now passed through verbatim; SDK observability fields (`category`, `taxonomyVersion`, `upstreamStatus`, and derived `retryable`) are no longer merged into the public body. Emitted error envelopes now require top-level `retryable`, while inbound stateful forwarding tolerates an older owner response that omits it and defaults it to `false`. The removed observability metadata is available in the new `X-ApiFuse-Error-Observability` response header.
90
96
  - Unregistered `ProviderError` codes now default to HTTP 500 instead of 400 and emit an `unregistered_provider_error_code` structured-log signal; registered mappings remain unchanged and take precedence over the HTTP 400 fallback for unregistered input `ValidationError` codes.
91
97
  - Add an opt-in native connection idle read timeout with a typed error, independently from TCP/SOCKS/TLS establishment deadlines.
package/dist/define.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import ms from "ms";
2
2
  import { ProviderError, ValidationError } from "./errors.js";
3
+ import { NativeEgressPolicyValidationError, validateNativeProviderConfig, } from "./native-egress-policy.js";
3
4
  import { safeParseSchemaSync } from "./schema.js";
4
5
  import { resolveHealthCheckInputDateTokens } from "./server/self-test-input-tokens.js";
5
6
  import { HEALTH_CHECK_DEGRADED_THRESHOLD_MS_MAX, HEALTH_CHECK_DEGRADED_THRESHOLD_MS_MIN, HEALTH_CHECK_TIMEOUT_MS_MAX, HEALTH_CHECK_TIMEOUT_MS_MIN, OPERATION_TIMEOUT_MS_MAX, OPERATION_TIMEOUT_MS_MIN, STREAM_CHUNK_BYTES_MAX, STREAM_CHUNK_BYTES_MIN, STREAM_HEARTBEAT_MS_MAX, STREAM_HEARTBEAT_MS_MIN, STREAM_IDLE_TIMEOUT_MS_MAX, STREAM_IDLE_TIMEOUT_MS_MIN, STREAM_MAX_DURATION_MS_MAX, STREAM_MAX_DURATION_MS_MIN, } from "./types.js";
@@ -1407,6 +1408,14 @@ export function defineProvider(config) {
1407
1408
  validateProviderHealthMonitor(config.id, config.healthProbe ?? config.healthMonitor, config.healthProbe !== undefined ? "healthProbe" : "healthMonitor");
1408
1409
  validateOperationFixtures(config.id, operations);
1409
1410
  validateProviderDeployment(config.id, config.deployment);
1411
+ try {
1412
+ validateNativeProviderConfig(config.native);
1413
+ }
1414
+ catch (error) {
1415
+ if (error instanceof NativeEgressPolicyValidationError)
1416
+ throw new ValidationError(error.message);
1417
+ throw error;
1418
+ }
1410
1419
  validateProviderProxy(config);
1411
1420
  validateProviderStt(config);
1412
1421
  if (config.runtime === "browser" && !config.browser)
package/dist/errors.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { ProviderErrorCategory } from "./observability.js";
2
+ import type { HttpRedirectFailureReason } from "./types.js";
2
3
  export type ProviderErrorOptions = {
3
4
  fix?: string;
4
5
  code?: string;
@@ -44,6 +45,17 @@ export declare class TransportError extends ProviderError {
44
45
  readonly upstreamStatus?: number;
45
46
  constructor(message: string, options?: TransportErrorOptions);
46
47
  }
48
+ export type HttpRedirectErrorOptions = TransportErrorOptions & {
49
+ reason: HttpRedirectFailureReason;
50
+ /** Redacted redirect target suitable for provider diagnostics. */
51
+ target?: string;
52
+ };
53
+ /** Raised when an opt-in ctx.http redirect policy refuses or cannot resolve a hop. */
54
+ export declare class HttpRedirectError extends TransportError {
55
+ readonly reason: HttpRedirectFailureReason;
56
+ readonly target?: string;
57
+ constructor(message: string, options: HttpRedirectErrorOptions);
58
+ }
47
59
  export declare function isProviderError(value: unknown): value is ProviderError;
48
60
  export declare function isSessionExpiredError(value: unknown): value is SessionExpiredError;
49
61
  export declare function isTransportError(value: unknown): value is TransportError;
package/dist/errors.js CHANGED
@@ -111,6 +111,25 @@ export class TransportError extends ProviderError {
111
111
  defineErrorBrand(this, TRANSPORT_BRAND, true);
112
112
  }
113
113
  }
114
+ /** Raised when an opt-in ctx.http redirect policy refuses or cannot resolve a hop. */
115
+ export class HttpRedirectError extends TransportError {
116
+ reason;
117
+ target;
118
+ constructor(message, options) {
119
+ const { reason, target, ...transportOptions } = options;
120
+ super(message, {
121
+ ...transportOptions,
122
+ code: `http_redirect_${reason}`,
123
+ details: {
124
+ reason,
125
+ ...(target ? { target } : {}),
126
+ },
127
+ });
128
+ this.name = "HttpRedirectError";
129
+ this.reason = reason;
130
+ this.target = target;
131
+ }
132
+ }
114
133
  // Cross-module type guards. Prefer these over `instanceof` at any boundary that
115
134
  // may receive an error from a different copy/entrypoint of the SDK (see the HTTP
116
135
  // server error boundary). They recognize branded errors regardless of which
package/dist/index.d.ts CHANGED
@@ -22,7 +22,7 @@ export { type CreateCredentialContextOptions, createCredentialContext, } from ".
22
22
  export { createEnvContext } from "./runtime/env.js";
23
23
  export { executeOperation } from "./runtime/executor.js";
24
24
  export { createHttpClient } from "./runtime/http.js";
25
- export { createNativeNetworkClient, deriveNativeCredentialAffinityKey, NativeIdleTimeoutError, NativeNetworkError, NativeProxyExpiredError, resolveNativeGatewayProxy, type NativeGatewayProxy, type NativeGatewayProxyResolutionInput, type NativeGatewayProxySynthesizer, type NativeGatewayProxySynthesisInput, type NativeNetworkClientOptions, type NativeNetworkErrorCode, } from "./runtime/native-network.js";
25
+ 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";
26
26
  export type { Insight, InsightSeverity } from "./runtime/insights.js";
27
27
  export { generateInsights } from "./runtime/insights.js";
28
28
  export { type InstrumentationOptions, type InstrumentedProviderContext, wrapWithInstrumentation, } from "./runtime/instrumentation.js";
@@ -37,7 +37,7 @@ export { APIFUSE_DESCRIPTION_KEY_META_KEY, APIFUSE_REDACTION_MARKER, APIFUSE_SEN
37
37
  export { createServerApp, ERROR_OBSERVABILITY_HEADER, type ServeOptions, serve, } from "./server/index.js";
38
38
  export { getStealthProfile, listStealthProfiles } from "./stealth/profiles.js";
39
39
  export * from "./stream.js";
40
- export type { ApiFuseResponse, AuthConfig, AuthContext, AuthFlowDefinition, AuthFlowInputHandler, AuthFlowStartHandler, AuthMode, AuthTurn, Bcp47Locale, BrowserEngine, BrowserOptions, BrowserResourceBody, BrowserResourceDecision, BrowserResourceMethod, BrowserResourcePolicy, BrowserResourceRequest, BrowserResourceRoute, ConnectionMode, ContextDeclaration, CookieJar, ContextScratchpad, CredentialContext, CredentialDeclaration, E164PhoneNumber, EnvContext, FlowContext, FlowContextStore, HealthCheckAssertionContext, HealthCheckCase, HealthCheckCaseResult, HealthCheckSuite, HealthCheckUnsupported, HealthJourneyDefinition, HealthJourneyEventContext, HealthJourneyGatewayContext, HealthJourneyJournalContext, HealthJourneyManualTriggerPolicy, HealthJourneyRunContext, HealthJourneyRunResult, HealthJourneySchedule, HealthScheduleRandomization, HealthJourneySmsContext, HealthJourneyStep, HttpClient, HttpMethod, HttpResponse, HttpRetryOptions, HttpRetrySummary, HttpStreamResponse, IanaTimeZone, InferSchemaOutput, Iso3166Alpha2CountryCode, Iso4217CurrencyCode, Iso8601Duration, NativeContext, NativeNetworkClient, NativeNetworkCloseReason, NativeNetworkConnection, NativeNetworkConnectInput, NativeNetworkConnectOptions, NativeNetworkDynamicGrantOptions, NativeNetworkEgressGrant, NativeProviderConfig, NativeProviderContext, NativeProxyDrainHandler, NativeProxyEgressInfo, NativeProxyExpiringEvent, NativeProxyExpiringReason, NativeTcpDynamicEgressRule, NativeTcpEgressGrant, NativeTcpEgressRule, NativeTcpPortRange, NativeTcpTlsMode, NativeTlsConnectOptions, OperationAnnotations, OperationApprovalPolicy, OperationContractMetadata, OperationDefinition, OperationDeprecationMetadata, OperationDocMeta, OperationErrorCode, OperationHandlerResult, OperationInputExample, OperationLifecycle, OperationObservabilityConfig, OperationObservabilitySensitiveConfig, OperationRelationships, OperationRiskClass, OperationSensitivePath, OperationToolRouterMetadata, OperationTransport, OperationTransportKind, ProbeInterval, ProviderAccessConfig, ProviderAccessVisibility, ProviderCache, ProviderCacheGetOrSetOptions, ProviderCacheKeyOptions, ProviderCacheLookupMeta, ProviderCacheResponseMeta, ProviderCacheResult, ProviderChoiceBindingOptions, ProviderChoiceContext, ProviderChoiceIssueOptions, ProviderChoiceParseOptions, ProviderContext, ProviderDefinition, ProviderDeploymentOverrides, ProviderFileRef, ProviderFilesContext, ProviderHealthMonitorConfig, ProviderHealthProbeConfig, ProviderLocale, ProviderLocaleKey, ProviderLocaleKeyInput, ProviderLogoProfile, ProviderLogoSource, ProviderMeta, ProviderProxyConfig, ProviderProxyMode, ProviderProxyPolicy, ProviderProxyProvider, ProviderProxySessionAffinity, ProviderPublicConnectionMode, ProviderPublicProfile, ProviderReviewed, ProviderResolvedFile, ProviderRuntimeState, ProviderSecretDeclaration, ProviderStateDurationString, ProviderStateNamespace, ProviderStreamEvent, ProviderSttConfig, ProviderSttMode, ProviderSupportLevel, RequestOptions, Rfc3339Instant, SchemaLike, SmsOrigin, SmsOtpExtractionPattern, SmsOtpMatcherDefinition, SseMessage, StandardSchemaV1, StateCasResult, StateNamespaceOptions, StateValue, StateWriteOptions, StealthClient, StealthCookieStore, StealthCookieStoreV1, StealthFetchOptions, StealthPlatform, StealthProfile, StealthRedirectHop, StealthRedirectRunOptions, StealthRedirectRunResult, StealthResponse, StealthSession, StealthSessionCookies, SttAudioInput, SttContext, SttPromptPolicy, SttSegment, SttTranscribeMode, SttTranscribeRequest, SttTranscript, SttUnsupportedOptionPolicy, SttUsage, SttVerificationCodeOptions, SttWarning, TraceConfig, TraceSpan, VerificationCodeCandidate, VerificationCodeCandidateSource, VerificationCodeExtractionResult, } from "./types.js";
40
+ export type { ApiFuseResponse, AuthConfig, AuthContext, AuthFlowDefinition, AuthFlowInputHandler, AuthFlowStartHandler, AuthMode, AuthTurn, Bcp47Locale, BrowserEngine, BrowserOptions, BrowserResourceBody, BrowserResourceDecision, BrowserResourceMethod, BrowserResourcePolicy, BrowserResourceRequest, BrowserResourceRoute, ConnectionMode, ContextDeclaration, CookieJar, ContextScratchpad, CredentialContext, CredentialDeclaration, E164PhoneNumber, EnvContext, FlowContext, FlowContextStore, HealthCheckAssertionContext, HealthCheckCase, HealthCheckCaseResult, HealthCheckSuite, HealthCheckUnsupported, HealthJourneyDefinition, HealthJourneyEventContext, HealthJourneyGatewayContext, HealthJourneyJournalContext, HealthJourneyManualTriggerPolicy, HealthJourneyRunContext, HealthJourneyRunResult, HealthJourneySchedule, HealthScheduleRandomization, HealthJourneySmsContext, HealthJourneyStep, HttpClient, HttpMethod, HttpRedirectFailureReason, HttpRedirectPolicy, HttpRedirectPolicyMode, HttpResponse, HttpRetryOptions, HttpRetrySummary, HttpStreamResponse, IanaTimeZone, InferSchemaOutput, Iso3166Alpha2CountryCode, Iso4217CurrencyCode, Iso8601Duration, NativeContext, NativeNetworkClient, NativeNetworkCloseReason, NativeNetworkConnection, NativeNetworkConnectInput, NativeNetworkConnectOptions, NativeNetworkDynamicGrantOptions, NativeNetworkEgressGrant, NativeProviderConfig, NativeProviderContext, NativeProxyDrainHandler, NativeProxyEgressInfo, NativeProxyExpiringEvent, NativeProxyExpiringReason, NativeTcpDynamicEgressRule, NativeTcpEgressGrant, NativeTcpEgressRule, NativeTcpPortRange, NativeTcpTlsMode, NativeTlsConnectOptions, OperationAnnotations, OperationApprovalPolicy, OperationContractMetadata, OperationDefinition, OperationDeprecationMetadata, OperationDocMeta, OperationErrorCode, OperationHandlerResult, OperationInputExample, OperationLifecycle, OperationObservabilityConfig, OperationObservabilitySensitiveConfig, OperationRelationships, OperationRiskClass, OperationSensitivePath, OperationToolRouterMetadata, OperationTransport, OperationTransportKind, ProbeInterval, ProviderAccessConfig, ProviderAccessVisibility, ProviderCache, ProviderCacheGetOrSetOptions, ProviderCacheKeyOptions, ProviderCacheLookupMeta, ProviderCacheResponseMeta, ProviderCacheResult, ProviderChoiceBindingOptions, ProviderChoiceContext, ProviderChoiceIssueOptions, ProviderChoiceParseOptions, ProviderContext, ProviderDefinition, ProviderDeploymentOverrides, ProviderFileRef, ProviderFilesContext, ProviderHealthMonitorConfig, ProviderHealthProbeConfig, ProviderLocale, ProviderLocaleKey, ProviderLocaleKeyInput, ProviderLogoProfile, ProviderLogoSource, ProviderMeta, ProviderProxyConfig, ProviderProxyMode, ProviderProxyPolicy, ProviderProxyProvider, ProviderProxySessionAffinity, ProviderPublicConnectionMode, ProviderPublicProfile, ProviderReviewed, ProviderResolvedFile, ProviderRuntimeState, ProviderSecretDeclaration, ProviderStateDurationString, ProviderStateNamespace, ProviderStreamEvent, ProviderSttConfig, ProviderSttMode, ProviderSupportLevel, RequestOptions, RedirectRunReason, Rfc3339Instant, SchemaLike, SmsOrigin, SmsOtpExtractionPattern, SmsOtpMatcherDefinition, SseMessage, StandardSchemaV1, StateCasResult, StateNamespaceOptions, StateValue, StateWriteOptions, StealthClient, StealthCookieStore, StealthCookieStoreV1, StealthFetchOptions, StealthPlatform, StealthProfile, StealthRedirectHop, StealthRedirectRunOptions, StealthRedirectRunResult, StealthResponse, StealthSession, StealthSessionCookies, SttAudioInput, SttContext, SttPromptPolicy, SttSegment, SttTranscribeMode, SttTranscribeRequest, SttTranscript, SttUnsupportedOptionPolicy, SttUsage, SttVerificationCodeOptions, SttWarning, TraceConfig, TraceSpan, VerificationCodeCandidate, VerificationCodeCandidateSource, VerificationCodeExtractionResult, } from "./types.js";
41
41
  export { DEFAULT_OPERATION_TRANSPORT, HttpRetryAfterPolicy, HttpRetryDelayStrategy, HttpRetryJitter, HttpRetryPreset, HttpRetryUnsafeMethodPolicy, PROBE_INTERVALS, STREAM_CHUNK_BYTES_MAX, STREAM_CHUNK_BYTES_MIN, STREAM_HEARTBEAT_MS_MAX, STREAM_HEARTBEAT_MS_MIN, STREAM_IDLE_TIMEOUT_MS_MAX, STREAM_IDLE_TIMEOUT_MS_MIN, STREAM_MAX_DURATION_MS_MAX, STREAM_MAX_DURATION_MS_MIN, } from "./types.js";
42
42
  export * from "./utils/date.js";
43
43
  export * from "./utils/parse.js";
package/dist/index.js CHANGED
@@ -20,7 +20,7 @@ export { createCredentialContext, } from "./runtime/credential.js";
20
20
  export { createEnvContext } from "./runtime/env.js";
21
21
  export { executeOperation } from "./runtime/executor.js";
22
22
  export { createHttpClient } from "./runtime/http.js";
23
- export { createNativeNetworkClient, deriveNativeCredentialAffinityKey, NativeIdleTimeoutError, NativeNetworkError, NativeProxyExpiredError, resolveNativeGatewayProxy, } from "./runtime/native-network.js";
23
+ export { createNativeNetworkClient, deriveNativeCredentialAffinityKey, NativeEgressGrantExpiredError, NativeEgressNotDeclaredError, NativeIdleTimeoutError, NativeNetworkError, NativeProxyExpiredError, resolveNativeGatewayProxy, } from "./runtime/native-network.js";
24
24
  export { generateInsights } from "./runtime/insights.js";
25
25
  export { wrapWithInstrumentation, } from "./runtime/instrumentation.js";
26
26
  export { prevalidate } from "./runtime/prevalidate.js";
@@ -0,0 +1,27 @@
1
+ import type { NativeTcpPortRange, NativeTcpTlsMode } from "./types.js";
2
+ export type StaticEgressRuleSnapshot = {
3
+ readonly host: string;
4
+ readonly ports: readonly number[];
5
+ readonly tls: NativeTcpTlsMode;
6
+ };
7
+ export type DynamicEgressRuleSnapshot = {
8
+ readonly sourceHost?: string;
9
+ readonly sourceHostSuffixes: readonly string[];
10
+ readonly sourcePorts: readonly number[];
11
+ readonly sourcePortRanges: readonly NativeTcpPortRange[];
12
+ readonly targetHostSuffixes: readonly string[];
13
+ readonly targetPorts: readonly number[];
14
+ readonly targetPortRanges: readonly NativeTcpPortRange[];
15
+ readonly tls: NativeTcpTlsMode;
16
+ readonly ttlMs?: number;
17
+ readonly maxGrants?: number;
18
+ };
19
+ export type NativeEgressPolicySnapshot = {
20
+ readonly staticRules: readonly StaticEgressRuleSnapshot[];
21
+ readonly dynamicRules: readonly DynamicEgressRuleSnapshot[];
22
+ };
23
+ export declare class NativeEgressPolicyValidationError extends Error {
24
+ constructor(message: string);
25
+ }
26
+ export declare function parseNativeEgressPolicy(value: unknown): NativeEgressPolicySnapshot;
27
+ export declare function validateNativeProviderConfig(value: unknown): void;
@@ -0,0 +1,225 @@
1
+ const NATIVE_PROVIDER_FIELD_RECORD = {
2
+ network: true,
3
+ };
4
+ const NATIVE_NETWORK_FIELD_RECORD = {
5
+ tcp: true,
6
+ dynamicTcp: true,
7
+ };
8
+ const NATIVE_TCP_RULE_FIELD_RECORD = {
9
+ host: true,
10
+ ports: true,
11
+ tls: true,
12
+ };
13
+ const NATIVE_DYNAMIC_TCP_RULE_FIELD_RECORD = {
14
+ sourceHost: true,
15
+ sourceHostSuffixes: true,
16
+ sourcePorts: true,
17
+ sourcePortRanges: true,
18
+ targetHostSuffixes: true,
19
+ targetPorts: true,
20
+ targetPortRanges: true,
21
+ tls: true,
22
+ ttlMs: true,
23
+ maxGrants: true,
24
+ };
25
+ const NATIVE_TCP_PORT_RANGE_FIELD_RECORD = {
26
+ start: true,
27
+ end: true,
28
+ };
29
+ const NATIVE_PROVIDER_FIELDS = Object.keys(NATIVE_PROVIDER_FIELD_RECORD);
30
+ const NATIVE_NETWORK_FIELDS = Object.keys(NATIVE_NETWORK_FIELD_RECORD);
31
+ const NATIVE_TCP_RULE_FIELDS = Object.keys(NATIVE_TCP_RULE_FIELD_RECORD);
32
+ const NATIVE_DYNAMIC_TCP_RULE_FIELDS = Object.keys(NATIVE_DYNAMIC_TCP_RULE_FIELD_RECORD);
33
+ const NATIVE_TCP_PORT_RANGE_FIELDS = Object.keys(NATIVE_TCP_PORT_RANGE_FIELD_RECORD);
34
+ export class NativeEgressPolicyValidationError extends Error {
35
+ constructor(message) {
36
+ super(message);
37
+ this.name = "NativeEgressPolicyValidationError";
38
+ }
39
+ }
40
+ function fail(message) {
41
+ throw new NativeEgressPolicyValidationError(message);
42
+ }
43
+ function dataRecord(value, fieldPath, allowed) {
44
+ if (!value || typeof value !== "object" || Array.isArray(value))
45
+ fail(`${fieldPath} must be an object`);
46
+ const prototype = Reflect.getPrototypeOf(value);
47
+ if (prototype !== Object.prototype && prototype !== null)
48
+ fail(`${fieldPath} must be a plain object`);
49
+ const record = {};
50
+ for (const key of Reflect.ownKeys(value)) {
51
+ if (typeof key !== "string")
52
+ fail(`${fieldPath} must not contain symbol fields`);
53
+ if (!allowed.includes(key))
54
+ fail(`Unknown field ${fieldPath}.${key}`);
55
+ const descriptor = Reflect.getOwnPropertyDescriptor(value, key);
56
+ if (!descriptor || !("value" in descriptor))
57
+ fail(`${fieldPath}.${key} must be a data field`);
58
+ record[key] = descriptor.value;
59
+ }
60
+ return record;
61
+ }
62
+ function dataArray(value, fieldPath) {
63
+ if (!Array.isArray(value))
64
+ fail(`${fieldPath} must be an array`);
65
+ const result = [];
66
+ for (const key of Reflect.ownKeys(value)) {
67
+ if (key === "length")
68
+ continue;
69
+ if (typeof key !== "string" || !/^(?:0|[1-9]\d*)$/.test(key))
70
+ fail(`${fieldPath} must not contain non-index fields`);
71
+ const descriptor = Reflect.getOwnPropertyDescriptor(value, key);
72
+ if (!descriptor || !("value" in descriptor))
73
+ fail(`${fieldPath}[${key}] must be a data field`);
74
+ result[Number(key)] = descriptor.value;
75
+ }
76
+ if (result.length !== value.length)
77
+ fail(`${fieldPath} must not be sparse`);
78
+ for (let index = 0; index < result.length; index += 1) {
79
+ if (!(index in result))
80
+ fail(`${fieldPath} must not be sparse`);
81
+ }
82
+ return result;
83
+ }
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
+ 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("*"))
100
+ fail(`${fieldPath} must be an exact ${suffix ? "DNS suffix" : "hostname"}, not a wildcard`);
101
+ const normalized = value.trim().toLowerCase().replace(/\.$/, "");
102
+ if (!normalized)
103
+ fail(`${fieldPath} must be a non-empty hostname`);
104
+ return normalized;
105
+ }
106
+ function port(value, fieldPath) {
107
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 1 || value > 65_535)
108
+ fail(`${fieldPath} must be an integer from 1 to 65535`);
109
+ return value;
110
+ }
111
+ function ports(value, fieldPath) {
112
+ return dataArray(value, fieldPath).map((value, index) => port(value, `${fieldPath}[${index}]`));
113
+ }
114
+ function hostSuffixes(value, fieldPath) {
115
+ return dataArray(value, fieldPath).map((value, index) => host(value, `${fieldPath}[${index}]`, true));
116
+ }
117
+ function ranges(value, fieldPath) {
118
+ return dataArray(value, fieldPath).map((value, index) => {
119
+ const rangePath = `${fieldPath}[${index}]`;
120
+ const record = dataRecord(value, rangePath, NATIVE_TCP_PORT_RANGE_FIELDS);
121
+ const start = port(record.start, `${rangePath}.start`);
122
+ const end = port(record.end, `${rangePath}.end`);
123
+ if (start > end)
124
+ fail(`${rangePath}.start must not exceed end`);
125
+ return { start, end };
126
+ });
127
+ }
128
+ function tls(value, fieldPath) {
129
+ if (value !== "required" && value !== "allowed" && value !== "disabled")
130
+ fail(`${fieldPath} must be required, allowed, or disabled`);
131
+ return value;
132
+ }
133
+ function positiveInteger(value, fieldPath) {
134
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value <= 0)
135
+ fail(`${fieldPath} must be a positive integer`);
136
+ return value;
137
+ }
138
+ export function parseNativeEgressPolicy(value) {
139
+ try {
140
+ const policy = dataRecord(value, "native.network", NATIVE_NETWORK_FIELDS);
141
+ const staticRules = policy.tcp === undefined
142
+ ? []
143
+ : dataArray(policy.tcp, "native.network.tcp").map((value, index) => {
144
+ const fieldPath = `native.network.tcp[${index}]`;
145
+ const rule = dataRecord(value, fieldPath, NATIVE_TCP_RULE_FIELDS);
146
+ const declaredPorts = ports(rule.ports, `${fieldPath}.ports`);
147
+ if (declaredPorts.length === 0)
148
+ fail(`${fieldPath}.ports must not be empty`);
149
+ return {
150
+ host: host(rule.host, `${fieldPath}.host`),
151
+ ports: declaredPorts,
152
+ tls: tls(rule.tls, `${fieldPath}.tls`),
153
+ };
154
+ });
155
+ const dynamicRules = policy.dynamicTcp === undefined
156
+ ? []
157
+ : dataArray(policy.dynamicTcp, "native.network.dynamicTcp").map((value, index) => {
158
+ const fieldPath = `native.network.dynamicTcp[${index}]`;
159
+ const rule = dataRecord(value, fieldPath, NATIVE_DYNAMIC_TCP_RULE_FIELDS);
160
+ const sourceHost = rule.sourceHost === undefined
161
+ ? undefined
162
+ : host(rule.sourceHost, `${fieldPath}.sourceHost`);
163
+ const sourceHostSuffixes = rule.sourceHostSuffixes === undefined
164
+ ? []
165
+ : hostSuffixes(rule.sourceHostSuffixes, `${fieldPath}.sourceHostSuffixes`);
166
+ if (sourceHost === undefined && sourceHostSuffixes.length === 0)
167
+ fail(`${fieldPath} must declare sourceHost or a non-empty sourceHostSuffixes list`);
168
+ const sourcePorts = rule.sourcePorts === undefined
169
+ ? []
170
+ : ports(rule.sourcePorts, `${fieldPath}.sourcePorts`);
171
+ const sourcePortRanges = rule.sourcePortRanges === undefined
172
+ ? []
173
+ : ranges(rule.sourcePortRanges, `${fieldPath}.sourcePortRanges`);
174
+ if (sourcePorts.length === 0 && sourcePortRanges.length === 0)
175
+ 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`);
179
+ const targetPorts = rule.targetPorts === undefined
180
+ ? []
181
+ : ports(rule.targetPorts, `${fieldPath}.targetPorts`);
182
+ const targetPortRanges = rule.targetPortRanges === undefined
183
+ ? []
184
+ : ranges(rule.targetPortRanges, `${fieldPath}.targetPortRanges`);
185
+ if (targetPorts.length === 0 && targetPortRanges.length === 0)
186
+ fail(`${fieldPath} must declare a non-empty targetPorts or targetPortRanges list`);
187
+ return {
188
+ ...(sourceHost === undefined ? {} : { sourceHost }),
189
+ sourceHostSuffixes,
190
+ sourcePorts,
191
+ sourcePortRanges,
192
+ targetHostSuffixes,
193
+ targetPorts,
194
+ targetPortRanges,
195
+ tls: tls(rule.tls, `${fieldPath}.tls`),
196
+ ...(rule.ttlMs === undefined
197
+ ? {}
198
+ : { ttlMs: positiveInteger(rule.ttlMs, `${fieldPath}.ttlMs`) }),
199
+ ...(rule.maxGrants === undefined
200
+ ? {}
201
+ : { maxGrants: positiveInteger(rule.maxGrants, `${fieldPath}.maxGrants`) }),
202
+ };
203
+ });
204
+ return { staticRules, dynamicRules };
205
+ }
206
+ catch (error) {
207
+ if (error instanceof NativeEgressPolicyValidationError)
208
+ throw error;
209
+ throw new NativeEgressPolicyValidationError("Native egress policy could not be inspected safely");
210
+ }
211
+ }
212
+ export function validateNativeProviderConfig(value) {
213
+ if (value === undefined)
214
+ return;
215
+ try {
216
+ const native = dataRecord(value, "native", NATIVE_PROVIDER_FIELDS);
217
+ if (native.network !== undefined)
218
+ parseNativeEgressPolicy(native.network);
219
+ }
220
+ catch (error) {
221
+ if (error instanceof NativeEgressPolicyValidationError)
222
+ throw error;
223
+ throw new NativeEgressPolicyValidationError("Native provider config could not be inspected safely");
224
+ }
225
+ }
@@ -3,10 +3,10 @@ export type { CredentialsAuthChallengeDefinition, CredentialsAuthChallengeReques
3
3
  export { createFormCeremony } from "./ceremonies/index.js";
4
4
  export { assertFreshProviderChoiceIssuedAt, createProviderChoiceToken, ProviderChoiceTokenError, type ProviderChoiceTokenErrorReason, type ProviderChoiceTokenPayload, parseProviderChoiceToken, } from "./choice-token.js";
5
5
  export { centered, delayed, defineHealthJourney, defineOperation, defineProvider, defineSmsOtpMatcher, every, } from "./define.js";
6
- export { AuthError, isProviderError, isSessionExpiredError, isTransportError, ProviderError, SessionExpiredError, TransportError, ValidationError, } from "./errors.js";
6
+ export { AuthError, HttpRedirectError, isProviderError, isSessionExpiredError, isTransportError, ProviderError, SessionExpiredError, TransportError, ValidationError, } from "./errors.js";
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, 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, SchemaLike, SmsOtpMatcherDefinition, StandardSchemaV1, StateCasResult, StateNamespaceOptions, StateValue, StateWriteOptions, } from "./types.js";
11
- export { createNativeNetworkClient, deriveNativeCredentialAffinityKey, 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, 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";
12
12
  export { HttpRetryAfterPolicy, HttpRetryDelayStrategy, HttpRetryJitter, HttpRetryPreset, HttpRetryUnsafeMethodPolicy, } from "./types.js";
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";