@tempoxyz/id 0.0.0-stage → 0.0.1

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 (1096) hide show
  1. package/README.md +121 -2
  2. package/dist/App.d.ts +121 -0
  3. package/dist/App.d.ts.map +1 -0
  4. package/dist/App.js +132 -0
  5. package/dist/App.js.map +1 -0
  6. package/dist/app/client/.assetsignore +2 -0
  7. package/dist/app/client/_headers +4 -0
  8. package/dist/app/client/assets/Account-BYLpNFf3.css +1 -0
  9. package/dist/app/client/assets/Account-BllJah07.js +1 -0
  10. package/dist/app/client/assets/Amount-E_7snI0-.js +1 -0
  11. package/dist/app/client/assets/Amount-ZdtluGf-.css +1 -0
  12. package/dist/app/client/assets/Approval-CgV5JHlb.css +1 -0
  13. package/dist/app/client/assets/Approval-yKflypU2.js +1 -0
  14. package/dist/app/client/assets/ArrowUp-CRvqfMNU.js +1 -0
  15. package/dist/app/client/assets/Authentication-BAXhOh_4.js +2 -0
  16. package/dist/app/client/assets/BRLA-CZvVDNYr.png +0 -0
  17. package/dist/app/client/assets/BRZ-Cn3jEi9t.svg +1 -0
  18. package/dist/app/client/assets/CHFAU-DCedc4aH.png +0 -0
  19. package/dist/app/client/assets/Callout-B736759d.js +1 -0
  20. package/dist/app/client/assets/Callout-DBfEmP7q.css +1 -0
  21. package/dist/app/client/assets/Check-DVgD8tDG.js +1 -0
  22. package/dist/app/client/assets/ChevronRight-CsXtIZCB.js +1 -0
  23. package/dist/app/client/assets/ChooseAccount-BjxfQjPK.js +1 -0
  24. package/dist/app/client/assets/ChooseAccount-DL3wgJhE.css +1 -0
  25. package/dist/app/client/assets/Client-JrABNovb.js +1 -0
  26. package/dist/app/client/assets/Close-CRvWlhqc.js +1 -0
  27. package/dist/app/client/assets/Cloud-DgJsrqpQ.js +1 -0
  28. package/dist/app/client/assets/CodeInput-79Ctx8ZA.js +1 -0
  29. package/dist/app/client/assets/CodeInput-BqRteSwD.css +1 -0
  30. package/dist/app/client/assets/DLUSD-BnRXm3EI.png +0 -0
  31. package/dist/app/client/assets/Deposit-CclrAoXL.css +1 -0
  32. package/dist/app/client/assets/Deposit-c7uYn2Eb.js +1 -0
  33. package/dist/app/client/assets/DevTools-BYkmtuV5.css +1 -0
  34. package/dist/app/client/assets/DevTools-BgnzDGo2.js +1 -0
  35. package/dist/app/client/assets/DeviceApproval-BBUVv58e.js +1 -0
  36. package/dist/app/client/assets/DeviceApproval-BffFLD8F.css +1 -0
  37. package/dist/app/client/assets/EURAU-sjieTTB9.svg +1 -0
  38. package/dist/app/client/assets/EURC.e-CxYiiwkz.svg +1 -0
  39. package/dist/app/client/assets/Fingerprint-BNCA6qOJ.js +1 -0
  40. package/dist/app/client/assets/GBPA-DI_25xSG.svg +4 -0
  41. package/dist/app/client/assets/GUSD-BDEP2Qb-.svg +1 -0
  42. package/dist/app/client/assets/GeistMono-Variable-BRXCGrxA.woff2 +0 -0
  43. package/dist/app/client/assets/Globe-f0eWzcEI.js +1 -0
  44. package/dist/app/client/assets/Grant-5a-n1gJH.css +1 -0
  45. package/dist/app/client/assets/Grant-Dp7mpcEi.js +1 -0
  46. package/dist/app/client/assets/Hex-C9KeV7_9.css +1 -0
  47. package/dist/app/client/assets/Hex-CSp2U46W.js +10 -0
  48. package/dist/app/client/assets/IconChip-DpZHa1JW.js +1 -0
  49. package/dist/app/client/assets/IconChip-yqaQ2y_d.css +1 -0
  50. package/dist/app/client/assets/InputGroup-BlZvt9In.css +1 -0
  51. package/dist/app/client/assets/InputGroup-CsOeBnpB.js +1 -0
  52. package/dist/app/client/assets/Inter-cyrillic-e3OmmzmJ.woff2 +0 -0
  53. package/dist/app/client/assets/Inter-cyrillic-ext-DOWZeO4Q.woff2 +0 -0
  54. package/dist/app/client/assets/Inter-greek-BD3ujQlX.woff2 +0 -0
  55. package/dist/app/client/assets/Inter-greek-ext-CXEwbus4.woff2 +0 -0
  56. package/dist/app/client/assets/Inter-latin-BDFm4vTb.woff2 +0 -0
  57. package/dist/app/client/assets/Inter-latin-ext-E7a9JEPe.woff2 +0 -0
  58. package/dist/app/client/assets/Inter-symbols-DEch7Rxr.woff2 +0 -0
  59. package/dist/app/client/assets/Inter-vietnamese-Bg9723vR.woff2 +0 -0
  60. package/dist/app/client/assets/Loader-Cm9YJNNJ.js +1 -0
  61. package/dist/app/client/assets/MACH-sK0r79kQ.svg +4 -0
  62. package/dist/app/client/assets/OUSD-BFXgVo-Z.svg +5 -0
  63. package/dist/app/client/assets/OUSD.dark-BbbjMvA1.svg +17 -0
  64. package/dist/app/client/assets/OUSD.light-B_zpSz_c.svg +17 -0
  65. package/dist/app/client/assets/PRIME-CiFp2-3e.svg +14 -0
  66. package/dist/app/client/assets/PopoverPopup-DprRXRQe.js +1 -0
  67. package/dist/app/client/assets/Rows-DPGTUdA8.css +1 -0
  68. package/dist/app/client/assets/Rows-Qqo3evtk.js +1 -0
  69. package/dist/app/client/assets/SBC-BTYkbkiD.svg +1 -0
  70. package/dist/app/client/assets/SEKAU-CB5Fc6o8.svg +5 -0
  71. package/dist/app/client/assets/Separator-CZUjVQOL.js +1 -0
  72. package/dist/app/client/assets/SignIn-HdaDzFmq.js +1 -0
  73. package/dist/app/client/assets/SignIn-mlBTwUq4.css +1 -0
  74. package/dist/app/client/assets/Stack-CkkvkOzj.js +1 -0
  75. package/dist/app/client/assets/Stack-D7Yt22Ed.css +1 -0
  76. package/dist/app/client/assets/Tag-BMh6ajrW.css +1 -0
  77. package/dist/app/client/assets/Tag-CLOVANTX.js +1 -0
  78. package/dist/app/client/assets/ToolbarRootContext-Zty_Dh3J.js +1 -0
  79. package/dist/app/client/assets/Tooltip-CLATV6YU.js +1 -0
  80. package/dist/app/client/assets/Tooltip-d3y9ESUJ.css +1 -0
  81. package/dist/app/client/assets/USD1-COVcO_PB.svg +30 -0
  82. package/dist/app/client/assets/USDB-Ckwb6UQw.svg +11 -0
  83. package/dist/app/client/assets/USDC.e-3nMsKAMC.svg +1 -0
  84. package/dist/app/client/assets/USDT0-ia60Dw0e.svg +1 -0
  85. package/dist/app/client/assets/USDY-CB4iet2q.svg +16 -0
  86. package/dist/app/client/assets/USDe-BXHQCd92.svg +1 -0
  87. package/dist/app/client/assets/Upgrade-D0_aO5AP.js +1 -0
  88. package/dist/app/client/assets/WalletUpgrade-BPsPNQsd.js +1 -0
  89. package/dist/app/client/assets/WalletUpgrade-C04kW0Jl.css +1 -0
  90. package/dist/app/client/assets/YLDS-CRh8Zw0g.svg +3 -0
  91. package/dist/app/client/assets/___-I98bns4o.css +1 -0
  92. package/dist/app/client/assets/___.flows-XOlLwMIy.js +5 -0
  93. package/dist/app/client/assets/alphaUSD-CpCFoVuh.svg +1 -0
  94. package/dist/app/client/assets/authorize-C-MlCyaM.js +1 -0
  95. package/dist/app/client/assets/betaUSD-9A8AjgYg.svg +1 -0
  96. package/dist/app/client/assets/cUSD-WsQfa-iC.svg +1 -0
  97. package/dist/app/client/assets/cbBTC-DvUDqrDi.svg +1 -0
  98. package/dist/app/client/assets/choose-account-nXR-SKa2.js +1 -0
  99. package/dist/app/client/assets/deposit-G8tiLPN4.js +1 -0
  100. package/dist/app/client/assets/device-BojBF7hZ.js +1 -0
  101. package/dist/app/client/assets/error-KiOpX7GD.js +1 -0
  102. package/dist/app/client/assets/frxUSD-n9pTpinR.svg +1 -0
  103. package/dist/app/client/assets/getPseudoElementBounds-BsLy4zf_.js +1 -0
  104. package/dist/app/client/assets/goUSD-D9kUvHsF.svg +5 -0
  105. package/dist/app/client/assets/iUSD-CWCJAq9X.svg +1 -0
  106. package/dist/app/client/assets/index-BZH0M7Nf.js +13 -0
  107. package/dist/app/client/assets/index-CIYxHmYA.css +1 -0
  108. package/dist/app/client/assets/login-DUjpk60p.js +1 -0
  109. package/dist/app/client/assets/pathUSD-BvaO6ooS.svg +25 -0
  110. package/dist/app/client/assets/preload-helper-Bs9KvdYl.js +1 -0
  111. package/dist/app/client/assets/rUSD-B-xuFS7T.svg +1 -0
  112. package/dist/app/client/assets/reUSD-CkIUs0Lx.svg +1 -0
  113. package/dist/app/client/assets/removable-DMiA3t_o.js +1 -0
  114. package/dist/app/client/assets/reset-co-CHrff.css +1 -0
  115. package/dist/app/client/assets/rolldown-runtime-WkwZ5CU-.js +1 -0
  116. package/dist/app/client/assets/routes-CK8cthzA.js +1 -0
  117. package/dist/app/client/assets/sUSDe-j9GOnH7I.svg +1 -0
  118. package/dist/app/client/assets/siUSD-C10QUNYS.svg +1 -0
  119. package/dist/app/client/assets/stcUSD-DIntDJeh.svg +1 -0
  120. package/dist/app/client/assets/syrupUSDC-DhYwZqdM.svg +5 -0
  121. package/dist/app/client/assets/thetaUSD-Dgmksf6G.svg +1 -0
  122. package/dist/app/client/assets/useNavigate-CB6S2u4J.js +1 -0
  123. package/dist/app/client/assets/useQuery-BpHfPhTT.js +1 -0
  124. package/dist/app/client/assets/useRegisterFieldControl-DsslqY-V.js +1 -0
  125. package/dist/app/client/assets/wYLDS-CaCKDrO-.svg +10 -0
  126. package/dist/app/client/assets/wsrUSD-B2Ey0bDQ.svg +1 -0
  127. package/dist/app/client/assets/zyzz-DYC-X0_B.css +1 -0
  128. package/dist/app/client/assets/zyzz.config-DX_D_7j3.js +2 -0
  129. package/dist/app/db/auth.d.ts +3412 -0
  130. package/dist/app/db/auth.d.ts.map +1 -0
  131. package/dist/app/db/auth.js +349 -0
  132. package/dist/app/db/auth.js.map +1 -0
  133. package/dist/app/db/schema.d.ts +1091 -0
  134. package/dist/app/db/schema.d.ts.map +1 -0
  135. package/dist/app/db/schema.js +183 -0
  136. package/dist/app/db/schema.js.map +1 -0
  137. package/dist/app/db/table.d.ts +8 -0
  138. package/dist/app/db/table.d.ts.map +1 -0
  139. package/dist/app/db/table.js +28 -0
  140. package/dist/app/db/table.js.map +1 -0
  141. package/dist/app/server/.vite/manifest.json +2093 -0
  142. package/dist/app/server/assets/Account-BYLpNFf3.css +1 -0
  143. package/dist/app/server/assets/Account-G_SUeRU3.js +2 -0
  144. package/dist/app/server/assets/Account-G_SUeRU3.js.map +1 -0
  145. package/dist/app/server/assets/Amount-Cgwdr3Xt.js +2 -0
  146. package/dist/app/server/assets/Amount-Cgwdr3Xt.js.map +1 -0
  147. package/dist/app/server/assets/Amount-ZdtluGf-.css +1 -0
  148. package/dist/app/server/assets/Approval-CgV5JHlb.css +1 -0
  149. package/dist/app/server/assets/Approval-DvkB9tWA.js +2 -0
  150. package/dist/app/server/assets/Approval-DvkB9tWA.js.map +1 -0
  151. package/dist/app/server/assets/ArrowUp-DpK_zNgZ.js +2 -0
  152. package/dist/app/server/assets/ArrowUp-DpK_zNgZ.js.map +1 -0
  153. package/dist/app/server/assets/Authentication-BOkhlNQu.js +2 -0
  154. package/dist/app/server/assets/Authentication-BOkhlNQu.js.map +1 -0
  155. package/dist/app/server/assets/Authentication-C3oNZAVX.js +2 -0
  156. package/dist/app/server/assets/Authentication-C3oNZAVX.js.map +1 -0
  157. package/dist/app/server/assets/BRLA-CZvVDNYr.png +0 -0
  158. package/dist/app/server/assets/BRZ-Cn3jEi9t.svg +1 -0
  159. package/dist/app/server/assets/Bytes-C7CRVS3J.js +4 -0
  160. package/dist/app/server/assets/Bytes-C7CRVS3J.js.map +1 -0
  161. package/dist/app/server/assets/CHFAU-DCedc4aH.png +0 -0
  162. package/dist/app/server/assets/Callout-DBfEmP7q.css +1 -0
  163. package/dist/app/server/assets/Callout-tQoAitWq.js +2 -0
  164. package/dist/app/server/assets/Callout-tQoAitWq.js.map +1 -0
  165. package/dist/app/server/assets/ChainList-C4A_7e-9.js +6 -0
  166. package/dist/app/server/assets/ChainList-C4A_7e-9.js.map +1 -0
  167. package/dist/app/server/assets/ChainName-BMnJyJrd.js +2 -0
  168. package/dist/app/server/assets/ChainName-BMnJyJrd.js.map +1 -0
  169. package/dist/app/server/assets/Check-DU_oR3Ev.js +2 -0
  170. package/dist/app/server/assets/Check-DU_oR3Ev.js.map +1 -0
  171. package/dist/app/server/assets/ChevronRight-DTBnw-W6.js +2 -0
  172. package/dist/app/server/assets/ChevronRight-DTBnw-W6.js.map +1 -0
  173. package/dist/app/server/assets/ChooseAccount-BizJvMrY.js +2 -0
  174. package/dist/app/server/assets/ChooseAccount-BizJvMrY.js.map +1 -0
  175. package/dist/app/server/assets/ChooseAccount-DL3wgJhE.css +1 -0
  176. package/dist/app/server/assets/Client-Dx3KrpJZ.js +2 -0
  177. package/dist/app/server/assets/Client-Dx3KrpJZ.js.map +1 -0
  178. package/dist/app/server/assets/ClientOnly-CKLiu67O.js +2 -0
  179. package/dist/app/server/assets/ClientOnly-CKLiu67O.js.map +1 -0
  180. package/dist/app/server/assets/Close-DUeE37ev.js +2 -0
  181. package/dist/app/server/assets/Close-DUeE37ev.js.map +1 -0
  182. package/dist/app/server/assets/Cloud-CLB3rTTy.js +2 -0
  183. package/dist/app/server/assets/Cloud-CLB3rTTy.js.map +1 -0
  184. package/dist/app/server/assets/CodeInput-BqRteSwD.css +1 -0
  185. package/dist/app/server/assets/CodeInput-FsPzVuLU.js +2 -0
  186. package/dist/app/server/assets/CodeInput-FsPzVuLU.js.map +1 -0
  187. package/dist/app/server/assets/Credential-DFjcrdyI.js +2 -0
  188. package/dist/app/server/assets/Credential-DFjcrdyI.js.map +1 -0
  189. package/dist/app/server/assets/DLUSD-BnRXm3EI.png +0 -0
  190. package/dist/app/server/assets/Deposit-CclrAoXL.css +1 -0
  191. package/dist/app/server/assets/Deposit-ChYGRfW2.js +2 -0
  192. package/dist/app/server/assets/Deposit-ChYGRfW2.js.map +1 -0
  193. package/dist/app/server/assets/DevTools-BYkmtuV5.css +1 -0
  194. package/dist/app/server/assets/DevTools-ZJVXqrIK.js +2 -0
  195. package/dist/app/server/assets/DevTools-ZJVXqrIK.js.map +1 -0
  196. package/dist/app/server/assets/DeviceApproval-BffFLD8F.css +1 -0
  197. package/dist/app/server/assets/DeviceApproval-Bqe3Mi78.js +2 -0
  198. package/dist/app/server/assets/DeviceApproval-Bqe3Mi78.js.map +1 -0
  199. package/dist/app/server/assets/EURAU-sjieTTB9.svg +1 -0
  200. package/dist/app/server/assets/EURC.e-CxYiiwkz.svg +1 -0
  201. package/dist/app/server/assets/ExecutionError-CDszGSF1.js +9 -0
  202. package/dist/app/server/assets/ExecutionError-CDszGSF1.js.map +1 -0
  203. package/dist/app/server/assets/Fingerprint-DhOPOdRr.js +2 -0
  204. package/dist/app/server/assets/Fingerprint-DhOPOdRr.js.map +1 -0
  205. package/dist/app/server/assets/GBPA-DI_25xSG.svg +4 -0
  206. package/dist/app/server/assets/GUSD-BDEP2Qb-.svg +1 -0
  207. package/dist/app/server/assets/GeistMono-Variable-BRXCGrxA.woff2 +0 -0
  208. package/dist/app/server/assets/Globe-2CxqxU-7.js +2 -0
  209. package/dist/app/server/assets/Globe-2CxqxU-7.js.map +1 -0
  210. package/dist/app/server/assets/Grant-5a-n1gJH.css +1 -0
  211. package/dist/app/server/assets/Grant-D_tun0mF.js +2 -0
  212. package/dist/app/server/assets/Grant-D_tun0mF.js.map +1 -0
  213. package/dist/app/server/assets/Hex-C9KeV7_9.css +1 -0
  214. package/dist/app/server/assets/Hex-Z6m_0Y0m.js +11 -0
  215. package/dist/app/server/assets/Hex-Z6m_0Y0m.js.map +1 -0
  216. package/dist/app/server/assets/IconChip-C9ZrmGB5.js +2 -0
  217. package/dist/app/server/assets/IconChip-C9ZrmGB5.js.map +1 -0
  218. package/dist/app/server/assets/IconChip-yqaQ2y_d.css +1 -0
  219. package/dist/app/server/assets/InputGroup-BlZvt9In.css +1 -0
  220. package/dist/app/server/assets/InputGroup-hpjuLuR7.js +2 -0
  221. package/dist/app/server/assets/InputGroup-hpjuLuR7.js.map +1 -0
  222. package/dist/app/server/assets/Inter-cyrillic-e3OmmzmJ.woff2 +0 -0
  223. package/dist/app/server/assets/Inter-cyrillic-ext-DOWZeO4Q.woff2 +0 -0
  224. package/dist/app/server/assets/Inter-greek-BD3ujQlX.woff2 +0 -0
  225. package/dist/app/server/assets/Inter-greek-ext-CXEwbus4.woff2 +0 -0
  226. package/dist/app/server/assets/Inter-latin-BDFm4vTb.woff2 +0 -0
  227. package/dist/app/server/assets/Inter-latin-ext-E7a9JEPe.woff2 +0 -0
  228. package/dist/app/server/assets/Inter-symbols-DEch7Rxr.woff2 +0 -0
  229. package/dist/app/server/assets/Inter-vietnamese-Bg9723vR.woff2 +0 -0
  230. package/dist/app/server/assets/Loader-DnKC9P5p.js +2 -0
  231. package/dist/app/server/assets/Loader-DnKC9P5p.js.map +1 -0
  232. package/dist/app/server/assets/MACH-sK0r79kQ.svg +4 -0
  233. package/dist/app/server/assets/Match-CyVdYcSf.js +2 -0
  234. package/dist/app/server/assets/Match-CyVdYcSf.js.map +1 -0
  235. package/dist/app/server/assets/OUSD-BFXgVo-Z.svg +5 -0
  236. package/dist/app/server/assets/OUSD.dark-BbbjMvA1.svg +17 -0
  237. package/dist/app/server/assets/OUSD.light-B_zpSz_c.svg +17 -0
  238. package/dist/app/server/assets/PRIME-CiFp2-3e.svg +14 -0
  239. package/dist/app/server/assets/PopoverPopup-CwqeQelI.js +2 -0
  240. package/dist/app/server/assets/PopoverPopup-CwqeQelI.js.map +1 -0
  241. package/dist/app/server/assets/Rows-CQKQwTI1.js +2 -0
  242. package/dist/app/server/assets/Rows-CQKQwTI1.js.map +1 -0
  243. package/dist/app/server/assets/Rows-DPGTUdA8.css +1 -0
  244. package/dist/app/server/assets/SBC-BTYkbkiD.svg +1 -0
  245. package/dist/app/server/assets/SEKAU-CB5Fc6o8.svg +5 -0
  246. package/dist/app/server/assets/Separator-DrI7KRAs.js +2 -0
  247. package/dist/app/server/assets/Separator-DrI7KRAs.js.map +1 -0
  248. package/dist/app/server/assets/SignIn-DfeeLEmN.js +2 -0
  249. package/dist/app/server/assets/SignIn-DfeeLEmN.js.map +1 -0
  250. package/dist/app/server/assets/SignIn-mlBTwUq4.css +1 -0
  251. package/dist/app/server/assets/Stack-D7Yt22Ed.css +1 -0
  252. package/dist/app/server/assets/Stack-DGktaLZc.js +2 -0
  253. package/dist/app/server/assets/Stack-DGktaLZc.js.map +1 -0
  254. package/dist/app/server/assets/Tag-9vSRBpph.js +2 -0
  255. package/dist/app/server/assets/Tag-9vSRBpph.js.map +1 -0
  256. package/dist/app/server/assets/Tag-BMh6ajrW.css +1 -0
  257. package/dist/app/server/assets/ToolbarRootContext-BH_CFSWd.js +2 -0
  258. package/dist/app/server/assets/ToolbarRootContext-BH_CFSWd.js.map +1 -0
  259. package/dist/app/server/assets/Tooltip-DLX41peb.js +2 -0
  260. package/dist/app/server/assets/Tooltip-DLX41peb.js.map +1 -0
  261. package/dist/app/server/assets/Tooltip-d3y9ESUJ.css +1 -0
  262. package/dist/app/server/assets/USD1-COVcO_PB.svg +30 -0
  263. package/dist/app/server/assets/USDB-Ckwb6UQw.svg +11 -0
  264. package/dist/app/server/assets/USDC.e-3nMsKAMC.svg +1 -0
  265. package/dist/app/server/assets/USDT0-ia60Dw0e.svg +1 -0
  266. package/dist/app/server/assets/USDY-CB4iet2q.svg +16 -0
  267. package/dist/app/server/assets/USDe-BXHQCd92.svg +1 -0
  268. package/dist/app/server/assets/Upgrade-Dbfm2nm0.js +2 -0
  269. package/dist/app/server/assets/Upgrade-Dbfm2nm0.js.map +1 -0
  270. package/dist/app/server/assets/WalletUpgrade-C04kW0Jl.css +1 -0
  271. package/dist/app/server/assets/WalletUpgrade-CWKc5fYt.js +2 -0
  272. package/dist/app/server/assets/WalletUpgrade-CWKc5fYt.js.map +1 -0
  273. package/dist/app/server/assets/YLDS-CRh8Zw0g.svg +3 -0
  274. package/dist/app/server/assets/___-I98bns4o.css +1 -0
  275. package/dist/app/server/assets/___.flows-Cc-awUoC.js +6 -0
  276. package/dist/app/server/assets/___.flows-Cc-awUoC.js.map +1 -0
  277. package/dist/app/server/assets/_tanstack-start-manifest_v-U7TrtUSA.js +1 -0
  278. package/dist/app/server/assets/_zyzz__2Fhome_2Frunner_2Fwork_2Fid_2Fid_2Fsrc_2Fapp_2Froutes_2F_5B__5D.flows-B1pPOqsM.css +1 -0
  279. package/dist/app/server/assets/_zyzz__2Fhome_2Frunner_2Fwork_2Fid_2Fid_2Fsrc_2Fapp_2Froutes_2F_5B__5D.flows.tsx-CKALi9oD.js +2 -0
  280. package/dist/app/server/assets/_zyzz__2Fhome_2Frunner_2Fwork_2Fid_2Fid_2Fsrc_2Fapp_2Froutes_2F_5B__5D.flows.tsx-CKALi9oD.js.map +1 -0
  281. package/dist/app/server/assets/_zyzz_shared-BbDIEd_j.css +1 -0
  282. package/dist/app/server/assets/alphaUSD-CpCFoVuh.svg +1 -0
  283. package/dist/app/server/assets/arktype-aI7TBD0R-D1R3Byo5.js +2 -0
  284. package/dist/app/server/assets/arktype-aI7TBD0R-D1R3Byo5.js.map +1 -0
  285. package/dist/app/server/assets/async-local-storage-DlOvwxXd.js +2 -0
  286. package/dist/app/server/assets/async-local-storage-DlOvwxXd.js.map +1 -0
  287. package/dist/app/server/assets/authorize-BXzTo2Pb.js +2 -0
  288. package/dist/app/server/assets/authorize-BXzTo2Pb.js.map +1 -0
  289. package/dist/app/server/assets/authorize-BzoUqOdA.js +2 -0
  290. package/dist/app/server/assets/authorize-BzoUqOdA.js.map +1 -0
  291. package/dist/app/server/assets/authorize-DXYo-K2n-rmQQ42x1.js +56 -0
  292. package/dist/app/server/assets/authorize-DXYo-K2n-rmQQ42x1.js.map +1 -0
  293. package/dist/app/server/assets/authorize-DfjPYJqS.css +1 -0
  294. package/dist/app/server/assets/betaUSD-9A8AjgYg.svg +1 -0
  295. package/dist/app/server/assets/bun-sqlite-dialect-DoOVo4ja-CtyBkVMb.js +2 -0
  296. package/dist/app/server/assets/bun-sqlite-dialect-DoOVo4ja-CtyBkVMb.js.map +1 -0
  297. package/dist/app/server/assets/cUSD-WsQfa-iC.svg +1 -0
  298. package/dist/app/server/assets/call-dzi0xjZd.js +31 -0
  299. package/dist/app/server/assets/call-dzi0xjZd.js.map +1 -0
  300. package/dist/app/server/assets/cbBTC-DvUDqrDi.svg +1 -0
  301. package/dist/app/server/assets/ccip-DjD8z_3B.js +2 -0
  302. package/dist/app/server/assets/ccip-DjD8z_3B.js.map +1 -0
  303. package/dist/app/server/assets/choose-account-_X7xq5am.js +2 -0
  304. package/dist/app/server/assets/choose-account-_X7xq5am.js.map +1 -0
  305. package/dist/app/server/assets/choose-account-lqA5SLx9.css +1 -0
  306. package/dist/app/server/assets/choose-account-zm-5Qs3e.js +2 -0
  307. package/dist/app/server/assets/choose-account-zm-5Qs3e.js.map +1 -0
  308. package/dist/app/server/assets/compiled-query-Ds2NVcFT.js +2 -0
  309. package/dist/app/server/assets/compiled-query-Ds2NVcFT.js.map +1 -0
  310. package/dist/app/server/assets/convert-BIC8n32x.js +2 -0
  311. package/dist/app/server/assets/convert-BIC8n32x.js.map +1 -0
  312. package/dist/app/server/assets/cookie-DxViaO10.js +2 -0
  313. package/dist/app/server/assets/cookie-DxViaO10.js.map +1 -0
  314. package/dist/app/server/assets/core-BBrZXfrB.js +56 -0
  315. package/dist/app/server/assets/core-BBrZXfrB.js.map +1 -0
  316. package/dist/app/server/assets/d1-sqlite-dialect-m0f01-4z-Cv-csE1u.js +2 -0
  317. package/dist/app/server/assets/d1-sqlite-dialect-m0f01-4z-Cv-csE1u.js.map +1 -0
  318. package/dist/app/server/assets/decodeFunctionData-bP6V2ai4.js +2 -0
  319. package/dist/app/server/assets/decodeFunctionData-bP6V2ai4.js.map +1 -0
  320. package/dist/app/server/assets/default-u_dwuiYb-DOrMMcg9.js +2 -0
  321. package/dist/app/server/assets/default-u_dwuiYb-DOrMMcg9.js.map +1 -0
  322. package/dist/app/server/assets/deposit-BBaNI01u.js +2 -0
  323. package/dist/app/server/assets/deposit-BBaNI01u.js.map +1 -0
  324. package/dist/app/server/assets/deposit-LWS6ZTuf.js +2 -0
  325. package/dist/app/server/assets/deposit-LWS6ZTuf.js.map +1 -0
  326. package/dist/app/server/assets/deposit-oFx15XCA.css +1 -0
  327. package/dist/app/server/assets/device-CrXlusjr.js +2 -0
  328. package/dist/app/server/assets/device-CrXlusjr.js.map +1 -0
  329. package/dist/app/server/assets/device-DdFMgYe2.js +2 -0
  330. package/dist/app/server/assets/device-DdFMgYe2.js.map +1 -0
  331. package/dist/app/server/assets/device-tMCpu5zk.css +1 -0
  332. package/dist/app/server/assets/dist-CR6FW-yS.js +1 -0
  333. package/dist/app/server/assets/dist-CoH0hD1s.js +15 -0
  334. package/dist/app/server/assets/dist-CoH0hD1s.js.map +1 -0
  335. package/dist/app/server/assets/dist-DcICI3fd.js +2 -0
  336. package/dist/app/server/assets/dist-DcICI3fd.js.map +1 -0
  337. package/dist/app/server/assets/effect-QlVUlMFu-mXPkuQTb.js +2 -0
  338. package/dist/app/server/assets/effect-QlVUlMFu-mXPkuQTb.js.map +1 -0
  339. package/dist/app/server/assets/empty-plugin-adapters-BaGcmrjC.js +2 -0
  340. package/dist/app/server/assets/empty-plugin-adapters-BaGcmrjC.js.map +1 -0
  341. package/dist/app/server/assets/error-CXy8gqdE.css +1 -0
  342. package/dist/app/server/assets/error-DXDT2AHy.js +2 -0
  343. package/dist/app/server/assets/error-DXDT2AHy.js.map +1 -0
  344. package/dist/app/server/assets/error-bnVzy9tx.js +2 -0
  345. package/dist/app/server/assets/error-bnVzy9tx.js.map +1 -0
  346. package/dist/app/server/assets/esm-C6SW--yt.js +4 -0
  347. package/dist/app/server/assets/esm-C6SW--yt.js.map +1 -0
  348. package/dist/app/server/assets/factory-dvoOlKer.js +5 -0
  349. package/dist/app/server/assets/factory-dvoOlKer.js.map +1 -0
  350. package/dist/app/server/assets/frxUSD-n9pTpinR.svg +1 -0
  351. package/dist/app/server/assets/get-id-field-OwLpfjj2.js +6 -0
  352. package/dist/app/server/assets/get-id-field-OwLpfjj2.js.map +1 -0
  353. package/dist/app/server/assets/getPseudoElementBounds-PkWU72kn.js +2 -0
  354. package/dist/app/server/assets/getPseudoElementBounds-PkWU72kn.js.map +1 -0
  355. package/dist/app/server/assets/goUSD-D9kUvHsF.svg +5 -0
  356. package/dist/app/server/assets/iUSD-CWCJAq9X.svg +1 -0
  357. package/dist/app/server/assets/index-CLddUTqr-CC33CMvS.js +2 -0
  358. package/dist/app/server/assets/index-CLddUTqr-CC33CMvS.js.map +1 -0
  359. package/dist/app/server/assets/index-DZEfthgZ-Ec2MMQ_e.js +2 -0
  360. package/dist/app/server/assets/index-DZEfthgZ-Ec2MMQ_e.js.map +1 -0
  361. package/dist/app/server/assets/kysely-adapter-B8tQwTcu.js +1 -0
  362. package/dist/app/server/assets/lazyRouteComponent-DPOOPZw_.js +2 -0
  363. package/dist/app/server/assets/lazyRouteComponent-DPOOPZw_.js.map +1 -0
  364. package/dist/app/server/assets/load-server-Dr0IlySo.js +3 -0
  365. package/dist/app/server/assets/load-server-Dr0IlySo.js.map +1 -0
  366. package/dist/app/server/assets/login-BLq3tEEr.js +2 -0
  367. package/dist/app/server/assets/login-BLq3tEEr.js.map +1 -0
  368. package/dist/app/server/assets/login-DCIrAbED.js +2 -0
  369. package/dist/app/server/assets/login-DCIrAbED.js.map +1 -0
  370. package/dist/app/server/assets/login-msDnt3yT.css +1 -0
  371. package/dist/app/server/assets/matchContext-ByrIUj4L.js +2 -0
  372. package/dist/app/server/assets/matchContext-ByrIUj4L.js.map +1 -0
  373. package/dist/app/server/assets/node-sqlite-dialect-BowWLXvK.js +2 -0
  374. package/dist/app/server/assets/node-sqlite-dialect-BowWLXvK.js.map +1 -0
  375. package/dist/app/server/assets/pathUSD-BvaO6ooS.svg +25 -0
  376. package/dist/app/server/assets/rUSD-B-xuFS7T.svg +1 -0
  377. package/dist/app/server/assets/reUSD-CkIUs0Lx.svg +1 -0
  378. package/dist/app/server/assets/react-dom-DYzj0HXX.js +2 -0
  379. package/dist/app/server/assets/react-dom-DYzj0HXX.js.map +1 -0
  380. package/dist/app/server/assets/removable-BCLTvPOx.js +2 -0
  381. package/dist/app/server/assets/removable-BCLTvPOx.js.map +1 -0
  382. package/dist/app/server/assets/reset-DZWeTZeQ.js +2 -0
  383. package/dist/app/server/assets/reset-DZWeTZeQ.js.map +1 -0
  384. package/dist/app/server/assets/reset-co-CHrff.css +1 -0
  385. package/dist/app/server/assets/resolveError-CZXXvCJR.js +2 -0
  386. package/dist/app/server/assets/resolveError-CZXXvCJR.js.map +1 -0
  387. package/dist/app/server/assets/rolldown-runtime-BWaJ3C7D.js +1 -0
  388. package/dist/app/server/assets/router-Bqz5X4Qw.js +2 -0
  389. package/dist/app/server/assets/router-Bqz5X4Qw.js.map +1 -0
  390. package/dist/app/server/assets/router-CclzitkY.css +1 -0
  391. package/dist/app/server/assets/routes-BLQdKqcZ.js +2 -0
  392. package/dist/app/server/assets/routes-BLQdKqcZ.js.map +1 -0
  393. package/dist/app/server/assets/routes-BgiIzrOt.css +1 -0
  394. package/dist/app/server/assets/routes-Bv6WzsSR.js +2 -0
  395. package/dist/app/server/assets/routes-Bv6WzsSR.js.map +1 -0
  396. package/dist/app/server/assets/sUSDe-j9GOnH7I.svg +1 -0
  397. package/dist/app/server/assets/schema-check-oLqvHR8y.js +9 -0
  398. package/dist/app/server/assets/schema-check-oLqvHR8y.js.map +1 -0
  399. package/dist/app/server/assets/secp256k1-yg8eeIYU.js +2 -0
  400. package/dist/app/server/assets/secp256k1-yg8eeIYU.js.map +1 -0
  401. package/dist/app/server/assets/server-RRUiOef2.js +76 -0
  402. package/dist/app/server/assets/server-RRUiOef2.js.map +1 -0
  403. package/dist/app/server/assets/siUSD-C10QUNYS.svg +1 -0
  404. package/dist/app/server/assets/sqlite-adapter-C_LAV4e3.js +2 -0
  405. package/dist/app/server/assets/sqlite-adapter-C_LAV4e3.js.map +1 -0
  406. package/dist/app/server/assets/sqlite-introspector-DSCAP82F-Crx7Ny14.js +6 -0
  407. package/dist/app/server/assets/sqlite-introspector-DSCAP82F-Crx7Ny14.js.map +1 -0
  408. package/dist/app/server/assets/standard-json-DY77efq0.js +2 -0
  409. package/dist/app/server/assets/standard-json-DY77efq0.js.map +1 -0
  410. package/dist/app/server/assets/standard-json-ig2t0wRt.js +2 -0
  411. package/dist/app/server/assets/standard-json-ig2t0wRt.js.map +1 -0
  412. package/dist/app/server/assets/standard-json-t-LNckA6.js +2 -0
  413. package/dist/app/server/assets/standard-json-t-LNckA6.js.map +1 -0
  414. package/dist/app/server/assets/standard-openapi-CONmVRl8.js +2 -0
  415. package/dist/app/server/assets/standard-openapi-CONmVRl8.js.map +1 -0
  416. package/dist/app/server/assets/start-C63VetBp.js +2 -0
  417. package/dist/app/server/assets/start-C63VetBp.js.map +1 -0
  418. package/dist/app/server/assets/stcUSD-DIntDJeh.svg +1 -0
  419. package/dist/app/server/assets/sury-CWZTCd75-CDaOS2oM.js +2 -0
  420. package/dist/app/server/assets/sury-CWZTCd75-CDaOS2oM.js.map +1 -0
  421. package/dist/app/server/assets/syrupUSDC-DhYwZqdM.svg +5 -0
  422. package/dist/app/server/assets/thetaUSD-Dgmksf6G.svg +1 -0
  423. package/dist/app/server/assets/typebox-Dei93FPO-D_lCVdAz.js +2 -0
  424. package/dist/app/server/assets/typebox-Dei93FPO-D_lCVdAz.js.map +1 -0
  425. package/dist/app/server/assets/useNavigate-D6d1w7KE.js +2 -0
  426. package/dist/app/server/assets/useNavigate-D6d1w7KE.js.map +1 -0
  427. package/dist/app/server/assets/useQuery-BRpCr5vj.js +2 -0
  428. package/dist/app/server/assets/useQuery-BRpCr5vj.js.map +1 -0
  429. package/dist/app/server/assets/useRegisterFieldControl-cJesrOWK.js +2 -0
  430. package/dist/app/server/assets/useRegisterFieldControl-cJesrOWK.js.map +1 -0
  431. package/dist/app/server/assets/utils-C4ZXZIZW.js +2 -0
  432. package/dist/app/server/assets/utils-C4ZXZIZW.js.map +1 -0
  433. package/dist/app/server/assets/utils-D57zfcg-.js +2 -0
  434. package/dist/app/server/assets/utils-D57zfcg-.js.map +1 -0
  435. package/dist/app/server/assets/valibot--1zFm7rT-CIKoH3MS.js +2 -0
  436. package/dist/app/server/assets/valibot--1zFm7rT-CIKoH3MS.js.map +1 -0
  437. package/dist/app/server/assets/valibot-D_HTw1Gn-BdPyLkXt.js +2 -0
  438. package/dist/app/server/assets/valibot-D_HTw1Gn-BdPyLkXt.js.map +1 -0
  439. package/dist/app/server/assets/wYLDS-CaCKDrO-.svg +10 -0
  440. package/dist/app/server/assets/wsrUSD-B2Ey0bDQ.svg +1 -0
  441. package/dist/app/server/assets/zod-Bwrt9trS-BezI5Gi1.js +2 -0
  442. package/dist/app/server/assets/zod-Bwrt9trS-BezI5Gi1.js.map +1 -0
  443. package/dist/app/server/assets/zod-DSgpEGAE-DZ7M_Q33.js +2 -0
  444. package/dist/app/server/assets/zod-DSgpEGAE-DZ7M_Q33.js.map +1 -0
  445. package/dist/app/server/assets/zyzz-6R2K52xP.css +1 -0
  446. package/dist/app/server/assets/zyzz.config-CJRpjn0E.js +3 -0
  447. package/dist/app/server/assets/zyzz.config-CJRpjn0E.js.map +1 -0
  448. package/dist/app/server/index.js +532 -0
  449. package/dist/app/server/index.js.map +1 -0
  450. package/dist/app/server/wrangler.json +1 -0
  451. package/dist/cli/Admin.d.ts +34 -0
  452. package/dist/cli/Admin.d.ts.map +1 -0
  453. package/dist/cli/Admin.js +61 -0
  454. package/dist/cli/Admin.js.map +1 -0
  455. package/dist/cli/Apps.d.ts +9 -0
  456. package/dist/cli/Apps.d.ts.map +1 -0
  457. package/dist/cli/Apps.js +34 -0
  458. package/dist/cli/Apps.js.map +1 -0
  459. package/dist/cli/Cli.d.ts +13 -0
  460. package/dist/cli/Cli.d.ts.map +1 -0
  461. package/dist/cli/Cli.js +26 -0
  462. package/dist/cli/Cli.js.map +1 -0
  463. package/dist/cli/Project.d.ts +17 -0
  464. package/dist/cli/Project.d.ts.map +1 -0
  465. package/dist/cli/Project.js +90 -0
  466. package/dist/cli/Project.js.map +1 -0
  467. package/dist/cli/Realms.d.ts +24 -0
  468. package/dist/cli/Realms.d.ts.map +1 -0
  469. package/dist/cli/Realms.js +48 -0
  470. package/dist/cli/Realms.js.map +1 -0
  471. package/dist/cli/Session.d.ts +79 -0
  472. package/dist/cli/Session.d.ts.map +1 -0
  473. package/dist/cli/Session.js +229 -0
  474. package/dist/cli/Session.js.map +1 -0
  475. package/dist/cli/User.d.ts +24 -0
  476. package/dist/cli/User.d.ts.map +1 -0
  477. package/dist/cli/User.js +34 -0
  478. package/dist/cli/User.js.map +1 -0
  479. package/dist/cli/V1.d.ts +32 -0
  480. package/dist/cli/V1.d.ts.map +1 -0
  481. package/dist/cli/V1.js +38 -0
  482. package/dist/cli/V1.js.map +1 -0
  483. package/dist/cli/bin.d.ts +3 -0
  484. package/dist/cli/bin.d.ts.map +1 -0
  485. package/dist/cli/bin.js +46 -0
  486. package/dist/cli/bin.js.map +1 -0
  487. package/dist/cli/commands/admin/apps/create.d.ts +23 -0
  488. package/dist/cli/commands/admin/apps/create.d.ts.map +1 -0
  489. package/dist/cli/commands/admin/apps/create.js +84 -0
  490. package/dist/cli/commands/admin/apps/create.js.map +1 -0
  491. package/dist/cli/commands/admin/apps/delete.d.ts +15 -0
  492. package/dist/cli/commands/admin/apps/delete.d.ts.map +1 -0
  493. package/dist/cli/commands/admin/apps/delete.js +41 -0
  494. package/dist/cli/commands/admin/apps/delete.js.map +1 -0
  495. package/dist/cli/commands/admin/apps/index.d.ts +5 -0
  496. package/dist/cli/commands/admin/apps/index.d.ts.map +1 -0
  497. package/dist/cli/commands/admin/apps/index.js +14 -0
  498. package/dist/cli/commands/admin/apps/index.js.map +1 -0
  499. package/dist/cli/commands/admin/apps/list.d.ts +10 -0
  500. package/dist/cli/commands/admin/apps/list.d.ts.map +1 -0
  501. package/dist/cli/commands/admin/apps/list.js +26 -0
  502. package/dist/cli/commands/admin/apps/list.js.map +1 -0
  503. package/dist/cli/commands/admin/apps/rotate-secret.d.ts +17 -0
  504. package/dist/cli/commands/admin/apps/rotate-secret.d.ts.map +1 -0
  505. package/dist/cli/commands/admin/apps/rotate-secret.js +47 -0
  506. package/dist/cli/commands/admin/apps/rotate-secret.js.map +1 -0
  507. package/dist/cli/commands/admin/apps/update.d.ts +20 -0
  508. package/dist/cli/commands/admin/apps/update.d.ts.map +1 -0
  509. package/dist/cli/commands/admin/apps/update.js +71 -0
  510. package/dist/cli/commands/admin/apps/update.js.map +1 -0
  511. package/dist/cli/commands/admin/index.d.ts +5 -0
  512. package/dist/cli/commands/admin/index.d.ts.map +1 -0
  513. package/dist/cli/commands/admin/index.js +13 -0
  514. package/dist/cli/commands/admin/index.js.map +1 -0
  515. package/dist/cli/commands/admin/migrate.d.ts +10 -0
  516. package/dist/cli/commands/admin/migrate.d.ts.map +1 -0
  517. package/dist/cli/commands/admin/migrate.js +20 -0
  518. package/dist/cli/commands/admin/migrate.js.map +1 -0
  519. package/dist/cli/commands/admin/realms/add.d.ts +13 -0
  520. package/dist/cli/commands/admin/realms/add.d.ts.map +1 -0
  521. package/dist/cli/commands/admin/realms/add.js +42 -0
  522. package/dist/cli/commands/admin/realms/add.js.map +1 -0
  523. package/dist/cli/commands/admin/realms/index.d.ts +5 -0
  524. package/dist/cli/commands/admin/realms/index.d.ts.map +1 -0
  525. package/dist/cli/commands/admin/realms/index.js +13 -0
  526. package/dist/cli/commands/admin/realms/index.js.map +1 -0
  527. package/dist/cli/commands/admin/realms/list.d.ts +14 -0
  528. package/dist/cli/commands/admin/realms/list.d.ts.map +1 -0
  529. package/dist/cli/commands/admin/realms/list.js +36 -0
  530. package/dist/cli/commands/admin/realms/list.js.map +1 -0
  531. package/dist/cli/commands/admin/realms/passkeys/index.d.ts +5 -0
  532. package/dist/cli/commands/admin/realms/passkeys/index.d.ts.map +1 -0
  533. package/dist/cli/commands/admin/realms/passkeys/index.js +13 -0
  534. package/dist/cli/commands/admin/realms/passkeys/index.js.map +1 -0
  535. package/dist/cli/commands/admin/realms/passkeys/set.d.ts +17 -0
  536. package/dist/cli/commands/admin/realms/passkeys/set.d.ts.map +1 -0
  537. package/dist/cli/commands/admin/realms/passkeys/set.js +46 -0
  538. package/dist/cli/commands/admin/realms/passkeys/set.js.map +1 -0
  539. package/dist/cli/commands/admin/realms/privy/index.d.ts +5 -0
  540. package/dist/cli/commands/admin/realms/privy/index.d.ts.map +1 -0
  541. package/dist/cli/commands/admin/realms/privy/index.js +13 -0
  542. package/dist/cli/commands/admin/realms/privy/index.js.map +1 -0
  543. package/dist/cli/commands/admin/realms/privy/set.d.ts +19 -0
  544. package/dist/cli/commands/admin/realms/privy/set.d.ts.map +1 -0
  545. package/dist/cli/commands/admin/realms/privy/set.js +66 -0
  546. package/dist/cli/commands/admin/realms/privy/set.js.map +1 -0
  547. package/dist/cli/commands/admin/realms/remove.d.ts +12 -0
  548. package/dist/cli/commands/admin/realms/remove.d.ts.map +1 -0
  549. package/dist/cli/commands/admin/realms/remove.js +35 -0
  550. package/dist/cli/commands/admin/realms/remove.js.map +1 -0
  551. package/dist/cli/commands/admin/realms/secp256k1/disable.d.ts +16 -0
  552. package/dist/cli/commands/admin/realms/secp256k1/disable.d.ts.map +1 -0
  553. package/dist/cli/commands/admin/realms/secp256k1/disable.js +42 -0
  554. package/dist/cli/commands/admin/realms/secp256k1/disable.js.map +1 -0
  555. package/dist/cli/commands/admin/realms/secp256k1/enable.d.ts +16 -0
  556. package/dist/cli/commands/admin/realms/secp256k1/enable.d.ts.map +1 -0
  557. package/dist/cli/commands/admin/realms/secp256k1/enable.js +42 -0
  558. package/dist/cli/commands/admin/realms/secp256k1/enable.js.map +1 -0
  559. package/dist/cli/commands/admin/realms/secp256k1/index.d.ts +9 -0
  560. package/dist/cli/commands/admin/realms/secp256k1/index.d.ts.map +1 -0
  561. package/dist/cli/commands/admin/realms/secp256k1/index.js +17 -0
  562. package/dist/cli/commands/admin/realms/secp256k1/index.js.map +1 -0
  563. package/dist/cli/commands/admin/realms/set.d.ts +17 -0
  564. package/dist/cli/commands/admin/realms/set.d.ts.map +1 -0
  565. package/dist/cli/commands/admin/realms/set.js +46 -0
  566. package/dist/cli/commands/admin/realms/set.js.map +1 -0
  567. package/dist/cli/commands/admin/rotate-key.d.ts +16 -0
  568. package/dist/cli/commands/admin/rotate-key.d.ts.map +1 -0
  569. package/dist/cli/commands/admin/rotate-key.js +46 -0
  570. package/dist/cli/commands/admin/rotate-key.js.map +1 -0
  571. package/dist/cli/commands/init.d.ts +11 -0
  572. package/dist/cli/commands/init.d.ts.map +1 -0
  573. package/dist/cli/commands/init.js +34 -0
  574. package/dist/cli/commands/init.js.map +1 -0
  575. package/dist/cli/commands/login.d.ts +12 -0
  576. package/dist/cli/commands/login.d.ts.map +1 -0
  577. package/dist/cli/commands/login.js +29 -0
  578. package/dist/cli/commands/login.js.map +1 -0
  579. package/dist/cli/commands/logout.d.ts +8 -0
  580. package/dist/cli/commands/logout.d.ts.map +1 -0
  581. package/dist/cli/commands/logout.js +19 -0
  582. package/dist/cli/commands/logout.js.map +1 -0
  583. package/dist/cli/commands/whoami.d.ts +12 -0
  584. package/dist/cli/commands/whoami.d.ts.map +1 -0
  585. package/dist/cli/commands/whoami.js +24 -0
  586. package/dist/cli/commands/whoami.js.map +1 -0
  587. package/dist/client/Actions.d.ts +108 -0
  588. package/dist/client/Actions.d.ts.map +1 -0
  589. package/dist/client/Actions.js +94 -0
  590. package/dist/client/Actions.js.map +1 -0
  591. package/dist/client/Auth.d.ts +143 -0
  592. package/dist/client/Auth.d.ts.map +1 -0
  593. package/dist/client/Auth.js +106 -0
  594. package/dist/client/Auth.js.map +1 -0
  595. package/dist/client/Authorization.d.ts +29 -0
  596. package/dist/client/Authorization.d.ts.map +1 -0
  597. package/dist/client/Authorization.js +12 -0
  598. package/dist/client/Authorization.js.map +1 -0
  599. package/dist/client/Decorator.d.ts +172 -0
  600. package/dist/client/Decorator.d.ts.map +1 -0
  601. package/dist/client/Decorator.js +241 -0
  602. package/dist/client/Decorator.js.map +1 -0
  603. package/dist/client/Key.d.ts +82 -0
  604. package/dist/client/Key.d.ts.map +1 -0
  605. package/dist/client/Key.js +81 -0
  606. package/dist/client/Key.js.map +1 -0
  607. package/dist/client/Pending.d.ts +38 -0
  608. package/dist/client/Pending.d.ts.map +1 -0
  609. package/dist/client/Pending.js +12 -0
  610. package/dist/client/Pending.js.map +1 -0
  611. package/dist/client/Permissions.d.ts +36 -0
  612. package/dist/client/Permissions.d.ts.map +1 -0
  613. package/dist/client/Permissions.js +16 -0
  614. package/dist/client/Permissions.js.map +1 -0
  615. package/dist/client/Storage.d.ts +27 -0
  616. package/dist/client/Storage.d.ts.map +1 -0
  617. package/dist/client/Storage.js +16 -0
  618. package/dist/client/Storage.js.map +1 -0
  619. package/dist/client/TempoAccount.d.ts +52 -0
  620. package/dist/client/TempoAccount.d.ts.map +1 -0
  621. package/dist/client/TempoAccount.js +17 -0
  622. package/dist/client/TempoAccount.js.map +1 -0
  623. package/dist/client/Tokens.d.ts +25 -0
  624. package/dist/client/Tokens.d.ts.map +1 -0
  625. package/dist/client/Tokens.js +12 -0
  626. package/dist/client/Tokens.js.map +1 -0
  627. package/dist/client/User.d.ts +21 -0
  628. package/dist/client/User.d.ts.map +1 -0
  629. package/dist/client/User.js +12 -0
  630. package/dist/client/User.js.map +1 -0
  631. package/dist/client/actions/account.d.ts +75 -0
  632. package/dist/client/actions/account.d.ts.map +1 -0
  633. package/dist/client/actions/account.js +102 -0
  634. package/dist/client/actions/account.js.map +1 -0
  635. package/dist/client/actions/device.d.ts +52 -0
  636. package/dist/client/actions/device.d.ts.map +1 -0
  637. package/dist/client/actions/device.js +103 -0
  638. package/dist/client/actions/device.js.map +1 -0
  639. package/dist/client/actions/email.d.ts +89 -0
  640. package/dist/client/actions/email.d.ts.map +1 -0
  641. package/dist/client/actions/email.js +86 -0
  642. package/dist/client/actions/email.js.map +1 -0
  643. package/dist/client/actions/oauth.d.ts +112 -0
  644. package/dist/client/actions/oauth.d.ts.map +1 -0
  645. package/dist/client/actions/oauth.js +103 -0
  646. package/dist/client/actions/oauth.js.map +1 -0
  647. package/dist/client/actions/passkey.d.ts +140 -0
  648. package/dist/client/actions/passkey.d.ts.map +1 -0
  649. package/dist/client/actions/passkey.js +170 -0
  650. package/dist/client/actions/passkey.js.map +1 -0
  651. package/dist/client/actions/realm.d.ts +25 -0
  652. package/dist/client/actions/realm.d.ts.map +1 -0
  653. package/dist/client/actions/realm.js +16 -0
  654. package/dist/client/actions/realm.js.map +1 -0
  655. package/dist/client/actions/redirect.d.ts +152 -0
  656. package/dist/client/actions/redirect.d.ts.map +1 -0
  657. package/dist/client/actions/redirect.js +311 -0
  658. package/dist/client/actions/redirect.js.map +1 -0
  659. package/dist/client/internal/accessKey.d.ts +21 -0
  660. package/dist/client/internal/accessKey.d.ts.map +1 -0
  661. package/dist/client/internal/accessKey.js +38 -0
  662. package/dist/client/internal/accessKey.js.map +1 -0
  663. package/dist/client/internal/account.d.ts +17 -0
  664. package/dist/client/internal/account.d.ts.map +1 -0
  665. package/dist/client/internal/account.js +3 -0
  666. package/dist/client/internal/account.js.map +1 -0
  667. package/dist/client/internal/api.d.ts +110 -0
  668. package/dist/client/internal/api.d.ts.map +1 -0
  669. package/dist/client/internal/api.js +136 -0
  670. package/dist/client/internal/api.js.map +1 -0
  671. package/dist/client/internal/headless.d.ts +159 -0
  672. package/dist/client/internal/headless.d.ts.map +1 -0
  673. package/dist/client/internal/headless.js +196 -0
  674. package/dist/client/internal/headless.js.map +1 -0
  675. package/dist/client/internal/indexedDb.d.ts +8 -0
  676. package/dist/client/internal/indexedDb.d.ts.map +1 -0
  677. package/dist/client/internal/indexedDb.js +32 -0
  678. package/dist/client/internal/indexedDb.js.map +1 -0
  679. package/dist/client/internal/request.d.ts +56 -0
  680. package/dist/client/internal/request.d.ts.map +1 -0
  681. package/dist/client/internal/request.js +44 -0
  682. package/dist/client/internal/request.js.map +1 -0
  683. package/dist/client/internal/store.d.ts +12 -0
  684. package/dist/client/internal/store.d.ts.map +1 -0
  685. package/dist/client/internal/store.js +15 -0
  686. package/dist/client/internal/store.js.map +1 -0
  687. package/dist/client/internal/verifier.d.ts +25 -0
  688. package/dist/client/internal/verifier.d.ts.map +1 -0
  689. package/dist/client/internal/verifier.js +52 -0
  690. package/dist/client/internal/verifier.js.map +1 -0
  691. package/dist/client.d.ts +18 -0
  692. package/dist/client.d.ts.map +1 -0
  693. package/dist/client.js +18 -0
  694. package/dist/client.js.map +1 -0
  695. package/dist/index.d.ts +6 -0
  696. package/dist/index.d.ts.map +1 -0
  697. package/dist/index.js +6 -0
  698. package/dist/index.js.map +1 -0
  699. package/dist/internal/Apps.d.ts +3169 -0
  700. package/dist/internal/Apps.d.ts.map +1 -0
  701. package/dist/internal/Apps.js +948 -0
  702. package/dist/internal/Apps.js.map +1 -0
  703. package/dist/internal/Auth.d.ts +4287 -0
  704. package/dist/internal/Auth.d.ts.map +1 -0
  705. package/dist/internal/Auth.js +185 -0
  706. package/dist/internal/Auth.js.map +1 -0
  707. package/dist/internal/Authorize.d.ts +526 -0
  708. package/dist/internal/Authorize.d.ts.map +1 -0
  709. package/dist/internal/Authorize.js +330 -0
  710. package/dist/internal/Authorize.js.map +1 -0
  711. package/dist/internal/Cache.d.ts +56 -0
  712. package/dist/internal/Cache.d.ts.map +1 -0
  713. package/dist/internal/Cache.js +65 -0
  714. package/dist/internal/Cache.js.map +1 -0
  715. package/dist/internal/Chain.d.ts +738 -0
  716. package/dist/internal/Chain.d.ts.map +1 -0
  717. package/dist/internal/Chain.js +65 -0
  718. package/dist/internal/Chain.js.map +1 -0
  719. package/dist/internal/ChainList.d.ts +117 -0
  720. package/dist/internal/ChainList.d.ts.map +1 -0
  721. package/dist/internal/ChainList.js +148 -0
  722. package/dist/internal/ChainList.js.map +1 -0
  723. package/dist/internal/ChainName.d.ts +11 -0
  724. package/dist/internal/ChainName.d.ts.map +1 -0
  725. package/dist/internal/ChainName.js +13 -0
  726. package/dist/internal/ChainName.js.map +1 -0
  727. package/dist/internal/CodeEmail.d.ts +38 -0
  728. package/dist/internal/CodeEmail.d.ts.map +1 -0
  729. package/dist/internal/CodeEmail.js +85 -0
  730. package/dist/internal/CodeEmail.js.map +1 -0
  731. package/dist/internal/ConfigurableAccount.d.ts +600 -0
  732. package/dist/internal/ConfigurableAccount.d.ts.map +1 -0
  733. package/dist/internal/ConfigurableAccount.js +795 -0
  734. package/dist/internal/ConfigurableAccount.js.map +1 -0
  735. package/dist/internal/Device.d.ts +246 -0
  736. package/dist/internal/Device.d.ts.map +1 -0
  737. package/dist/internal/Device.js +257 -0
  738. package/dist/internal/Device.js.map +1 -0
  739. package/dist/internal/Env.d.ts +97 -0
  740. package/dist/internal/Env.d.ts.map +1 -0
  741. package/dist/internal/Env.js +2 -0
  742. package/dist/internal/Env.js.map +1 -0
  743. package/dist/internal/ErrorResponse.d.ts +608 -0
  744. package/dist/internal/ErrorResponse.d.ts.map +1 -0
  745. package/dist/internal/ErrorResponse.js +701 -0
  746. package/dist/internal/ErrorResponse.js.map +1 -0
  747. package/dist/internal/Id.d.ts +10 -0
  748. package/dist/internal/Id.d.ts.map +1 -0
  749. package/dist/internal/Id.js +34 -0
  750. package/dist/internal/Id.js.map +1 -0
  751. package/dist/internal/KeyAuthorization.d.ts +1650 -0
  752. package/dist/internal/KeyAuthorization.d.ts.map +1 -0
  753. package/dist/internal/KeyAuthorization.js +1187 -0
  754. package/dist/internal/KeyAuthorization.js.map +1 -0
  755. package/dist/internal/Limits.d.ts +70 -0
  756. package/dist/internal/Limits.d.ts.map +1 -0
  757. package/dist/internal/Limits.js +36 -0
  758. package/dist/internal/Limits.js.map +1 -0
  759. package/dist/internal/Log.d.ts +34 -0
  760. package/dist/internal/Log.d.ts.map +1 -0
  761. package/dist/internal/Log.js +99 -0
  762. package/dist/internal/Log.js.map +1 -0
  763. package/dist/internal/LogLine.d.ts +29 -0
  764. package/dist/internal/LogLine.d.ts.map +1 -0
  765. package/dist/internal/LogLine.js +50 -0
  766. package/dist/internal/LogLine.js.map +1 -0
  767. package/dist/internal/Migrations.d.ts +28 -0
  768. package/dist/internal/Migrations.d.ts.map +1 -0
  769. package/dist/internal/Migrations.js +82 -0
  770. package/dist/internal/Migrations.js.map +1 -0
  771. package/dist/internal/Owner.d.ts +230 -0
  772. package/dist/internal/Owner.d.ts.map +1 -0
  773. package/dist/internal/Owner.js +101 -0
  774. package/dist/internal/Owner.js.map +1 -0
  775. package/dist/internal/Passkey.d.ts +901 -0
  776. package/dist/internal/Passkey.d.ts.map +1 -0
  777. package/dist/internal/Passkey.js +1185 -0
  778. package/dist/internal/Passkey.js.map +1 -0
  779. package/dist/internal/PendingKey.d.ts +49 -0
  780. package/dist/internal/PendingKey.d.ts.map +1 -0
  781. package/dist/internal/PendingKey.js +58 -0
  782. package/dist/internal/PendingKey.js.map +1 -0
  783. package/dist/internal/Privy.d.ts +138 -0
  784. package/dist/internal/Privy.d.ts.map +1 -0
  785. package/dist/internal/Privy.js +285 -0
  786. package/dist/internal/Privy.js.map +1 -0
  787. package/dist/internal/RateLimit.d.ts +218 -0
  788. package/dist/internal/RateLimit.d.ts.map +1 -0
  789. package/dist/internal/RateLimit.js +209 -0
  790. package/dist/internal/RateLimit.js.map +1 -0
  791. package/dist/internal/Realm.d.ts +290 -0
  792. package/dist/internal/Realm.d.ts.map +1 -0
  793. package/dist/internal/Realm.js +502 -0
  794. package/dist/internal/Realm.js.map +1 -0
  795. package/dist/internal/RequestId.d.ts +16 -0
  796. package/dist/internal/RequestId.d.ts.map +1 -0
  797. package/dist/internal/RequestId.js +78 -0
  798. package/dist/internal/RequestId.js.map +1 -0
  799. package/dist/internal/SigningKey.d.ts +126 -0
  800. package/dist/internal/SigningKey.d.ts.map +1 -0
  801. package/dist/internal/SigningKey.js +221 -0
  802. package/dist/internal/SigningKey.js.map +1 -0
  803. package/dist/internal/TempoAccount.d.ts +181 -0
  804. package/dist/internal/TempoAccount.d.ts.map +1 -0
  805. package/dist/internal/TempoAccount.js +369 -0
  806. package/dist/internal/TempoAccount.js.map +1 -0
  807. package/dist/internal/TestInbox.d.ts +42 -0
  808. package/dist/internal/TestInbox.d.ts.map +1 -0
  809. package/dist/internal/TestInbox.js +20 -0
  810. package/dist/internal/TestInbox.js.map +1 -0
  811. package/dist/internal/Timing.d.ts +52 -0
  812. package/dist/internal/Timing.d.ts.map +1 -0
  813. package/dist/internal/Timing.js +116 -0
  814. package/dist/internal/Timing.js.map +1 -0
  815. package/dist/internal/Validation.d.ts +52 -0
  816. package/dist/internal/Validation.d.ts.map +1 -0
  817. package/dist/internal/Validation.js +22 -0
  818. package/dist/internal/Validation.js.map +1 -0
  819. package/dist/internal/Verification.d.ts +24 -0
  820. package/dist/internal/Verification.d.ts.map +1 -0
  821. package/dist/internal/Verification.js +37 -0
  822. package/dist/internal/Verification.js.map +1 -0
  823. package/dist/internal/Wallet.d.ts +66 -0
  824. package/dist/internal/Wallet.d.ts.map +1 -0
  825. package/dist/internal/Wallet.js +59 -0
  826. package/dist/internal/Wallet.js.map +1 -0
  827. package/dist/internal/owners/Passkey.d.ts +9 -0
  828. package/dist/internal/owners/Passkey.d.ts.map +1 -0
  829. package/dist/internal/owners/Passkey.js +58 -0
  830. package/dist/internal/owners/Passkey.js.map +1 -0
  831. package/dist/internal/owners/Privy.d.ts +13 -0
  832. package/dist/internal/owners/Privy.d.ts.map +1 -0
  833. package/dist/internal/owners/Privy.js +59 -0
  834. package/dist/internal/owners/Privy.js.map +1 -0
  835. package/dist/internal/owners/Secp256k1.d.ts +12 -0
  836. package/dist/internal/owners/Secp256k1.d.ts.map +1 -0
  837. package/dist/internal/owners/Secp256k1.js +99 -0
  838. package/dist/internal/owners/Secp256k1.js.map +1 -0
  839. package/dist/worker.d.ts +18 -0
  840. package/dist/worker.d.ts.map +1 -0
  841. package/dist/worker.js +18 -0
  842. package/dist/worker.js.map +1 -0
  843. package/package.json +83 -3
  844. package/src/Api.ts +157 -0
  845. package/src/App.ts +316 -0
  846. package/src/api/account.ts +2266 -0
  847. package/src/api/authenticate.ts +1662 -0
  848. package/src/api/authorize.ts +1086 -0
  849. package/src/api/device.ts +516 -0
  850. package/src/api/health.ts +72 -0
  851. package/src/api/lib/AccountStep.ts +485 -0
  852. package/src/api/lib/Auth.ts +164 -0
  853. package/src/api/lib/Configure.ts +921 -0
  854. package/src/api/lib/Consent.ts +388 -0
  855. package/src/api/lib/Cors.ts +160 -0
  856. package/src/api/lib/Database.ts +10 -0
  857. package/src/api/lib/DeviceRequest.ts +244 -0
  858. package/src/api/lib/FirstAccount.ts +136 -0
  859. package/src/api/lib/Headless.ts +616 -0
  860. package/src/api/lib/IsolateCache.ts +28 -0
  861. package/src/api/lib/KeySigner.ts +690 -0
  862. package/src/api/lib/PasskeyLink.ts +162 -0
  863. package/src/api/lib/Session.ts +64 -0
  864. package/src/api/lib/SignInConsent.ts +393 -0
  865. package/src/api/oauth.ts +1796 -0
  866. package/src/app/components/CodeInput.tsx +153 -0
  867. package/src/app/components/DevTools.tsx +1071 -0
  868. package/src/app/components/Grant.tsx +476 -0
  869. package/src/app/components/icons/BRLA.png +0 -0
  870. package/src/app/components/icons/BRZ.svg +1 -0
  871. package/src/app/components/icons/CHFAU.png +0 -0
  872. package/src/app/components/icons/DLUSD.png +0 -0
  873. package/src/app/components/icons/EURAU.svg +1 -0
  874. package/src/app/components/icons/EURC.e.svg +1 -0
  875. package/src/app/components/icons/GBPA.svg +4 -0
  876. package/src/app/components/icons/GUSD.svg +1 -0
  877. package/src/app/components/icons/MACH.svg +4 -0
  878. package/src/app/components/icons/OUSD.svg +5 -0
  879. package/src/app/components/icons/PRIME.svg +14 -0
  880. package/src/app/components/icons/SBC.svg +1 -0
  881. package/src/app/components/icons/SEKAU.svg +5 -0
  882. package/src/app/components/icons/USD1.svg +30 -0
  883. package/src/app/components/icons/USDB.svg +11 -0
  884. package/src/app/components/icons/USDC.e.svg +1 -0
  885. package/src/app/components/icons/USDT0.svg +1 -0
  886. package/src/app/components/icons/USDY.svg +16 -0
  887. package/src/app/components/icons/USDe.svg +1 -0
  888. package/src/app/components/icons/YLDS.svg +3 -0
  889. package/src/app/components/icons/alphaUSD.svg +1 -0
  890. package/src/app/components/icons/betaUSD.svg +1 -0
  891. package/src/app/components/icons/cUSD.svg +1 -0
  892. package/src/app/components/icons/cbBTC.svg +1 -0
  893. package/src/app/components/icons/frxUSD.svg +1 -0
  894. package/src/app/components/icons/goUSD.svg +5 -0
  895. package/src/app/components/icons/iUSD.svg +1 -0
  896. package/src/app/components/icons/pathUSD.svg +25 -0
  897. package/src/app/components/icons/rUSD.svg +1 -0
  898. package/src/app/components/icons/reUSD.svg +1 -0
  899. package/src/app/components/icons/sUSDe.svg +1 -0
  900. package/src/app/components/icons/siUSD.svg +1 -0
  901. package/src/app/components/icons/stcUSD.svg +1 -0
  902. package/src/app/components/icons/syrupUSDC.svg +5 -0
  903. package/src/app/components/icons/thetaUSD.svg +1 -0
  904. package/src/app/components/icons/wYLDS.svg +10 -0
  905. package/src/app/components/icons/wsrUSD.svg +1 -0
  906. package/src/app/components/logos/OUSD.dark.svg +17 -0
  907. package/src/app/components/logos/OUSD.light.svg +17 -0
  908. package/src/app/coverage.server.ts +73 -0
  909. package/src/app/coverage.ts +69 -0
  910. package/src/app/crons/cleanup.ts +104 -0
  911. package/src/app/db/auth.ts +440 -0
  912. package/src/app/db/migrations/0000_better_auth.sql +53 -0
  913. package/src/app/db/migrations/0001_oauth_provider.sql +162 -0
  914. package/src/app/db/migrations/0002_device_code.sql +17 -0
  915. package/src/app/db/migrations/0003_realms.sql +27 -0
  916. package/src/app/db/migrations/0004_default_realm.sql +2 -0
  917. package/src/app/db/migrations/0005_passkeys.sql +30 -0
  918. package/src/app/db/migrations/0006_first_accounts.sql +9 -0
  919. package/src/app/db/migrations/0007_pending_keys.sql +13 -0
  920. package/src/app/db/migrations/0008_secp256k1_owners.sql +18 -0
  921. package/src/app/db/migrations/0009_device_requests.sql +8 -0
  922. package/src/app/db/migrations/0010_device_keys.sql +4 -0
  923. package/src/app/db/migrations/0011_registered_passkeys.sql +2 -0
  924. package/src/app/db/migrations/0012_passkey_accounts.sql +7 -0
  925. package/src/app/db/migrations/0013_first_party_apps.sql +4 -0
  926. package/src/app/db/migrations/0014_logout_revokes_tokens.sql +17 -0
  927. package/src/app/db/migrations/0015_expiry_indexes.sql +9 -0
  928. package/src/app/db/migrations/0016_configurable_accounts.sql +15 -0
  929. package/src/app/db/migrations/0017_account_config_keys.sql +3 -0
  930. package/src/app/db/migrations/0018_better_auth_1_8.sql +9 -0
  931. package/src/app/db/migrations/0019_drop_provider_account_index.sql +1 -0
  932. package/src/app/db/migrations/meta/0000_snapshot.json +362 -0
  933. package/src/app/db/migrations/meta/0001_snapshot.json +1487 -0
  934. package/src/app/db/migrations/meta/0002_snapshot.json +1603 -0
  935. package/src/app/db/migrations/meta/0003_snapshot.json +1760 -0
  936. package/src/app/db/migrations/meta/0004_snapshot.json +1760 -0
  937. package/src/app/db/migrations/meta/0005_snapshot.json +1911 -0
  938. package/src/app/db/migrations/meta/0006_snapshot.json +1967 -0
  939. package/src/app/db/migrations/meta/0007_snapshot.json +2047 -0
  940. package/src/app/db/migrations/meta/0008_snapshot.json +2157 -0
  941. package/src/app/db/migrations/meta/0009_snapshot.json +2207 -0
  942. package/src/app/db/migrations/meta/0010_snapshot.json +2231 -0
  943. package/src/app/db/migrations/meta/0011_snapshot.json +2231 -0
  944. package/src/app/db/migrations/meta/0012_snapshot.json +2231 -0
  945. package/src/app/db/migrations/meta/0013_snapshot.json +2231 -0
  946. package/src/app/db/migrations/meta/0014_snapshot.json +2231 -0
  947. package/src/app/db/migrations/meta/0015_snapshot.json +2375 -0
  948. package/src/app/db/migrations/meta/0016_snapshot.json +2475 -0
  949. package/src/app/db/migrations/meta/0017_snapshot.json +2481 -0
  950. package/src/app/db/migrations/meta/0018_snapshot.json +2535 -0
  951. package/src/app/db/migrations/meta/0019_snapshot.json +2514 -0
  952. package/src/app/db/migrations/meta/_journal.json +146 -0
  953. package/src/app/db/schema.ts +241 -0
  954. package/src/app/db/table.ts +31 -0
  955. package/src/app/env.ts +57 -0
  956. package/src/app/inbox.ts +190 -0
  957. package/src/app/lib/Client.ts +82 -0
  958. package/src/app/lib/Inbox.ts +11 -0
  959. package/src/app/lib/Loader.ts +21 -0
  960. package/src/app/lib/Upgrade.ts +221 -0
  961. package/src/app/package.json +8 -0
  962. package/src/app/public/_headers +4 -0
  963. package/src/app/routeTree.gen.ts +219 -0
  964. package/src/app/router.tsx +47 -0
  965. package/src/app/routes/[_].flows.tsx +4254 -0
  966. package/src/app/routes/__root.tsx +172 -0
  967. package/src/app/routes/authorize.tsx +379 -0
  968. package/src/app/routes/choose-account.tsx +144 -0
  969. package/src/app/routes/deposit.tsx +107 -0
  970. package/src/app/routes/device.tsx +273 -0
  971. package/src/app/routes/error.tsx +62 -0
  972. package/src/app/routes/index.tsx +511 -0
  973. package/src/app/routes/login.tsx +577 -0
  974. package/src/app/screens/Account.tsx +559 -0
  975. package/src/app/screens/Approval.tsx +444 -0
  976. package/src/app/screens/ChooseAccount.tsx +206 -0
  977. package/src/app/screens/Deposit.tsx +523 -0
  978. package/src/app/screens/DeviceApproval.tsx +500 -0
  979. package/src/app/screens/NotFound.tsx +62 -0
  980. package/src/app/screens/SignIn.tsx +372 -0
  981. package/src/app/screens/WalletUpgrade.tsx +121 -0
  982. package/src/app/screens/chains/base.svg +3 -0
  983. package/src/app/screens/chains/ethereum.svg +11 -0
  984. package/src/app/screens/chains/solana.svg +4 -0
  985. package/src/app/screens/chains/tempo.svg +4 -0
  986. package/src/app/server.ts +342 -0
  987. package/src/app/vite.config.ts +128 -0
  988. package/src/app/void.config.ts +36 -0
  989. package/src/app/wallet.ts +69 -0
  990. package/src/app/zyzz.config.ts +52 -0
  991. package/src/cli/Admin.ts +74 -0
  992. package/src/cli/Apps.ts +27 -0
  993. package/src/cli/Cli.ts +41 -0
  994. package/src/cli/Project.ts +119 -0
  995. package/src/cli/Realms.ts +49 -0
  996. package/src/cli/Session.ts +290 -0
  997. package/src/cli/User.ts +40 -0
  998. package/src/cli/V1.ts +54 -0
  999. package/src/cli/bin.ts +44 -0
  1000. package/src/cli/commands/admin/apps/create.ts +96 -0
  1001. package/src/cli/commands/admin/apps/delete.ts +38 -0
  1002. package/src/cli/commands/admin/apps/index.ts +15 -0
  1003. package/src/cli/commands/admin/apps/list.ts +25 -0
  1004. package/src/cli/commands/admin/apps/rotate-secret.ts +47 -0
  1005. package/src/cli/commands/admin/apps/update.ts +79 -0
  1006. package/src/cli/commands/admin/index.ts +14 -0
  1007. package/src/cli/commands/admin/migrate.ts +19 -0
  1008. package/src/cli/commands/admin/realms/add.ts +40 -0
  1009. package/src/cli/commands/admin/realms/index.ts +14 -0
  1010. package/src/cli/commands/admin/realms/list.ts +38 -0
  1011. package/src/cli/commands/admin/realms/passkeys/index.ts +15 -0
  1012. package/src/cli/commands/admin/realms/passkeys/set.ts +44 -0
  1013. package/src/cli/commands/admin/realms/privy/index.ts +14 -0
  1014. package/src/cli/commands/admin/realms/privy/set.ts +69 -0
  1015. package/src/cli/commands/admin/realms/remove.ts +33 -0
  1016. package/src/cli/commands/admin/realms/secp256k1/disable.ts +40 -0
  1017. package/src/cli/commands/admin/realms/secp256k1/enable.ts +40 -0
  1018. package/src/cli/commands/admin/realms/secp256k1/index.ts +19 -0
  1019. package/src/cli/commands/admin/realms/set.ts +46 -0
  1020. package/src/cli/commands/admin/rotate-key.ts +47 -0
  1021. package/src/cli/commands/init.ts +42 -0
  1022. package/src/cli/commands/login.ts +32 -0
  1023. package/src/cli/commands/logout.ts +19 -0
  1024. package/src/cli/commands/whoami.ts +23 -0
  1025. package/src/client/Actions.ts +180 -0
  1026. package/src/client/Auth.ts +267 -0
  1027. package/src/client/Authorization.ts +34 -0
  1028. package/src/client/Decorator.ts +444 -0
  1029. package/src/client/Key.ts +137 -0
  1030. package/src/client/Pending.ts +45 -0
  1031. package/src/client/Permissions.ts +41 -0
  1032. package/src/client/Storage.ts +29 -0
  1033. package/src/client/TempoAccount.ts +55 -0
  1034. package/src/client/Tokens.ts +27 -0
  1035. package/src/client/User.ts +23 -0
  1036. package/src/client/actions/account.ts +171 -0
  1037. package/src/client/actions/device.ts +166 -0
  1038. package/src/client/actions/email.ts +164 -0
  1039. package/src/client/actions/oauth.ts +179 -0
  1040. package/src/client/actions/passkey.ts +333 -0
  1041. package/src/client/actions/realm.ts +37 -0
  1042. package/src/client/actions/redirect.ts +502 -0
  1043. package/src/client/internal/accessKey.ts +54 -0
  1044. package/src/client/internal/account.ts +18 -0
  1045. package/src/client/internal/api.ts +242 -0
  1046. package/src/client/internal/headless.ts +308 -0
  1047. package/src/client/internal/indexedDb.ts +44 -0
  1048. package/src/client/internal/request.ts +70 -0
  1049. package/src/client/internal/store.ts +20 -0
  1050. package/src/client/internal/verifier.ts +75 -0
  1051. package/src/client.ts +17 -0
  1052. package/src/index.ts +5 -0
  1053. package/src/internal/Apps.ts +1283 -0
  1054. package/src/internal/Auth.ts +273 -0
  1055. package/src/internal/Authorize.ts +433 -0
  1056. package/src/internal/Balance.ts +144 -0
  1057. package/src/internal/BodyLimit.ts +31 -0
  1058. package/src/internal/Cache.ts +119 -0
  1059. package/src/internal/Chain.ts +99 -0
  1060. package/src/internal/ChainList.ts +270 -0
  1061. package/src/internal/ChainName.ts +14 -0
  1062. package/src/internal/ChainStatus.ts +65 -0
  1063. package/src/internal/CodeEmail.ts +138 -0
  1064. package/src/internal/ConfigurableAccount.ts +1315 -0
  1065. package/src/internal/Device.ts +471 -0
  1066. package/src/internal/Env.ts +92 -0
  1067. package/src/internal/ErrorResponse.ts +896 -0
  1068. package/src/internal/Faucet.ts +43 -0
  1069. package/src/internal/Id.ts +41 -0
  1070. package/src/internal/KeyAuthorization.ts +1536 -0
  1071. package/src/internal/Limits.ts +40 -0
  1072. package/src/internal/Log.ts +166 -0
  1073. package/src/internal/LogLine.ts +81 -0
  1074. package/src/internal/Logout.ts +356 -0
  1075. package/src/internal/Migrations.ts +120 -0
  1076. package/src/internal/OpenApi.ts +300 -0
  1077. package/src/internal/Owner.ts +310 -0
  1078. package/src/internal/Passkey.ts +1904 -0
  1079. package/src/internal/PendingKey.ts +104 -0
  1080. package/src/internal/Privy.ts +536 -0
  1081. package/src/internal/RateLimit.ts +346 -0
  1082. package/src/internal/Realm.ts +814 -0
  1083. package/src/internal/RequestId.ts +118 -0
  1084. package/src/internal/SignInGrant.ts +175 -0
  1085. package/src/internal/SigningKey.ts +319 -0
  1086. package/src/internal/TempoAccount.ts +545 -0
  1087. package/src/internal/TestInbox.ts +51 -0
  1088. package/src/internal/Timing.ts +172 -0
  1089. package/src/internal/Validation.ts +52 -0
  1090. package/src/internal/Verification.ts +58 -0
  1091. package/src/internal/Wallet.ts +101 -0
  1092. package/src/internal/owners/Passkey.ts +76 -0
  1093. package/src/internal/owners/Privy.ts +82 -0
  1094. package/src/internal/owners/Secp256k1.ts +139 -0
  1095. package/src/types/app.d.ts +39 -0
  1096. package/src/worker.ts +17 -0
@@ -0,0 +1,1796 @@
1
+ /**
2
+ * The OAuth and OpenID protocol paths under `/oauth2` and `/.well-known`, and the device grant's
3
+ * `/device/code`, which discovery advertises. Only the listed paths reach
4
+ * Better Auth, since its handler also serves client and consent management that Tempo ID calls only in
5
+ * process. Bodies and responses pass through, except that an error response gains `request_id`.
6
+ * A browser's authorization receives Tempo ID's page of its next step in place of a redirect to it.
7
+ * The device grant carries Tempo ID's key authorization through `/device/code` and `/oauth2/token`.
8
+ * Tempo ID serves `/oauth2/end-session` itself, since Better Auth's logout fetches the signing keys
9
+ * over HTTP and renders its own page.
10
+ * @module
11
+ */
12
+ import { decodeBasicCredentials } from '@better-auth/core/oauth2'
13
+ import { isAPIError } from 'better-auth/api'
14
+ import type { Context } from 'hono'
15
+ import { Hono } from 'hono'
16
+ import { Base64 } from 'ox'
17
+ import { env } from 'void/env'
18
+ import * as z from 'zod'
19
+ import * as Apps from '../internal/Apps.js'
20
+ import * as Authorize from '../internal/Authorize.js'
21
+ import * as BodyLimit from '../internal/BodyLimit.js'
22
+ import * as Device from '../internal/Device.js'
23
+ import type { Env } from '../internal/Env.js'
24
+ import * as ErrorResponse from '../internal/ErrorResponse.js'
25
+ import * as KeyAuthorization from '../internal/KeyAuthorization.js'
26
+ import * as Log from '../internal/Log.js'
27
+ import * as Logout from '../internal/Logout.js'
28
+ import * as OpenApi from '../internal/OpenApi.js'
29
+ import * as RateLimit from '../internal/RateLimit.js'
30
+ import * as SigningKey from '../internal/SigningKey.js'
31
+ import * as Timing from '../internal/Timing.js'
32
+ import * as Validation from '../internal/Validation.js'
33
+ import * as AccountStep from './lib/AccountStep.js'
34
+ import { db } from './lib/Database.js'
35
+ import * as DeviceRequest from './lib/DeviceRequest.js'
36
+ import * as Session from './lib/Session.js'
37
+ import * as SignInConsent from './lib/SignInConsent.js'
38
+
39
+ namespace schema {
40
+ export namespace openidConfiguration {
41
+ export const response = z
42
+ .looseObject({
43
+ authorization_endpoint: z.url().meta({
44
+ description: 'The authorization endpoint.',
45
+ examples: ['https://id.tempo.xyz/oauth2/authorize'],
46
+ }),
47
+ issuer: z.url().meta({
48
+ description: "The issuer's identifier, every token's `iss`.",
49
+ examples: ['https://id.tempo.xyz'],
50
+ }),
51
+ jwks_uri: z.url().meta({
52
+ description: "The issuer's signing keys.",
53
+ examples: ['https://id.tempo.xyz/oauth2/jwks'],
54
+ }),
55
+ token_endpoint: z.url().meta({
56
+ description: 'The token endpoint.',
57
+ examples: ['https://id.tempo.xyz/oauth2/token'],
58
+ }),
59
+ })
60
+ .meta({
61
+ description:
62
+ "The issuer's metadata (RFC 8414 §2, OpenID Connect Discovery §3), with the members that RFC 8414 defines.",
63
+ id: 'AuthorizationServerMetadata',
64
+ })
65
+ }
66
+
67
+ export namespace oauthAuthorizationServer {
68
+ export const response = openidConfiguration.response
69
+ }
70
+
71
+ export namespace authorize {
72
+ export const query = z.object({
73
+ challenge: z
74
+ .string()
75
+ .optional()
76
+ .meta({
77
+ description:
78
+ "A message, such as a sign-in challenge from the app's backend, whose EIP-191 hash becomes the key authorization's `witness` (TIP-1053). Requires `key_authorization`, and the app's `tempo-id:sign` scope.",
79
+ examples: ['Sign in to app.example.com\nNonce: 7f3a9c2e5b1d4f60'],
80
+ }),
81
+ client_id: z.string().meta({
82
+ description: "The app's client ID.",
83
+ examples: ['tempo-cli'],
84
+ }),
85
+ code_challenge: z.string().meta({
86
+ description:
87
+ 'The PKCE challenge: the base64url SHA-256 hash of the code verifier (RFC 7636 §4.2).',
88
+ examples: ['E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM'],
89
+ }),
90
+ code_challenge_method: z.literal('S256').meta({
91
+ description: 'The PKCE challenge method.',
92
+ }),
93
+ key_authorization: z
94
+ .string()
95
+ .optional()
96
+ .meta({
97
+ description:
98
+ "A key authorization for the app's own key, as base64url JSON in the shape of `KeyAuthorizationRequest`. The approval page shows the key, and `/oauth2/token` returns it beside the tokens once approval signs it. A key that breaks a rule returns to the redirect URI with the refusal.",
99
+ examples: [
100
+ 'eyJhZGRyZXNzIjoiMHg4MWMwZjIyYmQxNzNjMTE1ZDE4ZWVlYTBmNmEzOGU5MzVlY2Y1MmZiIn0',
101
+ ],
102
+ }),
103
+ prompt: z
104
+ .enum(['consent', 'login', 'none', 'select_account'])
105
+ .optional()
106
+ .meta({
107
+ description:
108
+ 'Whether the user signs in or consents again (OIDC Core §3.1.2.1). Absent to reuse the session and stored consent.',
109
+ examples: ['consent'],
110
+ }),
111
+ redirect_uri: z.url().meta({
112
+ description: "One of the app's registered redirect URIs.",
113
+ examples: ['https://app.example/callback'],
114
+ }),
115
+ resource: z
116
+ .url()
117
+ .optional()
118
+ .meta({
119
+ description:
120
+ "The API the access token is for (RFC 8707). Absent for Tempo ID's own origin.",
121
+ examples: ['https://id.tempo.xyz'],
122
+ }),
123
+ response_type: z.literal('code').meta({
124
+ description: 'The authorization code flow.',
125
+ }),
126
+ scope: z.string().meta({
127
+ description: 'Space-separated OAuth scopes.',
128
+ examples: ['openid profile email'],
129
+ }),
130
+ state: z
131
+ .string()
132
+ .optional()
133
+ .meta({
134
+ description:
135
+ 'An opaque value that the redirect returns to the app unchanged.',
136
+ examples: ['af0ifjsldkj'],
137
+ }),
138
+ })
139
+
140
+ export const response = z
141
+ .object({
142
+ redirect: z.boolean().meta({
143
+ description: 'Whether the app sends the browser to `url`.',
144
+ examples: [true],
145
+ }),
146
+ url: z.string().meta({
147
+ description:
148
+ 'Where the browser goes next: the sign-in page, the consent page, or the redirect URI with a code.',
149
+ examples: [
150
+ 'https://app.example/callback?code=SplxlOBeZQQYbYS6WxSbIA',
151
+ ],
152
+ }),
153
+ })
154
+ .meta({
155
+ description:
156
+ 'The next step of the authorization, for a request that a script sends.',
157
+ })
158
+ }
159
+
160
+ export namespace token {
161
+ /** An OAuth error response from the issuer, passed through. It carries no `reason`. */
162
+ export const error = z
163
+ .object({
164
+ error: z.string().meta({
165
+ description:
166
+ 'The RFC 6749 error code, such as `invalid_grant` or `invalid_client`.',
167
+ examples: ['invalid_grant'],
168
+ }),
169
+ error_description: z
170
+ .string()
171
+ .optional()
172
+ .meta({
173
+ description:
174
+ "The issuer's description of the error. Absent when the issuer sends none.",
175
+ examples: ['invalid code'],
176
+ }),
177
+ error_uri: z
178
+ .url()
179
+ .optional()
180
+ .meta({
181
+ description:
182
+ 'A page about the error. Absent when the issuer sends none.',
183
+ examples: ['https://example.com/docs/errors#invalid_grant'],
184
+ }),
185
+ request_id: z
186
+ .string()
187
+ .optional()
188
+ .meta({
189
+ description:
190
+ 'The request ID, which Tempo ID adds and `X-Request-Id` also carries.',
191
+ examples: ['5b3e1f2a-8c4d-4e6f-9a0b-7c2d1e3f4a5b'],
192
+ }),
193
+ })
194
+ .meta({
195
+ description:
196
+ "The issuer's OAuth error response (RFC 6749 §5.2), passed through.",
197
+ id: 'OAuthErrorResponse',
198
+ })
199
+
200
+ export const form = z.object({
201
+ client_id: z
202
+ .string()
203
+ .optional()
204
+ .meta({
205
+ description:
206
+ "The app's client ID. Absent when the app authenticates with HTTP Basic `Authorization`.",
207
+ examples: ['tempo-cli'],
208
+ }),
209
+ client_secret: z
210
+ .string()
211
+ .optional()
212
+ .meta({
213
+ description: "A confidential app's secret.",
214
+ examples: ['3bTm9qXc2Lr7WvN5kYp8Hs4Df6Ga1Je0'],
215
+ }),
216
+ code: z
217
+ .string()
218
+ .optional()
219
+ .meta({
220
+ description:
221
+ 'The authorization code to redeem, for the `authorization_code` grant.',
222
+ examples: ['SplxlOBeZQQYbYS6WxSbIA'],
223
+ }),
224
+ code_verifier: z
225
+ .string()
226
+ .optional()
227
+ .meta({
228
+ description:
229
+ "The PKCE verifier whose S256 hash is the authorization request's `code_challenge` (RFC 7636 §4.5).",
230
+ examples: ['dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk'],
231
+ }),
232
+ device_code: z
233
+ .string()
234
+ .optional()
235
+ .meta({
236
+ description:
237
+ 'The device code, for the device code grant (RFC 8628 §3.4).',
238
+ examples: ['GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS'],
239
+ }),
240
+ grant_type: z
241
+ .enum([
242
+ 'authorization_code',
243
+ 'client_credentials',
244
+ 'refresh_token',
245
+ 'urn:ietf:params:oauth:grant-type:device_code',
246
+ ])
247
+ .meta({
248
+ description: 'The OAuth grant that the request redeems.',
249
+ examples: ['authorization_code'],
250
+ }),
251
+ redirect_uri: z
252
+ .string()
253
+ .optional()
254
+ .meta({
255
+ description:
256
+ 'The redirect URI of the authorization request, for the `authorization_code` grant.',
257
+ examples: ['https://app.example/callback'],
258
+ }),
259
+ refresh_token: z
260
+ .string()
261
+ .optional()
262
+ .meta({
263
+ description:
264
+ 'The refresh token to redeem, for the `refresh_token` grant.',
265
+ examples: ['yAjhKk7QnRZ3vD9pLm2Xc8Ws5Tf1Ub4N'],
266
+ }),
267
+ resource: z
268
+ .url()
269
+ .optional()
270
+ .meta({
271
+ description:
272
+ "The API the access token is for (RFC 8707). Absent for Tempo ID's own origin.",
273
+ examples: ['https://id.tempo.xyz'],
274
+ }),
275
+ scope: z
276
+ .string()
277
+ .optional()
278
+ .meta({
279
+ description:
280
+ 'Space-separated OAuth scopes to request. Absent to keep the scopes of the grant.',
281
+ examples: ['openid profile email'],
282
+ }),
283
+ })
284
+
285
+ export const response = z
286
+ .looseObject({
287
+ access_token: z.string().meta({
288
+ description:
289
+ 'The access token, an RS256 JWT for the requested resource.',
290
+ examples: [
291
+ 'eyJhbGciOiJSUzI1NiIsInR5cCI6ImF0K2p3dCJ9.e30.c2lnbmF0dXJl',
292
+ ],
293
+ }),
294
+ account: KeyAuthorization.schema.account.optional().meta({
295
+ description:
296
+ 'The Tempo Account that the key acts for. Present beside `key_authorization`.',
297
+ examples: ['0x9a073914db0d149375ac2b7fbb72c68c0780fb5f'],
298
+ }),
299
+ expires_in: z.number().meta({
300
+ description: 'How long the access token lasts, in seconds.',
301
+ examples: [300],
302
+ }),
303
+ id_token: z
304
+ .string()
305
+ .optional()
306
+ .meta({
307
+ description:
308
+ 'The ID token, an RS256 JWT. Absent without the `openid` scope.',
309
+ examples: ['eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.e30.c2lnbmF0dXJl'],
310
+ }),
311
+ key_authorization: KeyAuthorization.schema.rpc.optional().meta({
312
+ description:
313
+ 'The key authorization that the approval page or the device page signed, for the first redemption of a code or device code whose request carried `key_authorization`. Absent for every other code, a refresh, and a key that expired.',
314
+ }),
315
+ refresh_token: z
316
+ .string()
317
+ .optional()
318
+ .meta({
319
+ description:
320
+ 'The refresh token. Absent without the `offline_access` scope.',
321
+ examples: ['yAjhKk7QnRZ3vD9pLm2Xc8Ws5Tf1Ub4N'],
322
+ }),
323
+ scope: z
324
+ .string()
325
+ .optional()
326
+ .meta({
327
+ description: 'Space-separated OAuth scopes of the tokens.',
328
+ examples: ['openid profile email'],
329
+ }),
330
+ token_type: z.string().meta({
331
+ description: 'The type of the access token (RFC 6749 §7.1).',
332
+ examples: ['Bearer'],
333
+ }),
334
+ })
335
+ .meta({
336
+ description: "The issuer's token response (RFC 6749 §5.1).",
337
+ id: 'TokenResponse',
338
+ })
339
+ }
340
+
341
+ export namespace deviceCode {
342
+ export const form = z.object({
343
+ client_id: z
344
+ .string()
345
+ .optional()
346
+ .meta({
347
+ description:
348
+ 'The client ID of an app that holds the device grant. Absent when the app authenticates with HTTP Basic `Authorization`.',
349
+ examples: ['tempo-cli'],
350
+ }),
351
+ client_secret: z
352
+ .string()
353
+ .optional()
354
+ .meta({
355
+ description: "A confidential app's secret.",
356
+ examples: ['3bTm9qXc2Lr7WvN5kYp8Hs4Df6Ga1Je0'],
357
+ }),
358
+ resource: z
359
+ .url()
360
+ .optional()
361
+ .meta({
362
+ description:
363
+ "The API the access token is for (RFC 8707). Absent for Tempo ID's own origin.",
364
+ examples: ['https://id.tempo.xyz'],
365
+ }),
366
+ scope: z
367
+ .string()
368
+ .optional()
369
+ .meta({
370
+ description:
371
+ 'Space-separated OAuth scopes. Defaults to `openid email offline_access`.',
372
+ examples: ['openid email offline_access'],
373
+ }),
374
+ })
375
+
376
+ /** The parameters that Tempo ID adds to the device authorization request. */
377
+ export const extension = z.object({
378
+ // The device page shows the challenge as the message that the key signs, so control and format
379
+ // characters, such as bidi overrides, cannot reorder it. Newlines and tabs stay.
380
+ challenge: Authorize.schema.challenge.refine(
381
+ (value) =>
382
+ value === undefined || /^(?:[\t\n]|[^\p{Cc}\p{Cf}])*$/u.test(value),
383
+ {
384
+ message:
385
+ 'Remove control and format characters, such as bidi overrides',
386
+ },
387
+ ),
388
+ device: z
389
+ .string()
390
+ .trim()
391
+ .min(1)
392
+ .max(64)
393
+ // The device page shows the name as the device reports it, so control and format characters,
394
+ // such as bidi overrides, cannot reorder the text around it.
395
+ .regex(/^[^\p{Cc}\p{Cf}]*$/u, {
396
+ message:
397
+ 'Remove control and format characters, such as bidi overrides',
398
+ })
399
+ .optional()
400
+ .meta({
401
+ description:
402
+ "The name that the device page shows, such as the machine's hostname. It holds no control or format characters.",
403
+ examples: ['ada-macbook'],
404
+ }),
405
+ key_authorization: authorize.query.shape.key_authorization.meta({
406
+ description:
407
+ "A key authorization for the app's own key, as base64url JSON in the shape of `KeyAuthorizationRequest`, from a public first-party app only. The device page shows it, approval signs it, and `/oauth2/token` returns it beside the tokens.",
408
+ examples: [
409
+ 'eyJhZGRyZXNzIjoiMHg4MWMwZjIyYmQxNzNjMTE1ZDE4ZWVlYTBmNmEzOGU5MzVlY2Y1MmZiIn0',
410
+ ],
411
+ }),
412
+ })
413
+
414
+ export const response = z
415
+ .object({
416
+ device_code: z.string().meta({
417
+ description:
418
+ 'The secret code that the device polls `/oauth2/token` with (RFC 8628 §3.2). The device keeps it private.',
419
+ examples: ['GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS'],
420
+ }),
421
+ expires_in: z.number().meta({
422
+ description: 'Seconds until the device code and user code expire.',
423
+ examples: [600],
424
+ }),
425
+ interval: z.number().meta({
426
+ description: 'Seconds between polls.',
427
+ examples: [5],
428
+ }),
429
+ user_code: z.string().meta({
430
+ description:
431
+ 'The code that the user enters on the verification page: eight consonants.',
432
+ examples: ['WDJBMJHT'],
433
+ }),
434
+ verification_uri: z.url().meta({
435
+ description: 'The page where the user enters the user code.',
436
+ examples: ['https://id.tempo.xyz/device'],
437
+ }),
438
+ verification_uri_complete: z.url().meta({
439
+ description:
440
+ 'The verification page with the user code filled in, for a link or QR code.',
441
+ examples: ['https://id.tempo.xyz/device?user_code=WDJBMJHT'],
442
+ }),
443
+ })
444
+ .meta({
445
+ description:
446
+ "The issuer's device authorization response (RFC 8628 §3.2).",
447
+ })
448
+
449
+ /** Better Auth's response, with the members that the device page's record reads. */
450
+ export const issued = z.looseObject({
451
+ device_code: z.string(),
452
+ expires_in: z.number(),
453
+ user_code: z.string(),
454
+ })
455
+ }
456
+
457
+ export namespace introspect {
458
+ export const form = z.object({
459
+ client_id: token.form.shape.client_id,
460
+ client_secret: token.form.shape.client_secret,
461
+ token: z.string().meta({
462
+ description: 'The token to introspect.',
463
+ examples: ['yAjhKk7QnRZ3vD9pLm2Xc8Ws5Tf1Ub4N'],
464
+ }),
465
+ token_type_hint: z
466
+ .enum(['access_token', 'refresh_token'])
467
+ .optional()
468
+ .meta({
469
+ description:
470
+ 'The type of `token`, which helps the issuer find it (RFC 7662 §2.1).',
471
+ examples: ['refresh_token'],
472
+ }),
473
+ })
474
+
475
+ export const response = z
476
+ .looseObject({
477
+ active: z.boolean().meta({
478
+ description:
479
+ 'Whether the token is active. An inactive token has no other members.',
480
+ examples: [true],
481
+ }),
482
+ client_id: z
483
+ .string()
484
+ .optional()
485
+ .meta({
486
+ description: 'The client ID of the app that the token belongs to.',
487
+ examples: ['tempo-cli'],
488
+ }),
489
+ exp: z
490
+ .number()
491
+ .optional()
492
+ .meta({
493
+ description: 'When the token expires, in Unix seconds.',
494
+ examples: [1792076100],
495
+ }),
496
+ iat: z
497
+ .number()
498
+ .optional()
499
+ .meta({
500
+ description: 'When the issuer issued the token, in Unix seconds.',
501
+ examples: [1792075800],
502
+ }),
503
+ iss: z
504
+ .string()
505
+ .optional()
506
+ .meta({
507
+ description: "The issuer's identifier.",
508
+ examples: ['https://id.tempo.xyz'],
509
+ }),
510
+ scope: z
511
+ .string()
512
+ .optional()
513
+ .meta({
514
+ description: 'Space-separated OAuth scopes of the token.',
515
+ examples: ['openid profile email'],
516
+ }),
517
+ sub: z
518
+ .string()
519
+ .optional()
520
+ .meta({
521
+ description: "The user ID of the token's subject.",
522
+ examples: ['user_01JZ8Q6W3N1R5B4V7C2X9K0M3T'],
523
+ }),
524
+ })
525
+ .meta({
526
+ description: "The issuer's introspection response (RFC 7662 §2.2).",
527
+ id: 'IntrospectionResponse',
528
+ })
529
+ }
530
+
531
+ export namespace revoke {
532
+ export const form = z.object({
533
+ client_id: token.form.shape.client_id,
534
+ client_secret: token.form.shape.client_secret,
535
+ token: z.string().meta({
536
+ description: 'The access or refresh token to revoke.',
537
+ examples: ['yAjhKk7QnRZ3vD9pLm2Xc8Ws5Tf1Ub4N'],
538
+ }),
539
+ token_type_hint: introspect.form.shape.token_type_hint,
540
+ })
541
+ }
542
+
543
+ export namespace userinfo {
544
+ export const response = z
545
+ .looseObject({
546
+ email: z
547
+ .string()
548
+ .optional()
549
+ .meta({
550
+ description:
551
+ "The user's email address. Absent without the `email` scope.",
552
+ examples: ['ada@example.com'],
553
+ }),
554
+ email_verified: z
555
+ .boolean()
556
+ .optional()
557
+ .meta({
558
+ description:
559
+ 'Whether the issuer verified the email address. Absent without the `email` scope.',
560
+ examples: [true],
561
+ }),
562
+ sub: z.string().meta({
563
+ description: 'The user ID.',
564
+ examples: ['user_01JZ8Q6W3N1R5B4V7C2X9K0M3T'],
565
+ }),
566
+ })
567
+ .meta({
568
+ description: "The issuer's UserInfo response (OIDC Core §5.3.2).",
569
+ id: 'UserInfoResponse',
570
+ })
571
+ }
572
+
573
+ export namespace endSession {
574
+ export const query = z.object({
575
+ client_id: z
576
+ .string()
577
+ .optional()
578
+ .meta({
579
+ description:
580
+ "The app's client ID. Absent when `id_token_hint` names the app.",
581
+ examples: ['tempo-cli'],
582
+ }),
583
+ continuation: z
584
+ .string()
585
+ .optional()
586
+ .meta({
587
+ description:
588
+ 'The sealed parameters of a form POST that carried no session cookie, which its 303 sends here. Absent otherwise.',
589
+ examples: ['a3f1c2…'],
590
+ }),
591
+ id_token_hint: z
592
+ .string()
593
+ .optional()
594
+ .meta({
595
+ description:
596
+ 'An ID token that Tempo ID issued to the app, even an expired one, which names the session to end. Required without `continuation`.',
597
+ examples: ['eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.e30.c2lnbmF0dXJl'],
598
+ }),
599
+ post_logout_redirect_uri: z
600
+ .url()
601
+ .optional()
602
+ .meta({
603
+ description:
604
+ "Where the browser goes after sign-out: one of the app's registered post-logout redirect URIs.",
605
+ examples: ['https://app.example/signed-out'],
606
+ }),
607
+ state: authorize.query.shape.state,
608
+ })
609
+
610
+ export const form = query.omit({ continuation: true }).extend({
611
+ id_token_hint: z.string().meta({
612
+ description:
613
+ 'An ID token that Tempo ID issued to the app, which names the session to end. It may be expired.',
614
+ examples: ['eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.e30.c2lnbmF0dXJl'],
615
+ }),
616
+ })
617
+
618
+ export const response = z.object({
619
+ signed_out: z.literal(true).meta({
620
+ description:
621
+ 'The browser holds no session that the hint names, since it ended or never held one.',
622
+ }),
623
+ })
624
+ }
625
+
626
+ export namespace jwks {
627
+ export const response = z
628
+ .object({
629
+ keys: z
630
+ .array(
631
+ z.looseObject({
632
+ alg: z
633
+ .string()
634
+ .optional()
635
+ .meta({
636
+ description: 'The algorithm that the key signs with.',
637
+ examples: ['RS256'],
638
+ }),
639
+ kid: z
640
+ .string()
641
+ .optional()
642
+ .meta({
643
+ description:
644
+ 'The key ID, which matches the `kid` header of a token that the key signs.',
645
+ examples: ['Qq0BN2lPx8VzTRsaGgMjc5HbEFKY4Wty'],
646
+ }),
647
+ kty: z.string().meta({
648
+ description: 'The key family (RFC 7518 §6.1).',
649
+ examples: ['RSA'],
650
+ }),
651
+ }),
652
+ )
653
+ .meta({
654
+ description:
655
+ "The issuer's public signing keys, with the members of each key that RFC 7517 defines.",
656
+ }),
657
+ })
658
+ .meta({
659
+ description: "The issuer's JSON Web Key Set (RFC 7517 §5).",
660
+ id: 'JsonWebKeySet',
661
+ })
662
+ }
663
+ }
664
+
665
+ /**
666
+ * The issuer's refusals, which pass through with their own status, and the `unexpected` error
667
+ * response that Tempo ID returns when the issuer fails.
668
+ */
669
+ const passthrough = {
670
+ ...OpenApi.errors([]),
671
+ 400: {
672
+ content: {
673
+ 'application/json': { schema: OpenApi.resolver(schema.token.error) },
674
+ },
675
+ description: "The issuer's refusal, passed through.",
676
+ },
677
+ 401: {
678
+ content: {
679
+ 'application/json': { schema: OpenApi.resolver(schema.token.error) },
680
+ },
681
+ description: "The issuer's refusal of the client or token, passed through.",
682
+ },
683
+ } as const
684
+
685
+ /** The responses of `POST /oauth2/introspect` in the OpenAPI document. */
686
+ const introspectRoute = {
687
+ responses: {
688
+ 200: {
689
+ content: {
690
+ 'application/json': {
691
+ schema: OpenApi.resolver(schema.introspect.response),
692
+ },
693
+ },
694
+ description: "The issuer's introspection response.",
695
+ },
696
+ ...passthrough,
697
+ ...OpenApi.errors([...BodyLimit.errors, ...RateLimit.check.errors]),
698
+ },
699
+ security: [{}, { clientBasic: [] }],
700
+ tags: ['OAuth'],
701
+ }
702
+
703
+ /** The description and responses of `GET` and `POST /oauth2/end-session` in the OpenAPI document. */
704
+ const endSessionRoute = {
705
+ description:
706
+ "Signs the browser out of the session that the app's ID token names, if the browser holds it, and revokes the tokens that apps received through it (OpenID Connect RP-Initiated Logout). Any other session stays signed in, and Tempo ID redirects the browser to the app's post-logout redirect URI.",
707
+ responses: {
708
+ 302: {
709
+ description:
710
+ "Redirects the browser to the app's post-logout redirect URI, with `state`.",
711
+ },
712
+ ...OpenApi.responses({
713
+ errors: [...OpenApi.validate.errors, ...Logout.check.errors],
714
+ success: {
715
+ description:
716
+ 'The browser is signed out of the session that the hint names, for a request without `post_logout_redirect_uri`.',
717
+ schema: schema.endSession.response,
718
+ },
719
+ }),
720
+ },
721
+ tags: ['OAuth'],
722
+ }
723
+
724
+ /**
725
+ * Returns the refusal of the device authorization request `form`'s `key`, or `undefined`. Only a
726
+ * public first-party device app receives a key, since its poll sends no secret, and a third-party
727
+ * app authorizes keys through a redirect. The device page shows the key, so a key that approval
728
+ * would refuse is refused here, before the device shows a code.
729
+ */
730
+ async function refuseDeviceKey(
731
+ c: Context<Env>,
732
+ options: refuseDeviceKey.Options,
733
+ ): Promise<ErrorResponse.Instance<typeof refuseDeviceKey.errors> | undefined> {
734
+ const { form, key } = options
735
+ const clientId = basicClientId(c.req.raw) ?? form.get('client_id')
736
+ const app = clientId
737
+ ? await Timing.measure(
738
+ c,
739
+ Apps.get(db, { clientId, enabled: true }).catch((error: unknown) => {
740
+ if (error instanceof Apps.NotFoundError) return undefined
741
+ throw error
742
+ }),
743
+ 'Apps.get',
744
+ )
745
+ : undefined
746
+ if (!clientId || !app?.device || app.secret || !app.firstParty)
747
+ return new Authorize.RejectedError({
748
+ description: `Device grant refused: \`client_id\` ${clientId ?? '(none)'} names no enabled public first-party device app. Send the client ID of a registered device app, or leave out \`key_authorization\`.`,
749
+ })
750
+ return (
751
+ KeyAuthorization.check(key) ??
752
+ KeyAuthorization.checkChallenge({ app, clientId, key })
753
+ )
754
+ }
755
+
756
+ declare namespace refuseDeviceKey {
757
+ type Options = {
758
+ /** The device authorization request's form. */
759
+ form: URLSearchParams
760
+ /** The key that the form requests, with its challenge bound. */
761
+ key: KeyAuthorization.Key
762
+ }
763
+ }
764
+
765
+ namespace refuseDeviceKey {
766
+ /** The refusals `refuseDeviceKey` returns. Its return type admits no other. */
767
+ export const errors = [
768
+ ...KeyAuthorization.check.errors,
769
+ ...KeyAuthorization.checkChallenge.errors,
770
+ Authorize.RejectedError,
771
+ ] as const
772
+ }
773
+
774
+ /**
775
+ * Returns the refusal of a `form` that repeats one of `names`, or `undefined`. A request parameter
776
+ * appears at most once (RFC 6749 §3.1).
777
+ */
778
+ function repeated(form: URLSearchParams, options: repeated.Options) {
779
+ const name = options.names.find((entry) => form.getAll(entry).length > 1)
780
+ if (!name) return undefined
781
+ return new Validation.InvalidFieldError({
782
+ issues: [{ message: 'Repeated parameter. Send it once', path: [name] }],
783
+ })
784
+ }
785
+
786
+ declare namespace repeated {
787
+ type Options = {
788
+ /** The parameters that may appear once. */
789
+ names: readonly string[]
790
+ }
791
+ }
792
+
793
+ /** The protocol paths that Better Auth serves over HTTP, with any method it accepts. */
794
+ const paths = [
795
+ '/.well-known/oauth-authorization-server',
796
+ '/.well-known/openid-configuration',
797
+ '/oauth2/authorize',
798
+ '/oauth2/introspect',
799
+ '/oauth2/jwks',
800
+ '/oauth2/revoke',
801
+ '/oauth2/token',
802
+ '/oauth2/userinfo',
803
+ ] as const
804
+
805
+ /** Tempo ID's pages that an authorization redirects to, which `GET /oauth2/authorize` renders. */
806
+ const pages: ReadonlySet<string> = new Set([
807
+ '/authorize',
808
+ '/choose-account',
809
+ '/error',
810
+ '/login',
811
+ ])
812
+
813
+ /** The paths whose handler resolves the client that the request names, which `limitDiscovery` counts. */
814
+ const discoveryPaths: ReadonlySet<string> = new Set([
815
+ '/device/code',
816
+ '/oauth2/authorize',
817
+ '/oauth2/introspect',
818
+ '/oauth2/revoke',
819
+ '/oauth2/token',
820
+ ])
821
+
822
+ /** The OAuth and OpenID protocol routes. */
823
+ export const oauth = new Hono<Env>()
824
+ .get(
825
+ '/.well-known/openid-configuration',
826
+ OpenApi.describeRoute({
827
+ description: "Reads the issuer's OpenID Connect discovery document.",
828
+ responses: OpenApi.responses({
829
+ success: {
830
+ description: 'The discovery document.',
831
+ schema: schema.openidConfiguration.response,
832
+ },
833
+ }),
834
+ tags: ['OAuth'],
835
+ }),
836
+ (c) => discovery(c),
837
+ )
838
+ .get(
839
+ '/.well-known/oauth-authorization-server',
840
+ OpenApi.describeRoute({
841
+ description: "Reads the issuer's authorization server metadata.",
842
+ responses: OpenApi.responses({
843
+ success: {
844
+ description: 'The metadata.',
845
+ schema: schema.oauthAuthorizationServer.response,
846
+ },
847
+ }),
848
+ tags: ['OAuth'],
849
+ }),
850
+ (c) => discovery(c),
851
+ )
852
+ .get(
853
+ '/oauth2/authorize',
854
+ OpenApi.describeRoute({
855
+ description:
856
+ 'Starts an authorization. A signed-out browser receives the sign-in page, and a signed-in one the consent page or a redirect to the redirect URI with a code.',
857
+ responses: {
858
+ 200: {
859
+ content: {
860
+ 'application/json': {
861
+ schema: OpenApi.resolver(schema.authorize.response),
862
+ },
863
+ 'text/html': { schema: { type: 'string' } },
864
+ },
865
+ description:
866
+ "The next step as JSON, for a request from a script. A browser navigation receives Tempo ID's page of the next step, such as the sign-in page or the error page.",
867
+ },
868
+ 302: {
869
+ description:
870
+ 'Redirects the browser to the redirect URI with a code. A refused `key_authorization` returns to the redirect URI with `error` and `error_description`.',
871
+ },
872
+ ...passthrough,
873
+ // A third-party app's requests count per address, before the redirect.
874
+ ...OpenApi.errors(RateLimit.check.errors),
875
+ },
876
+ tags: ['OAuth'],
877
+ }),
878
+ OpenApi.input('query', schema.authorize.query),
879
+ async (c) => {
880
+ const response = await Timing.measure(c, forward(c), 'oauth2.forward')
881
+ // A redirect to one of Tempo ID's own pages renders that page in this response, so the
882
+ // browser loads the page without a second request. Its URL keeps the signed query.
883
+ const location = URL.parse(
884
+ response.headers.get('location') ?? '',
885
+ env.URL,
886
+ )
887
+ if (
888
+ response.status !== 302 ||
889
+ location?.origin !== new URL(env.URL).origin ||
890
+ !pages.has(location.pathname)
891
+ )
892
+ return response
893
+
894
+ const setCookie = response.headers.getSetCookie()
895
+ for (const cookie of setCookie)
896
+ c.header('set-cookie', cookie, { append: true })
897
+ const request = new Request(location, {
898
+ headers: SignInConsent.sessionHeaders(c, { setCookie }),
899
+ })
900
+ return Timing.measure(c, c.env.pages(c, { request }), 'page.render')
901
+ },
902
+ )
903
+ .post(
904
+ '/oauth2/token',
905
+ OpenApi.describeRoute({
906
+ description:
907
+ 'Redeems an authorization code, a refresh token, a device code, or client credentials for tokens.',
908
+ responses: {
909
+ 200: {
910
+ content: {
911
+ 'application/json': {
912
+ schema: OpenApi.resolver(schema.token.response),
913
+ },
914
+ },
915
+ description: 'The tokens.',
916
+ },
917
+ ...passthrough,
918
+ ...OpenApi.errors([
919
+ ...BodyLimit.errors,
920
+ ...OpenApi.validate.errors,
921
+ ...RateLimit.check.errors,
922
+ ]),
923
+ },
924
+ // Body credentials or HTTP Basic, so either requirement satisfies it.
925
+ security: [{}, { clientBasic: [] }],
926
+ tags: ['OAuth'],
927
+ }),
928
+ OpenApi.input('form', schema.token.form),
929
+ async (c) => {
930
+ const limited = await Timing.measure(
931
+ c,
932
+ RateLimit.check(c, {
933
+ limits: [{ binding: 'TOKEN_LIMIT', key: RateLimit.ip(c) }],
934
+ }),
935
+ 'RateLimit.check',
936
+ )
937
+ if (limited) return limited
938
+
939
+ // A client ID is the caller's to choose, so an app's limit counts only a request whose client
940
+ // secret matches. A public app has no secret, and only the IP address bounds its callers.
941
+ const form = new URLSearchParams(
942
+ await Timing.measure(c, c.req.text(), 'request.text'),
943
+ )
944
+ const credentials = clientCredentials({
945
+ authorization: c.req.header('authorization'),
946
+ form,
947
+ })
948
+ const authenticated = credentials
949
+ ? await Timing.measure(
950
+ c,
951
+ Apps.authenticate(db, credentials),
952
+ 'Apps.authenticate',
953
+ )
954
+ : false
955
+ const limitedApp = await Timing.measure(
956
+ c,
957
+ RateLimit.check(c, {
958
+ limits: [
959
+ {
960
+ binding: 'TOKEN_APP_LIMIT',
961
+ key: authenticated ? credentials?.clientId : undefined,
962
+ },
963
+ ],
964
+ }),
965
+ 'RateLimit.check',
966
+ )
967
+ if (limitedApp) return limitedApp
968
+
969
+ // Better Auth reads the last value of a parameter, so the row is read for the code it redeems.
970
+ const twice = repeated(form, { names: ['device_code', 'grant_type'] })
971
+ if (twice) return ErrorResponse.json(c, twice)
972
+ // The redemption deletes the device code's row, so the row that names its held key is read
973
+ // first.
974
+ const deviceCode =
975
+ form.get('grant_type') === Apps.deviceGrant
976
+ ? form.get('device_code')
977
+ : null
978
+ const row = deviceCode
979
+ ? await Timing.measure(
980
+ c,
981
+ Device.find(db, { deviceCode }),
982
+ 'Device.find',
983
+ )
984
+ : undefined
985
+ const response = await Timing.measure(c, forward(c), 'oauth2.forward')
986
+ if (!row || !response.ok) return response
987
+ return Timing.measure(
988
+ c,
989
+ withDeviceKey(c, { id: row.id, response }),
990
+ 'oauth2.withDeviceKey',
991
+ )
992
+ },
993
+ )
994
+ .post(
995
+ '/device/code',
996
+ OpenApi.describeRoute({
997
+ description:
998
+ 'Starts the device grant (RFC 8628 §3.1). The user approves the user code on the device page, and the device then redeems the device code at `/oauth2/token`.',
999
+ responses: {
1000
+ 200: {
1001
+ content: {
1002
+ 'application/json': {
1003
+ schema: OpenApi.resolver(schema.deviceCode.response),
1004
+ },
1005
+ },
1006
+ description: 'The device code.',
1007
+ },
1008
+ ...passthrough,
1009
+ ...OpenApi.errors([
1010
+ ...BodyLimit.errors,
1011
+ ...OpenApi.validate.errors,
1012
+ ...RateLimit.check.errors,
1013
+ ...refuseDeviceKey.errors,
1014
+ ]),
1015
+ },
1016
+ security: [{}, { clientBasic: [] }],
1017
+ tags: ['OAuth'],
1018
+ }),
1019
+ OpenApi.input(
1020
+ 'form',
1021
+ schema.deviceCode.form.extend(schema.deviceCode.extension.shape),
1022
+ ),
1023
+ async (c) => {
1024
+ // A client ID in the body is the caller's to choose, so only the IP address bounds a caller. Any
1025
+ // page can post this form from a visitor's browser, which sends `Origin` and a CLI does not, so
1026
+ // a page's requests count apart and spend none of the quota of a CLI at the same address.
1027
+ const ip = RateLimit.ip(c)
1028
+ const limited = await Timing.measure(
1029
+ c,
1030
+ RateLimit.check(c, {
1031
+ limits: [
1032
+ {
1033
+ binding: 'DEVICE_LIMIT',
1034
+ key:
1035
+ ip !== undefined && c.req.header('origin') !== undefined
1036
+ ? `${ip}:browser`
1037
+ : ip,
1038
+ },
1039
+ ],
1040
+ }),
1041
+ 'RateLimit.check',
1042
+ )
1043
+ if (limited) return limited
1044
+
1045
+ const form = new URLSearchParams(
1046
+ await Timing.measure(c, c.req.text(), 'request.text'),
1047
+ )
1048
+ // Better Auth reads the last value of a parameter, and Tempo ID's checks the first.
1049
+ const twice = repeated(form, { names: ['client_id', 'device'] })
1050
+ if (twice) return ErrorResponse.json(c, twice)
1051
+ // The issuer prefers Basic credentials to the form's `client_id`, so the two must name one app.
1052
+ const basic = basicClientId(c.req.raw)
1053
+ if (basic && form.has('client_id') && form.get('client_id') !== basic)
1054
+ return ErrorResponse.json(
1055
+ c,
1056
+ new Validation.InvalidFieldError({
1057
+ issues: [
1058
+ {
1059
+ message:
1060
+ 'Conflicting client ID. Send the one of the Basic credentials, or leave it out',
1061
+ path: ['client_id'],
1062
+ },
1063
+ ],
1064
+ }),
1065
+ )
1066
+ const extension = schema.deviceCode.extension.safeParse({
1067
+ challenge: form.get('challenge') ?? undefined,
1068
+ device: form.get('device') ?? undefined,
1069
+ key_authorization: form.get('key_authorization') ?? undefined,
1070
+ })
1071
+ if (!extension.success)
1072
+ return ErrorResponse.json(
1073
+ c,
1074
+ new Validation.InvalidFieldError({ issues: extension.error.issues }),
1075
+ )
1076
+ const { challenge, device } = extension.data
1077
+ const key = Authorize.fromQuery(form)
1078
+ if (key instanceof ErrorResponse.ResponseError)
1079
+ return ErrorResponse.json(c, key)
1080
+
1081
+ if (key) {
1082
+ const refused = await Timing.measure(
1083
+ c,
1084
+ refuseDeviceKey(c, { form, key }),
1085
+ 'oauth2.refuseDeviceKey',
1086
+ )
1087
+ if (refused) return ErrorResponse.json(c, refused)
1088
+ }
1089
+
1090
+ const response = await Timing.measure(c, forward(c), 'oauth2.forward')
1091
+ if (!response.ok) return response
1092
+ // The device page shows where each code came from and the key it requests.
1093
+ const code = schema.deviceCode.issued.parse(
1094
+ await Timing.measure(c, response.json(), 'response.json'),
1095
+ )
1096
+ await Timing.measure(
1097
+ c,
1098
+ DeviceRequest.create(c, {
1099
+ challenge,
1100
+ device: device ?? null,
1101
+ deviceCode: code.device_code,
1102
+ expiresIn: code.expires_in,
1103
+ key: key && unbound(form),
1104
+ }),
1105
+ 'DeviceRequest.create',
1106
+ )
1107
+
1108
+ // The user code reads in two groups of four, as the device page shows it.
1109
+ const userCode = Device.format(code.user_code)
1110
+ const verification = new URL(Device.page, env.URL)
1111
+ const headers = new Headers(response.headers)
1112
+ headers.delete('content-length')
1113
+ return new Response(
1114
+ JSON.stringify({
1115
+ ...code,
1116
+ user_code: userCode,
1117
+ verification_uri: verification.href,
1118
+ verification_uri_complete: `${verification.href}?${new URLSearchParams({ code: userCode })}`,
1119
+ }),
1120
+ { headers, status: response.status },
1121
+ )
1122
+ },
1123
+ )
1124
+ .post(
1125
+ '/oauth2/introspect',
1126
+ OpenApi.describeRoute({
1127
+ description:
1128
+ 'Introspects a token (RFC 7662). The app authenticates with its client credentials, in the body or as HTTP Basic `Authorization`.',
1129
+ ...introspectRoute,
1130
+ }),
1131
+ OpenApi.input('form', schema.introspect.form),
1132
+ (c) => forward(c),
1133
+ )
1134
+ .post(
1135
+ '/oauth2/revoke',
1136
+ OpenApi.describeRoute({
1137
+ description:
1138
+ 'Revokes an access or refresh token (RFC 7009). The app authenticates with its client credentials, in the body or as HTTP Basic `Authorization`.',
1139
+ responses: {
1140
+ 200: {
1141
+ content: {
1142
+ 'application/json': {
1143
+ schema: {
1144
+ description:
1145
+ 'Empty: the token is revoked, or was already invalid (RFC 7009 §2.2).',
1146
+ },
1147
+ },
1148
+ },
1149
+ description: 'The token is revoked.',
1150
+ },
1151
+ ...passthrough,
1152
+ ...OpenApi.errors([...BodyLimit.errors, ...RateLimit.check.errors]),
1153
+ },
1154
+ security: [{}, { clientBasic: [] }],
1155
+ tags: ['OAuth'],
1156
+ }),
1157
+ OpenApi.input('form', schema.revoke.form),
1158
+ (c) => forward(c),
1159
+ )
1160
+ .get(
1161
+ '/oauth2/userinfo',
1162
+ OpenApi.describeRoute({
1163
+ description: "Reads the token subject's claims (OIDC Core §5.3).",
1164
+ responses: {
1165
+ 200: {
1166
+ content: {
1167
+ 'application/json': {
1168
+ schema: OpenApi.resolver(schema.userinfo.response),
1169
+ },
1170
+ },
1171
+ description: "The issuer's UserInfo response.",
1172
+ },
1173
+ ...passthrough,
1174
+ },
1175
+ security: [{ accessToken: [] }],
1176
+ tags: ['OAuth'],
1177
+ }),
1178
+ (c) => forward(c),
1179
+ )
1180
+ .get(
1181
+ '/oauth2/end-session',
1182
+ OpenApi.describeRoute(endSessionRoute),
1183
+ OpenApi.validate('query', schema.endSession.query),
1184
+ async (c) => endSession(c, c.req.valid('query')),
1185
+ )
1186
+ .post(
1187
+ '/oauth2/end-session',
1188
+ OpenApi.describeRoute({
1189
+ ...endSessionRoute,
1190
+ responses: {
1191
+ ...endSessionRoute.responses,
1192
+ ...OpenApi.errors(BodyLimit.errors),
1193
+ 303: {
1194
+ description:
1195
+ 'Continues a form POST without the session cookie as `GET /oauth2/end-session` with the sealed parameters in `continuation`, which the browser sends with the cookie.',
1196
+ },
1197
+ },
1198
+ }),
1199
+ OpenApi.validate('form', schema.endSession.form),
1200
+ async (c) => endSession(c, c.req.valid('form')),
1201
+ )
1202
+ .get(
1203
+ '/oauth2/jwks',
1204
+ OpenApi.describeRoute({
1205
+ description:
1206
+ "Reads the issuer's signing keys. A verifier may cache the response for 60 seconds, since a new key signs 5 minutes after its rotation.",
1207
+ responses: OpenApi.responses({
1208
+ success: {
1209
+ description: 'The JSON Web Key Set.',
1210
+ schema: schema.jwks.response,
1211
+ },
1212
+ }),
1213
+ tags: ['OAuth'],
1214
+ }),
1215
+ async (c) => {
1216
+ const response = await Timing.measure(c, forward(c), 'oauth2.forward')
1217
+ if (!response.ok) return response
1218
+ // A verifier caches the key set a fifth of the publication delay, so it holds a rotation's new
1219
+ // key well before the key signs. An empty set, before the first token creates the first key,
1220
+ // stays uncached, so a verifier reads that key once it signs.
1221
+ const keys = schema.jwks.response.safeParse(
1222
+ await Timing.measure(c, response.clone().json(), 'response.json'),
1223
+ )
1224
+ if (keys.success && keys.data.keys.length > 0)
1225
+ response.headers.set(
1226
+ 'cache-control',
1227
+ `public, max-age=${SigningKey.publication / 5}`,
1228
+ )
1229
+ return response
1230
+ },
1231
+ )
1232
+ // The other method of each path that Better Auth accepts, such as a `POST` to `/oauth2/userinfo`.
1233
+ .on(['GET', 'POST'], [...paths], (c) => forward(c))
1234
+
1235
+ /**
1236
+ * Returns the client ID and secret of a token request: from HTTP Basic `Authorization`, whose parts
1237
+ * RFC 6749 §2.3.1 form-encodes, or else from the form body, as Better Auth reads them. Returns
1238
+ * `undefined` for a request without a client secret, with a repeated one, or with an
1239
+ * `Authorization` header that does not decode.
1240
+ */
1241
+ function clientCredentials(options: clientCredentials.Options) {
1242
+ const { authorization, form } = options
1243
+ // The issuer decodes with the same function, so both read the same credentials.
1244
+ if (authorization && /^Basic +/i.test(authorization))
1245
+ try {
1246
+ return decodeBasicCredentials(authorization)
1247
+ } catch {
1248
+ return undefined
1249
+ }
1250
+
1251
+ // Better Auth drops empty values and refuses a repeated one, so only a single value counts.
1252
+ const [clientId, ...otherIds] = form
1253
+ .getAll('client_id')
1254
+ .filter((value) => value.length > 0)
1255
+ const [clientSecret, ...otherSecrets] = form
1256
+ .getAll('client_secret')
1257
+ .filter((value) => value.length > 0)
1258
+ if (!clientId || !clientSecret || otherIds.length || otherSecrets.length)
1259
+ return undefined
1260
+ return { clientId, clientSecret }
1261
+ }
1262
+
1263
+ declare namespace clientCredentials {
1264
+ type Options = {
1265
+ /** The request's `Authorization` header. */
1266
+ authorization: string | undefined
1267
+ /** The request's form body. */
1268
+ form: URLSearchParams
1269
+ }
1270
+ }
1271
+
1272
+ /**
1273
+ * Serves RP-initiated logout for `GET` and `POST /oauth2/end-session`, with the request's parameters.
1274
+ * It ends the browser's session only when the hint names that session, since RP-Initiated Logout §2
1275
+ * asks the user to confirm any other logout. Every valid request redirects to the app.
1276
+ */
1277
+ async function endSession(
1278
+ c: Context<Env>,
1279
+ input: z.output<typeof schema.endSession.query>,
1280
+ ) {
1281
+ const parameters =
1282
+ input.continuation === undefined
1283
+ ? input
1284
+ : await Timing.measure(
1285
+ c,
1286
+ Logout.unseal(input.continuation, { secret: env.SECRET }),
1287
+ 'Logout.unseal',
1288
+ )
1289
+ if (!parameters)
1290
+ return ErrorResponse.json(
1291
+ c,
1292
+ new Validation.InvalidFieldError({
1293
+ issues: [
1294
+ {
1295
+ message:
1296
+ 'Expired or invalid continuation. Send the logout request again',
1297
+ path: ['continuation'],
1298
+ },
1299
+ ],
1300
+ }),
1301
+ )
1302
+ const hint = parameters.id_token_hint
1303
+ if (!hint)
1304
+ return ErrorResponse.json(
1305
+ c,
1306
+ new Validation.InvalidFieldError({
1307
+ issues: [{ message: 'Required', path: ['id_token_hint'] }],
1308
+ }),
1309
+ )
1310
+
1311
+ const jwks = await Timing.measure(
1312
+ c,
1313
+ SigningKey.hintKeys(db, { hint }),
1314
+ 'SigningKey.hintKeys',
1315
+ )
1316
+ const logout = await Timing.measure(
1317
+ c,
1318
+ Logout.check(db, {
1319
+ clientId: parameters.client_id,
1320
+ hint,
1321
+ issuer: env.URL,
1322
+ jwks,
1323
+ postLogoutRedirectUri: parameters.post_logout_redirect_uri,
1324
+ state: parameters.state,
1325
+ }),
1326
+ 'Logout.check',
1327
+ )
1328
+ if (logout instanceof ErrorResponse.ResponseError)
1329
+ return ErrorResponse.json(c, logout)
1330
+
1331
+ const token = await Timing.measure(c, Session.token(c), 'Session.token')
1332
+ // One statement ends the session that the hint names, when it is the browser's own session.
1333
+ const ended = token
1334
+ ? await Timing.measure(
1335
+ c,
1336
+ Logout.end(db, { sessionId: logout.sessionId, token }),
1337
+ 'Logout.end',
1338
+ )
1339
+ : undefined
1340
+ const holds = ended !== undefined
1341
+ // A browser sends the `SameSite=Lax` session cookie on a top-level GET, but not on a cross-site
1342
+ // form POST, so a POST without the session continues as that GET. The GET never redirects again,
1343
+ // and its URL holds the parameters sealed, so the ID token stays out of history and logs.
1344
+ if (!holds && c.req.method === 'POST') {
1345
+ const continuation = await Timing.measure(
1346
+ c,
1347
+ Logout.seal(
1348
+ {
1349
+ client_id: parameters.client_id,
1350
+ id_token_hint: hint,
1351
+ post_logout_redirect_uri: parameters.post_logout_redirect_uri,
1352
+ state: parameters.state,
1353
+ },
1354
+ { secret: env.SECRET },
1355
+ ),
1356
+ 'Logout.seal',
1357
+ )
1358
+ const url = new URL('/oauth2/end-session', env.URL)
1359
+ url.searchParams.set('continuation', continuation)
1360
+ c.header('cache-control', 'no-store')
1361
+ return c.redirect(url.href, 303)
1362
+ }
1363
+
1364
+ if (holds) {
1365
+ await Timing.measure(c, Session.clear(c), 'Session.clear')
1366
+ // The next sign-in chooses each app's account again, as after `POST /v1/auth/logout`.
1367
+ c.header('set-cookie', AccountStep.clear(), { append: true })
1368
+ }
1369
+
1370
+ c.header('cache-control', 'no-store')
1371
+ if (logout.redirect) return c.redirect(logout.redirect, 302)
1372
+ return c.json({ signed_out: true as const }, 200)
1373
+ }
1374
+
1375
+ /** The discovery members of front-channel logout, which Tempo ID's end-session does not deliver. */
1376
+ const frontchannel = [
1377
+ 'frontchannel_logout_session_supported',
1378
+ 'frontchannel_logout_supported',
1379
+ ] as const
1380
+
1381
+ /**
1382
+ * Forwards the discovery request `c` to Better Auth, and returns its document without the
1383
+ * `frontchannel` members. The issuer advertises front-channel logout unconditionally, but
1384
+ * `Logout.end` ends the session without the issuer's end-session page, which delivers it.
1385
+ */
1386
+ async function discovery(c: Context<Env>) {
1387
+ const response = await Timing.measure(c, forward(c), 'oauth2.forward')
1388
+ // Hono serves HEAD through this GET route, and the issuer responds to HEAD without a body.
1389
+ if (!response.ok || c.req.method === 'HEAD') return response
1390
+
1391
+ const document = z
1392
+ .record(z.string(), z.unknown())
1393
+ .parse(await Timing.measure(c, response.json(), 'response.json'))
1394
+ for (const member of frontchannel) delete document[member]
1395
+
1396
+ const headers = new Headers(response.headers)
1397
+ headers.delete('content-length')
1398
+ return new Response(JSON.stringify(document), {
1399
+ headers,
1400
+ status: response.status,
1401
+ })
1402
+ }
1403
+
1404
+ /**
1405
+ * Forwards the request `c` to Better Auth, and returns its response. An authorization request with
1406
+ * a key that Tempo ID refuses returns to the app's redirect URI instead, as `refuseKey` describes.
1407
+ * A request that names a third-party app past the address's `APP_DISCOVERY_LIMIT` responds with
1408
+ * `rate_limited`.
1409
+ */
1410
+ async function forward(c: Context<Env>) {
1411
+ const request = await Timing.measure(
1412
+ c,
1413
+ withResource(c),
1414
+ 'oauth2.withResource',
1415
+ )
1416
+ const body =
1417
+ request.method === 'POST'
1418
+ ? await Timing.measure(c, request.clone().text(), 'request.text')
1419
+ : undefined
1420
+ // Better Auth reads a `POST` request's parameters from its form body, and only from there.
1421
+ const form =
1422
+ body !== undefined &&
1423
+ request.headers
1424
+ .get('content-type')
1425
+ ?.toLowerCase()
1426
+ .includes('application/x-www-form-urlencoded')
1427
+ const query = form
1428
+ ? new URLSearchParams(body)
1429
+ : new URL(request.url).searchParams
1430
+
1431
+ const limited = await Timing.measure(
1432
+ c,
1433
+ limitDiscovery(c, { body, request }),
1434
+ 'oauth2.limitDiscovery',
1435
+ )
1436
+ if (limited) return limited
1437
+
1438
+ // Better Auth reads the last `client_id` of a form, and Tempo ID's checks the first, so a form
1439
+ // that names two apps is refused before either reads it.
1440
+ if (
1441
+ c.req.path === '/oauth2/authorize' &&
1442
+ query.getAll('client_id').length > 1
1443
+ )
1444
+ return ErrorResponse.json(
1445
+ c,
1446
+ new Validation.InvalidFieldError({
1447
+ issues: [
1448
+ { message: 'Repeated parameter. Send it once', path: ['client_id'] },
1449
+ ],
1450
+ }),
1451
+ )
1452
+
1453
+ // The issuer approves a device code through `/oauth2/authorize` with its `user_code`, and responds
1454
+ // whether the code is live without counting the request. The `/device` page approves device codes,
1455
+ // and counts each user's lookups.
1456
+ if (c.req.path === '/oauth2/authorize' && query.has('user_code'))
1457
+ return ErrorResponse.json(
1458
+ c,
1459
+ new Validation.InvalidFieldError({
1460
+ issues: [
1461
+ {
1462
+ message: 'Unsupported parameter. Approve a device code at /device',
1463
+ path: ['user_code'],
1464
+ },
1465
+ ],
1466
+ }),
1467
+ )
1468
+
1469
+ // The token endpoint runs as Better Auth's endpoint, without the router that `auth.handler` builds
1470
+ // from every endpoint for each request. The router's origin check and request hooks serve cookie
1471
+ // sessions and discovery, and the token endpoint reads neither. The form reads as the router reads
1472
+ // it, with the last value of a repeated parameter.
1473
+ if (c.req.path === '/oauth2/token' && form) {
1474
+ const params: Record<string, string> = {}
1475
+ for (const [name, value] of query) params[name] = value
1476
+ return Timing.measure(
1477
+ c,
1478
+ c.var.auth.api.oauth2Token({
1479
+ asResponse: true,
1480
+ // The endpoint validates the form against its schema, as for the router, so a form without
1481
+ // `grant_type` is refused there.
1482
+ body: params as typeof params & { grant_type: string },
1483
+ headers: request.headers,
1484
+ request,
1485
+ }),
1486
+ 'auth.oauth2Token',
1487
+ )
1488
+ }
1489
+
1490
+ if (c.req.path !== '/oauth2/authorize')
1491
+ return Timing.measure(c, c.var.auth.handler(request), 'auth.handler')
1492
+
1493
+ const refused = await Timing.measure(
1494
+ c,
1495
+ refuseKey(c, { query }),
1496
+ 'oauth2.refuseKey',
1497
+ )
1498
+ if (refused) return refused
1499
+ return Timing.measure(c, c.var.auth.handler(request), 'auth.handler')
1500
+ }
1501
+
1502
+ /**
1503
+ * Returns the `rate_limited` refusal when `request` names a third-party app whose row is missing or
1504
+ * stale and its address spent `APP_DISCOVERY_LIMIT`, or `undefined`. Resolving such an app fetches
1505
+ * its metadata document and writes its row before any sign-in, so each address starts a bounded
1506
+ * number of them. A request for an app with a fresh row, such as a refresh, counts only against the
1507
+ * path's own limit. The issuer prefers Basic credentials to the parameters and checks no match, so the limit
1508
+ * reads both.
1509
+ */
1510
+ async function limitDiscovery(
1511
+ c: Context<Env>,
1512
+ options: { body: string | undefined; request: Request },
1513
+ ) {
1514
+ const { body, request } = options
1515
+ const url = new URL(request.url)
1516
+ if (!discoveryPaths.has(url.pathname)) return undefined
1517
+ const clientIds = [
1518
+ ...url.searchParams.getAll('client_id'),
1519
+ ...bodyClientIds(body),
1520
+ basicClientId(request),
1521
+ ].filter((clientId) => clientId !== undefined)
1522
+ if (!clientIds.some(Apps.thirdParty)) return undefined
1523
+
1524
+ const stale = await Timing.measure(
1525
+ c,
1526
+ Apps.stale(db, { clientIds }),
1527
+ 'Apps.stale',
1528
+ )
1529
+ if (stale.length === 0) return undefined
1530
+ return Timing.measure(
1531
+ c,
1532
+ RateLimit.check(c, {
1533
+ limits: [{ binding: 'APP_DISCOVERY_LIMIT', key: RateLimit.ip(c) }],
1534
+ }),
1535
+ 'RateLimit.check',
1536
+ )
1537
+ }
1538
+
1539
+ /**
1540
+ * Returns every client ID in `body`, read as a form and as JSON: each `client_id`, and the `sub` and
1541
+ * `iss` of each `client_assertion`. The check counts each one, since the issuer drops an empty
1542
+ * value, reads the client of an assertion from its claims before it verifies the signature, and
1543
+ * `/device/code` also accepts JSON.
1544
+ */
1545
+ function bodyClientIds(body: string | undefined): readonly string[] {
1546
+ if (!body) return []
1547
+ const form = new URLSearchParams(body)
1548
+ const json = (() => {
1549
+ try {
1550
+ const value: unknown = JSON.parse(body)
1551
+ if (typeof value !== 'object' || value === null) return []
1552
+ const clientId = (value as Record<string, unknown>).client_id
1553
+ return typeof clientId === 'string' ? [clientId] : []
1554
+ } catch {
1555
+ // A form body is no JSON.
1556
+ return []
1557
+ }
1558
+ })()
1559
+ const assertions = form.getAll('client_assertion').flatMap((assertion) => {
1560
+ try {
1561
+ const [, payload] = assertion.split('.')
1562
+ const claims: unknown = JSON.parse(
1563
+ new TextDecoder().decode(Base64.toBytes(payload ?? '')),
1564
+ )
1565
+ if (typeof claims !== 'object' || claims === null) return []
1566
+ const { iss, sub } = claims as Record<string, unknown>
1567
+ return [iss, sub].filter((claim) => typeof claim === 'string')
1568
+ } catch {
1569
+ // An assertion that does not decode names no client, and the issuer refuses it.
1570
+ return []
1571
+ }
1572
+ })
1573
+ return [...form.getAll('client_id'), ...json, ...assertions]
1574
+ }
1575
+
1576
+ /** Returns the client ID of `request`'s Basic credentials, if any. */
1577
+ function basicClientId(request: Request) {
1578
+ const authorization = request.headers.get('authorization')
1579
+ if (!authorization || !/^Basic +/i.test(authorization)) return undefined
1580
+ // The issuer decodes with the same function, so both read the same client ID.
1581
+ try {
1582
+ return decodeBasicCredentials(authorization).clientId
1583
+ } catch {
1584
+ return undefined
1585
+ }
1586
+ }
1587
+
1588
+ /**
1589
+ * Returns the redirect to the app's redirect URI with the refusal (RFC 6749 §4.1.2.1) when the
1590
+ * authorization request's `query` carries a key or a challenge that Tempo ID refuses, before the
1591
+ * browser signs in.
1592
+ * Returns `undefined` for a request without a key, and for an unknown app or an unregistered
1593
+ * redirect URI, which Better Auth refuses without the redirect.
1594
+ */
1595
+ async function refuseKey(c: Context<Env>, options: { query: URLSearchParams }) {
1596
+ const { query } = options
1597
+ // A challenge without a key is refused too, since no witness would bind it.
1598
+ if (!query.has('key_authorization') && !query.has('challenge'))
1599
+ return undefined
1600
+ const clientId = query.get('client_id')
1601
+ const redirectUri = query.get('redirect_uri')
1602
+ if (!clientId || !redirectUri) return undefined
1603
+
1604
+ // A third-party app has a row only once Better Auth resolves its metadata document. A document
1605
+ // that fails to resolve leaves no app here, and Better Auth refuses the request itself.
1606
+ if (Apps.thirdParty(clientId)) {
1607
+ const resolved = await Timing.measure(
1608
+ c,
1609
+ c.var.auth.api
1610
+ .resolveOAuthClient({ body: { client_id: clientId } })
1611
+ .catch((error: unknown) => {
1612
+ if (isAPIError(error)) return { resolved: false }
1613
+ throw error
1614
+ }),
1615
+ 'auth.resolveOAuthClient',
1616
+ )
1617
+ if (!resolved.resolved) return undefined
1618
+ }
1619
+
1620
+ const app = await Timing.measure(
1621
+ c,
1622
+ Apps.get(db, { clientId }).catch((error: unknown) => {
1623
+ if (error instanceof Apps.NotFoundError) return undefined
1624
+ throw error
1625
+ }),
1626
+ 'Apps.get',
1627
+ )
1628
+ if (!app || !app.redirectUris.includes(redirectUri)) return undefined
1629
+
1630
+ const key = Authorize.fromQuery(query)
1631
+ const refused =
1632
+ key instanceof ErrorResponse.ResponseError
1633
+ ? key
1634
+ : key &&
1635
+ Authorize.checkKey({
1636
+ app,
1637
+ clientId,
1638
+ codeChallenge: query.get('code_challenge'),
1639
+ key,
1640
+ query,
1641
+ })
1642
+ if (!refused) return undefined
1643
+
1644
+ // Each parameter follows the registered URI's own, as Better Auth appends its refusals.
1645
+ const url = new URL(redirectUri)
1646
+ url.searchParams.append('error', refused.response.error)
1647
+ url.searchParams.append(
1648
+ 'error_description',
1649
+ refused.response.error_description,
1650
+ )
1651
+ const state = query.get('state')
1652
+ if (state) url.searchParams.append('state', state)
1653
+ url.searchParams.append('iss', env.URL)
1654
+ c.header('cache-control', 'no-store')
1655
+ return c.redirect(url.href, 302)
1656
+ }
1657
+
1658
+ /**
1659
+ * Returns the token `response` of the redeemed device code with row `id`, with the key that its
1660
+ * approval signed as `account` and `key_authorization`. Only the one redemption that succeeds
1661
+ * reaches here, so only it takes the key. The code is spent, so a failed take returns the tokens
1662
+ * alone.
1663
+ */
1664
+ async function withDeviceKey(c: Context<Env>, options: withDeviceKey.Options) {
1665
+ const { id, response } = options
1666
+ const key = await Timing.measure(
1667
+ c,
1668
+ Device.take(db, { id }),
1669
+ 'Device.take',
1670
+ ).catch((error: unknown) => {
1671
+ Log.error(c, {
1672
+ error,
1673
+ message: 'A device code redemption failed to take the held key.',
1674
+ })
1675
+ return undefined
1676
+ })
1677
+ if (!key) return response
1678
+
1679
+ const body = (await Timing.measure(
1680
+ c,
1681
+ response.json(),
1682
+ 'response.json',
1683
+ )) as Record<string, unknown>
1684
+ const headers = new Headers(response.headers)
1685
+ headers.delete('content-length')
1686
+ return new Response(
1687
+ JSON.stringify({
1688
+ ...body,
1689
+ account: key.account,
1690
+ key_authorization: key.keyAuthorization,
1691
+ }),
1692
+ { headers, status: response.status },
1693
+ )
1694
+ }
1695
+
1696
+ declare namespace withDeviceKey {
1697
+ type Options = {
1698
+ /** The `device_code` row ID of the redeemed code. */
1699
+ id: string
1700
+ /** The issuer's token response. */
1701
+ response: Response
1702
+ }
1703
+ }
1704
+
1705
+ /**
1706
+ * Returns the key of the device authorization request `form` without its challenge bound, as the
1707
+ * device page stores it and binds the challenge when it reads it.
1708
+ */
1709
+ function unbound(form: URLSearchParams) {
1710
+ const query = new URLSearchParams(form)
1711
+ query.delete('challenge')
1712
+ const key = Authorize.fromQuery(query)
1713
+ // The form's key already passed the same parse.
1714
+ return key instanceof ErrorResponse.ResponseError ? undefined : key
1715
+ }
1716
+
1717
+ /**
1718
+ * Returns the request with Tempo ID's origin as its `resource` when an authorization, a device
1719
+ * authorization, or a token request names none. Better Auth issues a JWT access token only for a `resource`, and every API
1720
+ * verifies the one audience. An authorization request with a key also asks for consent, and names
1721
+ * the key's expiry, as `Authorize.prepare` describes.
1722
+ */
1723
+ async function withResource(c: Context<Env>) {
1724
+ const request = c.req.raw
1725
+
1726
+ if (c.req.path === '/oauth2/authorize' && c.req.method === 'GET') {
1727
+ const url = new URL(request.url)
1728
+ if (!url.searchParams.has('resource'))
1729
+ url.searchParams.set('resource', env.URL)
1730
+ url.search = Authorize.prepare(url.searchParams).toString()
1731
+ return new Request(url, request)
1732
+ }
1733
+
1734
+ // The `POST` form of an authorization request carries its parameters in the body, which Better
1735
+ // Auth accepts only as a form. A key in that body gains the same consent and expiry. Better Auth
1736
+ // accepts any media type that contains the form's, in any case, so each one is read here as a
1737
+ // form and forwarded as exactly one.
1738
+ if (
1739
+ c.req.path === '/oauth2/authorize' &&
1740
+ c.req.method === 'POST' &&
1741
+ c.req
1742
+ .header('content-type')
1743
+ ?.split(';')[0]
1744
+ ?.toLowerCase()
1745
+ .includes('application/x-www-form-urlencoded')
1746
+ ) {
1747
+ const form = new URLSearchParams(
1748
+ await Timing.measure(c, c.req.text(), 'request.text'),
1749
+ )
1750
+ if (!form.has('resource')) form.set('resource', env.URL)
1751
+ const headers = new Headers(request.headers)
1752
+ headers.delete('content-length')
1753
+ headers.set('content-type', 'application/x-www-form-urlencoded')
1754
+ return new Request(request.url, {
1755
+ body: Authorize.prepare(form),
1756
+ headers,
1757
+ method: 'POST',
1758
+ })
1759
+ }
1760
+
1761
+ if (c.req.path === '/oauth2/token' && c.req.method === 'POST') {
1762
+ const form = new URLSearchParams(
1763
+ await Timing.measure(c, c.req.text(), 'request.text'),
1764
+ )
1765
+ if (!form.has('resource')) form.set('resource', env.URL)
1766
+ const headers = new Headers(request.headers)
1767
+ headers.delete('content-length')
1768
+ // The client authenticates, never a session. The issuer refuses a cookie without a trusted
1769
+ // `Origin`, such as a device's poll from a browser that holds Tempo ID's session.
1770
+ headers.delete('cookie')
1771
+ return new Request(request.url, { body: form, headers, method: 'POST' })
1772
+ }
1773
+
1774
+ // A device authorization request is a form (RFC 8628 §3.1), whose resource every redemption must
1775
+ // match. A device code binds to the user who approves it, so the request cannot bind one with
1776
+ // `user_id`.
1777
+ if (c.req.path === '/device/code' && c.req.method === 'POST') {
1778
+ const form = new URLSearchParams(
1779
+ await Timing.measure(c, c.req.text(), 'request.text'),
1780
+ )
1781
+ if (!form.has('resource')) form.set('resource', env.URL)
1782
+ if (!form.has('scope')) form.set('scope', Device.scope)
1783
+ form.delete('user_id')
1784
+ // Tempo ID reads its own parameters, which the issuer does not take.
1785
+ for (const name of ['challenge', 'device', 'key_authorization'])
1786
+ form.delete(name)
1787
+ const headers = new Headers(request.headers)
1788
+ headers.delete('content-length')
1789
+ // As for `/oauth2/token`, the client authenticates, and a session's cookie plays no part.
1790
+ headers.delete('cookie')
1791
+ headers.set('content-type', 'application/x-www-form-urlencoded')
1792
+ return new Request(request.url, { body: form, headers, method: 'POST' })
1793
+ }
1794
+
1795
+ return request
1796
+ }