alepha 0.15.3 → 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 (318) hide show
  1. package/README.md +26 -11
  2. package/dist/api/audits/index.d.ts +335 -335
  3. package/dist/api/audits/index.d.ts.map +1 -1
  4. package/dist/api/audits/index.js +11 -3
  5. package/dist/api/audits/index.js.map +1 -1
  6. package/dist/api/files/index.d.ts +3 -3
  7. package/dist/api/files/index.js +4 -3
  8. package/dist/api/files/index.js.map +1 -1
  9. package/dist/api/jobs/index.d.ts +198 -155
  10. package/dist/api/jobs/index.d.ts.map +1 -1
  11. package/dist/api/jobs/index.js +103 -5
  12. package/dist/api/jobs/index.js.map +1 -1
  13. package/dist/api/keys/index.d.ts +198 -198
  14. package/dist/api/keys/index.d.ts.map +1 -1
  15. package/dist/api/keys/index.js +3 -3
  16. package/dist/api/keys/index.js.map +1 -1
  17. package/dist/api/notifications/index.browser.js +1 -0
  18. package/dist/api/notifications/index.browser.js.map +1 -1
  19. package/dist/api/notifications/index.d.ts +3 -3
  20. package/dist/api/notifications/index.js +4 -3
  21. package/dist/api/notifications/index.js.map +1 -1
  22. package/dist/api/parameters/index.d.ts +263 -263
  23. package/dist/api/parameters/index.d.ts.map +1 -1
  24. package/dist/api/parameters/index.js +41 -30
  25. package/dist/api/parameters/index.js.map +1 -1
  26. package/dist/api/users/index.d.ts +383 -77
  27. package/dist/api/users/index.d.ts.map +1 -1
  28. package/dist/api/users/index.js +284 -72
  29. package/dist/api/users/index.js.map +1 -1
  30. package/dist/api/verifications/index.d.ts +131 -131
  31. package/dist/api/verifications/index.d.ts.map +1 -1
  32. package/dist/api/verifications/index.js +3 -3
  33. package/dist/api/verifications/index.js.map +1 -1
  34. package/dist/batch/index.d.ts +3 -3
  35. package/dist/batch/index.js +3 -3
  36. package/dist/batch/index.js.map +1 -1
  37. package/dist/bucket/index.d.ts +3 -3
  38. package/dist/bucket/index.js +6 -6
  39. package/dist/bucket/index.js.map +1 -1
  40. package/dist/cache/core/index.d.ts +3 -3
  41. package/dist/cache/core/index.js +3 -3
  42. package/dist/cache/core/index.js.map +1 -1
  43. package/dist/cli/index.d.ts +5612 -20
  44. package/dist/cli/index.d.ts.map +1 -1
  45. package/dist/cli/index.js +122 -91
  46. package/dist/cli/index.js.map +1 -1
  47. package/dist/command/index.d.ts +11 -4
  48. package/dist/command/index.d.ts.map +1 -1
  49. package/dist/command/index.js +8 -6
  50. package/dist/command/index.js.map +1 -1
  51. package/dist/core/index.browser.js.map +1 -1
  52. package/dist/core/index.d.ts +4 -8
  53. package/dist/core/index.d.ts.map +1 -1
  54. package/dist/core/index.js +3 -3
  55. package/dist/core/index.js.map +1 -1
  56. package/dist/core/index.native.js.map +1 -1
  57. package/dist/datetime/index.d.ts +3 -3
  58. package/dist/datetime/index.js +3 -3
  59. package/dist/datetime/index.js.map +1 -1
  60. package/dist/email/index.d.ts +16 -16
  61. package/dist/email/index.d.ts.map +1 -1
  62. package/dist/email/index.js +10562 -10
  63. package/dist/email/index.js.map +1 -1
  64. package/dist/fake/index.d.ts +3 -3
  65. package/dist/fake/index.js +3 -3
  66. package/dist/fake/index.js.map +1 -1
  67. package/dist/lock/core/index.d.ts +9 -4
  68. package/dist/lock/core/index.d.ts.map +1 -1
  69. package/dist/lock/core/index.js +12 -4
  70. package/dist/lock/core/index.js.map +1 -1
  71. package/dist/logger/index.d.ts +3 -3
  72. package/dist/logger/index.js +6 -3
  73. package/dist/logger/index.js.map +1 -1
  74. package/dist/mcp/index.d.ts +3 -3
  75. package/dist/mcp/index.js +3 -3
  76. package/dist/mcp/index.js.map +1 -1
  77. package/dist/orm/index.d.ts +12 -12
  78. package/dist/orm/index.js +4 -4
  79. package/dist/orm/index.js.map +1 -1
  80. package/dist/queue/core/index.d.ts +3 -3
  81. package/dist/queue/core/index.js +3 -3
  82. package/dist/queue/core/index.js.map +1 -1
  83. package/dist/react/auth/index.browser.js +2 -1
  84. package/dist/react/auth/index.browser.js.map +1 -1
  85. package/dist/react/auth/index.d.ts +3 -3
  86. package/dist/react/auth/index.js +5 -4
  87. package/dist/react/auth/index.js.map +1 -1
  88. package/dist/react/core/index.d.ts +6 -6
  89. package/dist/react/core/index.js +3 -3
  90. package/dist/react/core/index.js.map +1 -1
  91. package/dist/react/form/index.d.ts +3 -3
  92. package/dist/react/form/index.js +3 -3
  93. package/dist/react/form/index.js.map +1 -1
  94. package/dist/react/head/index.d.ts +3 -3
  95. package/dist/react/head/index.js +3 -3
  96. package/dist/react/head/index.js.map +1 -1
  97. package/dist/react/i18n/index.d.ts +3 -3
  98. package/dist/react/i18n/index.js +3 -3
  99. package/dist/react/i18n/index.js.map +1 -1
  100. package/dist/react/intro/index.css +337 -0
  101. package/dist/react/intro/index.css.map +1 -0
  102. package/dist/react/intro/index.d.ts +10 -0
  103. package/dist/react/intro/index.d.ts.map +1 -0
  104. package/dist/react/intro/index.js +222 -0
  105. package/dist/react/intro/index.js.map +1 -0
  106. package/dist/react/router/index.browser.js +2 -2
  107. package/dist/react/router/index.browser.js.map +1 -1
  108. package/dist/react/router/index.d.ts +11 -1
  109. package/dist/react/router/index.d.ts.map +1 -1
  110. package/dist/react/router/index.js +21 -11
  111. package/dist/react/router/index.js.map +1 -1
  112. package/dist/redis/index.d.ts +22 -22
  113. package/dist/redis/index.js +3 -3
  114. package/dist/redis/index.js.map +1 -1
  115. package/dist/retry/index.d.ts +3 -3
  116. package/dist/retry/index.js +3 -3
  117. package/dist/retry/index.js.map +1 -1
  118. package/dist/scheduler/index.d.ts +16 -4
  119. package/dist/scheduler/index.d.ts.map +1 -1
  120. package/dist/scheduler/index.js +45 -7
  121. package/dist/scheduler/index.js.map +1 -1
  122. package/dist/security/index.d.ts +3 -3
  123. package/dist/security/index.js +5 -5
  124. package/dist/security/index.js.map +1 -1
  125. package/dist/server/auth/index.d.ts +3 -3
  126. package/dist/server/auth/index.js +3 -3
  127. package/dist/server/auth/index.js.map +1 -1
  128. package/dist/server/cache/index.d.ts +3 -3
  129. package/dist/server/cache/index.js +3 -3
  130. package/dist/server/cache/index.js.map +1 -1
  131. package/dist/server/compress/index.d.ts +3 -3
  132. package/dist/server/compress/index.d.ts.map +1 -1
  133. package/dist/server/compress/index.js +4 -3
  134. package/dist/server/compress/index.js.map +1 -1
  135. package/dist/server/cookies/index.d.ts +3 -3
  136. package/dist/server/cookies/index.js +3 -3
  137. package/dist/server/cookies/index.js.map +1 -1
  138. package/dist/server/core/index.d.ts +14 -25
  139. package/dist/server/core/index.d.ts.map +1 -1
  140. package/dist/server/core/index.js +13 -29
  141. package/dist/server/core/index.js.map +1 -1
  142. package/dist/server/cors/index.d.ts +3 -3
  143. package/dist/server/cors/index.js +3 -3
  144. package/dist/server/cors/index.js.map +1 -1
  145. package/dist/server/health/index.d.ts +20 -20
  146. package/dist/server/health/index.js +3 -3
  147. package/dist/server/health/index.js.map +1 -1
  148. package/dist/server/helmet/index.d.ts +3 -3
  149. package/dist/server/helmet/index.js +3 -3
  150. package/dist/server/helmet/index.js.map +1 -1
  151. package/dist/server/links/index.d.ts +42 -42
  152. package/dist/server/links/index.d.ts.map +1 -1
  153. package/dist/server/links/index.js +4 -4
  154. package/dist/server/links/index.js.map +1 -1
  155. package/dist/server/metrics/index.d.ts +3 -3
  156. package/dist/server/metrics/index.js +3 -3
  157. package/dist/server/metrics/index.js.map +1 -1
  158. package/dist/server/multipart/index.d.ts +3 -3
  159. package/dist/server/multipart/index.js +3 -3
  160. package/dist/server/multipart/index.js.map +1 -1
  161. package/dist/server/proxy/index.d.ts +3 -3
  162. package/dist/server/proxy/index.js +3 -3
  163. package/dist/server/proxy/index.js.map +1 -1
  164. package/dist/server/rate-limit/index.d.ts +3 -3
  165. package/dist/server/rate-limit/index.js +3 -3
  166. package/dist/server/rate-limit/index.js.map +1 -1
  167. package/dist/server/static/index.d.ts +3 -3
  168. package/dist/server/static/index.js +6 -6
  169. package/dist/server/static/index.js.map +1 -1
  170. package/dist/server/swagger/index.d.ts +3 -3
  171. package/dist/server/swagger/index.js +6 -6
  172. package/dist/server/swagger/index.js.map +1 -1
  173. package/dist/sms/index.d.ts +3 -3
  174. package/dist/sms/index.js +6 -6
  175. package/dist/sms/index.js.map +1 -1
  176. package/dist/system/index.d.ts +3 -3
  177. package/dist/system/index.js +3 -3
  178. package/dist/system/index.js.map +1 -1
  179. package/dist/thread/index.d.ts +3 -3
  180. package/dist/thread/index.js +3 -3
  181. package/dist/thread/index.js.map +1 -1
  182. package/dist/topic/core/index.d.ts +3 -3
  183. package/dist/topic/core/index.js +3 -3
  184. package/dist/topic/core/index.js.map +1 -1
  185. package/dist/vite/index.d.ts +6286 -4
  186. package/dist/vite/index.d.ts.map +1 -1
  187. package/dist/vite/index.js +28 -2
  188. package/dist/vite/index.js.map +1 -1
  189. package/dist/websocket/index.d.ts +37 -37
  190. package/dist/websocket/index.d.ts.map +1 -1
  191. package/dist/websocket/index.js +3 -3
  192. package/dist/websocket/index.js.map +1 -1
  193. package/package.json +12 -4
  194. package/src/api/audits/controllers/AdminAuditController.ts +8 -0
  195. package/src/api/audits/index.ts +3 -3
  196. package/src/api/files/controllers/AdminFileStatsController.ts +1 -0
  197. package/src/api/files/index.ts +3 -3
  198. package/src/api/jobs/controllers/AdminJobController.ts +18 -2
  199. package/src/api/jobs/index.ts +4 -3
  200. package/src/api/jobs/services/JobAudits.spec.ts +89 -0
  201. package/src/api/jobs/services/JobAudits.ts +101 -0
  202. package/src/api/keys/index.ts +3 -3
  203. package/src/api/notifications/controllers/AdminNotificationController.ts +1 -0
  204. package/src/api/notifications/index.ts +3 -3
  205. package/src/api/parameters/controllers/AdminConfigController.ts +10 -0
  206. package/src/api/parameters/index.ts +5 -3
  207. package/src/api/users/__tests__/ApiKeys-integration.spec.ts +1 -1
  208. package/src/api/users/__tests__/ApiKeys.spec.ts +1 -1
  209. package/src/api/users/__tests__/EmailVerification.spec.ts +16 -1
  210. package/src/api/users/__tests__/PasswordReset.spec.ts +11 -0
  211. package/src/api/users/atoms/realmAuthSettingsAtom.ts +10 -0
  212. package/src/api/users/controllers/AdminIdentityController.ts +3 -0
  213. package/src/api/users/controllers/AdminSessionController.ts +3 -0
  214. package/src/api/users/controllers/AdminUserController.ts +5 -0
  215. package/src/api/users/index.ts +8 -9
  216. package/src/api/users/primitives/$realm.ts +117 -19
  217. package/src/api/users/providers/RealmProvider.ts +15 -7
  218. package/src/api/users/services/CredentialService.spec.ts +11 -0
  219. package/src/api/users/services/CredentialService.ts +47 -24
  220. package/src/api/users/services/IdentityService.ts +12 -4
  221. package/src/api/users/services/RegistrationService.spec.ts +11 -0
  222. package/src/api/users/services/RegistrationService.ts +33 -12
  223. package/src/api/users/services/SessionService.ts +83 -12
  224. package/src/api/users/services/UserAudits.ts +47 -0
  225. package/src/api/users/services/UserFiles.ts +19 -0
  226. package/src/api/users/services/UserJobs.spec.ts +107 -0
  227. package/src/api/users/services/UserJobs.ts +62 -0
  228. package/src/api/users/services/UserParameters.ts +23 -0
  229. package/src/api/users/services/UserService.ts +34 -17
  230. package/src/api/verifications/index.ts +3 -3
  231. package/src/batch/index.ts +3 -3
  232. package/src/bucket/index.ts +3 -3
  233. package/src/cache/core/index.ts +3 -3
  234. package/src/cli/commands/build.ts +1 -0
  235. package/src/cli/commands/db.ts +9 -0
  236. package/src/cli/commands/init.spec.ts +2 -17
  237. package/src/cli/commands/init.ts +37 -1
  238. package/src/cli/providers/ViteDevServerProvider.ts +36 -2
  239. package/src/cli/services/AlephaCliUtils.ts +17 -0
  240. package/src/cli/services/PackageManagerUtils.ts +15 -1
  241. package/src/cli/services/ProjectScaffolder.ts +8 -13
  242. package/src/cli/templates/agentMd.ts +2 -25
  243. package/src/cli/templates/apiAppSecurityTs.ts +37 -2
  244. package/src/cli/templates/mainCss.ts +2 -32
  245. package/src/cli/templates/webAppRouterTs.ts +5 -5
  246. package/src/cli/templates/webHomeComponentTsx.ts +10 -0
  247. package/src/command/helpers/Runner.ts +14 -1
  248. package/src/command/index.ts +3 -3
  249. package/src/core/helpers/primitive.ts +0 -5
  250. package/src/core/index.ts +3 -3
  251. package/src/datetime/index.ts +3 -3
  252. package/src/email/index.ts +3 -3
  253. package/src/email/index.workerd.ts +36 -0
  254. package/src/email/providers/LocalEmailProvider.ts +2 -2
  255. package/src/email/providers/WorkermailerEmailProvider.ts +221 -0
  256. package/src/fake/index.ts +3 -3
  257. package/src/lock/core/index.ts +3 -3
  258. package/src/lock/core/primitives/$lock.ts +13 -1
  259. package/src/logger/index.ts +3 -3
  260. package/src/logger/providers/PrettyFormatterProvider.ts +7 -0
  261. package/src/mcp/index.ts +3 -3
  262. package/src/orm/index.ts +3 -3
  263. package/src/orm/providers/drivers/NodeSqliteProvider.ts +1 -1
  264. package/src/queue/core/index.ts +3 -3
  265. package/src/react/auth/index.ts +3 -3
  266. package/src/react/auth/services/ReactAuth.ts +3 -1
  267. package/src/react/core/index.ts +3 -3
  268. package/src/react/form/index.ts +3 -3
  269. package/src/react/head/index.ts +3 -3
  270. package/src/react/i18n/index.ts +3 -3
  271. package/src/react/intro/components/GettingStarted.css +334 -0
  272. package/src/react/intro/components/GettingStarted.tsx +276 -0
  273. package/src/react/intro/index.ts +1 -0
  274. package/src/react/router/atoms/ssrManifestAtom.ts +7 -0
  275. package/src/react/router/index.browser.ts +2 -0
  276. package/src/react/router/index.ts +2 -0
  277. package/src/react/router/providers/ReactServerProvider.ts +14 -4
  278. package/src/react/router/providers/SSRManifestProvider.ts +7 -0
  279. package/src/redis/index.ts +3 -3
  280. package/src/retry/index.ts +3 -3
  281. package/src/router/index.ts +3 -3
  282. package/src/scheduler/index.ts +3 -3
  283. package/src/scheduler/index.workerd.ts +43 -0
  284. package/src/scheduler/providers/CronProvider.ts +53 -6
  285. package/src/scheduler/providers/WorkerdCronProvider.ts +102 -0
  286. package/src/security/index.ts +3 -3
  287. package/src/security/providers/JwtProvider.ts +2 -2
  288. package/src/server/auth/index.ts +3 -3
  289. package/src/server/cache/index.ts +3 -3
  290. package/src/server/compress/index.ts +3 -3
  291. package/src/server/compress/providers/ServerCompressProvider.ts +6 -0
  292. package/src/server/cookies/index.ts +3 -3
  293. package/src/server/core/index.ts +3 -3
  294. package/src/server/core/primitives/$action.spec.ts +3 -2
  295. package/src/server/core/primitives/$action.ts +6 -2
  296. package/src/server/core/providers/NodeHttpServerProvider.ts +2 -15
  297. package/src/server/core/providers/ServerProvider.ts +4 -2
  298. package/src/server/core/providers/ServerRouterProvider.ts +5 -27
  299. package/src/server/cors/index.ts +3 -3
  300. package/src/server/health/index.ts +3 -3
  301. package/src/server/helmet/index.ts +3 -3
  302. package/src/server/links/index.ts +3 -3
  303. package/src/server/links/providers/ServerLinksProvider.spec.ts +332 -0
  304. package/src/server/links/providers/ServerLinksProvider.ts +1 -1
  305. package/src/server/metrics/index.ts +3 -3
  306. package/src/server/multipart/index.ts +3 -3
  307. package/src/server/proxy/index.ts +3 -3
  308. package/src/server/rate-limit/index.ts +3 -3
  309. package/src/server/static/index.ts +3 -3
  310. package/src/server/swagger/index.ts +3 -3
  311. package/src/sms/index.ts +3 -3
  312. package/src/system/index.ts +3 -3
  313. package/src/thread/index.ts +3 -3
  314. package/src/topic/core/index.ts +3 -3
  315. package/src/vite/tasks/generateCloudflare.ts +38 -2
  316. package/src/websocket/index.ts +3 -3
  317. package/src/cli/templates/webHelloComponentTsx.ts +0 -30
  318. /package/src/api/users/{notifications → services}/UserNotifications.ts +0 -0
@@ -0,0 +1,89 @@
1
+ import { Alepha } from "alepha";
2
+ import { AlephaApiAudits, AuditService } from "alepha/api/audits";
3
+ import { AlephaOrm } from "alepha/orm";
4
+ import { describe, test } from "vitest";
5
+ import { JobAudits } from "./JobAudits.ts";
6
+
7
+ describe("JobAudits", () => {
8
+ test("should log trigger event", async ({ expect }) => {
9
+ const alepha = Alepha.create().with(AlephaOrm).with(AlephaApiAudits);
10
+
11
+ const jobAudits = alepha.inject(JobAudits);
12
+ const auditService = alepha.inject(AuditService);
13
+ await alepha.start();
14
+
15
+ // Log a trigger event
16
+ await jobAudits.logTrigger("my-test-job");
17
+
18
+ // Verify audit was recorded
19
+ const audits = await auditService.find({ type: "job", action: "trigger" });
20
+
21
+ expect(audits.content).toHaveLength(1);
22
+ expect(audits.content[0].type).toBe("job");
23
+ expect(audits.content[0].action).toBe("trigger");
24
+ expect(audits.content[0].resourceType).toBe("job");
25
+ expect(audits.content[0].resourceId).toBe("my-test-job");
26
+ expect(audits.content[0].description).toBe(
27
+ "Manually triggered job: my-test-job",
28
+ );
29
+ });
30
+
31
+ test("should log pause event", async ({ expect }) => {
32
+ const alepha = Alepha.create().with(AlephaOrm).with(AlephaApiAudits);
33
+
34
+ const jobAudits = alepha.inject(JobAudits);
35
+ const auditService = alepha.inject(AuditService);
36
+ await alepha.start();
37
+
38
+ await jobAudits.logPause("daily-cleanup");
39
+
40
+ const audits = await auditService.find({ type: "job", action: "pause" });
41
+
42
+ expect(audits.content).toHaveLength(1);
43
+ expect(audits.content[0].resourceId).toBe("daily-cleanup");
44
+ expect(audits.content[0].description).toBe("Paused job: daily-cleanup");
45
+ });
46
+
47
+ test("should log schedule change with cron metadata", async ({ expect }) => {
48
+ const alepha = Alepha.create().with(AlephaOrm).with(AlephaApiAudits);
49
+
50
+ const jobAudits = alepha.inject(JobAudits);
51
+ const auditService = alepha.inject(AuditService);
52
+ await alepha.start();
53
+
54
+ await jobAudits.logScheduleChange("backup-job", {
55
+ oldCron: "0 0 * * *",
56
+ newCron: "0 3 * * *",
57
+ });
58
+
59
+ const audits = await auditService.find({
60
+ type: "job",
61
+ action: "schedule_change",
62
+ });
63
+
64
+ expect(audits.content).toHaveLength(1);
65
+ expect(audits.content[0].resourceId).toBe("backup-job");
66
+ expect(audits.content[0].metadata).toEqual({
67
+ oldCron: "0 0 * * *",
68
+ newCron: "0 3 * * *",
69
+ });
70
+ });
71
+
72
+ test("should register job audit type", async ({ expect }) => {
73
+ const alepha = Alepha.create().with(AlephaOrm).with(AlephaApiAudits);
74
+
75
+ alepha.inject(JobAudits);
76
+ const auditService = alepha.inject(AuditService);
77
+ await alepha.start();
78
+
79
+ const types = auditService.getRegisteredTypes();
80
+ const jobType = types.find((t) => t.type === "job");
81
+
82
+ expect(jobType).toBeDefined();
83
+ expect(jobType?.actions).toContain("trigger");
84
+ expect(jobType?.actions).toContain("pause");
85
+ expect(jobType?.actions).toContain("resume");
86
+ expect(jobType?.actions).toContain("cancel");
87
+ expect(jobType?.actions).toContain("schedule_change");
88
+ });
89
+ });
@@ -0,0 +1,101 @@
1
+ import { $audit, type AuditLogOptions } from "alepha/api/audits";
2
+
3
+ /**
4
+ * Job-specific audit service.
5
+ *
6
+ * Provides type-safe audit logging for job-related events.
7
+ * This service is lazy-loaded when the audits feature is enabled.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * const jobAudits = alepha.inject(JobAudits);
12
+ * await jobAudits.logTrigger("my-job", { description: "Manually triggered" });
13
+ * ```
14
+ */
15
+ export class JobAudits {
16
+ protected readonly audit = $audit({
17
+ type: "job",
18
+ description: "Background job execution events",
19
+ actions: ["trigger", "pause", "resume", "cancel", "schedule_change"],
20
+ });
21
+
22
+ /**
23
+ * Log a manual job trigger event.
24
+ */
25
+ public async logTrigger(
26
+ jobName: string,
27
+ options: Omit<AuditLogOptions, "resourceType" | "resourceId"> = {},
28
+ ) {
29
+ await this.audit.log("trigger", {
30
+ ...options,
31
+ resourceType: "job",
32
+ resourceId: jobName,
33
+ description: options.description ?? `Manually triggered job: ${jobName}`,
34
+ });
35
+ }
36
+
37
+ /**
38
+ * Log a job pause event.
39
+ */
40
+ public async logPause(
41
+ jobName: string,
42
+ options: Omit<AuditLogOptions, "resourceType" | "resourceId"> = {},
43
+ ) {
44
+ await this.audit.log("pause", {
45
+ ...options,
46
+ resourceType: "job",
47
+ resourceId: jobName,
48
+ description: options.description ?? `Paused job: ${jobName}`,
49
+ });
50
+ }
51
+
52
+ /**
53
+ * Log a job resume event.
54
+ */
55
+ public async logResume(
56
+ jobName: string,
57
+ options: Omit<AuditLogOptions, "resourceType" | "resourceId"> = {},
58
+ ) {
59
+ await this.audit.log("resume", {
60
+ ...options,
61
+ resourceType: "job",
62
+ resourceId: jobName,
63
+ description: options.description ?? `Resumed job: ${jobName}`,
64
+ });
65
+ }
66
+
67
+ /**
68
+ * Log a job cancellation event.
69
+ */
70
+ public async logCancel(
71
+ jobName: string,
72
+ options: Omit<AuditLogOptions, "resourceType" | "resourceId"> = {},
73
+ ) {
74
+ await this.audit.log("cancel", {
75
+ ...options,
76
+ resourceType: "job",
77
+ resourceId: jobName,
78
+ description: options.description ?? `Cancelled job: ${jobName}`,
79
+ });
80
+ }
81
+
82
+ /**
83
+ * Log a job schedule change event.
84
+ */
85
+ public async logScheduleChange(
86
+ jobName: string,
87
+ options: Omit<AuditLogOptions, "resourceType" | "resourceId"> & {
88
+ oldCron?: string;
89
+ newCron?: string;
90
+ } = {},
91
+ ) {
92
+ const { oldCron, newCron, ...rest } = options;
93
+ await this.audit.log("schedule_change", {
94
+ ...rest,
95
+ resourceType: "job",
96
+ resourceId: jobName,
97
+ description: rest.description ?? `Changed schedule for job: ${jobName}`,
98
+ metadata: { oldCron, newCron, ...rest.metadata },
99
+ });
100
+ }
101
+ }
@@ -16,9 +16,9 @@ export * from "./schemas/revokeApiKeyResponseSchema.ts";
16
16
  export * from "./services/ApiKeyService.ts";
17
17
 
18
18
  /**
19
- * | type | quality | stability |
20
- * |------|---------|--------------|
21
- * | backend | good | experimental |
19
+ * | Stability | Since | Runtime |
20
+ * |-----------|-------|---------|
21
+ * | 3 - stable | 0.11.0 | node, bun, workerd|
22
22
  *
23
23
  * API key management module for programmatic access.
24
24
  *
@@ -15,6 +15,7 @@ export class AdminNotificationController {
15
15
  public readonly findNotifications = $action({
16
16
  path: this.url,
17
17
  group: this.group,
18
+ secure: true,
18
19
  description: "Find notifications with pagination and filtering",
19
20
  schema: {
20
21
  query: notificationQuerySchema,
@@ -25,9 +25,9 @@ export * from "./services/NotificationService.ts";
25
25
  // ---------------------------------------------------------------------------------------------------------------------
26
26
 
27
27
  /**
28
- * | type | quality | stability |
29
- * |------|---------|-----------|
30
- * | backend | standard | stable |
28
+ * | Stability | Since | Runtime |
29
+ * |-----------|-------|---------|
30
+ * | 3 - stable | 0.10.0 | node, bun, workerd|
31
31
  *
32
32
  * User notification management.
33
33
  *
@@ -41,6 +41,7 @@ export class AdminConfigController {
41
41
  */
42
42
  getConfigTree = $action({
43
43
  group: this.group,
44
+ secure: true,
44
45
  description:
45
46
  "Get tree structure of all configuration names for navigation.",
46
47
  path: "/configs/tree",
@@ -58,6 +59,7 @@ export class AdminConfigController {
58
59
  */
59
60
  listConfigNames = $action({
60
61
  group: this.group,
62
+ secure: true,
61
63
  description: "List all unique configuration names.",
62
64
  path: "/configs",
63
65
  method: "GET",
@@ -75,6 +77,7 @@ export class AdminConfigController {
75
77
  */
76
78
  getByStatus = $action({
77
79
  group: this.group,
80
+ secure: true,
78
81
  description: "Get all configurations with a specific status.",
79
82
  path: "/configs/status/:status",
80
83
  method: "GET",
@@ -95,6 +98,7 @@ export class AdminConfigController {
95
98
  */
96
99
  getHistory = $action({
97
100
  group: this.group,
101
+ secure: true,
98
102
  description: "Get all versions of a specific configuration.",
99
103
  path: "/configs/:name/history",
100
104
  method: "GET",
@@ -115,6 +119,7 @@ export class AdminConfigController {
115
119
  */
116
120
  getCurrent = $action({
117
121
  group: this.group,
122
+ secure: true,
118
123
  description: "Get current and next scheduled values for a configuration.",
119
124
  path: "/configs/:name",
120
125
  method: "GET",
@@ -139,6 +144,7 @@ export class AdminConfigController {
139
144
  */
140
145
  getVersion = $action({
141
146
  group: this.group,
147
+ secure: true,
142
148
  description: "Get a specific version of a configuration.",
143
149
  path: "/configs/:name/versions/:version",
144
150
  method: "GET",
@@ -157,6 +163,7 @@ export class AdminConfigController {
157
163
  */
158
164
  createVersion = $action({
159
165
  group: this.group,
166
+ secure: true,
160
167
  description:
161
168
  "Create a new version of a configuration (immediate or scheduled).",
162
169
  path: "/configs/:name",
@@ -184,6 +191,7 @@ export class AdminConfigController {
184
191
  */
185
192
  rollback = $action({
186
193
  group: this.group,
194
+ secure: true,
187
195
  description:
188
196
  "Rollback a configuration to a previous version (creates new version with old content).",
189
197
  path: "/configs/:name/rollback",
@@ -207,6 +215,7 @@ export class AdminConfigController {
207
215
  */
208
216
  activateNow = $action({
209
217
  group: this.group,
218
+ secure: true,
210
219
  description: "Activate a future/next configuration version immediately.",
211
220
  path: "/configs/:name/activate",
212
221
  method: "POST",
@@ -248,6 +257,7 @@ export class AdminConfigController {
248
257
  */
249
258
  checkScheduled = $action({
250
259
  group: this.group,
260
+ secure: true,
251
261
  description:
252
262
  "Manually trigger activation check for all scheduled configurations.",
253
263
  path: "/configs/activate-scheduled",
@@ -1,5 +1,6 @@
1
1
  import { $module } from "alepha";
2
2
  import { AdminConfigController } from "./controllers/AdminConfigController.ts";
3
+ import { $config } from "./primitives/$config.ts";
3
4
  import { ConfigActivationScheduler } from "./schedulers/ConfigActivationScheduler.ts";
4
5
  import { ConfigStore } from "./services/ConfigStore.ts";
5
6
 
@@ -19,9 +20,9 @@ export * from "./services/ConfigStore.ts";
19
20
  // ---------------------------------------------------------------------------------------------------------------------
20
21
 
21
22
  /**
22
- * | type | quality | stability |
23
- * |------|---------|-----------|
24
- * | backend | standard | stable |
23
+ * | Stability | Since | Runtime |
24
+ * |-----------|-------|---------|
25
+ * | 3 - stable | 0.9.0 | node, bun, workerd|
25
26
  *
26
27
  * Application configuration management.
27
28
  *
@@ -35,5 +36,6 @@ export * from "./services/ConfigStore.ts";
35
36
  */
36
37
  export const AlephaApiParameters = $module({
37
38
  name: "alepha.api.parameters",
39
+ primitives: [$config],
38
40
  services: [ConfigStore, AdminConfigController, ConfigActivationScheduler],
39
41
  });
@@ -33,7 +33,7 @@ const setup = async () => {
33
33
  // Create a realm with API keys enabled
34
34
  class TestApp {
35
35
  realm = $realm({
36
- apiKeys: true,
36
+ features: { apiKeys: true },
37
37
  });
38
38
 
39
39
  // A protected action to test API key authentication (any authenticated user)
@@ -20,7 +20,7 @@ const setup = async () => {
20
20
  // Create a realm with API keys enabled
21
21
  class TestApp {
22
22
  realm = $realm({
23
- apiKeys: true,
23
+ features: { apiKeys: true },
24
24
  });
25
25
  }
26
26
 
@@ -5,7 +5,13 @@ import { AlephaEmail, MemoryEmailProvider } from "alepha/email";
5
5
  import { AlephaSecurity } from "alepha/security";
6
6
  import { BadRequestError } from "alepha/server";
7
7
  import { describe, it } from "vitest";
8
- import { AlephaApiUsers, UserController, UserService } from "../index.ts";
8
+ import {
9
+ AlephaApiUsers,
10
+ RealmProvider,
11
+ UserController,
12
+ UserNotifications,
13
+ UserService,
14
+ } from "../index.ts";
9
15
 
10
16
  const setup = async () => {
11
17
  const alepha = Alepha.create({
@@ -16,9 +22,18 @@ const setup = async () => {
16
22
  alepha.with(AlephaEmail);
17
23
  alepha.with(AlephaApiVerification);
18
24
  alepha.with(AlephaApiUsers);
25
+ alepha.with(UserNotifications);
19
26
 
20
27
  await alepha.start();
21
28
 
29
+ // Enable notifications for the default realm
30
+ const realmProvider = alepha.inject(RealmProvider);
31
+ realmProvider.register("default", {
32
+ features: {
33
+ notifications: true,
34
+ },
35
+ });
36
+
22
37
  const emailProvider = alepha.inject(MemoryEmailProvider);
23
38
  emailProvider.records = [];
24
39
 
@@ -8,8 +8,10 @@ import { describe, it } from "vitest";
8
8
  import {
9
9
  AlephaApiUsers,
10
10
  CredentialService,
11
+ RealmProvider,
11
12
  SessionService,
12
13
  UserController,
14
+ UserNotifications,
13
15
  } from "../index.ts";
14
16
 
15
17
  const setup = async () => {
@@ -21,9 +23,18 @@ const setup = async () => {
21
23
  alepha.with(AlephaEmail);
22
24
  alepha.with(AlephaApiVerification);
23
25
  alepha.with(AlephaApiUsers);
26
+ alepha.with(UserNotifications);
24
27
 
25
28
  await alepha.start();
26
29
 
30
+ // Enable notifications for the default realm
31
+ const realmProvider = alepha.inject(RealmProvider);
32
+ realmProvider.register("default", {
33
+ features: {
34
+ notifications: true,
35
+ },
36
+ });
37
+
27
38
  const emailProvider = alepha.inject(MemoryEmailProvider);
28
39
  emailProvider.records = [];
29
40
 
@@ -62,6 +62,14 @@ export const realmAuthSettingsAtom = $atom({
62
62
  resetPasswordAllowed: t.boolean({
63
63
  description: "Enable forgot password functionality",
64
64
  }),
65
+ adminEmails: t.array(t.email(), {
66
+ description:
67
+ "List of email addresses that are automatically promoted to admin role on login",
68
+ }),
69
+ adminUsernames: t.array(t.text(), {
70
+ description:
71
+ "List of usernames that are automatically promoted to admin role on login",
72
+ }),
65
73
  passwordPolicy: t.object({
66
74
  minLength: t.integer({
67
75
  description: "Minimum password length",
@@ -97,6 +105,8 @@ export const realmAuthSettingsAtom = $atom({
97
105
  resetPasswordAllowed: false,
98
106
  firstNameLastNameEnabled: false,
99
107
  firstNameLastNameRequired: false,
108
+ adminEmails: [],
109
+ adminUsernames: [],
100
110
  // TODO: not implemented yet
101
111
  passwordPolicy: {
102
112
  minLength: 8,
@@ -15,6 +15,7 @@ export class AdminIdentityController {
15
15
  public readonly findIdentities = $action({
16
16
  path: this.url,
17
17
  group: this.group,
18
+ secure: true,
18
19
  description: "Find identities with pagination and filtering",
19
20
  schema: {
20
21
  query: t.extend(identityQuerySchema, {
@@ -34,6 +35,7 @@ export class AdminIdentityController {
34
35
  public readonly getIdentity = $action({
35
36
  path: `${this.url}/:id`,
36
37
  group: this.group,
38
+ secure: true,
37
39
  description: "Get an identity by ID",
38
40
  schema: {
39
41
  params: t.object({
@@ -55,6 +57,7 @@ export class AdminIdentityController {
55
57
  method: "DELETE",
56
58
  path: `${this.url}/:id`,
57
59
  group: this.group,
60
+ secure: true,
58
61
  description: "Delete an identity",
59
62
  schema: {
60
63
  params: t.object({
@@ -15,6 +15,7 @@ export class AdminSessionController {
15
15
  public readonly findSessions = $action({
16
16
  path: this.url,
17
17
  group: this.group,
18
+ secure: true,
18
19
  description: "Find sessions with pagination and filtering",
19
20
  schema: {
20
21
  query: t.extend(sessionQuerySchema, {
@@ -34,6 +35,7 @@ export class AdminSessionController {
34
35
  public readonly getSession = $action({
35
36
  path: `${this.url}/:id`,
36
37
  group: this.group,
38
+ secure: true,
37
39
  description: "Get a session by ID",
38
40
  schema: {
39
41
  params: t.object({
@@ -55,6 +57,7 @@ export class AdminSessionController {
55
57
  method: "DELETE",
56
58
  path: `${this.url}/:id`,
57
59
  group: this.group,
60
+ secure: true,
58
61
  description: "Delete a session",
59
62
  schema: {
60
63
  params: t.object({
@@ -17,6 +17,7 @@ export class AdminUserController {
17
17
  public readonly findUsers = $action({
18
18
  path: this.url,
19
19
  group: this.group,
20
+ secure: true,
20
21
  description: "Find users with pagination and filtering",
21
22
  schema: {
22
23
  query: t.extend(userQuerySchema, {
@@ -36,6 +37,7 @@ export class AdminUserController {
36
37
  public readonly getUser = $action({
37
38
  path: `${this.url}/:id`,
38
39
  group: this.group,
40
+ secure: true,
39
41
  description: "Get a user by ID",
40
42
  schema: {
41
43
  params: t.object({
@@ -57,6 +59,7 @@ export class AdminUserController {
57
59
  method: "POST",
58
60
  path: this.url,
59
61
  group: this.group,
62
+ secure: true,
60
63
  description: "Create a new user",
61
64
  schema: {
62
65
  query: t.object({
@@ -76,6 +79,7 @@ export class AdminUserController {
76
79
  method: "PATCH",
77
80
  path: `${this.url}/:id`,
78
81
  group: this.group,
82
+ secure: true,
79
83
  description: "Update a user",
80
84
  schema: {
81
85
  params: t.object({
@@ -98,6 +102,7 @@ export class AdminUserController {
98
102
  method: "DELETE",
99
103
  path: `${this.url}/:id`,
100
104
  group: this.group,
105
+ secure: true,
101
106
  description: "Delete a user",
102
107
  schema: {
103
108
  params: t.object({
@@ -1,6 +1,4 @@
1
1
  import { $module } from "alepha";
2
- import { 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";
@@ -9,7 +7,6 @@ import { AdminSessionController } from "./controllers/AdminSessionController.ts"
9
7
  import { AdminUserController } from "./controllers/AdminUserController.ts";
10
8
  import { RealmController } from "./controllers/RealmController.ts";
11
9
  import { UserController } from "./controllers/UserController.ts";
12
- import { UserNotifications } from "./notifications/UserNotifications.ts";
13
10
  import { RealmProvider } from "./providers/RealmProvider.ts";
14
11
  import { CredentialService } from "./services/CredentialService.ts";
15
12
  import { IdentityService } from "./services/IdentityService.ts";
@@ -52,14 +49,19 @@ export * from "./services/IdentityService.ts";
52
49
  export * from "./services/RegistrationService.ts";
53
50
  export * from "./services/SessionCrudService.ts";
54
51
  export * from "./services/SessionService.ts";
52
+ export * from "./services/UserAudits.ts";
53
+ export * from "./services/UserFiles.ts";
54
+ export * from "./services/UserJobs.ts";
55
+ export * from "./services/UserNotifications.ts";
56
+ export * from "./services/UserParameters.ts";
55
57
  export * from "./services/UserService.ts";
56
58
 
57
59
  // ---------------------------------------------------------------------------------------------------------------------
58
60
 
59
61
  /**
60
- * | type | quality | stability |
61
- * |------|---------|-----------|
62
- * | backend | epic | stable |
62
+ * | Stability | Since | Runtime |
63
+ * |-----------|-------|---------|
64
+ * | 3 - stable | 0.5.0 | node, bun, workerd|
63
65
  *
64
66
  * Complete user management with multi-realm support for multi-tenant applications.
65
67
  *
@@ -78,8 +80,6 @@ export * from "./services/UserService.ts";
78
80
  export const AlephaApiUsers = $module({
79
81
  name: "alepha.api.users",
80
82
  services: [
81
- AlephaApiVerification,
82
- AlephaApiNotifications,
83
83
  AlephaServerHelmet,
84
84
  AlephaServerCompress,
85
85
  AlephaEmail,
@@ -95,6 +95,5 @@ export const AlephaApiUsers = $module({
95
95
  AdminSessionController,
96
96
  AdminIdentityController,
97
97
  RealmController,
98
- UserNotifications,
99
98
  ],
100
99
  });