@lastshotlabs/bunshot 0.0.27 → 0.1.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/.oclif.manifest.json +39 -0
  2. package/README.md +8282 -2147
  3. package/dist/cli/commands/init.js +690 -0
  4. package/dist/cli/index.js +6 -0
  5. package/dist/cli.js +4 -4
  6. package/dist/packages/bunshot-admin/src/index.d.ts +15 -0
  7. package/dist/packages/bunshot-admin/src/index.js +11 -0
  8. package/dist/packages/bunshot-admin/src/lib/resourceTypes.d.ts +8 -0
  9. package/dist/packages/bunshot-admin/src/lib/resourceTypes.js +33 -0
  10. package/dist/packages/bunshot-admin/src/lib/typedRoute.d.ts +14 -0
  11. package/dist/packages/bunshot-admin/src/lib/typedRoute.js +17 -0
  12. package/dist/packages/bunshot-admin/src/plugin.d.ts +4 -0
  13. package/dist/packages/bunshot-admin/src/plugin.js +46 -0
  14. package/dist/packages/bunshot-admin/src/providers/auth0Access.d.ts +6 -0
  15. package/dist/packages/bunshot-admin/src/providers/auth0Access.js +32 -0
  16. package/dist/packages/bunshot-admin/src/routes/admin.d.ts +10 -0
  17. package/dist/packages/bunshot-admin/src/routes/admin.js +923 -0
  18. package/dist/packages/bunshot-admin/src/routes/mail.d.ts +6 -0
  19. package/dist/packages/bunshot-admin/src/routes/mail.js +114 -0
  20. package/dist/packages/bunshot-admin/src/routes/permissions.d.ts +8 -0
  21. package/dist/packages/bunshot-admin/src/routes/permissions.js +315 -0
  22. package/dist/packages/bunshot-admin/src/types/config.d.ts +16 -0
  23. package/dist/packages/bunshot-admin/src/types/config.js +37 -0
  24. package/dist/packages/bunshot-admin/src/types/env.d.ts +14 -0
  25. package/dist/packages/bunshot-admin/src/types/provider.d.ts +1 -0
  26. package/dist/packages/bunshot-admin/src/types/provider.js +4 -0
  27. package/dist/packages/bunshot-auth/src/adapters/memoryAuth.d.ts +66 -0
  28. package/dist/packages/bunshot-auth/src/adapters/memoryAuth.js +1063 -0
  29. package/dist/packages/bunshot-auth/src/adapters/mongoAuth.d.ts +2 -0
  30. package/dist/packages/bunshot-auth/src/adapters/mongoAuth.js +536 -0
  31. package/dist/packages/bunshot-auth/src/adapters/sqliteAuth.d.ts +88 -0
  32. package/dist/packages/bunshot-auth/src/adapters/sqliteAuth.js +1366 -0
  33. package/dist/packages/bunshot-auth/src/admin/bunshotAccess.d.ts +2 -0
  34. package/dist/packages/bunshot-auth/src/admin/bunshotAccess.js +23 -0
  35. package/dist/packages/bunshot-auth/src/admin/bunshotUsers.d.ts +5 -0
  36. package/dist/packages/bunshot-auth/src/admin/bunshotUsers.js +131 -0
  37. package/dist/packages/bunshot-auth/src/bootstrap.d.ts +38 -0
  38. package/dist/packages/bunshot-auth/src/bootstrap.js +384 -0
  39. package/dist/packages/bunshot-auth/src/config/appConfig.d.ts +3 -0
  40. package/dist/packages/bunshot-auth/src/config/appConfig.js +4 -0
  41. package/dist/packages/bunshot-auth/src/config/authConfig.d.ts +478 -0
  42. package/dist/packages/bunshot-auth/src/config/authConfig.js +46 -0
  43. package/dist/packages/bunshot-auth/src/config/configLock.d.ts +2 -0
  44. package/dist/packages/bunshot-auth/src/config/configLock.js +10 -0
  45. package/dist/packages/bunshot-auth/src/index.d.ts +25 -0
  46. package/dist/packages/bunshot-auth/src/index.js +23 -0
  47. package/dist/packages/bunshot-auth/src/infra/mongo.d.ts +15 -0
  48. package/dist/packages/bunshot-auth/src/infra/mongo.js +44 -0
  49. package/dist/packages/bunshot-auth/src/infra/queue.d.ts +14 -0
  50. package/dist/packages/bunshot-auth/src/infra/queue.js +27 -0
  51. package/dist/packages/bunshot-auth/src/infra/redis.d.ts +5 -0
  52. package/dist/packages/bunshot-auth/src/infra/redis.js +15 -0
  53. package/dist/packages/bunshot-auth/src/infra/signing.d.ts +7 -0
  54. package/dist/packages/bunshot-auth/src/infra/signing.js +8 -0
  55. package/dist/packages/bunshot-auth/src/lib/accountLockout.d.ts +34 -0
  56. package/dist/packages/bunshot-auth/src/lib/accountLockout.js +244 -0
  57. package/dist/packages/bunshot-auth/src/lib/adapterTiers.d.ts +1 -0
  58. package/dist/packages/bunshot-auth/src/lib/adapterTiers.js +1 -0
  59. package/dist/packages/bunshot-auth/src/lib/authAdapter.d.ts +1 -0
  60. package/dist/packages/bunshot-auth/src/lib/authAdapter.js +1 -0
  61. package/dist/packages/bunshot-auth/src/lib/authContext.d.ts +15 -0
  62. package/dist/packages/bunshot-auth/src/lib/authContext.js +1 -0
  63. package/dist/packages/bunshot-auth/src/lib/authEventBus.d.ts +4 -0
  64. package/dist/packages/bunshot-auth/src/lib/authEventBus.js +15 -0
  65. package/dist/packages/bunshot-auth/src/lib/authRateLimit.d.ts +28 -0
  66. package/dist/packages/bunshot-auth/src/lib/authRateLimit.js +205 -0
  67. package/dist/{lib → packages/bunshot-auth/src/lib}/breachedPassword.d.ts +8 -2
  68. package/dist/{lib → packages/bunshot-auth/src/lib}/breachedPassword.js +22 -9
  69. package/dist/packages/bunshot-auth/src/lib/cache.d.ts +12 -0
  70. package/dist/packages/bunshot-auth/src/lib/cache.js +120 -0
  71. package/dist/packages/bunshot-auth/src/lib/clientIp.d.ts +4 -0
  72. package/dist/{lib → packages/bunshot-auth/src/lib}/clientIp.js +14 -7
  73. package/dist/packages/bunshot-auth/src/lib/cookieOptions.d.ts +27 -0
  74. package/dist/packages/bunshot-auth/src/lib/cookieOptions.js +33 -0
  75. package/dist/packages/bunshot-auth/src/lib/credentialStuffing.d.ts +40 -0
  76. package/dist/packages/bunshot-auth/src/lib/credentialStuffing.js +211 -0
  77. package/dist/packages/bunshot-auth/src/lib/deletionCancelToken.d.ts +19 -0
  78. package/dist/packages/bunshot-auth/src/lib/deletionCancelToken.js +148 -0
  79. package/dist/packages/bunshot-auth/src/lib/emailTemplates.d.ts +23 -0
  80. package/dist/packages/bunshot-auth/src/lib/emailTemplates.js +265 -0
  81. package/dist/packages/bunshot-auth/src/lib/emailVerification.d.ts +30 -0
  82. package/dist/packages/bunshot-auth/src/lib/emailVerification.js +200 -0
  83. package/dist/packages/bunshot-auth/src/lib/env.d.ts +1 -0
  84. package/dist/packages/bunshot-auth/src/lib/env.js +3 -0
  85. package/dist/packages/bunshot-auth/src/lib/fingerprint.js +36 -0
  86. package/dist/{lib → packages/bunshot-auth/src/lib}/groups.d.ts +15 -16
  87. package/dist/{lib → packages/bunshot-auth/src/lib}/groups.js +22 -34
  88. package/dist/packages/bunshot-auth/src/lib/jwks.d.ts +28 -0
  89. package/dist/packages/bunshot-auth/src/lib/jwks.js +79 -0
  90. package/dist/packages/bunshot-auth/src/lib/jwt.d.ts +12 -0
  91. package/dist/packages/bunshot-auth/src/lib/jwt.js +86 -0
  92. package/dist/{lib → packages/bunshot-auth/src/lib}/logger.js +3 -3
  93. package/dist/{lib → packages/bunshot-auth/src/lib}/m2m.d.ts +5 -4
  94. package/dist/{lib → packages/bunshot-auth/src/lib}/m2m.js +6 -10
  95. package/dist/packages/bunshot-auth/src/lib/magicLink.d.ts +13 -0
  96. package/dist/packages/bunshot-auth/src/lib/magicLink.js +145 -0
  97. package/dist/packages/bunshot-auth/src/lib/mfaChallenge.d.ts +60 -0
  98. package/dist/packages/bunshot-auth/src/lib/mfaChallenge.js +419 -0
  99. package/dist/packages/bunshot-auth/src/lib/oauth.d.ts +82 -0
  100. package/dist/packages/bunshot-auth/src/lib/oauth.js +177 -0
  101. package/dist/packages/bunshot-auth/src/lib/oauthCode.d.ts +19 -0
  102. package/dist/packages/bunshot-auth/src/lib/oauthCode.js +182 -0
  103. package/dist/packages/bunshot-auth/src/lib/oauthReauth.d.ts +19 -0
  104. package/dist/packages/bunshot-auth/src/lib/oauthReauth.js +255 -0
  105. package/dist/packages/bunshot-auth/src/lib/organization.d.ts +66 -0
  106. package/dist/packages/bunshot-auth/src/lib/organization.js +225 -0
  107. package/dist/packages/bunshot-auth/src/lib/passwordHistory.d.ts +12 -0
  108. package/dist/packages/bunshot-auth/src/lib/passwordHistory.js +31 -0
  109. package/dist/packages/bunshot-auth/src/lib/resetPassword.d.ts +20 -0
  110. package/dist/packages/bunshot-auth/src/lib/resetPassword.js +148 -0
  111. package/dist/packages/bunshot-auth/src/lib/roles.d.ts +9 -0
  112. package/dist/packages/bunshot-auth/src/lib/roles.js +93 -0
  113. package/dist/packages/bunshot-auth/src/lib/saml.d.ts +29 -0
  114. package/dist/packages/bunshot-auth/src/lib/saml.js +73 -0
  115. package/dist/packages/bunshot-auth/src/lib/samlRequestId.d.ts +13 -0
  116. package/dist/packages/bunshot-auth/src/lib/samlRequestId.js +129 -0
  117. package/dist/{lib → packages/bunshot-auth/src/lib}/scim.d.ts +7 -7
  118. package/dist/{lib → packages/bunshot-auth/src/lib}/scim.js +15 -13
  119. package/dist/packages/bunshot-auth/src/lib/securityEventWiring.d.ts +22 -0
  120. package/dist/packages/bunshot-auth/src/lib/securityEventWiring.js +65 -0
  121. package/dist/packages/bunshot-auth/src/lib/session.d.ts +45 -0
  122. package/dist/packages/bunshot-auth/src/lib/session.js +1211 -0
  123. package/dist/packages/bunshot-auth/src/lib/storeInfra.d.ts +26 -0
  124. package/dist/packages/bunshot-auth/src/lib/storeInfra.js +18 -0
  125. package/dist/{lib → packages/bunshot-auth/src/lib}/suspension.d.ts +3 -2
  126. package/dist/{lib → packages/bunshot-auth/src/lib}/suspension.js +2 -5
  127. package/dist/packages/bunshot-auth/src/lib/validateAdapter.d.ts +16 -0
  128. package/dist/packages/bunshot-auth/src/lib/validateAdapter.js +161 -0
  129. package/dist/packages/bunshot-auth/src/middleware/bearerAuth.d.ts +13 -0
  130. package/dist/packages/bunshot-auth/src/middleware/bearerAuth.js +58 -0
  131. package/dist/{middleware → packages/bunshot-auth/src/middleware}/csrf.d.ts +5 -4
  132. package/dist/packages/bunshot-auth/src/middleware/csrf.js +138 -0
  133. package/dist/packages/bunshot-auth/src/middleware/identify.d.ts +4 -0
  134. package/dist/packages/bunshot-auth/src/middleware/identify.js +124 -0
  135. package/dist/{middleware → packages/bunshot-auth/src/middleware}/requireMfaSetup.d.ts +2 -2
  136. package/dist/{middleware → packages/bunshot-auth/src/middleware}/requireMfaSetup.js +10 -8
  137. package/dist/{middleware → packages/bunshot-auth/src/middleware}/requireRole.d.ts +2 -2
  138. package/dist/{middleware → packages/bunshot-auth/src/middleware}/requireRole.js +20 -16
  139. package/dist/{middleware → packages/bunshot-auth/src/middleware}/requireScope.d.ts +2 -2
  140. package/dist/{middleware → packages/bunshot-auth/src/middleware}/requireScope.js +6 -6
  141. package/dist/{middleware → packages/bunshot-auth/src/middleware}/requireStepUp.d.ts +2 -2
  142. package/dist/{middleware → packages/bunshot-auth/src/middleware}/requireStepUp.js +8 -7
  143. package/dist/{middleware → packages/bunshot-auth/src/middleware}/requireVerifiedEmail.d.ts +2 -2
  144. package/dist/{middleware → packages/bunshot-auth/src/middleware}/requireVerifiedEmail.js +7 -6
  145. package/dist/packages/bunshot-auth/src/middleware/scimAuth.d.ts +8 -0
  146. package/dist/packages/bunshot-auth/src/middleware/scimAuth.js +29 -0
  147. package/dist/packages/bunshot-auth/src/middleware/userAuth.d.ts +3 -0
  148. package/dist/packages/bunshot-auth/src/middleware/userAuth.js +6 -0
  149. package/dist/{models → packages/bunshot-auth/src/models}/AuthUser.d.ts +12 -8
  150. package/dist/packages/bunshot-auth/src/models/AuthUser.js +53 -0
  151. package/dist/packages/bunshot-auth/src/models/Group.d.ts +19 -0
  152. package/dist/packages/bunshot-auth/src/models/Group.js +22 -0
  153. package/dist/{models → packages/bunshot-auth/src/models}/GroupMembership.d.ts +6 -8
  154. package/dist/packages/bunshot-auth/src/models/GroupMembership.js +19 -0
  155. package/dist/{models → packages/bunshot-auth/src/models}/M2MClient.d.ts +1 -1
  156. package/dist/{models → packages/bunshot-auth/src/models}/M2MClient.js +5 -5
  157. package/dist/packages/bunshot-auth/src/models/TenantRole.d.ts +13 -0
  158. package/dist/packages/bunshot-auth/src/models/TenantRole.js +17 -0
  159. package/dist/packages/bunshot-auth/src/plugin.d.ts +4 -0
  160. package/dist/packages/bunshot-auth/src/plugin.js +277 -0
  161. package/dist/packages/bunshot-auth/src/routes/auth.d.ts +15 -0
  162. package/dist/packages/bunshot-auth/src/routes/auth.js +1624 -0
  163. package/dist/packages/bunshot-auth/src/routes/groups.d.ts +4 -0
  164. package/dist/packages/bunshot-auth/src/routes/groups.js +481 -0
  165. package/dist/packages/bunshot-auth/src/routes/m2m.d.ts +2 -0
  166. package/dist/packages/bunshot-auth/src/routes/m2m.js +145 -0
  167. package/dist/packages/bunshot-auth/src/routes/mfa.d.ts +6 -0
  168. package/dist/packages/bunshot-auth/src/routes/mfa.js +991 -0
  169. package/dist/packages/bunshot-auth/src/routes/oauth.d.ts +3 -0
  170. package/dist/packages/bunshot-auth/src/routes/oauth.js +1727 -0
  171. package/dist/packages/bunshot-auth/src/routes/oidc.d.ts +2 -0
  172. package/dist/packages/bunshot-auth/src/routes/oidc.js +84 -0
  173. package/dist/packages/bunshot-auth/src/routes/organizations.d.ts +3 -0
  174. package/dist/packages/bunshot-auth/src/routes/organizations.js +741 -0
  175. package/dist/packages/bunshot-auth/src/routes/passkey.d.ts +2 -0
  176. package/dist/packages/bunshot-auth/src/routes/passkey.js +199 -0
  177. package/dist/packages/bunshot-auth/src/routes/saml.d.ts +2 -0
  178. package/dist/packages/bunshot-auth/src/routes/saml.js +226 -0
  179. package/dist/packages/bunshot-auth/src/routes/scim.d.ts +3 -0
  180. package/dist/packages/bunshot-auth/src/routes/scim.js +588 -0
  181. package/dist/packages/bunshot-auth/src/runtime.d.ts +52 -0
  182. package/dist/packages/bunshot-auth/src/runtime.js +11 -0
  183. package/dist/{schemas → packages/bunshot-auth/src/schemas}/auth.d.ts +4 -5
  184. package/dist/packages/bunshot-auth/src/schemas/auth.js +24 -0
  185. package/dist/packages/bunshot-auth/src/schemas/error.d.ts +10 -0
  186. package/dist/packages/bunshot-auth/src/schemas/error.js +10 -0
  187. package/dist/packages/bunshot-auth/src/schemas/success.d.ts +10 -0
  188. package/dist/packages/bunshot-auth/src/schemas/success.js +10 -0
  189. package/dist/packages/bunshot-auth/src/services/auth.d.ts +39 -0
  190. package/dist/packages/bunshot-auth/src/services/auth.js +378 -0
  191. package/dist/{services → packages/bunshot-auth/src/services}/mfa.d.ts +41 -17
  192. package/dist/{services → packages/bunshot-auth/src/services}/mfa.js +259 -183
  193. package/dist/packages/bunshot-auth/src/testing.d.ts +31 -0
  194. package/dist/packages/bunshot-auth/src/testing.js +23 -0
  195. package/dist/packages/bunshot-auth/src/types/adapter.d.ts +1 -0
  196. package/dist/packages/bunshot-auth/src/types/adapter.js +1 -0
  197. package/dist/packages/bunshot-auth/src/types/config.d.ts +152 -0
  198. package/dist/packages/bunshot-auth/src/types/config.js +179 -0
  199. package/dist/{routes → packages/bunshot-auth/src/types}/groups.d.ts +2 -3
  200. package/dist/packages/bunshot-auth/src/types/groups.js +1 -0
  201. package/dist/packages/bunshot-auth/src/types/oauthCode.d.ts +6 -0
  202. package/dist/packages/bunshot-auth/src/types/oauthCode.js +1 -0
  203. package/dist/packages/bunshot-auth/src/types/oauthReauth.d.ts +13 -0
  204. package/dist/packages/bunshot-auth/src/types/oauthReauth.js +1 -0
  205. package/dist/packages/bunshot-auth/src/types/redis.d.ts +1 -0
  206. package/dist/packages/bunshot-auth/src/types/redis.js +1 -0
  207. package/dist/packages/bunshot-auth/src/types/saml.d.ts +10 -0
  208. package/dist/packages/bunshot-auth/src/types/saml.js +1 -0
  209. package/dist/packages/bunshot-auth/src/types/session.d.ts +18 -0
  210. package/dist/packages/bunshot-auth/src/types/session.js +1 -0
  211. package/dist/packages/bunshot-auth/src/types/store.d.ts +1 -0
  212. package/dist/packages/bunshot-auth/src/types/store.js +1 -0
  213. package/dist/packages/bunshot-core/src/adminProvider.d.ts +95 -0
  214. package/dist/packages/bunshot-core/src/adminProvider.js +1 -0
  215. package/dist/packages/bunshot-core/src/auditLog.d.ts +34 -0
  216. package/dist/packages/bunshot-core/src/auditLog.js +1 -0
  217. package/dist/packages/bunshot-core/src/auth-adapter.d.ts +227 -0
  218. package/dist/packages/bunshot-core/src/auth-adapter.js +4 -0
  219. package/dist/packages/bunshot-core/src/authVariables.d.ts +14 -0
  220. package/dist/packages/bunshot-core/src/authVariables.js +4 -0
  221. package/dist/packages/bunshot-core/src/cache.d.ts +12 -0
  222. package/dist/packages/bunshot-core/src/cache.js +21 -0
  223. package/dist/{lib → packages/bunshot-core/src}/captcha.d.ts +1 -10
  224. package/dist/packages/bunshot-core/src/captcha.js +1 -0
  225. package/dist/packages/bunshot-core/src/clearRegistry.d.ts +6 -0
  226. package/dist/packages/bunshot-core/src/clearRegistry.js +17 -0
  227. package/dist/packages/bunshot-core/src/clientIp.d.ts +3 -0
  228. package/dist/packages/bunshot-core/src/clientIp.js +45 -0
  229. package/dist/packages/bunshot-core/src/configLock.d.ts +4 -0
  230. package/dist/packages/bunshot-core/src/configLock.js +7 -0
  231. package/dist/packages/bunshot-core/src/configValidation.d.ts +22 -0
  232. package/dist/packages/bunshot-core/src/configValidation.js +39 -0
  233. package/dist/packages/bunshot-core/src/constants.js +10 -0
  234. package/dist/packages/bunshot-core/src/context/bunshotContext.d.ts +232 -0
  235. package/dist/packages/bunshot-core/src/context/bunshotContext.js +1 -0
  236. package/dist/packages/bunshot-core/src/context/contextAccess.d.ts +3 -0
  237. package/dist/packages/bunshot-core/src/context/contextAccess.js +16 -0
  238. package/dist/packages/bunshot-core/src/context/contextStore.d.ts +16 -0
  239. package/dist/packages/bunshot-core/src/context/contextStore.js +31 -0
  240. package/dist/packages/bunshot-core/src/context/frameworkConfig.d.ts +38 -0
  241. package/dist/packages/bunshot-core/src/context/frameworkConfig.js +1 -0
  242. package/dist/packages/bunshot-core/src/context/index.d.ts +4 -0
  243. package/dist/packages/bunshot-core/src/context/index.js +2 -0
  244. package/dist/packages/bunshot-core/src/context.d.ts +40 -0
  245. package/dist/packages/bunshot-core/src/context.js +35 -0
  246. package/dist/packages/bunshot-core/src/coreContracts.d.ts +47 -0
  247. package/dist/packages/bunshot-core/src/coreContracts.js +1 -0
  248. package/dist/packages/bunshot-core/src/coreRegistrar.d.ts +6 -0
  249. package/dist/packages/bunshot-core/src/coreRegistrar.js +42 -0
  250. package/dist/{lib → packages/bunshot-core/src}/createRoute.d.ts +4 -30
  251. package/dist/{lib → packages/bunshot-core/src}/createRoute.js +39 -88
  252. package/dist/packages/bunshot-core/src/cronRegistry.d.ts +11 -0
  253. package/dist/packages/bunshot-core/src/cronRegistry.js +1 -0
  254. package/dist/packages/bunshot-core/src/crypto.d.ts +43 -0
  255. package/dist/packages/bunshot-core/src/crypto.js +74 -0
  256. package/dist/packages/bunshot-core/src/csrf.d.ts +8 -0
  257. package/dist/packages/bunshot-core/src/csrf.js +1 -0
  258. package/dist/packages/bunshot-core/src/defaults/defaultFingerprint.d.ts +7 -0
  259. package/dist/packages/bunshot-core/src/defaults/defaultFingerprint.js +19 -0
  260. package/dist/packages/bunshot-core/src/defaults/memoryCacheAdapter.d.ts +6 -0
  261. package/dist/packages/bunshot-core/src/defaults/memoryCacheAdapter.js +40 -0
  262. package/dist/packages/bunshot-core/src/defaults/memoryRateLimit.d.ts +6 -0
  263. package/dist/packages/bunshot-core/src/defaults/memoryRateLimit.js +24 -0
  264. package/dist/packages/bunshot-core/src/emailTemplates.d.ts +5 -0
  265. package/dist/packages/bunshot-core/src/emailTemplates.js +10 -0
  266. package/dist/{lib/HttpError.d.ts → packages/bunshot-core/src/errors.d.ts} +4 -1
  267. package/dist/{lib/HttpError.js → packages/bunshot-core/src/errors.js} +7 -1
  268. package/dist/packages/bunshot-core/src/eventBus.d.ts +270 -0
  269. package/dist/packages/bunshot-core/src/eventBus.js +143 -0
  270. package/dist/packages/bunshot-core/src/idempotency.d.ts +18 -0
  271. package/dist/packages/bunshot-core/src/idempotency.js +1 -0
  272. package/dist/packages/bunshot-core/src/index.d.ts +60 -0
  273. package/dist/packages/bunshot-core/src/index.js +34 -0
  274. package/dist/packages/bunshot-core/src/mail.d.ts +14 -0
  275. package/dist/packages/bunshot-core/src/mail.js +8 -0
  276. package/dist/packages/bunshot-core/src/memoryEviction.d.ts +24 -0
  277. package/dist/packages/bunshot-core/src/memoryEviction.js +52 -0
  278. package/dist/packages/bunshot-core/src/pagination.d.ts +45 -0
  279. package/dist/packages/bunshot-core/src/pagination.js +61 -0
  280. package/dist/packages/bunshot-core/src/permissions.d.ts +64 -0
  281. package/dist/packages/bunshot-core/src/permissions.js +27 -0
  282. package/dist/packages/bunshot-core/src/plugin.d.ts +44 -0
  283. package/dist/packages/bunshot-core/src/plugin.js +1 -0
  284. package/dist/packages/bunshot-core/src/rateLimit.d.ts +5 -0
  285. package/dist/packages/bunshot-core/src/rateLimit.js +18 -0
  286. package/dist/packages/bunshot-core/src/redis.d.ts +21 -0
  287. package/dist/packages/bunshot-core/src/redis.js +1 -0
  288. package/dist/packages/bunshot-core/src/routeAuth.d.ts +5 -0
  289. package/dist/packages/bunshot-core/src/routeAuth.js +11 -0
  290. package/dist/packages/bunshot-core/src/routeOverrides.d.ts +24 -0
  291. package/dist/packages/bunshot-core/src/routeOverrides.js +25 -0
  292. package/dist/packages/bunshot-core/src/routerAdapter.d.ts +6 -0
  293. package/dist/packages/bunshot-core/src/routerAdapter.js +56 -0
  294. package/dist/packages/bunshot-core/src/secrets.d.ts +48 -0
  295. package/dist/packages/bunshot-core/src/secrets.js +8 -0
  296. package/dist/packages/bunshot-core/src/signing.d.ts +41 -0
  297. package/dist/packages/bunshot-core/src/signing.js +1 -0
  298. package/dist/packages/bunshot-core/src/sse.d.ts +36 -0
  299. package/dist/packages/bunshot-core/src/sse.js +1 -0
  300. package/dist/packages/bunshot-core/src/storageAdapter.js +1 -0
  301. package/dist/packages/bunshot-core/src/storeInfra.d.ts +44 -0
  302. package/dist/packages/bunshot-core/src/storeInfra.js +18 -0
  303. package/dist/packages/bunshot-core/src/storeType.d.ts +7 -0
  304. package/dist/packages/bunshot-core/src/storeType.js +1 -0
  305. package/dist/packages/bunshot-core/src/testing.d.ts +1 -0
  306. package/dist/packages/bunshot-core/src/testing.js +1 -0
  307. package/dist/packages/bunshot-core/src/uploadRegistry.d.ts +23 -0
  308. package/dist/packages/bunshot-core/src/uploadRegistry.js +4 -0
  309. package/dist/packages/bunshot-core/src/userResolver.d.ts +5 -0
  310. package/dist/packages/bunshot-core/src/userResolver.js +14 -0
  311. package/dist/packages/bunshot-core/src/wsMessages.d.ts +42 -0
  312. package/dist/packages/bunshot-core/src/wsMessages.js +4 -0
  313. package/dist/packages/bunshot-permissions/src/adapters/memory.d.ts +7 -0
  314. package/dist/packages/bunshot-permissions/src/adapters/memory.js +73 -0
  315. package/dist/packages/bunshot-permissions/src/index.d.ts +10 -0
  316. package/dist/packages/bunshot-permissions/src/index.js +5 -0
  317. package/dist/packages/bunshot-permissions/src/lib/bootstrap.d.ts +7 -0
  318. package/dist/packages/bunshot-permissions/src/lib/bootstrap.js +12 -0
  319. package/dist/packages/bunshot-permissions/src/lib/evaluator.d.ts +10 -0
  320. package/dist/packages/bunshot-permissions/src/lib/evaluator.js +165 -0
  321. package/dist/packages/bunshot-permissions/src/lib/registry.d.ts +2 -0
  322. package/dist/packages/bunshot-permissions/src/lib/registry.js +31 -0
  323. package/dist/packages/bunshot-permissions/src/lib/validation.d.ts +1 -0
  324. package/dist/packages/bunshot-permissions/src/lib/validation.js +1 -0
  325. package/dist/packages/bunshot-permissions/src/types/adapter.d.ts +1 -0
  326. package/dist/packages/bunshot-permissions/src/types/adapter.js +1 -0
  327. package/dist/packages/bunshot-permissions/src/types/evaluator.d.ts +1 -0
  328. package/dist/packages/bunshot-permissions/src/types/evaluator.js +1 -0
  329. package/dist/packages/bunshot-permissions/src/types/models.d.ts +1 -0
  330. package/dist/packages/bunshot-permissions/src/types/models.js +1 -0
  331. package/dist/packages/bunshot-permissions/src/types/registry.d.ts +1 -0
  332. package/dist/packages/bunshot-permissions/src/types/registry.js +1 -0
  333. package/dist/packages/bunshot-postgres/src/adapter.d.ts +6 -0
  334. package/dist/packages/bunshot-postgres/src/adapter.js +794 -0
  335. package/dist/packages/bunshot-postgres/src/connection.d.ts +15 -0
  336. package/dist/packages/bunshot-postgres/src/connection.js +16 -0
  337. package/dist/packages/bunshot-postgres/src/index.d.ts +4 -0
  338. package/dist/packages/bunshot-postgres/src/index.js +2 -0
  339. package/dist/packages/bunshot-postgres/src/schema.d.ts +997 -0
  340. package/dist/packages/bunshot-postgres/src/schema.js +105 -0
  341. package/dist/src/app.d.ts +230 -0
  342. package/dist/src/app.js +182 -0
  343. package/dist/src/cli/commands/init.d.ts +10 -0
  344. package/dist/src/cli/commands/init.js +709 -0
  345. package/dist/src/cli/index.d.ts +1 -0
  346. package/dist/src/cli/index.js +3 -0
  347. package/dist/src/entrypoints/mongo.d.ts +6 -0
  348. package/dist/src/entrypoints/mongo.js +4 -0
  349. package/dist/src/entrypoints/queue.d.ts +2 -0
  350. package/dist/src/entrypoints/queue.js +1 -0
  351. package/dist/src/entrypoints/redis.d.ts +1 -0
  352. package/dist/src/entrypoints/redis.js +1 -0
  353. package/dist/{adapters → src/framework/adapters}/localStorage.d.ts +1 -1
  354. package/dist/{adapters → src/framework/adapters}/localStorage.js +10 -10
  355. package/dist/src/framework/adapters/memoryStorage.d.ts +2 -0
  356. package/dist/src/framework/adapters/memoryStorage.js +45 -0
  357. package/dist/{adapters → src/framework/adapters}/s3Storage.d.ts +1 -1
  358. package/dist/{adapters → src/framework/adapters}/s3Storage.js +12 -12
  359. package/dist/src/framework/admin/bunshotAccess.d.ts +2 -0
  360. package/dist/src/framework/admin/bunshotAccess.js +23 -0
  361. package/dist/src/framework/admin/bunshotUsers.d.ts +2 -0
  362. package/dist/src/framework/admin/bunshotUsers.js +103 -0
  363. package/dist/src/framework/admin/index.d.ts +7 -0
  364. package/dist/src/framework/admin/index.js +21 -0
  365. package/dist/src/framework/boundaryAdapters/cacheFactories.d.ts +13 -0
  366. package/dist/src/framework/boundaryAdapters/cacheFactories.js +86 -0
  367. package/dist/src/framework/boundaryAdapters/index.d.ts +2 -0
  368. package/dist/src/framework/boundaryAdapters/index.js +1 -0
  369. package/dist/src/framework/boundaryAdapters.d.ts +17 -0
  370. package/dist/src/framework/boundaryAdapters.js +62 -0
  371. package/dist/src/framework/buildContext.d.ts +33 -0
  372. package/dist/src/framework/buildContext.js +119 -0
  373. package/dist/src/framework/config/schema.d.ts +447 -0
  374. package/dist/src/framework/config/schema.js +528 -0
  375. package/dist/src/framework/createInfrastructure.d.ts +76 -0
  376. package/dist/src/framework/createInfrastructure.js +221 -0
  377. package/dist/src/framework/lib/auditLog.d.ts +23 -0
  378. package/dist/src/framework/lib/auditLog.js +416 -0
  379. package/dist/src/framework/lib/captcha.d.ts +11 -0
  380. package/dist/{lib → src/framework/lib}/captcha.js +13 -10
  381. package/dist/{lib → src/framework/lib}/createDtoMapper.js +4 -4
  382. package/dist/src/framework/lib/createRoute.d.ts +1 -0
  383. package/dist/src/framework/lib/createRoute.js +2 -0
  384. package/dist/{lib → src/framework/lib}/idempotency.d.ts +2 -6
  385. package/dist/src/framework/lib/idempotency.js +74 -0
  386. package/dist/src/framework/lib/logger.d.ts +3 -0
  387. package/dist/src/framework/lib/logger.js +14 -0
  388. package/dist/src/framework/lib/metrics.d.ts +34 -0
  389. package/dist/{lib → src/framework/lib}/metrics.js +49 -57
  390. package/dist/src/framework/lib/pagination.d.ts +42 -0
  391. package/dist/src/framework/lib/pagination.js +51 -0
  392. package/dist/src/framework/lib/redisTransport.d.ts +38 -0
  393. package/dist/src/framework/lib/redisTransport.js +107 -0
  394. package/dist/src/framework/lib/resolveUserId.d.ts +2 -0
  395. package/dist/src/framework/lib/resolveUserId.js +5 -0
  396. package/dist/src/framework/lib/sseCollision.d.ts +6 -0
  397. package/dist/src/framework/lib/sseCollision.js +26 -0
  398. package/dist/src/framework/lib/storageAdapter.d.ts +1 -0
  399. package/dist/src/framework/lib/storageAdapter.js +1 -0
  400. package/dist/{lib → src/framework/lib}/stripUnreferencedSchemas.js +4 -4
  401. package/dist/src/framework/lib/tenant.d.ts +21 -0
  402. package/dist/src/framework/lib/tenant.js +70 -0
  403. package/dist/{lib → src/framework/lib}/upload.d.ts +11 -10
  404. package/dist/src/framework/lib/upload.js +132 -0
  405. package/dist/src/framework/lib/uploadRegistry.d.ts +23 -0
  406. package/dist/src/framework/lib/uploadRegistry.js +34 -0
  407. package/dist/{lib → src/framework/lib}/validate.d.ts +1 -1
  408. package/dist/{lib → src/framework/lib}/validate.js +2 -2
  409. package/dist/src/framework/lib/ws.d.ts +19 -0
  410. package/dist/src/framework/lib/ws.js +130 -0
  411. package/dist/src/framework/lib/wsHeartbeat.d.ts +12 -0
  412. package/dist/src/framework/lib/wsHeartbeat.js +53 -0
  413. package/dist/src/framework/lib/wsMessages.d.ts +25 -0
  414. package/dist/src/framework/lib/wsMessages.js +45 -0
  415. package/dist/src/framework/lib/wsNamespace.d.ts +17 -0
  416. package/dist/src/framework/lib/wsNamespace.js +19 -0
  417. package/dist/src/framework/lib/wsPresence.d.ts +17 -0
  418. package/dist/src/framework/lib/wsPresence.js +84 -0
  419. package/dist/src/framework/lib/wsTransport.d.ts +38 -0
  420. package/dist/src/framework/lib/wsTransport.js +9 -0
  421. package/dist/{lib → src/framework/lib}/zodToMongoose.d.ts +1 -1
  422. package/dist/{lib → src/framework/lib}/zodToMongoose.js +11 -11
  423. package/dist/{middleware → src/framework/middleware}/auditLog.d.ts +4 -3
  424. package/dist/src/framework/middleware/auditLog.js +42 -0
  425. package/dist/{middleware → src/framework/middleware}/botProtection.d.ts +2 -2
  426. package/dist/{middleware → src/framework/middleware}/botProtection.js +8 -9
  427. package/dist/src/framework/middleware/cacheResponse.d.ts +35 -0
  428. package/dist/src/framework/middleware/cacheResponse.js +126 -0
  429. package/dist/{middleware → src/framework/middleware}/captcha.d.ts +2 -3
  430. package/dist/src/framework/middleware/captcha.js +37 -0
  431. package/dist/{middleware → src/framework/middleware}/errorHandler.d.ts +1 -1
  432. package/dist/{middleware → src/framework/middleware}/errorHandler.js +2 -2
  433. package/dist/src/framework/middleware/index.js +1 -0
  434. package/dist/{middleware → src/framework/middleware}/logger.d.ts +1 -1
  435. package/dist/src/framework/middleware/metrics.d.ts +12 -0
  436. package/dist/src/framework/middleware/metrics.js +26 -0
  437. package/dist/{middleware → src/framework/middleware}/rateLimit.d.ts +2 -2
  438. package/dist/src/framework/middleware/rateLimit.js +22 -0
  439. package/dist/src/framework/middleware/requestId.d.ts +3 -0
  440. package/dist/{middleware → src/framework/middleware}/requestId.js +2 -2
  441. package/dist/{middleware → src/framework/middleware}/requestLogger.d.ts +3 -3
  442. package/dist/{middleware → src/framework/middleware}/requestLogger.js +17 -12
  443. package/dist/{middleware → src/framework/middleware}/requestSigning.d.ts +2 -2
  444. package/dist/{middleware → src/framework/middleware}/requestSigning.js +18 -20
  445. package/dist/src/framework/middleware/tenant.d.ts +14 -0
  446. package/dist/{middleware → src/framework/middleware}/tenant.js +31 -27
  447. package/dist/src/framework/middleware/upload.d.ts +5 -0
  448. package/dist/{middleware → src/framework/middleware}/upload.js +4 -4
  449. package/dist/{middleware → src/framework/middleware}/webhookAuth.d.ts +3 -3
  450. package/dist/{middleware → src/framework/middleware}/webhookAuth.js +11 -12
  451. package/dist/src/framework/models/AuditLog.d.ts +21 -0
  452. package/dist/src/framework/models/AuditLog.js +31 -0
  453. package/dist/src/framework/mountMiddleware.d.ts +91 -0
  454. package/dist/src/framework/mountMiddleware.js +128 -0
  455. package/dist/src/framework/mountOptionalEndpoints.d.ts +103 -0
  456. package/dist/src/framework/mountOptionalEndpoints.js +64 -0
  457. package/dist/src/framework/mountRoutes.d.ts +21 -0
  458. package/dist/src/framework/mountRoutes.js +144 -0
  459. package/dist/src/framework/persistence/cronRegistry.d.ts +28 -0
  460. package/dist/src/framework/persistence/cronRegistry.js +139 -0
  461. package/dist/src/framework/persistence/idempotency.d.ts +26 -0
  462. package/dist/src/framework/persistence/idempotency.js +178 -0
  463. package/dist/src/framework/persistence/index.d.ts +6 -0
  464. package/dist/src/framework/persistence/index.js +8 -0
  465. package/dist/src/framework/persistence/storeInfra.d.ts +9 -0
  466. package/dist/src/framework/persistence/storeInfra.js +1 -0
  467. package/dist/src/framework/persistence/uploadRegistry.d.ts +35 -0
  468. package/dist/src/framework/persistence/uploadRegistry.js +235 -0
  469. package/dist/src/framework/persistence/wsMessages.d.ts +22 -0
  470. package/dist/src/framework/persistence/wsMessages.js +296 -0
  471. package/dist/src/framework/preloadSchemas.d.ts +24 -0
  472. package/dist/src/framework/preloadSchemas.js +42 -0
  473. package/dist/src/framework/registerBoundaryAdapters.d.ts +23 -0
  474. package/dist/src/framework/registerBoundaryAdapters.js +46 -0
  475. package/dist/src/framework/routes/admin.d.ts +9 -0
  476. package/dist/src/framework/routes/admin.js +361 -0
  477. package/dist/src/framework/routes/health.d.ts +1 -0
  478. package/dist/src/framework/routes/health.js +21 -0
  479. package/dist/src/framework/routes/home.d.ts +1 -0
  480. package/dist/src/framework/routes/home.js +18 -0
  481. package/dist/src/framework/routes/jobs.d.ts +3 -0
  482. package/dist/{routes → src/framework/routes}/jobs.js +128 -103
  483. package/dist/src/framework/routes/metrics.d.ts +10 -0
  484. package/dist/src/framework/routes/metrics.js +57 -0
  485. package/dist/{routes → src/framework/routes}/uploads.d.ts +3 -3
  486. package/dist/src/framework/routes/uploads.js +262 -0
  487. package/dist/src/framework/runPluginLifecycle.d.ts +27 -0
  488. package/dist/src/framework/runPluginLifecycle.js +121 -0
  489. package/dist/src/framework/secrets/frameworkSecretSchema.d.ts +58 -0
  490. package/dist/src/framework/secrets/frameworkSecretSchema.js +20 -0
  491. package/dist/src/framework/secrets/index.d.ts +9 -0
  492. package/dist/src/framework/secrets/index.js +7 -0
  493. package/dist/src/framework/secrets/providers/envProvider.d.ts +15 -0
  494. package/dist/src/framework/secrets/providers/envProvider.js +18 -0
  495. package/dist/src/framework/secrets/providers/fileProvider.d.ts +8 -0
  496. package/dist/src/framework/secrets/providers/fileProvider.js +82 -0
  497. package/dist/src/framework/secrets/providers/ssmProvider.d.ts +20 -0
  498. package/dist/src/framework/secrets/providers/ssmProvider.js +127 -0
  499. package/dist/src/framework/secrets/resolveSecretBundle.d.ts +53 -0
  500. package/dist/src/framework/secrets/resolveSecretBundle.js +84 -0
  501. package/dist/src/framework/secrets/resolveSecrets.d.ts +18 -0
  502. package/dist/src/framework/secrets/resolveSecrets.js +34 -0
  503. package/dist/src/framework/sse/index.d.ts +21 -0
  504. package/dist/src/framework/sse/index.js +109 -0
  505. package/dist/src/framework/ws/index.d.ts +11 -0
  506. package/dist/src/framework/ws/index.js +8 -0
  507. package/dist/src/index.d.ts +87 -0
  508. package/dist/src/index.js +58 -0
  509. package/dist/src/lib/appConfig.d.ts +7 -0
  510. package/dist/src/lib/appConfig.js +27 -0
  511. package/dist/src/lib/appMeta.d.ts +7 -0
  512. package/dist/src/lib/appMeta.js +3 -0
  513. package/dist/src/lib/authConfig.d.ts +532 -0
  514. package/dist/{lib/appConfig.js → src/lib/authConfig.js} +75 -17
  515. package/dist/{lib → src/lib}/context.d.ts +6 -12
  516. package/dist/{lib → src/lib}/context.js +5 -5
  517. package/dist/src/lib/logger.d.ts +1 -0
  518. package/dist/src/lib/logger.js +1 -0
  519. package/dist/src/lib/mongo.d.ts +58 -0
  520. package/dist/src/lib/mongo.js +96 -0
  521. package/dist/src/lib/queue.d.ts +72 -0
  522. package/dist/src/lib/queue.js +152 -0
  523. package/dist/src/lib/redis.d.ts +28 -0
  524. package/dist/src/lib/redis.js +72 -0
  525. package/dist/{lib → src/lib}/signing.d.ts +2 -2
  526. package/dist/src/lib/signing.js +210 -0
  527. package/dist/src/lib/signingConfig.d.ts +40 -0
  528. package/dist/src/lib/signingConfig.js +28 -0
  529. package/dist/src/server.d.ts +146 -0
  530. package/dist/src/server.js +469 -0
  531. package/dist/src/shared/lib/HttpError.d.ts +1 -0
  532. package/dist/src/shared/lib/HttpError.js +2 -0
  533. package/dist/src/shared/lib/constants.d.ts +10 -0
  534. package/dist/src/shared/lib/crypto.d.ts +43 -0
  535. package/dist/src/shared/lib/crypto.js +74 -0
  536. package/dist/src/shared/lib/signing.d.ts +52 -0
  537. package/dist/{lib → src/shared/lib}/signing.js +35 -8
  538. package/dist/src/testing.d.ts +34 -0
  539. package/dist/src/testing.js +93 -0
  540. package/package.json +100 -26
  541. package/dist/adapters/memoryAuth.d.ts +0 -52
  542. package/dist/adapters/memoryAuth.js +0 -749
  543. package/dist/adapters/memoryStorage.d.ts +0 -3
  544. package/dist/adapters/memoryStorage.js +0 -44
  545. package/dist/adapters/mongoAuth.d.ts +0 -2
  546. package/dist/adapters/mongoAuth.js +0 -403
  547. package/dist/adapters/sqliteAuth.d.ts +0 -72
  548. package/dist/adapters/sqliteAuth.js +0 -858
  549. package/dist/app.d.ts +0 -559
  550. package/dist/app.js +0 -651
  551. package/dist/entrypoints/mongo.d.ts +0 -5
  552. package/dist/entrypoints/mongo.js +0 -4
  553. package/dist/entrypoints/queue.d.ts +0 -2
  554. package/dist/entrypoints/queue.js +0 -1
  555. package/dist/entrypoints/redis.d.ts +0 -1
  556. package/dist/entrypoints/redis.js +0 -1
  557. package/dist/index.d.ts +0 -117
  558. package/dist/index.js +0 -88
  559. package/dist/lib/appConfig.d.ts +0 -275
  560. package/dist/lib/auditLog.d.ts +0 -58
  561. package/dist/lib/auditLog.js +0 -218
  562. package/dist/lib/authAdapter.d.ts +0 -246
  563. package/dist/lib/authAdapter.js +0 -7
  564. package/dist/lib/authRateLimit.d.ts +0 -13
  565. package/dist/lib/authRateLimit.js +0 -117
  566. package/dist/lib/clientIp.d.ts +0 -14
  567. package/dist/lib/credentialStuffing.d.ts +0 -31
  568. package/dist/lib/credentialStuffing.js +0 -77
  569. package/dist/lib/crypto.d.ts +0 -11
  570. package/dist/lib/crypto.js +0 -22
  571. package/dist/lib/deletionCancelToken.d.ts +0 -12
  572. package/dist/lib/deletionCancelToken.js +0 -88
  573. package/dist/lib/emailVerification.d.ts +0 -19
  574. package/dist/lib/emailVerification.js +0 -129
  575. package/dist/lib/fingerprint.js +0 -36
  576. package/dist/lib/idempotency.js +0 -182
  577. package/dist/lib/jwks.d.ts +0 -25
  578. package/dist/lib/jwks.js +0 -51
  579. package/dist/lib/jwt.d.ts +0 -15
  580. package/dist/lib/jwt.js +0 -111
  581. package/dist/lib/metrics.d.ts +0 -14
  582. package/dist/lib/mfaChallenge.d.ts +0 -55
  583. package/dist/lib/mfaChallenge.js +0 -398
  584. package/dist/lib/mongo.d.ts +0 -39
  585. package/dist/lib/mongo.js +0 -124
  586. package/dist/lib/oauth.d.ts +0 -40
  587. package/dist/lib/oauth.js +0 -101
  588. package/dist/lib/oauthCode.d.ts +0 -15
  589. package/dist/lib/oauthCode.js +0 -95
  590. package/dist/lib/pagination.d.ts +0 -119
  591. package/dist/lib/pagination.js +0 -166
  592. package/dist/lib/queue.d.ts +0 -37
  593. package/dist/lib/queue.js +0 -117
  594. package/dist/lib/redis.d.ts +0 -9
  595. package/dist/lib/redis.js +0 -61
  596. package/dist/lib/resetPassword.d.ts +0 -12
  597. package/dist/lib/resetPassword.js +0 -93
  598. package/dist/lib/roles.d.ts +0 -7
  599. package/dist/lib/roles.js +0 -49
  600. package/dist/lib/saml.d.ts +0 -25
  601. package/dist/lib/saml.js +0 -64
  602. package/dist/lib/securityEvents.d.ts +0 -28
  603. package/dist/lib/securityEvents.js +0 -26
  604. package/dist/lib/session.d.ts +0 -49
  605. package/dist/lib/session.js +0 -597
  606. package/dist/lib/tenant.d.ts +0 -15
  607. package/dist/lib/tenant.js +0 -65
  608. package/dist/lib/upload.js +0 -112
  609. package/dist/lib/uploadRegistry.d.ts +0 -18
  610. package/dist/lib/uploadRegistry.js +0 -83
  611. package/dist/lib/ws.d.ts +0 -22
  612. package/dist/lib/ws.js +0 -96
  613. package/dist/lib/wsHeartbeat.d.ts +0 -12
  614. package/dist/lib/wsHeartbeat.js +0 -57
  615. package/dist/lib/wsMessages.d.ts +0 -40
  616. package/dist/lib/wsMessages.js +0 -330
  617. package/dist/lib/wsPresence.d.ts +0 -25
  618. package/dist/lib/wsPresence.js +0 -99
  619. package/dist/middleware/auditLog.js +0 -39
  620. package/dist/middleware/bearerAuth.d.ts +0 -2
  621. package/dist/middleware/bearerAuth.js +0 -11
  622. package/dist/middleware/cacheResponse.d.ts +0 -15
  623. package/dist/middleware/cacheResponse.js +0 -178
  624. package/dist/middleware/captcha.js +0 -36
  625. package/dist/middleware/csrf.js +0 -129
  626. package/dist/middleware/identify.d.ts +0 -3
  627. package/dist/middleware/identify.js +0 -122
  628. package/dist/middleware/index.js +0 -1
  629. package/dist/middleware/metrics.d.ts +0 -9
  630. package/dist/middleware/metrics.js +0 -26
  631. package/dist/middleware/rateLimit.js +0 -22
  632. package/dist/middleware/requestId.d.ts +0 -3
  633. package/dist/middleware/scimAuth.d.ts +0 -8
  634. package/dist/middleware/scimAuth.js +0 -29
  635. package/dist/middleware/tenant.d.ts +0 -5
  636. package/dist/middleware/upload.d.ts +0 -5
  637. package/dist/middleware/userAuth.d.ts +0 -3
  638. package/dist/middleware/userAuth.js +0 -6
  639. package/dist/models/AuditLog.d.ts +0 -30
  640. package/dist/models/AuditLog.js +0 -39
  641. package/dist/models/AuthUser.js +0 -55
  642. package/dist/models/Group.d.ts +0 -21
  643. package/dist/models/Group.js +0 -28
  644. package/dist/models/GroupMembership.js +0 -25
  645. package/dist/models/TenantRole.d.ts +0 -15
  646. package/dist/models/TenantRole.js +0 -23
  647. package/dist/routes/auth.d.ts +0 -12
  648. package/dist/routes/auth.js +0 -744
  649. package/dist/routes/groups.js +0 -346
  650. package/dist/routes/health.d.ts +0 -1
  651. package/dist/routes/health.js +0 -22
  652. package/dist/routes/home.d.ts +0 -1
  653. package/dist/routes/home.js +0 -16
  654. package/dist/routes/jobs.d.ts +0 -2
  655. package/dist/routes/m2m.d.ts +0 -2
  656. package/dist/routes/m2m.js +0 -72
  657. package/dist/routes/metrics.d.ts +0 -8
  658. package/dist/routes/metrics.js +0 -55
  659. package/dist/routes/mfa.d.ts +0 -5
  660. package/dist/routes/mfa.js +0 -628
  661. package/dist/routes/oauth.d.ts +0 -2
  662. package/dist/routes/oauth.js +0 -520
  663. package/dist/routes/oidc.d.ts +0 -2
  664. package/dist/routes/oidc.js +0 -29
  665. package/dist/routes/passkey.d.ts +0 -1
  666. package/dist/routes/passkey.js +0 -157
  667. package/dist/routes/saml.d.ts +0 -2
  668. package/dist/routes/saml.js +0 -86
  669. package/dist/routes/scim.d.ts +0 -2
  670. package/dist/routes/scim.js +0 -255
  671. package/dist/routes/uploads.js +0 -227
  672. package/dist/schemas/auth.js +0 -30
  673. package/dist/server.d.ts +0 -57
  674. package/dist/server.js +0 -112
  675. package/dist/services/auth.d.ts +0 -29
  676. package/dist/services/auth.js +0 -238
  677. package/dist/ws/index.d.ts +0 -10
  678. package/dist/ws/index.js +0 -39
  679. package/docs/sections/adding-middleware/full.md +0 -35
  680. package/docs/sections/adding-models/full.md +0 -125
  681. package/docs/sections/adding-models/overview.md +0 -13
  682. package/docs/sections/adding-routes/full.md +0 -182
  683. package/docs/sections/adding-routes/overview.md +0 -23
  684. package/docs/sections/auth-flow/full.md +0 -790
  685. package/docs/sections/auth-flow/overview.md +0 -10
  686. package/docs/sections/auth-security-examples/full.md +0 -388
  687. package/docs/sections/authentication/full.md +0 -130
  688. package/docs/sections/authentication/overview.md +0 -5
  689. package/docs/sections/cli/full.md +0 -42
  690. package/docs/sections/configuration/full.md +0 -172
  691. package/docs/sections/configuration/overview.md +0 -18
  692. package/docs/sections/configuration-example/full.md +0 -117
  693. package/docs/sections/configuration-example/overview.md +0 -30
  694. package/docs/sections/documentation/full.md +0 -171
  695. package/docs/sections/environment-variables/full.md +0 -55
  696. package/docs/sections/exports/full.md +0 -123
  697. package/docs/sections/extending-context/full.md +0 -59
  698. package/docs/sections/header.md +0 -3
  699. package/docs/sections/installation/full.md +0 -6
  700. package/docs/sections/jobs/full.md +0 -140
  701. package/docs/sections/jobs/overview.md +0 -15
  702. package/docs/sections/logging/full.md +0 -83
  703. package/docs/sections/metrics/full.md +0 -131
  704. package/docs/sections/mongodb-connections/full.md +0 -45
  705. package/docs/sections/mongodb-connections/overview.md +0 -7
  706. package/docs/sections/multi-tenancy/full.md +0 -66
  707. package/docs/sections/multi-tenancy/overview.md +0 -15
  708. package/docs/sections/oauth/full.md +0 -189
  709. package/docs/sections/oauth/overview.md +0 -16
  710. package/docs/sections/package-development/full.md +0 -7
  711. package/docs/sections/pagination/full.md +0 -93
  712. package/docs/sections/passkey-login/full.md +0 -90
  713. package/docs/sections/passkey-login/overview.md +0 -1
  714. package/docs/sections/peer-dependencies/full.md +0 -47
  715. package/docs/sections/quick-start/full.md +0 -43
  716. package/docs/sections/response-caching/full.md +0 -117
  717. package/docs/sections/response-caching/overview.md +0 -13
  718. package/docs/sections/roles/full.md +0 -225
  719. package/docs/sections/roles/overview.md +0 -14
  720. package/docs/sections/running-without-redis/full.md +0 -16
  721. package/docs/sections/running-without-redis-or-mongodb/full.md +0 -60
  722. package/docs/sections/signing/full.md +0 -203
  723. package/docs/sections/stack/full.md +0 -10
  724. package/docs/sections/uploads/full.md +0 -208
  725. package/docs/sections/versioning/full.md +0 -85
  726. package/docs/sections/webhook-auth/full.md +0 -100
  727. package/docs/sections/websocket/full.md +0 -196
  728. package/docs/sections/websocket/overview.md +0 -5
  729. package/docs/sections/websocket-rooms/full.md +0 -102
  730. package/docs/sections/websocket-rooms/overview.md +0 -5
  731. /package/dist/{lib/storageAdapter.js → packages/bunshot-admin/src/types/env.js} +0 -0
  732. /package/dist/{lib → packages/bunshot-auth/src/lib}/fingerprint.d.ts +0 -0
  733. /package/dist/{lib → packages/bunshot-auth/src/lib}/logger.d.ts +0 -0
  734. /package/dist/{lib → packages/bunshot-core/src}/constants.d.ts +0 -0
  735. /package/dist/{lib → packages/bunshot-core/src}/storageAdapter.d.ts +0 -0
  736. /package/dist/{lib → src/framework/lib}/createDtoMapper.d.ts +0 -0
  737. /package/dist/{lib → src/framework/lib}/stripUnreferencedSchemas.d.ts +0 -0
  738. /package/dist/{middleware → src/framework/middleware}/cors.d.ts +0 -0
  739. /package/dist/{middleware → src/framework/middleware}/cors.js +0 -0
  740. /package/dist/{middleware → src/framework/middleware}/index.d.ts +0 -0
  741. /package/dist/{middleware → src/framework/middleware}/logger.js +0 -0
  742. /package/dist/{lib → src/shared/lib}/constants.js +0 -0
@@ -0,0 +1,1211 @@
1
+ import { DEFAULT_MAX_ENTRIES, hashToken, timingSafeEqual } from '../../../bunshot-core/src/index.js';
2
+ import { DEFAULT_AUTH_CONFIG } from '../config/authConfig';
3
+ // ---------------------------------------------------------------------------
4
+ // TTL helpers
5
+ // ---------------------------------------------------------------------------
6
+ const DEFAULT_SESSION_TTL_SECONDS = 60 * 60 * 24 * 7; // 7 days
7
+ function getSessionTtlSeconds(cfg) {
8
+ return (cfg ?? DEFAULT_AUTH_CONFIG).sessionPolicy.absoluteTimeout ?? DEFAULT_SESSION_TTL_SECONDS;
9
+ }
10
+ function getSessionTtlMs(cfg) {
11
+ return getSessionTtlSeconds(cfg) * 1000;
12
+ }
13
+ function shouldPersistSessionMetadata(cfg) {
14
+ return (cfg ?? DEFAULT_AUTH_CONFIG).persistSessionMetadata;
15
+ }
16
+ function isIdleExpired(lastActiveAt, cfg) {
17
+ const idleTimeout = (cfg ?? DEFAULT_AUTH_CONFIG).sessionPolicy.idleTimeout;
18
+ if (!idleTimeout)
19
+ return false;
20
+ const idleSecs = (Date.now() - lastActiveAt) / 1000;
21
+ return idleSecs > idleTimeout;
22
+ }
23
+ export function createMemorySessionRepository() {
24
+ const sessions = new Map();
25
+ const userSessionIds = new Map();
26
+ const refreshTokenIndex = new Map();
27
+ function removeUserSessionId(userId, sessionId) {
28
+ const ids = userSessionIds.get(userId);
29
+ if (!ids)
30
+ return;
31
+ ids.delete(sessionId);
32
+ if (ids.size === 0) {
33
+ userSessionIds.delete(userId);
34
+ }
35
+ }
36
+ function purgeSessionImpl(sessionId) {
37
+ const entry = sessions.get(sessionId);
38
+ if (!entry)
39
+ return;
40
+ if (entry.refreshToken)
41
+ refreshTokenIndex.delete(entry.refreshToken);
42
+ if (entry.prevRefreshToken)
43
+ refreshTokenIndex.delete(entry.prevRefreshToken);
44
+ sessions.delete(sessionId);
45
+ removeUserSessionId(entry.userId, sessionId);
46
+ }
47
+ // Purge tombstoned sessions (token === null) whose natural TTL has passed.
48
+ // Called opportunistically on delete and on new-session creation so expired
49
+ // tombstones do not accumulate indefinitely in the in-memory dev store.
50
+ function sweepExpiredTombstones() {
51
+ const now = Date.now();
52
+ for (const [sessionId, s] of sessions) {
53
+ if (!s.token && s.expiresAt <= now) {
54
+ purgeSessionImpl(sessionId);
55
+ }
56
+ }
57
+ }
58
+ function deleteSessionImpl(sessionId, cfg) {
59
+ const entry = sessions.get(sessionId);
60
+ if (!entry)
61
+ return;
62
+ if (shouldPersistSessionMetadata(cfg)) {
63
+ if (entry.refreshToken)
64
+ refreshTokenIndex.delete(entry.refreshToken);
65
+ if (entry.prevRefreshToken)
66
+ refreshTokenIndex.delete(entry.prevRefreshToken);
67
+ entry.token = null;
68
+ entry.refreshToken = null;
69
+ entry.prevRefreshToken = null;
70
+ entry.prevTokenExpiresAt = null;
71
+ entry.refreshTokenPlain = null;
72
+ sweepExpiredTombstones();
73
+ }
74
+ else {
75
+ purgeSessionImpl(sessionId);
76
+ }
77
+ }
78
+ function trimSessionsToCapacity() {
79
+ sweepExpiredTombstones();
80
+ while (sessions.size >= DEFAULT_MAX_ENTRIES) {
81
+ const oldestSessionId = sessions.keys().next().value;
82
+ if (oldestSessionId === undefined)
83
+ break;
84
+ purgeSessionImpl(oldestSessionId);
85
+ }
86
+ }
87
+ function createSessionImpl(userId, token, sessionId, metadata, cfg) {
88
+ const now = Date.now();
89
+ const session = {
90
+ sessionId,
91
+ userId,
92
+ token,
93
+ createdAt: now,
94
+ lastActiveAt: now,
95
+ expiresAt: now + getSessionTtlMs(cfg),
96
+ ipAddress: metadata?.ipAddress,
97
+ userAgent: metadata?.userAgent,
98
+ };
99
+ trimSessionsToCapacity();
100
+ sessions.set(sessionId, session);
101
+ if (!userSessionIds.has(userId))
102
+ userSessionIds.set(userId, new Set());
103
+ userSessionIds.get(userId).add(sessionId);
104
+ }
105
+ return {
106
+ async createSession(userId, token, sessionId, metadata, cfg) {
107
+ createSessionImpl(userId, token, sessionId, metadata, cfg);
108
+ },
109
+ async atomicCreateSession(userId, token, sessionId, maxSessions, metadata, cfg) {
110
+ const now = Date.now();
111
+ const ids = userSessionIds.get(userId);
112
+ if (ids) {
113
+ let activeCount = 0;
114
+ let oldest = null;
115
+ for (const sid of ids) {
116
+ const s = sessions.get(sid);
117
+ if (s && s.token && s.expiresAt > now) {
118
+ activeCount++;
119
+ if (!oldest || s.createdAt < oldest.createdAt)
120
+ oldest = s;
121
+ }
122
+ }
123
+ while (activeCount >= maxSessions && oldest) {
124
+ deleteSessionImpl(oldest.sessionId, cfg);
125
+ activeCount--;
126
+ oldest = null;
127
+ for (const sid of ids) {
128
+ const s = sessions.get(sid);
129
+ if (s && s.token && s.expiresAt > now) {
130
+ if (!oldest || s.createdAt < oldest.createdAt)
131
+ oldest = s;
132
+ }
133
+ }
134
+ }
135
+ }
136
+ createSessionImpl(userId, token, sessionId, metadata, cfg);
137
+ },
138
+ async getSession(sessionId, cfg) {
139
+ const entry = sessions.get(sessionId);
140
+ if (!entry || !entry.token || entry.expiresAt <= Date.now())
141
+ return null;
142
+ if (isIdleExpired(entry.lastActiveAt, cfg)) {
143
+ deleteSessionImpl(sessionId, cfg);
144
+ return null;
145
+ }
146
+ return entry.token;
147
+ },
148
+ async deleteSession(sessionId, cfg) {
149
+ deleteSessionImpl(sessionId, cfg);
150
+ },
151
+ async getUserSessions(userId, cfg) {
152
+ const ids = userSessionIds.get(userId);
153
+ if (!ids)
154
+ return [];
155
+ const now = Date.now();
156
+ const config = cfg ?? DEFAULT_AUTH_CONFIG;
157
+ const includeInactive = config.includeInactiveSessions;
158
+ const persist = config.persistSessionMetadata;
159
+ const results = [];
160
+ for (const sessionId of ids) {
161
+ const s = sessions.get(sessionId);
162
+ if (!s)
163
+ continue;
164
+ const isActive = !!s.token && s.expiresAt > now;
165
+ if (!isActive && !persist)
166
+ continue;
167
+ if (!isActive && !includeInactive)
168
+ continue;
169
+ results.push({
170
+ sessionId: s.sessionId,
171
+ createdAt: s.createdAt,
172
+ lastActiveAt: s.lastActiveAt,
173
+ expiresAt: s.expiresAt,
174
+ ipAddress: s.ipAddress,
175
+ userAgent: s.userAgent,
176
+ isActive,
177
+ });
178
+ }
179
+ return results;
180
+ },
181
+ async getActiveSessionCount(userId) {
182
+ const ids = userSessionIds.get(userId);
183
+ if (!ids)
184
+ return 0;
185
+ const now = Date.now();
186
+ let count = 0;
187
+ for (const sessionId of ids) {
188
+ const s = sessions.get(sessionId);
189
+ if (s && s.token && s.expiresAt > now)
190
+ count++;
191
+ }
192
+ return count;
193
+ },
194
+ async evictOldestSession(userId, cfg) {
195
+ const ids = userSessionIds.get(userId);
196
+ if (!ids)
197
+ return;
198
+ const now = Date.now();
199
+ let oldest = null;
200
+ for (const sessionId of ids) {
201
+ const s = sessions.get(sessionId);
202
+ if (!s || !s.token || s.expiresAt <= now)
203
+ continue;
204
+ if (!oldest || s.createdAt < oldest.createdAt)
205
+ oldest = s;
206
+ }
207
+ if (oldest)
208
+ deleteSessionImpl(oldest.sessionId, cfg);
209
+ },
210
+ async updateSessionLastActive(sessionId) {
211
+ const entry = sessions.get(sessionId);
212
+ if (entry)
213
+ entry.lastActiveAt = Date.now();
214
+ },
215
+ async setRefreshToken(sessionId, refreshToken) {
216
+ const entry = sessions.get(sessionId);
217
+ if (!entry)
218
+ return;
219
+ const tokenHash = hashToken(refreshToken);
220
+ if (entry.refreshToken && entry.refreshToken !== tokenHash) {
221
+ refreshTokenIndex.delete(entry.refreshToken);
222
+ }
223
+ entry.refreshToken = tokenHash;
224
+ refreshTokenIndex.set(tokenHash, sessionId);
225
+ },
226
+ async getSessionByRefreshToken(refreshToken, cfg) {
227
+ const tokenHash = hashToken(refreshToken);
228
+ const sessionId = refreshTokenIndex.get(tokenHash);
229
+ if (!sessionId)
230
+ return null;
231
+ const entry = sessions.get(sessionId);
232
+ if (!entry)
233
+ return null;
234
+ if (isIdleExpired(entry.lastActiveAt, cfg)) {
235
+ deleteSessionImpl(sessionId, cfg);
236
+ return null;
237
+ }
238
+ if (entry.refreshToken && timingSafeEqual(entry.refreshToken, tokenHash)) {
239
+ return { sessionId: entry.sessionId, userId: entry.userId, newRefreshToken: refreshToken };
240
+ }
241
+ if (entry.prevRefreshToken &&
242
+ timingSafeEqual(entry.prevRefreshToken, tokenHash) &&
243
+ entry.prevTokenExpiresAt &&
244
+ entry.prevTokenExpiresAt > Date.now()) {
245
+ return {
246
+ sessionId: entry.sessionId,
247
+ userId: entry.userId,
248
+ newRefreshToken: entry.refreshTokenPlain ?? entry.refreshToken,
249
+ };
250
+ }
251
+ if (entry.prevRefreshToken && timingSafeEqual(entry.prevRefreshToken, tokenHash)) {
252
+ deleteSessionImpl(sessionId, cfg);
253
+ return null;
254
+ }
255
+ return null;
256
+ },
257
+ async rotateRefreshToken(sessionId, newRefreshToken, newAccessToken, cfg) {
258
+ const entry = sessions.get(sessionId);
259
+ if (!entry)
260
+ return;
261
+ const graceSeconds = (cfg ?? DEFAULT_AUTH_CONFIG).refreshToken?.rotationGraceSeconds ?? 30;
262
+ const newHash = hashToken(newRefreshToken);
263
+ const oldHash = entry.refreshToken;
264
+ if (entry.prevRefreshToken && entry.prevRefreshToken !== oldHash) {
265
+ refreshTokenIndex.delete(entry.prevRefreshToken);
266
+ }
267
+ entry.prevRefreshToken = oldHash;
268
+ entry.prevTokenExpiresAt = Date.now() + graceSeconds * 1000;
269
+ entry.refreshToken = newHash;
270
+ entry.refreshTokenPlain = newRefreshToken;
271
+ entry.token = newAccessToken;
272
+ refreshTokenIndex.set(newHash, sessionId);
273
+ },
274
+ async getSessionFingerprint(sessionId) {
275
+ return sessions.get(sessionId)?.fingerprint ?? null;
276
+ },
277
+ async setSessionFingerprint(sessionId, fingerprint) {
278
+ const entry = sessions.get(sessionId);
279
+ if (entry)
280
+ entry.fingerprint = fingerprint;
281
+ },
282
+ async setMfaVerifiedAt(sessionId) {
283
+ const entry = sessions.get(sessionId);
284
+ if (entry)
285
+ entry.mfaVerifiedAt = Math.floor(Date.now() / 1000);
286
+ },
287
+ async getMfaVerifiedAt(sessionId) {
288
+ return sessions.get(sessionId)?.mfaVerifiedAt ?? null;
289
+ },
290
+ };
291
+ }
292
+ // ---------------------------------------------------------------------------
293
+ // SQLite repository factory
294
+ // ---------------------------------------------------------------------------
295
+ export function createSqliteSessionRepository(db) {
296
+ let initialized = false;
297
+ function init() {
298
+ if (initialized)
299
+ return;
300
+ // Sessions table is created by sqliteAuth adapter's initSchema.
301
+ // Only create if it doesn't exist (standalone usage).
302
+ db.run(`CREATE TABLE IF NOT EXISTS sessions (
303
+ sessionId TEXT PRIMARY KEY,
304
+ userId TEXT NOT NULL,
305
+ token TEXT,
306
+ createdAt INTEGER NOT NULL,
307
+ lastActiveAt INTEGER NOT NULL,
308
+ expiresAt INTEGER NOT NULL,
309
+ ipAddress TEXT,
310
+ userAgent TEXT,
311
+ refreshToken TEXT,
312
+ prevRefreshToken TEXT,
313
+ prevTokenExpiresAt INTEGER,
314
+ fingerprint TEXT,
315
+ mfaVerifiedAt INTEGER,
316
+ refreshTokenPlain TEXT
317
+ )`);
318
+ db.run('CREATE INDEX IF NOT EXISTS idx_sessions_userId ON sessions(userId)');
319
+ db.run('CREATE UNIQUE INDEX IF NOT EXISTS idx_sessions_refreshToken ON sessions(refreshToken) WHERE refreshToken IS NOT NULL');
320
+ initialized = true;
321
+ }
322
+ function deleteSessionImpl(sessionId, cfg) {
323
+ init();
324
+ if ((cfg ?? DEFAULT_AUTH_CONFIG).persistSessionMetadata) {
325
+ db.run('UPDATE sessions SET token = NULL, refreshToken = NULL, prevRefreshToken = NULL, prevTokenExpiresAt = NULL WHERE sessionId = ?', [sessionId]);
326
+ }
327
+ else {
328
+ db.run('DELETE FROM sessions WHERE sessionId = ?', [sessionId]);
329
+ }
330
+ }
331
+ return {
332
+ async createSession(userId, token, sessionId, metadata, cfg) {
333
+ init();
334
+ const now = Date.now();
335
+ const expiresAt = now + getSessionTtlMs(cfg);
336
+ db.run('INSERT INTO sessions (sessionId, userId, token, createdAt, lastActiveAt, expiresAt, ipAddress, userAgent) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [
337
+ sessionId,
338
+ userId,
339
+ token,
340
+ now,
341
+ now,
342
+ expiresAt,
343
+ metadata?.ipAddress ?? null,
344
+ metadata?.userAgent ?? null,
345
+ ]);
346
+ },
347
+ async atomicCreateSession(userId, token, sessionId, maxSessions, metadata, cfg) {
348
+ init();
349
+ const now = Date.now();
350
+ const ttlMs = getSessionTtlMs(cfg);
351
+ const expiresAt = now + ttlMs;
352
+ db.transaction(() => {
353
+ const countRow = db
354
+ .query('SELECT COUNT(*) AS count FROM sessions WHERE userId = ? AND token IS NOT NULL AND expiresAt > ?')
355
+ .get(userId, now);
356
+ let activeCount = countRow?.count ?? 0;
357
+ while (activeCount >= maxSessions) {
358
+ const oldest = db
359
+ .query('SELECT sessionId FROM sessions WHERE userId = ? AND token IS NOT NULL AND expiresAt > ? ORDER BY createdAt ASC LIMIT 1')
360
+ .get(userId, now);
361
+ if (!oldest)
362
+ break;
363
+ deleteSessionImpl(oldest.sessionId, cfg);
364
+ activeCount--;
365
+ }
366
+ db.run('INSERT INTO sessions (sessionId, userId, token, createdAt, lastActiveAt, expiresAt, ipAddress, userAgent) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [
367
+ sessionId,
368
+ userId,
369
+ token,
370
+ now,
371
+ now,
372
+ expiresAt,
373
+ metadata?.ipAddress ?? null,
374
+ metadata?.userAgent ?? null,
375
+ ]);
376
+ })();
377
+ },
378
+ async getSession(sessionId, cfg) {
379
+ init();
380
+ const row = db
381
+ .query('SELECT token, lastActiveAt FROM sessions WHERE sessionId = ? AND expiresAt > ?')
382
+ .get(sessionId, Date.now());
383
+ if (!row || !row.token)
384
+ return null;
385
+ if (isIdleExpired(row.lastActiveAt, cfg)) {
386
+ deleteSessionImpl(sessionId, cfg);
387
+ return null;
388
+ }
389
+ return row.token;
390
+ },
391
+ async deleteSession(sessionId, cfg) {
392
+ deleteSessionImpl(sessionId, cfg);
393
+ },
394
+ async getUserSessions(userId, cfg) {
395
+ init();
396
+ const now = Date.now();
397
+ const rows = db
398
+ .query('SELECT sessionId, token, createdAt, lastActiveAt, expiresAt, ipAddress, userAgent FROM sessions WHERE userId = ? ORDER BY createdAt ASC')
399
+ .all(userId);
400
+ const config = cfg ?? DEFAULT_AUTH_CONFIG;
401
+ const includeInactive = config.includeInactiveSessions;
402
+ const persist = config.persistSessionMetadata;
403
+ const results = [];
404
+ for (const row of rows) {
405
+ const isActive = !!row.token && row.expiresAt > now;
406
+ if (!isActive && !persist)
407
+ continue;
408
+ if (!isActive && !includeInactive)
409
+ continue;
410
+ results.push({
411
+ sessionId: row.sessionId,
412
+ createdAt: row.createdAt,
413
+ lastActiveAt: row.lastActiveAt,
414
+ expiresAt: row.expiresAt,
415
+ ipAddress: row.ipAddress ?? undefined,
416
+ userAgent: row.userAgent ?? undefined,
417
+ isActive,
418
+ });
419
+ }
420
+ return results;
421
+ },
422
+ async getActiveSessionCount(userId) {
423
+ init();
424
+ const row = db
425
+ .query('SELECT COUNT(*) AS count FROM sessions WHERE userId = ? AND token IS NOT NULL AND expiresAt > ?')
426
+ .get(userId, Date.now());
427
+ return row?.count ?? 0;
428
+ },
429
+ async evictOldestSession(userId, cfg) {
430
+ init();
431
+ const now = Date.now();
432
+ const oldest = db
433
+ .query('SELECT sessionId FROM sessions WHERE userId = ? AND token IS NOT NULL AND expiresAt > ? ORDER BY createdAt ASC LIMIT 1')
434
+ .get(userId, now);
435
+ if (oldest)
436
+ deleteSessionImpl(oldest.sessionId, cfg);
437
+ },
438
+ async updateSessionLastActive(sessionId) {
439
+ init();
440
+ db.run('UPDATE sessions SET lastActiveAt = ? WHERE sessionId = ?', [Date.now(), sessionId]);
441
+ },
442
+ async setRefreshToken(sessionId, refreshToken) {
443
+ init();
444
+ const tokenHash = hashToken(refreshToken);
445
+ db.run('UPDATE sessions SET refreshToken = ? WHERE sessionId = ?', [tokenHash, sessionId]);
446
+ },
447
+ async getSessionByRefreshToken(refreshToken, cfg) {
448
+ init();
449
+ const tokenHash = hashToken(refreshToken);
450
+ let row = db
451
+ .query('SELECT sessionId, userId, refreshToken, lastActiveAt FROM sessions WHERE refreshToken = ?')
452
+ .get(tokenHash);
453
+ if (row) {
454
+ if (isIdleExpired(row.lastActiveAt, cfg)) {
455
+ deleteSessionImpl(row.sessionId, cfg);
456
+ return null;
457
+ }
458
+ return { sessionId: row.sessionId, userId: row.userId, newRefreshToken: refreshToken };
459
+ }
460
+ const graceRow = db
461
+ .query('SELECT sessionId, userId, refreshToken, refreshTokenPlain, prevTokenExpiresAt, lastActiveAt FROM sessions WHERE prevRefreshToken = ?')
462
+ .get(tokenHash);
463
+ if (!graceRow)
464
+ return null;
465
+ if (isIdleExpired(graceRow.lastActiveAt, cfg)) {
466
+ deleteSessionImpl(graceRow.sessionId, cfg);
467
+ return null;
468
+ }
469
+ if (graceRow.prevTokenExpiresAt && graceRow.prevTokenExpiresAt > Date.now()) {
470
+ return {
471
+ sessionId: graceRow.sessionId,
472
+ userId: graceRow.userId,
473
+ newRefreshToken: graceRow.refreshTokenPlain ?? graceRow.refreshToken,
474
+ };
475
+ }
476
+ deleteSessionImpl(graceRow.sessionId, cfg);
477
+ return null;
478
+ },
479
+ async rotateRefreshToken(sessionId, newRefreshToken, newAccessToken, cfg) {
480
+ init();
481
+ const graceSeconds = (cfg ?? DEFAULT_AUTH_CONFIG).refreshToken?.rotationGraceSeconds ?? 30;
482
+ const prevTokenExpiresAt = Date.now() + graceSeconds * 1000;
483
+ const newHash = hashToken(newRefreshToken);
484
+ db.run('UPDATE sessions SET prevRefreshToken = refreshToken, prevTokenExpiresAt = ?, refreshToken = ?, refreshTokenPlain = ?, token = ? WHERE sessionId = ?', [prevTokenExpiresAt, newHash, newRefreshToken, newAccessToken, sessionId]);
485
+ },
486
+ async getSessionFingerprint(sessionId) {
487
+ init();
488
+ const row = db
489
+ .query('SELECT fingerprint FROM sessions WHERE sessionId = ?')
490
+ .get(sessionId);
491
+ return row?.fingerprint ?? null;
492
+ },
493
+ async setSessionFingerprint(sessionId, fingerprint) {
494
+ init();
495
+ db.run('UPDATE sessions SET fingerprint = ? WHERE sessionId = ?', [fingerprint, sessionId]);
496
+ },
497
+ async setMfaVerifiedAt(sessionId) {
498
+ init();
499
+ const now = Math.floor(Date.now() / 1000);
500
+ db.run('UPDATE sessions SET mfaVerifiedAt = ? WHERE sessionId = ?', [now, sessionId]);
501
+ },
502
+ async getMfaVerifiedAt(sessionId) {
503
+ init();
504
+ const row = db
505
+ .query('SELECT mfaVerifiedAt FROM sessions WHERE sessionId = ?')
506
+ .get(sessionId);
507
+ return row?.mfaVerifiedAt ?? null;
508
+ },
509
+ };
510
+ }
511
+ // ---------------------------------------------------------------------------
512
+ // Redis repository factory
513
+ // ---------------------------------------------------------------------------
514
+ export function createRedisSessionRepository(getRedis, appName) {
515
+ function sessionKey(sessionId) {
516
+ return `session:${appName}:${sessionId}`;
517
+ }
518
+ function userSessionsKey(userId) {
519
+ return `usersessions:${appName}:${userId}`;
520
+ }
521
+ function refreshTokenKey(refreshToken) {
522
+ return `refreshtoken:${appName}:${refreshToken}`;
523
+ }
524
+ // Lua script: atomic session field update
525
+ const UPDATE_FIELD_LUA = `
526
+ local key = KEYS[1]
527
+ local field = ARGV[1]
528
+ local value = ARGV[2]
529
+ local valueType = ARGV[3]
530
+ local persist = ARGV[4] == "1"
531
+
532
+ local raw = redis.call('GET', key)
533
+ if not raw then return 0 end
534
+ local rec = cjson.decode(raw)
535
+ if valueType == "number" then
536
+ rec[field] = tonumber(value)
537
+ else
538
+ rec[field] = value
539
+ end
540
+ if persist then
541
+ redis.call('SET', key, cjson.encode(rec))
542
+ else
543
+ local ttl = redis.call('PTTL', key)
544
+ if ttl > 0 then
545
+ redis.call('SET', key, cjson.encode(rec), 'PX', ttl)
546
+ else
547
+ redis.call('SET', key, cjson.encode(rec))
548
+ end
549
+ end
550
+ return 1
551
+ `;
552
+ const WRITE_SESSION_LUA = `
553
+ local key = KEYS[1]
554
+ local rawJson = ARGV[1]
555
+ local persist = ARGV[2] == "1"
556
+
557
+ if persist then
558
+ redis.call('SET', key, rawJson)
559
+ else
560
+ local ttl = redis.call('PTTL', key)
561
+ if ttl > 0 then
562
+ redis.call('SET', key, rawJson, 'PX', ttl)
563
+ else
564
+ redis.call('SET', key, rawJson)
565
+ end
566
+ end
567
+ return 1
568
+ `;
569
+ // Lua script: atomic session creation
570
+ const ATOMIC_CREATE_SESSION_LUA = `
571
+ local userSessionsKey = KEYS[1]
572
+ local newSessionKey = KEYS[2]
573
+ local maxSessions = tonumber(ARGV[1])
574
+ local sessionId = ARGV[2]
575
+ local sessionJson = ARGV[3]
576
+ local createdAt = tonumber(ARGV[4])
577
+ local ttlSeconds = tonumber(ARGV[5])
578
+ local persist = ARGV[6] == "1"
579
+
580
+ local members = redis.call('ZRANGE', userSessionsKey, 0, -1)
581
+
582
+ local activeCount = 0
583
+ local activeSessions = {}
584
+ for i, sid in ipairs(members) do
585
+ local keyPrefix = ARGV[7]
586
+ local sKey = keyPrefix .. sid
587
+ local raw = redis.call('GET', sKey)
588
+ if raw then
589
+ local rec = cjson.decode(raw)
590
+ if rec.token and rec.expiresAt > createdAt then
591
+ activeCount = activeCount + 1
592
+ table.insert(activeSessions, { sid = sid, key = sKey, createdAt = rec.createdAt })
593
+ end
594
+ else
595
+ redis.call('ZREM', userSessionsKey, sid)
596
+ end
597
+ end
598
+
599
+ table.sort(activeSessions, function(a, b) return a.createdAt < b.createdAt end)
600
+
601
+ local evicted = 0
602
+ while activeCount >= maxSessions and evicted < #activeSessions do
603
+ evicted = evicted + 1
604
+ local victim = activeSessions[evicted]
605
+ redis.call('DEL', victim.key)
606
+ redis.call('ZREM', userSessionsKey, victim.sid)
607
+ activeCount = activeCount - 1
608
+ end
609
+
610
+ if persist then
611
+ redis.call('SET', newSessionKey, sessionJson)
612
+ else
613
+ redis.call('SET', newSessionKey, sessionJson, 'EX', ttlSeconds)
614
+ end
615
+ redis.call('ZADD', userSessionsKey, createdAt, sessionId)
616
+
617
+ return evicted
618
+ `;
619
+ async function updateSessionField(sessionId, field, value, persist, cfg) {
620
+ const redis = getRedis();
621
+ const key = sessionKey(sessionId);
622
+ const valueType = typeof value === 'number' ? 'number' : 'string';
623
+ const persistFlag = (persist ?? (cfg ?? DEFAULT_AUTH_CONFIG).persistSessionMetadata) ? '1' : '0';
624
+ const result = await redis.eval(UPDATE_FIELD_LUA, 1, key, field, String(value), valueType, persistFlag);
625
+ return result === 1;
626
+ }
627
+ async function writeSessionRecord(sessionId, record, cfg) {
628
+ const redis = getRedis();
629
+ const persistFlag = shouldPersistSessionMetadata(cfg) ? '1' : '0';
630
+ await redis.eval(WRITE_SESSION_LUA, 1, sessionKey(sessionId), JSON.stringify(record), persistFlag);
631
+ }
632
+ async function deleteSessionImpl(sessionId, cfg) {
633
+ const c = cfg ?? DEFAULT_AUTH_CONFIG;
634
+ const redis = getRedis();
635
+ const raw = await redis.get(sessionKey(sessionId));
636
+ if (!raw)
637
+ return;
638
+ const rec = JSON.parse(raw);
639
+ const persist = c.persistSessionMetadata;
640
+ if (rec.refreshToken)
641
+ await redis.del(refreshTokenKey(rec.refreshToken));
642
+ if (rec.prevRefreshToken)
643
+ await redis.del(refreshTokenKey(rec.prevRefreshToken));
644
+ if (persist) {
645
+ const updated = {
646
+ ...rec,
647
+ token: null,
648
+ refreshToken: null,
649
+ prevRefreshToken: null,
650
+ prevTokenExpiresAt: null,
651
+ };
652
+ await redis.set(sessionKey(sessionId), JSON.stringify(updated));
653
+ }
654
+ else {
655
+ await redis.del(sessionKey(sessionId));
656
+ }
657
+ if (!persist) {
658
+ await redis.zrem(userSessionsKey(rec.userId), sessionId);
659
+ }
660
+ }
661
+ async function getUserSessionsImpl(userId, cfg) {
662
+ const c = cfg ?? DEFAULT_AUTH_CONFIG;
663
+ const redis = getRedis();
664
+ const sessionIds = await redis.zrange(userSessionsKey(userId), 0, -1);
665
+ if (!sessionIds.length)
666
+ return [];
667
+ const now = Date.now();
668
+ const raws = await redis.mget(...sessionIds.map(sessionKey));
669
+ const results = [];
670
+ const toRemove = [];
671
+ for (let i = 0; i < sessionIds.length; i++) {
672
+ const raw = raws[i];
673
+ if (!raw) {
674
+ toRemove.push(sessionIds[i]);
675
+ continue;
676
+ }
677
+ const rec = JSON.parse(raw);
678
+ const isActive = !!rec.token && rec.expiresAt > now;
679
+ if (!isActive && !c.persistSessionMetadata) {
680
+ toRemove.push(sessionIds[i]);
681
+ continue;
682
+ }
683
+ if (!isActive && !c.includeInactiveSessions)
684
+ continue;
685
+ results.push({
686
+ sessionId: rec.sessionId,
687
+ createdAt: Number(rec.createdAt),
688
+ lastActiveAt: Number(rec.lastActiveAt),
689
+ expiresAt: Number(rec.expiresAt),
690
+ ipAddress: rec.ipAddress,
691
+ userAgent: rec.userAgent,
692
+ isActive,
693
+ });
694
+ }
695
+ if (toRemove.length) {
696
+ await redis.zrem(userSessionsKey(userId), ...toRemove);
697
+ }
698
+ return results;
699
+ }
700
+ return {
701
+ async createSession(userId, token, sessionId, metadata, cfg) {
702
+ const c = cfg ?? DEFAULT_AUTH_CONFIG;
703
+ const now = Date.now();
704
+ const ttlSeconds = getSessionTtlSeconds(c);
705
+ const expiresAt = now + getSessionTtlMs(c);
706
+ const record = JSON.stringify({
707
+ sessionId,
708
+ userId,
709
+ token,
710
+ createdAt: now,
711
+ lastActiveAt: now,
712
+ expiresAt,
713
+ ipAddress: metadata?.ipAddress,
714
+ userAgent: metadata?.userAgent,
715
+ });
716
+ const redis = getRedis();
717
+ const persist = c.persistSessionMetadata;
718
+ if (persist) {
719
+ await redis.set(sessionKey(sessionId), record);
720
+ }
721
+ else {
722
+ await redis.set(sessionKey(sessionId), record, 'EX', ttlSeconds);
723
+ }
724
+ await redis.zadd(userSessionsKey(userId), now, sessionId);
725
+ },
726
+ async atomicCreateSession(userId, token, sessionId, maxSessions, metadata, cfg) {
727
+ const c = cfg ?? DEFAULT_AUTH_CONFIG;
728
+ const now = Date.now();
729
+ const ttlSeconds = getSessionTtlSeconds(c);
730
+ const expiresAt = now + getSessionTtlMs(c);
731
+ const record = JSON.stringify({
732
+ sessionId,
733
+ userId,
734
+ token,
735
+ createdAt: now,
736
+ lastActiveAt: now,
737
+ expiresAt,
738
+ ipAddress: metadata?.ipAddress,
739
+ userAgent: metadata?.userAgent,
740
+ });
741
+ const redis = getRedis();
742
+ const persist = c.persistSessionMetadata;
743
+ const sessionKeyPrefix = `session:${appName}:`;
744
+ await redis.eval(ATOMIC_CREATE_SESSION_LUA, 2, userSessionsKey(userId), sessionKey(sessionId), maxSessions, sessionId, record, now, ttlSeconds, persist ? '1' : '0', sessionKeyPrefix);
745
+ },
746
+ async getSession(sessionId, cfg) {
747
+ const raw = await getRedis().get(sessionKey(sessionId));
748
+ if (!raw)
749
+ return null;
750
+ const rec = JSON.parse(raw);
751
+ if (!rec.token)
752
+ return null;
753
+ if (rec.expiresAt <= Date.now())
754
+ return null;
755
+ if (typeof rec.lastActiveAt === 'number' && isIdleExpired(rec.lastActiveAt, cfg)) {
756
+ await deleteSessionImpl(sessionId, cfg);
757
+ return null;
758
+ }
759
+ return rec.token;
760
+ },
761
+ async deleteSession(sessionId, cfg) {
762
+ await deleteSessionImpl(sessionId, cfg);
763
+ },
764
+ async getUserSessions(userId, cfg) {
765
+ return getUserSessionsImpl(userId, cfg);
766
+ },
767
+ async getActiveSessionCount(userId, cfg) {
768
+ const sessions = await getUserSessionsImpl(userId, cfg);
769
+ return sessions.filter(s => s.isActive).length;
770
+ },
771
+ async evictOldestSession(userId, cfg) {
772
+ const redis = getRedis();
773
+ const sessionIds = await redis.zrange(userSessionsKey(userId), 0, -1);
774
+ const now = Date.now();
775
+ for (const sid of sessionIds) {
776
+ const raw = await redis.get(sessionKey(sid));
777
+ if (!raw) {
778
+ await redis.zrem(userSessionsKey(userId), sid);
779
+ continue;
780
+ }
781
+ const rec = JSON.parse(raw);
782
+ if (rec.token && rec.expiresAt > now) {
783
+ await deleteSessionImpl(sid, cfg);
784
+ return;
785
+ }
786
+ }
787
+ },
788
+ async updateSessionLastActive(sessionId, cfg) {
789
+ const c = cfg ?? DEFAULT_AUTH_CONFIG;
790
+ const now = Date.now();
791
+ const updated = await updateSessionField(sessionId, 'lastActiveAt', now, undefined, c);
792
+ if (!updated)
793
+ return;
794
+ if (!c.persistSessionMetadata) {
795
+ const redis = getRedis();
796
+ const raw = await redis.get(sessionKey(sessionId));
797
+ if (raw) {
798
+ const rec = JSON.parse(raw);
799
+ if (rec.expiresAt <= now) {
800
+ await deleteSessionImpl(sessionId, c);
801
+ }
802
+ }
803
+ }
804
+ },
805
+ async setRefreshToken(sessionId, refreshToken, cfg) {
806
+ const redis = getRedis();
807
+ const raw = await redis.get(sessionKey(sessionId));
808
+ if (!raw)
809
+ return;
810
+ const rec = JSON.parse(raw);
811
+ const tokenHash = hashToken(refreshToken);
812
+ const oldHash = typeof rec.refreshToken === 'string' ? rec.refreshToken : null;
813
+ rec.refreshToken = tokenHash;
814
+ const refreshExpiry = (cfg ?? DEFAULT_AUTH_CONFIG).refreshToken?.refreshTokenExpiry ?? 2_592_000;
815
+ await writeSessionRecord(sessionId, rec, cfg);
816
+ if (oldHash && oldHash !== tokenHash) {
817
+ await redis.del(refreshTokenKey(oldHash));
818
+ }
819
+ await redis.set(refreshTokenKey(tokenHash), sessionId, 'EX', refreshExpiry);
820
+ },
821
+ async getSessionByRefreshToken(refreshToken, cfg) {
822
+ const redis = getRedis();
823
+ const tokenHash = hashToken(refreshToken);
824
+ const sessionId = await redis.get(refreshTokenKey(tokenHash));
825
+ if (!sessionId)
826
+ return null;
827
+ const raw = await redis.get(sessionKey(sessionId));
828
+ if (!raw)
829
+ return null;
830
+ const rec = JSON.parse(raw);
831
+ if (typeof rec.lastActiveAt === 'number' && isIdleExpired(rec.lastActiveAt, cfg)) {
832
+ await deleteSessionImpl(sessionId, cfg);
833
+ return null;
834
+ }
835
+ if (timingSafeEqual(rec.refreshToken ?? '', tokenHash)) {
836
+ return { sessionId: rec.sessionId, userId: rec.userId, newRefreshToken: refreshToken };
837
+ }
838
+ if (timingSafeEqual(rec.prevRefreshToken ?? '', tokenHash) &&
839
+ rec.prevTokenExpiresAt &&
840
+ rec.prevTokenExpiresAt > Date.now()) {
841
+ return {
842
+ sessionId: rec.sessionId,
843
+ userId: rec.userId,
844
+ newRefreshToken: rec.refreshTokenPlain ?? rec.refreshToken,
845
+ };
846
+ }
847
+ if (timingSafeEqual(rec.prevRefreshToken ?? '', tokenHash)) {
848
+ await deleteSessionImpl(sessionId, cfg);
849
+ return null;
850
+ }
851
+ return null;
852
+ },
853
+ async rotateRefreshToken(sessionId, newRefreshToken, newAccessToken, cfg) {
854
+ const c = cfg ?? DEFAULT_AUTH_CONFIG;
855
+ const redis = getRedis();
856
+ const raw = await redis.get(sessionKey(sessionId));
857
+ if (!raw)
858
+ return;
859
+ const rec = JSON.parse(raw);
860
+ const graceSeconds = c.refreshToken?.rotationGraceSeconds ?? 30;
861
+ const refreshExpiry = c.refreshToken?.refreshTokenExpiry ?? 2_592_000;
862
+ const newHash = hashToken(newRefreshToken);
863
+ const oldHash = rec.refreshToken;
864
+ const oldPrevHash = rec.prevRefreshToken;
865
+ rec.prevRefreshToken = oldHash;
866
+ rec.prevTokenExpiresAt = Date.now() + graceSeconds * 1000;
867
+ rec.refreshToken = newHash;
868
+ rec.refreshTokenPlain = newRefreshToken;
869
+ rec.token = newAccessToken;
870
+ await writeSessionRecord(sessionId, rec, c);
871
+ await redis.set(refreshTokenKey(newHash), sessionId, 'EX', refreshExpiry);
872
+ if (oldPrevHash && oldPrevHash !== oldHash) {
873
+ await redis.del(refreshTokenKey(oldPrevHash));
874
+ }
875
+ if (oldHash) {
876
+ const oldKeyTtl = Math.max(graceSeconds, 60);
877
+ await redis.expire(refreshTokenKey(oldHash), oldKeyTtl);
878
+ }
879
+ },
880
+ async getSessionFingerprint(sessionId) {
881
+ const redis = getRedis();
882
+ const raw = await redis.get(sessionKey(sessionId));
883
+ if (!raw)
884
+ return null;
885
+ const rec = JSON.parse(raw);
886
+ return rec.fingerprint ?? null;
887
+ },
888
+ async setSessionFingerprint(sessionId, fingerprint) {
889
+ await updateSessionField(sessionId, 'fingerprint', fingerprint);
890
+ },
891
+ async setMfaVerifiedAt(sessionId) {
892
+ const now = Math.floor(Date.now() / 1000);
893
+ await updateSessionField(sessionId, 'mfaVerifiedAt', now);
894
+ },
895
+ async getMfaVerifiedAt(sessionId) {
896
+ const redis = getRedis();
897
+ const raw = await redis.get(sessionKey(sessionId));
898
+ if (!raw)
899
+ return null;
900
+ const rec = JSON.parse(raw);
901
+ return rec.mfaVerifiedAt ?? null;
902
+ },
903
+ };
904
+ }
905
+ export function createMongoSessionRepository(conn, mg) {
906
+ function getSessionModel() {
907
+ if (conn.models['Session'])
908
+ return conn.models['Session'];
909
+ const { Schema } = mg;
910
+ const sessionSchema = new Schema({
911
+ sessionId: { type: String, required: true, unique: true },
912
+ userId: { type: String, required: true, index: true },
913
+ token: { type: String, default: null },
914
+ createdAt: { type: Date, required: true },
915
+ lastActiveAt: { type: Date, required: true },
916
+ expiresAt: { type: Date, required: true },
917
+ ipAddress: { type: String },
918
+ userAgent: { type: String },
919
+ refreshToken: { type: String, default: null },
920
+ prevRefreshToken: { type: String, default: null },
921
+ prevTokenExpiresAt: { type: Date, default: null },
922
+ refreshTokenPlain: { type: String, default: null },
923
+ fingerprint: { type: String, default: null },
924
+ mfaVerifiedAt: { type: Number, default: null },
925
+ }, { collection: 'sessions', timestamps: false });
926
+ sessionSchema.index({ refreshToken: 1 }, { unique: true, partialFilterExpression: { refreshToken: { $type: 'string' } } });
927
+ if (!DEFAULT_AUTH_CONFIG.persistSessionMetadata) {
928
+ sessionSchema.index({ expiresAt: 1 }, { expireAfterSeconds: 0 });
929
+ }
930
+ return conn.model('Session', sessionSchema);
931
+ }
932
+ function deleteSessionImpl(sessionId, cfg) {
933
+ const c = cfg ?? DEFAULT_AUTH_CONFIG;
934
+ const Session = getSessionModel();
935
+ if (c.persistSessionMetadata) {
936
+ return Session.updateOne({ sessionId }, {
937
+ $set: {
938
+ token: null,
939
+ refreshToken: null,
940
+ prevRefreshToken: null,
941
+ prevTokenExpiresAt: null,
942
+ },
943
+ }).then(() => { });
944
+ }
945
+ return Session.deleteOne({ sessionId }).then(() => { });
946
+ }
947
+ return {
948
+ async createSession(userId, token, sessionId, metadata, cfg) {
949
+ const now = new Date();
950
+ const expiresAt = new Date(Date.now() + getSessionTtlMs(cfg));
951
+ await getSessionModel().create({
952
+ sessionId,
953
+ userId,
954
+ token,
955
+ createdAt: now,
956
+ lastActiveAt: now,
957
+ expiresAt,
958
+ ipAddress: metadata?.ipAddress,
959
+ userAgent: metadata?.userAgent,
960
+ });
961
+ },
962
+ async atomicCreateSession(userId, token, sessionId, maxSessions, metadata, cfg) {
963
+ const c = cfg ?? DEFAULT_AUTH_CONFIG;
964
+ const session = await conn.startSession();
965
+ try {
966
+ await session.withTransaction(async () => {
967
+ const Session = getSessionModel();
968
+ const now = new Date();
969
+ let activeCount = await Session.countDocuments({ userId, token: { $ne: null }, expiresAt: { $gt: now } }, { session });
970
+ while (activeCount >= maxSessions) {
971
+ const oldest = await Session.findOne({ userId, token: { $ne: null }, expiresAt: { $gt: now } }, 'sessionId', { session, sort: { createdAt: 1 } }).lean();
972
+ if (!oldest)
973
+ break;
974
+ if (c.persistSessionMetadata) {
975
+ await Session.updateOne({ sessionId: oldest.sessionId }, {
976
+ $set: {
977
+ token: null,
978
+ refreshToken: null,
979
+ prevRefreshToken: null,
980
+ prevTokenExpiresAt: null,
981
+ },
982
+ }, { session });
983
+ }
984
+ else {
985
+ await Session.deleteOne({ sessionId: oldest.sessionId }, { session });
986
+ }
987
+ activeCount--;
988
+ }
989
+ const expiresAt = new Date(Date.now() + getSessionTtlMs(c));
990
+ await Session.create([
991
+ {
992
+ sessionId,
993
+ userId,
994
+ token,
995
+ createdAt: now,
996
+ lastActiveAt: now,
997
+ expiresAt,
998
+ ipAddress: metadata?.ipAddress,
999
+ userAgent: metadata?.userAgent,
1000
+ },
1001
+ ], { session });
1002
+ });
1003
+ }
1004
+ finally {
1005
+ await session.endSession();
1006
+ }
1007
+ },
1008
+ async getSession(sessionId, cfg) {
1009
+ const doc = (await getSessionModel()
1010
+ .findOne({ sessionId, expiresAt: { $gt: new Date() } }, 'token lastActiveAt')
1011
+ .lean());
1012
+ if (!doc?.token)
1013
+ return null;
1014
+ if (isIdleExpired(doc.lastActiveAt.getTime(), cfg)) {
1015
+ await deleteSessionImpl(sessionId, cfg);
1016
+ return null;
1017
+ }
1018
+ return doc.token;
1019
+ },
1020
+ async deleteSession(sessionId, cfg) {
1021
+ await deleteSessionImpl(sessionId, cfg);
1022
+ },
1023
+ async getUserSessions(userId, cfg) {
1024
+ const c = cfg ?? DEFAULT_AUTH_CONFIG;
1025
+ const now = new Date();
1026
+ const includeInactive = c.includeInactiveSessions;
1027
+ const persist = c.persistSessionMetadata;
1028
+ const query = { userId };
1029
+ if (!includeInactive) {
1030
+ query.token = { $ne: null };
1031
+ query.expiresAt = { $gt: now };
1032
+ }
1033
+ const docs = await getSessionModel().find(query).lean();
1034
+ const results = [];
1035
+ for (const doc of docs) {
1036
+ const isActive = !!doc.token && doc.expiresAt > now;
1037
+ if (!isActive && !persist)
1038
+ continue;
1039
+ if (!isActive && !includeInactive)
1040
+ continue;
1041
+ results.push({
1042
+ sessionId: doc.sessionId,
1043
+ createdAt: doc.createdAt.getTime(),
1044
+ lastActiveAt: doc.lastActiveAt.getTime(),
1045
+ expiresAt: doc.expiresAt.getTime(),
1046
+ ipAddress: doc.ipAddress,
1047
+ userAgent: doc.userAgent,
1048
+ isActive,
1049
+ });
1050
+ }
1051
+ return results;
1052
+ },
1053
+ async getActiveSessionCount(userId) {
1054
+ const now = new Date();
1055
+ return getSessionModel().countDocuments({
1056
+ userId,
1057
+ token: { $ne: null },
1058
+ expiresAt: { $gt: now },
1059
+ });
1060
+ },
1061
+ async evictOldestSession(userId, cfg) {
1062
+ const now = new Date();
1063
+ const oldest = await getSessionModel()
1064
+ .findOne({ userId, token: { $ne: null }, expiresAt: { $gt: now } }, 'sessionId')
1065
+ .sort({ createdAt: 1 })
1066
+ .lean();
1067
+ if (oldest)
1068
+ await deleteSessionImpl(oldest.sessionId, cfg);
1069
+ },
1070
+ async updateSessionLastActive(sessionId) {
1071
+ await getSessionModel().updateOne({ sessionId }, { $set: { lastActiveAt: new Date() } });
1072
+ },
1073
+ async setRefreshToken(sessionId, refreshToken) {
1074
+ const tokenHash = hashToken(refreshToken);
1075
+ await getSessionModel().updateOne({ sessionId }, { $set: { refreshToken: tokenHash } });
1076
+ },
1077
+ async getSessionByRefreshToken(refreshToken, cfg) {
1078
+ const Session = getSessionModel();
1079
+ const tokenHash = hashToken(refreshToken);
1080
+ let doc = (await Session.findOne({ refreshToken: tokenHash }).lean());
1081
+ if (doc) {
1082
+ if (isIdleExpired(doc.lastActiveAt.getTime(), cfg)) {
1083
+ await deleteSessionImpl(doc.sessionId, cfg);
1084
+ return null;
1085
+ }
1086
+ return { sessionId: doc.sessionId, userId: doc.userId, newRefreshToken: refreshToken };
1087
+ }
1088
+ doc = (await Session.findOne({ prevRefreshToken: tokenHash }).lean());
1089
+ if (!doc)
1090
+ return null;
1091
+ if (isIdleExpired(doc.lastActiveAt.getTime(), cfg)) {
1092
+ await deleteSessionImpl(doc.sessionId, cfg);
1093
+ return null;
1094
+ }
1095
+ if (doc.prevTokenExpiresAt && doc.prevTokenExpiresAt > new Date()) {
1096
+ return {
1097
+ sessionId: doc.sessionId,
1098
+ userId: doc.userId,
1099
+ newRefreshToken: doc.refreshTokenPlain ?? doc.refreshToken,
1100
+ };
1101
+ }
1102
+ await deleteSessionImpl(doc.sessionId, cfg);
1103
+ return null;
1104
+ },
1105
+ async rotateRefreshToken(sessionId, newRefreshToken, newAccessToken, cfg) {
1106
+ const graceSeconds = (cfg ?? DEFAULT_AUTH_CONFIG).refreshToken?.rotationGraceSeconds ?? 30;
1107
+ const Session = getSessionModel();
1108
+ const doc = await Session.findOne({ sessionId });
1109
+ if (!doc)
1110
+ return;
1111
+ const newHash = hashToken(newRefreshToken);
1112
+ doc.prevRefreshToken = doc.refreshToken;
1113
+ doc.prevTokenExpiresAt = new Date(Date.now() + graceSeconds * 1000);
1114
+ doc.refreshToken = newHash;
1115
+ doc.refreshTokenPlain = newRefreshToken;
1116
+ doc.token = newAccessToken;
1117
+ await doc.save();
1118
+ },
1119
+ async getSessionFingerprint(sessionId) {
1120
+ const doc = await getSessionModel().findOne({ sessionId }, 'fingerprint').lean();
1121
+ return doc?.fingerprint ?? null;
1122
+ },
1123
+ async setSessionFingerprint(sessionId, fingerprint) {
1124
+ await getSessionModel().updateOne({ sessionId }, { $set: { fingerprint } });
1125
+ },
1126
+ async setMfaVerifiedAt(sessionId) {
1127
+ const now = Math.floor(Date.now() / 1000);
1128
+ await getSessionModel().updateOne({ sessionId }, { $set: { mfaVerifiedAt: now } });
1129
+ },
1130
+ async getMfaVerifiedAt(sessionId) {
1131
+ const doc = await getSessionModel().findOne({ sessionId }, 'mfaVerifiedAt').lean();
1132
+ return doc?.mfaVerifiedAt ?? null;
1133
+ },
1134
+ };
1135
+ }
1136
+ // ---------------------------------------------------------------------------
1137
+ // Factory map
1138
+ // ---------------------------------------------------------------------------
1139
+ export const sessionFactories = {
1140
+ memory: () => createMemorySessionRepository(),
1141
+ sqlite: infra => createSqliteSessionRepository(infra.getSqliteDb()),
1142
+ redis: infra => createRedisSessionRepository(infra.getRedis, infra.appName),
1143
+ mongo: infra => {
1144
+ const { conn, mg } = infra.getMongo();
1145
+ return createMongoSessionRepository(conn, mg);
1146
+ },
1147
+ postgres: () => {
1148
+ throw new Error('[bunshot-auth] postgres store is not yet supported for session repository');
1149
+ },
1150
+ };
1151
+ // ---------------------------------------------------------------------------
1152
+ // Public API — thin wrappers delegating to ISessionRepository
1153
+ //
1154
+ // Callers pass the repo directly (resolved in bootstrap via sessionFactories).
1155
+ // ---------------------------------------------------------------------------
1156
+ export const createSession = async (repo, userId, token, sessionId, metadata, config) => {
1157
+ await repo.createSession(userId, token, sessionId, metadata, config);
1158
+ };
1159
+ export const atomicCreateSession = async (repo, userId, token, sessionId, maxSessions, metadata, config) => {
1160
+ await repo.atomicCreateSession(userId, token, sessionId, maxSessions, metadata, config);
1161
+ };
1162
+ export const getSession = async (repo, sessionId, config) => {
1163
+ const cfg = config ?? DEFAULT_AUTH_CONFIG;
1164
+ return repo.getSession(sessionId, cfg);
1165
+ };
1166
+ export const deleteSession = async (repo, sessionId, config) => {
1167
+ await repo.deleteSession(sessionId, config);
1168
+ };
1169
+ export const getUserSessions = async (repo, userId, config) => {
1170
+ return repo.getUserSessions(userId, config);
1171
+ };
1172
+ export const getActiveSessionCount = async (repo, userId, config) => {
1173
+ return repo.getActiveSessionCount(userId, config);
1174
+ };
1175
+ export const evictOldestSession = async (repo, userId, config) => {
1176
+ await repo.evictOldestSession(userId, config);
1177
+ };
1178
+ export const deleteUserSessions = async (repo, userId, config) => {
1179
+ const sessions = await repo.getUserSessions(userId, config);
1180
+ await Promise.all(sessions.map(s => repo.deleteSession(s.sessionId, config)));
1181
+ };
1182
+ export const deleteOtherSessions = async (repo, userId, currentSessionId, config) => {
1183
+ const sessions = await repo.getUserSessions(userId, config);
1184
+ const others = sessions.filter(s => s.sessionId !== currentSessionId);
1185
+ await Promise.all(others.map(s => repo.deleteSession(s.sessionId, config)));
1186
+ };
1187
+ export const updateSessionLastActive = async (repo, sessionId, config) => {
1188
+ await repo.updateSessionLastActive(sessionId, config);
1189
+ };
1190
+ export const setRefreshToken = async (repo, sessionId, refreshToken, config) => {
1191
+ await repo.setRefreshToken(sessionId, refreshToken, config);
1192
+ };
1193
+ export const getSessionByRefreshToken = async (repo, refreshToken, config) => {
1194
+ return repo.getSessionByRefreshToken(refreshToken, config);
1195
+ };
1196
+ export const rotateRefreshToken = async (repo, sessionId, newRefreshToken, newAccessToken, config) => {
1197
+ await repo.rotateRefreshToken(sessionId, newRefreshToken, newAccessToken, config);
1198
+ await repo.updateSessionLastActive(sessionId, config);
1199
+ };
1200
+ export const getSessionFingerprint = async (repo, sessionId) => {
1201
+ return repo.getSessionFingerprint(sessionId);
1202
+ };
1203
+ export const setSessionFingerprint = async (repo, sessionId, fingerprint) => {
1204
+ await repo.setSessionFingerprint(sessionId, fingerprint);
1205
+ };
1206
+ export const setMfaVerifiedAt = async (repo, sessionId) => {
1207
+ await repo.setMfaVerifiedAt(sessionId);
1208
+ };
1209
+ export const getMfaVerifiedAt = async (repo, sessionId) => {
1210
+ return repo.getMfaVerifiedAt(sessionId);
1211
+ };