alepha 0.15.4 → 0.15.5

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 (282) hide show
  1. package/README.md +26 -11
  2. package/dist/api/audits/index.d.ts +3 -3
  3. package/dist/api/audits/index.js +3 -3
  4. package/dist/api/audits/index.js.map +1 -1
  5. package/dist/api/files/index.d.ts +3 -3
  6. package/dist/api/files/index.js +3 -3
  7. package/dist/api/files/index.js.map +1 -1
  8. package/dist/api/jobs/index.d.ts +47 -4
  9. package/dist/api/jobs/index.d.ts.map +1 -1
  10. package/dist/api/jobs/index.js +100 -5
  11. package/dist/api/jobs/index.js.map +1 -1
  12. package/dist/api/keys/index.d.ts +3 -3
  13. package/dist/api/keys/index.js +3 -3
  14. package/dist/api/keys/index.js.map +1 -1
  15. package/dist/api/notifications/index.d.ts +3 -3
  16. package/dist/api/notifications/index.js +3 -3
  17. package/dist/api/notifications/index.js.map +1 -1
  18. package/dist/api/parameters/index.d.ts +263 -263
  19. package/dist/api/parameters/index.d.ts.map +1 -1
  20. package/dist/api/parameters/index.js +31 -30
  21. package/dist/api/parameters/index.js.map +1 -1
  22. package/dist/api/users/index.d.ts +373 -67
  23. package/dist/api/users/index.d.ts.map +1 -1
  24. package/dist/api/users/index.js +273 -72
  25. package/dist/api/users/index.js.map +1 -1
  26. package/dist/api/verifications/index.d.ts +3 -3
  27. package/dist/api/verifications/index.js +3 -3
  28. package/dist/api/verifications/index.js.map +1 -1
  29. package/dist/batch/index.d.ts +7 -7
  30. package/dist/batch/index.js +3 -3
  31. package/dist/batch/index.js.map +1 -1
  32. package/dist/bucket/index.d.ts +3 -3
  33. package/dist/bucket/index.js +6 -6
  34. package/dist/bucket/index.js.map +1 -1
  35. package/dist/cache/core/index.d.ts +3 -3
  36. package/dist/cache/core/index.js +3 -3
  37. package/dist/cache/core/index.js.map +1 -1
  38. package/dist/cli/index.d.ts +5607 -20
  39. package/dist/cli/index.d.ts.map +1 -1
  40. package/dist/cli/index.js +103 -89
  41. package/dist/cli/index.js.map +1 -1
  42. package/dist/command/index.d.ts +11 -4
  43. package/dist/command/index.d.ts.map +1 -1
  44. package/dist/command/index.js +8 -6
  45. package/dist/command/index.js.map +1 -1
  46. package/dist/core/index.browser.js.map +1 -1
  47. package/dist/core/index.d.ts +4 -8
  48. package/dist/core/index.d.ts.map +1 -1
  49. package/dist/core/index.js +3 -3
  50. package/dist/core/index.js.map +1 -1
  51. package/dist/core/index.native.js.map +1 -1
  52. package/dist/datetime/index.d.ts +3 -3
  53. package/dist/datetime/index.js +3 -3
  54. package/dist/datetime/index.js.map +1 -1
  55. package/dist/email/index.d.ts +3 -3
  56. package/dist/email/index.js +8 -8
  57. package/dist/email/index.js.map +1 -1
  58. package/dist/fake/index.d.ts +3 -3
  59. package/dist/fake/index.js +3 -3
  60. package/dist/fake/index.js.map +1 -1
  61. package/dist/lock/core/index.d.ts +3 -3
  62. package/dist/lock/core/index.js +3 -3
  63. package/dist/lock/core/index.js.map +1 -1
  64. package/dist/logger/index.d.ts +3 -3
  65. package/dist/logger/index.js +6 -3
  66. package/dist/logger/index.js.map +1 -1
  67. package/dist/mcp/index.d.ts +3 -3
  68. package/dist/mcp/index.js +3 -3
  69. package/dist/mcp/index.js.map +1 -1
  70. package/dist/orm/index.d.ts +12 -12
  71. package/dist/orm/index.js +4 -4
  72. package/dist/orm/index.js.map +1 -1
  73. package/dist/queue/core/index.d.ts +3 -3
  74. package/dist/queue/core/index.js +3 -3
  75. package/dist/queue/core/index.js.map +1 -1
  76. package/dist/react/auth/index.d.ts +3 -3
  77. package/dist/react/auth/index.js +3 -3
  78. package/dist/react/auth/index.js.map +1 -1
  79. package/dist/react/core/index.d.ts +3 -3
  80. package/dist/react/core/index.js +3 -3
  81. package/dist/react/core/index.js.map +1 -1
  82. package/dist/react/form/index.d.ts +3 -3
  83. package/dist/react/form/index.js +3 -3
  84. package/dist/react/form/index.js.map +1 -1
  85. package/dist/react/head/index.d.ts +3 -3
  86. package/dist/react/head/index.js +3 -3
  87. package/dist/react/head/index.js.map +1 -1
  88. package/dist/react/i18n/index.d.ts +3 -3
  89. package/dist/react/i18n/index.js +3 -3
  90. package/dist/react/i18n/index.js.map +1 -1
  91. package/dist/react/intro/index.css +337 -0
  92. package/dist/react/intro/index.css.map +1 -0
  93. package/dist/react/intro/index.d.ts +10 -0
  94. package/dist/react/intro/index.d.ts.map +1 -0
  95. package/dist/react/intro/index.js +222 -0
  96. package/dist/react/intro/index.js.map +1 -0
  97. package/dist/react/router/index.browser.js +2 -2
  98. package/dist/react/router/index.browser.js.map +1 -1
  99. package/dist/react/router/index.d.ts +1 -1
  100. package/dist/react/router/index.d.ts.map +1 -1
  101. package/dist/react/router/index.js +5 -5
  102. package/dist/react/router/index.js.map +1 -1
  103. package/dist/redis/index.d.ts +17 -17
  104. package/dist/redis/index.js +3 -3
  105. package/dist/redis/index.js.map +1 -1
  106. package/dist/retry/index.d.ts +3 -3
  107. package/dist/retry/index.js +3 -3
  108. package/dist/retry/index.js.map +1 -1
  109. package/dist/scheduler/index.d.ts +3 -3
  110. package/dist/scheduler/index.js +3 -3
  111. package/dist/scheduler/index.js.map +1 -1
  112. package/dist/security/index.d.ts +3 -3
  113. package/dist/security/index.js +5 -5
  114. package/dist/security/index.js.map +1 -1
  115. package/dist/server/auth/index.d.ts +3 -3
  116. package/dist/server/auth/index.js +3 -3
  117. package/dist/server/auth/index.js.map +1 -1
  118. package/dist/server/cache/index.d.ts +3 -3
  119. package/dist/server/cache/index.js +3 -3
  120. package/dist/server/cache/index.js.map +1 -1
  121. package/dist/server/compress/index.d.ts +3 -3
  122. package/dist/server/compress/index.js +3 -3
  123. package/dist/server/compress/index.js.map +1 -1
  124. package/dist/server/cookies/index.d.ts +3 -3
  125. package/dist/server/cookies/index.js +3 -3
  126. package/dist/server/cookies/index.js.map +1 -1
  127. package/dist/server/core/index.d.ts +5 -16
  128. package/dist/server/core/index.d.ts.map +1 -1
  129. package/dist/server/core/index.js +13 -29
  130. package/dist/server/core/index.js.map +1 -1
  131. package/dist/server/cors/index.d.ts +3 -3
  132. package/dist/server/cors/index.js +3 -3
  133. package/dist/server/cors/index.js.map +1 -1
  134. package/dist/server/health/index.d.ts +20 -20
  135. package/dist/server/health/index.js +3 -3
  136. package/dist/server/health/index.js.map +1 -1
  137. package/dist/server/helmet/index.d.ts +3 -3
  138. package/dist/server/helmet/index.js +3 -3
  139. package/dist/server/helmet/index.js.map +1 -1
  140. package/dist/server/links/index.d.ts +42 -42
  141. package/dist/server/links/index.d.ts.map +1 -1
  142. package/dist/server/links/index.js +3 -3
  143. package/dist/server/links/index.js.map +1 -1
  144. package/dist/server/metrics/index.d.ts +3 -3
  145. package/dist/server/metrics/index.js +3 -3
  146. package/dist/server/metrics/index.js.map +1 -1
  147. package/dist/server/multipart/index.d.ts +3 -3
  148. package/dist/server/multipart/index.js +3 -3
  149. package/dist/server/multipart/index.js.map +1 -1
  150. package/dist/server/proxy/index.d.ts +3 -3
  151. package/dist/server/proxy/index.js +3 -3
  152. package/dist/server/proxy/index.js.map +1 -1
  153. package/dist/server/rate-limit/index.d.ts +3 -3
  154. package/dist/server/rate-limit/index.js +3 -3
  155. package/dist/server/rate-limit/index.js.map +1 -1
  156. package/dist/server/static/index.d.ts +3 -3
  157. package/dist/server/static/index.js +6 -6
  158. package/dist/server/static/index.js.map +1 -1
  159. package/dist/server/swagger/index.d.ts +3 -3
  160. package/dist/server/swagger/index.js +6 -6
  161. package/dist/server/swagger/index.js.map +1 -1
  162. package/dist/sms/index.d.ts +3 -3
  163. package/dist/sms/index.js +6 -6
  164. package/dist/sms/index.js.map +1 -1
  165. package/dist/system/index.d.ts +3 -3
  166. package/dist/system/index.js +3 -3
  167. package/dist/system/index.js.map +1 -1
  168. package/dist/thread/index.d.ts +3 -3
  169. package/dist/thread/index.js +3 -3
  170. package/dist/thread/index.js.map +1 -1
  171. package/dist/topic/core/index.d.ts +3 -3
  172. package/dist/topic/core/index.js +3 -3
  173. package/dist/topic/core/index.js.map +1 -1
  174. package/dist/vite/index.d.ts +6284 -3
  175. package/dist/vite/index.d.ts.map +1 -1
  176. package/dist/websocket/index.d.ts +3 -3
  177. package/dist/websocket/index.js +3 -3
  178. package/dist/websocket/index.js.map +1 -1
  179. package/package.json +7 -2
  180. package/src/api/audits/index.ts +3 -3
  181. package/src/api/files/index.ts +3 -3
  182. package/src/api/jobs/controllers/AdminJobController.ts +15 -2
  183. package/src/api/jobs/index.ts +4 -3
  184. package/src/api/jobs/services/JobAudits.spec.ts +89 -0
  185. package/src/api/jobs/services/JobAudits.ts +101 -0
  186. package/src/api/keys/index.ts +3 -3
  187. package/src/api/notifications/index.ts +3 -3
  188. package/src/api/parameters/index.ts +5 -3
  189. package/src/api/users/__tests__/ApiKeys-integration.spec.ts +1 -1
  190. package/src/api/users/__tests__/ApiKeys.spec.ts +1 -1
  191. package/src/api/users/__tests__/EmailVerification.spec.ts +16 -1
  192. package/src/api/users/__tests__/PasswordReset.spec.ts +11 -0
  193. package/src/api/users/atoms/realmAuthSettingsAtom.ts +10 -0
  194. package/src/api/users/index.ts +8 -9
  195. package/src/api/users/primitives/$realm.ts +117 -19
  196. package/src/api/users/providers/RealmProvider.ts +15 -7
  197. package/src/api/users/services/CredentialService.spec.ts +11 -0
  198. package/src/api/users/services/CredentialService.ts +47 -24
  199. package/src/api/users/services/IdentityService.ts +12 -4
  200. package/src/api/users/services/RegistrationService.spec.ts +11 -0
  201. package/src/api/users/services/RegistrationService.ts +33 -12
  202. package/src/api/users/services/SessionService.ts +83 -12
  203. package/src/api/users/services/UserAudits.ts +47 -0
  204. package/src/api/users/services/UserFiles.ts +19 -0
  205. package/src/api/users/services/UserJobs.spec.ts +107 -0
  206. package/src/api/users/services/UserJobs.ts +62 -0
  207. package/src/api/users/services/UserParameters.ts +23 -0
  208. package/src/api/users/services/UserService.ts +34 -17
  209. package/src/api/verifications/index.ts +3 -3
  210. package/src/batch/index.ts +3 -3
  211. package/src/bucket/index.ts +3 -3
  212. package/src/cache/core/index.ts +3 -3
  213. package/src/cli/commands/db.ts +9 -0
  214. package/src/cli/commands/init.spec.ts +2 -17
  215. package/src/cli/commands/init.ts +37 -1
  216. package/src/cli/providers/ViteDevServerProvider.ts +5 -2
  217. package/src/cli/services/AlephaCliUtils.ts +17 -0
  218. package/src/cli/services/PackageManagerUtils.ts +15 -1
  219. package/src/cli/services/ProjectScaffolder.ts +8 -13
  220. package/src/cli/templates/agentMd.ts +2 -25
  221. package/src/cli/templates/apiAppSecurityTs.ts +37 -2
  222. package/src/cli/templates/mainCss.ts +2 -32
  223. package/src/cli/templates/webAppRouterTs.ts +5 -5
  224. package/src/cli/templates/webHomeComponentTsx.ts +10 -0
  225. package/src/command/helpers/Runner.ts +14 -1
  226. package/src/command/index.ts +3 -3
  227. package/src/core/helpers/primitive.ts +0 -5
  228. package/src/core/index.ts +3 -3
  229. package/src/datetime/index.ts +3 -3
  230. package/src/email/index.ts +3 -3
  231. package/src/email/providers/LocalEmailProvider.ts +2 -2
  232. package/src/fake/index.ts +3 -3
  233. package/src/lock/core/index.ts +3 -3
  234. package/src/logger/index.ts +3 -3
  235. package/src/logger/providers/PrettyFormatterProvider.ts +7 -0
  236. package/src/mcp/index.ts +3 -3
  237. package/src/orm/index.ts +3 -3
  238. package/src/orm/providers/drivers/NodeSqliteProvider.ts +1 -1
  239. package/src/queue/core/index.ts +3 -3
  240. package/src/react/auth/index.ts +3 -3
  241. package/src/react/core/index.ts +3 -3
  242. package/src/react/form/index.ts +3 -3
  243. package/src/react/head/index.ts +3 -3
  244. package/src/react/i18n/index.ts +3 -3
  245. package/src/react/intro/components/GettingStarted.css +334 -0
  246. package/src/react/intro/components/GettingStarted.tsx +276 -0
  247. package/src/react/intro/index.ts +1 -0
  248. package/src/react/router/index.browser.ts +2 -0
  249. package/src/react/router/index.ts +2 -0
  250. package/src/redis/index.ts +3 -3
  251. package/src/retry/index.ts +3 -3
  252. package/src/router/index.ts +3 -3
  253. package/src/scheduler/index.ts +3 -3
  254. package/src/security/index.ts +3 -3
  255. package/src/security/providers/JwtProvider.ts +2 -2
  256. package/src/server/auth/index.ts +3 -3
  257. package/src/server/cache/index.ts +3 -3
  258. package/src/server/compress/index.ts +3 -3
  259. package/src/server/cookies/index.ts +3 -3
  260. package/src/server/core/index.ts +3 -3
  261. package/src/server/core/primitives/$action.spec.ts +3 -2
  262. package/src/server/core/primitives/$action.ts +6 -2
  263. package/src/server/core/providers/NodeHttpServerProvider.ts +2 -15
  264. package/src/server/core/providers/ServerProvider.ts +4 -2
  265. package/src/server/core/providers/ServerRouterProvider.ts +5 -27
  266. package/src/server/cors/index.ts +3 -3
  267. package/src/server/health/index.ts +3 -3
  268. package/src/server/helmet/index.ts +3 -3
  269. package/src/server/links/index.ts +3 -3
  270. package/src/server/metrics/index.ts +3 -3
  271. package/src/server/multipart/index.ts +3 -3
  272. package/src/server/proxy/index.ts +3 -3
  273. package/src/server/rate-limit/index.ts +3 -3
  274. package/src/server/static/index.ts +3 -3
  275. package/src/server/swagger/index.ts +3 -3
  276. package/src/sms/index.ts +3 -3
  277. package/src/system/index.ts +3 -3
  278. package/src/thread/index.ts +3 -3
  279. package/src/topic/core/index.ts +3 -3
  280. package/src/websocket/index.ts +3 -3
  281. package/src/cli/templates/webHelloComponentTsx.ts +0 -30
  282. /package/src/api/users/{notifications → services}/UserNotifications.ts +0 -0
@@ -1,15 +1,13 @@
1
1
  import { $atom, $context, $inject, $module, Alepha, AlephaError, Json, isFileLike, t } from "alepha";
2
- import { $notification, AlephaApiNotifications } from "alepha/api/notifications";
3
- import { AlephaApiVerification } from "alepha/api/verifications";
4
2
  import { AlephaEmail } from "alepha/email";
5
3
  import { AlephaServerCompress } from "alepha/server/compress";
6
4
  import { AlephaServerHelmet } from "alepha/server/helmet";
7
5
  import { $action, BadRequestError, ConflictError, ForbiddenError, HttpError, NotFoundError, UnauthorizedError, okSchema } from "alepha/server";
8
6
  import { $entity, $repository, db, pageQuerySchema, parseQueryString, sql } from "alepha/orm";
9
- import { AlephaApiAudits, AuditService } from "alepha/api/audits";
10
7
  import { $logger } from "alepha/logger";
11
- import { $bucket } from "alepha/bucket";
8
+ import { AuditService } from "alepha/api/audits";
12
9
  import { $client } from "alepha/server/links";
10
+ import { $notification } from "alepha/api/notifications";
13
11
  import { $authCredentials, $authGithub, $authGoogle, ServerAuthProvider, authenticationProviderSchema } from "alepha/server/auth";
14
12
  import { createHash, randomBytes, randomInt, randomUUID } from "node:crypto";
15
13
  import { $cache } from "alepha/cache";
@@ -21,8 +19,10 @@ import { access, copyFile, cp, mkdir, readFile, readdir, rename, rm, stat, write
21
19
  import { PassThrough, Readable } from "node:stream";
22
20
  import { fileURLToPath } from "node:url";
23
21
  import { exec, spawn } from "node:child_process";
24
- import { AlephaApiFiles } from "alepha/api/files";
25
- import { AlephaApiJobs } from "alepha/api/jobs";
22
+ import { AlephaApiVerification } from "alepha/api/verifications";
23
+ import { $bucket } from "alepha/bucket";
24
+ import { $job } from "alepha/api/jobs";
25
+ import { $config } from "alepha/api/parameters";
26
26
 
27
27
  //#region ../../src/api/users/schemas/identityQuerySchema.ts
28
28
  const identityQuerySchema = t.extend(pageQuerySchema, {
@@ -112,6 +112,8 @@ const realmAuthSettingsAtom = $atom({
112
112
  firstNameLastNameEnabled: t.boolean({ description: "Enable first and last name for user accounts" }),
113
113
  firstNameLastNameRequired: t.boolean({ description: "Require first and last name for user accounts" }),
114
114
  resetPasswordAllowed: t.boolean({ description: "Enable forgot password functionality" }),
115
+ adminEmails: t.array(t.email(), { description: "List of email addresses that are automatically promoted to admin role on login" }),
116
+ adminUsernames: t.array(t.text(), { description: "List of usernames that are automatically promoted to admin role on login" }),
115
117
  passwordPolicy: t.object({
116
118
  minLength: t.integer({
117
119
  description: "Minimum password length",
@@ -138,6 +140,8 @@ const realmAuthSettingsAtom = $atom({
138
140
  resetPasswordAllowed: false,
139
141
  firstNameLastNameEnabled: false,
140
142
  firstNameLastNameRequired: false,
143
+ adminEmails: [],
144
+ adminUsernames: [],
141
145
  passwordPolicy: {
142
146
  minLength: 8,
143
147
  requireUppercase: true,
@@ -181,16 +185,17 @@ var RealmProvider = class {
181
185
  defaultSessions = $repository(sessions);
182
186
  defaultUsers = $repository(users);
183
187
  realms = /* @__PURE__ */ new Map();
184
- avatars = $bucket({
185
- maxSize: 5 * 1024 * 1024,
186
- mimeTypes: [
187
- "image/jpeg",
188
- "image/png",
189
- "image/gif",
190
- "image/webp"
191
- ]
192
- });
193
188
  register(realmName, realmOptions = {}) {
189
+ const features = {
190
+ jobs: false,
191
+ notifications: false,
192
+ apiKeys: false,
193
+ parameters: false,
194
+ files: false,
195
+ audits: false,
196
+ organizations: false,
197
+ ...realmOptions.features
198
+ };
194
199
  this.realms.set(realmName, {
195
200
  name: realmName,
196
201
  repositories: {
@@ -205,7 +210,8 @@ var RealmProvider = class {
205
210
  ...realmAuthSettingsAtom.options.default.passwordPolicy,
206
211
  ...realmOptions.settings?.passwordPolicy
207
212
  }
208
- }
213
+ },
214
+ features
209
215
  });
210
216
  return this.getRealm(realmName);
211
217
  }
@@ -233,12 +239,45 @@ var RealmProvider = class {
233
239
  }
234
240
  };
235
241
 
242
+ //#endregion
243
+ //#region ../../src/api/users/services/UserAudits.ts
244
+ /**
245
+ * User-specific audit wrapper service.
246
+ *
247
+ * This service wraps the core AuditService to provide user-related audit logging.
248
+ * It is lazy-loaded when the `audits` feature is enabled in the realm.
249
+ */
250
+ var UserAudits = class {
251
+ auditService = $inject(AuditService);
252
+ /**
253
+ * Record a user-related audit event.
254
+ */
255
+ recordUser(action, context) {
256
+ return this.auditService.recordUser(action, context);
257
+ }
258
+ /**
259
+ * Record an authentication-related audit event.
260
+ */
261
+ recordAuth(action, context) {
262
+ return this.auditService.recordAuth(action, context);
263
+ }
264
+ /**
265
+ * Record a generic audit event.
266
+ */
267
+ record(category, action, context) {
268
+ return this.auditService.record(category, action, context);
269
+ }
270
+ };
271
+
236
272
  //#endregion
237
273
  //#region ../../src/api/users/services/IdentityService.ts
238
274
  var IdentityService = class {
275
+ alepha = $inject(Alepha);
239
276
  log = $logger();
240
277
  realmProvider = $inject(RealmProvider);
241
- auditService = $inject(AuditService);
278
+ userAudits(realmName) {
279
+ if (this.realmProvider.getRealm(realmName).features.audits) return this.alepha.inject(UserAudits);
280
+ }
242
281
  identities(userRealmName) {
243
282
  return this.realmProvider.identityRepository(userRealmName);
244
283
  }
@@ -293,7 +332,7 @@ var IdentityService = class {
293
332
  userId: identity.userId
294
333
  });
295
334
  const realm = this.realmProvider.getRealm(userRealmName);
296
- await this.auditService.recordUser("update", {
335
+ await this.userAudits(userRealmName)?.recordUser("update", {
297
336
  userRealm: realm.name,
298
337
  resourceId: identity.userId,
299
338
  description: `Identity provider disconnected: ${identity.provider}`,
@@ -541,7 +580,7 @@ const userQuerySchema = t.extend(pageQuerySchema, {
541
580
  const userResourceSchema = users.schema;
542
581
 
543
582
  //#endregion
544
- //#region ../../src/api/users/notifications/UserNotifications.ts
583
+ //#region ../../src/api/users/services/UserNotifications.ts
545
584
  var UserNotifications = class {
546
585
  passwordReset = $notification({
547
586
  category: "security",
@@ -672,11 +711,16 @@ var UserNotifications = class {
672
711
  //#endregion
673
712
  //#region ../../src/api/users/services/UserService.ts
674
713
  var UserService = class {
714
+ alepha = $inject(Alepha);
675
715
  log = $logger();
676
716
  verificationController = $client();
677
- userNotifications = $inject(UserNotifications);
678
717
  realmProvider = $inject(RealmProvider);
679
- auditService = $inject(AuditService);
718
+ userAudits(realmName) {
719
+ if (this.realmProvider.getRealm(realmName).features.audits) return this.alepha.inject(UserAudits);
720
+ }
721
+ userNotifications(realmName) {
722
+ if (this.realmProvider.getRealm(realmName).features.notifications) return this.alepha.inject(UserNotifications);
723
+ }
680
724
  users(userRealmName) {
681
725
  return this.realmProvider.userRepository(userRealmName);
682
726
  }
@@ -715,7 +759,7 @@ var UserService = class {
715
759
  url.searchParams.set("email", email);
716
760
  url.searchParams.set("token", verification.token);
717
761
  const fullVerifyUrl = verifyUrl ? `${verifyUrl}${url.search}` : url.pathname + url.search;
718
- await this.userNotifications.emailVerificationLink.push({
762
+ await this.userNotifications(userRealmName)?.emailVerificationLink.push({
719
763
  contact: email,
720
764
  variables: {
721
765
  email,
@@ -728,7 +772,7 @@ var UserService = class {
728
772
  userId: user.id
729
773
  });
730
774
  } else {
731
- await this.userNotifications.emailVerification.push({
775
+ await this.userNotifications(userRealmName)?.emailVerification.push({
732
776
  contact: email,
733
777
  variables: {
734
778
  email,
@@ -783,7 +827,7 @@ var UserService = class {
783
827
  type
784
828
  });
785
829
  const realm = this.realmProvider.getRealm(userRealmName);
786
- await this.auditService.recordUser("update", {
830
+ await this.userAudits(userRealmName)?.recordUser("update", {
787
831
  userId: user.id,
788
832
  userEmail: email,
789
833
  userRealm: realm.name,
@@ -875,7 +919,7 @@ var UserService = class {
875
919
  username: user.username,
876
920
  email: user.email
877
921
  });
878
- await this.auditService.recordUser("create", {
922
+ await this.userAudits(userRealmName)?.recordUser("create", {
879
923
  userRealm: realm.name,
880
924
  resourceId: user.id,
881
925
  description: "User created",
@@ -905,7 +949,7 @@ var UserService = class {
905
949
  to: data[key]
906
950
  };
907
951
  const isRoleChange = data.roles !== void 0 && JSON.stringify(before.roles) !== JSON.stringify(data.roles);
908
- await this.auditService.recordUser(isRoleChange ? "role_change" : "update", {
952
+ await this.userAudits(userRealmName)?.recordUser(isRoleChange ? "role_change" : "update", {
909
953
  userRealm: realm.name,
910
954
  resourceId: user.id,
911
955
  description: isRoleChange ? "User roles changed" : `User updated: ${Object.keys(changes).join(", ")}`,
@@ -925,7 +969,7 @@ var UserService = class {
925
969
  await this.users(userRealmName).deleteById(id);
926
970
  this.log.info("User deleted", { userId: id });
927
971
  const realm = this.realmProvider.getRealm(userRealmName);
928
- await this.auditService.recordUser("delete", {
972
+ await this.userAudits(userRealmName)?.recordUser("delete", {
929
973
  userRealm: realm.name,
930
974
  resourceId: id,
931
975
  severity: "warning",
@@ -1180,13 +1224,18 @@ const registrationIntentResponseSchema = t.object({
1180
1224
  //#region ../../src/api/users/services/CredentialService.ts
1181
1225
  const INTENT_TTL_MINUTES$1 = 10;
1182
1226
  var CredentialService = class {
1227
+ alepha = $inject(Alepha);
1183
1228
  log = $logger();
1184
1229
  cryptoProvider = $inject(CryptoProvider);
1185
1230
  dateTimeProvider = $inject(DateTimeProvider);
1186
1231
  verificationController = $client();
1187
- userNotifications = $inject(UserNotifications);
1188
1232
  realmProvider = $inject(RealmProvider);
1189
- auditService = $inject(AuditService);
1233
+ userAudits(realmName) {
1234
+ if (this.realmProvider.getRealm(realmName).features.audits) return this.alepha.inject(UserAudits);
1235
+ }
1236
+ userNotifications(realmName) {
1237
+ if (this.realmProvider.getRealm(realmName).features.notifications) return this.alepha.inject(UserNotifications);
1238
+ }
1190
1239
  intentCache = $cache({
1191
1240
  name: "password-reset-intents",
1192
1241
  ttl: [INTENT_TTL_MINUTES$1, "minutes"]
@@ -1241,7 +1290,7 @@ var CredentialService = class {
1241
1290
  params: { type: "code" },
1242
1291
  body: { target: email }
1243
1292
  });
1244
- await this.userNotifications.passwordReset.push({
1293
+ await this.userNotifications(userRealmName)?.passwordReset.push({
1245
1294
  contact: email,
1246
1295
  variables: {
1247
1296
  email,
@@ -1316,7 +1365,7 @@ var CredentialService = class {
1316
1365
  email: intent.email
1317
1366
  });
1318
1367
  const realm = this.realmProvider.getRealm(intent.realmName);
1319
- await this.auditService.recordUser("update", {
1368
+ await this.userAudits(intent.realmName)?.recordUser("update", {
1320
1369
  userId: intent.userId,
1321
1370
  userEmail: intent.email,
1322
1371
  userRealm: realm.name,
@@ -1324,7 +1373,7 @@ var CredentialService = class {
1324
1373
  description: "Password reset completed",
1325
1374
  metadata: { email: intent.email }
1326
1375
  });
1327
- await this.auditService.record("security", "sessions_invalidated", {
1376
+ await this.userAudits(intent.realmName)?.record("security", "sessions_invalidated", {
1328
1377
  userId: intent.userId,
1329
1378
  userEmail: intent.email,
1330
1379
  userRealm: realm.name,
@@ -1375,7 +1424,7 @@ var CredentialService = class {
1375
1424
  await this.identities(userRealmName).updateById(identity.id, { password: hashedPassword });
1376
1425
  await this.sessions(userRealmName).deleteMany({ userId: { eq: user.id } });
1377
1426
  const realm = this.realmProvider.getRealm(userRealmName);
1378
- await this.auditService.recordUser("update", {
1427
+ await this.userAudits(userRealmName)?.recordUser("update", {
1379
1428
  userId: user.id,
1380
1429
  userEmail: email,
1381
1430
  userRealm: realm.name,
@@ -1383,7 +1432,7 @@ var CredentialService = class {
1383
1432
  description: "Password reset completed (legacy)",
1384
1433
  metadata: { email }
1385
1434
  });
1386
- await this.auditService.record("security", "sessions_invalidated", {
1435
+ await this.userAudits(userRealmName)?.record("security", "sessions_invalidated", {
1387
1436
  userId: user.id,
1388
1437
  userEmail: email,
1389
1438
  userRealm: realm.name,
@@ -1398,17 +1447,22 @@ var CredentialService = class {
1398
1447
  //#region ../../src/api/users/services/RegistrationService.ts
1399
1448
  const INTENT_TTL_MINUTES = 10;
1400
1449
  var RegistrationService = class {
1450
+ alepha = $inject(Alepha);
1401
1451
  log = $logger();
1402
1452
  dateTimeProvider = $inject(DateTimeProvider);
1403
1453
  cryptoProvider = $inject(CryptoProvider);
1404
1454
  verificationController = $client();
1405
- userNotifications = $inject(UserNotifications);
1406
1455
  realmProvider = $inject(RealmProvider);
1407
- auditService = $inject(AuditService);
1408
1456
  intentCache = $cache({
1409
1457
  name: "registration-intents",
1410
1458
  ttl: [INTENT_TTL_MINUTES, "minutes"]
1411
1459
  });
1460
+ userAudits(realmName) {
1461
+ if (this.realmProvider.getRealm(realmName).features.audits) return this.alepha.inject(UserAudits);
1462
+ }
1463
+ userNotifications(realmName) {
1464
+ if (this.realmProvider.getRealm(realmName).features.notifications) return this.alepha.inject(UserNotifications);
1465
+ }
1412
1466
  /**
1413
1467
  * Phase 1: Create a registration intent.
1414
1468
  *
@@ -1457,8 +1511,8 @@ var RegistrationService = class {
1457
1511
  phone: realmSettings?.verifyPhoneRequired === true && !!body.phoneNumber,
1458
1512
  captcha: false
1459
1513
  };
1460
- if (requirements.email && body.email) await this.sendEmailVerification(body.email);
1461
- if (requirements.phone && body.phoneNumber) await this.sendPhoneVerification(body.phoneNumber);
1514
+ if (requirements.email && body.email) await this.sendEmailVerification(body.email, userRealmName);
1515
+ if (requirements.phone && body.phoneNumber) await this.sendPhoneVerification(body.phoneNumber, userRealmName);
1462
1516
  const intentId = randomUUID();
1463
1517
  const expiresAt = this.dateTimeProvider.now().add(INTENT_TTL_MINUTES, "minutes").toISOString();
1464
1518
  const intent = {
@@ -1558,7 +1612,7 @@ var RegistrationService = class {
1558
1612
  username: user.username
1559
1613
  });
1560
1614
  const realm = this.realmProvider.getRealm(userRealmName);
1561
- await this.auditService.recordUser("create", {
1615
+ await this.userAudits(userRealmName)?.recordUser("create", {
1562
1616
  userId: user.id,
1563
1617
  userEmail: user.email ?? void 0,
1564
1618
  userRealm: realm.name,
@@ -1600,13 +1654,13 @@ var RegistrationService = class {
1600
1654
  /**
1601
1655
  * Send email verification code.
1602
1656
  */
1603
- async sendEmailVerification(email) {
1657
+ async sendEmailVerification(email, realmName) {
1604
1658
  this.log.debug("Sending email verification code", { email });
1605
1659
  const verification = await this.verificationController.requestVerificationCode({
1606
1660
  params: { type: "code" },
1607
1661
  body: { target: email }
1608
1662
  });
1609
- await this.userNotifications.emailVerification.push({
1663
+ await this.userNotifications(realmName)?.emailVerification.push({
1610
1664
  contact: email,
1611
1665
  variables: {
1612
1666
  email,
@@ -1619,14 +1673,14 @@ var RegistrationService = class {
1619
1673
  /**
1620
1674
  * Send phone verification code.
1621
1675
  */
1622
- async sendPhoneVerification(phoneNumber) {
1676
+ async sendPhoneVerification(phoneNumber, realmName) {
1623
1677
  this.log.debug("Sending phone verification code", { phoneNumber });
1624
1678
  try {
1625
1679
  const verification = await this.verificationController.requestVerificationCode({
1626
1680
  params: { type: "code" },
1627
1681
  body: { target: phoneNumber }
1628
1682
  });
1629
- await this.userNotifications.phoneVerification.push({
1683
+ await this.userNotifications(realmName)?.phoneVerification.push({
1630
1684
  contact: phoneNumber,
1631
1685
  variables: {
1632
1686
  phoneNumber,
@@ -3710,9 +3764,9 @@ var ShellProvider = class {};
3710
3764
  //#endregion
3711
3765
  //#region ../../src/system/index.ts
3712
3766
  /**
3713
- * | type | quality | stability |
3714
- * |------|---------|-----------|
3715
- * | tooling | standard | stable |
3767
+ * | Stability | Since | Runtime |
3768
+ * |-----------|-------|---------|
3769
+ * | 3 - stable | 0.14.0 | node, bun, browser|
3716
3770
  *
3717
3771
  * System-level abstractions for portable code across runtimes.
3718
3772
  *
@@ -3757,7 +3811,9 @@ var SessionService = class {
3757
3811
  log = $logger();
3758
3812
  realmProvider = $inject(RealmProvider);
3759
3813
  fileController = $client();
3760
- auditService = $inject(AuditService);
3814
+ userAudits(realmName) {
3815
+ if (this.realmProvider.getRealm(realmName).features.audits) return this.alepha.inject(UserAudits);
3816
+ }
3761
3817
  users(userRealmName) {
3762
3818
  return this.realmProvider.userRepository(userRealmName);
3763
3819
  }
@@ -3768,6 +3824,40 @@ var SessionService = class {
3768
3824
  return this.realmProvider.identityRepository(userRealmName);
3769
3825
  }
3770
3826
  /**
3827
+ * Check if user should be auto-promoted to admin based on adminEmails/adminUsernames settings.
3828
+ * If user matches and doesn't have admin role, promote them.
3829
+ */
3830
+ async ensureAdminRole(user, userRealmName) {
3831
+ if (user.roles.includes("admin")) return false;
3832
+ const { settings, name } = this.realmProvider.getRealm(userRealmName);
3833
+ const adminEmails = settings.adminEmails ?? [];
3834
+ const adminUsernames = settings.adminUsernames ?? [];
3835
+ const isAdminByEmail = user.email && adminEmails.includes(user.email);
3836
+ const isAdminByUsername = user.username && adminUsernames.includes(user.username);
3837
+ if (!isAdminByEmail && !isAdminByUsername) return false;
3838
+ user.roles = [...user.roles.filter((r) => r !== "admin"), "admin"];
3839
+ await this.users(userRealmName).updateById(user.id, { roles: user.roles });
3840
+ const reason = isAdminByEmail ? "adminEmails" : "adminUsernames";
3841
+ this.log.info(`User auto-promoted to admin via ${reason} setting`, {
3842
+ userId: user.id,
3843
+ email: user.email,
3844
+ username: user.username,
3845
+ realm: name
3846
+ });
3847
+ await this.userAudits(userRealmName)?.recordUser("role_change", {
3848
+ userId: user.id,
3849
+ userEmail: user.email ?? void 0,
3850
+ userRealm: name,
3851
+ resourceId: user.id,
3852
+ description: `User auto-promoted to admin via ${reason} setting`,
3853
+ metadata: {
3854
+ addedRole: "admin",
3855
+ reason
3856
+ }
3857
+ });
3858
+ return true;
3859
+ }
3860
+ /**
3771
3861
  * Random delay to prevent timing attacks (50-200ms)
3772
3862
  * Uses cryptographically secure random number generation
3773
3863
  */
@@ -3796,7 +3886,7 @@ var SessionService = class {
3796
3886
  username,
3797
3887
  realm: name
3798
3888
  });
3799
- await this.auditService.recordAuth("login_failed", {
3889
+ await this.userAudits(userRealmName)?.recordAuth("login_failed", {
3800
3890
  userRealm: name,
3801
3891
  description: "Username does not match required format",
3802
3892
  metadata: {
@@ -3816,7 +3906,7 @@ var SessionService = class {
3816
3906
  username,
3817
3907
  realm: name
3818
3908
  });
3819
- await this.auditService.recordAuth("login_failed", {
3909
+ await this.userAudits(userRealmName)?.recordAuth("login_failed", {
3820
3910
  userRealm: name,
3821
3911
  description: "Invalid login identifier format",
3822
3912
  metadata: {
@@ -3833,7 +3923,7 @@ var SessionService = class {
3833
3923
  username,
3834
3924
  realm: name
3835
3925
  });
3836
- await this.auditService.recordAuth("login_failed", {
3926
+ await this.userAudits(userRealmName)?.recordAuth("login_failed", {
3837
3927
  userRealm: name,
3838
3928
  description: "User not found",
3839
3929
  metadata: {
@@ -3863,7 +3953,7 @@ var SessionService = class {
3863
3953
  username,
3864
3954
  realm: name
3865
3955
  });
3866
- await this.auditService.recordAuth("login_failed", {
3956
+ await this.userAudits(userRealmName)?.recordAuth("login_failed", {
3867
3957
  userRealm: name,
3868
3958
  resourceId: user.id,
3869
3959
  description: "Invalid password",
@@ -3874,7 +3964,7 @@ var SessionService = class {
3874
3964
  });
3875
3965
  throw new InvalidCredentialsError();
3876
3966
  }
3877
- await this.auditService.recordAuth("login", {
3967
+ await this.userAudits(userRealmName)?.recordAuth("login", {
3878
3968
  userId: user.id,
3879
3969
  userEmail: user.email ?? void 0,
3880
3970
  userRealm: name,
@@ -3885,6 +3975,7 @@ var SessionService = class {
3885
3975
  username
3886
3976
  }
3887
3977
  });
3978
+ await this.ensureAdminRole(user, userRealmName);
3888
3979
  return user;
3889
3980
  } catch (error) {
3890
3981
  if (error instanceof InvalidCredentialsError) throw error;
@@ -3931,6 +4022,7 @@ var SessionService = class {
3931
4022
  throw new UnauthorizedError("Session expired");
3932
4023
  }
3933
4024
  const user = await this.users(userRealmName).findOne({ where: { id: { eq: session.userId } } });
4025
+ await this.ensureAdminRole(user, userRealmName);
3934
4026
  this.log.debug("Session refreshed", {
3935
4027
  sessionId: session.id,
3936
4028
  userId: session.userId
@@ -3948,7 +4040,7 @@ var SessionService = class {
3948
4040
  this.log.debug("Session deleted");
3949
4041
  if (session) {
3950
4042
  const { name } = this.realmProvider.getRealm(userRealmName);
3951
- await this.auditService.recordAuth("logout", {
4043
+ await this.userAudits(userRealmName)?.recordAuth("logout", {
3952
4044
  userId: session.userId,
3953
4045
  userRealm: name,
3954
4046
  sessionId: session.id,
@@ -3976,7 +4068,7 @@ var SessionService = class {
3976
4068
  userId: identity.userId
3977
4069
  });
3978
4070
  const user = await users.findById(identity.userId);
3979
- await this.auditService.recordAuth("login", {
4071
+ await this.userAudits(userRealmName)?.recordAuth("login", {
3980
4072
  userId: user.id,
3981
4073
  userEmail: user.email ?? void 0,
3982
4074
  userRealm: realm.name,
@@ -3987,6 +4079,7 @@ var SessionService = class {
3987
4079
  providerUserId: profile.sub
3988
4080
  }
3989
4081
  });
4082
+ await this.ensureAdminRole(user, userRealmName);
3990
4083
  return user;
3991
4084
  }
3992
4085
  if (!profile.email) {
@@ -4012,7 +4105,7 @@ var SessionService = class {
4012
4105
  providerUserId: profile.sub,
4013
4106
  userId: existing.id
4014
4107
  });
4015
- await this.auditService.recordAuth("login", {
4108
+ await this.userAudits(userRealmName)?.recordAuth("login", {
4016
4109
  userId: existing.id,
4017
4110
  userEmail: existing.email ?? void 0,
4018
4111
  userRealm: realm.name,
@@ -4024,6 +4117,7 @@ var SessionService = class {
4024
4117
  linked: true
4025
4118
  }
4026
4119
  });
4120
+ await this.ensureAdminRole(existing, userRealmName);
4027
4121
  return existing;
4028
4122
  }
4029
4123
  const user = await users.create({
@@ -4060,7 +4154,7 @@ var SessionService = class {
4060
4154
  email: user.email,
4061
4155
  username: user.username
4062
4156
  });
4063
- await this.auditService.recordUser("create", {
4157
+ await this.userAudits(userRealmName)?.recordUser("create", {
4064
4158
  userId: user.id,
4065
4159
  userEmail: user.email ?? void 0,
4066
4160
  userRealm: realm.name,
@@ -4073,7 +4167,7 @@ var SessionService = class {
4073
4167
  email: user.email
4074
4168
  }
4075
4169
  });
4076
- await this.auditService.recordAuth("login", {
4170
+ await this.userAudits(userRealmName)?.recordAuth("login", {
4077
4171
  userId: user.id,
4078
4172
  userEmail: user.email ?? void 0,
4079
4173
  userRealm: realm.name,
@@ -4085,6 +4179,7 @@ var SessionService = class {
4085
4179
  firstLogin: true
4086
4180
  }
4087
4181
  });
4182
+ await this.ensureAdminRole(user, userRealmName);
4088
4183
  return user;
4089
4184
  }
4090
4185
  };
@@ -4519,9 +4614,9 @@ var ApiKeyController = class {
4519
4614
  //#endregion
4520
4615
  //#region ../../src/api/keys/index.ts
4521
4616
  /**
4522
- * | type | quality | stability |
4523
- * |------|---------|--------------|
4524
- * | backend | good | experimental |
4617
+ * | Stability | Since | Runtime |
4618
+ * |-----------|-------|---------|
4619
+ * | 3 - stable | 0.11.0 | node, bun, workerd|
4525
4620
  *
4526
4621
  * API key management module for programmatic access.
4527
4622
  *
@@ -4555,6 +4650,95 @@ const AlephaApiKeys = $module({
4555
4650
  ]
4556
4651
  });
4557
4652
 
4653
+ //#endregion
4654
+ //#region ../../src/api/users/services/UserFiles.ts
4655
+ /**
4656
+ * User-specific file storage wrapper service.
4657
+ *
4658
+ * This service provides file storage for user-related files such as:
4659
+ * - User avatars/profile pictures
4660
+ *
4661
+ * It is lazy-loaded when the `files` feature is enabled in the realm.
4662
+ */
4663
+ var UserFiles = class {
4664
+ /**
4665
+ * Bucket for user avatar storage.
4666
+ */
4667
+ avatars = $bucket({
4668
+ maxSize: 5 * 1024 * 1024,
4669
+ mimeTypes: [
4670
+ "image/jpeg",
4671
+ "image/png",
4672
+ "image/gif",
4673
+ "image/webp"
4674
+ ]
4675
+ });
4676
+ };
4677
+
4678
+ //#endregion
4679
+ //#region ../../src/api/users/services/UserJobs.ts
4680
+ /**
4681
+ * User-specific jobs wrapper service.
4682
+ *
4683
+ * This service handles user-related scheduled jobs such as:
4684
+ * - Session purge (cleaning up expired sessions)
4685
+ * - Verification code cleanup
4686
+ * - Inactive user notifications
4687
+ *
4688
+ * It is lazy-loaded when the `jobs` feature is enabled in the realm.
4689
+ */
4690
+ var UserJobs = class {
4691
+ log = $logger();
4692
+ dateTimeProvider = $inject(DateTimeProvider);
4693
+ sessionRepository = $repository(sessions);
4694
+ /**
4695
+ * Purge expired sessions from the database.
4696
+ *
4697
+ * This job runs daily at 3:00 AM and removes all sessions
4698
+ * where the `expiresAt` timestamp has passed.
4699
+ */
4700
+ purgeExpiredSessions = $job({
4701
+ name: "users.purgeExpiredSessions",
4702
+ description: "Remove expired user sessions from the database",
4703
+ cron: "0 3 * * *",
4704
+ handler: async () => {
4705
+ const now = this.dateTimeProvider.nowISOString();
4706
+ this.log.info("Starting expired sessions purge", { cutoffTime: now });
4707
+ const expiredSessions = await this.sessionRepository.findMany({ where: { expiresAt: { lt: now } } });
4708
+ if (expiredSessions.length === 0) {
4709
+ this.log.info("No expired sessions found");
4710
+ return;
4711
+ }
4712
+ this.log.info("Found expired sessions", { count: expiredSessions.length });
4713
+ const deletedIds = await this.sessionRepository.deleteMany({ expiresAt: { lt: now } });
4714
+ this.log.info("Expired sessions purged successfully", { deletedCount: deletedIds.length });
4715
+ }
4716
+ });
4717
+ };
4718
+
4719
+ //#endregion
4720
+ //#region ../../src/api/users/services/UserParameters.ts
4721
+ /**
4722
+ * User-specific configuration service.
4723
+ *
4724
+ * This service wraps the core ConfigStore to provide realm settings management.
4725
+ * It is lazy-loaded when the `parameters` feature is enabled in the realm.
4726
+ */
4727
+ var UserParameters = class {
4728
+ /**
4729
+ * Realm authentication settings configuration.
4730
+ *
4731
+ * Controls user registration, login methods, verification requirements,
4732
+ * and password policies for the realm.
4733
+ */
4734
+ realmSettings = $config({
4735
+ name: "alepha.api.users.realmSettings",
4736
+ description: "Realm authentication and registration settings",
4737
+ schema: realmAuthSettingsAtom.schema,
4738
+ default: realmAuthSettingsAtom.options.default
4739
+ });
4740
+ };
4741
+
4558
4742
  //#endregion
4559
4743
  //#region ../../src/api/users/primitives/$realm.ts
4560
4744
  /**
@@ -4580,12 +4764,32 @@ const $realm = (options = {}) => {
4580
4764
  if (options.settings.emailRequired) options.settings.emailEnabled = true;
4581
4765
  if (options.settings.usernameRequired) options.settings.usernameEnabled = true;
4582
4766
  if (options.settings.phoneRequired) options.settings.phoneEnabled = true;
4767
+ const features = {
4768
+ jobs: false,
4769
+ notifications: false,
4770
+ apiKeys: false,
4771
+ parameters: false,
4772
+ files: false,
4773
+ audits: false,
4774
+ organizations: false,
4775
+ ...options.features
4776
+ };
4777
+ if (!features.notifications) {
4778
+ options.settings.verifyEmailRequired = false;
4779
+ options.settings.verifyPhoneRequired = false;
4780
+ options.settings.resetPasswordAllowed = false;
4781
+ }
4583
4782
  const realmRegistration = realmProvider.register(name, options);
4584
- alepha.with(AlephaApiFiles);
4585
- alepha.with(AlephaApiAudits);
4586
- alepha.with(AlephaApiJobs);
4783
+ if (features.files) alepha.with(UserFiles);
4784
+ if (features.audits) alepha.with(UserAudits);
4785
+ if (features.jobs) alepha.with(UserJobs);
4786
+ if (features.notifications) {
4787
+ alepha.with(AlephaApiVerification);
4788
+ alepha.with(UserNotifications);
4789
+ }
4790
+ if (features.parameters) alepha.with(UserParameters);
4587
4791
  const customResolvers = [...options.issuer?.resolvers ?? []];
4588
- if (options.apiKeys) {
4792
+ if (features.apiKeys) {
4589
4793
  alepha.with(AlephaApiKeys);
4590
4794
  const apiKeyService = alepha.inject(ApiKeyService);
4591
4795
  customResolvers.push(apiKeyService.createResolver());
@@ -4701,9 +4905,9 @@ const resetPasswordSchema = t.object({
4701
4905
  //#endregion
4702
4906
  //#region ../../src/api/users/index.ts
4703
4907
  /**
4704
- * | type | quality | stability |
4705
- * |------|---------|-----------|
4706
- * | backend | epic | stable |
4908
+ * | Stability | Since | Runtime |
4909
+ * |-----------|-------|---------|
4910
+ * | 3 - stable | 0.5.0 | node, bun, workerd|
4707
4911
  *
4708
4912
  * Complete user management with multi-realm support for multi-tenant applications.
4709
4913
  *
@@ -4722,8 +4926,6 @@ const resetPasswordSchema = t.object({
4722
4926
  const AlephaApiUsers = $module({
4723
4927
  name: "alepha.api.users",
4724
4928
  services: [
4725
- AlephaApiVerification,
4726
- AlephaApiNotifications,
4727
4929
  AlephaServerHelmet,
4728
4930
  AlephaServerCompress,
4729
4931
  AlephaEmail,
@@ -4738,11 +4940,10 @@ const AlephaApiUsers = $module({
4738
4940
  AdminUserController,
4739
4941
  AdminSessionController,
4740
4942
  AdminIdentityController,
4741
- RealmController,
4742
- UserNotifications
4943
+ RealmController
4743
4944
  ]
4744
4945
  });
4745
4946
 
4746
4947
  //#endregion
4747
- export { $realm, AdminIdentityController, AdminSessionController, AdminUserController, AlephaApiUsers, CredentialService, DEFAULT_USER_REALM_NAME, IdentityService, RealmController, RealmProvider, RegistrationService, SessionCrudService, SessionService, UserController, UserService, completePasswordResetRequestSchema, completeRegistrationRequestSchema, createUserSchema, identities, identityQuerySchema, identityResourceSchema, loginSchema, passwordResetIntentResponseSchema, realmAuthSettingsAtom, realmConfigSchema, registerSchema, registrationIntentResponseSchema, resetPasswordRequestSchema, resetPasswordSchema, sessionQuerySchema, sessionResourceSchema, sessions, updateUserSchema, userQuerySchema, userResourceSchema, users };
4948
+ export { $realm, AdminIdentityController, AdminSessionController, AdminUserController, AlephaApiUsers, CredentialService, DEFAULT_USER_REALM_NAME, IdentityService, RealmController, RealmProvider, RegistrationService, SessionCrudService, SessionService, UserAudits, UserController, UserFiles, UserJobs, UserNotifications, UserParameters, UserService, completePasswordResetRequestSchema, completeRegistrationRequestSchema, createUserSchema, identities, identityQuerySchema, identityResourceSchema, loginSchema, passwordResetIntentResponseSchema, realmAuthSettingsAtom, realmConfigSchema, registerSchema, registrationIntentResponseSchema, resetPasswordRequestSchema, resetPasswordSchema, sessionQuerySchema, sessionResourceSchema, sessions, updateUserSchema, userQuerySchema, userResourceSchema, users };
4748
4949
  //# sourceMappingURL=index.js.map