@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,511 @@
1
+ /**
2
+ * Organization service — business logic orchestrator.
3
+ *
4
+ * Composes the repository, cache, slug utilities, and audit log
5
+ * to provide the complete organization management API. All write
6
+ * operations follow the pattern:
7
+ * 1. Validate inputs
8
+ * 2. Perform DB operation (via repository)
9
+ * 3. Invalidate + re-cache (via cache)
10
+ * 4. Write audit log (fire-and-forget)
11
+ *
12
+ * Read operations check cache first, fall back to DB on miss.
13
+ *
14
+ * Status lifecycle rules:
15
+ * - suspend: active → suspended (super-admin blocked)
16
+ * - activate: suspended → active
17
+ * - archive: active|suspended → archived (super-admin blocked)
18
+ * - restore: archived → active
19
+ */
20
+ import { insertOrganization, findOrganizationById, findOrganizationBySlug, updateOrganization as repoUpdate, listOrganizations as repoList, listOrganizationsCursor as repoListCursor, slugExists, hardDeleteOrganization, getCascadeCounts as repoGetCascadeCounts, } from './repository.js';
21
+ import { getCachedOrganizationById, getCachedOrganizationBySlug, cacheOrganization, invalidateOrganizationCache, } from './cache.js';
22
+ import { generateSlug, validateSlug } from './slugs.js';
23
+ import { writeAuditLog } from '../lib/audit-log.js';
24
+ import { OrganizationNotFoundError, OrganizationValidationError } from './errors.js';
25
+ // Import directly from the type/resolver modules (not the clients barrel)
26
+ // to keep the org→clients dependency narrow and avoid pulling the entire
27
+ // clients service surface into the organizations module.
28
+ import { LOGIN_METHODS } from '../clients/types.js';
29
+ import { normalizeLoginMethods } from '../clients/resolve-login-methods.js';
30
+ // ---------------------------------------------------------------------------
31
+ // Validation helpers (private)
32
+ // ---------------------------------------------------------------------------
33
+ /**
34
+ * Validate + normalize a `defaultLoginMethods` input array.
35
+ *
36
+ * Throws {@link OrganizationValidationError} when:
37
+ * - the value is not an array
38
+ * - the array is empty
39
+ * - any element is not a valid {@link LoginMethod}
40
+ *
41
+ * Returns the normalized (deduplicated, order-preserving) array on success.
42
+ */
43
+ function validateDefaultLoginMethods(methods) {
44
+ if (methods === undefined)
45
+ return undefined;
46
+ if (!Array.isArray(methods) || methods.length === 0) {
47
+ throw new OrganizationValidationError('defaultLoginMethods: must be a non-empty array');
48
+ }
49
+ for (const m of methods) {
50
+ if (!LOGIN_METHODS.includes(m)) {
51
+ throw new OrganizationValidationError(`defaultLoginMethods: invalid method "${String(m)}"`);
52
+ }
53
+ }
54
+ return normalizeLoginMethods(methods);
55
+ }
56
+ // ---------------------------------------------------------------------------
57
+ // Create
58
+ // ---------------------------------------------------------------------------
59
+ /**
60
+ * Create a new organization.
61
+ *
62
+ * 1. Generate slug from name if not provided
63
+ * 2. Validate slug format and reserved words
64
+ * 3. Check slug uniqueness in the database
65
+ * 4. Insert organization via repository
66
+ * 5. Cache the new organization
67
+ * 6. Write audit log entry
68
+ *
69
+ * @param input - Organization creation data
70
+ * @param actorId - UUID of the user performing the action (for audit)
71
+ * @returns Created organization
72
+ * @throws OrganizationValidationError if slug is invalid or already taken
73
+ */
74
+ export async function createOrganization(input, actorId) {
75
+ // Generate or use provided slug
76
+ const slug = input.slug ?? generateSlug(input.name);
77
+ // Validate slug format and reserved words
78
+ const validation = validateSlug(slug);
79
+ if (!validation.isValid) {
80
+ throw new OrganizationValidationError(validation.error);
81
+ }
82
+ // Check uniqueness
83
+ const taken = await slugExists(slug);
84
+ if (taken) {
85
+ throw new OrganizationValidationError('Slug already in use');
86
+ }
87
+ // Validate + normalize defaultLoginMethods (throws on invalid input).
88
+ // Undefined → fall back to DB DEFAULT in the repository INSERT.
89
+ const defaultLoginMethods = validateDefaultLoginMethods(input.defaultLoginMethods);
90
+ // Insert into database
91
+ const org = await insertOrganization({
92
+ name: input.name,
93
+ slug,
94
+ defaultLocale: input.defaultLocale ?? 'en',
95
+ brandingLogoUrl: input.branding?.logoUrl,
96
+ brandingFaviconUrl: input.branding?.faviconUrl,
97
+ brandingPrimaryColor: input.branding?.primaryColor,
98
+ brandingCompanyName: input.branding?.companyName,
99
+ brandingCustomCss: input.branding?.customCss,
100
+ defaultLoginMethods,
101
+ });
102
+ // Cache the new organization
103
+ await cacheOrganization(org);
104
+ // Audit log (fire-and-forget) — include the resolved defaults so audit
105
+ // captures the effective configuration even when the caller relied on
106
+ // the DB DEFAULT.
107
+ await writeAuditLog({
108
+ organizationId: org.id,
109
+ actorId,
110
+ eventType: 'org.created',
111
+ eventCategory: 'admin',
112
+ metadata: {
113
+ slug: org.slug,
114
+ name: org.name,
115
+ defaultLoginMethods: org.defaultLoginMethods,
116
+ },
117
+ });
118
+ return org;
119
+ }
120
+ // ---------------------------------------------------------------------------
121
+ // Read
122
+ // ---------------------------------------------------------------------------
123
+ /**
124
+ * Find an organization by ID.
125
+ * Checks Redis cache first, falls back to database on miss.
126
+ *
127
+ * @param id - Organization UUID
128
+ * @returns Organization or null if not found
129
+ */
130
+ export async function getOrganizationById(id) {
131
+ // Try cache first
132
+ const cached = await getCachedOrganizationById(id);
133
+ if (cached)
134
+ return cached;
135
+ // Fall back to database
136
+ const org = await findOrganizationById(id);
137
+ if (org) {
138
+ await cacheOrganization(org);
139
+ }
140
+ return org;
141
+ }
142
+ /**
143
+ * Find an organization by slug.
144
+ * Checks Redis cache first, falls back to database on miss.
145
+ *
146
+ * @param slug - Organization slug
147
+ * @returns Organization or null if not found
148
+ */
149
+ export async function getOrganizationBySlug(slug) {
150
+ // Try cache first
151
+ const cached = await getCachedOrganizationBySlug(slug);
152
+ if (cached)
153
+ return cached;
154
+ // Fall back to database
155
+ const org = await findOrganizationBySlug(slug);
156
+ if (org) {
157
+ await cacheOrganization(org);
158
+ }
159
+ return org;
160
+ }
161
+ // ---------------------------------------------------------------------------
162
+ // Update
163
+ // ---------------------------------------------------------------------------
164
+ /**
165
+ * Update an organization's basic fields (name, locale).
166
+ *
167
+ * @param id - Organization UUID
168
+ * @param input - Fields to update
169
+ * @param actorId - UUID of the user performing the action
170
+ * @returns Updated organization
171
+ * @throws OrganizationNotFoundError if organization not found
172
+ */
173
+ export async function updateOrganization(id, input, actorId) {
174
+ // Build update data from input
175
+ const updateData = {};
176
+ if (input.name !== undefined)
177
+ updateData.name = input.name;
178
+ if (input.defaultLocale !== undefined)
179
+ updateData.defaultLocale = input.defaultLocale;
180
+ if (input.twoFactorPolicy !== undefined)
181
+ updateData.twoFactorPolicy = input.twoFactorPolicy;
182
+ // Validate + normalize defaultLoginMethods if provided (throws on invalid).
183
+ // Capture the previous value (for audit log diff) before the update is
184
+ // applied, so we can record the old → new transition.
185
+ let previousDefaultLoginMethods;
186
+ if (input.defaultLoginMethods !== undefined) {
187
+ const normalized = validateDefaultLoginMethods(input.defaultLoginMethods);
188
+ updateData.defaultLoginMethods = normalized;
189
+ // Look up the current value for the audit diff. We use the cache-aware
190
+ // accessor so we get a Date-deserialized object back; if the org doesn't
191
+ // exist the repo update will throw OrganizationNotFoundError below.
192
+ const existing = await getOrganizationById(id);
193
+ if (existing) {
194
+ previousDefaultLoginMethods = existing.defaultLoginMethods;
195
+ }
196
+ }
197
+ // Include branding fields if provided
198
+ if (input.branding) {
199
+ if (input.branding.logoUrl !== undefined)
200
+ updateData.brandingLogoUrl = input.branding.logoUrl;
201
+ if (input.branding.faviconUrl !== undefined)
202
+ updateData.brandingFaviconUrl = input.branding.faviconUrl;
203
+ if (input.branding.primaryColor !== undefined)
204
+ updateData.brandingPrimaryColor = input.branding.primaryColor;
205
+ if (input.branding.companyName !== undefined)
206
+ updateData.brandingCompanyName = input.branding.companyName;
207
+ if (input.branding.customCss !== undefined)
208
+ updateData.brandingCustomCss = input.branding.customCss;
209
+ }
210
+ let org;
211
+ try {
212
+ org = await repoUpdate(id, updateData);
213
+ }
214
+ catch (err) {
215
+ if (err instanceof Error && err.message === 'Organization not found') {
216
+ throw new OrganizationNotFoundError(id);
217
+ }
218
+ throw err;
219
+ }
220
+ // Invalidate old cache and re-cache the updated version
221
+ await invalidateOrganizationCache(org.slug, org.id);
222
+ await cacheOrganization(org);
223
+ // Audit log (fire-and-forget) — include old/new login methods when
224
+ // they changed, for forensic traceability.
225
+ const auditMetadata = {
226
+ fields: Object.keys(updateData),
227
+ };
228
+ if (input.defaultLoginMethods !== undefined) {
229
+ auditMetadata.previousDefaultLoginMethods = previousDefaultLoginMethods ?? null;
230
+ auditMetadata.newDefaultLoginMethods = org.defaultLoginMethods;
231
+ }
232
+ await writeAuditLog({
233
+ organizationId: org.id,
234
+ actorId,
235
+ eventType: 'org.updated',
236
+ eventCategory: 'admin',
237
+ metadata: auditMetadata,
238
+ });
239
+ return org;
240
+ }
241
+ /**
242
+ * Update an organization's branding configuration.
243
+ *
244
+ * @param id - Organization UUID
245
+ * @param branding - Branding fields to update
246
+ * @param actorId - UUID of the user performing the action
247
+ * @returns Updated organization
248
+ * @throws OrganizationNotFoundError if organization not found
249
+ */
250
+ export async function updateOrganizationBranding(id, branding, actorId) {
251
+ const updateData = {};
252
+ if (branding.logoUrl !== undefined)
253
+ updateData.brandingLogoUrl = branding.logoUrl;
254
+ if (branding.faviconUrl !== undefined)
255
+ updateData.brandingFaviconUrl = branding.faviconUrl;
256
+ if (branding.primaryColor !== undefined)
257
+ updateData.brandingPrimaryColor = branding.primaryColor;
258
+ if (branding.companyName !== undefined)
259
+ updateData.brandingCompanyName = branding.companyName;
260
+ if (branding.customCss !== undefined)
261
+ updateData.brandingCustomCss = branding.customCss;
262
+ let org;
263
+ try {
264
+ org = await repoUpdate(id, updateData);
265
+ }
266
+ catch (err) {
267
+ if (err instanceof Error && err.message === 'Organization not found') {
268
+ throw new OrganizationNotFoundError(id);
269
+ }
270
+ throw err;
271
+ }
272
+ await invalidateOrganizationCache(org.slug, org.id);
273
+ await cacheOrganization(org);
274
+ // Audit log (fire-and-forget)
275
+ await writeAuditLog({
276
+ organizationId: org.id,
277
+ actorId,
278
+ eventType: 'org.branding.updated',
279
+ eventCategory: 'admin',
280
+ metadata: { fields: Object.keys(updateData) },
281
+ });
282
+ return org;
283
+ }
284
+ // ---------------------------------------------------------------------------
285
+ // Status lifecycle
286
+ // ---------------------------------------------------------------------------
287
+ /**
288
+ * Load and validate an organization exists before a status change.
289
+ * @throws OrganizationNotFoundError if not found
290
+ */
291
+ async function loadOrgForStatusChange(id) {
292
+ const org = await findOrganizationById(id);
293
+ if (!org)
294
+ throw new OrganizationNotFoundError(id);
295
+ return org;
296
+ }
297
+ /**
298
+ * Suspend an organization (active → suspended).
299
+ * Super-admin organization cannot be suspended.
300
+ *
301
+ * @param id - Organization UUID
302
+ * @param reason - Optional reason for suspension
303
+ * @param actorId - UUID of the user performing the action
304
+ * @throws OrganizationNotFoundError if not found
305
+ * @throws OrganizationValidationError if super-admin, already suspended, or archived
306
+ */
307
+ export async function suspendOrganization(id, reason, actorId) {
308
+ const org = await loadOrgForStatusChange(id);
309
+ if (org.isSuperAdmin) {
310
+ throw new OrganizationValidationError('Super-admin organization cannot be suspended');
311
+ }
312
+ if (org.status === 'suspended') {
313
+ throw new OrganizationValidationError('Organization is already suspended');
314
+ }
315
+ if (org.status !== 'active') {
316
+ throw new OrganizationValidationError(`Cannot suspend organization from status: ${org.status}`);
317
+ }
318
+ await repoUpdate(id, { status: 'suspended' });
319
+ await invalidateOrganizationCache(org.slug, org.id);
320
+ await writeAuditLog({
321
+ organizationId: org.id,
322
+ actorId,
323
+ eventType: 'org.suspended',
324
+ eventCategory: 'admin',
325
+ metadata: { reason: reason ?? null },
326
+ });
327
+ }
328
+ /**
329
+ * Activate an organization (suspended → active).
330
+ *
331
+ * @param id - Organization UUID
332
+ * @param actorId - UUID of the user performing the action
333
+ * @throws OrganizationNotFoundError if not found
334
+ * @throws OrganizationValidationError if not currently suspended
335
+ */
336
+ export async function activateOrganization(id, actorId) {
337
+ const org = await loadOrgForStatusChange(id);
338
+ if (org.status !== 'suspended') {
339
+ throw new OrganizationValidationError(`Cannot activate organization from status: ${org.status}`);
340
+ }
341
+ await repoUpdate(id, { status: 'active' });
342
+ await invalidateOrganizationCache(org.slug, org.id);
343
+ await writeAuditLog({
344
+ organizationId: org.id,
345
+ actorId,
346
+ eventType: 'org.activated',
347
+ eventCategory: 'admin',
348
+ });
349
+ }
350
+ /**
351
+ * Archive an organization (soft-delete).
352
+ * Super-admin organization cannot be archived.
353
+ *
354
+ * @param id - Organization UUID
355
+ * @param actorId - UUID of the user performing the action
356
+ * @throws OrganizationNotFoundError if not found
357
+ * @throws OrganizationValidationError if super-admin or already archived
358
+ */
359
+ export async function archiveOrganization(id, actorId) {
360
+ const org = await loadOrgForStatusChange(id);
361
+ if (org.isSuperAdmin) {
362
+ throw new OrganizationValidationError('Super-admin organization cannot be archived');
363
+ }
364
+ if (org.status === 'archived') {
365
+ throw new OrganizationValidationError('Organization is already archived');
366
+ }
367
+ await repoUpdate(id, { status: 'archived' });
368
+ await invalidateOrganizationCache(org.slug, org.id);
369
+ await writeAuditLog({
370
+ organizationId: org.id,
371
+ actorId,
372
+ eventType: 'org.archived',
373
+ eventCategory: 'admin',
374
+ });
375
+ }
376
+ /**
377
+ * Restore an archived organization (archived → active).
378
+ *
379
+ * @param id - Organization UUID
380
+ * @param actorId - UUID of the user performing the action
381
+ * @throws OrganizationNotFoundError if not found
382
+ * @throws OrganizationValidationError if not currently archived
383
+ */
384
+ export async function restoreOrganization(id, actorId) {
385
+ const org = await loadOrgForStatusChange(id);
386
+ if (org.status !== 'archived') {
387
+ throw new OrganizationValidationError(`Cannot restore organization from status: ${org.status}`);
388
+ }
389
+ await repoUpdate(id, { status: 'active' });
390
+ await invalidateOrganizationCache(org.slug, org.id);
391
+ await writeAuditLog({
392
+ organizationId: org.id,
393
+ actorId,
394
+ eventType: 'org.restored',
395
+ eventCategory: 'admin',
396
+ });
397
+ }
398
+ // ---------------------------------------------------------------------------
399
+ // List
400
+ // ---------------------------------------------------------------------------
401
+ /**
402
+ * List organizations with pagination and filtering.
403
+ * Delegates directly to the repository.
404
+ *
405
+ * @param options - Pagination, filter, and sort options
406
+ * @returns Paginated result
407
+ */
408
+ export async function listOrganizations(options) {
409
+ return repoList(options);
410
+ }
411
+ /**
412
+ * List organizations with cursor-based keyset pagination.
413
+ * Provides stable, efficient pagination without COUNT queries.
414
+ * Delegates directly to the repository cursor implementation.
415
+ *
416
+ * @param options - Cursor, limit, filter, and sort options
417
+ * @returns Cursor-paginated result with nextCursor/hasMore
418
+ */
419
+ export async function listOrganizationsCursor(options) {
420
+ return repoListCursor(options);
421
+ }
422
+ // ---------------------------------------------------------------------------
423
+ // Slug validation
424
+ // ---------------------------------------------------------------------------
425
+ /**
426
+ * Validate if a slug is available and valid.
427
+ * Checks both format/reserved words AND database uniqueness.
428
+ *
429
+ * @param slug - Slug to validate
430
+ * @param excludeId - Optional org ID to exclude (for updates)
431
+ * @returns Object with isValid boolean and optional error message
432
+ */
433
+ export async function validateSlugAvailability(slug, excludeId) {
434
+ // Check format and reserved words first
435
+ const validation = validateSlug(slug);
436
+ if (!validation.isValid) {
437
+ return validation;
438
+ }
439
+ // Check database uniqueness
440
+ const taken = await slugExists(slug, excludeId);
441
+ if (taken) {
442
+ return { isValid: false, error: 'Slug already in use' };
443
+ }
444
+ return { isValid: true };
445
+ }
446
+ // ---------------------------------------------------------------------------
447
+ // Destroy (hard delete)
448
+ // ---------------------------------------------------------------------------
449
+ /**
450
+ * Get cascade counts for an organization (preview of what will be deleted).
451
+ *
452
+ * @param orgId - Organization UUID
453
+ * @returns Counts of each child entity type
454
+ */
455
+ export async function getCascadeCounts(orgId) {
456
+ return repoGetCascadeCounts(orgId);
457
+ }
458
+ /**
459
+ * Destroy an organization and all its child entities via CASCADE.
460
+ *
461
+ * Safety checks:
462
+ * 1. Organization must exist
463
+ * 2. Organization must NOT be the super-admin org (application-level check)
464
+ * 3. Cascade counts are calculated before deletion (for audit trail)
465
+ * 4. Audit log is written BEFORE deletion (org_id becomes NULL after DELETE)
466
+ * 5. Hard-delete with SQL-level super-admin guard (defense in depth)
467
+ * 6. Cache invalidated after successful deletion
468
+ *
469
+ * @param idOrSlug - Organization ID or slug
470
+ * @param actorId - ID of the admin performing the destruction (for audit log)
471
+ * @returns Object with the deleted org and cascade counts
472
+ * @throws OrganizationNotFoundError if org doesn't exist
473
+ * @throws OrganizationValidationError if org is super-admin
474
+ */
475
+ export async function destroyOrganization(idOrSlug, actorId) {
476
+ // 1. Resolve org (try by ID first, then by slug)
477
+ let org = await findOrganizationById(idOrSlug);
478
+ if (!org) {
479
+ org = await findOrganizationBySlug(idOrSlug);
480
+ }
481
+ if (!org) {
482
+ throw new OrganizationNotFoundError(idOrSlug);
483
+ }
484
+ // 2. Super-admin protection (application-level check)
485
+ if (org.isSuperAdmin) {
486
+ throw new OrganizationValidationError('Cannot destroy the super-admin organization');
487
+ }
488
+ // 3. Count cascade targets (for audit trail and response)
489
+ const cascadeCounts = await repoGetCascadeCounts(org.id);
490
+ // 4. Write audit log BEFORE deletion (org_id will be SET NULL after delete)
491
+ await writeAuditLog({
492
+ organizationId: org.id,
493
+ actorId,
494
+ eventType: 'org.destroyed',
495
+ eventCategory: 'admin',
496
+ metadata: {
497
+ name: org.name,
498
+ slug: org.slug,
499
+ cascadeCounts,
500
+ },
501
+ });
502
+ // 5. Hard-delete (CASCADE handles children)
503
+ const deleted = await hardDeleteOrganization(org.id);
504
+ if (!deleted) {
505
+ throw new OrganizationValidationError('Failed to delete organization — it may be the super-admin org');
506
+ }
507
+ // 6. Invalidate cache
508
+ await invalidateOrganizationCache(org.slug, org.id);
509
+ return { organization: org, cascadeCounts };
510
+ }
511
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/organizations/service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Slug generation and validation utilities.
3
+ *
4
+ * Organization slugs are URL-safe identifiers used in path-based
5
+ * multi-tenancy (e.g., /{slug}/.well-known/openid-configuration).
6
+ * They must be 3–100 characters, lowercase alphanumeric with hyphens,
7
+ * and cannot be a reserved system word.
8
+ *
9
+ * This module provides:
10
+ * - `generateSlug(name)` — Derive a slug from an organization name
11
+ * - `validateSlug(slug)` — Check format and reserved-word rules
12
+ * - `RESERVED_SLUGS` — The set of words that cannot be used as slugs
13
+ */
14
+ /**
15
+ * Reserved slugs that cannot be used as organization slugs.
16
+ * These conflict with system routes, well-known paths, or
17
+ * could cause confusion with internal functionality.
18
+ */
19
+ export declare const RESERVED_SLUGS: ReadonlySet<string>;
20
+ /**
21
+ * Generate a URL-safe slug from an organization name.
22
+ *
23
+ * Transformation rules:
24
+ * 1. Convert to lowercase
25
+ * 2. Replace non-alphanumeric characters with hyphens
26
+ * 3. Collapse multiple consecutive hyphens into one
27
+ * 4. Trim leading and trailing hyphens
28
+ * 5. Truncate to 100 characters (trimming trailing hyphens after truncation)
29
+ *
30
+ * Returns an empty string for empty/whitespace-only input — the caller
31
+ * (service layer) is responsible for validation.
32
+ *
33
+ * @param name - Organization name to derive a slug from
34
+ * @returns Generated slug string
35
+ */
36
+ export declare function generateSlug(name: string): string;
37
+ /** Result of slug validation — isValid flag with optional error message */
38
+ export interface SlugValidationResult {
39
+ isValid: boolean;
40
+ error?: string;
41
+ }
42
+ /**
43
+ * Validate a slug against format and reserved word rules.
44
+ *
45
+ * Checks (in order):
46
+ * 1. Minimum length (3 characters)
47
+ * 2. Maximum length (100 characters)
48
+ * 3. Format (lowercase alphanumeric + hyphens, no leading/trailing hyphens)
49
+ * 4. Not a reserved word
50
+ *
51
+ * Does NOT check uniqueness — that's the repository/service layer's job.
52
+ *
53
+ * @param slug - Slug string to validate
54
+ * @returns Object with isValid boolean and optional error message
55
+ */
56
+ export declare function validateSlug(slug: string): SlugValidationResult;
57
+ //# sourceMappingURL=slugs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slugs.d.ts","sourceRoot":"","sources":["../../src/organizations/slugs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,WAAW,CAAC,MAAM,CA8B7C,CAAC;AAiBH;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAgBjD;AAMD,2EAA2E;AAC3E,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,CA2B/D"}