@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,60 @@
1
+ /**
2
+ * Readiness probe handler — GET /ready.
3
+ *
4
+ * Separate from /health (liveness): /health confirms the server process
5
+ * is alive; /ready confirms the server can actually serve requests by
6
+ * checking that both PostgreSQL and Redis are reachable within a timeout.
7
+ *
8
+ * Kubernetes / ECS maps:
9
+ * - livenessProbe → GET /health
10
+ * - readinessProbe → GET /ready
11
+ *
12
+ * Returns 200 + { status: 'ready', checks } when both backends are healthy,
13
+ * or 503 + { status: 'not_ready', checks } when either is degraded.
14
+ */
15
+ import { getPool } from '../lib/database.js';
16
+ import { getRedis } from '../lib/redis.js';
17
+ import { logger } from '../lib/logger.js';
18
+ /** Maximum time (ms) to wait for each backend check before failing. */
19
+ const TIMEOUT_MS = 2000;
20
+ /**
21
+ * Race a promise against a timeout. Rejects with a descriptive error
22
+ * if the promise doesn't resolve within `TIMEOUT_MS`.
23
+ */
24
+ function withTimeout(promise, label) {
25
+ return Promise.race([
26
+ promise,
27
+ new Promise((_, reject) => setTimeout(() => reject(new Error(`${label} timeout after ${TIMEOUT_MS}ms`)), TIMEOUT_MS)),
28
+ ]);
29
+ }
30
+ /**
31
+ * Create the readiness probe middleware.
32
+ *
33
+ * Both DB and Redis are checked concurrently with individual timeouts.
34
+ * A single failure makes the overall probe return 503.
35
+ */
36
+ export function readyHandler() {
37
+ return async (ctx) => {
38
+ const checks = {};
39
+ // Run both checks concurrently — one failure doesn't block the other
40
+ const [dbResult, redisResult] = await Promise.allSettled([
41
+ withTimeout(getPool().query('SELECT 1'), 'db'),
42
+ withTimeout(getRedis().ping(), 'redis'),
43
+ ]);
44
+ checks.db =
45
+ dbResult.status === 'fulfilled'
46
+ ? { ok: true }
47
+ : { ok: false, error: String(dbResult.reason) };
48
+ checks.redis =
49
+ redisResult.status === 'fulfilled'
50
+ ? { ok: true }
51
+ : { ok: false, error: String(redisResult.reason) };
52
+ const ready = checks.db.ok && checks.redis.ok;
53
+ if (!ready) {
54
+ logger.warn({ event: 'ready.degraded', checks }, 'readiness probe failed');
55
+ }
56
+ ctx.status = ready ? 200 : 503;
57
+ ctx.body = { status: ready ? 'ready' : 'not_ready', checks };
58
+ };
59
+ }
60
+ //# sourceMappingURL=ready.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ready.js","sourceRoot":"","sources":["../../src/middleware/ready.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,uEAAuE;AACvE,MAAM,UAAU,GAAG,IAAI,CAAC;AAExB;;;GAGG;AACH,SAAS,WAAW,CAAI,OAAmB,EAAE,KAAa;IACxD,OAAO,OAAO,CAAC,IAAI,CAAC;QAClB,OAAO;QACP,IAAI,OAAO,CAAI,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAC3B,UAAU,CACR,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,KAAK,kBAAkB,UAAU,IAAI,CAAC,CAAC,EACjE,UAAU,CACX,CACF;KACF,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,KAAK,EAAE,GAAG,EAAE,EAAE;QACnB,MAAM,MAAM,GAAoD,EAAE,CAAC;QAEnE,qEAAqE;QACrE,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC;YACvD,WAAW,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC;YAC9C,WAAW,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,OAAO,CAAC;SACxC,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE;YACP,QAAQ,CAAC,MAAM,KAAK,WAAW;gBAC7B,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE;gBACd,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAEpD,MAAM,CAAC,KAAK;YACV,WAAW,CAAC,MAAM,KAAK,WAAW;gBAChC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE;gBACd,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;QAEvD,MAAM,KAAK,GAAG,MAAM,CAAC,EAAE,CAAC,EAAE,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAE9C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,EAAE,wBAAwB,CAAC,CAAC;QAC7E,CAAC;QAED,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QAC/B,GAAG,CAAC,IAAI,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC;IAC/D,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { Middleware } from 'koa';
2
+ import { type SecurityDecisionSink } from '../security/decision-context.js';
3
+ /** Closed request-completion record exposed to owner-controlled operational sinks. */
4
+ export interface OperationalRequestRecord {
5
+ /** Server-created request correlation identifier. */
6
+ readonly requestId: string;
7
+ /** Public HTTP method. */
8
+ readonly method: string;
9
+ /** Registered route template or closed unmatched fallback. */
10
+ readonly routeTemplate: string;
11
+ /** Final public status. */
12
+ readonly status: number;
13
+ /** Bounded request duration in milliseconds. */
14
+ readonly duration: number;
15
+ }
16
+ /** Sink for a normalized request-completion record. */
17
+ export type OperationalRequestSink = (record: OperationalRequestRecord) => void;
18
+ /**
19
+ * Replace bearer and interaction path segments before they reach structured or rendered logs.
20
+ *
21
+ * @param path - Public request path before operational logging.
22
+ * @returns A stable route-shaped path without bearer or interaction values.
23
+ */
24
+ export declare function sanitizeRequestPath(path: string): string;
25
+ /** Create request-correlation middleware that emits only sanitized route-shaped paths. */
26
+ export declare function requestLogger(decisionSink?: SecurityDecisionSink, operationalSink?: OperationalRequestSink): Middleware;
27
+ //# sourceMappingURL=request-logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-logger.d.ts","sourceRoot":"","sources":["../../src/middleware/request-logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAItC,OAAO,EAIL,KAAK,oBAAoB,EAC1B,MAAM,iCAAiC,CAAC;AAEzC,sFAAsF;AACtF,MAAM,WAAW,wBAAwB;IACvC,qDAAqD;IACrD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,0BAA0B;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,8DAA8D;IAC9D,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,2BAA2B;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,gDAAgD;IAChD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,uDAAuD;AACvD,MAAM,MAAM,sBAAsB,GAAG,CAAC,MAAM,EAAE,wBAAwB,KAAK,IAAI,CAAC;AAOhF;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOxD;AAED,0FAA0F;AAC1F,wBAAgB,aAAa,CAC3B,YAAY,CAAC,EAAE,oBAAoB,EACnC,eAAe,GAAE,sBAA8C,GAC9D,UAAU,CAwBZ"}
@@ -0,0 +1,46 @@
1
+ import { randomUUID } from 'crypto';
2
+ import { logger } from '../lib/logger.js';
3
+ import { registerProtocolRequestCorrelation } from '../oidc/protocol-security-observer.js';
4
+ import { finalizeSecurityDecision, initializeSecurityDecision, normalizedRouteTemplate, } from '../security/decision-context.js';
5
+ /** Emit one request-completion record through the production logger. */
6
+ const logOperationalRequest = (record) => {
7
+ logger.info(record, 'HTTP request completed');
8
+ };
9
+ /**
10
+ * Replace bearer and interaction path segments before they reach structured or rendered logs.
11
+ *
12
+ * @param path - Public request path before operational logging.
13
+ * @returns A stable route-shaped path without bearer or interaction values.
14
+ */
15
+ export function sanitizeRequestPath(path) {
16
+ return path
17
+ .replace(/^\/[^/]+\/auth\/magic-link\/[^/]+(?=\/|$)/, '/:organization/auth/magic-link/:artifact')
18
+ .replace(/^\/interaction\/[^/]+(?=\/|$)/, '/interaction/:interaction');
19
+ }
20
+ /** Create request-correlation middleware that emits only sanitized route-shaped paths. */
21
+ export function requestLogger(decisionSink, operationalSink = logOperationalRequest) {
22
+ return async (ctx, next) => {
23
+ const requestId = randomUUID();
24
+ ctx.state.requestId = requestId;
25
+ initializeSecurityDecision(ctx, requestId);
26
+ ctx.set('X-Request-Id', requestId);
27
+ registerProtocolRequestCorrelation(ctx.req, requestId);
28
+ const start = Date.now();
29
+ try {
30
+ await next();
31
+ }
32
+ finally {
33
+ const duration = Date.now() - start;
34
+ const routeTemplate = normalizedRouteTemplate(ctx);
35
+ operationalSink({
36
+ requestId,
37
+ method: ctx.method,
38
+ routeTemplate,
39
+ status: ctx.status,
40
+ duration,
41
+ });
42
+ await finalizeSecurityDecision(ctx, decisionSink);
43
+ }
44
+ };
45
+ }
46
+ //# sourceMappingURL=request-logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-logger.js","sourceRoot":"","sources":["../../src/middleware/request-logger.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,kCAAkC,EAAE,MAAM,uCAAuC,CAAC;AAC3F,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,uBAAuB,GAExB,MAAM,iCAAiC,CAAC;AAmBzC,wEAAwE;AACxE,MAAM,qBAAqB,GAA2B,CAAC,MAAM,EAAE,EAAE;IAC/D,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;AAChD,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,OAAO,IAAI;SACR,OAAO,CACN,2CAA2C,EAC3C,0CAA0C,CAC3C;SACA,OAAO,CAAC,+BAA+B,EAAE,2BAA2B,CAAC,CAAC;AAC3E,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,aAAa,CAC3B,YAAmC,EACnC,eAAe,GAA2B,qBAAqB;IAE/D,OAAO,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,MAAM,SAAS,GAAG,UAAU,EAAE,CAAC;QAC/B,GAAG,CAAC,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC;QAChC,0BAA0B,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC3C,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;QACnC,kCAAkC,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAEvD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,IAAI,EAAE,CAAC;QACf,CAAC;gBAAS,CAAC;YACT,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;YACpC,MAAM,aAAa,GAAG,uBAAuB,CAAC,GAAG,CAAC,CAAC;YACnD,eAAe,CAAC;gBACd,SAAS;gBACT,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,aAAa;gBACb,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,QAAQ;aACT,CAAC,CAAC;YACH,MAAM,wBAAwB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;QACpD,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Permission-based authorization middleware for admin API routes.
3
+ *
4
+ * Works downstream of requireAdminAuth() — checks that ctx.state.adminUser
5
+ * has the required permission(s) before allowing the request to proceed.
6
+ *
7
+ * Usage:
8
+ * ```typescript
9
+ * import { requirePermission } from '../middleware/require-permission.js';
10
+ *
11
+ * router.post('/organizations', requirePermission('org:create'), createOrgHandler);
12
+ * router.get('/organizations', requirePermission('org:read'), listOrgsHandler);
13
+ * ```
14
+ *
15
+ * @module middleware/require-permission
16
+ */
17
+ import type { Middleware } from 'koa';
18
+ /**
19
+ * Create middleware that requires specific admin permission(s).
20
+ *
21
+ * Must be used after requireAdminAuth() in the middleware chain.
22
+ * Checks ctx.state.adminUser.permissions for the required permission(s).
23
+ *
24
+ * @param requiredPermissions - One or more permission slugs (e.g., 'org:create')
25
+ * @returns Koa middleware that checks for the required permission(s)
26
+ */
27
+ export declare function requirePermission(...requiredPermissions: string[]): Middleware;
28
+ //# sourceMappingURL=require-permission.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-permission.d.ts","sourceRoot":"","sources":["../../src/middleware/require-permission.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAItC;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,mBAAmB,EAAE,MAAM,EAAE,GAAG,UAAU,CAqC9E"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Permission-based authorization middleware for admin API routes.
3
+ *
4
+ * Works downstream of requireAdminAuth() — checks that ctx.state.adminUser
5
+ * has the required permission(s) before allowing the request to proceed.
6
+ *
7
+ * Usage:
8
+ * ```typescript
9
+ * import { requirePermission } from '../middleware/require-permission.js';
10
+ *
11
+ * router.post('/organizations', requirePermission('org:create'), createOrgHandler);
12
+ * router.get('/organizations', requirePermission('org:read'), listOrgsHandler);
13
+ * ```
14
+ *
15
+ * @module middleware/require-permission
16
+ */
17
+ import { hasPermissions } from '../lib/admin-permissions.js';
18
+ import { recordSecurityDecision } from '../security/decision-context.js';
19
+ /**
20
+ * Create middleware that requires specific admin permission(s).
21
+ *
22
+ * Must be used after requireAdminAuth() in the middleware chain.
23
+ * Checks ctx.state.adminUser.permissions for the required permission(s).
24
+ *
25
+ * @param requiredPermissions - One or more permission slugs (e.g., 'org:create')
26
+ * @returns Koa middleware that checks for the required permission(s)
27
+ */
28
+ export function requirePermission(...requiredPermissions) {
29
+ return async (ctx, next) => {
30
+ const adminUser = ctx.state.adminUser;
31
+ // Safety check: requireAdminAuth() must have run first
32
+ if (!adminUser) {
33
+ recordSecurityDecision(ctx, {
34
+ decisionPoint: 'authentication',
35
+ reasonCode: 'authentication-required',
36
+ outcome: 'deny',
37
+ });
38
+ ctx.status = 401;
39
+ ctx.body = {
40
+ error: 'Authentication required',
41
+ message: 'Admin authentication middleware must be applied first',
42
+ };
43
+ return;
44
+ }
45
+ // Check if the user has all required permissions
46
+ if (!hasPermissions([...adminUser.permissions], requiredPermissions)) {
47
+ recordSecurityDecision(ctx, {
48
+ decisionPoint: 'permission',
49
+ reasonCode: 'permission-required',
50
+ outcome: 'deny',
51
+ detail: { permissions: requiredPermissions },
52
+ });
53
+ ctx.status = 403;
54
+ ctx.body = {
55
+ error: 'Forbidden',
56
+ message: 'The requested operation is not permitted',
57
+ };
58
+ return;
59
+ }
60
+ await next();
61
+ };
62
+ }
63
+ //# sourceMappingURL=require-permission.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-permission.js","sourceRoot":"","sources":["../../src/middleware/require-permission.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAEzE;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAG,mBAA6B;IAChE,OAAO,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC;QAEtC,uDAAuD;QACvD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,sBAAsB,CAAC,GAAG,EAAE;gBAC1B,aAAa,EAAE,gBAAgB;gBAC/B,UAAU,EAAE,yBAAyB;gBACrC,OAAO,EAAE,MAAM;aAChB,CAAC,CAAC;YACH,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;YACjB,GAAG,CAAC,IAAI,GAAG;gBACT,KAAK,EAAE,yBAAyB;gBAChC,OAAO,EAAE,uDAAuD;aACjE,CAAC;YACF,OAAO;QACT,CAAC;QAED,iDAAiD;QACjD,IAAI,CAAC,cAAc,CAAC,CAAC,GAAG,SAAS,CAAC,WAAW,CAAC,EAAE,mBAAmB,CAAC,EAAE,CAAC;YACrE,sBAAsB,CAAC,GAAG,EAAE;gBAC1B,aAAa,EAAE,YAAY;gBAC3B,UAAU,EAAE,qBAAqB;gBACjC,OAAO,EAAE,MAAM;gBACf,MAAM,EAAE,EAAE,WAAW,EAAE,mBAAmB,EAAE;aAC7C,CAAC,CAAC;YACH,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;YACjB,GAAG,CAAC,IAAI,GAAG;gBACT,KAAK,EAAE,WAAW;gBAClB,OAAO,EAAE,0CAA0C;aACpD,CAAC;YACF,OAAO;QACT,CAAC;QAED,MAAM,IAAI,EAAE,CAAC;IACf,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Organization-membership guard for user-specific administrative routes.
3
+ *
4
+ * This middleware must run after authentication and permission checks. Returning the same 404 for
5
+ * an absent user, an invalid identifier, and a user owned by another organization prevents the
6
+ * organization-prefixed API from becoming a cross-tenant object lookup or membership oracle.
7
+ */
8
+ import type { Middleware } from 'koa';
9
+ /**
10
+ * Requires the route's user to belong to the organization named in the same path.
11
+ *
12
+ * Place this middleware after `requirePermission(...)`. Callers without the operation's permission
13
+ * must receive the permission denial before Porta performs or reveals a tenant-membership lookup.
14
+ *
15
+ * @returns Koa middleware that continues only for a matching organization and user.
16
+ */
17
+ export declare function requireUserOrganization(): Middleware;
18
+ //# sourceMappingURL=require-user-organization.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-user-organization.d.ts","sourceRoot":"","sources":["../../src/middleware/require-user-organization.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAWtC;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,IAAI,UAAU,CAgCpD"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Organization-membership guard for user-specific administrative routes.
3
+ *
4
+ * This middleware must run after authentication and permission checks. Returning the same 404 for
5
+ * an absent user, an invalid identifier, and a user owned by another organization prevents the
6
+ * organization-prefixed API from becoming a cross-tenant object lookup or membership oracle.
7
+ */
8
+ import { z } from 'zod';
9
+ import { getUserById } from '../users/service.js';
10
+ import { recordSecurityDecision, recordSecurityReference } from '../security/decision-context.js';
11
+ const organizationUserParamsSchema = z.object({
12
+ orgId: z.string().uuid(),
13
+ userId: z.string().uuid(),
14
+ });
15
+ /**
16
+ * Requires the route's user to belong to the organization named in the same path.
17
+ *
18
+ * Place this middleware after `requirePermission(...)`. Callers without the operation's permission
19
+ * must receive the permission denial before Porta performs or reveals a tenant-membership lookup.
20
+ *
21
+ * @returns Koa middleware that continues only for a matching organization and user.
22
+ */
23
+ export function requireUserOrganization() {
24
+ return async function requireUserOrganizationMiddleware(ctx, next) {
25
+ const parsed = organizationUserParamsSchema.safeParse(ctx.params);
26
+ if (!parsed.success) {
27
+ recordSecurityDecision(ctx, {
28
+ decisionPoint: 'resource',
29
+ reasonCode: 'resource-not-found',
30
+ outcome: 'deny',
31
+ detail: { resourceType: 'user' },
32
+ });
33
+ ctx.status = 404;
34
+ ctx.body = { error: 'User not found' };
35
+ return;
36
+ }
37
+ const user = await getUserById(parsed.data.userId);
38
+ if (user === null || user.organizationId !== parsed.data.orgId) {
39
+ recordSecurityDecision(ctx, {
40
+ decisionPoint: 'resource',
41
+ reasonCode: 'resource-not-found',
42
+ outcome: 'deny',
43
+ detail: { resourceType: 'user' },
44
+ });
45
+ ctx.status = 404;
46
+ ctx.body = { error: 'User not found' };
47
+ return;
48
+ }
49
+ recordSecurityReference(ctx, 'resource', parsed.data.userId);
50
+ await next();
51
+ };
52
+ }
53
+ //# sourceMappingURL=require-user-organization.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-user-organization.js","sourceRoot":"","sources":["../../src/middleware/require-user-organization.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAElG,MAAM,4BAA4B,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE;IACxB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE;CAC1B,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO,KAAK,UAAU,iCAAiC,CAAC,GAAG,EAAE,IAAI;QAC/D,MAAM,MAAM,GAAG,4BAA4B,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAClE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,sBAAsB,CAAC,GAAG,EAAE;gBAC1B,aAAa,EAAE,UAAU;gBACzB,UAAU,EAAE,oBAAoB;gBAChC,OAAO,EAAE,MAAM;gBACf,MAAM,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE;aACjC,CAAC,CAAC;YACH,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;YACjB,GAAG,CAAC,IAAI,GAAG,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;YACvC,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnD,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,cAAc,KAAK,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAC/D,sBAAsB,CAAC,GAAG,EAAE;gBAC1B,aAAa,EAAE,UAAU;gBACzB,UAAU,EAAE,oBAAoB;gBAChC,OAAO,EAAE,MAAM;gBACf,MAAM,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE;aACjC,CAAC,CAAC;YACH,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;YACjB,GAAG,CAAC,IAAI,GAAG,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;YACvC,OAAO;QACT,CAAC;QAED,uBAAuB,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAE7D,MAAM,IAAI,EAAE,CAAC;IACf,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Root / public-surface handlers.
3
+ *
4
+ * Without these, a bare `GET /` would fall through to Koa's default 404
5
+ * handler and render "Not Found" — ugly, and the exact shape of that
6
+ * response (status code + header set) is a small fingerprint signal for
7
+ * scanners. This module serves an intentionally generic, no-information
8
+ * response at the public root so the deployment looks deliberate without
9
+ * disclosing anything about the software running behind it.
10
+ *
11
+ * Endpoints:
12
+ * GET / — 200 with a neutral HTML page
13
+ * HEAD / — 200, no body (mirrors GET /)
14
+ * GET /robots.txt — `User-agent: *\nDisallow: /` (keep crawlers out)
15
+ * GET /favicon.ico — 204 No Content (suppresses the browser's auto-request)
16
+ *
17
+ * Security properties:
18
+ * • No product name, version, vendor, or capability description.
19
+ * • No external asset references — page renders offline, nothing to
20
+ * fingerprint via network requests.
21
+ * • `X-Robots-Tag: noindex, nofollow` prevents accidental indexing.
22
+ * • `Cache-Control: no-store` avoids intermediate caches persisting
23
+ * the response (keeps future changes in our control).
24
+ * • `Content-Security-Policy: default-src 'none'; style-src 'unsafe-inline'`
25
+ * disables script execution and disallows any remote resource.
26
+ * • Inline `<style>` block — no external CSS, no JS.
27
+ *
28
+ * The body copy is intentionally terse and abstract. Do NOT add branding,
29
+ * support contacts, tenant hints, or links to admin/docs here.
30
+ */
31
+ import Router from '@koa/router';
32
+ /**
33
+ * Root-page-specific response headers applied to `/`, `/robots.txt`, and
34
+ * `/favicon.ico` only.
35
+ *
36
+ * General security headers (X-Content-Type-Options, X-Frame-Options,
37
+ * Referrer-Policy, Content-Security-Policy, etc.) are handled globally
38
+ * by the `securityHeaders()` middleware in `src/middleware/security-headers.ts`.
39
+ * This object only contains headers that are unique to the root-page surface:
40
+ *
41
+ * - `Cache-Control: no-store` — prevents proxies from caching the
42
+ * neutral root-page response.
43
+ * - `X-Robots-Tag: noindex, nofollow` — prevents accidental search
44
+ * engine indexing of the root endpoint.
45
+ *
46
+ * Exported for test assertions; kept as a plain object (not a Map) so
47
+ * tests can snapshot it directly.
48
+ */
49
+ export declare const ROOT_PAGE_HEADERS: Readonly<Record<string, string>>;
50
+ /**
51
+ * Create the Koa router that serves `/`, `/robots.txt`, and `/favicon.ico`.
52
+ *
53
+ * Mount this router early in the middleware stack — **after** `/health`
54
+ * (health takes priority for load-balancer probes) but **before** any
55
+ * `/:orgSlug/*` catch-all. The paths it owns are exact string matches, so
56
+ * it cannot accidentally shadow tenant or admin routes.
57
+ *
58
+ * The handlers are standalone and take no dependencies, so the router is
59
+ * safe to construct at app-factory time (no DB, Redis, or config access).
60
+ */
61
+ export declare function createRootPageRouter(): Router;
62
+ //# sourceMappingURL=root-page.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"root-page.d.ts","sourceRoot":"","sources":["../../src/middleware/root-page.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,MAAM,MAAM,aAAa,CAAC;AAoCjC;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAG7D,CAAC;AAEH;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAwC7C"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Root / public-surface handlers.
3
+ *
4
+ * Without these, a bare `GET /` would fall through to Koa's default 404
5
+ * handler and render "Not Found" — ugly, and the exact shape of that
6
+ * response (status code + header set) is a small fingerprint signal for
7
+ * scanners. This module serves an intentionally generic, no-information
8
+ * response at the public root so the deployment looks deliberate without
9
+ * disclosing anything about the software running behind it.
10
+ *
11
+ * Endpoints:
12
+ * GET / — 200 with a neutral HTML page
13
+ * HEAD / — 200, no body (mirrors GET /)
14
+ * GET /robots.txt — `User-agent: *\nDisallow: /` (keep crawlers out)
15
+ * GET /favicon.ico — 204 No Content (suppresses the browser's auto-request)
16
+ *
17
+ * Security properties:
18
+ * • No product name, version, vendor, or capability description.
19
+ * • No external asset references — page renders offline, nothing to
20
+ * fingerprint via network requests.
21
+ * • `X-Robots-Tag: noindex, nofollow` prevents accidental indexing.
22
+ * • `Cache-Control: no-store` avoids intermediate caches persisting
23
+ * the response (keeps future changes in our control).
24
+ * • `Content-Security-Policy: default-src 'none'; style-src 'unsafe-inline'`
25
+ * disables script execution and disallows any remote resource.
26
+ * • Inline `<style>` block — no external CSS, no JS.
27
+ *
28
+ * The body copy is intentionally terse and abstract. Do NOT add branding,
29
+ * support contacts, tenant hints, or links to admin/docs here.
30
+ */
31
+ import Router from '@koa/router';
32
+ /**
33
+ * Minimal HTML served at `GET /` and `HEAD /`.
34
+ *
35
+ * Kept as a single-line template to avoid accidental whitespace drift in
36
+ * tests that assert on the response body. The message deliberately says
37
+ * nothing: it does not name the product, the vendor, the protocol, or the
38
+ * purpose of the service. Anyone who arrived here intentionally already
39
+ * knows the URL they need; anyone who didn't gets a clean "nothing to see
40
+ * here" page instead of a stack-trace-adjacent 404.
41
+ */
42
+ const ROOT_HTML = [
43
+ '<!DOCTYPE html>',
44
+ '<html lang="en">',
45
+ '<head>',
46
+ '<meta charset="utf-8">',
47
+ '<meta name="viewport" content="width=device-width, initial-scale=1">',
48
+ '<meta name="robots" content="noindex, nofollow">',
49
+ '<title>\u00A0</title>',
50
+ '<style>',
51
+ 'html,body{height:100%;margin:0;padding:0;background:#fafafa;color:#555;',
52
+ 'font-family:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,',
53
+ 'Helvetica,Arial,sans-serif;}',
54
+ 'main{display:flex;align-items:center;justify-content:center;height:100%;',
55
+ 'padding:2rem;box-sizing:border-box;text-align:center;}',
56
+ 'p{margin:0;font-size:0.95rem;line-height:1.5;max-width:32rem;}',
57
+ '</style>',
58
+ '</head>',
59
+ '<body>',
60
+ '<main><p>This endpoint does not provide a public interface.</p></main>',
61
+ '</body>',
62
+ '</html>',
63
+ '',
64
+ ].join('\n');
65
+ /**
66
+ * Root-page-specific response headers applied to `/`, `/robots.txt`, and
67
+ * `/favicon.ico` only.
68
+ *
69
+ * General security headers (X-Content-Type-Options, X-Frame-Options,
70
+ * Referrer-Policy, Content-Security-Policy, etc.) are handled globally
71
+ * by the `securityHeaders()` middleware in `src/middleware/security-headers.ts`.
72
+ * This object only contains headers that are unique to the root-page surface:
73
+ *
74
+ * - `Cache-Control: no-store` — prevents proxies from caching the
75
+ * neutral root-page response.
76
+ * - `X-Robots-Tag: noindex, nofollow` — prevents accidental search
77
+ * engine indexing of the root endpoint.
78
+ *
79
+ * Exported for test assertions; kept as a plain object (not a Map) so
80
+ * tests can snapshot it directly.
81
+ */
82
+ export const ROOT_PAGE_HEADERS = Object.freeze({
83
+ 'Cache-Control': 'no-store',
84
+ 'X-Robots-Tag': 'noindex, nofollow',
85
+ });
86
+ /**
87
+ * Create the Koa router that serves `/`, `/robots.txt`, and `/favicon.ico`.
88
+ *
89
+ * Mount this router early in the middleware stack — **after** `/health`
90
+ * (health takes priority for load-balancer probes) but **before** any
91
+ * `/:orgSlug/*` catch-all. The paths it owns are exact string matches, so
92
+ * it cannot accidentally shadow tenant or admin routes.
93
+ *
94
+ * The handlers are standalone and take no dependencies, so the router is
95
+ * safe to construct at app-factory time (no DB, Redis, or config access).
96
+ */
97
+ export function createRootPageRouter() {
98
+ const router = new Router();
99
+ // GET / → neutral HTML. Also handles HEAD / because @koa/router
100
+ // automatically derives HEAD from GET with an empty body.
101
+ router.get('/', (ctx) => {
102
+ for (const [name, value] of Object.entries(ROOT_PAGE_HEADERS)) {
103
+ ctx.set(name, value);
104
+ }
105
+ ctx.type = 'text/html; charset=utf-8';
106
+ ctx.status = 200;
107
+ ctx.body = ROOT_HTML;
108
+ });
109
+ // GET /robots.txt → blanket Disallow.
110
+ // Explicit rule so scanners that respect robots.txt skip the whole host
111
+ // instead of probing every path looking for a 404 signature.
112
+ router.get('/robots.txt', (ctx) => {
113
+ for (const [name, value] of Object.entries(ROOT_PAGE_HEADERS)) {
114
+ ctx.set(name, value);
115
+ }
116
+ ctx.type = 'text/plain; charset=utf-8';
117
+ ctx.status = 200;
118
+ ctx.body = 'User-agent: *\nDisallow: /\n';
119
+ });
120
+ // GET /favicon.ico → 204 No Content.
121
+ // Browsers auto-fetch favicon.ico for every host; a 204 stops them
122
+ // retrying (which a 404 would log on every page load) and returns no
123
+ // identifying content.
124
+ router.get('/favicon.ico', (ctx) => {
125
+ for (const [name, value] of Object.entries(ROOT_PAGE_HEADERS)) {
126
+ ctx.set(name, value);
127
+ }
128
+ ctx.status = 204;
129
+ // Explicitly null the body so Koa doesn't set a default payload.
130
+ ctx.body = null;
131
+ });
132
+ return router;
133
+ }
134
+ //# sourceMappingURL=root-page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"root-page.js","sourceRoot":"","sources":["../../src/middleware/root-page.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC;;;;;;;;;GASG;AACH,MAAM,SAAS,GAAG;IAChB,iBAAiB;IACjB,kBAAkB;IAClB,QAAQ;IACR,wBAAwB;IACxB,sEAAsE;IACtE,kDAAkD;IAClD,uBAAuB;IACvB,SAAS;IACT,yEAAyE;IACzE,2EAA2E;IAC3E,8BAA8B;IAC9B,0EAA0E;IAC1E,wDAAwD;IACxD,gEAAgE;IAChE,UAAU;IACV,SAAS;IACT,QAAQ;IACR,wEAAwE;IACxE,SAAS;IACT,SAAS;IACT,EAAE;CACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAqC,MAAM,CAAC,MAAM,CAAC;IAC/E,eAAe,EAAE,UAAU;IAC3B,cAAc,EAAE,mBAAmB;CACpC,CAAC,CAAC;AAEH;;;;;;;;;;GAUG;AACH,MAAM,UAAU,oBAAoB;IAClC,MAAM,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;IAE5B,gEAAgE;IAChE,0DAA0D;IAC1D,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;QACtB,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,CAAC;YAC9D,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACvB,CAAC;QACD,GAAG,CAAC,IAAI,GAAG,0BAA0B,CAAC;QACtC,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;QACjB,GAAG,CAAC,IAAI,GAAG,SAAS,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,sCAAsC;IACtC,wEAAwE;IACxE,6DAA6D;IAC7D,MAAM,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,GAAG,EAAE,EAAE;QAChC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,CAAC;YAC9D,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACvB,CAAC;QACD,GAAG,CAAC,IAAI,GAAG,2BAA2B,CAAC;QACvC,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;QACjB,GAAG,CAAC,IAAI,GAAG,8BAA8B,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,qCAAqC;IACrC,mEAAmE;IACnE,qEAAqE;IACrE,uBAAuB;IACvB,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,GAAG,EAAE,EAAE;QACjC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,CAAC;YAC9D,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACvB,CAAC;QACD,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;QACjB,iEAAiE;QACjE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Global HTTP security headers middleware.
3
+ *
4
+ * Adds defence-in-depth security headers to every response produced by
5
+ * the Porta application. The headers mitigate a broad class of browser-
6
+ * side attacks (clickjacking, MIME-sniffing, cross-origin information
7
+ * leakage, protocol downgrade) without depending on an upstream reverse
8
+ * proxy — if the proxy is a dumb passthrough, these headers still reach
9
+ * the browser.
10
+ *
11
+ * Headers set on every response:
12
+ * X-Content-Type-Options: nosniff — prevent MIME-sniffing
13
+ * X-Frame-Options: DENY — prevent clickjacking
14
+ * Referrer-Policy: strict-origin-when-cross-origin
15
+ * — limit referrer leakage
16
+ * X-XSS-Protection: 0 — disable legacy XSS filter
17
+ * (buggy; rely on CSP instead)
18
+ * Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()
19
+ * — restrict browser APIs
20
+ * Content-Security-Policy — strict default, relaxed for
21
+ * HTML pages (see below)
22
+ *
23
+ * Conditional headers:
24
+ * Strict-Transport-Security — only emitted when the
25
+ * configured issuer URL uses https://
26
+ *
27
+ * Content-Security-Policy strategy:
28
+ * - Default (JSON / non-HTML responses):
29
+ * `default-src 'none'` — nothing to render, nothing to load.
30
+ * - HTML responses (login, consent, 2FA, password-reset, etc.):
31
+ * `default-src 'none'; style-src 'unsafe-inline'; frame-ancestors 'none'`
32
+ * The interaction templates use inline `<style>` blocks and may
33
+ * inject custom branding CSS via `{{{branding.customCss}}}`, hence
34
+ * `style-src 'unsafe-inline'` is required. Login pages must never
35
+ * be embedded in iframes (`frame-ancestors 'none'`).
36
+ *
37
+ * Note: `form-action` is intentionally omitted. Chrome enforces
38
+ * `form-action` on the entire redirect chain of a form submission,
39
+ * not just the immediate target. After login, the OIDC provider
40
+ * redirects through the authorization endpoint and then to the
41
+ * client's `redirect_uri` (a different origin). Chrome blocks
42
+ * this final redirect as a `form-action 'self'` violation, while
43
+ * Firefox only checks the immediate action URL. CSRF tokens are
44
+ * the primary defence against cross-site form attacks; removing
45
+ * `form-action` has negligible security impact given that
46
+ * `script-src 'unsafe-inline'` already allows fetch/XHR exfiltration.
47
+ *
48
+ * Placement:
49
+ * Mount early in the middleware stack — after `errorHandler()` and
50
+ * `requestLogger()` but before any route-specific middleware. This
51
+ * ensures headers are present even on error responses.
52
+ */
53
+ import type { Middleware } from 'koa';
54
+ /**
55
+ * Static security headers applied to every response regardless of
56
+ * content type or route.
57
+ */
58
+ export declare const STATIC_SECURITY_HEADERS: Readonly<Record<string, string>>;
59
+ /**
60
+ * Strict Content-Security-Policy for non-HTML (JSON, plain-text) responses.
61
+ * Disallows all resource loading — there is nothing for a browser to render
62
+ * in a JSON API response.
63
+ */
64
+ export declare const DEFAULT_CSP = "default-src 'none'";
65
+ /**
66
+ * Relaxed Content-Security-Policy for HTML pages (login, consent, 2FA,
67
+ * password reset, invitation, magic-link confirmation, etc.).
68
+ *
69
+ * - `style-src 'unsafe-inline'` — templates use inline `<style>` blocks,
70
+ * inline style attributes, and custom
71
+ * branding CSS injection.
72
+ * - `script-src 'unsafe-inline'` — login.hbs uses an inline `<script>` for
73
+ * dual-method email copying, and
74
+ * two-factor-verify.hbs uses one for
75
+ * OTP/recovery mode toggling.
76
+ * - `frame-ancestors 'none'` — prevents embedding in iframes
77
+ * (modern replacement for X-Frame-Options).
78
+ *
79
+ * `form-action` is intentionally omitted — see module-level doc comment.
80
+ */
81
+ export declare const HTML_CSP = "default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; frame-ancestors 'none'";
82
+ /**
83
+ * HSTS header value — one year, include subdomains.
84
+ * Only emitted when the configured issuer URL uses https.
85
+ */
86
+ export declare const HSTS_VALUE = "max-age=31536000; includeSubDomains";
87
+ /**
88
+ * Create the global security-headers Koa middleware.
89
+ *
90
+ * Sets static security headers on every response **before** downstream
91
+ * handlers run, then adjusts the Content-Security-Policy after the
92
+ * response body is produced — if the response is HTML, the CSP is
93
+ * relaxed to allow inline styles and form submissions.
94
+ *
95
+ * @returns Koa middleware function
96
+ */
97
+ export declare function securityHeaders(): Middleware;
98
+ //# sourceMappingURL=security-headers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security-headers.d.ts","sourceRoot":"","sources":["../../src/middleware/security-headers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAQtC;;;GAGG;AACH,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAMnE,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,WAAW,uBAAuB,CAAC;AAEhD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,QAAQ,sGACgF,CAAC;AAEtG;;;GAGG;AACH,eAAO,MAAM,UAAU,wCAAwC,CAAC;AAsBhE;;;;;;;;;GASG;AACH,wBAAgB,eAAe,IAAI,UAAU,CAqC5C"}