@apifuse/provider-sdk 2.1.0-beta.1 → 2.1.0-beta.11

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.
Files changed (212) hide show
  1. package/AUTHORING.md +208 -2
  2. package/CHANGELOG.md +51 -0
  3. package/README.md +118 -10
  4. package/SUBMISSION.md +87 -0
  5. package/bin/apifuse-check.ts +86 -4
  6. package/bin/apifuse-dev.ts +87 -13
  7. package/bin/apifuse-pack-check.ts +80 -0
  8. package/bin/apifuse-pack-smoke.ts +303 -2
  9. package/bin/apifuse-perf.ts +142 -49
  10. package/bin/apifuse-record.ts +182 -104
  11. package/bin/apifuse-submit-check.ts +2538 -0
  12. package/bin/apifuse.ts +1 -1
  13. package/dist/ceremonies/index.d.ts +41 -0
  14. package/dist/ceremonies/index.js +490 -0
  15. package/dist/choice-token.d.ts +24 -0
  16. package/dist/choice-token.js +74 -0
  17. package/dist/cli/commands.d.ts +10 -0
  18. package/dist/cli/commands.js +80 -0
  19. package/dist/cli/create.d.ts +47 -0
  20. package/dist/cli/create.js +762 -0
  21. package/dist/cli/templates/provider/.dockerignore.tpl +22 -0
  22. package/dist/cli/templates/provider/.gitignore.tpl +22 -0
  23. package/dist/cli/templates/provider/Dockerfile.tpl +7 -0
  24. package/dist/cli/templates/provider/README.md.tpl +160 -0
  25. package/dist/cli/templates/provider/dev.ts.tpl +5 -0
  26. package/dist/cli/templates/provider/domain/README.md.tpl +3 -0
  27. package/dist/cli/templates/provider/index.test.ts.tpl +13 -0
  28. package/dist/cli/templates/provider/index.ts.tpl +15 -0
  29. package/dist/cli/templates/provider/mappers/README.md.tpl +3 -0
  30. package/dist/cli/templates/provider/meta.ts.tpl +7 -0
  31. package/dist/cli/templates/provider/operations/index.ts.tpl +5 -0
  32. package/dist/cli/templates/provider/operations/ping.ts.tpl +24 -0
  33. package/dist/cli/templates/provider/schemas/ping.ts.tpl +24 -0
  34. package/dist/cli/templates/provider/start.ts.tpl +5 -0
  35. package/dist/cli/templates/provider/upstream/README.md.tpl +3 -0
  36. package/dist/config/loader.d.ts +107 -0
  37. package/dist/config/loader.js +935 -0
  38. package/dist/contract-json.d.ts +9 -0
  39. package/dist/contract-json.js +51 -0
  40. package/dist/contract-serialization.d.ts +4 -0
  41. package/dist/contract-serialization.js +78 -0
  42. package/dist/contract-types.d.ts +49 -0
  43. package/dist/contract-types.js +1 -0
  44. package/dist/contract.d.ts +6 -0
  45. package/dist/contract.js +155 -0
  46. package/dist/define.d.ts +97 -0
  47. package/dist/define.js +1320 -0
  48. package/dist/dev.d.ts +9 -0
  49. package/dist/dev.js +15 -0
  50. package/dist/errors.d.ts +59 -0
  51. package/dist/errors.js +97 -0
  52. package/dist/i18n/catalog.d.ts +29 -0
  53. package/dist/i18n/catalog.js +159 -0
  54. package/dist/i18n/index.d.ts +2 -0
  55. package/dist/i18n/index.js +2 -0
  56. package/dist/i18n/keys.d.ts +10 -0
  57. package/dist/i18n/keys.js +34 -0
  58. package/dist/index.d.ts +41 -0
  59. package/dist/index.js +37 -0
  60. package/dist/lint.d.ts +73 -0
  61. package/dist/lint.js +702 -0
  62. package/dist/observability.d.ts +5 -0
  63. package/dist/observability.js +39 -0
  64. package/dist/provider.d.ts +9 -0
  65. package/dist/provider.js +8 -0
  66. package/dist/public-schema-field-lint.d.ts +2 -0
  67. package/dist/public-schema-field-lint.js +158 -0
  68. package/dist/recipes/gov-api.d.ts +19 -0
  69. package/dist/recipes/gov-api.js +72 -0
  70. package/dist/recipes/rest-api.d.ts +21 -0
  71. package/dist/recipes/rest-api.js +115 -0
  72. package/dist/runtime/auth-flow.d.ts +14 -0
  73. package/dist/runtime/auth-flow.js +44 -0
  74. package/dist/runtime/browser.d.ts +25 -0
  75. package/dist/runtime/browser.js +1034 -0
  76. package/dist/runtime/cache.d.ts +10 -0
  77. package/dist/runtime/cache.js +372 -0
  78. package/dist/runtime/choice.d.ts +15 -0
  79. package/dist/runtime/choice.js +435 -0
  80. package/dist/runtime/credential.d.ts +8 -0
  81. package/dist/runtime/credential.js +61 -0
  82. package/dist/runtime/env.d.ts +2 -0
  83. package/dist/runtime/env.js +10 -0
  84. package/dist/runtime/executor.d.ts +16 -0
  85. package/dist/runtime/executor.js +51 -0
  86. package/dist/runtime/http.d.ts +8 -0
  87. package/dist/runtime/http.js +706 -0
  88. package/dist/runtime/insights.d.ts +9 -0
  89. package/dist/runtime/insights.js +324 -0
  90. package/dist/runtime/instrumentation.d.ts +8 -0
  91. package/dist/runtime/instrumentation.js +269 -0
  92. package/dist/runtime/key-derivation.d.ts +24 -0
  93. package/dist/runtime/key-derivation.js +73 -0
  94. package/dist/runtime/keyring.d.ts +25 -0
  95. package/dist/runtime/keyring.js +93 -0
  96. package/dist/runtime/namespace.d.ts +9 -0
  97. package/dist/runtime/namespace.js +19 -0
  98. package/dist/runtime/otlp.d.ts +39 -0
  99. package/dist/runtime/otlp.js +103 -0
  100. package/dist/runtime/perf.d.ts +12 -0
  101. package/dist/runtime/perf.js +52 -0
  102. package/dist/runtime/prevalidate.d.ts +12 -0
  103. package/dist/runtime/prevalidate.js +173 -0
  104. package/dist/runtime/provider.d.ts +2 -0
  105. package/dist/runtime/provider.js +11 -0
  106. package/dist/runtime/proxy-errors.d.ts +21 -0
  107. package/dist/runtime/proxy-errors.js +83 -0
  108. package/dist/runtime/proxy-telemetry.d.ts +8 -0
  109. package/dist/runtime/proxy-telemetry.js +174 -0
  110. package/dist/runtime/redis.d.ts +17 -0
  111. package/dist/runtime/redis.js +82 -0
  112. package/dist/runtime/request-options.d.ts +3 -0
  113. package/dist/runtime/request-options.js +42 -0
  114. package/dist/runtime/state.d.ts +17 -0
  115. package/dist/runtime/state.js +344 -0
  116. package/dist/runtime/stealth.d.ts +21 -0
  117. package/dist/runtime/stealth.js +980 -0
  118. package/dist/runtime/stt.d.ts +22 -0
  119. package/dist/runtime/stt.js +480 -0
  120. package/dist/runtime/trace.d.ts +26 -0
  121. package/dist/runtime/trace.js +142 -0
  122. package/dist/runtime/waterfall.d.ts +12 -0
  123. package/dist/runtime/waterfall.js +147 -0
  124. package/dist/schema.d.ts +74 -0
  125. package/dist/schema.js +243 -0
  126. package/dist/serve.d.ts +1 -0
  127. package/dist/serve.js +1 -0
  128. package/dist/server/index.d.ts +3 -0
  129. package/dist/server/index.js +2 -0
  130. package/dist/server/serve.d.ts +64 -0
  131. package/dist/server/serve.js +1110 -0
  132. package/dist/server/types.d.ts +136 -0
  133. package/dist/server/types.js +86 -0
  134. package/dist/stealth/profiles.d.ts +4 -0
  135. package/dist/stealth/profiles.js +259 -0
  136. package/dist/stream.d.ts +44 -0
  137. package/dist/stream.js +151 -0
  138. package/dist/testing/helpers.d.ts +23 -0
  139. package/dist/testing/helpers.js +95 -0
  140. package/dist/testing/index.d.ts +2 -0
  141. package/dist/testing/index.js +2 -0
  142. package/dist/testing/run.d.ts +34 -0
  143. package/dist/testing/run.js +303 -0
  144. package/dist/types.d.ts +1359 -0
  145. package/dist/types.js +61 -0
  146. package/dist/utils/date.d.ts +6 -0
  147. package/dist/utils/date.js +101 -0
  148. package/dist/utils/parse.d.ts +16 -0
  149. package/dist/utils/parse.js +51 -0
  150. package/dist/utils/text.d.ts +4 -0
  151. package/dist/utils/text.js +14 -0
  152. package/dist/utils/transform.d.ts +8 -0
  153. package/dist/utils/transform.js +48 -0
  154. package/package.json +57 -30
  155. package/src/ceremonies/index.ts +8 -2
  156. package/src/choice-token.ts +165 -0
  157. package/src/cli/commands.ts +34 -11
  158. package/src/cli/create.ts +214 -52
  159. package/src/cli/templates/provider/.dockerignore.tpl +22 -0
  160. package/src/cli/templates/provider/.gitignore.tpl +22 -0
  161. package/src/cli/templates/provider/README.md.tpl +120 -1
  162. package/src/cli/templates/provider/dev.ts.tpl +1 -1
  163. package/src/cli/templates/provider/domain/README.md.tpl +3 -0
  164. package/src/cli/templates/provider/index.ts.tpl +5 -48
  165. package/src/cli/templates/provider/mappers/README.md.tpl +3 -0
  166. package/src/cli/templates/provider/meta.ts.tpl +7 -0
  167. package/src/cli/templates/provider/operations/index.ts.tpl +5 -0
  168. package/src/cli/templates/provider/operations/ping.ts.tpl +24 -0
  169. package/src/cli/templates/provider/schemas/ping.ts.tpl +24 -0
  170. package/src/cli/templates/provider/start.ts.tpl +1 -1
  171. package/src/cli/templates/provider/upstream/README.md.tpl +3 -0
  172. package/src/config/loader.ts +1224 -9
  173. package/src/contract-json.ts +75 -0
  174. package/src/contract-serialization.ts +89 -0
  175. package/src/contract-types.ts +52 -0
  176. package/src/contract.ts +215 -0
  177. package/src/define.ts +1688 -48
  178. package/src/errors.ts +27 -0
  179. package/src/i18n/catalog.ts +277 -0
  180. package/src/i18n/index.ts +2 -0
  181. package/src/i18n/keys.ts +64 -0
  182. package/src/index.ts +179 -9
  183. package/src/lint.ts +547 -73
  184. package/src/observability.ts +41 -0
  185. package/src/provider.ts +104 -4
  186. package/src/public-schema-field-lint.ts +237 -0
  187. package/src/runtime/auth-flow.ts +7 -0
  188. package/src/runtime/browser.ts +762 -51
  189. package/src/runtime/cache.ts +528 -0
  190. package/src/runtime/choice.ts +760 -0
  191. package/src/runtime/executor.ts +32 -3
  192. package/src/runtime/http.ts +939 -195
  193. package/src/runtime/insights.ts +11 -11
  194. package/src/runtime/instrumentation.ts +12 -4
  195. package/src/runtime/key-derivation.ts +1 -1
  196. package/src/runtime/keyring.ts +4 -3
  197. package/src/runtime/proxy-errors.ts +132 -0
  198. package/src/runtime/proxy-telemetry.ts +253 -0
  199. package/src/runtime/redis.ts +116 -0
  200. package/src/runtime/request-options.ts +66 -0
  201. package/src/runtime/state.ts +563 -0
  202. package/src/runtime/stealth.ts +1336 -0
  203. package/src/runtime/stt.ts +629 -0
  204. package/src/runtime/trace.ts +1 -1
  205. package/src/schema.ts +363 -1
  206. package/src/server/serve.ts +1157 -75
  207. package/src/server/types.ts +37 -0
  208. package/src/stream.ts +210 -0
  209. package/src/testing/run.ts +31 -5
  210. package/src/types.ts +1145 -59
  211. package/src/runtime/tls.ts +0 -434
  212. package/src/types/playwright-stealth.d.ts +0 -9
package/src/types.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import type ms from "ms";
2
+
1
3
  import type { infer as ZodInfer, ZodType } from "zod";
2
4
 
3
5
  /** Minimal Standard Schema v1 shape accepted by provider operations. */
@@ -45,6 +47,51 @@ export interface OperationInputExample {
45
47
  rationale?: string;
46
48
  }
47
49
 
50
+ export type OperationRiskClass =
51
+ | "read"
52
+ | "write"
53
+ | "destructive"
54
+ | "external-send";
55
+
56
+ export type OperationApprovalPolicy = "never" | "risk-based" | "always";
57
+
58
+ export interface OperationToolRouterMetadata {
59
+ /** Optional MCP-safe override. Defaults to providerId__operationId. */
60
+ name?: string;
61
+ /** Safety class exposed to Tool Router clients and approval policy. */
62
+ riskClass?: OperationRiskClass;
63
+ /** OpenAI remote-MCP approval hint. Defaults from riskClass. */
64
+ approval?: OperationApprovalPolicy;
65
+ /** Override connection requirement when provider auth + openWorld inference is insufficient. */
66
+ requiresConnection?: boolean;
67
+ /** Public argument used to resolve the tenant-owned connection. Defaults to externalRef. */
68
+ connectionExternalRefParam?: string;
69
+ }
70
+
71
+ export type OperationSensitivePath = string;
72
+
73
+ export interface OperationObservabilitySensitiveConfig {
74
+ /**
75
+ * Additional dot paths to redact from captured invocation inputs. Use `*`
76
+ * for array elements, for example `items.*.phone`.
77
+ */
78
+ input?: readonly OperationSensitivePath[];
79
+ /**
80
+ * Additional dot paths to redact from captured invocation outputs. Use `*`
81
+ * for array elements, for example `items.*.paymentUrl`.
82
+ */
83
+ output?: readonly OperationSensitivePath[];
84
+ }
85
+
86
+ export interface OperationObservabilityConfig {
87
+ /**
88
+ * Complements schema-level `fields.*()` / `sensitive()` metadata for values
89
+ * that are shape-dependent, provider-normalized, or otherwise easier to
90
+ * express as stable public paths.
91
+ */
92
+ sensitive?: OperationObservabilitySensitiveConfig;
93
+ }
94
+
48
95
  export interface OperationAnnotations {
49
96
  readOnly?: boolean;
50
97
  destructive?: boolean;
@@ -80,10 +127,351 @@ export interface OperationAnnotations {
80
127
  export const OPERATION_TIMEOUT_MS_MIN = 1;
81
128
  export const OPERATION_TIMEOUT_MS_MAX = 60_000;
82
129
 
130
+ export const STREAM_HEARTBEAT_MS_MIN = 1_000;
131
+ export const STREAM_HEARTBEAT_MS_MAX = 60_000;
132
+ export const STREAM_IDLE_TIMEOUT_MS_MIN = 1_000;
133
+ export const STREAM_IDLE_TIMEOUT_MS_MAX = 300_000;
134
+ export const STREAM_MAX_DURATION_MS_MIN = 1_000;
135
+ export const STREAM_MAX_DURATION_MS_MAX = 1_800_000;
136
+ export const STREAM_CHUNK_BYTES_MIN = 1;
137
+ export const STREAM_CHUNK_BYTES_MAX = 1_048_576;
138
+
139
+ export type OperationTransportKind =
140
+ | "json"
141
+ | "sse"
142
+ | "http-stream"
143
+ | "websocket";
144
+
145
+ export interface OperationJsonTransport {
146
+ kind: "json";
147
+ }
148
+
149
+ export interface OperationSseTransport {
150
+ kind: "sse";
151
+ heartbeatMs?: number;
152
+ idleTimeoutMs?: number;
153
+ maxDurationMs?: number;
154
+ maxEventBytes?: number;
155
+ resumable?: false | "last-event-id";
156
+ events: Record<string, SchemaLike>;
157
+ }
158
+
159
+ export interface OperationHttpStreamTransport {
160
+ kind: "http-stream";
161
+ contentType?: string;
162
+ idleTimeoutMs?: number;
163
+ maxDurationMs?: number;
164
+ maxChunkBytes?: number;
165
+ }
166
+
167
+ export interface OperationWebSocketTransport {
168
+ kind: "websocket";
169
+ subprotocols?: readonly string[];
170
+ idleTimeoutMs?: number;
171
+ maxDurationMs?: number;
172
+ maxFrameBytes?: number;
173
+ /**
174
+ * WebSocket Operation metadata is future-ready. Gateway dispatch remains
175
+ * disabled until a gateway-managed session implementation is present.
176
+ */
177
+ dispatch: "unsupported";
178
+ }
179
+
180
+ export type OperationTransport =
181
+ | OperationJsonTransport
182
+ | OperationSseTransport
183
+ | OperationHttpStreamTransport
184
+ | OperationWebSocketTransport;
185
+
186
+ export const DEFAULT_OPERATION_TRANSPORT: OperationJsonTransport = {
187
+ kind: "json",
188
+ };
189
+
83
190
  export interface OperationRelationships {
84
191
  alternatives?: string[];
85
192
  }
86
193
 
194
+ export type Iso3166Alpha2CountryCode = Uppercase<string>;
195
+ export type Bcp47Locale = string;
196
+ export type ProviderLocale = Bcp47Locale;
197
+ export type ProviderLocaleKey = string & {
198
+ readonly __brand: "ProviderLocaleKey";
199
+ };
200
+ export type ProviderLocaleKeyInput = ProviderLocaleKey | string;
201
+ export type Iso8601Duration = string;
202
+ export type Rfc3339Instant = string;
203
+ export type IanaTimeZone = string;
204
+ export type Iso4217CurrencyCode = Uppercase<string>;
205
+ export type E164PhoneNumber = `+${string}`;
206
+
207
+ export type SmsOrigin =
208
+ | {
209
+ /** Sender represented as an ITU-T E.164 phone number. */
210
+ kind: "e164";
211
+ value: E164PhoneNumber;
212
+ display?: string;
213
+ }
214
+ | {
215
+ /** Country-local service sender, for example KR 1661-5270. */
216
+ kind: "nationalServiceCode";
217
+ country: Iso3166Alpha2CountryCode;
218
+ value: string;
219
+ display?: string;
220
+ };
221
+
222
+ export interface SmsOtpExtractionPattern {
223
+ /** RegExp or source string containing exactly one usable OTP capture. */
224
+ pattern: RegExp | string;
225
+ /** Named capture key or one-based numeric capture index. Defaults to first capture. */
226
+ capture?: string | number;
227
+ }
228
+
229
+ export interface SmsOtpMatcherDefinition {
230
+ id: string;
231
+ country: Iso3166Alpha2CountryCode;
232
+ locale?: Bcp47Locale;
233
+ phoneNumber?: E164PhoneNumber;
234
+ origins: readonly [SmsOrigin, ...SmsOrigin[]];
235
+ code: SmsOtpExtractionPattern;
236
+ maxAge: Iso8601Duration;
237
+ waitTimeout: Iso8601Duration;
238
+ clockSkew?: Iso8601Duration;
239
+ /** Runtime/fixture helper. Not serialized into generated registry artifacts. */
240
+ extractOtp(body: string): string | null;
241
+ }
242
+
243
+ export type SttTranscribeMode = "general" | "otp";
244
+ export type SttPromptPolicy = "none" | "default-hint" | "custom-hint";
245
+ export type SttUnsupportedOptionPolicy = "warn" | "error";
246
+ export type ProviderSttMode = "optional" | "required";
247
+
248
+ export interface ProviderSttConfig {
249
+ mode: ProviderSttMode;
250
+ }
251
+
252
+ export type SttAudioInput = {
253
+ kind: "base64";
254
+ data: string;
255
+ mediaType?: string;
256
+ durationMs?: number;
257
+ };
258
+
259
+ export interface SttVerificationCodeOptions {
260
+ locale?: Bcp47Locale;
261
+ codeLengths?: number | readonly number[] | { min: number; max: number };
262
+ }
263
+
264
+ export interface SttTranscribeRequest {
265
+ audio: SttAudioInput;
266
+ language?: Bcp47Locale;
267
+ mode?: SttTranscribeMode;
268
+ promptPolicy?: SttPromptPolicy;
269
+ initialPrompt?: string;
270
+ unsupportedOptionPolicy?: SttUnsupportedOptionPolicy;
271
+ verificationCode?: SttVerificationCodeOptions;
272
+ timeoutMs?: number;
273
+ maxAudioBytes?: number;
274
+ }
275
+
276
+ export interface SttSegment {
277
+ text: string;
278
+ startMs?: number;
279
+ endMs?: number;
280
+ confidence?: number;
281
+ }
282
+
283
+ export interface SttUsage {
284
+ audioDurationMs?: number;
285
+ audioBytes?: number;
286
+ billableUnits?: number;
287
+ }
288
+
289
+ export interface SttWarning {
290
+ code: "UNSUPPORTED_STT_OPTION" | "PROMPT_IGNORED" | "LOCALE_PARTIAL";
291
+ message: string;
292
+ }
293
+
294
+ export interface SttTranscript {
295
+ text: string;
296
+ language?: Bcp47Locale;
297
+ durationMs?: number;
298
+ segments?: readonly SttSegment[];
299
+ usage?: SttUsage;
300
+ warnings?: readonly SttWarning[];
301
+ verificationCode?: VerificationCodeExtractionResult;
302
+ }
303
+
304
+ export type VerificationCodeCandidateSource =
305
+ | "digits"
306
+ | "spoken_words"
307
+ | "mixed";
308
+
309
+ export interface VerificationCodeCandidate {
310
+ code: string;
311
+ source: VerificationCodeCandidateSource;
312
+ startIndex?: number;
313
+ endIndex?: number;
314
+ }
315
+
316
+ export interface VerificationCodeExtractionResult {
317
+ code: string;
318
+ candidates: readonly VerificationCodeCandidate[];
319
+ normalizedText: string;
320
+ }
321
+
322
+ export interface SttContext {
323
+ transcribe(request: SttTranscribeRequest): Promise<SttTranscript>;
324
+ extractVerificationCode(
325
+ text: string,
326
+ options?: SttVerificationCodeOptions,
327
+ ): VerificationCodeExtractionResult;
328
+ }
329
+
330
+ export interface HealthJourneySchedule {
331
+ kind: "interval";
332
+ /** ISO 8601 duration, for example PT8H. */
333
+ interval: Iso8601Duration;
334
+ jitter?: Iso8601Duration;
335
+ }
336
+
337
+ export interface HealthJourneyStep {
338
+ id: string;
339
+ description?: string;
340
+ operationId?: string;
341
+ usesSmsMatcher?: string;
342
+ coversOperations?: readonly string[];
343
+ safeBoundary?: "paymentWebviewUrl" | "paymentUrl" | "none";
344
+ kind?: "operation" | "smsOtp" | "assertion" | "journal";
345
+ }
346
+
347
+ export interface HealthJourneyGatewayContext {
348
+ connect?(options?: {
349
+ providerId?: string;
350
+ externalRef?: string;
351
+ authMode?: "credentials" | "oauth2";
352
+ input?: Record<string, unknown>;
353
+ metadata?: Record<string, unknown>;
354
+ }): Promise<{ connectionId: string; rowVersion: number }>;
355
+ disconnect?(connection: {
356
+ connectionId: string;
357
+ rowVersion: number;
358
+ }): Promise<void>;
359
+ execute(
360
+ providerId: string,
361
+ operationId: string,
362
+ input: unknown,
363
+ options?: {
364
+ connectionId?: string;
365
+ requestId?: string;
366
+ /**
367
+ * Set false when the journey will record the semantic operation
368
+ * outcome itself through `ctx.event.operation()`. Transport success
369
+ * must not become a competing public health sample in that case.
370
+ */
371
+ recordOperationEvent?: boolean;
372
+ },
373
+ ): Promise<{
374
+ data: unknown;
375
+ status: number;
376
+ duration: number;
377
+ meta?: Record<string, unknown>;
378
+ }>;
379
+ }
380
+
381
+ export interface SmsPhoneIdentity {
382
+ id: string;
383
+ country: Iso3166Alpha2CountryCode | string;
384
+ e164: E164PhoneNumber | string;
385
+ nationalNumber: string;
386
+ displayName?: string;
387
+ }
388
+
389
+ export interface HealthJourneySmsContext {
390
+ resolvePhone(params?: { matcherId?: string }): Promise<SmsPhoneIdentity>;
391
+ waitForOtp(params: {
392
+ matcherId: string;
393
+ attemptId: string;
394
+ phoneId?: string;
395
+ phoneNumber?: string;
396
+ signal?: AbortSignal;
397
+ }): Promise<{ code: string; messageId: string; receivedAt: string }>;
398
+ }
399
+
400
+ export interface HealthJourneyJournalContext {
401
+ sideEffect<T>(params: {
402
+ stepId: string;
403
+ kind: string;
404
+ idempotencyKey: string;
405
+ run: () => Promise<T>;
406
+ }): Promise<T>;
407
+ }
408
+
409
+ export interface HealthJourneyEventContext {
410
+ /**
411
+ * Record an operation-level health outcome that was proven by the journey but
412
+ * not emitted by a direct `ctx.gateway.execute()` call, such as a recovery or
413
+ * manual-review assertion. This is intentionally narrow; it is not a generic
414
+ * event bus.
415
+ */
416
+ operation(params: {
417
+ operationId: string;
418
+ status: "ok" | "degraded" | "down" | "unknown" | "not_reached";
419
+ stepId?: string;
420
+ label?: string;
421
+ error?: string;
422
+ latencyMs?: number;
423
+ statusCode?: number;
424
+ metadata?: Record<string, unknown>;
425
+ }): Promise<void>;
426
+ }
427
+
428
+ export interface HealthJourneyRunContext {
429
+ attemptId: string;
430
+ providerId: string;
431
+ journeyId: string;
432
+ gateway: HealthJourneyGatewayContext;
433
+ sms: HealthJourneySmsContext;
434
+ journal: HealthJourneyJournalContext;
435
+ state: ProviderRuntimeState;
436
+ event: HealthJourneyEventContext;
437
+ signal: AbortSignal;
438
+ secrets: Record<string, string | undefined>;
439
+ }
440
+
441
+ export type HealthJourneyManualTriggerPolicy =
442
+ | { enabled: false; reason?: string }
443
+ | {
444
+ enabled: true;
445
+ requiresAcknowledgement: boolean;
446
+ risk: "read_only" | "writes_external_state" | "sms_or_payment";
447
+ /** ISO 8601 duration. Minimum time between manual executions. */
448
+ minManualInterval: Iso8601Duration;
449
+ publicRationale: string;
450
+ };
451
+
452
+ export interface HealthJourneyRunResult {
453
+ status?: "ok" | "degraded" | "down" | "unknown";
454
+ label?: string;
455
+ metadata?: Record<string, unknown>;
456
+ }
457
+
458
+ export interface HealthJourneyDefinition {
459
+ id: string;
460
+ title?: string;
461
+ description?: string;
462
+ schedule: HealthJourneySchedule;
463
+ coversOperations: readonly [string, ...string[]];
464
+ timeout?: Iso8601Duration;
465
+ cooldown?: Iso8601Duration;
466
+ smsMatchers?: readonly SmsOtpMatcherDefinition[];
467
+ requiredSecrets?: readonly string[];
468
+ manualTrigger?: HealthJourneyManualTriggerPolicy;
469
+ steps: readonly [HealthJourneyStep, ...HealthJourneyStep[]];
470
+ run?: (
471
+ ctx: HealthJourneyRunContext,
472
+ ) => Promise<HealthJourneyRunResult | undefined>;
473
+ }
474
+
87
475
  /**
88
476
  * Health-check authoring surface owned by `@apifuse/provider-sdk`.
89
477
  *
@@ -95,17 +483,14 @@ export interface OperationRelationships {
95
483
  * See `openspec/changes/enforce-sdk-operation-health-suite/design.md` §D1.
96
484
  */
97
485
 
98
- /** Polling intervals supported by the health-monitor runtime. */
99
- export type ProbeInterval =
100
- | "30s"
101
- | "1m"
102
- | "3m"
103
- | "5m"
104
- | "15m"
105
- | "30m"
106
- | "1h"
107
- | "24h";
486
+ /** Polling interval duration accepted by the health-monitor runtime. */
487
+ export type ProbeInterval = ms.StringValue;
108
488
 
489
+ /**
490
+ * Common probe interval examples retained for discoverability/backwards
491
+ * compatibility. This list is not exhaustive; any positive `ms`-style duration
492
+ * string accepted by `@types/ms` (for example `2m`, `8h`, or `1 day`) is valid.
493
+ */
109
494
  export const PROBE_INTERVALS: readonly ProbeInterval[] = [
110
495
  "30s",
111
496
  "1m",
@@ -114,9 +499,16 @@ export const PROBE_INTERVALS: readonly ProbeInterval[] = [
114
499
  "15m",
115
500
  "30m",
116
501
  "1h",
502
+ "2h",
503
+ "8h",
117
504
  "24h",
118
505
  ] as const;
119
506
 
507
+ export const HEALTH_CHECK_TIMEOUT_MS_MIN = 1;
508
+ export const HEALTH_CHECK_TIMEOUT_MS_MAX = 60_000;
509
+ export const HEALTH_CHECK_DEGRADED_THRESHOLD_MS_MIN = 1;
510
+ export const HEALTH_CHECK_DEGRADED_THRESHOLD_MS_MAX = 60_000;
511
+
120
512
  /**
121
513
  * Context passed to a `HealthCheckCase.assertions` lambda.
122
514
  * `data` is typed against the operation's declared output schema (TOutput).
@@ -128,6 +520,28 @@ export interface HealthCheckAssertionContext<TOutput = unknown> {
128
520
  readonly status: number;
129
521
  /** Wall-clock duration of the operation invocation, in milliseconds. */
130
522
  readonly durationMs: number;
523
+ /** Optional provider response metadata such as cache hit/stale flags. */
524
+ readonly meta?: Record<string, unknown>;
525
+ }
526
+
527
+ export interface HealthCheckInputPreparationContext<TInput = unknown> {
528
+ readonly providerId: string;
529
+ readonly operationId: string;
530
+ readonly input: TInput;
531
+ readonly connectionId?: string;
532
+ readonly gateway: {
533
+ execute: (
534
+ providerId: string,
535
+ operationId: string,
536
+ input: unknown,
537
+ options?: { connectionId?: string },
538
+ ) => Promise<{
539
+ status: number;
540
+ duration: number;
541
+ data: unknown;
542
+ meta?: Record<string, unknown>;
543
+ }>;
544
+ };
131
545
  }
132
546
 
133
547
  /**
@@ -156,6 +570,14 @@ export interface HealthCheckCase<TInput = unknown, TOutput = unknown> {
156
570
  description?: string;
157
571
  /** Input passed to the operation handler for this case. */
158
572
  input: TInput;
573
+ /**
574
+ * Optional runtime input preparation hook for volatile probes. Use this when
575
+ * the durable probe input must be derived from a live read-only operation
576
+ * immediately before the checked operation executes.
577
+ */
578
+ prepareInput?: (
579
+ ctx: HealthCheckInputPreparationContext<TInput>,
580
+ ) => TInput | Promise<TInput>;
159
581
  /**
160
582
  * Assertion executed against the operation's response and timing.
161
583
  *
@@ -175,6 +597,8 @@ export interface HealthCheckCase<TInput = unknown, TOutput = unknown> {
175
597
  | Promise<HealthCheckCaseResult>;
176
598
  /** Override per-case degradation threshold (ms); falls back to the suite default. */
177
599
  degradedThresholdMs?: number;
600
+ /** Override per-case timeout in milliseconds; falls back to the suite/provider/runtime default. */
601
+ timeoutMs?: number;
178
602
  /** Expected outcome for "negative" cases (e.g., expecting a degraded baseline). Default: `"ok"`. */
179
603
  expectedStatus?: "ok" | "degraded";
180
604
  /** Runtime gate (env-driven); if returns false the case is skipped & logged. */
@@ -190,6 +614,8 @@ export interface HealthCheckSuite<TInput = unknown, TOutput = unknown> {
190
614
  interval: ProbeInterval;
191
615
  /** Per-case timeout in milliseconds. Default: 30000. */
192
616
  timeoutMs?: number;
617
+ /** Default degradation threshold for cases in this suite. Default: runtime threshold. */
618
+ degradedThresholdMs?: number;
193
619
  /** Non-empty list of cases. Empty arrays are rejected at definition time. */
194
620
  cases: [
195
621
  HealthCheckCase<TInput, TOutput>,
@@ -225,28 +651,49 @@ export interface HealthCheckUnsupported {
225
651
  */
226
652
  export interface ProviderHealthMonitorConfig {
227
653
  /**
228
- * Env-secret key names (e.g., "HEALTH_MONITOR_CATCHTABLE_PHONE") the
654
+ * Provider-wide default probe timeout in milliseconds. Individual
655
+ * `healthCheck.timeoutMs` and `healthCheck.cases[].timeoutMs` values take
656
+ * precedence. Defaults to the monitor runtime default.
657
+ */
658
+ defaultProbeTimeoutMs?: number;
659
+ /**
660
+ * Provider-wide default latency threshold in milliseconds before an
661
+ * otherwise successful probe is marked degraded. Suite/case thresholds take
662
+ * precedence. Defaults to the monitor runtime default.
663
+ */
664
+ defaultDegradedThresholdMs?: number;
665
+ /**
666
+ * Env-secret key names (e.g., "APIFUSE__HEALTH_MONITOR__CATCHTABLE_PHONE") the
229
667
  * synthetic-monitor runtime needs to execute probes that declare
230
668
  * `requiresConnection: true`.
231
669
  */
232
670
  requiredSecrets?: string[];
233
671
  /**
234
- * Runtime probe overrides keyed by probe id (for example
235
- * "catchtable/auth-flow" or "catchtable/waiting-lifecycle"). Use this for
236
- * health-monitor probes that are provider-scoped or cross-operation and
237
- * therefore cannot declare an `OperationDefinition.healthCheck.interval`.
672
+ * Mapping from provider auth ceremony input fields to runtime env-secret
673
+ * names. The health-monitor uses this to create a fresh connection for
674
+ * `requiresConnection: true` probes, then disconnects after execution.
675
+ */
676
+ credentialInputs?: Record<string, string>;
677
+ /**
678
+ * Runtime probe overrides keyed by generated registry probe id. Use this for
679
+ * operation health checks that need a runtime-specific interval or threshold
680
+ * without changing the provider-authored default suite.
238
681
  */
239
682
  probeOverrides?: Record<string, HealthMonitorProbeOverride>;
240
683
  /**
241
684
  * Override the default service account ID for this provider's probes.
242
- * Defaults to the runtime's `APIFUSE_SERVICE_ACCOUNT_ID` env var.
685
+ * Defaults to the runtime's `APIFUSE__HEALTH_MONITOR__SERVICE_ACCOUNT_ID` env var.
243
686
  */
244
687
  serviceAccount?: string;
245
688
  }
246
689
 
247
690
  export interface HealthMonitorProbeOverride {
248
- /** Optional runtime interval override. Must be one of PROBE_INTERVALS. */
691
+ /** Optional runtime interval override as a positive `ms`-style duration string. */
249
692
  interval?: ProbeInterval;
693
+ /** Optional timeout override for generated registry probes. */
694
+ timeoutMs?: number;
695
+ /** Optional degraded threshold override for generated registry probes. */
696
+ degradedThresholdMs?: number;
250
697
  }
251
698
 
252
699
  export interface OperationErrorCode {
@@ -257,10 +704,11 @@ export interface OperationErrorCode {
257
704
  }
258
705
 
259
706
  export interface OperationDocMeta {
260
- title?: string;
261
- description?: string;
262
- summary?: string;
263
- normalizationNotes?: string[];
707
+ titleKey?: ProviderLocaleKeyInput;
708
+ descriptionKey?: ProviderLocaleKeyInput;
709
+ summaryKey?: ProviderLocaleKeyInput;
710
+ markdownKey?: ProviderLocaleKeyInput;
711
+ normalizationNotesKeys?: ProviderLocaleKeyInput[];
264
712
  requestExample?: Record<string, unknown>;
265
713
  responseExample?: unknown;
266
714
  errorCodes?: OperationErrorCode[];
@@ -269,12 +717,12 @@ export interface OperationDocMeta {
269
717
  export type StealthPlatform = "macos" | "windows" | "linux" | "android" | "ios";
270
718
 
271
719
  export type BrowserEngine = "playwright-stealth" | "nodriver" | "selenium-uc";
272
-
273
720
  export interface BrowserOptions {
274
721
  headless?: boolean;
275
722
  stealth?: boolean;
276
723
  proxy?: string;
277
724
  engine?: BrowserEngine;
725
+ requireCdpPool?: boolean;
278
726
  }
279
727
 
280
728
  export interface StealthProfile {
@@ -295,42 +743,260 @@ export type ConnectionMode = AuthMode;
295
743
 
296
744
  export type ProviderReviewed = "first-party" | "community" | "staging";
297
745
 
746
+ export type ProviderAccessVisibility = "public" | "early_access";
747
+
748
+ export type ProviderProxyMode = "disabled" | "optional" | "required";
749
+
750
+ export type ProviderProxyProvider = "smartproxy" | "decodo" | "custom";
751
+
752
+ export type ProviderProxySessionAffinity =
753
+ | "request"
754
+ | "operation"
755
+ | "auth-flow"
756
+ | "connection";
757
+
758
+ export interface ProviderProxyPolicy {
759
+ /**
760
+ * Provider intent only. Transport details such as raw CONNECT, origin
761
+ * certificate verification, and vendor allocator endpoints are SDK-owned.
762
+ */
763
+ mode: ProviderProxyMode;
764
+ provider?: ProviderProxyProvider;
765
+ geo?: {
766
+ /** ISO 3166-1 alpha-2 country code, for example KR or US. */
767
+ country?: Iso3166Alpha2CountryCode;
768
+ subdivision?: string;
769
+ city?: string;
770
+ };
771
+ session?: {
772
+ affinity?: ProviderProxySessionAffinity;
773
+ lifetimeMinutes?: number;
774
+ poolSize?: number;
775
+ };
776
+ }
777
+
778
+ export type ProviderProxyConfig = boolean | ProviderProxyPolicy;
779
+
780
+ export interface ProviderAccessConfig {
781
+ /**
782
+ * Provider-level rollout visibility.
783
+ *
784
+ * - `public`: visible in public docs/catalog/OpenAPI and callable through
785
+ * the existing provider policy stack.
786
+ * - `early_access`: hidden from public discovery and callable only when the
787
+ * active customer organization has a provider-level access grant.
788
+ *
789
+ * This is intentionally provider-level only. It does not alter auth mode,
790
+ * operation schemas, health-check authoring, `openWorld`, or Connection
791
+ * requirements.
792
+ */
793
+ visibility?: ProviderAccessVisibility;
794
+ }
795
+
796
+ export type ProviderLogoSource = "asset" | "monogram" | "none";
797
+
798
+ export type ProviderLogoProfile =
799
+ | {
800
+ source: "asset";
801
+ path: string;
802
+ /**
803
+ * Absolute, customer-renderable URL emitted by discovery projections.
804
+ * Provider source definitions may omit this and let the registry projection
805
+ * derive it from the committed public asset path.
806
+ */
807
+ url?: string;
808
+ background?: string;
809
+ }
810
+ | {
811
+ source: "monogram" | "none";
812
+ background?: string;
813
+ fallbackReason: string;
814
+ };
815
+
816
+ export type ProviderPublicConnectionMode =
817
+ | "apifuse_managed"
818
+ | "workspace_enabled"
819
+ | "user_connected"
820
+ | "no_connection_required";
821
+
822
+ export type ProviderSupportLevel = "stable" | "beta" | "experimental";
823
+
824
+ export interface ProviderPublicProfile {
825
+ displayNameKey?: ProviderLocaleKeyInput;
826
+ shortDescriptionKey?: ProviderLocaleKeyInput;
827
+ longDescriptionKey?: ProviderLocaleKeyInput;
828
+ logo?: ProviderLogoProfile;
829
+ category?: string;
830
+ tags?: readonly string[];
831
+ capabilityKeys?: readonly ProviderLocaleKeyInput[];
832
+ examplePromptKeys?: readonly ProviderLocaleKeyInput[];
833
+ setupSummaryKey?: ProviderLocaleKeyInput;
834
+ connectionMode?: ProviderPublicConnectionMode;
835
+ requirementKeys?: readonly ProviderLocaleKeyInput[];
836
+ limitationKeys?: readonly ProviderLocaleKeyInput[];
837
+ availability?: {
838
+ regions?: readonly string[];
839
+ supportLevel?: ProviderSupportLevel;
840
+ };
841
+ /**
842
+ * Brand primary color as a 6-digit hex string (e.g. "#1a73e8").
843
+ * Single source of truth for all provider-specific color expressions
844
+ * (mood wash, monogram fallback, icon tint). The UI derives subtle washes
845
+ * via color-mix; provider definitions do not control mood percentages.
846
+ */
847
+ primaryColor?: string;
848
+ }
849
+
298
850
  export interface ProviderMeta {
299
851
  displayName: string;
300
- description?: string;
852
+ displayNameKey?: ProviderLocaleKeyInput;
853
+ descriptionKey: ProviderLocaleKeyInput;
301
854
  category: string;
302
- tags?: string[];
855
+ tags?: readonly string[];
303
856
  icon?: string;
304
- docTitle?: string;
305
- docDescription?: string;
306
- docSummary?: string;
307
- normalizationNotes?: string[];
857
+ docTitleKey?: ProviderLocaleKeyInput;
858
+ docDescriptionKey?: ProviderLocaleKeyInput;
859
+ docSummaryKey?: ProviderLocaleKeyInput;
860
+ docMarkdownKey?: ProviderLocaleKeyInput;
861
+ normalizationNotesKeys?: readonly ProviderLocaleKeyInput[];
308
862
  environment?: "staging";
309
863
  purpose?: string;
864
+ purposeKey?: ProviderLocaleKeyInput;
865
+ publicProfile?: ProviderPublicProfile;
866
+ contract?: {
867
+ publicSchemaFieldNames?: "normalized";
868
+ };
869
+ }
870
+
871
+ export type RequestParamPrimitive =
872
+ | string
873
+ | number
874
+ | boolean
875
+ | null
876
+ | undefined;
877
+ export type RequestParamValue =
878
+ | RequestParamPrimitive
879
+ | readonly RequestParamPrimitive[];
880
+ export type RequestParams = Record<string, RequestParamValue>;
881
+
882
+ export const HttpRetryPreset = {
883
+ Off: "off",
884
+ TransportTransient: "transport_transient",
885
+ SafeRead: "safe_read",
886
+ AggressiveRead: "aggressive_read",
887
+ RateLimitAware: "rate_limit_aware",
888
+ } as const;
889
+ export type HttpRetryPreset =
890
+ (typeof HttpRetryPreset)[keyof typeof HttpRetryPreset];
891
+
892
+ export const HttpRetryJitter = {
893
+ None: "none",
894
+ Full: "full",
895
+ Equal: "equal",
896
+ } as const;
897
+ export type HttpRetryJitter =
898
+ (typeof HttpRetryJitter)[keyof typeof HttpRetryJitter];
899
+
900
+ export const HttpRetryDelayStrategy = {
901
+ Fixed: "fixed",
902
+ Exponential: "exponential",
903
+ } as const;
904
+ export type HttpRetryDelayStrategy =
905
+ (typeof HttpRetryDelayStrategy)[keyof typeof HttpRetryDelayStrategy];
906
+
907
+ export const HttpRetryAfterPolicy = {
908
+ Ignore: "ignore",
909
+ /** Honor Retry-After up to maxDelayMs. */
910
+ Respect: "respect",
911
+ /** Honor Retry-After but also cap it to the SDK-computed backoff delay. */
912
+ Cap: "cap",
913
+ } as const;
914
+ export type HttpRetryAfterPolicy =
915
+ (typeof HttpRetryAfterPolicy)[keyof typeof HttpRetryAfterPolicy];
916
+
917
+ export const HttpRetryUnsafeMethodPolicy = {
918
+ Reject: "reject",
919
+ AllowExplicitUnsafe: "allow_explicit_unsafe",
920
+ } as const;
921
+ export type HttpRetryUnsafeMethodPolicy =
922
+ (typeof HttpRetryUnsafeMethodPolicy)[keyof typeof HttpRetryUnsafeMethodPolicy];
923
+
924
+ export interface HttpRetryOptions {
925
+ preset?: HttpRetryPreset;
926
+ /** Total logical ctx.http attempts, including the first attempt. */
927
+ attempts?: number;
928
+ methods?: readonly HttpMethod[];
929
+ statusCodes?: readonly number[];
930
+ errorCodes?: readonly string[];
931
+ delayStrategy?: HttpRetryDelayStrategy;
932
+ baseDelayMs?: number;
933
+ maxDelayMs?: number;
934
+ jitter?: HttpRetryJitter;
935
+ retryAfter?: HttpRetryAfterPolicy;
936
+ unsafeMethodPolicy?: HttpRetryUnsafeMethodPolicy;
937
+ }
938
+
939
+ export interface HttpRetrySummary {
940
+ attempts: number;
941
+ retries: number;
942
+ preset?: HttpRetryPreset;
943
+ transport: "native";
944
+ lastErrorCode?: string;
945
+ lastStatus?: number;
310
946
  }
311
947
 
312
948
  export interface RequestOptions {
313
949
  headers?: Record<string, string>;
314
- params?: Record<string, string>;
950
+ params?: RequestParams;
315
951
  proxy?: string;
316
952
  timeout?: number;
953
+ /**
954
+ * Defaults to true. Set to false when callers need to inspect upstream
955
+ * non-2xx bodies themselves instead of converting them to TransportError.
956
+ */
957
+ throwOnHttpError?: boolean;
958
+ retry?: boolean | HttpRetryPreset | HttpRetryOptions;
317
959
  }
318
960
 
319
- export interface TlsFetchOptions extends RequestOptions {
320
- method?: string;
961
+ export type HttpMethod =
962
+ | "HEAD"
963
+ | "head"
964
+ | "GET"
965
+ | "get"
966
+ | "POST"
967
+ | "post"
968
+ | "PUT"
969
+ | "put"
970
+ | "DELETE"
971
+ | "delete"
972
+ | "OPTIONS"
973
+ | "options"
974
+ | "TRACE"
975
+ | "trace"
976
+ | "PATCH"
977
+ | "patch";
978
+
979
+ export interface StealthFetchOptions extends RequestOptions {
980
+ method?: HttpMethod;
321
981
  body?: string | Buffer;
982
+ redirect?: "follow" | "manual" | "error";
983
+ /**
984
+ * Offsets policy-managed proxy pool selection for caller-managed retries.
985
+ * Use when a request receives an upstream challenge page rather than a
986
+ * transport error, so the next logical retry does not restart at the same
987
+ * operation-affinity proxy.
988
+ */
989
+ proxyAttemptOffset?: number;
990
+ /** Override the configured browser-like stealth profile for this request. */
322
991
  profile?: string;
323
992
  /**
324
- * Defaults to true. Set to false when callers need to inspect upstream
325
- * non-2xx bodies themselves instead of converting them to TransportError.
993
+ * Stealth transport certificate controls. Use only for proxy products that
994
+ * terminate CONNECT with a private CA instead of tunneling the origin
995
+ * certificate chain.
326
996
  */
327
- throwOnHttpError?: boolean;
328
- tls?: {
329
- ja3?: string;
330
- h2?: Record<string, unknown>;
997
+ stealth?: {
331
998
  insecureSkipVerify?: boolean;
332
999
  };
333
- headerOrder?: string[];
334
1000
  }
335
1001
 
336
1002
  export interface CookieJar {
@@ -340,9 +1006,20 @@ export interface CookieJar {
340
1006
  find?(predicate: (cookie: string) => boolean): string | undefined;
341
1007
  }
342
1008
 
343
- export interface DeclarativeTlsResponse {
1009
+ export interface StealthSessionCookies extends CookieJar {
1010
+ has(name: string): boolean;
1011
+ setFromCookieStrings(cookieStrings: readonly string[]): void;
1012
+ toHeader(): string;
1013
+ snapshot(): Record<string, string>;
1014
+ restore(cookies: Record<string, string>): void;
1015
+ clear(): void;
1016
+ }
1017
+
1018
+ export interface DeclarativeStealthResponse {
344
1019
  status: number;
345
1020
  ok: boolean;
1021
+ url?: string;
1022
+ redirected?: boolean;
346
1023
  headers: Record<string, string>;
347
1024
  rawHeaders: [string, string][];
348
1025
  body: string;
@@ -350,16 +1027,45 @@ export interface DeclarativeTlsResponse {
350
1027
  tlsInfo?: { protocol?: string; cipher?: string; [key: string]: unknown };
351
1028
  cookies: CookieJar;
352
1029
  json<T>(): Promise<T>;
1030
+ arrayBuffer(): Promise<ArrayBuffer>;
1031
+ bytes(): Promise<Uint8Array>;
353
1032
  }
354
1033
 
355
- export type TlsResponse = DeclarativeTlsResponse;
1034
+ export type StealthResponse = DeclarativeStealthResponse;
356
1035
 
357
1036
  export type RequestWithMethodOptions = RequestOptions & {
358
1037
  method?: string;
1038
+ body?: unknown;
359
1039
  };
360
1040
 
361
- export interface TlsSession {
362
- fetch(url: string, options?: TlsFetchOptions): Promise<TlsResponse>;
1041
+ export interface StealthRedirectHop {
1042
+ url: string;
1043
+ status: number;
1044
+ method: string;
1045
+ location?: string;
1046
+ nextUrl?: string;
1047
+ }
1048
+
1049
+ export interface StealthRedirectRunOptions
1050
+ extends Omit<StealthFetchOptions, "redirect"> {
1051
+ url: string;
1052
+ maxHops?: number;
1053
+ stopWhen?: (hop: StealthRedirectHop) => boolean | Promise<boolean>;
1054
+ }
1055
+
1056
+ export interface StealthRedirectRunResult {
1057
+ final: StealthResponse;
1058
+ hops: StealthRedirectHop[];
1059
+ reason: "completed" | "stopped" | "max_hops" | "missing_location" | "loop";
1060
+ cookies: Record<string, string>;
1061
+ }
1062
+
1063
+ export interface StealthSession {
1064
+ fetch(url: string, options?: StealthFetchOptions): Promise<StealthResponse>;
1065
+ cookies: StealthSessionCookies;
1066
+ redirects: {
1067
+ run(options: StealthRedirectRunOptions): Promise<StealthRedirectRunResult>;
1068
+ };
363
1069
  close(): void;
364
1070
  }
365
1071
 
@@ -369,6 +1075,9 @@ export interface ApiFuseResponse<T> {
369
1075
  requestId: string;
370
1076
  duration: number;
371
1077
  cached?: boolean;
1078
+ stale?: boolean;
1079
+ cache?: ProviderCacheResponseMeta;
1080
+ retry?: HttpRetrySummary;
372
1081
  };
373
1082
  }
374
1083
 
@@ -381,6 +1090,37 @@ export interface HttpResponse<T = unknown> {
381
1090
  text(): Promise<string>;
382
1091
  }
383
1092
 
1093
+ export interface HttpStreamResponse {
1094
+ status: number;
1095
+ ok: boolean;
1096
+ headers: Record<string, string>;
1097
+ body: ReadableStream<Uint8Array>;
1098
+ bytes(): AsyncIterable<Uint8Array>;
1099
+ textChunks(): AsyncIterable<string>;
1100
+ lines(): AsyncIterable<string>;
1101
+ }
1102
+
1103
+ export interface SseMessage {
1104
+ event: string;
1105
+ data: string;
1106
+ id?: string;
1107
+ retry?: number;
1108
+ json<T = unknown>(): T;
1109
+ }
1110
+
1111
+ export interface ProviderStreamEvent<TData = unknown> {
1112
+ event: string;
1113
+ data: TData;
1114
+ id?: string;
1115
+ retry?: number;
1116
+ }
1117
+
1118
+ export type OperationHandlerResult<TOutput> =
1119
+ | TOutput
1120
+ | Response
1121
+ | ReadableStream<Uint8Array>
1122
+ | AsyncIterable<ProviderStreamEvent>;
1123
+
384
1124
  export interface HttpClient {
385
1125
  request(url: string, opts?: RequestWithMethodOptions): Promise<HttpResponse>;
386
1126
  get(url: string, options?: RequestOptions): Promise<HttpResponse>;
@@ -395,18 +1135,142 @@ export interface HttpClient {
395
1135
  options?: RequestOptions,
396
1136
  ): Promise<HttpResponse>;
397
1137
  delete(url: string, options?: RequestOptions): Promise<HttpResponse>;
1138
+ stream(
1139
+ url: string,
1140
+ options?: RequestWithMethodOptions,
1141
+ ): Promise<HttpStreamResponse>;
1142
+ sse(
1143
+ url: string,
1144
+ options?: RequestWithMethodOptions,
1145
+ ): Promise<AsyncIterable<SseMessage>>;
1146
+ }
1147
+
1148
+ export interface ProviderCacheKeyOptions {
1149
+ /**
1150
+ * Additional field names to omit from stable key material. The SDK always
1151
+ * omits known secret-bearing names such as serviceKey, authorization,
1152
+ * cookie, token, password, and secret.
1153
+ */
1154
+ redactFields?: string[];
1155
+ }
1156
+
1157
+ export interface ProviderCacheGetOrSetOptions {
1158
+ /** Freshness TTL. A fresh hit returns without calling the loader. */
1159
+ ttlMs: number;
1160
+ /**
1161
+ * Optional stale window after ttlMs. If the loader fails while the entry is
1162
+ * still inside this window, stale data is returned and marked stale.
1163
+ */
1164
+ staleIfErrorMs?: number;
1165
+ /** Optional jitter applied to writes to avoid synchronized expiry. */
1166
+ jitterPct?: number;
1167
+ }
1168
+
1169
+ export interface ProviderCacheLookupMeta {
1170
+ key: string;
1171
+ hit: boolean;
1172
+ stale: boolean;
1173
+ ageMs?: number;
1174
+ source: "redis" | "memory" | "loader";
398
1175
  }
399
1176
 
400
- export interface TlsClient {
401
- fetch(url: string, options?: TlsFetchOptions): Promise<TlsResponse>;
402
- createSession(opts?: { profile?: string }): TlsSession;
1177
+ export interface ProviderCacheResult<T> {
1178
+ value: T;
1179
+ meta: ProviderCacheLookupMeta;
1180
+ }
1181
+
1182
+ export interface ProviderCacheResponseMeta {
1183
+ hit: boolean;
1184
+ stale: boolean;
1185
+ keys: string[];
1186
+ source?: "redis" | "memory" | "loader" | "mixed";
1187
+ }
1188
+
1189
+ export interface ProviderCache {
1190
+ key(
1191
+ namespace: string,
1192
+ parts: unknown,
1193
+ options?: ProviderCacheKeyOptions,
1194
+ ): string;
1195
+ get<T = unknown>(key: string): Promise<ProviderCacheResult<T> | null>;
1196
+ set<T = unknown>(
1197
+ key: string,
1198
+ value: T,
1199
+ options: ProviderCacheGetOrSetOptions,
1200
+ ): Promise<void>;
1201
+ delete(key: string): Promise<void>;
1202
+ getOrSet<T = unknown>(
1203
+ key: string,
1204
+ loader: () => Promise<T>,
1205
+ options: ProviderCacheGetOrSetOptions,
1206
+ ): Promise<ProviderCacheResult<T>>;
1207
+ responseMeta(): ProviderCacheResponseMeta | undefined;
1208
+ }
1209
+
1210
+ export interface StealthClient {
1211
+ fetch(url: string, options?: StealthFetchOptions): Promise<StealthResponse>;
1212
+ createSession(opts?: { profile?: string }): StealthSession;
1213
+ close?(): void;
403
1214
  }
404
1215
 
405
1216
  export interface BrowserClient {
406
1217
  readonly engine: BrowserEngine;
407
- newPage(): Promise<unknown>;
1218
+ close?(): Promise<void>;
1219
+ newPage(): Promise<BrowserPage>;
1220
+ rawPage(): Promise<BrowserPage>;
1221
+ withIsolatedContext<T>(
1222
+ handler: (page: BrowserPage) => Promise<T>,
1223
+ ): Promise<T>;
1224
+ solveChallenge(
1225
+ request: BrowserChallengeRequest,
1226
+ ): Promise<BrowserChallengeResult>;
408
1227
  }
409
1228
 
1229
+ export interface BrowserLocator {
1230
+ click(): Promise<void>;
1231
+ fill(text: string): Promise<void>;
1232
+ textContent(): Promise<string | null>;
1233
+ waitFor(options?: { timeout?: number }): Promise<void>;
1234
+ }
1235
+
1236
+ export interface BrowserFrame {
1237
+ id: string;
1238
+ name?: string;
1239
+ parentId?: string;
1240
+ url(): Promise<string>;
1241
+ title(): Promise<string>;
1242
+ content(): Promise<string>;
1243
+ evaluate<T>(fn: string | (() => T)): Promise<T>;
1244
+ locator(selector: string): BrowserLocator;
1245
+ }
1246
+
1247
+ export interface BrowserPage extends BrowserFrame {
1248
+ close(): Promise<void>;
1249
+ fill(selector: string, text: string): Promise<void>;
1250
+ goto(url: string): Promise<void>;
1251
+ pageId?: string;
1252
+ screenshot(options?: { fullPage?: boolean }): Promise<Buffer>;
1253
+ click(selector: string): Promise<void>;
1254
+ type(selector: string, text: string): Promise<void>;
1255
+ waitForSelector(
1256
+ selector: string,
1257
+ options?: { timeout?: number },
1258
+ ): Promise<void>;
1259
+ frames(): Promise<BrowserFrame[]>;
1260
+ }
1261
+
1262
+ export type BrowserChallengeRequest = {
1263
+ type: "recaptcha";
1264
+ siteKey?: string;
1265
+ timeout?: number;
1266
+ };
1267
+
1268
+ export type BrowserChallengeResult = {
1269
+ type: BrowserChallengeRequest["type"];
1270
+ solved: boolean;
1271
+ frameUrl?: string;
1272
+ };
1273
+
410
1274
  export type TraceAttributeValue = string | number | boolean;
411
1275
 
412
1276
  export interface TraceSpan {
@@ -462,6 +1326,107 @@ export interface ProviderRequestContext {
462
1326
  headers: Record<string, string>;
463
1327
  }
464
1328
 
1329
+ export interface ProviderChoiceBindingOptions {
1330
+ connection?: boolean;
1331
+ credentialKeys?: readonly string[];
1332
+ }
1333
+
1334
+ export type ProviderChoiceStorageOptions =
1335
+ | {
1336
+ readonly mode: "inline";
1337
+ }
1338
+ | {
1339
+ readonly mode: "server";
1340
+ readonly namespace: string;
1341
+ readonly state?: ProviderRuntimeState;
1342
+ readonly ttl?: ProviderStateDurationString;
1343
+ readonly maxEntries: number;
1344
+ readonly maxValueBytes: number;
1345
+ readonly unavailable?: "reject";
1346
+ }
1347
+ | {
1348
+ readonly mode: "auto";
1349
+ readonly namespace: string;
1350
+ readonly state?: ProviderRuntimeState;
1351
+ readonly ttl?: ProviderStateDurationString;
1352
+ readonly maxInlineBytes: number;
1353
+ readonly maxEntries: number;
1354
+ readonly maxValueBytes: number;
1355
+ readonly unavailable?: "reject";
1356
+ };
1357
+
1358
+ export interface ProviderChoiceIssueOptions<
1359
+ TPayload extends Record<string, unknown>,
1360
+ > {
1361
+ prefix: string;
1362
+ purpose: string;
1363
+ payload: TPayload;
1364
+ ttlMs: number;
1365
+ nowMs?: number;
1366
+ bind?: ProviderChoiceBindingOptions;
1367
+ storage?: ProviderChoiceStorageOptions;
1368
+ }
1369
+
1370
+ export interface ProviderChoiceParseOptions {
1371
+ token: string;
1372
+ prefix: string;
1373
+ purpose: string;
1374
+ ttlMs?: number;
1375
+ nowMs?: number;
1376
+ futureToleranceMs?: number;
1377
+ bind?: ProviderChoiceBindingOptions;
1378
+ storage?: ProviderChoiceStorageOptions;
1379
+ }
1380
+
1381
+ export interface ProviderChoiceContext {
1382
+ issue<TPayload extends Record<string, unknown>>(
1383
+ options: ProviderChoiceIssueOptions<TPayload> & {
1384
+ readonly storage?: { readonly mode: "inline" };
1385
+ },
1386
+ ): string;
1387
+ issue<TPayload extends Record<string, unknown>>(
1388
+ options: ProviderChoiceIssueOptions<TPayload> & {
1389
+ readonly storage: Extract<
1390
+ ProviderChoiceStorageOptions,
1391
+ { readonly mode: "server" }
1392
+ >;
1393
+ },
1394
+ ): Promise<string>;
1395
+ issue<TPayload extends Record<string, unknown>>(
1396
+ options: ProviderChoiceIssueOptions<TPayload> & {
1397
+ readonly storage: Extract<
1398
+ ProviderChoiceStorageOptions,
1399
+ { readonly mode: "auto" }
1400
+ >;
1401
+ },
1402
+ ): string | Promise<string>;
1403
+ issue<TPayload extends Record<string, unknown>>(
1404
+ options: ProviderChoiceIssueOptions<TPayload>,
1405
+ ): string | Promise<string>;
1406
+ parse(
1407
+ options: ProviderChoiceParseOptions & {
1408
+ readonly storage?: { readonly mode: "inline" };
1409
+ },
1410
+ ): Record<string, unknown>;
1411
+ parse(
1412
+ options: ProviderChoiceParseOptions & {
1413
+ readonly storage: Extract<
1414
+ ProviderChoiceStorageOptions,
1415
+ { readonly mode: "server" }
1416
+ >;
1417
+ },
1418
+ ): Promise<Record<string, unknown>>;
1419
+ parse(
1420
+ options: ProviderChoiceParseOptions & {
1421
+ readonly storage: Extract<
1422
+ ProviderChoiceStorageOptions,
1423
+ { readonly mode: "auto" }
1424
+ >;
1425
+ },
1426
+ ): Record<string, unknown> | Promise<Record<string, unknown>>;
1427
+ parse(options: ProviderChoiceParseOptions): Record<string, unknown>;
1428
+ }
1429
+
465
1430
  export interface ContextScratchpad {
466
1431
  get(key: string): unknown;
467
1432
  set(key: string, value: unknown): void;
@@ -476,8 +1441,11 @@ export interface FlowContext {
476
1441
  tenantId: string;
477
1442
  providerId: string;
478
1443
  http: HttpClient;
1444
+ stealth: StealthClient;
479
1445
  env: EnvContext;
1446
+ credential?: CredentialContext;
480
1447
  context: ContextScratchpad;
1448
+ stt: SttContext;
481
1449
  }
482
1450
 
483
1451
  export interface AuthTurn {
@@ -486,23 +1454,104 @@ export interface AuthTurn {
486
1454
  expiresAt?: string;
487
1455
  data?: Record<string, unknown>;
488
1456
  expectedInput?: Record<string, unknown>;
1457
+ /**
1458
+ * @deprecated Compatibility-only materialized provider auth hint.
1459
+ * Provider source must emit hintKey; SDK/server boundaries may materialize
1460
+ * this field from provider locale catalogs for legacy clients.
1461
+ */
489
1462
  hint?: string;
1463
+ /** Provider locale catalog key for the auth turn hint. */
1464
+ hintKey?: ProviderLocaleKeyInput;
490
1465
  timing?: {
491
1466
  suggestedPollIntervalMs?: number;
492
1467
  maxWaitMs?: number;
493
1468
  };
494
1469
  }
495
1470
 
496
- export type AuthFlowHandler = (
1471
+ export type AuthFlowStartHandler = (ctx: FlowContext) => Promise<AuthTurn>;
1472
+
1473
+ export type AuthFlowInputHandler = (
497
1474
  ctx: FlowContext,
498
1475
  input?: Record<string, unknown>,
499
1476
  ) => Promise<AuthTurn>;
500
1477
 
501
1478
  export interface AuthFlowDefinition {
502
- start: AuthFlowHandler;
503
- continue: AuthFlowHandler;
504
- poll?: AuthFlowHandler;
505
- abort?: AuthFlowHandler;
1479
+ start: AuthFlowStartHandler;
1480
+ continue: AuthFlowInputHandler;
1481
+ poll?: AuthFlowStartHandler;
1482
+ abort?: AuthFlowStartHandler;
1483
+ refresh?: AuthFlowInputHandler;
1484
+ }
1485
+
1486
+ export type ProviderStateDurationString =
1487
+ | `${number}${"ms" | "s" | "m" | "h" | "d"}`
1488
+ | `PT${string}`;
1489
+
1490
+ export interface StateNamespaceOptions {
1491
+ /** Default TTL used when a write omits ttl. Required to avoid unbounded state. */
1492
+ defaultTtl: ProviderStateDurationString;
1493
+ /** Maximum allowed TTL; writes are rejected when they exceed this policy. */
1494
+ maxTtl: ProviderStateDurationString;
1495
+ /** Maximum number of live entries in this namespace scope. */
1496
+ maxEntries: number;
1497
+ /** Maximum JSON-encoded value size in bytes. */
1498
+ maxValueBytes: number;
1499
+ }
1500
+
1501
+ export interface StateWriteOptions {
1502
+ ttl?: ProviderStateDurationString;
1503
+ }
1504
+
1505
+ export interface StateValue<T = unknown> {
1506
+ key: string;
1507
+ value: T;
1508
+ version: number;
1509
+ expiresAt: string;
1510
+ createdAt: string;
1511
+ updatedAt: string;
1512
+ }
1513
+
1514
+ export type StateCasResult<T = unknown> =
1515
+ | { ok: true; value: StateValue<T> }
1516
+ | { ok: false; current: StateValue<T> | null };
1517
+
1518
+ export interface ProviderStateNamespace {
1519
+ list<T = unknown>(options?: {
1520
+ limit?: number;
1521
+ /** Optional literal key prefix used for scoped recovery scans. */
1522
+ prefix?: string;
1523
+ }): Promise<StateValue<T>[]>;
1524
+ get<T = unknown>(key: string): Promise<StateValue<T> | null>;
1525
+ set<T = unknown>(
1526
+ key: string,
1527
+ value: T,
1528
+ options?: StateWriteOptions,
1529
+ ): Promise<StateValue<T>>;
1530
+ patch<T extends Record<string, unknown>>(
1531
+ key: string,
1532
+ partial: Partial<T>,
1533
+ options?: StateWriteOptions,
1534
+ ): Promise<StateValue<T>>;
1535
+ compareAndSet<T = unknown>(
1536
+ key: string,
1537
+ expectedVersion: number,
1538
+ value: T,
1539
+ options?: StateWriteOptions,
1540
+ ): Promise<StateCasResult<T>>;
1541
+ delete(key: string): Promise<void>;
1542
+ increment(
1543
+ key: string,
1544
+ field: string,
1545
+ delta?: number,
1546
+ options?: StateWriteOptions,
1547
+ ): Promise<StateValue<Record<string, unknown>>>;
1548
+ }
1549
+
1550
+ export interface ProviderRuntimeState {
1551
+ namespace(
1552
+ name: string,
1553
+ options: StateNamespaceOptions,
1554
+ ): ProviderStateNamespace;
506
1555
  }
507
1556
 
508
1557
  export interface ProviderContext {
@@ -510,10 +1559,14 @@ export interface ProviderContext {
510
1559
  credential: CredentialContext;
511
1560
  request?: ProviderRequestContext;
512
1561
  http: HttpClient;
513
- tls: TlsClient;
1562
+ cache: ProviderCache;
1563
+ state: ProviderRuntimeState;
1564
+ stealth: StealthClient;
514
1565
  browser: BrowserClient;
515
1566
  trace: TraceContext;
516
1567
  auth: AuthContext;
1568
+ stt: SttContext;
1569
+ choice: ProviderChoiceContext;
517
1570
  }
518
1571
 
519
1572
  export interface AuthConfig {
@@ -537,29 +1590,59 @@ export interface ContextDeclaration {
537
1590
  keys: string[];
538
1591
  }
539
1592
 
1593
+ export type OperationLifecycle = "stable" | "beta" | "deprecated" | "removed";
1594
+
1595
+ export interface OperationDeprecationMetadata {
1596
+ announcedAt: string;
1597
+ removalAfter: string;
1598
+ replacement?: string;
1599
+ migrationGuide: string;
1600
+ }
1601
+
1602
+ export interface OperationContractMetadata {
1603
+ /**
1604
+ * Callable operation contract version. Defaults to 1.0.0 for the clean
1605
+ * pre-GA baseline; it intentionally does not fall back to provider.version.
1606
+ */
1607
+ version?: string;
1608
+ lifecycle?: OperationLifecycle;
1609
+ deprecation?: OperationDeprecationMetadata;
1610
+ }
1611
+
540
1612
  export interface OperationDefinition<
541
1613
  TInput extends SchemaLike = SchemaLike,
542
1614
  TOutput extends SchemaLike = SchemaLike,
543
1615
  > {
544
- description?: string;
1616
+ descriptionKey?: ProviderLocaleKeyInput;
545
1617
  docs?: OperationDocMeta;
546
- whenToUse?: string[];
547
- whenNotToUse?: string[];
1618
+ whenToUseKeys?: readonly ProviderLocaleKeyInput[];
1619
+ whenNotToUseKeys?: readonly ProviderLocaleKeyInput[];
548
1620
  derivations?: Record<string, string>;
549
- inputExamples?: OperationInputExample[];
1621
+ inputExamples?: readonly OperationInputExample[];
550
1622
  annotations?: OperationAnnotations;
551
- tags?: string[];
1623
+ contract?: OperationContractMetadata;
1624
+ tags?: readonly string[];
552
1625
  relatedOperations?: OperationRelationships;
1626
+ toolRouter?: OperationToolRouterMetadata;
1627
+ observability?: OperationObservabilityConfig;
1628
+ transport?: OperationTransport;
1629
+ retryOnAuthRefresh?: boolean;
553
1630
  input: TInput;
554
1631
  output: TOutput;
555
1632
  handler(
556
1633
  ctx: ProviderContext,
557
1634
  input: InferSchemaOutput<TInput>,
558
- ): Promise<InferSchemaOutput<TOutput>>;
1635
+ ):
1636
+ | OperationHandlerResult<InferSchemaOutput<TOutput>>
1637
+ | Promise<OperationHandlerResult<InferSchemaOutput<TOutput>>>;
559
1638
  fixtures?: {
560
1639
  request: InferSchemaOutput<TInput>;
561
1640
  response: InferSchemaOutput<TOutput>;
562
1641
  };
1642
+ upstream?: {
1643
+ baseUrl?: string;
1644
+ proxy?: boolean | ProviderProxyPolicy;
1645
+ };
563
1646
  hints?: Record<string, string>;
564
1647
  healthCheck?: HealthCheckSuite<
565
1648
  InferSchemaOutput<TInput>,
@@ -577,16 +1660,19 @@ export interface ProviderDefinition {
577
1660
  profile: string;
578
1661
  platform: StealthPlatform;
579
1662
  };
580
- proxy?: boolean;
1663
+ proxy?: ProviderProxyConfig;
1664
+ stt?: ProviderSttConfig;
581
1665
  browser?: {
582
1666
  engine: BrowserEngine;
583
1667
  };
584
1668
  auth?: AuthConfig;
585
1669
  reviewed?: ProviderReviewed;
1670
+ access?: ProviderAccessConfig;
586
1671
  secrets?: ProviderSecretDeclaration[];
587
1672
  credential?: CredentialDeclaration;
588
1673
  context?: ContextDeclaration;
589
1674
  meta: ProviderMeta;
590
1675
  operations: Record<string, OperationDefinition<SchemaLike, SchemaLike>>;
591
1676
  healthMonitor?: ProviderHealthMonitorConfig;
1677
+ healthJourneys?: readonly HealthJourneyDefinition[];
592
1678
  }