@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,599 @@
1
+ /**
2
+ * Two-factor authentication service — business logic orchestrator.
3
+ *
4
+ * Composes the repository, cache, crypto utilities, and audit log
5
+ * to provide the complete 2FA management API. Functions are grouped by:
6
+ *
7
+ * - **Setup**: Initialize email OTP or TOTP, confirm TOTP enrollment
8
+ * - **Verification**: Verify OTP codes, TOTP codes, recovery codes
9
+ * - **Sending**: Generate and send OTP codes via email
10
+ * - **Management**: Get status, disable 2FA, regenerate recovery codes
11
+ * - **Policy**: Check org policy requirements, determine required method
12
+ *
13
+ * All write operations follow the pattern:
14
+ * 1. Validate preconditions (user state, existing 2FA, etc.)
15
+ * 2. Perform DB operations (via repository)
16
+ * 3. Update user 2FA state (via user repository)
17
+ * 4. Invalidate cache
18
+ * 5. Write audit log (fire-and-forget)
19
+ */
20
+ import { config } from '../config/index.js';
21
+ import { getPool } from '../lib/database.js';
22
+ import { writeAuditLog } from '../lib/audit-log.js';
23
+ import { logger } from '../lib/logger.js';
24
+ import { TwoFactorAlreadyEnabledError, TwoFactorNotEnabledError, TotpNotConfiguredError, OtpExpiredError, OtpInvalidError, RecoveryCodeInvalidError, RecoveryCodesExhaustedError, } from './errors.js';
25
+ import { encryptTotpSecret, decryptTotpSecret } from './crypto.js';
26
+ import { generateOtpCode, hashOtpCode, verifyOtpCode } from './otp.js';
27
+ import { generateTotpSecret, generateTotpUri, generateQrCodeDataUri, verifyTotpCode } from './totp.js';
28
+ import { generateRecoveryCodes, hashRecoveryCode, verifyRecoveryCode as verifyRecoveryCodeHash } from './recovery.js';
29
+ import { insertTotp, findTotpByUserId, markTotpVerified, deleteTotp, insertOtpCode, findActiveOtpCodes, markOtpCodeUsed, deleteExpiredOtpCodes, countActiveOtpCodes, findUnusedRecoveryCodes, markRecoveryCodeUsed, insertRecoveryCodes, deleteAllRecoveryCodes, countUnusedRecoveryCodes, } from './repository.js';
30
+ import { getCachedTwoFactorStatus, cacheTwoFactorStatus, invalidateTwoFactorCache, } from './cache.js';
31
+ import { findUserById, updateUser as repoUpdateUser } from '../users/repository.js';
32
+ // ---------------------------------------------------------------------------
33
+ // Constants
34
+ // ---------------------------------------------------------------------------
35
+ /** OTP code expiration time in minutes */
36
+ const OTP_EXPIRY_MINUTES = 10;
37
+ /** Maximum active OTP codes per user (rate limiting) */
38
+ const MAX_ACTIVE_OTP_CODES = 5;
39
+ /** Default dev/test encryption key — only used when config key is not set */
40
+ const DEV_ENCRYPTION_KEY = 'a'.repeat(64);
41
+ // ---------------------------------------------------------------------------
42
+ // Helpers
43
+ // ---------------------------------------------------------------------------
44
+ /**
45
+ * Get the 2FA encryption key from config, falling back to a dev key
46
+ * in non-production environments. Production requires a real key.
47
+ *
48
+ * @returns 64-character hex encryption key
49
+ */
50
+ function getEncryptionKey() {
51
+ if (config.twoFactorEncryptionKey) {
52
+ return config.twoFactorEncryptionKey;
53
+ }
54
+ // In development/test, use a predictable default — this is safe because
55
+ // dev/test TOTP secrets are throwaway data, not real user secrets
56
+ return DEV_ENCRYPTION_KEY;
57
+ }
58
+ /**
59
+ * Generate and hash recovery codes, returning both plaintext and hashes.
60
+ *
61
+ * @returns Object with plaintext codes (for display) and hashes (for storage)
62
+ */
63
+ async function generateAndHashRecoveryCodes() {
64
+ const plaintextCodes = generateRecoveryCodes();
65
+ const codeHashes = await Promise.all(plaintextCodes.map((code) => hashRecoveryCode(code)));
66
+ return { plaintextCodes, codeHashes };
67
+ }
68
+ // ===========================================================================
69
+ // Setup functions
70
+ // ===========================================================================
71
+ /**
72
+ * Set up email OTP as the 2FA method for a user.
73
+ *
74
+ * Enables 2FA with the 'email' method, generates recovery codes, and
75
+ * marks the user as 2FA-enabled in the users table. No TOTP config
76
+ * is created — email OTP codes are generated on-demand during login.
77
+ *
78
+ * @param userId - User UUID
79
+ * @param orgId - Organization UUID (for audit logging)
80
+ * @returns Setup result with recovery codes
81
+ * @throws TwoFactorAlreadyEnabledError if 2FA is already enabled
82
+ */
83
+ export async function setupEmailOtp(userId, orgId) {
84
+ // Check preconditions — user must not already have 2FA enabled
85
+ const user = await findUserById(userId);
86
+ if (!user) {
87
+ throw new TwoFactorNotEnabledError(userId);
88
+ }
89
+ // Check if 2FA is already enabled by reading the DB columns directly
90
+ if (user.twoFactorEnabled) {
91
+ throw new TwoFactorAlreadyEnabledError(userId);
92
+ }
93
+ // Generate recovery codes
94
+ const { plaintextCodes, codeHashes } = await generateAndHashRecoveryCodes();
95
+ // Store recovery codes in the database
96
+ await insertRecoveryCodes(userId, codeHashes);
97
+ // Enable 2FA on the user record
98
+ await repoUpdateUser(userId, {
99
+ twoFactorEnabled: true,
100
+ twoFactorMethod: 'email',
101
+ });
102
+ // Invalidate cache since 2FA state changed
103
+ await invalidateTwoFactorCache(userId);
104
+ // Audit log (fire-and-forget)
105
+ await writeAuditLog({
106
+ organizationId: orgId,
107
+ userId,
108
+ eventType: '2fa.setup.email',
109
+ eventCategory: 'auth',
110
+ metadata: { method: 'email' },
111
+ });
112
+ logger.info({ userId, method: 'email' }, '2FA setup complete (email OTP)');
113
+ return {
114
+ method: 'email',
115
+ recoveryCodes: plaintextCodes,
116
+ };
117
+ }
118
+ /**
119
+ * Start TOTP setup for a user.
120
+ *
121
+ * Generates a TOTP secret, encrypts it, stores it as unverified,
122
+ * and returns the otpauth:// URI and QR code for the user to scan.
123
+ * The setup is not complete until the user confirms with a valid
124
+ * TOTP code via `confirmTotpSetup()`.
125
+ *
126
+ * @param userId - User UUID
127
+ * @param email - User email (for TOTP URI display)
128
+ * @param orgSlug - Organization slug (used as TOTP issuer)
129
+ * @returns Setup result with TOTP URI, QR code, and recovery codes
130
+ * @throws TwoFactorAlreadyEnabledError if 2FA is already enabled
131
+ */
132
+ export async function setupTotp(userId, email, orgSlug) {
133
+ // Check preconditions — user must not already have 2FA enabled
134
+ const user = await findUserById(userId);
135
+ if (!user) {
136
+ throw new TwoFactorNotEnabledError(userId);
137
+ }
138
+ if (user.twoFactorEnabled) {
139
+ throw new TwoFactorAlreadyEnabledError(userId);
140
+ }
141
+ // Delete any existing unverified TOTP config (from previous incomplete setup)
142
+ await deleteTotp(userId);
143
+ // Generate a new TOTP secret and encrypt it for storage
144
+ const secret = generateTotpSecret();
145
+ const encryptionKey = getEncryptionKey();
146
+ const { encrypted, iv, tag } = encryptTotpSecret(secret, encryptionKey);
147
+ // Store the encrypted TOTP config (unverified — verified becomes true after confirm)
148
+ await insertTotp({
149
+ userId,
150
+ encryptedSecret: encrypted,
151
+ encryptionIv: iv,
152
+ encryptionTag: tag,
153
+ });
154
+ // Generate the otpauth URI and QR code for the user
155
+ const issuer = `Porta (${orgSlug})`;
156
+ const totpUri = generateTotpUri(secret, email, issuer);
157
+ const qrCodeDataUri = await generateQrCodeDataUri(totpUri);
158
+ // Generate recovery codes (stored but 2FA not yet enabled — that happens on confirm)
159
+ const { plaintextCodes, codeHashes } = await generateAndHashRecoveryCodes();
160
+ await deleteAllRecoveryCodes(userId); // Clear any old ones
161
+ await insertRecoveryCodes(userId, codeHashes);
162
+ // Invalidate cache since TOTP config changed
163
+ await invalidateTwoFactorCache(userId);
164
+ logger.info({ userId, method: 'totp' }, 'TOTP setup initiated (pending confirmation)');
165
+ return {
166
+ method: 'totp',
167
+ recoveryCodes: plaintextCodes,
168
+ totpUri,
169
+ qrCodeDataUri,
170
+ };
171
+ }
172
+ /**
173
+ * Retrieve existing pending (unverified) TOTP setup info.
174
+ *
175
+ * If a user has a pending TOTP setup (unverified record in DB), this
176
+ * decrypts the secret and regenerates the QR code for display.
177
+ * Does NOT regenerate the secret — preserves the existing one.
178
+ *
179
+ * Returns null if no pending setup exists.
180
+ *
181
+ * @param userId - User UUID
182
+ * @param email - User email (for TOTP URI display)
183
+ * @param orgSlug - Organization slug (used as TOTP issuer)
184
+ * @returns Setup info with QR code and secret, or null if no pending setup
185
+ */
186
+ export async function getPendingTotpSetupInfo(userId, email, orgSlug) {
187
+ const totp = await findTotpByUserId(userId);
188
+ if (!totp || totp.verified) {
189
+ return null;
190
+ }
191
+ // Decrypt the existing secret
192
+ const encryptionKey = getEncryptionKey();
193
+ const secret = decryptTotpSecret(totp.encryptedSecret, totp.encryptionIv, totp.encryptionTag, encryptionKey);
194
+ // Regenerate the URI and QR code from the existing secret
195
+ const issuer = `Porta (${orgSlug})`;
196
+ const totpUri = generateTotpUri(secret, email, issuer);
197
+ const qrCodeDataUri = await generateQrCodeDataUri(totpUri);
198
+ return { totpUri, qrCodeDataUri, totpSecret: secret };
199
+ }
200
+ /**
201
+ * Confirm TOTP setup by verifying the user's first TOTP code.
202
+ *
203
+ * Called after the user scans the QR code and enters a TOTP code
204
+ * from their authenticator app. This confirms the setup is correct
205
+ * and enables 2FA on the user record.
206
+ *
207
+ * @param userId - User UUID
208
+ * @param code - 6-digit TOTP code from the authenticator app
209
+ * @returns true if the code is valid and setup is confirmed
210
+ * @throws TotpNotConfiguredError if no pending TOTP setup exists
211
+ */
212
+ export async function confirmTotpSetup(userId, code) {
213
+ // Find the unverified TOTP config
214
+ const totp = await findTotpByUserId(userId);
215
+ if (!totp || totp.verified) {
216
+ throw new TotpNotConfiguredError(userId);
217
+ }
218
+ // Decrypt the secret to verify the code
219
+ const encryptionKey = getEncryptionKey();
220
+ const secret = decryptTotpSecret(totp.encryptedSecret, totp.encryptionIv, totp.encryptionTag, encryptionKey);
221
+ // Verify the TOTP code
222
+ const isValid = verifyTotpCode(code, secret);
223
+ if (!isValid) {
224
+ return false;
225
+ }
226
+ // Mark the TOTP config as verified
227
+ await markTotpVerified(userId);
228
+ // Enable 2FA on the user record
229
+ await repoUpdateUser(userId, {
230
+ twoFactorEnabled: true,
231
+ twoFactorMethod: 'totp',
232
+ });
233
+ // Invalidate cache since 2FA state changed
234
+ await invalidateTwoFactorCache(userId);
235
+ // Audit log (fire-and-forget)
236
+ const user = await findUserById(userId);
237
+ await writeAuditLog({
238
+ organizationId: user?.organizationId,
239
+ userId,
240
+ eventType: '2fa.setup.totp',
241
+ eventCategory: 'auth',
242
+ metadata: { method: 'totp' },
243
+ });
244
+ logger.info({ userId, method: 'totp' }, '2FA setup confirmed (TOTP)');
245
+ return true;
246
+ }
247
+ // ===========================================================================
248
+ // OTP email sending
249
+ // ===========================================================================
250
+ /**
251
+ * Generate and send an OTP code via email.
252
+ *
253
+ * Creates a 6-digit code, hashes it, stores the hash in the database
254
+ * with a 10-minute expiry, and sends the plaintext code via email.
255
+ * Rate-limited to MAX_ACTIVE_OTP_CODES active codes per user.
256
+ *
257
+ * Note: This function generates the code and stores it. The actual email
258
+ * sending is handled by the auth email service (Phase 8). For now, this
259
+ * function prepares the code — the route layer will call the email service.
260
+ *
261
+ * @param userId - User UUID
262
+ * @param email - User email to send the code to
263
+ * @param orgId - Organization UUID (for audit logging)
264
+ * @returns The plaintext OTP code (caller sends via email service)
265
+ * @throws Error if too many active codes exist (rate limiting)
266
+ */
267
+ export async function sendOtpCode(userId, email, orgId) {
268
+ // Rate limiting — prevent generating too many codes
269
+ const activeCount = await countActiveOtpCodes(userId);
270
+ if (activeCount >= MAX_ACTIVE_OTP_CODES) {
271
+ // Clean up expired codes first, then re-check
272
+ await deleteExpiredOtpCodes(userId);
273
+ const newCount = await countActiveOtpCodes(userId);
274
+ if (newCount >= MAX_ACTIVE_OTP_CODES) {
275
+ throw new Error('Too many active OTP codes. Please wait before requesting a new one.');
276
+ }
277
+ }
278
+ // Generate a new OTP code
279
+ const plaintext = generateOtpCode();
280
+ const codeHash = hashOtpCode(plaintext);
281
+ // Calculate expiration (10 minutes from now)
282
+ const expiresAt = new Date(Date.now() + OTP_EXPIRY_MINUTES * 60 * 1000);
283
+ // Store the hashed code in the database
284
+ await insertOtpCode(userId, codeHash, expiresAt);
285
+ // Audit log (fire-and-forget)
286
+ await writeAuditLog({
287
+ organizationId: orgId,
288
+ userId,
289
+ eventType: '2fa.otp.sent',
290
+ eventCategory: 'auth',
291
+ metadata: { email },
292
+ });
293
+ logger.debug({ userId, email }, 'OTP code generated for email sending');
294
+ // Return the plaintext code — the caller sends it via email
295
+ return plaintext;
296
+ }
297
+ // ===========================================================================
298
+ // Verification functions
299
+ // ===========================================================================
300
+ /**
301
+ * Verify an email OTP code.
302
+ *
303
+ * Checks all active (unused, not expired) OTP codes for the user,
304
+ * verifying the provided code against each hash. If a match is found,
305
+ * the code is marked as used.
306
+ *
307
+ * @param userId - User UUID
308
+ * @param code - 6-digit OTP code to verify
309
+ * @returns true if the code is valid
310
+ * @throws OtpInvalidError if no matching code is found
311
+ */
312
+ export async function verifyOtp(userId, code) {
313
+ // Find all active (unused, unexpired) OTP codes for this user
314
+ const activeCodes = await findActiveOtpCodes(userId);
315
+ if (activeCodes.length === 0) {
316
+ throw new OtpExpiredError();
317
+ }
318
+ // Try to match the code against each active hash
319
+ for (const otpRecord of activeCodes) {
320
+ if (verifyOtpCode(code, otpRecord.codeHash)) {
321
+ // Mark the matching code as used
322
+ await markOtpCodeUsed(otpRecord.id);
323
+ // Clean up expired codes in the background
324
+ deleteExpiredOtpCodes(userId).catch((err) => {
325
+ logger.warn({ err, userId }, 'Failed to clean up expired OTP codes');
326
+ });
327
+ return true;
328
+ }
329
+ }
330
+ // No match found
331
+ throw new OtpInvalidError();
332
+ }
333
+ /**
334
+ * Verify a TOTP code from an authenticator app.
335
+ *
336
+ * Decrypts the user's TOTP secret from the database and verifies
337
+ * the code with a ±1 step time window.
338
+ *
339
+ * @param userId - User UUID
340
+ * @param code - 6-digit TOTP code to verify
341
+ * @returns true if the code is valid
342
+ * @throws TotpNotConfiguredError if no verified TOTP config exists
343
+ */
344
+ export async function verifyTotp(userId, code) {
345
+ // Find the verified TOTP config
346
+ const totp = await findTotpByUserId(userId);
347
+ if (!totp || !totp.verified) {
348
+ throw new TotpNotConfiguredError(userId);
349
+ }
350
+ // Decrypt the secret
351
+ const encryptionKey = getEncryptionKey();
352
+ const secret = decryptTotpSecret(totp.encryptedSecret, totp.encryptionIv, totp.encryptionTag, encryptionKey);
353
+ // Verify the code with ±1 step window
354
+ return verifyTotpCode(code, secret);
355
+ }
356
+ /**
357
+ * Verify a recovery code.
358
+ *
359
+ * Recovery codes use Argon2id hashing with random salt, so we must
360
+ * iterate all unused codes and verify against each hash. If a match
361
+ * is found, the code is marked as used (single-use).
362
+ *
363
+ * @param userId - User UUID
364
+ * @param code - Recovery code in XXXX-XXXX format (case-insensitive)
365
+ * @returns true if the code is valid
366
+ * @throws RecoveryCodesExhaustedError if no unused codes remain
367
+ * @throws RecoveryCodeInvalidError if the code doesn't match any hash
368
+ */
369
+ export async function verifyRecoveryCode(userId, code) {
370
+ // Find all unused recovery codes
371
+ const unusedCodes = await findUnusedRecoveryCodes(userId);
372
+ if (unusedCodes.length === 0) {
373
+ throw new RecoveryCodesExhaustedError(userId);
374
+ }
375
+ // Try to match against each unused code hash (Argon2id — must iterate)
376
+ for (const recoveryRecord of unusedCodes) {
377
+ const isMatch = await verifyRecoveryCodeHash(code, recoveryRecord.codeHash);
378
+ if (isMatch) {
379
+ // Mark the matching code as used
380
+ await markRecoveryCodeUsed(recoveryRecord.id);
381
+ // Invalidate cache since recovery code count changed
382
+ await invalidateTwoFactorCache(userId);
383
+ // Audit log
384
+ const remaining = unusedCodes.length - 1;
385
+ await writeAuditLog({
386
+ userId,
387
+ eventType: '2fa.recovery.used',
388
+ eventCategory: 'auth',
389
+ metadata: { remainingCodes: remaining },
390
+ });
391
+ logger.info({ userId, remainingCodes: remaining }, 'Recovery code used');
392
+ return true;
393
+ }
394
+ }
395
+ // No match found
396
+ throw new RecoveryCodeInvalidError();
397
+ }
398
+ // ===========================================================================
399
+ // Management functions
400
+ // ===========================================================================
401
+ /**
402
+ * Get the current 2FA status for a user.
403
+ *
404
+ * Checks Redis cache first, falls back to building the status from
405
+ * the database. The status includes whether 2FA is enabled, the method,
406
+ * whether TOTP is configured (and verified), and remaining recovery codes.
407
+ *
408
+ * @param userId - User UUID
409
+ * @returns Current 2FA status
410
+ */
411
+ export async function getTwoFactorStatus(userId) {
412
+ // Try cache first
413
+ const cached = await getCachedTwoFactorStatus(userId);
414
+ if (cached)
415
+ return cached;
416
+ // Build status from database
417
+ const user = await findUserById(userId);
418
+ // Default status for unknown users — not enabled
419
+ if (!user) {
420
+ return {
421
+ enabled: false,
422
+ method: null,
423
+ totpConfigured: false,
424
+ recoveryCodesRemaining: 0,
425
+ };
426
+ }
427
+ // Check TOTP config existence and verification status
428
+ const totp = await findTotpByUserId(userId);
429
+ const recoveryCount = await countUnusedRecoveryCodes(userId);
430
+ const status = {
431
+ enabled: user.twoFactorEnabled,
432
+ method: user.twoFactorMethod ?? null,
433
+ totpConfigured: totp !== null && totp.verified,
434
+ recoveryCodesRemaining: recoveryCount,
435
+ };
436
+ // Cache the result
437
+ await cacheTwoFactorStatus(userId, status);
438
+ return status;
439
+ }
440
+ /**
441
+ * Disable 2FA for a user.
442
+ *
443
+ * Removes all 2FA data: TOTP config, active OTP codes, and recovery codes.
444
+ * Resets the user's 2FA flags in the users table.
445
+ *
446
+ * @param userId - User UUID
447
+ * @throws TwoFactorNotEnabledError if 2FA is not enabled
448
+ */
449
+ export async function disableTwoFactor(userId) {
450
+ const user = await findUserById(userId);
451
+ if (!user || !user.twoFactorEnabled) {
452
+ throw new TwoFactorNotEnabledError(userId);
453
+ }
454
+ // Delete all 2FA data
455
+ await deleteTotp(userId);
456
+ await deleteAllRecoveryCodes(userId);
457
+ await deleteExpiredOtpCodes(userId);
458
+ // Reset 2FA flags on the user record
459
+ await repoUpdateUser(userId, {
460
+ twoFactorEnabled: false,
461
+ twoFactorMethod: null,
462
+ });
463
+ // Invalidate cache
464
+ await invalidateTwoFactorCache(userId);
465
+ // Audit log
466
+ await writeAuditLog({
467
+ organizationId: user.organizationId,
468
+ userId,
469
+ eventType: '2fa.disabled',
470
+ eventCategory: 'auth',
471
+ metadata: { previousMethod: user.twoFactorMethod },
472
+ });
473
+ logger.info({ userId }, '2FA disabled');
474
+ }
475
+ /**
476
+ * Regenerate recovery codes for a user.
477
+ *
478
+ * Deletes all existing recovery codes and generates a fresh set of 10.
479
+ * The user must have 2FA enabled to regenerate codes.
480
+ *
481
+ * @param userId - User UUID
482
+ * @returns Array of new plaintext recovery codes (shown once to the user)
483
+ * @throws TwoFactorNotEnabledError if 2FA is not enabled
484
+ */
485
+ export async function regenerateRecoveryCodes(userId) {
486
+ const user = await findUserById(userId);
487
+ if (!user || !user.twoFactorEnabled) {
488
+ throw new TwoFactorNotEnabledError(userId);
489
+ }
490
+ // Delete old recovery codes
491
+ await deleteAllRecoveryCodes(userId);
492
+ // Generate new recovery codes
493
+ const { plaintextCodes, codeHashes } = await generateAndHashRecoveryCodes();
494
+ await insertRecoveryCodes(userId, codeHashes);
495
+ // Invalidate cache since recovery code count changed
496
+ await invalidateTwoFactorCache(userId);
497
+ // Audit log
498
+ await writeAuditLog({
499
+ organizationId: user.organizationId,
500
+ userId,
501
+ eventType: '2fa.recovery.regenerated',
502
+ eventCategory: 'auth',
503
+ });
504
+ logger.info({ userId }, 'Recovery codes regenerated');
505
+ return plaintextCodes;
506
+ }
507
+ /**
508
+ * Check if the organization's 2FA policy requires 2FA for a user.
509
+ *
510
+ * Returns true if the org policy is anything other than 'optional'
511
+ * AND the user has not yet enabled 2FA.
512
+ *
513
+ * @param org - Organization with twoFactorPolicy field
514
+ * @param user - User with 2FA state fields
515
+ * @returns true if 2FA is required but not yet set up
516
+ */
517
+ export function requiresTwoFactor(org, user) {
518
+ // If policy is optional, 2FA is never required
519
+ if (org.twoFactorPolicy === 'optional') {
520
+ return false;
521
+ }
522
+ // If user already has 2FA enabled, requirement is met
523
+ if (user.twoFactorEnabled) {
524
+ return false;
525
+ }
526
+ // Policy requires 2FA but user hasn't set it up yet
527
+ return true;
528
+ }
529
+ /**
530
+ * Determine which 2FA method the user should use based on org policy.
531
+ *
532
+ * If the user has 2FA enabled, returns their configured method.
533
+ * If the org requires a specific method, returns that method.
534
+ * If the org requires 'any', returns null (user chooses).
535
+ * If the policy is optional, returns null.
536
+ *
537
+ * @param org - Organization with twoFactorPolicy field
538
+ * @param user - User with 2FA state fields
539
+ * @returns The 2FA method to use, or null if no method is required/configured
540
+ */
541
+ export function determineTwoFactorMethod(org, user) {
542
+ // If user already has 2FA enabled, use their method
543
+ if (user.twoFactorEnabled && user.twoFactorMethod) {
544
+ return user.twoFactorMethod;
545
+ }
546
+ // Map org policy to required method
547
+ switch (org.twoFactorPolicy) {
548
+ case 'required_email':
549
+ return 'email';
550
+ case 'required_totp':
551
+ return 'totp';
552
+ case 'required_any':
553
+ // User gets to choose — return null to indicate "choose any"
554
+ return null;
555
+ case 'optional':
556
+ default:
557
+ return null;
558
+ }
559
+ }
560
+ /**
561
+ * Get an aggregate 2FA enrollment summary for an organization.
562
+ *
563
+ * Runs a single SQL query with conditional aggregation to count
564
+ * users by 2FA status, method, and calculate compliance rate.
565
+ *
566
+ * @param orgId - Organization UUID
567
+ * @returns Aggregate summary with counts and compliance rate
568
+ */
569
+ export async function getTwoFactorSummary(orgId) {
570
+ const pool = getPool();
571
+ const result = await pool.query(`SELECT
572
+ COUNT(*)::text AS total_users,
573
+ COUNT(*) FILTER (WHERE two_factor_enabled = TRUE)::text AS enabled_count,
574
+ COUNT(*) FILTER (WHERE two_factor_enabled = FALSE)::text AS disabled_count,
575
+ COUNT(*) FILTER (WHERE two_factor_method = 'totp')::text AS totp_count,
576
+ COUNT(*) FILTER (WHERE two_factor_method = 'email')::text AS email_count
577
+ FROM users
578
+ WHERE organization_id = $1
579
+ AND status != 'archived'`, [orgId]);
580
+ const row = result.rows[0];
581
+ const totalUsers = parseInt(row.total_users, 10);
582
+ const enabledCount = parseInt(row.enabled_count, 10);
583
+ const disabledCount = parseInt(row.disabled_count, 10);
584
+ const totpCount = parseInt(row.totp_count, 10);
585
+ const emailCount = parseInt(row.email_count, 10);
586
+ // Compliance rate: percentage of non-archived users with 2FA enabled (AR #92)
587
+ const complianceRate = totalUsers > 0
588
+ ? Math.round((enabledCount / totalUsers) * 10000) / 10000
589
+ : 0;
590
+ return {
591
+ totalUsers,
592
+ enabledCount,
593
+ disabledCount,
594
+ totpCount,
595
+ emailCount,
596
+ complianceRate,
597
+ };
598
+ }
599
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/two-factor/service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * TOTP (Time-based One-Time Password) utilities.
3
+ *
4
+ * Implements RFC 6238 TOTP using the `otpauth` library. Provides secret
5
+ * generation, otpauth:// URI construction, QR code generation for
6
+ * authenticator app enrollment, and code verification with a ±1 step
7
+ * time window to accommodate clock drift.
8
+ *
9
+ * QR code generation uses the `qrcode` library to produce data URIs
10
+ * that can be displayed inline in Handlebars templates.
11
+ */
12
+ /**
13
+ * Generate a new TOTP secret.
14
+ *
15
+ * Creates a 20-byte (160-bit) random secret, which is the standard
16
+ * size for SHA-1-based TOTP as recommended by RFC 4226 §4.
17
+ * The secret is returned as a base32-encoded string suitable for
18
+ * storage (after encryption) and otpauth:// URI construction.
19
+ *
20
+ * @returns Base32-encoded TOTP secret
21
+ */
22
+ export declare function generateTotpSecret(): string;
23
+ /**
24
+ * Generate an otpauth:// URI for authenticator app enrollment.
25
+ *
26
+ * The URI encodes the secret, issuer, account name, and TOTP parameters
27
+ * in a format understood by Google Authenticator, Authy, 1Password, etc.
28
+ *
29
+ * @param secret - Base32-encoded TOTP secret
30
+ * @param userEmail - User's email address (displayed as account name)
31
+ * @param issuer - Service name (e.g., "Porta" or org slug)
32
+ * @returns otpauth:// URI string
33
+ */
34
+ export declare function generateTotpUri(secret: string, userEmail: string, issuer: string): string;
35
+ /**
36
+ * Generate a QR code data URI from an otpauth:// URI.
37
+ *
38
+ * The returned data URI can be used directly in an <img src="..."> tag
39
+ * in Handlebars templates. Uses SVG format for crisp rendering at any size.
40
+ *
41
+ * @param uri - otpauth:// URI to encode
42
+ * @returns Data URI string (data:image/svg+xml;base64,...)
43
+ */
44
+ export declare function generateQrCodeDataUri(uri: string): Promise<string>;
45
+ /**
46
+ * Verify a TOTP code against a secret.
47
+ *
48
+ * Allows a ±1 step time window (i.e., the current 30-second window
49
+ * plus one window before and one after) to accommodate minor clock
50
+ * drift between the server and the user's authenticator app.
51
+ *
52
+ * @param code - The 6-digit TOTP code entered by the user
53
+ * @param secret - Base32-encoded TOTP secret
54
+ * @returns True if the code is valid within the time window
55
+ */
56
+ export declare function verifyTotpCode(code: string, secret: string): boolean;
57
+ //# sourceMappingURL=totp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"totp.d.ts","sourceRoot":"","sources":["../../src/two-factor/totp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAUH;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAI3C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,MAAM,CAWR;AAED;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQxE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAYpE"}