@apifuse/provider-sdk 2.2.0-beta.2 → 2.2.0-beta.21

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 (291) hide show
  1. package/AUTHORING.md +487 -0
  2. package/CHANGELOG.md +90 -0
  3. package/README.md +49 -3
  4. package/SUBMISSION.md +1 -1
  5. package/bin/apifuse-check.ts +44 -59
  6. package/bin/apifuse-create.ts +1 -1
  7. package/bin/apifuse-dev.ts +27 -52
  8. package/bin/apifuse-pack-check.ts +14 -0
  9. package/bin/apifuse-pack-smoke.ts +36 -81
  10. package/bin/apifuse-pack-types.ts +305 -0
  11. package/bin/apifuse-perf.ts +45 -127
  12. package/bin/apifuse-record.ts +659 -111
  13. package/bin/apifuse-submit-check.ts +546 -48
  14. package/bin/apifuse-sync-assets.ts +117 -0
  15. package/bin/apifuse.ts +1 -1
  16. package/bin/submit-check-delimited-text.ts +50 -0
  17. package/bin/submit-check-xml-semantics.ts +204 -0
  18. package/bin/submit-check-xml.ts +134 -0
  19. package/dist/auth-turn/index.d.ts +3 -3
  20. package/dist/auth.d.ts +2 -2
  21. package/dist/auth.js +9 -18
  22. package/dist/ceremonies/index.d.ts +9 -1
  23. package/dist/ceremonies/index.js +65 -18
  24. package/dist/cli/commands.d.ts +1 -1
  25. package/dist/cli/commands.js +8 -0
  26. package/dist/cli/create.d.ts +3 -0
  27. package/dist/cli/create.js +34 -35
  28. package/dist/cli/prompt-assets.d.ts +80 -0
  29. package/dist/cli/prompt-assets.js +743 -0
  30. package/dist/cli/templates/provider/AGENTS.md.tpl +17 -8
  31. package/dist/config/loader.d.ts +176 -8
  32. package/dist/config/loader.js +424 -95
  33. package/dist/contract-serialization.d.ts +2 -2
  34. package/dist/contract-serialization.js +3 -6
  35. package/dist/contract-types.d.ts +2 -2
  36. package/dist/contract.d.ts +3 -3
  37. package/dist/contract.js +4 -6
  38. package/dist/define.d.ts +9 -1
  39. package/dist/define.js +304 -119
  40. package/dist/dev.d.ts +1 -1
  41. package/dist/dev.js +1 -1
  42. package/dist/error-resolution.d.ts +2 -0
  43. package/dist/error-resolution.js +90 -0
  44. package/dist/errors.d.ts +22 -1
  45. package/dist/errors.js +88 -0
  46. package/dist/fixture-sanitization.d.ts +26 -0
  47. package/dist/fixture-sanitization.js +216 -0
  48. package/dist/i18n/catalog.d.ts +2 -2
  49. package/dist/i18n/catalog.js +4 -10
  50. package/dist/i18n/index.d.ts +2 -2
  51. package/dist/i18n/index.js +2 -2
  52. package/dist/i18n/keys.d.ts +2 -2
  53. package/dist/index.d.ts +46 -42
  54. package/dist/index.js +41 -37
  55. package/dist/lint.d.ts +1 -1
  56. package/dist/lint.js +8 -15
  57. package/dist/native-address.d.ts +43 -0
  58. package/dist/native-address.js +281 -0
  59. package/dist/native-egress-policy.d.ts +31 -0
  60. package/dist/native-egress-policy.js +288 -0
  61. package/dist/observability.d.ts +5 -2
  62. package/dist/observability.js +48 -1
  63. package/dist/provider.d.ts +12 -11
  64. package/dist/provider.js +10 -9
  65. package/dist/public-schema-field-lint.d.ts +1 -1
  66. package/dist/recipes/gov-api.js +1 -1
  67. package/dist/runtime/auth-flow.d.ts +2 -1
  68. package/dist/runtime/auth-flow.js +4 -3
  69. package/dist/runtime/browser.d.ts +1 -1
  70. package/dist/runtime/browser.js +15 -29
  71. package/dist/runtime/cache.d.ts +1 -1
  72. package/dist/runtime/cache.js +4 -8
  73. package/dist/runtime/choice.d.ts +1 -1
  74. package/dist/runtime/choice.js +31 -35
  75. package/dist/runtime/credential.d.ts +1 -1
  76. package/dist/runtime/credential.js +1 -1
  77. package/dist/runtime/env.d.ts +1 -1
  78. package/dist/runtime/executor.d.ts +1 -1
  79. package/dist/runtime/executor.js +31 -4
  80. package/dist/runtime/http.d.ts +2 -2
  81. package/dist/runtime/http.js +387 -47
  82. package/dist/runtime/insights.d.ts +1 -1
  83. package/dist/runtime/insights.js +6 -13
  84. package/dist/runtime/instrumentation.d.ts +2 -2
  85. package/dist/runtime/instrumentation.js +345 -22
  86. package/dist/runtime/keyring.js +1 -1
  87. package/dist/runtime/namespace.js +1 -1
  88. package/dist/runtime/native-network.d.ts +127 -0
  89. package/dist/runtime/native-network.js +1298 -0
  90. package/dist/runtime/otlp.d.ts +1 -1
  91. package/dist/runtime/perf.d.ts +1 -1
  92. package/dist/runtime/provider.d.ts +1 -1
  93. package/dist/runtime/provider.js +1 -2
  94. package/dist/runtime/proxy-errors.d.ts +1 -1
  95. package/dist/runtime/proxy-errors.js +9 -7
  96. package/dist/runtime/proxy-nodemaven.d.ts +56 -0
  97. package/dist/runtime/proxy-nodemaven.js +146 -0
  98. package/dist/runtime/proxy-retry-policy.d.ts +2 -2
  99. package/dist/runtime/proxy-retry-policy.js +2 -2
  100. package/dist/runtime/proxy-telemetry.d.ts +2 -1
  101. package/dist/runtime/proxy-telemetry.js +55 -52
  102. package/dist/runtime/redirects.d.ts +29 -0
  103. package/dist/runtime/redirects.js +36 -0
  104. package/dist/runtime/redis.d.ts +1 -1
  105. package/dist/runtime/redis.js +2 -4
  106. package/dist/runtime/request-options.d.ts +68 -1
  107. package/dist/runtime/request-options.js +548 -0
  108. package/dist/runtime/secrets.d.ts +27 -0
  109. package/dist/runtime/secrets.js +51 -0
  110. package/dist/runtime/state.d.ts +2 -2
  111. package/dist/runtime/state.js +238 -26
  112. package/dist/runtime/stealth.d.ts +5 -3
  113. package/dist/runtime/stealth.js +423 -143
  114. package/dist/runtime/stt.d.ts +1 -1
  115. package/dist/runtime/stt.js +11 -15
  116. package/dist/runtime/trace.d.ts +2 -2
  117. package/dist/runtime/trace.js +2 -4
  118. package/dist/runtime/waterfall.d.ts +1 -1
  119. package/dist/schema.d.ts +1 -1
  120. package/dist/schema.js +7 -15
  121. package/dist/serve.d.ts +1 -1
  122. package/dist/serve.js +1 -1
  123. package/dist/server/index.d.ts +7 -7
  124. package/dist/server/index.js +6 -6
  125. package/dist/server/self-test-input-tokens.d.ts +2 -1
  126. package/dist/server/self-test-input-tokens.js +18 -14
  127. package/dist/server/self-test-redaction.d.ts +1 -1
  128. package/dist/server/self-test-redaction.js +1 -1
  129. package/dist/server/self-test.d.ts +104 -3
  130. package/dist/server/self-test.js +673 -115
  131. package/dist/server/serve.d.ts +116 -4
  132. package/dist/server/serve.js +799 -128
  133. package/dist/server/types.d.ts +34 -9
  134. package/dist/server/types.js +8 -1
  135. package/dist/stateful/errors.d.ts +14 -0
  136. package/dist/stateful/errors.js +14 -0
  137. package/dist/stateful/http-provider-event-emitter.d.ts +40 -0
  138. package/dist/stateful/http-provider-event-emitter.js +237 -0
  139. package/dist/stateful/http-session-owner-registry.d.ts +44 -0
  140. package/dist/stateful/http-session-owner-registry.js +210 -0
  141. package/dist/stateful/index.d.ts +18 -0
  142. package/dist/stateful/index.js +18 -0
  143. package/dist/stateful/provider-event-delivery-failures.d.ts +32 -0
  144. package/dist/stateful/provider-event-delivery-failures.js +43 -0
  145. package/dist/stateful/provider-event-pipeline-metrics.d.ts +46 -0
  146. package/dist/stateful/provider-event-pipeline-metrics.js +48 -0
  147. package/dist/stateful/provider-event-pipeline.d.ts +50 -0
  148. package/dist/stateful/provider-event-pipeline.js +1 -0
  149. package/dist/stateful/provider-events.d.ts +101 -0
  150. package/dist/stateful/provider-events.js +289 -0
  151. package/dist/stateful/session-key.d.ts +15 -0
  152. package/dist/stateful/session-key.js +86 -0
  153. package/dist/stateful/stateful-provider-adapter-context.d.ts +5 -0
  154. package/dist/stateful/stateful-provider-adapter-context.js +42 -0
  155. package/dist/stateful/stateful-provider-adapter-metrics.d.ts +15 -0
  156. package/dist/stateful/stateful-provider-adapter-metrics.js +21 -0
  157. package/dist/stateful/stateful-provider-adapter.d.ts +98 -0
  158. package/dist/stateful/stateful-provider-adapter.js +287 -0
  159. package/dist/stateful/stateful-provider-observability.d.ts +62 -0
  160. package/dist/stateful/stateful-provider-observability.js +161 -0
  161. package/dist/stateful/stateful-provider-owner-forwarder.d.ts +41 -0
  162. package/dist/stateful/stateful-provider-owner-forwarder.js +215 -0
  163. package/dist/stateful/stateful-provider-runtime-context.d.ts +32 -0
  164. package/dist/stateful/stateful-provider-runtime-context.js +60 -0
  165. package/dist/stateful/stateful-provider-runtime-executor.d.ts +34 -0
  166. package/dist/stateful/stateful-provider-runtime-executor.js +52 -0
  167. package/dist/stateful/stateful-provider-session-routing.d.ts +71 -0
  168. package/dist/stateful/stateful-provider-session-routing.js +353 -0
  169. package/dist/stateful/stateful-provider-session-runtime.d.ts +98 -0
  170. package/dist/stateful/stateful-provider-session-runtime.js +245 -0
  171. package/dist/stateful-signing.d.ts +18 -0
  172. package/dist/stateful-signing.js +27 -0
  173. package/dist/stealth/profiles.d.ts +1 -1
  174. package/dist/stealth/profiles.js +5 -14
  175. package/dist/stream-evidence.d.ts +74 -0
  176. package/dist/stream-evidence.js +785 -0
  177. package/dist/stream.d.ts +1 -1
  178. package/dist/testing/index.d.ts +2 -2
  179. package/dist/testing/index.js +2 -2
  180. package/dist/testing/run.d.ts +32 -2
  181. package/dist/testing/run.js +478 -28
  182. package/dist/types.d.ts +342 -14
  183. package/dist/types.js +1 -0
  184. package/dist/user-input.d.ts +30 -0
  185. package/dist/user-input.js +66 -0
  186. package/package.json +16 -5
  187. package/src/auth-turn/index.ts +1 -1
  188. package/src/auth.ts +28 -86
  189. package/src/ceremonies/index.ts +103 -78
  190. package/src/cli/commands.ts +10 -0
  191. package/src/cli/create.ts +42 -35
  192. package/src/cli/prompt-assets.ts +865 -0
  193. package/src/cli/templates/provider/AGENTS.md.tpl +17 -8
  194. package/src/config/loader.ts +652 -204
  195. package/src/contract-serialization.ts +5 -11
  196. package/src/contract-types.ts +2 -2
  197. package/src/contract.ts +12 -28
  198. package/src/define.ts +499 -498
  199. package/src/dev.ts +4 -9
  200. package/src/error-resolution.ts +91 -0
  201. package/src/errors.ts +110 -5
  202. package/src/fixture-sanitization.ts +247 -0
  203. package/src/i18n/catalog.ts +10 -32
  204. package/src/i18n/index.ts +2 -2
  205. package/src/i18n/keys.ts +5 -11
  206. package/src/index.ts +112 -42
  207. package/src/lint.ts +88 -152
  208. package/src/native-address.ts +340 -0
  209. package/src/native-egress-policy.ts +358 -0
  210. package/src/observability.ts +51 -1
  211. package/src/provider.ts +66 -11
  212. package/src/public-schema-field-lint.ts +7 -33
  213. package/src/recipes/gov-api.ts +2 -5
  214. package/src/runtime/auth-flow.ts +7 -7
  215. package/src/runtime/browser.ts +64 -187
  216. package/src/runtime/cache.ts +20 -67
  217. package/src/runtime/choice.ts +79 -132
  218. package/src/runtime/credential.ts +2 -2
  219. package/src/runtime/env.ts +1 -1
  220. package/src/runtime/executor.ts +43 -20
  221. package/src/runtime/http.ts +494 -57
  222. package/src/runtime/insights.ts +15 -53
  223. package/src/runtime/instrumentation.ts +495 -66
  224. package/src/runtime/keyring.ts +7 -19
  225. package/src/runtime/namespace.ts +2 -7
  226. package/src/runtime/native-network.ts +1686 -0
  227. package/src/runtime/otlp.ts +12 -23
  228. package/src/runtime/perf.ts +1 -1
  229. package/src/runtime/provider.ts +4 -9
  230. package/src/runtime/proxy-errors.ts +29 -42
  231. package/src/runtime/proxy-nodemaven.ts +221 -0
  232. package/src/runtime/proxy-retry-policy.ts +3 -3
  233. package/src/runtime/proxy-telemetry.ts +79 -77
  234. package/src/runtime/redirects.ts +66 -0
  235. package/src/runtime/redis.ts +4 -12
  236. package/src/runtime/request-options.ts +679 -9
  237. package/src/runtime/secrets.ts +64 -0
  238. package/src/runtime/state.ts +353 -133
  239. package/src/runtime/stealth.ts +505 -154
  240. package/src/runtime/stt.ts +38 -94
  241. package/src/runtime/trace.ts +14 -44
  242. package/src/runtime/waterfall.ts +5 -18
  243. package/src/schema.ts +23 -84
  244. package/src/serve.ts +1 -1
  245. package/src/server/index.ts +29 -7
  246. package/src/server/self-test-input-tokens.ts +29 -14
  247. package/src/server/self-test-redaction.ts +2 -2
  248. package/src/server/self-test.ts +857 -132
  249. package/src/server/serve.ts +1151 -328
  250. package/src/server/types.ts +12 -13
  251. package/src/stateful/README.md +146 -0
  252. package/src/stateful/errors.ts +23 -0
  253. package/src/stateful/http-provider-event-emitter.ts +314 -0
  254. package/src/stateful/http-session-owner-registry.ts +306 -0
  255. package/src/stateful/index.ts +18 -0
  256. package/src/stateful/provider-event-delivery-failures.ts +80 -0
  257. package/src/stateful/provider-event-pipeline-metrics.ts +95 -0
  258. package/src/stateful/provider-event-pipeline.ts +61 -0
  259. package/src/stateful/provider-events.ts +462 -0
  260. package/src/stateful/session-key.ts +111 -0
  261. package/src/stateful/stateful-provider-adapter-context.ts +59 -0
  262. package/src/stateful/stateful-provider-adapter-metrics.ts +48 -0
  263. package/src/stateful/stateful-provider-adapter.ts +562 -0
  264. package/src/stateful/stateful-provider-observability.ts +261 -0
  265. package/src/stateful/stateful-provider-owner-forwarder.ts +287 -0
  266. package/src/stateful/stateful-provider-runtime-context.ts +92 -0
  267. package/src/stateful/stateful-provider-runtime-executor.ts +96 -0
  268. package/src/stateful/stateful-provider-session-routing.ts +555 -0
  269. package/src/stateful/stateful-provider-session-runtime.ts +403 -0
  270. package/src/stateful-signing.ts +46 -0
  271. package/src/stealth/profiles.ts +10 -26
  272. package/src/stream-evidence.ts +988 -0
  273. package/src/stream.ts +8 -19
  274. package/src/testing/index.ts +10 -2
  275. package/src/testing/run.ts +653 -74
  276. package/src/types.ts +408 -28
  277. package/src/user-input.ts +118 -0
  278. package/dist/cli/templates/provider/CLAUDE.md.tpl +0 -1
  279. package/src/cli/templates/provider/CLAUDE.md.tpl +0 -1
  280. /package/dist/cli/templates/provider/{skills → .agents/skills}/fixtures-and-recording/SKILL.md.tpl +0 -0
  281. /package/dist/cli/templates/provider/{skills → .agents/skills}/health-checks-and-fail-closed/SKILL.md.tpl +0 -0
  282. /package/dist/cli/templates/provider/{skills → .agents/skills}/normalization-standards/SKILL.md.tpl +0 -0
  283. /package/dist/cli/templates/provider/{skills → .agents/skills}/pagination-and-counts/SKILL.md.tpl +0 -0
  284. /package/dist/cli/templates/provider/{skills → .agents/skills}/upstream-contract-verification/SKILL.md.tpl +0 -0
  285. /package/dist/cli/templates/provider/{skills → .agents/skills}/upstream-notes/README.md.tpl +0 -0
  286. /package/src/cli/templates/provider/{skills → .agents/skills}/fixtures-and-recording/SKILL.md.tpl +0 -0
  287. /package/src/cli/templates/provider/{skills → .agents/skills}/health-checks-and-fail-closed/SKILL.md.tpl +0 -0
  288. /package/src/cli/templates/provider/{skills → .agents/skills}/normalization-standards/SKILL.md.tpl +0 -0
  289. /package/src/cli/templates/provider/{skills → .agents/skills}/pagination-and-counts/SKILL.md.tpl +0 -0
  290. /package/src/cli/templates/provider/{skills → .agents/skills}/upstream-contract-verification/SKILL.md.tpl +0 -0
  291. /package/src/cli/templates/provider/{skills → .agents/skills}/upstream-notes/README.md.tpl +0 -0
@@ -1,6 +1,6 @@
1
1
  import { createCipheriv, createDecipheriv, createHash, createHmac, randomBytes, timingSafeEqual, } from "node:crypto";
2
- import { assertFreshProviderChoiceIssuedAt, ProviderChoiceTokenError, } from "../choice-token";
3
- import { ProviderError } from "../errors";
2
+ import { assertFreshProviderChoiceIssuedAt, ProviderChoiceTokenError, } from "../choice-token.js";
3
+ import { isProviderError, ProviderError } from "../errors.js";
4
4
  export const PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV = "APIFUSE__PROVIDER_RUNTIME__CHOICE_TOKEN_MASTER_SECRET";
5
5
  const PRIMARY_CHOICE_TOKEN_KID = "v1";
6
6
  const MANAGED_CHOICE_TOKEN_VERSION = 1;
@@ -53,7 +53,7 @@ export function createProviderChoiceContext(options) {
53
53
  });
54
54
  }
55
55
  function parse(parseOptions) {
56
- const [actualPrefix, tokenKid, encodedIv, encryptedPayload, authTag, signature,] = parseManagedChoiceTokenParts(parseOptions.token);
56
+ const [actualPrefix, tokenKid, encodedIv, encryptedPayload, authTag, signature] = parseManagedChoiceTokenParts(parseOptions.token);
57
57
  if (actualPrefix !== parseOptions.prefix ||
58
58
  tokenKid !== kid ||
59
59
  !encodedIv ||
@@ -68,13 +68,7 @@ export function createProviderChoiceContext(options) {
68
68
  purpose: parseOptions.purpose,
69
69
  kid: tokenKid,
70
70
  });
71
- const signedBody = [
72
- parseOptions.prefix,
73
- tokenKid,
74
- encodedIv,
75
- encryptedPayload,
76
- authTag,
77
- ].join(".");
71
+ const signedBody = [parseOptions.prefix, tokenKid, encodedIv, encryptedPayload, authTag].join(".");
78
72
  assertManagedChoiceSignature({
79
73
  signedBody,
80
74
  signature,
@@ -117,13 +111,11 @@ export function createProviderChoiceContext(options) {
117
111
  export function createTestProviderChoiceContext(options) {
118
112
  return createProviderChoiceContext({
119
113
  ...options,
120
- masterSecret: options.masterSecret ??
121
- "apifuse-test-provider-runtime-choice-token-master-secret",
114
+ masterSecret: options.masterSecret ?? "apifuse-test-provider-runtime-choice-token-master-secret",
122
115
  });
123
116
  }
124
117
  function resolveChoiceMasterSecret(options) {
125
- const configured = options.masterSecret ??
126
- options.env?.get(PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV);
118
+ const configured = options.masterSecret ?? options.env?.get(PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV);
127
119
  const trimmed = configured?.trim();
128
120
  if (trimmed)
129
121
  return trimmed;
@@ -165,13 +157,7 @@ function encryptManagedChoiceToken(options) {
165
157
  ]).toString("base64url");
166
158
  const authTag = cipher.getAuthTag().toString("base64url");
167
159
  const encodedIv = iv.toString("base64url");
168
- const signedBody = [
169
- options.prefix,
170
- options.kid,
171
- encodedIv,
172
- encryptedPayload,
173
- authTag,
174
- ].join(".");
160
+ const signedBody = [options.prefix, options.kid, encodedIv, encryptedPayload, authTag].join(".");
175
161
  const signature = createHmac("sha256", options.keys.signing)
176
162
  .update(signedBody)
177
163
  .digest("base64url");
@@ -223,7 +209,25 @@ async function parseServerStoredChoice(options) {
223
209
  storage,
224
210
  contextState: options.contextState,
225
211
  });
226
- const record = await namespace.get(optionsStateKey(options.handle.state_id));
212
+ // Reading a server-stored choice back deserializes a persisted value. A
213
+ // corrupt/undecodable value would otherwise surface as a raw JSON.parse
214
+ // SyntaxError (or another unexpected throwable) that escapes the choice error
215
+ // taxonomy, gets masked as internal_error 500, and is treated as retryable by
216
+ // the hub -> reservation restart loop (2026-07-22 catchtable RCA, candidate A).
217
+ // Convert any non-branded throwable into a branded invalid_payload so it maps
218
+ // to a clean, non-retryable 400. Branded ProviderChoiceTokenError and genuine
219
+ // ProviderError (e.g. Redis-unavailable / state-unavailable) pass through so
220
+ // their category/retryable semantics are preserved.
221
+ let record;
222
+ try {
223
+ record = await namespace.get(optionsStateKey(options.handle.state_id));
224
+ }
225
+ catch (error) {
226
+ if (error instanceof ProviderChoiceTokenError || isProviderError(error)) {
227
+ throw error;
228
+ }
229
+ throw new ProviderChoiceTokenError("invalid_payload", "Provider choice token state payload could not be decoded.");
230
+ }
227
231
  if (!record) {
228
232
  throw new ProviderChoiceTokenError("invalid_payload", "Provider choice token state payload is missing.");
229
233
  }
@@ -345,9 +349,7 @@ function isManagedChoiceEnvelope(value) {
345
349
  typeof value.issued_at_ms === "number" &&
346
350
  "ttl_ms" in value &&
347
351
  typeof value.ttl_ms === "number" &&
348
- (!("binding" in value) ||
349
- value.binding === undefined ||
350
- isChoiceBinding(value.binding)));
352
+ (!("binding" in value) || value.binding === undefined || isChoiceBinding(value.binding)));
351
353
  }
352
354
  function isChoicePayload(value) {
353
355
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
@@ -355,29 +357,23 @@ function isChoicePayload(value) {
355
357
  function isChoiceBinding(value) {
356
358
  if (!value || typeof value !== "object" || Array.isArray(value))
357
359
  return false;
358
- return ((!("connection_hash" in value) ||
359
- typeof value.connection_hash === "string") &&
360
+ return ((!("connection_hash" in value) || typeof value.connection_hash === "string") &&
360
361
  (!("credential_hash" in value) || typeof value.credential_hash === "string"));
361
362
  }
362
363
  function assertManagedChoiceEnvelope(envelope, options) {
363
- if (envelope.provider_id !== options.providerId ||
364
- envelope.purpose !== options.purpose) {
364
+ if (envelope.provider_id !== options.providerId || envelope.purpose !== options.purpose) {
365
365
  throw new ProviderChoiceTokenError("invalid_payload", "Provider choice token payload is invalid.");
366
366
  }
367
367
  assertFreshProviderChoiceIssuedAt(envelope.issued_at_ms, {
368
368
  // Clamp to the issuer's embedded TTL so a caller-supplied value cannot
369
369
  // silently extend token validity past the deadline the issuer intended.
370
- ttlMs: options.ttlMs != null
371
- ? Math.min(options.ttlMs, envelope.ttl_ms)
372
- : envelope.ttl_ms,
370
+ ttlMs: options.ttlMs != null ? Math.min(options.ttlMs, envelope.ttl_ms) : envelope.ttl_ms,
373
371
  nowMs: options.nowMs,
374
372
  futureToleranceMs: options.futureToleranceMs,
375
373
  });
376
374
  }
377
375
  function createChoiceBinding(options) {
378
- const connectionHash = options.options?.connection
379
- ? hashRequiredConnection(options)
380
- : undefined;
376
+ const connectionHash = options.options?.connection ? hashRequiredConnection(options) : undefined;
381
377
  const credentialHash = options.options?.credentialKeys?.length
382
378
  ? hashCredentialKeys(options)
383
379
  : undefined;
@@ -1,4 +1,4 @@
1
- import type { AuthMode, CredentialContext } from "../types";
1
+ import type { AuthMode, CredentialContext } from "../types.js";
2
2
  export interface CreateCredentialContextOptions {
3
3
  allowedKeys?: string[];
4
4
  mode?: AuthMode;
@@ -1,4 +1,4 @@
1
- import { CredentialModeError } from "../errors";
1
+ import { CredentialModeError } from "../errors.js";
2
2
  function getAllowedKeys(allowedKeys, values) {
3
3
  if (allowedKeys) {
4
4
  return allowedKeys;
@@ -1,2 +1,2 @@
1
- import type { EnvContext } from "../types";
1
+ import type { EnvContext } from "../types.js";
2
2
  export declare function createEnvContext(allowedKeys?: string[]): EnvContext;
@@ -1,4 +1,4 @@
1
- import type { ProviderContext, ProviderDefinition } from "../types";
1
+ import type { ProviderContext, ProviderDefinition } from "../types.js";
2
2
  export declare function isStreamingOperation(provider: ProviderDefinition, operationId: string): boolean;
3
3
  /**
4
4
  * Execute a provider operation by calling its handler.
@@ -1,5 +1,7 @@
1
- import { ProviderError, SessionExpiredError } from "../errors";
2
- import { parseSchema } from "../schema";
1
+ import { isSessionExpiredError, isValidationError, ProviderError, SessionExpiredError, ValidationError, } from "../errors.js";
2
+ import { z } from "zod";
3
+ import { parseSchema } from "../schema.js";
4
+ import { assertRequiredSecretsPresent } from "./secrets.js";
3
5
  export function isStreamingOperation(provider, operationId) {
4
6
  const kind = provider.operations[operationId]?.transport?.kind ?? "json";
5
7
  return kind !== "json";
@@ -23,6 +25,12 @@ export async function executeOperation(provider, operationId, ctx, input, _optio
23
25
  fix: `Valid operations: ${Object.keys(provider.operations).join(", ")}`,
24
26
  });
25
27
  }
28
+ // SDK-owned secret presence gate (single source of truth): declared
29
+ // `required: true` secrets are validated here, before input parsing and the
30
+ // handler, so every invocation path (serve /v1, self-test probes, perf,
31
+ // record) fails with the same structured MISSING_SECRET error instead of a
32
+ // handler-specific crash. Providers must not re-check presence locally.
33
+ assertRequiredSecretsPresent(provider, ctx.env);
26
34
  const validatedInput = await parseSchema(operation.input, input, `operations.${operationId}.input`);
27
35
  const execute = () => ctx.trace.span(`handler:${operationId}`, () => Promise.resolve(operation.handler(ctx, validatedInput)));
28
36
  let result;
@@ -39,7 +47,12 @@ export async function executeOperation(provider, operationId, ctx, input, _optio
39
47
  // operation is safe to re-drive after refresh, which we signal by marking
40
48
  // the surfaced error retryable; non-idempotent operations (the default)
41
49
  // stay non-retryable so they are not auto-re-driven. See design.md §4.3 D3.
42
- if (error instanceof SessionExpiredError && operation.retryOnAuthRefresh) {
50
+ // Use the branded guard, not `instanceof`: a handler loaded through a
51
+ // duplicate/published SDK module can throw a correctly branded
52
+ // SessionExpiredError whose constructor identity differs from this
53
+ // executor's, which `instanceof` would miss — dropping the retryable
54
+ // upgrade and stranding an operation that opted into auth refresh.
55
+ if (isSessionExpiredError(error) && operation.retryOnAuthRefresh) {
43
56
  throw new SessionExpiredError(error.message, { retryable: true });
44
57
  }
45
58
  throw error;
@@ -47,5 +60,19 @@ export async function executeOperation(provider, operationId, ctx, input, _optio
47
60
  if (isStreamingOperation(provider, operationId)) {
48
61
  return result;
49
62
  }
50
- return parseSchema(operation.output, result, `operations.${operationId}.output`);
63
+ try {
64
+ return await parseSchema(operation.output, result, `operations.${operationId}.output`);
65
+ }
66
+ catch (cause) {
67
+ if (!(cause instanceof z.ZodError) && !isValidationError(cause)) {
68
+ throw cause;
69
+ }
70
+ throw new ValidationError(`Operation handler output failed schema validation.`, {
71
+ code: "OUTPUT_VALIDATION_FAILED",
72
+ category: "output_validation",
73
+ retryable: false,
74
+ zodError: isValidationError(cause) ? cause.zodError : cause,
75
+ ...(cause instanceof Error ? { cause } : {}),
76
+ });
77
+ }
51
78
  }
@@ -1,5 +1,5 @@
1
- import type { ProxyResolutionOptions } from "../config/loader";
2
- import type { HttpClient, HttpRetrySummary } from "../types";
1
+ import type { ProxyResolutionOptions } from "../config/loader.js";
2
+ import type { HttpClient, HttpRetrySummary } from "../types.js";
3
3
  export type HttpClientOptions = ProxyResolutionOptions & {
4
4
  warn?: (message: string) => void;
5
5
  userAgent?: string;