@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,224 @@
1
+ /**
2
+ * Mapping repository — PostgreSQL data access for RBAC join tables.
3
+ *
4
+ * Handles the role_permissions and user_roles join tables that link:
5
+ * - Roles ↔ Permissions (which permissions a role grants)
6
+ * - Users ↔ Roles (which roles a user has)
7
+ *
8
+ * Key patterns:
9
+ * - Bulk INSERT with ON CONFLICT DO NOTHING for idempotent assignment
10
+ * - Multi-table JOINs for permission resolution through roles
11
+ * - DISTINCT for deduplicated permission lists across multiple roles
12
+ * - Parameterized bulk VALUES lists for safe multi-row operations
13
+ *
14
+ * The permission resolution query (getPermissionsForUser) is the hot path
15
+ * for token claims — it resolves user → roles → permissions in a single query.
16
+ *
17
+ * Database tables: role_permissions, user_roles (see migration 006_roles_permissions.sql)
18
+ */
19
+ import { getPool } from '../lib/database.js';
20
+ import { mapRowToRole, mapRowToPermission, mapRowToUserRole } from './types.js';
21
+ // ===========================================================================
22
+ // Role-Permission Mapping
23
+ // ===========================================================================
24
+ /**
25
+ * Assign multiple permissions to a role (bulk insert).
26
+ *
27
+ * Uses ON CONFLICT DO NOTHING to make the operation idempotent —
28
+ * already-assigned permissions are silently skipped. This allows
29
+ * callers to assign without checking for existing assignments first.
30
+ *
31
+ * @param roleId - Role UUID
32
+ * @param permissionIds - Array of permission UUIDs to assign
33
+ */
34
+ export async function assignPermissionsToRole(roleId, permissionIds) {
35
+ if (permissionIds.length === 0)
36
+ return;
37
+ const pool = getPool();
38
+ // Build parameterized VALUES list: ($1, $2), ($1, $3), ($1, $4), ...
39
+ // $1 is always the roleId, subsequent params are permission IDs
40
+ const valuesList = [];
41
+ const params = [roleId];
42
+ for (let i = 0; i < permissionIds.length; i++) {
43
+ params.push(permissionIds[i]);
44
+ valuesList.push(`($1, $${i + 2})`);
45
+ }
46
+ await pool.query(`INSERT INTO role_permissions (role_id, permission_id)
47
+ VALUES ${valuesList.join(', ')}
48
+ ON CONFLICT DO NOTHING`, params);
49
+ }
50
+ /**
51
+ * Remove multiple permissions from a role.
52
+ *
53
+ * Silently succeeds if any of the permission IDs are not currently
54
+ * assigned to the role.
55
+ *
56
+ * @param roleId - Role UUID
57
+ * @param permissionIds - Array of permission UUIDs to remove
58
+ */
59
+ export async function removePermissionsFromRole(roleId, permissionIds) {
60
+ if (permissionIds.length === 0)
61
+ return;
62
+ const pool = getPool();
63
+ // Build parameterized IN list: $2, $3, $4, ...
64
+ const placeholders = permissionIds.map((_, i) => `$${i + 2}`).join(', ');
65
+ const params = [roleId, ...permissionIds];
66
+ await pool.query(`DELETE FROM role_permissions WHERE role_id = $1 AND permission_id IN (${placeholders})`, params);
67
+ }
68
+ /**
69
+ * Get all permissions assigned to a role.
70
+ *
71
+ * JOINs role_permissions with permissions table to return full
72
+ * Permission objects, ordered by slug for consistent output.
73
+ *
74
+ * @param roleId - Role UUID
75
+ * @returns Array of permissions assigned to the role
76
+ */
77
+ export async function getPermissionsForRole(roleId) {
78
+ const pool = getPool();
79
+ const result = await pool.query(`SELECT p.*
80
+ FROM role_permissions rp
81
+ JOIN permissions p ON p.id = rp.permission_id
82
+ WHERE rp.role_id = $1
83
+ ORDER BY p.slug ASC`, [roleId]);
84
+ return result.rows.map(mapRowToPermission);
85
+ }
86
+ /**
87
+ * Get all roles that have a specific permission assigned.
88
+ *
89
+ * JOINs role_permissions with roles table to return full Role objects,
90
+ * ordered by name for consistent output.
91
+ *
92
+ * @param permissionId - Permission UUID
93
+ * @returns Array of roles that have this permission
94
+ */
95
+ export async function getRolesWithPermission(permissionId) {
96
+ const pool = getPool();
97
+ const result = await pool.query(`SELECT r.*
98
+ FROM role_permissions rp
99
+ JOIN roles r ON r.id = rp.role_id
100
+ WHERE rp.permission_id = $1
101
+ ORDER BY r.name ASC`, [permissionId]);
102
+ return result.rows.map(mapRowToRole);
103
+ }
104
+ // ===========================================================================
105
+ // User-Role Mapping
106
+ // ===========================================================================
107
+ /**
108
+ * Assign multiple roles to a user (bulk insert).
109
+ *
110
+ * Uses ON CONFLICT DO NOTHING to make the operation idempotent —
111
+ * already-assigned roles are silently skipped. Tracks who performed
112
+ * the assignment via the optional assignedBy parameter.
113
+ *
114
+ * @param userId - User UUID
115
+ * @param roleIds - Array of role UUIDs to assign
116
+ * @param assignedBy - Optional UUID of the admin who performed the assignment
117
+ */
118
+ export async function assignRolesToUser(userId, roleIds, assignedBy) {
119
+ if (roleIds.length === 0)
120
+ return;
121
+ const pool = getPool();
122
+ // Build parameterized VALUES list
123
+ // $1 = userId, $2 = assignedBy (or null), subsequent params = roleIds
124
+ const valuesList = [];
125
+ const params = [userId, assignedBy ?? null];
126
+ for (let i = 0; i < roleIds.length; i++) {
127
+ params.push(roleIds[i]);
128
+ valuesList.push(`($1, $${i + 3}, $2)`);
129
+ }
130
+ await pool.query(`INSERT INTO user_roles (user_id, role_id, assigned_by)
131
+ VALUES ${valuesList.join(', ')}
132
+ ON CONFLICT DO NOTHING`, params);
133
+ }
134
+ /**
135
+ * Remove multiple roles from a user.
136
+ *
137
+ * Silently succeeds if any of the role IDs are not currently
138
+ * assigned to the user.
139
+ *
140
+ * @param userId - User UUID
141
+ * @param roleIds - Array of role UUIDs to remove
142
+ */
143
+ export async function removeRolesFromUser(userId, roleIds) {
144
+ if (roleIds.length === 0)
145
+ return;
146
+ const pool = getPool();
147
+ // Build parameterized IN list: $2, $3, $4, ...
148
+ const placeholders = roleIds.map((_, i) => `$${i + 2}`).join(', ');
149
+ const params = [userId, ...roleIds];
150
+ await pool.query(`DELETE FROM user_roles WHERE user_id = $1 AND role_id IN (${placeholders})`, params);
151
+ }
152
+ /**
153
+ * Get all roles assigned to a user.
154
+ *
155
+ * JOINs user_roles with roles table to return full Role objects,
156
+ * ordered by name for consistent output.
157
+ *
158
+ * @param userId - User UUID
159
+ * @returns Array of roles assigned to the user
160
+ */
161
+ export async function getRolesForUser(userId) {
162
+ const pool = getPool();
163
+ const result = await pool.query(`SELECT r.*
164
+ FROM user_roles ur
165
+ JOIN roles r ON r.id = ur.role_id
166
+ WHERE ur.user_id = $1
167
+ ORDER BY r.name ASC`, [userId]);
168
+ return result.rows.map(mapRowToRole);
169
+ }
170
+ /**
171
+ * Get all permissions for a user, resolved through their assigned roles.
172
+ *
173
+ * This is the hot path for token claims — it resolves the full chain:
174
+ * user_roles → roles → role_permissions → permissions
175
+ * in a single query. Results are deduplicated (DISTINCT) since a user
176
+ * may have the same permission through multiple roles.
177
+ *
178
+ * @param userId - User UUID
179
+ * @returns Deduplicated array of permissions the user has through their roles
180
+ */
181
+ export async function getPermissionsForUser(userId) {
182
+ const pool = getPool();
183
+ const result = await pool.query(`SELECT DISTINCT p.*
184
+ FROM user_roles ur
185
+ JOIN role_permissions rp ON rp.role_id = ur.role_id
186
+ JOIN permissions p ON p.id = rp.permission_id
187
+ WHERE ur.user_id = $1
188
+ ORDER BY p.slug ASC`, [userId]);
189
+ return result.rows.map(mapRowToPermission);
190
+ }
191
+ /**
192
+ * List user-role assignments for a specific role within an organization.
193
+ *
194
+ * Supports pagination for admin UI views showing which users have a
195
+ * particular role. JOINs with users table to filter by organization.
196
+ *
197
+ * @param roleId - Role UUID
198
+ * @param orgId - Organization UUID (to scope users)
199
+ * @param page - Page number (1-based)
200
+ * @param pageSize - Number of results per page
201
+ * @returns Paginated user-role assignments and total count
202
+ */
203
+ export async function getUsersWithRole(roleId, orgId, page, pageSize) {
204
+ const pool = getPool();
205
+ const offset = (page - 1) * pageSize;
206
+ // Count total matching assignments
207
+ const countResult = await pool.query(`SELECT COUNT(*)::int as count
208
+ FROM user_roles ur
209
+ JOIN users u ON u.id = ur.user_id
210
+ WHERE ur.role_id = $1 AND u.organization_id = $2`, [roleId, orgId]);
211
+ const total = parseInt(countResult.rows[0].count, 10);
212
+ // Fetch paginated data
213
+ const dataResult = await pool.query(`SELECT ur.*
214
+ FROM user_roles ur
215
+ JOIN users u ON u.id = ur.user_id
216
+ WHERE ur.role_id = $1 AND u.organization_id = $2
217
+ ORDER BY ur.created_at DESC
218
+ LIMIT $3 OFFSET $4`, [roleId, orgId, pageSize, offset]);
219
+ return {
220
+ rows: dataResult.rows.map(mapRowToUserRole),
221
+ total,
222
+ };
223
+ }
224
+ //# sourceMappingURL=mapping-repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapping-repository.js","sourceRoot":"","sources":["../../src/rbac/mapping-repository.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEhF,8EAA8E;AAC9E,0BAA0B;AAC1B,8EAA8E;AAE9E;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,MAAc,EACd,aAAuB;IAEvB,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAEvC,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IAEvB,qEAAqE;IACrE,gEAAgE;IAChE,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,MAAM,GAAc,CAAC,MAAM,CAAC,CAAC;IAEnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9C,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9B,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;IAED,MAAM,IAAI,CAAC,KAAK,CACd;cACU,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;4BACP,EACxB,MAAM,CACP,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,MAAc,EACd,aAAuB;IAEvB,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAEvC,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IAEvB,+CAA+C;IAC/C,MAAM,YAAY,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzE,MAAM,MAAM,GAAc,CAAC,MAAM,EAAE,GAAG,aAAa,CAAC,CAAC;IAErD,MAAM,IAAI,CAAC,KAAK,CACd,yEAAyE,YAAY,GAAG,EACxF,MAAM,CACP,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,MAAc;IACxD,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IAEvB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAC7B;;;;yBAIqB,EACrB,CAAC,MAAM,CAAC,CACT,CAAC;IAEF,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,YAAoB;IAC/D,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IAEvB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAC7B;;;;yBAIqB,EACrB,CAAC,YAAY,CAAC,CACf,CAAC;IAEF,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;AACvC,CAAC;AAED,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAc,EACd,OAAiB,EACjB,UAAmB;IAEnB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAEjC,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IAEvB,kCAAkC;IAClC,sEAAsE;IACtE,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,MAAM,GAAc,CAAC,MAAM,EAAE,UAAU,IAAI,IAAI,CAAC,CAAC;IAEvD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QACxB,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC;IAED,MAAM,IAAI,CAAC,KAAK,CACd;cACU,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;4BACP,EACxB,MAAM,CACP,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAAc,EACd,OAAiB;IAEjB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAEjC,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IAEvB,+CAA+C;IAC/C,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnE,MAAM,MAAM,GAAc,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC;IAE/C,MAAM,IAAI,CAAC,KAAK,CACd,6DAA6D,YAAY,GAAG,EAC5E,MAAM,CACP,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAc;IAClD,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IAEvB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAC7B;;;;yBAIqB,EACrB,CAAC,MAAM,CAAC,CACT,CAAC;IAEF,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;AACvC,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,MAAc;IACxD,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IAEvB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAC7B;;;;;yBAKqB,EACrB,CAAC,MAAM,CAAC,CACT,CAAC;IAEF,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAAc,EACd,KAAa,EACb,IAAY,EACZ,QAAgB;IAEhB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC;IAErC,mCAAmC;IACnC,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,KAAK,CAClC;;;sDAGkD,EAClD,CAAC,MAAM,EAAE,KAAK,CAAC,CAChB,CAAC;IACF,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAEtD,uBAAuB;IACvB,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,KAAK,CACjC;;;;;wBAKoB,EACpB,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,CAClC,CAAC;IAEF,OAAO;QACL,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC;QAC3C,KAAK;KACN,CAAC;AACJ,CAAC"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Permission repository — PostgreSQL data access layer.
3
+ *
4
+ * Provides CRUD operations for the `permissions` table using parameterized
5
+ * queries. Each function acquires the pool via `getPool()` and returns
6
+ * mapped Permission objects via `mapRowToPermission()`.
7
+ *
8
+ * Permissions are scoped to an application (application_id FK) with a
9
+ * unique slug per application enforced by DB constraint UNIQUE(application_id, slug).
10
+ * Permissions may optionally be linked to an application module (module_id FK).
11
+ *
12
+ * Key patterns:
13
+ * - Slug is immutable after creation (only name and description can be updated)
14
+ * - List supports optional module filter for scoped permission views
15
+ * - Role count for deletion guard (prevent deleting permissions assigned to roles)
16
+ *
17
+ * Database table: permissions (see migration 006_roles_permissions.sql)
18
+ */
19
+ import type { Permission, CreatePermissionInput, UpdatePermissionInput } from './types.js';
20
+ /**
21
+ * Insert a new permission into the database.
22
+ *
23
+ * Uses RETURNING * to get the full row back in a single round trip.
24
+ * The (application_id, slug) pair must be unique (enforced by DB constraint).
25
+ *
26
+ * @param input - Permission data to insert
27
+ * @returns The newly created permission
28
+ * @throws If (application_id, slug) already exists (unique constraint violation)
29
+ */
30
+ export declare function insertPermission(input: CreatePermissionInput): Promise<Permission>;
31
+ /**
32
+ * Find a permission by its UUID.
33
+ *
34
+ * @param id - Permission UUID
35
+ * @returns Permission or null if not found
36
+ */
37
+ export declare function findPermissionById(id: string): Promise<Permission | null>;
38
+ /**
39
+ * Find a permission by application ID and slug.
40
+ *
41
+ * @param applicationId - Application UUID
42
+ * @param slug - Permission slug (unique within application)
43
+ * @returns Permission or null if not found
44
+ */
45
+ export declare function findPermissionBySlug(applicationId: string, slug: string): Promise<Permission | null>;
46
+ /**
47
+ * Update a permission by ID (name and description only — slug is immutable).
48
+ *
49
+ * Only explicitly provided fields (not undefined) are included in the
50
+ * UPDATE statement. Null is a valid value for description (clears it).
51
+ *
52
+ * @param id - Permission UUID
53
+ * @param input - Fields to update (name, description only)
54
+ * @returns Updated permission
55
+ * @throws Error if permission not found or no fields provided
56
+ */
57
+ export declare function updatePermission(id: string, input: UpdatePermissionInput): Promise<Permission>;
58
+ /**
59
+ * Delete a permission by ID.
60
+ *
61
+ * Returns true if a row was deleted, false if the permission didn't exist.
62
+ * CASCADE constraints will automatically remove related role_permissions entries.
63
+ *
64
+ * @param id - Permission UUID
65
+ * @returns true if deleted, false if not found
66
+ */
67
+ export declare function deletePermission(id: string): Promise<boolean>;
68
+ /**
69
+ * List permissions for an application, optionally filtered by module.
70
+ *
71
+ * Returns a simple array ordered by slug ascending. When moduleId is
72
+ * provided, only permissions linked to that module are returned.
73
+ *
74
+ * @param applicationId - Application UUID
75
+ * @param moduleId - Optional module UUID to filter by
76
+ * @returns Array of permissions
77
+ */
78
+ export declare function listPermissionsByApplication(applicationId: string, moduleId?: string): Promise<Permission[]>;
79
+ /**
80
+ * Check if a permission slug already exists for a given application.
81
+ *
82
+ * Used for uniqueness validation before insert. Permission slugs are
83
+ * immutable, so no excludeId parameter is needed (unlike roles).
84
+ *
85
+ * @param applicationId - Application UUID
86
+ * @param slug - Slug to check
87
+ * @returns true if the slug already exists
88
+ */
89
+ export declare function permissionSlugExists(applicationId: string, slug: string): Promise<boolean>;
90
+ /**
91
+ * Count roles that have a specific permission assigned.
92
+ *
93
+ * Used by the service layer as a deletion guard: if roles have this
94
+ * permission, it cannot be deleted without force=true.
95
+ *
96
+ * @param permissionId - Permission UUID
97
+ * @returns Number of roles with this permission
98
+ */
99
+ export declare function countRolesWithPermission(permissionId: string): Promise<number>;
100
+ //# sourceMappingURL=permission-repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permission-repository.d.ts","sourceRoot":"","sources":["../../src/rbac/permission-repository.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAiB,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAO1G;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,UAAU,CAAC,CAiBxF;AAMD;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAU/E;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,aAAa,EAAE,MAAM,EACrB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAU5B;AAMD;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC,UAAU,CAAC,CA+BrB;AAMD;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CASnE;AAMD;;;;;;;;;GASG;AACH,wBAAsB,4BAA4B,CAChD,aAAa,EAAE,MAAM,EACrB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,UAAU,EAAE,CAAC,CAgBvB;AAMD;;;;;;;;;GASG;AACH,wBAAsB,oBAAoB,CACxC,aAAa,EAAE,MAAM,EACrB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,OAAO,CAAC,CAQlB;AAMD;;;;;;;;GAQG;AACH,wBAAsB,wBAAwB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CASpF"}
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Permission repository — PostgreSQL data access layer.
3
+ *
4
+ * Provides CRUD operations for the `permissions` table using parameterized
5
+ * queries. Each function acquires the pool via `getPool()` and returns
6
+ * mapped Permission objects via `mapRowToPermission()`.
7
+ *
8
+ * Permissions are scoped to an application (application_id FK) with a
9
+ * unique slug per application enforced by DB constraint UNIQUE(application_id, slug).
10
+ * Permissions may optionally be linked to an application module (module_id FK).
11
+ *
12
+ * Key patterns:
13
+ * - Slug is immutable after creation (only name and description can be updated)
14
+ * - List supports optional module filter for scoped permission views
15
+ * - Role count for deletion guard (prevent deleting permissions assigned to roles)
16
+ *
17
+ * Database table: permissions (see migration 006_roles_permissions.sql)
18
+ */
19
+ import { getPool } from '../lib/database.js';
20
+ import { mapRowToPermission } from './types.js';
21
+ // ---------------------------------------------------------------------------
22
+ // Insert
23
+ // ---------------------------------------------------------------------------
24
+ /**
25
+ * Insert a new permission into the database.
26
+ *
27
+ * Uses RETURNING * to get the full row back in a single round trip.
28
+ * The (application_id, slug) pair must be unique (enforced by DB constraint).
29
+ *
30
+ * @param input - Permission data to insert
31
+ * @returns The newly created permission
32
+ * @throws If (application_id, slug) already exists (unique constraint violation)
33
+ */
34
+ export async function insertPermission(input) {
35
+ const pool = getPool();
36
+ const result = await pool.query(`INSERT INTO permissions (application_id, module_id, name, slug, description)
37
+ VALUES ($1, $2, $3, $4, $5)
38
+ RETURNING *`, [
39
+ input.applicationId,
40
+ input.moduleId ?? null,
41
+ input.name,
42
+ input.slug,
43
+ input.description ?? null,
44
+ ]);
45
+ return mapRowToPermission(result.rows[0]);
46
+ }
47
+ // ---------------------------------------------------------------------------
48
+ // Find
49
+ // ---------------------------------------------------------------------------
50
+ /**
51
+ * Find a permission by its UUID.
52
+ *
53
+ * @param id - Permission UUID
54
+ * @returns Permission or null if not found
55
+ */
56
+ export async function findPermissionById(id) {
57
+ const pool = getPool();
58
+ const result = await pool.query('SELECT * FROM permissions WHERE id = $1', [id]);
59
+ if (result.rows.length === 0)
60
+ return null;
61
+ return mapRowToPermission(result.rows[0]);
62
+ }
63
+ /**
64
+ * Find a permission by application ID and slug.
65
+ *
66
+ * @param applicationId - Application UUID
67
+ * @param slug - Permission slug (unique within application)
68
+ * @returns Permission or null if not found
69
+ */
70
+ export async function findPermissionBySlug(applicationId, slug) {
71
+ const pool = getPool();
72
+ const result = await pool.query('SELECT * FROM permissions WHERE application_id = $1 AND slug = $2', [applicationId, slug]);
73
+ if (result.rows.length === 0)
74
+ return null;
75
+ return mapRowToPermission(result.rows[0]);
76
+ }
77
+ // ---------------------------------------------------------------------------
78
+ // Update
79
+ // ---------------------------------------------------------------------------
80
+ /**
81
+ * Update a permission by ID (name and description only — slug is immutable).
82
+ *
83
+ * Only explicitly provided fields (not undefined) are included in the
84
+ * UPDATE statement. Null is a valid value for description (clears it).
85
+ *
86
+ * @param id - Permission UUID
87
+ * @param input - Fields to update (name, description only)
88
+ * @returns Updated permission
89
+ * @throws Error if permission not found or no fields provided
90
+ */
91
+ export async function updatePermission(id, input) {
92
+ const pool = getPool();
93
+ // Build dynamic SET clause — only name and description are updatable
94
+ const setClauses = [];
95
+ const values = [id]; // $1 is always the ID
96
+ let paramIndex = 2;
97
+ if (input.name !== undefined) {
98
+ setClauses.push(`name = $${paramIndex}`);
99
+ values.push(input.name);
100
+ paramIndex++;
101
+ }
102
+ if (input.description !== undefined) {
103
+ setClauses.push(`description = $${paramIndex}`);
104
+ values.push(input.description);
105
+ }
106
+ if (setClauses.length === 0) {
107
+ throw new Error('No fields to update');
108
+ }
109
+ const sql = `UPDATE permissions SET ${setClauses.join(', ')} WHERE id = $1 RETURNING *`;
110
+ const result = await pool.query(sql, values);
111
+ if (result.rows.length === 0) {
112
+ throw new Error('Permission not found');
113
+ }
114
+ return mapRowToPermission(result.rows[0]);
115
+ }
116
+ // ---------------------------------------------------------------------------
117
+ // Delete
118
+ // ---------------------------------------------------------------------------
119
+ /**
120
+ * Delete a permission by ID.
121
+ *
122
+ * Returns true if a row was deleted, false if the permission didn't exist.
123
+ * CASCADE constraints will automatically remove related role_permissions entries.
124
+ *
125
+ * @param id - Permission UUID
126
+ * @returns true if deleted, false if not found
127
+ */
128
+ export async function deletePermission(id) {
129
+ const pool = getPool();
130
+ const result = await pool.query('DELETE FROM permissions WHERE id = $1', [id]);
131
+ return (result.rowCount ?? 0) > 0;
132
+ }
133
+ // ---------------------------------------------------------------------------
134
+ // List
135
+ // ---------------------------------------------------------------------------
136
+ /**
137
+ * List permissions for an application, optionally filtered by module.
138
+ *
139
+ * Returns a simple array ordered by slug ascending. When moduleId is
140
+ * provided, only permissions linked to that module are returned.
141
+ *
142
+ * @param applicationId - Application UUID
143
+ * @param moduleId - Optional module UUID to filter by
144
+ * @returns Array of permissions
145
+ */
146
+ export async function listPermissionsByApplication(applicationId, moduleId) {
147
+ const pool = getPool();
148
+ if (moduleId) {
149
+ const result = await pool.query('SELECT * FROM permissions WHERE application_id = $1 AND module_id = $2 ORDER BY slug ASC', [applicationId, moduleId]);
150
+ return result.rows.map(mapRowToPermission);
151
+ }
152
+ const result = await pool.query('SELECT * FROM permissions WHERE application_id = $1 ORDER BY slug ASC', [applicationId]);
153
+ return result.rows.map(mapRowToPermission);
154
+ }
155
+ // ---------------------------------------------------------------------------
156
+ // Slug existence check
157
+ // ---------------------------------------------------------------------------
158
+ /**
159
+ * Check if a permission slug already exists for a given application.
160
+ *
161
+ * Used for uniqueness validation before insert. Permission slugs are
162
+ * immutable, so no excludeId parameter is needed (unlike roles).
163
+ *
164
+ * @param applicationId - Application UUID
165
+ * @param slug - Slug to check
166
+ * @returns true if the slug already exists
167
+ */
168
+ export async function permissionSlugExists(applicationId, slug) {
169
+ const pool = getPool();
170
+ const result = await pool.query('SELECT EXISTS(SELECT 1 FROM permissions WHERE application_id = $1 AND slug = $2) as exists', [applicationId, slug]);
171
+ return result.rows[0].exists;
172
+ }
173
+ // ---------------------------------------------------------------------------
174
+ // Role count (deletion guard)
175
+ // ---------------------------------------------------------------------------
176
+ /**
177
+ * Count roles that have a specific permission assigned.
178
+ *
179
+ * Used by the service layer as a deletion guard: if roles have this
180
+ * permission, it cannot be deleted without force=true.
181
+ *
182
+ * @param permissionId - Permission UUID
183
+ * @returns Number of roles with this permission
184
+ */
185
+ export async function countRolesWithPermission(permissionId) {
186
+ const pool = getPool();
187
+ const result = await pool.query('SELECT COUNT(*)::int as count FROM role_permissions WHERE permission_id = $1', [permissionId]);
188
+ return parseInt(result.rows[0].count, 10);
189
+ }
190
+ //# sourceMappingURL=permission-repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permission-repository.js","sourceRoot":"","sources":["../../src/rbac/permission-repository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Permission service — business logic for permission management.
3
+ *
4
+ * Orchestrates permission CRUD operations with slug format validation,
5
+ * uniqueness checks, deletion guards, cache management, and audit logging.
6
+ *
7
+ * Permission slugs follow the module:resource:action format (e.g.,
8
+ * "crm:contacts:read") and are immutable after creation — only name
9
+ * and description can be updated.
10
+ *
11
+ * All write operations follow the pattern:
12
+ * validate → DB operation → cache invalidate → audit log
13
+ *
14
+ * @see permission-repository.ts — Database operations
15
+ * @see mapping-repository.ts — Role-permission lookups
16
+ * @see cache.ts — Redis cache operations
17
+ */
18
+ import type { Permission, Role, CreatePermissionInput, UpdatePermissionInput } from './types.js';
19
+ /**
20
+ * Create a new permission for an application.
21
+ *
22
+ * Validates that the slug follows the module:resource:action format
23
+ * and ensures uniqueness within the application.
24
+ *
25
+ * @param input - Permission creation data
26
+ * @param actorId - Optional UUID of the admin performing the action
27
+ * @returns The newly created permission
28
+ * @throws RbacValidationError if slug format is invalid or already exists
29
+ */
30
+ export declare function createPermission(input: CreatePermissionInput, actorId?: string): Promise<Permission>;
31
+ /**
32
+ * Find a permission by ID.
33
+ *
34
+ * @param id - Permission UUID
35
+ * @returns Permission or null if not found
36
+ */
37
+ export declare function findPermissionById(id: string): Promise<Permission | null>;
38
+ /**
39
+ * Find a permission by application ID and slug.
40
+ *
41
+ * @param applicationId - Application UUID
42
+ * @param slug - Permission slug
43
+ * @returns Permission or null if not found
44
+ */
45
+ export declare function findPermissionBySlug(applicationId: string, slug: string): Promise<Permission | null>;
46
+ /**
47
+ * List permissions for an application, optionally filtered by module.
48
+ *
49
+ * @param applicationId - Application UUID
50
+ * @param moduleId - Optional module UUID to filter by
51
+ * @returns Array of permissions
52
+ */
53
+ export declare function listPermissionsByApplication(applicationId: string, moduleId?: string): Promise<Permission[]>;
54
+ /**
55
+ * Update a permission by ID (name and description only — slug is immutable).
56
+ *
57
+ * @param id - Permission UUID
58
+ * @param input - Fields to update (name, description only)
59
+ * @param actorId - Optional UUID of the admin performing the action
60
+ * @returns Updated permission
61
+ * @throws PermissionNotFoundError if permission doesn't exist
62
+ */
63
+ export declare function updatePermission(id: string, input: UpdatePermissionInput, actorId?: string): Promise<Permission>;
64
+ /**
65
+ * Delete a permission by ID.
66
+ *
67
+ * By default (force=false), refuses to delete permissions that are
68
+ * assigned to any role. Pass force=true to delete regardless —
69
+ * CASCADE will remove role_permissions entries.
70
+ *
71
+ * @param id - Permission UUID
72
+ * @param force - If true, delete even if assigned to roles
73
+ * @param actorId - Optional UUID of the admin performing the action
74
+ * @throws PermissionNotFoundError if permission doesn't exist
75
+ * @throws RbacValidationError if assigned to roles and force is false
76
+ */
77
+ export declare function deletePermission(id: string, force?: boolean, actorId?: string): Promise<void>;
78
+ /**
79
+ * Get all roles that have a specific permission assigned.
80
+ *
81
+ * @param permissionId - Permission UUID
82
+ * @returns Array of roles with this permission
83
+ */
84
+ export declare function getRolesWithPermission(permissionId: string): Promise<Role[]>;
85
+ //# sourceMappingURL=permission-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permission-service.d.ts","sourceRoot":"","sources":["../../src/rbac/permission-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAiBH,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAMjG;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,qBAAqB,EAC5B,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,UAAU,CAAC,CAgCrB;AAMD;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAE/E;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,aAAa,EAAE,MAAM,EACrB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAE5B;AAED;;;;;;GAMG;AACH,wBAAsB,4BAA4B,CAChD,aAAa,EAAE,MAAM,EACrB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,UAAU,EAAE,CAAC,CAEvB;AAMD;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,qBAAqB,EAC5B,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,UAAU,CAAC,CAmBrB;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,MAAM,EACV,KAAK,GAAE,OAAe,EACtB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAgCf;AAMD;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAElF"}