theorum 0.1.15 → 1.1.3

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 (305) hide show
  1. package/README.md +241 -98
  2. package/esm/mod.d.ts +57 -28
  3. package/esm/mod.js +43 -23
  4. package/esm/src/cli/commands/bench.js +18 -18
  5. package/esm/src/cli/commands/fuzz-canary.d.ts +13 -0
  6. package/esm/src/cli/commands/fuzz-canary.js +191 -0
  7. package/esm/src/cli/commands/fuzz-guardrails.d.ts +3 -5
  8. package/esm/src/cli/commands/fuzz-guardrails.js +4 -581
  9. package/esm/src/cli/commands/guardrails-eval.d.ts +14 -0
  10. package/esm/src/cli/commands/guardrails-eval.js +15 -0
  11. package/esm/src/cli/commands/profile.js +35 -15
  12. package/esm/src/cli/commands/run.d.ts +3 -0
  13. package/esm/src/cli/commands/run.js +23 -32
  14. package/esm/src/cli/commands/test.d.ts +10 -1
  15. package/esm/src/cli/commands/test.js +34 -34
  16. package/esm/src/cli/event-log.d.ts +19 -0
  17. package/esm/src/cli/event-log.js +147 -0
  18. package/esm/src/cli/index.js +57 -11
  19. package/esm/src/cli/matrix/synthesizer.d.ts +10 -12
  20. package/esm/src/cli/matrix/synthesizer.js +45 -118
  21. package/esm/src/guardrails/canary-gate.d.ts +21 -0
  22. package/esm/src/guardrails/canary-gate.js +32 -0
  23. package/esm/src/guardrails/canary.d.ts +34 -0
  24. package/esm/src/guardrails/canary.js +150 -0
  25. package/esm/src/guardrails/corpus/canary-egress-attacks.d.ts +17 -0
  26. package/esm/src/guardrails/corpus/canary-egress-attacks.js +151 -0
  27. package/esm/src/guardrails/corpus/fuzz-inbound.d.ts +11 -0
  28. package/esm/src/guardrails/corpus/fuzz-inbound.js +213 -0
  29. package/esm/src/guardrails/corpus/inbound-payloads.d.ts +10 -0
  30. package/esm/src/guardrails/corpus/inbound-payloads.js +125 -0
  31. package/esm/src/guardrails/corpus/live-attacks.d.ts +20 -0
  32. package/esm/src/guardrails/corpus/live-attacks.js +231 -0
  33. package/esm/src/guardrails/corpus/mod.d.ts +14 -0
  34. package/esm/src/guardrails/corpus/mod.js +11 -0
  35. package/esm/src/guardrails/corpus/secrets.d.ts +17 -0
  36. package/esm/src/guardrails/corpus/secrets.js +17 -0
  37. package/esm/src/guardrails/corpus/strings.d.ts +28 -0
  38. package/esm/src/guardrails/corpus/strings.js +34 -0
  39. package/esm/src/guardrails/corpus/types.d.ts +38 -0
  40. package/esm/src/guardrails/corpus/types.js +6 -0
  41. package/esm/src/guardrails/egress.d.ts +32 -0
  42. package/esm/src/guardrails/egress.js +87 -0
  43. package/esm/src/guardrails/error.d.ts +14 -23
  44. package/esm/src/guardrails/error.js +87 -76
  45. package/esm/src/guardrails/eval/corpus.d.ts +108 -0
  46. package/esm/src/guardrails/eval/corpus.js +978 -0
  47. package/esm/src/guardrails/eval/mod.d.ts +51 -0
  48. package/esm/src/guardrails/eval/mod.js +133 -0
  49. package/esm/src/guardrails/eval/score.d.ts +66 -0
  50. package/esm/src/guardrails/eval/score.js +114 -0
  51. package/esm/src/guardrails/events.d.ts +25 -0
  52. package/esm/src/guardrails/events.js +56 -0
  53. package/esm/src/guardrails/hits.d.ts +24 -0
  54. package/esm/src/guardrails/hits.js +45 -0
  55. package/esm/src/guardrails/injection.js +28 -5
  56. package/esm/src/guardrails/lexicon.d.ts +39 -0
  57. package/esm/src/guardrails/lexicon.js +200 -0
  58. package/esm/src/guardrails/live-outbound-gate.d.ts +41 -0
  59. package/esm/src/guardrails/live-outbound-gate.js +222 -0
  60. package/esm/src/guardrails/mod.d.ts +30 -6
  61. package/esm/src/guardrails/mod.js +20 -5
  62. package/esm/src/guardrails/network.d.ts +19 -0
  63. package/esm/src/guardrails/network.js +234 -0
  64. package/esm/src/guardrails/policy.d.ts +35 -0
  65. package/esm/src/guardrails/policy.js +50 -0
  66. package/esm/src/guardrails/progressive-yield.d.ts +51 -0
  67. package/esm/src/guardrails/progressive-yield.js +98 -0
  68. package/esm/src/guardrails/quota.d.ts +17 -3
  69. package/esm/src/guardrails/quota.js +18 -4
  70. package/esm/src/guardrails/sanitize.d.ts +45 -19
  71. package/esm/src/guardrails/sanitize.js +177 -94
  72. package/esm/src/guardrails/sensitive.js +2 -1
  73. package/esm/src/guardrails/serialize.d.ts +35 -0
  74. package/esm/src/guardrails/serialize.js +58 -0
  75. package/esm/src/guardrails/testing.d.ts +17 -0
  76. package/esm/src/guardrails/testing.js +13 -0
  77. package/esm/src/guardrails/theorum-error.d.ts +12 -0
  78. package/esm/src/guardrails/theorum-error.js +15 -0
  79. package/esm/src/guardrails/tool-directives.d.ts +48 -0
  80. package/esm/src/guardrails/tool-directives.js +124 -0
  81. package/esm/src/guardrails/tool-result.d.ts +93 -0
  82. package/esm/src/guardrails/tool-result.js +276 -0
  83. package/esm/src/guardrails/types.d.ts +291 -0
  84. package/esm/src/guardrails/types.js +72 -0
  85. package/esm/src/host/client-turn.d.ts +19 -0
  86. package/esm/src/host/client-turn.js +36 -0
  87. package/esm/src/host/mint-trace.d.ts +1 -1
  88. package/esm/src/host/mod.d.ts +5 -3
  89. package/esm/src/host/mod.js +4 -3
  90. package/esm/src/kernel/auth/crypto.d.ts +42 -0
  91. package/esm/src/kernel/auth/crypto.js +106 -0
  92. package/esm/src/kernel/auth/mod.d.ts +11 -0
  93. package/esm/src/kernel/auth/mod.js +11 -0
  94. package/esm/src/kernel/auth/oauth.d.ts +47 -0
  95. package/esm/src/kernel/auth/oauth.js +278 -0
  96. package/esm/src/kernel/auth/types.d.ts +133 -0
  97. package/esm/src/kernel/auth/types.js +13 -0
  98. package/esm/src/kernel/engine/delta.d.ts +24 -2
  99. package/esm/src/kernel/engine/delta.js +478 -39
  100. package/esm/src/kernel/engine/live-inbound.d.ts +21 -0
  101. package/esm/src/kernel/engine/live-inbound.js +31 -0
  102. package/esm/src/kernel/engine/live-ingress.d.ts +19 -0
  103. package/esm/src/kernel/engine/live-ingress.js +47 -0
  104. package/esm/src/kernel/engine/repair.js +13 -12
  105. package/esm/src/kernel/engine/runner/gates.d.ts +1 -1
  106. package/esm/src/kernel/engine/runner/gates.js +130 -43
  107. package/esm/src/kernel/engine/runner/mod.d.ts +6 -4
  108. package/esm/src/kernel/engine/runner/mod.js +192 -53
  109. package/esm/src/kernel/engine/runner/schema-validation.js +3 -3
  110. package/esm/src/kernel/engine/runner/stages.d.ts +39 -0
  111. package/esm/src/kernel/engine/runner/stages.js +89 -0
  112. package/esm/src/kernel/engine/runner/state.d.ts +31 -0
  113. package/esm/src/kernel/engine/runner/steps.d.ts +1 -1
  114. package/esm/src/kernel/engine/runner/steps.js +244 -43
  115. package/esm/src/kernel/engine/runner/stream.d.ts +9 -3
  116. package/esm/src/kernel/engine/runner/stream.js +140 -44
  117. package/esm/src/kernel/engine/session/mod.d.ts +25 -0
  118. package/esm/src/kernel/engine/session/mod.js +557 -0
  119. package/esm/src/kernel/interaction-parts.d.ts +14 -0
  120. package/esm/src/kernel/interaction-parts.js +23 -0
  121. package/esm/src/kernel/mod.d.ts +21 -10
  122. package/esm/src/kernel/mod.js +11 -8
  123. package/esm/src/kernel/profile-graph.d.ts +159 -0
  124. package/esm/src/kernel/profile-graph.js +156 -0
  125. package/esm/src/kernel/registry/attachments.d.ts +12 -10
  126. package/esm/src/kernel/registry/attachments.js +33 -27
  127. package/esm/src/kernel/registry/catalog.d.ts +25 -24
  128. package/esm/src/kernel/registry/catalog.js +60 -101
  129. package/esm/src/kernel/registry/ingress.d.ts +9 -4
  130. package/esm/src/kernel/registry/ingress.js +97 -75
  131. package/esm/src/kernel/registry/profile-outputs.d.ts +4 -0
  132. package/esm/src/kernel/registry/profile-outputs.js +8 -0
  133. package/esm/src/kernel/registry/profiles.d.ts +55 -12
  134. package/esm/src/kernel/registry/profiles.js +413 -73
  135. package/esm/src/kernel/registry/provider-request.js +13 -7
  136. package/esm/src/kernel/registry/resolve.d.ts +8 -8
  137. package/esm/src/kernel/registry/resolve.js +169 -154
  138. package/esm/src/kernel/registry/schemas.js +1 -1
  139. package/esm/src/kernel/registry/sole-model.d.ts +8 -0
  140. package/esm/src/kernel/registry/sole-model.js +10 -0
  141. package/esm/src/kernel/registry/system-prompt.d.ts +10 -0
  142. package/esm/src/kernel/registry/system-prompt.js +40 -0
  143. package/esm/src/kernel/registry/system-role.d.ts +8 -0
  144. package/esm/src/kernel/registry/system-role.js +14 -0
  145. package/esm/src/kernel/registry/vault.d.ts +12 -7
  146. package/esm/src/kernel/registry/vault.js +32 -10
  147. package/esm/src/kernel/schema.d.ts +231 -0
  148. package/esm/src/kernel/schema.js +607 -0
  149. package/esm/src/kernel/stages.d.ts +175 -0
  150. package/esm/src/kernel/stages.js +476 -0
  151. package/esm/src/kernel/stop.d.ts +78 -19
  152. package/esm/src/kernel/stop.js +51 -16
  153. package/esm/src/kernel/tools/events.d.ts +41 -0
  154. package/esm/src/kernel/tools/events.js +71 -0
  155. package/esm/src/kernel/tools/execute.d.ts +84 -0
  156. package/esm/src/kernel/tools/execute.js +614 -0
  157. package/esm/src/kernel/tools/harness.d.ts +8 -0
  158. package/esm/src/kernel/tools/harness.js +46 -0
  159. package/esm/src/kernel/tools/invoke.d.ts +10 -0
  160. package/esm/src/kernel/tools/invoke.js +101 -0
  161. package/esm/src/kernel/tools/mod.d.ts +13 -0
  162. package/esm/src/kernel/tools/mod.js +11 -0
  163. package/esm/src/kernel/tools/permission.d.ts +15 -0
  164. package/esm/src/kernel/tools/permission.js +47 -0
  165. package/esm/src/kernel/tools/project.d.ts +12 -0
  166. package/esm/src/kernel/tools/project.js +36 -0
  167. package/esm/src/kernel/tools/registry.d.ts +23 -0
  168. package/esm/src/kernel/tools/registry.js +81 -0
  169. package/esm/src/kernel/tools/remote.d.ts +94 -0
  170. package/esm/src/kernel/tools/remote.js +577 -0
  171. package/esm/src/kernel/tools/resolve.d.ts +39 -0
  172. package/esm/src/kernel/tools/resolve.js +283 -0
  173. package/esm/src/kernel/tools/schema.d.ts +15 -0
  174. package/esm/src/kernel/tools/schema.js +176 -0
  175. package/esm/src/kernel/tools/stage-run.d.ts +105 -0
  176. package/esm/src/kernel/tools/stage-run.js +155 -0
  177. package/esm/src/kernel/tools/types.d.ts +394 -0
  178. package/esm/src/kernel/tools/types.js +9 -0
  179. package/esm/src/kernel/types.d.ts +540 -256
  180. package/esm/src/kernel/util/find-last.d.ts +2 -0
  181. package/esm/src/kernel/util/find-last.js +10 -0
  182. package/esm/src/observability/destinations.d.ts +31 -0
  183. package/esm/src/observability/destinations.js +67 -0
  184. package/esm/src/observability/mod.d.ts +10 -3
  185. package/esm/src/observability/mod.js +6 -2
  186. package/esm/src/observability/policy.d.ts +27 -0
  187. package/esm/src/observability/policy.js +80 -0
  188. package/esm/src/observability/resolve-policy.d.ts +16 -0
  189. package/esm/src/observability/resolve-policy.js +64 -0
  190. package/esm/src/observability/trace-attach.d.ts +8 -4
  191. package/esm/src/observability/trace-attach.js +50 -29
  192. package/esm/src/observability/trace-record.d.ts +23 -13
  193. package/esm/src/observability/trace-record.js +96 -39
  194. package/esm/src/observability/trace-sink.d.ts +19 -0
  195. package/esm/src/observability/trace-sink.js +10 -0
  196. package/esm/src/observability/trace-usage.d.ts +10 -3
  197. package/esm/src/observability/trace-usage.js +70 -17
  198. package/esm/src/observability/trace.d.ts +18 -7
  199. package/esm/src/observability/trace.js +34 -17
  200. package/esm/src/observability/types.d.ts +113 -0
  201. package/esm/src/observability/types.js +11 -0
  202. package/esm/src/presets/google/speech-voices.d.ts +11 -0
  203. package/esm/src/presets/google/speech-voices.js +41 -0
  204. package/esm/src/presets/google.d.ts +36 -24
  205. package/esm/src/presets/google.js +50 -63
  206. package/esm/src/presets/mod.d.ts +2 -2
  207. package/esm/src/presets/mod.js +1 -1
  208. package/esm/src/providers/create-provider.d.ts +20 -17
  209. package/esm/src/providers/create-provider.js +72 -26
  210. package/esm/src/providers/google/interactions/framing.d.ts +23 -0
  211. package/esm/src/providers/google/interactions/framing.js +269 -0
  212. package/esm/src/providers/google/interactions/mod.d.ts +7 -0
  213. package/esm/src/providers/google/interactions/mod.js +7 -0
  214. package/esm/src/providers/google/interactions/stream.d.ts +83 -0
  215. package/esm/src/providers/google/interactions/stream.js +588 -0
  216. package/esm/src/providers/google/keys.d.ts +26 -0
  217. package/esm/src/providers/{keys.js → google/keys.js} +19 -31
  218. package/esm/src/providers/google/live/framing.d.ts +49 -0
  219. package/esm/src/providers/google/live/framing.js +552 -0
  220. package/esm/src/providers/google/live/openapi-schema.d.ts +6 -0
  221. package/esm/src/providers/google/live/openapi-schema.js +46 -0
  222. package/esm/src/providers/google/live/session.d.ts +25 -0
  223. package/esm/src/providers/google/live/session.js +134 -0
  224. package/esm/src/providers/google/live/stream.d.ts +45 -0
  225. package/esm/src/providers/google/live/stream.js +214 -0
  226. package/esm/src/providers/google/urls.d.ts +6 -0
  227. package/esm/src/providers/google/urls.js +6 -0
  228. package/esm/src/providers/local/local.d.ts +30 -0
  229. package/esm/src/providers/{local.js → local/local.js} +66 -126
  230. package/esm/src/providers/local/mod.d.ts +9 -0
  231. package/esm/src/providers/local/mod.js +9 -0
  232. package/esm/src/providers/mod.d.ts +6 -3
  233. package/esm/src/providers/mod.js +3 -1
  234. package/esm/src/providers/openrouter/cache-control.d.ts +24 -0
  235. package/esm/src/providers/openrouter/cache-control.js +23 -0
  236. package/esm/src/providers/openrouter/chat.d.ts +107 -0
  237. package/esm/src/providers/{openrouter.js → openrouter/chat.js} +117 -231
  238. package/esm/src/providers/openrouter/image.d.ts +34 -0
  239. package/esm/src/providers/openrouter/image.js +275 -0
  240. package/esm/src/providers/openrouter/openai/chat-payload.d.ts +24 -0
  241. package/esm/src/providers/openrouter/openai/chat-payload.js +82 -0
  242. package/esm/src/providers/openrouter/openai/compat.d.ts +53 -0
  243. package/esm/src/providers/openrouter/openai/compat.js +213 -0
  244. package/esm/src/providers/openrouter/openai/image-payload.d.ts +18 -0
  245. package/esm/src/providers/openrouter/openai/image-payload.js +90 -0
  246. package/esm/src/providers/openrouter/openai/sdk-messages.d.ts +22 -0
  247. package/esm/src/providers/openrouter/openai/sdk-messages.js +122 -0
  248. package/esm/src/providers/openrouter/resolve-api-key.d.ts +9 -0
  249. package/esm/src/providers/openrouter/resolve-api-key.js +24 -0
  250. package/esm/src/providers/openrouter/speech.d.ts +23 -0
  251. package/esm/src/providers/{speech.js → openrouter/speech.js} +32 -55
  252. package/esm/src/providers/probe.d.ts +1 -0
  253. package/esm/src/providers/probe.js +22 -0
  254. package/esm/src/providers/shared/pcm.d.ts +12 -0
  255. package/esm/src/providers/{pcm.js → shared/pcm.js} +16 -3
  256. package/esm/src/providers/shared/sse.d.ts +18 -0
  257. package/esm/src/providers/shared/sse.js +87 -0
  258. package/esm/src/providers/shared/tool-args.d.ts +17 -0
  259. package/esm/src/providers/shared/tool-args.js +45 -0
  260. package/esm/src/providers/shared/upstream-tap.d.ts +5 -0
  261. package/esm/src/providers/{google-tap.js → shared/upstream-tap.js} +4 -7
  262. package/esm/src/providers/shared/upstream-tape.d.ts +6 -0
  263. package/esm/src/providers/{gemini-tape.js → shared/upstream-tape.js} +12 -22
  264. package/esm/src/providers/types.d.ts +27 -0
  265. package/esm/src/providers/types.js +1 -0
  266. package/package.json +11 -7
  267. package/docs/cli.md +0 -97
  268. package/docs/guardrails.md +0 -178
  269. package/docs/host.md +0 -97
  270. package/docs/kernel.md +0 -404
  271. package/docs/observability.md +0 -105
  272. package/docs/openrouter.md +0 -125
  273. package/docs/presets-google.md +0 -91
  274. package/docs/presets.md +0 -88
  275. package/docs/providers.md +0 -202
  276. package/docs/streaming.md +0 -96
  277. package/esm/src/kernel/engine/boundary.d.ts +0 -10
  278. package/esm/src/kernel/engine/boundary.js +0 -55
  279. package/esm/src/kernel/engine/runner/tools.d.ts +0 -13
  280. package/esm/src/kernel/engine/runner/tools.js +0 -198
  281. package/esm/src/kernel/registry/tools.d.ts +0 -12
  282. package/esm/src/kernel/registry/tools.js +0 -36
  283. package/esm/src/providers/expose-for-tests.d.ts +0 -1
  284. package/esm/src/providers/expose-for-tests.js +0 -25
  285. package/esm/src/providers/gemini-tape.d.ts +0 -2
  286. package/esm/src/providers/google-tap.d.ts +0 -3
  287. package/esm/src/providers/interactions.d.ts +0 -5
  288. package/esm/src/providers/interactions.js +0 -169
  289. package/esm/src/providers/keys.d.ts +0 -19
  290. package/esm/src/providers/local.d.ts +0 -29
  291. package/esm/src/providers/openrouter-mod.d.ts +0 -13
  292. package/esm/src/providers/openrouter-mod.js +0 -12
  293. package/esm/src/providers/openrouter-payload.d.ts +0 -39
  294. package/esm/src/providers/openrouter-payload.js +0 -195
  295. package/esm/src/providers/openrouter.d.ts +0 -15
  296. package/esm/src/providers/pcm.d.ts +0 -7
  297. package/esm/src/providers/provider.d.ts +0 -15
  298. package/esm/src/providers/provider.js +0 -202
  299. package/esm/src/providers/speech.d.ts +0 -23
  300. package/esm/src/providers/sse.d.ts +0 -7
  301. package/esm/src/providers/sse.js +0 -55
  302. package/esm/src/streaming/mod.d.ts +0 -9
  303. package/esm/src/streaming/mod.js +0 -8
  304. /package/esm/src/{streaming → host}/readStreamingJsonStringField.d.ts +0 -0
  305. /package/esm/src/{streaming → host}/readStreamingJsonStringField.js +0 -0
@@ -0,0 +1,47 @@
1
+ /**
2
+ * RFC-compliant OAuth 2.1 discovery and flow orchestration.
3
+ *
4
+ * Implements:
5
+ * - RFC 9728: OAuth 2.0 Protected Resource Metadata
6
+ * - RFC 8414 & OpenID Connect: Authorization Server Metadata
7
+ * - RFC 9207: Authorization Server Issuer Identification
8
+ * - RFC 8707: Resource Indicators
9
+ * - RFC 7636: PKCE (S256)
10
+ *
11
+ * @module
12
+ */
13
+ import type { AuthorizationServerMetadata, CreatePkceFlowOptions, ExchangePkceCodeOptions, ExchangePkceCodeResult, OAuth2Credential, OAuthTokens, PkceFlowResult, ProtectedResourceMetadata, RefreshOAuthTokenOptions } from './types.js';
14
+ /**
15
+ * Discover Protected Resource Metadata (RFC 9728 Section 3).
16
+ * Fetches `/.well-known/oauth-protected-resource`.
17
+ */
18
+ export declare function discoverResourceMetadata(resourceUrl: string, fetchFn?: typeof fetch): Promise<ProtectedResourceMetadata>;
19
+ export declare function discoverAuthServerMetadata(authServerUrl: string, fetchFn?: typeof fetch): Promise<AuthorizationServerMetadata>;
20
+ /**
21
+ * Initiate an OAuth 2.1 PKCE authorization flow statelesssly.
22
+ *
23
+ * Discovers resource & AS metadata (or uses preResolved), generates PKCE code_verifier/code_challenge,
24
+ * and packs the verifier, expected issuer, and resource into an HMAC-signed state token.
25
+ */
26
+ export declare function createOAuthPkceFlow(options: CreatePkceFlowOptions): Promise<PkceFlowResult>;
27
+ /**
28
+ * Validates the authorization response `iss` parameter per RFC 9207 Section 2.4.
29
+ *
30
+ * "The client MUST validate that the 'iss' parameter in the authorization response matches
31
+ * the issuer identifier of the authorization server... using simple string comparison (RFC 3986 Section 6.2.1)."
32
+ */
33
+ export declare function validateIssuer(expectedIssuer: string, receivedIss?: string): void;
34
+ /**
35
+ * Exchange authorization code for access and refresh tokens.
36
+ *
37
+ * Verifies state HMAC, performs RFC 9207 `iss` validation, and posts
38
+ * code_verifier and resource to the token_endpoint.
39
+ */
40
+ export declare function exchangeOAuthPkce(options: ExchangePkceCodeOptions): Promise<ExchangePkceCodeResult>;
41
+ /**
42
+ * Refresh an expired OAuth 2.1 access token.
43
+ */
44
+ export declare function refreshOAuthToken(options: RefreshOAuthTokenOptions): Promise<{
45
+ tokens: OAuthTokens;
46
+ credential: OAuth2Credential;
47
+ }>;
@@ -0,0 +1,278 @@
1
+ /**
2
+ * RFC-compliant OAuth 2.1 discovery and flow orchestration.
3
+ *
4
+ * Implements:
5
+ * - RFC 9728: OAuth 2.0 Protected Resource Metadata
6
+ * - RFC 8414 & OpenID Connect: Authorization Server Metadata
7
+ * - RFC 9207: Authorization Server Issuer Identification
8
+ * - RFC 8707: Resource Indicators
9
+ * - RFC 7636: PKCE (S256)
10
+ *
11
+ * @module
12
+ */
13
+ import { computeCodeChallenge, generateCodeVerifier, sealStatePayload, unsealStatePayload, } from './crypto.js';
14
+ /**
15
+ * Discover Protected Resource Metadata (RFC 9728 Section 3).
16
+ * Fetches `/.well-known/oauth-protected-resource`.
17
+ */
18
+ export async function discoverResourceMetadata(resourceUrl, fetchFn = fetch) {
19
+ const origin = new URL(resourceUrl).origin;
20
+ const metadataUrl = `${origin}/.well-known/oauth-protected-resource`;
21
+ const response = await fetchFn(metadataUrl, {
22
+ headers: { Accept: 'application/json' },
23
+ });
24
+ if (!response.ok) {
25
+ throw new Error(`Failed to discover protected resource metadata at ${metadataUrl} (HTTP ${response.status})`);
26
+ }
27
+ const data = (await response.json());
28
+ const authServers = Array.isArray(data.authorization_servers)
29
+ ? data.authorization_servers
30
+ : [];
31
+ if (authServers.length === 0) {
32
+ throw new Error(`Protected resource metadata at ${metadataUrl} did not declare any authorization_servers`);
33
+ }
34
+ return {
35
+ resource: typeof data.resource === 'string' ? data.resource : resourceUrl,
36
+ authorization_servers: authServers,
37
+ scopes_supported: Array.isArray(data.scopes_supported)
38
+ ? data.scopes_supported
39
+ : undefined,
40
+ bearer_methods_supported: Array.isArray(data.bearer_methods_supported)
41
+ ? data.bearer_methods_supported
42
+ : undefined,
43
+ };
44
+ }
45
+ /**
46
+ * Discover Authorization Server Metadata (RFC 8414 Section 3 & OpenID Connect Discovery 1.0).
47
+ * Queries `/.well-known/oauth-authorization-server` then `/.well-known/openid-configuration`.
48
+ */
49
+ function parseAuthServerMetadata(data, fallbackIssuer) {
50
+ if (typeof data.authorization_endpoint !== 'string' || typeof data.token_endpoint !== 'string') {
51
+ return undefined;
52
+ }
53
+ return {
54
+ issuer: typeof data.issuer === 'string' ? data.issuer : fallbackIssuer,
55
+ authorization_endpoint: data.authorization_endpoint,
56
+ token_endpoint: data.token_endpoint,
57
+ registration_endpoint: typeof data.registration_endpoint === 'string' ? data.registration_endpoint : undefined,
58
+ scopes_supported: Array.isArray(data.scopes_supported)
59
+ ? data.scopes_supported
60
+ : undefined,
61
+ response_types_supported: Array.isArray(data.response_types_supported)
62
+ ? data.response_types_supported
63
+ : undefined,
64
+ grant_types_supported: Array.isArray(data.grant_types_supported)
65
+ ? data.grant_types_supported
66
+ : undefined,
67
+ code_challenge_methods_supported: Array.isArray(data.code_challenge_methods_supported)
68
+ ? data.code_challenge_methods_supported
69
+ : undefined,
70
+ authorization_response_iss_parameter_supported: data.authorization_response_iss_parameter_supported === true,
71
+ client_id_metadata_document_supported: data.client_id_metadata_document_supported === true,
72
+ };
73
+ }
74
+ export async function discoverAuthServerMetadata(authServerUrl, fetchFn = fetch) {
75
+ const base = authServerUrl.replace(/\/$/, '');
76
+ const paths = ['/.well-known/oauth-authorization-server', '/.well-known/openid-configuration'];
77
+ for (const path of paths) {
78
+ try {
79
+ const response = await fetchFn(`${base}${path}`, {
80
+ headers: { Accept: 'application/json' },
81
+ });
82
+ if (!response.ok)
83
+ continue;
84
+ const data = (await response.json());
85
+ const parsed = parseAuthServerMetadata(data, authServerUrl);
86
+ if (parsed)
87
+ return parsed;
88
+ }
89
+ catch {
90
+ // Try next discovery endpoint
91
+ }
92
+ }
93
+ throw new Error(`Failed to discover authorization server metadata for "${authServerUrl}"`); // lexicon-exempt: developer contract / internal diagnostic — not end-user or model copy (P2)
94
+ }
95
+ /**
96
+ * Initiate an OAuth 2.1 PKCE authorization flow statelesssly.
97
+ *
98
+ * Discovers resource & AS metadata (or uses preResolved), generates PKCE code_verifier/code_challenge,
99
+ * and packs the verifier, expected issuer, and resource into an HMAC-signed state token.
100
+ */
101
+ export async function createOAuthPkceFlow(options) {
102
+ const fetchFn = options.fetchFn ?? fetch;
103
+ const pre = options.preResolved;
104
+ let issuer = pre?.issuer;
105
+ let authEndpoint = pre?.authorizationEndpoint;
106
+ let resource = pre?.resource;
107
+ if (!authEndpoint || !issuer) {
108
+ let asUrl = options.resourceServerUrl;
109
+ try {
110
+ // 1. Try RFC 9728 discovery on resource server
111
+ const resourceMeta = await discoverResourceMetadata(options.resourceServerUrl, fetchFn);
112
+ resource = resourceMeta.resource;
113
+ asUrl = resourceMeta.authorization_servers[0];
114
+ }
115
+ catch {
116
+ // If resource discovery fails, treat resourceServerUrl as direct AS URL
117
+ resource = options.resourceServerUrl;
118
+ }
119
+ // 2. Discover AS metadata
120
+ const asMeta = await discoverAuthServerMetadata(asUrl, fetchFn);
121
+ issuer = asMeta.issuer;
122
+ authEndpoint = asMeta.authorization_endpoint;
123
+ }
124
+ // 3. Generate PKCE verifier and S256 challenge
125
+ const codeVerifier = generateCodeVerifier();
126
+ const codeChallenge = await computeCodeChallenge(codeVerifier);
127
+ // 4. Seal stateless state envelope
128
+ const ttl = options.stateTtlMs ?? 10 * 60 * 1000; // 10 mins
129
+ const state = await sealStatePayload({
130
+ codeVerifier,
131
+ expectedIssuer: issuer,
132
+ resource,
133
+ redirectUri: options.redirectUri,
134
+ expiresAt: Date.now() + ttl,
135
+ clientId: options.clientId,
136
+ }, options.signingSecret);
137
+ // 5. Construct authorization URL
138
+ const authUrl = new URL(authEndpoint);
139
+ authUrl.searchParams.set('response_type', 'code');
140
+ authUrl.searchParams.set('client_id', options.clientId);
141
+ authUrl.searchParams.set('redirect_uri', options.redirectUri);
142
+ authUrl.searchParams.set('code_challenge', codeChallenge);
143
+ authUrl.searchParams.set('code_challenge_method', 'S256');
144
+ authUrl.searchParams.set('state', state);
145
+ if (resource) {
146
+ authUrl.searchParams.set('resource', resource);
147
+ }
148
+ if (options.scopes && options.scopes.length > 0) {
149
+ authUrl.searchParams.set('scope', options.scopes.join(' '));
150
+ }
151
+ return {
152
+ authorizationUrl: authUrl.toString(),
153
+ state,
154
+ codeVerifier,
155
+ codeChallenge,
156
+ issuer,
157
+ resource,
158
+ };
159
+ }
160
+ /**
161
+ * Validates the authorization response `iss` parameter per RFC 9207 Section 2.4.
162
+ *
163
+ * "The client MUST validate that the 'iss' parameter in the authorization response matches
164
+ * the issuer identifier of the authorization server... using simple string comparison (RFC 3986 Section 6.2.1)."
165
+ */
166
+ export function validateIssuer(expectedIssuer, receivedIss) {
167
+ if (!receivedIss) {
168
+ // If not provided, allowed only if AS did not support it, but if provided, must match exactly
169
+ return;
170
+ }
171
+ // Simple byte-exact string comparison (no URL normalization per 2026-07-28 spec)
172
+ if (expectedIssuer !== receivedIss) {
173
+ throw new Error(`RFC 9207 Issuer mismatch detected (potential mix-up attack): expected "${expectedIssuer}", received "${receivedIss}"`);
174
+ }
175
+ }
176
+ /**
177
+ * POST a form-encoded token request and parse the response.
178
+ *
179
+ * The authorization-code exchange and the refresh flow differ only in the body
180
+ * they send and the label on a failure, so the transport, the error shape, and
181
+ * the expiry computation live here once.
182
+ */
183
+ async function postTokenRequest(fetchFn, tokenEndpoint, body, failureLabel) {
184
+ const response = await fetchFn(tokenEndpoint, {
185
+ method: 'POST',
186
+ headers: {
187
+ 'Content-Type': 'application/x-www-form-urlencoded',
188
+ Accept: 'application/json',
189
+ },
190
+ body: body.toString(),
191
+ });
192
+ if (!response.ok) {
193
+ const errText = await response.text();
194
+ throw new Error(`${failureLabel} at ${tokenEndpoint} (HTTP ${response.status}): ${errText}`);
195
+ }
196
+ const tokens = (await response.json());
197
+ const expiresAt = tokens.expires_in !== undefined ? Date.now() + tokens.expires_in * 1000 : undefined;
198
+ return { tokens, expiresAt };
199
+ }
200
+ /**
201
+ * Exchange authorization code for access and refresh tokens.
202
+ *
203
+ * Verifies state HMAC, performs RFC 9207 `iss` validation, and posts
204
+ * code_verifier and resource to the token_endpoint.
205
+ */
206
+ export async function exchangeOAuthPkce(options) {
207
+ const fetchFn = options.fetchFn ?? fetch;
208
+ // 1. Unseal state envelope and verify HMAC + expiration
209
+ const statePayload = await unsealStatePayload(options.state, options.signingSecret);
210
+ // Validate redirect_uri matches authorization request per RFC 6749 Section 4.1.3
211
+ const effectiveRedirectUri = options.redirectUri || statePayload.redirectUri;
212
+ if (options.redirectUri &&
213
+ statePayload.redirectUri &&
214
+ options.redirectUri !== statePayload.redirectUri) {
215
+ throw new Error(`Redirect URI mismatch: expected "${statePayload.redirectUri}", received "${options.redirectUri}"`);
216
+ }
217
+ // 2. Validate RFC 9207 issuer
218
+ validateIssuer(statePayload.expectedIssuer, options.iss);
219
+ // 3. Resolve token endpoint
220
+ let tokenEndpoint = options.tokenEndpoint;
221
+ if (!tokenEndpoint) {
222
+ const asMeta = await discoverAuthServerMetadata(statePayload.expectedIssuer, fetchFn);
223
+ tokenEndpoint = asMeta.token_endpoint;
224
+ }
225
+ // 4. POST to token endpoint
226
+ const body = new URLSearchParams();
227
+ body.set('grant_type', 'authorization_code');
228
+ body.set('code', options.code);
229
+ body.set('redirect_uri', effectiveRedirectUri);
230
+ body.set('client_id', statePayload.clientId);
231
+ body.set('code_verifier', statePayload.codeVerifier);
232
+ if (statePayload.resource) {
233
+ body.set('resource', statePayload.resource);
234
+ }
235
+ const { tokens, expiresAt } = await postTokenRequest(fetchFn, tokenEndpoint, body, 'Token exchange failed');
236
+ const credential = {
237
+ type: 'oauth2',
238
+ issuer: statePayload.expectedIssuer,
239
+ resource: statePayload.resource,
240
+ accessToken: tokens.access_token,
241
+ refreshToken: tokens.refresh_token,
242
+ expiresAt,
243
+ tokenEndpoint,
244
+ clientId: statePayload.clientId,
245
+ scope: tokens.scope,
246
+ };
247
+ return { tokens, credential };
248
+ }
249
+ /**
250
+ * Refresh an expired OAuth 2.1 access token.
251
+ */
252
+ export async function refreshOAuthToken(options) {
253
+ const fetchFn = options.fetchFn ?? fetch;
254
+ const body = new URLSearchParams();
255
+ body.set('grant_type', 'refresh_token');
256
+ body.set('refresh_token', options.refreshToken);
257
+ body.set('client_id', options.clientId);
258
+ if (options.resource) {
259
+ body.set('resource', options.resource);
260
+ }
261
+ if (options.scope) {
262
+ body.set('scope', options.scope);
263
+ }
264
+ const { tokens, expiresAt } = await postTokenRequest(fetchFn, options.tokenEndpoint, body, 'Token refresh failed');
265
+ const credential = {
266
+ type: 'oauth2',
267
+ issuer: options.issuer,
268
+ resource: options.resource,
269
+ accessToken: tokens.access_token,
270
+ // Preserve existing refresh token if new one is not issued
271
+ refreshToken: tokens.refresh_token ?? options.refreshToken,
272
+ expiresAt,
273
+ tokenEndpoint: options.tokenEndpoint,
274
+ clientId: options.clientId,
275
+ scope: tokens.scope ?? options.scope,
276
+ };
277
+ return { tokens, credential };
278
+ }
@@ -0,0 +1,133 @@
1
+ /**
2
+ * OAuth 2.1 and Model Context Protocol authorization types.
3
+ *
4
+ * Implements current July 28, 2026 MCP specification requirements:
5
+ * - RFC 9728: Protected Resource Metadata
6
+ * - RFC 8414 & OpenID Connect: Authorization Server Metadata
7
+ * - RFC 9207: Authorization Server Issuer Identification (`iss` validation)
8
+ * - RFC 8707: Resource Indicators
9
+ * - RFC 7636: PKCE with S256
10
+ *
11
+ * @module
12
+ */
13
+ /** RFC 9728 Protected Resource Metadata */
14
+ export interface ProtectedResourceMetadata {
15
+ resource: string;
16
+ authorization_servers: string[];
17
+ scopes_supported?: string[];
18
+ bearer_methods_supported?: string[];
19
+ resource_documentation?: string;
20
+ [key: string]: unknown;
21
+ }
22
+ /** RFC 8414 / OpenID Connect Discovery Metadata */
23
+ export interface AuthorizationServerMetadata {
24
+ issuer: string;
25
+ authorization_endpoint: string;
26
+ token_endpoint: string;
27
+ registration_endpoint?: string;
28
+ scopes_supported?: string[];
29
+ response_types_supported?: string[];
30
+ grant_types_supported?: string[];
31
+ code_challenge_methods_supported?: string[];
32
+ authorization_response_iss_parameter_supported?: boolean;
33
+ client_id_metadata_document_supported?: boolean;
34
+ [key: string]: unknown;
35
+ }
36
+ /** Standard OAuth 2.1 token response */
37
+ export interface OAuthTokens {
38
+ access_token: string;
39
+ token_type?: string;
40
+ expires_in?: number;
41
+ refresh_token?: string;
42
+ scope?: string;
43
+ /** Custom extra parameters returned by AS */
44
+ [key: string]: unknown;
45
+ }
46
+ /** Normalized OAuth credential for storage / pass-through in TurnRequest */
47
+ export interface OAuth2Credential {
48
+ type: 'oauth2';
49
+ issuer: string;
50
+ resource?: string;
51
+ accessToken: string;
52
+ refreshToken?: string;
53
+ expiresAt?: number;
54
+ tokenEndpoint: string;
55
+ clientId: string;
56
+ scope?: string;
57
+ }
58
+ /** Bearer token credential */
59
+ export interface BearerCredential {
60
+ type: 'bearer';
61
+ token: string;
62
+ }
63
+ /** API key credential */
64
+ export interface ApiKeyCredential {
65
+ type: 'api_key';
66
+ key: string;
67
+ headerName?: string;
68
+ headerPrefix?: string;
69
+ }
70
+ /** Universal union of supported tool credentials */
71
+ export type ToolCredential = OAuth2Credential | BearerCredential | ApiKeyCredential;
72
+ /** Options for creating an OAuth 2.1 PKCE authorization flow */
73
+ export interface CreatePkceFlowOptions {
74
+ /** Target resource server URL (e.g. MCP server URL) or direct AS URL */
75
+ resourceServerUrl: string;
76
+ /** The OAuth client id or Client ID Metadata Document HTTPS URL */
77
+ clientId: string;
78
+ /** Redirect URI registered with the OAuth client */
79
+ redirectUri: string;
80
+ /** Desired scopes */
81
+ scopes?: string[];
82
+ /** Secret string used to HMAC-sign the stateless state envelope */
83
+ signingSecret: string;
84
+ /** State envelope TTL in milliseconds (default: 10 minutes) */
85
+ stateTtlMs?: number;
86
+ /** Optional pre-resolved discovery metadata to bypass runtime fetch */
87
+ preResolved?: {
88
+ issuer?: string;
89
+ authorizationEndpoint?: string;
90
+ tokenEndpoint?: string;
91
+ resource?: string;
92
+ };
93
+ /** Optional fetch function for testing or proxying */
94
+ fetchFn?: typeof fetch;
95
+ }
96
+ /** Result of initiating a PKCE flow */
97
+ export interface PkceFlowResult {
98
+ authorizationUrl: string;
99
+ state: string;
100
+ codeVerifier: string;
101
+ codeChallenge: string;
102
+ issuer: string;
103
+ resource?: string;
104
+ }
105
+ /** Options for exchanging an authorization code */
106
+ export interface ExchangePkceCodeOptions {
107
+ code: string;
108
+ state: string;
109
+ /** `iss` parameter returned in the authorization response query (RFC 9207) */
110
+ iss?: string;
111
+ /** Redirect URI matching the authorization request */
112
+ redirectUri: string;
113
+ /** Secret used to sign the state envelope */
114
+ signingSecret: string;
115
+ /** Optional token endpoint override (defaults to discovered AS token_endpoint) */
116
+ tokenEndpoint?: string;
117
+ fetchFn?: typeof fetch;
118
+ }
119
+ /** Result of token exchange */
120
+ export interface ExchangePkceCodeResult {
121
+ tokens: OAuthTokens;
122
+ credential: OAuth2Credential;
123
+ }
124
+ /** Options for refreshing an expired OAuth token */
125
+ export interface RefreshOAuthTokenOptions {
126
+ refreshToken: string;
127
+ tokenEndpoint: string;
128
+ clientId: string;
129
+ resource?: string;
130
+ scope?: string;
131
+ issuer: string;
132
+ fetchFn?: typeof fetch;
133
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * OAuth 2.1 and Model Context Protocol authorization types.
3
+ *
4
+ * Implements current July 28, 2026 MCP specification requirements:
5
+ * - RFC 9728: Protected Resource Metadata
6
+ * - RFC 8414 & OpenID Connect: Authorization Server Metadata
7
+ * - RFC 9207: Authorization Server Issuer Identification (`iss` validation)
8
+ * - RFC 8707: Resource Indicators
9
+ * - RFC 7636: PKCE with S256
10
+ *
11
+ * @module
12
+ */
13
+ export {};
@@ -1,8 +1,30 @@
1
1
  import type { TurnEvent, TurnTokens } from '../types.js';
2
+ declare function isCodeExecutionType(type: string): boolean;
3
+ declare function isGoogleBuiltinStepType(type: string): boolean;
4
+ declare function googleBuiltinEvidence(raw: Record<string, unknown>): TurnEvent;
5
+ /** Merge a later code-exec delta/step onto an earlier snapshot (partial code/stdout). */
6
+ declare function mergeCodeExecutionPayload(existing: Record<string, unknown> | undefined, incoming: Record<string, unknown>): Record<string, unknown>;
7
+ /** Normalize a Google `code_execution_*` step/delta into an `evidence` event. */
8
+ declare function codeExecutionEvidence(raw: Record<string, unknown>): TurnEvent;
9
+ /** Stable key so streamed deltas and batched `steps[]` do not double-emit. */
10
+ declare function codeExecutionStepKey(raw: Record<string, unknown>, index?: number): string;
2
11
  declare function eventsFromDelta(deltaValue: unknown): TurnEvent[];
12
+ /**
13
+ * Replay a completed Interactions `steps[]` array (non-SSE or stream tail).
14
+ * Emits typed code-execution evidence plus model_output text/media.
15
+ */
16
+ declare function eventsFromInteractionSteps(steps: unknown[], alreadyText: boolean): TurnEvent[];
3
17
  declare function groundingFromEvent(event: Record<string, unknown>): TurnEvent | undefined;
4
18
  declare function extractUsageTokens(raw: unknown): TurnTokens | undefined;
5
19
  declare function extractTokenEvent(event: Record<string, unknown>, interaction?: Record<string, unknown>): TurnEvent | undefined;
6
20
  declare function eventsFromComplete(event: Record<string, unknown>, alreadyText: boolean): TurnEvent[];
7
- declare function tryStructured(text: string): TurnEvent | undefined;
8
- export { eventsFromComplete, eventsFromDelta, extractTokenEvent, extractUsageTokens, groundingFromEvent, tryStructured, };
21
+ export type ParsedStructuredOutput = {
22
+ ok: true;
23
+ structured: unknown;
24
+ } | {
25
+ ok: false;
26
+ error: string;
27
+ };
28
+ /** Parse model text as structured JSON. Invalid JSON is a hard failure — never silent skip. */
29
+ declare function parseStructuredOutput(text: string): ParsedStructuredOutput;
30
+ export { codeExecutionEvidence, codeExecutionStepKey, eventsFromComplete, eventsFromDelta, eventsFromInteractionSteps, extractTokenEvent, extractUsageTokens, googleBuiltinEvidence, groundingFromEvent, isCodeExecutionType, isGoogleBuiltinStepType, mergeCodeExecutionPayload, parseStructuredOutput, };