@aeolus-fleet/gateway 0.0.0-stage → 0.0.0

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 (474) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +104 -2
  3. package/dist/adapters/crypto/call-keys.d.ts +7 -0
  4. package/dist/adapters/crypto/call-keys.js +18 -0
  5. package/dist/adapters/crypto/call-keys.js.map +1 -0
  6. package/dist/adapters/crypto/oauth-secrets.d.ts +3 -0
  7. package/dist/adapters/crypto/oauth-secrets.js +10 -0
  8. package/dist/adapters/crypto/oauth-secrets.js.map +1 -0
  9. package/dist/adapters/crypto/request-hasher.d.ts +3 -0
  10. package/dist/adapters/crypto/request-hasher.js +4 -0
  11. package/dist/adapters/crypto/request-hasher.js.map +1 -0
  12. package/dist/adapters/crypto/request-ids.d.ts +4 -0
  13. package/dist/adapters/crypto/request-ids.js +14 -0
  14. package/dist/adapters/crypto/request-ids.js.map +1 -0
  15. package/dist/adapters/crypto/sealer.d.ts +14 -0
  16. package/dist/adapters/crypto/sealer.js +41 -0
  17. package/dist/adapters/crypto/sealer.js.map +1 -0
  18. package/dist/adapters/crypto/ship-aliases.d.ts +7 -0
  19. package/dist/adapters/crypto/ship-aliases.js +19 -0
  20. package/dist/adapters/crypto/ship-aliases.js.map +1 -0
  21. package/dist/adapters/crypto/sign-in-seals.d.ts +7 -0
  22. package/dist/adapters/crypto/sign-in-seals.js +27 -0
  23. package/dist/adapters/crypto/sign-in-seals.js.map +1 -0
  24. package/dist/adapters/crypto/waiting-seals.d.ts +3 -0
  25. package/dist/adapters/crypto/waiting-seals.js +24 -0
  26. package/dist/adapters/crypto/waiting-seals.js.map +1 -0
  27. package/dist/adapters/fleet/console-sessions.d.ts +2 -0
  28. package/dist/adapters/fleet/console-sessions.js +23 -0
  29. package/dist/adapters/fleet/console-sessions.js.map +1 -0
  30. package/dist/adapters/fleet/core-version.d.ts +11 -0
  31. package/dist/adapters/fleet/core-version.js +59 -0
  32. package/dist/adapters/fleet/core-version.js.map +1 -0
  33. package/dist/adapters/fleet/fleet-network.d.ts +2 -0
  34. package/dist/adapters/fleet/fleet-network.js +44 -0
  35. package/dist/adapters/fleet/fleet-network.js.map +1 -0
  36. package/dist/adapters/fleet/rest-fleet-door.d.ts +14 -0
  37. package/dist/adapters/fleet/rest-fleet-door.js +189 -0
  38. package/dist/adapters/fleet/rest-fleet-door.js.map +1 -0
  39. package/dist/adapters/http/html.d.ts +15 -0
  40. package/dist/adapters/http/html.js +53 -0
  41. package/dist/adapters/http/html.js.map +1 -0
  42. package/dist/adapters/http/live.d.ts +29 -0
  43. package/dist/adapters/http/live.js +100 -0
  44. package/dist/adapters/http/live.js.map +1 -0
  45. package/dist/adapters/http/mcp-endpoint.d.ts +20 -0
  46. package/dist/adapters/http/mcp-endpoint.js +164 -0
  47. package/dist/adapters/http/mcp-endpoint.js.map +1 -0
  48. package/dist/adapters/http/mcp-task.d.ts +45 -0
  49. package/dist/adapters/http/mcp-task.js +35 -0
  50. package/dist/adapters/http/mcp-task.js.map +1 -0
  51. package/dist/adapters/http/oauth-routes.d.ts +35 -0
  52. package/dist/adapters/http/oauth-routes.js +305 -0
  53. package/dist/adapters/http/oauth-routes.js.map +1 -0
  54. package/dist/adapters/http/outside-parties-page.d.ts +6 -0
  55. package/dist/adapters/http/outside-parties-page.js +149 -0
  56. package/dist/adapters/http/outside-parties-page.js.map +1 -0
  57. package/dist/adapters/http/overview-page.d.ts +16 -0
  58. package/dist/adapters/http/overview-page.js +255 -0
  59. package/dist/adapters/http/overview-page.js.map +1 -0
  60. package/dist/adapters/http/parties-page.d.ts +6 -0
  61. package/dist/adapters/http/parties-page.js +141 -0
  62. package/dist/adapters/http/parties-page.js.map +1 -0
  63. package/dist/adapters/http/person-tools.d.ts +22 -0
  64. package/dist/adapters/http/person-tools.js +98 -0
  65. package/dist/adapters/http/person-tools.js.map +1 -0
  66. package/dist/adapters/http/signal.d.ts +52 -0
  67. package/dist/adapters/http/signal.js +220 -0
  68. package/dist/adapters/http/signal.js.map +1 -0
  69. package/dist/adapters/http/version.d.ts +6 -0
  70. package/dist/adapters/http/version.js +12 -0
  71. package/dist/adapters/http/version.js.map +1 -0
  72. package/dist/adapters/mcp/mcp-servers.d.ts +2 -0
  73. package/dist/adapters/mcp/mcp-servers.js +154 -0
  74. package/dist/adapters/mcp/mcp-servers.js.map +1 -0
  75. package/dist/adapters/oauth/client-metadata-documents.d.ts +9 -0
  76. package/dist/adapters/oauth/client-metadata-documents.js +25 -0
  77. package/dist/adapters/oauth/client-metadata-documents.js.map +1 -0
  78. package/dist/adapters/pagasae/pagasae-client.d.ts +8 -0
  79. package/dist/adapters/pagasae/pagasae-client.js +90 -0
  80. package/dist/adapters/pagasae/pagasae-client.js.map +1 -0
  81. package/dist/adapters/prisma/account-grants.d.ts +4 -0
  82. package/dist/adapters/prisma/account-grants.js +27 -0
  83. package/dist/adapters/prisma/account-grants.js.map +1 -0
  84. package/dist/adapters/prisma/calls.d.ts +4 -0
  85. package/dist/adapters/prisma/calls.js +35 -0
  86. package/dist/adapters/prisma/calls.js.map +1 -0
  87. package/dist/adapters/prisma/changes.d.ts +21 -0
  88. package/dist/adapters/prisma/changes.js +86 -0
  89. package/dist/adapters/prisma/changes.js.map +1 -0
  90. package/dist/adapters/prisma/client-calls.d.ts +4 -0
  91. package/dist/adapters/prisma/client-calls.js +50 -0
  92. package/dist/adapters/prisma/client-calls.js.map +1 -0
  93. package/dist/adapters/prisma/client.d.ts +8 -0
  94. package/dist/adapters/prisma/client.js +11 -0
  95. package/dist/adapters/prisma/client.js.map +1 -0
  96. package/dist/adapters/prisma/connection-store.d.ts +4 -0
  97. package/dist/adapters/prisma/connection-store.js +28 -0
  98. package/dist/adapters/prisma/connection-store.js.map +1 -0
  99. package/dist/adapters/prisma/fleet-forgetter.d.ts +4 -0
  100. package/dist/adapters/prisma/fleet-forgetter.js +10 -0
  101. package/dist/adapters/prisma/fleet-forgetter.js.map +1 -0
  102. package/dist/adapters/prisma/fleet-switches.d.ts +4 -0
  103. package/dist/adapters/prisma/fleet-switches.js +10 -0
  104. package/dist/adapters/prisma/fleet-switches.js.map +1 -0
  105. package/dist/adapters/prisma/generated/browser.d.ts +108 -0
  106. package/dist/adapters/prisma/generated/browser.js +18 -0
  107. package/dist/adapters/prisma/generated/browser.js.map +1 -0
  108. package/dist/adapters/prisma/generated/client.d.ts +127 -0
  109. package/dist/adapters/prisma/generated/client.js +38 -0
  110. package/dist/adapters/prisma/generated/client.js.map +1 -0
  111. package/dist/adapters/prisma/generated/commonInputTypes.d.ts +490 -0
  112. package/dist/adapters/prisma/generated/commonInputTypes.js +11 -0
  113. package/dist/adapters/prisma/generated/commonInputTypes.js.map +1 -0
  114. package/dist/adapters/prisma/generated/enums.d.ts +1 -0
  115. package/dist/adapters/prisma/generated/enums.js +12 -0
  116. package/dist/adapters/prisma/generated/enums.js.map +1 -0
  117. package/dist/adapters/prisma/generated/internal/class.d.ts +319 -0
  118. package/dist/adapters/prisma/generated/internal/class.js +50 -0
  119. package/dist/adapters/prisma/generated/internal/class.js.map +1 -0
  120. package/dist/adapters/prisma/generated/internal/prismaNamespace.d.ts +2102 -0
  121. package/dist/adapters/prisma/generated/internal/prismaNamespace.js +294 -0
  122. package/dist/adapters/prisma/generated/internal/prismaNamespace.js.map +1 -0
  123. package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.d.ts +273 -0
  124. package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.js +264 -0
  125. package/dist/adapters/prisma/generated/internal/prismaNamespaceBrowser.js.map +1 -0
  126. package/dist/adapters/prisma/generated/models/AccountGrant.d.ts +1056 -0
  127. package/dist/adapters/prisma/generated/models/AccountGrant.js +2 -0
  128. package/dist/adapters/prisma/generated/models/AccountGrant.js.map +1 -0
  129. package/dist/adapters/prisma/generated/models/AuthorizationCode.d.ts +1171 -0
  130. package/dist/adapters/prisma/generated/models/AuthorizationCode.js +2 -0
  131. package/dist/adapters/prisma/generated/models/AuthorizationCode.js.map +1 -0
  132. package/dist/adapters/prisma/generated/models/Call.d.ts +994 -0
  133. package/dist/adapters/prisma/generated/models/Call.js +2 -0
  134. package/dist/adapters/prisma/generated/models/Call.js.map +1 -0
  135. package/dist/adapters/prisma/generated/models/ClientCall.d.ts +1119 -0
  136. package/dist/adapters/prisma/generated/models/ClientCall.js +2 -0
  137. package/dist/adapters/prisma/generated/models/ClientCall.js.map +1 -0
  138. package/dist/adapters/prisma/generated/models/ClientCallReply.d.ts +1129 -0
  139. package/dist/adapters/prisma/generated/models/ClientCallReply.js +2 -0
  140. package/dist/adapters/prisma/generated/models/ClientCallReply.js.map +1 -0
  141. package/dist/adapters/prisma/generated/models/Connection.d.ts +1011 -0
  142. package/dist/adapters/prisma/generated/models/Connection.js +2 -0
  143. package/dist/adapters/prisma/generated/models/Connection.js.map +1 -0
  144. package/dist/adapters/prisma/generated/models/FleetSwitch.d.ts +945 -0
  145. package/dist/adapters/prisma/generated/models/FleetSwitch.js +2 -0
  146. package/dist/adapters/prisma/generated/models/FleetSwitch.js.map +1 -0
  147. package/dist/adapters/prisma/generated/models/InstallationRequest.d.ts +1030 -0
  148. package/dist/adapters/prisma/generated/models/InstallationRequest.js +2 -0
  149. package/dist/adapters/prisma/generated/models/InstallationRequest.js.map +1 -0
  150. package/dist/adapters/prisma/generated/models/IssuedToken.d.ts +1224 -0
  151. package/dist/adapters/prisma/generated/models/IssuedToken.js +2 -0
  152. package/dist/adapters/prisma/generated/models/IssuedToken.js.map +1 -0
  153. package/dist/adapters/prisma/generated/models/OAuthClient.d.ts +1005 -0
  154. package/dist/adapters/prisma/generated/models/OAuthClient.js +2 -0
  155. package/dist/adapters/prisma/generated/models/OAuthClient.js.map +1 -0
  156. package/dist/adapters/prisma/generated/models/OpenedDelivery.d.ts +1087 -0
  157. package/dist/adapters/prisma/generated/models/OpenedDelivery.js +2 -0
  158. package/dist/adapters/prisma/generated/models/OpenedDelivery.js.map +1 -0
  159. package/dist/adapters/prisma/generated/models/OutsidePartySwitch.d.ts +942 -0
  160. package/dist/adapters/prisma/generated/models/OutsidePartySwitch.js +2 -0
  161. package/dist/adapters/prisma/generated/models/OutsidePartySwitch.js.map +1 -0
  162. package/dist/adapters/prisma/generated/models/OwnerQuestion.d.ts +1035 -0
  163. package/dist/adapters/prisma/generated/models/OwnerQuestion.js +2 -0
  164. package/dist/adapters/prisma/generated/models/OwnerQuestion.js.map +1 -0
  165. package/dist/adapters/prisma/generated/models/Party.d.ts +1338 -0
  166. package/dist/adapters/prisma/generated/models/Party.js +2 -0
  167. package/dist/adapters/prisma/generated/models/Party.js.map +1 -0
  168. package/dist/adapters/prisma/generated/models/PendingRequest.d.ts +1252 -0
  169. package/dist/adapters/prisma/generated/models/PendingRequest.js +2 -0
  170. package/dist/adapters/prisma/generated/models/PendingRequest.js.map +1 -0
  171. package/dist/adapters/prisma/generated/models/PersonCrew.d.ts +974 -0
  172. package/dist/adapters/prisma/generated/models/PersonCrew.js +2 -0
  173. package/dist/adapters/prisma/generated/models/PersonCrew.js.map +1 -0
  174. package/dist/adapters/prisma/generated/models/RequestOutcomeNotice.d.ts +1120 -0
  175. package/dist/adapters/prisma/generated/models/RequestOutcomeNotice.js +2 -0
  176. package/dist/adapters/prisma/generated/models/RequestOutcomeNotice.js.map +1 -0
  177. package/dist/adapters/prisma/generated/models/ToolMark.d.ts +947 -0
  178. package/dist/adapters/prisma/generated/models/ToolMark.js +2 -0
  179. package/dist/adapters/prisma/generated/models/ToolMark.js.map +1 -0
  180. package/dist/adapters/prisma/generated/models.d.ts +19 -0
  181. package/dist/adapters/prisma/generated/models.js +2 -0
  182. package/dist/adapters/prisma/generated/models.js.map +1 -0
  183. package/dist/adapters/prisma/installation-requests.d.ts +4 -0
  184. package/dist/adapters/prisma/installation-requests.js +25 -0
  185. package/dist/adapters/prisma/installation-requests.js.map +1 -0
  186. package/dist/adapters/prisma/migrate.d.ts +5 -0
  187. package/dist/adapters/prisma/migrate.js +53 -0
  188. package/dist/adapters/prisma/migrate.js.map +1 -0
  189. package/dist/adapters/prisma/oauth-stores.d.ts +5 -0
  190. package/dist/adapters/prisma/oauth-stores.js +82 -0
  191. package/dist/adapters/prisma/oauth-stores.js.map +1 -0
  192. package/dist/adapters/prisma/opened-deliveries.d.ts +4 -0
  193. package/dist/adapters/prisma/opened-deliveries.js +29 -0
  194. package/dist/adapters/prisma/opened-deliveries.js.map +1 -0
  195. package/dist/adapters/prisma/outcome-notices.d.ts +4 -0
  196. package/dist/adapters/prisma/outcome-notices.js +24 -0
  197. package/dist/adapters/prisma/outcome-notices.js.map +1 -0
  198. package/dist/adapters/prisma/outside-party-switches.d.ts +4 -0
  199. package/dist/adapters/prisma/outside-party-switches.js +10 -0
  200. package/dist/adapters/prisma/outside-party-switches.js.map +1 -0
  201. package/dist/adapters/prisma/owner-questions.d.ts +8 -0
  202. package/dist/adapters/prisma/owner-questions.js +54 -0
  203. package/dist/adapters/prisma/owner-questions.js.map +1 -0
  204. package/dist/adapters/prisma/party-store.d.ts +7 -0
  205. package/dist/adapters/prisma/party-store.js +73 -0
  206. package/dist/adapters/prisma/party-store.js.map +1 -0
  207. package/dist/adapters/prisma/pending-requests.d.ts +11 -0
  208. package/dist/adapters/prisma/pending-requests.js +122 -0
  209. package/dist/adapters/prisma/pending-requests.js.map +1 -0
  210. package/dist/adapters/prisma/person-crews.d.ts +4 -0
  211. package/dist/adapters/prisma/person-crews.js +18 -0
  212. package/dist/adapters/prisma/person-crews.js.map +1 -0
  213. package/dist/adapters/prisma/tool-marks.d.ts +4 -0
  214. package/dist/adapters/prisma/tool-marks.js +15 -0
  215. package/dist/adapters/prisma/tool-marks.js.map +1 -0
  216. package/dist/adapters/timers/sleep.d.ts +3 -0
  217. package/dist/adapters/timers/sleep.js +11 -0
  218. package/dist/adapters/timers/sleep.js.map +1 -0
  219. package/dist/adapters/trpc/router.d.ts +408 -0
  220. package/dist/adapters/trpc/router.js +367 -0
  221. package/dist/adapters/trpc/router.js.map +1 -0
  222. package/dist/app.d.ts +43 -0
  223. package/dist/app.js +400 -0
  224. package/dist/app.js.map +1 -0
  225. package/dist/bin/aeolus-gateway.d.ts +2 -0
  226. package/dist/bin/aeolus-gateway.js +65 -0
  227. package/dist/bin/aeolus-gateway.js.map +1 -0
  228. package/dist/config.d.ts +41 -0
  229. package/dist/config.js +65 -0
  230. package/dist/config.js.map +1 -0
  231. package/dist/core/actors/authenticate-actor.d.ts +38 -0
  232. package/dist/core/actors/authenticate-actor.js +30 -0
  233. package/dist/core/actors/authenticate-actor.js.map +1 -0
  234. package/dist/core/connection/connect.d.ts +26 -0
  235. package/dist/core/connection/connect.js +57 -0
  236. package/dist/core/connection/connect.js.map +1 -0
  237. package/dist/core/connection/ports.d.ts +87 -0
  238. package/dist/core/connection/ports.js +2 -0
  239. package/dist/core/connection/ports.js.map +1 -0
  240. package/dist/core/connection/read-connection.d.ts +14 -0
  241. package/dist/core/connection/read-connection.js +24 -0
  242. package/dist/core/connection/read-connection.js.map +1 -0
  243. package/dist/core/installation/delete-fleet.d.ts +21 -0
  244. package/dist/core/installation/delete-fleet.js +21 -0
  245. package/dist/core/installation/delete-fleet.js.map +1 -0
  246. package/dist/core/installation/ports.d.ts +43 -0
  247. package/dist/core/installation/ports.js +2 -0
  248. package/dist/core/installation/ports.js.map +1 -0
  249. package/dist/core/installation/read-fleet.d.ts +18 -0
  250. package/dist/core/installation/read-fleet.js +9 -0
  251. package/dist/core/installation/read-fleet.js.map +1 -0
  252. package/dist/core/installation/request-id.d.ts +8 -0
  253. package/dist/core/installation/request-id.js +10 -0
  254. package/dist/core/installation/request-id.js.map +1 -0
  255. package/dist/core/installation/served.d.ts +12 -0
  256. package/dist/core/installation/served.js +8 -0
  257. package/dist/core/installation/served.js.map +1 -0
  258. package/dist/core/installation/set-fleet-enabled.d.ts +25 -0
  259. package/dist/core/installation/set-fleet-enabled.js +22 -0
  260. package/dist/core/installation/set-fleet-enabled.js.map +1 -0
  261. package/dist/core/mcp-in/call-tool.d.ts +42 -0
  262. package/dist/core/mcp-in/call-tool.js +82 -0
  263. package/dist/core/mcp-in/call-tool.js.map +1 -0
  264. package/dist/core/mcp-in/client-call.d.ts +51 -0
  265. package/dist/core/mcp-in/client-call.js +39 -0
  266. package/dist/core/mcp-in/client-call.js.map +1 -0
  267. package/dist/core/mcp-in/collect-replies.d.ts +29 -0
  268. package/dist/core/mcp-in/collect-replies.js +44 -0
  269. package/dist/core/mcp-in/collect-replies.js.map +1 -0
  270. package/dist/core/mcp-in/list-tools.d.ts +44 -0
  271. package/dist/core/mcp-in/list-tools.js +70 -0
  272. package/dist/core/mcp-in/list-tools.js.map +1 -0
  273. package/dist/core/mcp-in/ports.d.ts +85 -0
  274. package/dist/core/mcp-in/ports.js +2 -0
  275. package/dist/core/mcp-in/ports.js.map +1 -0
  276. package/dist/core/mcp-in/read-client-call.d.ts +23 -0
  277. package/dist/core/mcp-in/read-client-call.js +15 -0
  278. package/dist/core/mcp-in/read-client-call.js.map +1 -0
  279. package/dist/core/mcp-out/content-types.d.ts +12 -0
  280. package/dist/core/mcp-out/content-types.js +28 -0
  281. package/dist/core/mcp-out/content-types.js.map +1 -0
  282. package/dist/core/mcp-out/hand-call.d.ts +103 -0
  283. package/dist/core/mcp-out/hand-call.js +116 -0
  284. package/dist/core/mcp-out/hand-call.js.map +1 -0
  285. package/dist/core/mcp-out/mark-tool.d.ts +20 -0
  286. package/dist/core/mcp-out/mark-tool.js +17 -0
  287. package/dist/core/mcp-out/mark-tool.js.map +1 -0
  288. package/dist/core/mcp-out/ports.d.ts +66 -0
  289. package/dist/core/mcp-out/ports.js +2 -0
  290. package/dist/core/mcp-out/ports.js.map +1 -0
  291. package/dist/core/mcp-out/run-party.d.ts +26 -0
  292. package/dist/core/mcp-out/run-party.js +62 -0
  293. package/dist/core/mcp-out/run-party.js.map +1 -0
  294. package/dist/core/mcp-out/state-party.d.ts +38 -0
  295. package/dist/core/mcp-out/state-party.js +30 -0
  296. package/dist/core/mcp-out/state-party.js.map +1 -0
  297. package/dist/core/mcp-out/statement.d.ts +26 -0
  298. package/dist/core/mcp-out/statement.js +32 -0
  299. package/dist/core/mcp-out/statement.js.map +1 -0
  300. package/dist/core/oauth/authenticate-access-token.d.ts +25 -0
  301. package/dist/core/oauth/authenticate-access-token.js +19 -0
  302. package/dist/core/oauth/authenticate-access-token.js.map +1 -0
  303. package/dist/core/oauth/exchange-token.d.ts +32 -0
  304. package/dist/core/oauth/exchange-token.js +98 -0
  305. package/dist/core/oauth/exchange-token.js.map +1 -0
  306. package/dist/core/oauth/issue-code.d.ts +23 -0
  307. package/dist/core/oauth/issue-code.js +34 -0
  308. package/dist/core/oauth/issue-code.js.map +1 -0
  309. package/dist/core/oauth/ports.d.ts +103 -0
  310. package/dist/core/oauth/ports.js +2 -0
  311. package/dist/core/oauth/ports.js.map +1 -0
  312. package/dist/core/oauth/read-authorization.d.ts +43 -0
  313. package/dist/core/oauth/read-authorization.js +74 -0
  314. package/dist/core/oauth/read-authorization.js.map +1 -0
  315. package/dist/core/oauth/redirect-uri.d.ts +6 -0
  316. package/dist/core/oauth/redirect-uri.js +20 -0
  317. package/dist/core/oauth/redirect-uri.js.map +1 -0
  318. package/dist/core/oauth/register-client.d.ts +22 -0
  319. package/dist/core/oauth/register-client.js +20 -0
  320. package/dist/core/oauth/register-client.js.map +1 -0
  321. package/dist/core/operator/authenticate-operator.d.ts +22 -0
  322. package/dist/core/operator/authenticate-operator.js +26 -0
  323. package/dist/core/operator/authenticate-operator.js.map +1 -0
  324. package/dist/core/operator/ports.d.ts +15 -0
  325. package/dist/core/operator/ports.js +2 -0
  326. package/dist/core/operator/ports.js.map +1 -0
  327. package/dist/core/outside-parties/ports.d.ts +21 -0
  328. package/dist/core/outside-parties/ports.js +2 -0
  329. package/dist/core/outside-parties/ports.js.map +1 -0
  330. package/dist/core/outside-parties/set-outside-parties.d.ts +34 -0
  331. package/dist/core/outside-parties/set-outside-parties.js +34 -0
  332. package/dist/core/outside-parties/set-outside-parties.js.map +1 -0
  333. package/dist/core/parties/approve-party.d.ts +55 -0
  334. package/dist/core/parties/approve-party.js +111 -0
  335. package/dist/core/parties/approve-party.js.map +1 -0
  336. package/dist/core/parties/crew-party.d.ts +21 -0
  337. package/dist/core/parties/crew-party.js +29 -0
  338. package/dist/core/parties/crew-party.js.map +1 -0
  339. package/dist/core/parties/list-parties.d.ts +8 -0
  340. package/dist/core/parties/list-parties.js +8 -0
  341. package/dist/core/parties/list-parties.js.map +1 -0
  342. package/dist/core/parties/party.d.ts +46 -0
  343. package/dist/core/parties/party.js +2 -0
  344. package/dist/core/parties/party.js.map +1 -0
  345. package/dist/core/parties/ports.d.ts +39 -0
  346. package/dist/core/parties/ports.js +2 -0
  347. package/dist/core/parties/ports.js.map +1 -0
  348. package/dist/core/parties/shown-party.d.ts +21 -0
  349. package/dist/core/parties/shown-party.js +10 -0
  350. package/dist/core/parties/shown-party.js.map +1 -0
  351. package/dist/core/people/answer-delivery.d.ts +24 -0
  352. package/dist/core/people/answer-delivery.js +28 -0
  353. package/dist/core/people/answer-delivery.js.map +1 -0
  354. package/dist/core/people/crew-person-ship.d.ts +42 -0
  355. package/dist/core/people/crew-person-ship.js +59 -0
  356. package/dist/core/people/crew-person-ship.js.map +1 -0
  357. package/dist/core/people/done-delivery.d.ts +16 -0
  358. package/dist/core/people/done-delivery.js +9 -0
  359. package/dist/core/people/done-delivery.js.map +1 -0
  360. package/dist/core/people/inbox-entry.d.ts +14 -0
  361. package/dist/core/people/inbox-entry.js +11 -0
  362. package/dist/core/people/inbox-entry.js.map +1 -0
  363. package/dist/core/people/open-delivery.d.ts +30 -0
  364. package/dist/core/people/open-delivery.js +40 -0
  365. package/dist/core/people/open-delivery.js.map +1 -0
  366. package/dist/core/people/opened-of.d.ts +29 -0
  367. package/dist/core/people/opened-of.js +30 -0
  368. package/dist/core/people/opened-of.js.map +1 -0
  369. package/dist/core/people/person-crew.d.ts +39 -0
  370. package/dist/core/people/person-crew.js +61 -0
  371. package/dist/core/people/person-crew.js.map +1 -0
  372. package/dist/core/people/ports.d.ts +102 -0
  373. package/dist/core/people/ports.js +2 -0
  374. package/dist/core/people/ports.js.map +1 -0
  375. package/dist/core/people/read-inbox.d.ts +37 -0
  376. package/dist/core/people/read-inbox.js +36 -0
  377. package/dist/core/people/read-inbox.js.map +1 -0
  378. package/dist/core/requests/ask-for-client.d.ts +45 -0
  379. package/dist/core/requests/ask-for-client.js +33 -0
  380. package/dist/core/requests/ask-for-client.js.map +1 -0
  381. package/dist/core/requests/ask-for-server.d.ts +32 -0
  382. package/dist/core/requests/ask-for-server.js +42 -0
  383. package/dist/core/requests/ask-for-server.js.map +1 -0
  384. package/dist/core/requests/ask-owners.d.ts +28 -0
  385. package/dist/core/requests/ask-owners.js +85 -0
  386. package/dist/core/requests/ask-owners.js.map +1 -0
  387. package/dist/core/requests/decide-request.d.ts +53 -0
  388. package/dist/core/requests/decide-request.js +75 -0
  389. package/dist/core/requests/decide-request.js.map +1 -0
  390. package/dist/core/requests/expire-requests.d.ts +14 -0
  391. package/dist/core/requests/expire-requests.js +21 -0
  392. package/dist/core/requests/expire-requests.js.map +1 -0
  393. package/dist/core/requests/list-to-decide.d.ts +11 -0
  394. package/dist/core/requests/list-to-decide.js +13 -0
  395. package/dist/core/requests/list-to-decide.js.map +1 -0
  396. package/dist/core/requests/open-request.d.ts +21 -0
  397. package/dist/core/requests/open-request.js +26 -0
  398. package/dist/core/requests/open-request.js.map +1 -0
  399. package/dist/core/requests/outcome-notice.d.ts +13 -0
  400. package/dist/core/requests/outcome-notice.js +26 -0
  401. package/dist/core/requests/outcome-notice.js.map +1 -0
  402. package/dist/core/requests/ports.d.ts +186 -0
  403. package/dist/core/requests/ports.js +2 -0
  404. package/dist/core/requests/ports.js.map +1 -0
  405. package/dist/core/requests/read-waiting.d.ts +46 -0
  406. package/dist/core/requests/read-waiting.js +41 -0
  407. package/dist/core/requests/read-waiting.js.map +1 -0
  408. package/dist/core/requests/request-state.d.ts +5 -0
  409. package/dist/core/requests/request-state.js +10 -0
  410. package/dist/core/requests/request-state.js.map +1 -0
  411. package/dist/core/requests/tell-outcomes.d.ts +24 -0
  412. package/dist/core/requests/tell-outcomes.js +39 -0
  413. package/dist/core/requests/tell-outcomes.js.map +1 -0
  414. package/dist/core/requests/watch-waiting.d.ts +32 -0
  415. package/dist/core/requests/watch-waiting.js +31 -0
  416. package/dist/core/requests/watch-waiting.js.map +1 -0
  417. package/dist/core/shared/clock.d.ts +4 -0
  418. package/dist/core/shared/clock.js +2 -0
  419. package/dist/core/shared/clock.js.map +1 -0
  420. package/dist/core/shared/errors.d.ts +10 -0
  421. package/dist/core/shared/errors.js +6 -0
  422. package/dist/core/shared/errors.js.map +1 -0
  423. package/dist/core/shared/result.d.ts +16 -0
  424. package/dist/core/shared/result.js +7 -0
  425. package/dist/core/shared/result.js.map +1 -0
  426. package/dist/core/sign-in/account-token.d.ts +38 -0
  427. package/dist/core/sign-in/account-token.js +46 -0
  428. package/dist/core/sign-in/account-token.js.map +1 -0
  429. package/dist/core/sign-in/complete-sign-in.d.ts +55 -0
  430. package/dist/core/sign-in/complete-sign-in.js +50 -0
  431. package/dist/core/sign-in/complete-sign-in.js.map +1 -0
  432. package/dist/core/sign-in/end-sign-ins.d.ts +19 -0
  433. package/dist/core/sign-in/end-sign-ins.js +17 -0
  434. package/dist/core/sign-in/end-sign-ins.js.map +1 -0
  435. package/dist/core/sign-in/ports.d.ts +85 -0
  436. package/dist/core/sign-in/ports.js +2 -0
  437. package/dist/core/sign-in/ports.js.map +1 -0
  438. package/dist/core/sign-in/start-sign-in.d.ts +30 -0
  439. package/dist/core/sign-in/start-sign-in.js +25 -0
  440. package/dist/core/sign-in/start-sign-in.js.map +1 -0
  441. package/dist/core/vault/credential.d.ts +18 -0
  442. package/dist/core/vault/credential.js +2 -0
  443. package/dist/core/vault/credential.js.map +1 -0
  444. package/dist/outcome-worker.d.ts +29 -0
  445. package/dist/outcome-worker.js +60 -0
  446. package/dist/outcome-worker.js.map +1 -0
  447. package/dist/party-workers.d.ts +32 -0
  448. package/dist/party-workers.js +57 -0
  449. package/dist/party-workers.js.map +1 -0
  450. package/package.json +70 -4
  451. package/prisma.config.ts +18 -0
  452. package/src/adapters/prisma/migrations/20261018200000_init/migration.sql +35 -0
  453. package/src/adapters/prisma/migrations/20261018210000_parties/migration.sql +19 -0
  454. package/src/adapters/prisma/migrations/20261018220000_tool_marks/migration.sql +8 -0
  455. package/src/adapters/prisma/migrations/20261018230000_calls/migration.sql +13 -0
  456. package/src/adapters/prisma/migrations/20261019090000_oauth/migration.sql +60 -0
  457. package/src/adapters/prisma/migrations/20261019100000_client_parties/migration.sql +8 -0
  458. package/src/adapters/prisma/migrations/20261019110000_oauth_parties/migration.sql +5 -0
  459. package/src/adapters/prisma/migrations/20261019120000_client_calls/migration.sql +15 -0
  460. package/src/adapters/prisma/migrations/20261019130000_client_call_replies/migration.sql +20 -0
  461. package/src/adapters/prisma/migrations/20261019140000_identity_providers/migration.sql +10 -0
  462. package/src/adapters/prisma/migrations/20261020090000_no_identity_providers/migration.sql +2 -0
  463. package/src/adapters/prisma/migrations/20261020100000_account_grants_in_tokens/migration.sql +5 -0
  464. package/src/adapters/prisma/migrations/20261020110000_account_grants/migration.sql +15 -0
  465. package/src/adapters/prisma/migrations/20261020120000_person_crews/migration.sql +9 -0
  466. package/src/adapters/prisma/migrations/20261020130000_opened_deliveries/migration.sql +13 -0
  467. package/src/adapters/prisma/migrations/20261020140000_pending_requests/migration.sql +26 -0
  468. package/src/adapters/prisma/migrations/20261020150000_outside_party_switches/migration.sql +8 -0
  469. package/src/adapters/prisma/migrations/20261020160000_pending_requests_told/migration.sql +2 -0
  470. package/src/adapters/prisma/migrations/20261020170000_request_outcome_notices/migration.sql +17 -0
  471. package/src/adapters/prisma/migrations/20261020180000_owner_questions/migration.sql +11 -0
  472. package/src/adapters/prisma/migrations/20261020190000_request_changes/migration.sql +12 -0
  473. package/src/adapters/prisma/migrations/migration_lock.toml +3 -0
  474. package/src/adapters/prisma/schema.prisma +311 -0
@@ -0,0 +1,164 @@
1
+ /**
2
+ * The gateway's MCP endpoint for outside MCP clients (interop 3.3), over
3
+ * Streamable HTTP and stateless: each request is served by a fresh server for
4
+ * the client its access token names. No token, or one the gateway did not
5
+ * issue for this endpoint, gets 401 with where to sign in (RFC 9728). A
6
+ * client party gets 403 while its fleet's outside parties are off (interop I-3).
7
+ */
8
+ import { CLIENT_CAPABILITIES_META_KEY, createMcpHandler, isCallToolResult, McpServer, ProtocolError, ProtocolErrorCode } from '@modelcontextprotocol/server';
9
+ import { z } from 'zod';
10
+ import { isToolResultType } from '../../core/mcp-out/content-types.js';
11
+ import { createdTaskOf, DEADLINE_PASSED, taskOf, TASKS_EXTENSION } from './mcp-task.js';
12
+ import { personServerFor } from './person-tools.js';
13
+ import { runningVersion } from './version.js';
14
+ const HTTP_UNAUTHORIZED = 401;
15
+ const HTTP_FORBIDDEN = 403;
16
+ /** The gateway's own tool: the answer to a call that answered a handle. */
17
+ const RESULT_TOOL = {
18
+ name: 'aeolus_result',
19
+ title: 'Read a call',
20
+ description: "A call's state and, once it is answered, its answer. Call it with the handle a tool answered, and again later while the call is not answered.",
21
+ inputSchema: { type: 'object', properties: { handle: { type: 'string' } }, required: ['handle'] },
22
+ };
23
+ const argumentsSchema = z.record(z.string(), z.unknown()).default({});
24
+ const resultArgumentsSchema = z.object({ handle: z.string() });
25
+ const taskParamsSchema = z.looseObject({ taskId: z.string() });
26
+ /** The capabilities a client declares on each request (2026-07-28), as far as the gateway reads them. */
27
+ const envelopeSchema = z.object({ [CLIENT_CAPABILITIES_META_KEY]: z.object({ extensions: z.record(z.string(), z.unknown()).optional() }).optional() });
28
+ /** Whether the client declared the Tasks extension on this request: only then may it be answered a task. */
29
+ const isTaskClient = (envelope) => envelopeSchema.safeParse(envelope).data?.[CLIENT_CAPABILITIES_META_KEY]?.extensions?.[TASKS_EXTENSION] !== undefined;
30
+ /** tools/call's params, as the gateway reads them: its result may be a task, which the SDK's own tools/call does not type. */
31
+ const callParamsSchema = z.looseObject({ name: z.string(), arguments: z.unknown().optional() });
32
+ /** A tool's answer as one text block of JSON. */
33
+ const answered = (value, isError = false) => ({ content: [{ type: 'text', text: JSON.stringify(value) }], ...(isError ? { isError } : {}) });
34
+ /** A tool error the client's model reads: what went wrong, never a fleet's reasons. */
35
+ const toolError = (message) => ({ content: [{ type: 'text', text: message }], isError: true });
36
+ /** An answer that is an outside tool's result, as MCP out replies one, if it parses as one. */
37
+ function toolResultOf(payload) {
38
+ try {
39
+ const parsed = JSON.parse(payload);
40
+ return isCallToolResult(parsed) ? parsed : undefined;
41
+ }
42
+ catch {
43
+ return undefined;
44
+ }
45
+ }
46
+ /** What aeolus_result answers: the call's answer once completed, as the tool's own result where it is one; else its state. */
47
+ function resultOf(read) {
48
+ switch (read.state) {
49
+ case 'completed':
50
+ return (isToolResultType(read.answer.contentType) ? toolResultOf(read.answer.payload) : undefined) ?? { content: [{ type: 'text', text: read.answer.payload }] };
51
+ case 'failed':
52
+ return toolError(DEADLINE_PASSED);
53
+ case 'submitted':
54
+ case 'working':
55
+ return answered({ handle: read.handle, state: read.state });
56
+ }
57
+ }
58
+ /** The request as the SDK's web-standard handler takes it. Fastify has read the JSON body already. */
59
+ function webRequestOf(request) {
60
+ const headers = new Headers();
61
+ for (const [name, value] of Object.entries(request.headers)) {
62
+ for (const each of Array.isArray(value) ? value : [value]) {
63
+ if (each !== undefined) {
64
+ headers.append(name, each);
65
+ }
66
+ }
67
+ }
68
+ return new Request(new URL(request.url, `${request.protocol}://${request.host}`), { method: request.method, headers });
69
+ }
70
+ /** A JSON Schema of an object, as MCP's tool takes one. */
71
+ const objectSchema = z.object({ type: z.literal('object') }).catchall(z.json());
72
+ /** The MCP server one request of one client is served by. Its tools are known per request, from the fleet, so it lists them itself. */
73
+ function serverFor(holder, deps) {
74
+ const mcp = new McpServer({ name: 'aeolus-gateway', version: runningVersion() }, { capabilities: { tools: {}, extensions: { [TASKS_EXTENSION]: {} } } });
75
+ mcp.server.setRequestHandler('tools/list', async () => {
76
+ const listed = await deps.listTools({ fleetId: holder.fleetId, party: holder.party });
77
+ if (!listed.isOk) {
78
+ throw new Error(listed.error.message);
79
+ }
80
+ // Where each call goes stays with the gateway: the client sees aliases only.
81
+ return {
82
+ tools: listed.value.map(({ name, title, description, inputSchema }) => ({
83
+ name,
84
+ ...(title === undefined ? {} : { title }),
85
+ description,
86
+ inputSchema: objectSchema.parse(inputSchema),
87
+ })).concat(RESULT_TOOL),
88
+ };
89
+ });
90
+ mcp.server.setRequestHandler('tools/call', { params: callParamsSchema }, async (params, ctx) => {
91
+ const caller = { fleetId: holder.fleetId, party: holder.party };
92
+ if (params.name === RESULT_TOOL.name) {
93
+ const sent = resultArgumentsSchema.safeParse(params.arguments);
94
+ if (!sent.success) {
95
+ return toolError('aeolus_result takes the handle a tool answered');
96
+ }
97
+ const read = await deps.readClientCall(caller, sent.data.handle);
98
+ return read.isOk ? resultOf(read.value) : toolError(read.error.message);
99
+ }
100
+ const values = argumentsSchema.safeParse(params.arguments);
101
+ if (!values.success) {
102
+ return toolError('A tool takes its arguments as an object');
103
+ }
104
+ const called = await deps.callTool(caller, { name: params.name, arguments: values.data });
105
+ if (!called.isOk) {
106
+ return toolError(called.error.message);
107
+ }
108
+ const isUnanswered = called.value.state === 'submitted' || called.value.state === 'working';
109
+ return isUnanswered && isTaskClient(ctx.mcpReq.envelope) ? createdTaskOf(called.value) : resultOf(called.value);
110
+ });
111
+ /** The party's own call by its task id; another party's or none is an error. */
112
+ const readTask = async (taskId) => {
113
+ const read = await deps.readClientCall({ fleetId: holder.fleetId, party: holder.party }, taskId);
114
+ if (!read.isOk) {
115
+ throw new ProtocolError(ProtocolErrorCode.InvalidParams, `No task ${taskId} of this party`);
116
+ }
117
+ return read.value;
118
+ };
119
+ mcp.server.setRequestHandler('tasks/get', { params: taskParamsSchema }, async ({ taskId }) => taskOf(await readTask(taskId), resultOf));
120
+ // Acknowledged and nothing changes: a sent call cannot be unsent, and no call asks for input yet.
121
+ for (const method of ['tasks/cancel', 'tasks/update']) {
122
+ mcp.server.setRequestHandler(method, { params: taskParamsSchema }, async ({ taskId }) => {
123
+ await readTask(taskId);
124
+ return {};
125
+ });
126
+ }
127
+ return mcp;
128
+ }
129
+ export function registerMcpEndpoint(server, deps) {
130
+ const resourceMetadata = `${new URL(deps.resource).origin}/.well-known/oauth-protected-resource${new URL(deps.resource).pathname}`;
131
+ const unauthorized = (reply, error) => reply
132
+ .code(HTTP_UNAUTHORIZED)
133
+ .header('www-authenticate', `Bearer ${error === undefined ? '' : `error="${error}", `}resource_metadata="${resourceMetadata}"`)
134
+ .send({ error: error ?? 'unauthorized' });
135
+ server.all(new URL(deps.resource).pathname, async (request, reply) => {
136
+ const authorization = request.headers.authorization;
137
+ if (authorization?.startsWith('Bearer ') !== true) {
138
+ return unauthorized(reply, undefined);
139
+ }
140
+ const holder = await deps.authenticateAccessToken(authorization.slice('Bearer '.length));
141
+ if (!holder.isOk) {
142
+ return unauthorized(reply, 'invalid_token');
143
+ }
144
+ const held = holder.value;
145
+ const { person } = deps;
146
+ let serve;
147
+ if (held.kind === 'party') {
148
+ if (!(await deps.servesOutsideParties(held.fleetId))) {
149
+ return reply.code(HTTP_FORBIDDEN).send({ error: 'outside_parties_off', error_description: "This fleet's outside parties are off" });
150
+ }
151
+ serve = () => serverFor({ fleetId: held.fleetId, party: held.party }, deps);
152
+ }
153
+ else if (person === undefined) {
154
+ // An account's token is issued only where people sign in, so it finds their tools.
155
+ return unauthorized(reply, 'invalid_token');
156
+ }
157
+ else {
158
+ serve = () => personServerFor({ fleetId: held.fleetId, grantId: held.grantId }, person);
159
+ }
160
+ const handler = createMcpHandler(serve);
161
+ return handler.fetch(webRequestOf(request), { parsedBody: request.body });
162
+ });
163
+ }
164
+ //# sourceMappingURL=mcp-endpoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-endpoint.js","sourceRoot":"","sources":["../../../src/adapters/http/mcp-endpoint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import type { ReadCall } from '../../core/mcp-in/read-client-call.js';
2
+ export declare const TASKS_EXTENSION = "io.modelcontextprotocol/tasks";
3
+ /** What a failed call's task says: the ship never answered, and it may have run. */
4
+ export declare const DEADLINE_PASSED = "The call got no answer before its deadline. It may have run all the same.";
5
+ /** The task tools/call answers in place of its result, for a call not answered within its wait. */
6
+ export declare function createdTaskOf(read: ReadCall): {
7
+ status: "working";
8
+ taskId: string;
9
+ createdAt: string;
10
+ lastUpdatedAt: string;
11
+ ttlMs: null;
12
+ pollIntervalMs: number;
13
+ resultType: "task";
14
+ };
15
+ /** The task tasks/get answers: a completed call carries its answer as the tool's result, which resultOf gives. */
16
+ export declare function taskOf(read: ReadCall, resultOf: (read: ReadCall) => Record<string, unknown>): {
17
+ status: "working";
18
+ taskId: string;
19
+ createdAt: string;
20
+ lastUpdatedAt: string;
21
+ ttlMs: null;
22
+ pollIntervalMs: number;
23
+ resultType: "complete";
24
+ } | {
25
+ status: "completed";
26
+ result: Record<string, unknown>;
27
+ taskId: string;
28
+ createdAt: string;
29
+ lastUpdatedAt: string;
30
+ ttlMs: null;
31
+ pollIntervalMs: number;
32
+ resultType: "complete";
33
+ } | {
34
+ status: "failed";
35
+ error: {
36
+ code: number;
37
+ message: string;
38
+ };
39
+ taskId: string;
40
+ createdAt: string;
41
+ lastUpdatedAt: string;
42
+ ttlMs: null;
43
+ pollIntervalMs: number;
44
+ resultType: "complete";
45
+ };
@@ -0,0 +1,35 @@
1
+ /**
2
+ * An outside client's call as an MCP task (the Tasks extension,
3
+ * io.modelcontextprotocol/tasks, 2026-07-28). The task id is the call's
4
+ * handle, already an HMAC of its message id; the call store is the task's
5
+ * durable state, so the task exists once the call was kept (interop 3.3).
6
+ * Submitted and working are both MCP's working (interop 3.4).
7
+ */
8
+ import { INTERNAL_ERROR } from '@modelcontextprotocol/server';
9
+ export const TASKS_EXTENSION = 'io.modelcontextprotocol/tasks';
10
+ /** How often a client reads a task: the fleet answers in seconds, not milliseconds. */
11
+ const POLL_INTERVAL_MS = 2000;
12
+ /** What a failed call's task says: the ship never answered, and it may have run. */
13
+ export const DEADLINE_PASSED = 'The call got no answer before its deadline. It may have run all the same.';
14
+ /** The fields every task carries. The gateway keeps every call, so no task expires. */
15
+ function taskFieldsOf(read) {
16
+ return { taskId: read.handle, createdAt: read.createdAt.toISOString(), lastUpdatedAt: read.updatedAt.toISOString(), ttlMs: null, pollIntervalMs: POLL_INTERVAL_MS };
17
+ }
18
+ /** The task tools/call answers in place of its result, for a call not answered within its wait. */
19
+ export function createdTaskOf(read) {
20
+ return { resultType: 'task', ...taskFieldsOf(read), status: 'working' };
21
+ }
22
+ /** The task tasks/get answers: a completed call carries its answer as the tool's result, which resultOf gives. */
23
+ export function taskOf(read, resultOf) {
24
+ const task = { resultType: 'complete', ...taskFieldsOf(read) };
25
+ switch (read.state) {
26
+ case 'submitted':
27
+ case 'working':
28
+ return { ...task, status: 'working' };
29
+ case 'completed':
30
+ return { ...task, status: 'completed', result: resultOf(read) };
31
+ case 'failed':
32
+ return { ...task, status: 'failed', error: { code: INTERNAL_ERROR, message: DEADLINE_PASSED } };
33
+ }
34
+ }
35
+ //# sourceMappingURL=mcp-task.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-task.js","sourceRoot":"","sources":["../../../src/adapters/http/mcp-task.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAI9D,MAAM,CAAC,MAAM,eAAe,GAAG,+BAA+B,CAAC;AAE/D,uFAAuF;AACvF,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAE9B,oFAAoF;AACpF,MAAM,CAAC,MAAM,eAAe,GAAG,2EAA2E,CAAC;AAE3G,uFAAuF;AACvF,SAAS,YAAY,CAAC,IAAc;IAClC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,gBAAgB,EAAE,CAAC;AACtK,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,aAAa,CAAC,IAAc;IAC1C,OAAO,EAAE,UAAU,EAAE,MAAe,EAAE,GAAG,YAAY,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,SAAkB,EAAE,CAAC;AAC5F,CAAC;AAED,kHAAkH;AAClH,MAAM,UAAU,MAAM,CAAC,IAAc,EAAE,QAAqD;IAC1F,MAAM,IAAI,GAAG,EAAE,UAAU,EAAE,UAAmB,EAAE,GAAG,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;IACxE,QAAQ,IAAI,CAAC,KAAK,EAAE,CAAC;QACnB,KAAK,WAAW,CAAC;QACjB,KAAK,SAAS;YACZ,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,SAAkB,EAAE,CAAC;QACjD,KAAK,WAAW;YACd,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,WAAoB,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3E,KAAK,QAAQ;YACX,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,QAAiB,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe,EAAE,EAAE,CAAC;IAC7G,CAAC;AACH,CAAC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * The gateway's OAuth 2.1 authorization server over HTTP, for outside MCP
3
+ * clients (MCP 2026-07-28 authorization): the metadata of RFC 9728 and RFC
4
+ * 8414; /authorize, where a person picks what the client acts as (Q1 a) and
5
+ * is sent to pagasae to sign in; /pagasae/callback, where pagasae sends them
6
+ * back; the waiting page, where a client asked for waits for an approver
7
+ * (decision 0056); and /token. Each route parses the request and calls one
8
+ * use case. Only a signed-in account asks for a client, so a gateway where
9
+ * no pagasae is set answers no client (Thomas's question A).
10
+ */
11
+ import type { FastifyInstance } from 'fastify';
12
+ import type { ExchangeToken } from '../../core/oauth/exchange-token.js';
13
+ import type { ReadAuthorization } from '../../core/oauth/read-authorization.js';
14
+ import type { ReadWaiting } from '../../core/requests/read-waiting.js';
15
+ import type { WatchWaiting } from '../../core/requests/watch-waiting.js';
16
+ import type { Clock } from '../../core/shared/clock.js';
17
+ import type { CompleteSignIn } from '../../core/sign-in/complete-sign-in.js';
18
+ import { type StartSignIn } from '../../core/sign-in/start-sign-in.js';
19
+ import { type ChangeHub } from './live.js';
20
+ export interface OAuthRoutesDeps {
21
+ issuer: string;
22
+ resource: string;
23
+ readAuthorization: ReadAuthorization;
24
+ exchangeToken: ExchangeToken;
25
+ /** Signing people in through pagasae (decision 0054) and their clients' waits, followed live; unset where no pagasae is set. */
26
+ signIn?: {
27
+ start: StartSignIn;
28
+ complete: CompleteSignIn;
29
+ readWaiting: ReadWaiting;
30
+ watchWaiting: WatchWaiting;
31
+ hub: ChangeHub;
32
+ clock: Clock;
33
+ };
34
+ }
35
+ export declare function registerOAuthRoutes(server: FastifyInstance, deps: OAuthRoutesDeps): void;
@@ -0,0 +1,305 @@
1
+ import { z } from 'zod';
2
+ import { REQUEST_LIFETIME_MS } from '../../core/requests/open-request.js';
3
+ import { SIGN_IN_LIFETIME_MS } from '../../core/sign-in/start-sign-in.js';
4
+ import { acceptForms, escaped, isSameOrigin } from './html.js';
5
+ import { acceptWebsockets } from './live.js';
6
+ import { handshake, icon, ring, signInPage, statusBadge } from './signal.js';
7
+ const HTTP_FOUND = 302;
8
+ const HTTP_BAD_REQUEST = 400;
9
+ const HTTP_UNAUTHORIZED = 401;
10
+ const HTTP_FORBIDDEN = 403;
11
+ const HTTP_NOT_FOUND = 404;
12
+ const HTTP_BAD_GATEWAY = 502;
13
+ const MS_PER_SECOND = 1000;
14
+ /** Why the waiting page's live channel was closed: it does not open again. */
15
+ const CLOSE_OTHER_ORIGIN = 4403;
16
+ /** Whether the gateway is served over HTTPS, so its cookies go over HTTPS only. */
17
+ const isHttps = (issuer) => new URL(issuer).protocol === 'https:';
18
+ /** The parameters of an authorization request the page carries from its query to its form. */
19
+ const AUTHORIZATION_PARAMETERS = ['response_type', 'client_id', 'redirect_uri', 'code_challenge', 'code_challenge_method', 'resource', 'state', 'scope'];
20
+ const fieldsSchema = z.record(z.string(), z.unknown()).transform((fields) => Object.fromEntries(Object.entries(fields).flatMap(([name, value]) => (typeof value === 'string' ? [[name, value]] : []))));
21
+ /** What the person may pick the client to act as. */
22
+ const holderSchema = z.enum(['account', 'party']);
23
+ function fieldsOf(value) {
24
+ const fields = fieldsSchema.safeParse(value);
25
+ return fields.success ? fields.data : {};
26
+ }
27
+ function authorizationRequestOf(fields) {
28
+ return Object.fromEntries(AUTHORIZATION_PARAMETERS.map((name) => [name, fields[name]]));
29
+ }
30
+ /** A page of the gateway, never cached. */
31
+ function htmlPage(reply, page) {
32
+ return reply.code(page.status).type('text/html; charset=utf-8').header('cache-control', 'no-store').send(signInPage({ title: page.title, body: page.body }));
33
+ }
34
+ /** How an error page leads (design B): one ring in its tone around one icon, dashed for what ended, and one title. */
35
+ const ERROR_LOOKS = {
36
+ invalidClient: { tone: 'attention', icon: 'alert', heading: 'This client cannot connect' },
37
+ noPick: { tone: 'attention', icon: 'alert', heading: 'Pick how to connect' },
38
+ signInEnded: { tone: 'ended', icon: 'timerOff', heading: 'Sign-in ended', isDashed: true },
39
+ otherBrowser: { tone: 'attention', icon: 'shieldX', heading: 'Not this browser' },
40
+ noFleet: { tone: 'attention', icon: 'shieldX', heading: 'No fleet for you' },
41
+ outsidePartiesOff: { tone: 'ended', icon: 'powerOff', heading: 'Outside parties are off' },
42
+ signInFailed: { tone: 'attention', icon: 'alert', heading: 'Sign-in did not go through' },
43
+ requestEnded: { tone: 'ended', icon: 'timerOff', heading: 'Request ended', isDashed: true },
44
+ noSignIn: { tone: 'ended', icon: 'ban', heading: 'No sign-in here' },
45
+ };
46
+ /** A page that tells a person why their client got nothing, sending them nowhere. */
47
+ function errorPage(reply, page) {
48
+ const look = ERROR_LOOKS[page.look];
49
+ const lead = ring({ tone: look.tone, center: { icon: look.icon }, label: look.heading, size: 144, ...(look.isDashed === undefined ? {} : { isDashed: look.isDashed }) });
50
+ return htmlPage(reply, { status: page.status, title: page.title, body: `${lead}<h1>${escaped(look.heading)}</h1><p class="muted">${escaped(page.message)}</p>` });
51
+ }
52
+ /** The cookie the browser that started a sign-in holds its secret in, sent back to the callback only. */
53
+ const SIGN_IN_COOKIE = { name: 'aeolus_sign_in', path: '/pagasae/callback' };
54
+ /** The cookie the browser that asked for a client holds the same secret in, sent back to the waiting page only. */
55
+ const WAITING_COOKIE = { name: 'aeolus_waiting', path: '/authorize/waiting' };
56
+ function cookieHeader(cookie, set) {
57
+ return `${cookie.name}=${set.value}; Path=${cookie.path}; Max-Age=${String(set.maxAgeSeconds)}; HttpOnly;${set.isSecure ? ' Secure;' : ''} SameSite=Lax`;
58
+ }
59
+ /** The cookie's value from a Cookie header, if the browser sent it. */
60
+ function cookieValue(cookie, header) {
61
+ const prefix = `${cookie.name}=`;
62
+ return header
63
+ ?.split(';')
64
+ .map((part) => part.trim())
65
+ .find((part) => part.startsWith(prefix))
66
+ ?.slice(prefix.length);
67
+ }
68
+ function sendBack(reply, answer) {
69
+ const { refusal, issuer } = answer;
70
+ if (refusal.kind === 'invalidClient') {
71
+ return errorPage(reply, { status: HTTP_BAD_REQUEST, title: 'Connect an MCP client', look: 'invalidClient', message: refusal.message });
72
+ }
73
+ const url = new URL(refusal.redirectUri);
74
+ url.searchParams.append('error', refusal.error);
75
+ url.searchParams.append('error_description', refusal.description);
76
+ if (refusal.state !== null) {
77
+ url.searchParams.append('state', refusal.state);
78
+ }
79
+ url.searchParams.append('iss', issuer);
80
+ return reply.code(HTTP_FOUND).header('location', url.toString()).send();
81
+ }
82
+ /** The page at /authorize: the client, and the two picks (Q1 a), each starting a sign-in through pagasae. */
83
+ function pickPage(request, authorization) {
84
+ const hidden = Object.entries(request)
85
+ .flatMap(([name, value]) => (value === undefined ? [] : [`<input type="hidden" name="${escaped(name)}" value="${escaped(value)}">`]))
86
+ .join('');
87
+ return `${handshake({ name: authorization.clientName, fleet: 'Aeolus' })}
88
+ <h1>Connect an MCP client</h1>
89
+ <p><strong>${escaped(authorization.clientName)}</strong> asks to call your fleet's ships through the gateway.</p>
90
+ <form method="get" action="/authorize/sign-in">${hidden}<div class="tiles">
91
+ <button class="tile" name="holder" value="account">${icon('signIn', 20)}<strong>Sign in as yourself</strong><span class="muted">The client acts as you.</span></button>
92
+ <button class="tile" name="holder" value="party">${icon('hourglass', 20)}<strong>Ask for access for this client</strong><span class="muted">An approver of your fleet decides; the client then acts as its own party.</span></button>
93
+ </div></form>
94
+ <p class="muted">Client ${escaped(authorization.clientId)}, sent back to ${escaped(authorization.redirectUri)}.</p>`;
95
+ }
96
+ /**
97
+ * What the waiting page runs: it follows its request on the live channel
98
+ * and goes to its own address again once told to, there to be sent on; it
99
+ * goes there too when the request expires. A dropped socket opens again
100
+ * with backoff. It never reloads on a timer.
101
+ */
102
+ const WAITING_SCRIPT = `(function () {
103
+ var wait = 500, expiry, HOUR = 3600000;
104
+ function goOn() { location.replace(location.href); }
105
+ function countDown() {
106
+ var holder = document.querySelector('[data-expires-at]'), text = document.querySelector('[data-time-left]');
107
+ if (!holder || !text) return;
108
+ var hours = Math.max(0, Math.floor((Date.parse(holder.getAttribute('data-expires-at')) - Date.now()) / HOUR));
109
+ text.textContent = Math.floor(hours / 24) + ' d ' + (hours % 24) + ' h';
110
+ }
111
+ setInterval(countDown, 60000);
112
+ function open() {
113
+ var socket = new WebSocket((location.protocol === 'https:' ? 'wss://' : 'ws://') + location.host + '${WAITING_COOKIE.path}/live' + location.search);
114
+ socket.onopen = function () { wait = 500; };
115
+ socket.onmessage = function (event) {
116
+ var told = JSON.parse(event.data);
117
+ if (told.go) return goOn();
118
+ if (told.expiresAt) { clearTimeout(expiry); expiry = setTimeout(goOn, Math.max(0, Date.parse(told.expiresAt) - Date.now())); }
119
+ };
120
+ socket.onclose = function (event) {
121
+ if (event.code === ${String(CLOSE_OTHER_ORIGIN)}) return;
122
+ setTimeout(open, wait);
123
+ wait = Math.min(wait * 2, 10000);
124
+ };
125
+ }
126
+ open();
127
+ })();`;
128
+ const MS_PER_HOUR = 3_600_000;
129
+ const HOURS_PER_DAY = 24;
130
+ /** The time left of a request, in days and hours, as the waiting page's ring shows it. */
131
+ function timeLeft(expiresAt, now) {
132
+ const hours = Math.max(0, Math.floor((expiresAt.getTime() - now.getTime()) / MS_PER_HOUR));
133
+ return `${String(Math.floor(hours / HOURS_PER_DAY))} d ${String(hours % HOURS_PER_DAY)} h`;
134
+ }
135
+ /** The waiting page: the client waits for approval, the ring counting its time left, and the page goes on by itself once it is decided. */
136
+ function waitingPage(waiting) {
137
+ const left = timeLeft(waiting.expiresAt, waiting.now);
138
+ return `${handshake({ name: waiting.clientName, fleet: 'Aeolus' })}
139
+ <div data-expires-at="${waiting.expiresAt.toISOString()}">${ring({ tone: 'waiting', center: { text: left, icon: 'hourglass' }, label: `${left} left`, size: 176 })}</div>
140
+ ${statusBadge({ tone: 'waiting', icon: 'hourglass', label: 'Waiting for approval' })}
141
+ <p><strong>${escaped(waiting.clientName)}</strong> waits for an approver of your fleet.</p>
142
+ <p><span class="going-on">Goes on by itself</span></p>
143
+ <p class="muted">Closed this page? Connect again later.</p>
144
+ <script>${WAITING_SCRIPT}</script>`;
145
+ }
146
+ /** Client credentials in an HTTP Basic header (RFC 6749, 2.3.1): each part form-urlencoded. */
147
+ function basicCredentials(header) {
148
+ if (header?.startsWith('Basic ') !== true) {
149
+ return {};
150
+ }
151
+ const decoded = Buffer.from(header.slice('Basic '.length), 'base64').toString('utf8');
152
+ const separator = decoded.indexOf(':');
153
+ if (separator < 0) {
154
+ return {};
155
+ }
156
+ const decode = (part) => decodeURIComponent(part.replaceAll('+', ' '));
157
+ return { client_id: decode(decoded.slice(0, separator)), client_secret: decode(decoded.slice(separator + 1)) };
158
+ }
159
+ /** Signing people in through pagasae, and the waiting page (decisions 0054, 0056). */
160
+ function registerSignIn(server, deps) {
161
+ const { issuer, signIn } = deps;
162
+ const isSecure = isHttps(issuer);
163
+ server.get('/authorize/sign-in', async (request, reply) => {
164
+ const fields = fieldsOf(request.query);
165
+ const holder = holderSchema.safeParse(fields.holder);
166
+ if (!holder.success) {
167
+ return errorPage(reply, { status: HTTP_BAD_REQUEST, title: 'Connect an MCP client', look: 'noPick', message: 'Pick on the page whether to sign in as yourself or to ask for access for the client.' });
168
+ }
169
+ const started = await signIn.start({ request: authorizationRequestOf(fields), holder: holder.data });
170
+ if (!started.isOk) {
171
+ return sendBack(reply, { refusal: started.error, issuer });
172
+ }
173
+ const cookie = cookieHeader(SIGN_IN_COOKIE, { value: started.value.browserSecret, maxAgeSeconds: SIGN_IN_LIFETIME_MS / MS_PER_SECOND, isSecure });
174
+ return reply.code(HTTP_FOUND).header('location', started.value.redirectTo).header('set-cookie', cookie).send();
175
+ });
176
+ /** Where the browser goes next: back to the client, or, holding the secret in its waiting cookie, to the waiting page. */
177
+ const goOn = (reply, { answer, browserSecret }) => {
178
+ const cleared = cookieHeader(SIGN_IN_COOKIE, { value: '', maxAgeSeconds: 0, isSecure });
179
+ if (answer.kind === 'answered') {
180
+ return reply.code(HTTP_FOUND).header('location', answer.redirectTo).header('set-cookie', cleared).send();
181
+ }
182
+ const waiting = cookieHeader(WAITING_COOKIE, { value: browserSecret ?? '', maxAgeSeconds: REQUEST_LIFETIME_MS / MS_PER_SECOND, isSecure });
183
+ return reply.code(HTTP_FOUND).header('location', `${WAITING_COOKIE.path}?${new URLSearchParams({ waiting: answer.waiting }).toString()}`).header('set-cookie', [cleared, waiting]).send();
184
+ };
185
+ server.get(SIGN_IN_COOKIE.path, async (request, reply) => {
186
+ const { state, code, error } = fieldsOf(request.query);
187
+ const browserSecret = cookieValue(SIGN_IN_COOKIE, request.headers.cookie);
188
+ const completed = await signIn.complete({ state, code, error, browserSecret });
189
+ if (completed.isOk) {
190
+ return goOn(reply, { answer: completed.value, browserSecret });
191
+ }
192
+ void reply.header('set-cookie', cookieHeader(SIGN_IN_COOKIE, { value: '', maxAgeSeconds: 0, isSecure }));
193
+ const refusal = completed.error;
194
+ const title = 'Sign in';
195
+ switch (refusal.kind) {
196
+ case 'invalidClient':
197
+ case 'redirect':
198
+ return sendBack(reply, { refusal, issuer });
199
+ case 'unknownSignIn':
200
+ return errorPage(reply, { status: HTTP_BAD_REQUEST, title, look: 'signInEnded', message: 'This sign-in is unknown, or took over 10 minutes. Start again from your MCP client.' });
201
+ case 'otherBrowser':
202
+ return errorPage(reply, { status: HTTP_BAD_REQUEST, title, look: 'otherBrowser', message: 'This sign-in was started in another browser, so it is not yours to finish. Start again from your MCP client.' });
203
+ case 'fleetNotServed':
204
+ return errorPage(reply, { status: HTTP_FORBIDDEN, title, look: 'noFleet', message: 'This gateway does not serve the fleet you signed in to.' });
205
+ case 'outsidePartiesOff':
206
+ return errorPage(reply, { status: HTTP_FORBIDDEN, title, look: 'outsidePartiesOff', message: "Your fleet's outside parties are off, so no MCP client can ask for access. Sign in as yourself instead, or ask whoever runs your fleet." });
207
+ case 'pagasaeRefused':
208
+ return errorPage(reply, { status: HTTP_BAD_GATEWAY, title, look: 'signInFailed', message: `The sign-in did not go through: ${refusal.message}. Start again from your MCP client.` });
209
+ }
210
+ });
211
+ // The sealed waiting goes in the query, as it is longer than a path parameter may be.
212
+ server.get(WAITING_COOKIE.path, async (request, reply) => {
213
+ const { waiting = '' } = fieldsOf(request.query);
214
+ const read = await signIn.readWaiting({ waiting, browserSecret: cookieValue(WAITING_COOKIE, request.headers.cookie) });
215
+ const title = 'Waiting for approval';
216
+ if (read.isOk) {
217
+ if (read.value.kind === 'waiting') {
218
+ return htmlPage(reply, { status: 200, title, body: waitingPage({ ...read.value, now: signIn.clock.now() }) });
219
+ }
220
+ const cleared = cookieHeader(WAITING_COOKIE, { value: '', maxAgeSeconds: 0, isSecure });
221
+ return reply.code(HTTP_FOUND).header('location', read.value.redirectTo).header('set-cookie', cleared).send();
222
+ }
223
+ const refusal = read.error;
224
+ switch (refusal.kind) {
225
+ case 'invalidClient':
226
+ case 'redirect':
227
+ return sendBack(reply, { refusal, issuer });
228
+ case 'unknownWaiting':
229
+ return errorPage(reply, { status: HTTP_NOT_FOUND, title, look: 'requestEnded', message: 'This request is unknown, or ended long ago. Start again from your MCP client.' });
230
+ case 'otherBrowser':
231
+ return errorPage(reply, { status: HTTP_BAD_REQUEST, title, look: 'otherBrowser', message: 'This request was made in another browser, so it is not yours to follow. Start again from your MCP client.' });
232
+ }
233
+ });
234
+ // The waiting page's live channel: told when its request expires, and to go on once the request no longer waits.
235
+ acceptWebsockets(server, () => {
236
+ server.get(`${WAITING_COOKIE.path}/live`, { websocket: true }, async (socket, request) => {
237
+ if (!isSameOrigin(request)) {
238
+ socket.close(CLOSE_OTHER_ORIGIN, 'Opened only from the waiting page');
239
+ return;
240
+ }
241
+ const opened = { waiting: fieldsOf(request.query).waiting ?? '', browserSecret: cookieValue(WAITING_COOKIE, request.headers.cookie) };
242
+ const watched = await signIn.watchWaiting(opened);
243
+ // Whatever does not wait, refused or decided, the page's own address says.
244
+ if (!watched.isOk || !watched.value.isWaiting) {
245
+ socket.send(JSON.stringify({ go: true }));
246
+ return;
247
+ }
248
+ socket.send(JSON.stringify({ expiresAt: watched.value.expiresAt.toISOString() }));
249
+ const unsubscribe = signIn.hub.subscribe({
250
+ fleetId: watched.value.fleetId,
251
+ read: () => {
252
+ void signIn.watchWaiting(opened).then((again) => {
253
+ if (!again.isOk || !again.value.isWaiting) {
254
+ socket.send(JSON.stringify({ go: true }));
255
+ unsubscribe();
256
+ }
257
+ });
258
+ },
259
+ });
260
+ socket.on('close', unsubscribe);
261
+ });
262
+ });
263
+ }
264
+ export function registerOAuthRoutes(server, deps) {
265
+ acceptForms(server);
266
+ const protectedResource = { resource: deps.resource, authorization_servers: [deps.issuer], bearer_methods_supported: ['header'] };
267
+ server.get('/.well-known/oauth-protected-resource', () => protectedResource);
268
+ server.get(`/.well-known/oauth-protected-resource${new URL(deps.resource).pathname}`, () => protectedResource);
269
+ server.get('/.well-known/oauth-authorization-server', () => ({
270
+ issuer: deps.issuer,
271
+ authorization_endpoint: `${deps.issuer}/authorize`,
272
+ token_endpoint: `${deps.issuer}/token`,
273
+ response_types_supported: ['code'],
274
+ grant_types_supported: ['authorization_code', 'refresh_token'],
275
+ code_challenge_methods_supported: ['S256'],
276
+ token_endpoint_auth_methods_supported: ['none', 'client_secret_basic', 'client_secret_post'],
277
+ client_id_metadata_document_supported: true,
278
+ authorization_response_iss_parameter_supported: true,
279
+ }));
280
+ server.get('/authorize', async (request, reply) => {
281
+ if (deps.signIn === undefined) {
282
+ return errorPage(reply, { status: HTTP_FORBIDDEN, title: 'Connect an MCP client', look: 'noSignIn', message: 'This gateway signs no one in, so no MCP client can connect to it: its operator sets pagasae first.' });
283
+ }
284
+ const parameters = authorizationRequestOf(fieldsOf(request.query));
285
+ const read = await deps.readAuthorization(parameters);
286
+ if (!read.isOk) {
287
+ return sendBack(reply, { refusal: read.error, issuer: deps.issuer });
288
+ }
289
+ return htmlPage(reply, { status: 200, title: 'Connect an MCP client', body: pickPage(parameters, read.value) });
290
+ });
291
+ if (deps.signIn !== undefined) {
292
+ registerSignIn(server, { issuer: deps.issuer, signIn: deps.signIn });
293
+ }
294
+ server.post('/token', async (request, reply) => {
295
+ const exchanged = await deps.exchangeToken({ ...fieldsOf(request.body), ...basicCredentials(request.headers.authorization) });
296
+ void reply.header('cache-control', 'no-store').header('pragma', 'no-cache');
297
+ if (!exchanged.isOk) {
298
+ const status = exchanged.error.error === 'invalid_client' ? HTTP_UNAUTHORIZED : HTTP_BAD_REQUEST;
299
+ return reply.code(status).send({ error: exchanged.error.error, error_description: exchanged.error.description });
300
+ }
301
+ const { accessToken, refreshToken, expiresInSeconds, scope } = exchanged.value;
302
+ return { access_token: accessToken, token_type: 'Bearer', expires_in: expiresInSeconds, refresh_token: refreshToken, ...(scope === null ? {} : { scope }) };
303
+ });
304
+ }
305
+ //# sourceMappingURL=oauth-routes.js.map