@robelest/convex-auth 0.0.4-preview.25 → 0.0.4-preview.28

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 (666) hide show
  1. package/README.md +43 -36
  2. package/dist/bin.js +5765 -4880
  3. package/dist/browser/index.d.ts +30 -0
  4. package/dist/browser/index.js +93 -0
  5. package/dist/browser/locks.js +11 -0
  6. package/dist/browser/navigation.js +14 -0
  7. package/dist/{factors → browser}/passkey.js +23 -32
  8. package/dist/browser/runtime.js +92 -0
  9. package/dist/client/core/types.d.ts +452 -5
  10. package/dist/client/core/types.js +17 -0
  11. package/dist/client/errors.js +19 -0
  12. package/dist/client/factors/device.js +94 -0
  13. package/dist/{factors → client/factors}/totp.js +12 -4
  14. package/dist/client/index.d.ts +47 -1
  15. package/dist/client/index.js +269 -232
  16. package/dist/client/runtime/mutex.js +24 -0
  17. package/dist/client/runtime/proxy.js +30 -0
  18. package/dist/client/runtime/storage.js +45 -0
  19. package/dist/client/services/adapters.js +7 -0
  20. package/dist/client/services/http.js +6 -0
  21. package/dist/client/services/resolve.js +13 -0
  22. package/dist/client/services/runtime.js +6 -0
  23. package/dist/component/_generated/component.d.ts +1355 -1399
  24. package/dist/component/convex.config.d.ts +2 -2
  25. package/dist/component/index.d.ts +4 -26
  26. package/dist/component/index.js +1 -1
  27. package/dist/component/model.d.ts +26 -112
  28. package/dist/component/model.js +76 -54
  29. package/dist/component/modules.js +38 -0
  30. package/dist/component/public/factors/devices.js +1 -1
  31. package/dist/component/public/factors/passkeys.js +1 -1
  32. package/dist/component/public/factors/totp.js +1 -1
  33. package/dist/component/public/groups/core.js +2 -2
  34. package/dist/component/public/groups/invites.js +1 -1
  35. package/dist/component/public/groups/members.js +1 -1
  36. package/dist/component/public/identity/accounts.js +1 -1
  37. package/dist/component/public/identity/codes.js +1 -1
  38. package/dist/component/public/identity/sessions.js +39 -2
  39. package/dist/component/public/identity/tokens.js +82 -4
  40. package/dist/component/public/identity/users.js +1 -1
  41. package/dist/component/public/identity/verifiers.js +10 -4
  42. package/dist/component/public/security/keys.js +1 -1
  43. package/dist/component/public/security/limits.js +1 -1
  44. package/dist/component/public/{enterprise → sso}/audit.js +26 -26
  45. package/dist/component/public/sso/core.js +263 -0
  46. package/dist/component/public/sso/domains.js +280 -0
  47. package/dist/component/public/{enterprise → sso}/scim.js +87 -87
  48. package/dist/component/public/sso/secrets.js +125 -0
  49. package/dist/component/public/{enterprise → sso}/webhooks.js +59 -59
  50. package/dist/component/public.js +9 -9
  51. package/dist/component/schema.d.ts +472 -393
  52. package/dist/component/schema.js +36 -35
  53. package/dist/core/index.d.ts +380 -0
  54. package/dist/core/index.js +83 -0
  55. package/dist/otel.d.ts +69 -0
  56. package/dist/otel.js +82 -0
  57. package/dist/providers/anonymous.d.ts +15 -34
  58. package/dist/providers/anonymous.js +27 -35
  59. package/dist/providers/apple.d.ts +59 -0
  60. package/dist/providers/apple.js +58 -0
  61. package/dist/providers/credentials.d.ts +18 -34
  62. package/dist/providers/credentials.js +16 -27
  63. package/dist/providers/custom.d.ts +94 -0
  64. package/dist/providers/custom.js +119 -0
  65. package/dist/providers/device.d.ts +15 -49
  66. package/dist/providers/device.js +17 -34
  67. package/dist/providers/email.d.ts +21 -38
  68. package/dist/providers/email.js +36 -55
  69. package/dist/providers/github.d.ts +54 -0
  70. package/dist/providers/github.js +75 -0
  71. package/dist/providers/google.d.ts +54 -0
  72. package/dist/providers/google.js +61 -0
  73. package/dist/providers/index.d.ts +16 -12
  74. package/dist/providers/index.js +15 -11
  75. package/dist/providers/microsoft.d.ts +57 -0
  76. package/dist/providers/microsoft.js +101 -0
  77. package/dist/providers/passkey.d.ts +19 -35
  78. package/dist/providers/passkey.js +20 -30
  79. package/dist/providers/password.d.ts +17 -18
  80. package/dist/providers/password.js +121 -143
  81. package/dist/providers/phone.d.ts +13 -28
  82. package/dist/providers/phone.js +21 -46
  83. package/dist/providers/sso.d.ts +16 -36
  84. package/dist/providers/sso.js +21 -22
  85. package/dist/providers/totp.d.ts +13 -29
  86. package/dist/providers/totp.js +17 -27
  87. package/dist/server/auth-context.d.ts +204 -0
  88. package/dist/server/auth-context.js +76 -0
  89. package/dist/server/auth.d.ts +99 -244
  90. package/dist/server/auth.js +56 -152
  91. package/dist/server/componentContext.d.ts +12 -0
  92. package/dist/server/componentContext.js +1 -0
  93. package/dist/server/config.js +6 -67
  94. package/dist/server/constants.js +6 -0
  95. package/dist/server/contract.d.ts +105 -0
  96. package/dist/server/contract.js +43 -0
  97. package/dist/server/cookies.js +3 -2
  98. package/dist/server/core.js +31 -36
  99. package/dist/server/crypto.js +34 -44
  100. package/dist/server/db.js +6 -1
  101. package/dist/server/device.js +96 -130
  102. package/dist/server/env.js +48 -0
  103. package/dist/server/errors.js +20 -0
  104. package/dist/server/http.d.ts +15 -59
  105. package/dist/server/http.js +136 -120
  106. package/dist/server/identity.js +2 -2
  107. package/dist/server/index.d.ts +5 -4
  108. package/dist/server/index.js +3 -3
  109. package/dist/server/keys.js +10 -1
  110. package/dist/server/limits.js +26 -26
  111. package/dist/server/log.js +28 -0
  112. package/dist/server/mounts.d.ts +1107 -296
  113. package/dist/server/mounts.js +315 -196
  114. package/dist/server/mutations/account.js +11 -14
  115. package/dist/server/mutations/code.js +6 -5
  116. package/dist/server/mutations/invalidate.js +9 -11
  117. package/dist/server/mutations/oauth.js +112 -73
  118. package/dist/server/mutations/refresh.js +47 -97
  119. package/dist/server/mutations/register.js +37 -35
  120. package/dist/server/mutations/retrieve.js +16 -16
  121. package/dist/server/mutations/signature.js +15 -18
  122. package/dist/server/mutations/signin.js +10 -5
  123. package/dist/server/mutations/signout.js +11 -14
  124. package/dist/server/mutations/store.js +25 -18
  125. package/dist/server/mutations/verifier.js +11 -8
  126. package/dist/server/mutations/verify.js +53 -41
  127. package/dist/server/oauth/factory.js +44 -0
  128. package/dist/server/oauth/index.js +12 -0
  129. package/dist/server/oauth/runtime.js +248 -0
  130. package/dist/server/passkey.js +331 -365
  131. package/dist/server/payloads.d.ts +16 -0
  132. package/dist/server/payloads.js +30 -0
  133. package/dist/server/{ssr.d.ts → prefetch.d.ts} +2 -2
  134. package/dist/server/prefetch.js +635 -0
  135. package/dist/server/random.js +19 -0
  136. package/dist/server/redirects.js +10 -5
  137. package/dist/server/refresh.js +14 -86
  138. package/dist/server/runtime.d.ts +531 -31
  139. package/dist/server/runtime.js +106 -267
  140. package/dist/server/secret.js +44 -0
  141. package/dist/server/services/config.js +10 -0
  142. package/dist/server/services/group.js +211 -0
  143. package/dist/server/services/logger.js +8 -0
  144. package/dist/server/services/providers.js +22 -0
  145. package/dist/server/services/refresh.js +8 -0
  146. package/dist/server/services/resolve.js +27 -0
  147. package/dist/server/services/signin.js +8 -0
  148. package/dist/server/sessions.js +35 -34
  149. package/dist/server/signin.js +229 -140
  150. package/dist/server/{enterprise → sso}/config.js +10 -3
  151. package/dist/server/sso/domain.d.ts +614 -0
  152. package/dist/server/sso/domain.js +1175 -0
  153. package/dist/server/sso/http.js +1060 -0
  154. package/dist/server/sso/oidc.js +324 -0
  155. package/dist/server/sso/policies.js +59 -0
  156. package/dist/server/sso/policy.js +139 -0
  157. package/dist/server/sso/profile.js +22 -0
  158. package/dist/server/sso/provision.js +179 -0
  159. package/dist/{component/server/enterprise → server/sso}/saml.js +142 -56
  160. package/dist/{component/server/enterprise → server/sso}/scim.js +13 -7
  161. package/dist/server/sso/shared.js +74 -0
  162. package/dist/server/sso/validators.js +88 -0
  163. package/dist/server/sso/webhook.js +94 -0
  164. package/dist/server/tokens.js +16 -4
  165. package/dist/server/totp.js +155 -164
  166. package/dist/server/types.d.ts +306 -296
  167. package/dist/server/types.js +1 -30
  168. package/dist/server/url.js +32 -0
  169. package/dist/server/users.js +74 -40
  170. package/dist/server/utils/cache.js +51 -0
  171. package/dist/server/utils/dispatch.js +36 -0
  172. package/dist/server/utils/retry.js +24 -0
  173. package/dist/server/utils/span.js +32 -0
  174. package/dist/shared/errors.js +19 -0
  175. package/dist/shared/log.js +45 -0
  176. package/{src/test.ts → dist/test.d.ts} +21 -22
  177. package/dist/test.js +51 -0
  178. package/package.json +70 -42
  179. package/dist/authorization/index.d.ts.map +0 -1
  180. package/dist/authorization/index.js.map +0 -1
  181. package/dist/client/core/types.d.ts.map +0 -1
  182. package/dist/client/index.d.ts.map +0 -1
  183. package/dist/client/index.js.map +0 -1
  184. package/dist/component/_generated/api.d.ts +0 -75
  185. package/dist/component/_generated/api.d.ts.map +0 -1
  186. package/dist/component/_generated/api.js.map +0 -1
  187. package/dist/component/_generated/component.d.ts.map +0 -1
  188. package/dist/component/_generated/dataModel.d.ts +0 -42
  189. package/dist/component/_generated/dataModel.d.ts.map +0 -1
  190. package/dist/component/_generated/server.d.ts +0 -117
  191. package/dist/component/_generated/server.d.ts.map +0 -1
  192. package/dist/component/_generated/server.js.map +0 -1
  193. package/dist/component/_virtual/rolldown_runtime.js +0 -18
  194. package/dist/component/client/core/types.d.ts +0 -2
  195. package/dist/component/client/index.d.ts +0 -1
  196. package/dist/component/convex.config.d.ts.map +0 -1
  197. package/dist/component/convex.config.js.map +0 -1
  198. package/dist/component/functions.d.ts +0 -25
  199. package/dist/component/functions.d.ts.map +0 -1
  200. package/dist/component/functions.js.map +0 -1
  201. package/dist/component/index.d.ts.map +0 -1
  202. package/dist/component/model.d.ts.map +0 -1
  203. package/dist/component/model.js.map +0 -1
  204. package/dist/component/providers/anonymous.d.ts +0 -54
  205. package/dist/component/providers/anonymous.d.ts.map +0 -1
  206. package/dist/component/providers/credentials.d.ts +0 -38
  207. package/dist/component/providers/credentials.d.ts.map +0 -1
  208. package/dist/component/providers/device.d.ts +0 -67
  209. package/dist/component/providers/device.d.ts.map +0 -1
  210. package/dist/component/providers/email.d.ts +0 -62
  211. package/dist/component/providers/email.d.ts.map +0 -1
  212. package/dist/component/providers/oauth.d.ts +0 -25
  213. package/dist/component/providers/oauth.d.ts.map +0 -1
  214. package/dist/component/providers/oauth.js +0 -13
  215. package/dist/component/providers/oauth.js.map +0 -1
  216. package/dist/component/providers/passkey.d.ts +0 -57
  217. package/dist/component/providers/passkey.d.ts.map +0 -1
  218. package/dist/component/providers/password.d.ts +0 -88
  219. package/dist/component/providers/password.d.ts.map +0 -1
  220. package/dist/component/providers/phone.d.ts +0 -48
  221. package/dist/component/providers/phone.d.ts.map +0 -1
  222. package/dist/component/providers/sso.d.ts +0 -50
  223. package/dist/component/providers/sso.d.ts.map +0 -1
  224. package/dist/component/providers/totp.d.ts +0 -45
  225. package/dist/component/providers/totp.d.ts.map +0 -1
  226. package/dist/component/public/enterprise/audit.d.ts +0 -73
  227. package/dist/component/public/enterprise/audit.d.ts.map +0 -1
  228. package/dist/component/public/enterprise/audit.js.map +0 -1
  229. package/dist/component/public/enterprise/core.d.ts +0 -176
  230. package/dist/component/public/enterprise/core.d.ts.map +0 -1
  231. package/dist/component/public/enterprise/core.js +0 -292
  232. package/dist/component/public/enterprise/core.js.map +0 -1
  233. package/dist/component/public/enterprise/domains.d.ts +0 -174
  234. package/dist/component/public/enterprise/domains.d.ts.map +0 -1
  235. package/dist/component/public/enterprise/domains.js +0 -271
  236. package/dist/component/public/enterprise/domains.js.map +0 -1
  237. package/dist/component/public/enterprise/scim.d.ts +0 -245
  238. package/dist/component/public/enterprise/scim.d.ts.map +0 -1
  239. package/dist/component/public/enterprise/scim.js.map +0 -1
  240. package/dist/component/public/enterprise/secrets.d.ts +0 -78
  241. package/dist/component/public/enterprise/secrets.d.ts.map +0 -1
  242. package/dist/component/public/enterprise/secrets.js +0 -118
  243. package/dist/component/public/enterprise/secrets.js.map +0 -1
  244. package/dist/component/public/enterprise/webhooks.d.ts +0 -211
  245. package/dist/component/public/enterprise/webhooks.d.ts.map +0 -1
  246. package/dist/component/public/enterprise/webhooks.js.map +0 -1
  247. package/dist/component/public/factors/devices.d.ts +0 -157
  248. package/dist/component/public/factors/devices.d.ts.map +0 -1
  249. package/dist/component/public/factors/devices.js.map +0 -1
  250. package/dist/component/public/factors/passkeys.d.ts +0 -175
  251. package/dist/component/public/factors/passkeys.d.ts.map +0 -1
  252. package/dist/component/public/factors/passkeys.js.map +0 -1
  253. package/dist/component/public/factors/totp.d.ts +0 -189
  254. package/dist/component/public/factors/totp.d.ts.map +0 -1
  255. package/dist/component/public/factors/totp.js.map +0 -1
  256. package/dist/component/public/groups/core.d.ts +0 -137
  257. package/dist/component/public/groups/core.d.ts.map +0 -1
  258. package/dist/component/public/groups/core.js.map +0 -1
  259. package/dist/component/public/groups/invites.d.ts +0 -217
  260. package/dist/component/public/groups/invites.d.ts.map +0 -1
  261. package/dist/component/public/groups/invites.js.map +0 -1
  262. package/dist/component/public/groups/members.d.ts +0 -204
  263. package/dist/component/public/groups/members.d.ts.map +0 -1
  264. package/dist/component/public/groups/members.js.map +0 -1
  265. package/dist/component/public/identity/accounts.d.ts +0 -147
  266. package/dist/component/public/identity/accounts.d.ts.map +0 -1
  267. package/dist/component/public/identity/accounts.js.map +0 -1
  268. package/dist/component/public/identity/codes.d.ts +0 -104
  269. package/dist/component/public/identity/codes.d.ts.map +0 -1
  270. package/dist/component/public/identity/codes.js.map +0 -1
  271. package/dist/component/public/identity/sessions.d.ts +0 -128
  272. package/dist/component/public/identity/sessions.d.ts.map +0 -1
  273. package/dist/component/public/identity/sessions.js.map +0 -1
  274. package/dist/component/public/identity/tokens.d.ts +0 -169
  275. package/dist/component/public/identity/tokens.d.ts.map +0 -1
  276. package/dist/component/public/identity/tokens.js.map +0 -1
  277. package/dist/component/public/identity/users.d.ts +0 -212
  278. package/dist/component/public/identity/users.d.ts.map +0 -1
  279. package/dist/component/public/identity/users.js.map +0 -1
  280. package/dist/component/public/identity/verifiers.d.ts +0 -116
  281. package/dist/component/public/identity/verifiers.d.ts.map +0 -1
  282. package/dist/component/public/identity/verifiers.js.map +0 -1
  283. package/dist/component/public/security/keys.d.ts +0 -209
  284. package/dist/component/public/security/keys.d.ts.map +0 -1
  285. package/dist/component/public/security/keys.js.map +0 -1
  286. package/dist/component/public/security/limits.d.ts +0 -114
  287. package/dist/component/public/security/limits.d.ts.map +0 -1
  288. package/dist/component/public/security/limits.js.map +0 -1
  289. package/dist/component/public.d.ts +0 -28
  290. package/dist/component/public.d.ts.map +0 -1
  291. package/dist/component/schema.d.ts.map +0 -1
  292. package/dist/component/schema.js.map +0 -1
  293. package/dist/component/server/auth.d.ts +0 -447
  294. package/dist/component/server/auth.d.ts.map +0 -1
  295. package/dist/component/server/auth.js +0 -254
  296. package/dist/component/server/auth.js.map +0 -1
  297. package/dist/component/server/config.js +0 -121
  298. package/dist/component/server/config.js.map +0 -1
  299. package/dist/component/server/context.js +0 -53
  300. package/dist/component/server/context.js.map +0 -1
  301. package/dist/component/server/cookies.js +0 -47
  302. package/dist/component/server/cookies.js.map +0 -1
  303. package/dist/component/server/core.js +0 -576
  304. package/dist/component/server/core.js.map +0 -1
  305. package/dist/component/server/crypto.js +0 -56
  306. package/dist/component/server/crypto.js.map +0 -1
  307. package/dist/component/server/db.js +0 -87
  308. package/dist/component/server/db.js.map +0 -1
  309. package/dist/component/server/device.js +0 -152
  310. package/dist/component/server/device.js.map +0 -1
  311. package/dist/component/server/enterprise/config.js +0 -46
  312. package/dist/component/server/enterprise/config.js.map +0 -1
  313. package/dist/component/server/enterprise/domain.js +0 -974
  314. package/dist/component/server/enterprise/domain.js.map +0 -1
  315. package/dist/component/server/enterprise/http.js +0 -787
  316. package/dist/component/server/enterprise/http.js.map +0 -1
  317. package/dist/component/server/enterprise/oidc.js +0 -248
  318. package/dist/component/server/enterprise/oidc.js.map +0 -1
  319. package/dist/component/server/enterprise/policy.js +0 -85
  320. package/dist/component/server/enterprise/policy.js.map +0 -1
  321. package/dist/component/server/enterprise/saml.js.map +0 -1
  322. package/dist/component/server/enterprise/scim.js.map +0 -1
  323. package/dist/component/server/enterprise/shared.js +0 -51
  324. package/dist/component/server/enterprise/shared.js.map +0 -1
  325. package/dist/component/server/http.d.ts +0 -85
  326. package/dist/component/server/http.d.ts.map +0 -1
  327. package/dist/component/server/http.js +0 -351
  328. package/dist/component/server/http.js.map +0 -1
  329. package/dist/component/server/identity.js +0 -16
  330. package/dist/component/server/identity.js.map +0 -1
  331. package/dist/component/server/keys.js +0 -96
  332. package/dist/component/server/keys.js.map +0 -1
  333. package/dist/component/server/limits.js +0 -52
  334. package/dist/component/server/limits.js.map +0 -1
  335. package/dist/component/server/mutations/account.js +0 -46
  336. package/dist/component/server/mutations/account.js.map +0 -1
  337. package/dist/component/server/mutations/code.js +0 -68
  338. package/dist/component/server/mutations/code.js.map +0 -1
  339. package/dist/component/server/mutations/invalidate.js +0 -32
  340. package/dist/component/server/mutations/invalidate.js.map +0 -1
  341. package/dist/component/server/mutations/oauth.js +0 -116
  342. package/dist/component/server/mutations/oauth.js.map +0 -1
  343. package/dist/component/server/mutations/refresh.js +0 -119
  344. package/dist/component/server/mutations/refresh.js.map +0 -1
  345. package/dist/component/server/mutations/register.js +0 -87
  346. package/dist/component/server/mutations/register.js.map +0 -1
  347. package/dist/component/server/mutations/retrieve.js +0 -61
  348. package/dist/component/server/mutations/retrieve.js.map +0 -1
  349. package/dist/component/server/mutations/signature.js +0 -38
  350. package/dist/component/server/mutations/signature.js.map +0 -1
  351. package/dist/component/server/mutations/signin.js +0 -27
  352. package/dist/component/server/mutations/signin.js.map +0 -1
  353. package/dist/component/server/mutations/signout.js +0 -27
  354. package/dist/component/server/mutations/signout.js.map +0 -1
  355. package/dist/component/server/mutations/store/refs.js +0 -15
  356. package/dist/component/server/mutations/store/refs.js.map +0 -1
  357. package/dist/component/server/mutations/store.js +0 -70
  358. package/dist/component/server/mutations/store.js.map +0 -1
  359. package/dist/component/server/mutations/verifier.js +0 -18
  360. package/dist/component/server/mutations/verifier.js.map +0 -1
  361. package/dist/component/server/mutations/verify.js +0 -98
  362. package/dist/component/server/mutations/verify.js.map +0 -1
  363. package/dist/component/server/oauth.js +0 -242
  364. package/dist/component/server/oauth.js.map +0 -1
  365. package/dist/component/server/passkey.js +0 -415
  366. package/dist/component/server/passkey.js.map +0 -1
  367. package/dist/component/server/redirects.js +0 -40
  368. package/dist/component/server/redirects.js.map +0 -1
  369. package/dist/component/server/refresh.js +0 -99
  370. package/dist/component/server/refresh.js.map +0 -1
  371. package/dist/component/server/runtime.d.ts +0 -136
  372. package/dist/component/server/runtime.d.ts.map +0 -1
  373. package/dist/component/server/runtime.js +0 -456
  374. package/dist/component/server/runtime.js.map +0 -1
  375. package/dist/component/server/sessions.js +0 -71
  376. package/dist/component/server/sessions.js.map +0 -1
  377. package/dist/component/server/signin.js +0 -225
  378. package/dist/component/server/signin.js.map +0 -1
  379. package/dist/component/server/tokens.js +0 -17
  380. package/dist/component/server/tokens.js.map +0 -1
  381. package/dist/component/server/totp.js +0 -208
  382. package/dist/component/server/totp.js.map +0 -1
  383. package/dist/component/server/types.d.ts +0 -949
  384. package/dist/component/server/types.d.ts.map +0 -1
  385. package/dist/component/server/types.js +0 -79
  386. package/dist/component/server/types.js.map +0 -1
  387. package/dist/component/server/users.js +0 -123
  388. package/dist/component/server/users.js.map +0 -1
  389. package/dist/component/server/utils.js +0 -140
  390. package/dist/component/server/utils.js.map +0 -1
  391. package/dist/core/types.d.ts +0 -361
  392. package/dist/core/types.d.ts.map +0 -1
  393. package/dist/factors/device.js +0 -104
  394. package/dist/factors/device.js.map +0 -1
  395. package/dist/factors/passkey.js.map +0 -1
  396. package/dist/factors/totp.js.map +0 -1
  397. package/dist/providers/anonymous.d.ts.map +0 -1
  398. package/dist/providers/anonymous.js.map +0 -1
  399. package/dist/providers/credentials.d.ts.map +0 -1
  400. package/dist/providers/credentials.js.map +0 -1
  401. package/dist/providers/device.d.ts.map +0 -1
  402. package/dist/providers/device.js.map +0 -1
  403. package/dist/providers/email.d.ts.map +0 -1
  404. package/dist/providers/email.js.map +0 -1
  405. package/dist/providers/oauth.d.ts +0 -69
  406. package/dist/providers/oauth.d.ts.map +0 -1
  407. package/dist/providers/oauth.js +0 -43
  408. package/dist/providers/oauth.js.map +0 -1
  409. package/dist/providers/passkey.d.ts.map +0 -1
  410. package/dist/providers/passkey.js.map +0 -1
  411. package/dist/providers/password.d.ts.map +0 -1
  412. package/dist/providers/password.js.map +0 -1
  413. package/dist/providers/phone.d.ts.map +0 -1
  414. package/dist/providers/phone.js.map +0 -1
  415. package/dist/providers/sso.d.ts.map +0 -1
  416. package/dist/providers/sso.js.map +0 -1
  417. package/dist/providers/totp.d.ts.map +0 -1
  418. package/dist/providers/totp.js.map +0 -1
  419. package/dist/runtime/browser.js +0 -68
  420. package/dist/runtime/browser.js.map +0 -1
  421. package/dist/runtime/invite.js.map +0 -1
  422. package/dist/runtime/proxy.js +0 -70
  423. package/dist/runtime/proxy.js.map +0 -1
  424. package/dist/runtime/storage.js +0 -37
  425. package/dist/runtime/storage.js.map +0 -1
  426. package/dist/server/auth.d.ts.map +0 -1
  427. package/dist/server/auth.js.map +0 -1
  428. package/dist/server/config.d.ts +0 -1
  429. package/dist/server/config.js.map +0 -1
  430. package/dist/server/context.d.ts +0 -1
  431. package/dist/server/context.js.map +0 -1
  432. package/dist/server/cookies.d.ts +0 -1
  433. package/dist/server/cookies.js.map +0 -1
  434. package/dist/server/core.d.ts +0 -1315
  435. package/dist/server/core.d.ts.map +0 -1
  436. package/dist/server/core.js.map +0 -1
  437. package/dist/server/crypto.d.ts +0 -8
  438. package/dist/server/crypto.d.ts.map +0 -1
  439. package/dist/server/crypto.js.map +0 -1
  440. package/dist/server/db.d.ts +0 -1
  441. package/dist/server/db.js.map +0 -1
  442. package/dist/server/device.d.ts +0 -1
  443. package/dist/server/device.js.map +0 -1
  444. package/dist/server/enterprise/config.d.ts +0 -1
  445. package/dist/server/enterprise/config.js.map +0 -1
  446. package/dist/server/enterprise/domain.d.ts +0 -401
  447. package/dist/server/enterprise/domain.d.ts.map +0 -1
  448. package/dist/server/enterprise/domain.js +0 -974
  449. package/dist/server/enterprise/domain.js.map +0 -1
  450. package/dist/server/enterprise/http.d.ts +0 -26
  451. package/dist/server/enterprise/http.d.ts.map +0 -1
  452. package/dist/server/enterprise/http.js +0 -787
  453. package/dist/server/enterprise/http.js.map +0 -1
  454. package/dist/server/enterprise/oidc.d.ts +0 -1
  455. package/dist/server/enterprise/oidc.js +0 -248
  456. package/dist/server/enterprise/oidc.js.map +0 -1
  457. package/dist/server/enterprise/policy.d.ts +0 -1
  458. package/dist/server/enterprise/policy.js +0 -85
  459. package/dist/server/enterprise/policy.js.map +0 -1
  460. package/dist/server/enterprise/saml.d.ts +0 -1
  461. package/dist/server/enterprise/saml.js +0 -338
  462. package/dist/server/enterprise/saml.js.map +0 -1
  463. package/dist/server/enterprise/scim.d.ts +0 -1
  464. package/dist/server/enterprise/scim.js +0 -97
  465. package/dist/server/enterprise/scim.js.map +0 -1
  466. package/dist/server/enterprise/shared.d.ts +0 -5
  467. package/dist/server/enterprise/shared.d.ts.map +0 -1
  468. package/dist/server/enterprise/shared.js +0 -51
  469. package/dist/server/enterprise/shared.js.map +0 -1
  470. package/dist/server/enterprise/validators.d.ts +0 -1
  471. package/dist/server/enterprise/validators.js +0 -60
  472. package/dist/server/enterprise/validators.js.map +0 -1
  473. package/dist/server/http.d.ts.map +0 -1
  474. package/dist/server/http.js.map +0 -1
  475. package/dist/server/identity.d.ts +0 -1
  476. package/dist/server/identity.js.map +0 -1
  477. package/dist/server/keys.d.ts +0 -1
  478. package/dist/server/keys.js.map +0 -1
  479. package/dist/server/limits.d.ts +0 -1
  480. package/dist/server/limits.js.map +0 -1
  481. package/dist/server/mounts.d.ts.map +0 -1
  482. package/dist/server/mounts.js.map +0 -1
  483. package/dist/server/mutations/account.d.ts +0 -29
  484. package/dist/server/mutations/account.d.ts.map +0 -1
  485. package/dist/server/mutations/account.js.map +0 -1
  486. package/dist/server/mutations/code.d.ts +0 -30
  487. package/dist/server/mutations/code.d.ts.map +0 -1
  488. package/dist/server/mutations/code.js.map +0 -1
  489. package/dist/server/mutations/index.d.ts +0 -14
  490. package/dist/server/mutations/invalidate.d.ts +0 -20
  491. package/dist/server/mutations/invalidate.d.ts.map +0 -1
  492. package/dist/server/mutations/invalidate.js.map +0 -1
  493. package/dist/server/mutations/oauth.d.ts +0 -30
  494. package/dist/server/mutations/oauth.d.ts.map +0 -1
  495. package/dist/server/mutations/oauth.js.map +0 -1
  496. package/dist/server/mutations/refresh.d.ts +0 -21
  497. package/dist/server/mutations/refresh.d.ts.map +0 -1
  498. package/dist/server/mutations/refresh.js.map +0 -1
  499. package/dist/server/mutations/register.d.ts +0 -38
  500. package/dist/server/mutations/register.d.ts.map +0 -1
  501. package/dist/server/mutations/register.js.map +0 -1
  502. package/dist/server/mutations/retrieve.d.ts +0 -33
  503. package/dist/server/mutations/retrieve.d.ts.map +0 -1
  504. package/dist/server/mutations/retrieve.js.map +0 -1
  505. package/dist/server/mutations/signature.d.ts +0 -21
  506. package/dist/server/mutations/signature.d.ts.map +0 -1
  507. package/dist/server/mutations/signature.js.map +0 -1
  508. package/dist/server/mutations/signin.d.ts +0 -22
  509. package/dist/server/mutations/signin.d.ts.map +0 -1
  510. package/dist/server/mutations/signin.js.map +0 -1
  511. package/dist/server/mutations/signout.d.ts +0 -16
  512. package/dist/server/mutations/signout.d.ts.map +0 -1
  513. package/dist/server/mutations/signout.js.map +0 -1
  514. package/dist/server/mutations/store/refs.d.ts +0 -12
  515. package/dist/server/mutations/store/refs.d.ts.map +0 -1
  516. package/dist/server/mutations/store/refs.js.map +0 -1
  517. package/dist/server/mutations/store.d.ts +0 -306
  518. package/dist/server/mutations/store.d.ts.map +0 -1
  519. package/dist/server/mutations/store.js.map +0 -1
  520. package/dist/server/mutations/verifier.d.ts +0 -13
  521. package/dist/server/mutations/verifier.d.ts.map +0 -1
  522. package/dist/server/mutations/verifier.js.map +0 -1
  523. package/dist/server/mutations/verify.d.ts +0 -26
  524. package/dist/server/mutations/verify.d.ts.map +0 -1
  525. package/dist/server/mutations/verify.js.map +0 -1
  526. package/dist/server/oauth.d.ts +0 -1
  527. package/dist/server/oauth.js +0 -242
  528. package/dist/server/oauth.js.map +0 -1
  529. package/dist/server/passkey.d.ts +0 -27
  530. package/dist/server/passkey.d.ts.map +0 -1
  531. package/dist/server/passkey.js.map +0 -1
  532. package/dist/server/redirects.d.ts +0 -1
  533. package/dist/server/redirects.js.map +0 -1
  534. package/dist/server/refresh.d.ts +0 -1
  535. package/dist/server/refresh.js.map +0 -1
  536. package/dist/server/runtime.d.ts.map +0 -1
  537. package/dist/server/runtime.js.map +0 -1
  538. package/dist/server/sessions.d.ts +0 -1
  539. package/dist/server/sessions.js.map +0 -1
  540. package/dist/server/signin.d.ts +0 -1
  541. package/dist/server/signin.js.map +0 -1
  542. package/dist/server/ssr.d.ts.map +0 -1
  543. package/dist/server/ssr.js +0 -777
  544. package/dist/server/ssr.js.map +0 -1
  545. package/dist/server/templates.d.ts +0 -1
  546. package/dist/server/templates.js.map +0 -1
  547. package/dist/server/tokens.d.ts +0 -1
  548. package/dist/server/tokens.js.map +0 -1
  549. package/dist/server/totp.d.ts +0 -1
  550. package/dist/server/totp.js.map +0 -1
  551. package/dist/server/types.d.ts.map +0 -1
  552. package/dist/server/types.js.map +0 -1
  553. package/dist/server/users.d.ts +0 -1
  554. package/dist/server/users.js.map +0 -1
  555. package/dist/server/utils.d.ts +0 -1
  556. package/dist/server/utils.js +0 -140
  557. package/dist/server/utils.js.map +0 -1
  558. package/src/authorization/index.ts +0 -83
  559. package/src/cli/bin.ts +0 -5
  560. package/src/cli/command.ts +0 -70
  561. package/src/cli/index.ts +0 -1112
  562. package/src/cli/keys.ts +0 -23
  563. package/src/client/core/types.ts +0 -437
  564. package/src/client/factors/device.ts +0 -158
  565. package/src/client/factors/passkey.ts +0 -279
  566. package/src/client/factors/totp.ts +0 -150
  567. package/src/client/index.ts +0 -1124
  568. package/src/client/runtime/browser.ts +0 -112
  569. package/src/client/runtime/invite.ts +0 -63
  570. package/src/client/runtime/proxy.ts +0 -111
  571. package/src/client/runtime/storage.ts +0 -79
  572. package/src/component/_generated/api.ts +0 -96
  573. package/src/component/_generated/component.ts +0 -3774
  574. package/src/component/_generated/dataModel.ts +0 -60
  575. package/src/component/_generated/server.ts +0 -156
  576. package/src/component/convex.config.ts +0 -5
  577. package/src/component/functions.ts +0 -104
  578. package/src/component/index.ts +0 -42
  579. package/src/component/model.ts +0 -449
  580. package/src/component/public/enterprise/audit.ts +0 -125
  581. package/src/component/public/enterprise/core.ts +0 -355
  582. package/src/component/public/enterprise/domains.ts +0 -327
  583. package/src/component/public/enterprise/scim.ts +0 -397
  584. package/src/component/public/enterprise/secrets.ts +0 -133
  585. package/src/component/public/enterprise/webhooks.ts +0 -307
  586. package/src/component/public/factors/devices.ts +0 -224
  587. package/src/component/public/factors/passkeys.ts +0 -243
  588. package/src/component/public/factors/totp.ts +0 -259
  589. package/src/component/public/groups/core.ts +0 -481
  590. package/src/component/public/groups/invites.ts +0 -608
  591. package/src/component/public/groups/members.ts +0 -410
  592. package/src/component/public/identity/accounts.ts +0 -207
  593. package/src/component/public/identity/codes.ts +0 -149
  594. package/src/component/public/identity/sessions.ts +0 -210
  595. package/src/component/public/identity/tokens.ts +0 -251
  596. package/src/component/public/identity/users.ts +0 -355
  597. package/src/component/public/identity/verifiers.ts +0 -158
  598. package/src/component/public/security/keys.ts +0 -366
  599. package/src/component/public/security/limits.ts +0 -174
  600. package/src/component/public.ts +0 -27
  601. package/src/component/schema.ts +0 -505
  602. package/src/providers/anonymous.ts +0 -99
  603. package/src/providers/credentials.ts +0 -102
  604. package/src/providers/device.ts +0 -87
  605. package/src/providers/email.ts +0 -99
  606. package/src/providers/index.ts +0 -31
  607. package/src/providers/oauth.ts +0 -117
  608. package/src/providers/passkey.ts +0 -77
  609. package/src/providers/password.ts +0 -441
  610. package/src/providers/phone.ts +0 -93
  611. package/src/providers/sso.ts +0 -54
  612. package/src/providers/totp.ts +0 -62
  613. package/src/samlify.d.ts +0 -53
  614. package/src/server/auth.ts +0 -949
  615. package/src/server/config.ts +0 -200
  616. package/src/server/context.ts +0 -90
  617. package/src/server/cookies.ts +0 -49
  618. package/src/server/core.ts +0 -2004
  619. package/src/server/crypto.ts +0 -90
  620. package/src/server/db.ts +0 -203
  621. package/src/server/device.ts +0 -254
  622. package/src/server/enterprise/config.ts +0 -51
  623. package/src/server/enterprise/domain.ts +0 -1739
  624. package/src/server/enterprise/http.ts +0 -1331
  625. package/src/server/enterprise/oidc.ts +0 -500
  626. package/src/server/enterprise/policy.ts +0 -128
  627. package/src/server/enterprise/saml.ts +0 -578
  628. package/src/server/enterprise/scim.ts +0 -135
  629. package/src/server/enterprise/shared.ts +0 -134
  630. package/src/server/enterprise/validators.ts +0 -93
  631. package/src/server/http.ts +0 -790
  632. package/src/server/identity.ts +0 -18
  633. package/src/server/index.ts +0 -40
  634. package/src/server/keys.ts +0 -158
  635. package/src/server/limits.ts +0 -107
  636. package/src/server/mounts.ts +0 -924
  637. package/src/server/mutations/account.ts +0 -62
  638. package/src/server/mutations/code.ts +0 -119
  639. package/src/server/mutations/index.ts +0 -13
  640. package/src/server/mutations/invalidate.ts +0 -50
  641. package/src/server/mutations/oauth.ts +0 -243
  642. package/src/server/mutations/refresh.ts +0 -299
  643. package/src/server/mutations/register.ts +0 -155
  644. package/src/server/mutations/retrieve.ts +0 -109
  645. package/src/server/mutations/signature.ts +0 -57
  646. package/src/server/mutations/signin.ts +0 -54
  647. package/src/server/mutations/signout.ts +0 -43
  648. package/src/server/mutations/store/refs.ts +0 -10
  649. package/src/server/mutations/store.ts +0 -123
  650. package/src/server/mutations/verifier.ts +0 -34
  651. package/src/server/mutations/verify.ts +0 -200
  652. package/src/server/oauth.ts +0 -418
  653. package/src/server/passkey.ts +0 -838
  654. package/src/server/redirects.ts +0 -59
  655. package/src/server/refresh.ts +0 -218
  656. package/src/server/runtime.ts +0 -918
  657. package/src/server/sessions.ts +0 -132
  658. package/src/server/signin.ts +0 -445
  659. package/src/server/ssr.ts +0 -1747
  660. package/src/server/templates.ts +0 -82
  661. package/src/server/tokens.ts +0 -35
  662. package/src/server/totp.ts +0 -399
  663. package/src/server/types.ts +0 -1942
  664. package/src/server/users.ts +0 -291
  665. package/src/server/utils.ts +0 -220
  666. /package/dist/{runtime → client/runtime}/invite.js +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"file":"core.js","names":[],"sources":["../../../src/server/core.ts"],"sourcesContent":["import { Cv } from \"@robelest/fx/convex\";\nimport { Auth, GenericActionCtx, GenericDataModel } from \"convex/server\";\nimport { GenericId } from \"convex/values\";\n\nimport { materializeProvider } from \"./config\";\nimport { getSessionUserId } from \"./context\";\nimport {\n buildScopeChecker,\n checkKeyRateLimit,\n generateApiKey,\n hashApiKey,\n} from \"./keys\";\nimport { signInImpl } from \"./signin\";\nimport type {\n AuthProviderConfig,\n KeyDoc,\n KeyScope,\n ScopeChecker,\n UserOrderBy,\n UserWhere,\n} from \"./types\";\nimport { generateRandomString, sha256, TOKEN_SUB_CLAIM_DIVIDER } from \"./utils\";\n\ntype ComponentCtx = Pick<\n GenericActionCtx<GenericDataModel>,\n \"runQuery\" | \"runMutation\"\n>;\ntype ComponentReadCtx = Pick<GenericActionCtx<GenericDataModel>, \"runQuery\">;\ntype ComponentAuthReadCtx = ComponentReadCtx & { auth: Auth };\ntype AccountCredentials = { id: string; secret?: string };\ntype CreateAccountArgs = {\n provider: string;\n account: AccountCredentials;\n profile: Record<string, unknown>;\n shouldLinkViaEmail?: boolean;\n shouldLinkViaPhone?: boolean;\n};\ntype RetrieveAccountArgs = { provider: string; account: AccountCredentials };\ntype UpdateAccountCredentialsArgs = {\n provider: string;\n account: { id: string; secret: string };\n};\n\ntype CoreDeps = {\n config: any;\n getAuth: () => any;\n callInvalidateSessions: <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n args: { userId: GenericId<\"User\">; except?: GenericId<\"Session\">[] },\n ) => Promise<void>;\n callCreateAccountFromCredentials: <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n args: CreateAccountArgs,\n ) => Promise<any>;\n callRetrieveAccountWithCredentials: <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n args: RetrieveAccountArgs,\n ) => Promise<any>;\n callModifyAccount: <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n args: UpdateAccountCredentialsArgs,\n ) => Promise<void>;\n getEnrichCtx: () => <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n ) => any;\n inviteTokenAlphabet: string;\n inviteTokenLength: number;\n};\n\n/**\n * Build the core auth domains that back the canonical app API surface.\n *\n * Creates the grouped `user`, `session`, `account`, `provider`, `group`,\n * `member`, `invite`, and `key` APIs used by the higher-level auth\n * factory. Each namespace wraps the underlying Convex component functions with\n * application-friendly helpers, result shaping, and documentation-friendly\n * method names.\n *\n * @param deps - Internal component wiring, provider config, and helper\n * functions needed to construct the domain API surface.\n * @returns The core domain namespaces consumed by the auth factory.\n */\nexport function createCoreDomains(deps: CoreDeps) {\n const {\n config,\n getAuth,\n callInvalidateSessions,\n callCreateAccountFromCredentials,\n callRetrieveAccountWithCredentials,\n callModifyAccount,\n getEnrichCtx,\n inviteTokenAlphabet,\n inviteTokenLength,\n } = deps;\n\n const roleDefinitions = config.authorization.roles as Record<\n string,\n { label?: string; grants: string[] }\n >;\n\n const getRoleDefinition = (roleId: string) => {\n return roleDefinitions[roleId] ?? null;\n };\n\n const normalizeRoleIds = (roleIds?: string[]): string[] => {\n const normalized = Array.from(new Set(roleIds ?? []));\n const invalid = normalized.filter((id) => getRoleDefinition(id) === null);\n if (invalid.length > 0) {\n throw Cv.error({\n code: \"INVALID_ROLE_IDS\",\n message: \"One or more role IDs are invalid.\",\n invalidRoleIds: invalid,\n });\n }\n return normalized;\n };\n\n const listAllKeysByUser = async (ctx: ComponentCtx, userId: string) => {\n const items: Array<{ _id: string }> = [];\n let cursor: string | null = null;\n do {\n const page = (await ctx.runQuery(config.component.public.keyList, {\n where: { userId },\n limit: 100,\n cursor,\n })) as {\n items: Array<{ _id: string }>;\n nextCursor: string | null;\n };\n items.push(...page.items);\n cursor = page.nextCursor;\n } while (cursor !== null);\n return items;\n };\n\n const listAllMembersByUser = async (ctx: ComponentCtx, userId: string) => {\n const items: Array<{ _id: string }> = [];\n let cursor: string | null = null;\n do {\n const page = (await ctx.runQuery(config.component.public.memberList, {\n where: { userId },\n limit: 100,\n cursor,\n })) as {\n items: Array<{ _id: string }>;\n nextCursor: string | null;\n };\n items.push(...page.items);\n cursor = page.nextCursor;\n } while (cursor !== null);\n return items;\n };\n\n const resolveGrantedPermissions = (roleIds?: string[]) => {\n const grants = new Set<string>();\n for (const roleId of roleIds ?? []) {\n const role = getRoleDefinition(roleId);\n if (role === null) continue;\n for (const grant of role.grants) {\n grants.add(grant);\n }\n }\n return Array.from(grants).sort();\n };\n\n // Per-execution cache — attached to ctx so each function invocation has its own.\n // Eliminates redundant cross-component RPCs for the same entity within a handler.\n type CtxCache = {\n users: Map<string, any>;\n groups: Map<string, any>;\n };\n const AUTH_CACHE = Symbol(\"__convexAuthCache\");\n function cache(ctx: any): CtxCache {\n if (!ctx[AUTH_CACHE]) {\n ctx[AUTH_CACHE] = {\n users: new Map(),\n groups: new Map(),\n } satisfies CtxCache;\n }\n return ctx[AUTH_CACHE];\n }\n\n const user = {\n /**\n * Fetch a user document by ID.\n *\n * Results are **cached per-execution** — calling `auth.user.get(ctx, id)`\n * multiple times within the same query or mutation handler for the same\n * `userId` returns the cached result without an additional component read.\n *\n * @param ctx - Convex query or mutation context.\n * @param userId - The user's document ID.\n * @returns The user document, or `null` if not found.\n *\n * @example\n * ```ts\n * const user = await auth.user.get(ctx, userId);\n * const name = user?.name ?? user?.email ?? \"Unknown\";\n * ```\n */\n get: async (ctx: ComponentReadCtx, userId: string) => {\n const c = cache(ctx);\n if (c.users.has(userId)) return c.users.get(userId);\n const result = await ctx.runQuery(config.component.public.userGetById, {\n userId,\n });\n c.users.set(userId, result);\n return result;\n },\n /**\n * List users with optional filtering, pagination, and ordering.\n *\n * Supports filtering by `email`, `phone`, `name`, and `isAnonymous`.\n * Results are paginated — pass `cursor` from a previous response to\n * load the next page.\n *\n * @param ctx - Convex query or mutation context.\n * @param opts.where - Filter criteria (all optional, combined with AND).\n * @param opts.limit - Max items per page (default 50, max 100).\n * @param opts.cursor - Cursor from a previous `nextCursor` for pagination.\n * @param opts.orderBy - Sort field: `\"_creationTime\"` (default), `\"email\"`, etc.\n * @param opts.order - Sort direction: `\"asc\"` or `\"desc\"` (default `\"desc\"`).\n * @returns `{ items, nextCursor }` — `nextCursor` is `null` when no more pages.\n *\n * @example\n * ```ts\n * const { items, nextCursor } = await auth.user.list(ctx, {\n * where: { email: \"alice@example.com\" },\n * limit: 10,\n * });\n * ```\n */\n list: async (\n ctx: ComponentReadCtx,\n opts: {\n where?: UserWhere;\n limit?: number;\n cursor?: string | null;\n orderBy?: UserOrderBy;\n order?: \"asc\" | \"desc\";\n } = {},\n ) => {\n return await ctx.runQuery(config.component.public.userList, opts);\n },\n /**\n * Convenience method: resolve the current session user and fetch their\n * full document in one call. Returns `null` if unauthenticated.\n *\n * @param ctx - Convex query or mutation context with `auth` for session lookup.\n * @returns The authenticated user's document, or `null` if unauthenticated.\n *\n * @example\n * ```ts\n * const viewer = await auth.user.viewer(ctx);\n * if (!viewer) throw new Error(\"Not signed in\");\n * console.log(viewer.name, viewer.email);\n * ```\n */\n viewer: async (ctx: ComponentAuthReadCtx) => {\n const userId = await getSessionUserId(ctx);\n if (userId === null) return null;\n return await user.get(ctx, userId);\n },\n /**\n * Patch a user document. Accepts any fields defined on the User schema\n * (e.g. `name`, `image`, `email`, `extend`).\n *\n * @param ctx - Convex mutation context.\n * @param userId - The user's document ID.\n * @param data - Fields to merge into the user document.\n * @returns `{ userId }`.\n *\n * @example\n * ```ts\n * await auth.user.update(ctx, userId, {\n * name: \"Alice Smith\",\n * image: \"https://example.com/avatar.png\",\n * });\n * ```\n */\n update: async (\n ctx: ComponentCtx,\n userId: string,\n data: Record<string, unknown>,\n ) => {\n await ctx.runMutation(config.component.public.userPatch, {\n userId,\n data,\n });\n return { userId };\n },\n /**\n * Set the user's active group. Stored in `user.extend.lastActiveGroup`.\n * Pass `groupId: null` to clear. Useful for multi-workspace apps\n * where the UI needs to remember which workspace is selected.\n *\n * @param ctx - Convex mutation context.\n * @param opts.userId - The user's document ID.\n * @param opts.groupId - Group ID to set as active, or `null` to clear.\n * @returns `{ userId, groupId }` confirming the active group was set (or cleared).\n *\n * @example\n * ```ts\n * // Switch to a workspace\n * await auth.user.setActiveGroup(ctx, { userId, groupId: workspaceId });\n *\n * // Clear the active workspace\n * await auth.user.setActiveGroup(ctx, { userId, groupId: null });\n * ```\n */\n setActiveGroup: async (\n ctx: ComponentCtx,\n opts: { userId: string; groupId: string | null },\n ) => {\n const doc = await user.get(ctx, opts.userId);\n const existingExtend =\n doc !== null &&\n doc.extend !== null &&\n typeof doc.extend === \"object\" &&\n !Array.isArray(doc.extend)\n ? { ...(doc.extend as Record<string, unknown>) }\n : {};\n if (opts.groupId === null) {\n const { lastActiveGroup: _omit, ...rest } = existingExtend;\n await user.update(ctx, opts.userId, { extend: rest });\n return { userId: opts.userId, groupId: null };\n }\n await user.update(ctx, opts.userId, {\n extend: { ...existingExtend, lastActiveGroup: opts.groupId },\n });\n return { userId: opts.userId, groupId: opts.groupId };\n },\n /**\n * Read the user's active group ID from `user.extend.lastActiveGroup`.\n * Returns `null` if no active group is set.\n *\n * @param ctx - Convex query or mutation context.\n * @param opts.userId - The user's document ID.\n * @returns The active group's document ID, or `null` if none is set.\n *\n * @example\n * ```ts\n * const activeGroupId = await auth.user.getActiveGroup(ctx, { userId });\n * if (activeGroupId) {\n * const group = await auth.group.get(ctx, activeGroupId);\n * }\n * ```\n */\n getActiveGroup: async (\n ctx: ComponentReadCtx,\n opts: { userId: string },\n ): Promise<string | null> => {\n const doc = await user.get(ctx, opts.userId);\n if (\n doc !== null &&\n doc.extend !== null &&\n typeof doc.extend === \"object\" &&\n !Array.isArray(doc.extend)\n ) {\n const val = (doc.extend as Record<string, unknown>).lastActiveGroup;\n if (typeof val === \"string\") return val;\n }\n return null;\n },\n /**\n * Delete a user and all associated data.\n *\n * By default (`cascade: true`) deletes the user's sessions, accounts,\n * API keys, group memberships, passkey credentials, and TOTP factors.\n * Pass `{ cascade: false }` to delete only the user document itself.\n *\n * @param ctx - Convex mutation context.\n * @param userId - The user's document ID.\n * @param opts.cascade - Whether to delete related records (default `true`).\n * @returns `{ userId }`.\n * @throws `INVALID_PARAMETERS` if `cascade` is `false` but the user has linked data.\n */\n delete: async (\n ctx: ComponentCtx,\n userId: string,\n opts?: { cascade?: boolean },\n ) => {\n const cascade = opts?.cascade !== false;\n const [sessions, accounts, keys, members, passkeys, totps] =\n await Promise.all([\n ctx.runQuery(config.component.public.sessionListByUser, {\n userId,\n }) as Promise<Array<{ _id: string }>>,\n ctx.runQuery(config.component.public.accountListByUser, {\n userId,\n }) as Promise<Array<{ _id: string }>>,\n listAllKeysByUser(ctx, userId),\n listAllMembersByUser(ctx, userId),\n ctx.runQuery(config.component.public.passkeyListByUserId, {\n userId,\n }) as Promise<Array<{ _id: string }>>,\n ctx.runQuery(config.component.public.totpListByUserId, {\n userId,\n }) as Promise<Array<{ _id: string }>>,\n ]);\n const totalLinked =\n sessions.length +\n accounts.length +\n keys.length +\n members.length +\n passkeys.length +\n totps.length;\n if (!cascade && totalLinked > 0) {\n throw Cv.error({\n code: \"INVALID_PARAMETERS\",\n message: \"The provided parameters are invalid.\",\n });\n }\n const deletions: Promise<unknown>[] = [];\n for (const s of sessions)\n deletions.push(\n ctx.runMutation(config.component.public.sessionDelete, {\n sessionId: s._id,\n }),\n );\n for (const a of accounts)\n deletions.push(\n ctx.runMutation(config.component.public.accountDelete, {\n accountId: a._id,\n }),\n );\n for (const k of keys)\n deletions.push(\n ctx.runMutation(config.component.public.keyDelete, { keyId: k._id }),\n );\n for (const m of members)\n deletions.push(\n ctx.runMutation(config.component.public.memberRemove, {\n memberId: m._id,\n }),\n );\n for (const p of passkeys)\n deletions.push(\n ctx.runMutation(config.component.public.passkeyDelete, {\n passkeyId: p._id,\n }),\n );\n for (const t of totps)\n deletions.push(\n ctx.runMutation(config.component.public.totpDelete, {\n totpId: t._id,\n }),\n );\n await Promise.all(deletions);\n await ctx.runMutation(config.component.public.userDelete, { userId });\n return { userId };\n },\n };\n\n const session = {\n /**\n * Resolve the current session's ID from the JWT.\n *\n * Extracts the `sessionId` portion of the `subject` claim in the\n * identity token returned by `ctx.auth.getUserIdentity()`. The subject\n * is encoded as `userId<divider>sessionId`, so this splits on the\n * divider and returns the second segment.\n *\n * Returns `null` when there is no authenticated identity (i.e. no\n * valid session JWT).\n *\n * @param ctx - Convex query, mutation, or action context (must include `auth`).\n * @returns The current session's document ID, or `null` if unauthenticated.\n *\n * @example\n * ```ts\n * const sessionId = await auth.session.current(ctx);\n * if (!sessionId) throw new Error(\"Not signed in\");\n * ```\n */\n current: async (ctx: { auth: Auth }) => {\n const identity = await ctx.auth.getUserIdentity();\n if (identity === null) return null;\n const [, sessionId] = identity.subject.split(TOKEN_SUB_CLAIM_DIVIDER);\n return sessionId as GenericId<\"Session\">;\n },\n /**\n * Invalidate (sign out) all sessions for a given user.\n *\n * Marks every session belonging to `userId` as invalid so that\n * subsequent requests using those session JWTs will fail authentication.\n * Optionally, one or more sessions can be excluded — this is useful\n * when you want to sign out all *other* devices while keeping the\n * current session alive.\n *\n * This method delegates to the component's internal session\n * invalidation RPC.\n *\n * @param ctx - Convex action context.\n * @param args.userId - The user whose sessions should be invalidated.\n * @param args.except - Optional array of session IDs to keep valid.\n * @returns `{ userId, except }` confirming the operation.\n *\n * @example Sign out everywhere except the current session\n * ```ts\n * const sessionId = await auth.session.current(ctx);\n * await auth.session.invalidate(ctx, {\n * userId,\n * except: sessionId ? [sessionId] : [],\n * });\n * ```\n */\n invalidate: async <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n args: { userId: GenericId<\"User\">; except?: GenericId<\"Session\">[] },\n ) => {\n await callInvalidateSessions(ctx, args);\n return {\n userId: args.userId,\n except: args.except ?? [],\n };\n },\n /**\n * Fetch a session document by ID.\n *\n * Returns the full session document from the component database, or\n * `null` if no session with the given ID exists. Useful for inspecting\n * session metadata such as creation time or associated device info.\n *\n * @param ctx - Convex query or mutation context.\n * @param sessionId - The session's document ID.\n * @returns The session document, or `null` if not found.\n *\n * @example\n * ```ts\n * const session = await auth.session.get(ctx, sessionId);\n * if (!session) throw new Error(\"Session not found\");\n * ```\n */\n get: async (ctx: ComponentReadCtx, sessionId: string) => {\n return await ctx.runQuery(config.component.public.sessionGetById, {\n sessionId,\n });\n },\n /**\n * List all sessions belonging to a user.\n *\n * Returns every session document associated with the given `userId`,\n * including both active and expired sessions. This is useful for\n * building \"active sessions\" UIs or auditing sign-in history.\n *\n * @param ctx - Convex query or mutation context.\n * @param opts.userId - The user whose sessions to list.\n * @returns An array of session documents.\n *\n * @example\n * ```ts\n * const sessions = await auth.session.list(ctx, { userId });\n * console.log(`User has ${sessions.length} sessions`);\n * ```\n */\n list: async (ctx: ComponentReadCtx, opts: { userId: string }) => {\n return await ctx.runQuery(config.component.public.sessionListByUser, {\n userId: opts.userId,\n });\n },\n };\n\n const account = {\n /**\n * Create a new auth account linked to a user.\n *\n * Creates a credentials-based account record for a given provider. If\n * the user does not yet exist, one is created from the supplied\n * `profile`. If `shouldLinkViaEmail` or `shouldLinkViaPhone` is set,\n * the account may be linked to an existing user whose email or phone\n * matches the profile.\n *\n * The `account.secret` (e.g. a hashed password) is optional and\n * depends on the provider type.\n *\n * @param ctx - Convex action context.\n * @param args.provider - The provider ID (e.g. `\"password\"`, `\"credentials\"`).\n * @param args.account.id - Provider-specific account identifier (e.g. email address).\n * @param args.account.secret - Optional credential secret (e.g. hashed password).\n * @param args.profile - Profile data used to create or update the user document.\n * @param args.shouldLinkViaEmail - If `true`, link to an existing user by email match.\n * @param args.shouldLinkViaPhone - If `true`, link to an existing user by phone match.\n * @returns The created account and user information.\n *\n * @example\n * ```ts\n * const result = await auth.account.create(ctx, {\n * provider: \"password\",\n * account: { id: \"alice@example.com\", secret: hashedPassword },\n * profile: { email: \"alice@example.com\", name: \"Alice\" },\n * });\n * ```\n */\n create: async <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n args: CreateAccountArgs,\n ) => {\n const created = await callCreateAccountFromCredentials(ctx, args);\n return { ...created };\n },\n /**\n * Retrieve an auth account by provider and credentials.\n *\n * Looks up an account matching the given provider and account ID,\n * optionally verifying the secret (e.g. password). If the account\n * exists and the credentials are valid, the full account document is\n * returned. Returns `null` if no matching account is found or if the\n * credential verification fails (indicated by a string error from the\n * underlying RPC).\n *\n * @param ctx - Convex action context.\n * @param args.provider - The provider ID (e.g. `\"password\"`).\n * @param args.account.id - Provider-specific account identifier.\n * @param args.account.secret - Optional credential secret to verify.\n * @returns The account document, or `null` if not found or verification failed.\n *\n * @example\n * ```ts\n * const acct = await auth.account.get(ctx, {\n * provider: \"password\",\n * account: { id: \"alice@example.com\", secret: plainTextPassword },\n * });\n * if (!acct) throw new Error(\"Invalid credentials\");\n * ```\n */\n get: async <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n args: RetrieveAccountArgs,\n ) => {\n const result = await callRetrieveAccountWithCredentials(ctx, args);\n if (typeof result === \"string\") {\n return null;\n }\n return result;\n },\n /**\n * Update the credentials (secret) for an existing auth account.\n *\n * Replaces the stored secret for the account identified by `provider`\n * and `account.id`. This is the standard path for password changes\n * and password resets — the new secret is typically a freshly hashed\n * password.\n *\n * @param ctx - Convex action context.\n * @param args.provider - The provider ID (e.g. `\"password\"`).\n * @param args.account.id - Provider-specific account identifier.\n * @param args.account.secret - The new credential secret to store.\n * @returns `{ accountId }` confirming the update.\n *\n * @example Password reset\n * ```ts\n * await auth.account.update(ctx, {\n * provider: \"password\",\n * account: { id: \"alice@example.com\", secret: newHashedPassword },\n * });\n * ```\n */\n update: async <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n args: UpdateAccountCredentialsArgs,\n ) => {\n await callModifyAccount(ctx, args);\n return { accountId: args.account.id };\n },\n /**\n * Delete an auth account by ID.\n *\n * Removes the account record from the database. As a safety measure,\n * deletion is **refused** if this is the user's only remaining account\n * — the user must always have at least one linked account. If the\n * account is not found, returns an error result instead of throwing.\n *\n * @param ctx - Convex mutation context.\n * @param accountId - The account's document ID.\n * @returns `{ accountId }` on success.\n * @throws `ACCOUNT_NOT_FOUND` if the account does not exist.\n * @throws `INVALID_PARAMETERS` if it is the user's last account.\n *\n * @example\n * ```ts\n * await auth.account.delete(ctx, accountId);\n * ```\n */\n delete: async (ctx: ComponentCtx, accountId: string) => {\n const doc = await ctx.runQuery(config.component.public.accountGetById, {\n accountId,\n });\n if (doc === null) {\n throw Cv.error({\n code: \"ACCOUNT_NOT_FOUND\",\n message: \"Account not found.\",\n });\n }\n const allAccounts = (await ctx.runQuery(\n config.component.public.accountListByUser,\n { userId: (doc as any).userId },\n )) as Array<{ _id: string }>;\n if (allAccounts.length <= 1) {\n throw Cv.error({\n code: \"INVALID_PARAMETERS\",\n message: \"The provided parameters are invalid.\",\n });\n }\n await ctx.runMutation(config.component.public.accountDelete, {\n accountId,\n });\n return { accountId };\n },\n /**\n * List all passkey credentials registered for a user.\n *\n * Returns every WebAuthn passkey credential associated with the given\n * `userId`. Each document includes the credential's public key,\n * metadata (such as a human-readable name), and counters used for\n * replay protection.\n *\n * @param ctx - Convex query or mutation context.\n * @param opts.userId - The user whose passkeys to list.\n * @returns An array of passkey credential documents.\n *\n * @example\n * ```ts\n * const passkeys = await auth.account.listPasskeys(ctx, { userId });\n * for (const pk of passkeys) {\n * console.log(pk.name ?? \"Unnamed passkey\", pk._id);\n * }\n * ```\n */\n listPasskeys: async (ctx: ComponentReadCtx, opts: { userId: string }) => {\n return await ctx.runQuery(\n config.component.public.passkeyListByUserId,\n opts,\n );\n },\n /**\n * Rename a passkey credential.\n *\n * Updates the human-readable `name` metadata on a passkey document.\n * Useful for letting users label their passkeys (e.g. \"MacBook Pro\",\n * \"YubiKey 5\").\n *\n * @param ctx - Convex mutation context.\n * @param passkeyId - The passkey credential's document ID.\n * @param name - The new display name for the passkey.\n * @returns `{ passkeyId }` confirming the rename.\n *\n * @example\n * ```ts\n * await auth.account.renamePasskey(ctx, passkeyId, \"Work laptop\");\n * ```\n */\n renamePasskey: async (\n ctx: ComponentCtx,\n passkeyId: string,\n name: string,\n ) => {\n await ctx.runMutation(config.component.public.passkeyUpdateMeta, {\n passkeyId,\n data: { name },\n });\n return { passkeyId };\n },\n /**\n * Delete a passkey credential.\n *\n * Permanently removes a WebAuthn passkey credential from the database.\n * After deletion, the physical authenticator associated with this\n * credential can no longer be used to sign in.\n *\n * @param ctx - Convex mutation context.\n * @param passkeyId - The passkey credential's document ID.\n * @returns `{ passkeyId }` confirming the deletion.\n *\n * @example\n * ```ts\n * await auth.account.deletePasskey(ctx, passkeyId);\n * ```\n */\n deletePasskey: async (ctx: ComponentCtx, passkeyId: string) => {\n await ctx.runMutation(config.component.public.passkeyDelete, {\n passkeyId,\n });\n return { passkeyId };\n },\n /**\n * List all TOTP (time-based one-time password) factors for a user.\n *\n * Returns every TOTP authenticator factor registered for the given\n * `userId`. Each document includes the secret, issuer, and verification\n * metadata needed for two-factor authentication management UIs.\n *\n * @param ctx - Convex query or mutation context.\n * @param opts.userId - The user whose TOTP factors to list.\n * @returns An array of TOTP factor documents.\n *\n * @example\n * ```ts\n * const totps = await auth.account.listTotps(ctx, { userId });\n * const has2FA = totps.length > 0;\n * ```\n */\n listTotps: async (ctx: ComponentReadCtx, opts: { userId: string }) => {\n return await ctx.runQuery(config.component.public.totpListByUserId, opts);\n },\n /**\n * Delete a TOTP factor.\n *\n * Permanently removes a TOTP authenticator factor from the database.\n * After deletion, codes generated by the corresponding authenticator\n * app will no longer be accepted for two-factor authentication.\n *\n * @param ctx - Convex mutation context.\n * @param totpId - The TOTP factor's document ID.\n * @returns `{ totpId }` confirming the deletion.\n *\n * @example\n * ```ts\n * await auth.account.deleteTotp(ctx, totpId);\n * ```\n */\n deleteTotp: async (ctx: ComponentCtx, totpId: string) => {\n await ctx.runMutation(config.component.public.totpDelete, { totpId });\n return { totpId };\n },\n };\n\n const provider = {\n /**\n * Sign in through a specific provider from server-side code.\n *\n * Materializes the supplied provider config, runs the standard sign-in\n * flow, and returns the resulting `userId` and `sessionId` when the\n * provider completes authentication immediately. Returns `null` for\n * providers that require additional client-side steps (for example\n * redirects, email verification, or other non-immediate flows).\n *\n * This helper is useful for trusted server flows where you already know\n * which provider should handle the sign-in and want the same behavior as\n * the public auth API without generating tokens for the client.\n *\n * @param ctx - Convex action context.\n * @param providerConfig - Provider configuration object to materialize and use.\n * @param args.accountId - Optional account document ID to sign in with directly.\n * @param args.params - Optional provider-specific parameters forwarded to the sign-in flow.\n * @returns `{ userId, sessionId }` when sign-in succeeds immediately, or `null`\n * when the provider does not produce an immediate signed-in result.\n *\n * @example\n * ```ts\n * const signedIn = await auth.provider.signIn(ctx, passwordProvider, {\n * params: { email: \"alice@example.com\", password: \"secret\" },\n * });\n *\n * if (!signedIn) {\n * throw new Error(\"Provider requires another auth step\");\n * }\n * ```\n */\n signIn: async <DataModel extends GenericDataModel>(\n ctx: GenericActionCtx<DataModel>,\n providerConfig: AuthProviderConfig,\n args: {\n accountId?: GenericId<\"Account\">;\n params?: Record<string, unknown>;\n },\n ) => {\n const result = await signInImpl(\n getEnrichCtx()(ctx),\n materializeProvider(providerConfig),\n args as {\n accountId?: GenericId<\"Account\">;\n params?: Record<string, any>;\n },\n { generateTokens: false, allowExtraProviders: true },\n );\n return result.kind === \"signedIn\"\n ? result.signedIn !== null\n ? {\n userId: result.signedIn.userId,\n sessionId: result.signedIn.sessionId,\n }\n : null\n : null;\n },\n };\n\n const group = {\n /**\n * Create a new group (organization, workspace, team, etc.).\n *\n * Groups are hierarchical — set `parentGroupId` to nest under an existing\n * group, or omit it to create a root-level group. Two denormalized fields\n * are maintained automatically:\n *\n * - `rootGroupId` — the root ancestor (self-referencing for root groups).\n * - `isRoot` — `true` when the group has no parent.\n *\n * @param ctx - Convex mutation context.\n * @param data.name - Display name for the group.\n * @param data.slug - URL-safe slug (optional).\n * @param data.type - App-defined type string (e.g. `\"workspace\"`, `\"team\"`).\n * @param data.parentGroupId - Nest under this group. Omit for a root group.\n * @param data.tags - Faceted classification tags (normalized at write time).\n * @param data.extend - Arbitrary app-specific metadata.\n * @returns `{ groupId }`.\n *\n * @example Root group\n * ```ts\n * const { groupId } = await auth.group.create(ctx, {\n * name: \"Acme Corp\", type: \"workspace\",\n * });\n * ```\n *\n * @example Nested team\n * ```ts\n * const { groupId } = await auth.group.create(ctx, {\n * name: \"Engineering\", parentGroupId: orgId, type: \"team\",\n * });\n * ```\n */\n create: async (\n ctx: ComponentCtx,\n data: {\n name: string;\n slug?: string;\n type?: string;\n parentGroupId?: string;\n tags?: Array<{ key: string; value: string }>;\n extend?: Record<string, unknown>;\n },\n ): Promise<{ groupId: string }> => {\n const groupId = (await ctx.runMutation(\n config.component.public.groupCreate,\n data,\n )) as string;\n return { groupId };\n },\n /**\n * Fetch a group document by ID.\n *\n * Results are **cached per-execution** — calling `auth.group.get(ctx, id)`\n * multiple times within the same handler for the same `groupId` returns\n * the cached result without an additional component read.\n *\n * @param ctx - Convex query or mutation context.\n * @param groupId - The group's document ID.\n * @returns The group document (including `rootGroupId`, `isRoot`), or `null`.\n */\n get: async (ctx: ComponentReadCtx, groupId: string) => {\n const c = cache(ctx);\n if (c.groups.has(groupId)) return c.groups.get(groupId);\n const result = await ctx.runQuery(config.component.public.groupGet, {\n groupId,\n });\n c.groups.set(groupId, result);\n return result;\n },\n /**\n * List groups with optional filtering, pagination, and ordering.\n *\n * Supports filtering by `slug`, `type`, `parentGroupId`, `name`,\n * `isRoot`, and tags (`tagsAll`, `tagsAny`). The `isRoot` and\n * `parentGroupId` filters use dedicated indexes for efficient queries.\n *\n * @param ctx - Convex query or mutation context.\n * @param opts.where - Filter criteria (all optional, combined with AND).\n * @param opts.where.isRoot - `true` to find root groups, `false` for nested.\n * @param opts.where.parentGroupId - List direct children of this group.\n * @param opts.limit - Max items per page (default 50, max 100).\n * @param opts.cursor - Cursor from a previous `nextCursor`.\n * @param opts.orderBy - Sort field: `\"_creationTime\"`, `\"name\"`, `\"slug\"`, `\"type\"`.\n * @param opts.order - Sort direction: `\"asc\"` or `\"desc\"`.\n * @returns `{ items, nextCursor }`.\n *\n * @example List root workspaces\n * ```ts\n * const { items } = await auth.group.list(ctx, {\n * where: { isRoot: true },\n * orderBy: \"name\", order: \"asc\",\n * });\n * ```\n *\n * @example List children of a group\n * ```ts\n * const { items } = await auth.group.list(ctx, {\n * where: { parentGroupId: orgId },\n * });\n * ```\n */\n list: async (\n ctx: ComponentReadCtx,\n opts?: {\n where?: {\n slug?: string;\n type?: string;\n parentGroupId?: string;\n name?: string;\n isRoot?: boolean;\n tagsAll?: Array<{ key: string; value: string }>;\n tagsAny?: Array<{ key: string; value: string }>;\n };\n limit?: number;\n cursor?: string | null;\n orderBy?: \"_creationTime\" | \"name\" | \"slug\" | \"type\";\n order?: \"asc\" | \"desc\";\n },\n ) => {\n return await ctx.runQuery(config.component.public.groupList, {\n where: opts?.where,\n limit: opts?.limit,\n cursor: opts?.cursor,\n orderBy: opts?.orderBy,\n order: opts?.order,\n });\n },\n /**\n * Patch a group document.\n *\n * If `parentGroupId` is changed, the group's `rootGroupId` and `isRoot`\n * fields are recomputed automatically and cascaded to all descendants.\n *\n * @param ctx - Convex mutation context.\n * @param groupId - The group's document ID.\n * @param data - Fields to merge (e.g. `name`, `slug`, `tags`, `parentGroupId`).\n * @returns `{ groupId }`.\n *\n * @example\n * ```ts\n * await auth.group.update(ctx, groupId, {\n * name: \"Acme Corp (renamed)\",\n * slug: \"acme-corp\",\n * });\n * ```\n */\n update: async (\n ctx: ComponentCtx,\n groupId: string,\n data: Record<string, unknown>,\n ) => {\n await ctx.runMutation(config.component.public.groupUpdate, {\n groupId,\n data,\n });\n return { groupId };\n },\n /**\n * Delete a group and recursively cascade to all descendant groups,\n * their members, invites, and tags.\n *\n * @param ctx - Convex mutation context.\n * @param groupId - The group's document ID.\n * @returns `{ groupId }`.\n *\n * @example\n * ```ts\n * await auth.group.delete(ctx, groupId);\n * ```\n */\n delete: async (ctx: ComponentCtx, groupId: string) => {\n await ctx.runMutation(config.component.public.groupDelete, { groupId });\n return { groupId };\n },\n /**\n * Walk up the group hierarchy from `groupId` and return all ancestor\n * groups in order from immediate parent to root. Detects cycles and\n * respects `maxDepth` (default 32).\n *\n * @param ctx - Convex query or mutation context.\n * @param opts.groupId - Starting group ID.\n * @param opts.maxDepth - Max levels to traverse (default 32).\n * @param opts.includeSelf - Include the starting group in the result.\n * @returns `{ ancestors, cycleDetected, maxDepthReached }`.\n *\n * @example\n * ```ts\n * const { ancestors } = await auth.group.ancestors(ctx, {\n * groupId: teamId,\n * includeSelf: true,\n * });\n * const rootOrg = ancestors[ancestors.length - 1];\n * ```\n */\n ancestors: async (\n ctx: ComponentReadCtx,\n opts: { groupId: string; maxDepth?: number; includeSelf?: boolean },\n ) => {\n const maxDepth = Math.max(0, Math.floor(opts.maxDepth ?? 32));\n const visited = new Set<string>();\n const ancestors: any[] = [];\n let cycleDetected = false;\n let maxDepthReached = false;\n let currentGroupId: string | undefined = opts.groupId;\n let depth = 0;\n let isFirst = true;\n while (currentGroupId !== undefined) {\n if (depth > maxDepth) {\n maxDepthReached = true;\n break;\n }\n if (visited.has(currentGroupId)) {\n cycleDetected = true;\n break;\n }\n visited.add(currentGroupId);\n const doc = await group.get(ctx, currentGroupId);\n if (doc === null) break;\n if (isFirst) {\n isFirst = false;\n if (opts.includeSelf) ancestors.push(doc);\n currentGroupId = doc.parentGroupId;\n depth += 1;\n continue;\n }\n ancestors.push(doc);\n currentGroupId = doc.parentGroupId;\n depth += 1;\n }\n return { ancestors, cycleDetected, maxDepthReached };\n },\n };\n\n const member = {\n /**\n * Add a user to a group with optional role IDs.\n *\n * Role IDs are validated against the roles defined in `defineRoles()` —\n * invalid IDs throw `INVALID_ROLE_IDS`.\n * Throws `DUPLICATE_MEMBERSHIP` if the user is already a member.\n *\n * @param ctx - Convex mutation context.\n * @param data.groupId - The group to add the user to.\n * @param data.userId - The user's document ID.\n * @param data.roleIds - Role IDs from `defineRoles()` (optional).\n * @param data.status - Membership status string (optional, app-defined).\n * @param data.extend - Arbitrary app-specific metadata.\n * @returns `{ memberId }`.\n * @throws `INVALID_ROLE_IDS` if any supplied role IDs are not defined.\n *\n * @example\n * ```ts\n * const { memberId } = await auth.member.create(ctx, {\n * groupId: orgId,\n * userId,\n * roleIds: [roles.orgAdmin.id],\n * });\n * ```\n */\n create: async (\n ctx: ComponentCtx,\n data: {\n groupId: string;\n userId: string;\n roleIds?: string[];\n status?: string;\n extend?: Record<string, unknown>;\n },\n ) => {\n const roleIds = normalizeRoleIds(data.roleIds);\n const memberId = (await ctx.runMutation(\n config.component.public.memberAdd,\n { ...data, roleIds },\n )) as string;\n return { memberId };\n },\n /**\n * Fetch a membership document by its document ID.\n *\n * @param ctx - Convex query or mutation context.\n * @param memberId - The membership document ID.\n * @returns The membership document, or `null` if not found.\n *\n * @example\n * ```ts\n * const membership = await auth.member.get(ctx, memberId);\n * if (!membership) throw new Error(\"Membership not found\");\n * console.log(membership.roleIds, membership.groupId);\n * ```\n */\n get: async (ctx: ComponentReadCtx, memberId: string) => {\n return await ctx.runQuery(config.component.public.memberGet, {\n memberId,\n });\n },\n /**\n * List memberships with optional filtering and pagination.\n *\n * Supports filtering by `groupId`, `userId`, `roleId`, and `status`.\n * When `groupId` and `status` are both provided, a compound index\n * is used for efficient queries.\n *\n * @param ctx - Convex query or mutation context.\n * @param opts.where - Filter criteria (all optional).\n * @param opts.limit - Max items per page (default 50, max 100).\n * @param opts.cursor - Cursor for pagination.\n * @param opts.orderBy - Sort field: `\"_creationTime\"` or `\"status\"`.\n * @param opts.order - Sort direction: `\"asc\"` or `\"desc\"`.\n * @returns `{ items, nextCursor }`.\n *\n * @example\n * ```ts\n * const { items } = await auth.member.list(ctx, {\n * where: { groupId: orgId },\n * limit: 20,\n * orderBy: \"_creationTime\",\n * order: \"asc\",\n * });\n * ```\n */\n list: async (\n ctx: ComponentReadCtx,\n opts?: {\n where?: {\n groupId?: string;\n userId?: string;\n roleId?: string;\n status?: string;\n };\n limit?: number;\n cursor?: string | null;\n orderBy?: \"_creationTime\" | \"status\";\n order?: \"asc\" | \"desc\";\n },\n ) => {\n return await ctx.runQuery(config.component.public.memberList, {\n where: opts?.where,\n limit: opts?.limit,\n cursor: opts?.cursor,\n orderBy: opts?.orderBy,\n order: opts?.order,\n });\n },\n /**\n * Remove a membership by its document ID.\n *\n * @param ctx - Convex mutation context.\n * @param memberId - The membership document ID.\n * @returns `{ memberId }`.\n *\n * @example\n * ```ts\n * await auth.member.delete(ctx, memberId);\n * ```\n */\n delete: async (ctx: ComponentCtx, memberId: string) => {\n await ctx.runMutation(config.component.public.memberRemove, { memberId });\n return { memberId };\n },\n /**\n * Patch a membership's `roleIds`, `status`, or `extend` fields.\n * Role IDs are validated against `defineRoles()`.\n *\n * @param ctx - Convex mutation context.\n * @param memberId - The membership document ID.\n * @param data - Fields to merge. `roleIds` are validated.\n * @returns `{ memberId }`.\n * @throws `INVALID_ROLE_IDS` if any supplied role IDs are not defined.\n *\n * @example\n * ```ts\n * await auth.member.update(ctx, memberId, {\n * roleIds: [roles.orgAdmin.id],\n * status: \"active\",\n * });\n * ```\n */\n update: async (\n ctx: ComponentCtx,\n memberId: string,\n data: Record<string, unknown>,\n ) => {\n const nextData = { ...data };\n if (\"roleIds\" in nextData) {\n nextData.roleIds = normalizeRoleIds(\n Array.isArray(nextData.roleIds)\n ? (nextData.roleIds as string[])\n : undefined,\n );\n }\n await ctx.runMutation(config.component.public.memberUpdate, {\n memberId,\n data: nextData,\n });\n return { memberId };\n },\n /**\n * Resolve a user's membership in a group, optionally walking the\n * hierarchy and checking grants.\n *\n * **Default (no flags):** Direct lookup at `groupId` only — fast,\n * 1 component read. Replaces the old `getByUserAndGroup`.\n *\n * **`ancestry: true`:** Walk the group hierarchy from `groupId` up\n * to root, returning the first matching membership. Includes\n * `traversedGroupIds` in the result. Expensive (N reads).\n *\n * **`grants: [...]`:** Check if the user has all specified grants.\n * Works at the direct level by default. Combine with\n * `ancestry: true` to check inherited grants.\n *\n * @param ctx - Convex query or mutation context.\n * @param opts.userId - The user's document ID.\n * @param opts.groupId - The group to check membership in.\n * @param opts.ancestry - Walk the hierarchy (default `false`).\n * @param opts.maxDepth - Max hierarchy levels (default 32, only with ancestry).\n * @returns `{ membership, roleIds, grants }`.\n *\n * @example Direct lookup\n * ```ts\n * const result = await auth.member.inspect(ctx, { userId, groupId });\n * if (!result.membership) return null;\n * ```\n *\n * @example Check grants after inspection\n * ```ts\n * const result = await auth.member.inspect(ctx, {\n * userId, groupId,\n * });\n * const canCreate = result.grants.includes(\"issues.create\");\n * ```\n *\n * @example Walk hierarchy + check grants\n * ```ts\n * const result = await auth.member.inspect(ctx, {\n * userId, groupId: teamId, ancestry: true,\n * });\n * ```\n */\n inspect: async (\n ctx: ComponentReadCtx,\n opts: {\n userId: string;\n groupId: string;\n ancestry?: boolean;\n maxDepth?: number;\n },\n ) => {\n const useAncestry = opts.ancestry === true;\n\n let membership: any = null;\n\n if (useAncestry) {\n // Hierarchy walk — single component RPC\n const maxDepth = Math.max(0, Math.floor(opts.maxDepth ?? 32));\n const result = await ctx.runQuery(\n config.component.public.memberResolve,\n {\n userId: opts.userId,\n groupId: opts.groupId,\n maxDepth,\n ancestry: true,\n },\n );\n membership = result.membership;\n } else {\n // Fast path — direct lookup, 1 read\n const doc = await ctx.runQuery(\n config.component.public.memberGetByGroupAndUser,\n { userId: opts.userId, groupId: opts.groupId },\n );\n membership = doc;\n }\n\n if (membership === null) {\n return {\n membership: null,\n roleIds: [] as string[],\n grants: [] as string[],\n };\n }\n\n const membershipRoleIds = membership.roleIds ?? [];\n const membershipGrants = resolveGrantedPermissions(membershipRoleIds);\n\n return {\n membership,\n roleIds: membershipRoleIds,\n grants: membershipGrants,\n };\n },\n require: async (\n ctx: ComponentReadCtx,\n opts: {\n userId: string;\n groupId: string;\n ancestry?: boolean;\n roleIds?: string[];\n grants?: string[];\n maxDepth?: number;\n },\n ) => {\n const validatedRoleIds = normalizeRoleIds(opts.roleIds);\n const requiredGrants = Array.from(new Set(opts.grants ?? []));\n const roleFilter =\n validatedRoleIds.length > 0 ? new Set(validatedRoleIds) : null;\n const result = await member.inspect(ctx, {\n userId: opts.userId,\n groupId: opts.groupId,\n ancestry: opts.ancestry,\n maxDepth: opts.maxDepth,\n });\n if (result.membership === null) {\n throw Cv.error({\n code: \"NOT_A_MEMBER\",\n message: \"User is not a member of this group.\",\n groupId: opts.groupId,\n });\n }\n if (\n roleFilter !== null &&\n !result.roleIds.some((roleId: string) => roleFilter.has(roleId))\n ) {\n throw Cv.error({\n code: \"NOT_A_MEMBER\",\n message: \"User is not a member of this group.\",\n groupId: opts.groupId,\n });\n }\n const missingGrants = requiredGrants.filter(\n (grant) => !result.grants.includes(grant),\n );\n if (missingGrants.length > 0) {\n throw Cv.error({\n code: \"MISSING_GRANTS\",\n message: \"User is missing required grants.\",\n groupId: opts.groupId,\n missingGrants,\n });\n }\n return result;\n },\n };\n\n const invite = {\n /**\n * Create a pending invite. Returns a one-time `token` the recipient\n * uses to accept. Optionally scoped to a group with role IDs.\n *\n * @param ctx - Convex mutation context.\n * @param data.groupId - The group to invite the user to (optional).\n * @param data.invitedByUserId - The user who created this invite (optional).\n * @param data.email - The invitee's email address (optional).\n * @param data.roleIds - Role IDs from `defineRoles()` to assign on acceptance (optional).\n * @param data.expiresTime - Expiration timestamp in ms since epoch (optional).\n * @param data.extend - Arbitrary app-specific metadata (optional).\n * @returns `{ inviteId, token }`.\n * @throws `INVALID_ROLE_IDS` if any supplied role IDs are not defined.\n *\n * @example\n * ```ts\n * const { token } = await auth.invite.create(ctx, {\n * groupId, email: \"alice@example.com\", roleIds: [roles.member.id],\n * });\n * ```\n */\n create: async (\n ctx: ComponentCtx,\n data: {\n groupId?: string;\n invitedByUserId?: string;\n email?: string;\n roleIds?: string[];\n expiresTime?: number;\n extend?: Record<string, unknown>;\n },\n ) => {\n const roleIds = normalizeRoleIds(data.roleIds);\n const token = generateRandomString(\n inviteTokenLength,\n inviteTokenAlphabet,\n );\n const tokenHash = await sha256(token);\n const inviteId = (await ctx.runMutation(\n config.component.public.inviteCreate,\n { ...data, roleIds, tokenHash, status: \"pending\" },\n )) as string;\n return { inviteId, token };\n },\n /**\n * Fetch an invite document by ID.\n *\n * Returns the full invite document including its status, email,\n * group, role IDs, and token hash. Useful for displaying invite\n * details or checking status before performing actions.\n *\n * @param ctx - Convex query or mutation context.\n * @param inviteId - The invite's document ID.\n * @returns The invite document, or `null` if not found.\n *\n * @example\n * ```ts\n * const invite = await auth.invite.get(ctx, inviteId);\n * if (invite?.status === \"pending\") {\n * // show invite details\n * }\n * ```\n */\n get: async (ctx: ComponentReadCtx, inviteId: string) => {\n return await ctx.runQuery(config.component.public.inviteGet, {\n inviteId,\n });\n },\n token: {\n /**\n * Look up an invite by its raw token string.\n *\n * Hashes the raw token and queries the database for a matching\n * invite. This is the standard path for invite-link landing pages\n * where the token is extracted from the URL.\n *\n * @param ctx - Convex query or mutation context.\n * @param token - The raw invite token string from the invite link.\n * @returns The invite document, or `null` if no matching invite exists.\n *\n * @example\n * ```ts\n * const invite = await auth.invite.token.get(ctx, tokenFromUrl);\n * if (!invite || invite.status !== \"pending\") {\n * throw new Error(\"Invalid or expired invite\");\n * }\n * ```\n */\n get: async (ctx: ComponentReadCtx, token: string) => {\n const tokenHash = await sha256(token);\n return await ctx.runQuery(\n config.component.public.inviteGetByTokenHash,\n { tokenHash },\n );\n },\n /**\n * Accept an invite by token. Creates a membership and marks the invite as accepted.\n *\n * Hashes the raw token, finds the matching invite, creates a group\n * membership with the invite's role IDs, and transitions the invite\n * status to `\"accepted\"`.\n *\n * @param ctx - Convex mutation context.\n * @param args.token - The raw invite token string.\n * @param args.acceptedByUserId - The user accepting the invite.\n * @returns The created membership details.\n *\n * @example\n * ```ts\n * const result = await auth.invite.token.accept(ctx, {\n * token: tokenFromUrl,\n * acceptedByUserId: userId,\n * });\n * ```\n */\n accept: async (\n ctx: ComponentCtx,\n args: { token: string; acceptedByUserId: string },\n ) => {\n const tokenHash = await sha256(args.token);\n const result = await ctx.runMutation(\n config.component.public.inviteAcceptByToken,\n { tokenHash, acceptedByUserId: args.acceptedByUserId },\n );\n return { ...result };\n },\n },\n /**\n * List invites with optional filtering by group, status, email, etc.\n * Results are paginated.\n *\n * @param ctx - Convex query or mutation context.\n * @param opts.where - Filter criteria (all optional).\n * @param opts.where.status - `\"pending\"`, `\"accepted\"`, `\"revoked\"`, or `\"expired\"`.\n * @param opts.limit - Max items per page (default 50, max 100).\n * @param opts.cursor - Cursor from a previous `nextCursor` for pagination.\n * @param opts.orderBy - Sort field: `\"_creationTime\"`, `\"status\"`, `\"email\"`,\n * `\"expiresTime\"`, or `\"acceptedTime\"`.\n * @param opts.order - Sort direction: `\"asc\"` or `\"desc\"`.\n * @returns `{ items, nextCursor }` — `nextCursor` is `null` when there are no more pages.\n *\n * @example\n * ```ts\n * const { items } = await auth.invite.list(ctx, {\n * where: { groupId, status: \"pending\" },\n * orderBy: \"_creationTime\",\n * order: \"desc\",\n * });\n * ```\n */\n list: async (\n ctx: ComponentReadCtx,\n opts?: {\n where?: {\n tokenHash?: string;\n groupId?: string;\n status?: \"pending\" | \"accepted\" | \"revoked\" | \"expired\";\n email?: string;\n invitedByUserId?: string;\n roleId?: string;\n acceptedByUserId?: string;\n };\n limit?: number;\n cursor?: string | null;\n orderBy?:\n | \"_creationTime\"\n | \"status\"\n | \"email\"\n | \"expiresTime\"\n | \"acceptedTime\";\n order?: \"asc\" | \"desc\";\n },\n ) => {\n return await ctx.runQuery(config.component.public.inviteList, {\n where: opts?.where,\n limit: opts?.limit,\n cursor: opts?.cursor,\n orderBy: opts?.orderBy,\n order: opts?.order,\n });\n },\n /**\n * Accept an invite by ID. Optionally specify who accepted it.\n *\n * Transitions the invite's status to `\"accepted\"` and optionally\n * records the accepting user. Unlike `invite.token.accept`, this\n * method does not automatically create a group membership — use it\n * for admin-driven invite acceptance flows.\n *\n * @param ctx - Convex mutation context.\n * @param inviteId - The invite's document ID.\n * @param acceptedByUserId - The user who accepted the invite (optional).\n * @returns `{ inviteId, acceptedByUserId }`.\n *\n * @example\n * ```ts\n * await auth.invite.accept(ctx, inviteId, userId);\n * ```\n */\n accept: async (\n ctx: ComponentCtx,\n inviteId: string,\n acceptedByUserId?: string,\n ) => {\n await ctx.runMutation(config.component.public.inviteAccept, {\n inviteId,\n ...(acceptedByUserId ? { acceptedByUserId } : {}),\n });\n return {\n inviteId,\n acceptedByUserId: acceptedByUserId ?? null,\n };\n },\n /**\n * Revoke a pending invite. Sets its status to `\"revoked\"`.\n *\n * Once revoked, the invite's token can no longer be used to accept\n * the invitation. This is a permanent status change.\n *\n * @param ctx - Convex mutation context.\n * @param inviteId - The invite's document ID.\n * @returns `{ inviteId }`.\n *\n * @example\n * ```ts\n * await auth.invite.revoke(ctx, inviteId);\n * ```\n */\n revoke: async (ctx: ComponentCtx, inviteId: string) => {\n await ctx.runMutation(config.component.public.inviteRevoke, { inviteId });\n return { inviteId };\n },\n };\n\n const key = {\n /**\n * Create an API key for programmatic access. The returned `secret`\n * (prefixed `sk_`) is shown only once — it is stored as a hash.\n *\n * @param ctx - Convex mutation context.\n * @param opts.userId - Owner of the key.\n * @param opts.name - Human-readable name (e.g. `\"CI Pipeline\"`).\n * @param opts.scopes - Array of `{ resource, actions }` permission scopes.\n * @param opts.rateLimit - Optional per-key rate limit `{ maxRequests, windowMs }`.\n * @param opts.expiresAt - Optional expiration timestamp (ms since epoch).\n * @param opts.metadata - Arbitrary app-specific metadata.\n * @returns `{ keyId, secret }`. Store `secret` securely — it cannot be retrieved later.\n *\n * @example\n * ```ts\n * const { secret } = await auth.key.create(ctx, {\n * userId,\n * name: \"CI Pipeline\",\n * scopes: [{ resource: \"data\", actions: [\"read\"] }],\n * });\n * ```\n */\n create: async (\n ctx: ComponentCtx,\n opts: {\n userId: string;\n name: string;\n scopes: KeyScope[];\n rateLimit?: { maxRequests: number; windowMs: number };\n expiresAt?: number;\n metadata?: Record<string, unknown>;\n },\n ): Promise<{ keyId: string; secret: string }> => {\n const { raw, hashedKey, displayPrefix } = await generateApiKey(\"sk_\");\n const keyId = (await ctx.runMutation(config.component.public.keyInsert, {\n userId: opts.userId,\n prefix: displayPrefix,\n hashedKey,\n name: opts.name,\n scopes: opts.scopes,\n rateLimit: opts.rateLimit,\n expiresAt: opts.expiresAt,\n metadata: opts.metadata,\n })) as string;\n return { keyId, secret: raw };\n },\n /**\n * Verify an API key and return the owner's identity and scopes.\n *\n * Checks the key against the database, enforces expiration and rate\n * limits, and returns a `ScopeChecker` for permission evaluation.\n *\n * @param ctx - Convex mutation context (updates `lastUsedAt` and rate limit state).\n * @param rawKey - The raw `sk_*` key string.\n * @returns `{ userId, keyId, scopes }` where `scopes.can(resource, action)` checks permissions.\n * @throws `INVALID_API_KEY` if the key is not found.\n * @throws `API_KEY_REVOKED` if the key was revoked.\n * @throws `API_KEY_EXPIRED` if the key is past its `expiresAt`.\n * @throws `API_KEY_RATE_LIMITED` if the rate limit is exceeded.\n *\n * @example\n * ```ts\n * const { userId, scopes } = await auth.key.verify(ctx, rawKey);\n * const canRead = scopes.can(\"data\", \"read\");\n * ```\n */\n verify: async (\n ctx: ComponentCtx,\n rawKey: string,\n ): Promise<{ userId: string; keyId: string; scopes: ScopeChecker }> => {\n const hashedKey = await hashApiKey(rawKey);\n const doc = (await ctx.runQuery(\n config.component.public.keyGetByHashedKey,\n { hashedKey },\n )) as KeyDoc | null;\n if (!doc) {\n throw Cv.error({\n code: \"INVALID_API_KEY\",\n message: \"Invalid API key.\",\n });\n }\n const k = doc;\n if (k.revoked) {\n throw Cv.error({\n code: \"API_KEY_REVOKED\",\n message: \"This API key has been revoked.\",\n });\n }\n if (k.expiresAt && k.expiresAt < Date.now()) {\n throw Cv.error({\n code: \"API_KEY_EXPIRED\",\n message: \"This API key has expired.\",\n });\n }\n const patchData: Record<string, unknown> = { lastUsedAt: Date.now() };\n if (k.rateLimit) {\n const { limited, newState } = checkKeyRateLimit(\n k.rateLimit,\n k.rateLimitState ?? undefined,\n );\n if (limited) {\n throw Cv.error({\n code: \"API_KEY_RATE_LIMITED\",\n message: \"API key rate limit exceeded. Please try again later.\",\n });\n }\n patchData.rateLimitState = newState;\n }\n await ctx.runMutation(config.component.public.keyPatch, {\n keyId: k._id,\n data: patchData,\n });\n return {\n userId: k.userId,\n keyId: k._id,\n scopes: buildScopeChecker(k.scopes),\n };\n },\n /**\n * List API keys with optional filtering by user, revocation status, name,\n * or prefix. Results are paginated. Does not expose raw key secrets.\n *\n * @param ctx - Convex query or mutation context.\n * @param opts.where - Filter criteria (all optional, combined with AND).\n * @param opts.limit - Max items per page (default 50, max 100).\n * @param opts.cursor - Cursor from a previous `nextCursor` for pagination.\n * @param opts.orderBy - Sort field: `\"_creationTime\"`, `\"name\"`, `\"lastUsedAt\"`, `\"expiresAt\"`, or `\"revoked\"`.\n * @param opts.order - Sort direction: `\"asc\"` or `\"desc\"`.\n * @returns `{ items, nextCursor }` — `nextCursor` is `null` when no more pages.\n *\n * @example\n * ```ts\n * const { items } = await auth.key.list(ctx, {\n * where: { userId, revoked: false },\n * orderBy: \"lastUsedAt\",\n * order: \"desc\",\n * });\n * ```\n */\n list: async (\n ctx: ComponentReadCtx,\n opts?: {\n where?: {\n userId?: string;\n revoked?: boolean;\n name?: string;\n prefix?: string;\n };\n limit?: number;\n cursor?: string | null;\n orderBy?:\n | \"_creationTime\"\n | \"name\"\n | \"lastUsedAt\"\n | \"expiresAt\"\n | \"revoked\";\n order?: \"asc\" | \"desc\";\n },\n ) => {\n return await ctx.runQuery(config.component.public.keyList, {\n where: opts?.where,\n limit: opts?.limit,\n cursor: opts?.cursor,\n orderBy: opts?.orderBy,\n order: opts?.order,\n });\n },\n /**\n * Fetch an API key record by ID. Does not expose the raw key secret.\n *\n * Returns the key document including metadata, scopes, rate limit\n * configuration, and revocation status. The raw secret is never\n * stored or returned — only the hashed key and display prefix.\n *\n * @param ctx - Convex query or mutation context.\n * @param keyId - The API key's document ID.\n * @returns The key document, or `null` if not found.\n *\n * @example\n * ```ts\n * const key = await auth.key.get(ctx, keyId);\n * if (!key) throw new Error(\"Key not found\");\n * console.log(key.name, key.prefix);\n * ```\n */\n get: async (\n ctx: ComponentReadCtx,\n keyId: string,\n ): Promise<KeyDoc | null> => {\n const doc = (await ctx.runQuery(config.component.public.keyGetById, {\n keyId,\n })) as KeyDoc | null;\n return doc ?? null;\n },\n /**\n * Update a key's name, scopes, or rate limit.\n *\n * Patches the specified fields on the API key document. Only the\n * provided fields are changed — omitted fields remain unchanged.\n *\n * @param ctx - Convex mutation context.\n * @param keyId - The API key's document ID.\n * @param data - Fields to merge into the key document.\n * @returns `{ keyId }`.\n *\n * @example\n * ```ts\n * await auth.key.update(ctx, keyId, {\n * name: \"CI Pipeline (updated)\",\n * scopes: [{ resource: \"data\", actions: [\"read\", \"write\"] }],\n * });\n * ```\n */\n update: async (\n ctx: ComponentCtx,\n keyId: string,\n data: {\n name?: string;\n scopes?: KeyScope[];\n rateLimit?: { maxRequests: number; windowMs: number };\n },\n ) => {\n await ctx.runMutation(config.component.public.keyPatch, { keyId, data });\n return { keyId };\n },\n /**\n * Soft-delete: set `revoked: true`. The key can no longer be verified.\n *\n * After revocation, any subsequent calls to `auth.key.verify` with\n * this key will throw `API_KEY_REVOKED`.\n * The key record is preserved for audit purposes.\n *\n * @param ctx - Convex mutation context.\n * @param keyId - The API key's document ID.\n * @returns `{ keyId }`.\n *\n * @example\n * ```ts\n * await auth.key.revoke(ctx, keyId);\n * ```\n */\n revoke: async (ctx: ComponentCtx, keyId: string) => {\n await ctx.runMutation(config.component.public.keyPatch, {\n keyId,\n data: { revoked: true },\n });\n return { keyId };\n },\n /**\n * Hard-delete: permanently remove the key record.\n *\n * Unlike `revoke`, this permanently removes the key document from\n * the database. Use this when you need to fully clean up a key\n * rather than preserving it for audit history.\n *\n * @param ctx - Convex mutation context.\n * @param keyId - The API key's document ID.\n * @returns `{ keyId }`.\n *\n * @example\n * ```ts\n * await auth.key.delete(ctx, keyId);\n * ```\n */\n delete: async (ctx: ComponentCtx, keyId: string) => {\n await ctx.runMutation(config.component.public.keyDelete, { keyId });\n return { keyId };\n },\n /**\n * Rotate a key: revokes the old key and creates a new one with the\n * same user, scopes, and rate limit. Returns the new `keyId` and `secret`.\n * Throws if the key does not exist or is already revoked.\n *\n * @param ctx - Convex mutation context.\n * @param keyId - The existing API key's document ID to rotate.\n * @param opts.name - Optional new name for the rotated key (defaults to the old name).\n * @param opts.expiresAt - Optional new expiration timestamp in ms since epoch.\n * @returns `{ keyId, secret }` with the new key.\n * @throws `INVALID_PARAMETERS` if the key does not exist.\n * @throws `API_KEY_REVOKED` if the key is already revoked.\n *\n * @example\n * ```ts\n * const { keyId, secret } = await auth.key.rotate(ctx, oldKeyId, {\n * expiresAt: Date.now() + 30 * 24 * 60 * 60 * 1000, // 30 days\n * });\n * // Store secret securely — shown only once\n * ```\n */\n rotate: async (\n ctx: ComponentCtx,\n keyId: string,\n opts?: { name?: string; expiresAt?: number },\n ): Promise<{ keyId: string; secret: string }> => {\n const existing = await ctx.runQuery(config.component.public.keyGetById, {\n keyId,\n });\n if (!existing) {\n throw Cv.error({\n code: \"INVALID_PARAMETERS\",\n message: \"The provided parameters are invalid.\",\n });\n }\n if ((existing as any).revoked === true) {\n throw Cv.error({\n code: \"API_KEY_REVOKED\",\n message: \"This API key has been revoked.\",\n });\n }\n await ctx.runMutation(config.component.public.keyPatch, {\n keyId,\n data: { revoked: true },\n });\n return await key.create(ctx, {\n userId: (existing as any).userId,\n name: opts?.name ?? (existing as any).name,\n scopes: (existing as any).scopes ?? [],\n rateLimit: (existing as any).rateLimit,\n expiresAt: opts?.expiresAt,\n metadata: (existing as any).metadata,\n });\n },\n };\n\n return {\n user,\n session,\n account,\n provider,\n group,\n member,\n invite,\n key,\n };\n}\n"],"mappings":"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"}
@@ -1,56 +0,0 @@
1
- import { errorMessage } from "./utils.js";
2
- import { Cv } from "@robelest/fx/convex";
3
- import { Fx } from "@robelest/fx";
4
-
5
- //#region src/server/crypto.ts
6
- /**
7
- * Hash a secret using the provider's `crypto.hashSecret` function.
8
- *
9
- * Validates that the provider is a credentials provider and has the
10
- * required crypto function, returning typed errors through the Fx channel.
11
- */
12
- /** @internal */
13
- const hash = (provider, secret) => Fx.gen(function* () {
14
- if (provider.type !== "credentials") return yield* Cv.fail({
15
- code: "INVALID_CREDENTIALS_PROVIDER",
16
- message: `Provider ${provider.id} is not a credentials provider`
17
- });
18
- const hashSecretFn = provider.crypto?.hashSecret;
19
- if (!hashSecretFn) return yield* Cv.fail({
20
- code: "MISSING_CRYPTO_FUNCTION",
21
- message: `Provider ${provider.id} does not have a \`crypto.hashSecret\` function`
22
- });
23
- return yield* Fx.from({
24
- ok: () => hashSecretFn(secret),
25
- err: (e) => Cv.error({
26
- code: "INTERNAL_ERROR",
27
- message: `Hash failed: ${errorMessage(e)}`
28
- })
29
- });
30
- });
31
- /**
32
- * Verify a secret against a hash using the provider's `crypto.verifySecret` function.
33
- */
34
- /** @internal */
35
- const verify = (provider, secret, hashValue) => Fx.gen(function* () {
36
- if (provider.type !== "credentials") return yield* Cv.fail({
37
- code: "INVALID_CREDENTIALS_PROVIDER",
38
- message: `Provider ${provider.id} is not a credentials provider`
39
- });
40
- const verifySecretFn = provider.crypto?.verifySecret;
41
- if (!verifySecretFn) return yield* Cv.fail({
42
- code: "MISSING_CRYPTO_FUNCTION",
43
- message: `Provider ${provider.id} does not have a \`crypto.verifySecret\` function`
44
- });
45
- return yield* Fx.from({
46
- ok: () => verifySecretFn(secret, hashValue),
47
- err: (e) => Cv.error({
48
- code: "INTERNAL_ERROR",
49
- message: `Verify failed: ${errorMessage(e)}`
50
- })
51
- });
52
- });
53
-
54
- //#endregion
55
- export { hash, verify };
56
- //# sourceMappingURL=crypto.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"crypto.js","names":[],"sources":["../../../src/server/crypto.ts"],"sourcesContent":["import { Fx } from \"@robelest/fx\";\nimport { Cv } from \"@robelest/fx/convex\";\nimport { ConvexError } from \"convex/values\";\n\nimport { AuthProviderMaterializedConfig } from \"./types\";\nimport { ConvexAuthMaterializedConfig } from \"./types\";\nimport { errorMessage } from \"./utils\";\n\n/**\n * Hash a secret using the provider's `crypto.hashSecret` function.\n *\n * Validates that the provider is a credentials provider and has the\n * required crypto function, returning typed errors through the Fx channel.\n */\n/** @internal */\nexport const hash = (\n provider: any,\n secret: string,\n): Fx<string, ConvexError<any>> =>\n Fx.gen(function* () {\n if (provider.type !== \"credentials\") {\n return yield* Cv.fail({\n code: \"INVALID_CREDENTIALS_PROVIDER\",\n message: `Provider ${provider.id} is not a credentials provider`,\n });\n }\n\n const hashSecretFn = provider.crypto?.hashSecret as\n | ((s: string) => Promise<string>)\n | undefined;\n if (!hashSecretFn) {\n return yield* Cv.fail({\n code: \"MISSING_CRYPTO_FUNCTION\",\n message: `Provider ${provider.id} does not have a \\`crypto.hashSecret\\` function`,\n });\n }\n\n return yield* Fx.from({\n ok: () => hashSecretFn(secret),\n err: (e) =>\n Cv.error({\n code: \"INTERNAL_ERROR\",\n message: `Hash failed: ${errorMessage(e)}`,\n }),\n });\n });\n\n/**\n * Verify a secret against a hash using the provider's `crypto.verifySecret` function.\n */\n/** @internal */\nexport const verify = (\n provider: AuthProviderMaterializedConfig,\n secret: string,\n hashValue: string,\n): Fx<boolean, ConvexError<any>> =>\n Fx.gen(function* () {\n if (provider.type !== \"credentials\") {\n return yield* Cv.fail({\n code: \"INVALID_CREDENTIALS_PROVIDER\",\n message: `Provider ${provider.id} is not a credentials provider`,\n });\n }\n\n const verifySecretFn = (provider as any).crypto?.verifySecret as\n | ((s: string, h: string) => Promise<boolean>)\n | undefined;\n if (!verifySecretFn) {\n return yield* Cv.fail({\n code: \"MISSING_CRYPTO_FUNCTION\",\n message: `Provider ${provider.id} does not have a \\`crypto.verifySecret\\` function`,\n });\n }\n\n return yield* Fx.from({\n ok: () => verifySecretFn(secret, hashValue),\n err: (e) =>\n Cv.error({\n code: \"INTERNAL_ERROR\",\n message: `Verify failed: ${errorMessage(e)}`,\n }),\n });\n });\n\nexport type GetProviderOrThrowFunc = (\n provider: string,\n allowExtraProviders?: boolean,\n) => AuthProviderMaterializedConfig;\n\nexport type Config = ConvexAuthMaterializedConfig;\n"],"mappings":";;;;;;;;;;;;AAeA,MAAa,QACX,UACA,WAEA,GAAG,IAAI,aAAa;AAClB,KAAI,SAAS,SAAS,cACpB,QAAO,OAAO,GAAG,KAAK;EACpB,MAAM;EACN,SAAS,YAAY,SAAS,GAAG;EAClC,CAAC;CAGJ,MAAM,eAAe,SAAS,QAAQ;AAGtC,KAAI,CAAC,aACH,QAAO,OAAO,GAAG,KAAK;EACpB,MAAM;EACN,SAAS,YAAY,SAAS,GAAG;EAClC,CAAC;AAGJ,QAAO,OAAO,GAAG,KAAK;EACpB,UAAU,aAAa,OAAO;EAC9B,MAAM,MACJ,GAAG,MAAM;GACP,MAAM;GACN,SAAS,gBAAgB,aAAa,EAAE;GACzC,CAAC;EACL,CAAC;EACF;;;;;AAMJ,MAAa,UACX,UACA,QACA,cAEA,GAAG,IAAI,aAAa;AAClB,KAAI,SAAS,SAAS,cACpB,QAAO,OAAO,GAAG,KAAK;EACpB,MAAM;EACN,SAAS,YAAY,SAAS,GAAG;EAClC,CAAC;CAGJ,MAAM,iBAAkB,SAAiB,QAAQ;AAGjD,KAAI,CAAC,eACH,QAAO,OAAO,GAAG,KAAK;EACpB,MAAM;EACN,SAAS,YAAY,SAAS,GAAG;EAClC,CAAC;AAGJ,QAAO,OAAO,GAAG,KAAK;EACpB,UAAU,eAAe,QAAQ,UAAU;EAC3C,MAAM,MACJ,GAAG,MAAM;GACP,MAAM;GACN,SAAS,kBAAkB,aAAa,EAAE;GAC3C,CAAC;EACL,CAAC;EACF"}
@@ -1,87 +0,0 @@
1
- //#region src/server/db.ts
2
- /** @internal */
3
- function authDb(ctx, config) {
4
- const component = config.component;
5
- return {
6
- users: {
7
- getById: (userId) => ctx.runQuery(component.public.userGetById, { userId }),
8
- findByVerifiedEmail: (email) => ctx.runQuery(component.public.userFindByVerifiedEmail, { email }),
9
- findByVerifiedPhone: (phone) => ctx.runQuery(component.public.userFindByVerifiedPhone, { phone }),
10
- insert: (data) => ctx.runMutation(component.public.userInsert, { data }),
11
- patch: (userId, data) => ctx.runMutation(component.public.userPatch, {
12
- userId,
13
- data
14
- }),
15
- upsert: (userId, data) => ctx.runMutation(component.public.userUpsert, {
16
- userId,
17
- data
18
- })
19
- },
20
- accounts: {
21
- get: (provider, providerAccountId) => ctx.runQuery(component.public.accountGet, {
22
- provider,
23
- providerAccountId
24
- }),
25
- getById: (accountId) => ctx.runQuery(component.public.accountGetById, { accountId }),
26
- create: (args) => ctx.runMutation(component.public.accountInsert, args),
27
- patch: (accountId, data) => ctx.runMutation(component.public.accountPatch, {
28
- accountId,
29
- data
30
- }),
31
- delete: (accountId) => ctx.runMutation(component.public.accountDelete, { accountId })
32
- },
33
- sessions: {
34
- create: (userId, expirationTime) => ctx.runMutation(component.public.sessionCreate, {
35
- userId,
36
- expirationTime
37
- }),
38
- getById: (sessionId) => ctx.runQuery(component.public.sessionGetById, { sessionId }),
39
- delete: (sessionId) => ctx.runMutation(component.public.sessionDelete, { sessionId }),
40
- listByUser: (userId) => ctx.runQuery(component.public.sessionListByUser, { userId })
41
- },
42
- verifiers: {
43
- create: (sessionId) => ctx.runMutation(component.public.verifierCreate, { sessionId }),
44
- getById: (verifierId) => ctx.runQuery(component.public.verifierGetById, { verifierId }),
45
- getBySignature: (signature) => ctx.runQuery(component.public.verifierGetBySignature, { signature }),
46
- patch: (verifierId, data) => ctx.runMutation(component.public.verifierPatch, {
47
- verifierId,
48
- data
49
- }),
50
- delete: (verifierId) => ctx.runMutation(component.public.verifierDelete, { verifierId })
51
- },
52
- verificationCodes: {
53
- getByAccountId: (accountId) => ctx.runQuery(component.public.verificationCodeGetByAccountId, { accountId }),
54
- getByCode: (code) => ctx.runQuery(component.public.verificationCodeGetByCode, { code }),
55
- create: (args) => ctx.runMutation(component.public.verificationCodeCreate, args),
56
- delete: (verificationCodeId) => ctx.runMutation(component.public.verificationCodeDelete, { verificationCodeId })
57
- },
58
- refreshTokens: {
59
- create: (args) => ctx.runMutation(component.public.refreshTokenCreate, args),
60
- getById: (refreshTokenId) => ctx.runQuery(component.public.refreshTokenGetById, { refreshTokenId }),
61
- patch: (refreshTokenId, data) => ctx.runMutation(component.public.refreshTokenPatch, {
62
- refreshTokenId,
63
- data
64
- }),
65
- getChildren: (sessionId, parentRefreshTokenId) => ctx.runQuery(component.public.refreshTokenGetChildren, {
66
- sessionId,
67
- parentRefreshTokenId
68
- }),
69
- listBySession: (sessionId) => ctx.runQuery(component.public.refreshTokenListBySession, { sessionId }),
70
- deleteAll: (sessionId) => ctx.runMutation(component.public.refreshTokenDeleteAll, { sessionId }),
71
- getActive: (sessionId) => ctx.runQuery(component.public.refreshTokenGetActive, { sessionId })
72
- },
73
- rateLimits: {
74
- get: (identifier) => ctx.runQuery(component.public.rateLimitGet, { identifier }),
75
- create: (args) => ctx.runMutation(component.public.rateLimitCreate, args),
76
- patch: (rateLimitId, data) => ctx.runMutation(component.public.rateLimitPatch, {
77
- rateLimitId,
78
- data
79
- }),
80
- delete: (rateLimitId) => ctx.runMutation(component.public.rateLimitDelete, { rateLimitId })
81
- }
82
- };
83
- }
84
-
85
- //#endregion
86
- export { authDb };
87
- //# sourceMappingURL=db.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"db.js","names":[],"sources":["../../../src/server/db.ts"],"sourcesContent":["import {\n GenericActionCtx,\n GenericDataModel,\n GenericMutationCtx,\n FunctionReference,\n} from \"convex/server\";\n\ntype MutationCtxLike = Pick<\n GenericMutationCtx<GenericDataModel>,\n \"runQuery\" | \"runMutation\"\n>;\ntype ActionCtxLike = Pick<\n GenericActionCtx<GenericDataModel>,\n \"runQuery\" | \"runMutation\" | \"runAction\"\n>;\n\ntype CtxLike = MutationCtxLike | ActionCtxLike;\n\ntype AuthComponentApiLike = {\n public: {\n userGetById: FunctionReference<\"query\", \"internal\">;\n userFindByVerifiedEmail: FunctionReference<\"query\", \"internal\">;\n userFindByVerifiedPhone: FunctionReference<\"query\", \"internal\">;\n userInsert: FunctionReference<\"mutation\", \"internal\">;\n userPatch: FunctionReference<\"mutation\", \"internal\">;\n userUpsert: FunctionReference<\"mutation\", \"internal\">;\n accountGet: FunctionReference<\"query\", \"internal\">;\n accountGetById: FunctionReference<\"query\", \"internal\">;\n accountInsert: FunctionReference<\"mutation\", \"internal\">;\n accountPatch: FunctionReference<\"mutation\", \"internal\">;\n accountDelete: FunctionReference<\"mutation\", \"internal\">;\n sessionCreate: FunctionReference<\"mutation\", \"internal\">;\n sessionGetById: FunctionReference<\"query\", \"internal\">;\n sessionDelete: FunctionReference<\"mutation\", \"internal\">;\n sessionListByUser: FunctionReference<\"query\", \"internal\">;\n verifierCreate: FunctionReference<\"mutation\", \"internal\">;\n verifierGetById: FunctionReference<\"query\", \"internal\">;\n verifierGetBySignature: FunctionReference<\"query\", \"internal\">;\n verifierPatch: FunctionReference<\"mutation\", \"internal\">;\n verifierDelete: FunctionReference<\"mutation\", \"internal\">;\n verificationCodeGetByAccountId: FunctionReference<\"query\", \"internal\">;\n verificationCodeGetByCode: FunctionReference<\"query\", \"internal\">;\n verificationCodeCreate: FunctionReference<\"mutation\", \"internal\">;\n verificationCodeDelete: FunctionReference<\"mutation\", \"internal\">;\n refreshTokenCreate: FunctionReference<\"mutation\", \"internal\">;\n refreshTokenGetById: FunctionReference<\"query\", \"internal\">;\n refreshTokenPatch: FunctionReference<\"mutation\", \"internal\">;\n refreshTokenGetChildren: FunctionReference<\"query\", \"internal\">;\n refreshTokenListBySession: FunctionReference<\"query\", \"internal\">;\n refreshTokenDeleteAll: FunctionReference<\"mutation\", \"internal\">;\n refreshTokenGetActive: FunctionReference<\"query\", \"internal\">;\n rateLimitGet: FunctionReference<\"query\", \"internal\">;\n rateLimitCreate: FunctionReference<\"mutation\", \"internal\">;\n rateLimitPatch: FunctionReference<\"mutation\", \"internal\">;\n rateLimitDelete: FunctionReference<\"mutation\", \"internal\">;\n };\n};\n\n/** @internal */\nexport type AuthDbConfig = { component: AuthComponentApiLike };\n\n/** @internal */\nexport type AuthDb = ReturnType<typeof authDb>;\n\n/** @internal */\nexport function authDb(ctx: CtxLike, config: AuthDbConfig) {\n const component = config.component;\n return {\n users: {\n getById: (userId: string) =>\n ctx.runQuery(component.public.userGetById, { userId }),\n findByVerifiedEmail: (email: string) =>\n ctx.runQuery(component.public.userFindByVerifiedEmail, { email }),\n findByVerifiedPhone: (phone: string) =>\n ctx.runQuery(component.public.userFindByVerifiedPhone, { phone }),\n insert: (data: Record<string, unknown>) =>\n ctx.runMutation(component.public.userInsert, {\n data,\n }) as Promise<string>,\n patch: (userId: string, data: Record<string, unknown>) =>\n ctx.runMutation(component.public.userPatch, { userId, data }),\n upsert: (userId: string | undefined, data: Record<string, unknown>) =>\n ctx.runMutation(component.public.userUpsert, {\n userId,\n data,\n }) as Promise<string>,\n },\n accounts: {\n get: (provider: string, providerAccountId: string) =>\n ctx.runQuery(component.public.accountGet, {\n provider,\n providerAccountId,\n }),\n getById: (accountId: string) =>\n ctx.runQuery(component.public.accountGetById, { accountId }),\n create: (args: {\n userId: string;\n provider: string;\n providerAccountId: string;\n secret?: string;\n extend?: Record<string, unknown>;\n }) =>\n ctx.runMutation(\n component.public.accountInsert,\n args,\n ) as Promise<string>,\n patch: (accountId: string, data: Record<string, unknown>) =>\n ctx.runMutation(component.public.accountPatch, { accountId, data }),\n delete: (accountId: string) =>\n ctx.runMutation(component.public.accountDelete, { accountId }),\n },\n sessions: {\n create: (userId: string, expirationTime: number) =>\n ctx.runMutation(component.public.sessionCreate, {\n userId,\n expirationTime,\n }) as Promise<string>,\n getById: (sessionId: string) =>\n ctx.runQuery(component.public.sessionGetById, { sessionId }),\n delete: (sessionId: string) =>\n ctx.runMutation(component.public.sessionDelete, { sessionId }),\n listByUser: (userId: string) =>\n ctx.runQuery(component.public.sessionListByUser, { userId }),\n },\n verifiers: {\n create: (sessionId?: string) =>\n ctx.runMutation(component.public.verifierCreate, {\n sessionId,\n }) as Promise<string>,\n getById: (verifierId: string) =>\n ctx.runQuery(component.public.verifierGetById, { verifierId }),\n getBySignature: (signature: string) =>\n ctx.runQuery(component.public.verifierGetBySignature, { signature }),\n patch: (verifierId: string, data: Record<string, unknown>) =>\n ctx.runMutation(component.public.verifierPatch, { verifierId, data }),\n delete: (verifierId: string) =>\n ctx.runMutation(component.public.verifierDelete, { verifierId }),\n },\n verificationCodes: {\n getByAccountId: (accountId: string) =>\n ctx.runQuery(component.public.verificationCodeGetByAccountId, {\n accountId,\n }),\n getByCode: (code: string) =>\n ctx.runQuery(component.public.verificationCodeGetByCode, { code }),\n create: (args: {\n accountId: string;\n provider: string;\n code: string;\n expirationTime: number;\n verifier?: string;\n emailVerified?: string;\n phoneVerified?: string;\n }) => ctx.runMutation(component.public.verificationCodeCreate, args),\n delete: (verificationCodeId: string) =>\n ctx.runMutation(component.public.verificationCodeDelete, {\n verificationCodeId,\n }),\n },\n refreshTokens: {\n create: (args: {\n sessionId: string;\n expirationTime: number;\n parentRefreshTokenId?: string;\n }) =>\n ctx.runMutation(\n component.public.refreshTokenCreate,\n args,\n ) as Promise<string>,\n getById: (refreshTokenId: string) =>\n ctx.runQuery(component.public.refreshTokenGetById, { refreshTokenId }),\n patch: (refreshTokenId: string, data: Record<string, unknown>) =>\n ctx.runMutation(component.public.refreshTokenPatch, {\n refreshTokenId,\n data,\n }),\n getChildren: (sessionId: string, parentRefreshTokenId: string) =>\n ctx.runQuery(component.public.refreshTokenGetChildren, {\n sessionId,\n parentRefreshTokenId,\n }),\n listBySession: (sessionId: string) =>\n ctx.runQuery(component.public.refreshTokenListBySession, { sessionId }),\n deleteAll: (sessionId: string) =>\n ctx.runMutation(component.public.refreshTokenDeleteAll, { sessionId }),\n getActive: (sessionId: string) =>\n ctx.runQuery(component.public.refreshTokenGetActive, { sessionId }),\n },\n rateLimits: {\n get: (identifier: string) =>\n ctx.runQuery(component.public.rateLimitGet, { identifier }),\n create: (args: {\n identifier: string;\n attemptsLeft: number;\n lastAttemptTime: number;\n }) => ctx.runMutation(component.public.rateLimitCreate, args),\n patch: (rateLimitId: string, data: Record<string, unknown>) =>\n ctx.runMutation(component.public.rateLimitPatch, { rateLimitId, data }),\n delete: (rateLimitId: string) =>\n ctx.runMutation(component.public.rateLimitDelete, { rateLimitId }),\n },\n };\n}\n"],"mappings":"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"}
@@ -1,152 +0,0 @@
1
- import { userIdFromIdentitySubject } from "./identity.js";
2
- import { generateRandomString, requireEnv, sha256 } from "./utils.js";
3
- import { callSignIn } from "./mutations/signin.js";
4
- import { mutateDeviceAuthorize, mutateDeviceDelete, mutateDeviceInsert, mutateDeviceUpdateLastPolled, queryDeviceByCodeHash, queryDeviceByUserCode } from "./types.js";
5
- import { Cv } from "@robelest/fx/convex";
6
- import { Fx } from "@robelest/fx";
7
- import { ConvexError } from "convex/values";
8
-
9
- //#region src/server/device.ts
10
- /**
11
- * Server-side device authorization flow logic (RFC 8628).
12
- *
13
- * Handles the three phases of the device flow:
14
- * 1. (default) — Generate a device code + user code pair
15
- * 2. poll — Device checks whether the user has authorized yet
16
- * 3. verify — Authenticated user links a user code to their session
17
- *
18
- * Uses `@oslojs/crypto/random` for code generation and
19
- * `@oslojs/crypto/sha2` for hashing device codes before storage.
20
- */
21
- const DEVICE_CODE_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
22
- const DEVICE_CODE_LENGTH = 40;
23
- const DEVICE_FLOWS = [
24
- "create",
25
- "poll",
26
- "verify"
27
- ];
28
- /** @internal */
29
- const handleDevice = (ctx, provider, args) => Fx.from({
30
- ok: async () => {
31
- const params = args.params ?? {};
32
- const flow = typeof params.flow === "string" ? params.flow : "create";
33
- if (!DEVICE_FLOWS.some((candidate) => candidate === flow)) throw Cv.error({
34
- code: "DEVICE_MISSING_FLOW",
35
- message: "Missing `flow` parameter. Expected one of: create, poll, verify"
36
- });
37
- if (flow === "create") {
38
- const deviceCode = generateRandomString(DEVICE_CODE_LENGTH, DEVICE_CODE_ALPHABET);
39
- const deviceCodeHash = await sha256(deviceCode);
40
- const rawUserCode = generateRandomString(provider.userCodeLength, provider.charset);
41
- const mid = Math.floor(rawUserCode.length / 2);
42
- const userCode = rawUserCode.slice(0, mid) + "-" + rawUserCode.slice(mid);
43
- await mutateDeviceInsert(ctx, {
44
- deviceCodeHash,
45
- userCode,
46
- expiresAt: Date.now() + provider.expiresIn * 1e3,
47
- interval: provider.interval,
48
- status: "pending"
49
- });
50
- const verificationUri = provider.verificationUri ?? `${process.env.SITE_URL ?? requireEnv("SITE_URL")}/device`;
51
- return {
52
- kind: "deviceCode",
53
- deviceCode,
54
- userCode,
55
- verificationUri,
56
- verificationUriComplete: `${verificationUri}?user_code=${encodeURIComponent(userCode)}`,
57
- expiresIn: provider.expiresIn,
58
- interval: provider.interval
59
- };
60
- }
61
- if (flow === "poll") {
62
- if (typeof params.deviceCode !== "string") throw Cv.error({
63
- code: "DEVICE_MISSING_FLOW",
64
- message: "Missing `deviceCode` parameter for poll flow."
65
- });
66
- const doc$1 = await queryDeviceByCodeHash(ctx, await sha256(params.deviceCode));
67
- if (doc$1 === null) throw Cv.error({
68
- code: "DEVICE_CODE_EXPIRED",
69
- message: "The device code has expired. Please start a new authorization request."
70
- });
71
- if (Date.now() > doc$1.expiresAt) {
72
- await mutateDeviceDelete(ctx, doc$1._id);
73
- throw Cv.error({
74
- code: "DEVICE_CODE_EXPIRED",
75
- message: "The device code has expired. Please start a new authorization request."
76
- });
77
- }
78
- if (doc$1.lastPolledAt !== void 0 && (Date.now() - doc$1.lastPolledAt) / 1e3 < doc$1.interval) throw Cv.error({
79
- code: "DEVICE_SLOW_DOWN",
80
- message: "Polling too frequently. Increase the interval between requests."
81
- });
82
- await mutateDeviceUpdateLastPolled(ctx, doc$1._id, Date.now());
83
- if (doc$1.status === "pending") throw Cv.error({
84
- code: "DEVICE_AUTHORIZATION_PENDING",
85
- message: "The user has not yet authorized this device."
86
- });
87
- if (doc$1.status === "denied") {
88
- await mutateDeviceDelete(ctx, doc$1._id);
89
- throw Cv.error({
90
- code: "DEVICE_CODE_DENIED",
91
- message: "The authorization request was denied."
92
- });
93
- }
94
- if (!doc$1.userId || !doc$1.sessionId) throw Cv.error({
95
- code: "INTERNAL_ERROR",
96
- message: "Authorized device code missing userId or sessionId"
97
- });
98
- await mutateDeviceDelete(ctx, doc$1._id);
99
- return {
100
- kind: "signedIn",
101
- signedIn: await callSignIn(ctx, {
102
- userId: doc$1.userId,
103
- sessionId: doc$1.sessionId,
104
- generateTokens: true
105
- })
106
- };
107
- }
108
- if (typeof params.userCode !== "string") throw Cv.error({
109
- code: "DEVICE_INVALID_USER_CODE",
110
- message: "Missing `userCode` parameter for verify flow."
111
- });
112
- const identity = await ctx.auth.getUserIdentity();
113
- if (identity === null) throw Cv.error({
114
- code: "NOT_SIGNED_IN",
115
- message: "You must be signed in to authorize a device."
116
- });
117
- const userId = userIdFromIdentitySubject(identity.subject);
118
- const doc = await queryDeviceByUserCode(ctx, params.userCode);
119
- if (doc === null) throw Cv.error({
120
- code: "DEVICE_INVALID_USER_CODE",
121
- message: "Invalid or expired user code."
122
- });
123
- if (Date.now() > doc.expiresAt) {
124
- await mutateDeviceDelete(ctx, doc._id);
125
- throw Cv.error({
126
- code: "DEVICE_CODE_EXPIRED",
127
- message: "The device code has expired. Please start a new authorization request."
128
- });
129
- }
130
- if (doc.status !== "pending") throw Cv.error({
131
- code: "DEVICE_ALREADY_AUTHORIZED",
132
- message: "This device code has already been authorized."
133
- });
134
- const signInResult = await callSignIn(ctx, {
135
- userId,
136
- generateTokens: false
137
- });
138
- await mutateDeviceAuthorize(ctx, doc._id, signInResult.userId, signInResult.sessionId);
139
- return {
140
- kind: "signedIn",
141
- signedIn: null
142
- };
143
- },
144
- err: (e) => e instanceof ConvexError ? e : Cv.error({
145
- code: "INTERNAL_ERROR",
146
- message: `Device flow failed: ${String(e)}`
147
- })
148
- });
149
-
150
- //#endregion
151
- export { handleDevice };
152
- //# sourceMappingURL=device.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"device.js","names":["doc"],"sources":["../../../src/server/device.ts"],"sourcesContent":["/**\n * Server-side device authorization flow logic (RFC 8628).\n *\n * Handles the three phases of the device flow:\n * 1. (default) — Generate a device code + user code pair\n * 2. poll — Device checks whether the user has authorized yet\n * 3. verify — Authenticated user links a user code to their session\n *\n * Uses `@oslojs/crypto/random` for code generation and\n * `@oslojs/crypto/sha2` for hashing device codes before storage.\n */\n\nimport { Fx } from \"@robelest/fx\";\nimport { Cv } from \"@robelest/fx/convex\";\nimport { ConvexError } from \"convex/values\";\n\nimport { userIdFromIdentitySubject } from \"./identity\";\nimport { callSignIn } from \"./mutations/index\";\nimport { DeviceProviderConfig, GenericActionCtxWithAuthConfig } from \"./types\";\nimport {\n AuthDataModel,\n SessionInfo,\n mutateDeviceInsert,\n queryDeviceByCodeHash,\n queryDeviceByUserCode,\n mutateDeviceAuthorize,\n mutateDeviceUpdateLastPolled,\n mutateDeviceDelete,\n} from \"./types\";\nimport { generateRandomString, sha256 } from \"./utils\";\nimport { requireEnv } from \"./utils\";\n\ntype EnrichedActionCtx = GenericActionCtxWithAuthConfig<AuthDataModel>;\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEVICE_CODE_ALPHABET =\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\nconst DEVICE_CODE_LENGTH = 40;\nconst DEVICE_FLOWS = [\"create\", \"poll\", \"verify\"] as const;\n\n// ============================================================================\n// Create flow\n// ============================================================================\n\n// ============================================================================\n// Poll flow — pipeline of validations + status dispatch\n// ============================================================================\n\n// ============================================================================\n// Main dispatch\n// ============================================================================\n\ntype DeviceResult =\n | {\n kind: \"deviceCode\";\n deviceCode: string;\n userCode: string;\n verificationUri: string;\n verificationUriComplete: string;\n expiresIn: number;\n interval: number;\n }\n | { kind: \"signedIn\"; signedIn: SessionInfo | null };\n\n/** @internal */\nexport const handleDevice = (\n ctx: EnrichedActionCtx,\n provider: DeviceProviderConfig,\n args: { params?: Record<string, any> },\n): Fx<DeviceResult, ConvexError<any>> =>\n Fx.from({\n ok: async () => {\n const params = (args.params ?? {}) as Record<string, unknown>;\n const flow = (typeof params.flow === \"string\" ? params.flow : \"create\") as\n | \"create\"\n | \"poll\"\n | \"verify\";\n\n if (!DEVICE_FLOWS.some((candidate) => candidate === flow)) {\n throw Cv.error({\n code: \"DEVICE_MISSING_FLOW\",\n message:\n \"Missing `flow` parameter. Expected one of: create, poll, verify\",\n });\n }\n\n if (flow === \"create\") {\n const deviceCode = generateRandomString(\n DEVICE_CODE_LENGTH,\n DEVICE_CODE_ALPHABET,\n );\n const deviceCodeHash = await sha256(deviceCode);\n\n const rawUserCode = generateRandomString(\n provider.userCodeLength,\n provider.charset,\n );\n const mid = Math.floor(rawUserCode.length / 2);\n const userCode =\n rawUserCode.slice(0, mid) + \"-\" + rawUserCode.slice(mid);\n\n const expiresAt = Date.now() + provider.expiresIn * 1000;\n await mutateDeviceInsert(ctx, {\n deviceCodeHash,\n userCode,\n expiresAt,\n interval: provider.interval,\n status: \"pending\",\n });\n\n const verificationUri =\n provider.verificationUri ??\n `${process.env.SITE_URL ?? requireEnv(\"SITE_URL\")}/device`;\n\n return {\n kind: \"deviceCode\" as const,\n deviceCode,\n userCode,\n verificationUri,\n verificationUriComplete: `${verificationUri}?user_code=${encodeURIComponent(userCode)}`,\n expiresIn: provider.expiresIn,\n interval: provider.interval,\n };\n }\n\n if (flow === \"poll\") {\n if (typeof params.deviceCode !== \"string\") {\n throw Cv.error({\n code: \"DEVICE_MISSING_FLOW\",\n message: \"Missing `deviceCode` parameter for poll flow.\",\n });\n }\n\n const hash = await sha256(params.deviceCode);\n const doc = await queryDeviceByCodeHash(ctx, hash);\n if (doc === null) {\n throw Cv.error({\n code: \"DEVICE_CODE_EXPIRED\",\n message:\n \"The device code has expired. Please start a new authorization request.\",\n });\n }\n if (Date.now() > doc.expiresAt) {\n await mutateDeviceDelete(ctx, doc._id);\n throw Cv.error({\n code: \"DEVICE_CODE_EXPIRED\",\n message:\n \"The device code has expired. Please start a new authorization request.\",\n });\n }\n if (\n doc.lastPolledAt !== undefined &&\n (Date.now() - doc.lastPolledAt) / 1000 < doc.interval\n ) {\n throw Cv.error({\n code: \"DEVICE_SLOW_DOWN\",\n message:\n \"Polling too frequently. Increase the interval between requests.\",\n });\n }\n\n await mutateDeviceUpdateLastPolled(ctx, doc._id, Date.now());\n\n if (doc.status === \"pending\") {\n throw Cv.error({\n code: \"DEVICE_AUTHORIZATION_PENDING\",\n message: \"The user has not yet authorized this device.\",\n });\n }\n if (doc.status === \"denied\") {\n await mutateDeviceDelete(ctx, doc._id);\n throw Cv.error({\n code: \"DEVICE_CODE_DENIED\",\n message: \"The authorization request was denied.\",\n });\n }\n\n if (!doc.userId || !doc.sessionId) {\n throw Cv.error({\n code: \"INTERNAL_ERROR\",\n message: \"Authorized device code missing userId or sessionId\",\n });\n }\n\n await mutateDeviceDelete(ctx, doc._id);\n const signInResult = await callSignIn(ctx, {\n userId: doc.userId,\n sessionId: doc.sessionId,\n generateTokens: true,\n });\n return { kind: \"signedIn\" as const, signedIn: signInResult };\n }\n\n if (typeof params.userCode !== \"string\") {\n throw Cv.error({\n code: \"DEVICE_INVALID_USER_CODE\",\n message: \"Missing `userCode` parameter for verify flow.\",\n });\n }\n\n const identity = await ctx.auth.getUserIdentity();\n if (identity === null) {\n throw Cv.error({\n code: \"NOT_SIGNED_IN\",\n message: \"You must be signed in to authorize a device.\",\n });\n }\n\n const userId = userIdFromIdentitySubject(identity.subject);\n const doc = await queryDeviceByUserCode(ctx, params.userCode);\n if (doc === null) {\n throw Cv.error({\n code: \"DEVICE_INVALID_USER_CODE\",\n message: \"Invalid or expired user code.\",\n });\n }\n if (Date.now() > doc.expiresAt) {\n await mutateDeviceDelete(ctx, doc._id);\n throw Cv.error({\n code: \"DEVICE_CODE_EXPIRED\",\n message:\n \"The device code has expired. Please start a new authorization request.\",\n });\n }\n if (doc.status !== \"pending\") {\n throw Cv.error({\n code: \"DEVICE_ALREADY_AUTHORIZED\",\n message: \"This device code has already been authorized.\",\n });\n }\n\n const signInResult = await callSignIn(ctx, {\n userId,\n generateTokens: false,\n });\n await mutateDeviceAuthorize(\n ctx,\n doc._id,\n signInResult.userId,\n signInResult.sessionId,\n );\n return { kind: \"signedIn\" as const, signedIn: null };\n },\n err: (e) =>\n e instanceof ConvexError\n ? e\n : Cv.error({\n code: \"INTERNAL_ERROR\",\n message: `Device flow failed: ${String(e)}`,\n }),\n });\n"],"mappings":"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"}
@@ -1,46 +0,0 @@
1
- import { asRecord } from "./shared.js";
2
-
3
- //#region src/server/enterprise/config.ts
4
- const getProtocolConfig = (config, protocol) => {
5
- const base = asRecord(config);
6
- const direct = base?.[protocol];
7
- const viaProtocols = asRecord(base?.protocols)?.[protocol];
8
- return asRecord(direct) ?? asRecord(viaProtocols) ?? {};
9
- };
10
- /** @internal */
11
- function getOidcConfig(config) {
12
- return getProtocolConfig(config, "oidc");
13
- }
14
- /** @internal */
15
- function getPublicOidcConfig(config) {
16
- const { clientSecret: _clientSecret, ...publicOidc } = getOidcConfig(config);
17
- return publicOidc;
18
- }
19
- /** @internal */
20
- function withOidcSecretState(config, hasClientSecret) {
21
- return {
22
- ...config,
23
- hasClientSecret
24
- };
25
- }
26
- /** @internal */
27
- function getSamlConfig(config) {
28
- return getProtocolConfig(config, "saml");
29
- }
30
- /** @internal */
31
- function upsertProtocolConfig(config, protocol, protocolConfig) {
32
- const base = asRecord(config) ?? {};
33
- const protocols = asRecord(base.protocols) ?? {};
34
- protocols[protocol] = {
35
- ...asRecord(protocols[protocol]),
36
- ...protocolConfig
37
- };
38
- return {
39
- ...base,
40
- protocols
41
- };
42
- }
43
-
44
- //#endregion
45
- export { getOidcConfig, getPublicOidcConfig, getSamlConfig, upsertProtocolConfig, withOidcSecretState };
46
- //# sourceMappingURL=config.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.js","names":[],"sources":["../../../../src/server/enterprise/config.ts"],"sourcesContent":["import { asRecord } from \"./shared\";\n\nconst getProtocolConfig = (config: unknown, protocol: \"oidc\" | \"saml\") => {\n const base = asRecord(config);\n const direct = base?.[protocol];\n const viaProtocols = asRecord(base?.protocols)?.[protocol];\n return asRecord(direct) ?? asRecord(viaProtocols) ?? {};\n};\n\n/** @internal */\nexport function getOidcConfig(config: unknown): Record<string, any> {\n return getProtocolConfig(config, \"oidc\");\n}\n\n/** @internal */\nexport function getPublicOidcConfig(config: unknown): Record<string, any> {\n const oidc = getOidcConfig(config);\n const { clientSecret: _clientSecret, ...publicOidc } = oidc;\n return publicOidc;\n}\n\n/** @internal */\nexport function withOidcSecretState(\n config: Record<string, any>,\n hasClientSecret: boolean,\n) {\n return {\n ...config,\n hasClientSecret,\n };\n}\n\n/** @internal */\nexport function getSamlConfig(config: unknown): Record<string, any> {\n return getProtocolConfig(config, \"saml\");\n}\n\n/** @internal */\nexport function upsertProtocolConfig(\n config: unknown,\n protocol: \"oidc\" | \"saml\",\n protocolConfig: Record<string, unknown>,\n) {\n const base = asRecord(config) ?? {};\n const protocols = asRecord(base.protocols) ?? {};\n protocols[protocol] = {\n ...asRecord(protocols[protocol]),\n ...protocolConfig,\n };\n return { ...base, protocols };\n}\n"],"mappings":";;;AAEA,MAAM,qBAAqB,QAAiB,aAA8B;CACxE,MAAM,OAAO,SAAS,OAAO;CAC7B,MAAM,SAAS,OAAO;CACtB,MAAM,eAAe,SAAS,MAAM,UAAU,GAAG;AACjD,QAAO,SAAS,OAAO,IAAI,SAAS,aAAa,IAAI,EAAE;;;AAIzD,SAAgB,cAAc,QAAsC;AAClE,QAAO,kBAAkB,QAAQ,OAAO;;;AAI1C,SAAgB,oBAAoB,QAAsC;CAExE,MAAM,EAAE,cAAc,eAAe,GAAG,eAD3B,cAAc,OAAO;AAElC,QAAO;;;AAIT,SAAgB,oBACd,QACA,iBACA;AACA,QAAO;EACL,GAAG;EACH;EACD;;;AAIH,SAAgB,cAAc,QAAsC;AAClE,QAAO,kBAAkB,QAAQ,OAAO;;;AAI1C,SAAgB,qBACd,QACA,UACA,gBACA;CACA,MAAM,OAAO,SAAS,OAAO,IAAI,EAAE;CACnC,MAAM,YAAY,SAAS,KAAK,UAAU,IAAI,EAAE;AAChD,WAAU,YAAY;EACpB,GAAG,SAAS,UAAU,UAAU;EAChC,GAAG;EACJ;AACD,QAAO;EAAE,GAAG;EAAM;EAAW"}