@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,179 @@
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 { insertPermission, findPermissionById as repoFindPermissionById, findPermissionBySlug as repoFindPermissionBySlug, updatePermission as repoUpdatePermission, deletePermission as repoDeletePermission, listPermissionsByApplication as repoListPermissionsByApplication, permissionSlugExists, countRolesWithPermission, } from './permission-repository.js';
19
+ import { getRolesWithPermission as repoGetRolesWithPermission } from './mapping-repository.js';
20
+ import { invalidateAllUserRbacCaches } from './cache.js';
21
+ import { validatePermissionSlug } from './slugs.js';
22
+ import { PermissionNotFoundError, RbacValidationError } from './errors.js';
23
+ import { writeAuditLog } from '../lib/audit-log.js';
24
+ // ---------------------------------------------------------------------------
25
+ // Create
26
+ // ---------------------------------------------------------------------------
27
+ /**
28
+ * Create a new permission for an application.
29
+ *
30
+ * Validates that the slug follows the module:resource:action format
31
+ * and ensures uniqueness within the application.
32
+ *
33
+ * @param input - Permission creation data
34
+ * @param actorId - Optional UUID of the admin performing the action
35
+ * @returns The newly created permission
36
+ * @throws RbacValidationError if slug format is invalid or already exists
37
+ */
38
+ export async function createPermission(input, actorId) {
39
+ // Validate permission slug format (module:resource:action)
40
+ if (!validatePermissionSlug(input.slug)) {
41
+ throw new RbacValidationError(`Invalid permission slug format: "${input.slug}". Must follow module:resource:action pattern with at least 3 colon-separated segments.`);
42
+ }
43
+ // Check slug uniqueness within the application
44
+ const exists = await permissionSlugExists(input.applicationId, input.slug);
45
+ if (exists) {
46
+ throw new RbacValidationError(`Permission slug "${input.slug}" already exists for this application.`);
47
+ }
48
+ // Insert the permission
49
+ const permission = await insertPermission(input);
50
+ // Audit log (fire-and-forget)
51
+ void writeAuditLog({
52
+ eventType: 'permission.created',
53
+ eventCategory: 'admin',
54
+ actorId,
55
+ metadata: {
56
+ permissionId: permission.id,
57
+ applicationId: permission.applicationId,
58
+ slug: permission.slug,
59
+ },
60
+ });
61
+ return permission;
62
+ }
63
+ // ---------------------------------------------------------------------------
64
+ // Read
65
+ // ---------------------------------------------------------------------------
66
+ /**
67
+ * Find a permission by ID.
68
+ *
69
+ * @param id - Permission UUID
70
+ * @returns Permission or null if not found
71
+ */
72
+ export async function findPermissionById(id) {
73
+ return repoFindPermissionById(id);
74
+ }
75
+ /**
76
+ * Find a permission by application ID and slug.
77
+ *
78
+ * @param applicationId - Application UUID
79
+ * @param slug - Permission slug
80
+ * @returns Permission or null if not found
81
+ */
82
+ export async function findPermissionBySlug(applicationId, slug) {
83
+ return repoFindPermissionBySlug(applicationId, slug);
84
+ }
85
+ /**
86
+ * List permissions for an application, optionally filtered by module.
87
+ *
88
+ * @param applicationId - Application UUID
89
+ * @param moduleId - Optional module UUID to filter by
90
+ * @returns Array of permissions
91
+ */
92
+ export async function listPermissionsByApplication(applicationId, moduleId) {
93
+ return repoListPermissionsByApplication(applicationId, moduleId);
94
+ }
95
+ // ---------------------------------------------------------------------------
96
+ // Update
97
+ // ---------------------------------------------------------------------------
98
+ /**
99
+ * Update a permission by ID (name and description only — slug is immutable).
100
+ *
101
+ * @param id - Permission UUID
102
+ * @param input - Fields to update (name, description only)
103
+ * @param actorId - Optional UUID of the admin performing the action
104
+ * @returns Updated permission
105
+ * @throws PermissionNotFoundError if permission doesn't exist
106
+ */
107
+ export async function updatePermission(id, input, actorId) {
108
+ // Verify permission exists
109
+ const existing = await repoFindPermissionById(id);
110
+ if (!existing) {
111
+ throw new PermissionNotFoundError(id);
112
+ }
113
+ // Perform the update (slug is not updatable at the repository level)
114
+ const updated = await repoUpdatePermission(id, input);
115
+ // Audit log (fire-and-forget)
116
+ void writeAuditLog({
117
+ eventType: 'permission.updated',
118
+ eventCategory: 'admin',
119
+ actorId,
120
+ metadata: { permissionId: id, changes: input },
121
+ });
122
+ return updated;
123
+ }
124
+ // ---------------------------------------------------------------------------
125
+ // Delete
126
+ // ---------------------------------------------------------------------------
127
+ /**
128
+ * Delete a permission by ID.
129
+ *
130
+ * By default (force=false), refuses to delete permissions that are
131
+ * assigned to any role. Pass force=true to delete regardless —
132
+ * CASCADE will remove role_permissions entries.
133
+ *
134
+ * @param id - Permission UUID
135
+ * @param force - If true, delete even if assigned to roles
136
+ * @param actorId - Optional UUID of the admin performing the action
137
+ * @throws PermissionNotFoundError if permission doesn't exist
138
+ * @throws RbacValidationError if assigned to roles and force is false
139
+ */
140
+ export async function deletePermission(id, force = false, actorId) {
141
+ // Verify permission exists
142
+ const existing = await repoFindPermissionById(id);
143
+ if (!existing) {
144
+ throw new PermissionNotFoundError(id);
145
+ }
146
+ // Deletion guard: check for assigned roles
147
+ if (!force) {
148
+ const roleCount = await countRolesWithPermission(id);
149
+ if (roleCount > 0) {
150
+ throw new RbacValidationError(`Cannot delete permission "${existing.slug}": assigned to ${roleCount} role(s). Use force=true to override.`);
151
+ }
152
+ }
153
+ // Delete the permission (CASCADE handles related records)
154
+ await repoDeletePermission(id);
155
+ // Invalidate user caches — permissions may have changed for users who had this
156
+ if (force) {
157
+ await invalidateAllUserRbacCaches();
158
+ }
159
+ // Audit log (fire-and-forget)
160
+ void writeAuditLog({
161
+ eventType: 'permission.deleted',
162
+ eventCategory: 'admin',
163
+ actorId,
164
+ metadata: { permissionId: id, slug: existing.slug, force },
165
+ });
166
+ }
167
+ // ---------------------------------------------------------------------------
168
+ // Role lookups
169
+ // ---------------------------------------------------------------------------
170
+ /**
171
+ * Get all roles that have a specific permission assigned.
172
+ *
173
+ * @param permissionId - Permission UUID
174
+ * @returns Array of roles with this permission
175
+ */
176
+ export async function getRolesWithPermission(permissionId) {
177
+ return repoGetRolesWithPermission(permissionId);
178
+ }
179
+ //# sourceMappingURL=permission-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permission-service.js","sourceRoot":"","sources":["../../src/rbac/permission-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Role repository — PostgreSQL data access layer.
3
+ *
4
+ * Provides CRUD operations for the `roles` table using parameterized
5
+ * queries. Each function acquires the pool via `getPool()` and returns
6
+ * mapped Role objects via `mapRowToRole()`.
7
+ *
8
+ * Roles are scoped to an application (application_id FK) with a unique
9
+ * slug per application enforced by the DB constraint UNIQUE(application_id, slug).
10
+ *
11
+ * Key patterns:
12
+ * - Dynamic UPDATE query builder for partial updates (name, slug, description)
13
+ * - Simple list by application (no pagination — typically <100 roles per app)
14
+ * - Slug existence check with optional excludeId for update scenarios
15
+ * - User count for deletion guard (prevent deleting roles with assigned users)
16
+ *
17
+ * Database table: roles (see migration 006_roles_permissions.sql)
18
+ */
19
+ import type { Role, CreateRoleInput, UpdateRoleInput } from './types.js';
20
+ /**
21
+ * Insert a new role 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 - Role data to insert
27
+ * @returns The newly created role
28
+ * @throws If (application_id, slug) already exists (unique constraint violation)
29
+ */
30
+ export declare function insertRole(input: CreateRoleInput): Promise<Role>;
31
+ /**
32
+ * Find a role by its UUID.
33
+ *
34
+ * @param id - Role UUID
35
+ * @returns Role or null if not found
36
+ */
37
+ export declare function findRoleById(id: string): Promise<Role | null>;
38
+ /**
39
+ * Find a role by application ID and slug.
40
+ *
41
+ * @param applicationId - Application UUID
42
+ * @param slug - Role slug (unique within application)
43
+ * @returns Role or null if not found
44
+ */
45
+ export declare function findRoleBySlug(applicationId: string, slug: string): Promise<Role | null>;
46
+ /**
47
+ * Update a role's fields using a dynamic SET clause.
48
+ *
49
+ * Only explicitly provided fields (not undefined) are included in the
50
+ * UPDATE statement. This allows partial updates without overwriting
51
+ * fields that weren't specified. Null is a valid value for description
52
+ * (clears it).
53
+ *
54
+ * @param id - Role UUID
55
+ * @param input - Fields to update (only non-undefined fields are applied)
56
+ * @returns Updated role
57
+ * @throws Error if role not found or no fields provided
58
+ */
59
+ export declare function updateRole(id: string, input: UpdateRoleInput): Promise<Role>;
60
+ /**
61
+ * Delete a role by ID.
62
+ *
63
+ * Returns true if a row was deleted, false if the role didn't exist.
64
+ * CASCADE constraints will automatically remove related role_permissions
65
+ * and user_roles entries.
66
+ *
67
+ * @param id - Role UUID
68
+ * @returns true if deleted, false if not found
69
+ */
70
+ export declare function deleteRole(id: string): Promise<boolean>;
71
+ /**
72
+ * List all roles for an application, ordered by name ascending.
73
+ *
74
+ * Returns a simple array (no pagination) since applications typically
75
+ * have a manageable number of roles (<100).
76
+ *
77
+ * @param applicationId - Application UUID
78
+ * @returns Array of roles for the application
79
+ */
80
+ export declare function listRolesByApplication(applicationId: string): Promise<Role[]>;
81
+ /**
82
+ * Check if a role slug already exists for a given application.
83
+ *
84
+ * Used for uniqueness validation before insert or update. The optional
85
+ * excludeId parameter allows excluding a specific role (for updates —
86
+ * a role's own current slug should not block the update).
87
+ *
88
+ * @param applicationId - Application UUID
89
+ * @param slug - Slug to check
90
+ * @param excludeId - Optional role ID to exclude from the check
91
+ * @returns true if the slug already exists
92
+ */
93
+ export declare function roleSlugExists(applicationId: string, slug: string, excludeId?: string): Promise<boolean>;
94
+ /**
95
+ * Count users assigned to a role.
96
+ *
97
+ * Used by the service layer as a deletion guard: if users are assigned,
98
+ * the role cannot be deleted without force=true.
99
+ *
100
+ * @param roleId - Role UUID
101
+ * @returns Number of users with this role
102
+ */
103
+ export declare function countUsersWithRole(roleId: string): Promise<number>;
104
+ //# sourceMappingURL=role-repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"role-repository.d.ts","sourceRoot":"","sources":["../../src/rbac/role-repository.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAW,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAOlF;;;;;;;;;GASG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBtE;AAMD;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAUnE;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAU9F;AAgBD;;;;;;;;;;;;GAYG;AACH,wBAAsB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BlF;AAMD;;;;;;;;;GASG;AACH,wBAAsB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAS7D;AAMD;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CASnF;AAMD;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAClC,aAAa,EAAE,MAAM,EACrB,IAAI,EAAE,MAAM,EACZ,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,OAAO,CAAC,CAgBlB;AAMD;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CASxE"}
@@ -0,0 +1,202 @@
1
+ /**
2
+ * Role repository — PostgreSQL data access layer.
3
+ *
4
+ * Provides CRUD operations for the `roles` table using parameterized
5
+ * queries. Each function acquires the pool via `getPool()` and returns
6
+ * mapped Role objects via `mapRowToRole()`.
7
+ *
8
+ * Roles are scoped to an application (application_id FK) with a unique
9
+ * slug per application enforced by the DB constraint UNIQUE(application_id, slug).
10
+ *
11
+ * Key patterns:
12
+ * - Dynamic UPDATE query builder for partial updates (name, slug, description)
13
+ * - Simple list by application (no pagination — typically <100 roles per app)
14
+ * - Slug existence check with optional excludeId for update scenarios
15
+ * - User count for deletion guard (prevent deleting roles with assigned users)
16
+ *
17
+ * Database table: roles (see migration 006_roles_permissions.sql)
18
+ */
19
+ import { getPool } from '../lib/database.js';
20
+ import { mapRowToRole } from './types.js';
21
+ // ---------------------------------------------------------------------------
22
+ // Insert
23
+ // ---------------------------------------------------------------------------
24
+ /**
25
+ * Insert a new role 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 - Role data to insert
31
+ * @returns The newly created role
32
+ * @throws If (application_id, slug) already exists (unique constraint violation)
33
+ */
34
+ export async function insertRole(input) {
35
+ const pool = getPool();
36
+ const result = await pool.query(`INSERT INTO roles (application_id, name, slug, description)
37
+ VALUES ($1, $2, $3, $4)
38
+ RETURNING *`, [
39
+ input.applicationId,
40
+ input.name,
41
+ input.slug ?? null,
42
+ input.description ?? null,
43
+ ]);
44
+ return mapRowToRole(result.rows[0]);
45
+ }
46
+ // ---------------------------------------------------------------------------
47
+ // Find
48
+ // ---------------------------------------------------------------------------
49
+ /**
50
+ * Find a role by its UUID.
51
+ *
52
+ * @param id - Role UUID
53
+ * @returns Role or null if not found
54
+ */
55
+ export async function findRoleById(id) {
56
+ const pool = getPool();
57
+ const result = await pool.query('SELECT * FROM roles WHERE id = $1', [id]);
58
+ if (result.rows.length === 0)
59
+ return null;
60
+ return mapRowToRole(result.rows[0]);
61
+ }
62
+ /**
63
+ * Find a role by application ID and slug.
64
+ *
65
+ * @param applicationId - Application UUID
66
+ * @param slug - Role slug (unique within application)
67
+ * @returns Role or null if not found
68
+ */
69
+ export async function findRoleBySlug(applicationId, slug) {
70
+ const pool = getPool();
71
+ const result = await pool.query('SELECT * FROM roles WHERE application_id = $1 AND slug = $2', [applicationId, slug]);
72
+ if (result.rows.length === 0)
73
+ return null;
74
+ return mapRowToRole(result.rows[0]);
75
+ }
76
+ // ---------------------------------------------------------------------------
77
+ // Update
78
+ // ---------------------------------------------------------------------------
79
+ /**
80
+ * Mapping from UpdateRoleInput keys to database column names.
81
+ * Used by the dynamic query builder to construct SET clauses.
82
+ */
83
+ const FIELD_TO_COLUMN = {
84
+ name: 'name',
85
+ slug: 'slug',
86
+ description: 'description',
87
+ };
88
+ /**
89
+ * Update a role's fields using a dynamic SET clause.
90
+ *
91
+ * Only explicitly provided fields (not undefined) are included in the
92
+ * UPDATE statement. This allows partial updates without overwriting
93
+ * fields that weren't specified. Null is a valid value for description
94
+ * (clears it).
95
+ *
96
+ * @param id - Role UUID
97
+ * @param input - Fields to update (only non-undefined fields are applied)
98
+ * @returns Updated role
99
+ * @throws Error if role not found or no fields provided
100
+ */
101
+ export async function updateRole(id, input) {
102
+ const pool = getPool();
103
+ // Build dynamic SET clause from provided fields
104
+ const setClauses = [];
105
+ const values = [id]; // $1 is always the ID
106
+ let paramIndex = 2;
107
+ for (const [field, column] of Object.entries(FIELD_TO_COLUMN)) {
108
+ const value = input[field];
109
+ // Include the field if it's explicitly set (including null for clearing)
110
+ if (value !== undefined) {
111
+ setClauses.push(`${column} = $${paramIndex}`);
112
+ values.push(value);
113
+ paramIndex++;
114
+ }
115
+ }
116
+ if (setClauses.length === 0) {
117
+ throw new Error('No fields to update');
118
+ }
119
+ const sql = `UPDATE roles SET ${setClauses.join(', ')} WHERE id = $1 RETURNING *`;
120
+ const result = await pool.query(sql, values);
121
+ if (result.rows.length === 0) {
122
+ throw new Error('Role not found');
123
+ }
124
+ return mapRowToRole(result.rows[0]);
125
+ }
126
+ // ---------------------------------------------------------------------------
127
+ // Delete
128
+ // ---------------------------------------------------------------------------
129
+ /**
130
+ * Delete a role by ID.
131
+ *
132
+ * Returns true if a row was deleted, false if the role didn't exist.
133
+ * CASCADE constraints will automatically remove related role_permissions
134
+ * and user_roles entries.
135
+ *
136
+ * @param id - Role UUID
137
+ * @returns true if deleted, false if not found
138
+ */
139
+ export async function deleteRole(id) {
140
+ const pool = getPool();
141
+ const result = await pool.query('DELETE FROM roles WHERE id = $1', [id]);
142
+ return (result.rowCount ?? 0) > 0;
143
+ }
144
+ // ---------------------------------------------------------------------------
145
+ // List
146
+ // ---------------------------------------------------------------------------
147
+ /**
148
+ * List all roles for an application, ordered by name ascending.
149
+ *
150
+ * Returns a simple array (no pagination) since applications typically
151
+ * have a manageable number of roles (<100).
152
+ *
153
+ * @param applicationId - Application UUID
154
+ * @returns Array of roles for the application
155
+ */
156
+ export async function listRolesByApplication(applicationId) {
157
+ const pool = getPool();
158
+ const result = await pool.query('SELECT * FROM roles WHERE application_id = $1 ORDER BY name ASC', [applicationId]);
159
+ return result.rows.map(mapRowToRole);
160
+ }
161
+ // ---------------------------------------------------------------------------
162
+ // Slug existence check
163
+ // ---------------------------------------------------------------------------
164
+ /**
165
+ * Check if a role slug already exists for a given application.
166
+ *
167
+ * Used for uniqueness validation before insert or update. The optional
168
+ * excludeId parameter allows excluding a specific role (for updates —
169
+ * a role's own current slug should not block the update).
170
+ *
171
+ * @param applicationId - Application UUID
172
+ * @param slug - Slug to check
173
+ * @param excludeId - Optional role ID to exclude from the check
174
+ * @returns true if the slug already exists
175
+ */
176
+ export async function roleSlugExists(applicationId, slug, excludeId) {
177
+ const pool = getPool();
178
+ if (excludeId) {
179
+ const result = await pool.query('SELECT EXISTS(SELECT 1 FROM roles WHERE application_id = $1 AND slug = $2 AND id != $3) as exists', [applicationId, slug, excludeId]);
180
+ return result.rows[0].exists;
181
+ }
182
+ const result = await pool.query('SELECT EXISTS(SELECT 1 FROM roles WHERE application_id = $1 AND slug = $2) as exists', [applicationId, slug]);
183
+ return result.rows[0].exists;
184
+ }
185
+ // ---------------------------------------------------------------------------
186
+ // User count (deletion guard)
187
+ // ---------------------------------------------------------------------------
188
+ /**
189
+ * Count users assigned to a role.
190
+ *
191
+ * Used by the service layer as a deletion guard: if users are assigned,
192
+ * the role cannot be deleted without force=true.
193
+ *
194
+ * @param roleId - Role UUID
195
+ * @returns Number of users with this role
196
+ */
197
+ export async function countUsersWithRole(roleId) {
198
+ const pool = getPool();
199
+ const result = await pool.query('SELECT COUNT(*)::int as count FROM user_roles WHERE role_id = $1', [roleId]);
200
+ return parseInt(result.rows[0].count, 10);
201
+ }
202
+ //# sourceMappingURL=role-repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"role-repository.js","sourceRoot":"","sources":["../../src/rbac/role-repository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Role service — business logic for role management.
3
+ *
4
+ * Orchestrates role CRUD operations with slug validation, uniqueness
5
+ * checks, deletion guards, cache management, and audit logging.
6
+ * Also handles role-permission assignment operations.
7
+ *
8
+ * All write operations follow the pattern:
9
+ * validate → DB operation → cache invalidate/re-cache → audit log
10
+ *
11
+ * Uses fire-and-forget audit logging — audit failures never block
12
+ * the primary operation.
13
+ *
14
+ * @see role-repository.ts — Database operations
15
+ * @see mapping-repository.ts — Role-permission join table operations
16
+ * @see cache.ts — Redis cache operations
17
+ */
18
+ import type { Role, Permission, CreateRoleInput, UpdateRoleInput } from './types.js';
19
+ /**
20
+ * Create a new role for an application.
21
+ *
22
+ * Auto-generates a slug from the name if not explicitly provided.
23
+ * Validates slug format and ensures uniqueness within the application.
24
+ *
25
+ * @param input - Role creation data
26
+ * @param actorId - Optional UUID of the admin performing the action
27
+ * @returns The newly created role
28
+ * @throws RbacValidationError if slug is invalid or already exists
29
+ */
30
+ export declare function createRole(input: CreateRoleInput, actorId?: string): Promise<Role>;
31
+ /**
32
+ * Find a role by ID. Cache-first, falls back to DB.
33
+ *
34
+ * @param id - Role UUID
35
+ * @returns Role or null if not found
36
+ */
37
+ export declare function findRoleById(id: string): Promise<Role | null>;
38
+ /**
39
+ * Find a role by application ID and slug.
40
+ *
41
+ * @param applicationId - Application UUID
42
+ * @param slug - Role slug
43
+ * @returns Role or null if not found
44
+ */
45
+ export declare function findRoleBySlug(applicationId: string, slug: string): Promise<Role | null>;
46
+ /**
47
+ * List all roles for an application.
48
+ *
49
+ * @param applicationId - Application UUID
50
+ * @returns Array of roles
51
+ */
52
+ export declare function listRolesByApplication(applicationId: string): Promise<Role[]>;
53
+ /**
54
+ * Update a role by ID.
55
+ *
56
+ * If the slug is being changed, validates the new slug format and
57
+ * checks uniqueness within the application. Invalidates and re-caches
58
+ * the role after update.
59
+ *
60
+ * @param id - Role UUID
61
+ * @param input - Fields to update
62
+ * @param actorId - Optional UUID of the admin performing the action
63
+ * @returns Updated role
64
+ * @throws RoleNotFoundError if role doesn't exist
65
+ * @throws RbacValidationError if new slug is invalid or already exists
66
+ */
67
+ export declare function updateRole(id: string, input: UpdateRoleInput, actorId?: string): Promise<Role>;
68
+ /**
69
+ * Delete a role by ID.
70
+ *
71
+ * By default (force=false), refuses to delete roles that have users
72
+ * assigned. Pass force=true to delete regardless — CASCADE will
73
+ * remove user_roles and role_permissions entries.
74
+ *
75
+ * @param id - Role UUID
76
+ * @param force - If true, delete even if users are assigned
77
+ * @param actorId - Optional UUID of the admin performing the action
78
+ * @throws RoleNotFoundError if role doesn't exist
79
+ * @throws RbacValidationError if users are assigned and force is false
80
+ */
81
+ export declare function deleteRole(id: string, force?: boolean, actorId?: string): Promise<void>;
82
+ /**
83
+ * Assign permissions to a role.
84
+ *
85
+ * Delegates to the mapping repository for bulk insert. Invalidates
86
+ * all user RBAC caches since user permissions may have changed.
87
+ *
88
+ * @param roleId - Role UUID
89
+ * @param permissionIds - Array of permission UUIDs to assign
90
+ * @param actorId - Optional UUID of the admin performing the action
91
+ */
92
+ export declare function assignPermissionsToRole(roleId: string, permissionIds: string[], actorId?: string): Promise<void>;
93
+ /**
94
+ * Remove permissions from a role.
95
+ *
96
+ * Delegates to the mapping repository. Invalidates all user RBAC
97
+ * caches since user permissions may have changed.
98
+ *
99
+ * @param roleId - Role UUID
100
+ * @param permissionIds - Array of permission UUIDs to remove
101
+ * @param actorId - Optional UUID of the admin performing the action
102
+ */
103
+ export declare function removePermissionsFromRole(roleId: string, permissionIds: string[], actorId?: string): Promise<void>;
104
+ /**
105
+ * Get all permissions assigned to a role.
106
+ *
107
+ * @param roleId - Role UUID
108
+ * @returns Array of permissions
109
+ */
110
+ export declare function getPermissionsForRole(roleId: string): Promise<Permission[]>;
111
+ //# sourceMappingURL=role-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"role-service.d.ts","sourceRoot":"","sources":["../../src/rbac/role-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AA0BH,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAMrF;;;;;;;;;;GAUG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkCxF;AAMD;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAanE;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAE9F;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAEnF;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,UAAU,CAC9B,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,eAAe,EACtB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAuCf;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAsB,UAAU,CAC9B,EAAE,EAAE,MAAM,EACV,KAAK,GAAE,OAAe,EACtB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAkCf;AAMD;;;;;;;;;GASG;AACH,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EAAE,EACvB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAef;AAED;;;;;;;;;GASG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EAAE,EACvB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAef;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAEjF"}