@yielded/auth-persistence 0.1.0-beta.24 → 0.1.0-beta.26

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 (481) hide show
  1. package/README.md +6 -8
  2. package/dist/Adapter.d.mts +47 -33
  3. package/dist/Adapter.mjs +36 -23
  4. package/dist/OAuthPersistence.d.mts +35 -51
  5. package/dist/OAuthPersistence.mjs +60 -68
  6. package/dist/OAuthPersistence.mjs.map +1 -1
  7. package/dist/index.d.mts +2 -2
  8. package/dist/index.mjs +2 -2
  9. package/dist/internal/browser-login.d.mts +1 -1
  10. package/dist/internal/browser-login.mjs +29 -9
  11. package/dist/internal/browser-login.mjs.map +1 -1
  12. package/dist/internal/configuration.d.mts +13 -8
  13. package/dist/internal/configuration.mjs.map +1 -1
  14. package/dist/internal/crypto.d.mts +1 -0
  15. package/dist/internal/crypto.mjs +1 -1
  16. package/dist/internal/d1-planning.mjs +8 -0
  17. package/dist/internal/d1-planning.mjs.map +1 -0
  18. package/dist/internal/email-native-state.mjs +135 -0
  19. package/dist/internal/email-native-state.mjs.map +1 -0
  20. package/dist/internal/email-native.d.mts +17 -0
  21. package/dist/internal/email-native.mjs +245 -0
  22. package/dist/internal/email-native.mjs.map +1 -0
  23. package/dist/internal/email-policy.mjs +92 -0
  24. package/dist/internal/email-policy.mjs.map +1 -0
  25. package/dist/internal/email-registration-native.d.mts +38 -0
  26. package/dist/internal/email-registration-native.mjs +171 -0
  27. package/dist/internal/email-registration-native.mjs.map +1 -0
  28. package/dist/internal/models/email-model.d.mts +40 -104
  29. package/dist/internal/models/email-model.mjs +3 -5
  30. package/dist/internal/models/email-model.mjs.map +1 -1
  31. package/dist/internal/models/oauth-connected-model.d.mts +44 -213
  32. package/dist/internal/models/oauth-connected-model.mjs +6 -14
  33. package/dist/internal/models/oauth-connected-model.mjs.map +1 -1
  34. package/dist/internal/models/oauth-model.d.mts +95 -244
  35. package/dist/internal/models/oauth-model.mjs +28 -22
  36. package/dist/internal/models/oauth-model.mjs.map +1 -1
  37. package/dist/internal/models/passkey-model.d.mts +11 -147
  38. package/dist/internal/models/passkey-model.mjs +5 -24
  39. package/dist/internal/models/passkey-model.mjs.map +1 -1
  40. package/dist/internal/models/passkey-registration-ceremony-model.d.mts +5 -39
  41. package/dist/internal/models/passkey-write-model.d.mts +17 -75
  42. package/dist/internal/models/passkey-write-model.mjs +1 -7
  43. package/dist/internal/models/passkey-write-model.mjs.map +1 -1
  44. package/dist/internal/models/password-model.d.mts +16 -82
  45. package/dist/internal/models/password-model.mjs +1 -4
  46. package/dist/internal/models/password-model.mjs.map +1 -1
  47. package/dist/internal/models/phone-model.d.mts +86 -0
  48. package/dist/internal/models/phone-model.mjs +10 -0
  49. package/dist/internal/models/phone-model.mjs.map +1 -0
  50. package/dist/internal/models/proof-model.d.mts +43 -272
  51. package/dist/internal/models/proof-model.mjs +2 -10
  52. package/dist/internal/models/proof-model.mjs.map +1 -1
  53. package/dist/internal/models/session-model.d.mts +74 -93
  54. package/dist/internal/models/session-model.mjs +3 -11
  55. package/dist/internal/models/session-model.mjs.map +1 -1
  56. package/dist/internal/models/step-up-model.d.mts +12 -50
  57. package/dist/internal/models/step-up-model.mjs +2 -4
  58. package/dist/internal/models/step-up-model.mjs.map +1 -1
  59. package/dist/internal/models/totp-model.d.mts +76 -0
  60. package/dist/internal/models/totp-model.mjs +10 -0
  61. package/dist/internal/models/totp-model.mjs.map +1 -0
  62. package/dist/internal/native-sql-table.d.mts +21 -4
  63. package/dist/internal/native-sql-table.mjs +9 -5
  64. package/dist/internal/native-sql-table.mjs.map +1 -1
  65. package/dist/internal/oauth/native-accounts.d.mts +17 -0
  66. package/dist/internal/oauth/native-accounts.mjs +290 -0
  67. package/dist/internal/oauth/native-accounts.mjs.map +1 -0
  68. package/dist/internal/oauth/native-connected-state.d.mts +11 -0
  69. package/dist/internal/oauth/native-connected-state.mjs +146 -0
  70. package/dist/internal/oauth/native-connected-state.mjs.map +1 -0
  71. package/dist/internal/oauth/native-connected.d.mts +15 -0
  72. package/dist/internal/oauth/native-connected.mjs +462 -0
  73. package/dist/internal/oauth/native-connected.mjs.map +1 -0
  74. package/dist/internal/oauth/native-flow.mjs +138 -0
  75. package/dist/internal/oauth/native-flow.mjs.map +1 -0
  76. package/dist/internal/oauth/native-layers.d.mts +24 -0
  77. package/dist/internal/oauth/native-layers.mjs +13 -0
  78. package/dist/internal/oauth/native-layers.mjs.map +1 -0
  79. package/dist/internal/oauth/native-mutation.mjs +122 -0
  80. package/dist/internal/oauth/native-mutation.mjs.map +1 -0
  81. package/dist/internal/oauth/native-registration.d.mts +24 -0
  82. package/dist/internal/oauth/native-registration.mjs +328 -0
  83. package/dist/internal/oauth/native-registration.mjs.map +1 -0
  84. package/dist/internal/oauth/native-revocations.d.mts +17 -0
  85. package/dist/internal/oauth/native-revocations.mjs +106 -0
  86. package/dist/internal/oauth/native-revocations.mjs.map +1 -0
  87. package/dist/internal/oauth/native-sign-in.d.mts +17 -0
  88. package/dist/internal/oauth/native-sign-in.mjs +50 -0
  89. package/dist/internal/oauth/native-sign-in.mjs.map +1 -0
  90. package/dist/internal/oauth/native-state.d.mts +10 -0
  91. package/dist/internal/oauth/native-state.mjs +214 -0
  92. package/dist/internal/oauth/native-state.mjs.map +1 -0
  93. package/dist/internal/oauth/state.d.mts +10 -0
  94. package/dist/internal/oauth/state.mjs +3 -27
  95. package/dist/internal/oauth/state.mjs.map +1 -1
  96. package/dist/internal/passkey-actions.mjs +55 -0
  97. package/dist/internal/passkey-actions.mjs.map +1 -0
  98. package/dist/internal/passkey-inputs.mjs +73 -0
  99. package/dist/internal/passkey-inputs.mjs.map +1 -0
  100. package/dist/internal/passkey-managed.mjs +224 -0
  101. package/dist/internal/passkey-managed.mjs.map +1 -0
  102. package/dist/internal/passkey-native-ceremony.d.mts +35 -0
  103. package/dist/internal/passkey-native-ceremony.mjs +38 -0
  104. package/dist/internal/passkey-native-ceremony.mjs.map +1 -0
  105. package/dist/internal/passkey-native-flow.mjs +91 -0
  106. package/dist/internal/passkey-native-flow.mjs.map +1 -0
  107. package/dist/internal/passkey-native-registration.d.mts +10 -0
  108. package/dist/internal/passkey-native-registration.mjs +114 -0
  109. package/dist/internal/passkey-native-registration.mjs.map +1 -0
  110. package/dist/internal/passkey-native-state.d.mts +15 -0
  111. package/dist/internal/passkey-native-state.mjs +186 -0
  112. package/dist/internal/passkey-native-state.mjs.map +1 -0
  113. package/dist/internal/passkey-native-write.d.mts +82 -0
  114. package/dist/internal/passkey-native-write.mjs +330 -0
  115. package/dist/internal/passkey-native-write.mjs.map +1 -0
  116. package/dist/internal/passkey-native.d.mts +835 -0
  117. package/dist/internal/passkey-native.mjs +175 -0
  118. package/dist/internal/passkey-native.mjs.map +1 -0
  119. package/dist/internal/passkey-policy.mjs +115 -0
  120. package/dist/internal/passkey-policy.mjs.map +1 -0
  121. package/dist/internal/password-credentials.mjs +38 -9
  122. package/dist/internal/password-credentials.mjs.map +1 -1
  123. package/dist/internal/password-native.d.mts +14 -0
  124. package/dist/internal/password-native.mjs +292 -0
  125. package/dist/internal/password-native.mjs.map +1 -0
  126. package/dist/internal/password-policy.mjs +93 -0
  127. package/dist/internal/password-policy.mjs.map +1 -0
  128. package/dist/internal/password-registration-native.d.mts +22 -0
  129. package/dist/internal/password-registration-native.mjs +142 -0
  130. package/dist/internal/password-registration-native.mjs.map +1 -0
  131. package/dist/internal/persistence.d.mts +6 -19
  132. package/dist/internal/persistence.mjs +199 -166
  133. package/dist/internal/persistence.mjs.map +1 -1
  134. package/dist/internal/phone-composed.mjs +79 -0
  135. package/dist/internal/phone-composed.mjs.map +1 -0
  136. package/dist/internal/phone-native.d.mts +15 -0
  137. package/dist/internal/phone-native.mjs +354 -0
  138. package/dist/internal/phone-native.mjs.map +1 -0
  139. package/dist/internal/proof-native.d.mts +15 -0
  140. package/dist/internal/proof-native.mjs +289 -0
  141. package/dist/internal/proof-native.mjs.map +1 -0
  142. package/dist/internal/registration.mjs +50 -60
  143. package/dist/internal/registration.mjs.map +1 -1
  144. package/dist/internal/session-native-authority.d.mts +15 -0
  145. package/dist/internal/session-native-authority.mjs +91 -0
  146. package/dist/internal/session-native-authority.mjs.map +1 -0
  147. package/dist/internal/session-native-cleanup.d.mts +14 -0
  148. package/dist/internal/session-native-cleanup.mjs +48 -0
  149. package/dist/internal/session-native-cleanup.mjs.map +1 -0
  150. package/dist/internal/session-native-login.d.mts +15 -0
  151. package/dist/internal/session-native-login.mjs +87 -0
  152. package/dist/internal/session-native-login.mjs.map +1 -0
  153. package/dist/internal/session-native-pending-read.mjs +42 -0
  154. package/dist/internal/session-native-pending-read.mjs.map +1 -0
  155. package/dist/internal/session-native-pending.mjs +134 -0
  156. package/dist/internal/session-native-pending.mjs.map +1 -0
  157. package/dist/internal/session-native-record.mjs +79 -0
  158. package/dist/internal/session-native-record.mjs.map +1 -0
  159. package/dist/internal/session-native-state.mjs +130 -0
  160. package/dist/internal/session-native-state.mjs.map +1 -0
  161. package/dist/internal/session-native-stateful.d.mts +16 -0
  162. package/dist/internal/session-native-stateful.mjs +225 -0
  163. package/dist/internal/session-native-stateful.mjs.map +1 -0
  164. package/dist/internal/session-native-step-up.d.mts +15 -0
  165. package/dist/internal/session-native-step-up.mjs +212 -0
  166. package/dist/internal/session-native-step-up.mjs.map +1 -0
  167. package/dist/internal/session-native-validity.d.mts +15 -0
  168. package/dist/internal/session-native-validity.mjs +97 -0
  169. package/dist/internal/session-native-validity.mjs.map +1 -0
  170. package/dist/internal/session-policy.mjs +29 -0
  171. package/dist/internal/session-policy.mjs.map +1 -0
  172. package/dist/internal/sql-authority.d.mts +16 -0
  173. package/dist/internal/sql-authority.mjs +32 -0
  174. package/dist/internal/sql-authority.mjs.map +1 -0
  175. package/dist/internal/sql-change.mjs +21 -0
  176. package/dist/internal/sql-change.mjs.map +1 -0
  177. package/dist/internal/sql-cleanup.mjs +35 -0
  178. package/dist/internal/sql-cleanup.mjs.map +1 -0
  179. package/dist/internal/sql-commit.d.mts +72 -0
  180. package/dist/internal/sql-commit.mjs +176 -0
  181. package/dist/internal/sql-commit.mjs.map +1 -0
  182. package/dist/internal/sql-expression.d.mts +17 -0
  183. package/dist/internal/sql-expression.mjs +49 -0
  184. package/dist/internal/sql-expression.mjs.map +1 -0
  185. package/dist/internal/sql-oauth-connected-model.d.mts +7 -23
  186. package/dist/internal/sql-oauth-model.d.mts +27 -52
  187. package/dist/internal/sql-oauth-model.mjs +3 -4
  188. package/dist/internal/sql-oauth-model.mjs.map +1 -1
  189. package/dist/internal/sql-persistence.mjs +5 -9
  190. package/dist/internal/sql-persistence.mjs.map +1 -1
  191. package/dist/internal/sql-storage-validation.mjs +1 -2
  192. package/dist/internal/sql-storage-validation.mjs.map +1 -1
  193. package/dist/internal/sql-table.d.mts +3 -16
  194. package/dist/internal/sql-table.mjs +21 -42
  195. package/dist/internal/sql-table.mjs.map +1 -1
  196. package/dist/internal/standalone.mjs +2 -3
  197. package/dist/internal/standalone.mjs.map +1 -1
  198. package/dist/internal/step-up-state.mjs +5 -8
  199. package/dist/internal/step-up-state.mjs.map +1 -1
  200. package/dist/internal/storage-clock.mjs +44 -0
  201. package/dist/internal/storage-clock.mjs.map +1 -0
  202. package/dist/internal/storage-mapping.d.mts +11 -8
  203. package/dist/internal/storage-mapping.mjs +88 -302
  204. package/dist/internal/storage-mapping.mjs.map +1 -1
  205. package/dist/internal/storage-plans.mjs +15 -73
  206. package/dist/internal/storage-plans.mjs.map +1 -1
  207. package/dist/internal/storage-tables.d.mts +37 -520
  208. package/dist/internal/storage-tables.mjs +31 -211
  209. package/dist/internal/storage-tables.mjs.map +1 -1
  210. package/dist/internal/storage-validation.d.mts +1 -6
  211. package/dist/internal/storage-validation.mjs +1 -42
  212. package/dist/internal/storage-validation.mjs.map +1 -1
  213. package/dist/internal/table-model.d.mts +21 -0
  214. package/dist/internal/totp-native.d.mts +15 -0
  215. package/dist/internal/totp-native.mjs +401 -0
  216. package/dist/internal/totp-native.mjs.map +1 -0
  217. package/package.json +1 -1
  218. package/src/Adapter.ts +143 -199
  219. package/src/OAuthPersistence.ts +128 -271
  220. package/src/index.ts +1 -1
  221. package/src/internal/browser-login.ts +54 -24
  222. package/src/internal/configuration.ts +16 -31
  223. package/src/internal/d1-planning.ts +7 -0
  224. package/src/internal/email-native-state.ts +247 -0
  225. package/src/internal/email-native.ts +514 -0
  226. package/src/internal/email-policy.ts +235 -0
  227. package/src/internal/email-registration-native.ts +386 -0
  228. package/src/internal/models/email-model.ts +76 -214
  229. package/src/internal/models/oauth-connected-model.ts +50 -288
  230. package/src/internal/models/oauth-model.ts +147 -368
  231. package/src/internal/models/passkey-model.ts +11 -208
  232. package/src/internal/models/passkey-registration-ceremony-model.ts +6 -60
  233. package/src/internal/models/passkey-write-model.ts +14 -95
  234. package/src/internal/models/password-model.ts +28 -148
  235. package/src/internal/models/phone-model.ts +110 -0
  236. package/src/internal/models/proof-model.ts +48 -404
  237. package/src/internal/models/session-model.ts +102 -200
  238. package/src/internal/models/step-up-model.ts +17 -96
  239. package/src/internal/models/totp-model.ts +82 -0
  240. package/src/internal/native-sql-table.ts +32 -11
  241. package/src/internal/oauth/native-accounts.ts +576 -0
  242. package/src/internal/oauth/native-connected-state.ts +288 -0
  243. package/src/internal/oauth/native-connected.ts +888 -0
  244. package/src/internal/oauth/native-flow.ts +253 -0
  245. package/src/internal/oauth/native-layers.ts +83 -0
  246. package/src/internal/oauth/native-mutation.ts +222 -0
  247. package/src/internal/oauth/native-registration.ts +545 -0
  248. package/src/internal/oauth/native-revocations.ts +190 -0
  249. package/src/internal/oauth/native-sign-in.ts +111 -0
  250. package/src/internal/oauth/native-state.ts +346 -0
  251. package/src/internal/oauth/state.ts +2 -70
  252. package/src/internal/passkey-actions.ts +70 -0
  253. package/src/internal/passkey-inputs.ts +56 -0
  254. package/src/internal/passkey-managed.ts +360 -0
  255. package/src/internal/passkey-native-ceremony.ts +66 -0
  256. package/src/internal/passkey-native-flow.ts +140 -0
  257. package/src/internal/passkey-native-registration.ts +221 -0
  258. package/src/internal/passkey-native-state.ts +335 -0
  259. package/src/internal/passkey-native-write.ts +611 -0
  260. package/src/internal/passkey-native.ts +372 -0
  261. package/src/internal/passkey-policy.ts +246 -0
  262. package/src/internal/password-credentials.ts +52 -10
  263. package/src/internal/password-native.ts +571 -0
  264. package/src/internal/password-policy.ts +307 -0
  265. package/src/internal/password-registration-native.ts +322 -0
  266. package/src/internal/persistence.ts +336 -290
  267. package/src/internal/phone-composed.ts +86 -0
  268. package/src/internal/phone-native.ts +659 -0
  269. package/src/internal/proof-native.ts +448 -0
  270. package/src/internal/registration.ts +96 -143
  271. package/src/internal/session-native-authority.ts +247 -0
  272. package/src/internal/session-native-cleanup.ts +65 -0
  273. package/src/internal/session-native-login.ts +205 -0
  274. package/src/internal/session-native-pending-read.ts +68 -0
  275. package/src/internal/session-native-pending.ts +223 -0
  276. package/src/internal/session-native-record.ts +141 -0
  277. package/src/internal/session-native-state.ts +259 -0
  278. package/src/internal/session-native-stateful.ts +512 -0
  279. package/src/internal/session-native-step-up.ts +450 -0
  280. package/src/internal/session-native-validity.ts +208 -0
  281. package/src/internal/session-policy.ts +59 -0
  282. package/src/internal/sql-authority.ts +56 -0
  283. package/src/internal/sql-change.ts +38 -0
  284. package/src/internal/sql-cleanup.ts +56 -0
  285. package/src/internal/sql-commit.ts +435 -0
  286. package/src/internal/sql-expression.ts +94 -0
  287. package/src/internal/sql-metadata.ts +100 -0
  288. package/src/internal/sql-oauth-connected-model.ts +6 -95
  289. package/src/internal/sql-oauth-model.ts +31 -134
  290. package/src/internal/sql-persistence.ts +2 -6
  291. package/src/internal/sql-storage-validation.ts +1 -2
  292. package/src/internal/sql-table.ts +19 -52
  293. package/src/internal/standalone.ts +2 -11
  294. package/src/internal/step-up-state.ts +4 -17
  295. package/src/internal/storage-clock.ts +58 -0
  296. package/src/internal/storage-mapping.ts +125 -340
  297. package/src/internal/storage-plans.ts +14 -80
  298. package/src/internal/storage-tables.ts +28 -212
  299. package/src/internal/storage-validation.ts +0 -58
  300. package/src/internal/table-model.ts +24 -0
  301. package/src/internal/totp-native.ts +701 -0
  302. package/dist/internal/PasswordPreparedPostconditions.d.mts +0 -22
  303. package/dist/internal/PasswordPreparedPostconditions.mjs +0 -12
  304. package/dist/internal/PasswordPreparedPostconditions.mjs.map +0 -1
  305. package/dist/internal/authority-snapshot.mjs +0 -53
  306. package/dist/internal/authority-snapshot.mjs.map +0 -1
  307. package/dist/internal/email-kernel.d.mts +0 -276
  308. package/dist/internal/email-kernel.mjs +0 -497
  309. package/dist/internal/email-kernel.mjs.map +0 -1
  310. package/dist/internal/models/passkey-registration-ceremony-model.mjs +0 -18
  311. package/dist/internal/models/passkey-registration-ceremony-model.mjs.map +0 -1
  312. package/dist/internal/oauth/accounts.d.mts +0 -8
  313. package/dist/internal/oauth/accounts.mjs +0 -379
  314. package/dist/internal/oauth/accounts.mjs.map +0 -1
  315. package/dist/internal/oauth/connected-access.d.mts +0 -9
  316. package/dist/internal/oauth/connected-access.mjs +0 -229
  317. package/dist/internal/oauth/connected-access.mjs.map +0 -1
  318. package/dist/internal/oauth/connected-collection.d.mts +0 -7
  319. package/dist/internal/oauth/connected-collection.mjs +0 -214
  320. package/dist/internal/oauth/connected-collection.mjs.map +0 -1
  321. package/dist/internal/oauth/connected-custody.d.mts +0 -6
  322. package/dist/internal/oauth/connected-custody.mjs +0 -165
  323. package/dist/internal/oauth/connected-custody.mjs.map +0 -1
  324. package/dist/internal/oauth/connected-flow.d.mts +0 -7
  325. package/dist/internal/oauth/connected-flow.mjs +0 -324
  326. package/dist/internal/oauth/connected-flow.mjs.map +0 -1
  327. package/dist/internal/oauth/connected-input.mjs +0 -122
  328. package/dist/internal/oauth/connected-input.mjs.map +0 -1
  329. package/dist/internal/oauth/connected-keys.d.mts +0 -2
  330. package/dist/internal/oauth/connected-keys.mjs +0 -22
  331. package/dist/internal/oauth/connected-keys.mjs.map +0 -1
  332. package/dist/internal/oauth/connected-maintenance.d.mts +0 -9
  333. package/dist/internal/oauth/connected-maintenance.mjs +0 -226
  334. package/dist/internal/oauth/connected-maintenance.mjs.map +0 -1
  335. package/dist/internal/oauth/connected-management.d.mts +0 -9
  336. package/dist/internal/oauth/connected-management.mjs +0 -243
  337. package/dist/internal/oauth/connected-management.mjs.map +0 -1
  338. package/dist/internal/oauth/connected-reference.mjs +0 -63
  339. package/dist/internal/oauth/connected-reference.mjs.map +0 -1
  340. package/dist/internal/oauth/connected-settlement.d.mts +0 -8
  341. package/dist/internal/oauth/connected-settlement.mjs +0 -141
  342. package/dist/internal/oauth/connected-settlement.mjs.map +0 -1
  343. package/dist/internal/oauth/connected-sign-in.d.mts +0 -10
  344. package/dist/internal/oauth/connected-sign-in.mjs +0 -281
  345. package/dist/internal/oauth/connected-sign-in.mjs.map +0 -1
  346. package/dist/internal/oauth/connected-state.d.mts +0 -14
  347. package/dist/internal/oauth/connected-state.mjs +0 -469
  348. package/dist/internal/oauth/connected-state.mjs.map +0 -1
  349. package/dist/internal/oauth/connected-target.d.mts +0 -21
  350. package/dist/internal/oauth/connected-target.mjs +0 -117
  351. package/dist/internal/oauth/connected-target.mjs.map +0 -1
  352. package/dist/internal/oauth/flow.d.mts +0 -5
  353. package/dist/internal/oauth/flow.mjs +0 -279
  354. package/dist/internal/oauth/flow.mjs.map +0 -1
  355. package/dist/internal/oauth/input.mjs +0 -127
  356. package/dist/internal/oauth/input.mjs.map +0 -1
  357. package/dist/internal/oauth/owner.d.mts +0 -10
  358. package/dist/internal/oauth/owner.mjs +0 -10
  359. package/dist/internal/oauth/owner.mjs.map +0 -1
  360. package/dist/internal/oauth/query-compiler.d.mts +0 -7
  361. package/dist/internal/oauth/query-compiler.mjs +0 -9
  362. package/dist/internal/oauth/query-compiler.mjs.map +0 -1
  363. package/dist/internal/oauth/registration.d.mts +0 -7
  364. package/dist/internal/oauth/registration.mjs +0 -393
  365. package/dist/internal/oauth/registration.mjs.map +0 -1
  366. package/dist/internal/oauth/target.d.mts +0 -31
  367. package/dist/internal/oauth/target.mjs +0 -273
  368. package/dist/internal/oauth/target.mjs.map +0 -1
  369. package/dist/internal/oauth-kernel.d.mts +0 -1423
  370. package/dist/internal/oauth-kernel.mjs +0 -187
  371. package/dist/internal/oauth-kernel.mjs.map +0 -1
  372. package/dist/internal/passkey/admission.d.mts +0 -6
  373. package/dist/internal/passkey/admission.mjs +0 -220
  374. package/dist/internal/passkey/admission.mjs.map +0 -1
  375. package/dist/internal/passkey/credentials.d.mts +0 -14
  376. package/dist/internal/passkey/credentials.mjs +0 -249
  377. package/dist/internal/passkey/credentials.mjs.map +0 -1
  378. package/dist/internal/passkey/enrollment.mjs +0 -138
  379. package/dist/internal/passkey/enrollment.mjs.map +0 -1
  380. package/dist/internal/passkey/flow.d.mts +0 -21
  381. package/dist/internal/passkey/flow.mjs +0 -452
  382. package/dist/internal/passkey/flow.mjs.map +0 -1
  383. package/dist/internal/passkey/management.mjs +0 -231
  384. package/dist/internal/passkey/management.mjs.map +0 -1
  385. package/dist/internal/passkey/registration-ceremony.d.mts +0 -9
  386. package/dist/internal/passkey/registration-ceremony.mjs +0 -129
  387. package/dist/internal/passkey/registration-ceremony.mjs.map +0 -1
  388. package/dist/internal/passkey/registration-custody.d.mts +0 -2
  389. package/dist/internal/passkey/registration-custody.mjs +0 -52
  390. package/dist/internal/passkey/registration-custody.mjs.map +0 -1
  391. package/dist/internal/passkey/registration-write.mjs +0 -211
  392. package/dist/internal/passkey/registration-write.mjs.map +0 -1
  393. package/dist/internal/passkey/state.d.mts +0 -10
  394. package/dist/internal/passkey/state.mjs +0 -234
  395. package/dist/internal/passkey/state.mjs.map +0 -1
  396. package/dist/internal/passkey/target.d.mts +0 -20
  397. package/dist/internal/passkey/target.mjs +0 -200
  398. package/dist/internal/passkey/target.mjs.map +0 -1
  399. package/dist/internal/passkey/write-state.d.mts +0 -17
  400. package/dist/internal/passkey/write-state.mjs +0 -346
  401. package/dist/internal/passkey/write-state.mjs.map +0 -1
  402. package/dist/internal/passkey/write-target.mjs +0 -192
  403. package/dist/internal/passkey/write-target.mjs.map +0 -1
  404. package/dist/internal/passkey-kernel.d.mts +0 -6045
  405. package/dist/internal/passkey-kernel.mjs +0 -49
  406. package/dist/internal/passkey-kernel.mjs.map +0 -1
  407. package/dist/internal/passkeys.d.mts +0 -7
  408. package/dist/internal/passkeys.mjs +0 -387
  409. package/dist/internal/passkeys.mjs.map +0 -1
  410. package/dist/internal/password-credentials.d.mts +0 -11
  411. package/dist/internal/password-kernel.d.mts +0 -278
  412. package/dist/internal/password-kernel.mjs +0 -508
  413. package/dist/internal/password-kernel.mjs.map +0 -1
  414. package/dist/internal/phone-kernel.d.mts +0 -162
  415. package/dist/internal/phone-kernel.mjs +0 -437
  416. package/dist/internal/phone-kernel.mjs.map +0 -1
  417. package/dist/internal/proof-kernel.d.mts +0 -94
  418. package/dist/internal/proof-kernel.mjs +0 -624
  419. package/dist/internal/proof-kernel.mjs.map +0 -1
  420. package/dist/internal/query-operations.d.mts +0 -68
  421. package/dist/internal/session-kernel.d.mts +0 -62
  422. package/dist/internal/session-kernel.mjs +0 -820
  423. package/dist/internal/session-kernel.mjs.map +0 -1
  424. package/dist/internal/sql-oauth-connected-model.mjs +0 -7
  425. package/dist/internal/sql-oauth-connected-model.mjs.map +0 -1
  426. package/dist/internal/sql-query.d.mts +0 -12
  427. package/dist/internal/sql-query.mjs +0 -206
  428. package/dist/internal/sql-query.mjs.map +0 -1
  429. package/dist/internal/step-up-state.d.mts +0 -49
  430. package/dist/internal/transaction-execution-kernel.d.mts +0 -37
  431. package/dist/internal/transaction-execution-kernel.mjs +0 -120
  432. package/dist/internal/transaction-execution-kernel.mjs.map +0 -1
  433. package/dist/internal/transaction-kernel.d.mts +0 -81
  434. package/dist/internal/transaction-kernel.mjs +0 -264
  435. package/dist/internal/transaction-kernel.mjs.map +0 -1
  436. package/src/internal/PasswordPreparedPostconditions.ts +0 -30
  437. package/src/internal/authority-snapshot.ts +0 -91
  438. package/src/internal/email-kernel.ts +0 -1555
  439. package/src/internal/oauth/accounts.ts +0 -838
  440. package/src/internal/oauth/connected-access.ts +0 -388
  441. package/src/internal/oauth/connected-collection.ts +0 -345
  442. package/src/internal/oauth/connected-custody.ts +0 -308
  443. package/src/internal/oauth/connected-flow.ts +0 -562
  444. package/src/internal/oauth/connected-input.ts +0 -147
  445. package/src/internal/oauth/connected-keys.ts +0 -31
  446. package/src/internal/oauth/connected-maintenance.ts +0 -379
  447. package/src/internal/oauth/connected-management.ts +0 -391
  448. package/src/internal/oauth/connected-reference.ts +0 -135
  449. package/src/internal/oauth/connected-settlement.ts +0 -278
  450. package/src/internal/oauth/connected-sign-in.ts +0 -472
  451. package/src/internal/oauth/connected-state.ts +0 -924
  452. package/src/internal/oauth/connected-target.ts +0 -307
  453. package/src/internal/oauth/flow.ts +0 -505
  454. package/src/internal/oauth/input.ts +0 -201
  455. package/src/internal/oauth/owner.ts +0 -22
  456. package/src/internal/oauth/query-compiler.ts +0 -15
  457. package/src/internal/oauth/registration.ts +0 -676
  458. package/src/internal/oauth/target.ts +0 -803
  459. package/src/internal/oauth-kernel.ts +0 -294
  460. package/src/internal/passkey/admission.ts +0 -368
  461. package/src/internal/passkey/credentials.ts +0 -511
  462. package/src/internal/passkey/enrollment.ts +0 -326
  463. package/src/internal/passkey/flow.ts +0 -1062
  464. package/src/internal/passkey/management.ts +0 -426
  465. package/src/internal/passkey/registration-ceremony.ts +0 -283
  466. package/src/internal/passkey/registration-custody.ts +0 -91
  467. package/src/internal/passkey/registration-write.ts +0 -426
  468. package/src/internal/passkey/state.ts +0 -351
  469. package/src/internal/passkey/target.ts +0 -598
  470. package/src/internal/passkey/write-state.ts +0 -678
  471. package/src/internal/passkey/write-target.ts +0 -450
  472. package/src/internal/passkey-kernel.ts +0 -112
  473. package/src/internal/passkeys.ts +0 -652
  474. package/src/internal/password-kernel.ts +0 -1522
  475. package/src/internal/phone-kernel.ts +0 -872
  476. package/src/internal/proof-kernel.ts +0 -1992
  477. package/src/internal/query-operations.ts +0 -91
  478. package/src/internal/session-kernel.ts +0 -2406
  479. package/src/internal/sql-query.ts +0 -304
  480. package/src/internal/transaction-execution-kernel.ts +0 -335
  481. package/src/internal/transaction-kernel.ts +0 -603
@@ -0,0 +1,135 @@
1
+ import { exactSqlText } from "./sql-change.mjs";
2
+ import { Effect, Option, Schema } from "effect";
3
+ import { EmailCredentialSnapshot, EmailUnavailable } from "@yielded/auth/Email";
4
+ import { AuthenticationRevision } from "@yielded/auth/Sessions";
5
+ import { SqlClient } from "effect/sql/SqlClient";
6
+ import { LoginIdentifier } from "@yielded/auth/Identity";
7
+ //#region src/internal/email-native-state.ts
8
+ const emailUnavailable = () => EmailUnavailable.make({});
9
+ const ensureEmail = (condition) => {
10
+ if (!condition) throw emailUnavailable();
11
+ };
12
+ /** Every role binds the decoded native subject through its own physical column codec. */
13
+ const makeNativeEmailReader = Effect.fnUntraced(function* (tables, mapping, engineNow) {
14
+ const sql = (yield* SqlClient).withoutTransforms();
15
+ const s = mapping.subject, i = mapping.identifier, c = mapping.credential, a = mapping.authorityCredential;
16
+ const subject = tables(s.table).as("email_subject"), targetIdentifier = tables(i.table).as("email_target_identifier"), sourceIdentifier = tables(i.table).as("email_source_identifier"), targetCredential = tables(c.table).as("email_target_credential"), sourceCredential = tables(c.table).as("email_source_credential"), authority = tables(a.table).as("email_authority"), sourceAuthority = tables(a.table).as("email_source_authority"), cardinality = tables(c.table).as("email_cardinality");
17
+ const exact = (t, key, value) => exactSqlText(sql, t.column(key), t.value(key, value));
18
+ const id = (t, key, value) => sql`${t.column(key)} = ${t.value(key, value)}`;
19
+ const identifierKey = (t, value) => sql.and([exact(t, i.namespace, value.namespace), exact(t, i.value, value.value)]);
20
+ const credentialKey = (t, moduleId, value) => sql.and([
21
+ exact(t, c.moduleId, moduleId),
22
+ exact(t, c.identifierNamespace, value.namespace),
23
+ exact(t, c.identifierValue, value.value)
24
+ ]);
25
+ const selected = (t, row, prefix, key) => {
26
+ const decoded = t.decode(row, prefix);
27
+ return decoded[key] === null || decoded[key] === void 0 ? void 0 : decoded;
28
+ };
29
+ const owned = Effect.fnUntraced(function* (row, key, subjectId) {
30
+ return row !== void 0 && (yield* mapping.subjectId.toSubject(row[key])) === subjectId;
31
+ });
32
+ const read = Effect.fnUntraced(function* (input) {
33
+ const native = yield* mapping.subjectId.toNative(input.subjectId);
34
+ let source = input.sourceIdentifier;
35
+ if (input.sourceCredentialId !== void 0 && source === void 0) {
36
+ const table = tables(c.table);
37
+ const rows = yield* sql`select ${table.fields("email_source_lookup_")} from ${table.name} where ${exact(table, c.moduleId, input.moduleId)} and ${exact(table, c.credentialId, input.sourceCredentialId)} and ${id(table, c.subjectId, native)} limit 2`;
38
+ if (rows.length !== 1) return void 0;
39
+ const row = table.decode(rows[0], "email_source_lookup_");
40
+ ensureEmail(row[c.credentialId] === input.sourceCredentialId);
41
+ source = yield* Schema.decodeUnknownEffect(LoginIdentifier)({
42
+ namespace: row[c.identifierNamespace],
43
+ value: row[c.identifierValue]
44
+ });
45
+ }
46
+ const rows = yield* sql`select ${subject.fields("email_subject_")}, ${targetIdentifier.fields("email_target_identifier_")}, ${sourceIdentifier.fields("email_source_identifier_")}, ${targetCredential.fields("email_target_credential_")}, ${sourceCredential.fields("email_source_credential_")}, ${authority.fields("email_authority_")}, ${sourceAuthority.fields("email_source_authority_")}, ${engineNow ?? sql`0`} as engine_now, case when ${input.single === true && input.sourceCredentialId === void 0 ? sql`exists(select 1 from ${cardinality.name} where ${id(cardinality, c.subjectId, native)} and ${exact(cardinality, c.moduleId, input.moduleId)} and ${id(cardinality, c.status, c.activeStatusValue)})` : sql`1 = 0`} then 1 else 0 end as cardinality_conflict
47
+ from ${subject.name}
48
+ left join ${targetIdentifier.name} on ${identifierKey(targetIdentifier, input.identifier)}
49
+ left join ${sourceIdentifier.name} on ${source === void 0 ? sql`1 = 0` : identifierKey(sourceIdentifier, source)}
50
+ left join ${targetCredential.name} on ${credentialKey(targetCredential, input.moduleId, input.identifier)}
51
+ left join ${sourceCredential.name} on ${input.sourceCredentialId === void 0 ? sql`1 = 0` : sql.and([exact(sourceCredential, c.moduleId, input.moduleId), exact(sourceCredential, c.credentialId, input.sourceCredentialId)])}
52
+ left join ${sourceAuthority.name} on ${input.sourceCredentialId === void 0 ? sql`1 = 0` : sql.and([id(sourceAuthority, a.subjectId, native), exact(sourceAuthority, a.credentialId, input.sourceCredentialId)])}
53
+ left join ${authority.name} on ${id(authority, a.subjectId, native)} and ${id(authority, a.status, a.activeStatusValue)}
54
+ where ${id(subject, s.id, native)} and ${input.validity ?? sql`1 = 1`} limit 65`;
55
+ ensureEmail(rows.length <= 64);
56
+ const first = rows[0];
57
+ if (first === void 0) return void 0;
58
+ const subjectRow = subject.decode(first, "email_subject_");
59
+ ensureEmail((yield* mapping.subjectId.toSubject(subjectRow[s.id])) === input.subjectId);
60
+ if (!s.isActiveStatus(subjectRow[s.status])) return void 0;
61
+ const factors = [];
62
+ for (const row of rows) {
63
+ const factor = selected(authority, row, "email_authority_", a.credentialId);
64
+ if (factor === void 0) continue;
65
+ ensureEmail((yield* owned(factor, a.subjectId, input.subjectId)) && a.isActiveStatus(factor[a.status]));
66
+ ensureEmail(!factors.some((f) => f.credentialId === factor[a.credentialId]));
67
+ factors.push({
68
+ credentialId: factor[a.credentialId],
69
+ revision: factor[a.revision]
70
+ });
71
+ }
72
+ const revision = yield* Schema.decodeUnknownEffect(AuthenticationRevision)({
73
+ subjectId: input.subjectId,
74
+ securityRevision: subjectRow[s.securityRevision],
75
+ credentials: factors.sort((a, b) => String(a.credentialId).localeCompare(String(b.credentialId)))
76
+ });
77
+ const targetRow = selected(targetIdentifier, first, "email_target_identifier_", i.namespace), sourceRow = selected(sourceIdentifier, first, "email_source_identifier_", i.namespace), targetFactor = selected(targetCredential, first, "email_target_credential_", c.credentialId), sourceFactor = selected(sourceCredential, first, "email_source_credential_", c.credentialId);
78
+ const snapshot = Effect.fnUntraced(function* (identifierRow, credentialRow, value) {
79
+ if (identifierRow === void 0 || credentialRow === void 0 || value === void 0 || !i.isCurrent(identifierRow) || identifierRow[i.verifiedAt] === null || identifierRow[i.verifiedAt] === void 0 || !c.isActiveStatus(credentialRow[c.status]) || !(yield* owned(identifierRow, i.subjectId, input.subjectId)) || !(yield* owned(credentialRow, c.subjectId, input.subjectId))) return void 0;
80
+ ensureEmail(identifierRow[i.namespace] === value.namespace && identifierRow[i.value] === value.value && credentialRow[c.moduleId] === input.moduleId && credentialRow[c.identifierNamespace] === value.namespace && credentialRow[c.identifierValue] === value.value);
81
+ if (!revision.credentials.some((f) => f.credentialId === credentialRow[c.credentialId] && f.revision === credentialRow[c.credentialRevision])) return void 0;
82
+ const decoded = yield* c.decode({
83
+ moduleId: input.moduleId,
84
+ subject: subjectRow,
85
+ identifier: identifierRow,
86
+ credential: credentialRow
87
+ });
88
+ return yield* Schema.decodeEffect(EmailCredentialSnapshot)({
89
+ ...decoded,
90
+ revision,
91
+ requirement: yield* s.decodeRequirement(subjectRow)
92
+ });
93
+ });
94
+ ensureEmail(targetRow === void 0 || targetRow[i.namespace] === input.identifier.namespace && targetRow[i.value] === input.identifier.value);
95
+ ensureEmail(targetFactor === void 0 || targetFactor[c.moduleId] === input.moduleId && targetFactor[c.identifierNamespace] === input.identifier.namespace && targetFactor[c.identifierValue] === input.identifier.value);
96
+ const now = Number(first.engine_now);
97
+ ensureEmail(Number.isSafeInteger(now));
98
+ return {
99
+ native,
100
+ subject: subjectRow,
101
+ revision,
102
+ targetIdentifier: targetRow,
103
+ sourceIdentifier: sourceRow,
104
+ targetCredential: targetFactor,
105
+ sourceCredential: sourceFactor,
106
+ sourceAuthority: selected(sourceAuthority, first, "email_source_authority_", a.credentialId),
107
+ targetSnapshot: yield* snapshot(targetRow, targetFactor, input.identifier),
108
+ sourceSnapshot: yield* snapshot(sourceRow, sourceFactor, source),
109
+ cardinalityConflict: Number(first.cardinality_conflict) === 1,
110
+ now
111
+ };
112
+ });
113
+ return {
114
+ read,
115
+ lookup: Effect.fnUntraced(function* (input) {
116
+ const table = tables(i.table);
117
+ const rows = yield* sql`select ${table.fields("email_lookup_")} from ${table.name} where ${identifierKey(table, input.identifier)} limit 2`;
118
+ if (rows.length === 0) return Option.none();
119
+ ensureEmail(rows.length === 1);
120
+ const row = table.decode(rows[0], "email_lookup_");
121
+ ensureEmail(row[i.namespace] === input.identifier.namespace && row[i.value] === input.identifier.value);
122
+ if (!i.isCurrent(row) || row[i.verifiedAt] === null || row[i.verifiedAt] === void 0) return Option.none();
123
+ const subjectId = yield* mapping.subjectId.toSubject(row[i.subjectId]);
124
+ const result = yield* read({
125
+ ...input,
126
+ subjectId
127
+ });
128
+ return Option.fromUndefinedOr(result?.targetSnapshot);
129
+ })
130
+ };
131
+ });
132
+ //#endregion
133
+ export { emailUnavailable, ensureEmail, makeNativeEmailReader };
134
+
135
+ //# sourceMappingURL=email-native-state.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"email-native-state.mjs","names":[],"sources":["../../src/internal/email-native-state.ts"],"sourcesContent":["import { EmailCredentialSnapshot, EmailUnavailable } from \"@yielded/auth/Email\";\nimport { LoginIdentifier } from \"@yielded/auth/Identity\";\nimport type { SubjectId } from \"@yielded/auth/Schema\";\nimport { AuthenticationRevision } from \"@yielded/auth/Sessions\";\nimport { Effect, Option, Schema } from \"effect\";\nimport { SqlClient } from \"effect/sql/SqlClient\";\nimport type { Fragment } from \"effect/sql/Statement\";\n\nimport type { AnyEmailSignInMapping } from \"./models/email-model\";\nimport type { NativeSqlTables, SqlTable } from \"./native-sql-table\";\nimport { exactSqlText } from \"./sql-change\";\n\nexport const emailUnavailable = () => EmailUnavailable.make({});\n\nexport const ensureEmail: (condition: unknown) => asserts condition = (condition) => {\n if (!condition) throw emailUnavailable();\n};\n\n/** Every role binds the decoded native subject through its own physical column codec. */\nexport const makeNativeEmailReader = Effect.fnUntraced(function* (\n tables: NativeSqlTables,\n mapping: AnyEmailSignInMapping,\n engineNow?: Fragment,\n) {\n const sql = (yield* SqlClient).withoutTransforms();\n\n const s = mapping.subject,\n i = mapping.identifier,\n c = mapping.credential,\n a = mapping.authorityCredential;\n\n const subject = tables(s.table).as(\"email_subject\"),\n targetIdentifier = tables(i.table).as(\"email_target_identifier\"),\n sourceIdentifier = tables(i.table).as(\"email_source_identifier\"),\n targetCredential = tables(c.table).as(\"email_target_credential\"),\n sourceCredential = tables(c.table).as(\"email_source_credential\"),\n authority = tables(a.table).as(\"email_authority\"),\n sourceAuthority = tables(a.table).as(\"email_source_authority\"),\n cardinality = tables(c.table).as(\"email_cardinality\");\n\n const exact = (t: SqlTable, key: string, value: unknown) =>\n exactSqlText(sql, t.column(key), t.value(key, value));\n\n const id = (t: SqlTable, key: string, value: unknown) =>\n sql`${t.column(key)} = ${t.value(key, value)}`;\n\n const identifierKey = (t: SqlTable, value: LoginIdentifier) =>\n sql.and([exact(t, i.namespace, value.namespace), exact(t, i.value, value.value)]);\n\n const credentialKey = (t: SqlTable, moduleId: string, value: LoginIdentifier) =>\n sql.and([\n exact(t, c.moduleId, moduleId),\n exact(t, c.identifierNamespace, value.namespace),\n exact(t, c.identifierValue, value.value),\n ]);\n\n const selected = (t: SqlTable, row: Record<string, unknown>, prefix: string, key: string) => {\n const decoded = t.decode(row, prefix);\n\n return decoded[key] === null || decoded[key] === undefined ? undefined : decoded;\n };\n\n const owned = Effect.fnUntraced(function* (\n row: Record<string, unknown> | undefined,\n key: string,\n subjectId: SubjectId,\n ) {\n return row !== undefined && (yield* mapping.subjectId.toSubject(row[key])) === subjectId;\n });\n\n const read = Effect.fnUntraced(function* (input: {\n readonly moduleId: string;\n readonly subjectId: SubjectId;\n readonly identifier: LoginIdentifier;\n readonly sourceCredentialId?: string;\n readonly sourceIdentifier?: LoginIdentifier;\n readonly single?: boolean;\n readonly validity?: Fragment;\n }) {\n const native = yield* mapping.subjectId.toNative(input.subjectId);\n let source = input.sourceIdentifier;\n\n if (input.sourceCredentialId !== undefined && source === undefined) {\n const table = tables(c.table);\n\n const rows =\n yield* sql`select ${table.fields(\"email_source_lookup_\")} from ${table.name} where ${exact(table, c.moduleId, input.moduleId)} and ${exact(table, c.credentialId, input.sourceCredentialId)} and ${id(table, c.subjectId, native)} limit 2`;\n\n if (rows.length !== 1) return undefined;\n const row = table.decode(rows[0]!, \"email_source_lookup_\");\n\n ensureEmail(row[c.credentialId] === input.sourceCredentialId);\n source = yield* Schema.decodeUnknownEffect(LoginIdentifier)({\n namespace: row[c.identifierNamespace],\n value: row[c.identifierValue],\n });\n }\n\n const rows =\n yield* sql`select ${subject.fields(\"email_subject_\")}, ${targetIdentifier.fields(\"email_target_identifier_\")}, ${sourceIdentifier.fields(\"email_source_identifier_\")}, ${targetCredential.fields(\"email_target_credential_\")}, ${sourceCredential.fields(\"email_source_credential_\")}, ${authority.fields(\"email_authority_\")}, ${sourceAuthority.fields(\"email_source_authority_\")}, ${engineNow ?? sql`0`} as engine_now, case when ${input.single === true && input.sourceCredentialId === undefined ? sql`exists(select 1 from ${cardinality.name} where ${id(cardinality, c.subjectId, native)} and ${exact(cardinality, c.moduleId, input.moduleId)} and ${id(cardinality, c.status, c.activeStatusValue)})` : sql`1 = 0`} then 1 else 0 end as cardinality_conflict\n from ${subject.name}\n left join ${targetIdentifier.name} on ${identifierKey(targetIdentifier, input.identifier)}\n left join ${sourceIdentifier.name} on ${source === undefined ? sql`1 = 0` : identifierKey(sourceIdentifier, source)}\n left join ${targetCredential.name} on ${credentialKey(targetCredential, input.moduleId, input.identifier)}\n left join ${sourceCredential.name} on ${input.sourceCredentialId === undefined ? sql`1 = 0` : sql.and([exact(sourceCredential, c.moduleId, input.moduleId), exact(sourceCredential, c.credentialId, input.sourceCredentialId)])}\n left join ${sourceAuthority.name} on ${input.sourceCredentialId === undefined ? sql`1 = 0` : sql.and([id(sourceAuthority, a.subjectId, native), exact(sourceAuthority, a.credentialId, input.sourceCredentialId)])}\n left join ${authority.name} on ${id(authority, a.subjectId, native)} and ${id(authority, a.status, a.activeStatusValue)}\n where ${id(subject, s.id, native)} and ${input.validity ?? sql`1 = 1`} limit 65`;\n\n ensureEmail(rows.length <= 64);\n const first = rows[0];\n\n if (first === undefined) return undefined;\n const subjectRow = subject.decode(first, \"email_subject_\");\n\n ensureEmail((yield* mapping.subjectId.toSubject(subjectRow[s.id])) === input.subjectId);\n if (!s.isActiveStatus(subjectRow[s.status])) return undefined;\n const factors: { readonly credentialId: unknown; readonly revision: unknown }[] = [];\n\n for (const row of rows) {\n const factor = selected(authority, row, \"email_authority_\", a.credentialId);\n\n if (factor === undefined) continue;\n ensureEmail(\n (yield* owned(factor, a.subjectId, input.subjectId)) && a.isActiveStatus(factor[a.status]),\n );\n ensureEmail(!factors.some((f) => f.credentialId === factor[a.credentialId]));\n factors.push({ credentialId: factor[a.credentialId], revision: factor[a.revision] });\n }\n\n const revision = yield* Schema.decodeUnknownEffect(AuthenticationRevision)({\n subjectId: input.subjectId,\n securityRevision: subjectRow[s.securityRevision],\n credentials: factors.sort((a, b) =>\n String(a.credentialId).localeCompare(String(b.credentialId)),\n ),\n });\n\n const targetRow = selected(targetIdentifier, first, \"email_target_identifier_\", i.namespace),\n sourceRow = selected(sourceIdentifier, first, \"email_source_identifier_\", i.namespace),\n targetFactor = selected(targetCredential, first, \"email_target_credential_\", c.credentialId),\n sourceFactor = selected(sourceCredential, first, \"email_source_credential_\", c.credentialId);\n\n const snapshot = Effect.fnUntraced(function* (\n identifierRow: Record<string, unknown> | undefined,\n credentialRow: Record<string, unknown> | undefined,\n value: LoginIdentifier | undefined,\n ) {\n if (\n identifierRow === undefined ||\n credentialRow === undefined ||\n value === undefined ||\n !i.isCurrent(identifierRow) ||\n identifierRow[i.verifiedAt] === null ||\n identifierRow[i.verifiedAt] === undefined ||\n !c.isActiveStatus(credentialRow[c.status]) ||\n !(yield* owned(identifierRow, i.subjectId, input.subjectId)) ||\n !(yield* owned(credentialRow, c.subjectId, input.subjectId))\n )\n return undefined;\n ensureEmail(\n identifierRow[i.namespace] === value.namespace &&\n identifierRow[i.value] === value.value &&\n credentialRow[c.moduleId] === input.moduleId &&\n credentialRow[c.identifierNamespace] === value.namespace &&\n credentialRow[c.identifierValue] === value.value,\n );\n if (\n !revision.credentials.some(\n (f) =>\n f.credentialId === credentialRow[c.credentialId] &&\n f.revision === credentialRow[c.credentialRevision],\n )\n )\n return undefined;\n\n const decoded = yield* c.decode({\n moduleId: input.moduleId,\n subject: subjectRow,\n identifier: identifierRow,\n credential: credentialRow,\n });\n\n return yield* Schema.decodeEffect(EmailCredentialSnapshot)({\n ...decoded,\n revision,\n requirement: yield* s.decodeRequirement(subjectRow),\n });\n });\n\n ensureEmail(\n targetRow === undefined ||\n (targetRow[i.namespace] === input.identifier.namespace &&\n targetRow[i.value] === input.identifier.value),\n );\n ensureEmail(\n targetFactor === undefined ||\n (targetFactor[c.moduleId] === input.moduleId &&\n targetFactor[c.identifierNamespace] === input.identifier.namespace &&\n targetFactor[c.identifierValue] === input.identifier.value),\n );\n const now = Number(first.engine_now);\n\n ensureEmail(Number.isSafeInteger(now));\n\n return {\n native,\n subject: subjectRow,\n revision,\n targetIdentifier: targetRow,\n sourceIdentifier: sourceRow,\n targetCredential: targetFactor,\n sourceCredential: sourceFactor,\n sourceAuthority: selected(sourceAuthority, first, \"email_source_authority_\", a.credentialId),\n targetSnapshot: yield* snapshot(targetRow, targetFactor, input.identifier),\n sourceSnapshot: yield* snapshot(sourceRow, sourceFactor, source),\n cardinalityConflict: Number(first.cardinality_conflict) === 1,\n now,\n };\n });\n\n const lookup = Effect.fnUntraced(function* (input: {\n readonly moduleId: string;\n readonly identifier: LoginIdentifier;\n }) {\n const table = tables(i.table);\n\n const rows =\n yield* sql`select ${table.fields(\"email_lookup_\")} from ${table.name} where ${identifierKey(table, input.identifier)} limit 2`;\n\n if (rows.length === 0) return Option.none();\n ensureEmail(rows.length === 1);\n const row = table.decode(rows[0]!, \"email_lookup_\");\n\n ensureEmail(\n row[i.namespace] === input.identifier.namespace && row[i.value] === input.identifier.value,\n );\n if (!i.isCurrent(row) || row[i.verifiedAt] === null || row[i.verifiedAt] === undefined)\n return Option.none();\n const subjectId = yield* mapping.subjectId.toSubject(row[i.subjectId]);\n const result = yield* read({ ...input, subjectId });\n\n return Option.fromUndefinedOr(result?.targetSnapshot);\n });\n\n return { read, lookup };\n});\n"],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { AnyProofPersistenceMapping } from "./models/proof-model.mjs";
2
+ import { AnyEmailAddressMapping, AnyEmailSignInMapping } from "./models/email-model.mjs";
3
+ import { NativeSqlTables } from "./native-sql-table.mjs";
4
+ import { SqlBatchCommit } from "./sql-commit.mjs";
5
+ import { Crypto, Effect } from "effect";
6
+ import * as E from "@yielded/auth/Email";
7
+ import { LifecycleHooks } from "@yielded/auth/Hooks";
8
+ import { SqlClient } from "effect/sql/SqlClient";
9
+ //#region src/internal/email-native.d.ts
10
+ export declare const makeNativeEmailSignInServices: (tables: NativeSqlTables, mapping: AnyEmailSignInMapping) => Effect.Effect<{
11
+ readonly emailSignInTargets: E.EmailSignInTargets["Service"];
12
+ }, never, LifecycleHooks | SqlClient>;
13
+ export declare const makeNativeEmailAddressServices: (tables: NativeSqlTables, mapping: AnyEmailAddressMapping, proofs?: AnyProofPersistenceMapping | undefined) => Effect.Effect<{
14
+ readonly emailAddressPersistence: E.EmailAddressPersistence["Service"];
15
+ }, never, Crypto.Crypto | LifecycleHooks | SqlBatchCommit | SqlClient>;
16
+ //#endregion
17
+ //# sourceMappingURL=email-native.d.mts.map
@@ -0,0 +1,245 @@
1
+ import { PersistenceMappingError } from "./mapping-error.mjs";
2
+ import { sqlBatchAssertion } from "./d1-planning.mjs";
3
+ import { exactSqlText, executeSqlChange } from "./sql-change.mjs";
4
+ import { emailUnavailable, ensureEmail, makeNativeEmailReader } from "./email-native-state.mjs";
5
+ import { passwordEvidenceSatisfiedAt } from "./password-policy.mjs";
6
+ import { allocateEmailSecurityRevision, allocateEmailValue, sameEmailRevision, snapshotEmailMutation, validateEmailMutation } from "./email-policy.mjs";
7
+ import { SqlBatchCommit, appendSqlBatchStatement, makeSqlCommitExecutor, registerSqlBatchPostcondition, registerSqlCommitReceipt, registerSqlPostcondition } from "./sql-commit.mjs";
8
+ import { makeNativeProofStore } from "./proof-native.mjs";
9
+ import { Crypto, DateTime, Effect, Schema } from "effect";
10
+ import * as E from "@yielded/auth/Email";
11
+ import { CurrentCommitJournal } from "@yielded/auth/Hooks";
12
+ import { ProofRedemptionInput } from "@yielded/auth/Proofs";
13
+ import { SecurityRevision } from "@yielded/auth/Sessions";
14
+ import { SqlClient } from "effect/sql/SqlClient";
15
+ //#region src/internal/email-native.ts
16
+ const makeNativeEmailSignInServices = Effect.fnUntraced(function* (tables, mapping) {
17
+ const executor = yield* makeSqlCommitExecutor(emailUnavailable);
18
+ const reader = yield* makeNativeEmailReader(tables, mapping);
19
+ return { emailSignInTargets: E.EmailSignInTargets.of({ lookup: (input) => executor.read(reader.lookup(input)) }) };
20
+ });
21
+ const makeNativeEmailAddressServices = Effect.fnUntraced(function* (tables, mapping, proofs) {
22
+ const batch = yield* SqlBatchCommit;
23
+ const sql = (yield* SqlClient).withoutTransforms(), executor = yield* makeSqlCommitExecutor(emailUnavailable), crypto = yield* Crypto.Crypto;
24
+ const now = tables.expression(mapping.clock.engineNowMillis);
25
+ const reader = yield* makeNativeEmailReader(tables, mapping, now);
26
+ const s = mapping.subject, i = mapping.identifier, c = mapping.credential, a = mapping.authorityCredential;
27
+ const subject = tables(s.table), identifier = tables(i.table), credential = tables(c.table), authority = tables(a.table);
28
+ const exact = (t, key, value) => exactSqlText(sql, t.column(key), t.value(key, value));
29
+ const id = (t, key, value) => sql`${t.column(key)} = ${t.value(key, value)}`;
30
+ const identifierKey = (value) => sql.and([exact(identifier, i.namespace, value.namespace), exact(identifier, i.value, value.value)]);
31
+ const activeSubject = id(subject, s.status, s.activeStatusValue), activeCredential = id(credential, c.status, c.activeStatusValue), activeAuthority = id(authority, a.status, a.activeStatusValue);
32
+ const lock = sql.onDialectOrElse({
33
+ sqlite: () => sql``,
34
+ orElse: () => sql`for update`
35
+ });
36
+ const mode = "interactive";
37
+ const run = (work) => batch === void 0 ? executor.run(work.pipe(Effect.provideService(Crypto.Crypto, crypto))) : executor.batch(work.pipe(Effect.provideService(Crypto.Crypto, crypto))).pipe(Effect.provideService(SqlBatchCommit, batch));
38
+ const stage = Effect.fnUntraced(function* (statement) {
39
+ if (batch === void 0) ensureEmail((yield* executeSqlChange(sql, statement)) === 1);
40
+ else {
41
+ yield* appendSqlBatchStatement(sql`${statement}`);
42
+ yield* appendSqlBatchStatement(sqlBatchAssertion(sql, sql`changes() = 1`));
43
+ }
44
+ });
45
+ const prepare = (decision, project) => Effect.gen(function* () {
46
+ const receipt = project(decision, yield* CurrentCommitJournal);
47
+ yield* registerSqlCommitReceipt(receipt);
48
+ return receipt;
49
+ });
50
+ const target = Effect.fnUntraced(function* (input, sourceIdentifier) {
51
+ const state = yield* reader.read({
52
+ moduleId: input.moduleId,
53
+ subjectId: input.subjectId,
54
+ identifier: input.target,
55
+ ...input.sourceCredentialId === void 0 ? {} : { sourceCredentialId: input.sourceCredentialId },
56
+ ...sourceIdentifier === void 0 ? {} : { sourceIdentifier },
57
+ single: mapping.addressCardinality === "single"
58
+ });
59
+ if (state === void 0) return void 0;
60
+ const mutable = state.targetIdentifier !== void 0 && (yield* mapping.subjectId.toSubject(state.targetIdentifier[i.subjectId])) === input.subjectId && mapping.identifier.isMutableTarget(state.targetIdentifier) && (state.targetCredential === void 0 || !c.isActiveStatus(state.targetCredential[c.status]) && (yield* mapping.subjectId.toSubject(state.targetCredential[c.subjectId])) === input.subjectId);
61
+ const source = state.sourceSnapshot;
62
+ const eligible = (state.targetIdentifier === void 0 ? state.targetCredential === void 0 : mutable) && (input.sourceCredentialId === void 0 || source !== void 0) && (source === void 0 || source.identifier.namespace !== input.target.namespace || source.identifier.value !== input.target.value) && !state.cardinalityConflict;
63
+ const captured = {
64
+ revision: state.revision,
65
+ eligible,
66
+ ...source === void 0 ? {} : { source },
67
+ ...mutable ? { targetIdentifierRevision: yield* Schema.decodeUnknownEffect(SecurityRevision)(state.targetIdentifier[i.bindingRevision]) } : {}
68
+ };
69
+ return {
70
+ ...state,
71
+ target: captured
72
+ };
73
+ });
74
+ const mutate = (original, action, project) => run(Effect.gen(function* () {
75
+ const input = yield* snapshotEmailMutation(original);
76
+ const redemption = yield* Schema.decodeEffect(Schema.toCodecIso(ProofRedemptionInput))(yield* Schema.encodeEffect(Schema.toCodecIso(ProofRedemptionInput))(original.redemption.input));
77
+ const native = yield* mapping.subjectId.toNative(input.captured.revision.subjectId);
78
+ const locked = yield* sql`select ${subject.fields("email_locked_")} from ${subject.name} where ${id(subject, s.id, native)} limit 2 ${batch === void 0 ? lock : sql``}`;
79
+ if (locked.length !== 1) return yield* prepare("rejected", project);
80
+ ensureEmail((yield* mapping.subjectId.toSubject(subject.decode(locked[0], "email_locked_")[s.id])) === input.captured.revision.subjectId);
81
+ const current = yield* target({
82
+ moduleId: input.moduleId,
83
+ subjectId: input.captured.revision.subjectId,
84
+ target: input.target,
85
+ ...input.captured.source === void 0 ? {} : { sourceCredentialId: input.captured.source.credentialId }
86
+ }, input.captured.source?.identifier);
87
+ if (current === void 0 || proofs === void 0) return yield* prepare("rejected", project);
88
+ const requirement = yield* s.decodeActionRequirement(current.subject, action);
89
+ if (!(yield* validateEmailMutation(mapping, {
90
+ ...input,
91
+ redemption: {
92
+ input: redemption,
93
+ prepare: original.redemption.prepare
94
+ }
95
+ }, action, {
96
+ target: current.target,
97
+ requirement: Effect.succeed(requirement)
98
+ }, current.now))) return yield* prepare("rejected", project);
99
+ const requirements = [input.authorization.requirement, requirement];
100
+ const deadline = [...new Set(input.authorization.evidence.proofs.flatMap((proof) => requirements.map((r) => DateTime.toEpochMillis(proof.verifiedAt) + r.maximumAgeMillis)))].filter((time) => time > current.now).sort((a, b) => a - b).find((time) => requirements.some((r) => !passwordEvidenceSatisfiedAt(input.authorization.evidence, r, time)));
101
+ ensureEmail(deadline !== void 0);
102
+ const freshness = sql`${now} >= ${current.now} and ${now} < ${deadline}`;
103
+ const factorCondition = (revision) => sql.and([sql`(select count(*) from ${authority.name} where ${id(authority, a.subjectId, native)} and ${activeAuthority}) = ${revision.credentials.length}`, ...revision.credentials.map((f) => sql`exists(select 1 from ${authority.name} where ${id(authority, a.subjectId, native)} and ${exact(authority, a.credentialId, f.credentialId)} and ${exact(authority, a.revision, f.revision)} and ${activeAuthority})`)]);
104
+ if (batch !== void 0) {
105
+ yield* appendSqlBatchStatement(sqlBatchAssertion(sql, sql.and([
106
+ sql`exists(select 1 from ${subject.name} where ${id(subject, s.id, native)} and ${exact(subject, s.securityRevision, current.revision.securityRevision)} and ${activeSubject})`,
107
+ factorCondition(current.revision),
108
+ freshness
109
+ ])));
110
+ if (current.targetIdentifier !== void 0) {
111
+ ensureEmail(i.d1MutableTargetCondition !== void 0);
112
+ yield* appendSqlBatchStatement(sqlBatchAssertion(sql, sql`exists(select 1 from ${identifier.name} where ${identifierKey(input.target)} and ${id(identifier, i.subjectId, native)} and ${tables.expression(i.d1MutableTargetCondition({
113
+ identifier: input.target,
114
+ nativeSubjectId: native
115
+ }))})`));
116
+ }
117
+ if (current.target.source !== void 0) {
118
+ ensureEmail(i.d1CurrentCondition !== void 0);
119
+ yield* appendSqlBatchStatement(sqlBatchAssertion(sql, sql`exists(select 1 from ${identifier.name} where ${identifierKey(current.target.source.identifier)} and ${id(identifier, i.subjectId, native)} and ${tables.expression(i.d1CurrentCondition({
120
+ identifier: current.target.source.identifier,
121
+ nativeSubjectId: native,
122
+ bindingRevision: current.target.source.identifierRevision
123
+ }))})`));
124
+ }
125
+ }
126
+ const redeemed = yield* (yield* makeNativeProofStore(tables, proofs, batch !== void 0)).redeemLocked(redemption);
127
+ yield* registerSqlCommitReceipt(original.redemption.prepare(redeemed.decision, yield* CurrentCommitJournal, (value) => value));
128
+ if (redeemed.decision !== "redeemed") return yield* prepare("rejected", project);
129
+ const allocate = () => allocateEmailValue(mode, mapping.allocateRevision, mapping.allocateRevisionSync);
130
+ const targetIdentifierRevision = yield* allocate(), targetCredentialRevision = yield* allocate(), sourceIdentifierRevision = yield* allocate(), sourceCredentialRevision = yield* allocate();
131
+ const confirms = action === "verify-address" && current.target.targetIdentifierRevision !== void 0;
132
+ const nextSecurityRevision = confirms ? current.revision.securityRevision : yield* allocateEmailSecurityRevision(mapping, mode, current.revision.securityRevision);
133
+ ensureEmail(confirms || nextSecurityRevision !== current.revision.securityRevision);
134
+ const targetCredentialId = current.targetCredential === void 0 ? yield* allocateEmailValue(mode, mapping.allocateCredentialId, mapping.allocateCredentialIdSync) : yield* Schema.decodeUnknownEffect(Schema.String)(current.targetCredential[c.credentialId]);
135
+ const source = current.target.source;
136
+ if (action === "change-address") {
137
+ ensureEmail(source !== void 0);
138
+ yield* stage(sql`${identifier.update(i.encodeRetirement({
139
+ source: source.identifier,
140
+ bindingRevision: sourceIdentifierRevision
141
+ }))} where ${identifierKey(source.identifier)} and ${id(identifier, i.subjectId, native)} and ${exact(identifier, i.bindingRevision, source.identifierRevision)}`);
142
+ yield* stage(sql`${credential.update(c.encodeRetirement({
143
+ source: source.identifier,
144
+ credentialRevision: sourceCredentialRevision
145
+ }))} where ${exact(credential, c.moduleId, input.moduleId)} and ${exact(credential, c.credentialId, source.credentialId)} and ${id(credential, c.subjectId, native)} and ${exact(credential, c.credentialRevision, source.credentialRevision)} and ${activeCredential}`);
146
+ yield* stage(sql`${authority.update(a.encodeRetirement(sourceCredentialRevision))} where ${id(authority, a.subjectId, native)} and ${exact(authority, a.credentialId, source.credentialId)} and ${exact(authority, a.revision, source.credentialRevision)} and ${activeAuthority}`);
147
+ }
148
+ if (current.targetIdentifier === void 0) yield* stage(identifier.insert(i.encodeVerifiedInsert({
149
+ identifier: input.target,
150
+ subjectId: native,
151
+ verifiedAtMillis: current.now,
152
+ bindingRevision: targetIdentifierRevision
153
+ })));
154
+ else yield* stage(sql`${identifier.update(i.encodeVerification({
155
+ verifiedAtMillis: current.now,
156
+ bindingRevision: targetIdentifierRevision
157
+ }))} where ${identifierKey(input.target)} and ${id(identifier, i.subjectId, native)} and ${exact(identifier, i.bindingRevision, current.targetIdentifier[i.bindingRevision])} and ${identifier.column(i.verifiedAt)} is null`);
158
+ if (current.targetCredential === void 0) {
159
+ yield* stage(credential.insert(c.encodeVerifiedInsert({
160
+ moduleId: input.moduleId,
161
+ subjectId: native,
162
+ credentialId: targetCredentialId,
163
+ identifier: input.target,
164
+ credentialRevision: targetCredentialRevision
165
+ })));
166
+ yield* stage(authority.insert(a.encodeInsert({
167
+ subjectId: native,
168
+ credentialId: targetCredentialId,
169
+ revision: targetCredentialRevision
170
+ })));
171
+ } else {
172
+ const old = current.targetCredential[c.credentialRevision];
173
+ yield* stage(sql`${credential.update(c.encodeActivation({
174
+ identifier: input.target,
175
+ credentialRevision: targetCredentialRevision
176
+ }))} where ${exact(credential, c.moduleId, input.moduleId)} and ${exact(credential, c.credentialId, targetCredentialId)} and ${id(credential, c.subjectId, native)} and ${exact(credential, c.credentialRevision, old)}`);
177
+ yield* stage(sql`${authority.update(a.encodeActivation(targetCredentialRevision))} where ${id(authority, a.subjectId, native)} and ${exact(authority, a.credentialId, targetCredentialId)} and ${exact(authority, a.revision, old)}`);
178
+ }
179
+ if (!confirms) yield* stage(sql`${subject.update({ [s.securityRevision]: nextSecurityRevision })} where ${id(subject, s.id, native)} and ${exact(subject, s.securityRevision, current.revision.securityRevision)} and ${activeSubject} and ${freshness}`);
180
+ const revision = {
181
+ subjectId: current.revision.subjectId,
182
+ securityRevision: nextSecurityRevision,
183
+ credentials: [...current.revision.credentials.filter((f) => f.credentialId !== targetCredentialId && f.credentialId !== source?.credentialId), {
184
+ credentialId: targetCredentialId,
185
+ revision: targetCredentialRevision
186
+ }].sort((a, b) => a.credentialId.localeCompare(b.credentialId))
187
+ };
188
+ if (batch !== void 0) {
189
+ ensureEmail(i.d1CurrentCondition !== void 0);
190
+ const conditions = [
191
+ redeemed.validUntil,
192
+ freshness,
193
+ factorCondition(revision),
194
+ sql`exists(select 1 from ${subject.name} where ${id(subject, s.id, native)} and ${exact(subject, s.securityRevision, nextSecurityRevision)} and ${activeSubject})`,
195
+ sql`exists(select 1 from ${identifier.name} where ${identifierKey(input.target)} and ${id(identifier, i.subjectId, native)} and ${tables.expression(i.d1CurrentCondition({
196
+ identifier: input.target,
197
+ nativeSubjectId: native,
198
+ bindingRevision: targetIdentifierRevision
199
+ }))})`,
200
+ sql`exists(select 1 from ${identifier.name} where ${identifierKey(input.target)} and ${id(identifier, i.subjectId, native)} and ${exact(identifier, i.bindingRevision, targetIdentifierRevision)} and ${id(identifier, i.verifiedAt, mapping.clock.encodeInstant(current.now))})`,
201
+ sql`exists(select 1 from ${credential.name} where ${exact(credential, c.moduleId, input.moduleId)} and ${exact(credential, c.credentialId, targetCredentialId)} and ${id(credential, c.subjectId, native)} and ${exact(credential, c.credentialRevision, targetCredentialRevision)} and ${exact(credential, c.identifierNamespace, input.target.namespace)} and ${exact(credential, c.identifierValue, input.target.value)} and ${activeCredential})`
202
+ ];
203
+ if (source !== void 0) conditions.push(sql`exists(select 1 from ${identifier.name} where ${identifierKey(source.identifier)} and ${id(identifier, i.subjectId, native)} and ${exact(identifier, i.bindingRevision, sourceIdentifierRevision)} and not (${tables.expression(i.d1CurrentCondition({
204
+ identifier: source.identifier,
205
+ nativeSubjectId: native,
206
+ bindingRevision: sourceIdentifierRevision
207
+ }))}))`, sql`exists(select 1 from ${credential.name} where ${exact(credential, c.moduleId, input.moduleId)} and ${exact(credential, c.credentialId, source.credentialId)} and ${id(credential, c.subjectId, native)} and ${exact(credential, c.credentialRevision, sourceCredentialRevision)} and not (${activeCredential}))`, sql`exists(select 1 from ${authority.name} where ${id(authority, a.subjectId, native)} and ${exact(authority, a.credentialId, source.credentialId)} and ${exact(authority, a.revision, sourceCredentialRevision)} and not (${activeAuthority}))`);
208
+ yield* registerSqlBatchPostcondition({
209
+ name: "email-address-authority",
210
+ statement: sqlBatchAssertion(sql, sql.and(conditions))
211
+ });
212
+ } else yield* registerSqlPostcondition({
213
+ name: "email-address-authority",
214
+ check: Effect.gen(function* () {
215
+ const final = yield* reader.read({
216
+ validity: redeemed.validUntil,
217
+ moduleId: input.moduleId,
218
+ subjectId: revision.subjectId,
219
+ identifier: input.target,
220
+ ...source === void 0 ? {} : {
221
+ sourceCredentialId: source.credentialId,
222
+ sourceIdentifier: source.identifier
223
+ }
224
+ });
225
+ ensureEmail(final !== void 0 && sameEmailRevision(final.revision, revision) && final.now >= current.now && final.now < deadline && final.targetSnapshot !== void 0 && final.targetSnapshot.credentialId === targetCredentialId && final.targetSnapshot.credentialRevision === targetCredentialRevision && final.targetSnapshot.identifierRevision === targetIdentifierRevision && (yield* mapping.decodeInstant(final.targetIdentifier[i.verifiedAt])) === current.now);
226
+ const policy = yield* s.decodeActionRequirement(final.subject, action);
227
+ ensureEmail(passwordEvidenceSatisfiedAt(input.authorization.evidence, policy, final.now));
228
+ if (source !== void 0) ensureEmail(final.sourceIdentifier !== void 0 && final.sourceCredential !== void 0 && final.sourceAuthority !== void 0 && (yield* mapping.subjectId.toSubject(final.sourceAuthority[a.subjectId])) === revision.subjectId && final.sourceAuthority[a.credentialId] === source.credentialId && final.sourceAuthority[a.revision] === sourceCredentialRevision && !a.isActiveStatus(final.sourceAuthority[a.status]) && (yield* mapping.subjectId.toSubject(final.sourceIdentifier[i.subjectId])) === revision.subjectId && final.sourceIdentifier[i.bindingRevision] === sourceIdentifierRevision && !i.isCurrent(final.sourceIdentifier) && final.sourceCredential[c.credentialRevision] === sourceCredentialRevision && !c.isActiveStatus(final.sourceCredential[c.status]));
229
+ }).pipe(Effect.mapError((cause) => PersistenceMappingError.make({
230
+ operation: "decode",
231
+ cause
232
+ })))
233
+ });
234
+ return yield* prepare("changed", project);
235
+ }));
236
+ return { emailAddressPersistence: E.EmailAddressPersistence.of({
237
+ target: (input) => executor.read(Effect.flatMap(target(input), (value) => value === void 0 ? Effect.fail(emailUnavailable()) : Effect.succeed(value.target))),
238
+ verifyWithProof: (input, project) => mutate(input, "verify-address", project),
239
+ changeWithProof: (input, project) => mutate(input, "change-address", project)
240
+ }) };
241
+ });
242
+ //#endregion
243
+ export { makeNativeEmailAddressServices, makeNativeEmailSignInServices };
244
+
245
+ //# sourceMappingURL=email-native.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"email-native.mjs","names":["unavailable"],"sources":["../../src/internal/email-native.ts"],"sourcesContent":["import * as E from \"@yielded/auth/Email\";\nimport { CurrentCommitJournal, type LifecycleHooks } from \"@yielded/auth/Hooks\";\nimport { ProofRedemptionInput } from \"@yielded/auth/Proofs\";\nimport type { AuthenticationRevision } from \"@yielded/auth/Sessions\";\nimport { SecurityRevision } from \"@yielded/auth/Sessions\";\nimport { Crypto, DateTime, Effect, Schema } from \"effect\";\nimport { SqlClient } from \"effect/sql/SqlClient\";\nimport type { Fragment } from \"effect/sql/Statement\";\n\nimport { sqlBatchAssertion } from \"./d1-planning\";\nimport {\n makeNativeEmailReader,\n emailUnavailable as unavailable,\n ensureEmail as ensure,\n} from \"./email-native-state\";\nimport {\n allocateEmailValue,\n allocateEmailSecurityRevision,\n snapshotEmailMutation,\n validateEmailMutation,\n sameEmailRevision,\n} from \"./email-policy\";\nimport { PersistenceMappingError } from \"./mapping-error\";\nimport type { AnyEmailAddressMapping, AnyEmailSignInMapping } from \"./models/email-model\";\nimport type { AnyProofPersistenceMapping } from \"./models/proof-model\";\nimport type { NativeSqlTables, SqlTable } from \"./native-sql-table\";\nimport { passwordEvidenceSatisfiedAt } from \"./password-policy\";\nimport { makeNativeProofStore } from \"./proof-native\";\nimport { exactSqlText, executeSqlChange } from \"./sql-change\";\nimport {\n appendSqlBatchStatement,\n makeSqlCommitExecutor,\n registerSqlBatchPostcondition,\n registerSqlCommitReceipt,\n registerSqlPostcondition,\n SqlBatchCommit,\n} from \"./sql-commit\";\n\nexport const makeNativeEmailSignInServices = Effect.fnUntraced(function* (\n tables: NativeSqlTables,\n mapping: AnyEmailSignInMapping,\n): Effect.fn.Return<\n { readonly emailSignInTargets: E.EmailSignInTargets[\"Service\"] },\n never,\n SqlClient | LifecycleHooks\n> {\n const executor = yield* makeSqlCommitExecutor(unavailable);\n const reader = yield* makeNativeEmailReader(tables, mapping);\n\n return {\n emailSignInTargets: E.EmailSignInTargets.of({\n lookup: (input) => executor.read(reader.lookup(input)),\n }),\n };\n});\n\nexport const makeNativeEmailAddressServices = Effect.fnUntraced(function* (\n tables: NativeSqlTables,\n mapping: AnyEmailAddressMapping,\n proofs?: AnyProofPersistenceMapping,\n): Effect.fn.Return<\n { readonly emailAddressPersistence: E.EmailAddressPersistence[\"Service\"] },\n never,\n SqlClient | LifecycleHooks | Crypto.Crypto | SqlBatchCommit\n> {\n const batch = yield* SqlBatchCommit;\n\n const sql = (yield* SqlClient).withoutTransforms(),\n executor = yield* makeSqlCommitExecutor(unavailable),\n crypto = yield* Crypto.Crypto;\n\n const now = tables.expression(mapping.clock.engineNowMillis);\n const reader = yield* makeNativeEmailReader(tables, mapping, now);\n\n const s = mapping.subject,\n i = mapping.identifier,\n c = mapping.credential,\n a = mapping.authorityCredential;\n\n const subject = tables(s.table),\n identifier = tables(i.table),\n credential = tables(c.table),\n authority = tables(a.table);\n\n const exact = (t: SqlTable, key: string, value: unknown) =>\n exactSqlText(sql, t.column(key), t.value(key, value));\n\n const id = (t: SqlTable, key: string, value: unknown) =>\n sql`${t.column(key)} = ${t.value(key, value)}`;\n\n const identifierKey = (value: { readonly namespace: string; readonly value: string }) =>\n sql.and([\n exact(identifier, i.namespace, value.namespace),\n exact(identifier, i.value, value.value),\n ]);\n\n const activeSubject = id(subject, s.status, s.activeStatusValue),\n activeCredential = id(credential, c.status, c.activeStatusValue),\n activeAuthority = id(authority, a.status, a.activeStatusValue);\n\n const lock = sql.onDialectOrElse({ sqlite: () => sql``, orElse: () => sql`for update` });\n const mode = \"interactive\";\n\n const run = <A, X, R>(work: Effect.Effect<A, X, R>) =>\n batch === undefined\n ? executor.run(work.pipe(Effect.provideService(Crypto.Crypto, crypto)))\n : executor\n .batch(work.pipe(Effect.provideService(Crypto.Crypto, crypto)))\n .pipe(Effect.provideService(SqlBatchCommit, batch));\n\n const stage = Effect.fnUntraced(function* (statement: Fragment) {\n if (batch === undefined) ensure((yield* executeSqlChange(sql, statement)) === 1);\n else {\n yield* appendSqlBatchStatement(sql`${statement}`);\n yield* appendSqlBatchStatement(sqlBatchAssertion(sql, sql`changes() = 1`));\n }\n });\n\n const prepare = <A>(\n decision: E.EmailAddressDecision,\n project: E.PrepareEmailCommit<E.EmailAddressDecision, A>,\n ) =>\n Effect.gen(function* () {\n const receipt = project(decision, yield* CurrentCommitJournal);\n\n yield* registerSqlCommitReceipt(receipt);\n\n return receipt;\n });\n\n const target = Effect.fnUntraced(function* (\n input: Parameters<E.EmailAddressPersistence[\"Service\"][\"target\"]>[0],\n sourceIdentifier?: { readonly namespace: string; readonly value: string },\n ) {\n const state = yield* reader.read({\n moduleId: input.moduleId,\n subjectId: input.subjectId,\n identifier: input.target,\n ...(input.sourceCredentialId === undefined\n ? {}\n : { sourceCredentialId: input.sourceCredentialId }),\n ...(sourceIdentifier === undefined ? {} : { sourceIdentifier }),\n single: mapping.addressCardinality === \"single\",\n });\n\n if (state === undefined) return undefined;\n\n const owned =\n state.targetIdentifier !== undefined &&\n (yield* mapping.subjectId.toSubject(state.targetIdentifier[i.subjectId])) === input.subjectId;\n\n const mutable =\n owned &&\n mapping.identifier.isMutableTarget(state.targetIdentifier!) &&\n (state.targetCredential === undefined ||\n (!c.isActiveStatus(state.targetCredential[c.status]) &&\n (yield* mapping.subjectId.toSubject(state.targetCredential[c.subjectId])) ===\n input.subjectId));\n\n const source = state.sourceSnapshot;\n\n const eligible =\n (state.targetIdentifier === undefined ? state.targetCredential === undefined : mutable) &&\n (input.sourceCredentialId === undefined || source !== undefined) &&\n (source === undefined ||\n source.identifier.namespace !== input.target.namespace ||\n source.identifier.value !== input.target.value) &&\n !state.cardinalityConflict;\n\n const captured: E.EmailAddressTarget = {\n revision: state.revision,\n eligible,\n ...(source === undefined ? {} : { source }),\n ...(mutable\n ? {\n targetIdentifierRevision: yield* Schema.decodeUnknownEffect(SecurityRevision)(\n state.targetIdentifier![i.bindingRevision],\n ),\n }\n : {}),\n };\n\n return { ...state, target: captured };\n });\n\n const mutate = <A>(\n original: E.EmailAddressMutation,\n action: E.EmailAction,\n project: E.PrepareEmailCommit<E.EmailAddressDecision, A>,\n ) =>\n run(\n Effect.gen(function* () {\n const input = yield* snapshotEmailMutation(original);\n\n const redemption = yield* Schema.decodeEffect(Schema.toCodecIso(ProofRedemptionInput))(\n yield* Schema.encodeEffect(Schema.toCodecIso(ProofRedemptionInput))(\n original.redemption.input,\n ),\n );\n\n const native = yield* mapping.subjectId.toNative(input.captured.revision.subjectId);\n\n const locked =\n yield* sql`select ${subject.fields(\"email_locked_\")} from ${subject.name} where ${id(subject, s.id, native)} limit 2 ${batch === undefined ? lock : sql``}`;\n\n if (locked.length !== 1) return yield* prepare(\"rejected\", project);\n ensure(\n (yield* mapping.subjectId.toSubject(\n subject.decode(locked[0]!, \"email_locked_\")[s.id],\n )) === input.captured.revision.subjectId,\n );\n\n const current = yield* target(\n {\n moduleId: input.moduleId,\n subjectId: input.captured.revision.subjectId,\n target: input.target,\n ...(input.captured.source === undefined\n ? {}\n : { sourceCredentialId: input.captured.source.credentialId }),\n },\n input.captured.source?.identifier,\n );\n\n if (current === undefined || proofs === undefined)\n return yield* prepare(\"rejected\", project);\n const requirement = yield* s.decodeActionRequirement(current.subject, action);\n\n if (\n !(yield* validateEmailMutation(\n mapping,\n { ...input, redemption: { input: redemption, prepare: original.redemption.prepare } },\n action,\n { target: current.target, requirement: Effect.succeed(requirement) },\n current.now,\n ))\n )\n return yield* prepare(\"rejected\", project);\n const requirements = [input.authorization.requirement, requirement];\n\n const boundaries = [\n ...new Set(\n input.authorization.evidence.proofs.flatMap((proof) =>\n requirements.map(\n (r) => DateTime.toEpochMillis(proof.verifiedAt) + r.maximumAgeMillis,\n ),\n ),\n ),\n ]\n .filter((time) => time > current.now)\n .sort((a, b) => a - b);\n\n const deadline = boundaries.find((time) =>\n requirements.some(\n (r) => !passwordEvidenceSatisfiedAt(input.authorization.evidence, r, time),\n ),\n );\n\n ensure(deadline !== undefined);\n const freshness = sql`${now} >= ${current.now} and ${now} < ${deadline}`;\n\n const factorCondition = (revision: AuthenticationRevision) =>\n sql.and([\n sql`(select count(*) from ${authority.name} where ${id(authority, a.subjectId, native)} and ${activeAuthority}) = ${revision.credentials.length}`,\n ...revision.credentials.map(\n (f) =>\n sql`exists(select 1 from ${authority.name} where ${id(authority, a.subjectId, native)} and ${exact(authority, a.credentialId, f.credentialId)} and ${exact(authority, a.revision, f.revision)} and ${activeAuthority})`,\n ),\n ]);\n\n if (batch !== undefined) {\n yield* appendSqlBatchStatement(\n sqlBatchAssertion(\n sql,\n sql.and([\n sql`exists(select 1 from ${subject.name} where ${id(subject, s.id, native)} and ${exact(subject, s.securityRevision, current.revision.securityRevision)} and ${activeSubject})`,\n factorCondition(current.revision),\n freshness,\n ]),\n ),\n );\n if (current.targetIdentifier !== undefined) {\n ensure(i.d1MutableTargetCondition !== undefined);\n yield* appendSqlBatchStatement(\n sqlBatchAssertion(\n sql,\n sql`exists(select 1 from ${identifier.name} where ${identifierKey(input.target)} and ${id(identifier, i.subjectId, native)} and ${tables.expression(i.d1MutableTargetCondition({ identifier: input.target, nativeSubjectId: native }))})`,\n ),\n );\n }\n if (current.target.source !== undefined) {\n ensure(i.d1CurrentCondition !== undefined);\n yield* appendSqlBatchStatement(\n sqlBatchAssertion(\n sql,\n sql`exists(select 1 from ${identifier.name} where ${identifierKey(current.target.source.identifier)} and ${id(identifier, i.subjectId, native)} and ${tables.expression(i.d1CurrentCondition({ identifier: current.target.source.identifier, nativeSubjectId: native, bindingRevision: current.target.source.identifierRevision }))})`,\n ),\n );\n }\n }\n\n const proof = yield* makeNativeProofStore(tables, proofs, batch !== undefined),\n redeemed = yield* proof.redeemLocked(redemption);\n\n yield* registerSqlCommitReceipt(\n original.redemption.prepare(\n redeemed.decision,\n yield* CurrentCommitJournal,\n (value) => value,\n ),\n );\n if (redeemed.decision !== \"redeemed\") return yield* prepare(\"rejected\", project);\n\n const allocate = () =>\n allocateEmailValue(mode, mapping.allocateRevision, mapping.allocateRevisionSync);\n\n const targetIdentifierRevision = yield* allocate(),\n targetCredentialRevision = yield* allocate(),\n sourceIdentifierRevision = yield* allocate(),\n sourceCredentialRevision = yield* allocate();\n\n const confirms =\n action === \"verify-address\" && current.target.targetIdentifierRevision !== undefined;\n\n const nextSecurityRevision = confirms\n ? current.revision.securityRevision\n : yield* allocateEmailSecurityRevision(mapping, mode, current.revision.securityRevision);\n\n ensure(confirms || nextSecurityRevision !== current.revision.securityRevision);\n\n const targetCredentialId =\n current.targetCredential === undefined\n ? yield* allocateEmailValue(\n mode,\n mapping.allocateCredentialId,\n mapping.allocateCredentialIdSync,\n )\n : yield* Schema.decodeUnknownEffect(Schema.String)(\n current.targetCredential[c.credentialId],\n );\n\n const source = current.target.source;\n\n if (action === \"change-address\") {\n ensure(source !== undefined);\n yield* stage(\n sql`${identifier.update(i.encodeRetirement({ source: source.identifier, bindingRevision: sourceIdentifierRevision }))} where ${identifierKey(source.identifier)} and ${id(identifier, i.subjectId, native)} and ${exact(identifier, i.bindingRevision, source.identifierRevision)}`,\n );\n yield* stage(\n sql`${credential.update(c.encodeRetirement({ source: source.identifier, credentialRevision: sourceCredentialRevision }))} where ${exact(credential, c.moduleId, input.moduleId)} and ${exact(credential, c.credentialId, source.credentialId)} and ${id(credential, c.subjectId, native)} and ${exact(credential, c.credentialRevision, source.credentialRevision)} and ${activeCredential}`,\n );\n yield* stage(\n sql`${authority.update(a.encodeRetirement(sourceCredentialRevision))} where ${id(authority, a.subjectId, native)} and ${exact(authority, a.credentialId, source.credentialId)} and ${exact(authority, a.revision, source.credentialRevision)} and ${activeAuthority}`,\n );\n }\n if (current.targetIdentifier === undefined)\n yield* stage(\n identifier.insert(\n i.encodeVerifiedInsert({\n identifier: input.target,\n subjectId: native,\n verifiedAtMillis: current.now,\n bindingRevision: targetIdentifierRevision,\n }),\n ),\n );\n else\n yield* stage(\n sql`${identifier.update(i.encodeVerification({ verifiedAtMillis: current.now, bindingRevision: targetIdentifierRevision }))} where ${identifierKey(input.target)} and ${id(identifier, i.subjectId, native)} and ${exact(identifier, i.bindingRevision, current.targetIdentifier[i.bindingRevision])} and ${identifier.column(i.verifiedAt)} is null`,\n );\n if (current.targetCredential === undefined) {\n yield* stage(\n credential.insert(\n c.encodeVerifiedInsert({\n moduleId: input.moduleId,\n subjectId: native,\n credentialId: targetCredentialId,\n identifier: input.target,\n credentialRevision: targetCredentialRevision,\n }),\n ),\n );\n yield* stage(\n authority.insert(\n a.encodeInsert({\n subjectId: native,\n credentialId: targetCredentialId,\n revision: targetCredentialRevision,\n }),\n ),\n );\n } else {\n const old = current.targetCredential[c.credentialRevision];\n\n yield* stage(\n sql`${credential.update(c.encodeActivation({ identifier: input.target, credentialRevision: targetCredentialRevision }))} where ${exact(credential, c.moduleId, input.moduleId)} and ${exact(credential, c.credentialId, targetCredentialId)} and ${id(credential, c.subjectId, native)} and ${exact(credential, c.credentialRevision, old)}`,\n );\n yield* stage(\n sql`${authority.update(a.encodeActivation(targetCredentialRevision))} where ${id(authority, a.subjectId, native)} and ${exact(authority, a.credentialId, targetCredentialId)} and ${exact(authority, a.revision, old)}`,\n );\n }\n if (!confirms)\n yield* stage(\n sql`${subject.update({ [s.securityRevision]: nextSecurityRevision })} where ${id(subject, s.id, native)} and ${exact(subject, s.securityRevision, current.revision.securityRevision)} and ${activeSubject} and ${freshness}`,\n );\n\n const revision: AuthenticationRevision = {\n subjectId: current.revision.subjectId,\n securityRevision: nextSecurityRevision,\n credentials: [\n ...current.revision.credentials.filter(\n (f) =>\n f.credentialId !== targetCredentialId && f.credentialId !== source?.credentialId,\n ),\n { credentialId: targetCredentialId, revision: targetCredentialRevision },\n ].sort((a, b) => a.credentialId.localeCompare(b.credentialId)),\n };\n\n if (batch !== undefined) {\n ensure(i.d1CurrentCondition !== undefined);\n\n const conditions = [\n redeemed.validUntil,\n freshness,\n factorCondition(revision),\n sql`exists(select 1 from ${subject.name} where ${id(subject, s.id, native)} and ${exact(subject, s.securityRevision, nextSecurityRevision)} and ${activeSubject})`,\n sql`exists(select 1 from ${identifier.name} where ${identifierKey(input.target)} and ${id(identifier, i.subjectId, native)} and ${tables.expression(i.d1CurrentCondition({ identifier: input.target, nativeSubjectId: native, bindingRevision: targetIdentifierRevision }))})`,\n sql`exists(select 1 from ${identifier.name} where ${identifierKey(input.target)} and ${id(identifier, i.subjectId, native)} and ${exact(identifier, i.bindingRevision, targetIdentifierRevision)} and ${id(identifier, i.verifiedAt, mapping.clock.encodeInstant(current.now))})`,\n sql`exists(select 1 from ${credential.name} where ${exact(credential, c.moduleId, input.moduleId)} and ${exact(credential, c.credentialId, targetCredentialId)} and ${id(credential, c.subjectId, native)} and ${exact(credential, c.credentialRevision, targetCredentialRevision)} and ${exact(credential, c.identifierNamespace, input.target.namespace)} and ${exact(credential, c.identifierValue, input.target.value)} and ${activeCredential})`,\n ];\n\n if (source !== undefined)\n conditions.push(\n sql`exists(select 1 from ${identifier.name} where ${identifierKey(source.identifier)} and ${id(identifier, i.subjectId, native)} and ${exact(identifier, i.bindingRevision, sourceIdentifierRevision)} and not (${tables.expression(i.d1CurrentCondition({ identifier: source.identifier, nativeSubjectId: native, bindingRevision: sourceIdentifierRevision }))}))`,\n sql`exists(select 1 from ${credential.name} where ${exact(credential, c.moduleId, input.moduleId)} and ${exact(credential, c.credentialId, source.credentialId)} and ${id(credential, c.subjectId, native)} and ${exact(credential, c.credentialRevision, sourceCredentialRevision)} and not (${activeCredential}))`,\n sql`exists(select 1 from ${authority.name} where ${id(authority, a.subjectId, native)} and ${exact(authority, a.credentialId, source.credentialId)} and ${exact(authority, a.revision, sourceCredentialRevision)} and not (${activeAuthority}))`,\n );\n yield* registerSqlBatchPostcondition({\n name: \"email-address-authority\",\n statement: sqlBatchAssertion(sql, sql.and(conditions)),\n });\n } else\n yield* registerSqlPostcondition({\n name: \"email-address-authority\",\n check: Effect.gen(function* () {\n const final = yield* reader.read({\n validity: redeemed.validUntil,\n moduleId: input.moduleId,\n subjectId: revision.subjectId,\n identifier: input.target,\n ...(source === undefined\n ? {}\n : {\n sourceCredentialId: source.credentialId,\n sourceIdentifier: source.identifier,\n }),\n });\n\n ensure(\n final !== undefined &&\n sameEmailRevision(final.revision, revision) &&\n final.now >= current.now &&\n final.now < deadline &&\n final.targetSnapshot !== undefined &&\n final.targetSnapshot.credentialId === targetCredentialId &&\n final.targetSnapshot.credentialRevision === targetCredentialRevision &&\n final.targetSnapshot.identifierRevision === targetIdentifierRevision &&\n (yield* mapping.decodeInstant(final.targetIdentifier![i.verifiedAt])) ===\n current.now,\n );\n const policy = yield* s.decodeActionRequirement(final.subject, action);\n\n ensure(passwordEvidenceSatisfiedAt(input.authorization.evidence, policy, final.now));\n if (source !== undefined)\n ensure(\n final.sourceIdentifier !== undefined &&\n final.sourceCredential !== undefined &&\n final.sourceAuthority !== undefined &&\n (yield* mapping.subjectId.toSubject(final.sourceAuthority[a.subjectId])) ===\n revision.subjectId &&\n final.sourceAuthority[a.credentialId] === source.credentialId &&\n final.sourceAuthority[a.revision] === sourceCredentialRevision &&\n !a.isActiveStatus(final.sourceAuthority[a.status]) &&\n (yield* mapping.subjectId.toSubject(final.sourceIdentifier[i.subjectId])) ===\n revision.subjectId &&\n final.sourceIdentifier[i.bindingRevision] === sourceIdentifierRevision &&\n !i.isCurrent(final.sourceIdentifier) &&\n final.sourceCredential[c.credentialRevision] === sourceCredentialRevision &&\n !c.isActiveStatus(final.sourceCredential[c.status]),\n );\n }).pipe(\n Effect.mapError((cause) =>\n PersistenceMappingError.make({ operation: \"decode\", cause }),\n ),\n ),\n });\n\n return yield* prepare(\"changed\", project);\n }),\n );\n\n return {\n emailAddressPersistence: E.EmailAddressPersistence.of({\n target: (input) =>\n executor.read(\n Effect.flatMap(target(input), (value) =>\n value === undefined ? Effect.fail(unavailable()) : Effect.succeed(value.target),\n ),\n ),\n verifyWithProof: (input, project) => mutate(input, \"verify-address\", project),\n changeWithProof: (input, project) => mutate(input, \"change-address\", project),\n }),\n };\n});\n"],"mappings":"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"}
@@ -0,0 +1,92 @@
1
+ import { PersistenceMappingError } from "./mapping-error.mjs";
2
+ import { passwordEvidenceSatisfiedAt } from "./password-policy.mjs";
3
+ import { Effect } from "effect";
4
+ import { EmailUnavailable, snapshotEmailCredential, snapshotEmailRequirement, snapshotEmailRevision } from "@yielded/auth/Email";
5
+ import { snapshotAuthenticationEvidence } from "@yielded/auth/Sessions";
6
+ //#region src/internal/email-policy.ts
7
+ const unavailable = () => EmailUnavailable.make({});
8
+ const sameIdentifier = (left, right) => left.namespace === right.namespace && left.value === right.value;
9
+ const sameEmailRevision = (left, right) => {
10
+ if (left.subjectId !== right.subjectId || left.securityRevision !== right.securityRevision || left.credentials.length !== right.credentials.length) return false;
11
+ const expected = [...left.credentials].sort((a, b) => a.credentialId.localeCompare(b.credentialId));
12
+ const actual = [...right.credentials].sort((a, b) => a.credentialId.localeCompare(b.credentialId));
13
+ return expected.every((item, index) => item.credentialId === actual[index].credentialId && item.revision === actual[index].revision);
14
+ };
15
+ const emailActionModule = (moduleId, action) => `${moduleId}/${action === "verify-address" ? "verify-address" : "change-address"}`;
16
+ const emailActionPurpose = (action) => action === "verify-address" ? "email-address-verification" : "email-address-change";
17
+ const emailRedemptionMatches = (input, action) => {
18
+ const completion = input.redemption.input;
19
+ const binding = completion.binding;
20
+ return completion.moduleId === emailActionModule(input.moduleId, action) && completion.purpose === emailActionPurpose(action) && binding._tag === "IdentifierChange" && sameIdentifier(binding.identifier, input.target) && sameEmailRevision(binding.revision, input.captured.revision);
21
+ };
22
+ const snapshotEmailMutation = Effect.fn("EmailAddressPersistence.snapshotMutation")(function* (input) {
23
+ const evidence = yield* snapshotAuthenticationEvidence(input.authorization.evidence).pipe(Effect.mapError(unavailable));
24
+ const requirement = yield* snapshotEmailRequirement(input.authorization.requirement);
25
+ const source = input.captured.source === void 0 ? void 0 : yield* snapshotEmailCredential(input.captured.source);
26
+ return Object.freeze({
27
+ ...input,
28
+ target: Object.freeze({ ...input.target }),
29
+ ...input.invalidation === void 0 ? {} : { invalidation: Object.freeze({ ...input.invalidation }) },
30
+ captured: Object.freeze({
31
+ eligible: input.captured.eligible,
32
+ revision: snapshotEmailRevision(input.captured.revision),
33
+ ...input.captured.targetIdentifierRevision === void 0 ? {} : { targetIdentifierRevision: input.captured.targetIdentifierRevision },
34
+ ...source === void 0 ? {} : { source }
35
+ }),
36
+ authorization: Object.freeze({
37
+ challenge: Object.freeze({
38
+ ...input.authorization.challenge,
39
+ target: Object.freeze({ ...input.authorization.challenge.target }),
40
+ revision: snapshotEmailRevision(input.authorization.challenge.revision)
41
+ }),
42
+ evidence,
43
+ requirement
44
+ })
45
+ });
46
+ });
47
+ const validateEmailMutation = Effect.fn("EmailAddressPersistence.validateAuthority")(function* (policy, input, action, current, now) {
48
+ const confirmsExisting = action === "verify-address" && input.captured.targetIdentifierRevision !== void 0;
49
+ if (!input.captured.eligible || !emailRedemptionMatches(input, action) || input.authorization.challenge.moduleId !== input.moduleId || input.authorization.challenge.action !== action || input.authorization.challenge.commandId !== input.commandId || !sameIdentifier(input.authorization.challenge.target, input.target) || input.authorization.challenge.sourceCredentialId !== input.captured.source?.credentialId || !sameEmailRevision(input.authorization.challenge.revision, input.captured.revision) || input.authorization.challenge.targetIdentifierRevision !== input.captured.targetIdentifierRevision || input.authorization.evidence.flowId !== input.commandId || input.authorization.evidence.bindingDigest !== input.authorization.challenge.bindingDigest || !sameEmailRevision(input.authorization.evidence.revision, input.captured.revision) || action === "verify-address" && input.captured.source !== void 0 || action === "change-address" && input.captured.source === void 0 || confirmsExisting !== (input.invalidation === void 0) || input.invalidation?.existingSessions === "immediate" && policy.sessionInvalidation !== "same-authority-immediate") return false;
50
+ if (current === void 0 || !current.target.eligible || !sameEmailRevision(current.target.revision, input.captured.revision) || current.target.targetIdentifierRevision !== input.captured.targetIdentifierRevision || input.captured.source !== void 0 && (current.target.source === void 0 || current.target.source.identifierRevision !== input.captured.source.identifierRevision || current.target.source.credentialRevision !== input.captured.source.credentialRevision || !sameIdentifier(current.target.source.identifier, input.captured.source.identifier))) return false;
51
+ const currentRequirement = yield* current.requirement;
52
+ return passwordEvidenceSatisfiedAt(input.authorization.evidence, input.authorization.requirement, now) && passwordEvidenceSatisfiedAt(input.authorization.evidence, currentRequirement, now);
53
+ });
54
+ const allocateEmailValue = (mode, asynchronous, synchronous) => {
55
+ if (mode === "synchronous") return synchronous === void 0 ? Effect.fail(unavailable()) : Effect.try({
56
+ try: synchronous,
57
+ catch: (cause) => PersistenceMappingError.make({
58
+ operation: "mapping",
59
+ cause
60
+ })
61
+ });
62
+ if (asynchronous !== void 0) return asynchronous;
63
+ return synchronous === void 0 ? Effect.fail(unavailable()) : Effect.try({
64
+ try: synchronous,
65
+ catch: (cause) => PersistenceMappingError.make({
66
+ operation: "mapping",
67
+ cause
68
+ })
69
+ });
70
+ };
71
+ const allocateEmailSecurityRevision = (mapping, mode, current) => {
72
+ if (mode === "synchronous") return mapping.subject.nextSecurityRevisionSync === void 0 ? Effect.fail(unavailable()) : Effect.try({
73
+ try: () => mapping.subject.nextSecurityRevisionSync(current),
74
+ catch: (cause) => PersistenceMappingError.make({
75
+ operation: "mapping",
76
+ cause
77
+ })
78
+ });
79
+ if (mapping.subject.nextSecurityRevision !== void 0) return mapping.subject.nextSecurityRevision(current);
80
+ if (mapping.subject.nextSecurityRevisionSync !== void 0) return Effect.try({
81
+ try: () => mapping.subject.nextSecurityRevisionSync(current),
82
+ catch: (cause) => PersistenceMappingError.make({
83
+ operation: "mapping",
84
+ cause
85
+ })
86
+ });
87
+ return Effect.fail(unavailable());
88
+ };
89
+ //#endregion
90
+ export { allocateEmailSecurityRevision, allocateEmailValue, emailActionModule, emailActionPurpose, emailRedemptionMatches, sameEmailRevision, snapshotEmailMutation, validateEmailMutation };
91
+
92
+ //# sourceMappingURL=email-policy.mjs.map