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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (481) hide show
  1. package/README.md +6 -8
  2. package/dist/Adapter.d.mts +47 -33
  3. package/dist/Adapter.mjs +36 -23
  4. package/dist/OAuthPersistence.d.mts +35 -51
  5. package/dist/OAuthPersistence.mjs +60 -68
  6. package/dist/OAuthPersistence.mjs.map +1 -1
  7. package/dist/index.d.mts +2 -2
  8. package/dist/index.mjs +2 -2
  9. package/dist/internal/browser-login.d.mts +1 -1
  10. package/dist/internal/browser-login.mjs +29 -9
  11. package/dist/internal/browser-login.mjs.map +1 -1
  12. package/dist/internal/configuration.d.mts +13 -8
  13. package/dist/internal/configuration.mjs.map +1 -1
  14. package/dist/internal/crypto.d.mts +1 -0
  15. package/dist/internal/crypto.mjs +1 -1
  16. package/dist/internal/d1-planning.mjs +8 -0
  17. package/dist/internal/d1-planning.mjs.map +1 -0
  18. package/dist/internal/email-native-state.mjs +135 -0
  19. package/dist/internal/email-native-state.mjs.map +1 -0
  20. package/dist/internal/email-native.d.mts +17 -0
  21. package/dist/internal/email-native.mjs +245 -0
  22. package/dist/internal/email-native.mjs.map +1 -0
  23. package/dist/internal/email-policy.mjs +92 -0
  24. package/dist/internal/email-policy.mjs.map +1 -0
  25. package/dist/internal/email-registration-native.d.mts +38 -0
  26. package/dist/internal/email-registration-native.mjs +171 -0
  27. package/dist/internal/email-registration-native.mjs.map +1 -0
  28. package/dist/internal/models/email-model.d.mts +40 -104
  29. package/dist/internal/models/email-model.mjs +3 -5
  30. package/dist/internal/models/email-model.mjs.map +1 -1
  31. package/dist/internal/models/oauth-connected-model.d.mts +44 -213
  32. package/dist/internal/models/oauth-connected-model.mjs +6 -14
  33. package/dist/internal/models/oauth-connected-model.mjs.map +1 -1
  34. package/dist/internal/models/oauth-model.d.mts +95 -244
  35. package/dist/internal/models/oauth-model.mjs +28 -22
  36. package/dist/internal/models/oauth-model.mjs.map +1 -1
  37. package/dist/internal/models/passkey-model.d.mts +11 -147
  38. package/dist/internal/models/passkey-model.mjs +5 -24
  39. package/dist/internal/models/passkey-model.mjs.map +1 -1
  40. package/dist/internal/models/passkey-registration-ceremony-model.d.mts +5 -39
  41. package/dist/internal/models/passkey-write-model.d.mts +17 -75
  42. package/dist/internal/models/passkey-write-model.mjs +1 -7
  43. package/dist/internal/models/passkey-write-model.mjs.map +1 -1
  44. package/dist/internal/models/password-model.d.mts +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
@@ -1,872 +0,0 @@
1
- import {
2
- PhoneCustody,
3
- PhoneCommandId,
4
- PhoneLifecycleAction,
5
- PhoneLifecycleTarget,
6
- PhoneLifecyclePolicy,
7
- type PhoneMutationDecision,
8
- PhoneOtpUnavailable,
9
- PhoneCredentialSnapshot,
10
- type PhoneMutation,
11
- } from "@yielded/auth/PhoneOtp";
12
- import type { SubjectId } from "@yielded/auth/Schema";
13
- import { AuthenticationRequirement, SecurityRevision } from "@yielded/auth/Sessions";
14
- import { Context, Effect, Option, Schema } from "effect";
15
-
16
- import { digest, randomId } from "./crypto";
17
- /* oxlint-disable no-explicit-any -- existing storage kernels erase foreign table shapes; domain errors remain typed. */
18
- import type { SqlExpression as SQL } from "./query-operations";
19
- import type { QueryOperations, SqlFragment, SqlColumn } from "./query-operations";
20
- import { type TransactionOwner, type makeTransactionKernel } from "./transaction-kernel";
21
-
22
- export class CurrentPhoneTransaction extends Context.Service<
23
- CurrentPhoneTransaction,
24
- TransactionOwner<PhoneOtpUnavailable>
25
- >()("effect-auth/drizzle/CurrentPhoneTransaction") {}
26
-
27
- export const makePhoneKernel = <
28
- Fragment extends SqlFragment = SqlFragment,
29
- Column extends SqlColumn = SqlColumn,
30
- >(
31
- operations: QueryOperations<Fragment, Column>,
32
- transactions: Pick<ReturnType<typeof makeTransactionKernel>, "both" | "makeTransactionRows">,
33
- ) => {
34
- const { sql } = operations;
35
- const { both, makeTransactionRows } = transactions;
36
- const unavailable = () => PhoneOtpUnavailable.make({});
37
-
38
- const invariant: (value: unknown) => asserts value = (value) => {
39
- if (!value) throw unavailable();
40
- };
41
-
42
- const { equal, copiedRow, col } = makeTransactionRows(unavailable);
43
-
44
- const AdmissionReceipt = Schema.Struct({
45
- fingerprint: Schema.NonEmptyString,
46
- network: Schema.NonEmptyString,
47
- accepted: Schema.Boolean,
48
- expiresAtMillis: Schema.Natural,
49
- });
50
-
51
- const AdmissionCounter = Schema.Struct({ window: Schema.Natural, count: Schema.Natural });
52
-
53
- const CommandRecord = Schema.Struct({ commandId: PhoneCommandId, action: PhoneLifecycleAction });
54
-
55
- const State = Schema.Union([PhoneCustody, AdmissionReceipt, AdmissionCounter, CommandRecord]);
56
-
57
- const storageCodec = Schema.fromJsonString(
58
- Schema.Struct({ moduleId: Schema.NonEmptyString, record: State }),
59
- );
60
-
61
- const readStored = <A extends Schema.Top>(
62
- mapping: any,
63
- payload: string,
64
- schema: A,
65
- ): A["Type"] => {
66
- const stored = Schema.decodeSync(storageCodec)(payload);
67
-
68
- invariant(stored.moduleId === mapping.moduleId && Schema.is(schema)(stored.record));
69
-
70
- return stored.record;
71
- };
72
-
73
- const stringTuple = Schema.fromJsonString(Schema.Array(Schema.String));
74
-
75
- const scope = (moduleId: string, kind: string, key: string) =>
76
- digest(Schema.encodeSync(stringTuple)(["effect-auth/phone/v1", moduleId, kind, key]));
77
-
78
- const rejected: PhoneMutationDecision = { _tag: "Rejected" };
79
-
80
- const stateRead = Effect.fn("PhoneNative.stateRead")(function* (mapping: any, key: string) {
81
- const owner = yield* CurrentPhoneTransaction;
82
-
83
- return yield* owner.read(
84
- mapping.state.table,
85
- equal(mapping.state.table, { [mapping.state.scope]: key }),
86
- { limit: 1 },
87
- );
88
- });
89
-
90
- const stateWrite = Effect.fn("PhoneNative.stateWrite")(function* (
91
- mapping: any,
92
- key: string,
93
- value: typeof State.Type,
94
- observed: any,
95
- ) {
96
- const owner = yield* CurrentPhoneTransaction;
97
-
98
- const values = {
99
- [mapping.state.state]: Schema.encodeSync(storageCodec)({
100
- moduleId: mapping.moduleId,
101
- record: value,
102
- }),
103
- [mapping.state.version]: yield* randomId,
104
- };
105
-
106
- if (observed.rows.length === 0) {
107
- const inserted = yield* owner.insert(
108
- mapping.state.table,
109
- {
110
- ...copiedRow(
111
- mapping.state.encodeInsert({
112
- scope: key,
113
- state: values[mapping.state.state],
114
- version: values[mapping.state.version],
115
- }),
116
- ),
117
- [mapping.state.scope]: key,
118
- ...values,
119
- },
120
- { [mapping.state.scope]: key },
121
- );
122
-
123
- observed.rows = inserted.rows;
124
- } else yield* owner.update(mapping.state.table, { [mapping.state.scope]: key }, values);
125
- });
126
-
127
- const custodyRead = Effect.fn("PhoneNative.custodyRead")(function* (
128
- mapping: any,
129
- phoneNumber: string,
130
- ) {
131
- const key = yield* scope(mapping.moduleId, "custody", phoneNumber),
132
- observation = yield* stateRead(mapping, key);
133
-
134
- const custody =
135
- observation.rows.length === 0
136
- ? null
137
- : readStored(mapping, observation.rows[0]![mapping.state.state], PhoneCustody);
138
-
139
- invariant(custody === null || custody.phoneNumber === phoneNumber);
140
-
141
- return { key, observation, custody };
142
- });
143
-
144
- const capturePhone = Effect.fn("PhoneNative.capture")(function* (
145
- mapping: any,
146
- input: {
147
- readonly action: "register" | "verify" | "change";
148
- readonly phoneNumber: any;
149
- readonly subjectId?: SubjectId;
150
- readonly sourcePhoneNumber?: any;
151
- },
152
- ) {
153
- const owner = yield* CurrentPhoneTransaction;
154
- const destination = yield* custodyRead(mapping, input.phoneNumber);
155
-
156
- const source =
157
- input.sourcePhoneNumber === undefined
158
- ? null
159
- : yield* custodyRead(mapping, input.sourcePhoneNumber);
160
-
161
- const id = input.subjectId ?? destination.custody?.subjectId;
162
-
163
- const subject =
164
- id === undefined
165
- ? null
166
- : yield* owner.read(
167
- mapping.subject.table,
168
- equal(mapping.subject.table, { [mapping.subject.id]: mapping.subjectIds.toNative(id) }),
169
- { limit: 1 },
170
- );
171
-
172
- const row = subject?.rows[0];
173
-
174
- const active =
175
- row !== undefined &&
176
- (yield* owner.check(
177
- sql`exists(select 1 from ${mapping.subject.table} where ${both(owner.exact(mapping.subject.table, row), mapping.subject.activeCondition)})`,
178
- ));
179
-
180
- const targetIdentifier = yield* owner.read(
181
- mapping.identifier.table,
182
- equal(mapping.identifier.table, {
183
- [mapping.identifier.namespace]: "phone",
184
- [mapping.identifier.value]: input.phoneNumber,
185
- }),
186
- { limit: 1 },
187
- );
188
-
189
- let eligible =
190
- input.action === "register"
191
- ? destination.custody === null && targetIdentifier.rows.length === 0
192
- : active &&
193
- input.subjectId === id &&
194
- ((destination.custody === null && targetIdentifier.rows.length === 0) ||
195
- (destination.custody?.subjectId === id && destination.custody?.state === "unverified"));
196
-
197
- if (input.action === "change")
198
- eligible =
199
- eligible &&
200
- input.sourcePhoneNumber !== input.phoneNumber &&
201
- source?.custody?.subjectId === id &&
202
- source?.custody?.state === "verified";
203
- const credentials = [];
204
-
205
- for (const custody of [destination.custody, source?.custody])
206
- if (
207
- custody !== null &&
208
- custody !== undefined &&
209
- custody.state === "verified" &&
210
- custody.subjectId === id
211
- ) {
212
- const c = mapping.credential;
213
-
214
- const found = yield* owner.read(
215
- c.table,
216
- equal(c.table, {
217
- [c.id]: custody.credentialId,
218
- [c.subjectId]: mapping.subjectIds.toNative(id),
219
- }),
220
- { limit: 1 },
221
- );
222
-
223
- const cr = found.rows[0];
224
-
225
- if (
226
- cr === undefined ||
227
- cr[c.revision] !== custody.credentialRevision ||
228
- !(yield* owner.check(
229
- sql`exists(select 1 from ${c.table} where ${both(owner.exact(c.table, cr), c.activeCondition)})`,
230
- ))
231
- )
232
- eligible = false;
233
- else
234
- credentials.push({
235
- credentialId: custody.credentialId,
236
- revision: custody.credentialRevision,
237
- });
238
- }
239
-
240
- const target: PhoneLifecycleTarget = {
241
- phoneNumber: input.phoneNumber,
242
- custody: destination.custody,
243
- source: source?.custody ?? null,
244
- revision: active
245
- ? {
246
- subjectId: id!,
247
- securityRevision: SecurityRevision.make(row![mapping.subject.securityRevision]),
248
- credentials,
249
- }
250
- : null,
251
- eligible,
252
- };
253
-
254
- return { target, destination, source, subject, subjectRow: row, targetIdentifier };
255
- });
256
-
257
- const lookupPhone = Effect.fn("PhoneNative.lookup")(function* (
258
- mapping: any,
259
- input: { readonly moduleId: string; readonly phoneNumber: any },
260
- ) {
261
- invariant(input.moduleId === mapping.moduleId);
262
-
263
- const captured = yield* capturePhone(mapping, {
264
- action: "verify",
265
- phoneNumber: input.phoneNumber,
266
- });
267
-
268
- const { custody, revision } = captured.target;
269
-
270
- if (
271
- custody === null ||
272
- custody.state !== "verified" ||
273
- custody.verifiedAtMillis === null ||
274
- revision === null ||
275
- !revision.credentials.some((c) => c.credentialId === custody.credentialId)
276
- )
277
- return Option.none();
278
-
279
- const owner = yield* CurrentPhoneTransaction,
280
- i = mapping.identifier,
281
- row = captured.targetIdentifier.rows[0];
282
-
283
- if (
284
- row === undefined ||
285
- row[i.revision] !== custody.custodyRevision ||
286
- !(yield* owner.check(
287
- sql`exists(select 1 from ${i.table} where ${both(owner.exact(i.table, row), equal(i.table, { [i.subjectId]: mapping.subjectIds.toNative(custody.subjectId) }), i.activeCondition)})`,
288
- ))
289
- )
290
- return Option.none();
291
-
292
- return Option.some(
293
- Schema.decodeSync(PhoneCredentialSnapshot)({
294
- moduleId: mapping.moduleId,
295
- phoneNumber: input.phoneNumber,
296
- custodyRevision: custody.custodyRevision,
297
- verifiedAtMillis: custody.verifiedAtMillis,
298
- credentialId: custody.credentialId,
299
- credentialRevision: custody.credentialRevision,
300
- revision,
301
- }),
302
- );
303
- });
304
-
305
- const admitPhone = Effect.fn("PhoneNative.admit")(function* (
306
- mapping: any,
307
- input: {
308
- readonly moduleId: string;
309
- readonly action: "request" | "attempt";
310
- readonly requestId: string;
311
- readonly fingerprint: string;
312
- readonly networkKey: string;
313
- readonly replayLifetimeMillis: number;
314
- },
315
- ) {
316
- invariant(
317
- input.moduleId === mapping.moduleId &&
318
- Number.isSafeInteger(input.replayLifetimeMillis) &&
319
- input.replayLifetimeMillis >= 0 &&
320
- input.networkKey.length > 0 &&
321
- input.networkKey.length <= 1024 &&
322
- input.requestId.length > 0 &&
323
- input.requestId.length <= 256,
324
- );
325
-
326
- const owner = yield* CurrentPhoneTransaction,
327
- now = yield* owner.now(mapping),
328
- policy = mapping.admission;
329
-
330
- const key = yield* scope(mapping.moduleId, "admission", input.action + "/" + input.requestId),
331
- receipt = yield* stateRead(mapping, key);
332
-
333
- if (receipt.rows.length !== 0) {
334
- const saved = readStored(mapping, receipt.rows[0]![mapping.state.state], AdmissionReceipt);
335
-
336
- if (saved.expiresAtMillis > now)
337
- owner.postconditions.push(sql`${mapping.engineNowMillis} < ${saved.expiresAtMillis}`);
338
-
339
- return (
340
- saved.fingerprint === input.fingerprint &&
341
- saved.network === (yield* digest(input.networkKey)) &&
342
- saved.accepted === true &&
343
- saved.expiresAtMillis > now
344
- );
345
- }
346
-
347
- const window = Math.floor(now / policy.windowMillis),
348
- entries = [
349
- {
350
- key: yield* scope(
351
- mapping.moduleId,
352
- "network",
353
- input.action + "/" + (yield* digest(input.networkKey)),
354
- ),
355
- limit: input.action === "request" ? policy.networkRequests : policy.networkAttempts,
356
- },
357
- ...(input.action === "request"
358
- ? [
359
- {
360
- key: yield* scope(mapping.moduleId, "messages", "global"),
361
- limit: policy.maximumMessages,
362
- },
363
- ]
364
- : []),
365
- ].sort((a, b) => a.key.localeCompare(b.key));
366
-
367
- const updates = [];
368
- let accepted = true;
369
-
370
- for (const entry of entries) {
371
- const observed = yield* stateRead(mapping, entry.key),
372
- previous =
373
- observed.rows.length === 0
374
- ? undefined
375
- : readStored(mapping, observed.rows[0]![mapping.state.state], AdmissionCounter);
376
-
377
- const count = previous?.window === window ? previous.count : 0;
378
-
379
- if (count >= entry.limit) accepted = false;
380
- updates.push({ ...entry, observed, count });
381
- }
382
- if (accepted)
383
- for (const update of updates)
384
- yield* stateWrite(
385
- mapping,
386
- update.key,
387
- { window, count: update.count + 1 },
388
- update.observed,
389
- );
390
- yield* stateWrite(
391
- mapping,
392
- key,
393
- {
394
- fingerprint: input.fingerprint,
395
- network: yield* digest(input.networkKey),
396
- accepted,
397
- expiresAtMillis: now + Math.min(policy.requestRetentionMillis, input.replayLifetimeMillis),
398
- },
399
- receipt,
400
- );
401
- owner.postconditions.push(
402
- sql`${mapping.engineNowMillis} >= ${window * policy.windowMillis} and ${mapping.engineNowMillis} < ${(window + 1) * policy.windowMillis}`,
403
- );
404
-
405
- return accepted;
406
- });
407
-
408
- const preparePhoneMutation = Effect.fn("PhoneNative.prepareMutation")(function* (
409
- mapping: any,
410
- input: PhoneMutation,
411
- ) {
412
- const owner = yield* CurrentPhoneTransaction;
413
-
414
- invariant(
415
- input.moduleId === mapping.moduleId &&
416
- Schema.encodeSync(Schema.fromJsonString(PhoneLifecyclePolicy))(input.policy) ===
417
- Schema.encodeSync(Schema.fromJsonString(PhoneLifecyclePolicy))(mapping.policy),
418
- );
419
-
420
- const captured = yield* capturePhone(mapping, {
421
- action: input.action,
422
- phoneNumber: input.target.phoneNumber,
423
- ...(input.target.revision === null ? {} : { subjectId: input.target.revision.subjectId }),
424
- ...(input.target.source === null
425
- ? {}
426
- : { sourcePhoneNumber: input.target.source.phoneNumber }),
427
- });
428
-
429
- if (
430
- !captured.target.eligible ||
431
- Schema.encodeSync(Schema.fromJsonString(PhoneLifecycleTarget))(captured.target) !==
432
- Schema.encodeSync(Schema.fromJsonString(PhoneLifecycleTarget))(input.target)
433
- )
434
- return { decision: rejected };
435
- const binding = input.completion.input.binding;
436
-
437
- if (
438
- input.completion.input.moduleId !== `${mapping.moduleId}/lifecycle` ||
439
- input.completion.input.purpose !== "phone-lifecycle" ||
440
- binding.identifier.namespace !== "phone" ||
441
- binding.identifier.value !== input.target.phoneNumber
442
- )
443
- return { decision: rejected };
444
- if (
445
- input.action === "register"
446
- ? binding._tag !== "Identifier"
447
- : binding._tag === "Identifier" ||
448
- binding.revision.subjectId !== input.target.revision?.subjectId ||
449
- binding.revision.securityRevision !== input.target.revision?.securityRevision
450
- )
451
- return { decision: rejected };
452
- if (
453
- (input.action === "verify" && binding._tag !== "Subject") ||
454
- (input.action === "change" && binding._tag !== "IdentifierChange")
455
- )
456
- return { decision: rejected };
457
-
458
- const commandKey = yield* scope(mapping.moduleId, "command", input.commandId),
459
- command = yield* stateRead(mapping, commandKey);
460
-
461
- if (command.rows.length !== 0) return { decision: rejected };
462
-
463
- const now = yield* owner.now(mapping),
464
- guards: SQL[] = [];
465
-
466
- const credentialGuards: { id: string; condition: SQL }[] = [];
467
-
468
- if (input.action !== "register") {
469
- const authorization = input.authorization;
470
-
471
- if (authorization === undefined) return { decision: rejected };
472
- const { challenge, evidence } = authorization;
473
- const revision = captured.target.revision!;
474
-
475
- if (
476
- challenge.moduleId !== mapping.moduleId ||
477
- challenge.action !== input.action ||
478
- challenge.commandId !== input.commandId ||
479
- challenge.phoneNumber !== input.target.phoneNumber ||
480
- challenge.sourcePhoneNumber !== input.target.source?.phoneNumber ||
481
- challenge.flowId !== binding.flowId ||
482
- challenge.bindingDigest !== binding.contextDigest ||
483
- challenge.flowId !== evidence.flowId ||
484
- challenge.bindingDigest !== evidence.bindingDigest ||
485
- challenge.revision.subjectId !== revision.subjectId ||
486
- challenge.revision.securityRevision !== revision.securityRevision ||
487
- evidence.revision.subjectId !== revision.subjectId ||
488
- evidence.revision.securityRevision !== revision.securityRevision
489
- )
490
- return { decision: rejected };
491
- const c = mapping.credential;
492
-
493
- for (const item of [...evidence.revision.credentials].sort((a, b) =>
494
- a.credentialId.localeCompare(b.credentialId),
495
- )) {
496
- const found = yield* owner.read(
497
- c.table,
498
- equal(c.table, {
499
- [c.id]: item.credentialId,
500
- [c.subjectId]: mapping.subjectIds.toNative(revision.subjectId),
501
- }),
502
- { limit: 1 },
503
- ),
504
- row = found.rows[0];
505
-
506
- if (row === undefined || row[c.revision] !== item.revision) return { decision: rejected };
507
- const condition = sql`exists(select 1 from ${c.table} where ${both(owner.exact(c.table, row), c.activeCondition)})`;
508
-
509
- if (!(yield* owner.check(condition))) return { decision: rejected };
510
- credentialGuards.push({ id: item.credentialId, condition });
511
- }
512
- const proofs = evidence.proofs;
513
-
514
- if (
515
- proofs.length === 0 ||
516
- proofs.some(
517
- (p) => !evidence.revision.credentials.some((c) => c.credentialId === p.credentialId),
518
- )
519
- )
520
- return { decision: rejected };
521
-
522
- const requirements = [
523
- authorization.requirement,
524
- authorization.actionRequirement,
525
- ...(mapping.subject.decodeActionRequirement === undefined
526
- ? []
527
- : [
528
- Schema.decodeSync(AuthenticationRequirement)(
529
- mapping.subject.decodeActionRequirement(
530
- copiedRow(captured.subjectRow!),
531
- input.action,
532
- ),
533
- ),
534
- ]),
535
- Schema.decodeSync(AuthenticationRequirement)(
536
- mapping.subject.decodeRequirement(copiedRow(captured.subjectRow!)),
537
- ),
538
- ];
539
-
540
- const age = Math.min(
541
- input.policy.maximumEvidenceAgeMillis,
542
- ...requirements.map((r) => r.maximumAgeMillis),
543
- ),
544
- factors = new Set(proofs.flatMap((p) => p.factors)),
545
- credentials = new Set(proofs.map((p) => p.credentialId));
546
-
547
- for (const requirement of requirements)
548
- if (
549
- !requirement.alternatives.some(
550
- (a) =>
551
- a.factors.every((f) => factors.has(f)) &&
552
- credentials.size >= a.minimumCredentials &&
553
- proofs.some(
554
- (p) =>
555
- (!a.userVerified || p.userVerified) &&
556
- (!a.phishingResistant || p.phishingResistant),
557
- ),
558
- )
559
- )
560
- return { decision: rejected };
561
- for (const proof of proofs) {
562
- const at = proof.verifiedAt.epochMilliseconds;
563
-
564
- if (at > now || now - at >= age) return { decision: rejected };
565
- guards.push(
566
- sql`${mapping.engineNowMillis} >= ${at} and ${mapping.engineNowMillis} < ${at + age}`,
567
- );
568
- }
569
- }
570
-
571
- const subjectId =
572
- input.action === "register"
573
- ? mapping.subjectIds.toSubject(mapping.subjectIds.allocate())
574
- : captured.target.revision!.subjectId,
575
- nativeId = mapping.subjectIds.toNative(subjectId),
576
- securityRevision = SecurityRevision.make(yield* randomId),
577
- credentialRevision = SecurityRevision.make(yield* randomId),
578
- custodyRevision = SecurityRevision.make(yield* randomId),
579
- credentialId = captured.target.custody?.credentialId ?? (yield* randomId);
580
-
581
- invariant(mapping.subjectIds.toSubject(nativeId) === subjectId);
582
-
583
- const custody: PhoneCustody = {
584
- phoneNumber: input.target.phoneNumber,
585
- subjectId,
586
- credentialId,
587
- credentialRevision,
588
- custodyRevision,
589
- verifiedAtMillis: now,
590
- state: "verified",
591
- };
592
-
593
- const decision: PhoneMutationDecision = {
594
- _tag: "Accepted",
595
- credential: {
596
- moduleId: mapping.moduleId,
597
- phoneNumber: input.target.phoneNumber,
598
- custodyRevision,
599
- verifiedAtMillis: now,
600
- credentialId,
601
- credentialRevision,
602
- revision: {
603
- subjectId,
604
- securityRevision,
605
- credentials: [{ credentialId, revision: credentialRevision }],
606
- },
607
- },
608
- };
609
-
610
- const mutate = Effect.gen(function* () {
611
- if (input.action === "register")
612
- yield* owner.insert(
613
- mapping.subject.table,
614
- {
615
- ...copiedRow(
616
- mapping.subject.encodeInsert({
617
- id: nativeId,
618
- securityRevision,
619
- phoneNumber: input.target.phoneNumber,
620
- }),
621
- ),
622
- [mapping.subject.id]: nativeId,
623
- [mapping.subject.securityRevision]: securityRevision,
624
- },
625
- { [mapping.subject.id]: nativeId },
626
- );
627
- else
628
- yield* owner.update(
629
- mapping.subject.table,
630
- { [mapping.subject.id]: nativeId },
631
- { [mapping.subject.securityRevision]: securityRevision },
632
- );
633
-
634
- const i = mapping.identifier,
635
- c = mapping.credential;
636
-
637
- if (captured.source?.custody) {
638
- const old = captured.source.custody;
639
-
640
- const ir = yield* owner.read(
641
- i.table,
642
- equal(i.table, {
643
- [i.namespace]: "phone",
644
- [i.value]: old.phoneNumber,
645
- [i.subjectId]: nativeId,
646
- }),
647
- { limit: 1 },
648
- );
649
-
650
- invariant(ir.rows.length === 1 && ir.rows[0]![i.revision] === old.custodyRevision);
651
- invariant(
652
- yield* owner.check(
653
- sql`exists(select 1 from ${i.table} where ${both(owner.exact(i.table, ir.rows[0]!), i.activeCondition)})`,
654
- ),
655
- );
656
- yield* owner.update(
657
- i.table,
658
- { [i.namespace]: "phone", [i.value]: old.phoneNumber },
659
- { [i.status]: i.encodeStatus(false), [i.revision]: yield* randomId },
660
- );
661
- yield* owner.update(
662
- c.table,
663
- { [c.id]: old.credentialId, [c.subjectId]: nativeId },
664
- { [c.status]: c.encodeStatus(false), [c.revision]: yield* randomId },
665
- );
666
- yield* stateWrite(
667
- mapping,
668
- captured.source.key,
669
- {
670
- ...old,
671
- state: "retired",
672
- custodyRevision: SecurityRevision.make(yield* randomId),
673
- credentialRevision: SecurityRevision.make(yield* randomId),
674
- },
675
- captured.source.observation,
676
- );
677
- }
678
- if (captured.targetIdentifier.rows.length === 0) {
679
- const inserted = yield* owner.insert(
680
- i.table,
681
- {
682
- ...copiedRow(
683
- i.encodeInsert({
684
- phoneNumber: input.target.phoneNumber,
685
- subjectId: nativeId,
686
- revision: custodyRevision,
687
- verifiedAtMillis: now,
688
- active: true,
689
- }),
690
- ),
691
- [i.namespace]: "phone",
692
- [i.value]: input.target.phoneNumber,
693
- [i.subjectId]: nativeId,
694
- [i.revision]: custodyRevision,
695
- [i.verifiedAt]: mapping.encodeInstant(now),
696
- [i.status]: i.encodeStatus(true),
697
- },
698
- { [i.namespace]: "phone", [i.value]: input.target.phoneNumber },
699
- );
700
-
701
- captured.targetIdentifier.rows = inserted.rows;
702
- } else {
703
- const row = captured.targetIdentifier.rows[0]!;
704
-
705
- invariant(
706
- yield* owner.check(
707
- sql`exists(select 1 from ${i.table} where ${both(owner.exact(i.table, row), equal(i.table, { [i.subjectId]: nativeId }))})`,
708
- ),
709
- );
710
- yield* owner.update(
711
- i.table,
712
- { [i.namespace]: "phone", [i.value]: input.target.phoneNumber },
713
- {
714
- [i.revision]: custodyRevision,
715
- [i.verifiedAt]: mapping.encodeInstant(now),
716
- [i.status]: i.encodeStatus(true),
717
- },
718
- );
719
- }
720
-
721
- const credential = yield* owner.read(c.table, equal(c.table, { [c.id]: credentialId }), {
722
- limit: 1,
723
- });
724
-
725
- if (credential.rows.length === 0) {
726
- const inserted = yield* owner.insert(
727
- c.table,
728
- {
729
- ...copiedRow(
730
- c.encodeInsert({
731
- credentialId,
732
- subjectId: nativeId,
733
- revision: credentialRevision,
734
- active: true,
735
- }),
736
- ),
737
- [c.id]: credentialId,
738
- [c.subjectId]: nativeId,
739
- [c.revision]: credentialRevision,
740
- [c.status]: c.encodeStatus(true),
741
- },
742
- { [c.id]: credentialId },
743
- );
744
-
745
- credential.rows = inserted.rows;
746
- } else {
747
- invariant(
748
- yield* owner.check(
749
- sql`exists(select 1 from ${c.table} where ${both(owner.exact(c.table, credential.rows[0]!), equal(c.table, { [c.subjectId]: nativeId }))})`,
750
- ),
751
- );
752
- yield* owner.update(
753
- c.table,
754
- { [c.id]: credentialId },
755
- { [c.revision]: credentialRevision, [c.status]: c.encodeStatus(true) },
756
- );
757
- }
758
- yield* stateWrite(
759
- mapping,
760
- captured.destination.key,
761
- custody,
762
- captured.destination.observation,
763
- );
764
- yield* stateWrite(
765
- mapping,
766
- commandKey,
767
- { commandId: input.commandId, action: input.action },
768
- command,
769
- );
770
- owner.postconditions.push(
771
- ...guards,
772
- sql`exists(select 1 from ${i.table} where ${both(equal(i.table, { [i.namespace]: "phone", [i.value]: input.target.phoneNumber, [i.subjectId]: nativeId, [i.revision]: custodyRevision, [i.verifiedAt]: mapping.encodeInstant(now) }), i.activeCondition)})`,
773
- ...(captured.source?.custody === null || captured.source?.custody === undefined
774
- ? []
775
- : [
776
- sql`not exists(select 1 from ${i.table} where ${both(equal(i.table, { [i.namespace]: "phone", [i.value]: captured.source.custody.phoneNumber }), i.activeCondition)})`,
777
- sql`not exists(select 1 from ${c.table} where ${both(equal(c.table, { [c.id]: captured.source.custody.credentialId }), c.activeCondition)})`,
778
- ]),
779
- ...credentialGuards
780
- .filter((g) => g.id !== captured.source?.custody?.credentialId && g.id !== credentialId)
781
- .map((g) => g.condition),
782
- sql`exists(select 1 from ${c.table} where ${both(equal(c.table, { [c.id]: credentialId, [c.subjectId]: nativeId, [c.revision]: credentialRevision }), c.activeCondition)})`,
783
- sql`exists(select 1 from ${mapping.subject.table} where ${both(equal(mapping.subject.table, { [mapping.subject.id]: nativeId, [mapping.subject.securityRevision]: securityRevision }), mapping.subject.activeCondition)})`,
784
- );
785
-
786
- return true;
787
- });
788
-
789
- return {
790
- decision,
791
- mutate,
792
- appliedCondition: sql`exists(select 1 from ${mapping.state.table} where ${equal(mapping.state.table, { [mapping.state.scope]: commandKey })})`,
793
- };
794
- });
795
-
796
- /** Bounded cursor cleanup never removes custody or semantic-command tombstones. */
797
- const cleanupPhoneAdmission = Effect.fn("PhoneNative.cleanupAdmission")(function* (
798
- mapping: any,
799
- input: { readonly moduleId: string; readonly limit: number; readonly after?: string },
800
- ) {
801
- invariant(
802
- input.moduleId === mapping.moduleId &&
803
- Number.isSafeInteger(input.limit) &&
804
- input.limit >= 1 &&
805
- input.limit <= 1000,
806
- );
807
-
808
- const owner = yield* CurrentPhoneTransaction,
809
- now = yield* owner.now(mapping),
810
- state = mapping.state;
811
-
812
- // The page predicate matches every later row. Observing it would require the
813
- // page to be the whole table, so cleanup could not advance. Discover without
814
- // an observation, then guard each candidate by its scope.
815
- const page = yield* owner.read(
816
- state.table,
817
- input.after === undefined ? sql`1=1` : sql`${col(state.table, state.scope)} > ${input.after}`,
818
- {
819
- limit: input.limit,
820
- takeOnly: true,
821
- observe: false,
822
- orderBy: col(state.table, state.scope),
823
- },
824
- );
825
-
826
- let deleted = 0;
827
- const rows = [...page.rows];
828
-
829
- for (const candidate of rows) {
830
- const current = yield* owner.read(
831
- state.table,
832
- equal(state.table, { [state.scope]: candidate[state.scope] }),
833
- { limit: 1 },
834
- );
835
-
836
- const row = current.rows[0];
837
-
838
- if (row === undefined) continue;
839
- const stored = Schema.decodeSync(storageCodec)(row[state.state]);
840
-
841
- if (stored.moduleId !== mapping.moduleId) continue;
842
- const record = stored.record;
843
-
844
- if (
845
- (Schema.is(AdmissionReceipt)(record) && record.expiresAtMillis <= now) ||
846
- (Schema.is(AdmissionCounter)(record) &&
847
- (record.window + 1) * mapping.admission.windowMillis <= now)
848
- ) {
849
- yield* owner.remove(state.table, { [state.scope]: row[state.scope] });
850
- deleted++;
851
- }
852
- }
853
-
854
- return {
855
- deleted,
856
- nextCursor: rows.length === input.limit ? String(rows[rows.length - 1]![state.scope]) : null,
857
- };
858
- });
859
-
860
- return {
861
- unavailable,
862
- invariant,
863
- equal,
864
- copiedRow,
865
- col,
866
- capturePhone,
867
- lookupPhone,
868
- admitPhone,
869
- preparePhoneMutation,
870
- cleanupPhoneAdmission,
871
- };
872
- };