@yielded/auth-persistence 0.1.0-beta.25 → 0.1.0-beta.27

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 +14 -81
  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 +26 -147
  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 -354
  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 -1556
  439. package/src/internal/oauth/accounts.ts +0 -839
  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 -692
  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 -1523
  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,175 @@
1
+ import { sqlBatchAssertion } from "./d1-planning.mjs";
2
+ import { exactSqlText } from "./sql-change.mjs";
3
+ import { CurrentSqlCommit, SqlBatchCommit, makeSqlCommitExecutor, registerSqlBatchPostcondition, registerSqlCommitReceipt, registerSqlPostcondition } from "./sql-commit.mjs";
4
+ import { passkeyOperationInputs } from "./passkey-inputs.mjs";
5
+ import { passkeyAssertionPurposes, passkeyCredentialKey, passkeyMatchesAccess, validPasskeyCeremony } from "./passkey-policy.mjs";
6
+ import { makePasskeyNativeReadState, makePasskeyNativeState, passkeyNativeInvariant } from "./passkey-native-state.mjs";
7
+ import { Crypto, Effect, Option, Schema } from "effect";
8
+ import { CurrentCommitJournal } from "@yielded/auth/Hooks";
9
+ import * as M from "@yielded/auth/Passkey";
10
+ import { SqlError } from "effect/sql/SqlError";
11
+ //#region src/internal/passkey-native.ts
12
+ const unavailable = () => M.PasskeyUnavailable.make({});
13
+ const preparePasskeyNative = (value, prepare) => Effect.gen(function* () {
14
+ const receipt = prepare(value, yield* CurrentCommitJournal);
15
+ passkeyNativeInvariant(receipt?._tag === "PreparedCommit" && Effect.isEffect(receipt.read));
16
+ yield* registerSqlCommitReceipt(receipt);
17
+ return receipt;
18
+ });
19
+ const services = Effect.fnUntraced(function* (tables, mapping, batch) {
20
+ const boundOwner = yield* Effect.serviceOption(CurrentSqlCommit);
21
+ const state = yield* makePasskeyNativeState(tables, mapping);
22
+ const executor = yield* makeSqlCommitExecutor(unavailable);
23
+ const crypto = yield* Crypto.Crypto;
24
+ const { sql, ceremony: flow, credential } = state;
25
+ const read = mapping.read;
26
+ const provide = (effect) => Effect.provideService(effect, Crypto.Crypto, crypto);
27
+ const run = (effect, mode = "transaction") => batch === void 0 ? executor.run(provide(effect), mode) : executor.batch(provide(effect)).pipe(Effect.provideService(SqlBatchCommit, batch));
28
+ const advisory = (effect) => executor.read(provide(effect));
29
+ const issue = (original, prepare) => run(Effect.gen(function* () {
30
+ const ceremony = M.snapshotPasskeySync(passkeyOperationInputs.issue, original).ceremony;
31
+ if (!flow.validModule(ceremony.moduleId) || !validPasskeyCeremony(ceremony) || ceremony.purpose === "registration") return yield* preparePasskeyNative({ _tag: "Rejected" }, prepare);
32
+ const statement = flow.insert(ceremony);
33
+ let changed;
34
+ if (batch !== void 0) {
35
+ yield* flow.stage(statement, 1);
36
+ changed = 1;
37
+ } else changed = yield* flow.change(statement).pipe(Effect.catchIf((error) => Schema.is(SqlError)(error) && error.reason._tag === "UniqueViolation", () => Effect.succeed(0)));
38
+ return yield* preparePasskeyNative(changed === 1 ? {
39
+ _tag: "Issued",
40
+ ceremony
41
+ } : { _tag: "Rejected" }, prepare);
42
+ }), "statement");
43
+ const persistence = {
44
+ issue,
45
+ context: (original) => advisory(Effect.suspend(() => flow.context(M.snapshotPasskeySync(M.PasskeyAccess, original)))),
46
+ consume: (original, prepare) => run(Effect.gen(function* () {
47
+ const input = M.snapshotPasskeySync(passkeyOperationInputs.consume, original);
48
+ const captured = input.credential;
49
+ const revision = captured.revision.credentials.find((entry) => entry.credentialId === captured.credentialId);
50
+ const assertion = input.assertion;
51
+ if (!flow.validModule(input.access.moduleId) || !passkeyMatchesAccess(input.ceremony, input.access) || !passkeyAssertionPurposes.some((purpose) => purpose === input.ceremony.purpose) || !validPasskeyCeremony(input.ceremony) || revision === void 0 || !captured.active || captured.rpId !== input.ceremony.profile.rpId || assertion.protocolCredentialId !== captured.protocolCredentialId || assertion.backupEligible !== captured.backupEligible || assertion.userHandle !== void 0 && assertion.userHandle !== captured.userHandle) return yield* preparePasskeyNative("Rejected", prepare);
52
+ const consumed = flow.consume(input.access, input.ceremony);
53
+ if (batch === void 0) {
54
+ if ((yield* flow.change(consumed)) !== 1) return yield* preparePasskeyNative("Rejected", prepare);
55
+ } else yield* flow.stage(consumed, 1);
56
+ const key = yield* passkeyCredentialKey(captured.rpId, captured.protocolCredentialId);
57
+ const exact = (column, value) => exactSqlText(sql, credential.column(column), credential.value(column, value));
58
+ const counter = credential.column(read.credential.counter);
59
+ const next = credential.value(read.credential.counter, assertion.counter);
60
+ const merged = captured.backupEligible ? sql`case when ${counter} > ${next} then ${counter} else ${next} end` : next;
61
+ const identity = [
62
+ exact(read.credential.credentialId, captured.credentialId),
63
+ exact(read.credential.credentialKey, key),
64
+ exact(read.credential.credentialRevision, revision.revision),
65
+ sql`${credential.column(read.credential.backupEligible)} = ${credential.value(read.credential.backupEligible, mapping.telemetry.encodeBackupEligible(captured.backupEligible))}`,
66
+ state.active("credential")
67
+ ];
68
+ const statement = sql`${credential.update({
69
+ [read.credential.counter]: merged,
70
+ [read.credential.backupState]: mapping.telemetry.encodeBackupState(assertion.backupState),
71
+ [mapping.telemetry.lastUsedAt]: state.storedNow
72
+ })} where ${sql.and([...identity, captured.backupEligible ? sql`true` : sql`((${counter} = 0 and ${next} = 0) or ${counter} < ${next})`])}`;
73
+ let changed;
74
+ if (batch === void 0) {
75
+ changed = yield* flow.change(statement);
76
+ if (changed === 0 && sql.onDialectOrElse({
77
+ mysql: () => true,
78
+ orElse: () => false
79
+ }) && (captured.backupEligible || assertion.counter === 0)) {
80
+ if ((yield* sql`select 1 as matched from ${credential.name} where ${sql.and(identity)} and ${captured.backupEligible ? sql`${counter} >= ${next}` : sql`${counter} = 0`} and ${credential.column(read.credential.backupState)} = ${credential.value(read.credential.backupState, mapping.telemetry.encodeBackupState(assertion.backupState))}`).length === 1) changed = 1;
81
+ }
82
+ } else {
83
+ yield* flow.stage(statement, 1);
84
+ changed = 1;
85
+ }
86
+ if (Option.isSome(boundOwner)) {
87
+ const acceptedCounter = captured.backupEligible ? sql`${counter} >= ${credential.value(read.credential.counter, Math.max(captured.counter, assertion.counter))}` : sql`${counter} = ${next}`;
88
+ const condition = sql.and([flow.absent(input.access), changed === 1 ? sql`exists(select 1 from ${credential.name} where ${sql.and(identity)} and ${acceptedCounter}
89
+ and ${credential.column(read.credential.backupState)} = ${credential.value(read.credential.backupState, mapping.telemetry.encodeBackupState(assertion.backupState))})` : sql`true`]);
90
+ if (batch === void 0) yield* registerSqlPostcondition({
91
+ name: "passkey-consume-preserved",
92
+ check: Effect.gen(function* () {
93
+ const rows = yield* sql`select 1 where ${condition}`;
94
+ passkeyNativeInvariant(rows.length === 1);
95
+ })
96
+ });
97
+ else yield* registerSqlBatchPostcondition({
98
+ name: "passkey-consume-preserved",
99
+ statement: sqlBatchAssertion(sql, condition)
100
+ });
101
+ }
102
+ return yield* preparePasskeyNative(changed === 1 ? "Verified" : "Rejected", prepare);
103
+ })),
104
+ cleanup: (original, prepare) => run(Effect.gen(function* () {
105
+ const input = M.snapshotPasskeySync(passkeyOperationInputs.cleanup, original);
106
+ passkeyNativeInvariant(flow.validModule(input.moduleId));
107
+ return yield* preparePasskeyNative(yield* flow.cleanup(input.moduleId, input.limit, batch !== void 0), prepare);
108
+ }), "statement")
109
+ };
110
+ const credentials = makePasskeyNativeCredentialService(state, read, advisory);
111
+ return {
112
+ batch: batch !== void 0,
113
+ state,
114
+ executor,
115
+ run,
116
+ advisory,
117
+ passkeyPersistence: persistence,
118
+ passkeyCredentials: credentials
119
+ };
120
+ });
121
+ const makeNativePasskeyServices = (tables, mapping) => services(tables, mapping);
122
+ const makeBatchPasskeyServices = (tables, mapping) => Effect.flatMap(SqlBatchCommit, (batch) => services(tables, mapping, batch));
123
+ const makePasskeyNativeCredentialService = (state, read, advisory) => {
124
+ const { sql, joinedSubject: subject, joinedFactor: factor, joinedCredential: credential } = state;
125
+ return {
126
+ lookup: (original) => advisory(Effect.gen(function* () {
127
+ const input = M.snapshotPasskeySync(passkeyOperationInputs.lookup, original);
128
+ return yield* state.lookup(input.rpId, input.protocolCredentialId);
129
+ })),
130
+ listForSubject: (original) => advisory(Effect.gen(function* () {
131
+ const input = M.snapshotPasskeySync(passkeyOperationInputs.listForSubject, original);
132
+ const nativeId = state.native(input.subjectId);
133
+ const rows = yield* sql`select ${subject.fields("s_")}, ${factor.fields("f_")}, ${credential.fields("c_")}
134
+ from ${state.selected("subject", "passkey_subject")}
135
+ left join ${state.selected("authority", "passkey_factor")} on ${factor.column(read.authority.subjectId)} = ${factor.value(read.authority.subjectId, nativeId)}
136
+ left join ${state.selected("credential", "passkey_credential")} on ${credential.column(read.credential.subjectId)} = ${credential.value(read.credential.subjectId, nativeId)} and ${credential.column(read.credential.rpId)} = ${credential.value(read.credential.rpId, input.rpId)}
137
+ where ${subject.column(read.subject.id)} = ${subject.value(read.subject.id, nativeId)} limit 4097`;
138
+ if (rows.length === 0 || rows.length > 4096) return void 0;
139
+ const subjectRow = subject.decode(rows[0], "s_");
140
+ passkeyNativeInvariant(rows.every((selected) => {
141
+ const other = subject.decode(selected, "s_");
142
+ return state.sameId(read.subject.decodeId(other), nativeId) && other[read.subject.securityRevision] === subjectRow[read.subject.securityRevision];
143
+ }));
144
+ const revision = state.revision(subjectRow, rows.map((row) => factor.decode(row, "f_")));
145
+ passkeyNativeInvariant(revision.subjectId === input.subjectId);
146
+ const values = /* @__PURE__ */ new Map();
147
+ for (const selected of rows) {
148
+ const row = credential.decode(selected, "c_");
149
+ if (row[read.credential.credentialId] === null) continue;
150
+ const decoded = yield* state.decodeCredential(row, revision, subjectRow);
151
+ if (decoded !== void 0) values.set(decoded.credentialId, decoded);
152
+ }
153
+ const userHandle = values.values().next().value?.userHandle;
154
+ return M.snapshotPasskeySync(M.PasskeyEnrollmentSnapshot, {
155
+ revision,
156
+ ...userHandle === void 0 ? {} : { userHandle },
157
+ credentials: [...values.values()].map((value) => ({
158
+ type: "public-key",
159
+ id: value.protocolCredentialId
160
+ }))
161
+ });
162
+ }))
163
+ };
164
+ };
165
+ const makeNativePasskeyCredentialServices = Effect.fnUntraced(function* (tables, mapping) {
166
+ const state = yield* makePasskeyNativeReadState(tables, mapping);
167
+ const executor = yield* makeSqlCommitExecutor(unavailable);
168
+ const crypto = yield* Crypto.Crypto;
169
+ const advisory = (effect) => executor.read(Effect.provideService(effect, Crypto.Crypto, crypto));
170
+ return { passkeyCredentials: makePasskeyNativeCredentialService(state, mapping, advisory) };
171
+ });
172
+ //#endregion
173
+ export { makeBatchPasskeyServices, makeNativePasskeyCredentialServices, makeNativePasskeyServices, preparePasskeyNative };
174
+
175
+ //# sourceMappingURL=passkey-native.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"passkey-native.mjs","names":[],"sources":["../../src/internal/passkey-native.ts"],"sourcesContent":["import { CurrentCommitJournal } from \"@yielded/auth/Hooks\";\nimport * as M from \"@yielded/auth/Passkey\";\nimport { Crypto, Effect, Option, Schema } from \"effect\";\nimport { SqlError } from \"effect/sql/SqlError\";\n\nimport { sqlBatchAssertion } from \"./d1-planning\";\nimport type { NativeSqlTables } from \"./native-sql-table\";\nimport { passkeyOperationInputs } from \"./passkey-inputs\";\nimport {\n makePasskeyNativeReadState,\n makePasskeyNativeState,\n passkeyNativeInvariant,\n type PasskeyNativeMapping,\n type PasskeyNativeRead,\n type PasskeyNativeReadState,\n} from \"./passkey-native-state\";\nimport {\n passkeyAssertionPurposes,\n passkeyCredentialKey,\n passkeyMatchesAccess,\n validPasskeyCeremony,\n} from \"./passkey-policy\";\nimport { exactSqlText } from \"./sql-change\";\nimport {\n CurrentSqlCommit,\n makeSqlCommitExecutor,\n registerSqlCommitReceipt,\n registerSqlPostcondition,\n registerSqlBatchPostcondition,\n SqlBatchCommit,\n} from \"./sql-commit\";\n\nconst unavailable = () => M.PasskeyUnavailable.make({});\n\nexport const preparePasskeyNative = <Value, A>(\n value: Value,\n prepare: M.PreparePasskeyCommit<Value, A>,\n) =>\n Effect.gen(function* () {\n const journal = yield* CurrentCommitJournal;\n\n const receipt = prepare(value, journal);\n\n passkeyNativeInvariant(receipt?._tag === \"PreparedCommit\" && Effect.isEffect(receipt.read));\n yield* registerSqlCommitReceipt(receipt);\n\n return receipt;\n });\n\nconst services = Effect.fnUntraced(function* (\n tables: NativeSqlTables,\n mapping: PasskeyNativeMapping,\n batch?: SqlBatchCommit[\"Service\"],\n) {\n const boundOwner = yield* Effect.serviceOption(CurrentSqlCommit);\n const state = yield* makePasskeyNativeState(tables, mapping);\n const executor = yield* makeSqlCommitExecutor(unavailable);\n const crypto = yield* Crypto.Crypto;\n const { sql, ceremony: flow, credential } = state;\n const read = mapping.read;\n\n const provide = <A, E, R>(effect: Effect.Effect<A, E, R>) =>\n Effect.provideService(effect, Crypto.Crypto, crypto);\n\n const run = <A, E, R>(\n effect: Effect.Effect<A, E, R>,\n mode: \"transaction\" | \"statement\" = \"transaction\",\n ) =>\n batch === undefined\n ? executor.run(provide(effect), mode)\n : executor.batch(provide(effect)).pipe(Effect.provideService(SqlBatchCommit, batch));\n\n const advisory = <A, E, R>(effect: Effect.Effect<A, E, R>) => executor.read(provide(effect));\n\n const issue: M.PasskeyPersistence[\"Service\"][\"issue\"] = (original, prepare) =>\n run(\n Effect.gen(function* () {\n const input = M.snapshotPasskeySync(passkeyOperationInputs.issue, original);\n const ceremony = input.ceremony;\n\n if (\n !flow.validModule(ceremony.moduleId) ||\n !validPasskeyCeremony(ceremony) ||\n ceremony.purpose === \"registration\"\n )\n return yield* preparePasskeyNative({ _tag: \"Rejected\" }, prepare);\n const statement = flow.insert(ceremony);\n let changed: number;\n\n if (batch !== undefined) {\n yield* flow.stage(statement, 1);\n changed = 1;\n } else {\n changed = yield* flow.change(statement).pipe(\n Effect.catchIf(\n (error) => Schema.is(SqlError)(error) && error.reason._tag === \"UniqueViolation\",\n () => Effect.succeed(0),\n ),\n );\n }\n\n return yield* preparePasskeyNative(\n changed === 1 ? { _tag: \"Issued\", ceremony } : { _tag: \"Rejected\" },\n prepare,\n );\n }),\n \"statement\",\n );\n\n const persistence: M.PasskeyPersistence[\"Service\"] = {\n issue,\n context: (original) =>\n advisory(\n Effect.suspend(() => flow.context(M.snapshotPasskeySync(M.PasskeyAccess, original))),\n ),\n consume: (original, prepare) =>\n run(\n Effect.gen(function* () {\n const input = M.snapshotPasskeySync(passkeyOperationInputs.consume, original);\n const captured = input.credential;\n\n const revision = captured.revision.credentials.find(\n (entry) => entry.credentialId === captured.credentialId,\n );\n\n const assertion = input.assertion;\n\n if (\n !flow.validModule(input.access.moduleId) ||\n !passkeyMatchesAccess(input.ceremony, input.access) ||\n !passkeyAssertionPurposes.some((purpose) => purpose === input.ceremony.purpose) ||\n !validPasskeyCeremony(input.ceremony) ||\n revision === undefined ||\n !captured.active ||\n captured.rpId !== input.ceremony.profile.rpId ||\n assertion.protocolCredentialId !== captured.protocolCredentialId ||\n assertion.backupEligible !== captured.backupEligible ||\n (assertion.userHandle !== undefined && assertion.userHandle !== captured.userHandle)\n )\n return yield* preparePasskeyNative(\"Rejected\", prepare);\n const consumed = flow.consume(input.access, input.ceremony);\n\n if (batch === undefined) {\n if ((yield* flow.change(consumed)) !== 1)\n return yield* preparePasskeyNative(\"Rejected\", prepare);\n } else yield* flow.stage(consumed, 1);\n const key = yield* passkeyCredentialKey(captured.rpId, captured.protocolCredentialId);\n\n const exact = (column: string, value: unknown) =>\n exactSqlText(sql, credential.column(column), credential.value(column, value));\n\n const counter = credential.column(read.credential.counter);\n const next = credential.value(read.credential.counter, assertion.counter);\n\n const merged = captured.backupEligible\n ? sql`case when ${counter} > ${next} then ${counter} else ${next} end`\n : next;\n\n const identity = [\n exact(read.credential.credentialId, captured.credentialId),\n exact(read.credential.credentialKey, key),\n exact(read.credential.credentialRevision, revision.revision),\n sql`${credential.column(read.credential.backupEligible)} = ${credential.value(read.credential.backupEligible, mapping.telemetry.encodeBackupEligible(captured.backupEligible))}`,\n state.active(\"credential\"),\n ];\n\n const statement = sql`${credential.update({\n [read.credential.counter]: merged,\n [read.credential.backupState]: mapping.telemetry.encodeBackupState(\n assertion.backupState,\n ),\n [mapping.telemetry.lastUsedAt]: state.storedNow,\n })} where ${sql.and([\n ...identity,\n captured.backupEligible\n ? sql`true`\n : sql`((${counter} = 0 and ${next} = 0) or ${counter} < ${next})`,\n ])}`;\n\n let changed: number;\n\n if (batch === undefined) {\n changed = yield* flow.change(statement);\n if (\n changed === 0 &&\n sql.onDialectOrElse({ mysql: () => true, orElse: () => false }) &&\n (captured.backupEligible || assertion.counter === 0)\n ) {\n // mysql2 can disable FOUND_ROWS. The UPDATE still holds the row lock;\n // prove the unchanged telemetry matched this exact semantic key.\n const matched =\n yield* sql`select 1 as matched from ${credential.name} where ${sql.and(identity)} and ${captured.backupEligible ? sql`${counter} >= ${next}` : sql`${counter} = 0`} and ${credential.column(read.credential.backupState)} = ${credential.value(read.credential.backupState, mapping.telemetry.encodeBackupState(assertion.backupState))}`;\n\n if (matched.length === 1) changed = 1;\n }\n } else {\n yield* flow.stage(statement, 1);\n changed = 1;\n }\n\n if (Option.isSome(boundOwner)) {\n // Protect the accepted result from later bound application SQL. BE\n // retains the observed accepted floor; it does not compare an entire\n // telemetry snapshot or reject valid out-of-order assertions.\n const acceptedCounter = captured.backupEligible\n ? sql`${counter} >= ${credential.value(read.credential.counter, Math.max(captured.counter, assertion.counter))}`\n : sql`${counter} = ${next}`;\n\n const condition = sql.and([\n flow.absent(input.access),\n changed === 1\n ? sql`exists(select 1 from ${credential.name} where ${sql.and(identity)} and ${acceptedCounter}\n and ${credential.column(read.credential.backupState)} = ${credential.value(read.credential.backupState, mapping.telemetry.encodeBackupState(assertion.backupState))})`\n : sql`true`,\n ]);\n\n if (batch === undefined) {\n yield* registerSqlPostcondition({\n name: \"passkey-consume-preserved\",\n check: Effect.gen(function* () {\n const rows = yield* sql`select 1 where ${condition}`;\n\n passkeyNativeInvariant(rows.length === 1);\n }),\n });\n } else {\n yield* registerSqlBatchPostcondition({\n name: \"passkey-consume-preserved\",\n statement: sqlBatchAssertion(sql, condition),\n });\n }\n }\n\n return yield* preparePasskeyNative(changed === 1 ? \"Verified\" : \"Rejected\", prepare);\n }),\n ),\n cleanup: (original, prepare) =>\n run(\n Effect.gen(function* () {\n const input = M.snapshotPasskeySync(passkeyOperationInputs.cleanup, original);\n\n passkeyNativeInvariant(flow.validModule(input.moduleId));\n\n return yield* preparePasskeyNative(\n yield* flow.cleanup(input.moduleId, input.limit, batch !== undefined),\n prepare,\n );\n }),\n \"statement\",\n ),\n };\n\n const credentials = makePasskeyNativeCredentialService(state, read, advisory);\n\n return {\n batch: batch !== undefined,\n state,\n executor,\n run,\n advisory,\n passkeyPersistence: persistence,\n passkeyCredentials: credentials,\n };\n});\n\nexport const makeNativePasskeyServices = (tables: NativeSqlTables, mapping: PasskeyNativeMapping) =>\n services(tables, mapping);\n\nexport const makeBatchPasskeyServices = (tables: NativeSqlTables, mapping: PasskeyNativeMapping) =>\n Effect.flatMap(SqlBatchCommit, (batch) => services(tables, mapping, batch));\n\nexport type NativePasskeyServices = Effect.Success<ReturnType<typeof makeNativePasskeyServices>>;\n\nconst makePasskeyNativeCredentialService = (\n state: PasskeyNativeReadState,\n read: PasskeyNativeRead,\n advisory: <A, E, R>(\n effect: Effect.Effect<A, E, R>,\n ) => Effect.Effect<\n A,\n M.PasskeyUnavailable,\n Exclude<\n Exclude<Exclude<R, Crypto.Crypto>, import(\"effect/sql/SqlClient\").SqlClient>,\n import(\"@yielded/auth/Hooks\").LifecycleHooks\n >\n >,\n) => {\n const { sql, joinedSubject: subject, joinedFactor: factor, joinedCredential: credential } = state;\n\n const credentials: M.PasskeyCredentials[\"Service\"] = {\n lookup: (original) =>\n advisory(\n Effect.gen(function* () {\n const input = M.snapshotPasskeySync(passkeyOperationInputs.lookup, original);\n\n return yield* state.lookup(input.rpId, input.protocolCredentialId);\n }),\n ),\n listForSubject: (original) =>\n advisory(\n Effect.gen(function* () {\n const input = M.snapshotPasskeySync(passkeyOperationInputs.listForSubject, original);\n\n const nativeId = state.native(input.subjectId);\n\n const rows =\n yield* sql`select ${subject.fields(\"s_\")}, ${factor.fields(\"f_\")}, ${credential.fields(\"c_\")}\n from ${state.selected(\"subject\", \"passkey_subject\")}\n left join ${state.selected(\"authority\", \"passkey_factor\")} on ${factor.column(read.authority.subjectId)} = ${factor.value(read.authority.subjectId, nativeId)}\n left join ${state.selected(\"credential\", \"passkey_credential\")} on ${credential.column(read.credential.subjectId)} = ${credential.value(read.credential.subjectId, nativeId)} and ${credential.column(read.credential.rpId)} = ${credential.value(read.credential.rpId, input.rpId)}\n where ${subject.column(read.subject.id)} = ${subject.value(read.subject.id, nativeId)} limit 4097`;\n\n if (rows.length === 0 || rows.length > 4096) return undefined;\n const subjectRow = subject.decode(rows[0]!, \"s_\");\n\n passkeyNativeInvariant(\n rows.every((selected) => {\n const other = subject.decode(selected, \"s_\");\n\n return (\n state.sameId(read.subject.decodeId(other), nativeId) &&\n other[read.subject.securityRevision] === subjectRow[read.subject.securityRevision]\n );\n }),\n );\n\n const revision = state.revision(\n subjectRow,\n rows.map((row) => factor.decode(row, \"f_\")),\n );\n\n passkeyNativeInvariant(revision.subjectId === input.subjectId);\n const values = new Map<string, M.PasskeyCredential>();\n\n for (const selected of rows) {\n const row = credential.decode(selected, \"c_\");\n\n if (row[read.credential.credentialId] === null) continue;\n const decoded = yield* state.decodeCredential(row, revision, subjectRow);\n\n if (decoded !== undefined) values.set(decoded.credentialId, decoded);\n }\n const userHandle = values.values().next().value?.userHandle;\n\n return M.snapshotPasskeySync(M.PasskeyEnrollmentSnapshot, {\n revision,\n ...(userHandle === undefined ? {} : { userHandle }),\n credentials: [...values.values()].map((value) => ({\n type: \"public-key\" as const,\n id: value.protocolCredentialId,\n })),\n });\n }),\n ),\n };\n\n return credentials;\n};\n\nexport const makeNativePasskeyCredentialServices = Effect.fnUntraced(function* (\n tables: NativeSqlTables,\n mapping: PasskeyNativeRead,\n) {\n const state = yield* makePasskeyNativeReadState(tables, mapping);\n const executor = yield* makeSqlCommitExecutor(unavailable);\n const crypto = yield* Crypto.Crypto;\n\n const advisory = <A, E, R>(effect: Effect.Effect<A, E, R>) =>\n executor.read(Effect.provideService(effect, Crypto.Crypto, crypto));\n\n return { passkeyCredentials: makePasskeyNativeCredentialService(state, mapping, advisory) };\n});\n"],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ import { Crypto, DateTime, Effect, Schema } from "effect";
2
+ import { PasskeyCredential, PasskeyUnavailable, snapshotPasskeySync } from "@yielded/auth/Passkey";
3
+ //#region src/internal/passkey-policy.ts
4
+ const invariant = (value) => {
5
+ if (!value) throw PasskeyUnavailable.make({});
6
+ };
7
+ const encoder = new TextEncoder();
8
+ const decoder = new TextDecoder("utf-8", { fatal: true });
9
+ /** RP tuples have no collation-dependent string identity. */
10
+ const passkeyKey = Effect.fnUntraced(function* (kind, fields) {
11
+ const values = ["effect-auth/passkey/" + kind + "/v1", ...fields].map((field) => {
12
+ const bytes = encoder.encode(field);
13
+ invariant(decoder.decode(bytes) === field);
14
+ return bytes;
15
+ });
16
+ const packed = new Uint8Array(values.reduce((size, bytes) => size + 4 + bytes.length, 0));
17
+ const view = new DataView(packed.buffer);
18
+ let offset = 0;
19
+ for (const bytes of values) {
20
+ view.setUint32(offset, bytes.length, false);
21
+ packed.set(bytes, offset + 4);
22
+ offset += 4 + bytes.length;
23
+ }
24
+ const hashed = yield* (yield* Crypto.Crypto).digest("SHA-256", packed);
25
+ return "v1:" + Array.from(hashed, (value) => value.toString(16).padStart(2, "0")).join("");
26
+ });
27
+ const passkeyCredentialKey = (rpId, id) => passkeyKey("credential", [rpId, id]);
28
+ /** Private passkeyStorage is decoded Type data, never a consumer wire transform. */
29
+ const passkeyStorage = (schema, maximumBytes) => {
30
+ const codec = Schema.fromJsonString(Schema.toCodecJson(Schema.toType(schema)));
31
+ const encode = (value) => {
32
+ const text = "v1:" + Schema.encodeSync(codec)(snapshotPasskeySync(schema, value));
33
+ invariant(encoder.encode(text).length <= maximumBytes);
34
+ return text;
35
+ };
36
+ return {
37
+ encode,
38
+ decode: (text) => {
39
+ invariant(typeof text === "string" && text.startsWith("v1:"));
40
+ invariant(encoder.encode(text).length <= maximumBytes);
41
+ const value = snapshotPasskeySync(schema, Schema.decodeSync(codec)(text.slice(3)));
42
+ invariant(encode(value) === text);
43
+ return value;
44
+ }
45
+ };
46
+ };
47
+ const passkeyCredentialStorage = passkeyStorage(PasskeyCredential, 524288);
48
+ const samePasskeyCredential = (left, right) => {
49
+ const semantic = (value) => ({
50
+ ...value,
51
+ counter: 0,
52
+ backupState: false,
53
+ revision: {
54
+ ...value.revision,
55
+ credentials: []
56
+ }
57
+ });
58
+ return passkeyCredentialStorage.encode(semantic(left)) === passkeyCredentialStorage.encode(semantic(right));
59
+ };
60
+ const samePasskeyRevision = (left, right) => {
61
+ const pairs = new Map(left.credentials.map((item) => [item.credentialId, item.revision]));
62
+ return left.subjectId === right.subjectId && left.securityRevision === right.securityRevision && pairs.size === left.credentials.length && new Set(right.credentials.map((item) => item.credentialId)).size === right.credentials.length && pairs.size === right.credentials.length && right.credentials.every((item) => pairs.get(item.credentialId) === item.revision);
63
+ };
64
+ const passkeyAssertionPurposes = [
65
+ "sign-in",
66
+ "pending",
67
+ "step-up",
68
+ "action"
69
+ ];
70
+ const contextPurpose = {
71
+ SignIn: "sign-in",
72
+ Pending: "pending",
73
+ StepUp: "step-up",
74
+ Action: "action",
75
+ Enrollment: "enrollment",
76
+ Registration: "registration"
77
+ };
78
+ const validPasskeyCeremony = (ceremony) => ceremony.expiresAtMillis > ceremony.issuedAtMillis && ceremony.expiresAtMillis <= ceremony.requestBindingExpiresAtMillis && contextPurpose[ceremony.context._tag] === ceremony.purpose && new Set(ceremony.allowedCredentials.map((item) => item.id)).size === ceremony.allowedCredentials.length;
79
+ const passkeyMatchesAccess = (ceremony, access) => ceremony.moduleId === access.moduleId && ceremony.purpose === access.purpose && ceremony.flowId === access.flowId && ceremony.requestBindingVerifier === access.requestBindingVerifier && ceremony.requestBindingExpiresAtMillis === access.requestBindingExpiresAtMillis;
80
+ /** Reject stale bindings before evaluating application requirements. */
81
+ const validPasskeyActionEvidence = (facts, authorization) => {
82
+ const { challenge, evidence } = authorization;
83
+ const { expected, revision, nowMillis: now } = facts;
84
+ if (challenge.moduleId !== facts.moduleId || challenge.action !== expected.action || challenge.commandId !== expected.commandId || challenge.flowId !== expected.flowId || challenge.bindingDigest !== expected.bindingDigest || evidence.flowId !== expected.flowId || evidence.bindingDigest !== expected.bindingDigest || !samePasskeyRevision(challenge.revision, expected.revision) || revision.subjectId !== expected.revision.subjectId || revision.securityRevision !== expected.revision.securityRevision || evidence.revision.subjectId !== revision.subjectId || evidence.revision.securityRevision !== revision.securityRevision) return false;
85
+ for (const requested of [expected.revision, evidence.revision]) if (requested.credentials.some((item) => !revision.credentials.some((current) => current.credentialId === item.credentialId && current.revision === item.revision))) return false;
86
+ if (evidence.proofs.some((proof) => DateTime.toEpochMillis(proof.verifiedAt) > now || !evidence.revision.credentials.some((item) => item.credentialId === proof.credentialId))) return false;
87
+ return true;
88
+ };
89
+ /** SQL policy predicates remain native. This authorizes the exact evidence and
90
+ * returns the deadline every backend must retain through its final commit. */
91
+ const assessPasskeyAction = (facts, authorization, policy) => {
92
+ if (!validPasskeyActionEvidence(facts, authorization)) return void 0;
93
+ const { evidence } = authorization;
94
+ const now = facts.nowMillis;
95
+ let expiresBefore = Infinity;
96
+ for (const requirement of [
97
+ authorization.requirement,
98
+ facts.currentRequirement,
99
+ ...facts.originalRequirement === void 0 ? [] : [facts.originalRequirement]
100
+ ]) {
101
+ const age = Math.min(policy.maximumEvidenceAgeMillis, requirement.maximumAgeMillis);
102
+ const fresh = evidence.proofs.filter((proof) => now - DateTime.toEpochMillis(proof.verifiedAt) < age);
103
+ const factors = new Set(fresh.flatMap((proof) => proof.factors));
104
+ if (!requirement.alternatives.some((alternative) => alternative.factors.every((factor) => factors.has(factor)) && new Set(fresh.map((proof) => proof.credentialId)).size >= alternative.minimumCredentials && fresh.some((proof) => (!alternative.userVerified || proof.userVerified) && (!alternative.phishingResistant || proof.phishingResistant)))) return void 0;
105
+ for (const proof of fresh) expiresBefore = Math.min(expiresBefore, DateTime.toEpochMillis(proof.verifiedAt) + age);
106
+ }
107
+ return {
108
+ notBeforeMillis: now,
109
+ expiresBeforeMillis: expiresBefore
110
+ };
111
+ };
112
+ //#endregion
113
+ export { assessPasskeyAction, passkeyAssertionPurposes, passkeyCredentialKey, passkeyCredentialStorage, passkeyKey, passkeyMatchesAccess, passkeyStorage, samePasskeyCredential, samePasskeyRevision, validPasskeyActionEvidence, validPasskeyCeremony };
114
+
115
+ //# sourceMappingURL=passkey-policy.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"passkey-policy.mjs","names":[],"sources":["../../src/internal/passkey-policy.ts"],"sourcesContent":["import {\n PasskeyUnavailable,\n type PasskeyCeremony,\n PasskeyCredential,\n type PasskeyRevision,\n snapshotPasskeySync,\n type PasskeyAccess,\n type PasskeyActionAuthorization,\n type PasskeyManagementPolicy,\n type PasskeyRequirement,\n} from \"@yielded/auth/Passkey\";\nimport { Crypto, DateTime, Effect, Schema } from \"effect\";\n\nconst invariant: (value: unknown) => asserts value = (value) => {\n if (!value) throw PasskeyUnavailable.make({});\n};\n\nconst encoder = new TextEncoder();\n\nconst decoder = new TextDecoder(\"utf-8\", { fatal: true });\n\n/** RP tuples have no collation-dependent string identity. */\nexport const passkeyKey = Effect.fnUntraced(function* (\n kind: string,\n fields: ReadonlyArray<string>,\n) {\n const values = [\"effect-auth/passkey/\" + kind + \"/v1\", ...fields].map((field) => {\n const bytes = encoder.encode(field);\n\n invariant(decoder.decode(bytes) === field);\n\n return bytes;\n });\n\n const packed = new Uint8Array(values.reduce((size, bytes) => size + 4 + bytes.length, 0));\n const view = new DataView(packed.buffer);\n let offset = 0;\n\n for (const bytes of values) {\n view.setUint32(offset, bytes.length, false);\n packed.set(bytes, offset + 4);\n offset += 4 + bytes.length;\n }\n\n const crypto = yield* Crypto.Crypto;\n const hashed = yield* crypto.digest(\"SHA-256\", packed);\n\n return \"v1:\" + Array.from(hashed, (value) => value.toString(16).padStart(2, \"0\")).join(\"\");\n});\n\nexport const passkeyCredentialKey = (rpId: string, id: string) =>\n passkeyKey(\"credential\", [rpId, id]);\n\n/** Private passkeyStorage is decoded Type data, never a consumer wire transform. */\nexport const passkeyStorage = <S extends Schema.Codec<unknown, unknown, never, never>>(\n schema: S,\n maximumBytes: number,\n) => {\n const codec = Schema.fromJsonString(Schema.toCodecJson(Schema.toType(schema)));\n\n const encode = (value: S[\"Type\"]) => {\n const text = \"v1:\" + Schema.encodeSync(codec)(snapshotPasskeySync(schema, value));\n\n invariant(encoder.encode(text).length <= maximumBytes);\n\n return text;\n };\n\n return {\n encode,\n decode: (text: unknown): S[\"Type\"] => {\n invariant(typeof text === \"string\" && text.startsWith(\"v1:\"));\n invariant(encoder.encode(text).length <= maximumBytes);\n const value = snapshotPasskeySync(schema, Schema.decodeSync(codec)(text.slice(3)));\n\n invariant(encode(value) === text);\n\n return value;\n },\n };\n};\n\n// Legal 32 x 16 x 2048 origins require more than one MiB before JSON escaping.\nexport const passkeyCredentialStorage = passkeyStorage(PasskeyCredential, 512 * 1024);\n\nexport const samePasskeyCredential = (left: PasskeyCredential, right: PasskeyCredential) => {\n const semantic = (value: PasskeyCredential) => ({\n ...value,\n counter: 0,\n backupState: false,\n revision: { ...value.revision, credentials: [] },\n });\n\n return (\n passkeyCredentialStorage.encode(semantic(left)) ===\n passkeyCredentialStorage.encode(semantic(right))\n );\n};\n\nexport const samePasskeyRevision = (\n left: typeof PasskeyRevision.Type,\n right: typeof PasskeyRevision.Type,\n) => {\n const pairs = new Map(left.credentials.map((item) => [item.credentialId, item.revision]));\n\n return (\n left.subjectId === right.subjectId &&\n left.securityRevision === right.securityRevision &&\n pairs.size === left.credentials.length &&\n new Set(right.credentials.map((item) => item.credentialId)).size === right.credentials.length &&\n pairs.size === right.credentials.length &&\n right.credentials.every((item) => pairs.get(item.credentialId) === item.revision)\n );\n};\n\nexport const passkeyAssertionPurposes = [\"sign-in\", \"pending\", \"step-up\", \"action\"] as const;\n\nconst contextPurpose = {\n SignIn: \"sign-in\",\n Pending: \"pending\",\n StepUp: \"step-up\",\n Action: \"action\",\n Enrollment: \"enrollment\",\n Registration: \"registration\",\n} as const;\n\nexport const validPasskeyCeremony = (ceremony: PasskeyCeremony) =>\n ceremony.expiresAtMillis > ceremony.issuedAtMillis &&\n ceremony.expiresAtMillis <= ceremony.requestBindingExpiresAtMillis &&\n contextPurpose[ceremony.context._tag] === ceremony.purpose &&\n new Set(ceremony.allowedCredentials.map((item) => item.id)).size ===\n ceremony.allowedCredentials.length;\n\nexport const passkeyMatchesAccess = (ceremony: PasskeyCeremony, access: PasskeyAccess) =>\n ceremony.moduleId === access.moduleId &&\n ceremony.purpose === access.purpose &&\n ceremony.flowId === access.flowId &&\n ceremony.requestBindingVerifier === access.requestBindingVerifier &&\n ceremony.requestBindingExpiresAtMillis === access.requestBindingExpiresAtMillis;\n\nexport interface PasskeyActionFacts {\n readonly moduleId: string;\n readonly revision: typeof PasskeyRevision.Type;\n readonly nowMillis: number;\n readonly currentRequirement: typeof PasskeyRequirement.Type;\n readonly expected: {\n readonly action: PasskeyActionAuthorization[\"challenge\"][\"action\"];\n readonly commandId: string;\n readonly flowId: string;\n readonly bindingDigest: string;\n readonly revision: typeof PasskeyRevision.Type;\n };\n readonly originalRequirement?: typeof PasskeyRequirement.Type;\n}\n\n/** Reject stale bindings before evaluating application requirements. */\nexport const validPasskeyActionEvidence = (\n facts: Pick<PasskeyActionFacts, \"moduleId\" | \"revision\" | \"expected\" | \"nowMillis\">,\n authorization: PasskeyActionAuthorization,\n) => {\n const { challenge, evidence } = authorization;\n const { expected, revision, nowMillis: now } = facts;\n\n if (\n challenge.moduleId !== facts.moduleId ||\n challenge.action !== expected.action ||\n challenge.commandId !== expected.commandId ||\n challenge.flowId !== expected.flowId ||\n challenge.bindingDigest !== expected.bindingDigest ||\n evidence.flowId !== expected.flowId ||\n evidence.bindingDigest !== expected.bindingDigest ||\n !samePasskeyRevision(challenge.revision, expected.revision) ||\n revision.subjectId !== expected.revision.subjectId ||\n revision.securityRevision !== expected.revision.securityRevision ||\n evidence.revision.subjectId !== revision.subjectId ||\n evidence.revision.securityRevision !== revision.securityRevision\n )\n return false;\n for (const requested of [expected.revision, evidence.revision])\n if (\n requested.credentials.some(\n (item) =>\n !revision.credentials.some(\n (current) =>\n current.credentialId === item.credentialId && current.revision === item.revision,\n ),\n )\n )\n return false;\n if (\n evidence.proofs.some(\n (proof) =>\n DateTime.toEpochMillis(proof.verifiedAt) > now ||\n !evidence.revision.credentials.some((item) => item.credentialId === proof.credentialId),\n )\n )\n return false;\n\n return true;\n};\n\n/** SQL policy predicates remain native. This authorizes the exact evidence and\n * returns the deadline every backend must retain through its final commit. */\nexport const assessPasskeyAction = (\n facts: PasskeyActionFacts,\n authorization: PasskeyActionAuthorization,\n policy: PasskeyManagementPolicy,\n) => {\n if (!validPasskeyActionEvidence(facts, authorization)) return undefined;\n const { evidence } = authorization;\n const now = facts.nowMillis;\n let expiresBefore = Infinity;\n\n for (const requirement of [\n authorization.requirement,\n facts.currentRequirement,\n ...(facts.originalRequirement === undefined ? [] : [facts.originalRequirement]),\n ]) {\n const age = Math.min(policy.maximumEvidenceAgeMillis, requirement.maximumAgeMillis);\n\n const fresh = evidence.proofs.filter(\n (proof) => now - DateTime.toEpochMillis(proof.verifiedAt) < age,\n );\n\n const factors = new Set(fresh.flatMap((proof) => proof.factors));\n\n if (\n !requirement.alternatives.some(\n (alternative) =>\n alternative.factors.every((factor) => factors.has(factor)) &&\n new Set(fresh.map((proof) => proof.credentialId)).size >=\n alternative.minimumCredentials &&\n fresh.some(\n (proof) =>\n (!alternative.userVerified || proof.userVerified) &&\n (!alternative.phishingResistant || proof.phishingResistant),\n ),\n )\n )\n return undefined;\n for (const proof of fresh)\n expiresBefore = Math.min(expiresBefore, DateTime.toEpochMillis(proof.verifiedAt) + age);\n }\n\n return { notBeforeMillis: now, expiresBeforeMillis: expiresBefore };\n};\n"],"mappings":"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"}
@@ -1,21 +1,23 @@
1
1
  import { sqlMapping } from "./native-sql-table.mjs";
2
- import { NativeDatabase } from "./transaction-kernel.mjs";
3
2
  import { Effect, Option, Redacted, Schema } from "effect";
3
+ import { SqlClient } from "effect/sql";
4
4
  import { CurrentCommitJournal, hasCommitScope } from "@yielded/auth/Hooks";
5
- import { reportPersistenceFailure } from "@yielded/auth/Persistence";
6
5
  import { EncodedPasswordHash, PasswordUnavailable, snapshotPasswordCredential } from "@yielded/auth/Password";
6
+ import { reportPersistenceFailure } from "@yielded/auth/Persistence";
7
+ import { SecurityRevision } from "@yielded/auth/Sessions";
7
8
  //#region src/internal/password-credentials.ts
8
9
  const unavailable = () => PasswordUnavailable.make({});
9
10
  const failure = (effect) => reportPersistenceFailure(effect, Schema.is(PasswordUnavailable)).pipe(Effect.mapError(unavailable));
10
11
  const samePasswordCredentialSnapshot = (a, b) => a.moduleId === b.moduleId && a.revision.subjectId === b.revision.subjectId && a.revision.securityRevision === b.revision.securityRevision && a.revision.credentials.length === b.revision.credentials.length && new Set(a.revision.credentials.map((entry) => entry.credentialId)).size === a.revision.credentials.length && new Set(b.revision.credentials.map((entry) => entry.credentialId)).size === b.revision.credentials.length && a.revision.credentials.every((entry) => b.revision.credentials.some((other) => entry.credentialId === other.credentialId && entry.revision === other.revision)) && a.credentialId === b.credentialId && a.credentialRevision === b.credentialRevision && a.verifierVersion === b.verifierVersion && Redacted.value(a.verifier) === Redacted.value(b.verifier) && a.normalization === b.normalization && a.identifier.namespace === b.identifier.namespace && a.identifier.value === b.identifier.value && a.identifierBindingRevision === b.identifierBindingRevision && a.identifierVerifiedAtMillis === b.identifierVerifiedAtMillis;
11
12
  /** Lookup is read-only; rehash is one conditional maintenance write, never authentication. */
12
13
  const makePasswordCredentials = Effect.fnUntraced(function* (table, mapping, options) {
13
- const sql = (yield* NativeDatabase).$client.withoutTransforms();
14
+ const sql = (yield* SqlClient.SqlClient).withoutTransforms();
14
15
  const parent = yield* Effect.serviceOption(CurrentCommitJournal);
15
- const [s, i, c] = yield* sqlMapping(() => [
16
+ const [s, i, c, a] = yield* sqlMapping(() => [
16
17
  table(mapping.subject.table),
17
18
  table(mapping.identifier.table),
18
- table(mapping.credential.table)
19
+ table(mapping.credential.table),
20
+ table(mapping.authorityCredential.table)
19
21
  ]).pipe(failure);
20
22
  const standalone = Effect.gen(function* () {
21
23
  if (options.coordinated) {
@@ -37,28 +39,55 @@ const makePasswordCredentials = Effect.fnUntraced(function* (table, mapping, opt
37
39
  const subjectTable = s.as("password_subject");
38
40
  const identifierTable = i.as("password_identifier");
39
41
  const credentialTable = c.as("password_credential");
40
- const rows = yield* sqlMapping(() => sql`select ${subjectTable.fields("subject_")}, ${identifierTable.fields("identifier_")}, ${credentialTable.fields("credential_")}
42
+ const authorityTable = a.as("password_authority");
43
+ const authority = mapping.authorityCredential;
44
+ const rows = yield* sqlMapping(() => sql`select ${subjectTable.fields("subject_")}, ${identifierTable.fields("identifier_")}, ${credentialTable.fields("credential_")}, ${authorityTable.fields("authority_")}
41
45
  from ${subjectTable.name}
42
46
  inner join ${identifierTable.name} on ${identifierTable.column(mapping.identifier.namespace)} = ${identifierTable.value(mapping.identifier.namespace, identifier.namespace)}
43
47
  and ${identifierTable.column(mapping.identifier.value)} = ${identifierTable.value(mapping.identifier.value, identifier.value)}
44
48
  and ${identifierTable.column(mapping.identifier.subjectId)} = ${identifierTable.value(mapping.identifier.subjectId, nativeId)}
45
49
  inner join ${credentialTable.name} on ${credentialTable.column(mapping.credential.moduleId)} = ${credentialTable.value(mapping.credential.moduleId, moduleId)}
46
50
  and ${credentialTable.column(mapping.credential.subjectId)} = ${credentialTable.value(mapping.credential.subjectId, nativeId)}
47
- where ${subjectTable.column(mapping.subject.id)} = ${subjectTable.value(mapping.subject.id, nativeId)}
51
+ left join ${authorityTable.name} on ${authorityTable.column(authority.subjectId)} = ${authorityTable.value(authority.subjectId, nativeId)}
52
+ ${authority.status === void 0 || authority.d1ActiveStatusValue === void 0 ? sql`` : sql`and ${authorityTable.column(authority.status)} = ${authorityTable.value(authority.status, authority.d1ActiveStatusValue)}`}
53
+ where ${subjectTable.column(mapping.subject.id)} = ${subjectTable.value(mapping.subject.id, nativeId)} order by ${authorityTable.column(authority.credentialId)} limit 4097
48
54
  `).pipe(Effect.flatten);
49
- if (rows.length !== 1) return void 0;
55
+ if (rows.length === 0) return void 0;
56
+ if (rows.length > 4096) return yield* unavailable();
50
57
  const [subject, identifierRow, credential] = yield* sqlMapping(() => [
51
58
  s.decode(rows[0], "subject_"),
52
59
  i.decode(rows[0], "identifier_"),
53
60
  c.decode(rows[0], "credential_")
54
61
  ]);
55
62
  if (yield* sqlMapping(() => !mapping.subject.isActiveStatus(subject[mapping.subject.status]) || !mapping.identifier.isCurrent(identifierRow) || !mapping.subjectId.equals(nativeId, identifierRow[mapping.identifier.subjectId]) || !mapping.subjectId.equals(nativeId, subject[mapping.subject.id]) || !mapping.subjectId.equals(nativeId, credential[mapping.credential.subjectId]))) return void 0;
56
- return yield* sqlMapping(() => mapping.credential.decode({
63
+ const captured = yield* sqlMapping(() => mapping.credential.decode({
57
64
  moduleId,
58
65
  subject,
59
66
  identifier: identifierRow,
60
67
  credential
61
68
  })).pipe(Effect.flatten, Effect.flatMap(snapshotPasswordCredential));
69
+ const factors = /* @__PURE__ */ new Map();
70
+ for (const row of rows) {
71
+ const factor = yield* sqlMapping(() => a.decode(row, "authority_"));
72
+ if (factor[authority.credentialId] === null || factor[authority.credentialId] === void 0) continue;
73
+ if (!mapping.subjectId.equals(nativeId, factor[authority.subjectId])) return yield* unavailable();
74
+ if (authority.status !== void 0 && authority.isActiveStatus?.(factor[authority.status]) !== true) continue;
75
+ const credentialId = yield* Schema.decodeUnknownEffect(Schema.String)(factor[authority.credentialId]);
76
+ const revision = yield* Schema.decodeUnknownEffect(SecurityRevision)(factor[authority.revision]);
77
+ if (factors.has(credentialId)) return yield* unavailable();
78
+ factors.set(credentialId, revision);
79
+ }
80
+ if (factors.size > 64 || factors.get(captured.credentialId) !== captured.credentialRevision) return void 0;
81
+ return yield* snapshotPasswordCredential({
82
+ ...captured,
83
+ revision: {
84
+ ...captured.revision,
85
+ credentials: [...factors].map(([credentialId, revision]) => ({
86
+ credentialId,
87
+ revision
88
+ }))
89
+ }
90
+ });
62
91
  });
63
92
  return {
64
93
  findCredential: (uncaptured) => Effect.gen(function* () {
@@ -1 +1 @@
1
- {"version":3,"file":"password-credentials.mjs","names":[],"sources":["../../src/internal/password-credentials.ts"],"sourcesContent":["import { CurrentCommitJournal, hasCommitScope } from \"@yielded/auth/Hooks\";\nimport type { LoginIdentifier } from \"@yielded/auth/Identity\";\nimport {\n EncodedPasswordHash,\n type PasswordPersistence,\n PasswordUnavailable,\n snapshotPasswordCredential,\n type PasswordCredentialSnapshot,\n} from \"@yielded/auth/Password\";\nimport { reportPersistenceFailure } from \"@yielded/auth/Persistence\";\nimport { Effect, Option, Redacted, Schema } from \"effect\";\n\nimport type { PersistenceMappingError } from \"./mapping-error\";\nimport type { AnyPasswordPersistenceMapping } from \"./models/password-model\";\nimport { sqlMapping, type SqlTable } from \"./native-sql-table\";\nimport type { PasswordSqlConfiguration } from \"./password-kernel\";\nimport { NativeDatabase } from \"./transaction-kernel\";\n\ntype Row = Readonly<Record<string, unknown>>;\nconst unavailable = () => PasswordUnavailable.make({});\n\nconst failure = <A, E, R>(effect: Effect.Effect<A, E, R>) =>\n reportPersistenceFailure(effect, Schema.is(PasswordUnavailable)).pipe(\n Effect.mapError(unavailable),\n );\n\nexport const samePasswordCredentialSnapshot = (\n a: PasswordCredentialSnapshot,\n b: PasswordCredentialSnapshot,\n) =>\n a.moduleId === b.moduleId &&\n a.revision.subjectId === b.revision.subjectId &&\n a.revision.securityRevision === b.revision.securityRevision &&\n a.revision.credentials.length === b.revision.credentials.length &&\n new Set(a.revision.credentials.map((entry) => entry.credentialId)).size ===\n a.revision.credentials.length &&\n new Set(b.revision.credentials.map((entry) => entry.credentialId)).size ===\n b.revision.credentials.length &&\n a.revision.credentials.every((entry) =>\n b.revision.credentials.some(\n (other) => entry.credentialId === other.credentialId && entry.revision === other.revision,\n ),\n ) &&\n a.credentialId === b.credentialId &&\n a.credentialRevision === b.credentialRevision &&\n a.verifierVersion === b.verifierVersion &&\n Redacted.value(a.verifier) === Redacted.value(b.verifier) &&\n a.normalization === b.normalization &&\n a.identifier.namespace === b.identifier.namespace &&\n a.identifier.value === b.identifier.value &&\n a.identifierBindingRevision === b.identifierBindingRevision &&\n a.identifierVerifiedAtMillis === b.identifierVerifiedAtMillis;\n\n/** Lookup is read-only; rehash is one conditional maintenance write, never authentication. */\nexport const makePasswordCredentials = Effect.fnUntraced(function* (\n table: (table: object) => SqlTable,\n mapping: AnyPasswordPersistenceMapping,\n options: PasswordSqlConfiguration,\n): Effect.fn.Return<\n Pick<PasswordPersistence[\"Service\"], \"findCredential\" | \"rehashIfCurrent\">,\n PasswordUnavailable,\n NativeDatabase\n> {\n const sql = (yield* NativeDatabase).$client.withoutTransforms();\n const parent = yield* Effect.serviceOption(CurrentCommitJournal);\n\n const [s, i, c] = yield* sqlMapping(\n () =>\n [\n table(mapping.subject.table),\n table(mapping.identifier.table),\n table(mapping.credential.table),\n ] as const,\n ).pipe(failure);\n\n const standalone = Effect.gen(function* () {\n if (options.coordinated) {\n const current = yield* Effect.serviceOption(CurrentCommitJournal);\n\n if (Option.isNone(parent) || Option.isNone(current) || parent.value !== current.value)\n return yield* unavailable();\n } else {\n if (yield* hasCommitScope) return yield* unavailable();\n yield* options.standaloneGuard;\n }\n });\n\n const allocate = <A>(\n asynchronous: Effect.Effect<A, PersistenceMappingError> | undefined,\n sync: (() => A) | undefined,\n ) => {\n if (options.mode !== \"synchronous\" && asynchronous !== undefined) return asynchronous;\n\n return sync === undefined\n ? Effect.fail(unavailable())\n : Effect.try({ try: sync, catch: unavailable });\n };\n\n // Bind each native ID through its own column codec. Physical encodings of the\n // same application ID need not match across subject, identifier and password.\n const snapshot = Effect.fnUntraced(function* (\n nativeId: unknown,\n moduleId: string,\n identifier: LoginIdentifier,\n ) {\n const subjectTable = s.as(\"password_subject\");\n const identifierTable = i.as(\"password_identifier\");\n const credentialTable = c.as(\"password_credential\");\n\n const rows = yield* sqlMapping(\n () =>\n sql<Row>`select ${subjectTable.fields(\"subject_\")}, ${identifierTable.fields(\"identifier_\")}, ${credentialTable.fields(\"credential_\")}\n from ${subjectTable.name}\n inner join ${identifierTable.name} on ${identifierTable.column(mapping.identifier.namespace)} = ${identifierTable.value(mapping.identifier.namespace, identifier.namespace)}\n and ${identifierTable.column(mapping.identifier.value)} = ${identifierTable.value(mapping.identifier.value, identifier.value)}\n and ${identifierTable.column(mapping.identifier.subjectId)} = ${identifierTable.value(mapping.identifier.subjectId, nativeId)}\n inner join ${credentialTable.name} on ${credentialTable.column(mapping.credential.moduleId)} = ${credentialTable.value(mapping.credential.moduleId, moduleId)}\n and ${credentialTable.column(mapping.credential.subjectId)} = ${credentialTable.value(mapping.credential.subjectId, nativeId)}\n where ${subjectTable.column(mapping.subject.id)} = ${subjectTable.value(mapping.subject.id, nativeId)}\n `,\n ).pipe(Effect.flatten);\n\n if (rows.length !== 1) return undefined;\n\n const [subject, identifierRow, credential] = yield* sqlMapping(\n () =>\n [\n s.decode(rows[0]!, \"subject_\"),\n i.decode(rows[0]!, \"identifier_\"),\n c.decode(rows[0]!, \"credential_\"),\n ] as const,\n );\n\n if (\n yield* sqlMapping(\n () =>\n !mapping.subject.isActiveStatus(subject[mapping.subject.status]) ||\n !mapping.identifier.isCurrent(identifierRow) ||\n !mapping.subjectId.equals(nativeId, identifierRow[mapping.identifier.subjectId]) ||\n !mapping.subjectId.equals(nativeId, subject[mapping.subject.id]) ||\n !mapping.subjectId.equals(nativeId, credential[mapping.credential.subjectId]),\n )\n )\n return undefined;\n\n const captured = yield* sqlMapping(() =>\n mapping.credential.decode({ moduleId, subject, identifier: identifierRow, credential }),\n ).pipe(Effect.flatten, Effect.flatMap(snapshotPasswordCredential));\n\n return captured;\n });\n\n return {\n findCredential: (uncaptured) =>\n Effect.gen(function* () {\n const input = { ...uncaptured, identifier: { ...uncaptured.identifier } };\n\n yield* standalone;\n\n const identifiers = yield* sqlMapping(\n () => sql<Row>`select ${i.fields(\"i_\")} from ${i.name}\n where ${i.column(mapping.identifier.namespace)} = ${i.value(mapping.identifier.namespace, input.identifier.namespace)}\n and ${i.column(mapping.identifier.value)} = ${i.value(mapping.identifier.value, input.identifier.value)}`,\n ).pipe(Effect.flatten);\n\n const identifier =\n identifiers.length === 1\n ? yield* sqlMapping(() => i.decode(identifiers[0]!, \"i_\"))\n : undefined;\n\n if (\n identifier === undefined ||\n !(yield* sqlMapping(() => mapping.identifier.isCurrent(identifier)))\n )\n return Option.none();\n\n const credential = yield* snapshot(\n identifier[mapping.identifier.subjectId],\n input.moduleId,\n input.identifier,\n );\n\n return credential === undefined ||\n (input.subjectId !== undefined && credential.revision.subjectId !== input.subjectId)\n ? Option.none()\n : Option.some(credential);\n }).pipe(failure),\n rehashIfCurrent: (input) =>\n Effect.gen(function* () {\n const nextVerifier = Redacted.make(\n yield* Schema.decodeEffect(EncodedPasswordHash)(Redacted.value(input.nextVerifier)),\n );\n\n const credential = yield* snapshotPasswordCredential(input.credential);\n\n yield* standalone;\n const nativeId = yield* mapping.subjectId.toNative(credential.revision.subjectId);\n const version = yield* allocate(mapping.allocateRevision, mapping.allocateRevisionSync);\n\n if (version === credential.verifierVersion) return yield* unavailable();\n yield* sqlMapping(() => {\n const encoded = mapping.credential.encodeVerifier(nextVerifier, version);\n\n // A custom encoder cannot turn maintenance into a semantic credential change.\n const values = {\n [mapping.credential.verifier]: encoded[mapping.credential.verifier],\n [mapping.credential.verifierVersion]: encoded[mapping.credential.verifierVersion],\n };\n\n if (Object.values(values).some((value) => value === undefined)) throw unavailable();\n\n // Ordinary identity predicates retain index use; the full CAS ignores text collation.\n const exact = sql.and(\n Object.entries({\n [mapping.credential.moduleId]: credential.moduleId,\n [mapping.credential.subjectId]: nativeId,\n [mapping.credential.credentialId]: credential.credentialId,\n [mapping.credential.credentialRevision]: credential.credentialRevision,\n [mapping.credential.verifierVersion]: credential.verifierVersion,\n [mapping.credential.verifier]: Redacted.value(credential.verifier),\n [mapping.credential.normalization]: credential.normalization,\n }).map(([key, value]) => {\n const column = c.column(key),\n bound = c.value(key, value);\n\n if (typeof value !== \"string\") return sql`${column} = ${bound}`;\n\n return sql.onDialectOrElse({\n mysql: () => sql`binary ${column} = binary ${bound}`,\n pg: () =>\n sql`convert_to(cast(${column} as text), 'UTF8') = convert_to(cast(${bound} as text), 'UTF8')`,\n orElse: () => sql`cast(${column} as blob) = cast(${bound} as blob)`,\n });\n }),\n );\n\n return sql`${c.update(values)}\n where ${c.column(mapping.credential.moduleId)} = ${c.value(mapping.credential.moduleId, credential.moduleId)}\n and ${c.column(mapping.credential.subjectId)} = ${c.value(mapping.credential.subjectId, nativeId)}\n and ${c.column(mapping.credential.credentialId)} = ${c.value(mapping.credential.credentialId, credential.credentialId)}\n and ${exact}`;\n }).pipe(Effect.flatten);\n }).pipe(failure),\n } satisfies Pick<PasswordPersistence[\"Service\"], \"findCredential\" | \"rehashIfCurrent\">;\n});\n"],"mappings":";;;;;;;AAmBA,MAAM,oBAAoB,oBAAoB,KAAK,CAAC,CAAC;AAErD,MAAM,WAAoB,WACxB,yBAAyB,QAAQ,OAAO,GAAG,mBAAmB,CAAC,CAAC,CAAC,KAC/D,OAAO,SAAS,WAAW,CAC7B;AAEF,MAAa,kCACX,GACA,MAEA,EAAE,aAAa,EAAE,YACjB,EAAE,SAAS,cAAc,EAAE,SAAS,aACpC,EAAE,SAAS,qBAAqB,EAAE,SAAS,oBAC3C,EAAE,SAAS,YAAY,WAAW,EAAE,SAAS,YAAY,UACzD,IAAI,IAAI,EAAE,SAAS,YAAY,KAAK,UAAU,MAAM,YAAY,CAAC,CAAC,CAAC,SACjE,EAAE,SAAS,YAAY,UACzB,IAAI,IAAI,EAAE,SAAS,YAAY,KAAK,UAAU,MAAM,YAAY,CAAC,CAAC,CAAC,SACjE,EAAE,SAAS,YAAY,UACzB,EAAE,SAAS,YAAY,OAAO,UAC5B,EAAE,SAAS,YAAY,MACpB,UAAU,MAAM,iBAAiB,MAAM,gBAAgB,MAAM,aAAa,MAAM,QACnF,CACF,KACA,EAAE,iBAAiB,EAAE,gBACrB,EAAE,uBAAuB,EAAE,sBAC3B,EAAE,oBAAoB,EAAE,mBACxB,SAAS,MAAM,EAAE,QAAQ,MAAM,SAAS,MAAM,EAAE,QAAQ,KACxD,EAAE,kBAAkB,EAAE,iBACtB,EAAE,WAAW,cAAc,EAAE,WAAW,aACxC,EAAE,WAAW,UAAU,EAAE,WAAW,SACpC,EAAE,8BAA8B,EAAE,6BAClC,EAAE,+BAA+B,EAAE;;AAGrC,MAAa,0BAA0B,OAAO,WAAW,WACvD,OACA,SACA,SAKA;CACA,MAAM,OAAO,OAAO,eAAA,CAAgB,QAAQ,kBAAkB;CAC9D,MAAM,SAAS,OAAO,OAAO,cAAc,oBAAoB;CAE/D,MAAM,CAAC,GAAG,GAAG,KAAK,OAAO,iBAErB;EACE,MAAM,QAAQ,QAAQ,KAAK;EAC3B,MAAM,QAAQ,WAAW,KAAK;EAC9B,MAAM,QAAQ,WAAW,KAAK;CAChC,CACJ,CAAC,CAAC,KAAK,OAAO;CAEd,MAAM,aAAa,OAAO,IAAI,aAAa;EACzC,IAAI,QAAQ,aAAa;GACvB,MAAM,UAAU,OAAO,OAAO,cAAc,oBAAoB;GAEhE,IAAI,OAAO,OAAO,MAAM,KAAK,OAAO,OAAO,OAAO,KAAK,OAAO,UAAU,QAAQ,OAC9E,OAAO,OAAO,YAAY;EAC9B,OAAO;GACL,IAAI,OAAO,gBAAgB,OAAO,OAAO,YAAY;GACrD,OAAO,QAAQ;EACjB;CACF,CAAC;CAED,MAAM,YACJ,cACA,SACG;EACH,IAAI,QAAQ,SAAS,iBAAiB,iBAAiB,KAAA,GAAW,OAAO;EAEzE,OAAO,SAAS,KAAA,IACZ,OAAO,KAAK,YAAY,CAAC,IACzB,OAAO,IAAI;GAAE,KAAK;GAAM,OAAO;EAAY,CAAC;CAClD;CAIA,MAAM,WAAW,OAAO,WAAW,WACjC,UACA,UACA,YACA;EACA,MAAM,eAAe,EAAE,GAAG,kBAAkB;EAC5C,MAAM,kBAAkB,EAAE,GAAG,qBAAqB;EAClD,MAAM,kBAAkB,EAAE,GAAG,qBAAqB;EAElD,MAAM,OAAO,OAAO,iBAEhB,GAAQ,UAAU,aAAa,OAAO,UAAU,EAAE,IAAI,gBAAgB,OAAO,aAAa,EAAE,IAAI,gBAAgB,OAAO,aAAa,EAAE;aACjI,aAAa,KAAK;mBACZ,gBAAgB,KAAK,MAAM,gBAAgB,OAAO,QAAQ,WAAW,SAAS,EAAE,KAAK,gBAAgB,MAAM,QAAQ,WAAW,WAAW,WAAW,SAAS,EAAE;cACpK,gBAAgB,OAAO,QAAQ,WAAW,KAAK,EAAE,KAAK,gBAAgB,MAAM,QAAQ,WAAW,OAAO,WAAW,KAAK,EAAE;cACxH,gBAAgB,OAAO,QAAQ,WAAW,SAAS,EAAE,KAAK,gBAAgB,MAAM,QAAQ,WAAW,WAAW,QAAQ,EAAE;mBACnH,gBAAgB,KAAK,MAAM,gBAAgB,OAAO,QAAQ,WAAW,QAAQ,EAAE,KAAK,gBAAgB,MAAM,QAAQ,WAAW,UAAU,QAAQ,EAAE;cACtJ,gBAAgB,OAAO,QAAQ,WAAW,SAAS,EAAE,KAAK,gBAAgB,MAAM,QAAQ,WAAW,WAAW,QAAQ,EAAE;cACxH,aAAa,OAAO,QAAQ,QAAQ,EAAE,EAAE,KAAK,aAAa,MAAM,QAAQ,QAAQ,IAAI,QAAQ,EAAE;OAExG,CAAC,CAAC,KAAK,OAAO,OAAO;EAErB,IAAI,KAAK,WAAW,GAAG,OAAO,KAAA;EAE9B,MAAM,CAAC,SAAS,eAAe,cAAc,OAAO,iBAEhD;GACE,EAAE,OAAO,KAAK,IAAK,UAAU;GAC7B,EAAE,OAAO,KAAK,IAAK,aAAa;GAChC,EAAE,OAAO,KAAK,IAAK,aAAa;EAClC,CACJ;EAEA,IACE,OAAO,iBAEH,CAAC,QAAQ,QAAQ,eAAe,QAAQ,QAAQ,QAAQ,OAAO,KAC/D,CAAC,QAAQ,WAAW,UAAU,aAAa,KAC3C,CAAC,QAAQ,UAAU,OAAO,UAAU,cAAc,QAAQ,WAAW,UAAU,KAC/E,CAAC,QAAQ,UAAU,OAAO,UAAU,QAAQ,QAAQ,QAAQ,GAAG,KAC/D,CAAC,QAAQ,UAAU,OAAO,UAAU,WAAW,QAAQ,WAAW,UAAU,CAChF,GAEA,OAAO,KAAA;EAMT,OAAO,OAJiB,iBACtB,QAAQ,WAAW,OAAO;GAAE;GAAU;GAAS,YAAY;GAAe;EAAW,CAAC,CACxF,CAAC,CAAC,KAAK,OAAO,SAAS,OAAO,QAAQ,0BAA0B,CAAC;CAGnE,CAAC;CAED,OAAO;EACL,iBAAiB,eACf,OAAO,IAAI,aAAa;GACtB,MAAM,QAAQ;IAAE,GAAG;IAAY,YAAY,EAAE,GAAG,WAAW,WAAW;GAAE;GAExE,OAAO;GAEP,MAAM,cAAc,OAAO,iBACnB,GAAQ,UAAU,EAAE,OAAO,IAAI,EAAE,QAAQ,EAAE,KAAK;kBAC9C,EAAE,OAAO,QAAQ,WAAW,SAAS,EAAE,KAAK,EAAE,MAAM,QAAQ,WAAW,WAAW,MAAM,WAAW,SAAS,EAAE;kBAC9G,EAAE,OAAO,QAAQ,WAAW,KAAK,EAAE,KAAK,EAAE,MAAM,QAAQ,WAAW,OAAO,MAAM,WAAW,KAAK,GAC1G,CAAC,CAAC,KAAK,OAAO,OAAO;GAErB,MAAM,aACJ,YAAY,WAAW,IACnB,OAAO,iBAAiB,EAAE,OAAO,YAAY,IAAK,IAAI,CAAC,IACvD,KAAA;GAEN,IACE,eAAe,KAAA,KACf,EAAE,OAAO,iBAAiB,QAAQ,WAAW,UAAU,UAAU,CAAC,IAElE,OAAO,OAAO,KAAK;GAErB,MAAM,aAAa,OAAO,SACxB,WAAW,QAAQ,WAAW,YAC9B,MAAM,UACN,MAAM,UACR;GAEA,OAAO,eAAe,KAAA,KACnB,MAAM,cAAc,KAAA,KAAa,WAAW,SAAS,cAAc,MAAM,YACxE,OAAO,KAAK,IACZ,OAAO,KAAK,UAAU;EAC5B,CAAC,CAAC,CAAC,KAAK,OAAO;EACjB,kBAAkB,UAChB,OAAO,IAAI,aAAa;GACtB,MAAM,eAAe,SAAS,KAC5B,OAAO,OAAO,aAAa,mBAAmB,CAAC,CAAC,SAAS,MAAM,MAAM,YAAY,CAAC,CACpF;GAEA,MAAM,aAAa,OAAO,2BAA2B,MAAM,UAAU;GAErE,OAAO;GACP,MAAM,WAAW,OAAO,QAAQ,UAAU,SAAS,WAAW,SAAS,SAAS;GAChF,MAAM,UAAU,OAAO,SAAS,QAAQ,kBAAkB,QAAQ,oBAAoB;GAEtF,IAAI,YAAY,WAAW,iBAAiB,OAAO,OAAO,YAAY;GACtE,OAAO,iBAAiB;IACtB,MAAM,UAAU,QAAQ,WAAW,eAAe,cAAc,OAAO;IAGvE,MAAM,SAAS;MACZ,QAAQ,WAAW,WAAW,QAAQ,QAAQ,WAAW;MACzD,QAAQ,WAAW,kBAAkB,QAAQ,QAAQ,WAAW;IACnE;IAEA,IAAI,OAAO,OAAO,MAAM,CAAC,CAAC,MAAM,UAAU,UAAU,KAAA,CAAS,GAAG,MAAM,YAAY;IAGlF,MAAM,QAAQ,IAAI,IAChB,OAAO,QAAQ;MACZ,QAAQ,WAAW,WAAW,WAAW;MACzC,QAAQ,WAAW,YAAY;MAC/B,QAAQ,WAAW,eAAe,WAAW;MAC7C,QAAQ,WAAW,qBAAqB,WAAW;MACnD,QAAQ,WAAW,kBAAkB,WAAW;MAChD,QAAQ,WAAW,WAAW,SAAS,MAAM,WAAW,QAAQ;MAChE,QAAQ,WAAW,gBAAgB,WAAW;IACjD,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,WAAW;KACvB,MAAM,SAAS,EAAE,OAAO,GAAG,GACzB,QAAQ,EAAE,MAAM,KAAK,KAAK;KAE5B,IAAI,OAAO,UAAU,UAAU,OAAO,GAAG,GAAG,OAAO,KAAK;KAExD,OAAO,IAAI,gBAAgB;MACzB,aAAa,GAAG,UAAU,OAAO,YAAY;MAC7C,UACE,GAAG,mBAAmB,OAAO,uCAAuC,MAAM;MAC5E,cAAc,GAAG,QAAQ,OAAO,mBAAmB,MAAM;KAC3D,CAAC;IACH,CAAC,CACH;IAEA,OAAO,GAAG,GAAG,EAAE,OAAO,MAAM,EAAE;kBACtB,EAAE,OAAO,QAAQ,WAAW,QAAQ,EAAE,KAAK,EAAE,MAAM,QAAQ,WAAW,UAAU,WAAW,QAAQ,EAAE;kBACrG,EAAE,OAAO,QAAQ,WAAW,SAAS,EAAE,KAAK,EAAE,MAAM,QAAQ,WAAW,WAAW,QAAQ,EAAE;kBAC5F,EAAE,OAAO,QAAQ,WAAW,YAAY,EAAE,KAAK,EAAE,MAAM,QAAQ,WAAW,cAAc,WAAW,YAAY,EAAE;kBACjH;GACV,CAAC,CAAC,CAAC,KAAK,OAAO,OAAO;EACxB,CAAC,CAAC,CAAC,KAAK,OAAO;CACnB;AACF,CAAC"}
1
+ {"version":3,"file":"password-credentials.mjs","names":[],"sources":["../../src/internal/password-credentials.ts"],"sourcesContent":["import { CurrentCommitJournal, hasCommitScope } from \"@yielded/auth/Hooks\";\nimport type { LoginIdentifier } from \"@yielded/auth/Identity\";\nimport {\n EncodedPasswordHash,\n type PasswordPersistence,\n PasswordUnavailable,\n snapshotPasswordCredential,\n type PasswordCredentialSnapshot,\n} from \"@yielded/auth/Password\";\nimport { reportPersistenceFailure } from \"@yielded/auth/Persistence\";\nimport { SecurityRevision } from \"@yielded/auth/Sessions\";\nimport { Effect, Option, Redacted, Schema } from \"effect\";\nimport { SqlClient } from \"effect/sql\";\n\nimport type { PersistenceMappingError } from \"./mapping-error\";\nimport type { AnyPasswordPersistenceMapping } from \"./models/password-model\";\nimport { sqlMapping, type SqlTable } from \"./native-sql-table\";\nimport type { PasswordWorkflowOptions } from \"./password-policy\";\n\ntype Row = Readonly<Record<string, unknown>>;\nconst unavailable = () => PasswordUnavailable.make({});\n\nconst failure = <A, E, R>(effect: Effect.Effect<A, E, R>) =>\n reportPersistenceFailure(effect, Schema.is(PasswordUnavailable)).pipe(\n Effect.mapError(unavailable),\n );\n\nexport const samePasswordCredentialSnapshot = (\n a: PasswordCredentialSnapshot,\n b: PasswordCredentialSnapshot,\n) =>\n a.moduleId === b.moduleId &&\n a.revision.subjectId === b.revision.subjectId &&\n a.revision.securityRevision === b.revision.securityRevision &&\n a.revision.credentials.length === b.revision.credentials.length &&\n new Set(a.revision.credentials.map((entry) => entry.credentialId)).size ===\n a.revision.credentials.length &&\n new Set(b.revision.credentials.map((entry) => entry.credentialId)).size ===\n b.revision.credentials.length &&\n a.revision.credentials.every((entry) =>\n b.revision.credentials.some(\n (other) => entry.credentialId === other.credentialId && entry.revision === other.revision,\n ),\n ) &&\n a.credentialId === b.credentialId &&\n a.credentialRevision === b.credentialRevision &&\n a.verifierVersion === b.verifierVersion &&\n Redacted.value(a.verifier) === Redacted.value(b.verifier) &&\n a.normalization === b.normalization &&\n a.identifier.namespace === b.identifier.namespace &&\n a.identifier.value === b.identifier.value &&\n a.identifierBindingRevision === b.identifierBindingRevision &&\n a.identifierVerifiedAtMillis === b.identifierVerifiedAtMillis;\n\n/** Lookup is read-only; rehash is one conditional maintenance write, never authentication. */\nexport const makePasswordCredentials = Effect.fnUntraced(function* (\n table: (table: object) => SqlTable,\n mapping: AnyPasswordPersistenceMapping,\n options: PasswordWorkflowOptions,\n): Effect.fn.Return<\n Pick<PasswordPersistence[\"Service\"], \"findCredential\" | \"rehashIfCurrent\">,\n PasswordUnavailable,\n SqlClient.SqlClient\n> {\n const sql = (yield* SqlClient.SqlClient).withoutTransforms();\n const parent = yield* Effect.serviceOption(CurrentCommitJournal);\n\n const [s, i, c, a] = yield* sqlMapping(\n () =>\n [\n table(mapping.subject.table),\n table(mapping.identifier.table),\n table(mapping.credential.table),\n table(mapping.authorityCredential.table),\n ] as const,\n ).pipe(failure);\n\n const standalone = Effect.gen(function* () {\n if (options.coordinated) {\n const current = yield* Effect.serviceOption(CurrentCommitJournal);\n\n if (Option.isNone(parent) || Option.isNone(current) || parent.value !== current.value)\n return yield* unavailable();\n } else {\n if (yield* hasCommitScope) return yield* unavailable();\n yield* options.standaloneGuard;\n }\n });\n\n const allocate = <A>(\n asynchronous: Effect.Effect<A, PersistenceMappingError> | undefined,\n sync: (() => A) | undefined,\n ) => {\n if (options.mode !== \"synchronous\" && asynchronous !== undefined) return asynchronous;\n\n return sync === undefined\n ? Effect.fail(unavailable())\n : Effect.try({ try: sync, catch: unavailable });\n };\n\n // Bind each native ID through its own column codec. Physical encodings of the\n // same application ID need not match across subject, identifier and password.\n const snapshot = Effect.fnUntraced(function* (\n nativeId: unknown,\n moduleId: string,\n identifier: LoginIdentifier,\n ) {\n const subjectTable = s.as(\"password_subject\");\n const identifierTable = i.as(\"password_identifier\");\n const credentialTable = c.as(\"password_credential\");\n const authorityTable = a.as(\"password_authority\");\n const authority = mapping.authorityCredential;\n\n const rows = yield* sqlMapping(\n () =>\n sql<Row>`select ${subjectTable.fields(\"subject_\")}, ${identifierTable.fields(\"identifier_\")}, ${credentialTable.fields(\"credential_\")}, ${authorityTable.fields(\"authority_\")}\n from ${subjectTable.name}\n inner join ${identifierTable.name} on ${identifierTable.column(mapping.identifier.namespace)} = ${identifierTable.value(mapping.identifier.namespace, identifier.namespace)}\n and ${identifierTable.column(mapping.identifier.value)} = ${identifierTable.value(mapping.identifier.value, identifier.value)}\n and ${identifierTable.column(mapping.identifier.subjectId)} = ${identifierTable.value(mapping.identifier.subjectId, nativeId)}\n inner join ${credentialTable.name} on ${credentialTable.column(mapping.credential.moduleId)} = ${credentialTable.value(mapping.credential.moduleId, moduleId)}\n and ${credentialTable.column(mapping.credential.subjectId)} = ${credentialTable.value(mapping.credential.subjectId, nativeId)}\n left join ${authorityTable.name} on ${authorityTable.column(authority.subjectId)} = ${authorityTable.value(authority.subjectId, nativeId)}\n ${authority.status === undefined || authority.d1ActiveStatusValue === undefined ? sql`` : sql`and ${authorityTable.column(authority.status)} = ${authorityTable.value(authority.status, authority.d1ActiveStatusValue)}`}\n where ${subjectTable.column(mapping.subject.id)} = ${subjectTable.value(mapping.subject.id, nativeId)} order by ${authorityTable.column(authority.credentialId)} limit 4097\n `,\n ).pipe(Effect.flatten);\n\n if (rows.length === 0) return undefined;\n if (rows.length > 4096) return yield* unavailable();\n\n const [subject, identifierRow, credential] = yield* sqlMapping(\n () =>\n [\n s.decode(rows[0]!, \"subject_\"),\n i.decode(rows[0]!, \"identifier_\"),\n c.decode(rows[0]!, \"credential_\"),\n ] as const,\n );\n\n if (\n yield* sqlMapping(\n () =>\n !mapping.subject.isActiveStatus(subject[mapping.subject.status]) ||\n !mapping.identifier.isCurrent(identifierRow) ||\n !mapping.subjectId.equals(nativeId, identifierRow[mapping.identifier.subjectId]) ||\n !mapping.subjectId.equals(nativeId, subject[mapping.subject.id]) ||\n !mapping.subjectId.equals(nativeId, credential[mapping.credential.subjectId]),\n )\n )\n return undefined;\n\n const captured = yield* sqlMapping(() =>\n mapping.credential.decode({ moduleId, subject, identifier: identifierRow, credential }),\n ).pipe(Effect.flatten, Effect.flatMap(snapshotPasswordCredential));\n\n const factors = new Map<string, SecurityRevision>();\n\n for (const row of rows) {\n const factor = yield* sqlMapping(() => a.decode(row, \"authority_\"));\n\n if (factor[authority.credentialId] === null || factor[authority.credentialId] === undefined)\n continue;\n if (!mapping.subjectId.equals(nativeId, factor[authority.subjectId]))\n return yield* unavailable();\n if (\n authority.status !== undefined &&\n authority.isActiveStatus?.(factor[authority.status]) !== true\n )\n continue;\n\n const credentialId = yield* Schema.decodeUnknownEffect(Schema.String)(\n factor[authority.credentialId],\n );\n\n const revision = yield* Schema.decodeUnknownEffect(SecurityRevision)(\n factor[authority.revision],\n );\n\n if (factors.has(credentialId)) return yield* unavailable();\n factors.set(credentialId, revision);\n }\n if (factors.size > 64 || factors.get(captured.credentialId) !== captured.credentialRevision)\n return undefined;\n\n return yield* snapshotPasswordCredential({\n ...captured,\n revision: {\n ...captured.revision,\n credentials: [...factors].map(([credentialId, revision]) => ({ credentialId, revision })),\n },\n });\n });\n\n return {\n findCredential: (uncaptured) =>\n Effect.gen(function* () {\n const input = { ...uncaptured, identifier: { ...uncaptured.identifier } };\n\n yield* standalone;\n\n const identifiers = yield* sqlMapping(\n () => sql<Row>`select ${i.fields(\"i_\")} from ${i.name}\n where ${i.column(mapping.identifier.namespace)} = ${i.value(mapping.identifier.namespace, input.identifier.namespace)}\n and ${i.column(mapping.identifier.value)} = ${i.value(mapping.identifier.value, input.identifier.value)}`,\n ).pipe(Effect.flatten);\n\n const identifier =\n identifiers.length === 1\n ? yield* sqlMapping(() => i.decode(identifiers[0]!, \"i_\"))\n : undefined;\n\n if (\n identifier === undefined ||\n !(yield* sqlMapping(() => mapping.identifier.isCurrent(identifier)))\n )\n return Option.none();\n\n const credential = yield* snapshot(\n identifier[mapping.identifier.subjectId],\n input.moduleId,\n input.identifier,\n );\n\n return credential === undefined ||\n (input.subjectId !== undefined && credential.revision.subjectId !== input.subjectId)\n ? Option.none()\n : Option.some(credential);\n }).pipe(failure),\n rehashIfCurrent: (input) =>\n Effect.gen(function* () {\n const nextVerifier = Redacted.make(\n yield* Schema.decodeEffect(EncodedPasswordHash)(Redacted.value(input.nextVerifier)),\n );\n\n const credential = yield* snapshotPasswordCredential(input.credential);\n\n yield* standalone;\n const nativeId = yield* mapping.subjectId.toNative(credential.revision.subjectId);\n const version = yield* allocate(mapping.allocateRevision, mapping.allocateRevisionSync);\n\n if (version === credential.verifierVersion) return yield* unavailable();\n yield* sqlMapping(() => {\n const encoded = mapping.credential.encodeVerifier(nextVerifier, version);\n\n // A custom encoder cannot turn maintenance into a semantic credential change.\n const values = {\n [mapping.credential.verifier]: encoded[mapping.credential.verifier],\n [mapping.credential.verifierVersion]: encoded[mapping.credential.verifierVersion],\n };\n\n if (Object.values(values).some((value) => value === undefined)) throw unavailable();\n\n // Ordinary identity predicates retain index use; the full CAS ignores text collation.\n const exact = sql.and(\n Object.entries({\n [mapping.credential.moduleId]: credential.moduleId,\n [mapping.credential.subjectId]: nativeId,\n [mapping.credential.credentialId]: credential.credentialId,\n [mapping.credential.credentialRevision]: credential.credentialRevision,\n [mapping.credential.verifierVersion]: credential.verifierVersion,\n [mapping.credential.verifier]: Redacted.value(credential.verifier),\n [mapping.credential.normalization]: credential.normalization,\n }).map(([key, value]) => {\n const column = c.column(key),\n bound = c.value(key, value);\n\n if (typeof value !== \"string\") return sql`${column} = ${bound}`;\n\n return sql.onDialectOrElse({\n mysql: () => sql`binary ${column} = binary ${bound}`,\n pg: () =>\n sql`convert_to(cast(${column} as text), 'UTF8') = convert_to(cast(${bound} as text), 'UTF8')`,\n orElse: () => sql`cast(${column} as blob) = cast(${bound} as blob)`,\n });\n }),\n );\n\n return sql`${c.update(values)}\n where ${c.column(mapping.credential.moduleId)} = ${c.value(mapping.credential.moduleId, credential.moduleId)}\n and ${c.column(mapping.credential.subjectId)} = ${c.value(mapping.credential.subjectId, nativeId)}\n and ${c.column(mapping.credential.credentialId)} = ${c.value(mapping.credential.credentialId, credential.credentialId)}\n and ${exact}`;\n }).pipe(Effect.flatten);\n }).pipe(failure),\n } satisfies Pick<PasswordPersistence[\"Service\"], \"findCredential\" | \"rehashIfCurrent\">;\n});\n"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { AnyProofPersistenceMapping } from "./models/proof-model.mjs";
2
+ import { AnyPasswordPersistenceMapping } from "./models/password-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 { LifecycleHooks } from "@yielded/auth/Hooks";
7
+ import * as P from "@yielded/auth/Password";
8
+ import { SqlClient } from "effect/sql/SqlClient";
9
+ //#region src/internal/password-native.d.ts
10
+ export declare const makeNativePasswordServices: (tables: NativeSqlTables, mapping: AnyPasswordPersistenceMapping, proofs?: AnyProofPersistenceMapping | undefined) => Effect.Effect<{
11
+ readonly passwordPersistence: P.PasswordPersistence["Service"];
12
+ }, P.PasswordUnavailable, Crypto.Crypto | LifecycleHooks | SqlBatchCommit | SqlClient>;
13
+ //#endregion
14
+ //# sourceMappingURL=password-native.d.mts.map