@effect-auth/core 0.1.0-alpha.16 → 0.1.0-alpha.19

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 (637) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +307 -133
  3. package/dist/AbuseProtection.d.ts +100 -0
  4. package/dist/AbuseProtection.d.ts.map +1 -0
  5. package/dist/AbuseProtection.js +71 -0
  6. package/dist/AbuseProtection.js.map +1 -0
  7. package/dist/AccessGrant.d.ts +344 -0
  8. package/dist/AccessGrant.d.ts.map +1 -0
  9. package/dist/AccessGrant.js +687 -0
  10. package/dist/AccessGrant.js.map +1 -0
  11. package/dist/ApiKey.d.ts +0 -12
  12. package/dist/ApiKey.d.ts.map +1 -1
  13. package/dist/ApiKey.js +36 -27
  14. package/dist/ApiKey.js.map +1 -1
  15. package/dist/Assurance.d.ts +415 -0
  16. package/dist/Assurance.d.ts.map +1 -0
  17. package/dist/Assurance.js +764 -0
  18. package/dist/Assurance.js.map +1 -0
  19. package/dist/AtomicPlanExecutor.d.ts +28 -0
  20. package/dist/AtomicPlanExecutor.d.ts.map +1 -0
  21. package/dist/AtomicPlanExecutor.js +5 -0
  22. package/dist/AtomicPlanExecutor.js.map +1 -0
  23. package/dist/AuditLog.d.ts +2314 -52
  24. package/dist/AuditLog.d.ts.map +1 -1
  25. package/dist/AuditLog.js +511 -33
  26. package/dist/AuditLog.js.map +1 -1
  27. package/dist/AuthFlow.d.ts +128 -38
  28. package/dist/AuthFlow.d.ts.map +1 -1
  29. package/dist/AuthFlow.js +611 -263
  30. package/dist/AuthFlow.js.map +1 -1
  31. package/dist/AuthRateLimit.d.ts +96 -0
  32. package/dist/AuthRateLimit.d.ts.map +1 -0
  33. package/dist/AuthRateLimit.js +212 -0
  34. package/dist/AuthRateLimit.js.map +1 -0
  35. package/dist/Challenge.d.ts +0 -3
  36. package/dist/Challenge.d.ts.map +1 -1
  37. package/dist/Challenge.js +1 -4
  38. package/dist/Challenge.js.map +1 -1
  39. package/dist/Client.d.ts +205 -10
  40. package/dist/Client.d.ts.map +1 -1
  41. package/dist/Client.js +397 -16
  42. package/dist/Client.js.map +1 -1
  43. package/dist/CloudflareTurnstile.d.ts +28 -0
  44. package/dist/CloudflareTurnstile.d.ts.map +1 -0
  45. package/dist/CloudflareTurnstile.js +205 -0
  46. package/dist/CloudflareTurnstile.js.map +1 -0
  47. package/dist/Crypto.d.ts +0 -3
  48. package/dist/Crypto.d.ts.map +1 -1
  49. package/dist/Crypto.js +1 -4
  50. package/dist/Crypto.js.map +1 -1
  51. package/dist/DelegatedAccessStorageMigrations.d.ts +7 -0
  52. package/dist/DelegatedAccessStorageMigrations.d.ts.map +1 -0
  53. package/dist/DelegatedAccessStorageMigrations.js +159 -0
  54. package/dist/DelegatedAccessStorageMigrations.js.map +1 -0
  55. package/dist/DevEmail.d.ts +44 -0
  56. package/dist/DevEmail.d.ts.map +1 -0
  57. package/dist/DevEmail.js +115 -0
  58. package/dist/DevEmail.js.map +1 -0
  59. package/dist/DevelopmentSeed.d.ts +47 -0
  60. package/dist/DevelopmentSeed.d.ts.map +1 -0
  61. package/dist/DevelopmentSeed.js +337 -0
  62. package/dist/DevelopmentSeed.js.map +1 -0
  63. package/dist/DisposableEmailDomains.d.ts +19 -0
  64. package/dist/DisposableEmailDomains.d.ts.map +1 -0
  65. package/dist/DisposableEmailDomains.js +85 -0
  66. package/dist/DisposableEmailDomains.js.map +1 -0
  67. package/dist/DomainVerification.d.ts +0 -9
  68. package/dist/DomainVerification.d.ts.map +1 -1
  69. package/dist/DomainVerification.js +36 -22
  70. package/dist/DomainVerification.js.map +1 -1
  71. package/dist/DrizzleBunSqliteStorage.d.ts +18 -0
  72. package/dist/DrizzleBunSqliteStorage.d.ts.map +1 -0
  73. package/dist/DrizzleBunSqliteStorage.js +11 -0
  74. package/dist/DrizzleBunSqliteStorage.js.map +1 -0
  75. package/dist/DrizzleD1SqliteStorage.d.ts +4 -4
  76. package/dist/DrizzleD1SqliteStorage.d.ts.map +1 -1
  77. package/dist/DrizzleD1SqliteStorage.js +5 -5
  78. package/dist/DrizzleD1SqliteStorage.js.map +1 -1
  79. package/dist/DrizzleEffectSqliteStorage.d.ts +13 -4
  80. package/dist/DrizzleEffectSqliteStorage.d.ts.map +1 -1
  81. package/dist/DrizzleEffectSqliteStorage.js +71 -4
  82. package/dist/DrizzleEffectSqliteStorage.js.map +1 -1
  83. package/dist/DrizzleNodeSqliteStorage.d.ts +18 -0
  84. package/dist/DrizzleNodeSqliteStorage.d.ts.map +1 -0
  85. package/dist/DrizzleNodeSqliteStorage.js +11 -0
  86. package/dist/DrizzleNodeSqliteStorage.js.map +1 -0
  87. package/dist/DrizzlePostgresStorage.d.ts +26 -0
  88. package/dist/DrizzlePostgresStorage.d.ts.map +1 -0
  89. package/dist/DrizzlePostgresStorage.js +14 -0
  90. package/dist/DrizzlePostgresStorage.js.map +1 -0
  91. package/dist/EffectQbPostgresDelegatedAccessStorage.d.ts +34 -0
  92. package/dist/EffectQbPostgresDelegatedAccessStorage.d.ts.map +1 -0
  93. package/dist/EffectQbPostgresDelegatedAccessStorage.js +499 -0
  94. package/dist/EffectQbPostgresDelegatedAccessStorage.js.map +1 -0
  95. package/dist/EffectQbPostgresStorage.d.ts +178 -0
  96. package/dist/EffectQbPostgresStorage.d.ts.map +1 -0
  97. package/dist/EffectQbPostgresStorage.js +4637 -0
  98. package/dist/EffectQbPostgresStorage.js.map +1 -0
  99. package/dist/EffectQbSqliteDelegatedAccessStorage.d.ts +112 -0
  100. package/dist/EffectQbSqliteDelegatedAccessStorage.d.ts.map +1 -0
  101. package/dist/EffectQbSqliteDelegatedAccessStorage.js +602 -0
  102. package/dist/EffectQbSqliteDelegatedAccessStorage.js.map +1 -0
  103. package/dist/EffectQbSqliteStorage.d.ts +221 -23
  104. package/dist/EffectQbSqliteStorage.d.ts.map +1 -1
  105. package/dist/EffectQbSqliteStorage.js +2064 -135
  106. package/dist/EffectQbSqliteStorage.js.map +1 -1
  107. package/dist/EmailAuth.d.ts +65 -0
  108. package/dist/EmailAuth.d.ts.map +1 -0
  109. package/dist/EmailAuth.js +171 -0
  110. package/dist/EmailAuth.js.map +1 -0
  111. package/dist/EmailIdentityAuth.d.ts +30 -0
  112. package/dist/EmailIdentityAuth.d.ts.map +1 -0
  113. package/dist/EmailIdentityAuth.js +142 -0
  114. package/dist/EmailIdentityAuth.js.map +1 -0
  115. package/dist/EmailOtp.d.ts +10 -11
  116. package/dist/EmailOtp.d.ts.map +1 -1
  117. package/dist/EmailOtp.js +44 -81
  118. package/dist/EmailOtp.js.map +1 -1
  119. package/dist/EmailRisk.d.ts +48 -0
  120. package/dist/EmailRisk.d.ts.map +1 -0
  121. package/dist/EmailRisk.js +33 -0
  122. package/dist/EmailRisk.js.map +1 -0
  123. package/dist/EmailVerification.d.ts +10 -16
  124. package/dist/EmailVerification.d.ts.map +1 -1
  125. package/dist/EmailVerification.js +85 -42
  126. package/dist/EmailVerification.js.map +1 -1
  127. package/dist/Guard.d.ts +11 -0
  128. package/dist/Guard.d.ts.map +1 -0
  129. package/dist/Guard.js +11 -0
  130. package/dist/Guard.js.map +1 -0
  131. package/dist/HibpPwnedPasswords.d.ts +56 -0
  132. package/dist/HibpPwnedPasswords.d.ts.map +1 -0
  133. package/dist/HibpPwnedPasswords.js +232 -0
  134. package/dist/HibpPwnedPasswords.js.map +1 -0
  135. package/dist/HttpApi/AdminPermissionDefinition.d.ts +4 -0
  136. package/dist/HttpApi/AdminPermissionDefinition.d.ts.map +1 -0
  137. package/dist/HttpApi/AdminPermissionDefinition.js +4 -0
  138. package/dist/HttpApi/AdminPermissionDefinition.js.map +1 -0
  139. package/dist/HttpApi/AdminSecurityTimeline.d.ts +4 -0
  140. package/dist/HttpApi/AdminSecurityTimeline.d.ts.map +1 -0
  141. package/dist/HttpApi/AdminSecurityTimeline.js +4 -0
  142. package/dist/HttpApi/AdminSecurityTimeline.js.map +1 -0
  143. package/dist/HttpApi/AdminSession.d.ts +4 -0
  144. package/dist/HttpApi/AdminSession.d.ts.map +1 -0
  145. package/dist/HttpApi/AdminSession.js +4 -0
  146. package/dist/HttpApi/AdminSession.js.map +1 -0
  147. package/dist/HttpApi/AdminTrustedDevice.d.ts +4 -0
  148. package/dist/HttpApi/AdminTrustedDevice.d.ts.map +1 -0
  149. package/dist/HttpApi/AdminTrustedDevice.js +4 -0
  150. package/dist/HttpApi/AdminTrustedDevice.js.map +1 -0
  151. package/dist/HttpApi/Api.d.ts +939 -884
  152. package/dist/HttpApi/Api.d.ts.map +1 -1
  153. package/dist/HttpApi/Api.js +2254 -940
  154. package/dist/HttpApi/Api.js.map +1 -1
  155. package/dist/HttpApi/ApiKey.d.ts +4 -0
  156. package/dist/HttpApi/ApiKey.d.ts.map +1 -0
  157. package/dist/HttpApi/ApiKey.js +4 -0
  158. package/dist/HttpApi/ApiKey.js.map +1 -0
  159. package/dist/HttpApi/Audit.d.ts +6 -0
  160. package/dist/HttpApi/Audit.d.ts.map +1 -0
  161. package/dist/HttpApi/Audit.js +10 -0
  162. package/dist/HttpApi/Audit.js.map +1 -0
  163. package/dist/HttpApi/ClientApi.d.ts +917 -0
  164. package/dist/HttpApi/ClientApi.d.ts.map +1 -0
  165. package/dist/HttpApi/ClientApi.js +101 -0
  166. package/dist/HttpApi/ClientApi.js.map +1 -0
  167. package/dist/HttpApi/EmailAuth.d.ts +6 -0
  168. package/dist/HttpApi/EmailAuth.d.ts.map +1 -0
  169. package/dist/HttpApi/EmailAuth.js +6 -0
  170. package/dist/HttpApi/EmailAuth.js.map +1 -0
  171. package/dist/HttpApi/EmailGuards.d.ts +115 -0
  172. package/dist/HttpApi/EmailGuards.d.ts.map +1 -0
  173. package/dist/HttpApi/EmailGuards.js +191 -0
  174. package/dist/HttpApi/EmailGuards.js.map +1 -0
  175. package/dist/HttpApi/EmailOtp.d.ts +6 -0
  176. package/dist/HttpApi/EmailOtp.d.ts.map +1 -0
  177. package/dist/HttpApi/EmailOtp.js +6 -0
  178. package/dist/HttpApi/EmailOtp.js.map +1 -0
  179. package/dist/HttpApi/EmailVerification.d.ts +6 -0
  180. package/dist/HttpApi/EmailVerification.d.ts.map +1 -0
  181. package/dist/HttpApi/EmailVerification.js +6 -0
  182. package/dist/HttpApi/EmailVerification.js.map +1 -0
  183. package/dist/HttpApi/Endpoints.d.ts +661 -301
  184. package/dist/HttpApi/Endpoints.d.ts.map +1 -1
  185. package/dist/HttpApi/Endpoints.js +207 -120
  186. package/dist/HttpApi/Endpoints.js.map +1 -1
  187. package/dist/HttpApi/Errors.d.ts +37 -10
  188. package/dist/HttpApi/Errors.d.ts.map +1 -1
  189. package/dist/HttpApi/Errors.js +42 -4
  190. package/dist/HttpApi/Errors.js.map +1 -1
  191. package/dist/HttpApi/Identity.d.ts +6 -0
  192. package/dist/HttpApi/Identity.d.ts.map +1 -0
  193. package/dist/HttpApi/Identity.js +6 -0
  194. package/dist/HttpApi/Identity.js.map +1 -0
  195. package/dist/HttpApi/IdentityGuards.d.ts +31 -0
  196. package/dist/HttpApi/IdentityGuards.d.ts.map +1 -0
  197. package/dist/HttpApi/IdentityGuards.js +33 -0
  198. package/dist/HttpApi/IdentityGuards.js.map +1 -0
  199. package/dist/HttpApi/Jwt.d.ts +4 -0
  200. package/dist/HttpApi/Jwt.d.ts.map +1 -0
  201. package/dist/HttpApi/Jwt.js +4 -0
  202. package/dist/HttpApi/Jwt.js.map +1 -0
  203. package/dist/HttpApi/JwtDiscovery.d.ts +4 -0
  204. package/dist/HttpApi/JwtDiscovery.d.ts.map +1 -0
  205. package/dist/HttpApi/JwtDiscovery.js +4 -0
  206. package/dist/HttpApi/JwtDiscovery.js.map +1 -0
  207. package/dist/HttpApi/LoginApproval.d.ts +5 -0
  208. package/dist/HttpApi/LoginApproval.d.ts.map +1 -0
  209. package/dist/HttpApi/LoginApproval.js +5 -0
  210. package/dist/HttpApi/LoginApproval.js.map +1 -0
  211. package/dist/HttpApi/LoginNotification.d.ts +5 -0
  212. package/dist/HttpApi/LoginNotification.d.ts.map +1 -0
  213. package/dist/HttpApi/LoginNotification.js +5 -0
  214. package/dist/HttpApi/LoginNotification.js.map +1 -0
  215. package/dist/HttpApi/MagicLink.d.ts +6 -0
  216. package/dist/HttpApi/MagicLink.d.ts.map +1 -0
  217. package/dist/HttpApi/MagicLink.js +6 -0
  218. package/dist/HttpApi/MagicLink.js.map +1 -0
  219. package/dist/HttpApi/Mfa.d.ts +5 -0
  220. package/dist/HttpApi/Mfa.d.ts.map +1 -0
  221. package/dist/HttpApi/Mfa.js +5 -0
  222. package/dist/HttpApi/Mfa.js.map +1 -0
  223. package/dist/HttpApi/Middleware.d.ts +26 -0
  224. package/dist/HttpApi/Middleware.d.ts.map +1 -0
  225. package/dist/HttpApi/Middleware.js +13 -0
  226. package/dist/HttpApi/Middleware.js.map +1 -0
  227. package/dist/HttpApi/OAuth.d.ts +4 -0
  228. package/dist/HttpApi/OAuth.d.ts.map +1 -0
  229. package/dist/HttpApi/OAuth.js +4 -0
  230. package/dist/HttpApi/OAuth.js.map +1 -0
  231. package/dist/HttpApi/OAuthDeviceAuthorization.d.ts +106 -0
  232. package/dist/HttpApi/OAuthDeviceAuthorization.d.ts.map +1 -0
  233. package/dist/HttpApi/OAuthDeviceAuthorization.js +415 -0
  234. package/dist/HttpApi/OAuthDeviceAuthorization.js.map +1 -0
  235. package/dist/HttpApi/OAuthProviderAuthorization.d.ts +4 -0
  236. package/dist/HttpApi/OAuthProviderAuthorization.d.ts.map +1 -0
  237. package/dist/HttpApi/OAuthProviderAuthorization.js +4 -0
  238. package/dist/HttpApi/OAuthProviderAuthorization.js.map +1 -0
  239. package/dist/HttpApi/OAuthToken.d.ts +4 -0
  240. package/dist/HttpApi/OAuthToken.d.ts.map +1 -0
  241. package/dist/HttpApi/OAuthToken.js +4 -0
  242. package/dist/HttpApi/OAuthToken.js.map +1 -0
  243. package/dist/HttpApi/OidcDiscovery.d.ts +4 -0
  244. package/dist/HttpApi/OidcDiscovery.d.ts.map +1 -0
  245. package/dist/HttpApi/OidcDiscovery.js +4 -0
  246. package/dist/HttpApi/OidcDiscovery.js.map +1 -0
  247. package/dist/HttpApi/Operations/AdminPermissionDefinition.d.ts +28 -0
  248. package/dist/HttpApi/Operations/AdminPermissionDefinition.d.ts.map +1 -0
  249. package/dist/HttpApi/Operations/AdminPermissionDefinition.js +5 -0
  250. package/dist/HttpApi/Operations/AdminPermissionDefinition.js.map +1 -0
  251. package/dist/HttpApi/Operations/AdminSession.d.ts +16 -0
  252. package/dist/HttpApi/Operations/AdminSession.d.ts.map +1 -0
  253. package/dist/HttpApi/Operations/AdminSession.js +5 -0
  254. package/dist/HttpApi/Operations/AdminSession.js.map +1 -0
  255. package/dist/HttpApi/Operations/ApiKey.d.ts +16 -0
  256. package/dist/HttpApi/Operations/ApiKey.d.ts.map +1 -0
  257. package/dist/HttpApi/Operations/ApiKey.js +5 -0
  258. package/dist/HttpApi/Operations/ApiKey.js.map +1 -0
  259. package/dist/HttpApi/Operations/Discovery.d.ts +19 -0
  260. package/dist/HttpApi/Operations/Discovery.d.ts.map +1 -0
  261. package/dist/HttpApi/Operations/Discovery.js +7 -0
  262. package/dist/HttpApi/Operations/Discovery.js.map +1 -0
  263. package/dist/HttpApi/Operations/EmailAuth.d.ts +12 -0
  264. package/dist/HttpApi/Operations/EmailAuth.d.ts.map +1 -0
  265. package/dist/HttpApi/Operations/EmailAuth.js +5 -0
  266. package/dist/HttpApi/Operations/EmailAuth.js.map +1 -0
  267. package/dist/HttpApi/Operations/EmailOtp.d.ts +14 -0
  268. package/dist/HttpApi/Operations/EmailOtp.d.ts.map +1 -0
  269. package/dist/HttpApi/Operations/EmailOtp.js +5 -0
  270. package/dist/HttpApi/Operations/EmailOtp.js.map +1 -0
  271. package/dist/HttpApi/Operations/EmailVerification.d.ts +14 -0
  272. package/dist/HttpApi/Operations/EmailVerification.d.ts.map +1 -0
  273. package/dist/HttpApi/Operations/EmailVerification.js +5 -0
  274. package/dist/HttpApi/Operations/EmailVerification.js.map +1 -0
  275. package/dist/HttpApi/Operations/HttpOperation.d.ts +4 -0
  276. package/dist/HttpApi/Operations/HttpOperation.d.ts.map +1 -0
  277. package/dist/HttpApi/Operations/HttpOperation.js +2 -0
  278. package/dist/HttpApi/Operations/HttpOperation.js.map +1 -0
  279. package/dist/HttpApi/Operations/Identity.d.ts +22 -0
  280. package/dist/HttpApi/Operations/Identity.d.ts.map +1 -0
  281. package/dist/HttpApi/Operations/Identity.js +5 -0
  282. package/dist/HttpApi/Operations/Identity.js.map +1 -0
  283. package/dist/HttpApi/Operations/Jwt.d.ts +14 -0
  284. package/dist/HttpApi/Operations/Jwt.d.ts.map +1 -0
  285. package/dist/HttpApi/Operations/Jwt.js +5 -0
  286. package/dist/HttpApi/Operations/Jwt.js.map +1 -0
  287. package/dist/HttpApi/Operations/LoginApproval.d.ts +16 -0
  288. package/dist/HttpApi/Operations/LoginApproval.d.ts.map +1 -0
  289. package/dist/HttpApi/Operations/LoginApproval.js +5 -0
  290. package/dist/HttpApi/Operations/LoginApproval.js.map +1 -0
  291. package/dist/HttpApi/Operations/MagicLink.d.ts +14 -0
  292. package/dist/HttpApi/Operations/MagicLink.d.ts.map +1 -0
  293. package/dist/HttpApi/Operations/MagicLink.js +5 -0
  294. package/dist/HttpApi/Operations/MagicLink.js.map +1 -0
  295. package/dist/HttpApi/Operations/Mfa.d.ts +24 -0
  296. package/dist/HttpApi/Operations/Mfa.d.ts.map +1 -0
  297. package/dist/HttpApi/Operations/Mfa.js +5 -0
  298. package/dist/HttpApi/Operations/Mfa.js.map +1 -0
  299. package/dist/HttpApi/Operations/OAuth.d.ts +20 -0
  300. package/dist/HttpApi/Operations/OAuth.d.ts.map +1 -0
  301. package/dist/HttpApi/Operations/OAuth.js +5 -0
  302. package/dist/HttpApi/Operations/OAuth.js.map +1 -0
  303. package/dist/HttpApi/Operations/OAuthDeviceAuthorization.d.ts +23 -0
  304. package/dist/HttpApi/Operations/OAuthDeviceAuthorization.d.ts.map +1 -0
  305. package/dist/HttpApi/Operations/OAuthDeviceAuthorization.js +7 -0
  306. package/dist/HttpApi/Operations/OAuthDeviceAuthorization.js.map +1 -0
  307. package/dist/HttpApi/Operations/OAuthProviderAuthorization.d.ts +12 -0
  308. package/dist/HttpApi/Operations/OAuthProviderAuthorization.d.ts.map +1 -0
  309. package/dist/HttpApi/Operations/OAuthProviderAuthorization.js +5 -0
  310. package/dist/HttpApi/Operations/OAuthProviderAuthorization.js.map +1 -0
  311. package/dist/HttpApi/Operations/OAuthToken.d.ts +26 -0
  312. package/dist/HttpApi/Operations/OAuthToken.d.ts.map +1 -0
  313. package/dist/HttpApi/Operations/OAuthToken.js +9 -0
  314. package/dist/HttpApi/Operations/OAuthToken.js.map +1 -0
  315. package/dist/HttpApi/Operations/Passkey.d.ts +22 -0
  316. package/dist/HttpApi/Operations/Passkey.d.ts.map +1 -0
  317. package/dist/HttpApi/Operations/Passkey.js +5 -0
  318. package/dist/HttpApi/Operations/Passkey.js.map +1 -0
  319. package/dist/HttpApi/Operations/Password.d.ts +22 -0
  320. package/dist/HttpApi/Operations/Password.d.ts.map +1 -0
  321. package/dist/HttpApi/Operations/Password.js +5 -0
  322. package/dist/HttpApi/Operations/Password.js.map +1 -0
  323. package/dist/HttpApi/Operations/RecoveryCodes.d.ts +20 -0
  324. package/dist/HttpApi/Operations/RecoveryCodes.d.ts.map +1 -0
  325. package/dist/HttpApi/Operations/RecoveryCodes.js +5 -0
  326. package/dist/HttpApi/Operations/RecoveryCodes.js.map +1 -0
  327. package/dist/HttpApi/Operations/RefreshToken.d.ts +12 -0
  328. package/dist/HttpApi/Operations/RefreshToken.d.ts.map +1 -0
  329. package/dist/HttpApi/Operations/RefreshToken.js +5 -0
  330. package/dist/HttpApi/Operations/RefreshToken.js.map +1 -0
  331. package/dist/HttpApi/Operations/Security.d.ts +12 -0
  332. package/dist/HttpApi/Operations/Security.d.ts.map +1 -0
  333. package/dist/HttpApi/Operations/Security.js +5 -0
  334. package/dist/HttpApi/Operations/Security.js.map +1 -0
  335. package/dist/HttpApi/Operations/SecurityTimeline.d.ts +19 -0
  336. package/dist/HttpApi/Operations/SecurityTimeline.d.ts.map +1 -0
  337. package/dist/HttpApi/Operations/SecurityTimeline.js +7 -0
  338. package/dist/HttpApi/Operations/SecurityTimeline.js.map +1 -0
  339. package/dist/HttpApi/Operations/Session.d.ts +22 -0
  340. package/dist/HttpApi/Operations/Session.d.ts.map +1 -0
  341. package/dist/HttpApi/Operations/Session.js +5 -0
  342. package/dist/HttpApi/Operations/Session.js.map +1 -0
  343. package/dist/HttpApi/Operations/StepUp.d.ts +22 -0
  344. package/dist/HttpApi/Operations/StepUp.d.ts.map +1 -0
  345. package/dist/HttpApi/Operations/StepUp.js +5 -0
  346. package/dist/HttpApi/Operations/StepUp.js.map +1 -0
  347. package/dist/HttpApi/Operations/Totp.d.ts +20 -0
  348. package/dist/HttpApi/Operations/Totp.d.ts.map +1 -0
  349. package/dist/HttpApi/Operations/Totp.js +5 -0
  350. package/dist/HttpApi/Operations/Totp.js.map +1 -0
  351. package/dist/HttpApi/Operations/TrustedDevice.d.ts +23 -0
  352. package/dist/HttpApi/Operations/TrustedDevice.d.ts.map +1 -0
  353. package/dist/HttpApi/Operations/TrustedDevice.js +7 -0
  354. package/dist/HttpApi/Operations/TrustedDevice.js.map +1 -0
  355. package/dist/HttpApi/Operations/index.d.ts +28 -0
  356. package/dist/HttpApi/Operations/index.d.ts.map +1 -0
  357. package/dist/HttpApi/Operations/index.js +28 -0
  358. package/dist/HttpApi/Operations/index.js.map +1 -0
  359. package/dist/HttpApi/Passkey.d.ts +5 -0
  360. package/dist/HttpApi/Passkey.d.ts.map +1 -0
  361. package/dist/HttpApi/Passkey.js +5 -0
  362. package/dist/HttpApi/Passkey.js.map +1 -0
  363. package/dist/HttpApi/Password.d.ts +220 -0
  364. package/dist/HttpApi/Password.d.ts.map +1 -0
  365. package/dist/HttpApi/Password.js +237 -0
  366. package/dist/HttpApi/Password.js.map +1 -0
  367. package/dist/HttpApi/PasswordContract.d.ts +307 -0
  368. package/dist/HttpApi/PasswordContract.d.ts.map +1 -0
  369. package/dist/HttpApi/PasswordContract.js +63 -0
  370. package/dist/HttpApi/PasswordContract.js.map +1 -0
  371. package/dist/HttpApi/PasswordGuards.d.ts +82 -0
  372. package/dist/HttpApi/PasswordGuards.d.ts.map +1 -0
  373. package/dist/HttpApi/PasswordGuards.js +179 -0
  374. package/dist/HttpApi/PasswordGuards.js.map +1 -0
  375. package/dist/HttpApi/RecoveryCodes.d.ts +5 -0
  376. package/dist/HttpApi/RecoveryCodes.d.ts.map +1 -0
  377. package/dist/HttpApi/RecoveryCodes.js +5 -0
  378. package/dist/HttpApi/RecoveryCodes.js.map +1 -0
  379. package/dist/HttpApi/RefreshToken.d.ts +4 -0
  380. package/dist/HttpApi/RefreshToken.d.ts.map +1 -0
  381. package/dist/HttpApi/RefreshToken.js +4 -0
  382. package/dist/HttpApi/RefreshToken.js.map +1 -0
  383. package/dist/HttpApi/RequestGuards.d.ts +42 -0
  384. package/dist/HttpApi/RequestGuards.d.ts.map +1 -0
  385. package/dist/HttpApi/RequestGuards.js +194 -0
  386. package/dist/HttpApi/RequestGuards.js.map +1 -0
  387. package/dist/HttpApi/Schemas.d.ts +399 -84
  388. package/dist/HttpApi/Schemas.d.ts.map +1 -1
  389. package/dist/HttpApi/Schemas.js +225 -27
  390. package/dist/HttpApi/Schemas.js.map +1 -1
  391. package/dist/HttpApi/Security.d.ts +12 -93
  392. package/dist/HttpApi/Security.d.ts.map +1 -1
  393. package/dist/HttpApi/Security.js +65 -356
  394. package/dist/HttpApi/Security.js.map +1 -1
  395. package/dist/HttpApi/SecurityTimeline.d.ts +4 -0
  396. package/dist/HttpApi/SecurityTimeline.d.ts.map +1 -0
  397. package/dist/HttpApi/SecurityTimeline.js +4 -0
  398. package/dist/HttpApi/SecurityTimeline.js.map +1 -0
  399. package/dist/HttpApi/Session.d.ts +5 -0
  400. package/dist/HttpApi/Session.d.ts.map +1 -0
  401. package/dist/HttpApi/Session.js +5 -0
  402. package/dist/HttpApi/Session.js.map +1 -0
  403. package/dist/HttpApi/SessionGuards.d.ts +15 -0
  404. package/dist/HttpApi/SessionGuards.d.ts.map +1 -0
  405. package/dist/HttpApi/SessionGuards.js +37 -0
  406. package/dist/HttpApi/SessionGuards.js.map +1 -0
  407. package/dist/HttpApi/StepUp.d.ts +5 -0
  408. package/dist/HttpApi/StepUp.d.ts.map +1 -0
  409. package/dist/HttpApi/StepUp.js +5 -0
  410. package/dist/HttpApi/StepUp.js.map +1 -0
  411. package/dist/HttpApi/Totp.d.ts +5 -0
  412. package/dist/HttpApi/Totp.d.ts.map +1 -0
  413. package/dist/HttpApi/Totp.js +5 -0
  414. package/dist/HttpApi/Totp.js.map +1 -0
  415. package/dist/HttpApi/Transport.d.ts +4 -6
  416. package/dist/HttpApi/Transport.d.ts.map +1 -1
  417. package/dist/HttpApi/Transport.js +62 -36
  418. package/dist/HttpApi/Transport.js.map +1 -1
  419. package/dist/HttpApi/TrustedDevice.d.ts +4 -0
  420. package/dist/HttpApi/TrustedDevice.d.ts.map +1 -0
  421. package/dist/HttpApi/TrustedDevice.js +4 -0
  422. package/dist/HttpApi/TrustedDevice.js.map +1 -0
  423. package/dist/HttpApi/index.d.ts +11 -3
  424. package/dist/HttpApi/index.d.ts.map +1 -1
  425. package/dist/HttpApi/index.js +10 -2
  426. package/dist/HttpApi/index.js.map +1 -1
  427. package/dist/Identity.d.ts +138 -0
  428. package/dist/Identity.d.ts.map +1 -0
  429. package/dist/Identity.js +105 -0
  430. package/dist/Identity.js.map +1 -0
  431. package/dist/IdentityManagement.d.ts +189 -0
  432. package/dist/IdentityManagement.d.ts.map +1 -0
  433. package/dist/IdentityManagement.js +317 -0
  434. package/dist/IdentityManagement.js.map +1 -0
  435. package/dist/IncidentAction.d.ts +1 -4
  436. package/dist/IncidentAction.d.ts.map +1 -1
  437. package/dist/IncidentAction.js +15 -9
  438. package/dist/IncidentAction.js.map +1 -1
  439. package/dist/Internal.d.ts +2 -0
  440. package/dist/Internal.d.ts.map +1 -1
  441. package/dist/Internal.js +30 -0
  442. package/dist/Internal.js.map +1 -1
  443. package/dist/Invitation.d.ts +362 -0
  444. package/dist/Invitation.d.ts.map +1 -0
  445. package/dist/Invitation.js +633 -0
  446. package/dist/Invitation.js.map +1 -0
  447. package/dist/IpQualityScore.d.ts +38 -0
  448. package/dist/IpQualityScore.d.ts.map +1 -0
  449. package/dist/IpQualityScore.js +215 -0
  450. package/dist/IpQualityScore.js.map +1 -0
  451. package/dist/Jwt.d.ts +8 -29
  452. package/dist/Jwt.d.ts.map +1 -1
  453. package/dist/Jwt.js +67 -56
  454. package/dist/Jwt.js.map +1 -1
  455. package/dist/LoginApproval.d.ts +15 -30
  456. package/dist/LoginApproval.d.ts.map +1 -1
  457. package/dist/LoginApproval.js +47 -41
  458. package/dist/LoginApproval.js.map +1 -1
  459. package/dist/LoginNotification.d.ts +7 -11
  460. package/dist/LoginNotification.d.ts.map +1 -1
  461. package/dist/LoginNotification.js +30 -17
  462. package/dist/LoginNotification.js.map +1 -1
  463. package/dist/LoginRisk.d.ts +11 -13
  464. package/dist/LoginRisk.d.ts.map +1 -1
  465. package/dist/LoginRisk.js +66 -26
  466. package/dist/LoginRisk.js.map +1 -1
  467. package/dist/LoginRiskEnrichment.d.ts +145 -0
  468. package/dist/LoginRiskEnrichment.d.ts.map +1 -0
  469. package/dist/LoginRiskEnrichment.js +220 -0
  470. package/dist/LoginRiskEnrichment.js.map +1 -0
  471. package/dist/MagicLink.d.ts +9 -8
  472. package/dist/MagicLink.d.ts.map +1 -1
  473. package/dist/MagicLink.js +40 -73
  474. package/dist/MagicLink.js.map +1 -1
  475. package/dist/Mailer.d.ts +19 -12
  476. package/dist/Mailer.d.ts.map +1 -1
  477. package/dist/Mailer.js +10 -12
  478. package/dist/Mailer.js.map +1 -1
  479. package/dist/OAuth.d.ts +138 -96
  480. package/dist/OAuth.d.ts.map +1 -1
  481. package/dist/OAuth.js +522 -221
  482. package/dist/OAuth.js.map +1 -1
  483. package/dist/OAuthDeviceAuthorization.d.ts +378 -0
  484. package/dist/OAuthDeviceAuthorization.d.ts.map +1 -0
  485. package/dist/OAuthDeviceAuthorization.js +860 -0
  486. package/dist/OAuthDeviceAuthorization.js.map +1 -0
  487. package/dist/OAuthDeviceClient.d.ts +76 -0
  488. package/dist/OAuthDeviceClient.d.ts.map +1 -0
  489. package/dist/OAuthDeviceClient.js +362 -0
  490. package/dist/OAuthDeviceClient.js.map +1 -0
  491. package/dist/Passkey.d.ts +15 -17
  492. package/dist/Passkey.d.ts.map +1 -1
  493. package/dist/Passkey.js +86 -39
  494. package/dist/Passkey.js.map +1 -1
  495. package/dist/PasskeyBrowser.d.ts +39 -0
  496. package/dist/PasskeyBrowser.d.ts.map +1 -0
  497. package/dist/PasskeyBrowser.js +206 -0
  498. package/dist/PasskeyBrowser.js.map +1 -0
  499. package/dist/PasskeySimpleWebAuthn.d.ts.map +1 -1
  500. package/dist/PasskeySimpleWebAuthn.js +19 -7
  501. package/dist/PasskeySimpleWebAuthn.js.map +1 -1
  502. package/dist/Password.d.ts +71 -37
  503. package/dist/Password.d.ts.map +1 -1
  504. package/dist/Password.js +295 -81
  505. package/dist/Password.js.map +1 -1
  506. package/dist/PasswordRisk.d.ts +63 -0
  507. package/dist/PasswordRisk.d.ts.map +1 -0
  508. package/dist/PasswordRisk.js +37 -0
  509. package/dist/PasswordRisk.js.map +1 -0
  510. package/dist/Permission.d.ts +308 -0
  511. package/dist/Permission.d.ts.map +1 -0
  512. package/dist/Permission.js +827 -0
  513. package/dist/Permission.js.map +1 -0
  514. package/dist/Policy.d.ts +31 -18
  515. package/dist/Policy.d.ts.map +1 -1
  516. package/dist/Policy.js +58 -14
  517. package/dist/Policy.js.map +1 -1
  518. package/dist/PostgresDelegatedAccessStorageMigrations.d.ts +7 -0
  519. package/dist/PostgresDelegatedAccessStorageMigrations.d.ts.map +1 -0
  520. package/dist/PostgresDelegatedAccessStorageMigrations.js +119 -0
  521. package/dist/PostgresDelegatedAccessStorageMigrations.js.map +1 -0
  522. package/dist/PostgresStorageMigrations.d.ts +16 -0
  523. package/dist/PostgresStorageMigrations.d.ts.map +1 -0
  524. package/dist/PostgresStorageMigrations.js +674 -0
  525. package/dist/PostgresStorageMigrations.js.map +1 -0
  526. package/dist/Privacy.d.ts +0 -3
  527. package/dist/Privacy.d.ts.map +1 -1
  528. package/dist/Privacy.js +2 -5
  529. package/dist/Privacy.js.map +1 -1
  530. package/dist/RateLimiter.d.ts +0 -3
  531. package/dist/RateLimiter.d.ts.map +1 -1
  532. package/dist/RateLimiter.js +1 -4
  533. package/dist/RateLimiter.js.map +1 -1
  534. package/dist/RecoveryCode.d.ts +83 -11
  535. package/dist/RecoveryCode.d.ts.map +1 -1
  536. package/dist/RecoveryCode.js +273 -75
  537. package/dist/RecoveryCode.js.map +1 -1
  538. package/dist/RecoveryPolicy.d.ts +81 -0
  539. package/dist/RecoveryPolicy.d.ts.map +1 -0
  540. package/dist/RecoveryPolicy.js +119 -0
  541. package/dist/RecoveryPolicy.js.map +1 -0
  542. package/dist/RefreshToken.d.ts +0 -9
  543. package/dist/RefreshToken.d.ts.map +1 -1
  544. package/dist/RefreshToken.js +31 -22
  545. package/dist/RefreshToken.js.map +1 -1
  546. package/dist/Retention.d.ts +6 -1
  547. package/dist/Retention.d.ts.map +1 -1
  548. package/dist/Retention.js +49 -12
  549. package/dist/Retention.js.map +1 -1
  550. package/dist/SecurityTimeline.d.ts +1 -4
  551. package/dist/SecurityTimeline.d.ts.map +1 -1
  552. package/dist/SecurityTimeline.js +110 -17
  553. package/dist/SecurityTimeline.js.map +1 -1
  554. package/dist/Sessions.d.ts +124 -29
  555. package/dist/Sessions.d.ts.map +1 -1
  556. package/dist/Sessions.js +626 -94
  557. package/dist/Sessions.js.map +1 -1
  558. package/dist/SqliteStorageSchemaData.d.ts +2 -0
  559. package/dist/SqliteStorageSchemaData.d.ts.map +1 -0
  560. package/dist/SqliteStorageSchemaData.js +508 -0
  561. package/dist/SqliteStorageSchemaData.js.map +1 -0
  562. package/dist/StepUp.d.ts +132 -11
  563. package/dist/StepUp.d.ts.map +1 -1
  564. package/dist/StepUp.js +387 -19
  565. package/dist/StepUp.js.map +1 -1
  566. package/dist/Storage.d.ts +89 -23
  567. package/dist/Storage.d.ts.map +1 -1
  568. package/dist/Storage.js +10 -12
  569. package/dist/Storage.js.map +1 -1
  570. package/dist/StorageMigrations.d.ts +7 -1
  571. package/dist/StorageMigrations.d.ts.map +1 -1
  572. package/dist/StorageMigrations.js +256 -0
  573. package/dist/StorageMigrations.js.map +1 -1
  574. package/dist/StorageSchemaGenerator.d.ts +544 -0
  575. package/dist/StorageSchemaGenerator.d.ts.map +1 -0
  576. package/dist/StorageSchemaGenerator.js +1418 -0
  577. package/dist/StorageSchemaGenerator.js.map +1 -0
  578. package/dist/StrongFactor.d.ts +64 -0
  579. package/dist/StrongFactor.d.ts.map +1 -0
  580. package/dist/StrongFactor.js +100 -0
  581. package/dist/StrongFactor.js.map +1 -0
  582. package/dist/Testing.js +2 -2
  583. package/dist/Testing.js.map +1 -1
  584. package/dist/Totp.d.ts +88 -13
  585. package/dist/Totp.d.ts.map +1 -1
  586. package/dist/Totp.js +192 -34
  587. package/dist/Totp.js.map +1 -1
  588. package/dist/TrustedDevice.d.ts +0 -9
  589. package/dist/TrustedDevice.d.ts.map +1 -1
  590. package/dist/TrustedDevice.js +15 -17
  591. package/dist/TrustedDevice.js.map +1 -1
  592. package/dist/WaitUntil.d.ts +0 -3
  593. package/dist/WaitUntil.d.ts.map +1 -1
  594. package/dist/WaitUntil.js +1 -4
  595. package/dist/WaitUntil.js.map +1 -1
  596. package/dist/Webhook.d.ts +42 -12
  597. package/dist/Webhook.d.ts.map +1 -1
  598. package/dist/Webhook.js +165 -26
  599. package/dist/Webhook.js.map +1 -1
  600. package/dist/alchemy/cloudflare/Email.d.ts.map +1 -1
  601. package/dist/alchemy/cloudflare/Email.js +9 -4
  602. package/dist/alchemy/cloudflare/Email.js.map +1 -1
  603. package/dist/cloudflare/Email.js +1 -1
  604. package/dist/cloudflare/Email.js.map +1 -1
  605. package/dist/cloudflare/RequestMetadata.d.ts +49 -0
  606. package/dist/cloudflare/RequestMetadata.d.ts.map +1 -0
  607. package/dist/cloudflare/RequestMetadata.js +71 -0
  608. package/dist/cloudflare/RequestMetadata.js.map +1 -0
  609. package/dist/index.d.ts +0 -35
  610. package/dist/index.d.ts.map +1 -1
  611. package/dist/index.js +0 -35
  612. package/dist/index.js.map +1 -1
  613. package/dist/internal/AuthFlowFinalizer.d.ts +31 -0
  614. package/dist/internal/AuthFlowFinalizer.d.ts.map +1 -0
  615. package/dist/internal/AuthFlowFinalizer.js +182 -0
  616. package/dist/internal/AuthFlowFinalizer.js.map +1 -0
  617. package/migrations/0001_auth_storage.sql +1 -0
  618. package/migrations/0006_auth_totp_factor.sql +1 -0
  619. package/migrations/0024_auth_permission.sql +39 -0
  620. package/migrations/0025_auth_permission_definition.sql +19 -0
  621. package/migrations/0026_auth_user_identity.sql +59 -0
  622. package/migrations/0027_auth_audit_log_storage_order.sql +46 -0
  623. package/migrations/0028_auth_oauth_client_secret_key.sql +39 -0
  624. package/migrations/0029_auth_oauth_device_authorization.sql +28 -0
  625. package/migrations/delegated-access/0001_auth_delegated_access.sql +152 -0
  626. package/migrations/postgres/0001_auth_core.sql +77 -0
  627. package/migrations/postgres/0002_auth_security_oauth.sql +65 -0
  628. package/migrations/postgres/0003_auth_credentials_tokens.sql +43 -0
  629. package/migrations/postgres/0004_auth_security_history.sql +103 -0
  630. package/migrations/postgres/0005_auth_webhooks.sql +29 -0
  631. package/migrations/postgres/0006_auth_domain_timeline.sql +50 -0
  632. package/migrations/postgres/0007_auth_oauth_clients.sql +85 -0
  633. package/migrations/postgres/0008_auth_oauth_tokens.sql +63 -0
  634. package/migrations/postgres/0009_auth_permissions.sql +66 -0
  635. package/migrations/postgres/0010_auth_oauth_device_authorization.sql +50 -0
  636. package/migrations/postgres/delegated-access/0001_auth_delegated_access.sql +112 -0
  637. package/package.json +309 -2
@@ -0,0 +1,4637 @@
1
+ // oxlint-disable complexity, promise/prefer-await-to-then, typescript/no-explicit-any
2
+ import { Cause, Data, Effect, Layer, Option, Redacted, Schema } from "effect";
3
+ import { Column, Executor as CoreExecutor, Query, RowSet, Scalar, Table, } from "effect-qb";
4
+ import { Column as PostgresColumn, Errors as PostgresErrors, Executor, Jsonb, Query as PostgresQuery, Renderer, } from "effect-qb/postgres";
5
+ import { ApiKeyId, ApiKeyPrefix, ApiKeySecretHash, ApiKeyStore, ApiKeyStoreError, } from "./ApiKey.js";
6
+ import { parseAuthenticationEvents } from "./Assurance.js";
7
+ import { AtomicPlanError } from "./AtomicPlanExecutor.js";
8
+ import { AuditLogStore, AuditLogStoreError, auditEventActorUserId, auditEventUserId, decodeAuditEvent, filterAuditLogEvents, } from "./AuditLog.js";
9
+ import { DomainName, DomainVerificationId, DomainVerificationProofToken, DomainVerificationStore, DomainVerificationStoreError, } from "./DomainVerification.js";
10
+ import { AuthFlowId, ChallengeId, CredentialId, Email, IdentityId, OAuthAccountId, OAuthClientId, OAuthProviderId, PermissionId, RoleId, SessionId, UnixMillis, UserId, } from "./Identifiers.js";
11
+ import { isIdentityLoginEligible } from "./Identity.js";
12
+ import { currentUnixMillis } from "./Internal.js";
13
+ import { JwtError, JwtRevocationStore } from "./Jwt.js";
14
+ import { LoginApprovalReviewError, LoginApprovalReviewStore, } from "./LoginApproval.js";
15
+ import { LoginRiskContext, LoginRiskHistory, LoginRiskHistoryError, LoginRiskSignal, maxLoginRiskLevel, } from "./LoginRisk.js";
16
+ import { OAuthAuthorizationCodeStore, OAuthAuthorizationCodeStoreError, OAuthAccountStore, OAuthAccountStoreError, OAuthClientSecretHash, OAuthClientSecretPrefix, OAuthClientSecretStore, OAuthClientSecretStoreError, OAuthClientStore, OAuthClientStoreError, OAuthCodeChallenge, OAuthConsentStore, OAuthConsentStoreError, OAuthIdentityBridgeConflictError, OAuthIdentityBridgeStore, OAuthIdentityBridgeStoreError, OAuthProviderModeTokenStore, OAuthProviderModeTokenStoreError, OAuthProviderTokenVault, OAuthProviderTokenVaultError, } from "./OAuth.js";
17
+ import { OAuthDeviceAuthorizationId, OAuthDeviceAuthorizationStore, OAuthDeviceAuthorizationStoreError, OAuthDeviceCodeTokenCommitStore, OAuthDeviceCodeTokenCommitStoreError, } from "./OAuthDeviceAuthorization.js";
18
+ import { PasskeyCredentialId, PasskeyCredentialStore, PasskeyCredentialStoreError, } from "./Passkey.js";
19
+ import { canonicalPermissionScope, normalizePermissionDefinitionListLimit, PermissionStore, PermissionStoreError, } from "./Permission.js";
20
+ import { RecoveryCodeHash, RecoveryCodeLoginCommitStore, RecoveryCodeLoginCommitStoreError, RecoveryCodeSessionRotateStore, RecoveryCodeSessionRotateStoreError, RecoveryCodeStore, RecoveryCodeStoreError, } from "./RecoveryCode.js";
21
+ import { RefreshTokenFamilyId, RefreshTokenId, RefreshTokenSecretHash, RefreshTokenStore, RefreshTokenStoreError, } from "./RefreshToken.js";
22
+ import { SecurityTimelineEventId, SecurityTimelineStore, SecurityTimelineStoreError, filterSecurityTimelineEvents, } from "./SecurityTimeline.js";
23
+ import { CredentialStore, IdentityConflictError, IdentityStore, RegistrationConflictError, RegistrationFailureError, RegistrationStore, SessionStore, StorageError, UserStore, VerificationStore, } from "./Storage.js";
24
+ import { TotpFactorStore, TotpFactorStoreError, TotpLoginCommitStore, TotpLoginCommitStoreError, TotpSecret, TotpSessionRotateStore, TotpSessionRotateStoreError, } from "./Totp.js";
25
+ import { TrustedDeviceError, TrustedDeviceStore } from "./TrustedDevice.js";
26
+ import { WebhookOutboxItemId, WebhookOutboxStore, WebhookOutboxStoreError, WebhookReplayStore, WebhookReplayStoreError, filterDueWebhookOutboxRecords, } from "./Webhook.js";
27
+ class PostgresPlanBuildError extends Data.TaggedError("PostgresPlanBuildError") {
28
+ }
29
+ const postgresValueMappings = {
30
+ json: { toDriver: (value) => JSON.stringify(value) },
31
+ jsonb: { toDriver: (value) => JSON.stringify(value) },
32
+ };
33
+ const postgresRenderer = Renderer.make({
34
+ valueMappings: postgresValueMappings,
35
+ });
36
+ const jsonb = () => PostgresColumn.jsonb(Schema.Unknown).pipe(Column.nullable);
37
+ const int8 = () => PostgresColumn.int8();
38
+ const nullableInt8 = () => int8().pipe(Column.nullable);
39
+ const authPostgresUser = Table.make("auth_user", {
40
+ id: Column.text().pipe(Column.primaryKey),
41
+ created_at: int8(),
42
+ updated_at: int8(),
43
+ disabled_at: nullableInt8(),
44
+ metadata: jsonb(),
45
+ });
46
+ const authPostgresUserIdentity = Table.make("auth_user_identity", {
47
+ id: Column.text().pipe(Column.primaryKey),
48
+ user_id: Column.text(),
49
+ scope_type: Column.text(),
50
+ scope_id: Column.text(),
51
+ kind: Column.text(),
52
+ value: Column.text(),
53
+ normalized_value: Column.text(),
54
+ verified_at: nullableInt8(),
55
+ is_primary_login: Column.boolean(),
56
+ created_at: int8(),
57
+ updated_at: int8(),
58
+ revoked_at: nullableInt8(),
59
+ replaced_by_id: Column.text().pipe(Column.nullable),
60
+ metadata: jsonb(),
61
+ });
62
+ const authPostgresCredential = Table.make("auth_credential", {
63
+ id: Column.text().pipe(Column.primaryKey),
64
+ user_id: Column.text(),
65
+ type: Column.text(),
66
+ password_hash: Column.text().pipe(Column.nullable),
67
+ created_at: int8(),
68
+ updated_at: int8(),
69
+ revoked_at: nullableInt8(),
70
+ metadata: jsonb(),
71
+ });
72
+ const authPostgresPasskeyCredential = Table.make("auth_passkey_credential", {
73
+ id: Column.text().pipe(Column.primaryKey),
74
+ user_id: Column.text(),
75
+ credential_id: Column.text().pipe(Column.unique),
76
+ public_key: Column.text(),
77
+ sign_count: int8(),
78
+ transports: jsonb(),
79
+ backed_up: Column.boolean().pipe(Column.nullable),
80
+ created_at: int8(),
81
+ last_used_at: nullableInt8(),
82
+ revoked_at: nullableInt8(),
83
+ metadata: jsonb(),
84
+ });
85
+ const authPostgresSession = Table.make("auth_session", {
86
+ id: Column.text().pipe(Column.primaryKey),
87
+ user_id: Column.text(),
88
+ secret_hash: Column.text(),
89
+ created_at: int8(),
90
+ expires_at: int8(),
91
+ auth_time: int8(),
92
+ authentication_events: PostgresColumn.jsonb(Schema.Unknown),
93
+ aal: Column.text(),
94
+ amr: PostgresColumn.jsonb(Schema.Unknown),
95
+ claims: jsonb(),
96
+ mfa_verified_at: nullableInt8(),
97
+ metadata: jsonb(),
98
+ revoked_at: nullableInt8(),
99
+ last_seen_at: nullableInt8(),
100
+ rotated_at: nullableInt8(),
101
+ });
102
+ const authPostgresVerification = Table.make("auth_verification", {
103
+ id: Column.text().pipe(Column.primaryKey),
104
+ type: Column.text(),
105
+ subject: Column.text(),
106
+ secret_hash: Column.text().pipe(Column.nullable),
107
+ created_at: int8(),
108
+ expires_at: int8(),
109
+ metadata: jsonb(),
110
+ consumed_at: nullableInt8(),
111
+ });
112
+ const authPostgresTotpFactor = Table.make("auth_totp_factor", {
113
+ id: Column.text().pipe(Column.primaryKey),
114
+ user_id: Column.text(),
115
+ secret: Column.text(),
116
+ algorithm: Column.text(),
117
+ digits: Column.int(),
118
+ period: Column.int(),
119
+ created_at: int8(),
120
+ confirmed_at: nullableInt8(),
121
+ last_used_at: nullableInt8(),
122
+ last_accepted_counter: nullableInt8(),
123
+ revoked_at: nullableInt8(),
124
+ metadata: jsonb(),
125
+ });
126
+ const authPostgresRecoveryCode = Table.make("auth_recovery_code", {
127
+ id: Column.text().pipe(Column.primaryKey),
128
+ user_id: Column.text(),
129
+ code_hash: Column.text(),
130
+ created_at: int8(),
131
+ used_at: nullableInt8(),
132
+ revoked_at: nullableInt8(),
133
+ metadata: jsonb(),
134
+ });
135
+ const authPostgresApiKey = Table.make("auth_api_key", {
136
+ id: Column.text().pipe(Column.primaryKey),
137
+ user_id: Column.text(),
138
+ prefix: Column.text().pipe(Column.unique),
139
+ secret_hash: Column.text(),
140
+ scopes: PostgresColumn.jsonb(Schema.Unknown),
141
+ created_at: int8(),
142
+ expires_at: nullableInt8(),
143
+ last_used_at: nullableInt8(),
144
+ revoked_at: nullableInt8(),
145
+ metadata: jsonb(),
146
+ });
147
+ const authPostgresRefreshToken = Table.make("auth_refresh_token", {
148
+ id: Column.text().pipe(Column.primaryKey),
149
+ family_id: Column.text(),
150
+ user_id: Column.text(),
151
+ secret_hash: Column.text(),
152
+ created_at: int8(),
153
+ expires_at: int8(),
154
+ last_used_at: nullableInt8(),
155
+ rotated_at: nullableInt8(),
156
+ replaced_by_id: Column.text().pipe(Column.nullable),
157
+ revoked_at: nullableInt8(),
158
+ reuse_detected_at: nullableInt8(),
159
+ metadata: jsonb(),
160
+ });
161
+ const authPostgresJwtRevocation = Table.make("auth_jwt_revocation", {
162
+ jwt_id: Column.text().pipe(Column.primaryKey),
163
+ revoked_at: int8(),
164
+ expires_at: nullableInt8(),
165
+ reason: Column.text().pipe(Column.nullable),
166
+ });
167
+ const authPostgresOAuthAccount = Table.make("auth_oauth_account", {
168
+ id: Column.text().pipe(Column.primaryKey),
169
+ provider_id: Column.text(),
170
+ provider_account_id: Column.text(),
171
+ user_id: Column.text(),
172
+ email: Column.text().pipe(Column.nullable),
173
+ email_verified: Column.boolean().pipe(Column.nullable),
174
+ created_at: int8(),
175
+ updated_at: int8(),
176
+ unlinked_at: nullableInt8(),
177
+ metadata: jsonb(),
178
+ });
179
+ const authPostgresOAuthClient = Table.make("auth_oauth_client", {
180
+ id: Column.text().pipe(Column.primaryKey),
181
+ type: Column.text(),
182
+ status: Column.text(),
183
+ name: Column.text().pipe(Column.nullable),
184
+ redirect_uris: PostgresColumn.jsonb(Schema.Unknown),
185
+ allowed_grant_types: PostgresColumn.jsonb(Schema.Unknown),
186
+ allowed_response_types: PostgresColumn.jsonb(Schema.Unknown),
187
+ allowed_scopes: jsonb(),
188
+ created_at: nullableInt8(),
189
+ updated_at: nullableInt8(),
190
+ metadata: jsonb(),
191
+ });
192
+ const authPostgresOAuthConsent = Table.make("auth_oauth_consent", {
193
+ user_id: Column.text(),
194
+ client_id: Column.text(),
195
+ scopes: PostgresColumn.jsonb(Schema.Unknown),
196
+ granted_at: int8(),
197
+ expires_at: nullableInt8(),
198
+ revoked_at: nullableInt8(),
199
+ metadata: jsonb(),
200
+ });
201
+ const authPostgresOAuthAuthorizationCode = Table.make("auth_oauth_authorization_code", {
202
+ code_hash: Column.text().pipe(Column.primaryKey),
203
+ client_id: Column.text(),
204
+ subject: Column.text(),
205
+ redirect_uri: Column.text(),
206
+ scopes: PostgresColumn.jsonb(Schema.Unknown),
207
+ code_challenge: Column.text().pipe(Column.nullable),
208
+ code_challenge_method: Column.text().pipe(Column.nullable),
209
+ issued_at: int8(),
210
+ expires_at: int8(),
211
+ consumed_at: nullableInt8(),
212
+ metadata: jsonb(),
213
+ });
214
+ const authPostgresOAuthDeviceAuthorization = Table.make("auth_oauth_device_authorization", {
215
+ id: Column.text().pipe(Column.primaryKey),
216
+ device_code_hash: Column.text().pipe(Column.unique),
217
+ user_code_hash: Column.text().pipe(Column.unique),
218
+ client_id: Column.text(),
219
+ requested_scopes: PostgresColumn.jsonb(Schema.Unknown),
220
+ granted_scopes: jsonb(),
221
+ subject: Column.text().pipe(Column.nullable),
222
+ status: Column.text(),
223
+ issued_at: int8(),
224
+ expires_at: int8(),
225
+ poll_interval_seconds: Column.int(),
226
+ next_poll_at: int8(),
227
+ last_polled_at: nullableInt8(),
228
+ approved_at: nullableInt8(),
229
+ denied_at: nullableInt8(),
230
+ consumed_at: nullableInt8(),
231
+ metadata: jsonb(),
232
+ });
233
+ const authPostgresOAuthClientSecret = Table.make("auth_oauth_client_secret", {
234
+ prefix: Column.text(),
235
+ client_id: Column.text(),
236
+ secret_hash: Column.text(),
237
+ authentication_methods: PostgresColumn.jsonb(Schema.Unknown),
238
+ created_at: int8(),
239
+ expires_at: nullableInt8(),
240
+ last_used_at: nullableInt8(),
241
+ revoked_at: nullableInt8(),
242
+ metadata: jsonb(),
243
+ });
244
+ const authPostgresOAuthProviderModeToken = Table.make("auth_oauth_provider_mode_token", {
245
+ token_hash: Column.text().pipe(Column.primaryKey),
246
+ token_type: Column.text(),
247
+ client_id: Column.text(),
248
+ subject: Column.text(),
249
+ scopes: PostgresColumn.jsonb(Schema.Unknown),
250
+ issued_at: int8(),
251
+ expires_at: int8(),
252
+ issuer: Column.text().pipe(Column.nullable),
253
+ audience: jsonb(),
254
+ jwt_id: Column.text().pipe(Column.nullable),
255
+ revoked_at: nullableInt8(),
256
+ revocation_reason: Column.text().pipe(Column.nullable),
257
+ rotated_at: nullableInt8(),
258
+ replaced_by_token_hash: Column.text().pipe(Column.nullable),
259
+ metadata: jsonb(),
260
+ });
261
+ const authPostgresOAuthProviderTokenVault = Table.make("auth_oauth_provider_token_vault", {
262
+ account_id: Column.text().pipe(Column.primaryKey),
263
+ user_id: Column.text(),
264
+ provider_id: Column.text(),
265
+ provider_account_id: Column.text(),
266
+ access_token_ciphertext: Column.text(),
267
+ refresh_token_ciphertext: Column.text().pipe(Column.nullable),
268
+ id_token_ciphertext: Column.text().pipe(Column.nullable),
269
+ token_type: Column.text(),
270
+ scopes: jsonb(),
271
+ expires_at: nullableInt8(),
272
+ updated_at: int8(),
273
+ revoked_at: nullableInt8(),
274
+ revocation_reason: Column.text().pipe(Column.nullable),
275
+ });
276
+ const authPostgresAuditLog = Table.make("auth_audit_log", {
277
+ storage_id: int8().pipe(PostgresColumn.identityAlways, Column.primaryKey),
278
+ id: Column.text().pipe(Column.nullable),
279
+ type: Column.text(),
280
+ user_id: Column.text().pipe(Column.nullable),
281
+ actor_user_id: Column.text().pipe(Column.nullable),
282
+ occurred_at: int8(),
283
+ request_ip_hash: Column.text().pipe(Column.nullable),
284
+ request_user_agent_hash: Column.text().pipe(Column.nullable),
285
+ event: PostgresColumn.jsonb(Schema.Unknown),
286
+ created_at: int8(),
287
+ });
288
+ const authPostgresLoginApprovalReview = Table.make("auth_login_approval_review", {
289
+ approval_challenge_id: Column.text().pipe(Column.primaryKey),
290
+ flow_id: Column.text(),
291
+ user_id: Column.text(),
292
+ channel: Column.text(),
293
+ reason: Column.text(),
294
+ session_binding: Column.text(),
295
+ same_device_required: Column.boolean(),
296
+ status: Column.text(),
297
+ created_at: int8(),
298
+ expires_at: int8(),
299
+ reviewed_at: nullableInt8(),
300
+ reviewed_by: Column.text().pipe(Column.nullable),
301
+ denied_reason: Column.text().pipe(Column.nullable),
302
+ risk: jsonb(),
303
+ metadata: jsonb(),
304
+ review_metadata: jsonb(),
305
+ });
306
+ const authPostgresLoginRiskHistory = Table.make("auth_login_risk_history", {
307
+ id: Column.text().pipe(Column.primaryKey),
308
+ user_id: Column.text(),
309
+ occurred_at: int8(),
310
+ outcome: Column.text(),
311
+ method: Column.text(),
312
+ amr: PostgresColumn.jsonb(Schema.Unknown),
313
+ aal: Column.text(),
314
+ device_status: Column.text(),
315
+ device_key: Column.text().pipe(Column.nullable),
316
+ location_key: Column.text().pipe(Column.nullable),
317
+ country: Column.text().pipe(Column.nullable),
318
+ region: Column.text().pipe(Column.nullable),
319
+ latitude_micro: nullableInt8(),
320
+ longitude_micro: nullableInt8(),
321
+ risk_level: Column.text().pipe(Column.nullable),
322
+ created_at: int8(),
323
+ });
324
+ const authPostgresTrustedDevice = Table.make("auth_trusted_device", {
325
+ user_id: Column.text(),
326
+ token_hash: Column.text(),
327
+ created_at: int8(),
328
+ last_seen_at: int8(),
329
+ expires_at: int8(),
330
+ metadata: jsonb(),
331
+ });
332
+ const authPostgresDomainVerification = Table.make("auth_domain_verification", {
333
+ id: Column.text().pipe(Column.primaryKey),
334
+ owner_id: Column.text(),
335
+ domain: Column.text(),
336
+ proof_method: Column.text(),
337
+ proof_token: Column.text(),
338
+ status: Column.text(),
339
+ created_at: int8(),
340
+ expires_at: int8(),
341
+ verified_at: nullableInt8(),
342
+ revoked_at: nullableInt8(),
343
+ last_checked_at: nullableInt8(),
344
+ metadata: jsonb(),
345
+ });
346
+ const authPostgresSecurityTimeline = Table.make("auth_security_timeline", {
347
+ id: Column.text().pipe(Column.primaryKey),
348
+ user_id: Column.text(),
349
+ type: Column.text(),
350
+ category: Column.text(),
351
+ severity: Column.text(),
352
+ occurred_at: int8(),
353
+ summary: Column.text(),
354
+ actor: jsonb(),
355
+ request: jsonb(),
356
+ metadata: jsonb(),
357
+ });
358
+ const authPostgresWebhookOutbox = Table.make("auth_webhook_outbox", {
359
+ id: Column.text().pipe(Column.primaryKey),
360
+ endpoint_key: Column.text(),
361
+ event: PostgresColumn.jsonb(Schema.Unknown),
362
+ status: Column.text(),
363
+ attempts: Column.int(),
364
+ next_attempt_at: int8(),
365
+ created_at: int8(),
366
+ updated_at: int8(),
367
+ delivered_at: nullableInt8(),
368
+ last_error: Column.text().pipe(Column.nullable),
369
+ });
370
+ const authPostgresWebhookReplay = Table.make("auth_webhook_replay", {
371
+ id: Column.text().pipe(Column.primaryKey),
372
+ expires_at: int8(),
373
+ created_at: int8(),
374
+ });
375
+ const authPostgresPermissionDefinition = Table.make("auth_permission_definition", {
376
+ id: Column.text().pipe(Column.primaryKey),
377
+ description: Column.text().pipe(Column.nullable),
378
+ scope_type_present: Column.boolean(),
379
+ scope_type: Column.text(),
380
+ created_at: int8(),
381
+ updated_at: int8(),
382
+ disabled_at: nullableInt8(),
383
+ deleted_at: nullableInt8(),
384
+ });
385
+ const authPostgresRoleDefinition = Table.make("auth_role_definition", {
386
+ id: Column.text().pipe(Column.primaryKey),
387
+ description: Column.text().pipe(Column.nullable),
388
+ created_at: int8(),
389
+ updated_at: int8(),
390
+ disabled_at: nullableInt8(),
391
+ deleted_at: nullableInt8(),
392
+ });
393
+ const authPostgresPermissionGrant = Table.make("auth_permission_grant", {
394
+ subject_type: Column.text(),
395
+ subject_id: Column.text(),
396
+ permission_id: Column.text(),
397
+ scope_type: Column.text(),
398
+ scope_id_present: Column.boolean(),
399
+ scope_id: Column.text(),
400
+ expires_at: nullableInt8(),
401
+ metadata: jsonb(),
402
+ revoked_at: nullableInt8(),
403
+ });
404
+ const authPostgresRoleGrant = Table.make("auth_role_grant", {
405
+ subject_type: Column.text(),
406
+ subject_id: Column.text(),
407
+ role_id: Column.text(),
408
+ scope_type: Column.text(),
409
+ scope_id_present: Column.boolean(),
410
+ scope_id: Column.text(),
411
+ expires_at: nullableInt8(),
412
+ metadata: jsonb(),
413
+ revoked_at: nullableInt8(),
414
+ });
415
+ const authPostgresRolePermission = Table.make("auth_role_permission", {
416
+ role_id: Column.text(),
417
+ permission_id: Column.text(),
418
+ scope_type_present: Column.boolean(),
419
+ scope_type: Column.text(),
420
+ });
421
+ /** Canonical tables used by the maintained Postgres adapter, exposed for application-owned queries. */
422
+ export const effectQbPostgresTables = {
423
+ user: authPostgresUser,
424
+ userIdentity: authPostgresUserIdentity,
425
+ credential: authPostgresCredential,
426
+ passkeyCredential: authPostgresPasskeyCredential,
427
+ session: authPostgresSession,
428
+ verification: authPostgresVerification,
429
+ totpFactor: authPostgresTotpFactor,
430
+ recoveryCode: authPostgresRecoveryCode,
431
+ apiKey: authPostgresApiKey,
432
+ refreshToken: authPostgresRefreshToken,
433
+ jwtRevocation: authPostgresJwtRevocation,
434
+ oauthAccount: authPostgresOAuthAccount,
435
+ oauthClient: authPostgresOAuthClient,
436
+ oauthConsent: authPostgresOAuthConsent,
437
+ oauthAuthorizationCode: authPostgresOAuthAuthorizationCode,
438
+ oauthDeviceAuthorization: authPostgresOAuthDeviceAuthorization,
439
+ oauthClientSecret: authPostgresOAuthClientSecret,
440
+ oauthProviderModeToken: authPostgresOAuthProviderModeToken,
441
+ oauthProviderTokenVault: authPostgresOAuthProviderTokenVault,
442
+ auditLog: authPostgresAuditLog,
443
+ loginApprovalReview: authPostgresLoginApprovalReview,
444
+ loginRiskHistory: authPostgresLoginRiskHistory,
445
+ trustedDevice: authPostgresTrustedDevice,
446
+ domainVerification: authPostgresDomainVerification,
447
+ securityTimeline: authPostgresSecurityTimeline,
448
+ webhookOutbox: authPostgresWebhookOutbox,
449
+ webhookReplay: authPostgresWebhookReplay,
450
+ permissionDefinition: authPostgresPermissionDefinition,
451
+ roleDefinition: authPostgresRoleDefinition,
452
+ permissionGrant: authPostgresPermissionGrant,
453
+ roleGrant: authPostgresRoleGrant,
454
+ rolePermission: authPostgresRolePermission,
455
+ };
456
+ const userSelection = {
457
+ id: authPostgresUser.id,
458
+ createdAt: authPostgresUser.created_at,
459
+ updatedAt: authPostgresUser.updated_at,
460
+ disabledAt: authPostgresUser.disabled_at,
461
+ metadata: authPostgresUser.metadata,
462
+ };
463
+ const identitySelection = {
464
+ id: authPostgresUserIdentity.id,
465
+ userId: authPostgresUserIdentity.user_id,
466
+ scopeType: authPostgresUserIdentity.scope_type,
467
+ scopeId: authPostgresUserIdentity.scope_id,
468
+ kind: authPostgresUserIdentity.kind,
469
+ value: authPostgresUserIdentity.value,
470
+ normalizedValue: authPostgresUserIdentity.normalized_value,
471
+ verifiedAt: authPostgresUserIdentity.verified_at,
472
+ isPrimaryLogin: authPostgresUserIdentity.is_primary_login,
473
+ createdAt: authPostgresUserIdentity.created_at,
474
+ updatedAt: authPostgresUserIdentity.updated_at,
475
+ revokedAt: authPostgresUserIdentity.revoked_at,
476
+ replacedById: authPostgresUserIdentity.replaced_by_id,
477
+ metadata: authPostgresUserIdentity.metadata,
478
+ };
479
+ const credentialSelection = {
480
+ id: authPostgresCredential.id,
481
+ userId: authPostgresCredential.user_id,
482
+ type: authPostgresCredential.type,
483
+ passwordHash: authPostgresCredential.password_hash,
484
+ createdAt: authPostgresCredential.created_at,
485
+ updatedAt: authPostgresCredential.updated_at,
486
+ revokedAt: authPostgresCredential.revoked_at,
487
+ metadata: authPostgresCredential.metadata,
488
+ };
489
+ const passkeyCredentialSelection = {
490
+ id: authPostgresPasskeyCredential.id,
491
+ userId: authPostgresPasskeyCredential.user_id,
492
+ credentialId: authPostgresPasskeyCredential.credential_id,
493
+ publicKey: authPostgresPasskeyCredential.public_key,
494
+ signCount: authPostgresPasskeyCredential.sign_count,
495
+ transports: authPostgresPasskeyCredential.transports,
496
+ backedUp: authPostgresPasskeyCredential.backed_up,
497
+ createdAt: authPostgresPasskeyCredential.created_at,
498
+ lastUsedAt: authPostgresPasskeyCredential.last_used_at,
499
+ revokedAt: authPostgresPasskeyCredential.revoked_at,
500
+ metadata: authPostgresPasskeyCredential.metadata,
501
+ };
502
+ const sessionSelection = {
503
+ id: authPostgresSession.id,
504
+ userId: authPostgresSession.user_id,
505
+ secretHash: authPostgresSession.secret_hash,
506
+ createdAt: authPostgresSession.created_at,
507
+ expiresAt: authPostgresSession.expires_at,
508
+ authTime: authPostgresSession.auth_time,
509
+ authenticationEvents: authPostgresSession.authentication_events,
510
+ aal: authPostgresSession.aal,
511
+ amr: authPostgresSession.amr,
512
+ claims: authPostgresSession.claims,
513
+ mfaVerifiedAt: authPostgresSession.mfa_verified_at,
514
+ metadata: authPostgresSession.metadata,
515
+ revokedAt: authPostgresSession.revoked_at,
516
+ lastSeenAt: authPostgresSession.last_seen_at,
517
+ rotatedAt: authPostgresSession.rotated_at,
518
+ };
519
+ const verificationSelection = {
520
+ id: authPostgresVerification.id,
521
+ type: authPostgresVerification.type,
522
+ subject: authPostgresVerification.subject,
523
+ secretHash: authPostgresVerification.secret_hash,
524
+ createdAt: authPostgresVerification.created_at,
525
+ expiresAt: authPostgresVerification.expires_at,
526
+ metadata: authPostgresVerification.metadata,
527
+ consumedAt: authPostgresVerification.consumed_at,
528
+ };
529
+ const totpFactorSelection = {
530
+ id: authPostgresTotpFactor.id,
531
+ userId: authPostgresTotpFactor.user_id,
532
+ secret: authPostgresTotpFactor.secret,
533
+ algorithm: authPostgresTotpFactor.algorithm,
534
+ digits: authPostgresTotpFactor.digits,
535
+ period: authPostgresTotpFactor.period,
536
+ createdAt: authPostgresTotpFactor.created_at,
537
+ confirmedAt: authPostgresTotpFactor.confirmed_at,
538
+ lastUsedAt: authPostgresTotpFactor.last_used_at,
539
+ lastAcceptedCounter: authPostgresTotpFactor.last_accepted_counter,
540
+ revokedAt: authPostgresTotpFactor.revoked_at,
541
+ metadata: authPostgresTotpFactor.metadata,
542
+ };
543
+ const recoveryCodeSelection = {
544
+ id: authPostgresRecoveryCode.id,
545
+ userId: authPostgresRecoveryCode.user_id,
546
+ codeHash: authPostgresRecoveryCode.code_hash,
547
+ createdAt: authPostgresRecoveryCode.created_at,
548
+ usedAt: authPostgresRecoveryCode.used_at,
549
+ revokedAt: authPostgresRecoveryCode.revoked_at,
550
+ metadata: authPostgresRecoveryCode.metadata,
551
+ };
552
+ const apiKeySelection = {
553
+ id: authPostgresApiKey.id,
554
+ userId: authPostgresApiKey.user_id,
555
+ prefix: authPostgresApiKey.prefix,
556
+ secretHash: authPostgresApiKey.secret_hash,
557
+ scopes: authPostgresApiKey.scopes,
558
+ createdAt: authPostgresApiKey.created_at,
559
+ expiresAt: authPostgresApiKey.expires_at,
560
+ lastUsedAt: authPostgresApiKey.last_used_at,
561
+ revokedAt: authPostgresApiKey.revoked_at,
562
+ metadata: authPostgresApiKey.metadata,
563
+ };
564
+ const refreshTokenSelection = {
565
+ id: authPostgresRefreshToken.id,
566
+ familyId: authPostgresRefreshToken.family_id,
567
+ userId: authPostgresRefreshToken.user_id,
568
+ secretHash: authPostgresRefreshToken.secret_hash,
569
+ createdAt: authPostgresRefreshToken.created_at,
570
+ expiresAt: authPostgresRefreshToken.expires_at,
571
+ lastUsedAt: authPostgresRefreshToken.last_used_at,
572
+ rotatedAt: authPostgresRefreshToken.rotated_at,
573
+ replacedById: authPostgresRefreshToken.replaced_by_id,
574
+ revokedAt: authPostgresRefreshToken.revoked_at,
575
+ reuseDetectedAt: authPostgresRefreshToken.reuse_detected_at,
576
+ metadata: authPostgresRefreshToken.metadata,
577
+ };
578
+ const jwtRevocationSelection = {
579
+ jwtId: authPostgresJwtRevocation.jwt_id,
580
+ revokedAt: authPostgresJwtRevocation.revoked_at,
581
+ expiresAt: authPostgresJwtRevocation.expires_at,
582
+ reason: authPostgresJwtRevocation.reason,
583
+ };
584
+ const oauthAccountSelection = {
585
+ id: authPostgresOAuthAccount.id,
586
+ providerId: authPostgresOAuthAccount.provider_id,
587
+ providerAccountId: authPostgresOAuthAccount.provider_account_id,
588
+ userId: authPostgresOAuthAccount.user_id,
589
+ email: authPostgresOAuthAccount.email,
590
+ emailVerified: authPostgresOAuthAccount.email_verified,
591
+ createdAt: authPostgresOAuthAccount.created_at,
592
+ updatedAt: authPostgresOAuthAccount.updated_at,
593
+ unlinkedAt: authPostgresOAuthAccount.unlinked_at,
594
+ metadata: authPostgresOAuthAccount.metadata,
595
+ };
596
+ const oauthClientSelection = {
597
+ id: authPostgresOAuthClient.id,
598
+ type: authPostgresOAuthClient.type,
599
+ status: authPostgresOAuthClient.status,
600
+ name: authPostgresOAuthClient.name,
601
+ redirectUris: authPostgresOAuthClient.redirect_uris,
602
+ allowedGrantTypes: authPostgresOAuthClient.allowed_grant_types,
603
+ allowedResponseTypes: authPostgresOAuthClient.allowed_response_types,
604
+ allowedScopes: authPostgresOAuthClient.allowed_scopes,
605
+ createdAt: authPostgresOAuthClient.created_at,
606
+ updatedAt: authPostgresOAuthClient.updated_at,
607
+ metadata: authPostgresOAuthClient.metadata,
608
+ };
609
+ const oauthConsentSelection = {
610
+ userId: authPostgresOAuthConsent.user_id,
611
+ clientId: authPostgresOAuthConsent.client_id,
612
+ scopes: authPostgresOAuthConsent.scopes,
613
+ grantedAt: authPostgresOAuthConsent.granted_at,
614
+ expiresAt: authPostgresOAuthConsent.expires_at,
615
+ revokedAt: authPostgresOAuthConsent.revoked_at,
616
+ metadata: authPostgresOAuthConsent.metadata,
617
+ };
618
+ const oauthAuthorizationCodeSelection = {
619
+ codeHash: authPostgresOAuthAuthorizationCode.code_hash,
620
+ clientId: authPostgresOAuthAuthorizationCode.client_id,
621
+ subject: authPostgresOAuthAuthorizationCode.subject,
622
+ redirectUri: authPostgresOAuthAuthorizationCode.redirect_uri,
623
+ scopes: authPostgresOAuthAuthorizationCode.scopes,
624
+ codeChallenge: authPostgresOAuthAuthorizationCode.code_challenge,
625
+ codeChallengeMethod: authPostgresOAuthAuthorizationCode.code_challenge_method,
626
+ issuedAt: authPostgresOAuthAuthorizationCode.issued_at,
627
+ expiresAt: authPostgresOAuthAuthorizationCode.expires_at,
628
+ consumedAt: authPostgresOAuthAuthorizationCode.consumed_at,
629
+ metadata: authPostgresOAuthAuthorizationCode.metadata,
630
+ };
631
+ const oauthDeviceAuthorizationSelection = {
632
+ id: authPostgresOAuthDeviceAuthorization.id,
633
+ deviceCodeHash: authPostgresOAuthDeviceAuthorization.device_code_hash,
634
+ userCodeHash: authPostgresOAuthDeviceAuthorization.user_code_hash,
635
+ clientId: authPostgresOAuthDeviceAuthorization.client_id,
636
+ requestedScopes: authPostgresOAuthDeviceAuthorization.requested_scopes,
637
+ grantedScopes: authPostgresOAuthDeviceAuthorization.granted_scopes,
638
+ subject: authPostgresOAuthDeviceAuthorization.subject,
639
+ status: authPostgresOAuthDeviceAuthorization.status,
640
+ issuedAt: authPostgresOAuthDeviceAuthorization.issued_at,
641
+ expiresAt: authPostgresOAuthDeviceAuthorization.expires_at,
642
+ pollIntervalSeconds: authPostgresOAuthDeviceAuthorization.poll_interval_seconds,
643
+ nextPollAt: authPostgresOAuthDeviceAuthorization.next_poll_at,
644
+ lastPolledAt: authPostgresOAuthDeviceAuthorization.last_polled_at,
645
+ approvedAt: authPostgresOAuthDeviceAuthorization.approved_at,
646
+ deniedAt: authPostgresOAuthDeviceAuthorization.denied_at,
647
+ consumedAt: authPostgresOAuthDeviceAuthorization.consumed_at,
648
+ metadata: authPostgresOAuthDeviceAuthorization.metadata,
649
+ };
650
+ const oauthClientSecretSelection = {
651
+ prefix: authPostgresOAuthClientSecret.prefix,
652
+ clientId: authPostgresOAuthClientSecret.client_id,
653
+ secretHash: authPostgresOAuthClientSecret.secret_hash,
654
+ authenticationMethods: authPostgresOAuthClientSecret.authentication_methods,
655
+ createdAt: authPostgresOAuthClientSecret.created_at,
656
+ expiresAt: authPostgresOAuthClientSecret.expires_at,
657
+ lastUsedAt: authPostgresOAuthClientSecret.last_used_at,
658
+ revokedAt: authPostgresOAuthClientSecret.revoked_at,
659
+ metadata: authPostgresOAuthClientSecret.metadata,
660
+ };
661
+ const oauthProviderModeTokenSelection = {
662
+ tokenHash: authPostgresOAuthProviderModeToken.token_hash,
663
+ tokenType: authPostgresOAuthProviderModeToken.token_type,
664
+ clientId: authPostgresOAuthProviderModeToken.client_id,
665
+ subject: authPostgresOAuthProviderModeToken.subject,
666
+ scopes: authPostgresOAuthProviderModeToken.scopes,
667
+ issuedAt: authPostgresOAuthProviderModeToken.issued_at,
668
+ expiresAt: authPostgresOAuthProviderModeToken.expires_at,
669
+ issuer: authPostgresOAuthProviderModeToken.issuer,
670
+ audience: authPostgresOAuthProviderModeToken.audience,
671
+ jwtId: authPostgresOAuthProviderModeToken.jwt_id,
672
+ revokedAt: authPostgresOAuthProviderModeToken.revoked_at,
673
+ revocationReason: authPostgresOAuthProviderModeToken.revocation_reason,
674
+ rotatedAt: authPostgresOAuthProviderModeToken.rotated_at,
675
+ replacedByTokenHash: authPostgresOAuthProviderModeToken.replaced_by_token_hash,
676
+ metadata: authPostgresOAuthProviderModeToken.metadata,
677
+ };
678
+ const oauthProviderTokenVaultSelection = {
679
+ accountId: authPostgresOAuthProviderTokenVault.account_id,
680
+ userId: authPostgresOAuthProviderTokenVault.user_id,
681
+ providerId: authPostgresOAuthProviderTokenVault.provider_id,
682
+ providerAccountId: authPostgresOAuthProviderTokenVault.provider_account_id,
683
+ accessTokenCiphertext: authPostgresOAuthProviderTokenVault.access_token_ciphertext,
684
+ refreshTokenCiphertext: authPostgresOAuthProviderTokenVault.refresh_token_ciphertext,
685
+ idTokenCiphertext: authPostgresOAuthProviderTokenVault.id_token_ciphertext,
686
+ tokenType: authPostgresOAuthProviderTokenVault.token_type,
687
+ scopes: authPostgresOAuthProviderTokenVault.scopes,
688
+ expiresAt: authPostgresOAuthProviderTokenVault.expires_at,
689
+ updatedAt: authPostgresOAuthProviderTokenVault.updated_at,
690
+ revokedAt: authPostgresOAuthProviderTokenVault.revoked_at,
691
+ revocationReason: authPostgresOAuthProviderTokenVault.revocation_reason,
692
+ };
693
+ const auditLogSelection = {
694
+ id: authPostgresAuditLog.id,
695
+ type: authPostgresAuditLog.type,
696
+ userId: authPostgresAuditLog.user_id,
697
+ actorUserId: authPostgresAuditLog.actor_user_id,
698
+ occurredAt: authPostgresAuditLog.occurred_at,
699
+ requestIpHash: authPostgresAuditLog.request_ip_hash,
700
+ requestUserAgentHash: authPostgresAuditLog.request_user_agent_hash,
701
+ event: authPostgresAuditLog.event,
702
+ createdAt: authPostgresAuditLog.created_at,
703
+ };
704
+ const loginApprovalReviewSelection = {
705
+ approvalChallengeId: authPostgresLoginApprovalReview.approval_challenge_id,
706
+ flowId: authPostgresLoginApprovalReview.flow_id,
707
+ userId: authPostgresLoginApprovalReview.user_id,
708
+ channel: authPostgresLoginApprovalReview.channel,
709
+ reason: authPostgresLoginApprovalReview.reason,
710
+ sessionBinding: authPostgresLoginApprovalReview.session_binding,
711
+ sameDeviceRequired: authPostgresLoginApprovalReview.same_device_required,
712
+ status: authPostgresLoginApprovalReview.status,
713
+ createdAt: authPostgresLoginApprovalReview.created_at,
714
+ expiresAt: authPostgresLoginApprovalReview.expires_at,
715
+ reviewedAt: authPostgresLoginApprovalReview.reviewed_at,
716
+ reviewedBy: authPostgresLoginApprovalReview.reviewed_by,
717
+ deniedReason: authPostgresLoginApprovalReview.denied_reason,
718
+ risk: authPostgresLoginApprovalReview.risk,
719
+ metadata: authPostgresLoginApprovalReview.metadata,
720
+ reviewMetadata: authPostgresLoginApprovalReview.review_metadata,
721
+ };
722
+ const loginRiskHistorySelection = {
723
+ id: authPostgresLoginRiskHistory.id,
724
+ userId: authPostgresLoginRiskHistory.user_id,
725
+ occurredAt: authPostgresLoginRiskHistory.occurred_at,
726
+ outcome: authPostgresLoginRiskHistory.outcome,
727
+ method: authPostgresLoginRiskHistory.method,
728
+ amr: authPostgresLoginRiskHistory.amr,
729
+ aal: authPostgresLoginRiskHistory.aal,
730
+ deviceStatus: authPostgresLoginRiskHistory.device_status,
731
+ deviceKey: authPostgresLoginRiskHistory.device_key,
732
+ locationKey: authPostgresLoginRiskHistory.location_key,
733
+ country: authPostgresLoginRiskHistory.country,
734
+ region: authPostgresLoginRiskHistory.region,
735
+ latitudeMicro: authPostgresLoginRiskHistory.latitude_micro,
736
+ longitudeMicro: authPostgresLoginRiskHistory.longitude_micro,
737
+ riskLevel: authPostgresLoginRiskHistory.risk_level,
738
+ createdAt: authPostgresLoginRiskHistory.created_at,
739
+ };
740
+ const trustedDeviceSelection = {
741
+ userId: authPostgresTrustedDevice.user_id,
742
+ tokenHash: authPostgresTrustedDevice.token_hash,
743
+ createdAt: authPostgresTrustedDevice.created_at,
744
+ lastSeenAt: authPostgresTrustedDevice.last_seen_at,
745
+ expiresAt: authPostgresTrustedDevice.expires_at,
746
+ metadata: authPostgresTrustedDevice.metadata,
747
+ };
748
+ const domainVerificationSelection = {
749
+ id: authPostgresDomainVerification.id,
750
+ ownerId: authPostgresDomainVerification.owner_id,
751
+ domain: authPostgresDomainVerification.domain,
752
+ proofMethod: authPostgresDomainVerification.proof_method,
753
+ proofToken: authPostgresDomainVerification.proof_token,
754
+ status: authPostgresDomainVerification.status,
755
+ createdAt: authPostgresDomainVerification.created_at,
756
+ expiresAt: authPostgresDomainVerification.expires_at,
757
+ verifiedAt: authPostgresDomainVerification.verified_at,
758
+ revokedAt: authPostgresDomainVerification.revoked_at,
759
+ lastCheckedAt: authPostgresDomainVerification.last_checked_at,
760
+ metadata: authPostgresDomainVerification.metadata,
761
+ };
762
+ const securityTimelineSelection = {
763
+ id: authPostgresSecurityTimeline.id,
764
+ userId: authPostgresSecurityTimeline.user_id,
765
+ type: authPostgresSecurityTimeline.type,
766
+ category: authPostgresSecurityTimeline.category,
767
+ severity: authPostgresSecurityTimeline.severity,
768
+ occurredAt: authPostgresSecurityTimeline.occurred_at,
769
+ summary: authPostgresSecurityTimeline.summary,
770
+ actor: authPostgresSecurityTimeline.actor,
771
+ request: authPostgresSecurityTimeline.request,
772
+ metadata: authPostgresSecurityTimeline.metadata,
773
+ };
774
+ const webhookOutboxSelection = {
775
+ id: authPostgresWebhookOutbox.id,
776
+ endpointKey: authPostgresWebhookOutbox.endpoint_key,
777
+ event: authPostgresWebhookOutbox.event,
778
+ status: authPostgresWebhookOutbox.status,
779
+ attempts: authPostgresWebhookOutbox.attempts,
780
+ nextAttemptAt: authPostgresWebhookOutbox.next_attempt_at,
781
+ createdAt: authPostgresWebhookOutbox.created_at,
782
+ updatedAt: authPostgresWebhookOutbox.updated_at,
783
+ deliveredAt: authPostgresWebhookOutbox.delivered_at,
784
+ lastError: authPostgresWebhookOutbox.last_error,
785
+ };
786
+ const permissionDefinitionSelection = {
787
+ id: authPostgresPermissionDefinition.id,
788
+ description: authPostgresPermissionDefinition.description,
789
+ scopeTypePresent: authPostgresPermissionDefinition.scope_type_present,
790
+ scopeType: authPostgresPermissionDefinition.scope_type,
791
+ createdAt: authPostgresPermissionDefinition.created_at,
792
+ updatedAt: authPostgresPermissionDefinition.updated_at,
793
+ disabledAt: authPostgresPermissionDefinition.disabled_at,
794
+ deletedAt: authPostgresPermissionDefinition.deleted_at,
795
+ };
796
+ const roleDefinitionSelection = {
797
+ id: authPostgresRoleDefinition.id,
798
+ description: authPostgresRoleDefinition.description,
799
+ createdAt: authPostgresRoleDefinition.created_at,
800
+ updatedAt: authPostgresRoleDefinition.updated_at,
801
+ disabledAt: authPostgresRoleDefinition.disabled_at,
802
+ deletedAt: authPostgresRoleDefinition.deleted_at,
803
+ };
804
+ const permissionGrantSelection = {
805
+ subjectType: authPostgresPermissionGrant.subject_type,
806
+ subjectId: authPostgresPermissionGrant.subject_id,
807
+ permissionId: authPostgresPermissionGrant.permission_id,
808
+ scopeType: authPostgresPermissionGrant.scope_type,
809
+ scopeIdPresent: authPostgresPermissionGrant.scope_id_present,
810
+ scopeId: authPostgresPermissionGrant.scope_id,
811
+ expiresAt: authPostgresPermissionGrant.expires_at,
812
+ metadata: authPostgresPermissionGrant.metadata,
813
+ revokedAt: authPostgresPermissionGrant.revoked_at,
814
+ };
815
+ const roleGrantSelection = {
816
+ subjectType: authPostgresRoleGrant.subject_type,
817
+ subjectId: authPostgresRoleGrant.subject_id,
818
+ roleId: authPostgresRoleGrant.role_id,
819
+ scopeType: authPostgresRoleGrant.scope_type,
820
+ scopeIdPresent: authPostgresRoleGrant.scope_id_present,
821
+ scopeId: authPostgresRoleGrant.scope_id,
822
+ expiresAt: authPostgresRoleGrant.expires_at,
823
+ metadata: authPostgresRoleGrant.metadata,
824
+ revokedAt: authPostgresRoleGrant.revoked_at,
825
+ };
826
+ const rolePermissionSelection = {
827
+ roleId: authPostgresRolePermission.role_id,
828
+ permissionId: authPostgresRolePermission.permission_id,
829
+ scopeTypePresent: authPostgresRolePermission.scope_type_present,
830
+ scopeType: authPostgresRolePermission.scope_type,
831
+ };
832
+ /** Converts UnixMillis to a Postgres bigint parameter without precision loss. */
833
+ export const unixMillisToPostgresBigint = (value) => {
834
+ const number = Number(value);
835
+ if (!Number.isSafeInteger(number)) {
836
+ throw new RangeError("UnixMillis exceeds the safe Postgres bigint range");
837
+ }
838
+ return String(number);
839
+ };
840
+ const millisParam = unixMillisToPostgresBigint;
841
+ /** Converts a Postgres bigint result without permitting precision loss. */
842
+ export const postgresBigintToUnixMillis = (value) => {
843
+ if ((typeof value !== "string" &&
844
+ typeof value !== "number" &&
845
+ typeof value !== "bigint") ||
846
+ (typeof value === "string" && !/^-?\d+$/.test(value))) {
847
+ throw new TypeError("Expected a Postgres bigint UnixMillis value");
848
+ }
849
+ const bigint = BigInt(value);
850
+ if (bigint < BigInt(Number.MIN_SAFE_INTEGER) ||
851
+ bigint > BigInt(Number.MAX_SAFE_INTEGER)) {
852
+ throw new RangeError("Postgres bigint UnixMillis exceeds the safe range");
853
+ }
854
+ return UnixMillis(Number(bigint));
855
+ };
856
+ const safeIntegerToPostgresBigint = (value, label) => {
857
+ if (!Number.isSafeInteger(value)) {
858
+ throw new RangeError(`${label} exceeds the safe Postgres bigint range`);
859
+ }
860
+ return String(value);
861
+ };
862
+ const postgresBigintToSafeInteger = (value, label) => {
863
+ if ((typeof value !== "string" &&
864
+ typeof value !== "number" &&
865
+ typeof value !== "bigint") ||
866
+ (typeof value === "string" && !/^-?\d+$/.test(value)) ||
867
+ (typeof value === "number" && !Number.isSafeInteger(value))) {
868
+ throw new TypeError(`Expected a Postgres bigint ${label} value`);
869
+ }
870
+ const bigint = BigInt(value);
871
+ if (bigint < BigInt(Number.MIN_SAFE_INTEGER) ||
872
+ bigint > BigInt(Number.MAX_SAFE_INTEGER)) {
873
+ throw new RangeError(`Postgres bigint ${label} exceeds the safe range`);
874
+ }
875
+ return Number(bigint);
876
+ };
877
+ const optionalMillis = (value) => value === null || value === undefined
878
+ ? undefined
879
+ : postgresBigintToUnixMillis(value);
880
+ const optionalRecord = (value) => value === null || value === undefined
881
+ ? undefined
882
+ : value;
883
+ const scopeFrom = (type, id) => type === "tenant"
884
+ ? { type: "tenant", tenantId: String(id) }
885
+ : { type: "global" };
886
+ const scopeId = (scope) => scope.type === "tenant" ? scope.tenantId : "";
887
+ const decodeUser = (row) => ({
888
+ id: UserId(String(row.id)),
889
+ createdAt: postgresBigintToUnixMillis(row.createdAt ?? row.created_at),
890
+ updatedAt: postgresBigintToUnixMillis(row.updatedAt ?? row.updated_at),
891
+ ...(optionalMillis(row.disabledAt ?? row.disabled_at) === undefined
892
+ ? {}
893
+ : { disabledAt: optionalMillis(row.disabledAt ?? row.disabled_at) }),
894
+ ...(optionalRecord(row.metadata) === undefined
895
+ ? {}
896
+ : { metadata: optionalRecord(row.metadata) }),
897
+ });
898
+ const decodeIdentity = (row) => ({
899
+ id: IdentityId(String(row.id)),
900
+ userId: UserId(String(row.userId ?? row.user_id)),
901
+ scope: scopeFrom(row.scopeType ?? row.scope_type, row.scopeId ?? row.scope_id),
902
+ kind: String(row.kind),
903
+ value: String(row.value),
904
+ normalizedValue: String(row.normalizedValue ?? row.normalized_value),
905
+ ...(optionalMillis(row.verifiedAt ?? row.verified_at) === undefined
906
+ ? {}
907
+ : { verifiedAt: optionalMillis(row.verifiedAt ?? row.verified_at) }),
908
+ isPrimaryLogin: Boolean(row.isPrimaryLogin ?? row.is_primary_login),
909
+ createdAt: postgresBigintToUnixMillis(row.createdAt ?? row.created_at),
910
+ updatedAt: postgresBigintToUnixMillis(row.updatedAt ?? row.updated_at),
911
+ ...(optionalMillis(row.revokedAt ?? row.revoked_at) === undefined
912
+ ? {}
913
+ : { revokedAt: optionalMillis(row.revokedAt ?? row.revoked_at) }),
914
+ ...((row.replacedById ?? row.replaced_by_id) === null ||
915
+ (row.replacedById ?? row.replaced_by_id) === undefined
916
+ ? {}
917
+ : {
918
+ replacedById: IdentityId(String(row.replacedById ?? row.replaced_by_id)),
919
+ }),
920
+ ...(optionalRecord(row.metadata) === undefined
921
+ ? {}
922
+ : { metadata: optionalRecord(row.metadata) }),
923
+ });
924
+ const decodeCredential = (row) => ({
925
+ id: CredentialId(String(row.id)),
926
+ userId: UserId(String(row.userId ?? row.user_id)),
927
+ passwordHash: String(row.passwordHash ?? row.password_hash),
928
+ createdAt: postgresBigintToUnixMillis(row.createdAt ?? row.created_at),
929
+ updatedAt: postgresBigintToUnixMillis(row.updatedAt ?? row.updated_at),
930
+ ...(optionalMillis(row.revokedAt ?? row.revoked_at) === undefined
931
+ ? {}
932
+ : { revokedAt: optionalMillis(row.revokedAt ?? row.revoked_at) }),
933
+ ...(optionalRecord(row.metadata) === undefined
934
+ ? {}
935
+ : { metadata: optionalRecord(row.metadata) }),
936
+ });
937
+ const decodePasskeyCredential = (row) => ({
938
+ id: CredentialId(String(row.id)),
939
+ userId: UserId(String(row.userId ?? row.user_id)),
940
+ credentialId: PasskeyCredentialId(String(row.credentialId ?? row.credential_id)),
941
+ publicKey: String(row.publicKey ?? row.public_key),
942
+ signCount: postgresBigintToSafeInteger(row.signCount ?? row.sign_count, "sign count"),
943
+ ...(Array.isArray(row.transports)
944
+ ? { transports: row.transports.map(String) }
945
+ : {}),
946
+ ...((row.backedUp ?? row.backed_up) === null ||
947
+ (row.backedUp ?? row.backed_up) === undefined
948
+ ? {}
949
+ : { backedUp: Boolean(row.backedUp ?? row.backed_up) }),
950
+ createdAt: postgresBigintToUnixMillis(row.createdAt ?? row.created_at),
951
+ ...(optionalMillis(row.lastUsedAt ?? row.last_used_at) === undefined
952
+ ? {}
953
+ : { lastUsedAt: optionalMillis(row.lastUsedAt ?? row.last_used_at) }),
954
+ ...(optionalMillis(row.revokedAt ?? row.revoked_at) === undefined
955
+ ? {}
956
+ : { revokedAt: optionalMillis(row.revokedAt ?? row.revoked_at) }),
957
+ ...(optionalRecord(row.metadata) === undefined
958
+ ? {}
959
+ : { metadata: optionalRecord(row.metadata) }),
960
+ });
961
+ const decodeSession = (row) => ({
962
+ id: SessionId(String(row.id)),
963
+ userId: UserId(String(row.userId ?? row.user_id)),
964
+ secretHash: String(row.secretHash ?? row.secret_hash),
965
+ createdAt: postgresBigintToUnixMillis(row.createdAt ?? row.created_at),
966
+ expiresAt: postgresBigintToUnixMillis(row.expiresAt ?? row.expires_at),
967
+ authTime: postgresBigintToUnixMillis(row.authTime ?? row.auth_time),
968
+ authenticationEvents: parseAuthenticationEvents(row.authenticationEvents ?? row.authentication_events),
969
+ aal: String(row.aal),
970
+ amr: row.amr,
971
+ ...(row.claims === null || row.claims === undefined
972
+ ? {}
973
+ : { claims: row.claims }),
974
+ ...(optionalMillis(row.mfaVerifiedAt ?? row.mfa_verified_at) === undefined
975
+ ? {}
976
+ : {
977
+ mfaVerifiedAt: optionalMillis(row.mfaVerifiedAt ?? row.mfa_verified_at),
978
+ }),
979
+ ...(optionalRecord(row.metadata) === undefined
980
+ ? {}
981
+ : { metadata: optionalRecord(row.metadata) }),
982
+ ...(optionalMillis(row.revokedAt ?? row.revoked_at) === undefined
983
+ ? {}
984
+ : { revokedAt: optionalMillis(row.revokedAt ?? row.revoked_at) }),
985
+ ...(optionalMillis(row.lastSeenAt ?? row.last_seen_at) === undefined
986
+ ? {}
987
+ : { lastSeenAt: optionalMillis(row.lastSeenAt ?? row.last_seen_at) }),
988
+ ...(optionalMillis(row.rotatedAt ?? row.rotated_at) === undefined
989
+ ? {}
990
+ : { rotatedAt: optionalMillis(row.rotatedAt ?? row.rotated_at) }),
991
+ });
992
+ const decodeVerification = (row) => ({
993
+ id: ChallengeId(String(row.id)),
994
+ type: String(row.type),
995
+ subject: String(row.subject),
996
+ ...((row.secretHash ?? row.secret_hash) === null ||
997
+ (row.secretHash ?? row.secret_hash) === undefined
998
+ ? {}
999
+ : { secretHash: String(row.secretHash ?? row.secret_hash) }),
1000
+ createdAt: postgresBigintToUnixMillis(row.createdAt ?? row.created_at),
1001
+ expiresAt: postgresBigintToUnixMillis(row.expiresAt ?? row.expires_at),
1002
+ ...(optionalRecord(row.metadata) === undefined
1003
+ ? {}
1004
+ : { metadata: optionalRecord(row.metadata) }),
1005
+ ...(optionalMillis(row.consumedAt ?? row.consumed_at) === undefined
1006
+ ? {}
1007
+ : { consumedAt: optionalMillis(row.consumedAt ?? row.consumed_at) }),
1008
+ });
1009
+ const decodeTotpFactor = (row) => ({
1010
+ id: CredentialId(String(row.id)),
1011
+ userId: UserId(String(row.userId ?? row.user_id)),
1012
+ secret: Redacted.make(TotpSecret(String(row.secret))),
1013
+ algorithm: String(row.algorithm),
1014
+ digits: Number(row.digits),
1015
+ period: Number(row.period),
1016
+ createdAt: postgresBigintToUnixMillis(row.createdAt ?? row.created_at),
1017
+ ...(optionalMillis(row.confirmedAt ?? row.confirmed_at) === undefined
1018
+ ? {}
1019
+ : { confirmedAt: optionalMillis(row.confirmedAt ?? row.confirmed_at) }),
1020
+ ...(optionalMillis(row.lastUsedAt ?? row.last_used_at) === undefined
1021
+ ? {}
1022
+ : { lastUsedAt: optionalMillis(row.lastUsedAt ?? row.last_used_at) }),
1023
+ ...((row.lastAcceptedCounter ?? row.last_accepted_counter) === null ||
1024
+ (row.lastAcceptedCounter ?? row.last_accepted_counter) === undefined
1025
+ ? {}
1026
+ : {
1027
+ lastAcceptedCounter: Number(row.lastAcceptedCounter ?? row.last_accepted_counter),
1028
+ }),
1029
+ ...(optionalMillis(row.revokedAt ?? row.revoked_at) === undefined
1030
+ ? {}
1031
+ : { revokedAt: optionalMillis(row.revokedAt ?? row.revoked_at) }),
1032
+ ...(optionalRecord(row.metadata) === undefined
1033
+ ? {}
1034
+ : { metadata: optionalRecord(row.metadata) }),
1035
+ });
1036
+ const decodeRecoveryCode = (row) => ({
1037
+ id: CredentialId(String(row.id)),
1038
+ userId: UserId(String(row.userId ?? row.user_id)),
1039
+ codeHash: RecoveryCodeHash(String(row.codeHash ?? row.code_hash)),
1040
+ createdAt: postgresBigintToUnixMillis(row.createdAt ?? row.created_at),
1041
+ ...(optionalMillis(row.usedAt ?? row.used_at) === undefined
1042
+ ? {}
1043
+ : { usedAt: optionalMillis(row.usedAt ?? row.used_at) }),
1044
+ ...(optionalMillis(row.revokedAt ?? row.revoked_at) === undefined
1045
+ ? {}
1046
+ : { revokedAt: optionalMillis(row.revokedAt ?? row.revoked_at) }),
1047
+ ...(optionalRecord(row.metadata) === undefined
1048
+ ? {}
1049
+ : { metadata: optionalRecord(row.metadata) }),
1050
+ });
1051
+ const decodeApiKey = (row) => ({
1052
+ id: ApiKeyId(String(row.id)),
1053
+ userId: UserId(String(row.userId ?? row.user_id)),
1054
+ prefix: ApiKeyPrefix(String(row.prefix)),
1055
+ secretHash: ApiKeySecretHash(String(row.secretHash ?? row.secret_hash)),
1056
+ scopes: Array.isArray(row.scopes) ? row.scopes.map(String) : [],
1057
+ createdAt: postgresBigintToUnixMillis(row.createdAt ?? row.created_at),
1058
+ ...(optionalMillis(row.expiresAt ?? row.expires_at) === undefined
1059
+ ? {}
1060
+ : { expiresAt: optionalMillis(row.expiresAt ?? row.expires_at) }),
1061
+ ...(optionalMillis(row.lastUsedAt ?? row.last_used_at) === undefined
1062
+ ? {}
1063
+ : { lastUsedAt: optionalMillis(row.lastUsedAt ?? row.last_used_at) }),
1064
+ ...(optionalMillis(row.revokedAt ?? row.revoked_at) === undefined
1065
+ ? {}
1066
+ : { revokedAt: optionalMillis(row.revokedAt ?? row.revoked_at) }),
1067
+ ...(optionalRecord(row.metadata) === undefined
1068
+ ? {}
1069
+ : { metadata: optionalRecord(row.metadata) }),
1070
+ });
1071
+ const decodeRefreshToken = (row) => ({
1072
+ id: RefreshTokenId(String(row.id)),
1073
+ familyId: RefreshTokenFamilyId(String(row.familyId ?? row.family_id)),
1074
+ userId: UserId(String(row.userId ?? row.user_id)),
1075
+ secretHash: RefreshTokenSecretHash(String(row.secretHash ?? row.secret_hash)),
1076
+ createdAt: postgresBigintToUnixMillis(row.createdAt ?? row.created_at),
1077
+ expiresAt: postgresBigintToUnixMillis(row.expiresAt ?? row.expires_at),
1078
+ ...(optionalMillis(row.lastUsedAt ?? row.last_used_at) === undefined
1079
+ ? {}
1080
+ : { lastUsedAt: optionalMillis(row.lastUsedAt ?? row.last_used_at) }),
1081
+ ...(optionalMillis(row.rotatedAt ?? row.rotated_at) === undefined
1082
+ ? {}
1083
+ : { rotatedAt: optionalMillis(row.rotatedAt ?? row.rotated_at) }),
1084
+ ...((row.replacedById ?? row.replaced_by_id) === null ||
1085
+ (row.replacedById ?? row.replaced_by_id) === undefined
1086
+ ? {}
1087
+ : {
1088
+ replacedById: RefreshTokenId(String(row.replacedById ?? row.replaced_by_id)),
1089
+ }),
1090
+ ...(optionalMillis(row.revokedAt ?? row.revoked_at) === undefined
1091
+ ? {}
1092
+ : { revokedAt: optionalMillis(row.revokedAt ?? row.revoked_at) }),
1093
+ ...(optionalMillis(row.reuseDetectedAt ?? row.reuse_detected_at) === undefined
1094
+ ? {}
1095
+ : {
1096
+ reuseDetectedAt: optionalMillis(row.reuseDetectedAt ?? row.reuse_detected_at),
1097
+ }),
1098
+ ...(optionalRecord(row.metadata) === undefined
1099
+ ? {}
1100
+ : { metadata: optionalRecord(row.metadata) }),
1101
+ });
1102
+ const decodeJwtRevocation = (row) => ({
1103
+ jwtId: String(row.jwtId ?? row.jwt_id),
1104
+ revokedAt: postgresBigintToUnixMillis(row.revokedAt ?? row.revoked_at),
1105
+ ...(optionalMillis(row.expiresAt ?? row.expires_at) === undefined
1106
+ ? {}
1107
+ : { expiresAt: optionalMillis(row.expiresAt ?? row.expires_at) }),
1108
+ ...(row.reason === null || row.reason === undefined
1109
+ ? {}
1110
+ : { reason: String(row.reason) }),
1111
+ });
1112
+ const decodeOAuthAccount = (row) => ({
1113
+ id: OAuthAccountId(String(row.id)),
1114
+ providerId: OAuthProviderId(String(row.providerId ?? row.provider_id)),
1115
+ providerAccountId: String(row.providerAccountId ?? row.provider_account_id),
1116
+ userId: UserId(String(row.userId ?? row.user_id)),
1117
+ ...(row.email === null || row.email === undefined
1118
+ ? {}
1119
+ : { email: Email(String(row.email)) }),
1120
+ ...((row.emailVerified ?? row.email_verified) === null ||
1121
+ (row.emailVerified ?? row.email_verified) === undefined
1122
+ ? {}
1123
+ : { emailVerified: Boolean(row.emailVerified ?? row.email_verified) }),
1124
+ createdAt: postgresBigintToUnixMillis(row.createdAt ?? row.created_at),
1125
+ updatedAt: postgresBigintToUnixMillis(row.updatedAt ?? row.updated_at),
1126
+ ...(optionalMillis(row.unlinkedAt ?? row.unlinked_at) === undefined
1127
+ ? {}
1128
+ : { unlinkedAt: optionalMillis(row.unlinkedAt ?? row.unlinked_at) }),
1129
+ ...(optionalRecord(row.metadata) === undefined
1130
+ ? {}
1131
+ : { metadata: optionalRecord(row.metadata) }),
1132
+ });
1133
+ const stringArray = (value) => Array.isArray(value) ? value.map(String) : [];
1134
+ const decodeOAuthClient = (row) => ({
1135
+ id: OAuthClientId(String(row.id)),
1136
+ type: String(row.type),
1137
+ status: String(row.status),
1138
+ ...(row.name === null || row.name === undefined
1139
+ ? {}
1140
+ : { name: String(row.name) }),
1141
+ redirectUris: stringArray(row.redirectUris ?? row.redirect_uris),
1142
+ allowedGrantTypes: stringArray(row.allowedGrantTypes ?? row.allowed_grant_types),
1143
+ allowedResponseTypes: stringArray(row.allowedResponseTypes ?? row.allowed_response_types),
1144
+ ...((row.allowedScopes ?? row.allowed_scopes) === null ||
1145
+ (row.allowedScopes ?? row.allowed_scopes) === undefined
1146
+ ? {}
1147
+ : { allowedScopes: stringArray(row.allowedScopes ?? row.allowed_scopes) }),
1148
+ ...(optionalMillis(row.createdAt ?? row.created_at) === undefined
1149
+ ? {}
1150
+ : { createdAt: optionalMillis(row.createdAt ?? row.created_at) }),
1151
+ ...(optionalMillis(row.updatedAt ?? row.updated_at) === undefined
1152
+ ? {}
1153
+ : { updatedAt: optionalMillis(row.updatedAt ?? row.updated_at) }),
1154
+ ...(optionalRecord(row.metadata) === undefined
1155
+ ? {}
1156
+ : { metadata: optionalRecord(row.metadata) }),
1157
+ });
1158
+ const decodeOAuthConsent = (row) => ({
1159
+ userId: UserId(String(row.userId ?? row.user_id)),
1160
+ clientId: OAuthClientId(String(row.clientId ?? row.client_id)),
1161
+ scopes: stringArray(row.scopes),
1162
+ grantedAt: postgresBigintToUnixMillis(row.grantedAt ?? row.granted_at),
1163
+ ...(optionalMillis(row.expiresAt ?? row.expires_at) === undefined
1164
+ ? {}
1165
+ : { expiresAt: optionalMillis(row.expiresAt ?? row.expires_at) }),
1166
+ ...(optionalMillis(row.revokedAt ?? row.revoked_at) === undefined
1167
+ ? {}
1168
+ : { revokedAt: optionalMillis(row.revokedAt ?? row.revoked_at) }),
1169
+ ...(optionalRecord(row.metadata) === undefined
1170
+ ? {}
1171
+ : { metadata: optionalRecord(row.metadata) }),
1172
+ });
1173
+ const decodeOAuthAuthorizationCode = (row) => ({
1174
+ codeHash: String(row.codeHash ?? row.code_hash),
1175
+ clientId: OAuthClientId(String(row.clientId ?? row.client_id)),
1176
+ subject: String(row.subject),
1177
+ redirectUri: String(row.redirectUri ?? row.redirect_uri),
1178
+ scopes: stringArray(row.scopes),
1179
+ ...((row.codeChallenge ?? row.code_challenge) === null ||
1180
+ (row.codeChallenge ?? row.code_challenge) === undefined
1181
+ ? {}
1182
+ : {
1183
+ codeChallenge: OAuthCodeChallenge(String(row.codeChallenge ?? row.code_challenge)),
1184
+ }),
1185
+ ...((row.codeChallengeMethod ?? row.code_challenge_method) === null ||
1186
+ (row.codeChallengeMethod ?? row.code_challenge_method) === undefined
1187
+ ? {}
1188
+ : { codeChallengeMethod: "S256" }),
1189
+ issuedAt: postgresBigintToUnixMillis(row.issuedAt ?? row.issued_at),
1190
+ expiresAt: postgresBigintToUnixMillis(row.expiresAt ?? row.expires_at),
1191
+ ...(optionalMillis(row.consumedAt ?? row.consumed_at) === undefined
1192
+ ? {}
1193
+ : { consumedAt: optionalMillis(row.consumedAt ?? row.consumed_at) }),
1194
+ ...(optionalRecord(row.metadata) === undefined
1195
+ ? {}
1196
+ : { metadata: optionalRecord(row.metadata) }),
1197
+ });
1198
+ const decodeOAuthDeviceAuthorization = (row) => {
1199
+ const base = {
1200
+ id: OAuthDeviceAuthorizationId(String(row.id)),
1201
+ deviceCodeHash: String(row.deviceCodeHash ?? row.device_code_hash),
1202
+ userCodeHash: String(row.userCodeHash ?? row.user_code_hash),
1203
+ clientId: OAuthClientId(String(row.clientId ?? row.client_id)),
1204
+ requestedScopes: stringArray(row.requestedScopes ?? row.requested_scopes),
1205
+ issuedAt: postgresBigintToUnixMillis(row.issuedAt ?? row.issued_at),
1206
+ expiresAt: postgresBigintToUnixMillis(row.expiresAt ?? row.expires_at),
1207
+ pollIntervalSeconds: Number(row.pollIntervalSeconds ?? row.poll_interval_seconds),
1208
+ nextPollAt: postgresBigintToUnixMillis(row.nextPollAt ?? row.next_poll_at),
1209
+ ...(optionalMillis(row.lastPolledAt ?? row.last_polled_at) === undefined
1210
+ ? {}
1211
+ : {
1212
+ lastPolledAt: optionalMillis(row.lastPolledAt ?? row.last_polled_at),
1213
+ }),
1214
+ ...(optionalRecord(row.metadata) === undefined
1215
+ ? {}
1216
+ : { metadata: optionalRecord(row.metadata) }),
1217
+ };
1218
+ const status = String(row.status);
1219
+ if (status === "approved") {
1220
+ return {
1221
+ ...base,
1222
+ status: "approved",
1223
+ subject: String(row.subject),
1224
+ grantedScopes: stringArray(row.grantedScopes ?? row.granted_scopes),
1225
+ approvedAt: postgresBigintToUnixMillis(row.approvedAt ?? row.approved_at),
1226
+ ...(optionalMillis(row.consumedAt ?? row.consumed_at) === undefined
1227
+ ? {}
1228
+ : { consumedAt: optionalMillis(row.consumedAt ?? row.consumed_at) }),
1229
+ };
1230
+ }
1231
+ if (status === "denied") {
1232
+ return {
1233
+ ...base,
1234
+ status: "denied",
1235
+ deniedAt: postgresBigintToUnixMillis(row.deniedAt ?? row.denied_at),
1236
+ };
1237
+ }
1238
+ return { ...base, status: "pending" };
1239
+ };
1240
+ const decodeOAuthClientSecret = (row) => ({
1241
+ prefix: OAuthClientSecretPrefix(String(row.prefix)),
1242
+ clientId: OAuthClientId(String(row.clientId ?? row.client_id)),
1243
+ secretHash: OAuthClientSecretHash(String(row.secretHash ?? row.secret_hash)),
1244
+ authenticationMethods: stringArray(row.authenticationMethods ?? row.authentication_methods),
1245
+ createdAt: postgresBigintToUnixMillis(row.createdAt ?? row.created_at),
1246
+ ...(optionalMillis(row.expiresAt ?? row.expires_at) === undefined
1247
+ ? {}
1248
+ : { expiresAt: optionalMillis(row.expiresAt ?? row.expires_at) }),
1249
+ ...(optionalMillis(row.lastUsedAt ?? row.last_used_at) === undefined
1250
+ ? {}
1251
+ : { lastUsedAt: optionalMillis(row.lastUsedAt ?? row.last_used_at) }),
1252
+ ...(optionalMillis(row.revokedAt ?? row.revoked_at) === undefined
1253
+ ? {}
1254
+ : { revokedAt: optionalMillis(row.revokedAt ?? row.revoked_at) }),
1255
+ ...(optionalRecord(row.metadata) === undefined
1256
+ ? {}
1257
+ : { metadata: optionalRecord(row.metadata) }),
1258
+ });
1259
+ const decodeOAuthProviderModeTokenAudience = (value) => typeof value === "string"
1260
+ ? value
1261
+ : Array.isArray(value)
1262
+ ? value.map(String)
1263
+ : undefined;
1264
+ const decodeOAuthProviderModeToken = (row) => ({
1265
+ tokenHash: String(row.tokenHash ?? row.token_hash),
1266
+ tokenType: String(row.tokenType ?? row.token_type),
1267
+ clientId: OAuthClientId(String(row.clientId ?? row.client_id)),
1268
+ subject: String(row.subject),
1269
+ scopes: stringArray(row.scopes),
1270
+ issuedAt: postgresBigintToUnixMillis(row.issuedAt ?? row.issued_at),
1271
+ expiresAt: postgresBigintToUnixMillis(row.expiresAt ?? row.expires_at),
1272
+ ...(row.issuer === null || row.issuer === undefined
1273
+ ? {}
1274
+ : { issuer: String(row.issuer) }),
1275
+ ...(decodeOAuthProviderModeTokenAudience(row.audience) === undefined
1276
+ ? {}
1277
+ : { audience: decodeOAuthProviderModeTokenAudience(row.audience) }),
1278
+ ...((row.jwtId ?? row.jwt_id) === null ||
1279
+ (row.jwtId ?? row.jwt_id) === undefined
1280
+ ? {}
1281
+ : { jwtId: String(row.jwtId ?? row.jwt_id) }),
1282
+ ...(optionalMillis(row.revokedAt ?? row.revoked_at) === undefined
1283
+ ? {}
1284
+ : { revokedAt: optionalMillis(row.revokedAt ?? row.revoked_at) }),
1285
+ ...((row.revocationReason ?? row.revocation_reason) === null ||
1286
+ (row.revocationReason ?? row.revocation_reason) === undefined
1287
+ ? {}
1288
+ : {
1289
+ revocationReason: String(row.revocationReason ?? row.revocation_reason),
1290
+ }),
1291
+ ...(optionalMillis(row.rotatedAt ?? row.rotated_at) === undefined
1292
+ ? {}
1293
+ : { rotatedAt: optionalMillis(row.rotatedAt ?? row.rotated_at) }),
1294
+ ...((row.replacedByTokenHash ?? row.replaced_by_token_hash) === null ||
1295
+ (row.replacedByTokenHash ?? row.replaced_by_token_hash) === undefined
1296
+ ? {}
1297
+ : {
1298
+ replacedByTokenHash: String(row.replacedByTokenHash ?? row.replaced_by_token_hash),
1299
+ }),
1300
+ ...(optionalRecord(row.metadata) === undefined
1301
+ ? {}
1302
+ : { metadata: optionalRecord(row.metadata) }),
1303
+ });
1304
+ const decodeOAuthProviderTokenVault = (row) => ({
1305
+ accountId: OAuthAccountId(String(row.accountId ?? row.account_id)),
1306
+ userId: UserId(String(row.userId ?? row.user_id)),
1307
+ providerId: OAuthProviderId(String(row.providerId ?? row.provider_id)),
1308
+ providerAccountId: String(row.providerAccountId ?? row.provider_account_id),
1309
+ accessTokenCiphertext: Redacted.make(String(row.accessTokenCiphertext ?? row.access_token_ciphertext)),
1310
+ ...((row.refreshTokenCiphertext ?? row.refresh_token_ciphertext) === null ||
1311
+ (row.refreshTokenCiphertext ?? row.refresh_token_ciphertext) === undefined
1312
+ ? {}
1313
+ : {
1314
+ refreshTokenCiphertext: Redacted.make(String(row.refreshTokenCiphertext ?? row.refresh_token_ciphertext)),
1315
+ }),
1316
+ ...((row.idTokenCiphertext ?? row.id_token_ciphertext) === null ||
1317
+ (row.idTokenCiphertext ?? row.id_token_ciphertext) === undefined
1318
+ ? {}
1319
+ : {
1320
+ idTokenCiphertext: Redacted.make(String(row.idTokenCiphertext ?? row.id_token_ciphertext)),
1321
+ }),
1322
+ tokenType: String(row.tokenType ?? row.token_type),
1323
+ ...(row.scopes === null || row.scopes === undefined
1324
+ ? {}
1325
+ : { scopes: stringArray(row.scopes) }),
1326
+ ...(optionalMillis(row.expiresAt ?? row.expires_at) === undefined
1327
+ ? {}
1328
+ : { expiresAt: optionalMillis(row.expiresAt ?? row.expires_at) }),
1329
+ updatedAt: postgresBigintToUnixMillis(row.updatedAt ?? row.updated_at),
1330
+ ...(optionalMillis(row.revokedAt ?? row.revoked_at) === undefined
1331
+ ? {}
1332
+ : { revokedAt: optionalMillis(row.revokedAt ?? row.revoked_at) }),
1333
+ ...((row.revocationReason ?? row.revocation_reason) === null ||
1334
+ (row.revocationReason ?? row.revocation_reason) === undefined
1335
+ ? {}
1336
+ : {
1337
+ revocationReason: String(row.revocationReason ?? row.revocation_reason),
1338
+ }),
1339
+ });
1340
+ const providerTokenVaultTokens = (record) => ({
1341
+ accessTokenCiphertext: record.accessTokenCiphertext,
1342
+ ...(record.refreshTokenCiphertext === undefined
1343
+ ? {}
1344
+ : { refreshTokenCiphertext: record.refreshTokenCiphertext }),
1345
+ ...(record.idTokenCiphertext === undefined
1346
+ ? {}
1347
+ : { idTokenCiphertext: record.idTokenCiphertext }),
1348
+ tokenType: record.tokenType,
1349
+ ...(record.scopes === undefined ? {} : { scopes: record.scopes }),
1350
+ ...(record.expiresAt === undefined ? {} : { expiresAt: record.expiresAt }),
1351
+ });
1352
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
1353
+ const isLoginRiskLevel = (value) => value === "unknown" ||
1354
+ value === "low" ||
1355
+ value === "medium" ||
1356
+ value === "high" ||
1357
+ value === "critical";
1358
+ const decodeLoginRiskSignal = (value) => {
1359
+ const record = isRecord(value) ? value : {};
1360
+ return LoginRiskSignal.make({
1361
+ type: typeof record.type === "string" ? record.type : "unknown",
1362
+ ...(isLoginRiskLevel(record.level) ? { level: record.level } : {}),
1363
+ ...(isRecord(record.metadata) ? { metadata: record.metadata } : {}),
1364
+ });
1365
+ };
1366
+ const decodeLoginRiskContext = (value) => {
1367
+ if (!isRecord(value)) {
1368
+ return undefined;
1369
+ }
1370
+ return LoginRiskContext.make({
1371
+ level: isLoginRiskLevel(value.level) ? value.level : "unknown",
1372
+ signals: Array.isArray(value.signals)
1373
+ ? value.signals.map(decodeLoginRiskSignal)
1374
+ : [],
1375
+ ...(isRecord(value.metadata) ? { metadata: value.metadata } : {}),
1376
+ });
1377
+ };
1378
+ const encodeLoginRiskContext = (risk) => risk === undefined
1379
+ ? null
1380
+ : {
1381
+ level: risk.level,
1382
+ signals: risk.signals.map((signal) => ({
1383
+ type: signal.type,
1384
+ ...(signal.level === undefined ? {} : { level: signal.level }),
1385
+ ...(signal.metadata === undefined
1386
+ ? {}
1387
+ : { metadata: signal.metadata }),
1388
+ })),
1389
+ ...(risk.metadata === undefined ? {} : { metadata: risk.metadata }),
1390
+ };
1391
+ const decodeAuditLogEvent = (row) => decodeAuditEvent(row.event);
1392
+ const decodeLoginApprovalReview = (row) => ({
1393
+ approvalChallengeId: ChallengeId(String(row.approvalChallengeId ?? row.approval_challenge_id)),
1394
+ flowId: AuthFlowId(String(row.flowId ?? row.flow_id)),
1395
+ userId: UserId(String(row.userId ?? row.user_id)),
1396
+ channel: String(row.channel),
1397
+ reason: String(row.reason),
1398
+ sessionBinding: String(row.sessionBinding ?? row.session_binding),
1399
+ sameDeviceRequired: Boolean(row.sameDeviceRequired ?? row.same_device_required),
1400
+ status: String(row.status),
1401
+ createdAt: postgresBigintToUnixMillis(row.createdAt ?? row.created_at),
1402
+ expiresAt: postgresBigintToUnixMillis(row.expiresAt ?? row.expires_at),
1403
+ ...(optionalMillis(row.reviewedAt ?? row.reviewed_at) === undefined
1404
+ ? {}
1405
+ : { reviewedAt: optionalMillis(row.reviewedAt ?? row.reviewed_at) }),
1406
+ ...((row.reviewedBy ?? row.reviewed_by) === null ||
1407
+ (row.reviewedBy ?? row.reviewed_by) === undefined
1408
+ ? {}
1409
+ : {
1410
+ reviewedBy: String(row.reviewedBy ?? row.reviewed_by),
1411
+ }),
1412
+ ...((row.deniedReason ?? row.denied_reason) === null ||
1413
+ (row.deniedReason ?? row.denied_reason) === undefined
1414
+ ? {}
1415
+ : { deniedReason: String(row.deniedReason ?? row.denied_reason) }),
1416
+ ...(decodeLoginRiskContext(row.risk) === undefined
1417
+ ? {}
1418
+ : { risk: decodeLoginRiskContext(row.risk) }),
1419
+ ...(optionalRecord(row.metadata) === undefined
1420
+ ? {}
1421
+ : { metadata: optionalRecord(row.metadata) }),
1422
+ ...(optionalRecord(row.reviewMetadata ?? row.review_metadata) === undefined
1423
+ ? {}
1424
+ : {
1425
+ reviewMetadata: optionalRecord(row.reviewMetadata ?? row.review_metadata),
1426
+ }),
1427
+ });
1428
+ const decodeLoginRiskHistoryRecord = (row) => {
1429
+ const latitudeMicro = row.latitudeMicro ?? row.latitude_micro;
1430
+ const longitudeMicro = row.longitudeMicro ?? row.longitude_micro;
1431
+ return {
1432
+ id: String(row.id),
1433
+ userId: UserId(String(row.userId ?? row.user_id)),
1434
+ occurredAt: postgresBigintToUnixMillis(row.occurredAt ?? row.occurred_at),
1435
+ outcome: String(row.outcome),
1436
+ method: String(row.method),
1437
+ amr: Array.isArray(row.amr)
1438
+ ? row.amr.map(String)
1439
+ : [],
1440
+ aal: String(row.aal),
1441
+ device: {
1442
+ status: String(row.deviceStatus ?? row.device_status),
1443
+ },
1444
+ ...((row.deviceKey ?? row.device_key) === null ||
1445
+ (row.deviceKey ?? row.device_key) === undefined
1446
+ ? {}
1447
+ : { deviceKey: String(row.deviceKey ?? row.device_key) }),
1448
+ ...((row.locationKey ?? row.location_key) === null ||
1449
+ (row.locationKey ?? row.location_key) === undefined
1450
+ ? {}
1451
+ : { locationKey: String(row.locationKey ?? row.location_key) }),
1452
+ ...(row.country === null || row.country === undefined
1453
+ ? {}
1454
+ : { country: String(row.country) }),
1455
+ ...(row.region === null || row.region === undefined
1456
+ ? {}
1457
+ : { region: String(row.region) }),
1458
+ ...(latitudeMicro === null || latitudeMicro === undefined
1459
+ ? {}
1460
+ : {
1461
+ latitude: postgresBigintToSafeInteger(latitudeMicro, "latitude") / 1_000_000,
1462
+ }),
1463
+ ...(longitudeMicro === null || longitudeMicro === undefined
1464
+ ? {}
1465
+ : {
1466
+ longitude: postgresBigintToSafeInteger(longitudeMicro, "longitude") /
1467
+ 1_000_000,
1468
+ }),
1469
+ ...((row.riskLevel ?? row.risk_level) === null ||
1470
+ (row.riskLevel ?? row.risk_level) === undefined
1471
+ ? {}
1472
+ : {
1473
+ riskLevel: String(row.riskLevel ?? row.risk_level),
1474
+ }),
1475
+ createdAt: postgresBigintToUnixMillis(row.createdAt ?? row.created_at),
1476
+ };
1477
+ };
1478
+ const decodeTrustedDevice = (row) => ({
1479
+ userId: UserId(String(row.userId ?? row.user_id)),
1480
+ tokenHash: String(row.tokenHash ?? row.token_hash),
1481
+ createdAt: postgresBigintToUnixMillis(row.createdAt ?? row.created_at),
1482
+ lastSeenAt: postgresBigintToUnixMillis(row.lastSeenAt ?? row.last_seen_at),
1483
+ expiresAt: postgresBigintToUnixMillis(row.expiresAt ?? row.expires_at),
1484
+ ...(optionalRecord(row.metadata) === undefined
1485
+ ? {}
1486
+ : { metadata: optionalRecord(row.metadata) }),
1487
+ });
1488
+ const decodeDomainVerification = (row) => ({
1489
+ id: DomainVerificationId(String(row.id)),
1490
+ ownerId: String(row.ownerId ?? row.owner_id),
1491
+ domain: DomainName(String(row.domain)),
1492
+ proofMethod: String(row.proofMethod ?? row.proof_method),
1493
+ proofToken: DomainVerificationProofToken(String(row.proofToken ?? row.proof_token)),
1494
+ status: String(row.status),
1495
+ createdAt: postgresBigintToUnixMillis(row.createdAt ?? row.created_at),
1496
+ expiresAt: postgresBigintToUnixMillis(row.expiresAt ?? row.expires_at),
1497
+ ...(optionalMillis(row.verifiedAt ?? row.verified_at) === undefined
1498
+ ? {}
1499
+ : { verifiedAt: optionalMillis(row.verifiedAt ?? row.verified_at) }),
1500
+ ...(optionalMillis(row.revokedAt ?? row.revoked_at) === undefined
1501
+ ? {}
1502
+ : { revokedAt: optionalMillis(row.revokedAt ?? row.revoked_at) }),
1503
+ ...(optionalMillis(row.lastCheckedAt ?? row.last_checked_at) === undefined
1504
+ ? {}
1505
+ : {
1506
+ lastCheckedAt: optionalMillis(row.lastCheckedAt ?? row.last_checked_at),
1507
+ }),
1508
+ ...(optionalRecord(row.metadata) === undefined
1509
+ ? {}
1510
+ : { metadata: optionalRecord(row.metadata) }),
1511
+ });
1512
+ const decodeSecurityTimelineEvent = (row) => ({
1513
+ id: SecurityTimelineEventId(String(row.id)),
1514
+ userId: UserId(String(row.userId ?? row.user_id)),
1515
+ type: String(row.type),
1516
+ category: String(row.category),
1517
+ severity: String(row.severity),
1518
+ occurredAt: postgresBigintToUnixMillis(row.occurredAt ?? row.occurred_at),
1519
+ summary: String(row.summary),
1520
+ ...(row.actor === null || row.actor === undefined
1521
+ ? {}
1522
+ : { actor: row.actor }),
1523
+ ...(row.request === null || row.request === undefined
1524
+ ? {}
1525
+ : { request: row.request }),
1526
+ ...(optionalRecord(row.metadata) === undefined
1527
+ ? {}
1528
+ : { metadata: optionalRecord(row.metadata) }),
1529
+ });
1530
+ const decodeWebhookOutboxRecord = (row) => ({
1531
+ id: WebhookOutboxItemId(String(row.id)),
1532
+ endpointKey: String(row.endpointKey ?? row.endpoint_key),
1533
+ event: row.event,
1534
+ status: String(row.status),
1535
+ attempts: Number(row.attempts),
1536
+ nextAttemptAt: postgresBigintToUnixMillis(row.nextAttemptAt ?? row.next_attempt_at),
1537
+ createdAt: postgresBigintToUnixMillis(row.createdAt ?? row.created_at),
1538
+ updatedAt: postgresBigintToUnixMillis(row.updatedAt ?? row.updated_at),
1539
+ ...(optionalMillis(row.deliveredAt ?? row.delivered_at) === undefined
1540
+ ? {}
1541
+ : { deliveredAt: optionalMillis(row.deliveredAt ?? row.delivered_at) }),
1542
+ ...((row.lastError ?? row.last_error) === null ||
1543
+ (row.lastError ?? row.last_error) === undefined
1544
+ ? {}
1545
+ : { lastError: String(row.lastError ?? row.last_error) }),
1546
+ });
1547
+ const decodePermissionDefinition = (row) => ({
1548
+ id: PermissionId(String(row.id)),
1549
+ ...(row.description === null || row.description === undefined
1550
+ ? {}
1551
+ : { description: String(row.description) }),
1552
+ ...((row.scopeTypePresent ?? row.scope_type_present)
1553
+ ? { scopeType: String(row.scopeType ?? row.scope_type) }
1554
+ : {}),
1555
+ createdAt: postgresBigintToUnixMillis(row.createdAt ?? row.created_at),
1556
+ updatedAt: postgresBigintToUnixMillis(row.updatedAt ?? row.updated_at),
1557
+ ...(optionalMillis(row.disabledAt ?? row.disabled_at) === undefined
1558
+ ? {}
1559
+ : { disabledAt: optionalMillis(row.disabledAt ?? row.disabled_at) }),
1560
+ ...(optionalMillis(row.deletedAt ?? row.deleted_at) === undefined
1561
+ ? {}
1562
+ : { deletedAt: optionalMillis(row.deletedAt ?? row.deleted_at) }),
1563
+ });
1564
+ const decodeRoleDefinition = (row) => ({
1565
+ id: RoleId(String(row.id)),
1566
+ ...(row.description === null || row.description === undefined
1567
+ ? {}
1568
+ : { description: String(row.description) }),
1569
+ createdAt: postgresBigintToUnixMillis(row.createdAt ?? row.created_at),
1570
+ updatedAt: postgresBigintToUnixMillis(row.updatedAt ?? row.updated_at),
1571
+ ...(optionalMillis(row.disabledAt ?? row.disabled_at) === undefined
1572
+ ? {}
1573
+ : { disabledAt: optionalMillis(row.disabledAt ?? row.disabled_at) }),
1574
+ ...(optionalMillis(row.deletedAt ?? row.deleted_at) === undefined
1575
+ ? {}
1576
+ : { deletedAt: optionalMillis(row.deletedAt ?? row.deleted_at) }),
1577
+ });
1578
+ const decodePermissionScope = (scopeType, scopeIdPresent, storedScopeId) => {
1579
+ const type = String(scopeType);
1580
+ if (!scopeIdPresent) {
1581
+ return type === "global" ? undefined : { type };
1582
+ }
1583
+ return { type, id: String(storedScopeId) };
1584
+ };
1585
+ const decodePermissionGrant = (row) => ({
1586
+ subject: {
1587
+ type: String(row.subjectType ?? row.subject_type),
1588
+ id: String(row.subjectId ?? row.subject_id),
1589
+ },
1590
+ permission: PermissionId(String(row.permissionId ?? row.permission_id)),
1591
+ ...(decodePermissionScope(row.scopeType ?? row.scope_type, row.scopeIdPresent ?? row.scope_id_present, row.scopeId ?? row.scope_id) === undefined
1592
+ ? {}
1593
+ : {
1594
+ scope: decodePermissionScope(row.scopeType ?? row.scope_type, row.scopeIdPresent ?? row.scope_id_present, row.scopeId ?? row.scope_id),
1595
+ }),
1596
+ ...(optionalMillis(row.expiresAt ?? row.expires_at) === undefined
1597
+ ? {}
1598
+ : { expiresAt: optionalMillis(row.expiresAt ?? row.expires_at) }),
1599
+ ...(optionalRecord(row.metadata) === undefined
1600
+ ? {}
1601
+ : { metadata: optionalRecord(row.metadata) }),
1602
+ ...(optionalMillis(row.revokedAt ?? row.revoked_at) === undefined
1603
+ ? {}
1604
+ : { revokedAt: optionalMillis(row.revokedAt ?? row.revoked_at) }),
1605
+ });
1606
+ const decodeRoleGrant = (row) => ({
1607
+ subject: {
1608
+ type: String(row.subjectType ?? row.subject_type),
1609
+ id: String(row.subjectId ?? row.subject_id),
1610
+ },
1611
+ role: RoleId(String(row.roleId ?? row.role_id)),
1612
+ ...(decodePermissionScope(row.scopeType ?? row.scope_type, row.scopeIdPresent ?? row.scope_id_present, row.scopeId ?? row.scope_id) === undefined
1613
+ ? {}
1614
+ : {
1615
+ scope: decodePermissionScope(row.scopeType ?? row.scope_type, row.scopeIdPresent ?? row.scope_id_present, row.scopeId ?? row.scope_id),
1616
+ }),
1617
+ ...(optionalMillis(row.expiresAt ?? row.expires_at) === undefined
1618
+ ? {}
1619
+ : { expiresAt: optionalMillis(row.expiresAt ?? row.expires_at) }),
1620
+ ...(optionalRecord(row.metadata) === undefined
1621
+ ? {}
1622
+ : { metadata: optionalRecord(row.metadata) }),
1623
+ ...(optionalMillis(row.revokedAt ?? row.revoked_at) === undefined
1624
+ ? {}
1625
+ : { revokedAt: optionalMillis(row.revokedAt ?? row.revoked_at) }),
1626
+ });
1627
+ const decodeRolePermission = (row) => ({
1628
+ role: RoleId(String(row.roleId ?? row.role_id)),
1629
+ permission: PermissionId(String(row.permissionId ?? row.permission_id)),
1630
+ ...((row.scopeTypePresent ?? row.scope_type_present)
1631
+ ? { scopeType: String(row.scopeType ?? row.scope_type) }
1632
+ : {}),
1633
+ });
1634
+ const userValues = (row) => ({
1635
+ id: row.id,
1636
+ created_at: millisParam(row.createdAt),
1637
+ updated_at: millisParam(row.updatedAt),
1638
+ disabled_at: row.disabledAt === undefined ? null : millisParam(row.disabledAt),
1639
+ metadata: row.metadata ?? null,
1640
+ });
1641
+ const identityValues = (row) => ({
1642
+ id: row.id,
1643
+ user_id: row.userId,
1644
+ scope_type: row.scope.type,
1645
+ scope_id: scopeId(row.scope),
1646
+ kind: row.kind,
1647
+ value: row.value,
1648
+ normalized_value: row.normalizedValue,
1649
+ verified_at: row.verifiedAt === undefined ? null : millisParam(row.verifiedAt),
1650
+ is_primary_login: row.isPrimaryLogin ?? false,
1651
+ created_at: millisParam(row.createdAt),
1652
+ updated_at: millisParam(row.createdAt),
1653
+ revoked_at: null,
1654
+ replaced_by_id: null,
1655
+ metadata: row.metadata ?? null,
1656
+ });
1657
+ const credentialValues = (row) => ({
1658
+ id: row.id,
1659
+ user_id: row.userId,
1660
+ type: "password",
1661
+ password_hash: row.passwordHash,
1662
+ created_at: millisParam(row.createdAt),
1663
+ updated_at: millisParam(row.updatedAt),
1664
+ revoked_at: row.revokedAt === undefined ? null : millisParam(row.revokedAt),
1665
+ metadata: row.metadata ?? null,
1666
+ });
1667
+ const passkeyCredentialValues = (row) => ({
1668
+ id: row.id,
1669
+ user_id: row.userId,
1670
+ credential_id: row.credentialId,
1671
+ public_key: row.publicKey,
1672
+ sign_count: safeIntegerToPostgresBigint(row.signCount, "Passkey sign count"),
1673
+ transports: row.transports ?? null,
1674
+ backed_up: row.backedUp ?? null,
1675
+ created_at: millisParam(row.createdAt),
1676
+ last_used_at: row.lastUsedAt === undefined ? null : millisParam(row.lastUsedAt),
1677
+ revoked_at: row.revokedAt === undefined ? null : millisParam(row.revokedAt),
1678
+ metadata: row.metadata ?? null,
1679
+ });
1680
+ const sessionValues = (row) => ({
1681
+ id: row.id,
1682
+ user_id: row.userId,
1683
+ secret_hash: row.secretHash,
1684
+ created_at: millisParam(row.createdAt),
1685
+ expires_at: millisParam(row.expiresAt),
1686
+ auth_time: millisParam(row.authTime),
1687
+ authentication_events: row.authenticationEvents,
1688
+ aal: row.aal,
1689
+ amr: row.amr,
1690
+ claims: row.claims ?? null,
1691
+ mfa_verified_at: row.mfaVerifiedAt === undefined ? null : millisParam(row.mfaVerifiedAt),
1692
+ metadata: row.metadata ?? null,
1693
+ revoked_at: null,
1694
+ last_seen_at: null,
1695
+ rotated_at: null,
1696
+ });
1697
+ const verificationValues = (row) => ({
1698
+ id: row.id,
1699
+ type: row.type,
1700
+ subject: row.subject,
1701
+ secret_hash: row.secretHash ?? null,
1702
+ created_at: millisParam(row.createdAt),
1703
+ expires_at: millisParam(row.expiresAt),
1704
+ metadata: row.metadata ?? null,
1705
+ consumed_at: null,
1706
+ });
1707
+ const totpFactorValues = (row) => ({
1708
+ id: row.id,
1709
+ user_id: row.userId,
1710
+ secret: Redacted.value(row.secret),
1711
+ algorithm: row.algorithm,
1712
+ digits: row.digits,
1713
+ period: row.period,
1714
+ created_at: millisParam(row.createdAt),
1715
+ confirmed_at: row.confirmedAt === undefined ? null : millisParam(row.confirmedAt),
1716
+ last_used_at: row.lastUsedAt === undefined ? null : millisParam(row.lastUsedAt),
1717
+ last_accepted_counter: row.lastAcceptedCounter === undefined
1718
+ ? null
1719
+ : String(row.lastAcceptedCounter),
1720
+ revoked_at: row.revokedAt === undefined ? null : millisParam(row.revokedAt),
1721
+ metadata: row.metadata ?? null,
1722
+ });
1723
+ const recoveryCodeValues = (row) => ({
1724
+ id: row.id,
1725
+ user_id: row.userId,
1726
+ code_hash: row.codeHash,
1727
+ created_at: millisParam(row.createdAt),
1728
+ used_at: row.usedAt === undefined ? null : millisParam(row.usedAt),
1729
+ revoked_at: row.revokedAt === undefined ? null : millisParam(row.revokedAt),
1730
+ metadata: row.metadata ?? null,
1731
+ });
1732
+ const apiKeyValues = (row) => ({
1733
+ id: row.id,
1734
+ user_id: row.userId,
1735
+ prefix: row.prefix,
1736
+ secret_hash: row.secretHash,
1737
+ scopes: row.scopes,
1738
+ created_at: millisParam(row.createdAt),
1739
+ expires_at: row.expiresAt === undefined ? null : millisParam(row.expiresAt),
1740
+ last_used_at: row.lastUsedAt === undefined ? null : millisParam(row.lastUsedAt),
1741
+ revoked_at: row.revokedAt === undefined ? null : millisParam(row.revokedAt),
1742
+ metadata: row.metadata ?? null,
1743
+ });
1744
+ const refreshTokenValues = (row) => ({
1745
+ id: row.id,
1746
+ family_id: row.familyId,
1747
+ user_id: row.userId,
1748
+ secret_hash: row.secretHash,
1749
+ created_at: millisParam(row.createdAt),
1750
+ expires_at: millisParam(row.expiresAt),
1751
+ last_used_at: row.lastUsedAt === undefined ? null : millisParam(row.lastUsedAt),
1752
+ rotated_at: row.rotatedAt === undefined ? null : millisParam(row.rotatedAt),
1753
+ replaced_by_id: row.replacedById ?? null,
1754
+ revoked_at: row.revokedAt === undefined ? null : millisParam(row.revokedAt),
1755
+ reuse_detected_at: row.reuseDetectedAt === undefined ? null : millisParam(row.reuseDetectedAt),
1756
+ metadata: row.metadata ?? null,
1757
+ });
1758
+ const jwtRevocationValues = (row) => ({
1759
+ jwt_id: row.jwtId,
1760
+ revoked_at: millisParam(row.revokedAt),
1761
+ expires_at: row.expiresAt === undefined ? null : millisParam(row.expiresAt),
1762
+ reason: row.reason ?? null,
1763
+ });
1764
+ const oauthAccountValues = (row) => ({
1765
+ id: row.id,
1766
+ provider_id: row.providerId,
1767
+ provider_account_id: row.providerAccountId,
1768
+ user_id: row.userId,
1769
+ email: row.email ?? null,
1770
+ email_verified: row.emailVerified ?? null,
1771
+ created_at: millisParam(row.createdAt),
1772
+ updated_at: millisParam(row.updatedAt),
1773
+ unlinked_at: row.unlinkedAt === undefined ? null : millisParam(row.unlinkedAt),
1774
+ metadata: row.metadata ?? null,
1775
+ });
1776
+ const oauthClientValues = (row) => ({
1777
+ id: row.id,
1778
+ type: row.type,
1779
+ status: row.status,
1780
+ name: row.name ?? null,
1781
+ redirect_uris: row.redirectUris,
1782
+ allowed_grant_types: row.allowedGrantTypes,
1783
+ allowed_response_types: row.allowedResponseTypes,
1784
+ allowed_scopes: row.allowedScopes ?? null,
1785
+ created_at: row.createdAt === undefined ? null : millisParam(row.createdAt),
1786
+ updated_at: row.updatedAt === undefined ? null : millisParam(row.updatedAt),
1787
+ metadata: row.metadata ?? null,
1788
+ });
1789
+ const oauthConsentValues = (row) => ({
1790
+ user_id: row.userId,
1791
+ client_id: row.clientId,
1792
+ scopes: row.scopes,
1793
+ granted_at: millisParam(row.grantedAt),
1794
+ expires_at: row.expiresAt === undefined ? null : millisParam(row.expiresAt),
1795
+ revoked_at: row.revokedAt === undefined ? null : millisParam(row.revokedAt),
1796
+ metadata: row.metadata ?? null,
1797
+ });
1798
+ const oauthAuthorizationCodeValues = (row) => ({
1799
+ code_hash: row.codeHash,
1800
+ client_id: row.clientId,
1801
+ subject: row.subject,
1802
+ redirect_uri: row.redirectUri,
1803
+ scopes: row.scopes,
1804
+ code_challenge: row.codeChallenge ?? null,
1805
+ code_challenge_method: row.codeChallengeMethod ?? null,
1806
+ issued_at: millisParam(row.issuedAt),
1807
+ expires_at: millisParam(row.expiresAt),
1808
+ consumed_at: row.consumedAt === undefined ? null : millisParam(row.consumedAt),
1809
+ metadata: row.metadata ?? null,
1810
+ });
1811
+ const oauthDeviceAuthorizationValues = (row) => ({
1812
+ id: row.id,
1813
+ device_code_hash: row.deviceCodeHash,
1814
+ user_code_hash: row.userCodeHash,
1815
+ client_id: row.clientId,
1816
+ requested_scopes: row.requestedScopes,
1817
+ granted_scopes: null,
1818
+ subject: null,
1819
+ status: "pending",
1820
+ issued_at: millisParam(row.issuedAt),
1821
+ expires_at: millisParam(row.expiresAt),
1822
+ poll_interval_seconds: row.pollIntervalSeconds,
1823
+ next_poll_at: millisParam(row.nextPollAt),
1824
+ last_polled_at: row.lastPolledAt === undefined ? null : millisParam(row.lastPolledAt),
1825
+ approved_at: null,
1826
+ denied_at: null,
1827
+ consumed_at: null,
1828
+ metadata: row.metadata ?? null,
1829
+ });
1830
+ const oauthClientSecretValues = (row) => ({
1831
+ prefix: row.prefix,
1832
+ client_id: row.clientId,
1833
+ secret_hash: row.secretHash,
1834
+ authentication_methods: row.authenticationMethods,
1835
+ created_at: millisParam(row.createdAt),
1836
+ expires_at: row.expiresAt === undefined ? null : millisParam(row.expiresAt),
1837
+ last_used_at: row.lastUsedAt === undefined ? null : millisParam(row.lastUsedAt),
1838
+ revoked_at: row.revokedAt === undefined ? null : millisParam(row.revokedAt),
1839
+ metadata: row.metadata ?? null,
1840
+ });
1841
+ const oauthProviderModeTokenValues = (row) => ({
1842
+ token_hash: row.tokenHash,
1843
+ token_type: row.tokenType,
1844
+ client_id: row.clientId,
1845
+ subject: row.subject,
1846
+ scopes: row.scopes,
1847
+ issued_at: millisParam(row.issuedAt),
1848
+ expires_at: millisParam(row.expiresAt),
1849
+ issuer: row.issuer ?? null,
1850
+ audience: row.audience ?? null,
1851
+ jwt_id: row.jwtId ?? null,
1852
+ revoked_at: row.revokedAt === undefined ? null : millisParam(row.revokedAt),
1853
+ revocation_reason: row.revocationReason ?? null,
1854
+ rotated_at: row.rotatedAt === undefined ? null : millisParam(row.rotatedAt),
1855
+ replaced_by_token_hash: row.replacedByTokenHash ?? null,
1856
+ metadata: row.metadata ?? null,
1857
+ });
1858
+ const oauthProviderTokenVaultValues = (row) => ({
1859
+ account_id: row.accountId,
1860
+ user_id: row.userId,
1861
+ provider_id: row.providerId,
1862
+ provider_account_id: row.providerAccountId,
1863
+ access_token_ciphertext: Redacted.value(row.accessTokenCiphertext),
1864
+ refresh_token_ciphertext: row.refreshTokenCiphertext === undefined
1865
+ ? null
1866
+ : Redacted.value(row.refreshTokenCiphertext),
1867
+ id_token_ciphertext: row.idTokenCiphertext === undefined
1868
+ ? null
1869
+ : Redacted.value(row.idTokenCiphertext),
1870
+ token_type: row.tokenType,
1871
+ scopes: row.scopes ?? null,
1872
+ expires_at: row.expiresAt === undefined ? null : millisParam(row.expiresAt),
1873
+ updated_at: millisParam(row.updatedAt),
1874
+ revoked_at: row.revokedAt === undefined ? null : millisParam(row.revokedAt),
1875
+ revocation_reason: row.revocationReason ?? null,
1876
+ });
1877
+ const auditLogValues = (event, createdAt) => ({
1878
+ id: event.id ?? null,
1879
+ type: event.type,
1880
+ user_id: auditEventUserId(event) ?? null,
1881
+ actor_user_id: auditEventActorUserId(event) ?? null,
1882
+ occurred_at: millisParam(event.occurredAt),
1883
+ request_ip_hash: event.request?.ipHash ?? null,
1884
+ request_user_agent_hash: event.request?.userAgentHash ?? null,
1885
+ event,
1886
+ created_at: millisParam(createdAt),
1887
+ });
1888
+ const loginApprovalReviewValues = (row) => ({
1889
+ approval_challenge_id: row.approvalChallengeId,
1890
+ flow_id: row.flowId,
1891
+ user_id: row.userId,
1892
+ channel: row.channel,
1893
+ reason: row.reason,
1894
+ session_binding: row.sessionBinding,
1895
+ same_device_required: row.sameDeviceRequired,
1896
+ status: row.status,
1897
+ created_at: millisParam(row.createdAt),
1898
+ expires_at: millisParam(row.expiresAt),
1899
+ reviewed_at: row.reviewedAt === undefined ? null : millisParam(row.reviewedAt),
1900
+ reviewed_by: row.reviewedBy ?? null,
1901
+ denied_reason: row.deniedReason ?? null,
1902
+ risk: encodeLoginRiskContext(row.risk),
1903
+ metadata: row.metadata ?? null,
1904
+ review_metadata: row.reviewMetadata ?? null,
1905
+ });
1906
+ const coordinateMicro = (value) => value === undefined || !Number.isFinite(value)
1907
+ ? null
1908
+ : safeIntegerToPostgresBigint(Math.round(value * 1_000_000), "Login risk coordinate");
1909
+ const loginRiskHistoryValues = (row) => ({
1910
+ id: row.id,
1911
+ user_id: row.userId,
1912
+ occurred_at: millisParam(row.occurredAt),
1913
+ outcome: row.outcome,
1914
+ method: row.method,
1915
+ amr: row.amr,
1916
+ aal: row.aal,
1917
+ device_status: row.device.status,
1918
+ device_key: row.deviceKey ?? null,
1919
+ location_key: row.locationKey ?? null,
1920
+ country: row.country ?? null,
1921
+ region: row.region ?? null,
1922
+ latitude_micro: coordinateMicro(row.latitude),
1923
+ longitude_micro: coordinateMicro(row.longitude),
1924
+ risk_level: row.riskLevel ?? null,
1925
+ created_at: millisParam(row.createdAt),
1926
+ });
1927
+ const trustedDeviceValues = (input) => ({
1928
+ user_id: input.userId,
1929
+ token_hash: input.tokenHash,
1930
+ created_at: millisParam(input.now),
1931
+ last_seen_at: millisParam(input.now),
1932
+ expires_at: millisParam(input.expiresAt),
1933
+ metadata: input.metadata ?? null,
1934
+ });
1935
+ const domainVerificationValues = (record) => ({
1936
+ id: record.id,
1937
+ owner_id: record.ownerId,
1938
+ domain: record.domain,
1939
+ proof_method: record.proofMethod,
1940
+ proof_token: record.proofToken,
1941
+ status: record.status,
1942
+ created_at: millisParam(record.createdAt),
1943
+ expires_at: millisParam(record.expiresAt),
1944
+ verified_at: record.verifiedAt === undefined ? null : millisParam(record.verifiedAt),
1945
+ revoked_at: record.revokedAt === undefined ? null : millisParam(record.revokedAt),
1946
+ last_checked_at: record.lastCheckedAt === undefined
1947
+ ? null
1948
+ : millisParam(record.lastCheckedAt),
1949
+ metadata: record.metadata ?? null,
1950
+ });
1951
+ const securityTimelineValues = (event) => ({
1952
+ id: event.id,
1953
+ user_id: event.userId,
1954
+ type: event.type,
1955
+ category: event.category,
1956
+ severity: event.severity,
1957
+ occurred_at: millisParam(event.occurredAt),
1958
+ summary: event.summary,
1959
+ actor: event.actor ?? null,
1960
+ request: event.request ?? null,
1961
+ metadata: event.metadata ?? null,
1962
+ });
1963
+ const webhookOutboxValues = (record) => ({
1964
+ id: record.id,
1965
+ endpoint_key: record.endpointKey,
1966
+ event: record.event,
1967
+ status: record.status,
1968
+ attempts: record.attempts,
1969
+ next_attempt_at: millisParam(record.nextAttemptAt),
1970
+ created_at: millisParam(record.createdAt),
1971
+ updated_at: millisParam(record.updatedAt),
1972
+ delivered_at: record.deliveredAt === undefined ? null : millisParam(record.deliveredAt),
1973
+ last_error: record.lastError ?? null,
1974
+ });
1975
+ const permissionScopeValues = (scope) => ({
1976
+ scope_type: scope?.type ?? "global",
1977
+ scope_id_present: scope?.id !== undefined,
1978
+ scope_id: scope?.id ?? "",
1979
+ });
1980
+ const permissionDefinitionValues = (definition) => ({
1981
+ id: definition.id,
1982
+ description: definition.description ?? null,
1983
+ scope_type_present: definition.scopeType !== undefined,
1984
+ scope_type: definition.scopeType ?? "",
1985
+ created_at: millisParam(definition.createdAt),
1986
+ updated_at: millisParam(definition.updatedAt),
1987
+ disabled_at: definition.disabledAt === undefined
1988
+ ? null
1989
+ : millisParam(definition.disabledAt),
1990
+ deleted_at: definition.deletedAt === undefined
1991
+ ? null
1992
+ : millisParam(definition.deletedAt),
1993
+ });
1994
+ const roleDefinitionValues = (definition) => ({
1995
+ id: definition.id,
1996
+ description: definition.description ?? null,
1997
+ created_at: millisParam(definition.createdAt),
1998
+ updated_at: millisParam(definition.updatedAt),
1999
+ disabled_at: definition.disabledAt === undefined
2000
+ ? null
2001
+ : millisParam(definition.disabledAt),
2002
+ deleted_at: definition.deletedAt === undefined
2003
+ ? null
2004
+ : millisParam(definition.deletedAt),
2005
+ });
2006
+ const permissionGrantValues = (input) => ({
2007
+ subject_type: input.subject.type,
2008
+ subject_id: input.subject.id,
2009
+ permission_id: input.permission,
2010
+ ...permissionScopeValues(input.scope),
2011
+ expires_at: input.expiresAt === undefined ? null : millisParam(input.expiresAt),
2012
+ metadata: input.metadata ?? null,
2013
+ revoked_at: null,
2014
+ });
2015
+ const roleGrantValues = (input) => ({
2016
+ subject_type: input.subject.type,
2017
+ subject_id: input.subject.id,
2018
+ role_id: input.role,
2019
+ ...permissionScopeValues(input.scope),
2020
+ expires_at: input.expiresAt === undefined ? null : millisParam(input.expiresAt),
2021
+ metadata: input.metadata ?? null,
2022
+ revoked_at: null,
2023
+ });
2024
+ const rolePermissionValues = (input) => ({
2025
+ role_id: input.role,
2026
+ permission_id: input.permission,
2027
+ scope_type_present: input.scopeType !== undefined,
2028
+ scope_type: input.scopeType ?? "",
2029
+ });
2030
+ const execute = (executor, plan) => executor.execute(plan);
2031
+ const executeMapped = (executor, makePlan, mapError) => Effect.try({ try: makePlan, catch: mapError }).pipe(Effect.flatMap((plan) => Effect.try({
2032
+ try: () => execute(executor, plan),
2033
+ catch: mapError,
2034
+ }).pipe(Effect.flatMap((effect) => effect.pipe(Effect.mapError(mapError))))));
2035
+ const decodeMapped = (decode, mapError) => Effect.try({ try: decode, catch: mapError });
2036
+ const eq = (left, right) => Query.eq(left, right);
2037
+ const gt = (left, right) => Query.gt(left, right);
2038
+ const gte = (left, right) => Query.gte(left, right);
2039
+ const lt = (left, right) => Query.lt(left, right);
2040
+ const lte = (left, right) => Query.lte(left, right);
2041
+ const isNull = (value) => Query.isNull(value);
2042
+ const isNotNull = (value) => Query.isNotNull(value);
2043
+ const withoutNullRefinement = (value) => Query.cast(value, value[Scalar.TypeId].dbType);
2044
+ const or = (...values) => Query.or(...values);
2045
+ const and = (...values) => Query.and(...values);
2046
+ const exists = (plan) => Query.exists(plan);
2047
+ const inValues = (value, values) => Query.in(value, ...values);
2048
+ const insert = (table, values) => Query.insert(table, values);
2049
+ const update = (table, values) => Query.update(table, values);
2050
+ const selectForUpdate = (selection, table, predicate) => Query.lock("update")(Query.where(predicate)(Query.from(table)(Query.select(selection))));
2051
+ const metadataWithReason = (column, key, reason) => Jsonb.concat(Query.coalesce(column, Jsonb.toJsonb({})), Jsonb.toJsonb({ [key]: reason }));
2052
+ const storageError = (entity, operation, cause) => StorageError.fromUnknown(entity, operation, cause);
2053
+ const firstOption = (rows, decode) => rows[0] === undefined ? Option.none() : Option.some(decode(rows[0]));
2054
+ export const makeEffectQbPostgresExecutor = (sql) => Executor.make({
2055
+ renderer: postgresRenderer,
2056
+ valueMappings: postgresValueMappings,
2057
+ driver: Executor.driver((query) => sql.unsafe(query.sql, [...query.params])),
2058
+ });
2059
+ export const makeEffectQbPostgresAtomicPlanExecutor = (sql) => {
2060
+ const executePlans = (plans) => {
2061
+ if (plans.length === 0) {
2062
+ return Effect.succeed([]);
2063
+ }
2064
+ const rendered = Effect.try({
2065
+ try: () => plans.map((plan, statement) => {
2066
+ try {
2067
+ return { plan, rendered: postgresRenderer.render(plan) };
2068
+ }
2069
+ catch (error) {
2070
+ throw new AtomicPlanError({
2071
+ statement,
2072
+ phase: "render",
2073
+ commitState: "not-committed",
2074
+ cause: error,
2075
+ });
2076
+ }
2077
+ }),
2078
+ catch: (cause) => cause instanceof AtomicPlanError
2079
+ ? cause
2080
+ : new AtomicPlanError({
2081
+ phase: "render",
2082
+ commitState: "not-committed",
2083
+ cause,
2084
+ }),
2085
+ });
2086
+ return rendered.pipe(Effect.flatMap((entries) => sql.withTransaction(Effect.forEach(entries, ({ plan, rendered: query }, statement) => sql.unsafe(query.sql, [...query.params]).pipe(Effect.mapError((cause) => new AtomicPlanError({
2087
+ statement,
2088
+ phase: "execute",
2089
+ commitState: "not-committed",
2090
+ cause,
2091
+ })), Effect.flatMap((rows) => Effect.try({
2092
+ try: () => CoreExecutor.decodeRows(query, plan, rows, {
2093
+ driverMode: "raw",
2094
+ }),
2095
+ catch: (cause) => new AtomicPlanError({
2096
+ statement,
2097
+ phase: "decode",
2098
+ commitState: "not-committed",
2099
+ cause,
2100
+ }),
2101
+ })))))), Effect.catchCause((cause) => {
2102
+ if (Cause.hasInterruptsOnly(cause)) {
2103
+ return Effect.failCause(cause);
2104
+ }
2105
+ const failure = Cause.findErrorOption(cause);
2106
+ return Option.isSome(failure) &&
2107
+ failure.value instanceof AtomicPlanError
2108
+ ? Effect.fail(failure.value)
2109
+ : Effect.fail(new AtomicPlanError({
2110
+ phase: "transaction",
2111
+ commitState: "unknown",
2112
+ cause,
2113
+ }));
2114
+ }), Effect.map((results) => results));
2115
+ };
2116
+ return { dialect: "postgres", execute: executePlans };
2117
+ };
2118
+ export const postgresErrorDetails = (cause) => {
2119
+ let current = cause;
2120
+ const seen = new Set();
2121
+ let code;
2122
+ let constraintName;
2123
+ while (typeof current === "object" &&
2124
+ current !== null &&
2125
+ !seen.has(current)) {
2126
+ seen.add(current);
2127
+ const record = current;
2128
+ const candidateCode = record.code;
2129
+ if (code === undefined && typeof candidateCode === "string") {
2130
+ const normalized = candidateCode.trim().toUpperCase();
2131
+ if (/^[0-9A-Z]{5}$/.test(normalized)) {
2132
+ code = normalized;
2133
+ }
2134
+ }
2135
+ const candidateConstraint = record.constraintName ?? record.constraint;
2136
+ if (constraintName === undefined &&
2137
+ typeof candidateConstraint === "string" &&
2138
+ candidateConstraint.trim() !== "") {
2139
+ constraintName = candidateConstraint.trim();
2140
+ }
2141
+ current = record.cause ?? record.reason ?? record.raw;
2142
+ }
2143
+ return { code, constraintName };
2144
+ };
2145
+ const identityConflict = (row) => new IdentityConflictError({
2146
+ scope: row.scope,
2147
+ kind: row.kind,
2148
+ normalizedValue: row.normalizedValue,
2149
+ });
2150
+ const isExpectedIdentityConflict = (cause) => {
2151
+ const details = postgresErrorDetails(cause);
2152
+ return (details.code === "23505" &&
2153
+ (details.constraintName === "auth_user_identity_pkey" ||
2154
+ details.constraintName === "auth_user_identity_active_value_idx" ||
2155
+ details.constraintName === "auth_user_identity_active_primary_idx"));
2156
+ };
2157
+ const totpFactorStoreError = (operation, cause) => new TotpFactorStoreError({
2158
+ operation,
2159
+ message: `TOTP factor ${operation} failed`,
2160
+ cause,
2161
+ });
2162
+ const passkeyCredentialStoreError = (operation, cause) => new PasskeyCredentialStoreError({
2163
+ operation,
2164
+ message: `Passkey credential ${operation} failed`,
2165
+ cause,
2166
+ });
2167
+ const recoveryCodeStoreError = (operation, cause) => new RecoveryCodeStoreError({
2168
+ operation,
2169
+ message: `Recovery code ${operation} failed`,
2170
+ cause,
2171
+ });
2172
+ const apiKeyStoreError = (operation, cause) => new ApiKeyStoreError({
2173
+ operation,
2174
+ message: `API key ${operation} failed`,
2175
+ cause,
2176
+ });
2177
+ const refreshTokenStoreError = (operation, cause) => new RefreshTokenStoreError({
2178
+ operation,
2179
+ message: `Refresh token ${operation} failed`,
2180
+ cause,
2181
+ });
2182
+ const oauthAccountStoreError = (operation, cause) => new OAuthAccountStoreError({
2183
+ operation,
2184
+ message: `OAuth account ${operation} failed`,
2185
+ cause,
2186
+ });
2187
+ const oauthClientStoreError = (operation, cause) => new OAuthClientStoreError({
2188
+ operation,
2189
+ message: `OAuth client ${operation} failed`,
2190
+ cause,
2191
+ });
2192
+ const oauthConsentStoreError = (operation, cause) => new OAuthConsentStoreError({
2193
+ operation,
2194
+ message: `OAuth consent ${operation} failed`,
2195
+ cause,
2196
+ });
2197
+ const oauthAuthorizationCodeStoreError = (operation, cause) => new OAuthAuthorizationCodeStoreError({
2198
+ operation,
2199
+ message: `OAuth authorization code ${operation} failed`,
2200
+ cause,
2201
+ });
2202
+ const oauthDeviceAuthorizationStoreError = (operation, cause) => new OAuthDeviceAuthorizationStoreError({
2203
+ operation,
2204
+ message: `OAuth device authorization ${operation} failed`,
2205
+ cause,
2206
+ });
2207
+ const oauthDeviceCodeTokenCommitStoreError = (cause) => new OAuthDeviceCodeTokenCommitStoreError({
2208
+ operation: "commit",
2209
+ message: "OAuth device token commit failed",
2210
+ cause,
2211
+ });
2212
+ const oauthClientSecretStoreError = (operation, cause) => new OAuthClientSecretStoreError({
2213
+ operation,
2214
+ message: `OAuth client secret ${operation} failed`,
2215
+ cause,
2216
+ });
2217
+ const oauthProviderModeTokenStoreError = (operation, cause) => new OAuthProviderModeTokenStoreError({
2218
+ operation,
2219
+ message: `OAuth provider-mode token ${operation} failed`,
2220
+ cause,
2221
+ });
2222
+ const oauthProviderTokenVaultError = (operation, cause) => new OAuthProviderTokenVaultError({
2223
+ operation,
2224
+ message: `OAuth provider token vault ${operation} failed`,
2225
+ cause,
2226
+ });
2227
+ const jwtRevocationStoreError = (operation, cause) => new JwtError({
2228
+ operation: "revocation",
2229
+ message: `JWT revocation ${operation} failed`,
2230
+ cause,
2231
+ });
2232
+ const auditLogStoreError = (operation, cause) => new AuditLogStoreError({
2233
+ operation,
2234
+ message: `Audit log ${operation} failed`,
2235
+ cause,
2236
+ });
2237
+ const loginApprovalReviewStoreError = (operation, cause) => new LoginApprovalReviewError({
2238
+ message: `Login approval review ${operation} failed`,
2239
+ cause,
2240
+ });
2241
+ const loginRiskHistoryStoreError = (operation, cause) => new LoginRiskHistoryError({
2242
+ operation,
2243
+ message: `Login risk history ${operation} failed`,
2244
+ cause,
2245
+ });
2246
+ const trustedDeviceStoreError = (operation, cause) => new TrustedDeviceError({
2247
+ operation,
2248
+ message: `Trusted device ${operation} failed`,
2249
+ cause,
2250
+ });
2251
+ const domainVerificationStoreError = (operation, cause) => new DomainVerificationStoreError({
2252
+ operation,
2253
+ message: `Domain verification ${operation} failed`,
2254
+ cause,
2255
+ });
2256
+ const securityTimelineStoreError = (operation, cause) => new SecurityTimelineStoreError({
2257
+ operation,
2258
+ message: `Security timeline ${operation} failed`,
2259
+ cause,
2260
+ });
2261
+ const webhookOutboxStoreError = (operation, cause) => new WebhookOutboxStoreError({
2262
+ operation,
2263
+ message: `Webhook outbox ${operation} failed`,
2264
+ cause,
2265
+ });
2266
+ const webhookReplayStoreError = (operation, cause) => new WebhookReplayStoreError({
2267
+ operation,
2268
+ message: `Webhook replay ${operation} failed`,
2269
+ cause,
2270
+ });
2271
+ const permissionStoreError = (operation, cause) => new PermissionStoreError({
2272
+ operation,
2273
+ message: `Permission store ${operation} failed`,
2274
+ cause,
2275
+ });
2276
+ const jsonEqual = (left, right) => {
2277
+ if (Object.is(left, right)) {
2278
+ return true;
2279
+ }
2280
+ if (Array.isArray(left) && Array.isArray(right)) {
2281
+ return (left.length === right.length &&
2282
+ left.every((entry, index) => jsonEqual(entry, right[index])));
2283
+ }
2284
+ if (typeof left === "object" &&
2285
+ left !== null &&
2286
+ typeof right === "object" &&
2287
+ right !== null) {
2288
+ const leftRecord = left;
2289
+ const rightRecord = right;
2290
+ const leftKeys = Object.keys(leftRecord);
2291
+ return (leftKeys.length === Object.keys(rightRecord).length &&
2292
+ leftKeys.every((key) => Object.hasOwn(rightRecord, key) &&
2293
+ jsonEqual(leftRecord[key], rightRecord[key])));
2294
+ }
2295
+ return false;
2296
+ };
2297
+ const sameVerification = (actual, expected) => jsonEqual(decodeVerification(actual), expected);
2298
+ const updateAssuredSession = (executor, input) => execute(executor, update(authPostgresSession, {
2299
+ secret_hash: input.secretHash,
2300
+ rotated_at: millisParam(input.rotatedAt),
2301
+ authentication_events: input.authenticationEvents,
2302
+ auth_time: millisParam(input.authTime),
2303
+ aal: input.aal,
2304
+ amr: input.amr,
2305
+ mfa_verified_at: input.mfaVerifiedAt === undefined
2306
+ ? null
2307
+ : millisParam(input.mfaVerifiedAt),
2308
+ ...(input.claims === undefined ? {} : { claims: input.claims }),
2309
+ }).pipe(Query.where(eq(authPostgresSession.id, input.sessionId)), Query.where(eq(authPostgresSession.user_id, input.userId)), Query.returning(sessionSelection)));
2310
+ const insertSession = (executor, row) => Effect.try({
2311
+ try: () => insert(authPostgresSession, sessionValues(row)).pipe(Query.returning(sessionSelection)),
2312
+ catch: (cause) => new PostgresPlanBuildError({ cause }),
2313
+ }).pipe(Effect.flatMap((plan) => execute(executor, plan)));
2314
+ export const makeEffectQbPostgresUserStore = (executor) => UserStore.of({
2315
+ findById: (id) => execute(executor, Query.select(userSelection).pipe(Query.from(authPostgresUser), Query.where(eq(authPostgresUser.id, id)))).pipe(Effect.mapError((cause) => storageError("user", "find", cause)), Effect.map((rows) => firstOption(rows, decodeUser))),
2316
+ insert: (row) => execute(executor, insert(authPostgresUser, userValues(row))).pipe(Effect.mapError((cause) => storageError("user", "insert", cause)), Effect.asVoid),
2317
+ });
2318
+ export const makeEffectQbPostgresIdentityStore = (executor, sql) => {
2319
+ const findById = (id) => execute(executor, Query.select(identitySelection).pipe(Query.from(authPostgresUserIdentity), Query.where(eq(authPostgresUserIdentity.id, id)))).pipe(Effect.mapError((cause) => storageError("identity", "find", cause)), Effect.map((rows) => firstOption(rows, decodeIdentity)));
2320
+ const transactionError = (operation) => (cause) => storageError("identity", operation, cause);
2321
+ return IdentityStore.of({
2322
+ findById,
2323
+ findByKindAndNormalizedValue: (input) => execute(executor, Query.select(identitySelection).pipe(Query.from(authPostgresUserIdentity), Query.where(eq(authPostgresUserIdentity.scope_type, input.scope.type)), Query.where(eq(authPostgresUserIdentity.scope_id, scopeId(input.scope))), Query.where(eq(authPostgresUserIdentity.kind, input.kind)), Query.where(eq(authPostgresUserIdentity.normalized_value, input.normalizedValue)), Query.where(isNull(authPostgresUserIdentity.revoked_at)))).pipe(Effect.mapError((cause) => storageError("identity", "find", cause)), Effect.map((rows) => firstOption(rows, decodeIdentity))),
2324
+ listByUser: (input) => {
2325
+ let plan = Query.select(identitySelection).pipe(Query.from(authPostgresUserIdentity), Query.where(eq(authPostgresUserIdentity.user_id, input.userId)));
2326
+ if (input.includeRevoked !== true) {
2327
+ plan = plan.pipe(Query.where(isNull(authPostgresUserIdentity.revoked_at)));
2328
+ }
2329
+ plan = plan.pipe(Query.orderBy(authPostgresUserIdentity.created_at, "asc"), Query.orderBy(Query.collate(authPostgresUserIdentity.id, "C"), "asc"));
2330
+ return execute(executor, plan).pipe(Effect.mapError((cause) => storageError("identity", "find", cause)), Effect.map((rows) => rows.map(decodeIdentity)));
2331
+ },
2332
+ insert: (row) => execute(executor, insert(authPostgresUserIdentity, identityValues(row))).pipe(Effect.mapError((cause) => isExpectedIdentityConflict(cause)
2333
+ ? identityConflict(row)
2334
+ : storageError("identity", "insert", cause)), Effect.asVoid),
2335
+ markVerified: (input) => execute(executor, update(authPostgresUserIdentity, {
2336
+ verified_at: millisParam(input.verifiedAt),
2337
+ updated_at: millisParam(input.verifiedAt),
2338
+ }).pipe(Query.where(eq(authPostgresUserIdentity.id, input.id)), Query.where(eq(authPostgresUserIdentity.normalized_value, input.expectedNormalizedValue)), Query.where(isNull(authPostgresUserIdentity.revoked_at)), Query.returning(identitySelection))).pipe(Effect.mapError((cause) => storageError("identity", "update", cause)), Effect.map((rows) => firstOption(rows, decodeIdentity))),
2339
+ setPrimaryLogin: (input) => sql
2340
+ .withTransaction(Effect.gen(function* () {
2341
+ const locked = yield* execute(executor, Query.select(identitySelection).pipe(Query.from(authPostgresUserIdentity), Query.where(eq(authPostgresUserIdentity.user_id, input.userId)), Query.where(isNull(authPostgresUserIdentity.revoked_at)), Query.orderBy(authPostgresUserIdentity.created_at, "asc"), Query.orderBy(Query.collate(authPostgresUserIdentity.id, "C"), "asc"), Query.lock("update")));
2342
+ const selected = locked.find((row) => row.id === input.identityId);
2343
+ if (selected === undefined ||
2344
+ String(selected.updatedAt) !==
2345
+ millisParam(input.expectedUpdatedAt) ||
2346
+ (selected.kind === "email" && selected.verifiedAt === null)) {
2347
+ return Option.none();
2348
+ }
2349
+ yield* execute(executor, update(authPostgresUserIdentity, {
2350
+ is_primary_login: false,
2351
+ updated_at: millisParam(input.updatedAt),
2352
+ }).pipe(Query.where(eq(authPostgresUserIdentity.user_id, input.userId)), Query.where(isNull(authPostgresUserIdentity.revoked_at))));
2353
+ const rows = yield* execute(executor, update(authPostgresUserIdentity, {
2354
+ is_primary_login: true,
2355
+ updated_at: millisParam(input.updatedAt),
2356
+ }).pipe(Query.where(eq(authPostgresUserIdentity.id, input.identityId)), Query.where(eq(authPostgresUserIdentity.user_id, input.userId)), Query.where(isNull(authPostgresUserIdentity.revoked_at)), Query.returning(identitySelection)));
2357
+ return firstOption(rows, decodeIdentity);
2358
+ }))
2359
+ .pipe(Effect.mapError(transactionError("setPrimaryLogin"))),
2360
+ replace: (input) => sql
2361
+ .withTransaction(Effect.gen(function* () {
2362
+ if (input.replacement.userId !== input.userId) {
2363
+ return Option.none();
2364
+ }
2365
+ const locked = yield* execute(executor, Query.select(identitySelection).pipe(Query.from(authPostgresUserIdentity), Query.where(eq(authPostgresUserIdentity.user_id, input.userId)), Query.where(isNull(authPostgresUserIdentity.revoked_at)), Query.orderBy(authPostgresUserIdentity.created_at, "asc"), Query.orderBy(Query.collate(authPostgresUserIdentity.id, "C"), "asc"), Query.lock("update")));
2366
+ const previous = locked.find((row) => row.id === input.id);
2367
+ if (previous === undefined ||
2368
+ String(previous.updatedAt) !==
2369
+ millisParam(input.expectedUpdatedAt)) {
2370
+ return Option.none();
2371
+ }
2372
+ const active = locked.map(decodeIdentity);
2373
+ if (isIdentityLoginEligible(decodeIdentity(previous)) &&
2374
+ !isIdentityLoginEligible(input.replacement) &&
2375
+ active.filter(isIdentityLoginEligible).length <= 1) {
2376
+ return Option.none();
2377
+ }
2378
+ const updated = yield* execute(executor, update(authPostgresUserIdentity, {
2379
+ revoked_at: millisParam(input.replacedAt),
2380
+ replaced_by_id: input.replacement.id,
2381
+ is_primary_login: false,
2382
+ updated_at: millisParam(input.replacedAt),
2383
+ }).pipe(Query.where(eq(authPostgresUserIdentity.id, input.id)), Query.returning(identitySelection)));
2384
+ const row = input.replacement;
2385
+ const inserted = yield* execute(executor, insert(authPostgresUserIdentity, {
2386
+ ...identityValues(row),
2387
+ is_primary_login: row.isPrimaryLogin ?? Boolean(previous.isPrimaryLogin),
2388
+ }).pipe(Query.returning(identitySelection)));
2389
+ const [updatedPrevious] = updated;
2390
+ const [insertedReplacement] = inserted;
2391
+ return Option.some({
2392
+ previous: decodeIdentity(updatedPrevious),
2393
+ replacement: decodeIdentity(insertedReplacement),
2394
+ });
2395
+ }))
2396
+ .pipe(Effect.mapError((cause) => isExpectedIdentityConflict(cause)
2397
+ ? identityConflict(input.replacement)
2398
+ : transactionError("replace")(cause))),
2399
+ revoke: (input) => sql
2400
+ .withTransaction(Effect.gen(function* () {
2401
+ const rows = yield* execute(executor, Query.select(identitySelection).pipe(Query.from(authPostgresUserIdentity), Query.where(eq(authPostgresUserIdentity.user_id, input.userId)), Query.where(isNull(authPostgresUserIdentity.revoked_at)), Query.orderBy(authPostgresUserIdentity.created_at, "asc"), Query.orderBy(Query.collate(authPostgresUserIdentity.id, "C"), "asc"), Query.lock("update")));
2402
+ const selected = rows.find((row) => row.id === input.id);
2403
+ if (selected === undefined ||
2404
+ String(selected.updatedAt) !==
2405
+ millisParam(input.expectedUpdatedAt)) {
2406
+ return Option.none();
2407
+ }
2408
+ const eligible = rows.filter((row) => row.kind !== "email" || row.verifiedAt !== null);
2409
+ const selectedEligible = selected.kind !== "email" || selected.verifiedAt !== null;
2410
+ if (selectedEligible && eligible.length <= 1) {
2411
+ return Option.none();
2412
+ }
2413
+ const metadata = input.reason === undefined
2414
+ ? selected.metadata
2415
+ : {
2416
+ ...optionalRecord(selected.metadata),
2417
+ revokeReason: input.reason,
2418
+ };
2419
+ const revoked = yield* execute(executor, update(authPostgresUserIdentity, {
2420
+ revoked_at: millisParam(input.revokedAt),
2421
+ updated_at: millisParam(input.revokedAt),
2422
+ is_primary_login: false,
2423
+ metadata: metadata ?? null,
2424
+ }).pipe(Query.where(eq(authPostgresUserIdentity.id, input.id)), Query.returning(identitySelection)));
2425
+ if (selected.isPrimaryLogin === true) {
2426
+ const promoted = eligible.find((row) => row.id !== input.id);
2427
+ if (promoted !== undefined) {
2428
+ yield* execute(executor, update(authPostgresUserIdentity, {
2429
+ is_primary_login: true,
2430
+ updated_at: millisParam(input.revokedAt),
2431
+ }).pipe(Query.where(eq(authPostgresUserIdentity.id, promoted.id))));
2432
+ }
2433
+ }
2434
+ return firstOption(revoked, decodeIdentity);
2435
+ }))
2436
+ .pipe(Effect.mapError(transactionError("revoke"))),
2437
+ });
2438
+ };
2439
+ export const makeEffectQbPostgresCredentialStore = (executor) => {
2440
+ const find = (userId, operation = "find") => execute(executor, Query.select(credentialSelection).pipe(Query.from(authPostgresCredential), Query.where(eq(authPostgresCredential.user_id, userId)), Query.where(eq(authPostgresCredential.type, "password")))).pipe(Effect.mapError((cause) => storageError("credential", operation, cause)), Effect.map((rows) => firstOption(rows, decodeCredential)));
2441
+ return CredentialStore.of({
2442
+ findPasswordByUserId: find,
2443
+ insertPassword: (row) => execute(executor, insert(authPostgresCredential, credentialValues(row))).pipe(Effect.mapError((cause) => storageError("credential", "insert", cause)), Effect.asVoid),
2444
+ updatePassword: (input) => execute(executor, update(authPostgresCredential, {
2445
+ password_hash: input.passwordHash,
2446
+ updated_at: millisParam(input.updatedAt),
2447
+ }).pipe(Query.where(eq(authPostgresCredential.user_id, input.userId)), Query.where(eq(authPostgresCredential.type, "password")), Query.where(isNull(authPostgresCredential.revoked_at)), Query.returning(credentialSelection))).pipe(Effect.mapError((cause) => storageError("credential", "updatePassword", cause)), Effect.map((rows) => firstOption(rows, decodeCredential))),
2448
+ });
2449
+ };
2450
+ export const makeEffectQbPostgresPasskeyCredentialStore = (executor) => {
2451
+ const findByCredentialId = (credentialId, operation = "find") => {
2452
+ const mapError = (cause) => passkeyCredentialStoreError(operation, cause);
2453
+ return executeMapped(executor, () => Query.select(passkeyCredentialSelection).pipe(Query.from(authPostgresPasskeyCredential), Query.where(eq(authPostgresPasskeyCredential.credential_id, credentialId))), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodePasskeyCredential), mapError)));
2454
+ };
2455
+ return PasskeyCredentialStore.of({
2456
+ insert: (row) => {
2457
+ const mapError = (cause) => passkeyCredentialStoreError("insert", cause);
2458
+ return executeMapped(executor, () => insert(authPostgresPasskeyCredential, passkeyCredentialValues(row)), mapError).pipe(Effect.asVoid);
2459
+ },
2460
+ findByCredentialId,
2461
+ listByUser: (input) => {
2462
+ const mapError = (cause) => passkeyCredentialStoreError("list", cause);
2463
+ return executeMapped(executor, () => {
2464
+ let plan = Query.select(passkeyCredentialSelection).pipe(Query.from(authPostgresPasskeyCredential), Query.where(eq(authPostgresPasskeyCredential.user_id, input.userId)));
2465
+ if (input.includeRevoked !== true) {
2466
+ plan = plan.pipe(Query.where(isNull(authPostgresPasskeyCredential.revoked_at)));
2467
+ }
2468
+ return plan.pipe(Query.orderBy(authPostgresPasskeyCredential.created_at, "asc"), Query.orderBy(Query.collate(authPostgresPasskeyCredential.id, "C"), "asc"));
2469
+ }, mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => rows.map(decodePasskeyCredential), mapError)));
2470
+ },
2471
+ updateSignCount: (input) => {
2472
+ const mapError = (cause) => passkeyCredentialStoreError("update-sign-count", cause);
2473
+ return executeMapped(executor, () => update(authPostgresPasskeyCredential, {
2474
+ sign_count: safeIntegerToPostgresBigint(input.signCount, "Passkey sign count"),
2475
+ last_used_at: millisParam(input.lastUsedAt),
2476
+ ...(input.metadata === undefined
2477
+ ? {}
2478
+ : { metadata: input.metadata }),
2479
+ }).pipe(Query.where(eq(authPostgresPasskeyCredential.credential_id, input.credentialId)), Query.where(eq(authPostgresPasskeyCredential.sign_count, safeIntegerToPostgresBigint(input.expectedSignCount, "Expected passkey sign count"))), Query.where(isNull(authPostgresPasskeyCredential.revoked_at)), Query.returning(passkeyCredentialSelection)), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodePasskeyCredential), mapError)));
2480
+ },
2481
+ revoke: (input) => {
2482
+ const mapError = (cause) => passkeyCredentialStoreError("revoke", cause);
2483
+ return executeMapped(executor, () => {
2484
+ const values = {
2485
+ revoked_at: millisParam(input.revokedAt),
2486
+ ...(input.reason === undefined
2487
+ ? {}
2488
+ : {
2489
+ metadata: metadataWithReason(authPostgresPasskeyCredential.metadata, "revokeReason", input.reason),
2490
+ }),
2491
+ };
2492
+ return update(authPostgresPasskeyCredential, values).pipe(Query.where(eq(authPostgresPasskeyCredential.credential_id, input.credentialId)));
2493
+ }, mapError).pipe(Effect.asVoid);
2494
+ },
2495
+ });
2496
+ };
2497
+ export const makeEffectQbPostgresApiKeyStore = (executor) => {
2498
+ const find = (column, value, operation = "find") => {
2499
+ const mapError = (cause) => apiKeyStoreError(operation, cause);
2500
+ return executeMapped(executor, () => Query.select(apiKeySelection).pipe(Query.from(authPostgresApiKey), Query.where(eq(column, value))), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodeApiKey), mapError)));
2501
+ };
2502
+ return ApiKeyStore.of({
2503
+ insert: (row) => {
2504
+ const mapError = (cause) => apiKeyStoreError("insert", cause);
2505
+ return executeMapped(executor, () => insert(authPostgresApiKey, apiKeyValues(row)), mapError).pipe(Effect.asVoid);
2506
+ },
2507
+ findById: (id) => find(authPostgresApiKey.id, id),
2508
+ findByPrefix: (prefix) => find(authPostgresApiKey.prefix, prefix),
2509
+ listByUser: (input) => {
2510
+ const mapError = (cause) => apiKeyStoreError("list", cause);
2511
+ return executeMapped(executor, () => {
2512
+ let plan = Query.select(apiKeySelection).pipe(Query.from(authPostgresApiKey), Query.where(eq(authPostgresApiKey.user_id, input.userId)));
2513
+ if (input.includeRevoked !== true) {
2514
+ plan = plan.pipe(Query.where(isNull(authPostgresApiKey.revoked_at)));
2515
+ }
2516
+ return plan.pipe(Query.orderBy(authPostgresApiKey.created_at, "asc"), Query.orderBy(Query.collate(authPostgresApiKey.id, "C"), "asc"));
2517
+ }, mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => rows.map(decodeApiKey), mapError)));
2518
+ },
2519
+ markUsed: (input) => {
2520
+ const mapError = (cause) => apiKeyStoreError("mark-used", cause);
2521
+ return executeMapped(executor, () => update(authPostgresApiKey, {
2522
+ last_used_at: millisParam(input.lastUsedAt),
2523
+ ...(input.metadata === undefined
2524
+ ? {}
2525
+ : { metadata: input.metadata }),
2526
+ }).pipe(Query.where(eq(authPostgresApiKey.id, input.id)), Query.where(isNull(authPostgresApiKey.revoked_at)), Query.returning(apiKeySelection)), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodeApiKey), mapError)));
2527
+ },
2528
+ revoke: (input) => {
2529
+ const mapError = (cause) => apiKeyStoreError("revoke", cause);
2530
+ return executeMapped(executor, () => {
2531
+ const values = {
2532
+ revoked_at: millisParam(input.revokedAt),
2533
+ ...(input.reason === undefined
2534
+ ? {}
2535
+ : {
2536
+ metadata: metadataWithReason(authPostgresApiKey.metadata, "revokeReason", input.reason),
2537
+ }),
2538
+ };
2539
+ return update(authPostgresApiKey, values).pipe(Query.where(eq(authPostgresApiKey.id, input.id)));
2540
+ }, mapError).pipe(Effect.asVoid);
2541
+ },
2542
+ });
2543
+ };
2544
+ export const makeEffectQbPostgresJwtRevocationStore = (executor) => JwtRevocationStore.of({
2545
+ revoke: (record) => {
2546
+ const mapError = (cause) => jwtRevocationStoreError("revoke", cause);
2547
+ return executeMapped(executor, () => {
2548
+ const values = jwtRevocationValues(record);
2549
+ return insert(authPostgresJwtRevocation, values).pipe(PostgresQuery.onConflict("jwt_id", {
2550
+ update: {
2551
+ revoked_at: values.revoked_at,
2552
+ expires_at: values.expires_at,
2553
+ reason: values.reason,
2554
+ },
2555
+ }));
2556
+ }, mapError).pipe(Effect.asVoid);
2557
+ },
2558
+ find: (jwtId) => {
2559
+ const mapError = (cause) => jwtRevocationStoreError("find", cause);
2560
+ return executeMapped(executor, () => Query.select(jwtRevocationSelection).pipe(Query.from(authPostgresJwtRevocation), Query.where(eq(authPostgresJwtRevocation.jwt_id, jwtId))), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodeJwtRevocation), mapError)));
2561
+ },
2562
+ });
2563
+ const registrationReasonByConstraint = {
2564
+ auth_user_pkey: "user-id",
2565
+ auth_user_identity_pkey: "identity-id",
2566
+ auth_user_identity_active_value_idx: "identity-value",
2567
+ auth_credential_pkey: "credential-id",
2568
+ auth_credential_user_type_key: "password-credential",
2569
+ };
2570
+ export const makeEffectQbPostgresRegistrationStore = (atomic) => RegistrationStore.of({
2571
+ create: (input) => {
2572
+ if (input.identity.userId !== input.user.id ||
2573
+ (input.passwordCredential !== undefined &&
2574
+ input.passwordCredential.userId !== input.user.id)) {
2575
+ return Effect.fail(new RegistrationConflictError({ reason: "user-id" }));
2576
+ }
2577
+ const userPlan = insert(authPostgresUser, userValues(input.user)).pipe(Query.returning(userSelection));
2578
+ const identityPlan = insert(authPostgresUserIdentity, identityValues(input.identity)).pipe(Query.returning(identitySelection));
2579
+ const plans = input.passwordCredential === undefined
2580
+ ? [userPlan, identityPlan]
2581
+ : [
2582
+ userPlan,
2583
+ identityPlan,
2584
+ insert(authPostgresCredential, credentialValues(input.passwordCredential)).pipe(Query.returning(credentialSelection)),
2585
+ ];
2586
+ return atomic.execute(plans).pipe(Effect.map(() => ({
2587
+ user: input.user,
2588
+ identity: {
2589
+ ...input.identity,
2590
+ isPrimaryLogin: input.identity.isPrimaryLogin ?? false,
2591
+ updatedAt: input.identity.createdAt,
2592
+ },
2593
+ ...(input.passwordCredential === undefined
2594
+ ? {}
2595
+ : { passwordCredential: input.passwordCredential }),
2596
+ })), Effect.mapError((cause) => {
2597
+ const details = postgresErrorDetails(cause);
2598
+ const reason = details.code === "23505" && details.constraintName !== undefined
2599
+ ? registrationReasonByConstraint[details.constraintName]
2600
+ : undefined;
2601
+ return reason === undefined
2602
+ ? new RegistrationFailureError({
2603
+ message: "Atomic Postgres registration failed",
2604
+ cause,
2605
+ })
2606
+ : new RegistrationConflictError({ reason });
2607
+ }));
2608
+ },
2609
+ });
2610
+ export const makeEffectQbPostgresSessionStore = (executor) => {
2611
+ const result = (operation, plan) => {
2612
+ const mapError = (cause) => storageError("session", operation, cause);
2613
+ return execute(executor, plan).pipe(Effect.mapError(mapError), Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodeSession), mapError)));
2614
+ };
2615
+ const findForMutation = (operation, sessionId) => {
2616
+ const mapError = (cause) => storageError("session", operation, cause);
2617
+ return execute(executor, Query.select(sessionSelection).pipe(Query.from(authPostgresSession), Query.where(eq(authPostgresSession.id, sessionId)))).pipe(Effect.mapError(mapError), Effect.flatMap((rows) => decodeMapped(() => {
2618
+ const [selected] = rows;
2619
+ return selected === undefined
2620
+ ? Option.none()
2621
+ : Option.some({
2622
+ row: decodeSession(selected),
2623
+ rawAuthenticationEvents: selected.authenticationEvents ??
2624
+ selected.authentication_events,
2625
+ });
2626
+ }, mapError)));
2627
+ };
2628
+ const mutateExisting = (operation, sessionId, plan) => findForMutation(operation, sessionId).pipe(Effect.flatMap((existing) => Option.isNone(existing)
2629
+ ? Effect.succeed(Option.none())
2630
+ : result(operation, plan(existing.value))));
2631
+ const validateEvents = (operation, authenticationEvents) => decodeMapped(() => parseAuthenticationEvents(authenticationEvents), (cause) => storageError("session", operation, cause));
2632
+ return SessionStore.of({
2633
+ findById: (id) => result("find", Query.select(sessionSelection).pipe(Query.from(authPostgresSession), Query.where(eq(authPostgresSession.id, id)))),
2634
+ listByUser: (input) => {
2635
+ const mapError = (cause) => storageError("session", "listByUser", cause);
2636
+ return execute(executor, Query.select(sessionSelection).pipe(Query.from(authPostgresSession), Query.where(eq(authPostgresSession.user_id, input.userId)), Query.orderBy(authPostgresSession.created_at, "asc"), Query.orderBy(Query.collate(authPostgresSession.id, "C"), "asc"))).pipe(Effect.mapError(mapError), Effect.flatMap((rows) => decodeMapped(() => rows.map(decodeSession), mapError)));
2637
+ },
2638
+ insert: (row) => validateEvents("insert", row.authenticationEvents).pipe(Effect.flatMap(() => execute(executor, insert(authPostgresSession, sessionValues(row)))), Effect.mapError((cause) => storageError("session", "insert", cause)), Effect.asVoid),
2639
+ refresh: (input) => mutateExisting("refresh", input.sessionId, (existing) => update(authPostgresSession, {
2640
+ expires_at: millisParam(input.expiresAt),
2641
+ ...(input.lastSeenAt === undefined
2642
+ ? {}
2643
+ : { last_seen_at: millisParam(input.lastSeenAt) }),
2644
+ }).pipe(Query.where(eq(authPostgresSession.id, input.sessionId)), Query.where(eq(authPostgresSession.authentication_events, existing.rawAuthenticationEvents)), Query.returning(sessionSelection))),
2645
+ rotate: (input) => mutateExisting("rotate", input.sessionId, (existing) => update(authPostgresSession, {
2646
+ secret_hash: input.secretHash,
2647
+ rotated_at: millisParam(input.rotatedAt),
2648
+ ...(input.expiresAt === undefined
2649
+ ? {}
2650
+ : { expires_at: millisParam(input.expiresAt) }),
2651
+ }).pipe(Query.where(eq(authPostgresSession.id, input.sessionId)), Query.where(eq(authPostgresSession.authentication_events, existing.rawAuthenticationEvents)), Query.returning(sessionSelection))),
2652
+ updateClaims: (input) => input.claims === undefined
2653
+ ? result("updateClaims", Query.select(sessionSelection).pipe(Query.from(authPostgresSession), Query.where(eq(authPostgresSession.id, input.sessionId))))
2654
+ : mutateExisting("updateClaims", input.sessionId, (existing) => update(authPostgresSession, { claims: input.claims }).pipe(Query.where(eq(authPostgresSession.id, input.sessionId)), Query.where(eq(authPostgresSession.authentication_events, existing.rawAuthenticationEvents)), Query.returning(sessionSelection))),
2655
+ appendEvidence: (input) => validateEvents("appendEvidence", input.authenticationEvents).pipe(Effect.flatMap((authenticationEvents) => mutateExisting("appendEvidence", input.sessionId, (existing) => update(authPostgresSession, {
2656
+ authentication_events: authenticationEvents,
2657
+ auth_time: millisParam(input.authTime),
2658
+ aal: input.aal,
2659
+ amr: input.amr,
2660
+ mfa_verified_at: input.mfaVerifiedAt === undefined
2661
+ ? null
2662
+ : millisParam(input.mfaVerifiedAt),
2663
+ ...(input.claims === undefined ? {} : { claims: input.claims }),
2664
+ }).pipe(Query.where(eq(authPostgresSession.id, input.sessionId)), Query.where(eq(authPostgresSession.authentication_events, existing.rawAuthenticationEvents)), Query.returning(sessionSelection))))),
2665
+ assureAndRotate: (input) => validateEvents("assureAndRotate", input.authenticationEvents).pipe(Effect.flatMap((authenticationEvents) => mutateExisting("assureAndRotate", input.sessionId, (existing) => update(authPostgresSession, {
2666
+ secret_hash: input.secretHash,
2667
+ rotated_at: millisParam(input.rotatedAt),
2668
+ authentication_events: authenticationEvents,
2669
+ auth_time: millisParam(input.authTime),
2670
+ aal: input.aal,
2671
+ amr: input.amr,
2672
+ mfa_verified_at: input.mfaVerifiedAt === undefined
2673
+ ? null
2674
+ : millisParam(input.mfaVerifiedAt),
2675
+ ...(input.claims === undefined ? {} : { claims: input.claims }),
2676
+ }).pipe(Query.where(eq(authPostgresSession.id, input.sessionId)), Query.where(eq(authPostgresSession.secret_hash, input.expectedSecretHash)), Query.where(eq(authPostgresSession.authentication_events, input.expectedAuthenticationEvents)), Query.where(eq(authPostgresSession.authentication_events, existing.rawAuthenticationEvents)), Query.where(isNull(authPostgresSession.revoked_at)), Query.where(gt(authPostgresSession.expires_at, millisParam(input.now))), Query.returning(sessionSelection))))),
2677
+ revoke: (input) => execute(executor, update(authPostgresSession, {
2678
+ revoked_at: millisParam(input.revokedAt),
2679
+ }).pipe(Query.where(eq(authPostgresSession.id, input.sessionId)))).pipe(Effect.mapError((cause) => storageError("session", "revoke", cause)), Effect.asVoid),
2680
+ revokeAllForUser: (input) => execute(executor, update(authPostgresSession, {
2681
+ revoked_at: millisParam(input.revokedAt),
2682
+ }).pipe(Query.where(eq(authPostgresSession.user_id, input.userId)))).pipe(Effect.mapError((cause) => storageError("session", "revokeAllForUser", cause)), Effect.asVoid),
2683
+ });
2684
+ };
2685
+ export const makeEffectQbPostgresVerificationStore = (executor, sql) => {
2686
+ const findById = (id, operation = "find") => execute(executor, Query.select(verificationSelection).pipe(Query.from(authPostgresVerification), Query.where(eq(authPostgresVerification.id, id)))).pipe(Effect.mapError((cause) => storageError("verification", operation, cause)), Effect.map((rows) => firstOption(rows, decodeVerification)));
2687
+ return VerificationStore.of({
2688
+ findById,
2689
+ insert: (row) => execute(executor, insert(authPostgresVerification, verificationValues(row))).pipe(Effect.mapError((cause) => storageError("verification", "insert", cause)), Effect.asVoid),
2690
+ consume: (input) => {
2691
+ let plan = update(authPostgresVerification, {
2692
+ consumed_at: millisParam(input.consumedAt),
2693
+ }).pipe(Query.where(eq(authPostgresVerification.id, input.id)), Query.where(isNull(authPostgresVerification.consumed_at)), Query.where(gt(authPostgresVerification.expires_at, millisParam(input.consumedAt))));
2694
+ if (input.type !== undefined) {
2695
+ plan = plan.pipe(Query.where(eq(authPostgresVerification.type, input.type)));
2696
+ }
2697
+ return execute(executor, plan.pipe(Query.returning({
2698
+ ...verificationSelection,
2699
+ consumedAt: withoutNullRefinement(authPostgresVerification.consumed_at),
2700
+ }))).pipe(Effect.mapError((cause) => storageError("verification", "consume", cause)), Effect.map((rows) => firstOption(rows, decodeVerification)));
2701
+ },
2702
+ deleteExpired: (input) => {
2703
+ const { limit } = input;
2704
+ if (limit === undefined) {
2705
+ return execute(executor, Query.delete(authPostgresVerification).pipe(Query.where(lte(authPostgresVerification.expires_at, millisParam(input.now))), Query.returning({ id: authPostgresVerification.id }))).pipe(Effect.mapError((cause) => storageError("verification", "deleteExpired", cause)), Effect.map((rows) => rows.length));
2706
+ }
2707
+ return sql
2708
+ .withTransaction(Effect.gen(function* () {
2709
+ const selected = yield* execute(executor, Query.select({ id: authPostgresVerification.id }).pipe(Query.from(authPostgresVerification), Query.where(lte(authPostgresVerification.expires_at, millisParam(input.now))), Query.orderBy(authPostgresVerification.expires_at, "asc"), Query.orderBy(Query.collate(authPostgresVerification.id, "C"), "asc"), Query.limit(limit), Query.lock("update")));
2710
+ if (selected.length === 0) {
2711
+ return 0;
2712
+ }
2713
+ const deleted = yield* execute(executor, Query.delete(authPostgresVerification).pipe(Query.where(inValues(authPostgresVerification.id, selected.map((row) => row.id))), Query.returning({ id: authPostgresVerification.id })));
2714
+ return deleted.length;
2715
+ }))
2716
+ .pipe(Effect.mapError((cause) => storageError("verification", "deleteExpired", cause)));
2717
+ },
2718
+ });
2719
+ };
2720
+ const normalizedLimit = (limit) => {
2721
+ if (limit === undefined) {
2722
+ return undefined;
2723
+ }
2724
+ const normalized = Math.floor(limit);
2725
+ if (Number.isNaN(normalized) || normalized <= 0) {
2726
+ return 0;
2727
+ }
2728
+ return Number.isFinite(normalized) && normalized <= Number.MAX_SAFE_INTEGER
2729
+ ? normalized
2730
+ : undefined;
2731
+ };
2732
+ export const makeEffectQbPostgresAuditLogStore = (executor, sql) => AuditLogStore.of({
2733
+ insertMany: (events) => {
2734
+ if (events.length === 0) {
2735
+ return Effect.void;
2736
+ }
2737
+ const mapError = (cause) => auditLogStoreError("insertMany", cause);
2738
+ return Effect.gen(function* () {
2739
+ const createdAt = yield* currentUnixMillis;
2740
+ yield* sql.withTransaction(Effect.forEach(events, (event) => executeMapped(executor, () => insert(authPostgresAuditLog, auditLogValues(event, createdAt)), mapError)).pipe(Effect.asVoid));
2741
+ }).pipe(Effect.mapError((cause) => cause instanceof AuditLogStoreError ? cause : mapError(cause)));
2742
+ },
2743
+ list: (input = {}) => {
2744
+ if (input.types !== undefined && input.types.length === 0) {
2745
+ return Effect.succeed([]);
2746
+ }
2747
+ const mapError = (cause) => auditLogStoreError("list", cause);
2748
+ return executeMapped(executor, () => {
2749
+ let plan = Query.select(auditLogSelection).pipe(Query.from(authPostgresAuditLog));
2750
+ if (input.userId !== undefined) {
2751
+ plan = plan.pipe(Query.where(eq(authPostgresAuditLog.user_id, input.userId)));
2752
+ }
2753
+ if (input.beforeOccurredAt !== undefined) {
2754
+ plan = plan.pipe(Query.where(lt(authPostgresAuditLog.occurred_at, millisParam(input.beforeOccurredAt))));
2755
+ }
2756
+ if (input.types !== undefined) {
2757
+ plan = plan.pipe(Query.where(inValues(authPostgresAuditLog.type, input.types)));
2758
+ }
2759
+ plan = plan.pipe(Query.orderBy(authPostgresAuditLog.occurred_at, "desc"), Query.orderBy(Query.collate(Query.coalesce(authPostgresAuditLog.id, Query.literal("")), "C"), "desc"), Query.orderBy(authPostgresAuditLog.storage_id, "asc"));
2760
+ const limit = normalizedLimit(input.limit);
2761
+ return limit === undefined ? plan : plan.pipe(Query.limit(limit));
2762
+ }, mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => filterAuditLogEvents(rows.map(decodeAuditLogEvent), {
2763
+ ...input,
2764
+ limit: undefined,
2765
+ }), mapError)));
2766
+ },
2767
+ deleteBefore: (input) => {
2768
+ const mapError = (cause) => auditLogStoreError("deleteBefore", cause);
2769
+ return executeMapped(executor, () => {
2770
+ let plan = Query.delete(authPostgresAuditLog).pipe(Query.where(lt(authPostgresAuditLog.occurred_at, millisParam(input.beforeOccurredAt))));
2771
+ if (input.userId !== undefined) {
2772
+ plan = plan.pipe(Query.where(eq(authPostgresAuditLog.user_id, input.userId)));
2773
+ }
2774
+ return plan.pipe(Query.returning({ id: authPostgresAuditLog.id }));
2775
+ }, mapError).pipe(Effect.map((rows) => rows.length));
2776
+ },
2777
+ });
2778
+ export const makeEffectQbPostgresLoginApprovalReviewStore = (executor) => {
2779
+ const findByApprovalChallengeId = (input, operation = "find") => {
2780
+ const mapError = (cause) => loginApprovalReviewStoreError(operation, cause);
2781
+ return executeMapped(executor, () => Query.select(loginApprovalReviewSelection).pipe(Query.from(authPostgresLoginApprovalReview), Query.where(eq(authPostgresLoginApprovalReview.approval_challenge_id, input.approvalChallengeId))), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodeLoginApprovalReview), mapError)));
2782
+ };
2783
+ const transition = (status, input) => {
2784
+ const operation = status === "approved" ? "approve" : "deny";
2785
+ const mapError = (cause) => loginApprovalReviewStoreError(operation, cause);
2786
+ return executeMapped(executor, () => update(authPostgresLoginApprovalReview, {
2787
+ status,
2788
+ reviewed_at: millisParam(input.reviewedAt),
2789
+ reviewed_by: input.reviewedBy ?? null,
2790
+ ...(status === "denied"
2791
+ ? { denied_reason: input.reason ?? null }
2792
+ : {}),
2793
+ review_metadata: input.metadata ?? null,
2794
+ }).pipe(Query.where(eq(authPostgresLoginApprovalReview.approval_challenge_id, input.approvalChallengeId)), Query.where(eq(authPostgresLoginApprovalReview.status, "pending")), Query.returning({
2795
+ ...loginApprovalReviewSelection,
2796
+ reviewedAt: withoutNullRefinement(authPostgresLoginApprovalReview.reviewed_at),
2797
+ })), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodeLoginApprovalReview), mapError)));
2798
+ };
2799
+ return LoginApprovalReviewStore.of({
2800
+ insertPending: (input) => {
2801
+ const mapError = (cause) => loginApprovalReviewStoreError("insert", cause);
2802
+ return executeMapped(executor, () => insert(authPostgresLoginApprovalReview, loginApprovalReviewValues(input)), mapError).pipe(Effect.as(input));
2803
+ },
2804
+ findByApprovalChallengeId,
2805
+ approve: (input) => transition("approved", input),
2806
+ deny: (input) => transition("denied", input),
2807
+ });
2808
+ };
2809
+ const defaultLoginRiskHistoryRecentWindowMillis = 15 * 60 * 1000;
2810
+ const defaultLoginRiskHistoryWindowMillis = 90 * 24 * 60 * 60 * 1000;
2811
+ const defaultLoginRiskImpossibleTravelWindowMillis = 24 * 60 * 60 * 1000;
2812
+ const defaultLoginRiskImpossibleTravelKmh = 900;
2813
+ const positiveWindowMillis = (value, defaultValue) => value === undefined || !Number.isFinite(value)
2814
+ ? defaultValue
2815
+ : Math.max(0, value);
2816
+ const resolvedLoginRiskHistoryOptions = (options) => ({
2817
+ recentWindowMillis: positiveWindowMillis(options?.recentWindowMillis, defaultLoginRiskHistoryRecentWindowMillis),
2818
+ historyWindowMillis: positiveWindowMillis(options?.historyWindowMillis, defaultLoginRiskHistoryWindowMillis),
2819
+ impossibleTravelWindowMillis: positiveWindowMillis(options?.impossibleTravelWindowMillis, defaultLoginRiskImpossibleTravelWindowMillis),
2820
+ impossibleTravelKmh: options?.impossibleTravelKmh === undefined ||
2821
+ !Number.isFinite(options.impossibleTravelKmh)
2822
+ ? defaultLoginRiskImpossibleTravelKmh
2823
+ : Math.max(0, options.impossibleTravelKmh),
2824
+ });
2825
+ const toRadians = (degrees) => (degrees * Math.PI) / 180;
2826
+ const distanceKm = (first, second) => {
2827
+ const earthRadiusKm = 6371;
2828
+ const latitudeDelta = toRadians(second.latitude - first.latitude);
2829
+ const longitudeDelta = toRadians(second.longitude - first.longitude);
2830
+ const firstLatitude = toRadians(first.latitude);
2831
+ const secondLatitude = toRadians(second.latitude);
2832
+ const haversine = Math.sin(latitudeDelta / 2) ** 2 +
2833
+ Math.cos(firstLatitude) *
2834
+ Math.cos(secondLatitude) *
2835
+ Math.sin(longitudeDelta / 2) ** 2;
2836
+ return (2 *
2837
+ earthRadiusKm *
2838
+ Math.atan2(Math.sqrt(haversine), Math.sqrt(1 - haversine)));
2839
+ };
2840
+ const hasCoordinates = (value) => value.latitude !== undefined &&
2841
+ Number.isFinite(value.latitude) &&
2842
+ value.longitude !== undefined &&
2843
+ Number.isFinite(value.longitude);
2844
+ const loginRiskHistoryLookupResult = (input, rows, options) => {
2845
+ const normalized = resolvedLoginRiskHistoryOptions(options);
2846
+ const occurredAt = Number(input.occurredAt);
2847
+ const recentStart = occurredAt - normalized.recentWindowMillis;
2848
+ const historyStart = occurredAt - normalized.historyWindowMillis;
2849
+ const impossibleTravelStart = occurredAt - normalized.impossibleTravelWindowMillis;
2850
+ const previousRows = rows.filter((row) => Number(row.occurredAt) < occurredAt);
2851
+ const recentRows = previousRows.filter((row) => Number(row.occurredAt) >= recentStart);
2852
+ const historyRows = previousRows.filter((row) => Number(row.occurredAt) >= historyStart);
2853
+ const recentFailedLoginCount = recentRows.filter((row) => row.outcome === "failure").length;
2854
+ const recentSuccessfulLoginCount = recentRows.filter((row) => row.outcome === "success").length;
2855
+ const knownDevice = input.deviceKey === undefined
2856
+ ? undefined
2857
+ : historyRows.some((row) => row.deviceKey === input.deviceKey);
2858
+ const knownLocation = input.locationKey === undefined
2859
+ ? undefined
2860
+ : historyRows.some((row) => row.locationKey === input.locationKey);
2861
+ const currentLocation = {
2862
+ latitude: input.request?.latitude,
2863
+ longitude: input.request?.longitude,
2864
+ };
2865
+ const impossibleTravel = hasCoordinates(currentLocation)
2866
+ ? previousRows
2867
+ .filter((row) => row.outcome === "success" &&
2868
+ Number(row.occurredAt) >= impossibleTravelStart)
2869
+ .some((row) => {
2870
+ const previousLocation = {
2871
+ latitude: row.latitude,
2872
+ longitude: row.longitude,
2873
+ };
2874
+ if (!hasCoordinates(previousLocation)) {
2875
+ return false;
2876
+ }
2877
+ const elapsedHours = (occurredAt - Number(row.occurredAt)) / 3_600_000;
2878
+ return (elapsedHours > 0 &&
2879
+ distanceKm(previousLocation, currentLocation) / elapsedHours >
2880
+ normalized.impossibleTravelKmh);
2881
+ })
2882
+ : undefined;
2883
+ const recentRiskLevels = recentRows.flatMap((row) => row.riskLevel === undefined ? [] : [row.riskLevel]);
2884
+ const riskLevel = recentRiskLevels.length === 0
2885
+ ? undefined
2886
+ : maxLoginRiskLevel(recentRiskLevels, "unknown");
2887
+ const reasons = [
2888
+ ...(recentFailedLoginCount > 0 ? ["recent-failed-login"] : []),
2889
+ ...(knownDevice === false ? ["new-device"] : []),
2890
+ ...(knownLocation === false ? ["new-location"] : []),
2891
+ ...(impossibleTravel === true ? ["impossible-travel"] : []),
2892
+ ];
2893
+ return {
2894
+ recentLoginCount: recentRows.length,
2895
+ recentFailedLoginCount,
2896
+ recentSuccessfulLoginCount,
2897
+ ...(knownDevice === undefined
2898
+ ? {}
2899
+ : { knownDevice, newDevice: !knownDevice }),
2900
+ ...(knownLocation === undefined
2901
+ ? {}
2902
+ : { knownLocation, newLocation: !knownLocation }),
2903
+ ...(impossibleTravel === undefined ? {} : { impossibleTravel }),
2904
+ ...(riskLevel === undefined ? {} : { riskLevel }),
2905
+ ...(reasons.length === 0 ? {} : { reasons }),
2906
+ };
2907
+ };
2908
+ export const makeEffectQbPostgresLoginRiskHistoryStore = (executor, options) => LoginRiskHistory.of({
2909
+ lookup: (input) => {
2910
+ const mapError = (cause) => loginRiskHistoryStoreError("lookup", cause);
2911
+ return executeMapped(executor, () => {
2912
+ const normalized = resolvedLoginRiskHistoryOptions(options);
2913
+ const occurredAt = Number(input.occurredAt);
2914
+ const earliestOccurredAt = Math.min(occurredAt - normalized.recentWindowMillis, occurredAt - normalized.historyWindowMillis, occurredAt - normalized.impossibleTravelWindowMillis);
2915
+ return Query.select(loginRiskHistorySelection).pipe(Query.from(authPostgresLoginRiskHistory), Query.where(eq(authPostgresLoginRiskHistory.user_id, input.userId)), Query.where(lt(authPostgresLoginRiskHistory.occurred_at, millisParam(input.occurredAt))), Query.where(gte(authPostgresLoginRiskHistory.occurred_at, String(Math.ceil(earliestOccurredAt)))), Query.orderBy(authPostgresLoginRiskHistory.occurred_at, "asc"), Query.orderBy(Query.collate(authPostgresLoginRiskHistory.id, "C"), "asc"));
2916
+ }, mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => loginRiskHistoryLookupResult(input, rows.map(decodeLoginRiskHistoryRecord), options), mapError)));
2917
+ },
2918
+ record: (input) => {
2919
+ const mapError = (cause) => loginRiskHistoryStoreError("record", cause);
2920
+ return Effect.gen(function* () {
2921
+ const createdAt = input.createdAt ?? (yield* currentUnixMillis);
2922
+ yield* executeMapped(executor, () => insert(authPostgresLoginRiskHistory, loginRiskHistoryValues({ ...input, createdAt })), mapError);
2923
+ }).pipe(Effect.asVoid);
2924
+ },
2925
+ deleteBefore: (input) => {
2926
+ const mapError = (cause) => loginRiskHistoryStoreError("deleteBefore", cause);
2927
+ return executeMapped(executor, () => {
2928
+ let plan = Query.delete(authPostgresLoginRiskHistory).pipe(Query.where(lt(authPostgresLoginRiskHistory.occurred_at, millisParam(input.beforeOccurredAt))));
2929
+ if (input.userId !== undefined) {
2930
+ plan = plan.pipe(Query.where(eq(authPostgresLoginRiskHistory.user_id, input.userId)));
2931
+ }
2932
+ return plan.pipe(Query.returning({ id: authPostgresLoginRiskHistory.id }));
2933
+ }, mapError).pipe(Effect.map((rows) => rows.length));
2934
+ },
2935
+ });
2936
+ export const makeEffectQbPostgresTrustedDeviceStore = (executor) => {
2937
+ const findIncludingExpired = (input) => {
2938
+ const mapError = (cause) => trustedDeviceStoreError("trust", cause);
2939
+ return executeMapped(executor, () => Query.select(trustedDeviceSelection).pipe(Query.from(authPostgresTrustedDevice), Query.where(eq(authPostgresTrustedDevice.user_id, input.userId)), Query.where(eq(authPostgresTrustedDevice.token_hash, input.tokenHash))), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodeTrustedDevice), mapError)));
2940
+ };
2941
+ return TrustedDeviceStore.of({
2942
+ find: (input) => {
2943
+ const mapError = (cause) => trustedDeviceStoreError("status", cause);
2944
+ return executeMapped(executor, () => Query.select(trustedDeviceSelection).pipe(Query.from(authPostgresTrustedDevice), Query.where(eq(authPostgresTrustedDevice.user_id, input.userId)), Query.where(eq(authPostgresTrustedDevice.token_hash, input.tokenHash)), Query.where(gt(authPostgresTrustedDevice.expires_at, millisParam(input.now)))), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodeTrustedDevice), mapError)));
2945
+ },
2946
+ upsert: (input) => {
2947
+ const mapError = (cause) => trustedDeviceStoreError("trust", cause);
2948
+ return executeMapped(executor, () => {
2949
+ const values = trustedDeviceValues(input);
2950
+ return insert(authPostgresTrustedDevice, values).pipe(PostgresQuery.onConflict(["user_id", "token_hash"], {
2951
+ update: {
2952
+ last_seen_at: Query.excluded(authPostgresTrustedDevice.last_seen_at),
2953
+ expires_at: Query.excluded(authPostgresTrustedDevice.expires_at),
2954
+ ...(input.metadata === undefined
2955
+ ? {}
2956
+ : {
2957
+ metadata: Query.excluded(authPostgresTrustedDevice.metadata),
2958
+ }),
2959
+ },
2960
+ where: lte(authPostgresTrustedDevice.last_seen_at, Query.excluded(authPostgresTrustedDevice.last_seen_at)),
2961
+ }), Query.returning(trustedDeviceSelection));
2962
+ }, mapError).pipe(Effect.flatMap((rows) => rows[0] === undefined
2963
+ ? findIncludingExpired(input).pipe(Effect.flatMap(Option.match({
2964
+ onNone: () => Effect.fail(trustedDeviceStoreError("trust", "missing row")),
2965
+ onSome: Effect.succeed,
2966
+ })))
2967
+ : decodeMapped(() => decodeTrustedDevice(rows[0]), mapError)));
2968
+ },
2969
+ listForUser: (input) => {
2970
+ const mapError = (cause) => trustedDeviceStoreError("list", cause);
2971
+ return executeMapped(executor, () => {
2972
+ let plan = Query.select(trustedDeviceSelection).pipe(Query.from(authPostgresTrustedDevice), Query.where(eq(authPostgresTrustedDevice.user_id, input.userId)), Query.where(gt(authPostgresTrustedDevice.expires_at, millisParam(input.now))), Query.orderBy(authPostgresTrustedDevice.last_seen_at, "desc"), Query.orderBy(Query.collate(authPostgresTrustedDevice.token_hash, "C"), "desc"));
2973
+ const limit = normalizedLimit(input.limit);
2974
+ if (limit !== undefined) {
2975
+ plan = plan.pipe(Query.limit(limit));
2976
+ }
2977
+ return plan;
2978
+ }, mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => rows.map(decodeTrustedDevice), mapError)));
2979
+ },
2980
+ revokeForUser: (input) => {
2981
+ const mapError = (cause) => trustedDeviceStoreError("revoke", cause);
2982
+ return executeMapped(executor, () => Query.delete(authPostgresTrustedDevice).pipe(Query.where(eq(authPostgresTrustedDevice.user_id, input.userId)), Query.where(eq(authPostgresTrustedDevice.token_hash, input.tokenHash))), mapError).pipe(Effect.asVoid);
2983
+ },
2984
+ });
2985
+ };
2986
+ export const makeEffectQbPostgresDomainVerificationStore = (executor) => {
2987
+ const find = (predicate, operation = "find") => {
2988
+ const mapError = (cause) => domainVerificationStoreError(operation, cause);
2989
+ return executeMapped(executor, () => Query.select(domainVerificationSelection).pipe(Query.from(authPostgresDomainVerification), Query.where(predicate)), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodeDomainVerification), mapError)));
2990
+ };
2991
+ return DomainVerificationStore.of({
2992
+ upsert: (record) => {
2993
+ const mapError = (cause) => domainVerificationStoreError("upsert", cause);
2994
+ return executeMapped(executor, () => {
2995
+ const values = domainVerificationValues(record);
2996
+ return insert(authPostgresDomainVerification, values).pipe(PostgresQuery.onConflict(["owner_id", "domain"], {
2997
+ update: {
2998
+ id: values.id,
2999
+ proof_method: values.proof_method,
3000
+ proof_token: values.proof_token,
3001
+ status: values.status,
3002
+ created_at: values.created_at,
3003
+ expires_at: values.expires_at,
3004
+ verified_at: values.verified_at,
3005
+ revoked_at: values.revoked_at,
3006
+ last_checked_at: values.last_checked_at,
3007
+ metadata: values.metadata,
3008
+ },
3009
+ }));
3010
+ }, mapError).pipe(Effect.asVoid);
3011
+ },
3012
+ findById: (id) => find(eq(authPostgresDomainVerification.id, id)),
3013
+ findByOwnerAndDomain: (input) => find(Query.and(eq(authPostgresDomainVerification.owner_id, input.ownerId), eq(authPostgresDomainVerification.domain, input.domain))),
3014
+ listByOwner: (input) => {
3015
+ const mapError = (cause) => domainVerificationStoreError("list", cause);
3016
+ return executeMapped(executor, () => {
3017
+ let plan = Query.select(domainVerificationSelection).pipe(Query.from(authPostgresDomainVerification), Query.where(eq(authPostgresDomainVerification.owner_id, input.ownerId)), Query.orderBy(authPostgresDomainVerification.created_at, "asc"), Query.orderBy(Query.collate(authPostgresDomainVerification.id, "C"), "asc"));
3018
+ if (input.includeRevoked !== true) {
3019
+ plan = plan.pipe(Query.where(inValues(authPostgresDomainVerification.status, [
3020
+ "pending",
3021
+ "verified",
3022
+ ])));
3023
+ }
3024
+ return plan;
3025
+ }, mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => rows.map(decodeDomainVerification), mapError)));
3026
+ },
3027
+ markVerified: (input) => {
3028
+ const mapError = (cause) => domainVerificationStoreError("mark-verified", cause);
3029
+ return executeMapped(executor, () => update(authPostgresDomainVerification, {
3030
+ status: "verified",
3031
+ verified_at: millisParam(input.verifiedAt),
3032
+ last_checked_at: millisParam(input.verifiedAt),
3033
+ ...(input.metadata === undefined
3034
+ ? {}
3035
+ : { metadata: input.metadata }),
3036
+ }).pipe(Query.where(eq(authPostgresDomainVerification.id, input.id)), Query.where(eq(authPostgresDomainVerification.status, "pending")), Query.returning({
3037
+ ...domainVerificationSelection,
3038
+ verifiedAt: withoutNullRefinement(authPostgresDomainVerification.verified_at),
3039
+ lastCheckedAt: withoutNullRefinement(authPostgresDomainVerification.last_checked_at),
3040
+ })), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodeDomainVerification), mapError)));
3041
+ },
3042
+ revoke: (input) => {
3043
+ const mapError = (cause) => domainVerificationStoreError("revoke", cause);
3044
+ return executeMapped(executor, () => update(authPostgresDomainVerification, {
3045
+ status: "revoked",
3046
+ revoked_at: millisParam(input.revokedAt),
3047
+ ...(input.reason === undefined
3048
+ ? {}
3049
+ : {
3050
+ metadata: metadataWithReason(authPostgresDomainVerification.metadata, "revokeReason", input.reason),
3051
+ }),
3052
+ }).pipe(Query.where(eq(authPostgresDomainVerification.id, input.id))), mapError).pipe(Effect.asVoid);
3053
+ },
3054
+ });
3055
+ };
3056
+ export const makeEffectQbPostgresSecurityTimelineStore = (executor) => SecurityTimelineStore.of({
3057
+ insert: (event) => {
3058
+ const mapError = (cause) => securityTimelineStoreError("insert", cause);
3059
+ return executeMapped(executor, () => insert(authPostgresSecurityTimeline, securityTimelineValues(event)), mapError).pipe(Effect.asVoid);
3060
+ },
3061
+ listByUser: (input) => {
3062
+ if (input.types?.length === 0 || input.categories?.length === 0) {
3063
+ return Effect.succeed([]);
3064
+ }
3065
+ const mapError = (cause) => securityTimelineStoreError("list", cause);
3066
+ return executeMapped(executor, () => {
3067
+ let plan = Query.select(securityTimelineSelection).pipe(Query.from(authPostgresSecurityTimeline), Query.where(eq(authPostgresSecurityTimeline.user_id, input.userId)));
3068
+ if (input.beforeOccurredAt !== undefined) {
3069
+ plan = plan.pipe(Query.where(lt(authPostgresSecurityTimeline.occurred_at, millisParam(input.beforeOccurredAt))));
3070
+ }
3071
+ if (input.types !== undefined) {
3072
+ plan = plan.pipe(Query.where(inValues(authPostgresSecurityTimeline.type, input.types)));
3073
+ }
3074
+ if (input.categories !== undefined) {
3075
+ plan = plan.pipe(Query.where(inValues(authPostgresSecurityTimeline.category, input.categories)));
3076
+ }
3077
+ plan = plan.pipe(Query.orderBy(authPostgresSecurityTimeline.occurred_at, "desc"), Query.orderBy(Query.collate(authPostgresSecurityTimeline.id, "C"), "desc"));
3078
+ const limit = normalizedLimit(input.limit);
3079
+ return limit === undefined ? plan : plan.pipe(Query.limit(limit));
3080
+ }, mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => filterSecurityTimelineEvents(rows.map(decodeSecurityTimelineEvent), { ...input, limit: undefined }), mapError)));
3081
+ },
3082
+ deleteBefore: (input) => {
3083
+ const mapError = (cause) => securityTimelineStoreError("deleteBefore", cause);
3084
+ return executeMapped(executor, () => {
3085
+ let plan = Query.delete(authPostgresSecurityTimeline).pipe(Query.where(lt(authPostgresSecurityTimeline.occurred_at, millisParam(input.beforeOccurredAt))));
3086
+ if (input.userId !== undefined) {
3087
+ plan = plan.pipe(Query.where(eq(authPostgresSecurityTimeline.user_id, input.userId)));
3088
+ }
3089
+ return plan.pipe(Query.returning({ id: authPostgresSecurityTimeline.id }));
3090
+ }, mapError).pipe(Effect.map((rows) => rows.length));
3091
+ },
3092
+ });
3093
+ export const makeEffectQbPostgresWebhookOutboxStore = (executor, sql) => WebhookOutboxStore.of({
3094
+ enqueue: (input) => {
3095
+ const mapError = (cause) => webhookOutboxStoreError("enqueue", cause);
3096
+ return Effect.gen(function* () {
3097
+ const now = input.now ?? (yield* currentUnixMillis);
3098
+ const record = {
3099
+ id: input.id,
3100
+ endpointKey: input.endpointKey,
3101
+ event: input.event,
3102
+ status: "pending",
3103
+ attempts: 0,
3104
+ nextAttemptAt: input.nextAttemptAt ?? now,
3105
+ createdAt: now,
3106
+ updatedAt: now,
3107
+ };
3108
+ yield* executeMapped(executor, () => insert(authPostgresWebhookOutbox, webhookOutboxValues(record)), mapError);
3109
+ return record;
3110
+ });
3111
+ },
3112
+ claimDue: (input) => {
3113
+ const mapError = (cause) => webhookOutboxStoreError("claimDue", cause);
3114
+ return Effect.gen(function* () {
3115
+ const now = input.now ?? (yield* currentUnixMillis);
3116
+ const rows = yield* executeMapped(executor, () => {
3117
+ let plan = Query.select(webhookOutboxSelection).pipe(Query.from(authPostgresWebhookOutbox), Query.where(lte(authPostgresWebhookOutbox.next_attempt_at, millisParam(now))), Query.where(inValues(authPostgresWebhookOutbox.status, [
3118
+ "pending",
3119
+ "failed",
3120
+ ])), Query.orderBy(authPostgresWebhookOutbox.next_attempt_at, "asc"), Query.orderBy(authPostgresWebhookOutbox.created_at, "asc"), Query.orderBy(Query.collate(authPostgresWebhookOutbox.id, "C"), "asc"));
3121
+ if (input.endpointKey !== undefined) {
3122
+ plan = plan.pipe(Query.where(eq(authPostgresWebhookOutbox.endpoint_key, input.endpointKey)));
3123
+ }
3124
+ const limit = normalizedLimit(input.limit);
3125
+ return limit === undefined ? plan : plan.pipe(Query.limit(limit));
3126
+ }, mapError);
3127
+ return yield* decodeMapped(() => filterDueWebhookOutboxRecords(rows.map(decodeWebhookOutboxRecord), {
3128
+ ...input,
3129
+ now,
3130
+ limit: undefined,
3131
+ }), mapError);
3132
+ });
3133
+ },
3134
+ markDelivered: (input) => {
3135
+ const mapError = (cause) => webhookOutboxStoreError("markDelivered", cause);
3136
+ return Effect.gen(function* () {
3137
+ const deliveredAt = input.deliveredAt ?? (yield* currentUnixMillis);
3138
+ yield* executeMapped(executor, () => update(authPostgresWebhookOutbox, {
3139
+ status: "delivered",
3140
+ delivered_at: millisParam(deliveredAt),
3141
+ updated_at: millisParam(deliveredAt),
3142
+ last_error: null,
3143
+ }).pipe(Query.where(eq(authPostgresWebhookOutbox.id, input.id)), Query.where(inValues(authPostgresWebhookOutbox.status, [
3144
+ "pending",
3145
+ "failed",
3146
+ "delivered",
3147
+ ]))), mapError);
3148
+ }).pipe(Effect.asVoid);
3149
+ },
3150
+ markFailed: (input) => {
3151
+ const mapError = (cause) => webhookOutboxStoreError("markFailed", cause);
3152
+ return sql
3153
+ .withTransaction(Effect.gen(function* () {
3154
+ const rows = yield* executeMapped(executor, () => selectForUpdate(webhookOutboxSelection, authPostgresWebhookOutbox, eq(authPostgresWebhookOutbox.id, input.id)), mapError);
3155
+ const existing = yield* decodeMapped(() => firstOption(rows, decodeWebhookOutboxRecord), mapError);
3156
+ if (Option.isNone(existing) ||
3157
+ existing.value.status === "delivered" ||
3158
+ existing.value.status === "dead_lettered") {
3159
+ return;
3160
+ }
3161
+ const failedAt = input.failedAt ?? (yield* currentUnixMillis);
3162
+ yield* executeMapped(executor, () => update(authPostgresWebhookOutbox, {
3163
+ status: "failed",
3164
+ attempts: existing.value.attempts + 1,
3165
+ next_attempt_at: millisParam(input.nextAttemptAt),
3166
+ updated_at: millisParam(failedAt),
3167
+ last_error: input.error ?? null,
3168
+ }).pipe(Query.where(eq(authPostgresWebhookOutbox.id, input.id)), Query.where(inValues(authPostgresWebhookOutbox.status, [
3169
+ "pending",
3170
+ "failed",
3171
+ ]))), mapError);
3172
+ }))
3173
+ .pipe(Effect.mapError((cause) => cause instanceof WebhookOutboxStoreError ? cause : mapError(cause)), Effect.asVoid);
3174
+ },
3175
+ markDeadLettered: (input) => {
3176
+ const mapError = (cause) => webhookOutboxStoreError("markDeadLettered", cause);
3177
+ return Effect.gen(function* () {
3178
+ const deadLetteredAt = input.deadLetteredAt ?? (yield* currentUnixMillis);
3179
+ yield* executeMapped(executor, () => update(authPostgresWebhookOutbox, {
3180
+ status: "dead_lettered",
3181
+ updated_at: millisParam(deadLetteredAt),
3182
+ last_error: input.error ?? null,
3183
+ }).pipe(Query.where(eq(authPostgresWebhookOutbox.id, input.id)), Query.where(inValues(authPostgresWebhookOutbox.status, [
3184
+ "pending",
3185
+ "failed",
3186
+ ]))), mapError);
3187
+ }).pipe(Effect.asVoid);
3188
+ },
3189
+ deleteBefore: (input) => {
3190
+ const mapError = (cause) => webhookOutboxStoreError("deleteBefore", cause);
3191
+ return executeMapped(executor, () => {
3192
+ let plan = Query.delete(authPostgresWebhookOutbox).pipe(Query.where(lt(authPostgresWebhookOutbox.updated_at, millisParam(input.beforeUpdatedAt))), Query.where(inValues(authPostgresWebhookOutbox.status, input.statuses)));
3193
+ if (input.endpointKey !== undefined) {
3194
+ plan = plan.pipe(Query.where(eq(authPostgresWebhookOutbox.endpoint_key, input.endpointKey)));
3195
+ }
3196
+ return plan.pipe(Query.returning({ id: authPostgresWebhookOutbox.id }));
3197
+ }, mapError).pipe(Effect.map((rows) => rows.length));
3198
+ },
3199
+ });
3200
+ export const makeEffectQbPostgresWebhookReplayStore = (executor) => WebhookReplayStore.of({
3201
+ claim: (input) => {
3202
+ const mapError = (cause) => webhookReplayStoreError("claim", cause);
3203
+ return Effect.gen(function* () {
3204
+ const now = input.now ?? (yield* currentUnixMillis);
3205
+ const rows = yield* executeMapped(executor, () => insert(authPostgresWebhookReplay, {
3206
+ id: input.id,
3207
+ expires_at: millisParam(input.expiresAt),
3208
+ created_at: millisParam(now),
3209
+ }).pipe(PostgresQuery.onConflict("id", {
3210
+ update: {
3211
+ expires_at: millisParam(input.expiresAt),
3212
+ created_at: millisParam(now),
3213
+ },
3214
+ where: lt(authPostgresWebhookReplay.expires_at, millisParam(now)),
3215
+ }), Query.returning({ id: authPostgresWebhookReplay.id })), mapError);
3216
+ return rows.length > 0;
3217
+ });
3218
+ },
3219
+ deleteExpired: (input = {}) => {
3220
+ const mapError = (cause) => webhookReplayStoreError("deleteExpired", cause);
3221
+ return Effect.gen(function* () {
3222
+ const now = input.now ?? (yield* currentUnixMillis);
3223
+ const rows = yield* executeMapped(executor, () => Query.delete(authPostgresWebhookReplay).pipe(Query.where(lt(authPostgresWebhookReplay.expires_at, millisParam(now))), Query.returning({ id: authPostgresWebhookReplay.id })), mapError);
3224
+ return rows.length;
3225
+ });
3226
+ },
3227
+ });
3228
+ export const makeEffectQbPostgresTotpFactorStore = (executor) => {
3229
+ const findById = (id, operation = "find") => execute(executor, Query.select(totpFactorSelection).pipe(Query.from(authPostgresTotpFactor), Query.where(eq(authPostgresTotpFactor.id, id)))).pipe(Effect.mapError((cause) => totpFactorStoreError(operation, cause)), Effect.map((rows) => firstOption(rows, decodeTotpFactor)));
3230
+ return TotpFactorStore.of({
3231
+ insert: (row) => execute(executor, insert(authPostgresTotpFactor, totpFactorValues(row))).pipe(Effect.mapError((cause) => totpFactorStoreError("insert", cause)), Effect.asVoid),
3232
+ findById,
3233
+ listByUser: (input) => {
3234
+ let plan = Query.select(totpFactorSelection).pipe(Query.from(authPostgresTotpFactor), Query.where(eq(authPostgresTotpFactor.user_id, input.userId)));
3235
+ if (input.includeRevoked !== true) {
3236
+ plan = plan.pipe(Query.where(isNull(authPostgresTotpFactor.revoked_at)));
3237
+ }
3238
+ if (input.includeUnconfirmed !== true) {
3239
+ plan = plan.pipe(Query.where(isNotNull(authPostgresTotpFactor.confirmed_at)));
3240
+ }
3241
+ plan = plan.pipe(Query.orderBy(authPostgresTotpFactor.created_at, "asc"), Query.orderBy(Query.collate(authPostgresTotpFactor.id, "C"), "asc"));
3242
+ return execute(executor, plan).pipe(Effect.mapError((cause) => totpFactorStoreError("list", cause)), Effect.map((rows) => rows.map(decodeTotpFactor)));
3243
+ },
3244
+ confirm: (input) => execute(executor, update(authPostgresTotpFactor, {
3245
+ confirmed_at: millisParam(input.confirmedAt),
3246
+ ...(input.metadata === undefined ? {} : { metadata: input.metadata }),
3247
+ }).pipe(Query.where(eq(authPostgresTotpFactor.id, input.id)), Query.where(isNull(authPostgresTotpFactor.revoked_at)), Query.returning(totpFactorSelection))).pipe(Effect.mapError((cause) => totpFactorStoreError("confirm", cause)), Effect.map((rows) => firstOption(rows, decodeTotpFactor))),
3248
+ acceptCounter: (input) => execute(executor, update(authPostgresTotpFactor, {
3249
+ last_used_at: millisParam(input.lastUsedAt),
3250
+ last_accepted_counter: String(input.counter),
3251
+ ...(input.metadata === undefined ? {} : { metadata: input.metadata }),
3252
+ }).pipe(Query.where(eq(authPostgresTotpFactor.id, input.id)), Query.where(isNotNull(authPostgresTotpFactor.confirmed_at)), Query.where(isNull(authPostgresTotpFactor.revoked_at)), Query.where(or(isNull(authPostgresTotpFactor.last_accepted_counter), Query.lt(authPostgresTotpFactor.last_accepted_counter, String(input.counter)))), Query.returning(totpFactorSelection))).pipe(Effect.mapError((cause) => totpFactorStoreError("accept-counter", cause)), Effect.flatMap((rows) => {
3253
+ if (rows[0] !== undefined) {
3254
+ return Effect.succeed({
3255
+ _tag: "Accepted",
3256
+ factor: decodeTotpFactor(rows[0]),
3257
+ });
3258
+ }
3259
+ return findById(input.id, "accept-counter").pipe(Effect.map((factor) => Option.isSome(factor) &&
3260
+ factor.value.confirmedAt !== undefined &&
3261
+ factor.value.revokedAt === undefined &&
3262
+ factor.value.lastAcceptedCounter !== undefined &&
3263
+ factor.value.lastAcceptedCounter >= input.counter
3264
+ ? { _tag: "Replay" }
3265
+ : { _tag: "Unavailable" }));
3266
+ })),
3267
+ revoke: (input) => findById(input.id, "revoke").pipe(Effect.flatMap((found) => {
3268
+ if (Option.isNone(found)) {
3269
+ return Effect.void;
3270
+ }
3271
+ const metadata = input.reason === undefined
3272
+ ? (found.value.metadata ?? null)
3273
+ : { ...found.value.metadata, revokeReason: input.reason };
3274
+ return execute(executor, update(authPostgresTotpFactor, {
3275
+ revoked_at: millisParam(input.revokedAt),
3276
+ metadata,
3277
+ }).pipe(Query.where(eq(authPostgresTotpFactor.id, input.id)))).pipe(Effect.mapError((cause) => totpFactorStoreError("revoke", cause)), Effect.asVoid);
3278
+ })),
3279
+ });
3280
+ };
3281
+ export const makeEffectQbPostgresRecoveryCodeStore = (executor, sql) => {
3282
+ const findById = (id, operation = "find") => execute(executor, Query.select(recoveryCodeSelection).pipe(Query.from(authPostgresRecoveryCode), Query.where(eq(authPostgresRecoveryCode.id, id)))).pipe(Effect.mapError((cause) => recoveryCodeStoreError(operation, cause)), Effect.map((rows) => firstOption(rows, decodeRecoveryCode)));
3283
+ const insertOne = (row) => execute(executor, insert(authPostgresRecoveryCode, recoveryCodeValues(row))).pipe(Effect.asVoid);
3284
+ return RecoveryCodeStore.of({
3285
+ insertMany: (rows) => sql
3286
+ .withTransaction(Effect.forEach(rows, insertOne, { discard: true }))
3287
+ .pipe(Effect.mapError((cause) => recoveryCodeStoreError("insert", cause))),
3288
+ findById,
3289
+ listByUser: (input) => {
3290
+ let plan = Query.select(recoveryCodeSelection).pipe(Query.from(authPostgresRecoveryCode), Query.where(eq(authPostgresRecoveryCode.user_id, input.userId)));
3291
+ if (input.includeUsed !== true) {
3292
+ plan = plan.pipe(Query.where(isNull(authPostgresRecoveryCode.used_at)));
3293
+ }
3294
+ if (input.includeRevoked !== true) {
3295
+ plan = plan.pipe(Query.where(isNull(authPostgresRecoveryCode.revoked_at)));
3296
+ }
3297
+ plan = plan.pipe(Query.orderBy(authPostgresRecoveryCode.created_at, "asc"), Query.orderBy(Query.collate(authPostgresRecoveryCode.id, "C"), "asc"));
3298
+ return execute(executor, plan).pipe(Effect.mapError((cause) => recoveryCodeStoreError("list", cause)), Effect.map((rows) => rows.map(decodeRecoveryCode)));
3299
+ },
3300
+ markUsed: (input) => execute(executor, update(authPostgresRecoveryCode, {
3301
+ used_at: millisParam(input.usedAt),
3302
+ ...(input.metadata === undefined ? {} : { metadata: input.metadata }),
3303
+ }).pipe(Query.where(eq(authPostgresRecoveryCode.id, input.id)), Query.where(isNull(authPostgresRecoveryCode.used_at)), Query.where(isNull(authPostgresRecoveryCode.revoked_at)), Query.returning({
3304
+ ...recoveryCodeSelection,
3305
+ usedAt: withoutNullRefinement(authPostgresRecoveryCode.used_at),
3306
+ }))).pipe(Effect.mapError((cause) => recoveryCodeStoreError("mark-used", cause)), Effect.map((rows) => firstOption(rows, decodeRecoveryCode))),
3307
+ replaceActiveForUser: (input) => sql
3308
+ .withTransaction(Effect.gen(function* () {
3309
+ yield* execute(executor, update(authPostgresRecoveryCode, {
3310
+ revoked_at: millisParam(input.revokedAt),
3311
+ ...(input.revokeReason === undefined
3312
+ ? {}
3313
+ : {
3314
+ metadata: metadataWithReason(authPostgresRecoveryCode.metadata, "revokeReason", input.revokeReason),
3315
+ }),
3316
+ }).pipe(Query.where(eq(authPostgresRecoveryCode.user_id, input.userId)), Query.where(isNull(authPostgresRecoveryCode.used_at)), Query.where(isNull(authPostgresRecoveryCode.revoked_at))));
3317
+ yield* Effect.forEach(input.rows, insertOne, { discard: true });
3318
+ }))
3319
+ .pipe(Effect.mapError((cause) => recoveryCodeStoreError("replace-active", cause))),
3320
+ revoke: (input) => findById(input.id, "revoke").pipe(Effect.flatMap((found) => {
3321
+ if (Option.isNone(found)) {
3322
+ return Effect.void;
3323
+ }
3324
+ const metadata = input.reason === undefined
3325
+ ? (found.value.metadata ?? null)
3326
+ : { ...found.value.metadata, revokeReason: input.reason };
3327
+ return execute(executor, update(authPostgresRecoveryCode, {
3328
+ revoked_at: millisParam(input.revokedAt),
3329
+ metadata,
3330
+ }).pipe(Query.where(eq(authPostgresRecoveryCode.id, input.id)))).pipe(Effect.mapError((cause) => recoveryCodeStoreError("revoke", cause)), Effect.asVoid);
3331
+ })),
3332
+ });
3333
+ };
3334
+ export const makeEffectQbPostgresTotpSessionRotateStore = (sql) => {
3335
+ const executor = makeEffectQbPostgresExecutor(sql);
3336
+ return TotpSessionRotateStore.of({
3337
+ acceptAndRotate: (input) => sql
3338
+ .withTransaction(Effect.gen(function* () {
3339
+ const factors = yield* execute(executor, selectForUpdate(totpFactorSelection, authPostgresTotpFactor, eq(authPostgresTotpFactor.id, input.factorId)));
3340
+ const sessions = yield* execute(executor, selectForUpdate(sessionSelection, authPostgresSession, eq(authPostgresSession.id, input.sessionId)));
3341
+ const [factor] = factors;
3342
+ const [session] = sessions;
3343
+ if (factor === undefined ||
3344
+ factor.userId !== input.userId ||
3345
+ factor.confirmedAt === null ||
3346
+ factor.revokedAt !== null ||
3347
+ (factor.lastAcceptedCounter !== null &&
3348
+ Number(factor.lastAcceptedCounter) >= input.counter) ||
3349
+ session === undefined ||
3350
+ session.userId !== input.userId ||
3351
+ session.revokedAt !== null ||
3352
+ postgresBigintToUnixMillis(session.expiresAt) <= input.now ||
3353
+ session.secretHash !== input.expectedSecretHash ||
3354
+ !jsonEqual(session.authenticationEvents, input.expectedAuthenticationEvents)) {
3355
+ return Option.none();
3356
+ }
3357
+ yield* execute(executor, update(authPostgresTotpFactor, {
3358
+ last_used_at: millisParam(input.lastUsedAt),
3359
+ last_accepted_counter: String(input.counter),
3360
+ ...(input.factorMetadata === undefined
3361
+ ? {}
3362
+ : { metadata: input.factorMetadata }),
3363
+ }).pipe(Query.where(eq(authPostgresTotpFactor.id, input.factorId))));
3364
+ const updated = yield* updateAssuredSession(executor, input);
3365
+ return yield* decodeMapped(() => firstOption(updated, decodeSession), (cause) => cause);
3366
+ }))
3367
+ .pipe(Effect.mapError((cause) => new TotpSessionRotateStoreError({
3368
+ message: "Atomic TOTP session rotation failed",
3369
+ cause,
3370
+ }))),
3371
+ });
3372
+ };
3373
+ export const makeEffectQbPostgresRecoveryCodeSessionRotateStore = (sql) => {
3374
+ const executor = makeEffectQbPostgresExecutor(sql);
3375
+ return RecoveryCodeSessionRotateStore.of({
3376
+ consumeAndRotate: (input) => sql
3377
+ .withTransaction(Effect.gen(function* () {
3378
+ const codes = yield* execute(executor, selectForUpdate(recoveryCodeSelection, authPostgresRecoveryCode, eq(authPostgresRecoveryCode.id, input.codeId)));
3379
+ const sessions = yield* execute(executor, selectForUpdate(sessionSelection, authPostgresSession, eq(authPostgresSession.id, input.sessionId)));
3380
+ const [code] = codes;
3381
+ const [session] = sessions;
3382
+ if (code === undefined ||
3383
+ code.userId !== input.userId ||
3384
+ code.usedAt !== null ||
3385
+ code.revokedAt !== null ||
3386
+ session === undefined ||
3387
+ session.userId !== input.userId ||
3388
+ session.revokedAt !== null ||
3389
+ postgresBigintToUnixMillis(session.expiresAt) <= input.now ||
3390
+ session.secretHash !== input.expectedSecretHash ||
3391
+ !jsonEqual(session.authenticationEvents, input.expectedAuthenticationEvents)) {
3392
+ return Option.none();
3393
+ }
3394
+ yield* execute(executor, update(authPostgresRecoveryCode, {
3395
+ used_at: millisParam(input.usedAt),
3396
+ ...(input.codeMetadata === undefined
3397
+ ? {}
3398
+ : { metadata: input.codeMetadata }),
3399
+ }).pipe(Query.where(eq(authPostgresRecoveryCode.id, input.codeId))));
3400
+ const updated = yield* updateAssuredSession(executor, input);
3401
+ return yield* decodeMapped(() => firstOption(updated, decodeSession), (cause) => cause);
3402
+ }))
3403
+ .pipe(Effect.mapError((cause) => new RecoveryCodeSessionRotateStoreError({
3404
+ message: "Atomic recovery session rotation failed",
3405
+ cause,
3406
+ }))),
3407
+ });
3408
+ };
3409
+ export const makeEffectQbPostgresTotpLoginCommitStore = (sql) => {
3410
+ const executor = makeEffectQbPostgresExecutor(sql);
3411
+ return TotpLoginCommitStore.of({
3412
+ commit: (input) => {
3413
+ if (input.verification.type !== "auth-flow-state" ||
3414
+ input.verification.subject !== input.userId ||
3415
+ (input.session === undefined &&
3416
+ input.continuation !== "login-approval") ||
3417
+ (input.session !== undefined && input.continuation !== undefined) ||
3418
+ (input.session !== undefined && input.session.userId !== input.userId)) {
3419
+ return Effect.succeed(false);
3420
+ }
3421
+ return sql
3422
+ .withTransaction(Effect.gen(function* () {
3423
+ const verifications = yield* execute(executor, selectForUpdate(verificationSelection, authPostgresVerification, eq(authPostgresVerification.id, input.verification.id)));
3424
+ const [verification] = verifications;
3425
+ if (verification === undefined ||
3426
+ !sameVerification(verification, input.verification) ||
3427
+ verification.consumedAt !== null ||
3428
+ postgresBigintToUnixMillis(verification.expiresAt) <=
3429
+ input.consumedAt) {
3430
+ return false;
3431
+ }
3432
+ const factors = yield* execute(executor, selectForUpdate(totpFactorSelection, authPostgresTotpFactor, eq(authPostgresTotpFactor.id, input.factorId)));
3433
+ const [factor] = factors;
3434
+ if (factor === undefined ||
3435
+ factor.userId !== input.userId ||
3436
+ factor.confirmedAt === null ||
3437
+ factor.revokedAt !== null ||
3438
+ (factor.lastAcceptedCounter !== null &&
3439
+ Number(factor.lastAcceptedCounter) >= input.counter)) {
3440
+ return false;
3441
+ }
3442
+ if (input.session !== undefined) {
3443
+ const sessions = yield* execute(executor, Query.select({ id: authPostgresSession.id }).pipe(Query.from(authPostgresSession), Query.where(eq(authPostgresSession.id, input.session.id))));
3444
+ if (sessions[0] !== undefined) {
3445
+ return false;
3446
+ }
3447
+ }
3448
+ yield* execute(executor, update(authPostgresVerification, {
3449
+ consumed_at: millisParam(input.consumedAt),
3450
+ }).pipe(Query.where(eq(authPostgresVerification.id, input.verification.id))));
3451
+ yield* execute(executor, update(authPostgresTotpFactor, {
3452
+ last_used_at: millisParam(input.lastUsedAt),
3453
+ last_accepted_counter: String(input.counter),
3454
+ ...(input.factorMetadata === undefined
3455
+ ? {}
3456
+ : { metadata: input.factorMetadata }),
3457
+ }).pipe(Query.where(eq(authPostgresTotpFactor.id, input.factorId))));
3458
+ if (input.session !== undefined) {
3459
+ yield* insertSession(executor, input.session);
3460
+ }
3461
+ return true;
3462
+ }))
3463
+ .pipe(Effect.mapError((cause) => new TotpLoginCommitStoreError({
3464
+ message: "Atomic TOTP login commit failed",
3465
+ cause,
3466
+ })));
3467
+ },
3468
+ });
3469
+ };
3470
+ export const makeEffectQbPostgresRecoveryCodeLoginCommitStore = (sql) => {
3471
+ const executor = makeEffectQbPostgresExecutor(sql);
3472
+ return RecoveryCodeLoginCommitStore.of({
3473
+ commit: (input) => {
3474
+ if (input.verification.type !== "auth-flow-state" ||
3475
+ input.verification.subject !== input.userId ||
3476
+ (input.session === undefined &&
3477
+ input.continuation !== "login-approval") ||
3478
+ (input.session !== undefined && input.continuation !== undefined) ||
3479
+ (input.session !== undefined && input.session.userId !== input.userId)) {
3480
+ return Effect.succeed(false);
3481
+ }
3482
+ return sql
3483
+ .withTransaction(Effect.gen(function* () {
3484
+ const verifications = yield* execute(executor, selectForUpdate(verificationSelection, authPostgresVerification, eq(authPostgresVerification.id, input.verification.id)));
3485
+ const [verification] = verifications;
3486
+ if (verification === undefined ||
3487
+ !sameVerification(verification, input.verification) ||
3488
+ verification.consumedAt !== null ||
3489
+ postgresBigintToUnixMillis(verification.expiresAt) <=
3490
+ input.consumedAt) {
3491
+ return false;
3492
+ }
3493
+ const codes = yield* execute(executor, selectForUpdate(recoveryCodeSelection, authPostgresRecoveryCode, eq(authPostgresRecoveryCode.id, input.codeId)));
3494
+ const [code] = codes;
3495
+ if (code === undefined ||
3496
+ code.userId !== input.userId ||
3497
+ code.usedAt !== null ||
3498
+ code.revokedAt !== null) {
3499
+ return false;
3500
+ }
3501
+ if (input.session !== undefined) {
3502
+ const sessions = yield* execute(executor, Query.select({ id: authPostgresSession.id }).pipe(Query.from(authPostgresSession), Query.where(eq(authPostgresSession.id, input.session.id))));
3503
+ if (sessions[0] !== undefined) {
3504
+ return false;
3505
+ }
3506
+ }
3507
+ yield* execute(executor, update(authPostgresVerification, {
3508
+ consumed_at: millisParam(input.consumedAt),
3509
+ }).pipe(Query.where(eq(authPostgresVerification.id, input.verification.id))));
3510
+ yield* execute(executor, update(authPostgresRecoveryCode, {
3511
+ used_at: millisParam(input.usedAt),
3512
+ ...(input.codeMetadata === undefined
3513
+ ? {}
3514
+ : { metadata: input.codeMetadata }),
3515
+ }).pipe(Query.where(eq(authPostgresRecoveryCode.id, input.codeId))));
3516
+ if (input.session !== undefined) {
3517
+ yield* insertSession(executor, input.session);
3518
+ }
3519
+ return true;
3520
+ }))
3521
+ .pipe(Effect.mapError((cause) => new RecoveryCodeLoginCommitStoreError({
3522
+ message: "Atomic recovery-code login commit failed",
3523
+ cause,
3524
+ })));
3525
+ },
3526
+ });
3527
+ };
3528
+ export const makeEffectQbPostgresRefreshTokenStore = (executor, sql) => {
3529
+ const find = (column, value, operation = "find") => execute(executor, Query.select(refreshTokenSelection).pipe(Query.from(authPostgresRefreshToken), Query.where(eq(column, value)))).pipe(Effect.mapError((cause) => refreshTokenStoreError(operation, cause)), Effect.map((rows) => firstOption(rows, decodeRefreshToken)));
3530
+ const list = (column, value, includeRevoked) => {
3531
+ let plan = Query.select(refreshTokenSelection).pipe(Query.from(authPostgresRefreshToken), Query.where(eq(column, value)));
3532
+ if (includeRevoked !== true) {
3533
+ plan = plan.pipe(Query.where(isNull(authPostgresRefreshToken.revoked_at)));
3534
+ }
3535
+ plan = plan.pipe(Query.orderBy(authPostgresRefreshToken.created_at, "asc"), Query.orderBy(Query.collate(authPostgresRefreshToken.id, "C"), "asc"));
3536
+ return execute(executor, plan).pipe(Effect.mapError((cause) => refreshTokenStoreError("list", cause)), Effect.map((rows) => rows.map(decodeRefreshToken)));
3537
+ };
3538
+ const updateRevoke = (row, revokedAt, reasonKey, reason) => execute(executor, update(authPostgresRefreshToken, {
3539
+ revoked_at: millisParam(revokedAt),
3540
+ metadata: reason === undefined
3541
+ ? (row.metadata ?? null)
3542
+ : { ...row.metadata, [reasonKey]: reason },
3543
+ }).pipe(Query.where(eq(authPostgresRefreshToken.id, row.id)))).pipe(Effect.asVoid);
3544
+ return RefreshTokenStore.of({
3545
+ insert: (row) => execute(executor, insert(authPostgresRefreshToken, refreshTokenValues(row))).pipe(Effect.mapError((cause) => refreshTokenStoreError("insert", cause)), Effect.asVoid),
3546
+ findById: (id) => find(authPostgresRefreshToken.id, id),
3547
+ findBySecretHash: (hash) => find(authPostgresRefreshToken.secret_hash, hash),
3548
+ listByUser: (input) => list(authPostgresRefreshToken.user_id, input.userId, input.includeRevoked),
3549
+ listByFamily: (input) => list(authPostgresRefreshToken.family_id, input.familyId, input.includeRevoked),
3550
+ rotate: (input) => sql
3551
+ .withTransaction(Effect.gen(function* () {
3552
+ const currentRows = yield* execute(executor, selectForUpdate(refreshTokenSelection, authPostgresRefreshToken, eq(authPostgresRefreshToken.id, input.id)));
3553
+ const [current] = currentRows;
3554
+ if (current === undefined ||
3555
+ current.rotatedAt !== null ||
3556
+ current.revokedAt !== null) {
3557
+ return Option.none();
3558
+ }
3559
+ const previousRows = yield* execute(executor, update(authPostgresRefreshToken, {
3560
+ last_used_at: millisParam(input.rotatedAt),
3561
+ rotated_at: millisParam(input.rotatedAt),
3562
+ replaced_by_id: input.replacement.id,
3563
+ }).pipe(Query.where(eq(authPostgresRefreshToken.id, input.id)), Query.returning(refreshTokenSelection)));
3564
+ const { replacement } = input;
3565
+ const replacementRows = yield* execute(executor, insert(authPostgresRefreshToken, refreshTokenValues(replacement)).pipe(Query.returning(refreshTokenSelection)));
3566
+ return Option.some({
3567
+ previous: decodeRefreshToken(previousRows[0]),
3568
+ replacement: decodeRefreshToken(replacementRows[0]),
3569
+ });
3570
+ }))
3571
+ .pipe(Effect.mapError((cause) => refreshTokenStoreError("rotate", cause))),
3572
+ markReuseDetected: (input) => execute(executor, update(authPostgresRefreshToken, {
3573
+ reuse_detected_at: millisParam(input.reuseDetectedAt),
3574
+ }).pipe(Query.where(eq(authPostgresRefreshToken.id, input.id)), Query.returning(refreshTokenSelection))).pipe(Effect.mapError((cause) => refreshTokenStoreError("reuse", cause)), Effect.map((rows) => firstOption(rows, decodeRefreshToken))),
3575
+ revoke: (input) => find(authPostgresRefreshToken.id, input.id, "revoke").pipe(Effect.flatMap((found) => Option.isNone(found)
3576
+ ? Effect.void
3577
+ : updateRevoke(found.value, input.revokedAt, "revokeReason", input.reason)), Effect.mapError((cause) => cause instanceof RefreshTokenStoreError
3578
+ ? cause
3579
+ : refreshTokenStoreError("revoke", cause))),
3580
+ revokeFamily: (input) => execute(executor, update(authPostgresRefreshToken, {
3581
+ revoked_at: millisParam(input.revokedAt),
3582
+ ...(input.reason === undefined
3583
+ ? {}
3584
+ : {
3585
+ metadata: metadataWithReason(authPostgresRefreshToken.metadata, "familyRevokeReason", input.reason),
3586
+ }),
3587
+ }).pipe(Query.where(eq(authPostgresRefreshToken.family_id, input.familyId)))).pipe(Effect.asVoid, Effect.mapError((cause) => refreshTokenStoreError("revoke", cause))),
3588
+ });
3589
+ };
3590
+ export const makeEffectQbPostgresOAuthAccountStore = (executor, _sql) => {
3591
+ const find = (plan, operation = "find") => execute(executor, plan).pipe(Effect.mapError((cause) => oauthAccountStoreError(operation, cause)), Effect.map((rows) => firstOption(rows, decodeOAuthAccount)));
3592
+ return OAuthAccountStore.of({
3593
+ insert: (row) => execute(executor, insert(authPostgresOAuthAccount, oauthAccountValues(row))).pipe(Effect.mapError((cause) => oauthAccountStoreError("insert", cause)), Effect.asVoid),
3594
+ findById: (id) => find(Query.select(oauthAccountSelection).pipe(Query.from(authPostgresOAuthAccount), Query.where(eq(authPostgresOAuthAccount.id, id)))),
3595
+ findByProviderAccount: (input) => {
3596
+ let plan = Query.select(oauthAccountSelection).pipe(Query.from(authPostgresOAuthAccount), Query.where(eq(authPostgresOAuthAccount.provider_id, input.providerId)), Query.where(eq(authPostgresOAuthAccount.provider_account_id, input.providerAccountId)));
3597
+ if (input.includeUnlinked !== true) {
3598
+ plan = plan.pipe(Query.where(isNull(authPostgresOAuthAccount.unlinked_at)));
3599
+ }
3600
+ return find(plan);
3601
+ },
3602
+ listByUser: (input) => {
3603
+ let plan = Query.select(oauthAccountSelection).pipe(Query.from(authPostgresOAuthAccount), Query.where(eq(authPostgresOAuthAccount.user_id, input.userId)));
3604
+ if (input.includeUnlinked !== true) {
3605
+ plan = plan.pipe(Query.where(isNull(authPostgresOAuthAccount.unlinked_at)));
3606
+ }
3607
+ plan = plan.pipe(Query.orderBy(authPostgresOAuthAccount.created_at, "asc"), Query.orderBy(Query.collate(authPostgresOAuthAccount.id, "C"), "asc"));
3608
+ return execute(executor, plan).pipe(Effect.mapError((cause) => oauthAccountStoreError("list", cause)), Effect.map((rows) => rows.map(decodeOAuthAccount)));
3609
+ },
3610
+ unlink: (input) => execute(executor, update(authPostgresOAuthAccount, {
3611
+ unlinked_at: millisParam(input.unlinkedAt),
3612
+ ...(input.reason === undefined
3613
+ ? {}
3614
+ : {
3615
+ metadata: metadataWithReason(authPostgresOAuthAccount.metadata, "unlinkReason", input.reason),
3616
+ }),
3617
+ }).pipe(Query.where(eq(authPostgresOAuthAccount.provider_id, input.providerId)), Query.where(eq(authPostgresOAuthAccount.provider_account_id, input.providerAccountId)), Query.where(isNull(authPostgresOAuthAccount.unlinked_at)), Query.returning({
3618
+ ...oauthAccountSelection,
3619
+ unlinkedAt: withoutNullRefinement(authPostgresOAuthAccount.unlinked_at),
3620
+ }))).pipe(Effect.mapError((cause) => oauthAccountStoreError("unlink", cause)), Effect.map((rows) => firstOption(rows, decodeOAuthAccount))),
3621
+ });
3622
+ };
3623
+ const oauthClientRedirectUriValidationResult = (client, input) => {
3624
+ if (client === undefined) {
3625
+ return { valid: false, reason: "unknown_client" };
3626
+ }
3627
+ if (client.status !== "active") {
3628
+ return { valid: false, reason: "disabled_client" };
3629
+ }
3630
+ if (!client.allowedResponseTypes.includes(input.responseType ?? "code")) {
3631
+ return { valid: false, reason: "unsupported_response_type" };
3632
+ }
3633
+ if (input.grantType !== undefined &&
3634
+ !client.allowedGrantTypes.includes(input.grantType)) {
3635
+ return { valid: false, reason: "unsupported_grant_type" };
3636
+ }
3637
+ if (!client.redirectUris.includes(input.redirectUri)) {
3638
+ return { valid: false, reason: "redirect_uri_mismatch" };
3639
+ }
3640
+ return { valid: true, client };
3641
+ };
3642
+ export const makeEffectQbPostgresOAuthClientStore = (executor) => {
3643
+ const find = (clientId, operation = "find") => {
3644
+ const mapError = (cause) => oauthClientStoreError(operation, cause);
3645
+ return executeMapped(executor, () => Query.select(oauthClientSelection).pipe(Query.from(authPostgresOAuthClient), Query.where(eq(authPostgresOAuthClient.id, clientId))), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodeOAuthClient), mapError)));
3646
+ };
3647
+ return OAuthClientStore.of({
3648
+ upsert: (record) => {
3649
+ const mapError = (cause) => oauthClientStoreError("upsert", cause);
3650
+ return executeMapped(executor, () => {
3651
+ const values = oauthClientValues(record);
3652
+ return insert(authPostgresOAuthClient, values).pipe(PostgresQuery.onConflict("id", {
3653
+ update: {
3654
+ type: values.type,
3655
+ status: values.status,
3656
+ name: values.name,
3657
+ redirect_uris: values.redirect_uris,
3658
+ allowed_grant_types: values.allowed_grant_types,
3659
+ allowed_response_types: values.allowed_response_types,
3660
+ allowed_scopes: values.allowed_scopes,
3661
+ created_at: values.created_at,
3662
+ updated_at: values.updated_at,
3663
+ metadata: values.metadata,
3664
+ },
3665
+ }));
3666
+ }, mapError).pipe(Effect.asVoid);
3667
+ },
3668
+ find: (input) => find(input.clientId),
3669
+ list: (input = {}) => {
3670
+ const mapError = (cause) => oauthClientStoreError("list", cause);
3671
+ return executeMapped(executor, () => {
3672
+ let plan = Query.select(oauthClientSelection).pipe(Query.from(authPostgresOAuthClient), Query.orderBy(Query.collate(authPostgresOAuthClient.id, "C"), "asc"));
3673
+ if (input.includeDisabled !== true) {
3674
+ plan = plan.pipe(Query.where(eq(authPostgresOAuthClient.status, "active")));
3675
+ }
3676
+ return plan;
3677
+ }, mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => rows.map(decodeOAuthClient), mapError)));
3678
+ },
3679
+ validateRedirectUri: (input) => find(input.clientId, "validate-redirect-uri").pipe(Effect.map((client) => oauthClientRedirectUriValidationResult(Option.isSome(client) ? client.value : undefined, input))),
3680
+ });
3681
+ };
3682
+ const oauthConsentIsActive = (record, input) => record.revokedAt === undefined &&
3683
+ (record.expiresAt === undefined || record.expiresAt > input.now) &&
3684
+ (input.scopes ?? []).every((scope) => record.scopes.includes(scope));
3685
+ export const makeEffectQbPostgresOAuthConsentStore = (executor) => {
3686
+ const find = (input, operation = "find-active") => {
3687
+ const mapError = (cause) => oauthConsentStoreError(operation, cause);
3688
+ return executeMapped(executor, () => Query.select(oauthConsentSelection).pipe(Query.from(authPostgresOAuthConsent), Query.where(eq(authPostgresOAuthConsent.user_id, input.userId)), Query.where(eq(authPostgresOAuthConsent.client_id, input.clientId))), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodeOAuthConsent), mapError)));
3689
+ };
3690
+ return OAuthConsentStore.of({
3691
+ upsert: (record) => {
3692
+ const mapError = (cause) => oauthConsentStoreError("upsert", cause);
3693
+ return executeMapped(executor, () => {
3694
+ const values = oauthConsentValues(record);
3695
+ return insert(authPostgresOAuthConsent, values).pipe(PostgresQuery.onConflict(["user_id", "client_id"], {
3696
+ update: {
3697
+ scopes: values.scopes,
3698
+ granted_at: values.granted_at,
3699
+ expires_at: values.expires_at,
3700
+ revoked_at: values.revoked_at,
3701
+ metadata: values.metadata,
3702
+ },
3703
+ }));
3704
+ }, mapError).pipe(Effect.asVoid);
3705
+ },
3706
+ findActive: (input) => find(input).pipe(Effect.map((record) => Option.isSome(record) && oauthConsentIsActive(record.value, input)
3707
+ ? record
3708
+ : Option.none())),
3709
+ listForUser: (input) => {
3710
+ const mapError = (cause) => oauthConsentStoreError("list-for-user", cause);
3711
+ return executeMapped(executor, () => Query.select(oauthConsentSelection).pipe(Query.from(authPostgresOAuthConsent), Query.where(eq(authPostgresOAuthConsent.user_id, input.userId)), Query.orderBy(authPostgresOAuthConsent.granted_at, "asc"), Query.orderBy(Query.collate(authPostgresOAuthConsent.client_id, "C"), "asc")), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => rows
3712
+ .map(decodeOAuthConsent)
3713
+ .filter((record) => input.includeInactive === true ||
3714
+ oauthConsentIsActive(record, input)), mapError)));
3715
+ },
3716
+ revoke: (input) => {
3717
+ const mapError = (cause) => oauthConsentStoreError("revoke", cause);
3718
+ return executeMapped(executor, () => update(authPostgresOAuthConsent, {
3719
+ revoked_at: Query.coalesce(authPostgresOAuthConsent.revoked_at, millisParam(input.revokedAt)),
3720
+ ...(input.reason === undefined
3721
+ ? {}
3722
+ : {
3723
+ metadata: metadataWithReason(authPostgresOAuthConsent.metadata, "revokeReason", input.reason),
3724
+ }),
3725
+ }).pipe(Query.where(eq(authPostgresOAuthConsent.user_id, input.userId)), Query.where(eq(authPostgresOAuthConsent.client_id, input.clientId)), Query.returning(oauthConsentSelection)), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodeOAuthConsent), mapError)));
3726
+ },
3727
+ deleteInactive: (input) => {
3728
+ const mapError = (cause) => oauthConsentStoreError("deleteInactive", cause);
3729
+ return executeMapped(executor, () => {
3730
+ const predicates = [
3731
+ ...(input.beforeExpiresAt === undefined
3732
+ ? []
3733
+ : [
3734
+ lt(authPostgresOAuthConsent.expires_at, millisParam(input.beforeExpiresAt)),
3735
+ ]),
3736
+ ...(input.beforeRevokedAt === undefined
3737
+ ? []
3738
+ : [
3739
+ lt(authPostgresOAuthConsent.revoked_at, millisParam(input.beforeRevokedAt)),
3740
+ ]),
3741
+ ];
3742
+ return Query.delete(authPostgresOAuthConsent).pipe(Query.where(predicates.length === 1
3743
+ ? predicates[0]
3744
+ : or(predicates[0], predicates[1])), Query.returning({ clientId: authPostgresOAuthConsent.client_id }));
3745
+ }, mapError).pipe(Effect.map((rows) => rows.length));
3746
+ },
3747
+ });
3748
+ };
3749
+ export const makeEffectQbPostgresOAuthAuthorizationCodeStore = (executor, sql) => {
3750
+ const find = (codeHash, operation = "find") => {
3751
+ const mapError = (cause) => oauthAuthorizationCodeStoreError(operation, cause);
3752
+ return executeMapped(executor, () => Query.select(oauthAuthorizationCodeSelection).pipe(Query.from(authPostgresOAuthAuthorizationCode), Query.where(eq(authPostgresOAuthAuthorizationCode.code_hash, codeHash))), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodeOAuthAuthorizationCode), mapError)));
3753
+ };
3754
+ return OAuthAuthorizationCodeStore.of({
3755
+ upsert: (record) => {
3756
+ const mapError = (cause) => oauthAuthorizationCodeStoreError("upsert", cause);
3757
+ return executeMapped(executor, () => {
3758
+ const values = oauthAuthorizationCodeValues(record);
3759
+ return insert(authPostgresOAuthAuthorizationCode, values).pipe(PostgresQuery.onConflict("code_hash", {
3760
+ update: {
3761
+ client_id: values.client_id,
3762
+ subject: values.subject,
3763
+ redirect_uri: values.redirect_uri,
3764
+ scopes: values.scopes,
3765
+ code_challenge: values.code_challenge,
3766
+ code_challenge_method: values.code_challenge_method,
3767
+ issued_at: values.issued_at,
3768
+ expires_at: values.expires_at,
3769
+ consumed_at: values.consumed_at,
3770
+ metadata: values.metadata,
3771
+ },
3772
+ }));
3773
+ }, mapError).pipe(Effect.asVoid);
3774
+ },
3775
+ findByHash: (input) => find(input.codeHash),
3776
+ markConsumed: (input) => {
3777
+ const mapError = (cause) => oauthAuthorizationCodeStoreError("mark-consumed", cause);
3778
+ return sql
3779
+ .withTransaction(Effect.gen(function* () {
3780
+ const selected = yield* executeMapped(executor, () => selectForUpdate(oauthAuthorizationCodeSelection, authPostgresOAuthAuthorizationCode, eq(authPostgresOAuthAuthorizationCode.code_hash, input.codeHash)), mapError);
3781
+ const existing = yield* decodeMapped(() => firstOption(selected, decodeOAuthAuthorizationCode), mapError);
3782
+ if (Option.isNone(existing)) {
3783
+ return { status: "missing" };
3784
+ }
3785
+ if (existing.value.consumedAt !== undefined) {
3786
+ return {
3787
+ status: "already_consumed",
3788
+ record: existing.value,
3789
+ };
3790
+ }
3791
+ const rows = yield* executeMapped(executor, () => update(authPostgresOAuthAuthorizationCode, {
3792
+ consumed_at: millisParam(input.consumedAt),
3793
+ }).pipe(Query.where(eq(authPostgresOAuthAuthorizationCode.code_hash, input.codeHash)), Query.where(isNull(authPostgresOAuthAuthorizationCode.consumed_at)), Query.returning({
3794
+ ...oauthAuthorizationCodeSelection,
3795
+ consumedAt: withoutNullRefinement(authPostgresOAuthAuthorizationCode.consumed_at),
3796
+ })), mapError);
3797
+ return yield* decodeMapped(() => ({
3798
+ status: "consumed",
3799
+ record: decodeOAuthAuthorizationCode(rows[0]),
3800
+ }), mapError);
3801
+ }))
3802
+ .pipe(Effect.mapError((cause) => cause instanceof OAuthAuthorizationCodeStoreError
3803
+ ? cause
3804
+ : mapError(cause)));
3805
+ },
3806
+ });
3807
+ };
3808
+ export const makeEffectQbPostgresOAuthDeviceAuthorizationStore = (executor, sql) => {
3809
+ const find = (column, value, operation) => {
3810
+ const mapError = (cause) => oauthDeviceAuthorizationStoreError(operation, cause);
3811
+ return executeMapped(executor, () => Query.select(oauthDeviceAuthorizationSelection).pipe(Query.from(authPostgresOAuthDeviceAuthorization), Query.where(eq(column, value))), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodeOAuthDeviceAuthorization), mapError)));
3812
+ };
3813
+ const selectedColumns = `
3814
+ case when u.id is null then c.id else u.id end as id,
3815
+ case when u.id is null then c.device_code_hash else u.device_code_hash end as device_code_hash,
3816
+ case when u.id is null then c.user_code_hash else u.user_code_hash end as user_code_hash,
3817
+ case when u.id is null then c.client_id else u.client_id end as client_id,
3818
+ case when u.id is null then c.requested_scopes else u.requested_scopes end as requested_scopes,
3819
+ case when u.id is null then c.granted_scopes else u.granted_scopes end as granted_scopes,
3820
+ case when u.id is null then c.subject else u.subject end as subject,
3821
+ case when u.id is null then c.status else u.status end as status,
3822
+ case when u.id is null then c.issued_at else u.issued_at end as issued_at,
3823
+ case when u.id is null then c.expires_at else u.expires_at end as expires_at,
3824
+ case when u.id is null then c.poll_interval_seconds else u.poll_interval_seconds end as poll_interval_seconds,
3825
+ case when u.id is null then c.next_poll_at else u.next_poll_at end as next_poll_at,
3826
+ case when u.id is null then c.last_polled_at else u.last_polled_at end as last_polled_at,
3827
+ case when u.id is null then c.approved_at else u.approved_at end as approved_at,
3828
+ case when u.id is null then c.denied_at else u.denied_at end as denied_at,
3829
+ case when u.id is null then c.consumed_at else u.consumed_at end as consumed_at,
3830
+ case when u.id is null then c.metadata else u.metadata end as metadata`;
3831
+ return OAuthDeviceAuthorizationStore.of({
3832
+ insert: (record) => Effect.suspend(() => execute(executor, insert(authPostgresOAuthDeviceAuthorization, oauthDeviceAuthorizationValues(record)).pipe(Query.returning({ id: authPostgresOAuthDeviceAuthorization.id })))).pipe(Effect.as(true), Effect.catch((error) => postgresErrorDetails(error).code === "23505"
3833
+ ? Effect.succeed(false)
3834
+ : Effect.fail(oauthDeviceAuthorizationStoreError("insert", error)))),
3835
+ findByDeviceCodeHash: (input) => find(authPostgresOAuthDeviceAuthorization.device_code_hash, input.deviceCodeHash, "find-by-device-code-hash"),
3836
+ findByUserCodeHash: (input) => find(authPostgresOAuthDeviceAuthorization.user_code_hash, input.userCodeHash, "find-by-user-code-hash"),
3837
+ findById: (id) => find(authPostgresOAuthDeviceAuthorization.id, id, "find-by-id"),
3838
+ decide: (input) => {
3839
+ const mapError = (cause) => oauthDeviceAuthorizationStoreError("decide", cause);
3840
+ const status = input.decision === "approve" ? "approved" : "denied";
3841
+ const subject = input.decision === "approve" ? input.subject : null;
3842
+ const grantedScopes = input.decision === "approve"
3843
+ ? JSON.stringify(input.grantedScopes)
3844
+ : null;
3845
+ return sql
3846
+ .unsafe(`with candidate as materialized (
3847
+ select * from auth_oauth_device_authorization where id = $1 for update
3848
+ ), updated as (
3849
+ update auth_oauth_device_authorization d set
3850
+ status = $3,
3851
+ subject = $4,
3852
+ granted_scopes = $5::jsonb,
3853
+ approved_at = case when $3 = 'approved' then $2::bigint else null end,
3854
+ denied_at = case when $3 = 'denied' then $2::bigint else null end,
3855
+ metadata = coalesce($6::jsonb, c.metadata)
3856
+ from candidate c
3857
+ where d.id = c.id and c.status = 'pending' and c.expires_at > $2::bigint
3858
+ returning d.*
3859
+ )
3860
+ select
3861
+ case when u.id is not null then $3 when c.expires_at <= $2::bigint then 'expired' else 'already_decided' end as action,
3862
+ ${selectedColumns}
3863
+ from candidate c left join updated u on true`, [
3864
+ input.id,
3865
+ millisParam(input.decidedAt),
3866
+ status,
3867
+ subject,
3868
+ grantedScopes,
3869
+ input.metadata === undefined
3870
+ ? null
3871
+ : JSON.stringify(input.metadata),
3872
+ ])
3873
+ .pipe(Effect.mapError(mapError), Effect.flatMap((rows) => decodeMapped(() => {
3874
+ const [row] = rows;
3875
+ if (row === undefined) {
3876
+ return { status: "missing" };
3877
+ }
3878
+ const record = decodeOAuthDeviceAuthorization(row);
3879
+ if (row.action === "expired") {
3880
+ return { status: "expired", record };
3881
+ }
3882
+ if (row.action === "already_decided") {
3883
+ return {
3884
+ status: "already_decided",
3885
+ record: record,
3886
+ };
3887
+ }
3888
+ return record.status === "approved"
3889
+ ? { status: "approved", record }
3890
+ : {
3891
+ status: "denied",
3892
+ record: record,
3893
+ };
3894
+ }, mapError)));
3895
+ },
3896
+ poll: (input) => {
3897
+ const mapError = (cause) => oauthDeviceAuthorizationStoreError("poll", cause);
3898
+ return sql
3899
+ .unsafe(`with candidate as materialized (
3900
+ select d.*,
3901
+ case
3902
+ when d.consumed_at is not null then 'already_consumed'
3903
+ when d.expires_at <= $3::bigint then 'expired'
3904
+ when d.status = 'denied' then 'denied'
3905
+ when d.status = 'approved' then 'approved'
3906
+ when d.next_poll_at > $3::bigint then 'slow_down'
3907
+ when d.status = 'pending' then 'pending'
3908
+ else 'pending'
3909
+ end as action
3910
+ from auth_oauth_device_authorization d
3911
+ where d.device_code_hash = $1 and d.client_id = $2
3912
+ for update
3913
+ ), updated as (
3914
+ update auth_oauth_device_authorization d set
3915
+ poll_interval_seconds = case when c.action = 'slow_down' then c.poll_interval_seconds + 5 else c.poll_interval_seconds end,
3916
+ next_poll_at = $3::bigint + (case when c.action = 'slow_down' then c.poll_interval_seconds + 5 else c.poll_interval_seconds end) * 1000,
3917
+ last_polled_at = $3::bigint
3918
+ from candidate c
3919
+ where d.id = c.id and c.action in ('slow_down', 'pending')
3920
+ returning d.*
3921
+ )
3922
+ select c.action, ${selectedColumns}
3923
+ from candidate c left join updated u on true`, [input.deviceCodeHash, input.clientId, millisParam(input.now)])
3924
+ .pipe(Effect.mapError(mapError), Effect.flatMap((rows) => decodeMapped(() => {
3925
+ const [row] = rows;
3926
+ if (row === undefined) {
3927
+ return { status: "missing" };
3928
+ }
3929
+ const record = decodeOAuthDeviceAuthorization(row);
3930
+ switch (row.action) {
3931
+ case "expired": {
3932
+ return { status: "expired", record };
3933
+ }
3934
+ case "denied": {
3935
+ return {
3936
+ status: "denied",
3937
+ record: record,
3938
+ };
3939
+ }
3940
+ case "already_consumed": {
3941
+ return {
3942
+ status: "already_consumed",
3943
+ record: record,
3944
+ };
3945
+ }
3946
+ case "slow_down": {
3947
+ return {
3948
+ status: "slow_down",
3949
+ record,
3950
+ interval: record.pollIntervalSeconds,
3951
+ };
3952
+ }
3953
+ case "pending": {
3954
+ return {
3955
+ status: "pending",
3956
+ record: record,
3957
+ };
3958
+ }
3959
+ default: {
3960
+ return {
3961
+ status: "approved",
3962
+ record: record,
3963
+ };
3964
+ }
3965
+ }
3966
+ }, mapError)));
3967
+ },
3968
+ deleteExpired: (input) => {
3969
+ const mapError = (cause) => oauthDeviceAuthorizationStoreError("delete-expired", cause);
3970
+ return executeMapped(executor, () => Query.delete(authPostgresOAuthDeviceAuthorization).pipe(Query.where(lte(authPostgresOAuthDeviceAuthorization.expires_at, millisParam(input.beforeExpiresAt))), Query.returning({ id: authPostgresOAuthDeviceAuthorization.id })), mapError).pipe(Effect.map((rows) => rows.length));
3971
+ },
3972
+ });
3973
+ };
3974
+ export const makeEffectQbPostgresOAuthDeviceCodeTokenCommitStore = (sql) => {
3975
+ const executor = makeEffectQbPostgresExecutor(sql);
3976
+ const mapError = oauthDeviceCodeTokenCommitStoreError;
3977
+ return OAuthDeviceCodeTokenCommitStore.of({
3978
+ commit: (input) => sql
3979
+ .withTransaction(Effect.gen(function* () {
3980
+ const selected = yield* executeMapped(executor, () => selectForUpdate(oauthDeviceAuthorizationSelection, authPostgresOAuthDeviceAuthorization, eq(authPostgresOAuthDeviceAuthorization.id, input.authorization.id)), mapError);
3981
+ const existing = yield* decodeMapped(() => selected[0] === undefined
3982
+ ? undefined
3983
+ : decodeOAuthDeviceAuthorization(selected[0]), mapError);
3984
+ if (existing === undefined) {
3985
+ return { status: "missing" };
3986
+ }
3987
+ if (existing.status !== "approved") {
3988
+ return { status: "missing" };
3989
+ }
3990
+ if (existing.consumedAt !== undefined) {
3991
+ return {
3992
+ status: "already_consumed",
3993
+ record: existing,
3994
+ };
3995
+ }
3996
+ const expected = input.authorization;
3997
+ const sameArray = (left, right) => left.length === right.length &&
3998
+ left.every((value, index) => value === right[index]);
3999
+ const matchesApprovedSnapshot = existing.id === expected.id &&
4000
+ existing.deviceCodeHash === expected.deviceCodeHash &&
4001
+ existing.userCodeHash === expected.userCodeHash &&
4002
+ existing.clientId === expected.clientId &&
4003
+ sameArray(existing.requestedScopes, expected.requestedScopes) &&
4004
+ existing.subject === expected.subject &&
4005
+ sameArray(existing.grantedScopes, expected.grantedScopes) &&
4006
+ Number(existing.issuedAt) === Number(expected.issuedAt) &&
4007
+ Number(existing.expiresAt) === Number(expected.expiresAt) &&
4008
+ existing.pollIntervalSeconds === expected.pollIntervalSeconds &&
4009
+ Number(existing.nextPollAt) === Number(expected.nextPollAt) &&
4010
+ (existing.lastPolledAt === undefined
4011
+ ? expected.lastPolledAt === undefined
4012
+ : Number(existing.lastPolledAt) ===
4013
+ Number(expected.lastPolledAt)) &&
4014
+ Number(existing.approvedAt) === Number(expected.approvedAt) &&
4015
+ JSON.stringify(existing.metadata ?? null) ===
4016
+ JSON.stringify(expected.metadata ?? null);
4017
+ if (!matchesApprovedSnapshot) {
4018
+ return { status: "missing" };
4019
+ }
4020
+ if (Number(existing.expiresAt) <= Number(input.consumedAt)) {
4021
+ return {
4022
+ status: "expired",
4023
+ record: existing,
4024
+ };
4025
+ }
4026
+ yield* Effect.forEach(input.tokenRecords, (record) => executeMapped(executor, () => insert(authPostgresOAuthProviderModeToken, oauthProviderModeTokenValues(record)), mapError), { discard: true });
4027
+ const updated = yield* executeMapped(executor, () => update(authPostgresOAuthDeviceAuthorization, {
4028
+ consumed_at: millisParam(input.consumedAt),
4029
+ last_polled_at: millisParam(input.consumedAt),
4030
+ next_poll_at: millisParam(UnixMillis(Number(input.consumedAt) +
4031
+ existing.pollIntervalSeconds * 1000)),
4032
+ }).pipe(Query.where(eq(authPostgresOAuthDeviceAuthorization.id, input.authorization.id)), Query.where(eq(authPostgresOAuthDeviceAuthorization.status, "approved")), Query.where(isNull(authPostgresOAuthDeviceAuthorization.consumed_at)), Query.where(gt(authPostgresOAuthDeviceAuthorization.expires_at, millisParam(input.consumedAt))), Query.returning({
4033
+ ...oauthDeviceAuthorizationSelection,
4034
+ consumedAt: withoutNullRefinement(authPostgresOAuthDeviceAuthorization.consumed_at),
4035
+ })), mapError);
4036
+ return yield* decodeMapped(() => {
4037
+ const [row] = updated;
4038
+ if (row === undefined) {
4039
+ throw new Error("OAuth device authorization consume CAS failed");
4040
+ }
4041
+ return {
4042
+ status: "committed",
4043
+ record: decodeOAuthDeviceAuthorization(row),
4044
+ };
4045
+ }, mapError);
4046
+ }))
4047
+ .pipe(Effect.mapError((cause) => cause instanceof OAuthDeviceCodeTokenCommitStoreError
4048
+ ? cause
4049
+ : mapError(cause))),
4050
+ });
4051
+ };
4052
+ export const makeEffectQbPostgresOAuthClientSecretStore = (executor) => {
4053
+ const find = (input, operation = "find") => {
4054
+ const mapError = (cause) => oauthClientSecretStoreError(operation, cause);
4055
+ return executeMapped(executor, () => Query.select(oauthClientSecretSelection).pipe(Query.from(authPostgresOAuthClientSecret), Query.where(eq(authPostgresOAuthClientSecret.client_id, input.clientId)), Query.where(eq(authPostgresOAuthClientSecret.prefix, input.prefix))), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodeOAuthClientSecret), mapError)));
4056
+ };
4057
+ return OAuthClientSecretStore.of({
4058
+ upsert: (record) => {
4059
+ const mapError = (cause) => oauthClientSecretStoreError("upsert", cause);
4060
+ return executeMapped(executor, () => {
4061
+ const values = oauthClientSecretValues(record);
4062
+ return insert(authPostgresOAuthClientSecret, values).pipe(PostgresQuery.onConflict(["client_id", "prefix"], {
4063
+ update: {
4064
+ secret_hash: values.secret_hash,
4065
+ authentication_methods: values.authentication_methods,
4066
+ created_at: values.created_at,
4067
+ expires_at: values.expires_at,
4068
+ last_used_at: values.last_used_at,
4069
+ revoked_at: values.revoked_at,
4070
+ metadata: values.metadata,
4071
+ },
4072
+ }));
4073
+ }, mapError).pipe(Effect.asVoid);
4074
+ },
4075
+ findByClientIdAndPrefix: (input) => find(input),
4076
+ markUsed: (input) => {
4077
+ const mapError = (cause) => oauthClientSecretStoreError("mark-used", cause);
4078
+ return executeMapped(executor, () => update(authPostgresOAuthClientSecret, {
4079
+ last_used_at: millisParam(input.lastUsedAt),
4080
+ ...(input.metadata === undefined
4081
+ ? {}
4082
+ : { metadata: input.metadata }),
4083
+ }).pipe(Query.where(eq(authPostgresOAuthClientSecret.client_id, input.clientId)), Query.where(eq(authPostgresOAuthClientSecret.prefix, input.prefix)), Query.where(isNull(authPostgresOAuthClientSecret.revoked_at)), Query.returning(oauthClientSecretSelection)), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodeOAuthClientSecret), mapError)));
4084
+ },
4085
+ revoke: (input) => {
4086
+ const mapError = (cause) => oauthClientSecretStoreError("revoke", cause);
4087
+ return executeMapped(executor, () => update(authPostgresOAuthClientSecret, {
4088
+ revoked_at: millisParam(input.revokedAt),
4089
+ ...(input.reason === undefined
4090
+ ? {}
4091
+ : {
4092
+ metadata: metadataWithReason(authPostgresOAuthClientSecret.metadata, "revokeReason", input.reason),
4093
+ }),
4094
+ }).pipe(Query.where(eq(authPostgresOAuthClientSecret.client_id, input.clientId)), Query.where(eq(authPostgresOAuthClientSecret.prefix, input.prefix)), Query.returning(oauthClientSecretSelection)), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodeOAuthClientSecret), mapError)));
4095
+ },
4096
+ });
4097
+ };
4098
+ export const makeEffectQbPostgresOAuthProviderModeTokenStore = (executor) => {
4099
+ const find = (tokenHash, operation = "find") => {
4100
+ const mapError = (cause) => oauthProviderModeTokenStoreError(operation, cause);
4101
+ return executeMapped(executor, () => Query.select(oauthProviderModeTokenSelection).pipe(Query.from(authPostgresOAuthProviderModeToken), Query.where(eq(authPostgresOAuthProviderModeToken.token_hash, tokenHash))), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodeOAuthProviderModeToken), mapError)));
4102
+ };
4103
+ return OAuthProviderModeTokenStore.of({
4104
+ upsert: (record) => {
4105
+ const mapError = (cause) => oauthProviderModeTokenStoreError("upsert", cause);
4106
+ return executeMapped(executor, () => {
4107
+ const values = oauthProviderModeTokenValues(record);
4108
+ return insert(authPostgresOAuthProviderModeToken, values).pipe(PostgresQuery.onConflict("token_hash", {
4109
+ update: {
4110
+ token_type: values.token_type,
4111
+ client_id: values.client_id,
4112
+ subject: values.subject,
4113
+ scopes: values.scopes,
4114
+ issued_at: values.issued_at,
4115
+ expires_at: values.expires_at,
4116
+ issuer: values.issuer,
4117
+ audience: values.audience,
4118
+ jwt_id: values.jwt_id,
4119
+ revoked_at: values.revoked_at,
4120
+ revocation_reason: values.revocation_reason,
4121
+ rotated_at: values.rotated_at,
4122
+ replaced_by_token_hash: values.replaced_by_token_hash,
4123
+ metadata: values.metadata,
4124
+ },
4125
+ }));
4126
+ }, mapError).pipe(Effect.asVoid);
4127
+ },
4128
+ findByHash: (input) => find(input.tokenHash),
4129
+ revokeByHash: (input) => {
4130
+ const mapError = (cause) => oauthProviderModeTokenStoreError("revoke", cause);
4131
+ return executeMapped(executor, () => {
4132
+ let plan = update(authPostgresOAuthProviderModeToken, {
4133
+ revoked_at: Query.coalesce(authPostgresOAuthProviderModeToken.revoked_at, millisParam(input.revokedAt)),
4134
+ ...(input.reason === undefined
4135
+ ? {}
4136
+ : {
4137
+ revocation_reason: Query.coalesce(authPostgresOAuthProviderModeToken.revocation_reason, input.reason),
4138
+ }),
4139
+ }).pipe(Query.where(eq(authPostgresOAuthProviderModeToken.token_hash, input.tokenHash)));
4140
+ if (input.tokenTypeHint !== undefined) {
4141
+ plan = plan.pipe(Query.where(eq(authPostgresOAuthProviderModeToken.token_type, input.tokenTypeHint)));
4142
+ }
4143
+ return plan.pipe(Query.returning(oauthProviderModeTokenSelection));
4144
+ }, mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodeOAuthProviderModeToken), mapError)));
4145
+ },
4146
+ rotateRefreshToken: (input) => {
4147
+ const mapError = (cause) => oauthProviderModeTokenStoreError("rotate", cause);
4148
+ return executeMapped(executor, () => update(authPostgresOAuthProviderModeToken, {
4149
+ rotated_at: millisParam(input.rotatedAt),
4150
+ replaced_by_token_hash: input.replacedByTokenHash,
4151
+ }).pipe(Query.where(eq(authPostgresOAuthProviderModeToken.token_hash, input.tokenHash)), Query.where(eq(authPostgresOAuthProviderModeToken.token_type, "refresh_token")), Query.where(isNull(authPostgresOAuthProviderModeToken.revoked_at)), Query.where(isNull(authPostgresOAuthProviderModeToken.rotated_at)), Query.returning({
4152
+ ...oauthProviderModeTokenSelection,
4153
+ rotatedAt: withoutNullRefinement(authPostgresOAuthProviderModeToken.rotated_at),
4154
+ replacedByTokenHash: withoutNullRefinement(authPostgresOAuthProviderModeToken.replaced_by_token_hash),
4155
+ })), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodeOAuthProviderModeToken), mapError)));
4156
+ },
4157
+ deleteRetired: (input) => {
4158
+ const mapError = (cause) => oauthProviderModeTokenStoreError("deleteRetired", cause);
4159
+ return executeMapped(executor, () => {
4160
+ const predicates = [
4161
+ ...(input.beforeExpiresAt === undefined
4162
+ ? []
4163
+ : [
4164
+ lt(authPostgresOAuthProviderModeToken.expires_at, millisParam(input.beforeExpiresAt)),
4165
+ ]),
4166
+ ...(input.beforeRevokedAt === undefined
4167
+ ? []
4168
+ : [
4169
+ lt(authPostgresOAuthProviderModeToken.revoked_at, millisParam(input.beforeRevokedAt)),
4170
+ ]),
4171
+ ...(input.beforeRotatedAt === undefined
4172
+ ? []
4173
+ : [
4174
+ lt(authPostgresOAuthProviderModeToken.rotated_at, millisParam(input.beforeRotatedAt)),
4175
+ ]),
4176
+ ];
4177
+ return Query.delete(authPostgresOAuthProviderModeToken).pipe(Query.where(predicates.length === 1 ? predicates[0] : or(...predicates)), Query.returning({
4178
+ tokenHash: authPostgresOAuthProviderModeToken.token_hash,
4179
+ }));
4180
+ }, mapError).pipe(Effect.map((rows) => rows.length));
4181
+ },
4182
+ });
4183
+ };
4184
+ export const makeEffectQbPostgresOAuthProviderTokenVault = (executor) => {
4185
+ const findActive = (accountId, operation) => {
4186
+ const mapError = (cause) => oauthProviderTokenVaultError(operation, cause);
4187
+ return executeMapped(executor, () => Query.select(oauthProviderTokenVaultSelection).pipe(Query.from(authPostgresOAuthProviderTokenVault), Query.where(eq(authPostgresOAuthProviderTokenVault.account_id, accountId)), Query.where(isNull(authPostgresOAuthProviderTokenVault.revoked_at))), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodeOAuthProviderTokenVault), mapError)));
4188
+ };
4189
+ return OAuthProviderTokenVault.of({
4190
+ upsert: (record) => {
4191
+ // The executor error contains bound query parameters, including ciphertexts.
4192
+ const mapError = (_cause) => oauthProviderTokenVaultError("upsert", new Error("Postgres OAuth provider token vault upsert failed"));
4193
+ return executeMapped(executor, () => {
4194
+ const values = oauthProviderTokenVaultValues(record);
4195
+ return insert(authPostgresOAuthProviderTokenVault, values).pipe(PostgresQuery.onConflict("account_id", {
4196
+ update: {
4197
+ user_id: values.user_id,
4198
+ provider_id: values.provider_id,
4199
+ provider_account_id: values.provider_account_id,
4200
+ access_token_ciphertext: values.access_token_ciphertext,
4201
+ refresh_token_ciphertext: values.refresh_token_ciphertext,
4202
+ id_token_ciphertext: values.id_token_ciphertext,
4203
+ token_type: values.token_type,
4204
+ scopes: values.scopes,
4205
+ expires_at: values.expires_at,
4206
+ updated_at: values.updated_at,
4207
+ revoked_at: values.revoked_at,
4208
+ revocation_reason: values.revocation_reason,
4209
+ },
4210
+ }));
4211
+ }, mapError).pipe(Effect.asVoid);
4212
+ },
4213
+ refreshTokenForAccount: (input) => findActive(input.accountId, "refresh-token").pipe(Effect.map((record) => Option.isNone(record) ||
4214
+ record.value.refreshTokenCiphertext === undefined
4215
+ ? Option.none()
4216
+ : Option.some(record.value.refreshTokenCiphertext))),
4217
+ tokensForAccount: (input) => findActive(input.accountId, "tokens").pipe(Effect.map((record) => Option.isNone(record)
4218
+ ? Option.none()
4219
+ : Option.some(providerTokenVaultTokens(record.value)))),
4220
+ markRevoked: (input) => {
4221
+ const mapError = (cause) => oauthProviderTokenVaultError("mark-revoked", cause);
4222
+ return executeMapped(executor, () => update(authPostgresOAuthProviderTokenVault, {
4223
+ revoked_at: millisParam(input.revokedAt),
4224
+ revocation_reason: input.reason,
4225
+ }).pipe(Query.where(eq(authPostgresOAuthProviderTokenVault.account_id, input.accountId)), Query.returning(oauthProviderTokenVaultSelection)), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodeOAuthProviderTokenVault), mapError)));
4226
+ },
4227
+ });
4228
+ };
4229
+ const permissionScopeKey = (scope) => [
4230
+ scope?.type ?? "global",
4231
+ scope?.id !== undefined,
4232
+ scope?.id ?? "",
4233
+ ];
4234
+ const comparePermissionText = (left, right) => left === right
4235
+ ? 0
4236
+ : left === undefined
4237
+ ? -1
4238
+ : right === undefined
4239
+ ? 1
4240
+ : left < right
4241
+ ? -1
4242
+ : 1;
4243
+ const comparePermissionScopes = (left, right) => {
4244
+ if (left === undefined || right === undefined) {
4245
+ return left === right ? 0 : left === undefined ? -1 : 1;
4246
+ }
4247
+ return (comparePermissionText(left.type, right.type) ||
4248
+ comparePermissionText(left.id, right.id));
4249
+ };
4250
+ const permissionScopesMatchExactly = (left, right) => {
4251
+ const leftKey = permissionScopeKey(left);
4252
+ const rightKey = permissionScopeKey(right);
4253
+ return leftKey.every((value, index) => value === rightKey[index]);
4254
+ };
4255
+ const permissionGrantIsActive = (grant, at) => grant.revokedAt === undefined &&
4256
+ (grant.expiresAt === undefined || Number(grant.expiresAt) > Number(at));
4257
+ const comparePermissionGrants = (left, right) => comparePermissionText(left.subject.type, right.subject.type) ||
4258
+ comparePermissionText(left.subject.id, right.subject.id) ||
4259
+ comparePermissionText(left.permission, right.permission) ||
4260
+ comparePermissionScopes(left.scope, right.scope);
4261
+ const compareRoleGrants = (left, right) => comparePermissionText(left.subject.type, right.subject.type) ||
4262
+ comparePermissionText(left.subject.id, right.subject.id) ||
4263
+ comparePermissionText(left.role, right.role) ||
4264
+ comparePermissionScopes(left.scope, right.scope);
4265
+ const compareRolePermissions = (left, right) => comparePermissionText(left.role, right.role) ||
4266
+ comparePermissionText(left.permission, right.permission) ||
4267
+ comparePermissionText(left.scopeType, right.scopeType);
4268
+ export const makeEffectQbPostgresPermissionStore = (executor) => {
4269
+ const findPermissionDefinition = (id, operation = "find_permission_definition") => {
4270
+ const mapError = (cause) => permissionStoreError(operation, cause);
4271
+ return executeMapped(executor, () => Query.select(permissionDefinitionSelection).pipe(Query.from(authPostgresPermissionDefinition), Query.where(eq(authPostgresPermissionDefinition.id, id))), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodePermissionDefinition), mapError)));
4272
+ };
4273
+ const findRoleDefinition = (id, operation = "find_role_definition") => {
4274
+ const mapError = (cause) => permissionStoreError(operation, cause);
4275
+ return executeMapped(executor, () => Query.select(roleDefinitionSelection).pipe(Query.from(authPostgresRoleDefinition), Query.where(eq(authPostgresRoleDefinition.id, id))), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodeRoleDefinition), mapError)));
4276
+ };
4277
+ const mutatePermissionDefinition = (operation, input, makeValues) => {
4278
+ const mapError = (cause) => permissionStoreError(operation, cause);
4279
+ const returning = operation === "delete_permission_definition"
4280
+ ? {
4281
+ ...permissionDefinitionSelection,
4282
+ deletedAt: withoutNullRefinement(authPostgresPermissionDefinition.deleted_at),
4283
+ }
4284
+ : permissionDefinitionSelection;
4285
+ return executeMapped(executor, () => update(authPostgresPermissionDefinition, makeValues()).pipe(Query.where(eq(authPostgresPermissionDefinition.id, input.id)), Query.where(eq(authPostgresPermissionDefinition.updated_at, millisParam(input.expectedUpdatedAt))), Query.where(isNull(authPostgresPermissionDefinition.deleted_at)), Query.returning(returning)), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodePermissionDefinition), mapError)));
4286
+ };
4287
+ const mutateRoleDefinition = (operation, input, makeValues) => {
4288
+ const mapError = (cause) => permissionStoreError(operation, cause);
4289
+ const returning = operation === "delete_role_definition"
4290
+ ? {
4291
+ ...roleDefinitionSelection,
4292
+ deletedAt: withoutNullRefinement(authPostgresRoleDefinition.deleted_at),
4293
+ }
4294
+ : roleDefinitionSelection;
4295
+ return executeMapped(executor, () => update(authPostgresRoleDefinition, makeValues()).pipe(Query.where(eq(authPostgresRoleDefinition.id, input.id)), Query.where(eq(authPostgresRoleDefinition.updated_at, millisParam(input.expectedUpdatedAt))), Query.where(isNull(authPostgresRoleDefinition.deleted_at)), Query.returning(returning)), mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => firstOption(rows, decodeRoleDefinition), mapError)));
4296
+ };
4297
+ const checkResult = (operation, makeAllowed) => {
4298
+ const mapError = (cause) => permissionStoreError(operation, cause);
4299
+ return executeMapped(executor, () => Query.select({ allowed: makeAllowed() }), mapError).pipe(Effect.map((rows) => Boolean(rows[0]?.allowed)));
4300
+ };
4301
+ return PermissionStore.of({
4302
+ createPermissionDefinition: (definition) => {
4303
+ const mapError = (cause) => permissionStoreError("create_permission_definition", cause);
4304
+ return executeMapped(executor, () => insert(authPostgresPermissionDefinition, permissionDefinitionValues(definition)).pipe(PostgresQuery.onConflict("id"), Query.returning(permissionDefinitionSelection)), mapError).pipe(Effect.map((rows) => rows.length > 0));
4305
+ },
4306
+ findPermissionDefinition: (id) => findPermissionDefinition(id),
4307
+ listPermissionDefinitions: (input = {}) => {
4308
+ const mapError = (cause) => permissionStoreError("list_permission_definitions", cause);
4309
+ return executeMapped(executor, () => {
4310
+ let plan = Query.select(permissionDefinitionSelection).pipe(Query.from(authPostgresPermissionDefinition));
4311
+ if (input.includeDisabled !== true) {
4312
+ plan = plan.pipe(Query.where(isNull(authPostgresPermissionDefinition.disabled_at)));
4313
+ }
4314
+ if (input.includeDeleted !== true) {
4315
+ plan = plan.pipe(Query.where(isNull(authPostgresPermissionDefinition.deleted_at)));
4316
+ }
4317
+ if (input.after !== undefined) {
4318
+ plan = plan.pipe(Query.where(gt(Query.collate(authPostgresPermissionDefinition.id, "C"), input.after)));
4319
+ }
4320
+ return plan.pipe(Query.orderBy(Query.collate(authPostgresPermissionDefinition.id, "C"), "asc"), Query.limit(normalizePermissionDefinitionListLimit(input.limit)));
4321
+ }, mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => rows.map(decodePermissionDefinition), mapError)));
4322
+ },
4323
+ updatePermissionDefinition: (input) => mutatePermissionDefinition("update_permission_definition", input, () => ({
4324
+ ...(input.description === undefined
4325
+ ? {}
4326
+ : { description: input.description }),
4327
+ ...(input.scopeType === undefined
4328
+ ? {}
4329
+ : {
4330
+ scope_type_present: input.scopeType !== null,
4331
+ scope_type: input.scopeType ?? "",
4332
+ }),
4333
+ updated_at: millisParam(input.updatedAt),
4334
+ })),
4335
+ setPermissionDefinitionDisabled: (input) => mutatePermissionDefinition("set_permission_definition_disabled", input, () => ({
4336
+ disabled_at: input.disabledAt === undefined
4337
+ ? null
4338
+ : millisParam(input.disabledAt),
4339
+ updated_at: millisParam(input.updatedAt),
4340
+ })),
4341
+ deletePermissionDefinition: (input) => mutatePermissionDefinition("delete_permission_definition", input, () => ({
4342
+ deleted_at: millisParam(input.deletedAt),
4343
+ updated_at: millisParam(input.updatedAt),
4344
+ })),
4345
+ createRoleDefinition: (definition) => {
4346
+ const mapError = (cause) => permissionStoreError("create_role_definition", cause);
4347
+ return executeMapped(executor, () => insert(authPostgresRoleDefinition, roleDefinitionValues(definition)).pipe(PostgresQuery.onConflict("id"), Query.returning(roleDefinitionSelection)), mapError).pipe(Effect.map((rows) => rows.length > 0));
4348
+ },
4349
+ findRoleDefinition: (id) => findRoleDefinition(id),
4350
+ listRoleDefinitions: (input = {}) => {
4351
+ const mapError = (cause) => permissionStoreError("list_role_definitions", cause);
4352
+ return executeMapped(executor, () => {
4353
+ let plan = Query.select(roleDefinitionSelection).pipe(Query.from(authPostgresRoleDefinition));
4354
+ if (input.includeDisabled !== true) {
4355
+ plan = plan.pipe(Query.where(isNull(authPostgresRoleDefinition.disabled_at)));
4356
+ }
4357
+ if (input.includeDeleted !== true) {
4358
+ plan = plan.pipe(Query.where(isNull(authPostgresRoleDefinition.deleted_at)));
4359
+ }
4360
+ return plan;
4361
+ }, mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => rows
4362
+ .map(decodeRoleDefinition)
4363
+ .sort((left, right) => comparePermissionText(left.id, right.id)), mapError)));
4364
+ },
4365
+ updateRoleDefinition: (input) => mutateRoleDefinition("update_role_definition", input, () => ({
4366
+ ...(input.description === undefined
4367
+ ? {}
4368
+ : { description: input.description }),
4369
+ updated_at: millisParam(input.updatedAt),
4370
+ })),
4371
+ setRoleDefinitionDisabled: (input) => mutateRoleDefinition("set_role_definition_disabled", input, () => ({
4372
+ disabled_at: input.disabledAt === undefined ? null : millisParam(input.disabledAt),
4373
+ updated_at: millisParam(input.updatedAt),
4374
+ })),
4375
+ deleteRoleDefinition: (input) => mutateRoleDefinition("delete_role_definition", input, () => ({
4376
+ deleted_at: millisParam(input.deletedAt),
4377
+ updated_at: millisParam(input.updatedAt),
4378
+ })),
4379
+ grantPermission: (input) => {
4380
+ const mapError = (cause) => permissionStoreError("grant_permission", cause);
4381
+ return executeMapped(executor, () => {
4382
+ const scope = canonicalPermissionScope(input.scope);
4383
+ const values = permissionGrantValues({
4384
+ ...input,
4385
+ ...(scope === undefined ? { scope: undefined } : { scope }),
4386
+ });
4387
+ return insert(authPostgresPermissionGrant, values).pipe(PostgresQuery.onConflict([
4388
+ "subject_type",
4389
+ "subject_id",
4390
+ "permission_id",
4391
+ "scope_type",
4392
+ "scope_id_present",
4393
+ "scope_id",
4394
+ ], {
4395
+ update: {
4396
+ expires_at: values.expires_at,
4397
+ metadata: values.metadata,
4398
+ revoked_at: null,
4399
+ },
4400
+ }));
4401
+ }, mapError).pipe(Effect.asVoid);
4402
+ },
4403
+ revokePermission: (input) => {
4404
+ const mapError = (cause) => permissionStoreError("revoke_permission", cause);
4405
+ return executeMapped(executor, () => {
4406
+ const [scopeType, scopeIdPresent, requestedScopeId] = permissionScopeKey(canonicalPermissionScope(input.scope));
4407
+ return update(authPostgresPermissionGrant, {
4408
+ revoked_at: millisParam(input.revokedAt ?? UnixMillis(Date.now())),
4409
+ }).pipe(Query.where(eq(authPostgresPermissionGrant.subject_type, input.subject.type)), Query.where(eq(authPostgresPermissionGrant.subject_id, input.subject.id)), Query.where(eq(authPostgresPermissionGrant.permission_id, input.permission)), Query.where(eq(authPostgresPermissionGrant.scope_type, scopeType)), Query.where(eq(authPostgresPermissionGrant.scope_id_present, scopeIdPresent)), Query.where(eq(authPostgresPermissionGrant.scope_id, requestedScopeId)));
4410
+ }, mapError).pipe(Effect.asVoid);
4411
+ },
4412
+ listPermissionGrants: (input = {}) => Effect.suspend(() => {
4413
+ const mapError = (cause) => permissionStoreError("list_permission_grants", cause);
4414
+ const at = input.at ?? UnixMillis(Date.now());
4415
+ const activity = input.activity ?? "active";
4416
+ return executeMapped(executor, () => {
4417
+ let plan = Query.select(permissionGrantSelection).pipe(Query.from(authPostgresPermissionGrant));
4418
+ if (input.subject !== undefined) {
4419
+ plan = plan.pipe(Query.where(eq(authPostgresPermissionGrant.subject_type, input.subject.type)), Query.where(eq(authPostgresPermissionGrant.subject_id, input.subject.id)));
4420
+ }
4421
+ if (input.permission !== undefined) {
4422
+ plan = plan.pipe(Query.where(eq(authPostgresPermissionGrant.permission_id, input.permission)));
4423
+ }
4424
+ if (input.scope !== undefined) {
4425
+ const [scopeType, scopeIdPresent, requestedScopeId] = permissionScopeKey(canonicalPermissionScope(input.scope));
4426
+ plan = plan.pipe(Query.where(eq(authPostgresPermissionGrant.scope_type, scopeType)), Query.where(eq(authPostgresPermissionGrant.scope_id_present, scopeIdPresent)), Query.where(eq(authPostgresPermissionGrant.scope_id, requestedScopeId)));
4427
+ }
4428
+ return plan;
4429
+ }, mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => rows
4430
+ .map(decodePermissionGrant)
4431
+ .filter((grant) => (input.scope === undefined ||
4432
+ permissionScopesMatchExactly(grant.scope, input.scope)) &&
4433
+ (activity === "all" ||
4434
+ permissionGrantIsActive(grant, at) ===
4435
+ (activity === "active")))
4436
+ .sort(comparePermissionGrants), mapError)));
4437
+ }),
4438
+ grantRole: (input) => {
4439
+ const mapError = (cause) => permissionStoreError("grant_role", cause);
4440
+ return executeMapped(executor, () => {
4441
+ const scope = canonicalPermissionScope(input.scope);
4442
+ const values = roleGrantValues({
4443
+ ...input,
4444
+ ...(scope === undefined ? { scope: undefined } : { scope }),
4445
+ });
4446
+ return insert(authPostgresRoleGrant, values).pipe(PostgresQuery.onConflict([
4447
+ "subject_type",
4448
+ "subject_id",
4449
+ "role_id",
4450
+ "scope_type",
4451
+ "scope_id_present",
4452
+ "scope_id",
4453
+ ], {
4454
+ update: {
4455
+ expires_at: values.expires_at,
4456
+ metadata: values.metadata,
4457
+ revoked_at: null,
4458
+ },
4459
+ }));
4460
+ }, mapError).pipe(Effect.asVoid);
4461
+ },
4462
+ revokeRole: (input) => {
4463
+ const mapError = (cause) => permissionStoreError("revoke_role", cause);
4464
+ return executeMapped(executor, () => {
4465
+ const [scopeType, scopeIdPresent, requestedScopeId] = permissionScopeKey(canonicalPermissionScope(input.scope));
4466
+ return update(authPostgresRoleGrant, {
4467
+ revoked_at: millisParam(input.revokedAt ?? UnixMillis(Date.now())),
4468
+ }).pipe(Query.where(eq(authPostgresRoleGrant.subject_type, input.subject.type)), Query.where(eq(authPostgresRoleGrant.subject_id, input.subject.id)), Query.where(eq(authPostgresRoleGrant.role_id, input.role)), Query.where(eq(authPostgresRoleGrant.scope_type, scopeType)), Query.where(eq(authPostgresRoleGrant.scope_id_present, scopeIdPresent)), Query.where(eq(authPostgresRoleGrant.scope_id, requestedScopeId)));
4469
+ }, mapError).pipe(Effect.asVoid);
4470
+ },
4471
+ listRoleGrants: (input = {}) => Effect.suspend(() => {
4472
+ const mapError = (cause) => permissionStoreError("list_role_grants", cause);
4473
+ const at = input.at ?? UnixMillis(Date.now());
4474
+ const activity = input.activity ?? "active";
4475
+ return executeMapped(executor, () => {
4476
+ let plan = Query.select(roleGrantSelection).pipe(Query.from(authPostgresRoleGrant));
4477
+ if (input.subject !== undefined) {
4478
+ plan = plan.pipe(Query.where(eq(authPostgresRoleGrant.subject_type, input.subject.type)), Query.where(eq(authPostgresRoleGrant.subject_id, input.subject.id)));
4479
+ }
4480
+ if (input.role !== undefined) {
4481
+ plan = plan.pipe(Query.where(eq(authPostgresRoleGrant.role_id, input.role)));
4482
+ }
4483
+ if (input.scope !== undefined) {
4484
+ const [scopeType, scopeIdPresent, requestedScopeId] = permissionScopeKey(canonicalPermissionScope(input.scope));
4485
+ plan = plan.pipe(Query.where(eq(authPostgresRoleGrant.scope_type, scopeType)), Query.where(eq(authPostgresRoleGrant.scope_id_present, scopeIdPresent)), Query.where(eq(authPostgresRoleGrant.scope_id, requestedScopeId)));
4486
+ }
4487
+ return plan;
4488
+ }, mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => rows
4489
+ .map(decodeRoleGrant)
4490
+ .filter((grant) => (input.scope === undefined ||
4491
+ permissionScopesMatchExactly(grant.scope, input.scope)) &&
4492
+ (activity === "all" ||
4493
+ permissionGrantIsActive(grant, at) ===
4494
+ (activity === "active")))
4495
+ .sort(compareRoleGrants), mapError)));
4496
+ }),
4497
+ assignRolePermission: (input) => {
4498
+ const mapError = (cause) => permissionStoreError("assign_role_permission", cause);
4499
+ return executeMapped(executor, () => insert(authPostgresRolePermission, rolePermissionValues(input)).pipe(PostgresQuery.onConflict([
4500
+ "role_id",
4501
+ "permission_id",
4502
+ "scope_type_present",
4503
+ "scope_type",
4504
+ ])), mapError).pipe(Effect.asVoid);
4505
+ },
4506
+ removeRolePermission: (input) => {
4507
+ const mapError = (cause) => permissionStoreError("remove_role_permission", cause);
4508
+ return executeMapped(executor, () => Query.delete(authPostgresRolePermission).pipe(Query.where(eq(authPostgresRolePermission.role_id, input.role)), Query.where(eq(authPostgresRolePermission.permission_id, input.permission)), Query.where(eq(authPostgresRolePermission.scope_type_present, input.scopeType !== undefined)), Query.where(eq(authPostgresRolePermission.scope_type, input.scopeType ?? ""))), mapError).pipe(Effect.asVoid);
4509
+ },
4510
+ listRolePermissions: (input = {}) => {
4511
+ const mapError = (cause) => permissionStoreError("list_role_permissions", cause);
4512
+ return executeMapped(executor, () => {
4513
+ let plan = Query.select(rolePermissionSelection).pipe(Query.from(authPostgresRolePermission));
4514
+ if (input.role !== undefined) {
4515
+ plan = plan.pipe(Query.where(eq(authPostgresRolePermission.role_id, input.role)));
4516
+ }
4517
+ if (input.permission !== undefined) {
4518
+ plan = plan.pipe(Query.where(eq(authPostgresRolePermission.permission_id, input.permission)));
4519
+ }
4520
+ if (input.scopeType !== undefined) {
4521
+ plan = plan.pipe(Query.where(eq(authPostgresRolePermission.scope_type_present, input.scopeType !== null)));
4522
+ if (input.scopeType !== null) {
4523
+ plan = plan.pipe(Query.where(eq(authPostgresRolePermission.scope_type, input.scopeType)));
4524
+ }
4525
+ }
4526
+ return plan;
4527
+ }, mapError).pipe(Effect.flatMap((rows) => decodeMapped(() => rows.map(decodeRolePermission).sort(compareRolePermissions), mapError)));
4528
+ },
4529
+ hasPermission: (input) => checkResult("has_permission", () => {
4530
+ const now = millisParam(UnixMillis(Date.now()));
4531
+ const [scopeType, scopeIdPresent, requestedScopeId] = permissionScopeKey(canonicalPermissionScope(input.scope));
4532
+ const direct = exists(Query.select({ value: Query.literal(1) }).pipe(Query.from(authPostgresPermissionGrant), Query.where(eq(authPostgresPermissionGrant.subject_type, input.subject.type)), Query.where(eq(authPostgresPermissionGrant.subject_id, input.subject.id)), Query.where(eq(authPostgresPermissionGrant.permission_id, input.permission)), Query.where(isNull(authPostgresPermissionGrant.revoked_at)), Query.where(or(isNull(authPostgresPermissionGrant.expires_at), gt(authPostgresPermissionGrant.expires_at, now))), Query.where(or(and(eq(authPostgresPermissionGrant.scope_type, "global"), eq(authPostgresPermissionGrant.scope_id_present, false)), and(eq(authPostgresPermissionGrant.scope_type, scopeType), eq(authPostgresPermissionGrant.scope_id_present, scopeIdPresent), eq(authPostgresPermissionGrant.scope_id, requestedScopeId))))));
4533
+ const rolePermission = exists(Query.select({ value: Query.literal(1) }).pipe(Query.from(authPostgresRolePermission), Query.where(eq(authPostgresRolePermission.role_id, authPostgresRoleGrant.role_id)), Query.where(eq(authPostgresRolePermission.permission_id, input.permission)), Query.where(or(eq(authPostgresRolePermission.scope_type_present, false), and(eq(authPostgresRolePermission.scope_type_present, true), eq(authPostgresRolePermission.scope_type, scopeType))))));
4534
+ const role = exists(Query.select({ value: Query.literal(1) }).pipe(Query.from(authPostgresRoleGrant), Query.where(eq(authPostgresRoleGrant.subject_type, input.subject.type)), Query.where(eq(authPostgresRoleGrant.subject_id, input.subject.id)), Query.where(isNull(authPostgresRoleGrant.revoked_at)), Query.where(or(isNull(authPostgresRoleGrant.expires_at), gt(authPostgresRoleGrant.expires_at, now))), Query.where(or(and(eq(authPostgresRoleGrant.scope_type, "global"), eq(authPostgresRoleGrant.scope_id_present, false)), and(eq(authPostgresRoleGrant.scope_type, scopeType), eq(authPostgresRoleGrant.scope_id_present, scopeIdPresent), eq(authPostgresRoleGrant.scope_id, requestedScopeId)))), Query.where(rolePermission)));
4535
+ return or(direct, role);
4536
+ }),
4537
+ hasRole: (input) => checkResult("has_role", () => {
4538
+ const now = millisParam(UnixMillis(Date.now()));
4539
+ const [scopeType, scopeIdPresent, requestedScopeId] = permissionScopeKey(canonicalPermissionScope(input.scope));
4540
+ return exists(Query.select({ value: Query.literal(1) }).pipe(Query.from(authPostgresRoleGrant), Query.where(eq(authPostgresRoleGrant.subject_type, input.subject.type)), Query.where(eq(authPostgresRoleGrant.subject_id, input.subject.id)), Query.where(eq(authPostgresRoleGrant.role_id, input.role)), Query.where(isNull(authPostgresRoleGrant.revoked_at)), Query.where(or(isNull(authPostgresRoleGrant.expires_at), gt(authPostgresRoleGrant.expires_at, now))), Query.where(or(and(eq(authPostgresRoleGrant.scope_type, "global"), eq(authPostgresRoleGrant.scope_id_present, false)), and(eq(authPostgresRoleGrant.scope_type, scopeType), eq(authPostgresRoleGrant.scope_id_present, scopeIdPresent), eq(authPostgresRoleGrant.scope_id, requestedScopeId))))));
4541
+ }),
4542
+ });
4543
+ };
4544
+ const oauthBridgeReasonByConstraint = {
4545
+ auth_user_pkey: "user-id",
4546
+ auth_user_identity_pkey: "identity-id",
4547
+ auth_user_identity_active_value_idx: "identity-value",
4548
+ auth_oauth_account_pkey: "oauth-account-id",
4549
+ auth_oauth_account_provider_account_key: "provider-account",
4550
+ };
4551
+ export const makeEffectQbPostgresOAuthIdentityBridgeStore = (sql) => {
4552
+ const executor = makeEffectQbPostgresExecutor(sql);
4553
+ return OAuthIdentityBridgeStore.of({
4554
+ create: (input) => {
4555
+ if (input.account.userId !== input.user.id ||
4556
+ (input.identity !== undefined &&
4557
+ input.identity.userId !== input.user.id)) {
4558
+ return Effect.fail(new OAuthIdentityBridgeConflictError({ reason: "user-id" }));
4559
+ }
4560
+ return sql
4561
+ .withTransaction(Effect.gen(function* () {
4562
+ const userRows = yield* execute(executor, insert(authPostgresUser, userValues(input.user)).pipe(Query.returning(userSelection)));
4563
+ let identity;
4564
+ if (input.identity !== undefined) {
4565
+ const row = input.identity;
4566
+ const identityRows = yield* execute(executor, insert(authPostgresUserIdentity, identityValues(row)).pipe(Query.returning(identitySelection)));
4567
+ identity = decodeIdentity(identityRows[0]);
4568
+ }
4569
+ const { account } = input;
4570
+ const accountRows = yield* execute(executor, insert(authPostgresOAuthAccount, oauthAccountValues(account)).pipe(Query.returning(oauthAccountSelection)));
4571
+ return {
4572
+ user: decodeUser(userRows[0]),
4573
+ ...(identity === undefined ? {} : { identity }),
4574
+ account: decodeOAuthAccount(accountRows[0]),
4575
+ };
4576
+ }))
4577
+ .pipe(Effect.mapError((cause) => {
4578
+ const details = postgresErrorDetails(cause);
4579
+ const reason = details.code === "23505" && details.constraintName !== undefined
4580
+ ? oauthBridgeReasonByConstraint[details.constraintName]
4581
+ : undefined;
4582
+ return reason === undefined
4583
+ ? new OAuthIdentityBridgeStoreError({
4584
+ message: "Atomic OAuth identity creation failed",
4585
+ cause,
4586
+ })
4587
+ : new OAuthIdentityBridgeConflictError({ reason });
4588
+ }));
4589
+ },
4590
+ });
4591
+ };
4592
+ export const makeEffectQbPostgresCoreStores = (sql, options = {}) => {
4593
+ const executor = makeEffectQbPostgresExecutor(sql);
4594
+ const atomic = makeEffectQbPostgresAtomicPlanExecutor(sql);
4595
+ return {
4596
+ userStore: makeEffectQbPostgresUserStore(executor),
4597
+ identityStore: makeEffectQbPostgresIdentityStore(executor, sql),
4598
+ registrationStore: makeEffectQbPostgresRegistrationStore(atomic),
4599
+ credentialStore: makeEffectQbPostgresCredentialStore(executor),
4600
+ passkeyCredentialStore: makeEffectQbPostgresPasskeyCredentialStore(executor),
4601
+ sessionStore: makeEffectQbPostgresSessionStore(executor),
4602
+ verificationStore: makeEffectQbPostgresVerificationStore(executor, sql),
4603
+ auditLogStore: makeEffectQbPostgresAuditLogStore(executor, sql),
4604
+ loginApprovalReviewStore: makeEffectQbPostgresLoginApprovalReviewStore(executor),
4605
+ loginRiskHistoryStore: makeEffectQbPostgresLoginRiskHistoryStore(executor, options.loginRiskHistory),
4606
+ trustedDeviceStore: makeEffectQbPostgresTrustedDeviceStore(executor),
4607
+ domainVerificationStore: makeEffectQbPostgresDomainVerificationStore(executor),
4608
+ securityTimelineStore: makeEffectQbPostgresSecurityTimelineStore(executor),
4609
+ webhookOutboxStore: makeEffectQbPostgresWebhookOutboxStore(executor, sql),
4610
+ webhookReplayStore: makeEffectQbPostgresWebhookReplayStore(executor),
4611
+ totpFactorStore: makeEffectQbPostgresTotpFactorStore(executor),
4612
+ totpSessionRotateStore: makeEffectQbPostgresTotpSessionRotateStore(sql),
4613
+ totpLoginCommitStore: makeEffectQbPostgresTotpLoginCommitStore(sql),
4614
+ recoveryCodeStore: makeEffectQbPostgresRecoveryCodeStore(executor, sql),
4615
+ recoveryCodeSessionRotateStore: makeEffectQbPostgresRecoveryCodeSessionRotateStore(sql),
4616
+ recoveryCodeLoginCommitStore: makeEffectQbPostgresRecoveryCodeLoginCommitStore(sql),
4617
+ apiKeyStore: makeEffectQbPostgresApiKeyStore(executor),
4618
+ refreshTokenStore: makeEffectQbPostgresRefreshTokenStore(executor, sql),
4619
+ jwtRevocationStore: makeEffectQbPostgresJwtRevocationStore(executor),
4620
+ oauthAccountStore: makeEffectQbPostgresOAuthAccountStore(executor, sql),
4621
+ oauthIdentityBridgeStore: makeEffectQbPostgresOAuthIdentityBridgeStore(sql),
4622
+ oauthClientStore: makeEffectQbPostgresOAuthClientStore(executor),
4623
+ oauthConsentStore: makeEffectQbPostgresOAuthConsentStore(executor),
4624
+ oauthAuthorizationCodeStore: makeEffectQbPostgresOAuthAuthorizationCodeStore(executor, sql),
4625
+ oauthDeviceAuthorizationStore: makeEffectQbPostgresOAuthDeviceAuthorizationStore(executor, sql),
4626
+ oauthDeviceCodeTokenCommitStore: makeEffectQbPostgresOAuthDeviceCodeTokenCommitStore(sql),
4627
+ oauthClientSecretStore: makeEffectQbPostgresOAuthClientSecretStore(executor),
4628
+ oauthProviderModeTokenStore: makeEffectQbPostgresOAuthProviderModeTokenStore(executor),
4629
+ oauthProviderTokenVault: makeEffectQbPostgresOAuthProviderTokenVault(executor),
4630
+ permissionStore: makeEffectQbPostgresPermissionStore(executor),
4631
+ };
4632
+ };
4633
+ export const EffectQbPostgresCoreStoresLive = (sql, options = {}) => {
4634
+ const stores = makeEffectQbPostgresCoreStores(sql, options);
4635
+ return Layer.mergeAll(Layer.succeed(UserStore)(stores.userStore), Layer.succeed(IdentityStore)(stores.identityStore), Layer.succeed(RegistrationStore)(stores.registrationStore), Layer.succeed(CredentialStore)(stores.credentialStore), Layer.succeed(PasskeyCredentialStore)(stores.passkeyCredentialStore), Layer.succeed(SessionStore)(stores.sessionStore), Layer.succeed(VerificationStore)(stores.verificationStore), Layer.succeed(AuditLogStore)(stores.auditLogStore), Layer.succeed(LoginApprovalReviewStore)(stores.loginApprovalReviewStore), Layer.succeed(LoginRiskHistory)(stores.loginRiskHistoryStore), Layer.succeed(TrustedDeviceStore)(stores.trustedDeviceStore), Layer.succeed(DomainVerificationStore)(stores.domainVerificationStore), Layer.succeed(SecurityTimelineStore)(stores.securityTimelineStore), Layer.succeed(WebhookOutboxStore)(stores.webhookOutboxStore), Layer.succeed(WebhookReplayStore)(stores.webhookReplayStore), Layer.succeed(TotpFactorStore)(stores.totpFactorStore), Layer.succeed(TotpSessionRotateStore)(stores.totpSessionRotateStore), Layer.succeed(TotpLoginCommitStore)(stores.totpLoginCommitStore), Layer.succeed(RecoveryCodeStore)(stores.recoveryCodeStore), Layer.succeed(RecoveryCodeSessionRotateStore)(stores.recoveryCodeSessionRotateStore), Layer.succeed(RecoveryCodeLoginCommitStore)(stores.recoveryCodeLoginCommitStore), Layer.succeed(ApiKeyStore)(stores.apiKeyStore), Layer.succeed(RefreshTokenStore)(stores.refreshTokenStore), Layer.succeed(JwtRevocationStore)(stores.jwtRevocationStore), Layer.succeed(OAuthAccountStore)(stores.oauthAccountStore), Layer.succeed(OAuthIdentityBridgeStore)(stores.oauthIdentityBridgeStore), Layer.succeed(OAuthClientStore)(stores.oauthClientStore), Layer.succeed(OAuthConsentStore)(stores.oauthConsentStore), Layer.succeed(OAuthAuthorizationCodeStore)(stores.oauthAuthorizationCodeStore), Layer.succeed(OAuthDeviceAuthorizationStore)(stores.oauthDeviceAuthorizationStore), Layer.succeed(OAuthDeviceCodeTokenCommitStore)(stores.oauthDeviceCodeTokenCommitStore), Layer.succeed(OAuthClientSecretStore)(stores.oauthClientSecretStore), Layer.succeed(OAuthProviderModeTokenStore)(stores.oauthProviderModeTokenStore), Layer.succeed(OAuthProviderTokenVault)(stores.oauthProviderTokenVault), Layer.succeed(PermissionStore)(stores.permissionStore));
4636
+ };
4637
+ //# sourceMappingURL=EffectQbPostgresStorage.js.map