@portaidentity/server 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (742) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/LICENSE +21 -0
  3. package/README.md +33 -0
  4. package/dist/applications/cache.d.ts +64 -0
  5. package/dist/applications/cache.d.ts.map +1 -0
  6. package/dist/applications/cache.js +161 -0
  7. package/dist/applications/cache.js.map +1 -0
  8. package/dist/applications/errors.d.ts +25 -0
  9. package/dist/applications/errors.d.ts.map +1 -0
  10. package/dist/applications/errors.js +31 -0
  11. package/dist/applications/errors.js.map +1 -0
  12. package/dist/applications/index.d.ts +17 -0
  13. package/dist/applications/index.d.ts.map +1 -0
  14. package/dist/applications/index.js +19 -0
  15. package/dist/applications/index.js.map +1 -0
  16. package/dist/applications/repository.d.ts +184 -0
  17. package/dist/applications/repository.d.ts.map +1 -0
  18. package/dist/applications/repository.js +367 -0
  19. package/dist/applications/repository.js.map +1 -0
  20. package/dist/applications/service.d.ts +160 -0
  21. package/dist/applications/service.d.ts.map +1 -0
  22. package/dist/applications/service.js +388 -0
  23. package/dist/applications/service.js.map +1 -0
  24. package/dist/applications/slugs.d.ts +61 -0
  25. package/dist/applications/slugs.d.ts.map +1 -0
  26. package/dist/applications/slugs.js +115 -0
  27. package/dist/applications/slugs.js.map +1 -0
  28. package/dist/applications/types.d.ts +129 -0
  29. package/dist/applications/types.d.ts.map +1 -0
  30. package/dist/applications/types.js +62 -0
  31. package/dist/applications/types.js.map +1 -0
  32. package/dist/auth/csrf.d.ts +71 -0
  33. package/dist/auth/csrf.d.ts.map +1 -0
  34. package/dist/auth/csrf.js +112 -0
  35. package/dist/auth/csrf.js.map +1 -0
  36. package/dist/auth/email-renderer.d.ts +37 -0
  37. package/dist/auth/email-renderer.d.ts.map +1 -0
  38. package/dist/auth/email-renderer.js +116 -0
  39. package/dist/auth/email-renderer.js.map +1 -0
  40. package/dist/auth/email-service.d.ts +154 -0
  41. package/dist/auth/email-service.d.ts.map +1 -0
  42. package/dist/auth/email-service.js +415 -0
  43. package/dist/auth/email-service.js.map +1 -0
  44. package/dist/auth/email-transport.d.ts +65 -0
  45. package/dist/auth/email-transport.d.ts.map +1 -0
  46. package/dist/auth/email-transport.js +82 -0
  47. package/dist/auth/email-transport.js.map +1 -0
  48. package/dist/auth/i18n.d.ts +81 -0
  49. package/dist/auth/i18n.d.ts.map +1 -0
  50. package/dist/auth/i18n.js +395 -0
  51. package/dist/auth/i18n.js.map +1 -0
  52. package/dist/auth/index.d.ts +28 -0
  53. package/dist/auth/index.d.ts.map +1 -0
  54. package/dist/auth/index.js +31 -0
  55. package/dist/auth/index.js.map +1 -0
  56. package/dist/auth/interaction-authority.d.ts +39 -0
  57. package/dist/auth/interaction-authority.d.ts.map +1 -0
  58. package/dist/auth/interaction-authority.js +30 -0
  59. package/dist/auth/interaction-authority.js.map +1 -0
  60. package/dist/auth/magic-link-session.d.ts +81 -0
  61. package/dist/auth/magic-link-session.d.ts.map +1 -0
  62. package/dist/auth/magic-link-session.js +183 -0
  63. package/dist/auth/magic-link-session.js.map +1 -0
  64. package/dist/auth/rate-limiter.d.ts +143 -0
  65. package/dist/auth/rate-limiter.d.ts.map +1 -0
  66. package/dist/auth/rate-limiter.js +220 -0
  67. package/dist/auth/rate-limiter.js.map +1 -0
  68. package/dist/auth/recovery-crypto.d.ts +34 -0
  69. package/dist/auth/recovery-crypto.d.ts.map +1 -0
  70. package/dist/auth/recovery-crypto.js +103 -0
  71. package/dist/auth/recovery-crypto.js.map +1 -0
  72. package/dist/auth/recovery-job-processor.d.ts +24 -0
  73. package/dist/auth/recovery-job-processor.d.ts.map +1 -0
  74. package/dist/auth/recovery-job-processor.js +123 -0
  75. package/dist/auth/recovery-job-processor.js.map +1 -0
  76. package/dist/auth/recovery-job-repository.d.ts +219 -0
  77. package/dist/auth/recovery-job-repository.d.ts.map +1 -0
  78. package/dist/auth/recovery-job-repository.js +340 -0
  79. package/dist/auth/recovery-job-repository.js.map +1 -0
  80. package/dist/auth/recovery-service.d.ts +27 -0
  81. package/dist/auth/recovery-service.d.ts.map +1 -0
  82. package/dist/auth/recovery-service.js +53 -0
  83. package/dist/auth/recovery-service.js.map +1 -0
  84. package/dist/auth/recovery-worker.d.ts +158 -0
  85. package/dist/auth/recovery-worker.d.ts.map +1 -0
  86. package/dist/auth/recovery-worker.js +306 -0
  87. package/dist/auth/recovery-worker.js.map +1 -0
  88. package/dist/auth/template-engine.d.ts +134 -0
  89. package/dist/auth/template-engine.d.ts.map +1 -0
  90. package/dist/auth/template-engine.js +225 -0
  91. package/dist/auth/template-engine.js.map +1 -0
  92. package/dist/auth/token-repository.d.ts +238 -0
  93. package/dist/auth/token-repository.d.ts.map +1 -0
  94. package/dist/auth/token-repository.js +475 -0
  95. package/dist/auth/token-repository.js.map +1 -0
  96. package/dist/auth/tokens.d.ts +45 -0
  97. package/dist/auth/tokens.d.ts.map +1 -0
  98. package/dist/auth/tokens.js +51 -0
  99. package/dist/auth/tokens.js.map +1 -0
  100. package/dist/cli/bootstrap.d.ts +55 -0
  101. package/dist/cli/bootstrap.d.ts.map +1 -0
  102. package/dist/cli/bootstrap.js +90 -0
  103. package/dist/cli/bootstrap.js.map +1 -0
  104. package/dist/cli/commands/health.d.ts +20 -0
  105. package/dist/cli/commands/health.d.ts.map +1 -0
  106. package/dist/cli/commands/health.js +80 -0
  107. package/dist/cli/commands/health.js.map +1 -0
  108. package/dist/cli/commands/init.d.ts +48 -0
  109. package/dist/cli/commands/init.d.ts.map +1 -0
  110. package/dist/cli/commands/init.js +349 -0
  111. package/dist/cli/commands/init.js.map +1 -0
  112. package/dist/cli/commands/migrate.d.ts +19 -0
  113. package/dist/cli/commands/migrate.d.ts.map +1 -0
  114. package/dist/cli/commands/migrate.js +88 -0
  115. package/dist/cli/commands/migrate.js.map +1 -0
  116. package/dist/cli/commands/seed.d.ts +19 -0
  117. package/dist/cli/commands/seed.d.ts.map +1 -0
  118. package/dist/cli/commands/seed.js +71 -0
  119. package/dist/cli/commands/seed.js.map +1 -0
  120. package/dist/cli/commands/user-2fa.d.ts +29 -0
  121. package/dist/cli/commands/user-2fa.d.ts.map +1 -0
  122. package/dist/cli/commands/user-2fa.js +113 -0
  123. package/dist/cli/commands/user-2fa.js.map +1 -0
  124. package/dist/cli/error-handler.d.ts +31 -0
  125. package/dist/cli/error-handler.d.ts.map +1 -0
  126. package/dist/cli/error-handler.js +65 -0
  127. package/dist/cli/error-handler.js.map +1 -0
  128. package/dist/cli/index.d.ts +48 -0
  129. package/dist/cli/index.d.ts.map +1 -0
  130. package/dist/cli/index.js +99 -0
  131. package/dist/cli/index.js.map +1 -0
  132. package/dist/cli/output.d.ts +94 -0
  133. package/dist/cli/output.d.ts.map +1 -0
  134. package/dist/cli/output.js +124 -0
  135. package/dist/cli/output.js.map +1 -0
  136. package/dist/cli/prompt.d.ts +48 -0
  137. package/dist/cli/prompt.d.ts.map +1 -0
  138. package/dist/cli/prompt.js +96 -0
  139. package/dist/cli/prompt.js.map +1 -0
  140. package/dist/clients/cache.d.ts +63 -0
  141. package/dist/clients/cache.d.ts.map +1 -0
  142. package/dist/clients/cache.js +160 -0
  143. package/dist/clients/cache.js.map +1 -0
  144. package/dist/clients/crypto.d.ts +69 -0
  145. package/dist/clients/crypto.d.ts.map +1 -0
  146. package/dist/clients/crypto.js +83 -0
  147. package/dist/clients/crypto.js.map +1 -0
  148. package/dist/clients/errors.d.ts +27 -0
  149. package/dist/clients/errors.d.ts.map +1 -0
  150. package/dist/clients/errors.js +33 -0
  151. package/dist/clients/errors.js.map +1 -0
  152. package/dist/clients/index.d.ts +19 -0
  153. package/dist/clients/index.d.ts.map +1 -0
  154. package/dist/clients/index.js +23 -0
  155. package/dist/clients/index.js.map +1 -0
  156. package/dist/clients/repository.d.ts +161 -0
  157. package/dist/clients/repository.d.ts.map +1 -0
  158. package/dist/clients/repository.js +318 -0
  159. package/dist/clients/repository.js.map +1 -0
  160. package/dist/clients/resolve-login-methods.d.ts +74 -0
  161. package/dist/clients/resolve-login-methods.d.ts.map +1 -0
  162. package/dist/clients/resolve-login-methods.js +68 -0
  163. package/dist/clients/resolve-login-methods.js.map +1 -0
  164. package/dist/clients/secret-repository.d.ts +109 -0
  165. package/dist/clients/secret-repository.d.ts.map +1 -0
  166. package/dist/clients/secret-repository.js +166 -0
  167. package/dist/clients/secret-repository.js.map +1 -0
  168. package/dist/clients/secret-service.d.ts +87 -0
  169. package/dist/clients/secret-service.d.ts.map +1 -0
  170. package/dist/clients/secret-service.js +204 -0
  171. package/dist/clients/secret-service.js.map +1 -0
  172. package/dist/clients/service.d.ts +158 -0
  173. package/dist/clients/service.d.ts.map +1 -0
  174. package/dist/clients/service.js +523 -0
  175. package/dist/clients/service.js.map +1 -0
  176. package/dist/clients/types.d.ts +214 -0
  177. package/dist/clients/types.d.ts.map +1 -0
  178. package/dist/clients/types.js +77 -0
  179. package/dist/clients/types.js.map +1 -0
  180. package/dist/clients/validators.d.ts +87 -0
  181. package/dist/clients/validators.d.ts.map +1 -0
  182. package/dist/clients/validators.js +164 -0
  183. package/dist/clients/validators.js.map +1 -0
  184. package/dist/config/index.d.ts +23 -0
  185. package/dist/config/index.d.ts.map +1 -0
  186. package/dist/config/index.js +52 -0
  187. package/dist/config/index.js.map +1 -0
  188. package/dist/config/schema.d.ts +35 -0
  189. package/dist/config/schema.d.ts.map +1 -0
  190. package/dist/config/schema.js +167 -0
  191. package/dist/config/schema.js.map +1 -0
  192. package/dist/custom-claims/cache.d.ts +48 -0
  193. package/dist/custom-claims/cache.d.ts.map +1 -0
  194. package/dist/custom-claims/cache.js +122 -0
  195. package/dist/custom-claims/cache.js.map +1 -0
  196. package/dist/custom-claims/errors.d.ts +25 -0
  197. package/dist/custom-claims/errors.d.ts.map +1 -0
  198. package/dist/custom-claims/errors.js +31 -0
  199. package/dist/custom-claims/errors.js.map +1 -0
  200. package/dist/custom-claims/index.d.ts +14 -0
  201. package/dist/custom-claims/index.d.ts.map +1 -0
  202. package/dist/custom-claims/index.js +17 -0
  203. package/dist/custom-claims/index.js.map +1 -0
  204. package/dist/custom-claims/repository.d.ts +147 -0
  205. package/dist/custom-claims/repository.d.ts.map +1 -0
  206. package/dist/custom-claims/repository.js +338 -0
  207. package/dist/custom-claims/repository.js.map +1 -0
  208. package/dist/custom-claims/service.d.ts +129 -0
  209. package/dist/custom-claims/service.d.ts.map +1 -0
  210. package/dist/custom-claims/service.js +296 -0
  211. package/dist/custom-claims/service.js.map +1 -0
  212. package/dist/custom-claims/types.d.ts +132 -0
  213. package/dist/custom-claims/types.d.ts.map +1 -0
  214. package/dist/custom-claims/types.js +61 -0
  215. package/dist/custom-claims/types.js.map +1 -0
  216. package/dist/custom-claims/validators.d.ts +61 -0
  217. package/dist/custom-claims/validators.d.ts.map +1 -0
  218. package/dist/custom-claims/validators.js +136 -0
  219. package/dist/custom-claims/validators.js.map +1 -0
  220. package/dist/index.d.ts +14 -0
  221. package/dist/index.d.ts.map +1 -0
  222. package/dist/index.js +91 -0
  223. package/dist/index.js.map +1 -0
  224. package/dist/lib/admin-permissions.d.ts +147 -0
  225. package/dist/lib/admin-permissions.d.ts.map +1 -0
  226. package/dist/lib/admin-permissions.js +261 -0
  227. package/dist/lib/admin-permissions.js.map +1 -0
  228. package/dist/lib/audit-log.d.ts +45 -0
  229. package/dist/lib/audit-log.d.ts.map +1 -0
  230. package/dist/lib/audit-log.js +79 -0
  231. package/dist/lib/audit-log.js.map +1 -0
  232. package/dist/lib/branding-assets.d.ts +47 -0
  233. package/dist/lib/branding-assets.d.ts.map +1 -0
  234. package/dist/lib/branding-assets.js +93 -0
  235. package/dist/lib/branding-assets.js.map +1 -0
  236. package/dist/lib/bulk-operations.d.ts +54 -0
  237. package/dist/lib/bulk-operations.d.ts.map +1 -0
  238. package/dist/lib/bulk-operations.js +201 -0
  239. package/dist/lib/bulk-operations.js.map +1 -0
  240. package/dist/lib/cursor.d.ts +110 -0
  241. package/dist/lib/cursor.d.ts.map +1 -0
  242. package/dist/lib/cursor.js +115 -0
  243. package/dist/lib/cursor.js.map +1 -0
  244. package/dist/lib/data-export.d.ts +67 -0
  245. package/dist/lib/data-export.d.ts.map +1 -0
  246. package/dist/lib/data-export.js +272 -0
  247. package/dist/lib/data-export.js.map +1 -0
  248. package/dist/lib/data-import-plan.d.ts +50 -0
  249. package/dist/lib/data-import-plan.d.ts.map +1 -0
  250. package/dist/lib/data-import-plan.js +235 -0
  251. package/dist/lib/data-import-plan.js.map +1 -0
  252. package/dist/lib/data-import.d.ts +276 -0
  253. package/dist/lib/data-import.d.ts.map +1 -0
  254. package/dist/lib/data-import.js +1694 -0
  255. package/dist/lib/data-import.js.map +1 -0
  256. package/dist/lib/database.d.ts +22 -0
  257. package/dist/lib/database.d.ts.map +1 -0
  258. package/dist/lib/database.js +103 -0
  259. package/dist/lib/database.js.map +1 -0
  260. package/dist/lib/entity-history.d.ts +52 -0
  261. package/dist/lib/entity-history.d.ts.map +1 -0
  262. package/dist/lib/entity-history.js +121 -0
  263. package/dist/lib/entity-history.js.map +1 -0
  264. package/dist/lib/etag.d.ts +92 -0
  265. package/dist/lib/etag.d.ts.map +1 -0
  266. package/dist/lib/etag.js +155 -0
  267. package/dist/lib/etag.js.map +1 -0
  268. package/dist/lib/image-validator.d.ts +44 -0
  269. package/dist/lib/image-validator.d.ts.map +1 -0
  270. package/dist/lib/image-validator.js +204 -0
  271. package/dist/lib/image-validator.js.map +1 -0
  272. package/dist/lib/logger.d.ts +15 -0
  273. package/dist/lib/logger.d.ts.map +1 -0
  274. package/dist/lib/logger.js +84 -0
  275. package/dist/lib/logger.js.map +1 -0
  276. package/dist/lib/migrator.d.ts +14 -0
  277. package/dist/lib/migrator.d.ts.map +1 -0
  278. package/dist/lib/migrator.js +34 -0
  279. package/dist/lib/migrator.js.map +1 -0
  280. package/dist/lib/redis.d.ts +5 -0
  281. package/dist/lib/redis.d.ts.map +1 -0
  282. package/dist/lib/redis.js +29 -0
  283. package/dist/lib/redis.js.map +1 -0
  284. package/dist/lib/runtime-paths.d.ts +38 -0
  285. package/dist/lib/runtime-paths.d.ts.map +1 -0
  286. package/dist/lib/runtime-paths.js +50 -0
  287. package/dist/lib/runtime-paths.js.map +1 -0
  288. package/dist/lib/session-tracking.d.ts +81 -0
  289. package/dist/lib/session-tracking.d.ts.map +1 -0
  290. package/dist/lib/session-tracking.js +145 -0
  291. package/dist/lib/session-tracking.js.map +1 -0
  292. package/dist/lib/signing-key-crypto.d.ts +53 -0
  293. package/dist/lib/signing-key-crypto.d.ts.map +1 -0
  294. package/dist/lib/signing-key-crypto.js +108 -0
  295. package/dist/lib/signing-key-crypto.js.map +1 -0
  296. package/dist/lib/signing-keys.d.ts +141 -0
  297. package/dist/lib/signing-keys.d.ts.map +1 -0
  298. package/dist/lib/signing-keys.js +206 -0
  299. package/dist/lib/signing-keys.js.map +1 -0
  300. package/dist/lib/stats.d.ts +83 -0
  301. package/dist/lib/stats.d.ts.map +1 -0
  302. package/dist/lib/stats.js +187 -0
  303. package/dist/lib/stats.js.map +1 -0
  304. package/dist/lib/super-admin-protection.d.ts +69 -0
  305. package/dist/lib/super-admin-protection.d.ts.map +1 -0
  306. package/dist/lib/super-admin-protection.js +102 -0
  307. package/dist/lib/super-admin-protection.js.map +1 -0
  308. package/dist/lib/system-config.d.ts +79 -0
  309. package/dist/lib/system-config.d.ts.map +1 -0
  310. package/dist/lib/system-config.js +159 -0
  311. package/dist/lib/system-config.js.map +1 -0
  312. package/dist/middleware/admin-auth.d.ts +100 -0
  313. package/dist/middleware/admin-auth.d.ts.map +1 -0
  314. package/dist/middleware/admin-auth.js +241 -0
  315. package/dist/middleware/admin-auth.js.map +1 -0
  316. package/dist/middleware/admin-cors.d.ts +41 -0
  317. package/dist/middleware/admin-cors.d.ts.map +1 -0
  318. package/dist/middleware/admin-cors.js +83 -0
  319. package/dist/middleware/admin-cors.js.map +1 -0
  320. package/dist/middleware/admin-mutation-audit.d.ts +9 -0
  321. package/dist/middleware/admin-mutation-audit.d.ts.map +1 -0
  322. package/dist/middleware/admin-mutation-audit.js +76 -0
  323. package/dist/middleware/admin-mutation-audit.js.map +1 -0
  324. package/dist/middleware/admin-rate-limiter.d.ts +56 -0
  325. package/dist/middleware/admin-rate-limiter.d.ts.map +1 -0
  326. package/dist/middleware/admin-rate-limiter.js +97 -0
  327. package/dist/middleware/admin-rate-limiter.js.map +1 -0
  328. package/dist/middleware/client-secret-hash.d.ts +34 -0
  329. package/dist/middleware/client-secret-hash.d.ts.map +1 -0
  330. package/dist/middleware/client-secret-hash.js +74 -0
  331. package/dist/middleware/client-secret-hash.js.map +1 -0
  332. package/dist/middleware/error-handler.d.ts +3 -0
  333. package/dist/middleware/error-handler.d.ts.map +1 -0
  334. package/dist/middleware/error-handler.js +93 -0
  335. package/dist/middleware/error-handler.js.map +1 -0
  336. package/dist/middleware/health.d.ts +3 -0
  337. package/dist/middleware/health.d.ts.map +1 -0
  338. package/dist/middleware/health.js +35 -0
  339. package/dist/middleware/health.js.map +1 -0
  340. package/dist/middleware/metrics.d.ts +40 -0
  341. package/dist/middleware/metrics.d.ts.map +1 -0
  342. package/dist/middleware/metrics.js +75 -0
  343. package/dist/middleware/metrics.js.map +1 -0
  344. package/dist/middleware/oidc-client-tenant.d.ts +37 -0
  345. package/dist/middleware/oidc-client-tenant.d.ts.map +1 -0
  346. package/dist/middleware/oidc-client-tenant.js +156 -0
  347. package/dist/middleware/oidc-client-tenant.js.map +1 -0
  348. package/dist/middleware/oidc-cors.d.ts +33 -0
  349. package/dist/middleware/oidc-cors.d.ts.map +1 -0
  350. package/dist/middleware/oidc-cors.js +68 -0
  351. package/dist/middleware/oidc-cors.js.map +1 -0
  352. package/dist/middleware/oidc-preflight-cors.d.ts +54 -0
  353. package/dist/middleware/oidc-preflight-cors.d.ts.map +1 -0
  354. package/dist/middleware/oidc-preflight-cors.js +267 -0
  355. package/dist/middleware/oidc-preflight-cors.js.map +1 -0
  356. package/dist/middleware/prompt-login-reset.d.ts +103 -0
  357. package/dist/middleware/prompt-login-reset.d.ts.map +1 -0
  358. package/dist/middleware/prompt-login-reset.js +204 -0
  359. package/dist/middleware/prompt-login-reset.js.map +1 -0
  360. package/dist/middleware/ready.d.ts +23 -0
  361. package/dist/middleware/ready.d.ts.map +1 -0
  362. package/dist/middleware/ready.js +60 -0
  363. package/dist/middleware/ready.js.map +1 -0
  364. package/dist/middleware/request-logger.d.ts +27 -0
  365. package/dist/middleware/request-logger.d.ts.map +1 -0
  366. package/dist/middleware/request-logger.js +46 -0
  367. package/dist/middleware/request-logger.js.map +1 -0
  368. package/dist/middleware/require-permission.d.ts +28 -0
  369. package/dist/middleware/require-permission.d.ts.map +1 -0
  370. package/dist/middleware/require-permission.js +63 -0
  371. package/dist/middleware/require-permission.js.map +1 -0
  372. package/dist/middleware/require-user-organization.d.ts +18 -0
  373. package/dist/middleware/require-user-organization.d.ts.map +1 -0
  374. package/dist/middleware/require-user-organization.js +53 -0
  375. package/dist/middleware/require-user-organization.js.map +1 -0
  376. package/dist/middleware/root-page.d.ts +62 -0
  377. package/dist/middleware/root-page.d.ts.map +1 -0
  378. package/dist/middleware/root-page.js +134 -0
  379. package/dist/middleware/root-page.js.map +1 -0
  380. package/dist/middleware/security-headers.d.ts +98 -0
  381. package/dist/middleware/security-headers.d.ts.map +1 -0
  382. package/dist/middleware/security-headers.js +159 -0
  383. package/dist/middleware/security-headers.js.map +1 -0
  384. package/dist/middleware/tenant-resolver.d.ts +37 -0
  385. package/dist/middleware/tenant-resolver.d.ts.map +1 -0
  386. package/dist/middleware/tenant-resolver.js +71 -0
  387. package/dist/middleware/tenant-resolver.js.map +1 -0
  388. package/dist/middleware/token-rate-limiter.d.ts +89 -0
  389. package/dist/middleware/token-rate-limiter.d.ts.map +1 -0
  390. package/dist/middleware/token-rate-limiter.js +189 -0
  391. package/dist/middleware/token-rate-limiter.js.map +1 -0
  392. package/dist/oidc/account-finder.d.ts +52 -0
  393. package/dist/oidc/account-finder.d.ts.map +1 -0
  394. package/dist/oidc/account-finder.js +134 -0
  395. package/dist/oidc/account-finder.js.map +1 -0
  396. package/dist/oidc/adapter-factory.d.ts +90 -0
  397. package/dist/oidc/adapter-factory.d.ts.map +1 -0
  398. package/dist/oidc/adapter-factory.js +165 -0
  399. package/dist/oidc/adapter-factory.js.map +1 -0
  400. package/dist/oidc/configuration.d.ts +155 -0
  401. package/dist/oidc/configuration.d.ts.map +1 -0
  402. package/dist/oidc/configuration.js +531 -0
  403. package/dist/oidc/configuration.js.map +1 -0
  404. package/dist/oidc/postgres-adapter.d.ts +159 -0
  405. package/dist/oidc/postgres-adapter.d.ts.map +1 -0
  406. package/dist/oidc/postgres-adapter.js +222 -0
  407. package/dist/oidc/postgres-adapter.js.map +1 -0
  408. package/dist/oidc/protocol-security-observer.d.ts +38 -0
  409. package/dist/oidc/protocol-security-observer.d.ts.map +1 -0
  410. package/dist/oidc/protocol-security-observer.js +93 -0
  411. package/dist/oidc/protocol-security-observer.js.map +1 -0
  412. package/dist/oidc/provider.d.ts +37 -0
  413. package/dist/oidc/provider.d.ts.map +1 -0
  414. package/dist/oidc/provider.js +71 -0
  415. package/dist/oidc/provider.js.map +1 -0
  416. package/dist/oidc/redis-adapter.d.ts +140 -0
  417. package/dist/oidc/redis-adapter.d.ts.map +1 -0
  418. package/dist/oidc/redis-adapter.js +344 -0
  419. package/dist/oidc/redis-adapter.js.map +1 -0
  420. package/dist/organizations/cache.d.ts +60 -0
  421. package/dist/organizations/cache.d.ts.map +1 -0
  422. package/dist/organizations/cache.js +157 -0
  423. package/dist/organizations/cache.js.map +1 -0
  424. package/dist/organizations/errors.d.ts +25 -0
  425. package/dist/organizations/errors.d.ts.map +1 -0
  426. package/dist/organizations/errors.js +31 -0
  427. package/dist/organizations/errors.js.map +1 -0
  428. package/dist/organizations/index.d.ts +15 -0
  429. package/dist/organizations/index.d.ts.map +1 -0
  430. package/dist/organizations/index.js +15 -0
  431. package/dist/organizations/index.js.map +1 -0
  432. package/dist/organizations/repository.d.ts +183 -0
  433. package/dist/organizations/repository.d.ts.map +1 -0
  434. package/dist/organizations/repository.js +354 -0
  435. package/dist/organizations/repository.js.map +1 -0
  436. package/dist/organizations/service.d.ts +168 -0
  437. package/dist/organizations/service.d.ts.map +1 -0
  438. package/dist/organizations/service.js +511 -0
  439. package/dist/organizations/service.js.map +1 -0
  440. package/dist/organizations/slugs.d.ts +57 -0
  441. package/dist/organizations/slugs.d.ts.map +1 -0
  442. package/dist/organizations/slugs.js +130 -0
  443. package/dist/organizations/slugs.js.map +1 -0
  444. package/dist/organizations/types.d.ts +146 -0
  445. package/dist/organizations/types.d.ts.map +1 -0
  446. package/dist/organizations/types.js +49 -0
  447. package/dist/organizations/types.js.map +1 -0
  448. package/dist/rbac/cache.d.ts +110 -0
  449. package/dist/rbac/cache.d.ts.map +1 -0
  450. package/dist/rbac/cache.js +271 -0
  451. package/dist/rbac/cache.js.map +1 -0
  452. package/dist/rbac/errors.d.ts +34 -0
  453. package/dist/rbac/errors.d.ts.map +1 -0
  454. package/dist/rbac/errors.js +43 -0
  455. package/dist/rbac/errors.js.map +1 -0
  456. package/dist/rbac/index.d.ts +17 -0
  457. package/dist/rbac/index.d.ts.map +1 -0
  458. package/dist/rbac/index.js +21 -0
  459. package/dist/rbac/index.js.map +1 -0
  460. package/dist/rbac/mapping-repository.d.ts +121 -0
  461. package/dist/rbac/mapping-repository.d.ts.map +1 -0
  462. package/dist/rbac/mapping-repository.js +224 -0
  463. package/dist/rbac/mapping-repository.js.map +1 -0
  464. package/dist/rbac/permission-repository.d.ts +100 -0
  465. package/dist/rbac/permission-repository.d.ts.map +1 -0
  466. package/dist/rbac/permission-repository.js +190 -0
  467. package/dist/rbac/permission-repository.js.map +1 -0
  468. package/dist/rbac/permission-service.d.ts +85 -0
  469. package/dist/rbac/permission-service.d.ts.map +1 -0
  470. package/dist/rbac/permission-service.js +179 -0
  471. package/dist/rbac/permission-service.js.map +1 -0
  472. package/dist/rbac/role-repository.d.ts +104 -0
  473. package/dist/rbac/role-repository.d.ts.map +1 -0
  474. package/dist/rbac/role-repository.js +202 -0
  475. package/dist/rbac/role-repository.js.map +1 -0
  476. package/dist/rbac/role-service.d.ts +111 -0
  477. package/dist/rbac/role-service.d.ts.map +1 -0
  478. package/dist/rbac/role-service.js +256 -0
  479. package/dist/rbac/role-service.js.map +1 -0
  480. package/dist/rbac/slugs.d.ts +116 -0
  481. package/dist/rbac/slugs.d.ts.map +1 -0
  482. package/dist/rbac/slugs.js +178 -0
  483. package/dist/rbac/slugs.js.map +1 -0
  484. package/dist/rbac/types.d.ts +187 -0
  485. package/dist/rbac/types.d.ts.map +1 -0
  486. package/dist/rbac/types.js +75 -0
  487. package/dist/rbac/types.js.map +1 -0
  488. package/dist/rbac/user-role-service.d.ts +101 -0
  489. package/dist/rbac/user-role-service.d.ts.map +1 -0
  490. package/dist/rbac/user-role-service.js +166 -0
  491. package/dist/rbac/user-role-service.js.map +1 -0
  492. package/dist/routes/applications.d.ts +40 -0
  493. package/dist/routes/applications.d.ts.map +1 -0
  494. package/dist/routes/applications.js +284 -0
  495. package/dist/routes/applications.js.map +1 -0
  496. package/dist/routes/audit.d.ts +31 -0
  497. package/dist/routes/audit.d.ts.map +1 -0
  498. package/dist/routes/audit.js +140 -0
  499. package/dist/routes/audit.js.map +1 -0
  500. package/dist/routes/branding.d.ts +17 -0
  501. package/dist/routes/branding.d.ts.map +1 -0
  502. package/dist/routes/branding.js +104 -0
  503. package/dist/routes/branding.js.map +1 -0
  504. package/dist/routes/bulk.d.ts +37 -0
  505. package/dist/routes/bulk.d.ts.map +1 -0
  506. package/dist/routes/bulk.js +94 -0
  507. package/dist/routes/bulk.js.map +1 -0
  508. package/dist/routes/clients.d.ts +44 -0
  509. package/dist/routes/clients.d.ts.map +1 -0
  510. package/dist/routes/clients.js +353 -0
  511. package/dist/routes/clients.js.map +1 -0
  512. package/dist/routes/config.d.ts +35 -0
  513. package/dist/routes/config.d.ts.map +1 -0
  514. package/dist/routes/config.js +115 -0
  515. package/dist/routes/config.js.map +1 -0
  516. package/dist/routes/custom-claims.d.ts +38 -0
  517. package/dist/routes/custom-claims.d.ts.map +1 -0
  518. package/dist/routes/custom-claims.js +208 -0
  519. package/dist/routes/custom-claims.js.map +1 -0
  520. package/dist/routes/exports.d.ts +21 -0
  521. package/dist/routes/exports.d.ts.map +1 -0
  522. package/dist/routes/exports.js +98 -0
  523. package/dist/routes/exports.js.map +1 -0
  524. package/dist/routes/imports.d.ts +18 -0
  525. package/dist/routes/imports.d.ts.map +1 -0
  526. package/dist/routes/imports.js +72 -0
  527. package/dist/routes/imports.js.map +1 -0
  528. package/dist/routes/interactions.d.ts +111 -0
  529. package/dist/routes/interactions.d.ts.map +1 -0
  530. package/dist/routes/interactions.js +1074 -0
  531. package/dist/routes/interactions.js.map +1 -0
  532. package/dist/routes/invitation.d.ts +31 -0
  533. package/dist/routes/invitation.d.ts.map +1 -0
  534. package/dist/routes/invitation.js +342 -0
  535. package/dist/routes/invitation.js.map +1 -0
  536. package/dist/routes/keys.d.ts +28 -0
  537. package/dist/routes/keys.d.ts.map +1 -0
  538. package/dist/routes/keys.js +91 -0
  539. package/dist/routes/keys.js.map +1 -0
  540. package/dist/routes/magic-link.d.ts +43 -0
  541. package/dist/routes/magic-link.d.ts.map +1 -0
  542. package/dist/routes/magic-link.js +264 -0
  543. package/dist/routes/magic-link.js.map +1 -0
  544. package/dist/routes/organizations.d.ts +38 -0
  545. package/dist/routes/organizations.d.ts.map +1 -0
  546. package/dist/routes/organizations.js +347 -0
  547. package/dist/routes/organizations.js.map +1 -0
  548. package/dist/routes/password-reset.d.ts +65 -0
  549. package/dist/routes/password-reset.d.ts.map +1 -0
  550. package/dist/routes/password-reset.js +493 -0
  551. package/dist/routes/password-reset.js.map +1 -0
  552. package/dist/routes/permissions.d.ts +33 -0
  553. package/dist/routes/permissions.d.ts.map +1 -0
  554. package/dist/routes/permissions.js +166 -0
  555. package/dist/routes/permissions.js.map +1 -0
  556. package/dist/routes/roles.d.ts +37 -0
  557. package/dist/routes/roles.d.ts.map +1 -0
  558. package/dist/routes/roles.js +222 -0
  559. package/dist/routes/roles.js.map +1 -0
  560. package/dist/routes/sessions.d.ts +37 -0
  561. package/dist/routes/sessions.d.ts.map +1 -0
  562. package/dist/routes/sessions.js +121 -0
  563. package/dist/routes/sessions.js.map +1 -0
  564. package/dist/routes/stats.d.ts +28 -0
  565. package/dist/routes/stats.d.ts.map +1 -0
  566. package/dist/routes/stats.js +65 -0
  567. package/dist/routes/stats.js.map +1 -0
  568. package/dist/routes/two-factor-admin.d.ts +54 -0
  569. package/dist/routes/two-factor-admin.d.ts.map +1 -0
  570. package/dist/routes/two-factor-admin.js +344 -0
  571. package/dist/routes/two-factor-admin.js.map +1 -0
  572. package/dist/routes/two-factor.d.ts +31 -0
  573. package/dist/routes/two-factor.d.ts.map +1 -0
  574. package/dist/routes/two-factor.js +595 -0
  575. package/dist/routes/two-factor.js.map +1 -0
  576. package/dist/routes/user-roles.d.ts +33 -0
  577. package/dist/routes/user-roles.d.ts.map +1 -0
  578. package/dist/routes/user-roles.js +129 -0
  579. package/dist/routes/user-roles.js.map +1 -0
  580. package/dist/routes/users.d.ts +61 -0
  581. package/dist/routes/users.d.ts.map +1 -0
  582. package/dist/routes/users.js +868 -0
  583. package/dist/routes/users.js.map +1 -0
  584. package/dist/security/decision-context.d.ts +52 -0
  585. package/dist/security/decision-context.d.ts.map +1 -0
  586. package/dist/security/decision-context.js +150 -0
  587. package/dist/security/decision-context.js.map +1 -0
  588. package/dist/security/decision-event.d.ts +128 -0
  589. package/dist/security/decision-event.d.ts.map +1 -0
  590. package/dist/security/decision-event.js +225 -0
  591. package/dist/security/decision-event.js.map +1 -0
  592. package/dist/security/transport-decision.d.ts +6 -0
  593. package/dist/security/transport-decision.d.ts.map +1 -0
  594. package/dist/security/transport-decision.js +37 -0
  595. package/dist/security/transport-decision.js.map +1 -0
  596. package/dist/server.d.ts +50 -0
  597. package/dist/server.d.ts.map +1 -0
  598. package/dist/server.js +491 -0
  599. package/dist/server.js.map +1 -0
  600. package/dist/two-factor/cache.d.ts +47 -0
  601. package/dist/two-factor/cache.d.ts.map +1 -0
  602. package/dist/two-factor/cache.js +122 -0
  603. package/dist/two-factor/cache.js.map +1 -0
  604. package/dist/two-factor/crypto.d.ts +41 -0
  605. package/dist/two-factor/crypto.d.ts.map +1 -0
  606. package/dist/two-factor/crypto.js +94 -0
  607. package/dist/two-factor/crypto.js.map +1 -0
  608. package/dist/two-factor/errors.d.ts +82 -0
  609. package/dist/two-factor/errors.d.ts.map +1 -0
  610. package/dist/two-factor/errors.js +112 -0
  611. package/dist/two-factor/errors.js.map +1 -0
  612. package/dist/two-factor/index.d.ts +18 -0
  613. package/dist/two-factor/index.d.ts.map +1 -0
  614. package/dist/two-factor/index.js +25 -0
  615. package/dist/two-factor/index.js.map +1 -0
  616. package/dist/two-factor/otp.d.ts +43 -0
  617. package/dist/two-factor/otp.d.ts.map +1 -0
  618. package/dist/two-factor/otp.js +57 -0
  619. package/dist/two-factor/otp.js.map +1 -0
  620. package/dist/two-factor/recovery.d.ts +45 -0
  621. package/dist/two-factor/recovery.d.ts.map +1 -0
  622. package/dist/two-factor/recovery.js +104 -0
  623. package/dist/two-factor/recovery.js.map +1 -0
  624. package/dist/two-factor/repository.d.ts +156 -0
  625. package/dist/two-factor/repository.d.ts.map +1 -0
  626. package/dist/two-factor/repository.js +251 -0
  627. package/dist/two-factor/repository.js.map +1 -0
  628. package/dist/two-factor/service.d.ts +232 -0
  629. package/dist/two-factor/service.d.ts.map +1 -0
  630. package/dist/two-factor/service.js +599 -0
  631. package/dist/two-factor/service.js.map +1 -0
  632. package/dist/two-factor/totp.d.ts +57 -0
  633. package/dist/two-factor/totp.d.ts.map +1 -0
  634. package/dist/two-factor/totp.js +96 -0
  635. package/dist/two-factor/totp.js.map +1 -0
  636. package/dist/two-factor/types.d.ts +152 -0
  637. package/dist/two-factor/types.d.ts.map +1 -0
  638. package/dist/two-factor/types.js +64 -0
  639. package/dist/two-factor/types.js.map +1 -0
  640. package/dist/users/cache.d.ts +49 -0
  641. package/dist/users/cache.d.ts.map +1 -0
  642. package/dist/users/cache.js +140 -0
  643. package/dist/users/cache.js.map +1 -0
  644. package/dist/users/claims.d.ts +67 -0
  645. package/dist/users/claims.d.ts.map +1 -0
  646. package/dist/users/claims.js +104 -0
  647. package/dist/users/claims.js.map +1 -0
  648. package/dist/users/errors.d.ts +25 -0
  649. package/dist/users/errors.d.ts.map +1 -0
  650. package/dist/users/errors.js +31 -0
  651. package/dist/users/errors.js.map +1 -0
  652. package/dist/users/gdpr.d.ts +110 -0
  653. package/dist/users/gdpr.d.ts.map +1 -0
  654. package/dist/users/gdpr.js +211 -0
  655. package/dist/users/gdpr.js.map +1 -0
  656. package/dist/users/index.d.ts +20 -0
  657. package/dist/users/index.d.ts.map +1 -0
  658. package/dist/users/index.js +19 -0
  659. package/dist/users/index.js.map +1 -0
  660. package/dist/users/password.d.ts +85 -0
  661. package/dist/users/password.d.ts.map +1 -0
  662. package/dist/users/password.js +138 -0
  663. package/dist/users/password.js.map +1 -0
  664. package/dist/users/repository.d.ts +263 -0
  665. package/dist/users/repository.d.ts.map +1 -0
  666. package/dist/users/repository.js +499 -0
  667. package/dist/users/repository.js.map +1 -0
  668. package/dist/users/service.d.ts +299 -0
  669. package/dist/users/service.d.ts.map +1 -0
  670. package/dist/users/service.js +698 -0
  671. package/dist/users/service.js.map +1 -0
  672. package/dist/users/types.d.ts +220 -0
  673. package/dist/users/types.d.ts.map +1 -0
  674. package/dist/users/types.js +77 -0
  675. package/dist/users/types.js.map +1 -0
  676. package/locales/default/en/common.json +10 -0
  677. package/locales/default/en/consent.json +13 -0
  678. package/locales/default/en/emails.json +17 -0
  679. package/locales/default/en/errors.json +21 -0
  680. package/locales/default/en/forgot-password.json +11 -0
  681. package/locales/default/en/invitation.json +18 -0
  682. package/locales/default/en/login.json +17 -0
  683. package/locales/default/en/logout.json +9 -0
  684. package/locales/default/en/magic-link.json +12 -0
  685. package/locales/default/en/reset-password.json +16 -0
  686. package/locales/default/en/two-factor.json +29 -0
  687. package/migrations/.gitkeep +0 -0
  688. package/migrations/001_extensions.sql +22 -0
  689. package/migrations/002_organizations.sql +43 -0
  690. package/migrations/003_applications.sql +50 -0
  691. package/migrations/004_clients.sql +74 -0
  692. package/migrations/005_users.sql +119 -0
  693. package/migrations/006_roles_permissions.sql +80 -0
  694. package/migrations/007_custom_claims.sql +55 -0
  695. package/migrations/008_config.sql +51 -0
  696. package/migrations/009_audit_log.sql +31 -0
  697. package/migrations/010_oidc_adapter.sql +34 -0
  698. package/migrations/011_seed.sql +53 -0
  699. package/migrations/012_two_factor.sql +88 -0
  700. package/migrations/013_client_secret_sha256.sql +22 -0
  701. package/migrations/014_login_methods.sql +34 -0
  702. package/migrations/015_signing_key_encryption.sql +20 -0
  703. package/migrations/016_failed_login_count.sql +27 -0
  704. package/migrations/017_audit_retention.sql +11 -0
  705. package/migrations/018_admin_api_enhancements.sql +78 -0
  706. package/migrations/019_invitation_details.sql +27 -0
  707. package/migrations/020_two_factor_admin_permission.sql +108 -0
  708. package/migrations/021_auth_recovery_jobs.sql +74 -0
  709. package/migrations/022_recovery_artifact_ownership.sql +25 -0
  710. package/migrations/023_magic_link_authority.sql +39 -0
  711. package/package.json +106 -0
  712. package/templates/default/emails/invitation.hbs +39 -0
  713. package/templates/default/emails/invitation.txt.hbs +18 -0
  714. package/templates/default/emails/magic-link.hbs +30 -0
  715. package/templates/default/emails/magic-link.txt.hbs +11 -0
  716. package/templates/default/emails/otp-code.hbs +31 -0
  717. package/templates/default/emails/otp-code.txt.hbs +15 -0
  718. package/templates/default/emails/password-changed.hbs +24 -0
  719. package/templates/default/emails/password-changed.txt.hbs +7 -0
  720. package/templates/default/emails/password-reset.hbs +30 -0
  721. package/templates/default/emails/password-reset.txt.hbs +11 -0
  722. package/templates/default/emails/welcome.hbs +25 -0
  723. package/templates/default/emails/welcome.txt.hbs +9 -0
  724. package/templates/default/layouts/main.hbs +49 -0
  725. package/templates/default/pages/accept-invite.hbs +25 -0
  726. package/templates/default/pages/consent.hbs +27 -0
  727. package/templates/default/pages/error.hbs +15 -0
  728. package/templates/default/pages/forgot-password.hbs +21 -0
  729. package/templates/default/pages/invite-expired.hbs +6 -0
  730. package/templates/default/pages/invite-success.hbs +9 -0
  731. package/templates/default/pages/login.hbs +108 -0
  732. package/templates/default/pages/logout-success.hbs +5 -0
  733. package/templates/default/pages/logout.hbs +24 -0
  734. package/templates/default/pages/magic-link-sent.hbs +10 -0
  735. package/templates/default/pages/magic-link-success.hbs +17 -0
  736. package/templates/default/pages/reset-password.hbs +20 -0
  737. package/templates/default/pages/reset-success.hbs +9 -0
  738. package/templates/default/pages/two-factor-setup.hbs +65 -0
  739. package/templates/default/pages/two-factor-verify.hbs +77 -0
  740. package/templates/default/partials/flash-messages.hbs +10 -0
  741. package/templates/default/partials/footer.hbs +4 -0
  742. package/templates/default/partials/header.hbs +8 -0
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Admin API CORS allow-list middleware.
3
+ *
4
+ * Implements a strict CORS policy for `/api/admin/*` endpoints.
5
+ * By default (empty `adminCorsOrigins` config), **no CORS headers are
6
+ * emitted** — all cross-origin requests are blocked by the browser.
7
+ *
8
+ * When `ADMIN_CORS_ORIGINS` is configured with one or more origin URLs,
9
+ * only those exact origins receive CORS headers. This is intended for
10
+ * operators who deploy a web-based admin dashboard on a different origin.
11
+ *
12
+ * Non-browser clients (CLI, same-origin requests) never send an `Origin`
13
+ * header, so they pass through this middleware untouched.
14
+ *
15
+ * Placement: mount after the admin metadata router and before
16
+ * `setAdminAuthProvider()` — preflight `OPTIONS` requests don't carry
17
+ * an `Authorization` header, so CORS must respond before auth runs.
18
+ *
19
+ * @module middleware/admin-cors
20
+ */
21
+ // ---------------------------------------------------------------------------
22
+ // Constants — exported for test assertions
23
+ // ---------------------------------------------------------------------------
24
+ /** HTTP methods allowed for cross-origin admin API requests. */
25
+ export const CORS_ALLOWED_METHODS = 'GET, POST, PUT, PATCH, DELETE, OPTIONS';
26
+ /** HTTP headers allowed in cross-origin admin API requests. */
27
+ export const CORS_ALLOWED_HEADERS = 'Authorization, Content-Type';
28
+ /** Preflight cache duration in seconds (24 hours). */
29
+ export const CORS_MAX_AGE = '86400';
30
+ // ---------------------------------------------------------------------------
31
+ // Middleware factory
32
+ // ---------------------------------------------------------------------------
33
+ /**
34
+ * Create admin CORS middleware with the given application config.
35
+ *
36
+ * Uses a `Set` for O(1) origin lookup. The `Vary: Origin` header is
37
+ * required by the CORS specification when `Access-Control-Allow-Origin`
38
+ * is not the wildcard `*` — it tells caches that the response varies by
39
+ * the request's `Origin` header.
40
+ *
41
+ * @param config - Application config (reads `adminCorsOrigins`)
42
+ * @returns Koa middleware that handles CORS for `/api/admin/*` routes
43
+ */
44
+ export function adminCors(config) {
45
+ // Pre-compute the Set once at middleware creation time —
46
+ // config doesn't change at runtime.
47
+ const allowedOrigins = new Set(config.adminCorsOrigins);
48
+ return async function adminCorsMiddleware(ctx, next) {
49
+ // Only process requests to admin API paths.
50
+ // Non-admin paths (health, OIDC, interactions, etc.) are unaffected.
51
+ if (!ctx.path.startsWith('/api/admin')) {
52
+ return next();
53
+ }
54
+ const origin = ctx.get('Origin');
55
+ // No Origin header → not a cross-origin request (same-origin browser
56
+ // request, CLI tool, or server-to-server call). Pass through.
57
+ if (!origin) {
58
+ return next();
59
+ }
60
+ // Check if the requesting origin is in the allow-list.
61
+ // Only emit CORS headers when there's an explicit match.
62
+ if (allowedOrigins.size > 0 && allowedOrigins.has(origin)) {
63
+ ctx.set('Access-Control-Allow-Origin', origin);
64
+ ctx.set('Access-Control-Allow-Credentials', 'true');
65
+ ctx.set('Access-Control-Allow-Methods', CORS_ALLOWED_METHODS);
66
+ ctx.set('Access-Control-Allow-Headers', CORS_ALLOWED_HEADERS);
67
+ ctx.set('Access-Control-Max-Age', CORS_MAX_AGE);
68
+ // Vary: Origin is required by CORS spec — responses differ per origin.
69
+ ctx.set('Vary', 'Origin');
70
+ }
71
+ // Handle preflight requests — browsers send OPTIONS before the real
72
+ // request to check CORS policy. Respond with 204 regardless of
73
+ // whether the origin matched: if headers weren't set, the browser
74
+ // sees no CORS permission and blocks the follow-up request.
75
+ if (ctx.method === 'OPTIONS') {
76
+ ctx.status = 204;
77
+ ctx.body = '';
78
+ return;
79
+ }
80
+ return next();
81
+ };
82
+ }
83
+ //# sourceMappingURL=admin-cors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-cors.js","sourceRoot":"","sources":["../../src/middleware/admin-cors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAKH,8EAA8E;AAC9E,2CAA2C;AAC3C,8EAA8E;AAE9E,gEAAgE;AAChE,MAAM,CAAC,MAAM,oBAAoB,GAAG,wCAAwC,CAAC;AAE7E,+DAA+D;AAC/D,MAAM,CAAC,MAAM,oBAAoB,GAAG,6BAA6B,CAAC;AAElE,sDAAsD;AACtD,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC;AAEpC,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E;;;;;;;;;;GAUG;AACH,MAAM,UAAU,SAAS,CAAC,MAAiB;IACzC,yDAAyD;IACzD,oCAAoC;IACpC,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAExD,OAAO,KAAK,UAAU,mBAAmB,CAAC,GAAG,EAAE,IAAI;QACjD,4CAA4C;QAC5C,qEAAqE;QACrE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YACvC,OAAO,IAAI,EAAE,CAAC;QAChB,CAAC;QAED,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAEjC,qEAAqE;QACrE,+DAA+D;QAC/D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,EAAE,CAAC;QAChB,CAAC;QAED,uDAAuD;QACvD,yDAAyD;QACzD,IAAI,cAAc,CAAC,IAAI,GAAG,CAAC,IAAI,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1D,GAAG,CAAC,GAAG,CAAC,6BAA6B,EAAE,MAAM,CAAC,CAAC;YAC/C,GAAG,CAAC,GAAG,CAAC,kCAAkC,EAAE,MAAM,CAAC,CAAC;YACpD,GAAG,CAAC,GAAG,CAAC,8BAA8B,EAAE,oBAAoB,CAAC,CAAC;YAC9D,GAAG,CAAC,GAAG,CAAC,8BAA8B,EAAE,oBAAoB,CAAC,CAAC;YAC9D,GAAG,CAAC,GAAG,CAAC,wBAAwB,EAAE,YAAY,CAAC,CAAC;YAChD,uEAAuE;YACvE,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC5B,CAAC;QAED,oEAAoE;QACpE,gEAAgE;QAChE,kEAAkE;QAClE,4DAA4D;QAC5D,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC7B,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;YACjB,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC;YACd,OAAO;QACT,CAAC;QAED,OAAO,IAAI,EAAE,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { Middleware } from 'koa';
2
+ /**
3
+ * Atomically bind successful administrative mutations to one durable audit row.
4
+ *
5
+ * Bulk and import own specialized transaction/result semantics and are excluded here. Every other
6
+ * state-changing admin request shares one request-local PostgreSQL client across repository calls.
7
+ */
8
+ export declare function adminMutationAudit(): Middleware;
9
+ //# sourceMappingURL=admin-mutation-audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-mutation-audit.d.ts","sourceRoot":"","sources":["../../src/middleware/admin-mutation-audit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AA2BtC;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,UAAU,CA2C/C"}
@@ -0,0 +1,76 @@
1
+ import { writeAuditLogInTransaction } from '../lib/audit-log.js';
2
+ import { getDatabaseTransactionClient, runDatabaseTransaction } from '../lib/database.js';
3
+ import { normalizedRouteTemplate, recordSecurityDecision } from '../security/decision-context.js';
4
+ const MUTATION_METHODS = new Set(['POST', 'PUT', 'PATCH', 'DELETE']);
5
+ const SELF_MANAGED_MUTATION_PREFIXES = ['/api/admin/bulk', '/api/admin/import'];
6
+ /** Internal signal used to roll back a handled non-success response without replacing its body. */
7
+ class HandledMutationRejection extends Error {
8
+ }
9
+ /** Koa-compatible errors retain their public status after the transaction rolls back. */
10
+ function isPublicHttpError(error) {
11
+ if (!(error instanceof Error))
12
+ return false;
13
+ const status = Reflect.get(error, 'status');
14
+ return typeof status === 'number' && status >= 400 && status < 500;
15
+ }
16
+ /** Return whether a request belongs to the generic administrative mutation transaction. */
17
+ function ownsAdministrativeMutation(method, path) {
18
+ return (MUTATION_METHODS.has(method) &&
19
+ path.startsWith('/api/admin/') &&
20
+ !SELF_MANAGED_MUTATION_PREFIXES.some((prefix) => path.startsWith(prefix)));
21
+ }
22
+ /**
23
+ * Atomically bind successful administrative mutations to one durable audit row.
24
+ *
25
+ * Bulk and import own specialized transaction/result semantics and are excluded here. Every other
26
+ * state-changing admin request shares one request-local PostgreSQL client across repository calls.
27
+ */
28
+ export function adminMutationAudit() {
29
+ return async (ctx, next) => {
30
+ if (!ownsAdministrativeMutation(ctx.method, ctx.path)) {
31
+ await next();
32
+ return;
33
+ }
34
+ try {
35
+ await runDatabaseTransaction(async () => {
36
+ await next();
37
+ if (ctx.status >= 400)
38
+ throw new HandledMutationRejection();
39
+ const client = getDatabaseTransactionClient();
40
+ if (!client)
41
+ throw new Error('Administrative mutation transaction is unavailable');
42
+ const actor = ctx.state.adminUser;
43
+ if (!actor)
44
+ throw new Error('Administrative mutation actor is unavailable');
45
+ await writeAuditLogInTransaction(client, {
46
+ organizationId: actor.organizationId,
47
+ actorId: actor.id,
48
+ eventType: 'admin.mutation.committed',
49
+ eventCategory: 'admin',
50
+ metadata: {
51
+ method: ctx.method,
52
+ routeTemplate: normalizedRouteTemplate(ctx),
53
+ },
54
+ });
55
+ });
56
+ }
57
+ catch (error) {
58
+ if (error instanceof HandledMutationRejection)
59
+ return;
60
+ if (isPublicHttpError(error))
61
+ throw error;
62
+ recordSecurityDecision(ctx, {
63
+ decisionPoint: 'handler',
64
+ reasonCode: 'handler-failed',
65
+ outcome: 'error',
66
+ });
67
+ ctx.status = 503;
68
+ ctx.body = {
69
+ error: 'Administrative request could not be completed',
70
+ code: 'admin_mutation_unavailable',
71
+ requestId: ctx.state.requestId,
72
+ };
73
+ }
74
+ };
75
+ }
76
+ //# sourceMappingURL=admin-mutation-audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-mutation-audit.js","sourceRoot":"","sources":["../../src/middleware/admin-mutation-audit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Admin API rate limiter middleware.
3
+ *
4
+ * Protects state-changing admin endpoints (POST/PUT/PATCH/DELETE on
5
+ * `/api/admin/*`) against brute-force attacks and automated abuse.
6
+ * GET requests are read-only and pass through without rate limiting.
7
+ *
8
+ * Key format: `ratelimit:admin:{ip}` — per-IP only since admin-auth
9
+ * already restricts access to authenticated super-admin users. There
10
+ * is no per-user key because the IP-based counter is sufficient:
11
+ * legitimate admins won't make 60 write requests per minute, and
12
+ * attackers from the same IP are blocked regardless of identity.
13
+ *
14
+ * Limit: 60 requests / 60 seconds (sliding window).
15
+ *
16
+ * Reuses `checkRateLimit()` from `src/auth/rate-limiter.ts` which
17
+ * provides Redis INCR+EXPIRE sliding window and graceful degradation
18
+ * on Redis failure (allows request + logs warning).
19
+ *
20
+ * Placement: mount as global middleware in `src/server.ts` before the
21
+ * admin route routers. The path + method check ensures only write
22
+ * requests to `/api/admin/*` are counted.
23
+ *
24
+ * @module middleware/admin-rate-limiter
25
+ */
26
+ import type { Middleware } from 'koa';
27
+ import type { RateLimitConfig } from '../auth/rate-limiter.js';
28
+ /** Path prefix for admin API routes. */
29
+ export declare const ADMIN_PATH_PREFIX = "/api/admin/";
30
+ /**
31
+ * HTTP methods that are considered state-changing (write operations).
32
+ * Only these methods are rate-limited; GET/HEAD/OPTIONS pass through.
33
+ */
34
+ export declare const ADMIN_WRITE_METHODS: Set<string>;
35
+ /**
36
+ * Rate limit configuration for admin API write operations.
37
+ *
38
+ * 60 requests per 60-second window — generous enough for admin
39
+ * workflows (bulk operations, rapid CRUD during setup) while catching
40
+ * automated abuse or runaway scripts.
41
+ */
42
+ export declare const ADMIN_RATE_LIMIT: RateLimitConfig;
43
+ /**
44
+ * Create the admin API rate limiter middleware.
45
+ *
46
+ * Only intercepts requests that match ALL of:
47
+ * - Path starts with `/api/admin/`
48
+ * - Method is POST, PUT, PATCH, or DELETE
49
+ *
50
+ * Sets informational `X-RateLimit-*` headers on every matched response
51
+ * and returns `429` with a JSON error body when the limit is exceeded.
52
+ *
53
+ * @returns Koa middleware that rate-limits admin API write operations
54
+ */
55
+ export declare function adminRateLimiter(): Middleware;
56
+ //# sourceMappingURL=admin-rate-limiter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-rate-limiter.d.ts","sourceRoot":"","sources":["../../src/middleware/admin-rate-limiter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAEtC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAO/D,wCAAwC;AACxC,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAE/C;;;GAGG;AACH,eAAO,MAAM,mBAAmB,aAA8C,CAAC;AAE/E;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,EAAE,eAG9B,CAAC;AAMF;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,IAAI,UAAU,CAyC7C"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Admin API rate limiter middleware.
3
+ *
4
+ * Protects state-changing admin endpoints (POST/PUT/PATCH/DELETE on
5
+ * `/api/admin/*`) against brute-force attacks and automated abuse.
6
+ * GET requests are read-only and pass through without rate limiting.
7
+ *
8
+ * Key format: `ratelimit:admin:{ip}` — per-IP only since admin-auth
9
+ * already restricts access to authenticated super-admin users. There
10
+ * is no per-user key because the IP-based counter is sufficient:
11
+ * legitimate admins won't make 60 write requests per minute, and
12
+ * attackers from the same IP are blocked regardless of identity.
13
+ *
14
+ * Limit: 60 requests / 60 seconds (sliding window).
15
+ *
16
+ * Reuses `checkRateLimit()` from `src/auth/rate-limiter.ts` which
17
+ * provides Redis INCR+EXPIRE sliding window and graceful degradation
18
+ * on Redis failure (allows request + logs warning).
19
+ *
20
+ * Placement: mount as global middleware in `src/server.ts` before the
21
+ * admin route routers. The path + method check ensures only write
22
+ * requests to `/api/admin/*` are counted.
23
+ *
24
+ * @module middleware/admin-rate-limiter
25
+ */
26
+ import { checkRateLimit } from '../auth/rate-limiter.js';
27
+ import { logger } from '../lib/logger.js';
28
+ // ---------------------------------------------------------------------------
29
+ // Constants — exported for test assertions and documentation
30
+ // ---------------------------------------------------------------------------
31
+ /** Path prefix for admin API routes. */
32
+ export const ADMIN_PATH_PREFIX = '/api/admin/';
33
+ /**
34
+ * HTTP methods that are considered state-changing (write operations).
35
+ * Only these methods are rate-limited; GET/HEAD/OPTIONS pass through.
36
+ */
37
+ export const ADMIN_WRITE_METHODS = new Set(['POST', 'PUT', 'PATCH', 'DELETE']);
38
+ /**
39
+ * Rate limit configuration for admin API write operations.
40
+ *
41
+ * 60 requests per 60-second window — generous enough for admin
42
+ * workflows (bulk operations, rapid CRUD during setup) while catching
43
+ * automated abuse or runaway scripts.
44
+ */
45
+ export const ADMIN_RATE_LIMIT = {
46
+ max: 60,
47
+ windowSeconds: 60,
48
+ };
49
+ // ---------------------------------------------------------------------------
50
+ // Middleware factory
51
+ // ---------------------------------------------------------------------------
52
+ /**
53
+ * Create the admin API rate limiter middleware.
54
+ *
55
+ * Only intercepts requests that match ALL of:
56
+ * - Path starts with `/api/admin/`
57
+ * - Method is POST, PUT, PATCH, or DELETE
58
+ *
59
+ * Sets informational `X-RateLimit-*` headers on every matched response
60
+ * and returns `429` with a JSON error body when the limit is exceeded.
61
+ *
62
+ * @returns Koa middleware that rate-limits admin API write operations
63
+ */
64
+ export function adminRateLimiter() {
65
+ return async function adminRateLimiterMiddleware(ctx, next) {
66
+ // Only rate-limit write methods on admin API paths — GETs and
67
+ // non-admin paths pass through immediately without touching Redis.
68
+ if (!ctx.path.startsWith(ADMIN_PATH_PREFIX) || !ADMIN_WRITE_METHODS.has(ctx.method)) {
69
+ return next();
70
+ }
71
+ // Per-IP key — no user identifier needed since admin-auth already
72
+ // filters out unauthenticated requests, and legitimate admins
73
+ // won't hit 60 writes/minute under normal conditions.
74
+ const key = `ratelimit:admin:${ctx.ip}`;
75
+ const result = await checkRateLimit(key, ADMIN_RATE_LIMIT);
76
+ // Informational headers on all matched responses — helps admin
77
+ // clients (CLI, dashboards) monitor their usage.
78
+ ctx.set('X-RateLimit-Limit', String(ADMIN_RATE_LIMIT.max));
79
+ ctx.set('X-RateLimit-Remaining', String(result.remaining));
80
+ if (!result.allowed) {
81
+ logger.warn({
82
+ action: 'admin_rate_limit_exceeded',
83
+ method: ctx.method,
84
+ }, 'Admin API rate limit exceeded');
85
+ ctx.status = 429;
86
+ ctx.set('Retry-After', String(result.retryAfter));
87
+ ctx.body = {
88
+ error: 'Too Many Requests',
89
+ message: 'Admin API rate limit exceeded. Please try again later.',
90
+ retry_after: result.retryAfter,
91
+ };
92
+ return;
93
+ }
94
+ return next();
95
+ };
96
+ }
97
+ //# sourceMappingURL=admin-rate-limiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-rate-limiter.js","sourceRoot":"","sources":["../../src/middleware/admin-rate-limiter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEzD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,8EAA8E;AAC9E,6DAA6D;AAC7D,8EAA8E;AAE9E,wCAAwC;AACxC,MAAM,CAAC,MAAM,iBAAiB,GAAG,aAAa,CAAC;AAE/C;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;AAE/E;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAoB;IAC/C,GAAG,EAAE,EAAE;IACP,aAAa,EAAE,EAAE;CAClB,CAAC;AAEF,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,KAAK,UAAU,0BAA0B,CAAC,GAAG,EAAE,IAAI;QACxD,8DAA8D;QAC9D,mEAAmE;QACnE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACpF,OAAO,IAAI,EAAE,CAAC;QAChB,CAAC;QAED,kEAAkE;QAClE,8DAA8D;QAC9D,sDAAsD;QACtD,MAAM,GAAG,GAAG,mBAAmB,GAAG,CAAC,EAAE,EAAE,CAAC;QAExC,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;QAE3D,+DAA+D;QAC/D,iDAAiD;QACjD,GAAG,CAAC,GAAG,CAAC,mBAAmB,EAAE,MAAM,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3D,GAAG,CAAC,GAAG,CAAC,uBAAuB,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;QAE3D,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,CAAC,IAAI,CACT;gBACE,MAAM,EAAE,2BAA2B;gBACnC,MAAM,EAAE,GAAG,CAAC,MAAM;aACnB,EACD,+BAA+B,CAChC,CAAC;YAEF,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;YACjB,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;YAClD,GAAG,CAAC,IAAI,GAAG;gBACT,KAAK,EAAE,mBAAmB;gBAC1B,OAAO,EAAE,wDAAwD;gBACjE,WAAW,EAAE,MAAM,CAAC,UAAU;aAC/B,CAAC;YACF,OAAO;QACT,CAAC;QAED,OAAO,IAAI,EAAE,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * SHA-256 client secret pre-hashing middleware.
3
+ *
4
+ * Transforms client_secret values in incoming requests by replacing
5
+ * the plaintext with its SHA-256 hash BEFORE oidc-provider processes them.
6
+ *
7
+ * Supports:
8
+ * - client_secret_basic: Authorization: Basic base64(client_id:secret)
9
+ * - client_secret_post: client_secret in POST body
10
+ *
11
+ * This allows oidc-provider's built-in string comparison to work
12
+ * with our SHA-256-hashed secret storage — no monkey-patching needed.
13
+ *
14
+ * How it works:
15
+ * 1. At secret generation: SHA-256(secret) is stored in the DB
16
+ * 2. At request time: This middleware hashes the presented secret
17
+ * 3. In the adapter: findForOidc() returns SHA-256 hash as client_secret
18
+ * 4. oidc-provider compares: SHA-256(presented) === SHA-256(stored) → ✅ MATCH
19
+ *
20
+ * Security: SHA-256 is appropriate for machine-generated, high-entropy
21
+ * client secrets (48 bytes / 384 bits of randomness).
22
+ */
23
+ import type { Middleware } from 'koa';
24
+ /**
25
+ * Create middleware that pre-hashes client secrets with SHA-256.
26
+ *
27
+ * Must be mounted BEFORE oidc-provider's callback handler on the
28
+ * OIDC router. Transparently transforms secrets so oidc-provider
29
+ * can compare them against stored SHA-256 hashes.
30
+ *
31
+ * @returns Koa middleware function
32
+ */
33
+ export declare function clientSecretHash(): Middleware;
34
+ //# sourceMappingURL=client-secret-hash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-secret-hash.d.ts","sourceRoot":"","sources":["../../src/middleware/client-secret-hash.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAStC;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,IAAI,UAAU,CAqC7C"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * SHA-256 client secret pre-hashing middleware.
3
+ *
4
+ * Transforms client_secret values in incoming requests by replacing
5
+ * the plaintext with its SHA-256 hash BEFORE oidc-provider processes them.
6
+ *
7
+ * Supports:
8
+ * - client_secret_basic: Authorization: Basic base64(client_id:secret)
9
+ * - client_secret_post: client_secret in POST body
10
+ *
11
+ * This allows oidc-provider's built-in string comparison to work
12
+ * with our SHA-256-hashed secret storage — no monkey-patching needed.
13
+ *
14
+ * How it works:
15
+ * 1. At secret generation: SHA-256(secret) is stored in the DB
16
+ * 2. At request time: This middleware hashes the presented secret
17
+ * 3. In the adapter: findForOidc() returns SHA-256 hash as client_secret
18
+ * 4. oidc-provider compares: SHA-256(presented) === SHA-256(stored) → ✅ MATCH
19
+ *
20
+ * Security: SHA-256 is appropriate for machine-generated, high-entropy
21
+ * client secrets (48 bytes / 384 bits of randomness).
22
+ */
23
+ import { createHash } from 'node:crypto';
24
+ /**
25
+ * Compute SHA-256 hash of a string, returned as hex.
26
+ */
27
+ function sha256(input) {
28
+ return createHash('sha256').update(input).digest('hex');
29
+ }
30
+ /**
31
+ * Create middleware that pre-hashes client secrets with SHA-256.
32
+ *
33
+ * Must be mounted BEFORE oidc-provider's callback handler on the
34
+ * OIDC router. Transparently transforms secrets so oidc-provider
35
+ * can compare them against stored SHA-256 hashes.
36
+ *
37
+ * @returns Koa middleware function
38
+ */
39
+ export function clientSecretHash() {
40
+ return async (ctx, next) => {
41
+ // Handle client_secret_basic: Authorization: Basic base64(client_id:secret)
42
+ const authHeader = ctx.headers.authorization;
43
+ if (authHeader && authHeader.startsWith('Basic ')) {
44
+ try {
45
+ const encoded = authHeader.slice(6); // strip 'Basic '
46
+ const decoded = Buffer.from(encoded, 'base64').toString('utf8');
47
+ const colonIndex = decoded.indexOf(':');
48
+ if (colonIndex !== -1) {
49
+ const clientId = decoded.slice(0, colonIndex);
50
+ const secret = decoded.slice(colonIndex + 1);
51
+ if (secret.length > 0) {
52
+ // Hash the secret and re-encode the Basic auth header
53
+ const hashedSecret = sha256(secret);
54
+ const newEncoded = Buffer.from(`${clientId}:${hashedSecret}`).toString('base64');
55
+ ctx.headers.authorization = `Basic ${newEncoded}`;
56
+ // Also update the raw request header for oidc-provider
57
+ ctx.req.headers.authorization = `Basic ${newEncoded}`;
58
+ }
59
+ }
60
+ }
61
+ catch {
62
+ // Malformed Basic auth — let oidc-provider handle the error
63
+ }
64
+ }
65
+ // Handle client_secret_post: client_secret in POST body
66
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
67
+ const body = ctx.request.body;
68
+ if (body && typeof body.client_secret === 'string' && body.client_secret.length > 0) {
69
+ body.client_secret = sha256(body.client_secret);
70
+ }
71
+ await next();
72
+ };
73
+ }
74
+ //# sourceMappingURL=client-secret-hash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-secret-hash.js","sourceRoot":"","sources":["../../src/middleware/client-secret-hash.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC;;GAEG;AACH,SAAS,MAAM,CAAC,KAAa;IAC3B,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,4EAA4E;QAC5E,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;QAC7C,IAAI,UAAU,IAAI,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClD,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,iBAAiB;gBACtD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;gBAChE,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAExC,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;oBACtB,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;oBAC9C,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;oBAE7C,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBACtB,sDAAsD;wBACtD,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;wBACpC,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,IAAI,YAAY,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;wBACjF,GAAG,CAAC,OAAO,CAAC,aAAa,GAAG,SAAS,UAAU,EAAE,CAAC;wBAClD,uDAAuD;wBACvD,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,GAAG,SAAS,UAAU,EAAE,CAAC;oBACxD,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,4DAA4D;YAC9D,CAAC;QACH,CAAC;QAED,wDAAwD;QACxD,8DAA8D;QAC9D,MAAM,IAAI,GAAI,GAAG,CAAC,OAAe,CAAC,IAAI,CAAC;QACvC,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,aAAa,KAAK,QAAQ,IAAI,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpF,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAClD,CAAC;QAED,MAAM,IAAI,EAAE,CAAC;IACf,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Middleware } from 'koa';
2
+ export declare function errorHandler(): Middleware;
3
+ //# sourceMappingURL=error-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-handler.d.ts","sourceRoot":"","sources":["../../src/middleware/error-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAItC,wBAAgB,YAAY,IAAI,UAAU,CAsEzC"}
@@ -0,0 +1,93 @@
1
+ import { logger } from '../lib/logger.js';
2
+ import { recordSecurityDecision } from '../security/decision-context.js';
3
+ export function errorHandler() {
4
+ return async (ctx, next) => {
5
+ try {
6
+ await next();
7
+ }
8
+ catch (err) {
9
+ const error = err;
10
+ ctx.status = error.status || 500;
11
+ ctx.body = {
12
+ error: publicErrorMessage(ctx.status),
13
+ status: ctx.status,
14
+ };
15
+ if (ctx.status === 401) {
16
+ recordSecurityDecision(ctx, {
17
+ decisionPoint: 'authentication',
18
+ reasonCode: 'authentication-required',
19
+ outcome: 'deny',
20
+ });
21
+ }
22
+ else if (ctx.status === 403) {
23
+ recordSecurityDecision(ctx, {
24
+ decisionPoint: 'permission',
25
+ reasonCode: 'permission-required',
26
+ outcome: 'deny',
27
+ });
28
+ }
29
+ else if (ctx.status === 413) {
30
+ recordSecurityDecision(ctx, {
31
+ decisionPoint: 'validation',
32
+ reasonCode: 'body-too-large',
33
+ outcome: 'deny',
34
+ });
35
+ }
36
+ else if (ctx.status === 400) {
37
+ recordSecurityDecision(ctx, {
38
+ decisionPoint: 'validation',
39
+ reasonCode: 'malformed-body',
40
+ outcome: 'deny',
41
+ });
42
+ }
43
+ else if (ctx.status === 404) {
44
+ recordSecurityDecision(ctx, {
45
+ decisionPoint: 'resource',
46
+ reasonCode: 'resource-not-found',
47
+ outcome: 'deny',
48
+ });
49
+ }
50
+ else if (ctx.status === 405) {
51
+ recordSecurityDecision(ctx, {
52
+ decisionPoint: 'validation',
53
+ reasonCode: 'method-not-allowed',
54
+ outcome: 'deny',
55
+ });
56
+ }
57
+ else if (ctx.status < 500) {
58
+ recordSecurityDecision(ctx, {
59
+ decisionPoint: 'validation',
60
+ reasonCode: 'schema-invalid',
61
+ outcome: 'deny',
62
+ });
63
+ }
64
+ else {
65
+ recordSecurityDecision(ctx, {
66
+ decisionPoint: 'handler',
67
+ reasonCode: 'handler-failed',
68
+ outcome: 'error',
69
+ });
70
+ }
71
+ if (ctx.status >= 500) {
72
+ logger.error({ event: 'request-handler-failed', requestId: ctx.state.requestId }, 'Request handler failed');
73
+ }
74
+ }
75
+ };
76
+ }
77
+ /** Return one minimal public error label without exposing a thrown diagnostic. */
78
+ function publicErrorMessage(status) {
79
+ if (status === 400)
80
+ return 'Bad Request';
81
+ if (status === 401)
82
+ return 'Unauthorized';
83
+ if (status === 403)
84
+ return 'Forbidden';
85
+ if (status === 404)
86
+ return 'Not Found';
87
+ if (status === 405)
88
+ return 'Method Not Allowed';
89
+ if (status === 413)
90
+ return 'Payload Too Large';
91
+ return status < 500 ? 'Request Rejected' : 'Internal Server Error';
92
+ }
93
+ //# sourceMappingURL=error-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../src/middleware/error-handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Middleware } from 'koa';
2
+ export declare function healthCheck(): Middleware;
3
+ //# sourceMappingURL=health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/middleware/health.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAItC,wBAAgB,WAAW,IAAI,UAAU,CAgCxC"}
@@ -0,0 +1,35 @@
1
+ import { getPool } from '../lib/database.js';
2
+ import { getRedis } from '../lib/redis.js';
3
+ export function healthCheck() {
4
+ return async (ctx) => {
5
+ const checks = { server: 'ok' };
6
+ let healthy = true;
7
+ // Check PostgreSQL
8
+ try {
9
+ const pool = getPool();
10
+ await pool.query('SELECT 1');
11
+ checks.database = 'ok';
12
+ }
13
+ catch {
14
+ checks.database = 'error';
15
+ healthy = false;
16
+ }
17
+ // Check Redis
18
+ try {
19
+ const redis = getRedis();
20
+ await redis.ping();
21
+ checks.redis = 'ok';
22
+ }
23
+ catch {
24
+ checks.redis = 'error';
25
+ healthy = false;
26
+ }
27
+ ctx.status = healthy ? 200 : 503;
28
+ ctx.body = {
29
+ status: healthy ? 'healthy' : 'unhealthy',
30
+ checks,
31
+ timestamp: new Date().toISOString(),
32
+ };
33
+ };
34
+ }
35
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/middleware/health.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C,MAAM,UAAU,WAAW;IACzB,OAAO,KAAK,EAAE,GAAG,EAAE,EAAE;QACnB,MAAM,MAAM,GAA2B,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QACxD,IAAI,OAAO,GAAG,IAAI,CAAC;QAEnB,mBAAmB;QACnB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;YACvB,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAC7B,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC;QACzB,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,CAAC,QAAQ,GAAG,OAAO,CAAC;YAC1B,OAAO,GAAG,KAAK,CAAC;QAClB,CAAC;QAED,cAAc;QACd,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;YACzB,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;YACnB,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,CAAC,KAAK,GAAG,OAAO,CAAC;YACvB,OAAO,GAAG,KAAK,CAAC;QAClB,CAAC;QAED,GAAG,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QACjC,GAAG,CAAC,IAAI,GAAG;YACT,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW;YACzC,MAAM;YACN,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}