@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 +6 -0
- package/dist/define.js +9 -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 +37 -0
- package/dist/testing/run.js +32 -13
- package/dist/types.d.ts +23 -2
- package/package.json +1 -1
- package/src/define.ts +11 -0
- package/src/errors.ts +28 -0
- package/src/index.ts +6 -0
- package/src/native-egress-policy.ts +285 -0
- package/src/provider.ts +7 -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 +36 -0
- package/src/testing/run.ts +39 -14
- package/src/types.ts +32 -2
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
|
+
}
|
package/dist/provider.d.ts
CHANGED
|
@@ -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";
|