@apifuse/provider-sdk 2.2.0-beta.42 → 2.2.0-beta.44

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,13 @@
1
1
  # @apifuse/provider-sdk Changelog
2
2
 
3
+ ## 2.2.0-beta.44
4
+
5
+ - Release candidate for main commit a3091c0b4931c5ae48fe01b9776e4dc213db2716.
6
+
7
+ ## 2.2.0-beta.43
8
+
9
+ - Release candidate for main commit 5b8b6048514fb500ead400495bd5e1ed8695ed6d.
10
+
3
11
  ## 2.2.0-beta.42
4
12
 
5
13
  - Release candidate for main commit efbdbb409c9400e6211b061705b634e659f298bd.
@@ -551,7 +551,7 @@ function isProviderDefinition(value: unknown): value is ProviderDefinition {
551
551
  return (
552
552
  typeof value.id === "string" &&
553
553
  typeof value.version === "string" &&
554
- (value.runtime === "standard" || value.runtime === "browser") &&
554
+ (value.runtime === "standard" || value.runtime === "shared" || value.runtime === "browser") &&
555
555
  typeof value.meta.displayName === "string" &&
556
556
  typeof value.meta.category === "string"
557
557
  );
@@ -249,7 +249,7 @@ function isProviderDefinition(value: unknown): value is ProviderDefinition {
249
249
  return (
250
250
  typeof value.id === "string" &&
251
251
  typeof value.version === "string" &&
252
- (value.runtime === "standard" || value.runtime === "browser") &&
252
+ (value.runtime === "standard" || value.runtime === "shared" || value.runtime === "browser") &&
253
253
  typeof value.meta.displayName === "string" &&
254
254
  typeof value.meta.category === "string"
255
255
  );
@@ -1,7 +1,7 @@
1
1
  export declare const PROVIDER_NAME_REGEX: RegExp;
2
2
  export declare const CATEGORY_OPTIONS: readonly ["developer-tools", "finance", "commerce", "productivity", "marketing", "data", "communication", "other"];
3
3
  export declare const AUTH_MODE_OPTIONS: readonly ["none", "platform-managed", "credentials", "oauth2"];
4
- export declare const RUNTIME_OPTIONS: readonly ["standard", "browser"];
4
+ export declare const RUNTIME_OPTIONS: readonly ["standard", "shared", "browser"];
5
5
  export declare const PRESET_OPTIONS: readonly ["standalone", "monorepo"];
6
6
  export type CreateCategory = (typeof CATEGORY_OPTIONS)[number];
7
7
  export type CreateAuthMode = (typeof AUTH_MODE_OPTIONS)[number];
@@ -19,7 +19,7 @@ export const CATEGORY_OPTIONS = [
19
19
  "other",
20
20
  ];
21
21
  export const AUTH_MODE_OPTIONS = ["none", "platform-managed", "credentials", "oauth2"];
22
- export const RUNTIME_OPTIONS = ["standard", "browser"];
22
+ export const RUNTIME_OPTIONS = ["standard", "shared", "browser"];
23
23
  export const PRESET_OPTIONS = ["standalone", "monorepo"];
24
24
  const CREATE_CONFIG_SCHEMA = z.object({
25
25
  authMode: z.enum(AUTH_MODE_OPTIONS).optional(),
@@ -46,7 +46,7 @@ Options:
46
46
  --display-name <name>
47
47
  --category <category>
48
48
  --auth-mode <mode>
49
- --runtime <standard|browser>
49
+ --runtime <standard|shared|browser>
50
50
  --yes
51
51
  --dry-run
52
52
  --json
package/dist/define.d.ts CHANGED
@@ -130,6 +130,10 @@ export type ProviderBuilder<TDeclaration extends ProviderDeclaration> = <TOperat
130
130
  };
131
131
  /** Extract the declaration-derived operation context from a provider builder. */
132
132
  export type ProviderContextOf<TBuilder> = TBuilder extends ProviderBuilder<infer TDeclaration> ? ProviderContextFor<TDeclaration> : never;
133
+ /** Annotate an operation while preserving the declaration-derived context. */
134
+ export type OperationDefinitionFor<TBuilder, TInput extends SchemaLike = SchemaLike, TOutput extends SchemaLike = SchemaLike> = OperationDefinition<TInput, TOutput, ProviderContextOf<TBuilder>>;
135
+ /** Annotate a built provider while preserving the declaration-derived context. */
136
+ export type ProviderDefinitionFor<TBuilder> = ProviderDefinition<ProviderContextOf<TBuilder>>;
133
137
  /** Establish a provider declaration before its operations are contextually typed. */
134
138
  export declare function defineProvider<const TDeclaration extends ProviderDeclaration>(declaration: TDeclaration & Record<Exclude<keyof TDeclaration, keyof ProviderDeclaration>, never> & AuthStartNoInputGuard<TDeclaration>): ProviderBuilder<TDeclaration>;
135
139
  export {};
package/dist/index.d.ts CHANGED
@@ -4,7 +4,7 @@ export * from "./choice-token.js";
4
4
  export type { ApiFuseConfig, BrowserConfig, ProxyCacheStatus, ProxyProtocol, ProxyResolutionOptions, ProxyResolutionSource, ProxyUserAgentSource, ProxyVendorName, ResolvedProxyConfig, SessionConfig, SmartproxyAllocatorBodyClass, } from "./config/loader.js";
5
5
  export { defineConfig, loadApiFuseConfig, resolveProxy } from "./config/loader.js";
6
6
  export { canonicalJson, digestProviderContract, extractProviderContract, type JsonPrimitive, type JsonValue, PROVIDER_CONTRACT_SCHEMA_VERSION, type ProviderContractOperation, type ProviderContractSnapshot, } from "./contract.js";
7
- export { centered, delayed, defineHealthJourney, defineOperation, defineProvider, defineSmsOtpMatcher, defineStreamOperation, every, type AuthStartNoInputGuard, type ProviderBuilder, type ProviderContextOf, type ProviderDeclaration, } from "./define.js";
7
+ export { centered, delayed, defineHealthJourney, defineOperation, defineProvider, defineSmsOtpMatcher, defineStreamOperation, every, type AuthStartNoInputGuard, type OperationDefinitionFor, type ProviderBuilder, type ProviderContextOf, type ProviderDeclaration, type ProviderDefinitionFor, } from "./define.js";
8
8
  export { AssertionExpressionSchema, AssertionPredicateSchema, AssertStepSchema, BoundedJsonPathSchema, CandidateBlockSchema, CandidatePolicySchema, CredentialRefDeclarationSchema, defineHealthScenario, HealthScenarioSchema, HealthStepSchema, ExtractStepSchema, FindFirstSchema, GuardStepSchema, JournalPolicySchema, JsonTemplateSchema, ManualTriggerPolicySchema, OperandSchema, OperationStepSchema, QuantifierSchema, ReferenceSchema, RetryPolicySchema, SafeRegexSchema, ScopedAssertionExpressionSchema, ScopedAssertionPredicateSchema, ScopedItemReferenceSchema, ScopedOperandSchema, StepReferenceSchema, RelativeDateNodeSchema, ValueTypeSchema, } from "./health-scenario.js";
9
9
  export type { AssertionExpression, AssertionPredicate, AttemptReference, AssertResult, AssertStep, BoundedJsonPath, CandidateBlock, CandidatePolicy, CandidateReference, CredentialReference, CredentialRefDeclaration, EstablishedConnectionReference, ExtractStep, FindFirst, GuardAttribution, GuardReasonCode, GuardResult, GuardStep, HealthScenario, HealthStep, JsonTemplate, JournalPolicy, ManualTriggerPolicy, NonEmpty, OperationResult, OperationStep, Operand, Quantifier, ReferenceNode, Reference, RelativeDateNode, RetryPolicy, SafeRegex, ScopedAssertionExpression, ScopedAssertionPredicate, ScopedItemReference, ScopedOperand, StepBase, StepReference, ExtractResult, ValueType, } from "./health-scenario.js";
10
10
  export type { DevServerOptions } from "./dev.js";
@@ -3,7 +3,7 @@ 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 type { ProviderBuilder, ProviderContextOf, ProviderDeclaration, } from "./define.js";
6
+ export type { OperationDefinitionFor, ProviderBuilder, ProviderContextOf, ProviderDeclaration, ProviderDefinitionFor, } from "./define.js";
7
7
  export type { JsonPrimitive, JsonValue } from "./contract-json.js";
8
8
  export { AssertionExpressionSchema, AssertionPredicateSchema, AssertStepSchema, BoundedJsonPathSchema, CandidateBlockSchema, CandidatePolicySchema, CredentialRefDeclarationSchema, defineHealthScenario, HealthScenarioSchema, HealthStepSchema, ExtractStepSchema, FindFirstSchema, GuardStepSchema, JournalPolicySchema, JsonTemplateSchema, ManualTriggerPolicySchema, OperandSchema, OperationStepSchema, QuantifierSchema, ReferenceSchema, RetryPolicySchema, SafeRegexSchema, ScopedAssertionExpressionSchema, ScopedAssertionPredicateSchema, ScopedItemReferenceSchema, ScopedOperandSchema, StepReferenceSchema, RelativeDateNodeSchema, ValueTypeSchema, } from "./health-scenario.js";
9
9
  export type { AssertionExpression, AssertionPredicate, AttemptReference, AssertResult, AssertStep, BoundedJsonPath, CandidateBlock, CandidatePolicy, CandidateReference, CredentialReference, CredentialRefDeclaration, EstablishedConnectionReference, ExtractStep, FindFirst, GuardAttribution, GuardReasonCode, GuardResult, GuardStep, HealthScenario, HealthStep, JsonTemplate, JournalPolicy, ManualTriggerPolicy, NonEmpty, OperationResult, OperationStep, Operand, Quantifier, ReferenceNode, Reference, RelativeDateNode, RetryPolicy, SafeRegex, ScopedAssertionExpression, ScopedAssertionPredicate, ScopedItemReference, ScopedOperand, StepBase, StepReference, ExtractResult, ValueType, } from "./health-scenario.js";
@@ -53,17 +53,17 @@ export declare const ProviderServerStatefulForwardEnvelopeSchema: z.ZodObject<{
53
53
  export type ProviderServerStatefulForwardEnvelope = Readonly<z.infer<typeof ProviderServerStatefulForwardEnvelopeSchema>>;
54
54
  export type ProviderServerStatefulOwnerFence = Readonly<Pick<ProviderServerStatefulForwardEnvelope, "providerId" | "sessionKey" | "ownerPodId" | "generation" | "sourcePodId" | "forwardedAt" | "requestId" | "idempotencyKey">>;
55
55
  export type ProviderServerStatefulOwnerFenceValidator = (fence: ProviderServerStatefulOwnerFence, signal: AbortSignal) => boolean | Promise<boolean>;
56
- export type ProviderServerOperationExecutorInput = {
57
- readonly provider: ProviderDefinition;
56
+ export type ProviderServerOperationExecutorInput<TContext extends Partial<ProviderContext> = ProviderContext> = {
57
+ readonly provider: ProviderDefinition<TContext>;
58
58
  readonly operationId: string;
59
- readonly ctx: ProviderContext;
59
+ readonly ctx: TContext;
60
60
  readonly request: OperationRequest & {
61
61
  readonly deadlineAt?: string;
62
62
  };
63
63
  readonly signal?: AbortSignal;
64
64
  readonly internalStatefulForward?: ProviderServerStatefulForwardEnvelope;
65
65
  };
66
- export type ProviderServerOperationExecutor = (input: ProviderServerOperationExecutorInput) => Promise<unknown>;
66
+ export type ProviderServerOperationExecutor<TContext extends Partial<ProviderContext> = ProviderContext> = (input: ProviderServerOperationExecutorInput<TContext>) => Promise<unknown>;
67
67
  export declare function resolveProviderProxyAffinityKey(provider: ProviderDefinition, request: OperationRequest, operationId: string): string;
68
68
  export declare function resolveProviderResolverIdentityScope(provider: ProviderDefinition, affinityKey: string, contextId: string): string;
69
69
  export declare function resolveAuthFlowProxyAffinityKey(provider: ProviderDefinition, request: Pick<AuthFlowRequest, "connection" | "connectionId" | "externalRef" | "tenantId" | "providerId">): string;
@@ -138,12 +138,12 @@ export type ProviderServerLogEvent = (ProviderServerLogEventBase & {
138
138
  message: string;
139
139
  } | SelfTestCancellationLogEvent;
140
140
  export type ProviderServerLogger = (event: ProviderServerLogEvent) => void;
141
- export type ProviderServerOptions = {
141
+ export type ProviderServerOptions<TContext extends Partial<ProviderContext> = ProviderContext> = {
142
142
  logger?: ProviderServerLogger;
143
143
  /** Optional provider-specific operation executor. Stateful providers use this to preserve provider-local runtime semantics. */
144
- operationExecutor?: ProviderServerOperationExecutor;
144
+ operationExecutor?: ProviderServerOperationExecutor<TContext>;
145
145
  /** Optional signed internal executor for stateful owner forwarding. */
146
- internalOperationExecutor?: ProviderServerOperationExecutor;
146
+ internalOperationExecutor?: ProviderServerOperationExecutor<TContext>;
147
147
  statefulForwarding?: {
148
148
  readonly secret: string;
149
149
  readonly maxSkewMs?: number;
@@ -196,14 +196,14 @@ export type ProviderErrorCauseFrame = {
196
196
  * Primary, cross-runtime app factory. Declared capability ESM is preloaded
197
197
  * asynchronously, so this path works on Bun and every supported Node release.
198
198
  */
199
- export declare function createServerAppAsync(provider: ProviderDefinition, options?: ProviderServerOptions): Promise<Hono>;
199
+ export declare function createServerAppAsync<TContext extends Partial<ProviderContext> = ProviderContext>(provider: ProviderDefinition<TContext>, options?: ProviderServerOptions<TContext>): Promise<Hono>;
200
200
  /**
201
201
  * Synchronous compatibility factory. Standard providers remain synchronous on
202
202
  * every runtime because they load no capability modules. Providers declaring a
203
203
  * capability require Bun or Node >=22.12; older Node releases receive an
204
204
  * actionable error directing them to createServerAppAsync().
205
205
  */
206
- export declare function createServerApp(provider: ProviderDefinition, options?: ProviderServerOptions): Hono;
206
+ export declare function createServerApp<TContext extends Partial<ProviderContext> = ProviderContext>(provider: ProviderDefinition<TContext>, options?: ProviderServerOptions<TContext>): Hono;
207
207
  export type ProviderServerCloseOptions = {
208
208
  readonly timeoutMs?: number;
209
209
  };
@@ -211,7 +211,7 @@ export type ProviderServerHandle = {
211
211
  readonly port: number;
212
212
  close(options?: ProviderServerCloseOptions): Promise<void>;
213
213
  };
214
- export interface ServeOptions extends ProviderServerOptions {
214
+ export interface ServeOptions<TContext extends Partial<ProviderContext> = ProviderContext> extends ProviderServerOptions<TContext> {
215
215
  host?: string;
216
216
  port?: number;
217
217
  /**
@@ -221,5 +221,5 @@ export interface ServeOptions extends ProviderServerOptions {
221
221
  */
222
222
  selfTestPort?: number;
223
223
  }
224
- export declare function serve(provider: ProviderDefinition, options?: ServeOptions): Promise<ProviderServerHandle>;
224
+ export declare function serve<TContext extends Partial<ProviderContext> = ProviderContext>(provider: ProviderDefinition<TContext>, options?: ServeOptions<TContext>): Promise<ProviderServerHandle>;
225
225
  export {};
@@ -9,7 +9,7 @@ import { validateFailClosedDeclaration } from "../declaration-validation.js";
9
9
  import { safeProviderErrorObservability } from "../error-observability.js";
10
10
  import { SDK_OWNED_PROVIDER_ERROR_CODES, SDK_RUNTIME_OWNED_ERROR_CODES, SDK_STATUS_MAPPED_PROVIDER_ERROR_CODES, } from "../error-resolution.js";
11
11
  import { AuthError, isProviderError, isSessionExpiredError, isTransportError, isValidationError, ProviderError, } from "../errors.js";
12
- import { REDACTED_FIXTURE_VALUE, sanitizeDiagnosticText, } from "../fixture-sanitization.js";
12
+ import { sanitizeDiagnosticText } from "../fixture-sanitization.js";
13
13
  import { loadProviderLocaleCatalogs, localizeAuthTurn, } from "../i18n/catalog.js";
14
14
  import { categoryForStatus, sourceForCategory, isRetryableCategory, PROVIDER_OBSERVABILITY_TAXONOMY_VERSION, } from "../observability.js";
15
15
  import { createScratchpad } from "../runtime/auth-flow.js";
@@ -979,47 +979,8 @@ function extractRequestId(raw) {
979
979
  }
980
980
  const MAX_PROVIDER_ERROR_CAUSE_FRAMES = 5;
981
981
  const MAX_PROVIDER_ERROR_CAUSE_MESSAGE_LENGTH = 300;
982
- const UNSTRUCTURED_PROVIDER_ERROR_CAUSE_MESSAGE = "[UNSTRUCTURED_UPSTREAM_TEXT]";
983
- const PROVIDER_ERROR_CAUSE_RETAINED_URL_RUN = /https?:\/\/[^\s"'<>]+/giu;
984
- const PROVIDER_ERROR_CAUSE_TOKEN_RUN = /\S+/gu;
985
- const PROVIDER_ERROR_CAUSE_TOKEN_EDGE_PUNCTUATION = /^[^\p{L}\p{N}]+|[^\p{L}\p{N}]+$/gu;
986
- const STRUCTURALLY_SAFE_PROVIDER_ERROR_CAUSE_WORDS = new Set([
987
- "completion",
988
- "diagnostic",
989
- "provider",
990
- "rejected",
991
- "returned",
992
- "upstream",
993
- ]);
994
- /**
995
- * Cause frames fail closed when sanitization leaves a plausible credential-shaped free-text run.
996
- * Redaction sentinels and retained URLs are ignored. Every other whitespace token (or each side
997
- * of a structured key=value token) with at least eight Unicode characters must reduce to this
998
- * small vocabulary drawn from SDK diagnostics; counting punctuation keeps bare passwords opaque.
999
- */
1000
- function isStructurallySafeProviderErrorCauseMessage(message) {
1001
- const classifiableMessage = message
1002
- .replaceAll(REDACTED_FIXTURE_VALUE, " ")
1003
- .replace(PROVIDER_ERROR_CAUSE_RETAINED_URL_RUN, " ");
1004
- for (const match of classifiableMessage.matchAll(PROVIDER_ERROR_CAUSE_TOKEN_RUN)) {
1005
- const token = match[0];
1006
- for (const run of token.split("=")) {
1007
- const diagnosticWord = run
1008
- .replace(PROVIDER_ERROR_CAUSE_TOKEN_EDGE_PUNCTUATION, "")
1009
- .toLowerCase();
1010
- if (STRUCTURALLY_SAFE_PROVIDER_ERROR_CAUSE_WORDS.has(diagnosticWord))
1011
- continue;
1012
- if ([...run].length >= 8)
1013
- return false;
1014
- }
1015
- }
1016
- return true;
1017
- }
1018
982
  function providerErrorCauseMessage(message) {
1019
983
  const sanitized = sanitizeDiagnosticText(message);
1020
- if (!isStructurallySafeProviderErrorCauseMessage(sanitized)) {
1021
- return UNSTRUCTURED_PROVIDER_ERROR_CAUSE_MESSAGE;
1022
- }
1023
984
  return sanitized.length > MAX_PROVIDER_ERROR_CAUSE_MESSAGE_LENGTH
1024
985
  ? `${sanitized.slice(0, MAX_PROVIDER_ERROR_CAUSE_MESSAGE_LENGTH)}… [truncated]`
1025
986
  : sanitized;
@@ -1685,9 +1646,11 @@ function parseStatefulForwardingEnvelope(rawBody) {
1685
1646
  * asynchronously, so this path works on Bun and every supported Node release.
1686
1647
  */
1687
1648
  export async function createServerAppAsync(provider, options = {}) {
1688
- validateFailClosedDeclaration(provider);
1689
- validateStatefulServerConfig(options);
1690
- return createServerAppWithCapabilityModules(provider, options, await loadProviderCapabilityModules(provider));
1649
+ const runtimeProvider = provider;
1650
+ const runtimeOptions = options;
1651
+ validateFailClosedDeclaration(runtimeProvider);
1652
+ validateStatefulServerConfig(runtimeOptions);
1653
+ return createServerAppWithCapabilityModules(runtimeProvider, runtimeOptions, await loadProviderCapabilityModules(runtimeProvider));
1691
1654
  }
1692
1655
  /**
1693
1656
  * Synchronous compatibility factory. Standard providers remain synchronous on
@@ -1696,9 +1659,11 @@ export async function createServerAppAsync(provider, options = {}) {
1696
1659
  * actionable error directing them to createServerAppAsync().
1697
1660
  */
1698
1661
  export function createServerApp(provider, options = {}) {
1699
- validateFailClosedDeclaration(provider);
1700
- validateStatefulServerConfig(options);
1701
- return createServerAppWithCapabilityModules(provider, options, loadProviderCapabilityModulesSync(provider));
1662
+ const runtimeProvider = provider;
1663
+ const runtimeOptions = options;
1664
+ validateFailClosedDeclaration(runtimeProvider);
1665
+ validateStatefulServerConfig(runtimeOptions);
1666
+ return createServerAppWithCapabilityModules(runtimeProvider, runtimeOptions, loadProviderCapabilityModulesSync(runtimeProvider));
1702
1667
  }
1703
1668
  function createServerAppWithCapabilityModules(provider, serverOptions, capabilityModules) {
1704
1669
  const options = { ...serverOptions, capabilityModules };
package/dist/types.d.ts CHANGED
@@ -2024,7 +2024,7 @@ export interface ProviderDeploymentOverrides {
2024
2024
  };
2025
2025
  buildContext?: string;
2026
2026
  }
2027
- export interface ProviderDefinition {
2027
+ export interface ProviderDefinition<TContext = ProviderContext> {
2028
2028
  id: string;
2029
2029
  version: string;
2030
2030
  runtime: "standard" | "shared" | "browser";
@@ -2054,7 +2054,7 @@ export interface ProviderDefinition {
2054
2054
  credential?: CredentialDeclaration;
2055
2055
  context?: ContextDeclaration;
2056
2056
  meta: ProviderMeta;
2057
- operations: Record<string, OperationDefinition<SchemaLike, SchemaLike>>;
2057
+ operations: Record<string, OperationDefinition<SchemaLike, SchemaLike, TContext>>;
2058
2058
  healthMonitor?: ProviderHealthMonitorConfig;
2059
2059
  /** Transitional alias for `healthMonitor`; `defineProvider` mirrors both. */
2060
2060
  healthProbe?: ProviderHealthProbeConfig;
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.2.0-beta.42",
2
+ "version": "2.2.0-beta.44",
3
3
  "name": "@apifuse/provider-sdk",
4
4
  "private": false,
5
5
  "type": "module",
package/src/cli/create.ts CHANGED
@@ -26,7 +26,7 @@ export const CATEGORY_OPTIONS = [
26
26
  "other",
27
27
  ] as const;
28
28
  export const AUTH_MODE_OPTIONS = ["none", "platform-managed", "credentials", "oauth2"] as const;
29
- export const RUNTIME_OPTIONS = ["standard", "browser"] as const;
29
+ export const RUNTIME_OPTIONS = ["standard", "shared", "browser"] as const;
30
30
  export const PRESET_OPTIONS = ["standalone", "monorepo"] as const;
31
31
 
32
32
  export type CreateCategory = (typeof CATEGORY_OPTIONS)[number];
@@ -102,7 +102,7 @@ Options:
102
102
  --display-name <name>
103
103
  --category <category>
104
104
  --auth-mode <mode>
105
- --runtime <standard|browser>
105
+ --runtime <standard|shared|browser>
106
106
  --yes
107
107
  --dry-run
108
108
  --json
package/src/define.ts CHANGED
@@ -2892,6 +2892,16 @@ export type ProviderContextOf<TBuilder> = TBuilder extends ProviderBuilder<infer
2892
2892
  ? ProviderContextFor<TDeclaration>
2893
2893
  : never;
2894
2894
 
2895
+ /** Annotate an operation while preserving the declaration-derived context. */
2896
+ export type OperationDefinitionFor<
2897
+ TBuilder,
2898
+ TInput extends SchemaLike = SchemaLike,
2899
+ TOutput extends SchemaLike = SchemaLike,
2900
+ > = OperationDefinition<TInput, TOutput, ProviderContextOf<TBuilder>>;
2901
+
2902
+ /** Annotate a built provider while preserving the declaration-derived context. */
2903
+ export type ProviderDefinitionFor<TBuilder> = ProviderDefinition<ProviderContextOf<TBuilder>>;
2904
+
2895
2905
  /** Establish a provider declaration before its operations are contextually typed. */
2896
2906
  export function defineProvider<const TDeclaration extends ProviderDeclaration>(
2897
2907
  declaration: TDeclaration &
package/src/index.ts CHANGED
@@ -37,9 +37,11 @@ export {
37
37
  defineStreamOperation,
38
38
  every,
39
39
  type AuthStartNoInputGuard,
40
+ type OperationDefinitionFor,
40
41
  type ProviderBuilder,
41
42
  type ProviderContextOf,
42
43
  type ProviderDeclaration,
44
+ type ProviderDefinitionFor,
43
45
  } from "./define.js";
44
46
  export {
45
47
  AssertionExpressionSchema,
package/src/provider.ts CHANGED
@@ -36,9 +36,11 @@ export {
36
36
  every,
37
37
  } from "./define.js";
38
38
  export type {
39
+ OperationDefinitionFor,
39
40
  ProviderBuilder,
40
41
  ProviderContextOf,
41
42
  ProviderDeclaration,
43
+ ProviderDefinitionFor,
42
44
  } from "./define.js";
43
45
  export type { JsonPrimitive, JsonValue } from "./contract-json.js";
44
46
  export {
@@ -23,10 +23,7 @@ import {
23
23
  type ProviderErrorObservability,
24
24
  type ProviderErrorOptions,
25
25
  } from "../errors.js";
26
- import {
27
- REDACTED_FIXTURE_VALUE,
28
- sanitizeDiagnosticText,
29
- } from "../fixture-sanitization.js";
26
+ import { sanitizeDiagnosticText } from "../fixture-sanitization.js";
30
27
  import {
31
28
  loadProviderLocaleCatalogs,
32
29
  localizeAuthTurn,
@@ -234,17 +231,21 @@ export type ProviderServerStatefulOwnerFenceValidator = (
234
231
  signal: AbortSignal,
235
232
  ) => boolean | Promise<boolean>;
236
233
 
237
- export type ProviderServerOperationExecutorInput = {
238
- readonly provider: ProviderDefinition;
234
+ export type ProviderServerOperationExecutorInput<
235
+ TContext extends Partial<ProviderContext> = ProviderContext,
236
+ > = {
237
+ readonly provider: ProviderDefinition<TContext>;
239
238
  readonly operationId: string;
240
- readonly ctx: ProviderContext;
239
+ readonly ctx: TContext;
241
240
  readonly request: OperationRequest & { readonly deadlineAt?: string };
242
241
  readonly signal?: AbortSignal;
243
242
  readonly internalStatefulForward?: ProviderServerStatefulForwardEnvelope;
244
243
  };
245
244
 
246
- export type ProviderServerOperationExecutor = (
247
- input: ProviderServerOperationExecutorInput,
245
+ export type ProviderServerOperationExecutor<
246
+ TContext extends Partial<ProviderContext> = ProviderContext,
247
+ > = (
248
+ input: ProviderServerOperationExecutorInput<TContext>,
248
249
  ) => Promise<unknown>;
249
250
 
250
251
  type RequestCleanup = () => void | Promise<void>;
@@ -1072,12 +1073,12 @@ export type ProviderServerLogEvent =
1072
1073
 
1073
1074
  export type ProviderServerLogger = (event: ProviderServerLogEvent) => void;
1074
1075
 
1075
- export type ProviderServerOptions = {
1076
+ export type ProviderServerOptions<TContext extends Partial<ProviderContext> = ProviderContext> = {
1076
1077
  logger?: ProviderServerLogger;
1077
1078
  /** Optional provider-specific operation executor. Stateful providers use this to preserve provider-local runtime semantics. */
1078
- operationExecutor?: ProviderServerOperationExecutor;
1079
+ operationExecutor?: ProviderServerOperationExecutor<TContext>;
1079
1080
  /** Optional signed internal executor for stateful owner forwarding. */
1080
- internalOperationExecutor?: ProviderServerOperationExecutor;
1081
+ internalOperationExecutor?: ProviderServerOperationExecutor<TContext>;
1081
1082
  statefulForwarding?: {
1082
1083
  readonly secret: string;
1083
1084
  readonly maxSkewMs?: number;
@@ -1522,48 +1523,9 @@ export type ProviderErrorCauseFrame = {
1522
1523
 
1523
1524
  const MAX_PROVIDER_ERROR_CAUSE_FRAMES = 5;
1524
1525
  const MAX_PROVIDER_ERROR_CAUSE_MESSAGE_LENGTH = 300;
1525
- const UNSTRUCTURED_PROVIDER_ERROR_CAUSE_MESSAGE = "[UNSTRUCTURED_UPSTREAM_TEXT]";
1526
- const PROVIDER_ERROR_CAUSE_RETAINED_URL_RUN = /https?:\/\/[^\s"'<>]+/giu;
1527
- const PROVIDER_ERROR_CAUSE_TOKEN_RUN = /\S+/gu;
1528
- const PROVIDER_ERROR_CAUSE_TOKEN_EDGE_PUNCTUATION =
1529
- /^[^\p{L}\p{N}]+|[^\p{L}\p{N}]+$/gu;
1530
- const STRUCTURALLY_SAFE_PROVIDER_ERROR_CAUSE_WORDS = new Set([
1531
- "completion",
1532
- "diagnostic",
1533
- "provider",
1534
- "rejected",
1535
- "returned",
1536
- "upstream",
1537
- ]);
1538
-
1539
- /**
1540
- * Cause frames fail closed when sanitization leaves a plausible credential-shaped free-text run.
1541
- * Redaction sentinels and retained URLs are ignored. Every other whitespace token (or each side
1542
- * of a structured key=value token) with at least eight Unicode characters must reduce to this
1543
- * small vocabulary drawn from SDK diagnostics; counting punctuation keeps bare passwords opaque.
1544
- */
1545
- function isStructurallySafeProviderErrorCauseMessage(message: string): boolean {
1546
- const classifiableMessage = message
1547
- .replaceAll(REDACTED_FIXTURE_VALUE, " ")
1548
- .replace(PROVIDER_ERROR_CAUSE_RETAINED_URL_RUN, " ");
1549
- for (const match of classifiableMessage.matchAll(PROVIDER_ERROR_CAUSE_TOKEN_RUN)) {
1550
- const token = match[0];
1551
- for (const run of token.split("=")) {
1552
- const diagnosticWord = run
1553
- .replace(PROVIDER_ERROR_CAUSE_TOKEN_EDGE_PUNCTUATION, "")
1554
- .toLowerCase();
1555
- if (STRUCTURALLY_SAFE_PROVIDER_ERROR_CAUSE_WORDS.has(diagnosticWord)) continue;
1556
- if ([...run].length >= 8) return false;
1557
- }
1558
- }
1559
- return true;
1560
- }
1561
1526
 
1562
1527
  function providerErrorCauseMessage(message: string): string {
1563
1528
  const sanitized = sanitizeDiagnosticText(message);
1564
- if (!isStructurallySafeProviderErrorCauseMessage(sanitized)) {
1565
- return UNSTRUCTURED_PROVIDER_ERROR_CAUSE_MESSAGE;
1566
- }
1567
1529
  return sanitized.length > MAX_PROVIDER_ERROR_CAUSE_MESSAGE_LENGTH
1568
1530
  ? `${sanitized.slice(0, MAX_PROVIDER_ERROR_CAUSE_MESSAGE_LENGTH)}… [truncated]`
1569
1531
  : sanitized;
@@ -2413,16 +2375,18 @@ function parseStatefulForwardingEnvelope(rawBody: unknown): ProviderServerStatef
2413
2375
  * Primary, cross-runtime app factory. Declared capability ESM is preloaded
2414
2376
  * asynchronously, so this path works on Bun and every supported Node release.
2415
2377
  */
2416
- export async function createServerAppAsync(
2417
- provider: ProviderDefinition,
2418
- options: ProviderServerOptions = {},
2378
+ export async function createServerAppAsync<TContext extends Partial<ProviderContext> = ProviderContext>(
2379
+ provider: ProviderDefinition<TContext>,
2380
+ options: ProviderServerOptions<TContext> = {},
2419
2381
  ): Promise<Hono> {
2420
- validateFailClosedDeclaration(provider);
2421
- validateStatefulServerConfig(options);
2382
+ const runtimeProvider = provider as unknown as ProviderDefinition;
2383
+ const runtimeOptions = options as unknown as ProviderServerOptions;
2384
+ validateFailClosedDeclaration(runtimeProvider);
2385
+ validateStatefulServerConfig(runtimeOptions);
2422
2386
  return createServerAppWithCapabilityModules(
2423
- provider,
2424
- options,
2425
- await loadProviderCapabilityModules(provider),
2387
+ runtimeProvider,
2388
+ runtimeOptions,
2389
+ await loadProviderCapabilityModules(runtimeProvider),
2426
2390
  );
2427
2391
  }
2428
2392
 
@@ -2432,16 +2396,18 @@ export async function createServerAppAsync(
2432
2396
  * capability require Bun or Node >=22.12; older Node releases receive an
2433
2397
  * actionable error directing them to createServerAppAsync().
2434
2398
  */
2435
- export function createServerApp(
2436
- provider: ProviderDefinition,
2437
- options: ProviderServerOptions = {},
2399
+ export function createServerApp<TContext extends Partial<ProviderContext> = ProviderContext>(
2400
+ provider: ProviderDefinition<TContext>,
2401
+ options: ProviderServerOptions<TContext> = {},
2438
2402
  ): Hono {
2439
- validateFailClosedDeclaration(provider);
2440
- validateStatefulServerConfig(options);
2403
+ const runtimeProvider = provider as unknown as ProviderDefinition;
2404
+ const runtimeOptions = options as unknown as ProviderServerOptions;
2405
+ validateFailClosedDeclaration(runtimeProvider);
2406
+ validateStatefulServerConfig(runtimeOptions);
2441
2407
  return createServerAppWithCapabilityModules(
2442
- provider,
2443
- options,
2444
- loadProviderCapabilityModulesSync(provider),
2408
+ runtimeProvider,
2409
+ runtimeOptions,
2410
+ loadProviderCapabilityModulesSync(runtimeProvider),
2445
2411
  );
2446
2412
  }
2447
2413
 
@@ -3131,7 +3097,8 @@ export type ProviderServerHandle = {
3131
3097
  close(options?: ProviderServerCloseOptions): Promise<void>;
3132
3098
  };
3133
3099
 
3134
- export interface ServeOptions extends ProviderServerOptions {
3100
+ export interface ServeOptions<TContext extends Partial<ProviderContext> = ProviderContext>
3101
+ extends ProviderServerOptions<TContext> {
3135
3102
  host?: string;
3136
3103
  port?: number;
3137
3104
  /**
@@ -3158,9 +3125,9 @@ type ProcessSignalCoordinator = {
3158
3125
 
3159
3126
  const processSignalCoordinators = new Map<NodeJS.Signals, ProcessSignalCoordinator>();
3160
3127
 
3161
- export async function serve(
3162
- provider: ProviderDefinition,
3163
- options: ServeOptions = {},
3128
+ export async function serve<TContext extends Partial<ProviderContext> = ProviderContext>(
3129
+ provider: ProviderDefinition<TContext>,
3130
+ options: ServeOptions<TContext> = {},
3164
3131
  ): Promise<ProviderServerHandle> {
3165
3132
  const bunRuntime = getBunServeRuntime();
3166
3133
 
@@ -3175,7 +3142,7 @@ export async function serve(
3175
3142
  );
3176
3143
  const configuredSignals = resolveShutdownSignals(options.shutdown?.signals ?? true);
3177
3144
  const selfTestSecrets = resolveSelfTestMasterSecrets();
3178
- const serverAppOptions: ProviderServerOptions = {
3145
+ const serverAppOptions: ProviderServerOptions<TContext> = {
3179
3146
  logger: options.logger,
3180
3147
  ocr: options.ocr,
3181
3148
  stt: options.stt,
@@ -3205,12 +3172,15 @@ export async function serve(
3205
3172
  // socket the tenant-facing gateway never dials. Off by default — it only
3206
3173
  // starts when the shared self-test master secret env is present.
3207
3174
  if (selfTestSecrets && selfTestModule) {
3208
- const selfTestApp = selfTestModule.createSelfTestApp(provider, {
3209
- secrets: selfTestSecrets,
3210
- invoke: selfTestModule.createSelfTestInvoke(app),
3211
- authFlow: selfTestModule.createSelfTestAuthFlowInvoke(app),
3212
- logger,
3213
- });
3175
+ const selfTestApp = selfTestModule.createSelfTestApp(
3176
+ provider as unknown as ProviderDefinition,
3177
+ {
3178
+ secrets: selfTestSecrets,
3179
+ invoke: selfTestModule.createSelfTestInvoke(app),
3180
+ authFlow: selfTestModule.createSelfTestAuthFlowInvoke(app),
3181
+ logger,
3182
+ },
3183
+ );
3214
3184
  servers.push(
3215
3185
  bunRuntime.serve({
3216
3186
  port: options.selfTestPort ?? selfTestModule.resolveSelfTestPort(),
package/src/types.ts CHANGED
@@ -2479,7 +2479,7 @@ export interface ProviderDeploymentOverrides {
2479
2479
  buildContext?: string;
2480
2480
  }
2481
2481
 
2482
- export interface ProviderDefinition {
2482
+ export interface ProviderDefinition<TContext = ProviderContext> {
2483
2483
  id: string;
2484
2484
  version: string;
2485
2485
  runtime: "standard" | "shared" | "browser";
@@ -2509,7 +2509,7 @@ export interface ProviderDefinition {
2509
2509
  credential?: CredentialDeclaration;
2510
2510
  context?: ContextDeclaration;
2511
2511
  meta: ProviderMeta;
2512
- operations: Record<string, OperationDefinition<SchemaLike, SchemaLike>>;
2512
+ operations: Record<string, OperationDefinition<SchemaLike, SchemaLike, TContext>>;
2513
2513
  healthMonitor?: ProviderHealthMonitorConfig;
2514
2514
  /** Transitional alias for `healthMonitor`; `defineProvider` mirrors both. */
2515
2515
  healthProbe?: ProviderHealthProbeConfig;