@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,1662 @@
1
+ /** The sign-in routes under `/v1/auth`: email codes, passkeys, sign-out, and the session. @module */
2
+ import { verifyOAuthQueryParams } from '@better-auth/oauth-provider'
3
+ import { isAPIError } from 'better-auth/api'
4
+ import { eq } from 'drizzle-orm'
5
+ import type { Context } from 'hono'
6
+ import { Hono } from 'hono'
7
+ import { Hex } from 'ox'
8
+ import { Authentication } from 'webauthx/server'
9
+ import { env } from 'void/env'
10
+ import * as z from 'zod'
11
+ import * as Schema from '../app/db/schema.js'
12
+ import * as Apps from '../internal/Apps.js'
13
+ import * as core_Auth from '../internal/Auth.js'
14
+ import * as Authorize from '../internal/Authorize.js'
15
+ import * as BodyLimit from '../internal/BodyLimit.js'
16
+ import * as Cache from '../internal/Cache.js'
17
+ import * as Device from '../internal/Device.js'
18
+ import type { Env } from '../internal/Env.js'
19
+ import * as ErrorResponse from '../internal/ErrorResponse.js'
20
+ import * as KeyAuthorization from '../internal/KeyAuthorization.js'
21
+ import * as Log from '../internal/Log.js'
22
+ import * as Logout from '../internal/Logout.js'
23
+ import * as OpenApi from '../internal/OpenApi.js'
24
+ import * as Passkey from '../internal/Passkey.js'
25
+ import * as RateLimit from '../internal/RateLimit.js'
26
+ import * as Realm from '../internal/Realm.js'
27
+ import * as SignInGrant from '../internal/SignInGrant.js'
28
+ import * as TempoAccount from '../internal/TempoAccount.js'
29
+ import * as Timing from '../internal/Timing.js'
30
+ import * as Wallet from '../internal/Wallet.js'
31
+ import * as AccountStep from './lib/AccountStep.js'
32
+ import * as Auth from './lib/Auth.js'
33
+ import * as Cors from './lib/Cors.js'
34
+ import { db } from './lib/Database.js'
35
+ import * as FirstAccount from './lib/FirstAccount.js'
36
+ import * as Headless from './lib/Headless.js'
37
+ import * as PasskeyLink from './lib/PasskeyLink.js'
38
+ import * as Session from './lib/Session.js'
39
+ import * as SignInConsent from './lib/SignInConsent.js'
40
+
41
+ /** A hostname label: 1 to 63 letters, digits, and hyphens, with no hyphen at either end. */
42
+ const hostnameLabel = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/
43
+
44
+ namespace schema {
45
+ export namespace code {
46
+ export const json = z.object({
47
+ email: z
48
+ .string()
49
+ .trim()
50
+ .toLowerCase()
51
+ .pipe(
52
+ // A malformed or long address stops at its first failed check, so the refusal names it once.
53
+ z
54
+ .email({ abort: true })
55
+ .max(254, { abort: true, error: 'Invalid email address' })
56
+ // The email service refuses a local part over 64 characters, and a domain label that is
57
+ // not a hostname label: over 63 characters, or with a hyphen at either end.
58
+ .refine((value) => {
59
+ const [local = '', domain = ''] = value.split('@')
60
+ return (
61
+ local.length <= 64 &&
62
+ domain.split('.').every((label) => hostnameLabel.test(label))
63
+ )
64
+ }, 'Invalid email address'),
65
+ )
66
+ .meta({
67
+ description: "The user's email address.",
68
+ examples: ['ada@example.com'],
69
+ }),
70
+ })
71
+
72
+ export const response = z.object({
73
+ sent: z.literal(true).meta({
74
+ description:
75
+ 'The request is accepted. The value is the same for every address.',
76
+ }),
77
+ })
78
+ }
79
+
80
+ export namespace verify {
81
+ export const json = z
82
+ .object({
83
+ assertion: Passkey.schema.assertion.optional().meta({
84
+ description:
85
+ "The assertion of the email step's passkey, over a challenge from `POST /v1/auth/passkey/options` with `link`. Required with `link`, since only the person who holds the passkey can link it.",
86
+ }),
87
+ authorize: Authorize.schema.request.optional().meta({
88
+ description:
89
+ "The app's headless authorization request, as `POST /v1/authorize` takes it, from a first-party app's page. The sign-in then authorizes the app in the same request, creates a first Tempo Account for a user who holds none, and returns the authorization. A refusal that depends only on the app and the request, such as a key over the headless ceiling, comes before the sign-in and leaves the code unspent. A refusal of the authorization server after the sign-in, such as for a scope that the app's registration lacks, spends the code. Not with `link` or `oauth_query`.",
90
+ }),
91
+ code: z
92
+ .string()
93
+ .trim()
94
+ .regex(/^\d{6}$/)
95
+ .meta({
96
+ description: 'The six-digit emailed code.',
97
+ examples: ['123456'],
98
+ }),
99
+ email: code.json.shape.email,
100
+ link: z
101
+ .string()
102
+ .max(64)
103
+ .optional()
104
+ .meta({
105
+ description:
106
+ "The email step's `link`, which links the wallet.tempo passkey that asked for it to this user, with that passkey's `assertion`. An expired link refuses the sign-in with `passkey_link_expired`, and the code stays valid.",
107
+ examples: ['dGhlIG5vbmNlIHRoYXQgdGhlIHN0ZXAgY2Fycmllcw'],
108
+ }),
109
+ passkey: z.literal(true).optional().meta({
110
+ description:
111
+ "With `authorize`, requests the passkey step for an account that a passkey owns, in place of `webauthn_required`. The response's `authorization` is then the step, which the page signs, and `POST /v1/authorize` with `passkey: { assertion }` signs the key.",
112
+ }),
113
+ // The bound covers an authorization request's query, and limits what an unsigned query can
114
+ // write, since the passkey challenge stores its client ID before the signature is checked.
115
+ oauth_query: z
116
+ .string()
117
+ .max(8192)
118
+ .optional()
119
+ .meta({
120
+ description:
121
+ "The sign-in page's query string, which Better Auth signs when an app's authorization request sends the browser there. At most 8,192 characters.",
122
+ examples: [
123
+ 'client_id=client_01JZ8Q6W3N1R5B4V7C2X9K0M3T&response_type=code&exp=1760000000&sig=Gx3kB0',
124
+ ],
125
+ }),
126
+ })
127
+ .refine((value) => !value.link || value.assertion, {
128
+ message: 'Required with `link`.',
129
+ path: ['assertion'],
130
+ })
131
+ .refine(
132
+ (value) => !value.authorize || (!value.link && !value.oauth_query),
133
+ {
134
+ message: 'Not allowed with `link` or `oauth_query`.',
135
+ path: ['authorize'],
136
+ },
137
+ )
138
+
139
+ /** The user fields that the API returns. */
140
+ export const user = z
141
+ .object({
142
+ email: z.email().meta({
143
+ description: "The user's email address.",
144
+ examples: ['ada@example.com'],
145
+ }),
146
+ id: z.string().meta({
147
+ description:
148
+ "The user's ID, which is the `sub` of every token Tempo ID issues for the user.",
149
+ examples: ['user_01JZ8Q6W3N1R5B4V7C2X9K0M3T'],
150
+ }),
151
+ })
152
+ .meta({ description: 'The signed-in user.', id: 'User' })
153
+
154
+ export const response = z.object({
155
+ authorization: z
156
+ .union([Authorize.schema.response, Passkey.schema.headlessStep])
157
+ .optional()
158
+ .meta({
159
+ description:
160
+ "The app's headless authorization, for a sign-in that carried `authorize`, or a sign-in with key signature on the app's page whose options carried it. With `passkey`, the passkey step for a passkey-owned account. Absent for any other sign-in.",
161
+ }),
162
+ redirect: z
163
+ .url()
164
+ .nullable()
165
+ .meta({
166
+ description:
167
+ "Where the browser continues: the app's `redirect_uri` with an authorization code, or `null` for a sign-in that no app waits on.",
168
+ examples: [
169
+ 'https://app.example.com/callback?code=SplxlOBeZQQYbYS6WxSbIA',
170
+ ],
171
+ }),
172
+ user,
173
+ })
174
+
175
+ /** What Better Auth returns: the user, or the authorization that the sign-in continued. */
176
+ export const signedIn = z.union([
177
+ z.object({ url: z.string() }),
178
+ z.object({ user: z.object({ email: z.string(), id: z.string() }) }),
179
+ ])
180
+ }
181
+
182
+ export namespace passkeyOptions {
183
+ export const json = z
184
+ .object({
185
+ authorize: Authorize.schema.request.optional().meta({
186
+ description:
187
+ "The app's headless authorization request, as `POST /v1/authorize` takes it, from a first-party app's page. The challenge is then the digest of its key, so the passkey's one assertion signs the user in and signs the key, and `POST /v1/auth/passkey/verify` returns the authorization. Requires `client_id`, the same as its own.",
188
+ }),
189
+ client_id: z
190
+ .string()
191
+ .min(1)
192
+ .max(64)
193
+ .optional()
194
+ .meta({
195
+ description:
196
+ "The client ID of the first-party app whose page runs the ceremony, which selects the app's realms. Required from an app's page, whose `Origin` must be one of the app's redirect URI origins.",
197
+ examples: ['client_01JZ8Q6W3N1R5B4V7C2X9K0M3T'],
198
+ }),
199
+ credentialId: z
200
+ .union([
201
+ Passkey.schema.credentialId,
202
+ z.array(Passkey.schema.credentialId).max(16),
203
+ ])
204
+ .optional()
205
+ .meta({
206
+ description:
207
+ 'The credential ID, or up to 16 IDs, that the browser offers as `allowCredentials`, base64url. Defaults to every discoverable passkey of the relying party, as an empty list does.',
208
+ examples: ['KEbWNCc7NgaYnUyrNeFGX9_3Y-8'],
209
+ }),
210
+ link: verify.json.shape.link.meta({
211
+ description:
212
+ "The email step's `link`, which limits the options to that step's passkey, in place of `credentialId`. The emailed-code sign-in then sends the passkey's assertion with the `link`.",
213
+ examples: ['dGhlIG5vbmNlIHRoYXQgdGhlIHN0ZXAgY2Fycmllcw'],
214
+ }),
215
+ mediation: z
216
+ .enum(['conditional', 'optional', 'required', 'silent'])
217
+ .optional()
218
+ .meta({
219
+ description:
220
+ 'Returned in the options for `navigator.credentials.get()`, such as `conditional` for passkey autofill.',
221
+ examples: ['conditional'],
222
+ }),
223
+ oauth_query: verify.json.shape.oauth_query,
224
+ user_code: z
225
+ .string()
226
+ .max(32)
227
+ .optional()
228
+ .meta({
229
+ description:
230
+ "The user code of the device grant that the sign-in returns to, ignored with `oauth_query` or `client_id`. A pending, unbound code selects its app's realms, and any other code selects the `default` realm.",
231
+ examples: ['WDJB-MJHT'],
232
+ }),
233
+ })
234
+ .refine(
235
+ (value) =>
236
+ !value.authorize || value.authorize.client_id === value.client_id,
237
+ { message: 'Requires the same `client_id`.', path: ['authorize'] },
238
+ )
239
+
240
+ /** The `authorize` field as the page sent it, which the challenge stores with its expiry filled. */
241
+ export const sent = z.object({
242
+ authorize: z.looseObject({
243
+ key_authorization: z.looseObject({}).optional(),
244
+ }),
245
+ })
246
+
247
+ export const response = z.object({
248
+ options: z
249
+ .object({
250
+ mediation: passkeyOptions.json.shape.mediation,
251
+ publicKey: z
252
+ .object({
253
+ allowCredentials: z
254
+ .array(
255
+ z
256
+ .object({
257
+ id: z.string().meta({
258
+ description: 'A credential ID, base64url.',
259
+ examples: ['KEbWNCc7NgaYnUyrNeFGX9_3Y-8'],
260
+ }),
261
+ type: z.literal('public-key').meta({
262
+ description: 'The credential type.',
263
+ }),
264
+ })
265
+ .meta({ description: 'A passkey the browser offers.' }),
266
+ )
267
+ .optional()
268
+ .meta({
269
+ description:
270
+ 'The passkeys the browser offers, from `credentialId`. Absent, it offers every discoverable passkey of the relying party.',
271
+ }),
272
+ challenge: z.templateLiteral(['0x', z.string()]).meta({
273
+ description:
274
+ 'The single-use challenge, as hex. It expires after 5 minutes.',
275
+ examples: [
276
+ '0xf6310589abb21116acc6e123967ed0a125b5041c43f8e157237093e07eaa354c',
277
+ ],
278
+ }),
279
+ rpId: z.string().meta({
280
+ description: 'The relying party ID of the passkeys.',
281
+ examples: ['tempo.xyz'],
282
+ }),
283
+ userVerification: z.literal('required').meta({
284
+ description:
285
+ 'Every passkey sign-in requires user verification.',
286
+ }),
287
+ })
288
+ .meta({
289
+ description:
290
+ 'The `PublicKeyCredentialRequestOptions`, serialized with the challenge as hex.',
291
+ }),
292
+ })
293
+ .meta({
294
+ description: 'The options for `navigator.credentials.get()`.',
295
+ }),
296
+ })
297
+ }
298
+
299
+ export namespace passkeyVerify {
300
+ export const json = z.object({
301
+ assertion: Passkey.schema.assertion,
302
+ oauth_query: verify.json.shape.oauth_query,
303
+ })
304
+
305
+ export const response = z.union([
306
+ verify.response.meta({ description: 'The signed-in user.' }),
307
+ z
308
+ .object({
309
+ step: z
310
+ .object({
311
+ link: z.string().meta({
312
+ description:
313
+ 'Send as `link` with the emailed-code sign-in, which links the passkey to that user.',
314
+ examples: ['dGhlIG5vbmNlIHRoYXQgdGhlIHN0ZXAgY2Fycmllcw'],
315
+ }),
316
+ signed: z.literal(false).meta({
317
+ description:
318
+ 'Whether the assertion already signed a key authorization. This route signs none.',
319
+ }),
320
+ type: z.literal('email').meta({
321
+ description:
322
+ 'Sign in with an emailed code, which links the passkey to that user.',
323
+ }),
324
+ })
325
+ .meta({
326
+ description:
327
+ 'The email step, for a wallet.tempo passkey whose account has no email.',
328
+ }),
329
+ })
330
+ .meta({
331
+ description:
332
+ 'A passkey sign-in that continues when the user verifies an email address.',
333
+ }),
334
+ ])
335
+ }
336
+
337
+ export namespace logout {
338
+ export const response = z.object({
339
+ signed_out: z.literal(true).meta({
340
+ description: 'The session is over, or there was none.',
341
+ }),
342
+ })
343
+ }
344
+
345
+ export namespace session {
346
+ export const response = z.object({
347
+ user: verify.user
348
+ .extend({
349
+ name: z
350
+ .string()
351
+ .nullable()
352
+ .meta({
353
+ description:
354
+ "The user's name, or `null` for a user who signed up without one.",
355
+ examples: ['Ada Lovelace'],
356
+ }),
357
+ })
358
+ .nullable()
359
+ .meta({
360
+ description: 'The signed-in user, or `null` without a session.',
361
+ id: 'SessionUser',
362
+ }),
363
+ })
364
+ }
365
+
366
+ export namespace assets {
367
+ export const response = z.object({
368
+ assets: z
369
+ .array(
370
+ z.string().meta({
371
+ description:
372
+ "The path of a script or style sheet on Tempo ID's origin.",
373
+ examples: ['/assets/index-QK4GWdO3.js'],
374
+ }),
375
+ )
376
+ .meta({
377
+ description:
378
+ "The sign-in page's scripts and style sheets, each once.",
379
+ examples: [
380
+ ['/assets/index-QK4GWdO3.js', '/assets/zyzz-DYC-X0_B.css'],
381
+ ],
382
+ }),
383
+ })
384
+ }
385
+
386
+ export namespace methods {
387
+ export const query = z.object({
388
+ oauth_query: verify.json.shape.oauth_query,
389
+ return_to: z
390
+ .string()
391
+ .max(2048)
392
+ .optional()
393
+ .meta({
394
+ description:
395
+ "The page that sign-in returns to, from the sign-in page's query. Only a path on the device page passes, and any other value reads as absent.",
396
+ examples: ['/device?code=WDJB-MJHT'],
397
+ }),
398
+ })
399
+
400
+ export const response = z.object({
401
+ passkeys: z.boolean().meta({
402
+ description:
403
+ "Whether one of the sign-in's realms holds passkeys that sign in at Tempo ID's origin, so the page offers passkey sign-in.",
404
+ examples: [true],
405
+ }),
406
+ app: z
407
+ .string()
408
+ .nullable()
409
+ .meta({
410
+ description:
411
+ 'The display name of the app of the request in `oauth_query`, or its client ID without a name. `null` for a forged or expired query, or an unknown app.',
412
+ examples: ['Tempo Cash'],
413
+ }),
414
+ host: z
415
+ .string()
416
+ .nullable()
417
+ .meta({
418
+ description:
419
+ "The host of a third-party app's client ID, which the page shows beside its name, or `null` for a registered app or without an app.",
420
+ examples: ['app.example'],
421
+ }),
422
+ request: z
423
+ .object({
424
+ app: z.string().meta({
425
+ description:
426
+ "The app's display name, or its client ID without one.",
427
+ examples: ['Tempo Cash'],
428
+ }),
429
+ key: KeyAuthorization.schema.description,
430
+ })
431
+ .nullable()
432
+ .meta({
433
+ description:
434
+ 'The app and the key of the signed authorization request in `oauth_query`, which the sign-in grants. `null` when the sign-in grants no key, such as for an invalid query or a third-party app.',
435
+ }),
436
+ return_to: z
437
+ .string()
438
+ .nullable()
439
+ .meta({
440
+ description:
441
+ 'The page that sign-in returns to, a path on the device page, or `null` for the account.',
442
+ examples: ['/device?code=WDJB-MJHT'],
443
+ }),
444
+ user_code: z
445
+ .string()
446
+ .nullable()
447
+ .meta({
448
+ description:
449
+ 'The user code of the device page that sign-in returns to, or `null` without one.',
450
+ examples: ['WDJBMJHT'],
451
+ }),
452
+ verified: z.boolean().meta({
453
+ description:
454
+ 'Whether `app` is a registered app, whose name the page marks as verified. `false` for a third-party app, which names itself in its metadata document, and without an app.',
455
+ examples: [true],
456
+ }),
457
+ })
458
+ }
459
+ }
460
+
461
+ /**
462
+ * Returns the ID and stored address of the user with `email`, which wallet.tempo verified, and
463
+ * creates that user when none exists. A concurrent first sign-in can create the user first, so the
464
+ * read repeats.
465
+ */
466
+ async function emailUser(c: Context<Env>, options: emailUser.Options) {
467
+ const email = options.email.trim().toLowerCase()
468
+ const context = await Timing.measure(c, c.var.auth.$context, 'auth.context')
469
+ const found = await Timing.measure(
470
+ c,
471
+ context.internalAdapter.findUserByEmail(email),
472
+ 'db.user.findByEmail',
473
+ )
474
+ if (found) return { email: found.user.email, id: found.user.id }
475
+
476
+ try {
477
+ const created = await Timing.measure(
478
+ c,
479
+ context.internalAdapter.createUser(
480
+ { email, emailVerified: true, name: '' },
481
+ { method: 'passkey' },
482
+ ),
483
+ 'db.user.create',
484
+ )
485
+ return { email: created.email, id: created.id }
486
+ } catch (error) {
487
+ // The user hook refuses a new user outside `SIGN_UP_DOMAINS`.
488
+ if (
489
+ isAPIError(error) &&
490
+ error.body?.code === core_Auth.SignUpNotPermittedError.reason
491
+ )
492
+ throw new core_Auth.SignUpNotPermittedError({
493
+ domains: Auth.signUpDomains() ?? [],
494
+ })
495
+ const again = await Timing.measure(
496
+ c,
497
+ context.internalAdapter.findUserByEmail(email),
498
+ 'db.user.findByEmail',
499
+ )
500
+ if (again) return { email: again.user.email, id: again.user.id }
501
+ throw error
502
+ }
503
+ }
504
+
505
+ declare namespace emailUser {
506
+ type Options = {
507
+ /** The email address that wallet.tempo verified. */
508
+ email: string
509
+ }
510
+ }
511
+
512
+ namespace emailUser {
513
+ /** The refusals `emailUser` throws. */
514
+ export const errors = [core_Auth.SignUpNotPermittedError] as const
515
+ }
516
+
517
+ /** The sign-in routes under `/v1/auth`. */
518
+ export const authenticate = new Hono<Env>()
519
+ .post(
520
+ '/v1/auth/code',
521
+ OpenApi.describeRoute({
522
+ description:
523
+ 'Emails a sign-in code. The response is the same for every address, so it reveals no account.',
524
+ responses: OpenApi.responses({
525
+ errors: [
526
+ ...BodyLimit.errors,
527
+ ...Auth.sendCode.errors,
528
+ ...OpenApi.validate.errors,
529
+ ...RateLimit.check.errors,
530
+ ErrorResponse.CrossSiteRequestError,
531
+ ErrorResponse.UpstreamUnavailableError,
532
+ ],
533
+ success: {
534
+ description:
535
+ 'The response for every address: the email service accepted the code, or does not deliver to the address.',
536
+ schema: schema.code.response,
537
+ },
538
+ }),
539
+ tags: ['Authenticate'],
540
+ }),
541
+ OpenApi.validate('json', schema.code.json),
542
+ async (c) => {
543
+ const { email } = c.req.valid('json')
544
+ // The IP address's limit counts first, so a refused flood spends no address's sends.
545
+ const refused = await Timing.measure(
546
+ c,
547
+ RateLimit.check(c, {
548
+ limits: [
549
+ { binding: 'SIGN_IN_IP_LIMIT', key: RateLimit.ip(c) },
550
+ { binding: 'SIGN_IN_CODE_LIMIT', key: RateLimit.email({ email }) },
551
+ ],
552
+ }),
553
+ 'RateLimit.check',
554
+ )
555
+ if (refused) return refused
556
+
557
+ // The Workers limits count each location on its own, so the database counts the address's
558
+ // codes across every location.
559
+ const within = await Timing.measure(
560
+ c,
561
+ RateLimit.countCode(db, { email }),
562
+ 'RateLimit.countCode',
563
+ )
564
+ if (!within) {
565
+ RateLimit.describe(c, { policy: RateLimit.codePolicy })
566
+ return RateLimit.refuse(c, {
567
+ policy: RateLimit.codePolicy,
568
+ retryAfter: RateLimit.codePolicy.window,
569
+ })
570
+ }
571
+
572
+ // Every address receives a code, so the response reveals no account. The route waits for the
573
+ // email service, so a failed send refuses the request instead of a sign-in that never arrives.
574
+ const code = await Timing.measure(
575
+ c,
576
+ c.var.auth.api.createVerificationOTP({
577
+ body: { email, type: 'sign-in' },
578
+ }),
579
+ 'auth.createVerificationOTP',
580
+ )
581
+ const failure = await Timing.measure(
582
+ c,
583
+ Auth.sendCode(c, { code, email: email.toLowerCase() }),
584
+ 'Auth.sendCode',
585
+ ).catch((error: unknown) => error)
586
+ if (failure) {
587
+ // The refusal is the email service's, as for any upstream service, so it is a warning.
588
+ Log.warn(c, {
589
+ error: failure,
590
+ message: 'The email service refused a sign-in code.',
591
+ })
592
+ // A refusal of the address itself responds as a sent code, so the response is the same for
593
+ // every address. The email service's rate limit is one the caller can wait out. Any other
594
+ // refusal is an outage.
595
+ if (!(failure instanceof Auth.UndeliverableError))
596
+ return ErrorResponse.json(
597
+ c,
598
+ failure instanceof ErrorResponse.RateLimitedError
599
+ ? failure
600
+ : new ErrorResponse.UpstreamUnavailableError(),
601
+ )
602
+ }
603
+
604
+ return c.json({ sent: true as const }, 200)
605
+ },
606
+ )
607
+ .post(
608
+ '/v1/auth/code/verify',
609
+ OpenApi.describeRoute({
610
+ description:
611
+ 'Signs in with an emailed code, and sets the session cookie. For a user with no Tempo Account in the first realm of the app that `oauth_query` names, or in the `default` realm, it creates one when that realm creates accounts. A failed creation leaves the user signed in, and the next sign-in or `POST /v1/account` creates the account. With `authorize`, it also authorizes the app as `POST /v1/authorize` does, and a refusal after the sign-in carries `Tempo-Id-Signed-In: true`.',
612
+ responses: OpenApi.responses({
613
+ errors: [
614
+ ...BodyLimit.errors,
615
+ ...Cors.ownPage.errors,
616
+ ...OpenApi.validate.errors,
617
+ ...Headless.afterCode.errors,
618
+ ...Headless.check.errors,
619
+ ...Headless.keySignature.errors,
620
+ ...RateLimit.check.errors,
621
+ core_Auth.AuthorizationExpiredError,
622
+ core_Auth.InvalidCodeError,
623
+ core_Auth.SignUpNotPermittedError,
624
+ Passkey.LinkExpiredError,
625
+ Passkey.WebAuthnRejectedError,
626
+ ],
627
+ success: {
628
+ description: 'The signed-in user.',
629
+ schema: schema.verify.response,
630
+ },
631
+ }),
632
+ tags: ['Authenticate'],
633
+ }),
634
+ OpenApi.validate('json', schema.verify.json),
635
+ async (c) => {
636
+ const { assertion, authorize, code, email, link, oauth_query, passkey } =
637
+ c.req.valid('json')
638
+ const crossSite = Cors.ownPage(c, { oauth_query })
639
+ if (crossSite) return ErrorResponse.json(c, crossSite)
640
+ // Better Auth counts the guesses at each code. The IP address's limit bounds guesses across
641
+ // addresses.
642
+ const refused = await Timing.measure(
643
+ c,
644
+ RateLimit.check(c, {
645
+ limits: [{ binding: 'SIGN_IN_IP_LIMIT', key: RateLimit.ip(c) }],
646
+ }),
647
+ 'RateLimit.check',
648
+ )
649
+ if (refused) return refused
650
+
651
+ // The app's request is checked as a headless one before the code, so a refused request leaves
652
+ // the code unspent.
653
+ const app = authorize
654
+ ? await Timing.measure(
655
+ c,
656
+ Headless.app(c, { clientId: authorize.client_id }),
657
+ 'Headless.app',
658
+ )
659
+ : undefined
660
+ const refusesAuthorize =
661
+ authorize &&
662
+ Headless.check(authorize, { app, origin: c.req.header('origin') })
663
+ if (refusesAuthorize) return ErrorResponse.json(c, refusesAuthorize)
664
+
665
+ // The email step's link is checked before the code, so an expired one refuses the sign-in and
666
+ // leaves the code unspent. The sign-in then never ends without the passkey it was meant to link.
667
+ const deferred = link
668
+ ? await Timing.measure(
669
+ c,
670
+ PasskeyLink.claim(c, { nonce: link }),
671
+ 'PasskeyLink.claim',
672
+ )
673
+ : undefined
674
+ if (link && !deferred)
675
+ return ErrorResponse.json(c, new Passkey.LinkExpiredError())
676
+
677
+ // The link's passkey signs again before the code is checked, so a page left at the email step
678
+ // links nothing for the next person, and a refusal leaves the code unspent. On an app's page,
679
+ // that assertion can sign the key of the request that the options carried, as a digest
680
+ // sign-in does.
681
+ const challenge =
682
+ deferred && assertion
683
+ ? await Timing.measure(
684
+ c,
685
+ Passkey.take(db, {
686
+ clientDataJSON: assertion.metadata.clientDataJSON,
687
+ }),
688
+ 'Passkey.take',
689
+ )
690
+ : undefined
691
+ if (deferred) {
692
+ // Only a challenge that the options issued for this link confirms it.
693
+ const bound =
694
+ challenge && link
695
+ ? await Timing.measure(
696
+ c,
697
+ PasskeyLink.matches({ expected: challenge.link, nonce: link }),
698
+ 'PasskeyLink.matches',
699
+ )
700
+ : false
701
+ if (
702
+ !assertion ||
703
+ !challenge ||
704
+ !bound ||
705
+ challenge.clientId !== client({ oauth_query }) ||
706
+ challenge.origin !== Cors.appOrigin(c) ||
707
+ challenge.rpId !== deferred.rpId ||
708
+ assertion.id !== deferred.id ||
709
+ !Passkey.verify(assertion, {
710
+ challenge: challenge.challenge,
711
+ origin: challenge.origin ?? new URL(env.URL).origin,
712
+ publicKey: deferred.publicKey,
713
+ rpId: deferred.rpId,
714
+ }) ||
715
+ !(await Timing.measure(
716
+ c,
717
+ Headless.spend(c, { assertion, challenge }),
718
+ 'Headless.spend',
719
+ ))
720
+ )
721
+ return ErrorResponse.json(c, new Passkey.WebAuthnRejectedError())
722
+ }
723
+
724
+ const result = await Timing.measure(
725
+ c,
726
+ c.var.auth.api.signInEmailOTP({
727
+ // A call with a request returns a `Response` unless `asResponse` is false.
728
+ asResponse: false,
729
+ body: { email, otp: code, ...(oauth_query ? { oauth_query } : {}) },
730
+ // Better Auth sets `accept` to continue an authorization as JSON, and a request's own headers
731
+ // are immutable.
732
+ headers: new Headers(c.req.raw.headers),
733
+ // Better Auth continues an authorization only for a call that carries its request.
734
+ request: c.req.raw,
735
+ returnHeaders: true,
736
+ }),
737
+ 'auth.signInEmailOTP',
738
+ ).catch((error: unknown) => {
739
+ // Better Auth checks the authorization request's signature before the code, so a forged or
740
+ // expired one leaves the code unspent.
741
+ if (isAPIError(error) && error.body?.error === 'invalid_signature')
742
+ return new core_Auth.AuthorizationExpiredError()
743
+ // The user hook refuses a new user outside `SIGN_UP_DOMAINS`, after the code verifies.
744
+ if (
745
+ isAPIError(error) &&
746
+ error.body?.code === core_Auth.SignUpNotPermittedError.reason
747
+ )
748
+ return new core_Auth.SignUpNotPermittedError({
749
+ domains: Auth.signUpDomains() ?? [],
750
+ })
751
+ // Better Auth refuses a wrong, expired, or spent code, and a code past its guesses. Any other
752
+ // failure fails the request.
753
+ if (isAPIError(error)) return new core_Auth.InvalidCodeError()
754
+ throw error
755
+ })
756
+ if (result instanceof ErrorResponse.ResponseError)
757
+ return ErrorResponse.json(c, result)
758
+
759
+ for (const cookie of result.headers.getSetCookie())
760
+ c.header('set-cookie', cookie, { append: true })
761
+ c.header('cache-control', 'private, no-store')
762
+
763
+ // With `oauth_query`, Better Auth continues the app's authorization once the session exists, and
764
+ // returns its redirect in place of the user.
765
+ const signedIn = schema.verify.signedIn.parse(result.response)
766
+ const user = (() => {
767
+ if ('user' in signedIn)
768
+ return { email: signedIn.user.email, id: signedIn.user.id }
769
+ // Better Auth signs in the user whose address is the lowercase `email`, and the session
770
+ // that it created names that user.
771
+ const id = c.var.newSession?.user.id
772
+ if (!id) throw new Error('The signed-in user is missing.')
773
+ return { email, id }
774
+ })()
775
+
776
+ // The email step's passkey links to the user that the code signed in.
777
+ if (deferred) {
778
+ const linked = await Timing.measure(
779
+ c,
780
+ Passkey.link(db, {
781
+ credential: deferred,
782
+ id: deferred.id,
783
+ rpId: deferred.rpId,
784
+ userId: user.id,
785
+ }),
786
+ 'Passkey.link',
787
+ )
788
+ // The account step of the sign-in listed the user's keys before the link.
789
+ TempoAccount.forget(c)
790
+ // A concurrent sign-in can link the passkey to another user first. Its row decides, so this
791
+ // sign-in links nothing, and the cookie stays until it expires.
792
+ if (linked === user.id) PasskeyLink.release(c)
793
+ }
794
+
795
+ // A linked passkey owns its account, so the first account follows the link. The sign-in grant
796
+ // below can then sign the key with it.
797
+ await Timing.measure(
798
+ c,
799
+ FirstAccount.create(c, {
800
+ clientId: client({ oauth_query }),
801
+ // Better Auth signs in the user of the lowercase address.
802
+ email: user.email.toLowerCase(),
803
+ userId: user.id,
804
+ }),
805
+ 'FirstAccount.create',
806
+ )
807
+
808
+ // The link's assertion signs the key of the request that its options carried.
809
+ if (challenge?.authorize !== undefined && assertion) {
810
+ // The session exists, so the page reads any refusal from here, thrown ones included, as
811
+ // one after the sign-in.
812
+ c.header(Headless.signedInHeader, 'true')
813
+ const authorization = await Timing.measure(
814
+ c,
815
+ Headless.keySignature(c, {
816
+ assertion,
817
+ challenge,
818
+ email: user.email,
819
+ setCookie: result.headers.getSetCookie(),
820
+ }),
821
+ 'Headless.keySignature',
822
+ )
823
+ if (authorization instanceof Response) return authorization
824
+ if (authorization instanceof ErrorResponse.ResponseError)
825
+ return ErrorResponse.json(c, authorization)
826
+ return c.json({ authorization, redirect: null, user }, 200)
827
+ }
828
+
829
+ // The app's request authorizes in the same request, after the code signed the user in.
830
+ if (authorize && app) {
831
+ // The session exists, so the page reads any refusal from here, thrown ones included, as one
832
+ // after the sign-in.
833
+ c.header(Headless.signedInHeader, 'true')
834
+ const authorization = await Timing.measure(
835
+ c,
836
+ Headless.afterCode(c, {
837
+ app,
838
+ email: user.email,
839
+ passkey,
840
+ request: authorize,
841
+ setCookie: result.headers.getSetCookie(),
842
+ }),
843
+ 'Headless.afterCode',
844
+ )
845
+ if (authorization instanceof Response) return authorization
846
+ if (authorization instanceof ErrorResponse.ResponseError)
847
+ return ErrorResponse.json(c, authorization)
848
+ // A passkey signs only in the browser, so the page signs the digest and repeats the request
849
+ // at `POST /v1/authorize`.
850
+ if ('options' in authorization)
851
+ return c.json(
852
+ {
853
+ authorization: Passkey.schema.headlessStep.parse({
854
+ expiry: authorization.expiry,
855
+ step: { options: authorization.options, type: 'passkey' },
856
+ }),
857
+ redirect: null,
858
+ user,
859
+ },
860
+ 200,
861
+ )
862
+ return c.json({ authorization, redirect: null, user }, 200)
863
+ }
864
+
865
+ // The sign-in page showed the request's key, so the sign-in grants it.
866
+ const redirect =
867
+ 'user' in signedIn
868
+ ? null
869
+ : await Timing.measure(
870
+ c,
871
+ SignInConsent.afterSignIn(c, {
872
+ redirect: signedIn.url,
873
+ setCookie: result.headers.getSetCookie(),
874
+ }),
875
+ 'SignInConsent.afterSignIn',
876
+ )
877
+ return c.json({ redirect, user }, 200)
878
+ },
879
+ )
880
+ .post(
881
+ '/v1/auth/passkey/options',
882
+ OpenApi.describeRoute({
883
+ description:
884
+ "Issues a single-use challenge, and returns request options for the passkeys of the first realm whose relying party covers Tempo ID's origin, and also the page's origin from an app's page. The realms are those of the app that `oauth_query`, `client_id`, or `user_code` names, or the `default` realm. With `link`, that realm must be the `default` realm at the link's relying party.",
885
+ responses: OpenApi.responses({
886
+ errors: [
887
+ ...BodyLimit.errors,
888
+ ...Cors.ownPage.errors,
889
+ ...OpenApi.validate.errors,
890
+ ...Authorize.check.errors,
891
+ ...Passkey.checkPage.errors,
892
+ ...RateLimit.check.errors,
893
+ Passkey.LinkExpiredError,
894
+ Passkey.NotPermittedError,
895
+ ],
896
+ success: {
897
+ description: 'The request options.',
898
+ schema: schema.passkeyOptions.response,
899
+ },
900
+ }),
901
+ tags: ['Authenticate'],
902
+ }),
903
+ OpenApi.validate('json', schema.passkeyOptions.json),
904
+ async (c) => {
905
+ const {
906
+ authorize,
907
+ client_id,
908
+ credentialId,
909
+ link,
910
+ mediation,
911
+ oauth_query,
912
+ user_code,
913
+ } = c.req.valid('json')
914
+ const crossSite = Cors.ownPage(c, { oauth_query })
915
+ if (crossSite) return ErrorResponse.json(c, crossSite)
916
+ // Each view of the sign-in page requests options for its autofill, so the options requests
917
+ // count on their own key, and spend none of the address's quota for email sign-in.
918
+ const ip = RateLimit.ip(c)
919
+ const refused = await Timing.measure(
920
+ c,
921
+ RateLimit.check(c, {
922
+ limits: [
923
+ {
924
+ binding: 'SIGN_IN_IP_LIMIT',
925
+ key: ip ? `passkey-options:${ip}` : undefined,
926
+ },
927
+ ],
928
+ }),
929
+ 'RateLimit.check',
930
+ )
931
+ if (refused) return refused
932
+
933
+ const deferred = link
934
+ ? await Timing.measure(
935
+ c,
936
+ PasskeyLink.claim(c, { nonce: link }),
937
+ 'PasskeyLink.claim',
938
+ )
939
+ : undefined
940
+ if (link && !deferred)
941
+ return ErrorResponse.json(c, new Passkey.LinkExpiredError())
942
+
943
+ // A first-party app's page runs the ceremony at its own origin, which the challenge stores.
944
+ // Only an assertion for that origin, from a request that origin sends, spends it.
945
+ const page = Cors.appOrigin(c)
946
+ const app = client_id
947
+ ? await Timing.measure(
948
+ c,
949
+ // A disabled app can share its origin with an enabled one, which CORS admits.
950
+ Headless.app(c, { clientId: client_id }),
951
+ 'Headless.app',
952
+ )
953
+ : undefined
954
+ if (page || client_id) {
955
+ const refusal = Passkey.checkPage({
956
+ app,
957
+ clientId: client_id,
958
+ origin: c.req.header('origin'),
959
+ })
960
+ if (refusal) return ErrorResponse.json(c, refusal)
961
+ }
962
+
963
+ // The signature of `oauth_query` is checked when the session is created. Until then, its app
964
+ // selects only the relying party. An app's page continues no authorization, so its challenge
965
+ // names no app.
966
+ const clientId = client({ oauth_query })
967
+ // A device app comes from the code's own row, never from the request, and selects only the
968
+ // relying party, so the challenge names no app.
969
+ const userCode = user_code ? Device.normalize(user_code) : undefined
970
+ const deviceApp =
971
+ !clientId && !client_id && userCode
972
+ ? await Timing.measure(
973
+ c,
974
+ Device.client(db, { userCode }),
975
+ 'Device.client',
976
+ )
977
+ : undefined
978
+ const appId = clientId ?? client_id ?? deviceApp
979
+ const stored = appId
980
+ ? await Timing.measure(
981
+ c,
982
+ Cache.read(c, () => Realm.forApp(db, { clientId: appId }), [
983
+ 'realm.forApp',
984
+ appId,
985
+ ]),
986
+ 'Realm.forApp',
987
+ )
988
+ : [
989
+ await Timing.measure(
990
+ c,
991
+ Cache.read(c, () => Realm.get(db, { id: Realm.defaultId }), [
992
+ 'realm.get',
993
+ Realm.defaultId,
994
+ ]),
995
+ 'Realm.get',
996
+ ),
997
+ ]
998
+ const realms = await Timing.measure(
999
+ c,
1000
+ Realm.withDefaults(c, { db, origin: env.URL, realms: stored }),
1001
+ 'Realm.withDefaults',
1002
+ )
1003
+ const relyingParty = Passkey.relyingParty(realms, {
1004
+ origin: env.URL,
1005
+ page,
1006
+ })
1007
+ // Only a challenge of the `default` realm reads wallet.tempo, so a link's passkey signs again
1008
+ // only for a sign-in whose realms select that realm, at the link's relying party.
1009
+ const refusesLink =
1010
+ deferred &&
1011
+ (relyingParty?.realmId !== Realm.defaultId ||
1012
+ relyingParty.rpId !== deferred.rpId)
1013
+ if (!relyingParty || refusesLink)
1014
+ return ErrorResponse.json(
1015
+ c,
1016
+ new Passkey.NotPermittedError({
1017
+ // A device app stays unnamed, so the refusal names no app that a code reveals.
1018
+ clientId: (clientId ?? client_id) || undefined,
1019
+ origin: page,
1020
+ }),
1021
+ )
1022
+
1023
+ // A challenge for a link stores the link's digest, so only that link's code sign-in takes it.
1024
+ const linked = link
1025
+ ? await Timing.measure(
1026
+ c,
1027
+ PasskeyLink.digest({ nonce: link }),
1028
+ 'PasskeyLink.digest',
1029
+ )
1030
+ : undefined
1031
+ // On an app's page, the request is checked as a headless one before the ceremony, so a key
1032
+ // over the headless ceiling signs nothing. Its key's expiry is filled now, so the request that
1033
+ // the sign-in runs has the digest that the passkey signs.
1034
+ const refusesAuthorize =
1035
+ authorize &&
1036
+ (page
1037
+ ? Authorize.check(authorize, { app, origin: c.req.header('origin') })
1038
+ : new Authorize.InvalidOriginError({
1039
+ error_description:
1040
+ "Invalid `Origin`: none. A sign-in with `authorize` runs only on the app's page.",
1041
+ field: 'Origin',
1042
+ }))
1043
+ if (refusesAuthorize) return ErrorResponse.json(c, refusesAuthorize)
1044
+ const pinned = await (async () => {
1045
+ if (!authorize) return undefined
1046
+ const sent = schema.passkeyOptions.sent.parse(await c.req.json())
1047
+ const key = authorize.key_authorization
1048
+ return key
1049
+ ? {
1050
+ ...sent.authorize,
1051
+ key_authorization: {
1052
+ ...sent.authorize.key_authorization,
1053
+ expiry: key.expiry,
1054
+ },
1055
+ }
1056
+ : sent.authorize
1057
+ })()
1058
+
1059
+ // The challenge of a request with a key is the key's digest, so one passkey assertion signs in
1060
+ // and signs the key: on the sign-in page for the request it continues, and on an app's page for
1061
+ // `authorize`. A link's step on the sign-in page signs in only. The witness is the request's
1062
+ // own, from its `challenge`, or a random one.
1063
+ const keyChallenge = await (async () => {
1064
+ if (page) {
1065
+ const key = authorize?.key_authorization
1066
+ if (!key) return undefined
1067
+ const witness =
1068
+ key.witness ??
1069
+ Hex.fromBytes(crypto.getRandomValues(new Uint8Array(32)))
1070
+ return {
1071
+ digest: KeyAuthorization.digest({ key, witness }),
1072
+ witness,
1073
+ }
1074
+ }
1075
+ if (!oauth_query || link) return undefined
1076
+ return await Timing.measure(
1077
+ c,
1078
+ SignInConsent.keyChallenge(c, { oauthQuery: oauth_query }),
1079
+ 'SignInConsent.keyChallenge',
1080
+ )
1081
+ })()
1082
+ const challenge = await Timing.measure(
1083
+ c,
1084
+ Passkey.challenge(db, {
1085
+ authorize: pinned,
1086
+ clientId,
1087
+ keyChallenge,
1088
+ link: linked,
1089
+ origin: page,
1090
+ ...relyingParty,
1091
+ }),
1092
+ 'Passkey.challenge',
1093
+ )
1094
+ // A pending challenge holds the same key challenge, which only an app's challenge repeats.
1095
+ if (!challenge)
1096
+ return ErrorResponse.json(c, new Passkey.WebAuthnRejectedError())
1097
+ // Without a credential ID, the browser offers every discoverable passkey of the relying party,
1098
+ // as WebAuthn defines for an empty list. The challenge stays Tempo ID's either way.
1099
+ const allowed = (() => {
1100
+ if (deferred) return [deferred.id]
1101
+ return credentialId === undefined ? [] : [credentialId].flat()
1102
+ })()
1103
+ const options = schema.passkeyOptions.response.shape.options.parse({
1104
+ ...Authentication.getOptions({
1105
+ challenge,
1106
+ ...(allowed.length > 0 ? { credentialId: allowed } : {}),
1107
+ rpId: relyingParty.rpId,
1108
+ userVerification: 'required',
1109
+ }).options,
1110
+ ...(mediation ? { mediation } : {}),
1111
+ })
1112
+ c.header('cache-control', 'private, no-store')
1113
+ return c.json({ options }, 200)
1114
+ },
1115
+ )
1116
+ .post(
1117
+ '/v1/auth/passkey/verify',
1118
+ OpenApi.describeRoute({
1119
+ description:
1120
+ 'Signs in with a passkey assertion over a challenge from `POST /v1/auth/passkey/options`, and sets the session cookie. For a user with no Tempo Account in the first realm of the app that `oauth_query` names, or in the `default` realm, it creates one when that realm creates accounts. A failed creation leaves the user signed in, and the next sign-in or `POST /v1/account` creates the account.',
1121
+ responses: OpenApi.responses({
1122
+ errors: [
1123
+ ...BodyLimit.errors,
1124
+ ...Cors.ownPage.errors,
1125
+ ...OpenApi.validate.errors,
1126
+ ...ErrorResponse.fromUpstream.errors,
1127
+ ...Headless.keySignature.errors,
1128
+ ...RateLimit.check.errors,
1129
+ ...emailUser.errors,
1130
+ core_Auth.AuthorizationExpiredError,
1131
+ Passkey.WebAuthnRejectedError,
1132
+ ],
1133
+ success: {
1134
+ description:
1135
+ 'The signed-in user, with the authorization of a sign-in with key signature, or the email step for a wallet.tempo passkey without an email.',
1136
+ schema: schema.passkeyVerify.response,
1137
+ },
1138
+ }),
1139
+ tags: ['Authenticate'],
1140
+ }),
1141
+ OpenApi.validate('json', schema.passkeyVerify.json),
1142
+ async (c) => {
1143
+ const { assertion, oauth_query } = c.req.valid('json')
1144
+ const crossSite = Cors.ownPage(c, { oauth_query })
1145
+ if (crossSite) return ErrorResponse.json(c, crossSite)
1146
+ const refused = await Timing.measure(
1147
+ c,
1148
+ RateLimit.check(c, {
1149
+ limits: [{ binding: 'SIGN_IN_IP_LIMIT', key: RateLimit.ip(c) }],
1150
+ }),
1151
+ 'RateLimit.check',
1152
+ )
1153
+ if (refused) return refused
1154
+
1155
+ // The challenge is spent before any other check, so a failed attempt cannot be retried. The
1156
+ // same statement reads the passkey and its user.
1157
+ const { id } = assertion
1158
+ const taken = await Timing.measure(
1159
+ c,
1160
+ Passkey.takeWithKey(db, {
1161
+ clientDataJSON: assertion.metadata.clientDataJSON,
1162
+ id,
1163
+ }),
1164
+ 'Passkey.takeWithKey',
1165
+ )
1166
+ const challenge = taken?.challenge
1167
+ // A challenge serves only the sign-in it was issued for: the same app, or none, from the same
1168
+ // page. A challenge for an email step's link serves only that link's code sign-in.
1169
+ if (
1170
+ !challenge ||
1171
+ challenge.link !== undefined ||
1172
+ challenge.clientId !== client({ oauth_query }) ||
1173
+ challenge.origin !== Cors.appOrigin(c)
1174
+ )
1175
+ return ErrorResponse.json(c, new Passkey.WebAuthnRejectedError())
1176
+
1177
+ const key = taken.key
1178
+ // A passkey that Tempo ID does not store yet may be wallet.tempo's, which shares the `default`
1179
+ // realm's relying party, and links once it verifies.
1180
+ const credential = await (async () => {
1181
+ if (key || !c.env.WALLET || challenge.realmId !== Realm.defaultId)
1182
+ return undefined
1183
+ try {
1184
+ return await Timing.measure(
1185
+ c,
1186
+ Wallet.credential(c.env.WALLET, { id }),
1187
+ 'Wallet.credential',
1188
+ )
1189
+ } catch (error) {
1190
+ // Only the binding call throws, so the failure is wallet.tempo's.
1191
+ Log.warn(c, {
1192
+ error,
1193
+ message: 'The wallet service failed a passkey lookup.',
1194
+ })
1195
+ return (
1196
+ (error instanceof Error && ErrorResponse.fromUpstream(error)) ||
1197
+ new ErrorResponse.UpstreamUnavailableError()
1198
+ )
1199
+ }
1200
+ })()
1201
+ if (credential instanceof ErrorResponse.ResponseError)
1202
+ return ErrorResponse.json(c, credential)
1203
+ const publicKey = key?.publicKey ?? credential?.publicKey
1204
+ if (
1205
+ !publicKey ||
1206
+ !Passkey.verify(assertion, {
1207
+ challenge: challenge.challenge,
1208
+ origin: challenge.origin ?? new URL(env.URL).origin,
1209
+ publicKey: publicKey as `0x${string}`,
1210
+ rpId: challenge.rpId,
1211
+ })
1212
+ )
1213
+ return ErrorResponse.json(c, new Passkey.WebAuthnRejectedError())
1214
+ // An assertion of a sign-in with key signature on an app's page signs in once, whatever then
1215
+ // signs the key.
1216
+ const unspent = await Timing.measure(
1217
+ c,
1218
+ Headless.spend(c, { assertion, challenge }),
1219
+ 'Headless.spend',
1220
+ )
1221
+ if (!unspent)
1222
+ return ErrorResponse.json(c, new Passkey.WebAuthnRejectedError())
1223
+
1224
+ // A wallet.tempo account without an email links once the user verifies one with a code.
1225
+ if (credential && !credential.email) {
1226
+ const link = await Timing.measure(
1227
+ c,
1228
+ PasskeyLink.defer(c, { credential, id, rpId: challenge.rpId }),
1229
+ 'PasskeyLink.defer',
1230
+ )
1231
+ c.header('cache-control', 'private, no-store')
1232
+ return c.json(
1233
+ { step: { link, signed: false, type: 'email' as const } },
1234
+ 200,
1235
+ )
1236
+ }
1237
+
1238
+ // The user whom the passkey signs in, with the address that the response returns, when the
1239
+ // route already read it.
1240
+ const signer = await (async () => {
1241
+ if (key) return { user: key.user, userId: key.userId }
1242
+ // wallet.tempo verified the email, so its user is found or created by that address.
1243
+ const user = await Timing.measure(
1244
+ c,
1245
+ emailUser(c, { email: credential!.email! }),
1246
+ 'authenticate.emailUser',
1247
+ )
1248
+ const linked = await Timing.measure(
1249
+ c,
1250
+ Passkey.link(db, {
1251
+ credential: credential!,
1252
+ id,
1253
+ rpId: challenge.rpId,
1254
+ userId: user.id,
1255
+ }),
1256
+ 'Passkey.link',
1257
+ )
1258
+ TempoAccount.forget(c)
1259
+ // A concurrent first sign-in can link the passkey to another user, whose row decides.
1260
+ return linked
1261
+ ? { user: linked === user.id ? user : undefined, userId: linked }
1262
+ : undefined
1263
+ })()
1264
+ // Another passkey holds the address that wallet.tempo returned.
1265
+ if (!signer)
1266
+ return ErrorResponse.json(c, new Passkey.WebAuthnRejectedError())
1267
+ const { userId } = signer
1268
+
1269
+ // A sign-in that continues an app's request reads the user's accounts in the app's realms, so
1270
+ // their Privy users load beside the session's creation, and so does the user's first account.
1271
+ // The assertion already verified, and its challenge is spent. Both start only for a query that
1272
+ // Better Auth signed and that has not expired, which the sign-in checks too, so a forged query
1273
+ // creates no account in its app's realm.
1274
+ const signed = await (async () => {
1275
+ if (!oauth_query) return true
1276
+ const context = await Timing.measure(
1277
+ c,
1278
+ c.var.auth.$context,
1279
+ 'auth.context',
1280
+ )
1281
+ return await Timing.measure(
1282
+ c,
1283
+ verifyOAuthQueryParams(oauth_query, context.secret),
1284
+ 'auth.verifyOAuthQueryParams',
1285
+ )
1286
+ })()
1287
+ const appId = signed
1288
+ ? (client({ oauth_query }) ??
1289
+ Authorize.schema.request.safeParse(challenge.authorize).data
1290
+ ?.client_id)
1291
+ : undefined
1292
+ // Every branch settles before the response, so a refused sign-in leaves no first account
1293
+ // running after it. The other branches catch their own failures.
1294
+ const [settled] = await Promise.allSettled([
1295
+ Timing.measure(
1296
+ c,
1297
+ c.var.auth.api.signInPasskey({
1298
+ asResponse: false,
1299
+ body: {
1300
+ userId,
1301
+ ...(key ? { user: key.user } : {}),
1302
+ ...(oauth_query ? { oauth_query } : {}),
1303
+ },
1304
+ // Better Auth sets `accept` to continue an authorization as JSON, and a request's own
1305
+ // headers are immutable.
1306
+ headers: new Headers(c.req.raw.headers),
1307
+ request: c.req.raw,
1308
+ returnHeaders: true,
1309
+ }),
1310
+ 'auth.signInPasskey',
1311
+ ).catch((error: unknown) => {
1312
+ if (isAPIError(error) && error.body?.error === 'invalid_signature')
1313
+ return new core_Auth.AuthorizationExpiredError()
1314
+ throw error
1315
+ }),
1316
+ appId
1317
+ ? Timing.measure(
1318
+ c,
1319
+ AccountStep.prefetch(c, { clientId: appId, userId }),
1320
+ 'AccountStep.prefetch',
1321
+ )
1322
+ : undefined,
1323
+ // A linked or registered passkey owns its account, so only a sign-in passkey's user can
1324
+ // receive one. The verified assertion signs the user in, so the account needs no session.
1325
+ // The account step inside the sign-in finds at most this one account either way.
1326
+ signed
1327
+ ? Timing.measure(
1328
+ c,
1329
+ FirstAccount.create(c, {
1330
+ clientId: client({ oauth_query }),
1331
+ email: signer.user?.email,
1332
+ userId,
1333
+ }),
1334
+ 'FirstAccount.create',
1335
+ )
1336
+ : undefined,
1337
+ ])
1338
+ if (settled.status === 'rejected') throw settled.reason
1339
+ const result = settled.value
1340
+ if (result instanceof ErrorResponse.ResponseError)
1341
+ return ErrorResponse.json(c, result)
1342
+
1343
+ for (const cookie of result.headers.getSetCookie())
1344
+ c.header('set-cookie', cookie, { append: true })
1345
+ c.header('cache-control', 'private, no-store')
1346
+
1347
+ // With `oauth_query`, Better Auth continues the app's authorization once the session exists, and
1348
+ // returns its redirect in place of the user.
1349
+ const signedIn = schema.verify.signedIn.parse(result.response)
1350
+ if ('user' in signedIn) {
1351
+ const user = { email: signedIn.user.email, id: signedIn.user.id }
1352
+ if (challenge.authorize === undefined)
1353
+ return c.json({ redirect: null, user }, 200)
1354
+ // The session exists, so the page reads any refusal from here, thrown ones included, as
1355
+ // one after the sign-in.
1356
+ c.header(Headless.signedInHeader, 'true')
1357
+ const authorization = await Timing.measure(
1358
+ c,
1359
+ Headless.keySignature(c, {
1360
+ assertion,
1361
+ challenge,
1362
+ email: user.email,
1363
+ setCookie: result.headers.getSetCookie(),
1364
+ }),
1365
+ 'Headless.keySignature',
1366
+ )
1367
+ if (authorization instanceof Response) return authorization
1368
+ if (authorization instanceof ErrorResponse.ResponseError)
1369
+ return ErrorResponse.json(c, authorization)
1370
+ return c.json({ authorization, redirect: null, user }, 200)
1371
+ }
1372
+ // The passkey's row or wallet.tempo's address named the user, so only a passkey that a
1373
+ // concurrent sign-in linked to another user reads it again.
1374
+ const user = await (async () => {
1375
+ if (signer.user) return { email: signer.user.email, id: signer.user.id }
1376
+ const [row] = await Timing.measure(
1377
+ c,
1378
+ db
1379
+ .select({ email: Schema.user.email, id: Schema.user.id })
1380
+ .from(Schema.user)
1381
+ .where(eq(Schema.user.id, userId)),
1382
+ 'db.user.get',
1383
+ )
1384
+ return row
1385
+ })()
1386
+ if (!user) throw new Error('The signed-in user is missing.')
1387
+
1388
+ // The sign-in page showed the request's key, so the sign-in grants it. A key challenge was
1389
+ // the key's digest, so the same assertion signs it for an account that this passkey owns.
1390
+ const redirect = await Timing.measure(
1391
+ c,
1392
+ SignInConsent.afterSignIn(c, {
1393
+ keySignature: challenge.witness
1394
+ ? { assertion, witness: challenge.witness }
1395
+ : undefined,
1396
+ redirect: signedIn.url,
1397
+ setCookie: result.headers.getSetCookie(),
1398
+ }),
1399
+ 'SignInConsent.afterSignIn',
1400
+ )
1401
+ return c.json({ redirect, user }, 200)
1402
+ },
1403
+ )
1404
+ .post(
1405
+ '/v1/auth/logout',
1406
+ OpenApi.describeRoute({
1407
+ description:
1408
+ 'Signs out: ends the session, revokes the access and refresh tokens that apps received through it, and clears its cookie.',
1409
+ responses: OpenApi.responses({
1410
+ errors: [...BodyLimit.errors, ErrorResponse.CrossSiteRequestError],
1411
+ success: {
1412
+ description: 'The session is over.',
1413
+ schema: schema.logout.response,
1414
+ },
1415
+ }),
1416
+ tags: ['Authenticate'],
1417
+ }),
1418
+ async (c) => {
1419
+ // One statement ends the session and its apps' tokens. Better Auth's sign-out takes six round
1420
+ // trips, and runs only to expire the cookies.
1421
+ const token = await Timing.measure(c, Session.token(c), 'Session.token')
1422
+ if (token)
1423
+ await Timing.measure(c, Logout.end(db, { token }), 'Logout.end')
1424
+ await Timing.measure(c, Session.clear(c), 'Session.clear')
1425
+ // The next sign-in chooses each app's account again.
1426
+ c.header('set-cookie', AccountStep.clear(), { append: true })
1427
+ c.header('cache-control', 'private, no-store')
1428
+ return c.json({ signed_out: true as const }, 200)
1429
+ },
1430
+ )
1431
+ .get(
1432
+ '/v1/auth/session',
1433
+ OpenApi.describeRoute({
1434
+ description: 'Reads the signed-in user, or `null` without a session.',
1435
+ responses: OpenApi.responses({
1436
+ success: {
1437
+ description: 'The session.',
1438
+ schema: schema.session.response,
1439
+ },
1440
+ }),
1441
+ tags: ['Authenticate'],
1442
+ }),
1443
+ async (c) => {
1444
+ const session = await Timing.measure(c, Session.get(c), 'Session.get')
1445
+ c.header('cache-control', 'private, no-store')
1446
+ if (!session) return c.json({ user: null }, 200)
1447
+ return c.json(
1448
+ {
1449
+ user: {
1450
+ email: session.user.email,
1451
+ id: session.user.id,
1452
+ // Better Auth stores an empty name for a user who signed up without one.
1453
+ name: session.user.name || null,
1454
+ },
1455
+ },
1456
+ 200,
1457
+ )
1458
+ },
1459
+ )
1460
+ .get(
1461
+ '/v1/auth/assets',
1462
+ OpenApi.describeRoute({
1463
+ description:
1464
+ "Lists the sign-in page's scripts and style sheets, which a page on Tempo ID's site prefetches before it redirects. Browsers partition their caches by site, so a page on another site gains nothing.",
1465
+ responses: OpenApi.responses({
1466
+ success: {
1467
+ description: 'The assets.',
1468
+ schema: schema.assets.response,
1469
+ },
1470
+ }),
1471
+ tags: ['Authenticate'],
1472
+ }),
1473
+ async (c) => {
1474
+ const assets = await Timing.measure(
1475
+ c,
1476
+ c.env.signInAssets(),
1477
+ 'pages.assets',
1478
+ )
1479
+ // A deploy changes the list, so a browser keeps it for a short time only.
1480
+ c.header('cache-control', 'public, max-age=300')
1481
+ return c.json({ assets }, 200)
1482
+ },
1483
+ )
1484
+ .get(
1485
+ '/v1/auth/methods',
1486
+ OpenApi.describeRoute({
1487
+ description:
1488
+ 'Reads the sign-in methods that the sign-in page offers, the key that `oauth_query` grants, and the page that sign-in returns to. The app of `oauth_query`, or of a pending, unbound device code in `return_to`, selects the realms. The read binds nothing, and counts against the sign-in limit of the IP address.',
1489
+ responses: OpenApi.responses({
1490
+ errors: [...OpenApi.validate.errors],
1491
+ success: {
1492
+ description: 'The sign-in methods.',
1493
+ schema: schema.methods.response,
1494
+ },
1495
+ }),
1496
+ tags: ['Authenticate'],
1497
+ }),
1498
+ OpenApi.validate('query', schema.methods.query),
1499
+ async (c) => {
1500
+ const input = c.req.valid('query')
1501
+ // Sign-in returns only to an allowlisted path, so `return_to` never redirects to another site.
1502
+ const returnTo = Device.returnTo(input.return_to, { origin: env.URL })
1503
+ const query = (() => {
1504
+ if (!input.oauth_query) return undefined
1505
+ const query = new URLSearchParams(input.oauth_query)
1506
+ return query.has('sig') ? query : undefined
1507
+ })()
1508
+
1509
+ // The user code comes from `return_to`, but the app comes from the code's own row, so the
1510
+ // visitor selects no app by itself.
1511
+ const userCode = returnTo
1512
+ ? Device.normalize(
1513
+ new URL(returnTo, env.URL).searchParams.get('code') ?? '',
1514
+ )
1515
+ : undefined
1516
+ const clientId = await (async () => {
1517
+ if (query) return query.get('client_id') ?? undefined
1518
+ if (!userCode) return undefined
1519
+ // A live code's realms change the page, so each IP address's lookups count, and keep a guess
1520
+ // of a live code out of reach (RFC 8628 §5.1). Past the limit, the page shows the `default`
1521
+ // realm.
1522
+ const ip = RateLimit.ip(c)
1523
+ if (!ip) return undefined
1524
+ const outcome = await Timing.measure(
1525
+ c,
1526
+ c.env.SIGN_IN_IP_LIMIT.limit({ key: `device-lookup:${ip}` }),
1527
+ 'ratelimit.limit',
1528
+ )
1529
+ if (!outcome.success) return undefined
1530
+ return await Timing.measure(
1531
+ c,
1532
+ Device.client(db, { userCode }),
1533
+ 'Device.client',
1534
+ )
1535
+ })()
1536
+ const stored = clientId
1537
+ ? await Timing.measure(
1538
+ c,
1539
+ Cache.read(c, () => Realm.forApp(db, { clientId }), [
1540
+ 'realm.forApp',
1541
+ clientId,
1542
+ ]),
1543
+ 'Realm.forApp',
1544
+ )
1545
+ : [
1546
+ await Timing.measure(
1547
+ c,
1548
+ Cache.read(c, () => Realm.get(db, { id: Realm.defaultId }), [
1549
+ 'realm.get',
1550
+ Realm.defaultId,
1551
+ ]),
1552
+ 'Realm.get',
1553
+ ),
1554
+ ]
1555
+ const realms = await Timing.measure(
1556
+ c,
1557
+ Realm.withDefaults(c, { db, origin: env.URL, realms: stored }),
1558
+ 'Realm.withDefaults',
1559
+ )
1560
+ const request = query
1561
+ ? await Timing.measure(c, granted(c, { query }), 'authenticate.granted')
1562
+ : null
1563
+ return c.json(
1564
+ {
1565
+ app: request?.app ?? null,
1566
+ host: request?.host ?? null,
1567
+ passkeys: Boolean(Passkey.relyingParty(realms, { origin: env.URL })),
1568
+ // `request` keeps its `/v1` shape: it is `null` without a key that the sign-in grants.
1569
+ request: request?.key ? { app: request.app, key: request.key } : null,
1570
+ return_to: returnTo ?? null,
1571
+ user_code: userCode || null,
1572
+ verified: request?.verified ?? false,
1573
+ },
1574
+ 200,
1575
+ )
1576
+ },
1577
+ )
1578
+
1579
+ /** Returns the client ID of the app that `oauth_query` names, or `null` without one. */
1580
+ function client(options: client.Options) {
1581
+ if (!options.oauth_query) return null
1582
+ return new URLSearchParams(options.oauth_query).get('client_id')
1583
+ }
1584
+
1585
+ declare namespace client {
1586
+ type Options = {
1587
+ /** The sign-in page's query string, as the request sends it. */
1588
+ oauth_query?: string | undefined
1589
+ }
1590
+ }
1591
+
1592
+ /**
1593
+ * Returns the app of the signed authorization request `query`, whether it is first-party, and the
1594
+ * key that the sign-in grants, or `null` for a forged or expired query, or an unknown app. The key is
1595
+ * `null` for a request without one, with a `challenge`, whose key the approval page shows beside its
1596
+ * message, or from a third-party app, whose key the approval page shows beside the host that serves
1597
+ * its metadata document.
1598
+ */
1599
+ async function granted(c: Context<Env>, options: granted.Options) {
1600
+ const { query } = options
1601
+ const context = await Timing.measure(c, c.var.auth.$context, 'auth.context')
1602
+ const verified = await Timing.measure(
1603
+ c,
1604
+ verifyOAuthQueryParams(query.toString(), context.secret),
1605
+ 'auth.verifyOAuthQueryParams',
1606
+ )
1607
+ const clientId = query.get('client_id')
1608
+ if (!verified || !clientId) return null
1609
+
1610
+ // The sign-in page shows only the app's name, so the cache holds the name alone.
1611
+ const app = await Timing.measure(
1612
+ c,
1613
+ Cache.read(
1614
+ c,
1615
+ async () => {
1616
+ const found = await Apps.get(db, { clientId }).catch(
1617
+ (error: unknown) => {
1618
+ if (error instanceof Apps.NotFoundError) return undefined
1619
+ throw error
1620
+ },
1621
+ )
1622
+ return found ? { name: found.name } : undefined
1623
+ },
1624
+ ['apps.name', clientId],
1625
+ { keep: (found) => found !== undefined },
1626
+ ),
1627
+ 'Apps.get',
1628
+ )
1629
+ if (!app) return null
1630
+
1631
+ // A third-party app names itself in its metadata document, so only the approval page grants its key.
1632
+ const thirdParty = Apps.thirdParty(clientId)
1633
+ // A request that a sign-in already spent grants nothing at sign-in, so only the approval page
1634
+ // shows its key.
1635
+ const key =
1636
+ query.has('challenge') ||
1637
+ thirdParty ||
1638
+ !query.has('key_authorization') ||
1639
+ (await Timing.measure(
1640
+ c,
1641
+ SignInGrant.spent(db, { query }),
1642
+ 'SignInGrant.spent',
1643
+ ))
1644
+ ? undefined
1645
+ : Authorize.fromQuery(query)
1646
+ return {
1647
+ app: app.name ?? clientId,
1648
+ host: thirdParty ? new URL(clientId).host : null,
1649
+ key:
1650
+ key && !(key instanceof ErrorResponse.ResponseError)
1651
+ ? KeyAuthorization.describe(key)
1652
+ : null,
1653
+ verified: !thirdParty,
1654
+ }
1655
+ }
1656
+
1657
+ declare namespace granted {
1658
+ type Options = {
1659
+ /** The sign-in page's query. */
1660
+ query: URLSearchParams
1661
+ }
1662
+ }