@portaidentity/server 1.7.0

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 (742) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/LICENSE +21 -0
  3. package/README.md +33 -0
  4. package/dist/applications/cache.d.ts +64 -0
  5. package/dist/applications/cache.d.ts.map +1 -0
  6. package/dist/applications/cache.js +161 -0
  7. package/dist/applications/cache.js.map +1 -0
  8. package/dist/applications/errors.d.ts +25 -0
  9. package/dist/applications/errors.d.ts.map +1 -0
  10. package/dist/applications/errors.js +31 -0
  11. package/dist/applications/errors.js.map +1 -0
  12. package/dist/applications/index.d.ts +17 -0
  13. package/dist/applications/index.d.ts.map +1 -0
  14. package/dist/applications/index.js +19 -0
  15. package/dist/applications/index.js.map +1 -0
  16. package/dist/applications/repository.d.ts +184 -0
  17. package/dist/applications/repository.d.ts.map +1 -0
  18. package/dist/applications/repository.js +367 -0
  19. package/dist/applications/repository.js.map +1 -0
  20. package/dist/applications/service.d.ts +160 -0
  21. package/dist/applications/service.d.ts.map +1 -0
  22. package/dist/applications/service.js +388 -0
  23. package/dist/applications/service.js.map +1 -0
  24. package/dist/applications/slugs.d.ts +61 -0
  25. package/dist/applications/slugs.d.ts.map +1 -0
  26. package/dist/applications/slugs.js +115 -0
  27. package/dist/applications/slugs.js.map +1 -0
  28. package/dist/applications/types.d.ts +129 -0
  29. package/dist/applications/types.d.ts.map +1 -0
  30. package/dist/applications/types.js +62 -0
  31. package/dist/applications/types.js.map +1 -0
  32. package/dist/auth/csrf.d.ts +71 -0
  33. package/dist/auth/csrf.d.ts.map +1 -0
  34. package/dist/auth/csrf.js +112 -0
  35. package/dist/auth/csrf.js.map +1 -0
  36. package/dist/auth/email-renderer.d.ts +37 -0
  37. package/dist/auth/email-renderer.d.ts.map +1 -0
  38. package/dist/auth/email-renderer.js +116 -0
  39. package/dist/auth/email-renderer.js.map +1 -0
  40. package/dist/auth/email-service.d.ts +154 -0
  41. package/dist/auth/email-service.d.ts.map +1 -0
  42. package/dist/auth/email-service.js +415 -0
  43. package/dist/auth/email-service.js.map +1 -0
  44. package/dist/auth/email-transport.d.ts +65 -0
  45. package/dist/auth/email-transport.d.ts.map +1 -0
  46. package/dist/auth/email-transport.js +82 -0
  47. package/dist/auth/email-transport.js.map +1 -0
  48. package/dist/auth/i18n.d.ts +81 -0
  49. package/dist/auth/i18n.d.ts.map +1 -0
  50. package/dist/auth/i18n.js +395 -0
  51. package/dist/auth/i18n.js.map +1 -0
  52. package/dist/auth/index.d.ts +28 -0
  53. package/dist/auth/index.d.ts.map +1 -0
  54. package/dist/auth/index.js +31 -0
  55. package/dist/auth/index.js.map +1 -0
  56. package/dist/auth/interaction-authority.d.ts +39 -0
  57. package/dist/auth/interaction-authority.d.ts.map +1 -0
  58. package/dist/auth/interaction-authority.js +30 -0
  59. package/dist/auth/interaction-authority.js.map +1 -0
  60. package/dist/auth/magic-link-session.d.ts +81 -0
  61. package/dist/auth/magic-link-session.d.ts.map +1 -0
  62. package/dist/auth/magic-link-session.js +183 -0
  63. package/dist/auth/magic-link-session.js.map +1 -0
  64. package/dist/auth/rate-limiter.d.ts +143 -0
  65. package/dist/auth/rate-limiter.d.ts.map +1 -0
  66. package/dist/auth/rate-limiter.js +220 -0
  67. package/dist/auth/rate-limiter.js.map +1 -0
  68. package/dist/auth/recovery-crypto.d.ts +34 -0
  69. package/dist/auth/recovery-crypto.d.ts.map +1 -0
  70. package/dist/auth/recovery-crypto.js +103 -0
  71. package/dist/auth/recovery-crypto.js.map +1 -0
  72. package/dist/auth/recovery-job-processor.d.ts +24 -0
  73. package/dist/auth/recovery-job-processor.d.ts.map +1 -0
  74. package/dist/auth/recovery-job-processor.js +123 -0
  75. package/dist/auth/recovery-job-processor.js.map +1 -0
  76. package/dist/auth/recovery-job-repository.d.ts +219 -0
  77. package/dist/auth/recovery-job-repository.d.ts.map +1 -0
  78. package/dist/auth/recovery-job-repository.js +340 -0
  79. package/dist/auth/recovery-job-repository.js.map +1 -0
  80. package/dist/auth/recovery-service.d.ts +27 -0
  81. package/dist/auth/recovery-service.d.ts.map +1 -0
  82. package/dist/auth/recovery-service.js +53 -0
  83. package/dist/auth/recovery-service.js.map +1 -0
  84. package/dist/auth/recovery-worker.d.ts +158 -0
  85. package/dist/auth/recovery-worker.d.ts.map +1 -0
  86. package/dist/auth/recovery-worker.js +306 -0
  87. package/dist/auth/recovery-worker.js.map +1 -0
  88. package/dist/auth/template-engine.d.ts +134 -0
  89. package/dist/auth/template-engine.d.ts.map +1 -0
  90. package/dist/auth/template-engine.js +225 -0
  91. package/dist/auth/template-engine.js.map +1 -0
  92. package/dist/auth/token-repository.d.ts +238 -0
  93. package/dist/auth/token-repository.d.ts.map +1 -0
  94. package/dist/auth/token-repository.js +475 -0
  95. package/dist/auth/token-repository.js.map +1 -0
  96. package/dist/auth/tokens.d.ts +45 -0
  97. package/dist/auth/tokens.d.ts.map +1 -0
  98. package/dist/auth/tokens.js +51 -0
  99. package/dist/auth/tokens.js.map +1 -0
  100. package/dist/cli/bootstrap.d.ts +55 -0
  101. package/dist/cli/bootstrap.d.ts.map +1 -0
  102. package/dist/cli/bootstrap.js +90 -0
  103. package/dist/cli/bootstrap.js.map +1 -0
  104. package/dist/cli/commands/health.d.ts +20 -0
  105. package/dist/cli/commands/health.d.ts.map +1 -0
  106. package/dist/cli/commands/health.js +80 -0
  107. package/dist/cli/commands/health.js.map +1 -0
  108. package/dist/cli/commands/init.d.ts +48 -0
  109. package/dist/cli/commands/init.d.ts.map +1 -0
  110. package/dist/cli/commands/init.js +349 -0
  111. package/dist/cli/commands/init.js.map +1 -0
  112. package/dist/cli/commands/migrate.d.ts +19 -0
  113. package/dist/cli/commands/migrate.d.ts.map +1 -0
  114. package/dist/cli/commands/migrate.js +88 -0
  115. package/dist/cli/commands/migrate.js.map +1 -0
  116. package/dist/cli/commands/seed.d.ts +19 -0
  117. package/dist/cli/commands/seed.d.ts.map +1 -0
  118. package/dist/cli/commands/seed.js +71 -0
  119. package/dist/cli/commands/seed.js.map +1 -0
  120. package/dist/cli/commands/user-2fa.d.ts +29 -0
  121. package/dist/cli/commands/user-2fa.d.ts.map +1 -0
  122. package/dist/cli/commands/user-2fa.js +113 -0
  123. package/dist/cli/commands/user-2fa.js.map +1 -0
  124. package/dist/cli/error-handler.d.ts +31 -0
  125. package/dist/cli/error-handler.d.ts.map +1 -0
  126. package/dist/cli/error-handler.js +65 -0
  127. package/dist/cli/error-handler.js.map +1 -0
  128. package/dist/cli/index.d.ts +48 -0
  129. package/dist/cli/index.d.ts.map +1 -0
  130. package/dist/cli/index.js +99 -0
  131. package/dist/cli/index.js.map +1 -0
  132. package/dist/cli/output.d.ts +94 -0
  133. package/dist/cli/output.d.ts.map +1 -0
  134. package/dist/cli/output.js +124 -0
  135. package/dist/cli/output.js.map +1 -0
  136. package/dist/cli/prompt.d.ts +48 -0
  137. package/dist/cli/prompt.d.ts.map +1 -0
  138. package/dist/cli/prompt.js +96 -0
  139. package/dist/cli/prompt.js.map +1 -0
  140. package/dist/clients/cache.d.ts +63 -0
  141. package/dist/clients/cache.d.ts.map +1 -0
  142. package/dist/clients/cache.js +160 -0
  143. package/dist/clients/cache.js.map +1 -0
  144. package/dist/clients/crypto.d.ts +69 -0
  145. package/dist/clients/crypto.d.ts.map +1 -0
  146. package/dist/clients/crypto.js +83 -0
  147. package/dist/clients/crypto.js.map +1 -0
  148. package/dist/clients/errors.d.ts +27 -0
  149. package/dist/clients/errors.d.ts.map +1 -0
  150. package/dist/clients/errors.js +33 -0
  151. package/dist/clients/errors.js.map +1 -0
  152. package/dist/clients/index.d.ts +19 -0
  153. package/dist/clients/index.d.ts.map +1 -0
  154. package/dist/clients/index.js +23 -0
  155. package/dist/clients/index.js.map +1 -0
  156. package/dist/clients/repository.d.ts +161 -0
  157. package/dist/clients/repository.d.ts.map +1 -0
  158. package/dist/clients/repository.js +318 -0
  159. package/dist/clients/repository.js.map +1 -0
  160. package/dist/clients/resolve-login-methods.d.ts +74 -0
  161. package/dist/clients/resolve-login-methods.d.ts.map +1 -0
  162. package/dist/clients/resolve-login-methods.js +68 -0
  163. package/dist/clients/resolve-login-methods.js.map +1 -0
  164. package/dist/clients/secret-repository.d.ts +109 -0
  165. package/dist/clients/secret-repository.d.ts.map +1 -0
  166. package/dist/clients/secret-repository.js +166 -0
  167. package/dist/clients/secret-repository.js.map +1 -0
  168. package/dist/clients/secret-service.d.ts +87 -0
  169. package/dist/clients/secret-service.d.ts.map +1 -0
  170. package/dist/clients/secret-service.js +204 -0
  171. package/dist/clients/secret-service.js.map +1 -0
  172. package/dist/clients/service.d.ts +158 -0
  173. package/dist/clients/service.d.ts.map +1 -0
  174. package/dist/clients/service.js +523 -0
  175. package/dist/clients/service.js.map +1 -0
  176. package/dist/clients/types.d.ts +214 -0
  177. package/dist/clients/types.d.ts.map +1 -0
  178. package/dist/clients/types.js +77 -0
  179. package/dist/clients/types.js.map +1 -0
  180. package/dist/clients/validators.d.ts +87 -0
  181. package/dist/clients/validators.d.ts.map +1 -0
  182. package/dist/clients/validators.js +164 -0
  183. package/dist/clients/validators.js.map +1 -0
  184. package/dist/config/index.d.ts +23 -0
  185. package/dist/config/index.d.ts.map +1 -0
  186. package/dist/config/index.js +52 -0
  187. package/dist/config/index.js.map +1 -0
  188. package/dist/config/schema.d.ts +35 -0
  189. package/dist/config/schema.d.ts.map +1 -0
  190. package/dist/config/schema.js +167 -0
  191. package/dist/config/schema.js.map +1 -0
  192. package/dist/custom-claims/cache.d.ts +48 -0
  193. package/dist/custom-claims/cache.d.ts.map +1 -0
  194. package/dist/custom-claims/cache.js +122 -0
  195. package/dist/custom-claims/cache.js.map +1 -0
  196. package/dist/custom-claims/errors.d.ts +25 -0
  197. package/dist/custom-claims/errors.d.ts.map +1 -0
  198. package/dist/custom-claims/errors.js +31 -0
  199. package/dist/custom-claims/errors.js.map +1 -0
  200. package/dist/custom-claims/index.d.ts +14 -0
  201. package/dist/custom-claims/index.d.ts.map +1 -0
  202. package/dist/custom-claims/index.js +17 -0
  203. package/dist/custom-claims/index.js.map +1 -0
  204. package/dist/custom-claims/repository.d.ts +147 -0
  205. package/dist/custom-claims/repository.d.ts.map +1 -0
  206. package/dist/custom-claims/repository.js +338 -0
  207. package/dist/custom-claims/repository.js.map +1 -0
  208. package/dist/custom-claims/service.d.ts +129 -0
  209. package/dist/custom-claims/service.d.ts.map +1 -0
  210. package/dist/custom-claims/service.js +296 -0
  211. package/dist/custom-claims/service.js.map +1 -0
  212. package/dist/custom-claims/types.d.ts +132 -0
  213. package/dist/custom-claims/types.d.ts.map +1 -0
  214. package/dist/custom-claims/types.js +61 -0
  215. package/dist/custom-claims/types.js.map +1 -0
  216. package/dist/custom-claims/validators.d.ts +61 -0
  217. package/dist/custom-claims/validators.d.ts.map +1 -0
  218. package/dist/custom-claims/validators.js +136 -0
  219. package/dist/custom-claims/validators.js.map +1 -0
  220. package/dist/index.d.ts +14 -0
  221. package/dist/index.d.ts.map +1 -0
  222. package/dist/index.js +91 -0
  223. package/dist/index.js.map +1 -0
  224. package/dist/lib/admin-permissions.d.ts +147 -0
  225. package/dist/lib/admin-permissions.d.ts.map +1 -0
  226. package/dist/lib/admin-permissions.js +261 -0
  227. package/dist/lib/admin-permissions.js.map +1 -0
  228. package/dist/lib/audit-log.d.ts +45 -0
  229. package/dist/lib/audit-log.d.ts.map +1 -0
  230. package/dist/lib/audit-log.js +79 -0
  231. package/dist/lib/audit-log.js.map +1 -0
  232. package/dist/lib/branding-assets.d.ts +47 -0
  233. package/dist/lib/branding-assets.d.ts.map +1 -0
  234. package/dist/lib/branding-assets.js +93 -0
  235. package/dist/lib/branding-assets.js.map +1 -0
  236. package/dist/lib/bulk-operations.d.ts +54 -0
  237. package/dist/lib/bulk-operations.d.ts.map +1 -0
  238. package/dist/lib/bulk-operations.js +201 -0
  239. package/dist/lib/bulk-operations.js.map +1 -0
  240. package/dist/lib/cursor.d.ts +110 -0
  241. package/dist/lib/cursor.d.ts.map +1 -0
  242. package/dist/lib/cursor.js +115 -0
  243. package/dist/lib/cursor.js.map +1 -0
  244. package/dist/lib/data-export.d.ts +67 -0
  245. package/dist/lib/data-export.d.ts.map +1 -0
  246. package/dist/lib/data-export.js +272 -0
  247. package/dist/lib/data-export.js.map +1 -0
  248. package/dist/lib/data-import-plan.d.ts +50 -0
  249. package/dist/lib/data-import-plan.d.ts.map +1 -0
  250. package/dist/lib/data-import-plan.js +235 -0
  251. package/dist/lib/data-import-plan.js.map +1 -0
  252. package/dist/lib/data-import.d.ts +276 -0
  253. package/dist/lib/data-import.d.ts.map +1 -0
  254. package/dist/lib/data-import.js +1694 -0
  255. package/dist/lib/data-import.js.map +1 -0
  256. package/dist/lib/database.d.ts +22 -0
  257. package/dist/lib/database.d.ts.map +1 -0
  258. package/dist/lib/database.js +103 -0
  259. package/dist/lib/database.js.map +1 -0
  260. package/dist/lib/entity-history.d.ts +52 -0
  261. package/dist/lib/entity-history.d.ts.map +1 -0
  262. package/dist/lib/entity-history.js +121 -0
  263. package/dist/lib/entity-history.js.map +1 -0
  264. package/dist/lib/etag.d.ts +92 -0
  265. package/dist/lib/etag.d.ts.map +1 -0
  266. package/dist/lib/etag.js +155 -0
  267. package/dist/lib/etag.js.map +1 -0
  268. package/dist/lib/image-validator.d.ts +44 -0
  269. package/dist/lib/image-validator.d.ts.map +1 -0
  270. package/dist/lib/image-validator.js +204 -0
  271. package/dist/lib/image-validator.js.map +1 -0
  272. package/dist/lib/logger.d.ts +15 -0
  273. package/dist/lib/logger.d.ts.map +1 -0
  274. package/dist/lib/logger.js +84 -0
  275. package/dist/lib/logger.js.map +1 -0
  276. package/dist/lib/migrator.d.ts +14 -0
  277. package/dist/lib/migrator.d.ts.map +1 -0
  278. package/dist/lib/migrator.js +34 -0
  279. package/dist/lib/migrator.js.map +1 -0
  280. package/dist/lib/redis.d.ts +5 -0
  281. package/dist/lib/redis.d.ts.map +1 -0
  282. package/dist/lib/redis.js +29 -0
  283. package/dist/lib/redis.js.map +1 -0
  284. package/dist/lib/runtime-paths.d.ts +38 -0
  285. package/dist/lib/runtime-paths.d.ts.map +1 -0
  286. package/dist/lib/runtime-paths.js +50 -0
  287. package/dist/lib/runtime-paths.js.map +1 -0
  288. package/dist/lib/session-tracking.d.ts +81 -0
  289. package/dist/lib/session-tracking.d.ts.map +1 -0
  290. package/dist/lib/session-tracking.js +145 -0
  291. package/dist/lib/session-tracking.js.map +1 -0
  292. package/dist/lib/signing-key-crypto.d.ts +53 -0
  293. package/dist/lib/signing-key-crypto.d.ts.map +1 -0
  294. package/dist/lib/signing-key-crypto.js +108 -0
  295. package/dist/lib/signing-key-crypto.js.map +1 -0
  296. package/dist/lib/signing-keys.d.ts +141 -0
  297. package/dist/lib/signing-keys.d.ts.map +1 -0
  298. package/dist/lib/signing-keys.js +206 -0
  299. package/dist/lib/signing-keys.js.map +1 -0
  300. package/dist/lib/stats.d.ts +83 -0
  301. package/dist/lib/stats.d.ts.map +1 -0
  302. package/dist/lib/stats.js +187 -0
  303. package/dist/lib/stats.js.map +1 -0
  304. package/dist/lib/super-admin-protection.d.ts +69 -0
  305. package/dist/lib/super-admin-protection.d.ts.map +1 -0
  306. package/dist/lib/super-admin-protection.js +102 -0
  307. package/dist/lib/super-admin-protection.js.map +1 -0
  308. package/dist/lib/system-config.d.ts +79 -0
  309. package/dist/lib/system-config.d.ts.map +1 -0
  310. package/dist/lib/system-config.js +159 -0
  311. package/dist/lib/system-config.js.map +1 -0
  312. package/dist/middleware/admin-auth.d.ts +100 -0
  313. package/dist/middleware/admin-auth.d.ts.map +1 -0
  314. package/dist/middleware/admin-auth.js +241 -0
  315. package/dist/middleware/admin-auth.js.map +1 -0
  316. package/dist/middleware/admin-cors.d.ts +41 -0
  317. package/dist/middleware/admin-cors.d.ts.map +1 -0
  318. package/dist/middleware/admin-cors.js +83 -0
  319. package/dist/middleware/admin-cors.js.map +1 -0
  320. package/dist/middleware/admin-mutation-audit.d.ts +9 -0
  321. package/dist/middleware/admin-mutation-audit.d.ts.map +1 -0
  322. package/dist/middleware/admin-mutation-audit.js +76 -0
  323. package/dist/middleware/admin-mutation-audit.js.map +1 -0
  324. package/dist/middleware/admin-rate-limiter.d.ts +56 -0
  325. package/dist/middleware/admin-rate-limiter.d.ts.map +1 -0
  326. package/dist/middleware/admin-rate-limiter.js +97 -0
  327. package/dist/middleware/admin-rate-limiter.js.map +1 -0
  328. package/dist/middleware/client-secret-hash.d.ts +34 -0
  329. package/dist/middleware/client-secret-hash.d.ts.map +1 -0
  330. package/dist/middleware/client-secret-hash.js +74 -0
  331. package/dist/middleware/client-secret-hash.js.map +1 -0
  332. package/dist/middleware/error-handler.d.ts +3 -0
  333. package/dist/middleware/error-handler.d.ts.map +1 -0
  334. package/dist/middleware/error-handler.js +93 -0
  335. package/dist/middleware/error-handler.js.map +1 -0
  336. package/dist/middleware/health.d.ts +3 -0
  337. package/dist/middleware/health.d.ts.map +1 -0
  338. package/dist/middleware/health.js +35 -0
  339. package/dist/middleware/health.js.map +1 -0
  340. package/dist/middleware/metrics.d.ts +40 -0
  341. package/dist/middleware/metrics.d.ts.map +1 -0
  342. package/dist/middleware/metrics.js +75 -0
  343. package/dist/middleware/metrics.js.map +1 -0
  344. package/dist/middleware/oidc-client-tenant.d.ts +37 -0
  345. package/dist/middleware/oidc-client-tenant.d.ts.map +1 -0
  346. package/dist/middleware/oidc-client-tenant.js +156 -0
  347. package/dist/middleware/oidc-client-tenant.js.map +1 -0
  348. package/dist/middleware/oidc-cors.d.ts +33 -0
  349. package/dist/middleware/oidc-cors.d.ts.map +1 -0
  350. package/dist/middleware/oidc-cors.js +68 -0
  351. package/dist/middleware/oidc-cors.js.map +1 -0
  352. package/dist/middleware/oidc-preflight-cors.d.ts +54 -0
  353. package/dist/middleware/oidc-preflight-cors.d.ts.map +1 -0
  354. package/dist/middleware/oidc-preflight-cors.js +267 -0
  355. package/dist/middleware/oidc-preflight-cors.js.map +1 -0
  356. package/dist/middleware/prompt-login-reset.d.ts +103 -0
  357. package/dist/middleware/prompt-login-reset.d.ts.map +1 -0
  358. package/dist/middleware/prompt-login-reset.js +204 -0
  359. package/dist/middleware/prompt-login-reset.js.map +1 -0
  360. package/dist/middleware/ready.d.ts +23 -0
  361. package/dist/middleware/ready.d.ts.map +1 -0
  362. package/dist/middleware/ready.js +60 -0
  363. package/dist/middleware/ready.js.map +1 -0
  364. package/dist/middleware/request-logger.d.ts +27 -0
  365. package/dist/middleware/request-logger.d.ts.map +1 -0
  366. package/dist/middleware/request-logger.js +46 -0
  367. package/dist/middleware/request-logger.js.map +1 -0
  368. package/dist/middleware/require-permission.d.ts +28 -0
  369. package/dist/middleware/require-permission.d.ts.map +1 -0
  370. package/dist/middleware/require-permission.js +63 -0
  371. package/dist/middleware/require-permission.js.map +1 -0
  372. package/dist/middleware/require-user-organization.d.ts +18 -0
  373. package/dist/middleware/require-user-organization.d.ts.map +1 -0
  374. package/dist/middleware/require-user-organization.js +53 -0
  375. package/dist/middleware/require-user-organization.js.map +1 -0
  376. package/dist/middleware/root-page.d.ts +62 -0
  377. package/dist/middleware/root-page.d.ts.map +1 -0
  378. package/dist/middleware/root-page.js +134 -0
  379. package/dist/middleware/root-page.js.map +1 -0
  380. package/dist/middleware/security-headers.d.ts +98 -0
  381. package/dist/middleware/security-headers.d.ts.map +1 -0
  382. package/dist/middleware/security-headers.js +159 -0
  383. package/dist/middleware/security-headers.js.map +1 -0
  384. package/dist/middleware/tenant-resolver.d.ts +37 -0
  385. package/dist/middleware/tenant-resolver.d.ts.map +1 -0
  386. package/dist/middleware/tenant-resolver.js +71 -0
  387. package/dist/middleware/tenant-resolver.js.map +1 -0
  388. package/dist/middleware/token-rate-limiter.d.ts +89 -0
  389. package/dist/middleware/token-rate-limiter.d.ts.map +1 -0
  390. package/dist/middleware/token-rate-limiter.js +189 -0
  391. package/dist/middleware/token-rate-limiter.js.map +1 -0
  392. package/dist/oidc/account-finder.d.ts +52 -0
  393. package/dist/oidc/account-finder.d.ts.map +1 -0
  394. package/dist/oidc/account-finder.js +134 -0
  395. package/dist/oidc/account-finder.js.map +1 -0
  396. package/dist/oidc/adapter-factory.d.ts +90 -0
  397. package/dist/oidc/adapter-factory.d.ts.map +1 -0
  398. package/dist/oidc/adapter-factory.js +165 -0
  399. package/dist/oidc/adapter-factory.js.map +1 -0
  400. package/dist/oidc/configuration.d.ts +155 -0
  401. package/dist/oidc/configuration.d.ts.map +1 -0
  402. package/dist/oidc/configuration.js +531 -0
  403. package/dist/oidc/configuration.js.map +1 -0
  404. package/dist/oidc/postgres-adapter.d.ts +159 -0
  405. package/dist/oidc/postgres-adapter.d.ts.map +1 -0
  406. package/dist/oidc/postgres-adapter.js +222 -0
  407. package/dist/oidc/postgres-adapter.js.map +1 -0
  408. package/dist/oidc/protocol-security-observer.d.ts +38 -0
  409. package/dist/oidc/protocol-security-observer.d.ts.map +1 -0
  410. package/dist/oidc/protocol-security-observer.js +93 -0
  411. package/dist/oidc/protocol-security-observer.js.map +1 -0
  412. package/dist/oidc/provider.d.ts +37 -0
  413. package/dist/oidc/provider.d.ts.map +1 -0
  414. package/dist/oidc/provider.js +71 -0
  415. package/dist/oidc/provider.js.map +1 -0
  416. package/dist/oidc/redis-adapter.d.ts +140 -0
  417. package/dist/oidc/redis-adapter.d.ts.map +1 -0
  418. package/dist/oidc/redis-adapter.js +344 -0
  419. package/dist/oidc/redis-adapter.js.map +1 -0
  420. package/dist/organizations/cache.d.ts +60 -0
  421. package/dist/organizations/cache.d.ts.map +1 -0
  422. package/dist/organizations/cache.js +157 -0
  423. package/dist/organizations/cache.js.map +1 -0
  424. package/dist/organizations/errors.d.ts +25 -0
  425. package/dist/organizations/errors.d.ts.map +1 -0
  426. package/dist/organizations/errors.js +31 -0
  427. package/dist/organizations/errors.js.map +1 -0
  428. package/dist/organizations/index.d.ts +15 -0
  429. package/dist/organizations/index.d.ts.map +1 -0
  430. package/dist/organizations/index.js +15 -0
  431. package/dist/organizations/index.js.map +1 -0
  432. package/dist/organizations/repository.d.ts +183 -0
  433. package/dist/organizations/repository.d.ts.map +1 -0
  434. package/dist/organizations/repository.js +354 -0
  435. package/dist/organizations/repository.js.map +1 -0
  436. package/dist/organizations/service.d.ts +168 -0
  437. package/dist/organizations/service.d.ts.map +1 -0
  438. package/dist/organizations/service.js +511 -0
  439. package/dist/organizations/service.js.map +1 -0
  440. package/dist/organizations/slugs.d.ts +57 -0
  441. package/dist/organizations/slugs.d.ts.map +1 -0
  442. package/dist/organizations/slugs.js +130 -0
  443. package/dist/organizations/slugs.js.map +1 -0
  444. package/dist/organizations/types.d.ts +146 -0
  445. package/dist/organizations/types.d.ts.map +1 -0
  446. package/dist/organizations/types.js +49 -0
  447. package/dist/organizations/types.js.map +1 -0
  448. package/dist/rbac/cache.d.ts +110 -0
  449. package/dist/rbac/cache.d.ts.map +1 -0
  450. package/dist/rbac/cache.js +271 -0
  451. package/dist/rbac/cache.js.map +1 -0
  452. package/dist/rbac/errors.d.ts +34 -0
  453. package/dist/rbac/errors.d.ts.map +1 -0
  454. package/dist/rbac/errors.js +43 -0
  455. package/dist/rbac/errors.js.map +1 -0
  456. package/dist/rbac/index.d.ts +17 -0
  457. package/dist/rbac/index.d.ts.map +1 -0
  458. package/dist/rbac/index.js +21 -0
  459. package/dist/rbac/index.js.map +1 -0
  460. package/dist/rbac/mapping-repository.d.ts +121 -0
  461. package/dist/rbac/mapping-repository.d.ts.map +1 -0
  462. package/dist/rbac/mapping-repository.js +224 -0
  463. package/dist/rbac/mapping-repository.js.map +1 -0
  464. package/dist/rbac/permission-repository.d.ts +100 -0
  465. package/dist/rbac/permission-repository.d.ts.map +1 -0
  466. package/dist/rbac/permission-repository.js +190 -0
  467. package/dist/rbac/permission-repository.js.map +1 -0
  468. package/dist/rbac/permission-service.d.ts +85 -0
  469. package/dist/rbac/permission-service.d.ts.map +1 -0
  470. package/dist/rbac/permission-service.js +179 -0
  471. package/dist/rbac/permission-service.js.map +1 -0
  472. package/dist/rbac/role-repository.d.ts +104 -0
  473. package/dist/rbac/role-repository.d.ts.map +1 -0
  474. package/dist/rbac/role-repository.js +202 -0
  475. package/dist/rbac/role-repository.js.map +1 -0
  476. package/dist/rbac/role-service.d.ts +111 -0
  477. package/dist/rbac/role-service.d.ts.map +1 -0
  478. package/dist/rbac/role-service.js +256 -0
  479. package/dist/rbac/role-service.js.map +1 -0
  480. package/dist/rbac/slugs.d.ts +116 -0
  481. package/dist/rbac/slugs.d.ts.map +1 -0
  482. package/dist/rbac/slugs.js +178 -0
  483. package/dist/rbac/slugs.js.map +1 -0
  484. package/dist/rbac/types.d.ts +187 -0
  485. package/dist/rbac/types.d.ts.map +1 -0
  486. package/dist/rbac/types.js +75 -0
  487. package/dist/rbac/types.js.map +1 -0
  488. package/dist/rbac/user-role-service.d.ts +101 -0
  489. package/dist/rbac/user-role-service.d.ts.map +1 -0
  490. package/dist/rbac/user-role-service.js +166 -0
  491. package/dist/rbac/user-role-service.js.map +1 -0
  492. package/dist/routes/applications.d.ts +40 -0
  493. package/dist/routes/applications.d.ts.map +1 -0
  494. package/dist/routes/applications.js +284 -0
  495. package/dist/routes/applications.js.map +1 -0
  496. package/dist/routes/audit.d.ts +31 -0
  497. package/dist/routes/audit.d.ts.map +1 -0
  498. package/dist/routes/audit.js +140 -0
  499. package/dist/routes/audit.js.map +1 -0
  500. package/dist/routes/branding.d.ts +17 -0
  501. package/dist/routes/branding.d.ts.map +1 -0
  502. package/dist/routes/branding.js +104 -0
  503. package/dist/routes/branding.js.map +1 -0
  504. package/dist/routes/bulk.d.ts +37 -0
  505. package/dist/routes/bulk.d.ts.map +1 -0
  506. package/dist/routes/bulk.js +94 -0
  507. package/dist/routes/bulk.js.map +1 -0
  508. package/dist/routes/clients.d.ts +44 -0
  509. package/dist/routes/clients.d.ts.map +1 -0
  510. package/dist/routes/clients.js +353 -0
  511. package/dist/routes/clients.js.map +1 -0
  512. package/dist/routes/config.d.ts +35 -0
  513. package/dist/routes/config.d.ts.map +1 -0
  514. package/dist/routes/config.js +115 -0
  515. package/dist/routes/config.js.map +1 -0
  516. package/dist/routes/custom-claims.d.ts +38 -0
  517. package/dist/routes/custom-claims.d.ts.map +1 -0
  518. package/dist/routes/custom-claims.js +208 -0
  519. package/dist/routes/custom-claims.js.map +1 -0
  520. package/dist/routes/exports.d.ts +21 -0
  521. package/dist/routes/exports.d.ts.map +1 -0
  522. package/dist/routes/exports.js +98 -0
  523. package/dist/routes/exports.js.map +1 -0
  524. package/dist/routes/imports.d.ts +18 -0
  525. package/dist/routes/imports.d.ts.map +1 -0
  526. package/dist/routes/imports.js +72 -0
  527. package/dist/routes/imports.js.map +1 -0
  528. package/dist/routes/interactions.d.ts +111 -0
  529. package/dist/routes/interactions.d.ts.map +1 -0
  530. package/dist/routes/interactions.js +1074 -0
  531. package/dist/routes/interactions.js.map +1 -0
  532. package/dist/routes/invitation.d.ts +31 -0
  533. package/dist/routes/invitation.d.ts.map +1 -0
  534. package/dist/routes/invitation.js +342 -0
  535. package/dist/routes/invitation.js.map +1 -0
  536. package/dist/routes/keys.d.ts +28 -0
  537. package/dist/routes/keys.d.ts.map +1 -0
  538. package/dist/routes/keys.js +91 -0
  539. package/dist/routes/keys.js.map +1 -0
  540. package/dist/routes/magic-link.d.ts +43 -0
  541. package/dist/routes/magic-link.d.ts.map +1 -0
  542. package/dist/routes/magic-link.js +264 -0
  543. package/dist/routes/magic-link.js.map +1 -0
  544. package/dist/routes/organizations.d.ts +38 -0
  545. package/dist/routes/organizations.d.ts.map +1 -0
  546. package/dist/routes/organizations.js +347 -0
  547. package/dist/routes/organizations.js.map +1 -0
  548. package/dist/routes/password-reset.d.ts +65 -0
  549. package/dist/routes/password-reset.d.ts.map +1 -0
  550. package/dist/routes/password-reset.js +493 -0
  551. package/dist/routes/password-reset.js.map +1 -0
  552. package/dist/routes/permissions.d.ts +33 -0
  553. package/dist/routes/permissions.d.ts.map +1 -0
  554. package/dist/routes/permissions.js +166 -0
  555. package/dist/routes/permissions.js.map +1 -0
  556. package/dist/routes/roles.d.ts +37 -0
  557. package/dist/routes/roles.d.ts.map +1 -0
  558. package/dist/routes/roles.js +222 -0
  559. package/dist/routes/roles.js.map +1 -0
  560. package/dist/routes/sessions.d.ts +37 -0
  561. package/dist/routes/sessions.d.ts.map +1 -0
  562. package/dist/routes/sessions.js +121 -0
  563. package/dist/routes/sessions.js.map +1 -0
  564. package/dist/routes/stats.d.ts +28 -0
  565. package/dist/routes/stats.d.ts.map +1 -0
  566. package/dist/routes/stats.js +65 -0
  567. package/dist/routes/stats.js.map +1 -0
  568. package/dist/routes/two-factor-admin.d.ts +54 -0
  569. package/dist/routes/two-factor-admin.d.ts.map +1 -0
  570. package/dist/routes/two-factor-admin.js +344 -0
  571. package/dist/routes/two-factor-admin.js.map +1 -0
  572. package/dist/routes/two-factor.d.ts +31 -0
  573. package/dist/routes/two-factor.d.ts.map +1 -0
  574. package/dist/routes/two-factor.js +595 -0
  575. package/dist/routes/two-factor.js.map +1 -0
  576. package/dist/routes/user-roles.d.ts +33 -0
  577. package/dist/routes/user-roles.d.ts.map +1 -0
  578. package/dist/routes/user-roles.js +129 -0
  579. package/dist/routes/user-roles.js.map +1 -0
  580. package/dist/routes/users.d.ts +61 -0
  581. package/dist/routes/users.d.ts.map +1 -0
  582. package/dist/routes/users.js +868 -0
  583. package/dist/routes/users.js.map +1 -0
  584. package/dist/security/decision-context.d.ts +52 -0
  585. package/dist/security/decision-context.d.ts.map +1 -0
  586. package/dist/security/decision-context.js +150 -0
  587. package/dist/security/decision-context.js.map +1 -0
  588. package/dist/security/decision-event.d.ts +128 -0
  589. package/dist/security/decision-event.d.ts.map +1 -0
  590. package/dist/security/decision-event.js +225 -0
  591. package/dist/security/decision-event.js.map +1 -0
  592. package/dist/security/transport-decision.d.ts +6 -0
  593. package/dist/security/transport-decision.d.ts.map +1 -0
  594. package/dist/security/transport-decision.js +37 -0
  595. package/dist/security/transport-decision.js.map +1 -0
  596. package/dist/server.d.ts +50 -0
  597. package/dist/server.d.ts.map +1 -0
  598. package/dist/server.js +491 -0
  599. package/dist/server.js.map +1 -0
  600. package/dist/two-factor/cache.d.ts +47 -0
  601. package/dist/two-factor/cache.d.ts.map +1 -0
  602. package/dist/two-factor/cache.js +122 -0
  603. package/dist/two-factor/cache.js.map +1 -0
  604. package/dist/two-factor/crypto.d.ts +41 -0
  605. package/dist/two-factor/crypto.d.ts.map +1 -0
  606. package/dist/two-factor/crypto.js +94 -0
  607. package/dist/two-factor/crypto.js.map +1 -0
  608. package/dist/two-factor/errors.d.ts +82 -0
  609. package/dist/two-factor/errors.d.ts.map +1 -0
  610. package/dist/two-factor/errors.js +112 -0
  611. package/dist/two-factor/errors.js.map +1 -0
  612. package/dist/two-factor/index.d.ts +18 -0
  613. package/dist/two-factor/index.d.ts.map +1 -0
  614. package/dist/two-factor/index.js +25 -0
  615. package/dist/two-factor/index.js.map +1 -0
  616. package/dist/two-factor/otp.d.ts +43 -0
  617. package/dist/two-factor/otp.d.ts.map +1 -0
  618. package/dist/two-factor/otp.js +57 -0
  619. package/dist/two-factor/otp.js.map +1 -0
  620. package/dist/two-factor/recovery.d.ts +45 -0
  621. package/dist/two-factor/recovery.d.ts.map +1 -0
  622. package/dist/two-factor/recovery.js +104 -0
  623. package/dist/two-factor/recovery.js.map +1 -0
  624. package/dist/two-factor/repository.d.ts +156 -0
  625. package/dist/two-factor/repository.d.ts.map +1 -0
  626. package/dist/two-factor/repository.js +251 -0
  627. package/dist/two-factor/repository.js.map +1 -0
  628. package/dist/two-factor/service.d.ts +232 -0
  629. package/dist/two-factor/service.d.ts.map +1 -0
  630. package/dist/two-factor/service.js +599 -0
  631. package/dist/two-factor/service.js.map +1 -0
  632. package/dist/two-factor/totp.d.ts +57 -0
  633. package/dist/two-factor/totp.d.ts.map +1 -0
  634. package/dist/two-factor/totp.js +96 -0
  635. package/dist/two-factor/totp.js.map +1 -0
  636. package/dist/two-factor/types.d.ts +152 -0
  637. package/dist/two-factor/types.d.ts.map +1 -0
  638. package/dist/two-factor/types.js +64 -0
  639. package/dist/two-factor/types.js.map +1 -0
  640. package/dist/users/cache.d.ts +49 -0
  641. package/dist/users/cache.d.ts.map +1 -0
  642. package/dist/users/cache.js +140 -0
  643. package/dist/users/cache.js.map +1 -0
  644. package/dist/users/claims.d.ts +67 -0
  645. package/dist/users/claims.d.ts.map +1 -0
  646. package/dist/users/claims.js +104 -0
  647. package/dist/users/claims.js.map +1 -0
  648. package/dist/users/errors.d.ts +25 -0
  649. package/dist/users/errors.d.ts.map +1 -0
  650. package/dist/users/errors.js +31 -0
  651. package/dist/users/errors.js.map +1 -0
  652. package/dist/users/gdpr.d.ts +110 -0
  653. package/dist/users/gdpr.d.ts.map +1 -0
  654. package/dist/users/gdpr.js +211 -0
  655. package/dist/users/gdpr.js.map +1 -0
  656. package/dist/users/index.d.ts +20 -0
  657. package/dist/users/index.d.ts.map +1 -0
  658. package/dist/users/index.js +19 -0
  659. package/dist/users/index.js.map +1 -0
  660. package/dist/users/password.d.ts +85 -0
  661. package/dist/users/password.d.ts.map +1 -0
  662. package/dist/users/password.js +138 -0
  663. package/dist/users/password.js.map +1 -0
  664. package/dist/users/repository.d.ts +263 -0
  665. package/dist/users/repository.d.ts.map +1 -0
  666. package/dist/users/repository.js +499 -0
  667. package/dist/users/repository.js.map +1 -0
  668. package/dist/users/service.d.ts +299 -0
  669. package/dist/users/service.d.ts.map +1 -0
  670. package/dist/users/service.js +698 -0
  671. package/dist/users/service.js.map +1 -0
  672. package/dist/users/types.d.ts +220 -0
  673. package/dist/users/types.d.ts.map +1 -0
  674. package/dist/users/types.js +77 -0
  675. package/dist/users/types.js.map +1 -0
  676. package/locales/default/en/common.json +10 -0
  677. package/locales/default/en/consent.json +13 -0
  678. package/locales/default/en/emails.json +17 -0
  679. package/locales/default/en/errors.json +21 -0
  680. package/locales/default/en/forgot-password.json +11 -0
  681. package/locales/default/en/invitation.json +18 -0
  682. package/locales/default/en/login.json +17 -0
  683. package/locales/default/en/logout.json +9 -0
  684. package/locales/default/en/magic-link.json +12 -0
  685. package/locales/default/en/reset-password.json +16 -0
  686. package/locales/default/en/two-factor.json +29 -0
  687. package/migrations/.gitkeep +0 -0
  688. package/migrations/001_extensions.sql +22 -0
  689. package/migrations/002_organizations.sql +43 -0
  690. package/migrations/003_applications.sql +50 -0
  691. package/migrations/004_clients.sql +74 -0
  692. package/migrations/005_users.sql +119 -0
  693. package/migrations/006_roles_permissions.sql +80 -0
  694. package/migrations/007_custom_claims.sql +55 -0
  695. package/migrations/008_config.sql +51 -0
  696. package/migrations/009_audit_log.sql +31 -0
  697. package/migrations/010_oidc_adapter.sql +34 -0
  698. package/migrations/011_seed.sql +53 -0
  699. package/migrations/012_two_factor.sql +88 -0
  700. package/migrations/013_client_secret_sha256.sql +22 -0
  701. package/migrations/014_login_methods.sql +34 -0
  702. package/migrations/015_signing_key_encryption.sql +20 -0
  703. package/migrations/016_failed_login_count.sql +27 -0
  704. package/migrations/017_audit_retention.sql +11 -0
  705. package/migrations/018_admin_api_enhancements.sql +78 -0
  706. package/migrations/019_invitation_details.sql +27 -0
  707. package/migrations/020_two_factor_admin_permission.sql +108 -0
  708. package/migrations/021_auth_recovery_jobs.sql +74 -0
  709. package/migrations/022_recovery_artifact_ownership.sql +25 -0
  710. package/migrations/023_magic_link_authority.sql +39 -0
  711. package/package.json +106 -0
  712. package/templates/default/emails/invitation.hbs +39 -0
  713. package/templates/default/emails/invitation.txt.hbs +18 -0
  714. package/templates/default/emails/magic-link.hbs +30 -0
  715. package/templates/default/emails/magic-link.txt.hbs +11 -0
  716. package/templates/default/emails/otp-code.hbs +31 -0
  717. package/templates/default/emails/otp-code.txt.hbs +15 -0
  718. package/templates/default/emails/password-changed.hbs +24 -0
  719. package/templates/default/emails/password-changed.txt.hbs +7 -0
  720. package/templates/default/emails/password-reset.hbs +30 -0
  721. package/templates/default/emails/password-reset.txt.hbs +11 -0
  722. package/templates/default/emails/welcome.hbs +25 -0
  723. package/templates/default/emails/welcome.txt.hbs +9 -0
  724. package/templates/default/layouts/main.hbs +49 -0
  725. package/templates/default/pages/accept-invite.hbs +25 -0
  726. package/templates/default/pages/consent.hbs +27 -0
  727. package/templates/default/pages/error.hbs +15 -0
  728. package/templates/default/pages/forgot-password.hbs +21 -0
  729. package/templates/default/pages/invite-expired.hbs +6 -0
  730. package/templates/default/pages/invite-success.hbs +9 -0
  731. package/templates/default/pages/login.hbs +108 -0
  732. package/templates/default/pages/logout-success.hbs +5 -0
  733. package/templates/default/pages/logout.hbs +24 -0
  734. package/templates/default/pages/magic-link-sent.hbs +10 -0
  735. package/templates/default/pages/magic-link-success.hbs +17 -0
  736. package/templates/default/pages/reset-password.hbs +20 -0
  737. package/templates/default/pages/reset-success.hbs +9 -0
  738. package/templates/default/pages/two-factor-setup.hbs +65 -0
  739. package/templates/default/pages/two-factor-verify.hbs +77 -0
  740. package/templates/default/partials/flash-messages.hbs +10 -0
  741. package/templates/default/partials/footer.hbs +4 -0
  742. package/templates/default/partials/header.hbs +8 -0
@@ -0,0 +1,219 @@
1
+ /**
2
+ * Durable PostgreSQL repository for account-recovery work.
3
+ *
4
+ * Public request handlers enqueue only protected, tenant-bound input. A worker later claims a
5
+ * bounded batch and performs account-specific work outside the request path. Every transition is
6
+ * conditional on the current claim owner so a stale worker cannot complete or reschedule work
7
+ * reclaimed by another process.
8
+ */
9
+ import type { Pool, PoolClient, QueryResult, QueryResultRow } from 'pg';
10
+ /** Closed recovery operations accepted by the durable queue. */
11
+ export declare const RECOVERY_JOB_TYPES: readonly ['magic_link', 'password_reset'];
12
+ /** Closed durable lifecycle states for recovery work. */
13
+ export declare const RECOVERY_JOB_STATUSES: readonly ['available', 'claimed', 'completed', 'terminal_failure'];
14
+ /** Maximum number of jobs one worker pass may claim. */
15
+ export declare const RECOVERY_JOB_CLAIM_LIMIT = 25;
16
+ /** Maximum processing attempts retained by the durable schema. */
17
+ export declare const RECOVERY_JOB_ATTEMPT_LIMIT = 5;
18
+ /** Recovery operation represented by a durable job. */
19
+ export type RecoveryJobType = (typeof RECOVERY_JOB_TYPES)[number];
20
+ /** Durable lifecycle state of recovery work. */
21
+ export type RecoveryJobStatus = (typeof RECOVERY_JOB_STATUSES)[number];
22
+ /**
23
+ * Authenticated-encryption envelope for a normalized recovery address.
24
+ *
25
+ * The repository treats these values as opaque protected bytes encoded by the caller. Plaintext
26
+ * addresses must never cross this boundary.
27
+ */
28
+ export interface ProtectedRecoveryAddress {
29
+ /** Authenticated ciphertext encoded as base64url. */
30
+ readonly ciphertext: string;
31
+ /** Unique AES-GCM initialization vector encoded as base64url. */
32
+ readonly iv: string;
33
+ /** AES-GCM authentication tag encoded as base64url. */
34
+ readonly tag: string;
35
+ /** Non-secret identifier for the encryption key used by the envelope. */
36
+ readonly keyId: string;
37
+ }
38
+ /** Input accepted when one public recovery request enqueues durable work. */
39
+ export interface EnqueueRecoveryJobInput {
40
+ /** Recovery operation to perform. */
41
+ readonly jobType: RecoveryJobType;
42
+ /** Tenant authority resolved by the public route. */
43
+ readonly organizationId: string;
44
+ /** Protected normalized recovery address. */
45
+ readonly protectedAddress: ProtectedRecoveryAddress;
46
+ /** OIDC interaction binding for a magic-link request, otherwise null. */
47
+ readonly interactionUid: string | null;
48
+ /** Keyed, domain-separated digest identifying this admitted request. */
49
+ readonly idempotencyDigest: string;
50
+ /** Earliest time at which a worker may claim the job. */
51
+ readonly availableAt: Date;
52
+ }
53
+ /** Durable recovery job returned to request and worker services. */
54
+ export interface RecoveryJob {
55
+ /** Durable job identifier. */
56
+ readonly id: string;
57
+ /** Recovery operation represented by the job. */
58
+ readonly jobType: RecoveryJobType;
59
+ /** Tenant authority persisted with the job. */
60
+ readonly organizationId: string;
61
+ /** Protected recovery address. */
62
+ readonly protectedAddress: ProtectedRecoveryAddress;
63
+ /** OIDC interaction binding, or null for standalone work. */
64
+ readonly interactionUid: string | null;
65
+ /** Keyed, domain-separated request idempotency digest. */
66
+ readonly idempotencyDigest: string;
67
+ /** Current durable lifecycle state. */
68
+ readonly status: RecoveryJobStatus;
69
+ /** Earliest claim time. */
70
+ readonly availableAt: Date;
71
+ /** Time at which the current worker claimed the job. */
72
+ readonly claimedAt: Date | null;
73
+ /** Current worker owner identifier. */
74
+ readonly claimedBy: string | null;
75
+ /** Number of processing attempts already started. */
76
+ readonly attemptCount: number;
77
+ /** Closed failure reason from the latest unsuccessful attempt. */
78
+ readonly lastFailureReason: string | null;
79
+ /** Terminal transition time. */
80
+ readonly completedAt: Date | null;
81
+ /** Job creation time. */
82
+ readonly createdAt: Date;
83
+ /** Latest durable transition time. */
84
+ readonly updatedAt: Date;
85
+ }
86
+ /** Recovery job returned from an atomic claim with its acquisition reason. */
87
+ export interface ClaimedRecoveryJob extends RecoveryJob {
88
+ /**
89
+ * How this worker acquired the row. An exhausted lease must be terminally closed without
90
+ * performing account-specific work because the prior fifth attempt has an unknown outcome.
91
+ */
92
+ readonly claimDisposition: 'available' | 'lease_reclaimed' | 'lease_exhausted';
93
+ }
94
+ /** Result of an idempotent enqueue operation. */
95
+ export interface EnqueueRecoveryJobResult {
96
+ /** Durable row representing the request. */
97
+ readonly job: RecoveryJob;
98
+ /** Whether this call inserted the row rather than observing an existing idempotency match. */
99
+ readonly inserted: boolean;
100
+ }
101
+ /** Input for one bounded atomic claim operation. */
102
+ export interface ClaimRecoveryJobsInput {
103
+ /** Unique worker-process identifier. */
104
+ readonly workerId: string;
105
+ /** Repository clock value used for every row in the transition. */
106
+ readonly now: Date;
107
+ /** Claims at or before this instant may be reclaimed. */
108
+ readonly leaseExpiredBefore: Date;
109
+ /** Maximum jobs to claim, bounded to the product policy maximum. */
110
+ readonly limit?: number;
111
+ }
112
+ /** Input for charging one processing attempt against an owned claim. */
113
+ export interface BeginRecoveryJobAttemptInput {
114
+ /** Durable job identifier. */
115
+ readonly jobId: string;
116
+ /** Worker that currently owns the claim. */
117
+ readonly workerId: string;
118
+ /** Repository clock value used for the transition. */
119
+ readonly now: Date;
120
+ }
121
+ /** Input for returning an owned claim to the available queue. */
122
+ export interface RetryRecoveryJobInput {
123
+ /** Durable job identifier. */
124
+ readonly jobId: string;
125
+ /** Worker that currently owns the claim. */
126
+ readonly workerId: string;
127
+ /** Earliest time at which the retry may be claimed. */
128
+ readonly availableAt: Date;
129
+ /** Closed privacy-safe failure reason. */
130
+ readonly reason: string;
131
+ /** Repository clock value used for the transition. */
132
+ readonly now: Date;
133
+ }
134
+ /** Input for a terminal owned-claim transition. */
135
+ export interface FinishRecoveryJobInput {
136
+ /** Durable job identifier. */
137
+ readonly jobId: string;
138
+ /** Worker that currently owns the claim. */
139
+ readonly workerId: string;
140
+ /** Repository clock value used for the transition. */
141
+ readonly now: Date;
142
+ /** Closed reason required for terminal failure and omitted for success. */
143
+ readonly reason?: string;
144
+ }
145
+ /** Minimal query boundary shared by PostgreSQL pools and transaction clients. */
146
+ export interface RecoveryJobDatabase {
147
+ /** Execute one parameterized query. */
148
+ query<Row extends QueryResultRow = QueryResultRow>(text: string, values?: readonly unknown[]): Promise<QueryResult<Row>>;
149
+ }
150
+ /**
151
+ * Create a durable recovery-job repository.
152
+ *
153
+ * Passing a transaction client keeps enqueue operations composable with a request-owned
154
+ * transaction. Omitting the argument uses Porta's connected application pool.
155
+ *
156
+ * @param database - PostgreSQL pool or transaction client.
157
+ * @returns Typed repository for durable recovery work.
158
+ */
159
+ export declare function createRecoveryJobRepository(database?: RecoveryJobDatabase): RecoveryJobRepository;
160
+ /** PostgreSQL implementation of durable recovery-work transitions. */
161
+ export declare class RecoveryJobRepository {
162
+ /** Query boundary used by every repository operation. */
163
+ protected readonly database: RecoveryJobDatabase;
164
+ /**
165
+ * Create a repository over a pool or existing transaction.
166
+ *
167
+ * @param database - Parameterized PostgreSQL query boundary.
168
+ */
169
+ constructor(database: RecoveryJobDatabase);
170
+ /**
171
+ * Insert one durable job or return the existing idempotency match.
172
+ *
173
+ * @param input - Protected tenant-bound recovery request.
174
+ * @returns Durable row and whether this invocation inserted it.
175
+ */
176
+ enqueue(input: EnqueueRecoveryJobInput): Promise<EnqueueRecoveryJobResult>;
177
+ /**
178
+ * Atomically lease a bounded batch of available or lease-expired jobs.
179
+ *
180
+ * Leasing does not charge a processing attempt. The worker starts each attempt separately, just
181
+ * before invoking account-specific work, so a crash while walking a batch cannot consume the
182
+ * retry budget of jobs it never started.
183
+ *
184
+ * @param input - Worker identity, clock, lease cutoff, and optional bound.
185
+ * @returns Claimed rows with an explicit fresh, reclaimed, or exhausted-lease disposition.
186
+ */
187
+ claimAvailable(input: ClaimRecoveryJobsInput): Promise<readonly ClaimedRecoveryJob[]>;
188
+ /**
189
+ * Charge one processing attempt immediately before an owned job is processed.
190
+ *
191
+ * @param input - Owned job identity and repository clock.
192
+ * @returns The updated claimed row, or null when ownership was lost or the budget is exhausted.
193
+ */
194
+ beginAttempt(input: BeginRecoveryJobAttemptInput): Promise<RecoveryJob | null>;
195
+ /**
196
+ * Return an owned claim to the queue after a transient failure.
197
+ *
198
+ * @param input - Owned job, retry time, closed reason, and repository clock.
199
+ * @returns True only when the caller still owned the claim.
200
+ */
201
+ scheduleRetry(input: RetryRecoveryJobInput): Promise<boolean>;
202
+ /**
203
+ * Mark an owned claim complete after its external effects settle.
204
+ *
205
+ * @param input - Owned job and repository clock; reason must be omitted.
206
+ * @returns True only when the caller still owned the claim.
207
+ */
208
+ markCompleted(input: FinishRecoveryJobInput): Promise<boolean>;
209
+ /**
210
+ * Mark an owned claim terminally failed with a closed privacy-safe reason.
211
+ *
212
+ * @param input - Owned job, repository clock, and required closed reason.
213
+ * @returns True only when the caller still owned the claim.
214
+ */
215
+ markTerminalFailure(input: FinishRecoveryJobInput): Promise<boolean>;
216
+ }
217
+ /** PostgreSQL clients accepted by the repository factory. */
218
+ export type RecoveryJobPostgresClient = Pool | PoolClient;
219
+ //# sourceMappingURL=recovery-job-repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recovery-job-repository.d.ts","sourceRoot":"","sources":["../../src/auth/recovery-job-repository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,340 @@
1
+ /**
2
+ * Durable PostgreSQL repository for account-recovery work.
3
+ *
4
+ * Public request handlers enqueue only protected, tenant-bound input. A worker later claims a
5
+ * bounded batch and performs account-specific work outside the request path. Every transition is
6
+ * conditional on the current claim owner so a stale worker cannot complete or reschedule work
7
+ * reclaimed by another process.
8
+ */
9
+ import { z } from 'zod';
10
+ import { getPool } from '../lib/database.js';
11
+ /** Closed recovery operations accepted by the durable queue. */
12
+ export const RECOVERY_JOB_TYPES = ['magic_link', 'password_reset'];
13
+ /** Closed durable lifecycle states for recovery work. */
14
+ export const RECOVERY_JOB_STATUSES = [
15
+ 'available',
16
+ 'claimed',
17
+ 'completed',
18
+ 'terminal_failure',
19
+ ];
20
+ /** Maximum number of jobs one worker pass may claim. */
21
+ export const RECOVERY_JOB_CLAIM_LIMIT = 25;
22
+ /** Maximum processing attempts retained by the durable schema. */
23
+ export const RECOVERY_JOB_ATTEMPT_LIMIT = 5;
24
+ const uuidSchema = z.string().uuid();
25
+ const protectedTextSchema = z
26
+ .string()
27
+ .min(1)
28
+ .max(4096)
29
+ .regex(/^[A-Za-z0-9_-]+$/);
30
+ const keyIdSchema = z.string().regex(/^[A-Za-z0-9_-]{8,64}$/);
31
+ const digestSchema = z.string().regex(/^[0-9a-f]{64}$/);
32
+ const interactionUidSchema = z.string().min(1).max(128).nullable();
33
+ const reasonSchema = z.string().regex(/^[a-z][a-z0-9_]{0,63}$/);
34
+ const enqueueSchema = z
35
+ .object({
36
+ jobType: z.enum(RECOVERY_JOB_TYPES),
37
+ organizationId: uuidSchema,
38
+ protectedAddress: z
39
+ .object({
40
+ ciphertext: protectedTextSchema,
41
+ iv: protectedTextSchema,
42
+ tag: protectedTextSchema,
43
+ keyId: keyIdSchema,
44
+ })
45
+ .strict(),
46
+ interactionUid: interactionUidSchema,
47
+ idempotencyDigest: digestSchema,
48
+ availableAt: z.date(),
49
+ })
50
+ .strict()
51
+ .superRefine((input, context) => {
52
+ const interactionMatchesType = input.jobType === 'magic_link' ||
53
+ (input.jobType === 'password_reset' && input.interactionUid === null);
54
+ if (!interactionMatchesType) {
55
+ context.addIssue({
56
+ code: 'custom',
57
+ path: ['interactionUid'],
58
+ message: 'interaction binding does not match the recovery job type',
59
+ });
60
+ }
61
+ });
62
+ const claimSchema = z
63
+ .object({
64
+ workerId: uuidSchema,
65
+ now: z.date(),
66
+ leaseExpiredBefore: z.date(),
67
+ limit: z.number().int().min(1).max(RECOVERY_JOB_CLAIM_LIMIT).default(RECOVERY_JOB_CLAIM_LIMIT),
68
+ })
69
+ .strict()
70
+ .refine((input) => input.leaseExpiredBefore.getTime() <= input.now.getTime(), {
71
+ path: ['leaseExpiredBefore'],
72
+ message: 'lease expiry cutoff cannot be later than the repository clock',
73
+ });
74
+ const retrySchema = z
75
+ .object({
76
+ jobId: uuidSchema,
77
+ workerId: uuidSchema,
78
+ availableAt: z.date(),
79
+ reason: reasonSchema,
80
+ now: z.date(),
81
+ })
82
+ .strict()
83
+ .refine((input) => input.availableAt.getTime() >= input.now.getTime(), {
84
+ path: ['availableAt'],
85
+ message: 'retry availability cannot precede the repository clock',
86
+ });
87
+ const beginAttemptSchema = z
88
+ .object({
89
+ jobId: uuidSchema,
90
+ workerId: uuidSchema,
91
+ now: z.date(),
92
+ })
93
+ .strict();
94
+ const finishSchema = z
95
+ .object({
96
+ jobId: uuidSchema,
97
+ workerId: uuidSchema,
98
+ now: z.date(),
99
+ reason: reasonSchema.optional(),
100
+ })
101
+ .strict();
102
+ const JOB_COLUMNS = `
103
+ id, job_type, organization_id,
104
+ address_ciphertext, address_iv, address_tag, address_key_id,
105
+ interaction_uid, idempotency_digest, status, available_at,
106
+ claimed_at, claimed_by, attempt_count, last_failure_reason,
107
+ completed_at, created_at, updated_at
108
+ `;
109
+ const QUALIFIED_JOB_COLUMNS = `
110
+ job.id, job.job_type, job.organization_id,
111
+ job.address_ciphertext, job.address_iv, job.address_tag, job.address_key_id,
112
+ job.interaction_uid, job.idempotency_digest, job.status, job.available_at,
113
+ job.claimed_at, job.claimed_by, job.attempt_count, job.last_failure_reason,
114
+ job.completed_at, job.created_at, job.updated_at
115
+ `;
116
+ /** Map one database row to the public repository model. */
117
+ function mapRecoveryJob(row) {
118
+ return {
119
+ id: row.id,
120
+ jobType: row.job_type,
121
+ organizationId: row.organization_id,
122
+ protectedAddress: {
123
+ ciphertext: row.address_ciphertext,
124
+ iv: row.address_iv,
125
+ tag: row.address_tag,
126
+ keyId: row.address_key_id,
127
+ },
128
+ interactionUid: row.interaction_uid,
129
+ idempotencyDigest: row.idempotency_digest,
130
+ status: row.status,
131
+ availableAt: row.available_at,
132
+ claimedAt: row.claimed_at,
133
+ claimedBy: row.claimed_by,
134
+ attemptCount: row.attempt_count,
135
+ lastFailureReason: row.last_failure_reason,
136
+ completedAt: row.completed_at,
137
+ createdAt: row.created_at,
138
+ updatedAt: row.updated_at,
139
+ };
140
+ }
141
+ /**
142
+ * Create a durable recovery-job repository.
143
+ *
144
+ * Passing a transaction client keeps enqueue operations composable with a request-owned
145
+ * transaction. Omitting the argument uses Porta's connected application pool.
146
+ *
147
+ * @param database - PostgreSQL pool or transaction client.
148
+ * @returns Typed repository for durable recovery work.
149
+ */
150
+ export function createRecoveryJobRepository(database = getPool()) {
151
+ return new RecoveryJobRepository(database);
152
+ }
153
+ /** PostgreSQL implementation of durable recovery-work transitions. */
154
+ export class RecoveryJobRepository {
155
+ /** Query boundary used by every repository operation. */
156
+ database;
157
+ /**
158
+ * Create a repository over a pool or existing transaction.
159
+ *
160
+ * @param database - Parameterized PostgreSQL query boundary.
161
+ */
162
+ constructor(database) {
163
+ this.database = database;
164
+ }
165
+ /**
166
+ * Insert one durable job or return the existing idempotency match.
167
+ *
168
+ * @param input - Protected tenant-bound recovery request.
169
+ * @returns Durable row and whether this invocation inserted it.
170
+ */
171
+ async enqueue(input) {
172
+ const parsed = enqueueSchema.parse(input);
173
+ const result = await this.database.query(`INSERT INTO auth_recovery_jobs (
174
+ job_type, organization_id,
175
+ address_ciphertext, address_iv, address_tag, address_key_id,
176
+ interaction_uid, idempotency_digest, available_at
177
+ ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
178
+ ON CONFLICT (organization_id, job_type, idempotency_digest) DO NOTHING
179
+ RETURNING ${JOB_COLUMNS}`, [
180
+ parsed.jobType,
181
+ parsed.organizationId,
182
+ parsed.protectedAddress.ciphertext,
183
+ parsed.protectedAddress.iv,
184
+ parsed.protectedAddress.tag,
185
+ parsed.protectedAddress.keyId,
186
+ parsed.interactionUid,
187
+ parsed.idempotencyDigest,
188
+ parsed.availableAt,
189
+ ]);
190
+ if (result.rows[0]) {
191
+ return { job: mapRecoveryJob(result.rows[0]), inserted: true };
192
+ }
193
+ const existing = await this.database.query(`SELECT ${JOB_COLUMNS}
194
+ FROM auth_recovery_jobs
195
+ WHERE organization_id = $1
196
+ AND job_type = $2
197
+ AND idempotency_digest = $3`, [parsed.organizationId, parsed.jobType, parsed.idempotencyDigest]);
198
+ if (!existing.rows[0]) {
199
+ throw new Error('Recovery job idempotency row disappeared after insert conflict');
200
+ }
201
+ return { job: mapRecoveryJob(existing.rows[0]), inserted: false };
202
+ }
203
+ /**
204
+ * Atomically lease a bounded batch of available or lease-expired jobs.
205
+ *
206
+ * Leasing does not charge a processing attempt. The worker starts each attempt separately, just
207
+ * before invoking account-specific work, so a crash while walking a batch cannot consume the
208
+ * retry budget of jobs it never started.
209
+ *
210
+ * @param input - Worker identity, clock, lease cutoff, and optional bound.
211
+ * @returns Claimed rows with an explicit fresh, reclaimed, or exhausted-lease disposition.
212
+ */
213
+ async claimAvailable(input) {
214
+ const parsed = claimSchema.parse(input);
215
+ const result = await this.database.query(`WITH candidates AS (
216
+ SELECT id, status AS previous_status, attempt_count AS previous_attempt_count
217
+ FROM auth_recovery_jobs
218
+ WHERE (status = 'available' AND available_at <= $1 AND attempt_count < $5)
219
+ OR (status = 'claimed' AND claimed_at <= $2 AND attempt_count <= $5)
220
+ ORDER BY COALESCE(claimed_at, available_at), created_at, id
221
+ LIMIT $3
222
+ FOR UPDATE SKIP LOCKED
223
+ )
224
+ UPDATE auth_recovery_jobs AS job
225
+ SET status = 'claimed',
226
+ claimed_at = $1,
227
+ claimed_by = $4,
228
+ last_failure_reason = NULL,
229
+ completed_at = NULL,
230
+ updated_at = $1
231
+ FROM candidates
232
+ WHERE job.id = candidates.id
233
+ RETURNING ${QUALIFIED_JOB_COLUMNS},
234
+ CASE
235
+ WHEN candidates.previous_status = 'available' THEN 'available'
236
+ WHEN candidates.previous_attempt_count >= $5 THEN 'lease_exhausted'
237
+ ELSE 'lease_reclaimed'
238
+ END AS claim_disposition`, [
239
+ parsed.now,
240
+ parsed.leaseExpiredBefore,
241
+ parsed.limit,
242
+ parsed.workerId,
243
+ RECOVERY_JOB_ATTEMPT_LIMIT,
244
+ ]);
245
+ return result.rows.map((row) => ({
246
+ ...mapRecoveryJob(row),
247
+ claimDisposition: row.claim_disposition,
248
+ }));
249
+ }
250
+ /**
251
+ * Charge one processing attempt immediately before an owned job is processed.
252
+ *
253
+ * @param input - Owned job identity and repository clock.
254
+ * @returns The updated claimed row, or null when ownership was lost or the budget is exhausted.
255
+ */
256
+ async beginAttempt(input) {
257
+ const parsed = beginAttemptSchema.parse(input);
258
+ const result = await this.database.query(`UPDATE auth_recovery_jobs
259
+ SET attempt_count = attempt_count + 1,
260
+ updated_at = $3
261
+ WHERE id = $1
262
+ AND claimed_by = $2
263
+ AND status = 'claimed'
264
+ AND attempt_count < $4
265
+ RETURNING ${JOB_COLUMNS}`, [parsed.jobId, parsed.workerId, parsed.now, RECOVERY_JOB_ATTEMPT_LIMIT]);
266
+ return result.rows[0] ? mapRecoveryJob(result.rows[0]) : null;
267
+ }
268
+ /**
269
+ * Return an owned claim to the queue after a transient failure.
270
+ *
271
+ * @param input - Owned job, retry time, closed reason, and repository clock.
272
+ * @returns True only when the caller still owned the claim.
273
+ */
274
+ async scheduleRetry(input) {
275
+ const parsed = retrySchema.parse(input);
276
+ const result = await this.database.query(`UPDATE auth_recovery_jobs
277
+ SET status = 'available',
278
+ available_at = $3,
279
+ claimed_at = NULL,
280
+ claimed_by = NULL,
281
+ last_failure_reason = $4,
282
+ updated_at = $5
283
+ WHERE id = $1
284
+ AND claimed_by = $2
285
+ AND status = 'claimed'
286
+ AND attempt_count < $6`, [
287
+ parsed.jobId,
288
+ parsed.workerId,
289
+ parsed.availableAt,
290
+ parsed.reason,
291
+ parsed.now,
292
+ RECOVERY_JOB_ATTEMPT_LIMIT,
293
+ ]);
294
+ return result.rowCount === 1;
295
+ }
296
+ /**
297
+ * Mark an owned claim complete after its external effects settle.
298
+ *
299
+ * @param input - Owned job and repository clock; reason must be omitted.
300
+ * @returns True only when the caller still owned the claim.
301
+ */
302
+ async markCompleted(input) {
303
+ const parsed = finishSchema.parse(input);
304
+ if (parsed.reason !== undefined) {
305
+ throw new Error('Completed recovery jobs cannot carry a failure reason');
306
+ }
307
+ const result = await this.database.query(`UPDATE auth_recovery_jobs
308
+ SET status = 'completed',
309
+ claimed_at = NULL,
310
+ claimed_by = NULL,
311
+ last_failure_reason = NULL,
312
+ completed_at = $3,
313
+ updated_at = $3
314
+ WHERE id = $1
315
+ AND claimed_by = $2
316
+ AND status = 'claimed'`, [parsed.jobId, parsed.workerId, parsed.now]);
317
+ return result.rowCount === 1;
318
+ }
319
+ /**
320
+ * Mark an owned claim terminally failed with a closed privacy-safe reason.
321
+ *
322
+ * @param input - Owned job, repository clock, and required closed reason.
323
+ * @returns True only when the caller still owned the claim.
324
+ */
325
+ async markTerminalFailure(input) {
326
+ const parsed = finishSchema.extend({ reason: reasonSchema }).parse(input);
327
+ const result = await this.database.query(`UPDATE auth_recovery_jobs
328
+ SET status = 'terminal_failure',
329
+ claimed_at = NULL,
330
+ claimed_by = NULL,
331
+ last_failure_reason = $3,
332
+ completed_at = $4,
333
+ updated_at = $4
334
+ WHERE id = $1
335
+ AND claimed_by = $2
336
+ AND status = 'claimed'`, [parsed.jobId, parsed.workerId, parsed.reason, parsed.now]);
337
+ return result.rowCount === 1;
338
+ }
339
+ }
340
+ //# sourceMappingURL=recovery-job-repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recovery-job-repository.js","sourceRoot":"","sources":["../../src/auth/recovery-job-repository.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C,gEAAgE;AAChE,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,YAAY,EAAE,gBAAgB,CAAU,CAAC;AAE5E,yDAAyD;AACzD,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,WAAW;IACX,SAAS;IACT,WAAW;IACX,kBAAkB;CACV,CAAC;AAEX,wDAAwD;AACxD,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAC;AAE3C,kEAAkE;AAClE,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC;AA8K5C,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;AACrC,MAAM,mBAAmB,GAAG,CAAC;KAC1B,MAAM,EAAE;KACR,GAAG,CAAC,CAAC,CAAC;KACN,GAAG,CAAC,IAAI,CAAC;KACT,KAAK,CAAC,kBAAkB,CAAC,CAAC;AAC7B,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;AAC9D,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;AACxD,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;AACnE,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;AAEhE,MAAM,aAAa,GAAG,CAAC;KACpB,MAAM,CAAC;IACN,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC;IACnC,cAAc,EAAE,UAAU;IAC1B,gBAAgB,EAAE,CAAC;SAChB,MAAM,CAAC;QACN,UAAU,EAAE,mBAAmB;QAC/B,EAAE,EAAE,mBAAmB;QACvB,GAAG,EAAE,mBAAmB;QACxB,KAAK,EAAE,WAAW;KACnB,CAAC;SACD,MAAM,EAAE;IACX,cAAc,EAAE,oBAAoB;IACpC,iBAAiB,EAAE,YAAY;IAC/B,WAAW,EAAE,CAAC,CAAC,IAAI,EAAE;CACtB,CAAC;KACD,MAAM,EAAE;KACR,WAAW,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IAC9B,MAAM,sBAAsB,GAC1B,KAAK,CAAC,OAAO,KAAK,YAAY;QAC9B,CAAC,KAAK,CAAC,OAAO,KAAK,gBAAgB,IAAI,KAAK,CAAC,cAAc,KAAK,IAAI,CAAC,CAAC;IACxE,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAC5B,OAAO,CAAC,QAAQ,CAAC;YACf,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,gBAAgB,CAAC;YACxB,OAAO,EAAE,0DAA0D;SACpE,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,MAAM,WAAW,GAAG,CAAC;KAClB,MAAM,CAAC;IACN,QAAQ,EAAE,UAAU;IACpB,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE;IACb,kBAAkB,EAAE,CAAC,CAAC,IAAI,EAAE;IAC5B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC,OAAO,CAAC,wBAAwB,CAAC;CAC/F,CAAC;KACD,MAAM,EAAE;KACR,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,kBAAkB,CAAC,OAAO,EAAE,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE;IAC5E,IAAI,EAAE,CAAC,oBAAoB,CAAC;IAC5B,OAAO,EAAE,+DAA+D;CACzE,CAAC,CAAC;AAEL,MAAM,WAAW,GAAG,CAAC;KAClB,MAAM,CAAC;IACN,KAAK,EAAE,UAAU;IACjB,QAAQ,EAAE,UAAU;IACpB,WAAW,EAAE,CAAC,CAAC,IAAI,EAAE;IACrB,MAAM,EAAE,YAAY;IACpB,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE;CACd,CAAC;KACD,MAAM,EAAE;KACR,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,EAAE,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE;IACrE,IAAI,EAAE,CAAC,aAAa,CAAC;IACrB,OAAO,EAAE,wDAAwD;CAClE,CAAC,CAAC;AAEL,MAAM,kBAAkB,GAAG,CAAC;KACzB,MAAM,CAAC;IACN,KAAK,EAAE,UAAU;IACjB,QAAQ,EAAE,UAAU;IACpB,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE;CACd,CAAC;KACD,MAAM,EAAE,CAAC;AAEZ,MAAM,YAAY,GAAG,CAAC;KACnB,MAAM,CAAC;IACN,KAAK,EAAE,UAAU;IACjB,QAAQ,EAAE,UAAU;IACpB,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE;IACb,MAAM,EAAE,YAAY,CAAC,QAAQ,EAAE;CAChC,CAAC;KACD,MAAM,EAAE,CAAC;AAEZ,MAAM,WAAW,GAAG;;;;;;CAMnB,CAAC;AAEF,MAAM,qBAAqB,GAAG;;;;;;CAM7B,CAAC;AAEF,2DAA2D;AAC3D,SAAS,cAAc,CAAC,GAAmB;IACzC,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,OAAO,EAAE,GAAG,CAAC,QAAQ;QACrB,cAAc,EAAE,GAAG,CAAC,eAAe;QACnC,gBAAgB,EAAE;YAChB,UAAU,EAAE,GAAG,CAAC,kBAAkB;YAClC,EAAE,EAAE,GAAG,CAAC,UAAU;YAClB,GAAG,EAAE,GAAG,CAAC,WAAW;YACpB,KAAK,EAAE,GAAG,CAAC,cAAc;SAC1B;QACD,cAAc,EAAE,GAAG,CAAC,eAAe;QACnC,iBAAiB,EAAE,GAAG,CAAC,kBAAkB;QACzC,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,WAAW,EAAE,GAAG,CAAC,YAAY;QAC7B,SAAS,EAAE,GAAG,CAAC,UAAU;QACzB,SAAS,EAAE,GAAG,CAAC,UAAU;QACzB,YAAY,EAAE,GAAG,CAAC,aAAa;QAC/B,iBAAiB,EAAE,GAAG,CAAC,mBAAmB;QAC1C,WAAW,EAAE,GAAG,CAAC,YAAY;QAC7B,SAAS,EAAE,GAAG,CAAC,UAAU;QACzB,SAAS,EAAE,GAAG,CAAC,UAAU;KAC1B,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,2BAA2B,CACzC,QAAQ,GAAwB,OAAO,EAAE;IAEzC,OAAO,IAAI,qBAAqB,CAAC,QAAQ,CAAC,CAAC;AAC7C,CAAC;AAED,sEAAsE;AACtE,MAAM,OAAO,qBAAqB;IAChC,yDAAyD;IACtC,QAAQ,CAAsB;IAEjD;;;;OAIG;IACH,YAAmB,QAA6B;QAC9C,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,OAAO,CAAC,KAA8B;QACjD,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CACtC;;;;;;mBAMa,WAAW,EAAE,EAC1B;YACE,MAAM,CAAC,OAAO;YACd,MAAM,CAAC,cAAc;YACrB,MAAM,CAAC,gBAAgB,CAAC,UAAU;YAClC,MAAM,CAAC,gBAAgB,CAAC,EAAE;YAC1B,MAAM,CAAC,gBAAgB,CAAC,GAAG;YAC3B,MAAM,CAAC,gBAAgB,CAAC,KAAK;YAC7B,MAAM,CAAC,cAAc;YACrB,MAAM,CAAC,iBAAiB;YACxB,MAAM,CAAC,WAAW;SACnB,CACF,CAAC;QAEF,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACnB,OAAO,EAAE,GAAG,EAAE,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QACjE,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CACxC,UAAU,WAAW;;;;qCAIU,EAC/B,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,iBAAiB,CAAC,CAClE,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;QACpF,CAAC;QAED,OAAO,EAAE,GAAG,EAAE,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IACpE,CAAC;IAED;;;;;;;;;OASG;IACI,KAAK,CAAC,cAAc,CACzB,KAA6B;QAE7B,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACxC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CACtC;;;;;;;;;;;;;;;;;;mBAkBa,qBAAqB;;;;;kCAKN,EAC5B;YACE,MAAM,CAAC,GAAG;YACV,MAAM,CAAC,kBAAkB;YACzB,MAAM,CAAC,KAAK;YACZ,MAAM,CAAC,QAAQ;YACf,0BAA0B;SAC3B,CACF,CAAC;QAEF,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YAC/B,GAAG,cAAc,CAAC,GAAG,CAAC;YACtB,gBAAgB,EAAE,GAAG,CAAC,iBAAiB;SACxC,CAAC,CAAC,CAAC;IACN,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,YAAY,CAAC,KAAmC;QAC3D,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CACtC;;;;;;;mBAOa,WAAW,EAAE,EAC1B,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,EAAE,0BAA0B,CAAC,CACxE,CAAC;QAEF,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAChE,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,aAAa,CAAC,KAA4B;QACrD,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACxC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CACtC;;;;;;;;;;gCAU0B,EAC1B;YACE,MAAM,CAAC,KAAK;YACZ,MAAM,CAAC,QAAQ;YACf,MAAM,CAAC,WAAW;YAClB,MAAM,CAAC,MAAM;YACb,MAAM,CAAC,GAAG;YACV,0BAA0B;SAC3B,CACF,CAAC;QAEF,OAAO,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,aAAa,CAAC,KAA6B;QACtD,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;QAC3E,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CACtC;;;;;;;;;gCAS0B,EAC1B,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,CAC5C,CAAC;QAEF,OAAO,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,mBAAmB,CAAC,KAA6B;QAC5D,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC1E,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CACtC;;;;;;;;;gCAS0B,EAC1B,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAC3D,CAAC;QAEF,OAAO,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC;IAC/B,CAAC;CACF"}
@@ -0,0 +1,27 @@
1
+ /** Public enqueue and application lifecycle boundary for durable recovery work. */
2
+ import { type EnqueueRecoveryJobResult, type RecoveryJobType } from './recovery-job-repository.js';
3
+ import { type InteractionAuthorityProvider } from './interaction-authority.js';
4
+ /** Input accepted after public validation, CSRF, and rate limiting. */
5
+ export interface EnqueueAccountRecoveryInput {
6
+ /** Closed recovery operation. */
7
+ readonly jobType: RecoveryJobType;
8
+ /** Resolved tenant UUID. */
9
+ readonly organizationId: string;
10
+ /** Publicly submitted recovery address. */
11
+ readonly email: string;
12
+ /** Interaction binding for magic links, otherwise null. */
13
+ readonly interactionUid: string | null;
14
+ /** Per-form CSRF value that identifies one admitted action without storing it. */
15
+ readonly actionNonce: string;
16
+ }
17
+ /** Protect and durably enqueue one account-independent recovery request. */
18
+ export declare function enqueueAccountRecovery(input: EnqueueAccountRecoveryInput): Promise<EnqueueRecoveryJobResult>;
19
+ /**
20
+ * Start the singleton recovery worker after all application dependencies are ready.
21
+ *
22
+ * @param provider - Live provider authority required by interaction-bound magic-link jobs.
23
+ */
24
+ export declare function startAccountRecoveryWorker(provider?: InteractionAuthorityProvider): void;
25
+ /** Stop accepting claims and await the bounded active-cycle settlement window. */
26
+ export declare function stopAccountRecoveryWorker(): Promise<boolean>;
27
+ //# sourceMappingURL=recovery-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recovery-service.d.ts","sourceRoot":"","sources":["../../src/auth/recovery-service.ts"],"names":[],"mappings":"AAAA,mFAAmF;AAGnF,OAAO,EAEL,KAAK,wBAAwB,EAC7B,KAAK,eAAe,EACrB,MAAM,8BAA8B,CAAC;AAOtC,OAAO,EAEL,KAAK,4BAA4B,EAClC,MAAM,4BAA4B,CAAC;AAEpC,uEAAuE;AACvE,MAAM,WAAW,2BAA2B;IAC1C,iCAAiC;IACjC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,4BAA4B;IAC5B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,2CAA2C;IAC3C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,2DAA2D;IAC3D,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,kFAAkF;IAClF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAID,4EAA4E;AAC5E,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,2BAA2B,GACjC,OAAO,CAAC,wBAAwB,CAAC,CAqBnC;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,CAAC,EAAE,4BAA4B,GAAG,IAAI,CASxF;AAED,kFAAkF;AAClF,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,OAAO,CAAC,CAKlE"}
@@ -0,0 +1,53 @@
1
+ /** Public enqueue and application lifecycle boundary for durable recovery work. */
2
+ import { createAccountRecoveryJobProcessor } from './recovery-job-processor.js';
3
+ import { createRecoveryJobRepository, } from './recovery-job-repository.js';
4
+ import { normalizeRecoveryAddress, protectRecoveryAddress, recoveryIdempotencyDigest, } from './recovery-crypto.js';
5
+ import { createRecoveryWorker } from './recovery-worker.js';
6
+ import { createInteractionAuthorityResolver, } from './interaction-authority.js';
7
+ let worker = null;
8
+ /** Protect and durably enqueue one account-independent recovery request. */
9
+ export async function enqueueAccountRecovery(input) {
10
+ const requestAuthority = {
11
+ organizationId: input.organizationId,
12
+ jobType: input.jobType,
13
+ interactionUid: input.interactionUid,
14
+ };
15
+ const normalized = normalizeRecoveryAddress(input.email);
16
+ const idempotencyDigest = recoveryIdempotencyDigest(requestAuthority, input.actionNonce);
17
+ const result = await createRecoveryJobRepository().enqueue({
18
+ jobType: input.jobType,
19
+ organizationId: input.organizationId,
20
+ protectedAddress: protectRecoveryAddress(normalized, {
21
+ ...requestAuthority,
22
+ idempotencyDigest,
23
+ }),
24
+ interactionUid: input.interactionUid,
25
+ idempotencyDigest,
26
+ availableAt: new Date(),
27
+ });
28
+ worker?.wake();
29
+ return result;
30
+ }
31
+ /**
32
+ * Start the singleton recovery worker after all application dependencies are ready.
33
+ *
34
+ * @param provider - Live provider authority required by interaction-bound magic-link jobs.
35
+ */
36
+ export function startAccountRecoveryWorker(provider) {
37
+ if (worker)
38
+ return;
39
+ worker = createRecoveryWorker({
40
+ repository: createRecoveryJobRepository(),
41
+ processor: createAccountRecoveryJobProcessor(provider ? createInteractionAuthorityResolver(provider) : undefined),
42
+ });
43
+ worker.start();
44
+ }
45
+ /** Stop accepting claims and await the bounded active-cycle settlement window. */
46
+ export async function stopAccountRecoveryWorker() {
47
+ const active = worker;
48
+ if (!active)
49
+ return true;
50
+ worker = null;
51
+ return active.stop();
52
+ }
53
+ //# sourceMappingURL=recovery-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recovery-service.js","sourceRoot":"","sources":["../../src/auth/recovery-service.ts"],"names":[],"mappings":"AAAA,mFAAmF;AAEnF,OAAO,EAAE,iCAAiC,EAAE,MAAM,6BAA6B,CAAC;AAChF,OAAO,EACL,2BAA2B,GAG5B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,wBAAwB,EACxB,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,oBAAoB,EAAuB,MAAM,sBAAsB,CAAC;AACjF,OAAO,EACL,kCAAkC,GAEnC,MAAM,4BAA4B,CAAC;AAgBpC,IAAI,MAAM,GAA0B,IAAI,CAAC;AAEzC,4EAA4E;AAC5E,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,KAAkC;IAElC,MAAM,gBAAgB,GAAG;QACvB,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,cAAc,EAAE,KAAK,CAAC,cAAc;KAC5B,CAAC;IACX,MAAM,UAAU,GAAG,wBAAwB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACzD,MAAM,iBAAiB,GAAG,yBAAyB,CAAC,gBAAgB,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;IACzF,MAAM,MAAM,GAAG,MAAM,2BAA2B,EAAE,CAAC,OAAO,CAAC;QACzD,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,gBAAgB,EAAE,sBAAsB,CAAC,UAAU,EAAE;YACnD,GAAG,gBAAgB;YACnB,iBAAiB;SAClB,CAAC;QACF,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,iBAAiB;QACjB,WAAW,EAAE,IAAI,IAAI,EAAE;KACxB,CAAC,CAAC;IACH,MAAM,EAAE,IAAI,EAAE,CAAC;IACf,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,0BAA0B,CAAC,QAAuC;IAChF,IAAI,MAAM;QAAE,OAAO;IACnB,MAAM,GAAG,oBAAoB,CAAC;QAC5B,UAAU,EAAE,2BAA2B,EAAE;QACzC,SAAS,EAAE,iCAAiC,CAC1C,QAAQ,CAAC,CAAC,CAAC,kCAAkC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CACpE;KACF,CAAC,CAAC;IACH,MAAM,CAAC,KAAK,EAAE,CAAC;AACjB,CAAC;AAED,kFAAkF;AAClF,MAAM,CAAC,KAAK,UAAU,yBAAyB;IAC7C,MAAM,MAAM,GAAG,MAAM,CAAC;IACtB,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,GAAG,IAAI,CAAC;IACd,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;AACvB,CAAC"}