@hilbras/keystone 1.6.0 → 2.5.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 (604) hide show
  1. package/CHANGELOG.md +625 -0
  2. package/README.md +198 -50
  3. package/dist/cli.js +25 -27
  4. package/dist/cli.js.map +1 -1
  5. package/dist/config.d.ts +23 -1
  6. package/dist/config.d.ts.map +1 -1
  7. package/dist/config.js +53 -8
  8. package/dist/config.js.map +1 -1
  9. package/dist/container.d.ts +4 -1
  10. package/dist/container.d.ts.map +1 -1
  11. package/dist/container.js.map +1 -1
  12. package/dist/db/migrations/0008_flashy_firestar.sql +5 -0
  13. package/dist/db/migrations/0009_daffy_changeling.sql +1 -0
  14. package/dist/db/migrations/0010_wealthy_shadow_king.sql +37 -0
  15. package/dist/db/migrations/0011_overrated_vector.sql +18 -0
  16. package/dist/db/migrations/0012_brave_darkhawk.sql +28 -0
  17. package/dist/db/migrations/0013_wonderful_chimera.sql +5 -0
  18. package/dist/db/migrations/0014_magical_morph.sql +48 -0
  19. package/dist/db/migrations/0015_chief_vargas.sql +7 -0
  20. package/dist/db/migrations/0016_gorgeous_charles_xavier.sql +5 -0
  21. package/dist/db/migrations/0017_flashy_nekra.sql +1 -0
  22. package/{src/db/migrations/meta/0007_snapshot.json → dist/db/migrations/meta/0008_snapshot.json} +136 -32
  23. package/{src/db/migrations/meta/0006_snapshot.json → dist/db/migrations/meta/0009_snapshot.json} +359 -30
  24. package/{src/db/migrations/meta/0005_snapshot.json → dist/db/migrations/meta/0010_snapshot.json} +459 -29
  25. package/{src/db/migrations/meta/0004_snapshot.json → dist/db/migrations/meta/0011_snapshot.json} +594 -30
  26. package/dist/db/migrations/meta/0012_snapshot.json +3891 -0
  27. package/dist/db/migrations/meta/0013_snapshot.json +3919 -0
  28. package/dist/db/migrations/meta/0014_snapshot.json +4311 -0
  29. package/dist/db/migrations/meta/0015_snapshot.json +4340 -0
  30. package/dist/db/migrations/meta/0016_snapshot.json +4363 -0
  31. package/dist/db/migrations/meta/0017_snapshot.json +4370 -0
  32. package/dist/db/migrations/meta/_journal.json +70 -0
  33. package/dist/db/reencryptOidcSecrets.d.ts +2 -0
  34. package/dist/db/reencryptOidcSecrets.d.ts.map +1 -0
  35. package/dist/db/reencryptOidcSecrets.js +41 -0
  36. package/dist/db/reencryptOidcSecrets.js.map +1 -0
  37. package/dist/db/schema.d.ts +2693 -88
  38. package/dist/db/schema.d.ts.map +1 -1
  39. package/dist/db/schema.js +157 -4
  40. package/dist/db/schema.js.map +1 -1
  41. package/dist/db/seed.js +67 -40
  42. package/dist/db/seed.js.map +1 -1
  43. package/dist/di.d.ts.map +1 -1
  44. package/dist/di.js +11 -3
  45. package/dist/di.js.map +1 -1
  46. package/dist/index.d.ts +2 -2
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +34 -3
  49. package/dist/index.js.map +1 -1
  50. package/dist/lib/errors.d.ts +2 -1
  51. package/dist/lib/errors.d.ts.map +1 -1
  52. package/dist/lib/errors.js +10 -0
  53. package/dist/lib/errors.js.map +1 -1
  54. package/dist/plugins/appContext.d.ts.map +1 -1
  55. package/dist/plugins/appContext.js +3 -12
  56. package/dist/plugins/appContext.js.map +1 -1
  57. package/dist/plugins/audit.d.ts.map +1 -1
  58. package/dist/plugins/audit.js +26 -6
  59. package/dist/plugins/audit.js.map +1 -1
  60. package/dist/plugins/auth.d.ts.map +1 -1
  61. package/dist/plugins/auth.js +32 -7
  62. package/dist/plugins/auth.js.map +1 -1
  63. package/dist/plugins/headerSanitization.d.ts +15 -0
  64. package/dist/plugins/headerSanitization.d.ts.map +1 -0
  65. package/dist/plugins/headerSanitization.js +39 -0
  66. package/dist/plugins/headerSanitization.js.map +1 -0
  67. package/dist/plugins/metrics.d.ts.map +1 -1
  68. package/dist/plugins/mtls.d.ts +21 -2
  69. package/dist/plugins/mtls.d.ts.map +1 -1
  70. package/dist/plugins/mtls.js +94 -47
  71. package/dist/plugins/mtls.js.map +1 -1
  72. package/dist/plugins/permissions.d.ts.map +1 -1
  73. package/dist/plugins/permissions.js +29 -9
  74. package/dist/plugins/permissions.js.map +1 -1
  75. package/dist/plugins/rateLimit.d.ts +16 -0
  76. package/dist/plugins/rateLimit.d.ts.map +1 -1
  77. package/dist/plugins/rateLimit.js +16 -3
  78. package/dist/plugins/rateLimit.js.map +1 -1
  79. package/dist/plugins/requestLogger.d.ts.map +1 -1
  80. package/dist/repositories/apiKey.d.ts.map +1 -1
  81. package/dist/repositories/application.d.ts +1 -1
  82. package/dist/repositories/application.d.ts.map +1 -1
  83. package/dist/repositories/application.js +9 -3
  84. package/dist/repositories/application.js.map +1 -1
  85. package/dist/repositories/audit.d.ts.map +1 -1
  86. package/dist/repositories/index.d.ts +3 -0
  87. package/dist/repositories/index.d.ts.map +1 -1
  88. package/dist/repositories/index.js +3 -0
  89. package/dist/repositories/index.js.map +1 -1
  90. package/dist/repositories/mfaChallenge.d.ts +23 -0
  91. package/dist/repositories/mfaChallenge.d.ts.map +1 -0
  92. package/dist/repositories/mfaChallenge.js +71 -0
  93. package/dist/repositories/mfaChallenge.js.map +1 -0
  94. package/dist/repositories/oidcConnection.d.ts +27 -43
  95. package/dist/repositories/oidcConnection.d.ts.map +1 -1
  96. package/dist/repositories/oidcConnection.js +15 -6
  97. package/dist/repositories/oidcConnection.js.map +1 -1
  98. package/dist/repositories/organization.d.ts +9 -9
  99. package/dist/repositories/organization.d.ts.map +1 -1
  100. package/dist/repositories/organization.js +91 -37
  101. package/dist/repositories/organization.js.map +1 -1
  102. package/dist/repositories/permission.d.ts.map +1 -1
  103. package/dist/repositories/permission.js +27 -5
  104. package/dist/repositories/permission.js.map +1 -1
  105. package/dist/repositories/samlConnection.d.ts +28 -28
  106. package/dist/repositories/samlConnection.d.ts.map +1 -1
  107. package/dist/repositories/samlConnection.js +12 -4
  108. package/dist/repositories/samlConnection.js.map +1 -1
  109. package/dist/repositories/scimConnection.d.ts +38 -0
  110. package/dist/repositories/scimConnection.d.ts.map +1 -0
  111. package/dist/repositories/scimConnection.js +123 -0
  112. package/dist/repositories/scimConnection.js.map +1 -0
  113. package/dist/repositories/scimGroup.d.ts +36 -0
  114. package/dist/repositories/scimGroup.d.ts.map +1 -0
  115. package/dist/repositories/scimGroup.js +113 -0
  116. package/dist/repositories/scimGroup.js.map +1 -0
  117. package/dist/repositories/session.d.ts +24 -13
  118. package/dist/repositories/session.d.ts.map +1 -1
  119. package/dist/repositories/session.js +13 -1
  120. package/dist/repositories/session.js.map +1 -1
  121. package/dist/repositories/types.d.ts +117 -6
  122. package/dist/repositories/types.d.ts.map +1 -1
  123. package/dist/repositories/types.js +7 -1
  124. package/dist/repositories/types.js.map +1 -1
  125. package/dist/repositories/user.d.ts +23 -1
  126. package/dist/repositories/user.d.ts.map +1 -1
  127. package/dist/repositories/user.js +180 -4
  128. package/dist/repositories/user.js.map +1 -1
  129. package/dist/routes/admin/billing.js +4 -4
  130. package/dist/routes/admin/billing.js.map +1 -1
  131. package/dist/routes/admin/helpers.d.ts +16 -20
  132. package/dist/routes/admin/helpers.d.ts.map +1 -1
  133. package/dist/routes/admin/helpers.js +53 -10
  134. package/dist/routes/admin/helpers.js.map +1 -1
  135. package/dist/routes/admin/organizations.d.ts.map +1 -1
  136. package/dist/routes/admin/organizations.js +105 -69
  137. package/dist/routes/admin/organizations.js.map +1 -1
  138. package/dist/routes/admin/permissions.d.ts.map +1 -1
  139. package/dist/routes/admin/permissions.js +48 -14
  140. package/dist/routes/admin/permissions.js.map +1 -1
  141. package/dist/routes/admin/platform.d.ts.map +1 -1
  142. package/dist/routes/admin/platform.js +86 -35
  143. package/dist/routes/admin/platform.js.map +1 -1
  144. package/dist/routes/admin/sso.d.ts.map +1 -1
  145. package/dist/routes/admin/sso.js +143 -12
  146. package/dist/routes/admin/sso.js.map +1 -1
  147. package/dist/routes/admin/webhooks.js +8 -8
  148. package/dist/routes/admin/webhooks.js.map +1 -1
  149. package/dist/routes/apiKeys.d.ts.map +1 -1
  150. package/dist/routes/apiKeys.js +23 -5
  151. package/dist/routes/apiKeys.js.map +1 -1
  152. package/dist/routes/auth.d.ts.map +1 -1
  153. package/dist/routes/auth.js +112 -22
  154. package/dist/routes/auth.js.map +1 -1
  155. package/dist/routes/authz.d.ts.map +1 -1
  156. package/dist/routes/authz.js +16 -4
  157. package/dist/routes/authz.js.map +1 -1
  158. package/dist/routes/config.d.ts.map +1 -1
  159. package/dist/routes/config.js +16 -14
  160. package/dist/routes/config.js.map +1 -1
  161. package/dist/routes/federation.d.ts.map +1 -1
  162. package/dist/routes/federation.js +17 -3
  163. package/dist/routes/federation.js.map +1 -1
  164. package/dist/routes/magicLinks.d.ts.map +1 -1
  165. package/dist/routes/magicLinks.js +15 -3
  166. package/dist/routes/magicLinks.js.map +1 -1
  167. package/dist/routes/oauth.d.ts.map +1 -1
  168. package/dist/routes/oauth.js +60 -5
  169. package/dist/routes/oauth.js.map +1 -1
  170. package/dist/routes/oauth2.d.ts.map +1 -1
  171. package/dist/routes/oauth2.js +188 -22
  172. package/dist/routes/oauth2.js.map +1 -1
  173. package/dist/routes/oidcEnterprise.d.ts.map +1 -1
  174. package/dist/routes/oidcEnterprise.js +67 -21
  175. package/dist/routes/oidcEnterprise.js.map +1 -1
  176. package/dist/routes/password.d.ts.map +1 -1
  177. package/dist/routes/password.js.map +1 -1
  178. package/dist/routes/profile.js +4 -4
  179. package/dist/routes/profile.js.map +1 -1
  180. package/dist/routes/saml.d.ts +33 -0
  181. package/dist/routes/saml.d.ts.map +1 -1
  182. package/dist/routes/saml.js +217 -12
  183. package/dist/routes/saml.js.map +1 -1
  184. package/dist/routes/scim.d.ts +13 -0
  185. package/dist/routes/scim.d.ts.map +1 -1
  186. package/dist/routes/scim.js +885 -110
  187. package/dist/routes/scim.js.map +1 -1
  188. package/dist/routes/sdk.d.ts.map +1 -1
  189. package/dist/routes/sdk.js +24 -8
  190. package/dist/routes/sdk.js.map +1 -1
  191. package/dist/routes/serviceAccounts.d.ts.map +1 -1
  192. package/dist/routes/serviceAccounts.js +63 -2
  193. package/dist/routes/serviceAccounts.js.map +1 -1
  194. package/dist/routes/setup.d.ts.map +1 -1
  195. package/dist/routes/setup.js +15 -16
  196. package/dist/routes/setup.js.map +1 -1
  197. package/dist/routes/smsOtp.js +1 -1
  198. package/dist/routes/smsOtp.js.map +1 -1
  199. package/dist/routes/totp.d.ts.map +1 -1
  200. package/dist/routes/totp.js +112 -23
  201. package/dist/routes/totp.js.map +1 -1
  202. package/dist/routes/webauthn.d.ts.map +1 -1
  203. package/dist/routes/webauthn.js +44 -8
  204. package/dist/routes/webauthn.js.map +1 -1
  205. package/dist/routes/workflows.d.ts.map +1 -1
  206. package/dist/routes/workflows.js +58 -25
  207. package/dist/routes/workflows.js.map +1 -1
  208. package/dist/sdk/index.d.ts.map +1 -1
  209. package/dist/sdk/index.js +141 -40
  210. package/dist/sdk/index.js.map +1 -1
  211. package/dist/sdk/types.d.ts +64 -30
  212. package/dist/sdk/types.d.ts.map +1 -1
  213. package/dist/services/application/authentication.d.ts +39 -1
  214. package/dist/services/application/authentication.d.ts.map +1 -1
  215. package/dist/services/application/authentication.js +43 -1
  216. package/dist/services/application/authentication.js.map +1 -1
  217. package/dist/services/application/identity.d.ts +10 -7
  218. package/dist/services/application/identity.d.ts.map +1 -1
  219. package/dist/services/application/identity.js +13 -10
  220. package/dist/services/application/identity.js.map +1 -1
  221. package/dist/services/application/organization.d.ts +16 -8
  222. package/dist/services/application/organization.d.ts.map +1 -1
  223. package/dist/services/application/organization.js +160 -12
  224. package/dist/services/application/organization.js.map +1 -1
  225. package/dist/services/applications.js +2 -2
  226. package/dist/services/applications.js.map +1 -1
  227. package/dist/services/audit.d.ts +1 -0
  228. package/dist/services/audit.d.ts.map +1 -1
  229. package/dist/services/audit.js +13 -0
  230. package/dist/services/audit.js.map +1 -1
  231. package/dist/services/cache.d.ts.map +1 -1
  232. package/dist/services/configuration/profiles.d.ts +4 -0
  233. package/dist/services/configuration/profiles.d.ts.map +1 -1
  234. package/dist/services/configuration/profiles.js +50 -0
  235. package/dist/services/configuration/profiles.js.map +1 -1
  236. package/dist/services/configuration.d.ts.map +1 -1
  237. package/dist/services/configuration.js.map +1 -1
  238. package/dist/services/connectors/google.d.ts +18 -1
  239. package/dist/services/connectors/google.d.ts.map +1 -1
  240. package/dist/services/connectors/google.js +27 -4
  241. package/dist/services/connectors/google.js.map +1 -1
  242. package/dist/services/connectors/oidc.d.ts +14 -2
  243. package/dist/services/connectors/oidc.d.ts.map +1 -1
  244. package/dist/services/connectors/oidc.js +35 -6
  245. package/dist/services/connectors/oidc.js.map +1 -1
  246. package/dist/services/connectors/types.d.ts +13 -1
  247. package/dist/services/connectors/types.d.ts.map +1 -1
  248. package/dist/services/connectors/zitadel.d.ts.map +1 -1
  249. package/dist/services/connectors/zitadel.js +4 -3
  250. package/dist/services/connectors/zitadel.js.map +1 -1
  251. package/dist/services/domain/authentication.d.ts +43 -4
  252. package/dist/services/domain/authentication.d.ts.map +1 -1
  253. package/dist/services/domain/authentication.js +119 -40
  254. package/dist/services/domain/authentication.js.map +1 -1
  255. package/dist/services/domain/authorization.d.ts +11 -0
  256. package/dist/services/domain/authorization.d.ts.map +1 -1
  257. package/dist/services/domain/authorization.js +36 -1
  258. package/dist/services/domain/authorization.js.map +1 -1
  259. package/dist/services/domain/identity.d.ts +21 -9
  260. package/dist/services/domain/identity.d.ts.map +1 -1
  261. package/dist/services/domain/identity.js +187 -10
  262. package/dist/services/domain/identity.js.map +1 -1
  263. package/dist/services/domain/organization.d.ts +11 -10
  264. package/dist/services/domain/organization.d.ts.map +1 -1
  265. package/dist/services/domain/organization.js +48 -30
  266. package/dist/services/domain/organization.js.map +1 -1
  267. package/dist/services/emailVerification.d.ts +2 -2
  268. package/dist/services/enterpriseSso.d.ts +13 -6
  269. package/dist/services/enterpriseSso.d.ts.map +1 -1
  270. package/dist/services/enterpriseSso.js +75 -6
  271. package/dist/services/enterpriseSso.js.map +1 -1
  272. package/dist/services/events/subscribers/auditLog.js +1 -1
  273. package/dist/services/events/subscribers/auditLog.js.map +1 -1
  274. package/dist/services/events/types.d.ts +7 -1
  275. package/dist/services/events/types.d.ts.map +1 -1
  276. package/dist/services/events/types.js.map +1 -1
  277. package/dist/services/events/validate.d.ts.map +1 -1
  278. package/dist/services/events/validate.js +33 -0
  279. package/dist/services/events/validate.js.map +1 -1
  280. package/dist/services/features.d.ts.map +1 -1
  281. package/dist/services/features.js.map +1 -1
  282. package/dist/services/federation.d.ts +6 -1
  283. package/dist/services/federation.d.ts.map +1 -1
  284. package/dist/services/federation.js +31 -4
  285. package/dist/services/federation.js.map +1 -1
  286. package/dist/services/ipControls.js +2 -2
  287. package/dist/services/ipControls.js.map +1 -1
  288. package/dist/services/magicLinks.d.ts +2 -2
  289. package/dist/services/magicLinks.d.ts.map +1 -1
  290. package/dist/services/magicLinks.js +13 -9
  291. package/dist/services/magicLinks.js.map +1 -1
  292. package/dist/services/mfa.d.ts +53 -0
  293. package/dist/services/mfa.d.ts.map +1 -0
  294. package/dist/services/mfa.js +157 -0
  295. package/dist/services/mfa.js.map +1 -0
  296. package/dist/services/oauth2.d.ts +88 -14
  297. package/dist/services/oauth2.d.ts.map +1 -1
  298. package/dist/services/oauth2.js +125 -16
  299. package/dist/services/oauth2.js.map +1 -1
  300. package/dist/services/oidcSecretFormat.d.ts +3 -0
  301. package/dist/services/oidcSecretFormat.d.ts.map +1 -0
  302. package/dist/services/oidcSecretFormat.js +5 -0
  303. package/dist/services/oidcSecretFormat.js.map +1 -0
  304. package/dist/services/organizations.d.ts +4 -16
  305. package/dist/services/organizations.d.ts.map +1 -1
  306. package/dist/services/organizations.js +0 -62
  307. package/dist/services/organizations.js.map +1 -1
  308. package/dist/services/permissions.d.ts.map +1 -1
  309. package/dist/services/permissions.js +9 -1
  310. package/dist/services/permissions.js.map +1 -1
  311. package/dist/services/plugins/registry.d.ts.map +1 -1
  312. package/dist/services/plugins/registry.js.map +1 -1
  313. package/dist/services/plugins/types.d.ts.map +1 -1
  314. package/dist/services/queue/bullmq.d.ts.map +1 -1
  315. package/dist/services/queue/inProcess.d.ts.map +1 -1
  316. package/dist/services/redirectUri.d.ts +56 -0
  317. package/dist/services/redirectUri.d.ts.map +1 -0
  318. package/dist/services/redirectUri.js +129 -0
  319. package/dist/services/redirectUri.js.map +1 -0
  320. package/dist/services/redis.d.ts +1 -1
  321. package/dist/services/redis.d.ts.map +1 -1
  322. package/dist/services/scimCredentials.d.ts +46 -0
  323. package/dist/services/scimCredentials.d.ts.map +1 -0
  324. package/dist/services/scimCredentials.js +123 -0
  325. package/dist/services/scimCredentials.js.map +1 -0
  326. package/dist/services/scimLegacyMigration.d.ts +12 -0
  327. package/dist/services/scimLegacyMigration.d.ts.map +1 -0
  328. package/dist/services/scimLegacyMigration.js +44 -0
  329. package/dist/services/scimLegacyMigration.js.map +1 -0
  330. package/dist/services/secrets/awsKms.d.ts +2 -2
  331. package/dist/services/secrets/awsKms.d.ts.map +1 -1
  332. package/dist/services/secrets/awsKms.js +3 -5
  333. package/dist/services/secrets/awsKms.js.map +1 -1
  334. package/dist/services/secrets/azureKeyVault.d.ts.map +1 -1
  335. package/dist/services/secrets/database.d.ts.map +1 -1
  336. package/dist/services/secrets/database.js.map +1 -1
  337. package/dist/services/secrets/environment.d.ts.map +1 -1
  338. package/dist/services/secrets/environment.js.map +1 -1
  339. package/dist/services/secrets/index.d.ts.map +1 -1
  340. package/dist/services/secrets/password.d.ts.map +1 -1
  341. package/dist/services/secrets/password.js +0 -4
  342. package/dist/services/secrets/password.js.map +1 -1
  343. package/dist/services/secrets/provider.d.ts +2 -3
  344. package/dist/services/secrets/provider.d.ts.map +1 -1
  345. package/dist/services/secrets/vault.d.ts.map +1 -1
  346. package/dist/services/serviceAccounts.d.ts +20 -0
  347. package/dist/services/serviceAccounts.d.ts.map +1 -1
  348. package/dist/services/serviceAccounts.js +47 -1
  349. package/dist/services/serviceAccounts.js.map +1 -1
  350. package/dist/services/sessionRevocation.d.ts +76 -0
  351. package/dist/services/sessionRevocation.d.ts.map +1 -0
  352. package/dist/services/sessionRevocation.js +86 -0
  353. package/dist/services/sessionRevocation.js.map +1 -0
  354. package/dist/services/setup/configWriter.d.ts.map +1 -1
  355. package/dist/services/setup/configWriter.js.map +1 -1
  356. package/dist/services/singleUse.d.ts +68 -0
  357. package/dist/services/singleUse.d.ts.map +1 -0
  358. package/dist/services/singleUse.js +54 -0
  359. package/dist/services/singleUse.js.map +1 -0
  360. package/dist/services/smsOtp.d.ts.map +1 -1
  361. package/dist/services/smsOtp.js +12 -8
  362. package/dist/services/smsOtp.js.map +1 -1
  363. package/dist/services/ssoEndpointPolicy.d.ts +8 -0
  364. package/dist/services/ssoEndpointPolicy.d.ts.map +1 -0
  365. package/dist/services/ssoEndpointPolicy.js +136 -0
  366. package/dist/services/ssoEndpointPolicy.js.map +1 -0
  367. package/dist/services/stepUp.d.ts +35 -0
  368. package/dist/services/stepUp.d.ts.map +1 -0
  369. package/dist/services/stepUp.js +65 -0
  370. package/dist/services/stepUp.js.map +1 -0
  371. package/dist/services/tokens.d.ts +39 -11
  372. package/dist/services/tokens.d.ts.map +1 -1
  373. package/dist/services/tokens.js +80 -14
  374. package/dist/services/tokens.js.map +1 -1
  375. package/dist/services/totp.d.ts +46 -0
  376. package/dist/services/totp.d.ts.map +1 -1
  377. package/dist/services/totp.js +178 -41
  378. package/dist/services/totp.js.map +1 -1
  379. package/dist/services/trustedProxies.d.ts +90 -0
  380. package/dist/services/trustedProxies.d.ts.map +1 -0
  381. package/dist/services/trustedProxies.js +283 -0
  382. package/dist/services/trustedProxies.js.map +1 -0
  383. package/dist/services/users.d.ts +20 -12
  384. package/dist/services/users.d.ts.map +1 -1
  385. package/dist/services/users.js +24 -51
  386. package/dist/services/users.js.map +1 -1
  387. package/dist/services/webauthn.d.ts +8 -4
  388. package/dist/services/webauthn.d.ts.map +1 -1
  389. package/dist/services/webauthn.js +4 -4
  390. package/dist/services/webauthn.js.map +1 -1
  391. package/dist/services/webhooks.d.ts +20 -20
  392. package/dist/services/workflows/engine.d.ts +4 -2
  393. package/dist/services/workflows/engine.d.ts.map +1 -1
  394. package/dist/services/workflows/engine.js +181 -12
  395. package/dist/services/workflows/engine.js.map +1 -1
  396. package/dist/services/workflows/steps.d.ts +2 -0
  397. package/dist/services/workflows/steps.d.ts.map +1 -1
  398. package/dist/services/workflows/steps.js +8 -75
  399. package/dist/services/workflows/steps.js.map +1 -1
  400. package/dist/setup-server.js +2 -1
  401. package/dist/setup-server.js.map +1 -1
  402. package/dist/types.d.ts +33 -4
  403. package/dist/types.d.ts.map +1 -1
  404. package/dist/types.js +26 -2
  405. package/dist/types.js.map +1 -1
  406. package/package.json +25 -3
  407. package/dist/tests/errors.test.d.ts +0 -2
  408. package/dist/tests/errors.test.d.ts.map +0 -1
  409. package/dist/tests/errors.test.js +0 -64
  410. package/dist/tests/errors.test.js.map +0 -1
  411. package/dist/tests/events.test.d.ts +0 -2
  412. package/dist/tests/events.test.d.ts.map +0 -1
  413. package/dist/tests/events.test.js +0 -45
  414. package/dist/tests/events.test.js.map +0 -1
  415. package/dist/tests/featureFlags.test.d.ts +0 -2
  416. package/dist/tests/featureFlags.test.d.ts.map +0 -1
  417. package/dist/tests/featureFlags.test.js +0 -24
  418. package/dist/tests/featureFlags.test.js.map +0 -1
  419. package/dist/tests/integration/queue.test.d.ts +0 -2
  420. package/dist/tests/integration/queue.test.d.ts.map +0 -1
  421. package/dist/tests/integration/queue.test.js +0 -49
  422. package/dist/tests/integration/queue.test.js.map +0 -1
  423. package/dist/tests/plugins.test.d.ts +0 -2
  424. package/dist/tests/plugins.test.d.ts.map +0 -1
  425. package/dist/tests/plugins.test.js +0 -56
  426. package/dist/tests/plugins.test.js.map +0 -1
  427. package/dist/tests/result.test.d.ts +0 -2
  428. package/dist/tests/result.test.d.ts.map +0 -1
  429. package/dist/tests/result.test.js +0 -46
  430. package/dist/tests/result.test.js.map +0 -1
  431. package/dist/tests/setup/configWriter.test.d.ts +0 -2
  432. package/dist/tests/setup/configWriter.test.d.ts.map +0 -1
  433. package/dist/tests/setup/configWriter.test.js +0 -55
  434. package/dist/tests/setup/configWriter.test.js.map +0 -1
  435. package/dist/tests/setup/validation.test.d.ts +0 -2
  436. package/dist/tests/setup/validation.test.d.ts.map +0 -1
  437. package/dist/tests/setup/validation.test.js +0 -26
  438. package/dist/tests/setup/validation.test.js.map +0 -1
  439. package/dist/tests/smoke.test.d.ts +0 -2
  440. package/dist/tests/smoke.test.d.ts.map +0 -1
  441. package/dist/tests/smoke.test.js +0 -124
  442. package/dist/tests/smoke.test.js.map +0 -1
  443. package/src/cli.ts +0 -172
  444. package/src/config.ts +0 -143
  445. package/src/container.ts +0 -48
  446. package/src/db/index.ts +0 -53
  447. package/src/db/migrations/0000_skinny_ben_parker.sql +0 -553
  448. package/src/db/migrations/0001_brief_joseph.sql +0 -10
  449. package/src/db/migrations/0002_add_account_lockout.sql +0 -3
  450. package/src/db/migrations/0003_steep_rachel_grey.sql +0 -1
  451. package/src/db/migrations/0004_clever_bill_hollister.sql +0 -20
  452. package/src/db/migrations/0005_steep_the_call.sql +0 -2
  453. package/src/db/migrations/0006_ambitious_boomer.sql +0 -17
  454. package/src/db/migrations/0007_greedy_vindicator.sql +0 -40
  455. package/src/db/migrations/meta/0000_snapshot.json +0 -2964
  456. package/src/db/migrations/meta/0001_snapshot.json +0 -3031
  457. package/src/db/migrations/meta/0003_snapshot.json +0 -3051
  458. package/src/db/migrations/meta/_journal.json +0 -62
  459. package/src/db/schema.ts +0 -676
  460. package/src/db/seed.ts +0 -146
  461. package/src/di.ts +0 -81
  462. package/src/index.ts +0 -326
  463. package/src/lib/errors.ts +0 -139
  464. package/src/lib/result.ts +0 -44
  465. package/src/lib/webhookSignature.ts +0 -41
  466. package/src/plugins/appContext.ts +0 -76
  467. package/src/plugins/audit.ts +0 -42
  468. package/src/plugins/auth.ts +0 -230
  469. package/src/plugins/metrics.ts +0 -41
  470. package/src/plugins/mtls.ts +0 -94
  471. package/src/plugins/permissions.ts +0 -29
  472. package/src/plugins/rateLimit.ts +0 -133
  473. package/src/plugins/requestLogger.ts +0 -25
  474. package/src/plugins/tracing.ts +0 -22
  475. package/src/repositories/apiKey.ts +0 -158
  476. package/src/repositories/application.ts +0 -70
  477. package/src/repositories/audit.ts +0 -32
  478. package/src/repositories/index.ts +0 -9
  479. package/src/repositories/oidcConnection.ts +0 -111
  480. package/src/repositories/organization.ts +0 -167
  481. package/src/repositories/permission.ts +0 -153
  482. package/src/repositories/samlConnection.ts +0 -96
  483. package/src/repositories/session.ts +0 -86
  484. package/src/repositories/types.ts +0 -134
  485. package/src/repositories/user.ts +0 -161
  486. package/src/routes/admin/billing.ts +0 -48
  487. package/src/routes/admin/helpers.ts +0 -50
  488. package/src/routes/admin/index.ts +0 -16
  489. package/src/routes/admin/organizations.ts +0 -299
  490. package/src/routes/admin/permissions.ts +0 -80
  491. package/src/routes/admin/platform.ts +0 -335
  492. package/src/routes/admin/sso.ts +0 -138
  493. package/src/routes/admin/webhooks.ts +0 -73
  494. package/src/routes/admin.ts +0 -1
  495. package/src/routes/apiKeys.ts +0 -60
  496. package/src/routes/auth.ts +0 -214
  497. package/src/routes/authz.ts +0 -38
  498. package/src/routes/config.ts +0 -67
  499. package/src/routes/emailVerification.ts +0 -73
  500. package/src/routes/federation.ts +0 -156
  501. package/src/routes/helpers.ts +0 -17
  502. package/src/routes/magicLinks.ts +0 -107
  503. package/src/routes/oauth.ts +0 -167
  504. package/src/routes/oauth2.ts +0 -284
  505. package/src/routes/oidcEnterprise.ts +0 -166
  506. package/src/routes/password.ts +0 -90
  507. package/src/routes/profile.ts +0 -44
  508. package/src/routes/saml.ts +0 -209
  509. package/src/routes/scim.ts +0 -199
  510. package/src/routes/sdk.ts +0 -141
  511. package/src/routes/serviceAccounts.ts +0 -124
  512. package/src/routes/sessions.ts +0 -62
  513. package/src/routes/setup.ts +0 -315
  514. package/src/routes/smsOtp.ts +0 -67
  515. package/src/routes/totp.ts +0 -122
  516. package/src/routes/webauthn.ts +0 -147
  517. package/src/routes/workflows.ts +0 -157
  518. package/src/sdk/index.ts +0 -152
  519. package/src/sdk/types.ts +0 -54
  520. package/src/services/anomalyDetection.ts +0 -73
  521. package/src/services/application/authentication.ts +0 -75
  522. package/src/services/application/identity.ts +0 -56
  523. package/src/services/application/index.ts +0 -3
  524. package/src/services/application/organization.ts +0 -77
  525. package/src/services/applications.ts +0 -89
  526. package/src/services/audit.ts +0 -41
  527. package/src/services/auditExport.ts +0 -59
  528. package/src/services/billing.ts +0 -87
  529. package/src/services/cache.ts +0 -131
  530. package/src/services/configuration/profiles.ts +0 -115
  531. package/src/services/configuration.ts +0 -120
  532. package/src/services/connectors/google.ts +0 -92
  533. package/src/services/connectors/oidc.ts +0 -111
  534. package/src/services/connectors/registry.ts +0 -124
  535. package/src/services/connectors/types.ts +0 -38
  536. package/src/services/connectors/zitadel.ts +0 -77
  537. package/src/services/devices.ts +0 -76
  538. package/src/services/domain/authentication.ts +0 -279
  539. package/src/services/domain/authorization.ts +0 -49
  540. package/src/services/domain/identity.ts +0 -108
  541. package/src/services/domain/index.ts +0 -4
  542. package/src/services/domain/organization.ts +0 -114
  543. package/src/services/email.ts +0 -167
  544. package/src/services/emailVerification.ts +0 -75
  545. package/src/services/enterpriseSso.ts +0 -58
  546. package/src/services/events/bus.ts +0 -43
  547. package/src/services/events/subscribers/anomaly.ts +0 -13
  548. package/src/services/events/subscribers/auditLog.ts +0 -21
  549. package/src/services/events/subscribers/webhook.ts +0 -39
  550. package/src/services/events/subscribers/webhookDispatch.ts +0 -14
  551. package/src/services/events/types.ts +0 -106
  552. package/src/services/events/validate.ts +0 -118
  553. package/src/services/featureFlags.ts +0 -90
  554. package/src/services/features.ts +0 -22
  555. package/src/services/federation.ts +0 -30
  556. package/src/services/hibp.ts +0 -28
  557. package/src/services/ipControls.ts +0 -99
  558. package/src/services/magicLinks.ts +0 -51
  559. package/src/services/oauth2.ts +0 -216
  560. package/src/services/organizations.ts +0 -171
  561. package/src/services/permissions.ts +0 -146
  562. package/src/services/plugins/registry.ts +0 -242
  563. package/src/services/plugins/types.ts +0 -98
  564. package/src/services/queue/bullmq.ts +0 -104
  565. package/src/services/queue/inProcess.ts +0 -75
  566. package/src/services/queue/index.ts +0 -19
  567. package/src/services/queue/types.ts +0 -26
  568. package/src/services/redis.ts +0 -16
  569. package/src/services/secrets/awsKms.ts +0 -97
  570. package/src/services/secrets/azureKeyVault.ts +0 -171
  571. package/src/services/secrets/database.ts +0 -166
  572. package/src/services/secrets/environment.ts +0 -117
  573. package/src/services/secrets/index.ts +0 -50
  574. package/src/services/secrets/password.ts +0 -73
  575. package/src/services/secrets/provider.ts +0 -36
  576. package/src/services/secrets/vault.ts +0 -149
  577. package/src/services/secrets.ts +0 -2
  578. package/src/services/serviceAccounts.ts +0 -74
  579. package/src/services/setup/configWriter.ts +0 -200
  580. package/src/services/setup/diagnostics.ts +0 -76
  581. package/src/services/setup/token.ts +0 -42
  582. package/src/services/setup/types.ts +0 -40
  583. package/src/services/setup/validation.ts +0 -205
  584. package/src/services/sms.ts +0 -81
  585. package/src/services/smsOtp.ts +0 -74
  586. package/src/services/tokens.ts +0 -287
  587. package/src/services/totp.ts +0 -113
  588. package/src/services/users.ts +0 -239
  589. package/src/services/webauthn.ts +0 -193
  590. package/src/services/webhooks.ts +0 -190
  591. package/src/services/workflows/engine.ts +0 -125
  592. package/src/services/workflows/steps.ts +0 -129
  593. package/src/services/zitadel.ts +0 -277
  594. package/src/setup-server.ts +0 -71
  595. package/src/tests/errors.test.ts +0 -74
  596. package/src/tests/events.test.ts +0 -52
  597. package/src/tests/featureFlags.test.ts +0 -26
  598. package/src/tests/integration/queue.test.ts +0 -54
  599. package/src/tests/plugins.test.ts +0 -73
  600. package/src/tests/result.test.ts +0 -52
  601. package/src/tests/setup/configWriter.test.ts +0 -69
  602. package/src/tests/setup/validation.test.ts +0 -29
  603. package/src/tests/smoke.test.ts +0 -136
  604. package/src/types.ts +0 -70
@@ -1,214 +0,0 @@
1
- import { z } from "zod";
2
- import type { FastifyInstance } from "fastify";
3
- import { getSdk } from "../sdk/index.js";
4
- import {
5
- setSessionCookies,
6
- clearSessionCookies,
7
- getRefreshToken,
8
- } from "../plugins/auth.js";
9
- import { rateLimit } from "../plugins/rateLimit.js";
10
- import { checkImpossibleTravel } from "../services/anomalyDetection.js";
11
- import { sendSuspiciousLoginAlert } from "../services/email.js";
12
- import { checkIpAllowed } from "../services/ipControls.js";
13
- import { toPublicUser } from "../types.js";
14
- import { verifyTOTP } from "../services/totp.js";
15
- import { sendResultError } from "./helpers.js";
16
-
17
- /**
18
- * Fire-and-forget impossible-travel check after a successful login.
19
- * Emits a suspicious-login email when the user's previous login came from a
20
- * different IP within the anomaly window.
21
- */
22
- function detectImpossibleTravel(user: { id: string; email: string }, ip?: string, userAgent?: string): void {
23
- checkImpossibleTravel(user.id, ip)
24
- .then(async (suspicious) => {
25
- if (!suspicious) return;
26
- await sendSuspiciousLoginAlert({
27
- email: user.email,
28
- ipAddress: ip,
29
- userAgent,
30
- reason: "Sign-in from a new location within minutes of the previous one",
31
- });
32
- })
33
- .catch((err: unknown) => {
34
- console.error("[anomaly] impossible-travel check failed:", err);
35
- });
36
- }
37
-
38
- const RegisterSchema = z.object({
39
- username: z.string().min(3).max(32).regex(/^[a-zA-Z0-9_-]+$/),
40
- email: z.string().email().max(255),
41
- password: z.string().min(8).max(128),
42
- name: z.string().max(255).optional(),
43
- client_id: z.string().optional(),
44
- metadata: z.record(z.string(), z.unknown()).optional(),
45
- });
46
-
47
- const LoginSchema = z.object({
48
- email: z.string().email().max(255),
49
- password: z.string().min(1).max(128),
50
- client_id: z.string().optional(),
51
- totp_code: z.string().min(6).max(8).optional(),
52
- });
53
-
54
- const RefreshSchema = z.object({
55
- client_id: z.string().optional(),
56
- });
57
-
58
- export default async function authRoutes(app: FastifyInstance) {
59
- const sdk = getSdk();
60
-
61
- app.post(
62
- "/register",
63
- {
64
- preHandler: [
65
- rateLimit({
66
- keyPrefix: "register",
67
- maxAttempts: 5,
68
- windowSeconds: 900,
69
- }),
70
- ],
71
- },
72
- async (request, reply) => {
73
- const body = RegisterSchema.parse(request.body);
74
-
75
- const ipCheck = await checkIpAllowed(body.client_id, request.ip);
76
- if (!ipCheck.allowed) {
77
- return reply.status(403).send({ error: ipCheck.reason, code: "IP_NOT_ALLOWED" });
78
- }
79
-
80
- const result = await sdk.authentication.register({
81
- username: body.username,
82
- email: body.email,
83
- password: body.password,
84
- name: body.name,
85
- clientId: body.client_id,
86
- metadata: body.metadata,
87
- });
88
-
89
- if (!result.success) return sendResultError(reply, result);
90
-
91
- await request.audit("user_registered", { userId: result.data.user.id, email: result.data.user.email });
92
- setSessionCookies(reply, result.data.accessToken, result.data.refreshToken, body.client_id);
93
- return { user: toPublicUser(result.data.user) };
94
- }
95
- );
96
-
97
- app.post(
98
- "/login",
99
- {
100
- preHandler: [
101
- rateLimit({
102
- keyPrefix: "login",
103
- maxAttempts: 5,
104
- windowSeconds: 900,
105
- }),
106
- ],
107
- },
108
- async (request, reply) => {
109
- const body = LoginSchema.parse(request.body);
110
-
111
- const ipCheck = await checkIpAllowed(body.client_id, request.ip);
112
- if (!ipCheck.allowed) {
113
- return reply.status(403).send({ error: ipCheck.reason, code: "IP_NOT_ALLOWED" });
114
- }
115
-
116
- const result = await sdk.authentication.login({
117
- email: body.email,
118
- password: body.password,
119
- clientId: body.client_id,
120
- });
121
-
122
- if (!result.success) return sendResultError(reply, result);
123
-
124
- if (body.totp_code) {
125
- const validTotp = await verifyTOTP(result.data.user.id, body.totp_code);
126
- if (!validTotp) {
127
- return reply.status(401).send({ error: "Invalid two-factor code." });
128
- }
129
- }
130
-
131
- await request.audit("user_login", { userId: result.data.user.id });
132
- detectImpossibleTravel(result.data.user, request.ip, request.headers["user-agent"]);
133
- setSessionCookies(reply, result.data.accessToken, result.data.refreshToken, body.client_id);
134
- return { user: toPublicUser(result.data.user) };
135
- }
136
- );
137
-
138
- app.post(
139
- "/token-login",
140
- {
141
- preHandler: [
142
- rateLimit({
143
- keyPrefix: "login",
144
- maxAttempts: 5,
145
- windowSeconds: 900,
146
- }),
147
- ],
148
- },
149
- async (request, reply) => {
150
- const body = LoginSchema.parse(request.body);
151
-
152
- const ipCheck = await checkIpAllowed(body.client_id, request.ip);
153
- if (!ipCheck.allowed) {
154
- return reply.status(403).send({ error: ipCheck.reason, code: "IP_NOT_ALLOWED" });
155
- }
156
-
157
- const result = await sdk.authentication.login({
158
- email: body.email,
159
- password: body.password,
160
- clientId: body.client_id,
161
- });
162
-
163
- if (!result.success) return sendResultError(reply, result);
164
-
165
- if (body.totp_code) {
166
- const validTotp = await verifyTOTP(result.data.user.id, body.totp_code);
167
- if (!validTotp) {
168
- return reply.status(401).send({ error: "Invalid two-factor code." });
169
- }
170
- }
171
-
172
- await request.audit("user_token_login", { userId: result.data.user.id });
173
- detectImpossibleTravel(result.data.user, request.ip, request.headers["user-agent"]);
174
- return {
175
- accessToken: result.data.accessToken,
176
- user: toPublicUser(result.data.user),
177
- };
178
- }
179
- );
180
-
181
- app.get("/me", { preHandler: [app.authenticate] }, async (request) => {
182
- return { user: request.user ? toPublicUser(request.user) : null };
183
- });
184
-
185
- app.post("/refresh", async (request, reply) => {
186
- const body = RefreshSchema.parse(request.body ?? {});
187
- const clientId = body.client_id;
188
-
189
- const refreshToken = getRefreshToken(request, clientId) || getRefreshToken(request);
190
- if (!refreshToken) {
191
- return reply.status(401).send({ error: "Unauthorized" });
192
- }
193
-
194
- const result = await sdk.authentication.refresh(refreshToken, clientId);
195
- if (!result.success) return sendResultError(reply, result);
196
-
197
- await request.audit("token_refresh", {});
198
- setSessionCookies(reply, result.data.accessToken, result.data.refreshToken, clientId);
199
- return { success: true };
200
- });
201
-
202
- app.post("/logout", async (request, reply) => {
203
- const appClientId = request.state?.app?.clientId;
204
- const refreshToken =
205
- getRefreshToken(request, appClientId) || getRefreshToken(request);
206
- const result = await sdk.authentication.logout(refreshToken);
207
- if (!result.success) return sendResultError(reply, result);
208
-
209
- await request.audit("user_logout", { userId: request.user?.id });
210
- clearSessionCookies(reply, appClientId);
211
- clearSessionCookies(reply);
212
- return { success: true };
213
- });
214
- }
@@ -1,38 +0,0 @@
1
- import { z } from "zod";
2
- import type { FastifyInstance, FastifyRequest, FastifyReply } from "fastify";
3
- import { getSdk } from "../sdk/index.js";
4
-
5
- const CheckSchema = z.object({
6
- resource: z.string().min(1),
7
- action: z.string().min(1),
8
- });
9
-
10
- export default async function authzRoutes(app: FastifyInstance) {
11
- const sdk = getSdk();
12
-
13
- app.post(
14
- "/authz/check",
15
- { preHandler: [app.authenticate] },
16
- async (request: FastifyRequest, reply: FastifyReply) => {
17
- const body = CheckSchema.parse(request.body);
18
- const membership = request.state?.membership;
19
-
20
- if (!membership) {
21
- return reply.status(403).send({
22
- allowed: false,
23
- reason: "No organization context",
24
- });
25
- }
26
-
27
- const allowed = await sdk.authorization.hasPermission(membership.role, body.resource, body.action);
28
- await request.audit("authz_check", {
29
- resource: body.resource,
30
- action: body.action,
31
- role: membership.role,
32
- allowed,
33
- });
34
-
35
- return { allowed };
36
- }
37
- );
38
- }
@@ -1,67 +0,0 @@
1
- import type { FastifyInstance, FastifyRequest, FastifyReply } from "fastify";
2
- import { z } from "zod";
3
- import { createConfigWriter } from "../services/setup/configWriter.js";
4
- import { queue } from "../services/queue/index.js";
5
-
6
- const UpdateConfigSchema = z.object({
7
- values: z.record(z.string(), z.string()),
8
- });
9
-
10
- async function requireOwner(request: FastifyRequest, reply: FastifyReply) {
11
- await request.server.authenticate(request, reply);
12
- if (reply.sent) return;
13
- if (request.user!.role !== "owner") {
14
- return reply.status(403).send({ error: "Forbidden: owner access required" });
15
- }
16
- }
17
-
18
- export default async function configRoutes(app: FastifyInstance) {
19
- // Read current configuration values from the configured store (.env by default).
20
- app.get("/", { preHandler: [requireOwner] }, async (_request: FastifyRequest, reply: FastifyReply) => {
21
- try {
22
- const writer = createConfigWriter();
23
- const values = await writer.read();
24
- return reply.send({ values });
25
- } catch (err) {
26
- app.log.error({ err }, "Failed to read configuration");
27
- return reply.status(500).send({ error: "Failed to read configuration" });
28
- }
29
- });
30
-
31
- // Update configuration values. A restart is required for most changes to take effect.
32
- app.put("/", { preHandler: [requireOwner] }, async (request: FastifyRequest, reply: FastifyReply) => {
33
- const parsed = UpdateConfigSchema.safeParse(request.body);
34
- if (!parsed.success) {
35
- return reply.status(400).send({ error: "Invalid input", details: parsed.error.issues });
36
- }
37
-
38
- try {
39
- const writer = createConfigWriter();
40
- const backup = await writer.backup();
41
- if (!backup.success) {
42
- return reply.status(500).send({ error: backup.error.message, code: backup.error.code });
43
- }
44
-
45
- const writeResult = await writer.write(parsed.data.values);
46
- if (!writeResult.success) {
47
- return reply.status(500).send({ error: writeResult.error.message, code: writeResult.error.code });
48
- }
49
-
50
- return reply.send({ ok: true, backupPath: backup.data || undefined });
51
- } catch (err) {
52
- request.log.error({ err }, "Failed to update configuration");
53
- return reply.status(500).send({ error: "Failed to update configuration" });
54
- }
55
- });
56
-
57
- // Restart the server so new configuration is loaded.
58
- app.post("/restart", { preHandler: [requireOwner] }, async (_request: FastifyRequest, reply: FastifyReply) => {
59
- reply.status(202).send({ ok: true, message: "Server is restarting" });
60
- try {
61
- await queue.close?.();
62
- } catch {
63
- // ignore
64
- }
65
- setTimeout(() => process.exit(0), 500);
66
- });
67
- }
@@ -1,73 +0,0 @@
1
- import { z } from "zod";
2
- import type { FastifyInstance, FastifyRequest, FastifyReply } from "fastify";
3
- import { findUserByEmail } from "../services/users.js";
4
- import {
5
- sendVerificationEmail,
6
- consumeVerificationToken,
7
- } from "../services/emailVerification.js";
8
- import { rateLimit } from "../plugins/rateLimit.js";
9
-
10
- const SendSchema = z.object({
11
- email: z.string().email(),
12
- });
13
-
14
- export default async function emailVerificationRoutes(app: FastifyInstance) {
15
- // Authenticated: resend the verification email for the signed-in user.
16
- app.post("/email-verification/send", { preHandler: [app.authenticate] }, async (request: FastifyRequest, reply: FastifyReply) => {
17
- const user = request.user;
18
- if (!user) return reply.status(401).send({ error: "Unauthorized" });
19
- if (user.emailVerified) return { success: true, alreadyVerified: true };
20
-
21
- try {
22
- await sendVerificationEmail(user);
23
- } catch (err) {
24
- request.log.error({ err }, "Failed to send verification email");
25
- return reply.status(500).send({ error: "Failed to send verification email" });
26
- }
27
-
28
- await request.audit("email_verification_sent", { userId: user.id });
29
- return { success: true };
30
- });
31
-
32
- // Unauthenticated: request a verification email by address.
33
- // Always returns success to avoid user enumeration.
34
- app.post("/email-verification/request", {
35
- preHandler: [
36
- rateLimit({
37
- keyPrefix: "email-verification",
38
- maxAttempts: 3,
39
- windowSeconds: 900,
40
- }),
41
- ],
42
- }, async (request: FastifyRequest, reply: FastifyReply) => {
43
- const body = SendSchema.parse(request.body);
44
- const user = await findUserByEmail(body.email);
45
- if (!user || user.emailVerified) {
46
- return reply.status(200).send({ success: true });
47
- }
48
-
49
- try {
50
- await sendVerificationEmail(user);
51
- await request.audit("email_verification_sent", { userId: user.id });
52
- } catch (err) {
53
- request.log.error({ err }, "Failed to send verification email");
54
- }
55
-
56
- return { success: true };
57
- });
58
-
59
- app.get("/email-verification/verify", async (request: FastifyRequest, reply: FastifyReply) => {
60
- const query = request.query as { token?: string };
61
- if (!query.token) {
62
- return reply.status(400).send({ error: "Missing token" });
63
- }
64
-
65
- const user = await consumeVerificationToken(query.token);
66
- if (!user) {
67
- return reply.status(400).send({ error: "Invalid or expired token" });
68
- }
69
-
70
- await request.audit("email_verified", { userId: user.id });
71
- return { success: true, email: user.email };
72
- });
73
- }
@@ -1,156 +0,0 @@
1
- import crypto from "node:crypto";
2
- import { z } from "zod";
3
- import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
4
- import { config } from "../config.js";
5
- import { listSupportedProviders, listConfiguredProviders } from "../services/connectors/registry.js";
6
- import { getSdk } from "../sdk/index.js";
7
- import { setSessionCookies, clearSessionCookies } from "../plugins/auth.js";
8
- import { findApplicationByClientId } from "../services/applications.js";
9
- import type { Application } from "../db/schema.js";
10
- import { buildOAuthErrorRedirect, buildOAuthErrorResponse } from "../lib/errors.js";
11
- import { sendResultError } from "./helpers.js";
12
-
13
- function isProvider(value: string): boolean {
14
- return listSupportedProviders().includes(value);
15
- }
16
-
17
- function randomState(): string {
18
- return crypto.randomBytes(24).toString("base64url");
19
- }
20
-
21
- function publicUrl(): string {
22
- return config.AUTH_API_PUBLIC_URL || `http://localhost:${config.PORT}`;
23
- }
24
-
25
- function callbackRedirectUri(provider: string): string {
26
- return `${publicUrl()}/federation/${provider}/callback`;
27
- }
28
-
29
- function setFederationState(reply: FastifyReply, state: string, clientId?: string): void {
30
- reply.setCookie("fed_state", state, {
31
- path: "/",
32
- httpOnly: true,
33
- secure: config.COOKIE_SECURE,
34
- sameSite: "lax" as const,
35
- domain: config.COOKIE_DOMAIN || undefined,
36
- maxAge: 600,
37
- });
38
- if (clientId) {
39
- reply.setCookie("fed_client_id", clientId, {
40
- path: "/",
41
- httpOnly: true,
42
- secure: config.COOKIE_SECURE,
43
- sameSite: "lax" as const,
44
- domain: config.COOKIE_DOMAIN || undefined,
45
- maxAge: 600,
46
- });
47
- }
48
- }
49
-
50
- function clearFederationCookies(reply: FastifyReply): void {
51
- const opts = {
52
- path: "/",
53
- httpOnly: true,
54
- secure: config.COOKIE_SECURE,
55
- sameSite: "lax" as const,
56
- domain: config.COOKIE_DOMAIN || undefined,
57
- };
58
- reply.clearCookie("fed_state", opts);
59
- reply.clearCookie("fed_client_id", opts);
60
- }
61
-
62
- function redirectTargetUrl(clientId?: string, app?: Application): string {
63
- if (app?.redirectUris?.length) return app.redirectUris[0];
64
- return process.env.CLIENT_APP_URL || "http://localhost:5173";
65
- }
66
-
67
- const LinkIdentitySchema = z.object({
68
- providerType: z.string(),
69
- providerId: z.string().uuid(),
70
- externalSub: z.string(),
71
- email: z.string().email().optional(),
72
- });
73
-
74
- export default async function federationRoutes(app: FastifyInstance) {
75
- const sdk = getSdk();
76
-
77
- app.get("/:provider/start", async (request, reply) => {
78
- const { provider } = request.params as { provider: string };
79
- if (!isProvider(provider)) {
80
- return reply.status(400).send({ error: "Unsupported federation provider" });
81
- }
82
- const query = request.query as { client_id?: string; redirect_uri?: string };
83
- const state = randomState();
84
- setFederationState(reply, state, query.client_id);
85
-
86
- try {
87
- const result = await sdk.identity.getFederationAuthorizeUrl(provider, state, callbackRedirectUri(provider));
88
- if (!result.success) return sendResultError(reply, result);
89
- return reply.redirect(result.data.url);
90
- } catch (err) {
91
- request.log.error({ err }, "Federation start failed");
92
- clearFederationCookies(reply);
93
- const { statusCode, body } = buildOAuthErrorResponse(err);
94
- return reply.status(statusCode).send(body);
95
- }
96
- });
97
-
98
- app.get("/:provider/callback", async (request, reply) => {
99
- const { provider } = request.params as { provider: string };
100
- if (!isProvider(provider)) {
101
- return reply.status(400).send({ error: "Unsupported federation provider" });
102
- }
103
-
104
- const { code, state } = request.query as { code?: string; state?: string };
105
- const cookieState = request.cookies.fed_state;
106
- const clientId = request.cookies.fed_client_id;
107
-
108
- if (!code || !state || state !== cookieState) {
109
- clearFederationCookies(reply);
110
- return reply.redirect(`${redirectTargetUrl(clientId)}?error=${encodeURIComponent("Invalid federation state")}`);
111
- }
112
- clearFederationCookies(reply);
113
-
114
- try {
115
- const result = await sdk.identity.completeFederationLogin(provider, code, callbackRedirectUri(provider));
116
- if (!result.success) return sendResultError(reply, result);
117
- const app = clientId ? await findApplicationByClientId(clientId) : undefined;
118
- setSessionCookies(reply, result.data.tokens.accessToken, result.data.tokens.refreshToken, app?.clientId);
119
- return reply.redirect(redirectTargetUrl(clientId, app));
120
- } catch (err) {
121
- request.log.error({ err }, "Federation callback failed");
122
- clearSessionCookies(reply);
123
- const url = buildOAuthErrorRedirect(err, redirectTargetUrl(clientId), { state });
124
- return reply.redirect(url);
125
- }
126
- });
127
-
128
- app.get("/providers", async () => {
129
- return {
130
- providers: listConfiguredProviders(),
131
- };
132
- });
133
-
134
- app.post(
135
- "/link",
136
- { preHandler: [app.authenticate] },
137
- async (request: FastifyRequest, reply) => {
138
- const body = LinkIdentitySchema.parse(request.body);
139
- const result = await sdk.identity.linkUserIdentity(
140
- request.user!.id,
141
- body.providerId,
142
- body.providerType,
143
- body.externalSub,
144
- body.email
145
- );
146
- if (!result.success) return sendResultError(reply, result);
147
- await request.audit("federation_identity_linked", { userId: request.user!.id, providerType: body.providerType, providerId: body.providerId });
148
- return reply.status(201).send({ success: true });
149
- }
150
- );
151
-
152
- app.get("/identities", { preHandler: [app.authenticate] }, async (request: FastifyRequest) => {
153
- const rows = await app.container.identityRepository.listByUserId(request.user!.id);
154
- return { identities: rows };
155
- });
156
- }
@@ -1,17 +0,0 @@
1
- import type { FastifyReply } from "fastify";
2
-
3
- export function sendResultError(reply: FastifyReply, result: { success: false; error: { statusCode?: number; message: string; code: string } }) {
4
- return reply.status(result.error.statusCode ?? 400).send({ error: result.error.message, code: result.error.code });
5
- }
6
-
7
- /**
8
- * Escape special XML characters to prevent XML injection.
9
- */
10
- export function escapeXml(value: string): string {
11
- return value
12
- .replace(/&/g, "&")
13
- .replace(/</g, "&lt;")
14
- .replace(/>/g, "&gt;")
15
- .replace(/"/g, "&quot;")
16
- .replace(/'/g, "&apos;");
17
- }
@@ -1,107 +0,0 @@
1
- import { z } from "zod";
2
- import type { FastifyInstance, FastifyRequest } from "fastify";
3
- import { findUserByEmail } from "../services/users.js";
4
- import {
5
- generateMagicLink,
6
- storeMagicLink,
7
- consumeMagicLink,
8
- magicLinkExpiresAt,
9
- } from "../services/magicLinks.js";
10
- import { createTokenSet } from "../services/tokens.js";
11
- import { fingerprintFromRequest, recordDevice } from "../services/devices.js";
12
- import { setSessionCookies } from "../plugins/auth.js";
13
- import { emailProvider } from "../services/email.js";
14
- import { toPublicUser } from "../types.js";
15
- import { config } from "../config.js";
16
- import { rateLimit } from "../plugins/rateLimit.js";
17
-
18
- const SendSchema = z.object({
19
- email: z.string().email(),
20
- });
21
-
22
- function magicLinkUrl(token: string): string {
23
- // The link lands on the client app (Keystone admin UI or a client
24
- // application), which exchanges the token via the verify endpoint.
25
- const base = process.env.CLIENT_APP_URL || "http://localhost:5173";
26
- return `${base}/#magic-link=${encodeURIComponent(token)}`;
27
- }
28
-
29
- function postLoginRedirect(): string {
30
- return process.env.CLIENT_APP_URL || "http://localhost:5173";
31
- }
32
-
33
- export default async function magicLinkRoutes(app: FastifyInstance) {
34
- app.post("/magic-link/send", {
35
- preHandler: [
36
- rateLimit({
37
- keyPrefix: "magic-link",
38
- maxAttempts: 3,
39
- windowSeconds: 900,
40
- }),
41
- ],
42
- }, async (request, reply) => {
43
- const body = SendSchema.parse(request.body);
44
- const user = await findUserByEmail(body.email);
45
- if (!user) {
46
- return reply.status(200).send({ success: true });
47
- }
48
-
49
- const { token, tokenHash } = generateMagicLink();
50
- await storeMagicLink(user.id, tokenHash, magicLinkExpiresAt());
51
-
52
- try {
53
- const url = magicLinkUrl(token);
54
- const ttlMinutes = Math.round(config.MAGIC_LINK_TTL_SECONDS / 60);
55
- await emailProvider.send({
56
- to: user.email,
57
- subject: "Your sign-in link",
58
- text: `Click the link to sign in:\n\n${url}\n\nThis link expires in ${ttlMinutes} minutes and can only be used once.`,
59
- html: `<p>Click <a href="${url}">here</a> to sign in.</p><p>This link expires in ${ttlMinutes} minutes and can only be used once.</p>`,
60
- });
61
- } catch (err) {
62
- request.log.error({ err }, "Failed to send magic link email");
63
- }
64
-
65
- await request.audit("magic_link_sent", { userId: user.id });
66
-
67
- return { success: true };
68
- });
69
-
70
- app.get("/magic-link/verify", async (request: FastifyRequest, reply) => {
71
- const query = request.query as { token?: string; redirect?: string };
72
- if (!query.token) {
73
- return reply.status(400).send({ error: "Missing token" });
74
- }
75
-
76
- const user = await consumeMagicLink(query.token);
77
- if (!user) {
78
- return reply.status(400).send({ error: "Invalid or expired token" });
79
- }
80
-
81
- const fingerprint = fingerprintFromRequest(request);
82
- await recordDevice(user.id, fingerprint, request.ip, request.headers["user-agent"]);
83
-
84
- const tokens = await createTokenSet(
85
- user,
86
- request.ip,
87
- request.headers["user-agent"],
88
- {},
89
- fingerprint
90
- );
91
- setSessionCookies(reply, tokens.accessToken, tokens.refreshToken);
92
-
93
- await request.audit("magic_link_verified", { userId: user.id });
94
-
95
- // Browser flow: redirect back to the app after setting session cookies.
96
- const accept = request.headers.accept || "";
97
- if (accept.includes("text/html")) {
98
- return reply.redirect(postLoginRedirect());
99
- }
100
-
101
- return {
102
- user: toPublicUser(user),
103
- accessToken: tokens.accessToken,
104
- refreshToken: tokens.refreshToken,
105
- };
106
- });
107
- }