@toa.io/extensions.exposition 1.0.0-alpha.282 → 1.0.0-alpha.284

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 (667) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/components/exposition.octets/manifest.toa.yaml +11 -0
  3. package/components/exposition.octets/types/index.d.ts +3 -0
  4. package/components/exposition.octets/types/toa.d.ts +41 -0
  5. package/components/identity.bans/operations/transit.js +1 -1
  6. package/components/identity.bans/tsconfig.json +1 -1
  7. package/components/identity.bans/tsconfig.tsbuildinfo +1 -1
  8. package/components/identity.bans/types/index.d.ts +3 -0
  9. package/components/identity.bans/types/toa.d.ts +34 -0
  10. package/components/identity.basic/manifest.toa.yaml +13 -2
  11. package/components/identity.basic/operations/add.js +1 -1
  12. package/components/identity.basic/operations/authenticate.js +1 -1
  13. package/components/identity.basic/operations/check.js +1 -1
  14. package/components/identity.basic/operations/delete.js +1 -1
  15. package/components/identity.basic/operations/incept.js +18 -2
  16. package/components/identity.basic/operations/info.js +1 -1
  17. package/components/identity.basic/operations/lib/credentials.js +1 -1
  18. package/components/identity.basic/operations/transit.js +3 -2
  19. package/components/identity.basic/source/add.ts +3 -3
  20. package/components/identity.basic/source/authenticate.ts +2 -2
  21. package/components/identity.basic/source/check.ts +1 -1
  22. package/components/identity.basic/source/delete.ts +2 -2
  23. package/components/identity.basic/source/incept.ts +31 -3
  24. package/components/identity.basic/source/info.ts +1 -1
  25. package/components/identity.basic/source/transit.ts +6 -4
  26. package/components/identity.basic/tsconfig.json +1 -1
  27. package/components/identity.basic/tsconfig.tsbuildinfo +1 -1
  28. package/components/identity.basic/types/index.d.ts +22 -0
  29. package/components/identity.basic/types/toa.d.ts +121 -0
  30. package/components/identity.clients/manifest.toa.yaml +243 -0
  31. package/components/identity.clients/operations/describe.js +44 -0
  32. package/components/identity.clients/operations/lib/Context.js +2 -0
  33. package/components/identity.clients/operations/lib/Entity.js +2 -0
  34. package/components/identity.clients/operations/lib/canonical.js +24 -0
  35. package/components/identity.clients/operations/lib/cimd.js +86 -0
  36. package/components/identity.clients/operations/lib/errors.js +5 -0
  37. package/components/identity.clients/operations/lib/index.js +7 -0
  38. package/components/identity.clients/operations/lib/redirect.js +32 -0
  39. package/components/identity.clients/operations/register.js +84 -0
  40. package/components/identity.clients/source/describe.ts +65 -0
  41. package/components/identity.clients/source/lib/Context.ts +38 -0
  42. package/components/identity.clients/source/lib/Entity.ts +31 -0
  43. package/components/identity.clients/source/lib/canonical.test.ts +43 -0
  44. package/components/identity.clients/source/lib/canonical.ts +27 -0
  45. package/components/identity.clients/source/lib/cimd.test.ts +120 -0
  46. package/components/identity.clients/source/lib/cimd.ts +107 -0
  47. package/components/identity.clients/source/lib/errors.ts +4 -0
  48. package/components/identity.clients/source/lib/index.ts +6 -0
  49. package/components/identity.clients/source/lib/redirect.test.ts +41 -0
  50. package/components/identity.clients/source/lib/redirect.ts +35 -0
  51. package/components/identity.clients/source/register.ts +125 -0
  52. package/components/identity.clients/tsconfig.json +10 -0
  53. package/components/identity.clients/tsconfig.tsbuildinfo +1 -0
  54. package/components/identity.clients/types/index.d.ts +3 -0
  55. package/components/identity.clients/types/toa.d.ts +109 -0
  56. package/components/identity.credentials/operations/list.js +1 -1
  57. package/components/identity.credentials/source/list.ts +2 -1
  58. package/components/identity.credentials/tsconfig.json +4 -2
  59. package/components/identity.credentials/tsconfig.tsbuildinfo +1 -1
  60. package/components/identity.credentials/types/index.d.ts +3 -0
  61. package/components/identity.credentials/types/toa.d.ts +30 -0
  62. package/components/identity.federation/manifest.toa.yaml +37 -1
  63. package/components/identity.federation/operations/authenticate.js +7 -3
  64. package/components/identity.federation/operations/create.js +1 -1
  65. package/components/identity.federation/operations/decode.js +1 -1
  66. package/components/identity.federation/operations/delete.js +1 -1
  67. package/components/identity.federation/operations/incept.js +6 -2
  68. package/components/identity.federation/operations/lib/Configuration.js +1 -1
  69. package/components/identity.federation/operations/lib/Ctx.js +1 -1
  70. package/components/identity.federation/operations/lib/Payload.js +1 -1
  71. package/components/identity.federation/operations/lib/decode.js +23 -9
  72. package/components/identity.federation/operations/lib/discovery.js +1 -1
  73. package/components/identity.federation/operations/lib/errors.js +5 -1
  74. package/components/identity.federation/operations/lib/exchange.js +12 -7
  75. package/components/identity.federation/operations/lib/index.js +2 -1
  76. package/components/identity.federation/operations/lib/jose.js +1 -1
  77. package/components/identity.federation/operations/lib/principal.js +14 -0
  78. package/components/identity.federation/operations/lib/resolve.js +1 -1
  79. package/components/identity.federation/operations/list.js +1 -1
  80. package/components/identity.federation/operations/types/Scheme.js +1 -1
  81. package/components/identity.federation/operations/types/configuration.js +1 -1
  82. package/components/identity.federation/operations/types/context.js +1 -1
  83. package/components/identity.federation/operations/types/entity.js +1 -1
  84. package/components/identity.federation/operations/types/index.js +1 -1
  85. package/components/identity.federation/source/authenticate.ts +9 -3
  86. package/components/identity.federation/source/incept.ts +7 -1
  87. package/components/identity.federation/source/lib/Ctx.ts +2 -2
  88. package/components/identity.federation/source/lib/decode.ts +25 -9
  89. package/components/identity.federation/source/lib/errors.ts +5 -0
  90. package/components/identity.federation/source/lib/exchange.ts +11 -7
  91. package/components/identity.federation/source/lib/index.ts +1 -0
  92. package/components/identity.federation/source/lib/principal.ts +17 -0
  93. package/components/identity.federation/source/types/configuration.ts +1 -1
  94. package/components/identity.federation/source/types/context.ts +6 -2
  95. package/components/identity.federation/tsconfig.json +4 -2
  96. package/components/identity.federation/tsconfig.tsbuildinfo +1 -1
  97. package/components/identity.federation/types/index.d.ts +3 -0
  98. package/components/identity.federation/types/toa.d.ts +127 -0
  99. package/components/identity.grants/manifest.toa.yaml +245 -0
  100. package/components/identity.grants/operations/authorize.js +54 -0
  101. package/components/identity.grants/operations/exchange.js +89 -0
  102. package/components/identity.grants/operations/lib/code.js +30 -0
  103. package/components/identity.grants/operations/lib/identify.js +15 -0
  104. package/components/identity.grants/operations/lib/index.js +3 -0
  105. package/components/identity.grants/operations/list.js +18 -0
  106. package/components/identity.grants/operations/revoke.js +25 -0
  107. package/components/identity.grants/source/authorize.ts +90 -0
  108. package/components/identity.grants/source/exchange.ts +130 -0
  109. package/components/identity.grants/source/lib/code.ts +39 -0
  110. package/components/identity.grants/source/lib/identify.ts +16 -0
  111. package/components/identity.grants/source/lib/index.ts +3 -0
  112. package/components/identity.grants/source/list.ts +28 -0
  113. package/components/identity.grants/source/revoke.ts +38 -0
  114. package/components/identity.grants/tsconfig.json +10 -0
  115. package/components/identity.grants/tsconfig.tsbuildinfo +1 -0
  116. package/components/identity.grants/types/index.d.ts +60 -0
  117. package/components/identity.grants/types/toa.d.ts +108 -0
  118. package/components/identity.keys/manifest.toa.yaml +1 -0
  119. package/components/identity.keys/operations/create.js +1 -1
  120. package/components/identity.keys/operations/disable.js +1 -1
  121. package/components/identity.keys/operations/revoke.js +1 -1
  122. package/components/identity.keys/source/create.ts +1 -1
  123. package/components/identity.keys/source/revoke.ts +1 -1
  124. package/components/identity.keys/tsconfig.json +1 -1
  125. package/components/identity.keys/tsconfig.tsbuildinfo +1 -1
  126. package/components/identity.keys/types/index.d.ts +3 -0
  127. package/components/identity.keys/types/toa.d.ts +47 -0
  128. package/components/identity.otp/operations/authenticate.js +1 -1
  129. package/components/identity.otp/operations/issue.js +1 -1
  130. package/components/identity.otp/operations/lib/Context.js +1 -1
  131. package/components/identity.otp/operations/lib/Entity.js +1 -1
  132. package/components/identity.otp/operations/lib/index.js +1 -1
  133. package/components/identity.otp/source/lib/Context.ts +4 -2
  134. package/components/identity.otp/tsconfig.json +1 -1
  135. package/components/identity.otp/tsconfig.tsbuildinfo +1 -1
  136. package/components/identity.otp/types/index.d.ts +3 -0
  137. package/components/identity.otp/types/toa.d.ts +56 -0
  138. package/components/identity.passkeys/manifest.toa.yaml +3 -0
  139. package/components/identity.passkeys/operations/authenticate.js +1 -1
  140. package/components/identity.passkeys/operations/challenge.js +1 -1
  141. package/components/identity.passkeys/operations/create.js +1 -1
  142. package/components/identity.passkeys/operations/delete.js +1 -1
  143. package/components/identity.passkeys/operations/lib/const.js +1 -1
  144. package/components/identity.passkeys/operations/list.js +1 -1
  145. package/components/identity.passkeys/operations/types/Configuration.js +1 -1
  146. package/components/identity.passkeys/operations/types/Context.js +1 -1
  147. package/components/identity.passkeys/operations/types/Passkey.js +1 -1
  148. package/components/identity.passkeys/operations/types/index.js +1 -1
  149. package/components/identity.passkeys/operations/use.js +1 -1
  150. package/components/identity.passkeys/source/authenticate.ts +1 -1
  151. package/components/identity.passkeys/source/challenge.ts +1 -1
  152. package/components/identity.passkeys/source/create.ts +1 -1
  153. package/components/identity.passkeys/source/types/Context.ts +2 -1
  154. package/components/identity.passkeys/source/use.ts +1 -1
  155. package/components/identity.passkeys/tsconfig.json +1 -1
  156. package/components/identity.passkeys/tsconfig.tsbuildinfo +1 -1
  157. package/components/identity.passkeys/types/index.d.ts +3 -0
  158. package/components/identity.passkeys/types/toa.d.ts +120 -0
  159. package/components/identity.roles/operations/grant.js +1 -1
  160. package/components/identity.roles/operations/lib/Entity.js +1 -1
  161. package/components/identity.roles/operations/list.js +1 -1
  162. package/components/identity.roles/operations/principal.js +29 -5
  163. package/components/identity.roles/source/principal.ts +33 -5
  164. package/components/identity.roles/tsconfig.json +1 -1
  165. package/components/identity.roles/tsconfig.tsbuildinfo +1 -1
  166. package/components/identity.roles/types/index.d.ts +3 -0
  167. package/components/identity.roles/types/toa.d.ts +43 -0
  168. package/components/identity.tokens/manifest.toa.yaml +34 -3
  169. package/components/identity.tokens/operations/authenticate.js +9 -1
  170. package/components/identity.tokens/operations/decrypt.js +3 -3
  171. package/components/identity.tokens/operations/encrypt.js +1 -1
  172. package/components/identity.tokens/operations/issue.js +3 -2
  173. package/components/identity.tokens/operations/lib/form.js +24 -0
  174. package/components/identity.tokens/operations/lib/index.js +2 -2
  175. package/components/identity.tokens/operations/lib/jose.js +1 -1
  176. package/components/identity.tokens/operations/lib/key.js +1 -1
  177. package/components/identity.tokens/operations/lib/pad.js +1 -1
  178. package/components/identity.tokens/operations/revoke.js +1 -1
  179. package/components/identity.tokens/source/authenticate.test.ts +8 -5
  180. package/components/identity.tokens/source/authenticate.ts +12 -1
  181. package/components/identity.tokens/source/decrypt.test.ts +1 -1
  182. package/components/identity.tokens/source/decrypt.ts +4 -3
  183. package/components/identity.tokens/source/encrypt.test.ts +1 -1
  184. package/components/identity.tokens/source/encrypt.ts +2 -1
  185. package/components/identity.tokens/source/issue.test.ts +71 -0
  186. package/components/identity.tokens/source/issue.ts +4 -2
  187. package/components/identity.tokens/source/lib/form.test.ts +25 -0
  188. package/components/identity.tokens/source/lib/form.ts +31 -0
  189. package/components/identity.tokens/source/lib/index.ts +2 -1
  190. package/components/identity.tokens/tsconfig.json +1 -1
  191. package/components/identity.tokens/tsconfig.tsbuildinfo +1 -1
  192. package/components/identity.tokens/types/index.d.ts +61 -0
  193. package/components/identity.tokens/types/toa.d.ts +113 -0
  194. package/documentation/access.md +13 -0
  195. package/documentation/cache.md +10 -1
  196. package/documentation/components.md +3 -0
  197. package/documentation/consent.md +101 -0
  198. package/documentation/identity.md +3 -1
  199. package/documentation/introspection.md +13 -5
  200. package/documentation/io.md +42 -2
  201. package/documentation/map.md +8 -0
  202. package/documentation/mcp.md +180 -0
  203. package/documentation/oauth.md +180 -0
  204. package/documentation/protocol.md +4 -0
  205. package/documentation/rpc.md +140 -0
  206. package/documentation/tree.md +3 -0
  207. package/features/auth.bearer.feature +120 -0
  208. package/features/cache.feature +46 -0
  209. package/features/identity.basic.feature +44 -0
  210. package/features/identity.federation.feature +2 -5
  211. package/features/introspection.feature +333 -0
  212. package/features/mcp.feature +687 -0
  213. package/features/oauth.clients.feature +195 -0
  214. package/features/oauth.discovery.feature +164 -0
  215. package/features/oauth.grants.feature +299 -0
  216. package/features/octets.cloudinary.feature +1 -0
  217. package/features/rpc.feature +429 -0
  218. package/features/steps/Cloudinary.ts +13 -0
  219. package/features/steps/Components.ts +0 -4
  220. package/features/steps/Gateway.ts +23 -2
  221. package/features/steps/Parameters.ts +22 -7
  222. package/features/steps/Realtime.ts +3 -0
  223. package/features/steps/components/echo/manifest.toa.yaml +3 -0
  224. package/features/steps/components/octets.tester/manifest.toa.yaml +2 -0
  225. package/features/steps/components/octets.tester/operations/redirect.js +6 -1
  226. package/features/steps/components/pots/manifest.toa.yaml +2 -0
  227. package/features/steps/components/users/manifest.toa.yaml +1 -0
  228. package/package.json +8 -6
  229. package/readme.md +6 -0
  230. package/schemas/annotation.cos.yaml +63 -0
  231. package/schemas/call.cos.yaml +18 -0
  232. package/source/Annotation.ts +54 -0
  233. package/source/Directive.test.ts +15 -15
  234. package/source/Directive.ts +77 -9
  235. package/source/Endpoint.test.ts +67 -0
  236. package/source/Endpoint.ts +31 -11
  237. package/source/Factory.ts +6 -2
  238. package/source/Gateway.ts +73 -11
  239. package/source/HTTP/Context.ts +7 -0
  240. package/source/HTTP/Server.ts +15 -5
  241. package/source/HTTP/exceptions.ts +2 -2
  242. package/source/HTTP/formats/form.ts +21 -0
  243. package/source/HTTP/formats/index.ts +17 -2
  244. package/source/HTTP/messages.test.ts +25 -1
  245. package/source/HTTP/messages.ts +20 -4
  246. package/source/Interception.ts +8 -2
  247. package/source/Introspection.ts +102 -0
  248. package/source/MCP/Server.ts +275 -0
  249. package/source/MCP/discover.ts +52 -0
  250. package/source/MCP/errors.ts +81 -0
  251. package/source/MCP/index.ts +1 -0
  252. package/source/MCP/schema.test.ts +85 -0
  253. package/source/MCP/schema.ts +87 -0
  254. package/source/MCP/tools.ts +156 -0
  255. package/source/MCP/types.ts +81 -0
  256. package/source/Query.ts +48 -8
  257. package/source/RPC/Context.ts +78 -0
  258. package/source/RPC/Dispatcher.ts +130 -0
  259. package/source/RPC/errors.test.ts +52 -0
  260. package/source/RPC/errors.ts +83 -0
  261. package/source/RPC/index.ts +1 -0
  262. package/source/RPC/names.test.ts +122 -0
  263. package/source/RPC/names.ts +182 -0
  264. package/source/RPC/types.ts +34 -0
  265. package/source/RTD/Directives.ts +52 -2
  266. package/source/RTD/Endpoint.ts +2 -1
  267. package/source/RTD/Method.ts +14 -11
  268. package/source/RTD/Node.ts +38 -7
  269. package/source/RTD/Route.ts +30 -3
  270. package/source/RTD/Tree.ts +37 -1
  271. package/source/RTD/expiration.test.ts +1 -1
  272. package/source/RTD/walk.test.ts +110 -0
  273. package/source/const.ts +15 -0
  274. package/source/deployment.ts +11 -1
  275. package/source/directives/auth/Anonymous.test.ts +38 -0
  276. package/source/directives/auth/Anonymous.ts +12 -0
  277. package/source/directives/auth/Anyone.ts +4 -0
  278. package/source/directives/auth/Authorization.ts +108 -22
  279. package/source/directives/auth/Delegate.test.ts +36 -0
  280. package/source/directives/auth/Delegate.ts +14 -0
  281. package/source/directives/auth/Echo.ts +5 -0
  282. package/source/directives/auth/Incept.ts +16 -10
  283. package/source/directives/auth/Role.ts +13 -0
  284. package/source/directives/auth/Rule.ts +29 -0
  285. package/source/directives/auth/Scheme.ts +5 -0
  286. package/source/directives/auth/schemes.test.ts +8 -4
  287. package/source/directives/auth/schemes.ts +22 -9
  288. package/source/directives/auth/types.ts +26 -2
  289. package/source/directives/cache/Cache.ts +14 -5
  290. package/source/directives/cache/Control.ts +0 -3
  291. package/source/directives/dev/Development.ts +1 -1
  292. package/source/directives/flow/Fetch.ts +1 -1
  293. package/source/directives/flow/Flow.ts +1 -1
  294. package/source/directives/index.ts +5 -2
  295. package/source/directives/io/Directive.ts +1 -1
  296. package/source/directives/io/IO.ts +34 -3
  297. package/source/directives/io/Input.ts +3 -2
  298. package/source/directives/io/Output.ts +10 -4
  299. package/source/directives/io/Status.test.ts +84 -0
  300. package/source/directives/io/Status.ts +46 -0
  301. package/source/directives/io/Throttle.ts +1 -1
  302. package/source/directives/io/lib/throttle/Quotas.ts +2 -2
  303. package/source/directives/map/Headers.ts +11 -0
  304. package/source/directives/map/Map.ts +10 -1
  305. package/source/directives/map/Mapping.ts +23 -0
  306. package/source/directives/map/Segments.ts +12 -0
  307. package/source/directives/mcp/MCP.ts +33 -0
  308. package/source/directives/mcp/Tool.test.ts +66 -0
  309. package/source/directives/mcp/Tool.ts +28 -0
  310. package/source/directives/mcp/index.ts +6 -0
  311. package/source/directives/oauth/Discovery.ts +70 -0
  312. package/source/directives/oauth/documents.ts +113 -0
  313. package/source/directives/oauth/index.ts +3 -0
  314. package/source/directives/octets/Delete.ts +1 -1
  315. package/source/directives/octets/Get.ts +1 -1
  316. package/source/directives/octets/Octets.ts +1 -1
  317. package/source/directives/octets/Workflow.ts +1 -1
  318. package/source/directives/octets/workflows/Execution.ts +1 -1
  319. package/source/directives/require/Directive.ts +1 -1
  320. package/source/directives/require/Headers.ts +1 -1
  321. package/source/directives/require/Require.ts +2 -2
  322. package/source/index.ts +6 -0
  323. package/source/octets.d.ts +17 -0
  324. package/source/schemas.ts +2 -0
  325. package/source/userland.ts +47 -0
  326. package/transpiled/Annotation.d.ts +41 -0
  327. package/transpiled/Directive.d.ts +18 -1
  328. package/transpiled/Directive.js +50 -6
  329. package/transpiled/Directive.js.map +1 -1
  330. package/transpiled/Endpoint.d.ts +9 -0
  331. package/transpiled/Endpoint.js +27 -11
  332. package/transpiled/Endpoint.js.map +1 -1
  333. package/transpiled/Factory.js +6 -2
  334. package/transpiled/Factory.js.map +1 -1
  335. package/transpiled/Gateway.d.ts +19 -2
  336. package/transpiled/Gateway.js +51 -9
  337. package/transpiled/Gateway.js.map +1 -1
  338. package/transpiled/HTTP/Context.d.ts +6 -0
  339. package/transpiled/HTTP/Context.js +6 -0
  340. package/transpiled/HTTP/Context.js.map +1 -1
  341. package/transpiled/HTTP/Server.d.ts +8 -1
  342. package/transpiled/HTTP/Server.js +4 -3
  343. package/transpiled/HTTP/Server.js.map +1 -1
  344. package/transpiled/HTTP/exceptions.d.ts +1 -1
  345. package/transpiled/HTTP/exceptions.js +2 -2
  346. package/transpiled/HTTP/exceptions.js.map +1 -1
  347. package/transpiled/HTTP/formats/form.d.ts +9 -0
  348. package/transpiled/HTTP/formats/form.js +18 -0
  349. package/transpiled/HTTP/formats/form.js.map +1 -0
  350. package/transpiled/HTTP/formats/index.d.ts +10 -2
  351. package/transpiled/HTTP/formats/index.js +10 -0
  352. package/transpiled/HTTP/formats/index.js.map +1 -1
  353. package/transpiled/HTTP/messages.d.ts +12 -0
  354. package/transpiled/HTTP/messages.js +12 -4
  355. package/transpiled/HTTP/messages.js.map +1 -1
  356. package/transpiled/Interception.d.ts +4 -1
  357. package/transpiled/Interception.js +4 -2
  358. package/transpiled/Interception.js.map +1 -1
  359. package/transpiled/Introspection.d.ts +40 -0
  360. package/transpiled/Introspection.js +50 -1
  361. package/transpiled/Introspection.js.map +1 -1
  362. package/transpiled/MCP/Server.d.ts +41 -0
  363. package/transpiled/MCP/Server.js +180 -0
  364. package/transpiled/MCP/Server.js.map +1 -0
  365. package/transpiled/MCP/discover.d.ts +13 -0
  366. package/transpiled/MCP/discover.js +29 -0
  367. package/transpiled/MCP/discover.js.map +1 -0
  368. package/transpiled/MCP/errors.d.ts +24 -0
  369. package/transpiled/MCP/errors.js +67 -0
  370. package/transpiled/MCP/errors.js.map +1 -0
  371. package/transpiled/MCP/index.d.ts +1 -0
  372. package/transpiled/MCP/index.js +2 -0
  373. package/transpiled/MCP/index.js.map +1 -0
  374. package/transpiled/MCP/schema.d.ts +18 -0
  375. package/transpiled/MCP/schema.js +64 -0
  376. package/transpiled/MCP/schema.js.map +1 -0
  377. package/transpiled/MCP/tools.d.ts +31 -0
  378. package/transpiled/MCP/tools.js +121 -0
  379. package/transpiled/MCP/tools.js.map +1 -0
  380. package/transpiled/MCP/types.d.ts +64 -0
  381. package/transpiled/MCP/types.js +13 -0
  382. package/transpiled/MCP/types.js.map +1 -0
  383. package/transpiled/Query.d.ts +7 -0
  384. package/transpiled/Query.js +38 -7
  385. package/transpiled/Query.js.map +1 -1
  386. package/transpiled/RPC/Context.d.ts +11 -0
  387. package/transpiled/RPC/Context.js +63 -0
  388. package/transpiled/RPC/Context.js.map +1 -0
  389. package/transpiled/RPC/Dispatcher.d.ts +19 -0
  390. package/transpiled/RPC/Dispatcher.js +100 -0
  391. package/transpiled/RPC/Dispatcher.js.map +1 -0
  392. package/transpiled/RPC/errors.d.ts +18 -0
  393. package/transpiled/RPC/errors.js +67 -0
  394. package/transpiled/RPC/errors.js.map +1 -0
  395. package/transpiled/RPC/index.d.ts +1 -0
  396. package/transpiled/RPC/index.js +2 -0
  397. package/transpiled/RPC/index.js.map +1 -0
  398. package/transpiled/RPC/names.d.ts +30 -0
  399. package/transpiled/RPC/names.js +121 -0
  400. package/transpiled/RPC/names.js.map +1 -0
  401. package/transpiled/RPC/types.d.ts +27 -0
  402. package/transpiled/RPC/types.js +8 -0
  403. package/transpiled/RPC/types.js.map +1 -0
  404. package/transpiled/RTD/Directives.d.ts +41 -2
  405. package/transpiled/RTD/Endpoint.d.ts +2 -1
  406. package/transpiled/RTD/Method.d.ts +8 -3
  407. package/transpiled/RTD/Method.js +12 -10
  408. package/transpiled/RTD/Method.js.map +1 -1
  409. package/transpiled/RTD/Node.d.ts +20 -2
  410. package/transpiled/RTD/Node.js +22 -4
  411. package/transpiled/RTD/Node.js.map +1 -1
  412. package/transpiled/RTD/Route.d.ts +2 -1
  413. package/transpiled/RTD/Route.js +27 -2
  414. package/transpiled/RTD/Route.js.map +1 -1
  415. package/transpiled/RTD/Tree.d.ts +3 -1
  416. package/transpiled/RTD/Tree.js +26 -0
  417. package/transpiled/RTD/Tree.js.map +1 -1
  418. package/transpiled/const.d.ts +12 -0
  419. package/transpiled/const.js +12 -0
  420. package/transpiled/const.js.map +1 -1
  421. package/transpiled/deployment.js +6 -0
  422. package/transpiled/deployment.js.map +1 -1
  423. package/transpiled/directives/auth/Anonymous.d.ts +6 -0
  424. package/transpiled/directives/auth/Anonymous.js +10 -0
  425. package/transpiled/directives/auth/Anonymous.js.map +1 -1
  426. package/transpiled/directives/auth/Anyone.d.ts +1 -0
  427. package/transpiled/directives/auth/Anyone.js +3 -0
  428. package/transpiled/directives/auth/Anyone.js.map +1 -1
  429. package/transpiled/directives/auth/Authorization.d.ts +28 -2
  430. package/transpiled/directives/auth/Authorization.js +87 -19
  431. package/transpiled/directives/auth/Authorization.js.map +1 -1
  432. package/transpiled/directives/auth/Delegate.d.ts +5 -0
  433. package/transpiled/directives/auth/Delegate.js +10 -0
  434. package/transpiled/directives/auth/Delegate.js.map +1 -1
  435. package/transpiled/directives/auth/Echo.d.ts +2 -0
  436. package/transpiled/directives/auth/Echo.js +4 -0
  437. package/transpiled/directives/auth/Echo.js.map +1 -1
  438. package/transpiled/directives/auth/Incept.d.ts +1 -1
  439. package/transpiled/directives/auth/Incept.js +13 -8
  440. package/transpiled/directives/auth/Incept.js.map +1 -1
  441. package/transpiled/directives/auth/Role.d.ts +2 -0
  442. package/transpiled/directives/auth/Role.js +9 -0
  443. package/transpiled/directives/auth/Role.js.map +1 -1
  444. package/transpiled/directives/auth/Rule.d.ts +5 -0
  445. package/transpiled/directives/auth/Rule.js +20 -0
  446. package/transpiled/directives/auth/Rule.js.map +1 -1
  447. package/transpiled/directives/auth/Scheme.d.ts +2 -0
  448. package/transpiled/directives/auth/Scheme.js +4 -0
  449. package/transpiled/directives/auth/Scheme.js.map +1 -1
  450. package/transpiled/directives/auth/schemes.d.ts +16 -4
  451. package/transpiled/directives/auth/schemes.js +20 -8
  452. package/transpiled/directives/auth/schemes.js.map +1 -1
  453. package/transpiled/directives/auth/types.d.ts +20 -2
  454. package/transpiled/directives/cache/Cache.d.ts +1 -1
  455. package/transpiled/directives/cache/Cache.js +10 -3
  456. package/transpiled/directives/cache/Cache.js.map +1 -1
  457. package/transpiled/directives/cache/Control.js +0 -2
  458. package/transpiled/directives/cache/Control.js.map +1 -1
  459. package/transpiled/directives/dev/Development.d.ts +1 -1
  460. package/transpiled/directives/dev/Development.js +1 -1
  461. package/transpiled/directives/dev/Development.js.map +1 -1
  462. package/transpiled/directives/flow/Flow.d.ts +1 -1
  463. package/transpiled/directives/flow/Flow.js +1 -1
  464. package/transpiled/directives/flow/Flow.js.map +1 -1
  465. package/transpiled/directives/index.js +4 -2
  466. package/transpiled/directives/index.js.map +1 -1
  467. package/transpiled/directives/io/Directive.d.ts +1 -1
  468. package/transpiled/directives/io/IO.d.ts +7 -1
  469. package/transpiled/directives/io/IO.js +25 -3
  470. package/transpiled/directives/io/IO.js.map +1 -1
  471. package/transpiled/directives/io/Input.d.ts +3 -2
  472. package/transpiled/directives/io/Input.js +2 -1
  473. package/transpiled/directives/io/Input.js.map +1 -1
  474. package/transpiled/directives/io/Output.d.ts +5 -3
  475. package/transpiled/directives/io/Output.js +8 -3
  476. package/transpiled/directives/io/Output.js.map +1 -1
  477. package/transpiled/directives/io/Status.d.ts +19 -0
  478. package/transpiled/directives/io/Status.js +34 -0
  479. package/transpiled/directives/io/Status.js.map +1 -0
  480. package/transpiled/directives/io/Throttle.d.ts +1 -1
  481. package/transpiled/directives/io/Throttle.js +1 -1
  482. package/transpiled/directives/io/Throttle.js.map +1 -1
  483. package/transpiled/directives/io/lib/throttle/Quotas.d.ts +1 -1
  484. package/transpiled/directives/io/lib/throttle/Quotas.js +2 -2
  485. package/transpiled/directives/io/lib/throttle/Quotas.js.map +1 -1
  486. package/transpiled/directives/map/Headers.d.ts +2 -0
  487. package/transpiled/directives/map/Headers.js +8 -0
  488. package/transpiled/directives/map/Headers.js.map +1 -1
  489. package/transpiled/directives/map/Map.d.ts +3 -1
  490. package/transpiled/directives/map/Map.js +7 -1
  491. package/transpiled/directives/map/Map.js.map +1 -1
  492. package/transpiled/directives/map/Mapping.d.ts +13 -0
  493. package/transpiled/directives/map/Mapping.js +20 -0
  494. package/transpiled/directives/map/Mapping.js.map +1 -1
  495. package/transpiled/directives/map/Segments.d.ts +3 -0
  496. package/transpiled/directives/map/Segments.js +9 -0
  497. package/transpiled/directives/map/Segments.js.map +1 -1
  498. package/transpiled/directives/mcp/MCP.d.ts +15 -0
  499. package/transpiled/directives/mcp/MCP.js +23 -0
  500. package/transpiled/directives/mcp/MCP.js.map +1 -0
  501. package/transpiled/directives/mcp/Tool.d.ts +13 -0
  502. package/transpiled/directives/mcp/Tool.js +23 -0
  503. package/transpiled/directives/mcp/Tool.js.map +1 -0
  504. package/transpiled/directives/mcp/index.d.ts +4 -0
  505. package/transpiled/directives/mcp/index.js +4 -0
  506. package/transpiled/directives/mcp/index.js.map +1 -0
  507. package/transpiled/directives/oauth/Discovery.d.ts +23 -0
  508. package/transpiled/directives/oauth/Discovery.js +55 -0
  509. package/transpiled/directives/oauth/Discovery.js.map +1 -0
  510. package/transpiled/directives/oauth/documents.d.ts +9 -0
  511. package/transpiled/directives/oauth/documents.js +82 -0
  512. package/transpiled/directives/oauth/documents.js.map +1 -0
  513. package/transpiled/directives/oauth/index.d.ts +2 -0
  514. package/transpiled/directives/oauth/index.js +3 -0
  515. package/transpiled/directives/oauth/index.js.map +1 -0
  516. package/transpiled/directives/octets/Octets.d.ts +1 -1
  517. package/transpiled/directives/octets/Octets.js +1 -1
  518. package/transpiled/directives/octets/Octets.js.map +1 -1
  519. package/transpiled/directives/require/Directive.d.ts +1 -1
  520. package/transpiled/directives/require/Headers.d.ts +1 -1
  521. package/transpiled/directives/require/Headers.js +1 -1
  522. package/transpiled/directives/require/Headers.js.map +1 -1
  523. package/transpiled/directives/require/Require.d.ts +1 -1
  524. package/transpiled/directives/require/Require.js +2 -2
  525. package/transpiled/directives/require/Require.js.map +1 -1
  526. package/transpiled/index.d.ts +2 -0
  527. package/transpiled/schemas.d.ts +2 -0
  528. package/transpiled/schemas.js +1 -0
  529. package/transpiled/schemas.js.map +1 -1
  530. package/transpiled/userland.d.ts +39 -0
  531. package/transpiled/userland.js +7 -0
  532. package/transpiled/userland.js.map +1 -0
  533. package/tsconfig.tsbuildinfo +1 -1
  534. package/components/identity.bans/operations/transit.d.ts +0 -14
  535. package/components/identity.bans/operations/transit.js.map +0 -1
  536. package/components/identity.basic/operations/add.d.ts +0 -3
  537. package/components/identity.basic/operations/add.js.map +0 -1
  538. package/components/identity.basic/operations/authenticate.d.ts +0 -13
  539. package/components/identity.basic/operations/authenticate.js.map +0 -1
  540. package/components/identity.basic/operations/check.d.ts +0 -7
  541. package/components/identity.basic/operations/check.js.map +0 -1
  542. package/components/identity.basic/operations/delete.d.ts +0 -7
  543. package/components/identity.basic/operations/delete.js.map +0 -1
  544. package/components/identity.basic/operations/incept.d.ts +0 -12
  545. package/components/identity.basic/operations/incept.js.map +0 -1
  546. package/components/identity.basic/operations/info.d.ts +0 -10
  547. package/components/identity.basic/operations/info.js.map +0 -1
  548. package/components/identity.basic/operations/lib/credentials.d.ts +0 -5
  549. package/components/identity.basic/operations/lib/credentials.js.map +0 -1
  550. package/components/identity.basic/operations/transit.d.ts +0 -14
  551. package/components/identity.basic/operations/transit.js.map +0 -1
  552. package/components/identity.basic/operations/types.d.ts +0 -61
  553. package/components/identity.basic/operations/types.js +0 -2
  554. package/components/identity.basic/operations/types.js.map +0 -1
  555. package/components/identity.basic/source/types.ts +0 -69
  556. package/components/identity.credentials/operations/list.d.ts +0 -51
  557. package/components/identity.credentials/operations/list.js.map +0 -1
  558. package/components/identity.federation/operations/authenticate.d.ts +0 -16
  559. package/components/identity.federation/operations/authenticate.js.map +0 -1
  560. package/components/identity.federation/operations/create.d.ts +0 -8
  561. package/components/identity.federation/operations/create.js.map +0 -1
  562. package/components/identity.federation/operations/decode.d.ts +0 -3
  563. package/components/identity.federation/operations/decode.js.map +0 -1
  564. package/components/identity.federation/operations/delete.d.ts +0 -8
  565. package/components/identity.federation/operations/delete.js.map +0 -1
  566. package/components/identity.federation/operations/incept.d.ts +0 -11
  567. package/components/identity.federation/operations/incept.js.map +0 -1
  568. package/components/identity.federation/operations/lib/Configuration.d.ts +0 -39
  569. package/components/identity.federation/operations/lib/Configuration.js.map +0 -1
  570. package/components/identity.federation/operations/lib/Ctx.d.ts +0 -8
  571. package/components/identity.federation/operations/lib/Ctx.js.map +0 -1
  572. package/components/identity.federation/operations/lib/Payload.d.ts +0 -5
  573. package/components/identity.federation/operations/lib/Payload.js.map +0 -1
  574. package/components/identity.federation/operations/lib/decode.d.ts +0 -3
  575. package/components/identity.federation/operations/lib/decode.js.map +0 -1
  576. package/components/identity.federation/operations/lib/discovery.d.ts +0 -5
  577. package/components/identity.federation/operations/lib/discovery.js.map +0 -1
  578. package/components/identity.federation/operations/lib/errors.d.ts +0 -70
  579. package/components/identity.federation/operations/lib/errors.js.map +0 -1
  580. package/components/identity.federation/operations/lib/exchange.d.ts +0 -3
  581. package/components/identity.federation/operations/lib/exchange.js.map +0 -1
  582. package/components/identity.federation/operations/lib/index.d.ts +0 -4
  583. package/components/identity.federation/operations/lib/index.js.map +0 -1
  584. package/components/identity.federation/operations/lib/jose.d.ts +0 -1
  585. package/components/identity.federation/operations/lib/jose.js.map +0 -1
  586. package/components/identity.federation/operations/lib/resolve.d.ts +0 -3
  587. package/components/identity.federation/operations/lib/resolve.js.map +0 -1
  588. package/components/identity.federation/operations/list.d.ts +0 -7
  589. package/components/identity.federation/operations/list.js.map +0 -1
  590. package/components/identity.federation/operations/types/Scheme.d.ts +0 -1
  591. package/components/identity.federation/operations/types/Scheme.js.map +0 -1
  592. package/components/identity.federation/operations/types/configuration.d.ts +0 -22
  593. package/components/identity.federation/operations/types/configuration.js.map +0 -1
  594. package/components/identity.federation/operations/types/context.d.ts +0 -35
  595. package/components/identity.federation/operations/types/context.js.map +0 -1
  596. package/components/identity.federation/operations/types/entity.d.ts +0 -9
  597. package/components/identity.federation/operations/types/entity.js.map +0 -1
  598. package/components/identity.federation/operations/types/index.d.ts +0 -4
  599. package/components/identity.federation/operations/types/index.js.map +0 -1
  600. package/components/identity.keys/operations/create.d.ts +0 -22
  601. package/components/identity.keys/operations/create.js.map +0 -1
  602. package/components/identity.keys/operations/disable.d.ts +0 -5
  603. package/components/identity.keys/operations/disable.js.map +0 -1
  604. package/components/identity.keys/operations/revoke.d.ts +0 -15
  605. package/components/identity.keys/operations/revoke.js.map +0 -1
  606. package/components/identity.otp/operations/authenticate.d.ts +0 -12
  607. package/components/identity.otp/operations/authenticate.js.map +0 -1
  608. package/components/identity.otp/operations/issue.d.ts +0 -12
  609. package/components/identity.otp/operations/issue.js.map +0 -1
  610. package/components/identity.otp/operations/lib/Context.d.ts +0 -14
  611. package/components/identity.otp/operations/lib/Context.js.map +0 -1
  612. package/components/identity.otp/operations/lib/Entity.d.ts +0 -6
  613. package/components/identity.otp/operations/lib/Entity.js.map +0 -1
  614. package/components/identity.otp/operations/lib/index.d.ts +0 -1
  615. package/components/identity.otp/operations/lib/index.js.map +0 -1
  616. package/components/identity.passkeys/operations/authenticate.d.ts +0 -16
  617. package/components/identity.passkeys/operations/authenticate.js.map +0 -1
  618. package/components/identity.passkeys/operations/challenge.d.ts +0 -35
  619. package/components/identity.passkeys/operations/challenge.js.map +0 -1
  620. package/components/identity.passkeys/operations/create.d.ts +0 -19
  621. package/components/identity.passkeys/operations/create.js.map +0 -1
  622. package/components/identity.passkeys/operations/delete.d.ts +0 -8
  623. package/components/identity.passkeys/operations/delete.js.map +0 -1
  624. package/components/identity.passkeys/operations/lib/const.d.ts +0 -1
  625. package/components/identity.passkeys/operations/lib/const.js.map +0 -1
  626. package/components/identity.passkeys/operations/list.d.ts +0 -7
  627. package/components/identity.passkeys/operations/list.js.map +0 -1
  628. package/components/identity.passkeys/operations/types/Configuration.d.ts +0 -6
  629. package/components/identity.passkeys/operations/types/Configuration.js.map +0 -1
  630. package/components/identity.passkeys/operations/types/Context.d.ts +0 -15
  631. package/components/identity.passkeys/operations/types/Context.js.map +0 -1
  632. package/components/identity.passkeys/operations/types/Passkey.d.ts +0 -12
  633. package/components/identity.passkeys/operations/types/Passkey.js.map +0 -1
  634. package/components/identity.passkeys/operations/types/index.d.ts +0 -2
  635. package/components/identity.passkeys/operations/types/index.js.map +0 -1
  636. package/components/identity.passkeys/operations/use.d.ts +0 -16
  637. package/components/identity.passkeys/operations/use.js.map +0 -1
  638. package/components/identity.roles/operations/grant.d.ts +0 -10
  639. package/components/identity.roles/operations/grant.js.map +0 -1
  640. package/components/identity.roles/operations/lib/Entity.d.ts +0 -5
  641. package/components/identity.roles/operations/lib/Entity.js.map +0 -1
  642. package/components/identity.roles/operations/list.d.ts +0 -2
  643. package/components/identity.roles/operations/list.js.map +0 -1
  644. package/components/identity.roles/operations/principal.d.ts +0 -13
  645. package/components/identity.roles/operations/principal.js.map +0 -1
  646. package/components/identity.tokens/operations/authenticate.d.ts +0 -9
  647. package/components/identity.tokens/operations/authenticate.js.map +0 -1
  648. package/components/identity.tokens/operations/decrypt.d.ts +0 -15
  649. package/components/identity.tokens/operations/decrypt.js.map +0 -1
  650. package/components/identity.tokens/operations/encrypt.d.ts +0 -8
  651. package/components/identity.tokens/operations/encrypt.js.map +0 -1
  652. package/components/identity.tokens/operations/issue.d.ts +0 -24
  653. package/components/identity.tokens/operations/issue.js.map +0 -1
  654. package/components/identity.tokens/operations/lib/index.d.ts +0 -3
  655. package/components/identity.tokens/operations/lib/index.js.map +0 -1
  656. package/components/identity.tokens/operations/lib/jose.d.ts +0 -1
  657. package/components/identity.tokens/operations/lib/jose.js.map +0 -1
  658. package/components/identity.tokens/operations/lib/key.d.ts +0 -1
  659. package/components/identity.tokens/operations/lib/key.js.map +0 -1
  660. package/components/identity.tokens/operations/lib/pad.d.ts +0 -1
  661. package/components/identity.tokens/operations/lib/pad.js.map +0 -1
  662. package/components/identity.tokens/operations/lib/types.d.ts +0 -88
  663. package/components/identity.tokens/operations/lib/types.js +0 -2
  664. package/components/identity.tokens/operations/lib/types.js.map +0 -1
  665. package/components/identity.tokens/operations/revoke.d.ts +0 -2
  666. package/components/identity.tokens/operations/revoke.js.map +0 -1
  667. package/components/identity.tokens/source/lib/types.ts +0 -102
@@ -0,0 +1,65 @@
1
+ import { ERR_UNKNOWN_CLIENT, permits, read } from './lib/index.js'
2
+ import type { Maybe } from '@toa.io/core'
3
+ import type { Operation } from '@toa.io/bridges.node'
4
+ import type { Client, Context } from './lib/index.js'
5
+
6
+ /**
7
+ * What a client is, whichever way it came to be known: a `client_id` that is an https URL
8
+ * publishes its own metadata, and anything else was registered here. The caller is not told
9
+ * which, and neither mechanism is visible past this operation.
10
+ *
11
+ * Whether a redirect is one the client may receive a code at is answered here too. The rule
12
+ * is this component's — nothing else knows a loopback port is ignored — and asking for it
13
+ * with the client saves a second call on the path a person is waiting on.
14
+ */
15
+ export class Computation implements Operation {
16
+ private context!: Context
17
+
18
+ public mount (context: Context): void {
19
+ this.context = context
20
+ }
21
+
22
+ public async execute (input: Input): Promise<Maybe<Output>> {
23
+ const client = input.id.startsWith(HTTPS)
24
+ ? await read(input.id, this.context)
25
+ : await this.registered(input)
26
+
27
+ if (client instanceof Error)
28
+ return client
29
+
30
+ return {
31
+ ...client,
32
+ ...(input.redirect === undefined
33
+ ? {}
34
+ : { permitted: permits(client.redirect_uris, input.redirect) })
35
+ }
36
+ }
37
+
38
+ private async registered (input: Input): Promise<Client | Error> {
39
+ const entity = await this.context.local.observe({ query: { id: input.id } })
40
+
41
+ // credentials are scoped to an authority, and so is what may act for them
42
+ if (entity === null || entity.authority !== input.authority)
43
+ return ERR_UNKNOWN_CLIENT
44
+
45
+ return {
46
+ client_id: entity.id,
47
+ client_name: entity.name,
48
+ client_uri: entity.uri,
49
+ logo_uri: entity.logo,
50
+ redirect_uris: entity.uris
51
+ }
52
+ }
53
+ }
54
+
55
+ const HTTPS = 'https://'
56
+
57
+ interface Input {
58
+ authority: string
59
+ id: string
60
+ redirect?: string
61
+ }
62
+
63
+ interface Output extends Client {
64
+ permitted?: boolean
65
+ }
@@ -0,0 +1,38 @@
1
+ import type { Call, Observation, Transition } from '@toa.io/core'
2
+ import type { Stash } from '@toa.io/extensions.stash'
3
+ import type { Logs } from '@toa.io/extensions.telemetry'
4
+ import type { Entity } from './Entity.js'
5
+
6
+ export interface Context {
7
+ stash: Stash
8
+ fetch: Fetch
9
+ logs: Logs
10
+ local: {
11
+ observe: Observation<Entity>
12
+ transit: Call<Entity, TransitInput>
13
+ }
14
+ configuration: Configuration
15
+ }
16
+
17
+ export type Fetch = (input: string | URL | Request, init?: RequestInit) => Promise<Response>
18
+
19
+ export type TransitInput = Omit<Entity, 'id' | '_created'>
20
+
21
+ export interface Configuration {
22
+ /** Origins whose Client ID Metadata Documents may be read. Empty admits nobody. */
23
+ readonly trust: string[]
24
+
25
+ /** Seconds a document is held before it is read again. */
26
+ readonly lifetime: number
27
+
28
+ /** Seconds a registration nothing has used is kept. */
29
+ readonly ttl: number
30
+
31
+ /** Bytes of a document that are read. */
32
+ readonly size: number
33
+
34
+ /** Milliseconds a document has to arrive. */
35
+ readonly timeout: number
36
+ }
37
+
38
+ export type { Transition }
@@ -0,0 +1,31 @@
1
+ export interface Entity {
2
+ id: string
3
+ authority: string
4
+ name?: string
5
+ uris: string[]
6
+ uri?: string
7
+ logo?: string
8
+ scope?: string
9
+ expires?: number
10
+ _created?: number
11
+ }
12
+
13
+ /** What a client says about itself, in the shape both mechanisms carry it. */
14
+ export interface Metadata {
15
+ client_name?: string
16
+ client_uri?: string
17
+ logo_uri?: string
18
+ redirect_uris: string[]
19
+ scope?: string
20
+ token_endpoint_auth_method?: string
21
+ }
22
+
23
+ /** A client, however it came to be known. */
24
+ export interface Client {
25
+ client_id: string
26
+ client_name?: string
27
+ client_uri?: string
28
+ logo_uri?: string
29
+ redirect_uris: string[]
30
+ issued?: number
31
+ }
@@ -0,0 +1,43 @@
1
+ import { it } from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+
4
+ import { identify } from './canonical.js'
5
+ import type { Metadata } from './Entity.js'
6
+
7
+ const metadata: Metadata = {
8
+ client_name: 'Claude',
9
+ redirect_uris: ['https://claude.ai/api/mcp/auth_callback', 'http://localhost/callback']
10
+ }
11
+
12
+ it('should be the id the entity accepts', () => {
13
+ assert.match(identify('nex', metadata), /^[a-f0-9]{32}$/)
14
+ })
15
+
16
+ it('should give the same client the same id, however many times it registers', () => {
17
+ assert.equal(identify('nex', metadata), identify('nex', { ...metadata }))
18
+ })
19
+
20
+ it('should not depend on the order the redirects were written in', () => {
21
+ const reordered = { ...metadata, redirect_uris: [...metadata.redirect_uris].reverse() }
22
+
23
+ assert.equal(identify('nex', metadata), identify('nex', reordered))
24
+ })
25
+
26
+ it('should not depend on what is not honoured', () => {
27
+ const noisy = { ...metadata, token_endpoint_auth_method: 'none' } as Metadata
28
+
29
+ assert.equal(identify('nex', metadata), identify('nex', noisy))
30
+ })
31
+
32
+ it('should separate authorities, which credentials are scoped to', () => {
33
+ assert.notEqual(identify('nex', metadata), identify('other', metadata))
34
+ })
35
+
36
+ it('should separate what differs', () => {
37
+ for (const changed of [
38
+ { ...metadata, client_name: 'Not Claude' },
39
+ { ...metadata, redirect_uris: ['https://claude.ai/api/mcp/auth_callback'] },
40
+ { ...metadata, scope: 'app:notes' }
41
+ ])
42
+ assert.notEqual(identify('nex', metadata), identify('nex', changed))
43
+ })
@@ -0,0 +1,27 @@
1
+ import { createHash } from 'node:crypto'
2
+ import type { Metadata } from './Entity.js'
3
+
4
+ /**
5
+ * The id of a registration: a hash of what it says, so identical metadata is one client
6
+ * however many times it arrives. A client cannot remember that it registered here, and
7
+ * registers again on every fresh connection; without this the registry only grows.
8
+ *
9
+ * Only what is honoured is hashed. A field this component ignores would otherwise mint a
10
+ * client per release of whoever sends it, and the authority is in there because credentials
11
+ * are scoped to one.
12
+ */
13
+ export function identify (authority: string, metadata: Metadata): string {
14
+ const canonical = JSON.stringify([
15
+ authority,
16
+ metadata.client_name ?? null,
17
+ metadata.client_uri ?? null,
18
+ metadata.logo_uri ?? null,
19
+ metadata.scope ?? null,
20
+ [...metadata.redirect_uris].sort()
21
+ ])
22
+
23
+ return createHash('sha256').update(canonical).digest('hex').slice(0, LENGTH)
24
+ }
25
+
26
+ /** What the entity prototype accepts as an id. */
27
+ const LENGTH = 32
@@ -0,0 +1,120 @@
1
+ import { it, beforeEach, mock } from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+
4
+ import { read } from './cimd.js'
5
+ import type { Context } from './Context.js'
6
+
7
+ const ID = 'https://claude.ai/oauth/claude-code-client-metadata'
8
+
9
+ const document = {
10
+ client_id: ID,
11
+ client_name: 'Claude Code',
12
+ redirect_uris: ['http://localhost/callback', 'http://127.0.0.1/callback']
13
+ }
14
+
15
+ let context: Context
16
+ let fetched: string[]
17
+ let stored: Record<string, string>
18
+
19
+ function respond (body: unknown, ok = true): Response {
20
+ return {
21
+ ok,
22
+ text: async () => JSON.stringify(body)
23
+ } as unknown as Response
24
+ }
25
+
26
+ beforeEach(() => {
27
+ fetched = []
28
+ stored = {}
29
+
30
+ context = {
31
+ configuration: {
32
+ trust: ['https://claude.ai'],
33
+ lifetime: 3600,
34
+ ttl: 2592000,
35
+ size: 16384,
36
+ timeout: 3000
37
+ },
38
+ stash: {
39
+ get: mock.fn(async (key: string) => stored[key] ?? null),
40
+ set: mock.fn(async (key: string, value: string) => {
41
+ stored[key] = value
42
+ })
43
+ },
44
+ fetch: mock.fn(async (input: string) => {
45
+ fetched.push(input)
46
+
47
+ return respond(document)
48
+ }),
49
+ logs: { debug: mock.fn() }
50
+ } as unknown as Context
51
+ })
52
+
53
+ it('should read what the client publishes', async () => {
54
+ const client = await read(ID, context)
55
+
56
+ assert.deepEqual(client, {
57
+ client_id: ID,
58
+ client_name: 'Claude Code',
59
+ client_uri: undefined,
60
+ logo_uri: undefined,
61
+ redirect_uris: document.redirect_uris
62
+ })
63
+ })
64
+
65
+ it('should hold it, rather than read it per request', async () => {
66
+ await read(ID, context)
67
+ await read(ID, context)
68
+
69
+ assert.equal(fetched.length, 1)
70
+ })
71
+
72
+ it('should not reach an origin the configuration does not name', async () => {
73
+ const client = await read('https://evil.example/metadata', context)
74
+
75
+ assert.ok(client instanceof Error)
76
+ assert.equal(fetched.length, 0, 'an untrusted origin must not be fetched at all')
77
+ })
78
+
79
+ it('should not reach a host that merely starts like a trusted one', async () => {
80
+ const client = await read('https://claude.ai.evil.example/metadata', context)
81
+
82
+ assert.ok(client instanceof Error)
83
+ assert.equal(fetched.length, 0)
84
+ })
85
+
86
+ it('should refuse anything but https', async () => {
87
+ for (const id of ['http://claude.ai/metadata', 'file:///etc/passwd', 'not a url']) {
88
+ const client = await read(id, context)
89
+
90
+ assert.ok(client instanceof Error, id)
91
+ }
92
+
93
+ assert.equal(fetched.length, 0)
94
+ })
95
+
96
+ it('should refuse a document that names another client', async () => {
97
+ context.fetch = mock.fn(async () => respond({ ...document, client_id: 'https://claude.ai/other' }))
98
+
99
+ assert.ok(await read(ID, context) instanceof Error)
100
+ })
101
+
102
+ it('should refuse a document with no redirect to send a code to', async () => {
103
+ context.fetch = mock.fn(async () => respond({ client_id: ID, redirect_uris: [] }))
104
+
105
+ assert.ok(await read(ID, context) instanceof Error)
106
+ })
107
+
108
+ it('should remember that a document did not answer', async () => {
109
+ let calls = 0
110
+
111
+ context.fetch = mock.fn(async () => {
112
+ calls++
113
+
114
+ return respond({}, false)
115
+ })
116
+
117
+ assert.ok(await read(ID, context) instanceof Error)
118
+ assert.ok(await read(ID, context) instanceof Error)
119
+ assert.equal(calls, 1, 'a document that failed must not be refetched per request')
120
+ })
@@ -0,0 +1,107 @@
1
+ import { createHash } from 'node:crypto'
2
+ import { ERR_UNKNOWN_CLIENT } from './errors.js'
3
+ import type { Context } from './Context.js'
4
+ import type { Client, Metadata } from './Entity.js'
5
+
6
+ /**
7
+ * A Client ID Metadata Document: the client publishes what it is at an https URL, and that
8
+ * URL is its `client_id`. Control of the origin is what proves the identity, so nothing is
9
+ * registered and nothing is written — the document is read and held for a while.
10
+ */
11
+ export async function read (id: string, context: Context): Promise<Client | Error> {
12
+ // before anything is fetched: the id is the caller's to choose, and this runs inside
13
+ // the cluster. An origin the configuration does not name is not reached at all.
14
+ if (!trusted(id, context.configuration.trust))
15
+ return ERR_UNKNOWN_CLIENT
16
+
17
+ const key = CACHE + createHash('sha256').update(id).digest('hex')
18
+ const cached = await context.stash.get(key)
19
+
20
+ if (cached !== null)
21
+ return cached === MISS ? ERR_UNKNOWN_CLIENT : JSON.parse(cached) as Client
22
+
23
+ const client = await fetch(id, context)
24
+
25
+ // a document that does not answer is remembered too, or a bad id is fetched per request
26
+ await context.stash.set(key, client instanceof Error ? MISS : JSON.stringify(client),
27
+ 'EX', context.configuration.lifetime)
28
+
29
+ return client
30
+ }
31
+
32
+ /**
33
+ * An https URL whose origin the configuration names. Compared by origin so that a path on a
34
+ * trusted host cannot be escaped by one that merely starts the same way.
35
+ */
36
+ function trusted (id: string, trust: string[]): boolean {
37
+ let url: URL
38
+
39
+ try {
40
+ url = new URL(id)
41
+ } catch {
42
+ return false
43
+ }
44
+
45
+ if (url.protocol !== 'https:')
46
+ return false
47
+
48
+ return trust.some((origin) => {
49
+ try {
50
+ return new URL(origin).origin === url.origin
51
+ } catch {
52
+ return false
53
+ }
54
+ })
55
+ }
56
+
57
+ async function fetch (id: string, context: Context): Promise<Client | Error> {
58
+ const { size, timeout } = context.configuration
59
+
60
+ try {
61
+ const response = await context.fetch(id, {
62
+ redirect: 'error', // a redirect leaves the origin that was trusted
63
+ signal: AbortSignal.timeout(timeout),
64
+ headers: { accept: 'application/json' }
65
+ })
66
+
67
+ if (!response.ok)
68
+ return ERR_UNKNOWN_CLIENT
69
+
70
+ const text = await response.text()
71
+
72
+ if (text.length > size)
73
+ return ERR_UNKNOWN_CLIENT
74
+
75
+ return validate(id, JSON.parse(text) as Metadata & { client_id?: string })
76
+ } catch (error: unknown) {
77
+ context.logs.debug('Client metadata document is unreadable', {
78
+ client: id,
79
+ error: error?.toString?.()
80
+ })
81
+
82
+ return ERR_UNKNOWN_CLIENT
83
+ }
84
+ }
85
+
86
+ function validate (id: string, metadata: Metadata & { client_id?: string }): Client | Error {
87
+ // the document names itself, so one client's cannot claim another's identity
88
+ if (metadata.client_id !== id)
89
+ return ERR_UNKNOWN_CLIENT
90
+
91
+ if (!Array.isArray(metadata.redirect_uris) || metadata.redirect_uris.length === 0 ||
92
+ metadata.redirect_uris.some((uri) => typeof uri !== 'string'))
93
+ return ERR_UNKNOWN_CLIENT
94
+
95
+ return {
96
+ client_id: id,
97
+ client_name: metadata.client_name,
98
+ client_uri: metadata.client_uri,
99
+ logo_uri: metadata.logo_uri,
100
+ redirect_uris: metadata.redirect_uris
101
+ }
102
+ }
103
+
104
+ const CACHE = 'cimd:'
105
+
106
+ /** Held in place of a document that could not be read, so a bad id is not refetched. */
107
+ const MISS = ''
@@ -0,0 +1,4 @@
1
+ export const ERR_UNKNOWN_CLIENT = new (class UnknownClientError extends Error {
2
+ public readonly code = 'UNKNOWN_CLIENT'
3
+ public override readonly message = 'No such client'
4
+ })()
@@ -0,0 +1,6 @@
1
+ export * from './canonical.js'
2
+ export * from './cimd.js'
3
+ export * from './Context.js'
4
+ export * from './Entity.js'
5
+ export * from './errors.js'
6
+ export * from './redirect.js'
@@ -0,0 +1,41 @@
1
+ import { it } from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+
4
+ import { permits } from './redirect.js'
5
+
6
+ const hosted = ['https://claude.ai/api/mcp/auth_callback']
7
+ const native = ['http://localhost/callback', 'http://127.0.0.1/callback']
8
+
9
+ it('should permit an exact match', () => {
10
+ assert.equal(permits(hosted, 'https://claude.ai/api/mcp/auth_callback'), true)
11
+ })
12
+
13
+ it('should refuse anything else on a registered host', () => {
14
+ assert.equal(permits(hosted, 'https://claude.ai/api/mcp/auth_callback/x'), false)
15
+ assert.equal(permits(hosted, 'https://claude.ai/'), false)
16
+ })
17
+
18
+ it('should refuse a host that merely starts the same way', () => {
19
+ assert.equal(permits(hosted, 'https://claude.ai.evil.example/api/mcp/auth_callback'), false)
20
+ })
21
+
22
+ it('should ignore the port of a loopback address', () => {
23
+ for (const redirect of [
24
+ 'http://localhost:3118/callback',
25
+ 'http://localhost:51234/callback',
26
+ 'http://127.0.0.1:3118/callback'
27
+ ])
28
+ assert.equal(permits(native, redirect), true)
29
+ })
30
+
31
+ it('should not ignore the path of a loopback address', () => {
32
+ assert.equal(permits(native, 'http://localhost:3118/stolen'), false)
33
+ })
34
+
35
+ it('should not treat a remote address as loopback', () => {
36
+ assert.equal(permits(['http://example.com/callback'], 'http://example.com:8080/callback'), false)
37
+ })
38
+
39
+ it('should not cross schemes', () => {
40
+ assert.equal(permits(native, 'https://localhost:3118/callback'), false)
41
+ })
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Whether a client may receive a code at this address.
3
+ *
4
+ * Exact string comparison, which RFC 6749 §3.1.2.3 requires, except for a loopback
5
+ * address: a native client binds whatever port is free when it starts, so RFC 8252 §7.3
6
+ * has the port ignored there. Claude Code registers `http://localhost/callback` and
7
+ * `http://127.0.0.1/callback` and comes back on an ephemeral port; comparing those
8
+ * literally would refuse every one of them.
9
+ */
10
+ export function permits (registered: string[], redirect: string): boolean {
11
+ return registered.some((uri) => uri === redirect || loopback(uri, redirect))
12
+ }
13
+
14
+ function loopback (registered: string, redirect: string): boolean {
15
+ const a = parse(registered)
16
+ const b = parse(redirect)
17
+
18
+ if (a === null || b === null)
19
+ return false
20
+
21
+ return a.protocol === 'http:' && b.protocol === 'http:' &&
22
+ LOOPBACK.has(a.hostname) && a.hostname === b.hostname &&
23
+ a.pathname === b.pathname && a.search === b.search
24
+ }
25
+
26
+ function parse (value: string): URL | null {
27
+ try {
28
+ return new URL(value)
29
+ } catch {
30
+ return null
31
+ }
32
+ }
33
+
34
+ /** `localhost` resolves through the host's own configuration, which RFC 8252 §8.3 warns of. */
35
+ const LOOPBACK = new Set(['127.0.0.1', '[::1]', 'localhost'])
@@ -0,0 +1,125 @@
1
+ import { identify } from './lib/index.js'
2
+ import type { Maybe } from '@toa.io/core'
3
+ import type { Operation } from '@toa.io/bridges.node'
4
+ import type { Context, Metadata } from './lib/index.js'
5
+
6
+ /**
7
+ * Dynamic Client Registration, RFC 7591: the client sends what it is and is given an
8
+ * identifier for it. Unauthenticated, as the specification has it — a registration grants
9
+ * nothing on its own, and stays inert until a user consents to the client on a page that
10
+ * shows them its name and where it would send them.
11
+ *
12
+ * The identifier is a hash of the metadata, so registering the same thing twice is the
13
+ * same client rather than another row. A client cannot remember it registered here.
14
+ */
15
+ export class Effect implements Operation {
16
+ private transit!: Context['local']['transit']
17
+ private ttl!: number
18
+
19
+ public mount (context: Context): void {
20
+ this.transit = context.local.transit
21
+ this.ttl = context.configuration.ttl
22
+ }
23
+
24
+ public async execute (input: Input): Promise<Maybe<Output>> {
25
+ const { authority } = input
26
+
27
+ if (input.token_endpoint_auth_method !== undefined &&
28
+ input.token_endpoint_auth_method !== 'none')
29
+ return invalid('invalid_client_metadata',
30
+ 'Only public clients are supported: token_endpoint_auth_method must be `none`')
31
+
32
+ const uris = input.redirect_uris.map(normalize)
33
+
34
+ for (const uri of uris)
35
+ if (uri instanceof Error)
36
+ return invalid('invalid_redirect_uri', uri.message)
37
+
38
+ const metadata: Metadata = {
39
+ client_name: input.client_name,
40
+ client_uri: input.client_uri,
41
+ logo_uri: input.logo_uri,
42
+ scope: input.scope,
43
+ redirect_uris: uris as string[]
44
+ }
45
+
46
+ const id = identify(authority, metadata)
47
+
48
+ const entity = await this.transit({
49
+ query: { id },
50
+ input: {
51
+ authority,
52
+ name: metadata.client_name,
53
+ uri: metadata.client_uri,
54
+ logo: metadata.logo_uri,
55
+ scope: metadata.scope,
56
+ uris: metadata.redirect_uris,
57
+ expires: Date.now() + this.ttl * 1000
58
+ }
59
+ })
60
+
61
+ return {
62
+ client_id: id,
63
+ // of the record, not of this request: registering again answers what it answered
64
+ client_id_issued_at: Math.floor((entity._created ?? Date.now()) / 1000),
65
+ client_name: entity.name,
66
+ client_uri: entity.uri,
67
+ logo_uri: entity.logo,
68
+ redirect_uris: entity.uris,
69
+ grant_types: ['authorization_code'],
70
+ response_types: ['code'],
71
+ token_endpoint_auth_method: 'none'
72
+ }
73
+ }
74
+ }
75
+
76
+ /** Absolute, no fragment, and either https or a loopback address (RFC 8252 §7.3). */
77
+ function normalize (value: string): string | Error {
78
+ let url: URL
79
+
80
+ try {
81
+ url = new URL(value)
82
+ } catch {
83
+ return new Error(`\`${value}\` is not an absolute URI`)
84
+ }
85
+
86
+ if (url.hash !== '')
87
+ return new Error(`\`${value}\` carries a fragment`)
88
+
89
+ if (url.protocol === 'https:')
90
+ return url.href
91
+
92
+ if (url.protocol === 'http:' && LOOPBACK.has(url.hostname))
93
+ return url.href
94
+
95
+ return new Error(`\`${value}\` is neither https nor a loopback address`)
96
+ }
97
+
98
+ /** RFC 7591 §3.2.2: a registration error is a body, and `map:status` makes it the status. */
99
+ function invalid (error: string, description: string): Output {
100
+ return { status: BAD_REQUEST, error, error_description: description }
101
+ }
102
+
103
+ const BAD_REQUEST = 400
104
+
105
+ const LOOPBACK = new Set(['127.0.0.1', '[::1]', 'localhost'])
106
+
107
+ interface Input extends Metadata {
108
+ authority: string
109
+ }
110
+
111
+ interface Output {
112
+ /** Read and removed by `map:status`; absent on a success, which answers 201. */
113
+ status?: number
114
+ client_id?: string
115
+ client_id_issued_at?: number
116
+ client_name?: string
117
+ client_uri?: string
118
+ logo_uri?: string
119
+ redirect_uris?: string[]
120
+ grant_types?: string[]
121
+ response_types?: string[]
122
+ token_endpoint_auth_method?: string
123
+ error?: string
124
+ error_description?: string
125
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "../../../../tsconfig.component.json",
3
+ "compilerOptions": {
4
+ "outDir": "./operations",
5
+ "rootDir": "./source"
6
+ },
7
+ "include": [
8
+ "source"
9
+ ]
10
+ }