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

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