@hilbras/keystone 1.5.0 → 1.9.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 (559) hide show
  1. package/CHANGELOG.md +272 -0
  2. package/README.md +59 -25
  3. package/dist/cli.js +25 -27
  4. package/dist/cli.js.map +1 -1
  5. package/dist/config.d.ts +15 -1
  6. package/dist/config.d.ts.map +1 -1
  7. package/dist/config.js +45 -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/{src/db/migrations/meta/0007_snapshot.json → dist/db/migrations/meta/0008_snapshot.json} +136 -32
  20. package/{src/db/migrations/meta/0006_snapshot.json → dist/db/migrations/meta/0009_snapshot.json} +359 -30
  21. package/{src/db/migrations/meta/0005_snapshot.json → dist/db/migrations/meta/0010_snapshot.json} +459 -29
  22. package/{src/db/migrations/meta/0004_snapshot.json → dist/db/migrations/meta/0011_snapshot.json} +594 -30
  23. package/dist/db/migrations/meta/0012_snapshot.json +3891 -0
  24. package/dist/db/migrations/meta/0013_snapshot.json +3919 -0
  25. package/dist/db/migrations/meta/0014_snapshot.json +4311 -0
  26. package/dist/db/migrations/meta/_journal.json +49 -0
  27. package/dist/db/reencryptOidcSecrets.d.ts +2 -0
  28. package/dist/db/reencryptOidcSecrets.d.ts.map +1 -0
  29. package/dist/db/reencryptOidcSecrets.js +41 -0
  30. package/dist/db/reencryptOidcSecrets.js.map +1 -0
  31. package/dist/db/schema.d.ts +2521 -53
  32. package/dist/db/schema.d.ts.map +1 -1
  33. package/dist/db/schema.js +118 -3
  34. package/dist/db/schema.js.map +1 -1
  35. package/dist/db/seed.js +67 -40
  36. package/dist/db/seed.js.map +1 -1
  37. package/dist/di.d.ts.map +1 -1
  38. package/dist/di.js +11 -3
  39. package/dist/di.js.map +1 -1
  40. package/dist/index.d.ts +2 -2
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +26 -2
  43. package/dist/index.js.map +1 -1
  44. package/dist/lib/errors.d.ts +2 -1
  45. package/dist/lib/errors.d.ts.map +1 -1
  46. package/dist/lib/errors.js +10 -0
  47. package/dist/lib/errors.js.map +1 -1
  48. package/dist/plugins/appContext.d.ts.map +1 -1
  49. package/dist/plugins/appContext.js +3 -12
  50. package/dist/plugins/appContext.js.map +1 -1
  51. package/dist/plugins/audit.d.ts.map +1 -1
  52. package/dist/plugins/audit.js +26 -6
  53. package/dist/plugins/audit.js.map +1 -1
  54. package/dist/plugins/auth.d.ts.map +1 -1
  55. package/dist/plugins/auth.js +32 -7
  56. package/dist/plugins/auth.js.map +1 -1
  57. package/dist/plugins/metrics.d.ts.map +1 -1
  58. package/dist/plugins/mtls.d.ts.map +1 -1
  59. package/dist/plugins/permissions.d.ts.map +1 -1
  60. package/dist/plugins/permissions.js +29 -9
  61. package/dist/plugins/permissions.js.map +1 -1
  62. package/dist/plugins/rateLimit.d.ts +15 -0
  63. package/dist/plugins/rateLimit.d.ts.map +1 -1
  64. package/dist/plugins/rateLimit.js +11 -1
  65. package/dist/plugins/rateLimit.js.map +1 -1
  66. package/dist/plugins/requestLogger.d.ts.map +1 -1
  67. package/dist/repositories/apiKey.d.ts.map +1 -1
  68. package/dist/repositories/application.d.ts.map +1 -1
  69. package/dist/repositories/application.js +1 -1
  70. package/dist/repositories/application.js.map +1 -1
  71. package/dist/repositories/audit.d.ts.map +1 -1
  72. package/dist/repositories/index.d.ts +3 -0
  73. package/dist/repositories/index.d.ts.map +1 -1
  74. package/dist/repositories/index.js +3 -0
  75. package/dist/repositories/index.js.map +1 -1
  76. package/dist/repositories/mfaChallenge.d.ts +23 -0
  77. package/dist/repositories/mfaChallenge.d.ts.map +1 -0
  78. package/dist/repositories/mfaChallenge.js +71 -0
  79. package/dist/repositories/mfaChallenge.js.map +1 -0
  80. package/dist/repositories/oidcConnection.d.ts +27 -43
  81. package/dist/repositories/oidcConnection.d.ts.map +1 -1
  82. package/dist/repositories/oidcConnection.js +15 -6
  83. package/dist/repositories/oidcConnection.js.map +1 -1
  84. package/dist/repositories/organization.d.ts +9 -9
  85. package/dist/repositories/organization.d.ts.map +1 -1
  86. package/dist/repositories/organization.js +91 -37
  87. package/dist/repositories/organization.js.map +1 -1
  88. package/dist/repositories/permission.d.ts.map +1 -1
  89. package/dist/repositories/permission.js +27 -5
  90. package/dist/repositories/permission.js.map +1 -1
  91. package/dist/repositories/samlConnection.d.ts +28 -28
  92. package/dist/repositories/samlConnection.d.ts.map +1 -1
  93. package/dist/repositories/samlConnection.js +12 -4
  94. package/dist/repositories/samlConnection.js.map +1 -1
  95. package/dist/repositories/scimConnection.d.ts +38 -0
  96. package/dist/repositories/scimConnection.d.ts.map +1 -0
  97. package/dist/repositories/scimConnection.js +123 -0
  98. package/dist/repositories/scimConnection.js.map +1 -0
  99. package/dist/repositories/scimGroup.d.ts +36 -0
  100. package/dist/repositories/scimGroup.d.ts.map +1 -0
  101. package/dist/repositories/scimGroup.js +113 -0
  102. package/dist/repositories/scimGroup.js.map +1 -0
  103. package/dist/repositories/session.d.ts +23 -13
  104. package/dist/repositories/session.d.ts.map +1 -1
  105. package/dist/repositories/session.js +13 -1
  106. package/dist/repositories/session.js.map +1 -1
  107. package/dist/repositories/types.d.ts +112 -5
  108. package/dist/repositories/types.d.ts.map +1 -1
  109. package/dist/repositories/types.js +7 -1
  110. package/dist/repositories/types.js.map +1 -1
  111. package/dist/repositories/user.d.ts +23 -1
  112. package/dist/repositories/user.d.ts.map +1 -1
  113. package/dist/repositories/user.js +180 -4
  114. package/dist/repositories/user.js.map +1 -1
  115. package/dist/routes/admin/billing.js +4 -4
  116. package/dist/routes/admin/billing.js.map +1 -1
  117. package/dist/routes/admin/helpers.d.ts +16 -20
  118. package/dist/routes/admin/helpers.d.ts.map +1 -1
  119. package/dist/routes/admin/helpers.js +53 -10
  120. package/dist/routes/admin/helpers.js.map +1 -1
  121. package/dist/routes/admin/organizations.d.ts.map +1 -1
  122. package/dist/routes/admin/organizations.js +76 -69
  123. package/dist/routes/admin/organizations.js.map +1 -1
  124. package/dist/routes/admin/permissions.d.ts.map +1 -1
  125. package/dist/routes/admin/permissions.js +48 -14
  126. package/dist/routes/admin/permissions.js.map +1 -1
  127. package/dist/routes/admin/platform.d.ts.map +1 -1
  128. package/dist/routes/admin/platform.js +86 -35
  129. package/dist/routes/admin/platform.js.map +1 -1
  130. package/dist/routes/admin/sso.d.ts.map +1 -1
  131. package/dist/routes/admin/sso.js +143 -12
  132. package/dist/routes/admin/sso.js.map +1 -1
  133. package/dist/routes/admin/webhooks.js +8 -8
  134. package/dist/routes/admin/webhooks.js.map +1 -1
  135. package/dist/routes/apiKeys.d.ts.map +1 -1
  136. package/dist/routes/apiKeys.js +23 -5
  137. package/dist/routes/apiKeys.js.map +1 -1
  138. package/dist/routes/auth.d.ts.map +1 -1
  139. package/dist/routes/auth.js +112 -22
  140. package/dist/routes/auth.js.map +1 -1
  141. package/dist/routes/authz.d.ts.map +1 -1
  142. package/dist/routes/authz.js +16 -4
  143. package/dist/routes/authz.js.map +1 -1
  144. package/dist/routes/config.d.ts.map +1 -1
  145. package/dist/routes/config.js +16 -14
  146. package/dist/routes/config.js.map +1 -1
  147. package/dist/routes/federation.d.ts.map +1 -1
  148. package/dist/routes/federation.js +17 -3
  149. package/dist/routes/federation.js.map +1 -1
  150. package/dist/routes/magicLinks.d.ts.map +1 -1
  151. package/dist/routes/magicLinks.js +15 -3
  152. package/dist/routes/magicLinks.js.map +1 -1
  153. package/dist/routes/oauth.d.ts.map +1 -1
  154. package/dist/routes/oauth.js +22 -3
  155. package/dist/routes/oauth.js.map +1 -1
  156. package/dist/routes/oauth2.d.ts.map +1 -1
  157. package/dist/routes/oauth2.js +104 -11
  158. package/dist/routes/oauth2.js.map +1 -1
  159. package/dist/routes/oidcEnterprise.d.ts.map +1 -1
  160. package/dist/routes/oidcEnterprise.js +67 -21
  161. package/dist/routes/oidcEnterprise.js.map +1 -1
  162. package/dist/routes/password.d.ts.map +1 -1
  163. package/dist/routes/password.js.map +1 -1
  164. package/dist/routes/profile.js +4 -4
  165. package/dist/routes/profile.js.map +1 -1
  166. package/dist/routes/saml.d.ts +9 -0
  167. package/dist/routes/saml.d.ts.map +1 -1
  168. package/dist/routes/saml.js +187 -11
  169. package/dist/routes/saml.js.map +1 -1
  170. package/dist/routes/scim.d.ts +13 -0
  171. package/dist/routes/scim.d.ts.map +1 -1
  172. package/dist/routes/scim.js +885 -110
  173. package/dist/routes/scim.js.map +1 -1
  174. package/dist/routes/sdk.d.ts.map +1 -1
  175. package/dist/routes/sdk.js +24 -8
  176. package/dist/routes/sdk.js.map +1 -1
  177. package/dist/routes/serviceAccounts.d.ts.map +1 -1
  178. package/dist/routes/serviceAccounts.js +2 -1
  179. package/dist/routes/serviceAccounts.js.map +1 -1
  180. package/dist/routes/setup.d.ts.map +1 -1
  181. package/dist/routes/setup.js +15 -16
  182. package/dist/routes/setup.js.map +1 -1
  183. package/dist/routes/smsOtp.js +1 -1
  184. package/dist/routes/smsOtp.js.map +1 -1
  185. package/dist/routes/totp.d.ts.map +1 -1
  186. package/dist/routes/totp.js +113 -23
  187. package/dist/routes/totp.js.map +1 -1
  188. package/dist/routes/webauthn.d.ts.map +1 -1
  189. package/dist/routes/webauthn.js +44 -8
  190. package/dist/routes/webauthn.js.map +1 -1
  191. package/dist/routes/workflows.d.ts.map +1 -1
  192. package/dist/routes/workflows.js +58 -25
  193. package/dist/routes/workflows.js.map +1 -1
  194. package/dist/sdk/index.d.ts.map +1 -1
  195. package/dist/sdk/index.js +141 -40
  196. package/dist/sdk/index.js.map +1 -1
  197. package/dist/sdk/types.d.ts +60 -29
  198. package/dist/sdk/types.d.ts.map +1 -1
  199. package/dist/services/application/authentication.d.ts +39 -1
  200. package/dist/services/application/authentication.d.ts.map +1 -1
  201. package/dist/services/application/authentication.js +43 -1
  202. package/dist/services/application/authentication.js.map +1 -1
  203. package/dist/services/application/identity.d.ts +10 -7
  204. package/dist/services/application/identity.d.ts.map +1 -1
  205. package/dist/services/application/identity.js +13 -10
  206. package/dist/services/application/identity.js.map +1 -1
  207. package/dist/services/application/organization.d.ts +11 -7
  208. package/dist/services/application/organization.d.ts.map +1 -1
  209. package/dist/services/application/organization.js +160 -12
  210. package/dist/services/application/organization.js.map +1 -1
  211. package/dist/services/applications.js +2 -2
  212. package/dist/services/applications.js.map +1 -1
  213. package/dist/services/audit.d.ts +1 -0
  214. package/dist/services/audit.d.ts.map +1 -1
  215. package/dist/services/audit.js +13 -0
  216. package/dist/services/audit.js.map +1 -1
  217. package/dist/services/cache.d.ts.map +1 -1
  218. package/dist/services/configuration/profiles.d.ts +4 -0
  219. package/dist/services/configuration/profiles.d.ts.map +1 -1
  220. package/dist/services/configuration/profiles.js +50 -0
  221. package/dist/services/configuration/profiles.js.map +1 -1
  222. package/dist/services/configuration.d.ts.map +1 -1
  223. package/dist/services/configuration.js.map +1 -1
  224. package/dist/services/connectors/google.d.ts.map +1 -1
  225. package/dist/services/connectors/google.js +3 -2
  226. package/dist/services/connectors/google.js.map +1 -1
  227. package/dist/services/connectors/oidc.d.ts.map +1 -1
  228. package/dist/services/connectors/oidc.js +6 -3
  229. package/dist/services/connectors/oidc.js.map +1 -1
  230. package/dist/services/connectors/zitadel.d.ts.map +1 -1
  231. package/dist/services/connectors/zitadel.js +4 -3
  232. package/dist/services/connectors/zitadel.js.map +1 -1
  233. package/dist/services/domain/authentication.d.ts +43 -4
  234. package/dist/services/domain/authentication.d.ts.map +1 -1
  235. package/dist/services/domain/authentication.js +82 -20
  236. package/dist/services/domain/authentication.js.map +1 -1
  237. package/dist/services/domain/authorization.d.ts +11 -0
  238. package/dist/services/domain/authorization.d.ts.map +1 -1
  239. package/dist/services/domain/authorization.js +36 -1
  240. package/dist/services/domain/authorization.js.map +1 -1
  241. package/dist/services/domain/identity.d.ts +21 -9
  242. package/dist/services/domain/identity.d.ts.map +1 -1
  243. package/dist/services/domain/identity.js +187 -10
  244. package/dist/services/domain/identity.js.map +1 -1
  245. package/dist/services/domain/organization.d.ts +6 -9
  246. package/dist/services/domain/organization.d.ts.map +1 -1
  247. package/dist/services/domain/organization.js +48 -30
  248. package/dist/services/domain/organization.js.map +1 -1
  249. package/dist/services/emailVerification.d.ts +2 -2
  250. package/dist/services/enterpriseSso.d.ts +13 -6
  251. package/dist/services/enterpriseSso.d.ts.map +1 -1
  252. package/dist/services/enterpriseSso.js +75 -6
  253. package/dist/services/enterpriseSso.js.map +1 -1
  254. package/dist/services/events/subscribers/auditLog.js +1 -1
  255. package/dist/services/events/subscribers/auditLog.js.map +1 -1
  256. package/dist/services/events/types.d.ts +7 -1
  257. package/dist/services/events/types.d.ts.map +1 -1
  258. package/dist/services/events/types.js.map +1 -1
  259. package/dist/services/events/validate.d.ts.map +1 -1
  260. package/dist/services/events/validate.js +27 -0
  261. package/dist/services/events/validate.js.map +1 -1
  262. package/dist/services/features.d.ts.map +1 -1
  263. package/dist/services/features.js.map +1 -1
  264. package/dist/services/federation.d.ts +6 -1
  265. package/dist/services/federation.d.ts.map +1 -1
  266. package/dist/services/federation.js +31 -4
  267. package/dist/services/federation.js.map +1 -1
  268. package/dist/services/ipControls.js +2 -2
  269. package/dist/services/ipControls.js.map +1 -1
  270. package/dist/services/magicLinks.d.ts +2 -2
  271. package/dist/services/mfa.d.ts +53 -0
  272. package/dist/services/mfa.d.ts.map +1 -0
  273. package/dist/services/mfa.js +157 -0
  274. package/dist/services/mfa.js.map +1 -0
  275. package/dist/services/oauth2.d.ts +16 -12
  276. package/dist/services/oauth2.d.ts.map +1 -1
  277. package/dist/services/oauth2.js +22 -13
  278. package/dist/services/oauth2.js.map +1 -1
  279. package/dist/services/oidcSecretFormat.d.ts +3 -0
  280. package/dist/services/oidcSecretFormat.d.ts.map +1 -0
  281. package/dist/services/oidcSecretFormat.js +5 -0
  282. package/dist/services/oidcSecretFormat.js.map +1 -0
  283. package/dist/services/organizations.d.ts +4 -16
  284. package/dist/services/organizations.d.ts.map +1 -1
  285. package/dist/services/organizations.js +0 -62
  286. package/dist/services/organizations.js.map +1 -1
  287. package/dist/services/permissions.d.ts.map +1 -1
  288. package/dist/services/permissions.js +9 -1
  289. package/dist/services/permissions.js.map +1 -1
  290. package/dist/services/plugins/registry.d.ts.map +1 -1
  291. package/dist/services/plugins/registry.js.map +1 -1
  292. package/dist/services/plugins/types.d.ts.map +1 -1
  293. package/dist/services/queue/bullmq.d.ts.map +1 -1
  294. package/dist/services/queue/inProcess.d.ts.map +1 -1
  295. package/dist/services/redis.d.ts +1 -1
  296. package/dist/services/redis.d.ts.map +1 -1
  297. package/dist/services/scimCredentials.d.ts +46 -0
  298. package/dist/services/scimCredentials.d.ts.map +1 -0
  299. package/dist/services/scimCredentials.js +123 -0
  300. package/dist/services/scimCredentials.js.map +1 -0
  301. package/dist/services/scimLegacyMigration.d.ts +12 -0
  302. package/dist/services/scimLegacyMigration.d.ts.map +1 -0
  303. package/dist/services/scimLegacyMigration.js +44 -0
  304. package/dist/services/scimLegacyMigration.js.map +1 -0
  305. package/dist/services/secrets/awsKms.d.ts +2 -2
  306. package/dist/services/secrets/awsKms.d.ts.map +1 -1
  307. package/dist/services/secrets/awsKms.js +3 -5
  308. package/dist/services/secrets/awsKms.js.map +1 -1
  309. package/dist/services/secrets/azureKeyVault.d.ts.map +1 -1
  310. package/dist/services/secrets/database.d.ts.map +1 -1
  311. package/dist/services/secrets/database.js.map +1 -1
  312. package/dist/services/secrets/environment.d.ts.map +1 -1
  313. package/dist/services/secrets/environment.js.map +1 -1
  314. package/dist/services/secrets/index.d.ts.map +1 -1
  315. package/dist/services/secrets/password.d.ts.map +1 -1
  316. package/dist/services/secrets/password.js +0 -4
  317. package/dist/services/secrets/password.js.map +1 -1
  318. package/dist/services/secrets/provider.d.ts +2 -3
  319. package/dist/services/secrets/provider.d.ts.map +1 -1
  320. package/dist/services/secrets/vault.d.ts.map +1 -1
  321. package/dist/services/setup/configWriter.d.ts.map +1 -1
  322. package/dist/services/setup/configWriter.js.map +1 -1
  323. package/dist/services/ssoEndpointPolicy.d.ts +8 -0
  324. package/dist/services/ssoEndpointPolicy.d.ts.map +1 -0
  325. package/dist/services/ssoEndpointPolicy.js +136 -0
  326. package/dist/services/ssoEndpointPolicy.js.map +1 -0
  327. package/dist/services/stepUp.d.ts +35 -0
  328. package/dist/services/stepUp.d.ts.map +1 -0
  329. package/dist/services/stepUp.js +65 -0
  330. package/dist/services/stepUp.js.map +1 -0
  331. package/dist/services/tokens.d.ts +37 -11
  332. package/dist/services/tokens.d.ts.map +1 -1
  333. package/dist/services/tokens.js +75 -14
  334. package/dist/services/tokens.js.map +1 -1
  335. package/dist/services/totp.d.ts +46 -0
  336. package/dist/services/totp.d.ts.map +1 -1
  337. package/dist/services/totp.js +178 -41
  338. package/dist/services/totp.js.map +1 -1
  339. package/dist/services/users.d.ts +20 -12
  340. package/dist/services/users.d.ts.map +1 -1
  341. package/dist/services/users.js +24 -51
  342. package/dist/services/users.js.map +1 -1
  343. package/dist/services/webauthn.d.ts +8 -4
  344. package/dist/services/webauthn.d.ts.map +1 -1
  345. package/dist/services/webauthn.js +4 -4
  346. package/dist/services/webauthn.js.map +1 -1
  347. package/dist/services/webhooks.d.ts +20 -20
  348. package/dist/services/workflows/engine.d.ts +4 -2
  349. package/dist/services/workflows/engine.d.ts.map +1 -1
  350. package/dist/services/workflows/engine.js +181 -12
  351. package/dist/services/workflows/engine.js.map +1 -1
  352. package/dist/services/workflows/steps.d.ts +2 -0
  353. package/dist/services/workflows/steps.d.ts.map +1 -1
  354. package/dist/services/workflows/steps.js +8 -75
  355. package/dist/services/workflows/steps.js.map +1 -1
  356. package/dist/setup-server.js.map +1 -1
  357. package/dist/types.d.ts +33 -4
  358. package/dist/types.d.ts.map +1 -1
  359. package/dist/types.js +26 -2
  360. package/dist/types.js.map +1 -1
  361. package/package.json +26 -3
  362. package/dist/tests/errors.test.d.ts +0 -2
  363. package/dist/tests/errors.test.d.ts.map +0 -1
  364. package/dist/tests/errors.test.js +0 -64
  365. package/dist/tests/errors.test.js.map +0 -1
  366. package/dist/tests/events.test.d.ts +0 -2
  367. package/dist/tests/events.test.d.ts.map +0 -1
  368. package/dist/tests/events.test.js +0 -45
  369. package/dist/tests/events.test.js.map +0 -1
  370. package/dist/tests/featureFlags.test.d.ts +0 -2
  371. package/dist/tests/featureFlags.test.d.ts.map +0 -1
  372. package/dist/tests/featureFlags.test.js +0 -24
  373. package/dist/tests/featureFlags.test.js.map +0 -1
  374. package/dist/tests/integration/queue.test.d.ts +0 -2
  375. package/dist/tests/integration/queue.test.d.ts.map +0 -1
  376. package/dist/tests/integration/queue.test.js +0 -49
  377. package/dist/tests/integration/queue.test.js.map +0 -1
  378. package/dist/tests/plugins.test.d.ts +0 -2
  379. package/dist/tests/plugins.test.d.ts.map +0 -1
  380. package/dist/tests/plugins.test.js +0 -56
  381. package/dist/tests/plugins.test.js.map +0 -1
  382. package/dist/tests/result.test.d.ts +0 -2
  383. package/dist/tests/result.test.d.ts.map +0 -1
  384. package/dist/tests/result.test.js +0 -46
  385. package/dist/tests/result.test.js.map +0 -1
  386. package/dist/tests/setup/configWriter.test.d.ts +0 -2
  387. package/dist/tests/setup/configWriter.test.d.ts.map +0 -1
  388. package/dist/tests/setup/configWriter.test.js +0 -55
  389. package/dist/tests/setup/configWriter.test.js.map +0 -1
  390. package/dist/tests/setup/validation.test.d.ts +0 -2
  391. package/dist/tests/setup/validation.test.d.ts.map +0 -1
  392. package/dist/tests/setup/validation.test.js +0 -26
  393. package/dist/tests/setup/validation.test.js.map +0 -1
  394. package/dist/tests/smoke.test.d.ts +0 -2
  395. package/dist/tests/smoke.test.d.ts.map +0 -1
  396. package/dist/tests/smoke.test.js +0 -124
  397. package/dist/tests/smoke.test.js.map +0 -1
  398. package/src/cli.ts +0 -172
  399. package/src/config.ts +0 -143
  400. package/src/container.ts +0 -48
  401. package/src/db/index.ts +0 -53
  402. package/src/db/migrations/0000_skinny_ben_parker.sql +0 -553
  403. package/src/db/migrations/0001_brief_joseph.sql +0 -10
  404. package/src/db/migrations/0002_add_account_lockout.sql +0 -3
  405. package/src/db/migrations/0003_steep_rachel_grey.sql +0 -1
  406. package/src/db/migrations/0004_clever_bill_hollister.sql +0 -20
  407. package/src/db/migrations/0005_steep_the_call.sql +0 -2
  408. package/src/db/migrations/0006_ambitious_boomer.sql +0 -17
  409. package/src/db/migrations/0007_greedy_vindicator.sql +0 -40
  410. package/src/db/migrations/meta/0000_snapshot.json +0 -2964
  411. package/src/db/migrations/meta/0001_snapshot.json +0 -3031
  412. package/src/db/migrations/meta/0003_snapshot.json +0 -3051
  413. package/src/db/migrations/meta/_journal.json +0 -62
  414. package/src/db/schema.ts +0 -676
  415. package/src/db/seed.ts +0 -146
  416. package/src/di.ts +0 -81
  417. package/src/index.ts +0 -326
  418. package/src/lib/errors.ts +0 -139
  419. package/src/lib/result.ts +0 -44
  420. package/src/lib/webhookSignature.ts +0 -41
  421. package/src/plugins/appContext.ts +0 -76
  422. package/src/plugins/audit.ts +0 -42
  423. package/src/plugins/auth.ts +0 -230
  424. package/src/plugins/metrics.ts +0 -41
  425. package/src/plugins/mtls.ts +0 -94
  426. package/src/plugins/permissions.ts +0 -29
  427. package/src/plugins/rateLimit.ts +0 -133
  428. package/src/plugins/requestLogger.ts +0 -25
  429. package/src/plugins/tracing.ts +0 -22
  430. package/src/repositories/apiKey.ts +0 -158
  431. package/src/repositories/application.ts +0 -70
  432. package/src/repositories/audit.ts +0 -32
  433. package/src/repositories/index.ts +0 -9
  434. package/src/repositories/oidcConnection.ts +0 -111
  435. package/src/repositories/organization.ts +0 -167
  436. package/src/repositories/permission.ts +0 -153
  437. package/src/repositories/samlConnection.ts +0 -96
  438. package/src/repositories/session.ts +0 -86
  439. package/src/repositories/types.ts +0 -134
  440. package/src/repositories/user.ts +0 -161
  441. package/src/routes/admin/billing.ts +0 -48
  442. package/src/routes/admin/helpers.ts +0 -50
  443. package/src/routes/admin/index.ts +0 -16
  444. package/src/routes/admin/organizations.ts +0 -299
  445. package/src/routes/admin/permissions.ts +0 -80
  446. package/src/routes/admin/platform.ts +0 -335
  447. package/src/routes/admin/sso.ts +0 -138
  448. package/src/routes/admin/webhooks.ts +0 -73
  449. package/src/routes/admin.ts +0 -1
  450. package/src/routes/apiKeys.ts +0 -60
  451. package/src/routes/auth.ts +0 -214
  452. package/src/routes/authz.ts +0 -38
  453. package/src/routes/config.ts +0 -67
  454. package/src/routes/emailVerification.ts +0 -73
  455. package/src/routes/federation.ts +0 -156
  456. package/src/routes/helpers.ts +0 -17
  457. package/src/routes/magicLinks.ts +0 -107
  458. package/src/routes/oauth.ts +0 -167
  459. package/src/routes/oauth2.ts +0 -284
  460. package/src/routes/oidcEnterprise.ts +0 -166
  461. package/src/routes/password.ts +0 -90
  462. package/src/routes/profile.ts +0 -44
  463. package/src/routes/saml.ts +0 -209
  464. package/src/routes/scim.ts +0 -199
  465. package/src/routes/sdk.ts +0 -141
  466. package/src/routes/serviceAccounts.ts +0 -124
  467. package/src/routes/sessions.ts +0 -62
  468. package/src/routes/setup.ts +0 -315
  469. package/src/routes/smsOtp.ts +0 -67
  470. package/src/routes/totp.ts +0 -122
  471. package/src/routes/webauthn.ts +0 -147
  472. package/src/routes/workflows.ts +0 -157
  473. package/src/sdk/index.ts +0 -152
  474. package/src/sdk/types.ts +0 -54
  475. package/src/services/anomalyDetection.ts +0 -73
  476. package/src/services/application/authentication.ts +0 -75
  477. package/src/services/application/identity.ts +0 -56
  478. package/src/services/application/index.ts +0 -3
  479. package/src/services/application/organization.ts +0 -77
  480. package/src/services/applications.ts +0 -89
  481. package/src/services/audit.ts +0 -41
  482. package/src/services/auditExport.ts +0 -59
  483. package/src/services/billing.ts +0 -87
  484. package/src/services/cache.ts +0 -131
  485. package/src/services/configuration/profiles.ts +0 -115
  486. package/src/services/configuration.ts +0 -120
  487. package/src/services/connectors/google.ts +0 -92
  488. package/src/services/connectors/oidc.ts +0 -111
  489. package/src/services/connectors/registry.ts +0 -124
  490. package/src/services/connectors/types.ts +0 -38
  491. package/src/services/connectors/zitadel.ts +0 -77
  492. package/src/services/devices.ts +0 -76
  493. package/src/services/domain/authentication.ts +0 -279
  494. package/src/services/domain/authorization.ts +0 -49
  495. package/src/services/domain/identity.ts +0 -108
  496. package/src/services/domain/index.ts +0 -4
  497. package/src/services/domain/organization.ts +0 -114
  498. package/src/services/email.ts +0 -167
  499. package/src/services/emailVerification.ts +0 -75
  500. package/src/services/enterpriseSso.ts +0 -58
  501. package/src/services/events/bus.ts +0 -43
  502. package/src/services/events/subscribers/anomaly.ts +0 -13
  503. package/src/services/events/subscribers/auditLog.ts +0 -21
  504. package/src/services/events/subscribers/webhook.ts +0 -39
  505. package/src/services/events/subscribers/webhookDispatch.ts +0 -14
  506. package/src/services/events/types.ts +0 -106
  507. package/src/services/events/validate.ts +0 -118
  508. package/src/services/featureFlags.ts +0 -90
  509. package/src/services/features.ts +0 -22
  510. package/src/services/federation.ts +0 -30
  511. package/src/services/hibp.ts +0 -28
  512. package/src/services/ipControls.ts +0 -99
  513. package/src/services/magicLinks.ts +0 -51
  514. package/src/services/oauth2.ts +0 -216
  515. package/src/services/organizations.ts +0 -171
  516. package/src/services/permissions.ts +0 -146
  517. package/src/services/plugins/registry.ts +0 -242
  518. package/src/services/plugins/types.ts +0 -98
  519. package/src/services/queue/bullmq.ts +0 -104
  520. package/src/services/queue/inProcess.ts +0 -75
  521. package/src/services/queue/index.ts +0 -19
  522. package/src/services/queue/types.ts +0 -26
  523. package/src/services/redis.ts +0 -16
  524. package/src/services/secrets/awsKms.ts +0 -97
  525. package/src/services/secrets/azureKeyVault.ts +0 -171
  526. package/src/services/secrets/database.ts +0 -166
  527. package/src/services/secrets/environment.ts +0 -117
  528. package/src/services/secrets/index.ts +0 -50
  529. package/src/services/secrets/password.ts +0 -73
  530. package/src/services/secrets/provider.ts +0 -36
  531. package/src/services/secrets/vault.ts +0 -149
  532. package/src/services/secrets.ts +0 -2
  533. package/src/services/serviceAccounts.ts +0 -74
  534. package/src/services/setup/configWriter.ts +0 -200
  535. package/src/services/setup/diagnostics.ts +0 -76
  536. package/src/services/setup/token.ts +0 -42
  537. package/src/services/setup/types.ts +0 -40
  538. package/src/services/setup/validation.ts +0 -205
  539. package/src/services/sms.ts +0 -81
  540. package/src/services/smsOtp.ts +0 -74
  541. package/src/services/tokens.ts +0 -287
  542. package/src/services/totp.ts +0 -113
  543. package/src/services/users.ts +0 -239
  544. package/src/services/webauthn.ts +0 -193
  545. package/src/services/webhooks.ts +0 -190
  546. package/src/services/workflows/engine.ts +0 -125
  547. package/src/services/workflows/steps.ts +0 -129
  548. package/src/services/zitadel.ts +0 -277
  549. package/src/setup-server.ts +0 -71
  550. package/src/tests/errors.test.ts +0 -74
  551. package/src/tests/events.test.ts +0 -52
  552. package/src/tests/featureFlags.test.ts +0 -26
  553. package/src/tests/integration/queue.test.ts +0 -54
  554. package/src/tests/plugins.test.ts +0 -73
  555. package/src/tests/result.test.ts +0 -52
  556. package/src/tests/setup/configWriter.test.ts +0 -69
  557. package/src/tests/setup/validation.test.ts +0 -29
  558. package/src/tests/smoke.test.ts +0 -136
  559. package/src/types.ts +0 -70
package/src/lib/result.ts DELETED
@@ -1,44 +0,0 @@
1
- export interface KeystoneError {
2
- code: string;
3
- message: string;
4
- statusCode?: number;
5
- details?: Record<string, unknown>;
6
- }
7
-
8
- export type Result<T> =
9
- | { success: true; data: T; error?: undefined }
10
- | { success: false; data?: undefined; error: KeystoneError };
11
-
12
- export function ok<T>(data: T): Result<T> {
13
- return { success: true, data };
14
- }
15
-
16
- export function err<T>(error: KeystoneError): Result<T> {
17
- return { success: false, error };
18
- }
19
-
20
- export function errFromMessage<T>(
21
- code: string,
22
- message: string,
23
- statusCode?: number,
24
- details?: Record<string, unknown>
25
- ): Result<T> {
26
- return err({ code, message, statusCode, details });
27
- }
28
-
29
- export function mapResult<T, U>(result: Result<T>, fn: (data: T) => U): Result<U> {
30
- if (result.success) {
31
- return ok(fn(result.data));
32
- }
33
- return err(result.error);
34
- }
35
-
36
- export async function flatMapResult<T, U>(
37
- result: Result<T>,
38
- fn: (data: T) => Promise<Result<U>>
39
- ): Promise<Result<U>> {
40
- if (result.success) {
41
- return fn(result.data);
42
- }
43
- return err(result.error);
44
- }
@@ -1,41 +0,0 @@
1
- import crypto from "node:crypto";
2
-
3
- /**
4
- * Sign a webhook payload using HMAC-SHA256.
5
- * Returns a signature string in the format "t=<timestamp>,v1=<hex>".
6
- */
7
- export function signWebhookPayload(secret: string, payload: unknown): string {
8
- const timestamp = Math.floor(Date.now() / 1000);
9
- const body = JSON.stringify(payload);
10
- const signedPayload = `${timestamp}.${body}`;
11
- const signature = crypto.createHmac("sha256", secret).update(signedPayload).digest("hex");
12
- return `t=${timestamp},v1=${signature}`;
13
- }
14
-
15
- /**
16
- * Verify a webhook signature.
17
- * Returns true if the signature matches the payload and timestamp is within tolerance.
18
- */
19
- export function verifyWebhookPayload(
20
- secret: string,
21
- signatureHeader: string,
22
- payload: unknown,
23
- toleranceSeconds = 300
24
- ): boolean {
25
- const parts = signatureHeader.split(",").reduce<Record<string, string>>((acc, part) => {
26
- const [key, value] = part.split("=");
27
- if (key && value) acc[key.trim()] = value.trim();
28
- return acc;
29
- }, {});
30
-
31
- const timestamp = Number(parts.t);
32
- const signature = parts.v1;
33
- if (!timestamp || !signature) return false;
34
-
35
- const now = Math.floor(Date.now() / 1000);
36
- if (Math.abs(now - timestamp) > toleranceSeconds) return false;
37
-
38
- const body = JSON.stringify(payload);
39
- const expected = crypto.createHmac("sha256", secret).update(`${timestamp}.${body}`).digest("hex");
40
- return crypto.timingSafeEqual(Buffer.from(signature, "hex"), Buffer.from(expected, "hex"));
41
- }
@@ -1,76 +0,0 @@
1
- import fp from "fastify-plugin";
2
- import type { FastifyInstance, FastifyRequest } from "fastify";
3
- import { eq, and, arrayContains } from "drizzle-orm";
4
- import { db } from "../db/index.js";
5
- import { applications, organizations, orgMemberships } from "../db/schema.js";
6
-
7
- export default fp(async function appContextPlugin(app: FastifyInstance) {
8
- app.addHook("onRequest", async (request: FastifyRequest) => {
9
- // Ensure every request has a fresh state object.
10
- request.state = {};
11
-
12
- const clientId = extractClientId(request);
13
- const origin = request.headers.origin;
14
-
15
- const appRecord = clientId
16
- ? await findApplicationByClientId(clientId)
17
- : origin
18
- ? await findApplicationByOrigin(origin)
19
- : undefined;
20
-
21
- if (!appRecord) return;
22
-
23
- request.state.app = appRecord;
24
- request.state.org = appRecord.organization;
25
-
26
- if (request.user) {
27
- const [membership] = await db
28
- .select()
29
- .from(orgMemberships)
30
- .where(
31
- and(
32
- eq(orgMemberships.orgId, appRecord.organization.id),
33
- eq(orgMemberships.userId, request.user.id)
34
- )
35
- )
36
- .limit(1);
37
- if (membership) {
38
- request.state.membership = membership;
39
- }
40
- }
41
- });
42
- });
43
-
44
- function extractClientId(request: FastifyRequest): string | undefined {
45
- const header = request.headers["x-app-client-id"];
46
- if (typeof header === "string" && header) return header;
47
-
48
- const query = (request.query as Record<string, string | undefined>).client_id;
49
- if (query) return query;
50
-
51
- return undefined;
52
- }
53
-
54
- async function findApplicationByClientId(clientId: string) {
55
- const [row] = await db
56
- .select()
57
- .from(applications)
58
- .where(and(eq(applications.clientId, clientId), eq(applications.isActive, true)))
59
- .innerJoin(organizations, eq(applications.orgId, organizations.id))
60
- .limit(1);
61
-
62
- if (!row) return undefined;
63
- return { ...row.applications, organization: row.organizations };
64
- }
65
-
66
- async function findApplicationByOrigin(origin: string) {
67
- const [row] = await db
68
- .select()
69
- .from(applications)
70
- .where(and(arrayContains(applications.allowedOrigins, [origin]), eq(applications.isActive, true)))
71
- .innerJoin(organizations, eq(applications.orgId, organizations.id))
72
- .limit(1);
73
-
74
- if (!row) return undefined;
75
- return { ...row.applications, organization: row.organizations };
76
- }
@@ -1,42 +0,0 @@
1
- import fp from "fastify-plugin";
2
- import type { FastifyInstance, FastifyRequest } from "fastify";
3
- import { audit, type AuditEvent } from "../services/audit.js";
4
- import { emit } from "../services/events/bus.js";
5
- import type { EventPayload } from "../services/events/types.js";
6
-
7
- declare module "fastify" {
8
- interface FastifyRequest {
9
- audit: (event: AuditEvent, metadata?: Record<string, unknown>) => Promise<void>;
10
- emitEvent: (event: string, metadata?: Record<string, unknown>) => Promise<void>;
11
- }
12
- }
13
-
14
- function buildPayload(request: FastifyRequest, metadata?: Record<string, unknown>): EventPayload {
15
- return {
16
- userId: request.user?.id,
17
- orgId: request.state?.org?.id,
18
- appId: request.state?.app?.id,
19
- requestId: request.id,
20
- ip: request.ip,
21
- userAgent: request.headers["user-agent"],
22
- metadata,
23
- };
24
- }
25
-
26
- export default fp(async function auditPlugin(app: FastifyInstance) {
27
- app.decorateRequest("audit", async function (
28
- this: FastifyRequest,
29
- event: AuditEvent,
30
- metadata?: Record<string, unknown>
31
- ) {
32
- await audit({ ...buildPayload(this, metadata), event });
33
- });
34
-
35
- app.decorateRequest("emitEvent", async function (
36
- this: FastifyRequest,
37
- event: string,
38
- metadata?: Record<string, unknown>
39
- ) {
40
- await emit({ type: event, payload: buildPayload(this, metadata) });
41
- });
42
- });
@@ -1,230 +0,0 @@
1
- import fp from "fastify-plugin";
2
- import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
3
- import { eq, and, gt, isNull } from "drizzle-orm";
4
- import { config } from "../config.js";
5
- import { db } from "../db/index.js";
6
- import { apiKeys, users, serviceAccounts, type User } from "../db/schema.js";
7
- import { verifyAccessToken, hashApiKey } from "../services/tokens.js";
8
- import type { TokenClaims } from "../types.js";
9
-
10
- declare module "fastify" {
11
- interface FastifyInstance {
12
- authenticate: (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
13
- authenticateOrApiKey: (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
14
- requireScopes: (...scopes: string[]) => (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
15
- }
16
-
17
- interface FastifyRequest {
18
- serviceAccount?: typeof serviceAccounts.$inferSelect;
19
- apiKeyScopes?: string[];
20
- }
21
- }
22
-
23
- const DEFAULT_ACCESS_COOKIE = config.COOKIE_NAME;
24
- const DEFAULT_REFRESH_COOKIE = `${config.COOKIE_NAME}-refresh`;
25
-
26
- export function accessCookieName(clientId?: string): string {
27
- return clientId ? `app-${clientId}-session` : DEFAULT_ACCESS_COOKIE;
28
- }
29
-
30
- export function refreshCookieName(clientId?: string): string {
31
- return clientId ? `app-${clientId}-session-refresh` : DEFAULT_REFRESH_COOKIE;
32
- }
33
-
34
- function cookieOptions(): {
35
- path: string;
36
- httpOnly: boolean;
37
- secure: boolean;
38
- sameSite: "strict" | "lax" | "none";
39
- domain: string | undefined;
40
- } {
41
- const sameSite = (config.COOKIE_SAME_SITE as "strict" | "lax" | "none") || (config.NODE_ENV === "production" ? "strict" : "lax");
42
- return {
43
- path: "/",
44
- httpOnly: true,
45
- secure: config.COOKIE_SECURE,
46
- sameSite,
47
- domain: config.COOKIE_DOMAIN || undefined,
48
- };
49
- }
50
-
51
- export function setSessionCookies(
52
- reply: FastifyReply,
53
- accessToken: string,
54
- refreshToken: string,
55
- clientId?: string
56
- ): void {
57
- const opts = cookieOptions();
58
-
59
- reply.setCookie(accessCookieName(clientId), accessToken, {
60
- ...opts,
61
- maxAge: config.ACCESS_TOKEN_TTL_SECONDS,
62
- });
63
- reply.setCookie(refreshCookieName(clientId), refreshToken, {
64
- ...opts,
65
- maxAge: config.REFRESH_TOKEN_TTL_SECONDS,
66
- });
67
- }
68
-
69
- export function clearSessionCookies(reply: FastifyReply, clientId?: string): void {
70
- const opts = cookieOptions();
71
- reply.clearCookie(accessCookieName(clientId), opts);
72
- reply.clearCookie(refreshCookieName(clientId), opts);
73
- }
74
-
75
- export function getRefreshToken(request: FastifyRequest, clientId?: string): string | undefined {
76
- return request.cookies[refreshCookieName(clientId)];
77
- }
78
-
79
- async function resolveUserFromClaims(claims: TokenClaims) {
80
- const [user] = await db.select().from(users).where(eq(users.id, claims.sub)).limit(1);
81
- return user;
82
- }
83
-
84
- async function resolveApiKeyRecord(key: string) {
85
- const hash = hashApiKey(key);
86
- const [keyRecord] = await db
87
- .select()
88
- .from(apiKeys)
89
- .where(and(eq(apiKeys.keyHash, hash), isNull(apiKeys.revokedAt)))
90
- .limit(1);
91
- return keyRecord;
92
- }
93
-
94
- async function resolveUserFromApiKey(key: string): Promise<{ user: User; scopes: string[] } | undefined> {
95
- const keyRecord = await resolveApiKeyRecord(key);
96
- if (!keyRecord) return undefined;
97
- if (keyRecord.expiresAt && keyRecord.expiresAt < new Date()) return undefined;
98
-
99
- await db.update(apiKeys).set({ lastUsedAt: new Date() }).where(eq(apiKeys.id, keyRecord.id));
100
-
101
- if (keyRecord.userId) {
102
- const [user] = await db.select().from(users).where(eq(users.id, keyRecord.userId)).limit(1);
103
- if (!user) return undefined;
104
- return { user, scopes: keyRecord.scopes ?? [] };
105
- }
106
-
107
- return undefined;
108
- }
109
-
110
- function extractAccessToken(request: FastifyRequest): string | undefined {
111
- // Prefer the app-specific cookie if an app context is present.
112
- const appClientId = request.state?.app?.clientId;
113
- const appCookie = appClientId ? request.cookies[accessCookieName(appClientId)] : undefined;
114
- if (appCookie) return appCookie;
115
-
116
- const defaultCookie = request.cookies[DEFAULT_ACCESS_COOKIE];
117
- if (defaultCookie) return defaultCookie;
118
-
119
- const header = request.headers.authorization;
120
- if (header?.startsWith("Bearer ")) return header.slice(7);
121
- return undefined;
122
- }
123
-
124
- export default fp(async function authPlugin(app: FastifyInstance) {
125
- app.decorate("authenticate", async function authenticate(request, reply) {
126
- const token = extractAccessToken(request);
127
- if (!token) {
128
- return reply.status(401).send({ error: "Unauthorized" });
129
- }
130
- try {
131
- const claims = await verifyAccessToken(token);
132
- const user = await resolveUserFromClaims(claims);
133
- if (!user) {
134
- return reply.status(401).send({ error: "User not found" });
135
- }
136
- request.user = user;
137
- } catch {
138
- return reply.status(401).send({ error: "Invalid token" });
139
- }
140
- });
141
-
142
- app.decorate("authenticateOrApiKey", async function authenticateOrApiKey(request, reply) {
143
- const token = extractAccessToken(request);
144
- if (!token) {
145
- return reply.status(401).send({ error: "Unauthorized" });
146
- }
147
-
148
- try {
149
- const claims = await verifyAccessToken(token);
150
- const user = await resolveUserFromClaims(claims);
151
- if (!user) {
152
- return reply.status(401).send({ error: "User not found" });
153
- }
154
- request.user = user;
155
- return;
156
- } catch {
157
- // Not a valid access token — try API key.
158
- }
159
-
160
- const apiKeyUser = await resolveUserFromApiKey(token);
161
- if (apiKeyUser) {
162
- request.user = apiKeyUser.user;
163
- request.apiKeyScopes = apiKeyUser.scopes;
164
- return;
165
- }
166
-
167
- const serviceAccount = await resolveServiceAccountFromApiKey(token);
168
- if (serviceAccount) {
169
- request.serviceAccount = serviceAccount;
170
- request.apiKeyScopes = ["api:read", "api:write", "service_account"];
171
- // Synthesize a user so existing routes that expect request.user keep working.
172
- request.user = {
173
- id: `sa:${serviceAccount.id}`,
174
- email: `service-account@${serviceAccount.id}.internal`,
175
- username: `sa-${serviceAccount.id.slice(0, 8)}`,
176
- name: serviceAccount.name,
177
- avatarUrl: null,
178
- emailVerified: true,
179
- plan: "enterprise",
180
- role: "service_account",
181
- provider: "api_key",
182
- zitadelUserId: null,
183
- defaultOrgId: serviceAccount.orgId,
184
- phoneNumber: null,
185
- phoneVerified: false,
186
- totpSecret: null,
187
- totpEnabled: false,
188
- totpVerifiedAt: null,
189
- createdAt: serviceAccount.createdAt,
190
- updatedAt: serviceAccount.updatedAt,
191
- } as User;
192
- return;
193
- }
194
-
195
- return reply.status(401).send({ error: "Invalid token or API key" });
196
- });
197
-
198
- app.decorate("requireScopes", function requireScopes(...required: string[]) {
199
- return async function scopeCheck(request: FastifyRequest, reply: FastifyReply) {
200
- // Session-based authentication has full scope access.
201
- if (!request.apiKeyScopes) return;
202
- const scopes = request.apiKeyScopes;
203
- const hasAll = required.every((scope) => scopes.includes(scope) || scopes.includes("service_account"));
204
- if (!hasAll) {
205
- return reply.status(403).send({ error: "Insufficient API key scope", required });
206
- }
207
- };
208
- });
209
- });
210
-
211
- async function resolveServiceAccountFromApiKey(key: string) {
212
- const hash = hashApiKey(key);
213
- const [keyRecord] = await db
214
- .select()
215
- .from(apiKeys)
216
- .where(and(eq(apiKeys.keyHash, hash), isNull(apiKeys.revokedAt)))
217
- .limit(1);
218
-
219
- if (!keyRecord) return undefined;
220
- if (keyRecord.expiresAt && keyRecord.expiresAt < new Date()) return undefined;
221
- if (!keyRecord.serviceAccountId) return undefined;
222
-
223
- await db.update(apiKeys).set({ lastUsedAt: new Date() }).where(eq(apiKeys.id, keyRecord.id));
224
- const [account] = await db
225
- .select()
226
- .from(serviceAccounts)
227
- .where(and(eq(serviceAccounts.id, keyRecord.serviceAccountId), eq(serviceAccounts.isActive, true)))
228
- .limit(1);
229
- return account;
230
- }
@@ -1,41 +0,0 @@
1
- import fp from "fastify-plugin";
2
- import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
3
- import { register, Counter, Histogram } from "prom-client";
4
-
5
- export const httpRequestsTotal = new Counter({
6
- name: "keystone_http_requests_total",
7
- help: "Total HTTP requests",
8
- labelNames: ["method", "route", "status_code"],
9
- });
10
-
11
- export const httpRequestDurationSeconds = new Histogram({
12
- name: "keystone_http_request_duration_seconds",
13
- help: "HTTP request duration in seconds",
14
- labelNames: ["method", "route", "status_code"],
15
- buckets: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10],
16
- });
17
-
18
- export const failedLoginsTotal = new Counter({
19
- name: "keystone_failed_logins_total",
20
- help: "Total failed login attempts",
21
- labelNames: ["reason"],
22
- });
23
-
24
- export default fp(async function metricsPlugin(app: FastifyInstance) {
25
- app.addHook("onResponse", async (request: FastifyRequest, reply: FastifyReply) => {
26
- const route = (request as unknown as { routeOptions?: { url?: string } }).routeOptions?.url || request.url;
27
- const labels = {
28
- method: request.method,
29
- route,
30
- status_code: String(reply.statusCode),
31
- };
32
- httpRequestsTotal.inc(labels);
33
- const elapsedMs = (reply as unknown as { elapsedTime?: number }).elapsedTime ?? 0;
34
- httpRequestDurationSeconds.observe(labels, elapsedMs / 1000);
35
- });
36
-
37
- app.get("/metrics", async (_request: FastifyRequest, reply: FastifyReply) => {
38
- reply.header("Content-Type", register.contentType);
39
- return register.metrics();
40
- });
41
- });
@@ -1,94 +0,0 @@
1
- import fp from "fastify-plugin";
2
- import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
3
- import { eq } from "drizzle-orm";
4
- import { db } from "../db/index.js";
5
- import { serviceAccounts } from "../db/schema.js";
6
-
7
- /**
8
- * mTLS authentication plugin.
9
- *
10
- * In production, terminate TLS at a reverse proxy (nginx, envoy, AWS ALB, etc.)
11
- * that validates the client certificate and forwards the certificate fingerprint
12
- * or subject in a trusted header. This plugin reads that header and maps
13
- * certificates to service accounts.
14
- *
15
- * Headers read:
16
- * - x-client-cert-fingerprint: SHA-256 fingerprint of the client certificate
17
- * - x-forwarded-client-cert: PEM-encoded client certificate or DN subject
18
- * - x-service-account-id: Optional explicit service account ID (for non-mTLS fallback)
19
- */
20
-
21
- const MTLS_HEADER = "x-forwarded-client-cert";
22
- const MTLS_FINGERPRINT_HEADER = "x-client-cert-fingerprint";
23
- const SERVICE_ACCOUNT_ID_HEADER = "x-service-account-id";
24
-
25
- declare module "fastify" {
26
- interface FastifyInstance {
27
- requireMTLS: (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
28
- }
29
- }
30
-
31
- export function extractClientCert(request: FastifyRequest): { fingerprint?: string; subject?: string } {
32
- const fingerprint = request.headers[MTLS_FINGERPRINT_HEADER];
33
- const cert = request.headers[MTLS_HEADER];
34
- return {
35
- fingerprint: typeof fingerprint === "string" ? fingerprint : undefined,
36
- subject: typeof cert === "string" ? cert : undefined,
37
- };
38
- }
39
-
40
- async function resolveServiceAccount(request: FastifyRequest): Promise<typeof serviceAccounts.$inferSelect | undefined> {
41
- const explicitId = request.headers[SERVICE_ACCOUNT_ID_HEADER];
42
- if (typeof explicitId === "string" && explicitId) {
43
- const [sa] = await db
44
- .select()
45
- .from(serviceAccounts)
46
- .where(eq(serviceAccounts.id, explicitId))
47
- .limit(1);
48
- if (sa?.isActive) {
49
- return sa;
50
- }
51
- }
52
-
53
- const { fingerprint, subject } = extractClientCert(request);
54
- if (!fingerprint && !subject) return undefined;
55
-
56
- // Look up service accounts by name matching the fingerprint or subject.
57
- // In a production system, you would store the certificate fingerprint in
58
- // the service_accounts table and query by it directly.
59
- const [sa] = await db
60
- .select()
61
- .from(serviceAccounts)
62
- .where(eq(serviceAccounts.name, fingerprint || subject || ""))
63
- .limit(1);
64
-
65
- if (sa?.isActive) {
66
- return sa;
67
- }
68
-
69
- return undefined;
70
- }
71
-
72
- export function requireMTLS() {
73
- return async function (request: FastifyRequest, reply: FastifyReply) {
74
- const { fingerprint, subject } = extractClientCert(request);
75
- const explicitId = request.headers[SERVICE_ACCOUNT_ID_HEADER];
76
-
77
- if (!fingerprint && !subject && !explicitId) {
78
- return reply.status(401).send({ error: "Client certificate required" });
79
- }
80
-
81
- const serviceAccount = await resolveServiceAccount(request);
82
- if (!serviceAccount) {
83
- request.log.warn({ fingerprint, subject }, "mTLS: no matching service account found");
84
- return reply.status(403).send({ error: "Client certificate not mapped to a service account" });
85
- }
86
-
87
- request.serviceAccount = serviceAccount;
88
- request.log.debug({ serviceAccountId: serviceAccount.id }, "mTLS: service account authenticated");
89
- };
90
- }
91
-
92
- export default fp(async function mtlsPlugin(app: FastifyInstance) {
93
- app.decorate("requireMTLS", requireMTLS());
94
- });
@@ -1,29 +0,0 @@
1
- import fp from "fastify-plugin";
2
- import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
3
- import { requirePermission, hasPermission, type PermissionInput } from "../services/permissions.js";
4
-
5
- declare module "fastify" {
6
- interface FastifyInstance {
7
- requirePermission: (resource: string, action: string) => (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
8
- }
9
- }
10
-
11
- export default fp(async function permissionsPlugin(app: FastifyInstance) {
12
- app.decorate(
13
- "requirePermission",
14
- function (resource: string, action: string) {
15
- return async function (request: FastifyRequest, reply: FastifyReply) {
16
- const membership = request.state?.membership;
17
- if (!membership) {
18
- return reply.status(403).send({ error: "Organization membership required" });
19
- }
20
- try {
21
- await requirePermission(membership.role, resource, action);
22
- } catch (err) {
23
- const message = err instanceof Error ? err.message : "Forbidden";
24
- return reply.status(403).send({ error: message });
25
- }
26
- };
27
- }
28
- );
29
- });