alepha 0.21.2 → 0.22.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 (463) hide show
  1. package/README.md +0 -1
  2. package/dist/api/audits/index.browser.js.map +1 -1
  3. package/dist/api/audits/index.d.ts +393 -403
  4. package/dist/api/audits/index.d.ts.map +1 -1
  5. package/dist/api/audits/index.js +25 -56
  6. package/dist/api/audits/index.js.map +1 -1
  7. package/dist/api/files/index.browser.js +31 -1
  8. package/dist/api/files/index.browser.js.map +1 -1
  9. package/dist/api/files/index.d.ts +313 -208
  10. package/dist/api/files/index.d.ts.map +1 -1
  11. package/dist/api/files/index.js +152 -42
  12. package/dist/api/files/index.js.map +1 -1
  13. package/dist/api/jobs/index.browser.js +2 -2
  14. package/dist/api/jobs/index.browser.js.map +1 -1
  15. package/dist/api/jobs/index.d.ts +289 -292
  16. package/dist/api/jobs/index.d.ts.map +1 -1
  17. package/dist/api/jobs/index.js +39 -33
  18. package/dist/api/jobs/index.js.map +1 -1
  19. package/dist/api/keys/index.d.ts +211 -216
  20. package/dist/api/keys/index.d.ts.map +1 -1
  21. package/dist/api/keys/index.js.map +1 -1
  22. package/dist/api/notifications/index.browser.js.map +1 -1
  23. package/dist/api/notifications/index.d.ts +188 -195
  24. package/dist/api/notifications/index.d.ts.map +1 -1
  25. package/dist/api/notifications/index.js.map +1 -1
  26. package/dist/api/oauth/index.d.ts +71 -76
  27. package/dist/api/oauth/index.d.ts.map +1 -1
  28. package/dist/api/oauth/index.js.map +1 -1
  29. package/dist/api/organizations/index.browser.js.map +1 -1
  30. package/dist/api/organizations/index.d.ts +104 -109
  31. package/dist/api/organizations/index.d.ts.map +1 -1
  32. package/dist/api/organizations/index.js.map +1 -1
  33. package/dist/api/parameters/index.browser.js +43 -16
  34. package/dist/api/parameters/index.browser.js.map +1 -1
  35. package/dist/api/parameters/index.d.ts +488 -344
  36. package/dist/api/parameters/index.d.ts.map +1 -1
  37. package/dist/api/parameters/index.js +175 -35
  38. package/dist/api/parameters/index.js.map +1 -1
  39. package/dist/api/payments/index.d.ts +396 -402
  40. package/dist/api/payments/index.d.ts.map +1 -1
  41. package/dist/api/payments/index.js.map +1 -1
  42. package/dist/api/subscriptions/index.d.ts +644 -652
  43. package/dist/api/subscriptions/index.d.ts.map +1 -1
  44. package/dist/api/subscriptions/index.js +1 -1
  45. package/dist/api/subscriptions/index.js.map +1 -1
  46. package/dist/api/users/index.browser.js +7 -0
  47. package/dist/api/users/index.browser.js.map +1 -1
  48. package/dist/api/users/index.d.ts +1073 -1006
  49. package/dist/api/users/index.d.ts.map +1 -1
  50. package/dist/api/users/index.js +283 -61
  51. package/dist/api/users/index.js.map +1 -1
  52. package/dist/api/verifications/index.browser.js.map +1 -1
  53. package/dist/api/verifications/index.d.ts +134 -140
  54. package/dist/api/verifications/index.d.ts.map +1 -1
  55. package/dist/api/verifications/index.js.map +1 -1
  56. package/dist/background/index.d.ts +95 -0
  57. package/dist/background/index.d.ts.map +1 -0
  58. package/dist/background/index.js +121 -0
  59. package/dist/background/index.js.map +1 -0
  60. package/dist/background/index.workerd.js +110 -0
  61. package/dist/background/index.workerd.js.map +1 -0
  62. package/dist/batch/index.d.ts +5 -7
  63. package/dist/batch/index.d.ts.map +1 -1
  64. package/dist/batch/index.js.map +1 -1
  65. package/dist/bin/index.js.map +1 -1
  66. package/dist/bucket/index.d.ts +76 -54
  67. package/dist/bucket/index.d.ts.map +1 -1
  68. package/dist/bucket/index.js +58 -11
  69. package/dist/bucket/index.js.map +1 -1
  70. package/dist/bucket/index.workerd.js +200 -5
  71. package/dist/bucket/index.workerd.js.map +1 -1
  72. package/dist/cache/core/index.d.ts +7 -10
  73. package/dist/cache/core/index.d.ts.map +1 -1
  74. package/dist/cache/core/index.js.map +1 -1
  75. package/dist/cache/core/index.workerd.js.map +1 -1
  76. package/dist/cache/database/index.d.ts +22 -26
  77. package/dist/cache/database/index.d.ts.map +1 -1
  78. package/dist/cache/database/index.js.map +1 -1
  79. package/dist/cache/redis/index.d.ts +4 -7
  80. package/dist/cache/redis/index.d.ts.map +1 -1
  81. package/dist/cache/redis/index.js.map +1 -1
  82. package/dist/captcha/index.d.ts +3 -6
  83. package/dist/captcha/index.d.ts.map +1 -1
  84. package/dist/captcha/index.js.map +1 -1
  85. package/dist/cli/config/index.d.ts.map +1 -1
  86. package/dist/cli/config/index.js.map +1 -1
  87. package/dist/cli/core/index.d.ts +417 -214
  88. package/dist/cli/core/index.d.ts.map +1 -1
  89. package/dist/cli/core/index.js +325 -563
  90. package/dist/cli/core/index.js.map +1 -1
  91. package/dist/cli/devtools/index.d.ts +3 -5
  92. package/dist/cli/devtools/index.d.ts.map +1 -1
  93. package/dist/cli/devtools/index.js.map +1 -1
  94. package/dist/cli/i18n/index.d.ts +8 -12
  95. package/dist/cli/i18n/index.d.ts.map +1 -1
  96. package/dist/cli/i18n/index.js.map +1 -1
  97. package/dist/cli/platform/index.d.ts +126 -1342
  98. package/dist/cli/platform/index.d.ts.map +1 -1
  99. package/dist/cli/platform/index.js +136 -2374
  100. package/dist/cli/platform/index.js.map +1 -1
  101. package/dist/cli/platform-lib/index.d.ts +1446 -0
  102. package/dist/cli/platform-lib/index.d.ts.map +1 -0
  103. package/dist/cli/platform-lib/index.js +2597 -0
  104. package/dist/cli/platform-lib/index.js.map +1 -0
  105. package/dist/cli/vendor/index.d.ts +17 -21
  106. package/dist/cli/vendor/index.d.ts.map +1 -1
  107. package/dist/cli/vendor/index.js.map +1 -1
  108. package/dist/command/index.d.ts +21 -20
  109. package/dist/command/index.d.ts.map +1 -1
  110. package/dist/command/index.js +39 -10
  111. package/dist/command/index.js.map +1 -1
  112. package/dist/{containers → container}/core/index.d.ts +13 -15
  113. package/dist/container/core/index.d.ts.map +1 -0
  114. package/dist/{containers → container}/core/index.js +23 -14
  115. package/dist/container/core/index.js.map +1 -0
  116. package/dist/{containers → container}/core/index.workerd.js +37 -22
  117. package/dist/container/core/index.workerd.js.map +1 -0
  118. package/dist/core/index.browser.js +27 -1
  119. package/dist/core/index.browser.js.map +1 -1
  120. package/dist/core/index.d.ts +48 -24
  121. package/dist/core/index.d.ts.map +1 -1
  122. package/dist/core/index.js +27 -1
  123. package/dist/core/index.js.map +1 -1
  124. package/dist/core/index.native.js +27 -1
  125. package/dist/core/index.native.js.map +1 -1
  126. package/dist/core/index.workerd.js +27 -1
  127. package/dist/core/index.workerd.js.map +1 -1
  128. package/dist/crypto/index.browser.js.map +1 -1
  129. package/dist/crypto/index.d.ts +5 -8
  130. package/dist/crypto/index.d.ts.map +1 -1
  131. package/dist/crypto/index.js.map +1 -1
  132. package/dist/datetime/index.d.ts +3 -4
  133. package/dist/datetime/index.d.ts.map +1 -1
  134. package/dist/datetime/index.js.map +1 -1
  135. package/dist/email/brevo/index.d.ts +2 -4
  136. package/dist/email/brevo/index.d.ts.map +1 -1
  137. package/dist/email/brevo/index.js.map +1 -1
  138. package/dist/email/cloudflare/index.d.ts +20 -7
  139. package/dist/email/cloudflare/index.d.ts.map +1 -1
  140. package/dist/email/cloudflare/index.js +46 -9
  141. package/dist/email/cloudflare/index.js.map +1 -1
  142. package/dist/email/core/index.d.ts +6 -9
  143. package/dist/email/core/index.d.ts.map +1 -1
  144. package/dist/email/core/index.js.map +1 -1
  145. package/dist/email/core/index.workerd.js.map +1 -1
  146. package/dist/email/smtp/index.d.ts +10 -13
  147. package/dist/email/smtp/index.d.ts.map +1 -1
  148. package/dist/email/smtp/index.js +107 -32
  149. package/dist/email/smtp/index.js.map +1 -1
  150. package/dist/fake/index.d.ts +1 -2
  151. package/dist/fake/index.d.ts.map +1 -1
  152. package/dist/fake/index.js.map +1 -1
  153. package/dist/lock/core/index.d.ts +9 -14
  154. package/dist/lock/core/index.d.ts.map +1 -1
  155. package/dist/lock/core/index.js.map +1 -1
  156. package/dist/lock/redis/index.d.ts +2 -4
  157. package/dist/lock/redis/index.d.ts.map +1 -1
  158. package/dist/lock/redis/index.js.map +1 -1
  159. package/dist/logger/index.d.ts +105 -76
  160. package/dist/logger/index.d.ts.map +1 -1
  161. package/dist/logger/index.js +196 -174
  162. package/dist/logger/index.js.map +1 -1
  163. package/dist/mcp/index.d.ts +16 -20
  164. package/dist/mcp/index.d.ts.map +1 -1
  165. package/dist/mcp/index.js.map +1 -1
  166. package/dist/orm/core/index.browser.js.map +1 -1
  167. package/dist/orm/core/index.bun.js +19 -1
  168. package/dist/orm/core/index.bun.js.map +1 -1
  169. package/dist/orm/core/index.d.ts +76 -62
  170. package/dist/orm/core/index.d.ts.map +1 -1
  171. package/dist/orm/core/index.js +20 -2
  172. package/dist/orm/core/index.js.map +1 -1
  173. package/dist/orm/postgres/index.bun.js.map +1 -1
  174. package/dist/orm/postgres/index.d.ts +28 -20
  175. package/dist/orm/postgres/index.d.ts.map +1 -1
  176. package/dist/orm/postgres/index.js.map +1 -1
  177. package/dist/queue/core/index.d.ts +12 -15
  178. package/dist/queue/core/index.d.ts.map +1 -1
  179. package/dist/queue/core/index.js.map +1 -1
  180. package/dist/queue/core/index.workerd.js.map +1 -1
  181. package/dist/queue/redis/index.d.ts +3 -5
  182. package/dist/queue/redis/index.d.ts.map +1 -1
  183. package/dist/queue/redis/index.js.map +1 -1
  184. package/dist/react/auth/index.browser.js +9 -2
  185. package/dist/react/auth/index.browser.js.map +1 -1
  186. package/dist/react/auth/index.d.ts +14 -9
  187. package/dist/react/auth/index.d.ts.map +1 -1
  188. package/dist/react/auth/index.js +9 -2
  189. package/dist/react/auth/index.js.map +1 -1
  190. package/dist/react/core/index.d.ts +7 -8
  191. package/dist/react/core/index.d.ts.map +1 -1
  192. package/dist/react/core/index.js +6 -3
  193. package/dist/react/core/index.js.map +1 -1
  194. package/dist/react/form/index.d.ts +2 -4
  195. package/dist/react/form/index.d.ts.map +1 -1
  196. package/dist/react/form/index.js.map +1 -1
  197. package/dist/react/head/index.browser.js.map +1 -1
  198. package/dist/react/head/index.d.ts +2 -4
  199. package/dist/react/head/index.d.ts.map +1 -1
  200. package/dist/react/head/index.js.map +1 -1
  201. package/dist/react/i18n/index.d.ts +47 -11
  202. package/dist/react/i18n/index.d.ts.map +1 -1
  203. package/dist/react/i18n/index.js +33 -1
  204. package/dist/react/i18n/index.js.map +1 -1
  205. package/dist/react/intro/index.d.ts +1 -2
  206. package/dist/react/intro/index.d.ts.map +1 -1
  207. package/dist/react/intro/index.js +2 -2
  208. package/dist/react/intro/index.js.map +1 -1
  209. package/dist/react/router/index.browser.js +65 -19
  210. package/dist/react/router/index.browser.js.map +1 -1
  211. package/dist/react/router/index.d.ts +327 -222
  212. package/dist/react/router/index.d.ts.map +1 -1
  213. package/dist/react/router/index.js +65 -29
  214. package/dist/react/router/index.js.map +1 -1
  215. package/dist/react/testing/index.d.ts +1 -2
  216. package/dist/react/testing/index.d.ts.map +1 -1
  217. package/dist/react/testing/index.js +16 -17
  218. package/dist/react/testing/index.js.map +1 -1
  219. package/dist/react/ui/index.d.ts +20 -25
  220. package/dist/react/ui/index.d.ts.map +1 -1
  221. package/dist/react/ui/index.js.map +1 -1
  222. package/dist/redis/index.bun.js.map +1 -1
  223. package/dist/redis/index.d.ts +17 -19
  224. package/dist/redis/index.d.ts.map +1 -1
  225. package/dist/redis/index.js.map +1 -1
  226. package/dist/retry/index.d.ts +2 -4
  227. package/dist/retry/index.d.ts.map +1 -1
  228. package/dist/retry/index.js.map +1 -1
  229. package/dist/router/index.d.ts.map +1 -1
  230. package/dist/router/index.js.map +1 -1
  231. package/dist/scheduler/index.d.ts +10 -13
  232. package/dist/scheduler/index.d.ts.map +1 -1
  233. package/dist/scheduler/index.js.map +1 -1
  234. package/dist/scheduler/index.workerd.js.map +1 -1
  235. package/dist/security/index.browser.js.map +1 -1
  236. package/dist/security/index.d.ts +45 -48
  237. package/dist/security/index.d.ts.map +1 -1
  238. package/dist/security/index.js.map +1 -1
  239. package/dist/server/auth/index.browser.js.map +1 -1
  240. package/dist/server/auth/index.d.ts +167 -172
  241. package/dist/server/auth/index.d.ts.map +1 -1
  242. package/dist/server/auth/index.js +4 -8
  243. package/dist/server/auth/index.js.map +1 -1
  244. package/dist/server/cookies/index.browser.js.map +1 -1
  245. package/dist/server/cookies/index.d.ts +5 -7
  246. package/dist/server/cookies/index.d.ts.map +1 -1
  247. package/dist/server/cookies/index.js.map +1 -1
  248. package/dist/server/core/index.browser.js.map +1 -1
  249. package/dist/server/core/index.d.ts +88 -73
  250. package/dist/server/core/index.d.ts.map +1 -1
  251. package/dist/server/core/index.js +19 -0
  252. package/dist/server/core/index.js.map +1 -1
  253. package/dist/server/cors/index.d.ts +11 -14
  254. package/dist/server/cors/index.d.ts.map +1 -1
  255. package/dist/server/cors/index.js.map +1 -1
  256. package/dist/server/etag/index.d.ts +6 -9
  257. package/dist/server/etag/index.d.ts.map +1 -1
  258. package/dist/server/etag/index.js.map +1 -1
  259. package/dist/server/health/index.d.ts +18 -21
  260. package/dist/server/health/index.d.ts.map +1 -1
  261. package/dist/server/health/index.js.map +1 -1
  262. package/dist/server/links/index.browser.js +2 -0
  263. package/dist/server/links/index.browser.js.map +1 -1
  264. package/dist/server/links/index.d.ts +63 -67
  265. package/dist/server/links/index.d.ts.map +1 -1
  266. package/dist/server/links/index.js +2 -0
  267. package/dist/server/links/index.js.map +1 -1
  268. package/dist/server/metrics/index.d.ts +5 -7
  269. package/dist/server/metrics/index.d.ts.map +1 -1
  270. package/dist/server/metrics/index.js.map +1 -1
  271. package/dist/server/proxy/index.d.ts +3 -5
  272. package/dist/server/proxy/index.d.ts.map +1 -1
  273. package/dist/server/proxy/index.js.map +1 -1
  274. package/dist/server/rate-limit/index.d.ts +10 -13
  275. package/dist/server/rate-limit/index.d.ts.map +1 -1
  276. package/dist/server/rate-limit/index.js.map +1 -1
  277. package/dist/server/static/index.d.ts +3 -5
  278. package/dist/server/static/index.d.ts.map +1 -1
  279. package/dist/server/static/index.js.map +1 -1
  280. package/dist/server/swagger/index.d.ts +5 -8
  281. package/dist/server/swagger/index.d.ts.map +1 -1
  282. package/dist/server/swagger/index.js.map +1 -1
  283. package/dist/sms/index.d.ts +3 -5
  284. package/dist/sms/index.d.ts.map +1 -1
  285. package/dist/sms/index.js.map +1 -1
  286. package/dist/system/index.browser.js.map +1 -1
  287. package/dist/system/index.d.ts +2 -4
  288. package/dist/system/index.d.ts.map +1 -1
  289. package/dist/system/index.js.map +1 -1
  290. package/dist/system/index.workerd.js.map +1 -1
  291. package/dist/topic/core/index.d.ts +4 -6
  292. package/dist/topic/core/index.d.ts.map +1 -1
  293. package/dist/topic/core/index.js.map +1 -1
  294. package/dist/topic/redis/index.d.ts +5 -8
  295. package/dist/topic/redis/index.d.ts.map +1 -1
  296. package/dist/topic/redis/index.js.map +1 -1
  297. package/package.json +45 -22
  298. package/src/api/audits/__tests__/AuditService.spec.ts +18 -110
  299. package/src/api/audits/controllers/AdminAuditController.ts +14 -0
  300. package/src/api/audits/services/AuditService.ts +21 -88
  301. package/src/api/files/__tests__/FileService.spec.ts +207 -2
  302. package/src/api/files/index.ts +3 -0
  303. package/src/api/files/schemas/fileCreatorSummarySchema.ts +22 -0
  304. package/src/api/files/schemas/fileResourceSchema.ts +10 -1
  305. package/src/api/files/services/FileService.ts +170 -72
  306. package/src/api/jobs/__tests__/$job.spec.ts +24 -1
  307. package/src/api/jobs/index.ts +4 -3
  308. package/src/api/jobs/primitives/$job.ts +7 -3
  309. package/src/api/jobs/providers/DirectJobDispatcher.ts +17 -36
  310. package/src/api/jobs/providers/JobProvider.ts +53 -24
  311. package/src/api/jobs/schemas/jobConfigAtom.ts +1 -1
  312. package/src/api/jobs/schemas/jobExecutionResourceSchema.ts +4 -1
  313. package/src/api/keys/schemas/adminApiKeyResourceSchema.ts +3 -1
  314. package/src/api/parameters/__tests__/$parameter.spec.ts +19 -2
  315. package/src/api/parameters/audits/ParameterAudits.ts +17 -0
  316. package/src/api/parameters/controllers/AdminParameterController.ts +95 -19
  317. package/src/api/parameters/index.ts +3 -0
  318. package/src/api/parameters/schemas/activateParameterBodySchema.ts +3 -3
  319. package/src/api/parameters/schemas/createParameterVersionBodySchema.ts +3 -2
  320. package/src/api/parameters/schemas/parameterCreatorSummarySchema.ts +25 -0
  321. package/src/api/parameters/schemas/parameterResponseSchema.ts +5 -0
  322. package/src/api/parameters/schemas/rollbackParameterBodySchema.ts +4 -2
  323. package/src/api/parameters/services/ParameterProvider.ts +69 -6
  324. package/src/api/subscriptions/jobs/SubscriptionJobs.ts +1 -1
  325. package/src/api/users/__tests__/AdminSessionController.spec.ts +37 -0
  326. package/src/api/users/audits/SessionAudits.ts +33 -0
  327. package/src/api/users/audits/UserAudits.ts +19 -43
  328. package/src/api/users/controllers/AdminUserController.ts +66 -1
  329. package/src/api/users/entities/sessions.ts +6 -0
  330. package/src/api/users/entities/users.ts +2 -0
  331. package/src/api/users/index.ts +9 -1
  332. package/src/api/users/primitives/$realm.ts +3 -0
  333. package/src/api/users/schemas/sessionResourceSchema.ts +16 -0
  334. package/src/api/users/schemas/updateUserSchema.ts +1 -8
  335. package/src/api/users/schemas/userQuerySchema.ts +7 -0
  336. package/src/api/users/services/CredentialService.ts +15 -6
  337. package/src/api/users/services/IdentityService.ts +2 -1
  338. package/src/api/users/services/RegistrationService.ts +2 -1
  339. package/src/api/users/services/SessionCrudService.ts +19 -2
  340. package/src/api/users/services/SessionService.ts +39 -19
  341. package/src/api/users/services/UserService.ts +106 -8
  342. package/src/background/__tests__/BackgroundTaskProvider.spec.ts +96 -0
  343. package/src/background/index.ts +37 -0
  344. package/src/background/index.workerd.ts +28 -0
  345. package/src/background/providers/BackgroundTaskProvider.ts +70 -0
  346. package/src/background/providers/WorkerdBackgroundTaskProvider.ts +43 -0
  347. package/src/bucket/__tests__/$bucket.spec.ts +18 -0
  348. package/src/bucket/__tests__/LocalFileStorageProvider.spec.ts +5 -0
  349. package/src/bucket/__tests__/MemoryFileStorageProvider.spec.ts +5 -0
  350. package/src/bucket/__tests__/NodeS3BucketProvider.spec.ts +23 -4
  351. package/src/bucket/__tests__/shared.ts +30 -0
  352. package/src/bucket/index.ts +5 -5
  353. package/src/bucket/index.workerd.ts +11 -4
  354. package/src/bucket/primitives/$bucket.ts +27 -0
  355. package/src/bucket/providers/FileStorageProvider.ts +13 -0
  356. package/src/bucket/providers/LocalFileStorageProvider.ts +17 -1
  357. package/src/bucket/providers/MemoryFileStorageProvider.ts +7 -0
  358. package/src/bucket/providers/{CloudflareR2Provider.ts → R2FileStorageProvider.ts} +10 -1
  359. package/src/bucket/providers/{NodeS3BucketProvider.ts → S3FileStorageProvider.ts} +27 -5
  360. package/src/cli/core/__tests__/BuildDockerTask.spec.ts +25 -1
  361. package/src/cli/core/__tests__/init.spec.ts +0 -219
  362. package/src/cli/core/commands/__tests__/BuildCommand.spec.ts +43 -0
  363. package/src/cli/core/commands/build.ts +108 -30
  364. package/src/cli/core/commands/init.ts +0 -12
  365. package/src/cli/core/commands/pack.ts +133 -0
  366. package/src/cli/core/index.ts +3 -0
  367. package/src/cli/core/providers/ViteDevServerProvider.ts +40 -16
  368. package/src/cli/core/services/PackageManagerUtils.ts +0 -16
  369. package/src/cli/core/services/ProjectScaffolder.ts +29 -291
  370. package/src/cli/core/tasks/BuildCloudflareTask.ts +353 -47
  371. package/src/cli/core/tasks/BuildDockerTask.ts +33 -3
  372. package/src/cli/core/tasks/BuildTask.ts +34 -0
  373. package/src/cli/core/templates/apiIndexTs.ts +1 -22
  374. package/src/cli/core/templates/mainCss.ts +0 -1
  375. package/src/cli/core/templates/webAppRouterTs.ts +0 -99
  376. package/src/cli/core/templates/webIndexTs.ts +1 -22
  377. package/src/cli/platform/__tests__/SecretsCommand.spec.ts +5 -3
  378. package/src/cli/platform/commands/SecretsCommand.ts +8 -6
  379. package/src/cli/platform/commands/platform.ts +192 -46
  380. package/src/cli/platform/index.ts +12 -52
  381. package/src/cli/{platform → platform-lib}/__tests__/CloudflareAdapter.spec.ts +426 -169
  382. package/src/cli/{platform → platform-lib}/__tests__/NamingService.spec.ts +91 -4
  383. package/src/cli/{platform → platform-lib}/__tests__/VercelAdapter.spec.ts +56 -85
  384. package/src/cli/{platform → platform-lib}/adapters/CloudflareAdapter.ts +402 -165
  385. package/src/cli/{platform → platform-lib}/adapters/PlatformAdapter.ts +62 -35
  386. package/src/cli/{platform → platform-lib}/adapters/VercelAdapter.ts +6 -10
  387. package/src/cli/{platform → platform-lib}/atoms/platformOptions.ts +34 -1
  388. package/src/cli/platform-lib/index.ts +67 -0
  389. package/src/cli/platform-lib/services/NamingService.ts +136 -0
  390. package/src/cli/{platform → platform-lib}/services/PlatformInspector.ts +60 -13
  391. package/src/cli/{platform → platform-lib}/services/PlatformOrchestrator.ts +54 -43
  392. package/src/cli/{platform → platform-lib}/services/WranglerApi.ts +4 -2
  393. package/src/command/__tests__/Runner.spec.ts +20 -0
  394. package/src/command/helpers/EnvUtils.ts +19 -3
  395. package/src/command/helpers/Runner.ts +12 -2
  396. package/src/command/providers/CliProvider.ts +34 -1
  397. package/src/{containers → container}/core/__tests__/$container.spec.ts +5 -5
  398. package/src/{containers → container}/core/index.ts +4 -4
  399. package/src/{containers → container}/core/index.workerd.ts +19 -3
  400. package/src/{containers → container}/core/primitives/$container.ts +1 -1
  401. package/src/{containers → container}/core/providers/CloudflareContainerProvider.ts +17 -19
  402. package/src/{containers → container}/core/providers/ContainerProvider.ts +16 -2
  403. package/src/{containers → container}/core/providers/MockContainerProvider.ts +1 -1
  404. package/src/core/Alepha.ts +49 -1
  405. package/src/core/__tests__/$env.spec.ts +42 -0
  406. package/src/core/__tests__/dump.spec.ts +47 -0
  407. package/src/email/cloudflare/__tests__/CloudflareEmailProvider.spec.ts +42 -10
  408. package/src/email/cloudflare/index.ts +14 -5
  409. package/src/email/cloudflare/providers/CloudflareEmailProvider.ts +54 -9
  410. package/src/logger/__tests__/Logger.spec.ts +55 -0
  411. package/src/logger/index.ts +13 -0
  412. package/src/logger/services/Logger.ts +31 -1
  413. package/src/orm/__tests__/orm-showcase-tests.ts +27 -0
  414. package/src/orm/__tests__/orm-showcase.spec.ts +12 -0
  415. package/src/orm/core/interfaces/PgQuery.ts +4 -1
  416. package/src/orm/core/services/Repository.ts +27 -11
  417. package/src/react/auth/hooks/useAuth.ts +10 -5
  418. package/src/react/core/__tests__/useQuery.browser.spec.tsx +25 -0
  419. package/src/react/core/hooks/useAction.ts +14 -3
  420. package/src/react/core/hooks/useQuery.ts +24 -4
  421. package/src/react/i18n/components/Translate.tsx +47 -0
  422. package/src/react/i18n/index.ts +2 -0
  423. package/src/react/intro/components/GettingStartedAdminSlide.tsx +2 -2
  424. package/src/react/router/__tests__/$page.spec.tsx +3 -2
  425. package/src/react/router/__tests__/page-can.spec.ts +18 -13
  426. package/src/react/router/hooks/useQueryParams.ts +114 -14
  427. package/src/react/router/primitives/$page.ts +85 -4
  428. package/src/react/router/providers/ReactBrowserRouterProvider.ts +3 -7
  429. package/src/react/router/providers/ReactServerProvider.ts +4 -13
  430. package/src/react/ui/services/SchemaControl.ts +3 -4
  431. package/src/server/core/providers/ServerMultipartProvider.ts +19 -0
  432. package/src/server/links/providers/LinkProvider.ts +10 -0
  433. package/dist/containers/core/index.d.ts.map +0 -1
  434. package/dist/containers/core/index.js.map +0 -1
  435. package/dist/containers/core/index.workerd.js.map +0 -1
  436. package/src/cli/core/templates/componentsJsonTs.ts +0 -39
  437. package/src/cli/core/templates/saasAdminLayoutTsx.ts +0 -77
  438. package/src/cli/core/templates/saasAdminPagesTsx.ts +0 -26
  439. package/src/cli/core/templates/saasAuthLayoutTsx.ts +0 -22
  440. package/src/cli/core/templates/saasAuthPagesTsx.ts +0 -62
  441. package/src/cli/core/templates/saasRealmProviderTs.ts +0 -52
  442. package/src/cli/platform/services/NamingService.ts +0 -54
  443. /package/dist/orm/core/{chunk-o8xxKEmq.js → chunk-B4FMCO8f.js} +0 -0
  444. /package/dist/react/testing/{chunk-6Ep1yQYe.js → chunk-BpyX8vjI.js} +0 -0
  445. /package/src/cli/{platform → platform-lib}/__tests__/GitHubSecretStore.spec.ts +0 -0
  446. /package/src/cli/{platform → platform-lib}/__tests__/PlatformCacheProvider.spec.ts +0 -0
  447. /package/src/cli/{platform → platform-lib}/__tests__/PlatformInspector.spec.ts +0 -0
  448. /package/src/cli/{platform → platform-lib}/__tests__/PlatformOrchestrator.spec.ts +0 -0
  449. /package/src/cli/{platform → platform-lib}/__tests__/SecretFilterService.spec.ts +0 -0
  450. /package/src/cli/{platform → platform-lib}/__tests__/detectResources.spec.ts +0 -0
  451. /package/src/cli/{platform → platform-lib}/providers/GitHubSecretStore.ts +0 -0
  452. /package/src/cli/{platform → platform-lib}/providers/MemorySecretStore.ts +0 -0
  453. /package/src/cli/{platform → platform-lib}/providers/PlatformCacheProvider.ts +0 -0
  454. /package/src/cli/{platform → platform-lib}/providers/SecretStoreProvider.ts +0 -0
  455. /package/src/cli/{platform → platform-lib}/schemas/cloudflare.ts +0 -0
  456. /package/src/cli/{platform → platform-lib}/schemas/platform.ts +0 -0
  457. /package/src/cli/{platform → platform-lib}/schemas/vercel.ts +0 -0
  458. /package/src/cli/{platform → platform-lib}/services/CloudflareApi.ts +0 -0
  459. /package/src/cli/{platform → platform-lib}/services/SecretFilterService.ts +0 -0
  460. /package/src/cli/{platform → platform-lib}/services/VercelApi.ts +0 -0
  461. /package/src/cli/{platform → platform-lib}/services/VercelCli.ts +0 -0
  462. /package/src/{containers → container}/core/interfaces/ContainerOptions.ts +0 -0
  463. /package/src/{containers → container}/core/providers/NodeContainerProvider.ts +0 -0
@@ -0,0 +1,17 @@
1
+ import { $audit } from "alepha/api/audits";
2
+
3
+ /**
4
+ * Runtime parameter (config) audit events.
5
+ *
6
+ * Holds the `parameter` audit type. Using `$audit` pulls in the audits module
7
+ * automatically — the parameters module does not need to import it. Register
8
+ * as a variant and log via `parameterAudits.parameter.log("rollback", …)`.
9
+ */
10
+ export class ParameterAudits {
11
+ public readonly parameter = $audit({
12
+ type: "parameter",
13
+ description:
14
+ "Runtime parameter changes (create, rollback, activate, delete).",
15
+ actions: ["create", "rollback", "activate", "delete"],
16
+ });
17
+ }
@@ -1,6 +1,7 @@
1
- import { $inject, AlephaError, t } from "alepha";
1
+ import { $inject, Alepha, AlephaError, t } from "alepha";
2
2
  import { $secure } from "alepha/security";
3
3
  import { $action, okSchema } from "alepha/server";
4
+ import { ParameterAudits } from "../audits/ParameterAudits.ts";
4
5
  import { activateParameterBodySchema } from "../schemas/activateParameterBodySchema.ts";
5
6
  import { createParameterVersionBodySchema } from "../schemas/createParameterVersionBodySchema.ts";
6
7
  import { parameterCurrentResponseSchema } from "../schemas/parameterCurrentResponseSchema.ts";
@@ -29,6 +30,7 @@ export class AdminParameterController {
29
30
  protected readonly url = "/parameters";
30
31
  protected readonly group = "admin:parameters";
31
32
  protected readonly provider = $inject(ParameterProvider);
33
+ protected readonly alepha = $inject(Alepha);
32
34
 
33
35
  /**
34
36
  * Get tree structure of all parameter names.
@@ -162,16 +164,26 @@ export class AdminParameterController {
162
164
  body: createParameterVersionBodySchema,
163
165
  response: parameterResponseSchema,
164
166
  },
165
- handler: async ({ params, body }) => {
166
- return this.provider.save(params.name, body.content, body.schemaHash, {
167
- activationDate: body.activationDate
168
- ? new Date(body.activationDate)
169
- : undefined,
170
- changeDescription: body.changeDescription,
171
- tags: body.tags,
172
- creatorId: body.creatorId,
173
- creatorName: body.creatorName,
167
+ handler: async ({ params, body, user }) => {
168
+ const result = await this.provider.save(
169
+ params.name,
170
+ body.content,
171
+ body.schemaHash,
172
+ {
173
+ activationDate: body.activationDate
174
+ ? new Date(body.activationDate)
175
+ : undefined,
176
+ changeDescription: body.changeDescription,
177
+ tags: body.tags,
178
+ creatorId: user?.id,
179
+ creatorName: this.creatorNameOf(user),
180
+ },
181
+ );
182
+ await this.audit("create", params.name, {
183
+ version: result.version,
184
+ scheduled: result.status !== "current",
174
185
  });
186
+ return result;
175
187
  },
176
188
  });
177
189
 
@@ -190,12 +202,21 @@ export class AdminParameterController {
190
202
  body: rollbackParameterBodySchema,
191
203
  response: parameterResponseSchema,
192
204
  },
193
- handler: async ({ params, body }) => {
194
- return this.provider.rollback(params.name, body.targetVersion, {
195
- changeDescription: body.changeDescription,
196
- creatorId: body.creatorId,
197
- creatorName: body.creatorName,
205
+ handler: async ({ params, body, user }) => {
206
+ const result = await this.provider.rollback(
207
+ params.name,
208
+ body.targetVersion,
209
+ {
210
+ changeDescription: body.changeDescription,
211
+ creatorId: user?.id,
212
+ creatorName: this.creatorNameOf(user),
213
+ },
214
+ );
215
+ await this.audit("rollback", params.name, {
216
+ version: result.version,
217
+ targetVersion: body.targetVersion,
198
218
  });
219
+ return result;
199
220
  },
200
221
  });
201
222
 
@@ -214,7 +235,7 @@ export class AdminParameterController {
214
235
  body: activateParameterBodySchema,
215
236
  response: parameterResponseSchema,
216
237
  },
217
- handler: async ({ params, body }) => {
238
+ handler: async ({ params, body, user }) => {
218
239
  const allVersions = await this.provider.getHistory(params.name);
219
240
  const withStatuses = this.provider.calculateStatuses(allVersions);
220
241
  const target = withStatuses.find((v) => v.version === body.version);
@@ -236,16 +257,21 @@ export class AdminParameterController {
236
257
  }
237
258
 
238
259
  // Create new version with same content but immediate activation
239
- return this.provider.save(
260
+ const result = await this.provider.save(
240
261
  params.name,
241
262
  target.content,
242
263
  target.schemaHash,
243
264
  {
244
265
  changeDescription: `Early activation of version ${body.version}`,
245
- creatorId: body.creatorId,
246
- creatorName: body.creatorName,
266
+ creatorId: user?.id,
267
+ creatorName: this.creatorNameOf(user),
247
268
  },
248
269
  );
270
+ await this.audit("activate", params.name, {
271
+ version: result.version,
272
+ activatedFrom: body.version,
273
+ });
274
+ return result;
249
275
  },
250
276
  });
251
277
 
@@ -264,6 +290,7 @@ export class AdminParameterController {
264
290
  },
265
291
  handler: async ({ params }) => {
266
292
  await this.provider.delete(params.name);
293
+ await this.audit("delete", params.name);
267
294
  return { ok: true };
268
295
  },
269
296
  });
@@ -290,7 +317,56 @@ export class AdminParameterController {
290
317
  },
291
318
  handler: async ({ body }) => {
292
319
  const deleted = await this.provider.deleteMany(body.names);
320
+ for (const name of deleted) {
321
+ await this.audit("delete", name);
322
+ }
293
323
  return { deleted };
294
324
  },
295
325
  });
326
+
327
+ /**
328
+ * Derive a human-readable creator name from the authenticated session token.
329
+ *
330
+ * The name is snapshotted onto the version at write time rather than joined
331
+ * from the users table on read: this keeps the parameters module free of any
332
+ * dependency on the users module (no import, no circular-import risk). The
333
+ * trade-off is that the stored name does not follow later user renames.
334
+ *
335
+ * Precedence: `username` → `email`. The token's `name` is intentionally
336
+ * skipped: the security layer fills it with a placeholder ("Anonymous User")
337
+ * when the issuer supplies no name, which would otherwise be snapshotted.
338
+ */
339
+ protected creatorNameOf(user?: {
340
+ username?: string;
341
+ email?: string;
342
+ }): string | undefined {
343
+ return user?.username ?? user?.email;
344
+ }
345
+
346
+ /**
347
+ * Record a parameter mutation via the `ParameterAudits` holder — best-effort.
348
+ *
349
+ * `ParameterAudits` is resolved lazily from the container; when it is not
350
+ * registered, auditing is silently skipped. Actor (userId / email / realm),
351
+ * IP, and request id are auto-filled by `AuditService` from the request
352
+ * context. Failures never break the underlying operation.
353
+ */
354
+ protected async audit(
355
+ action: "create" | "rollback" | "activate" | "delete",
356
+ name: string,
357
+ metadata?: Record<string, unknown>,
358
+ ): Promise<void> {
359
+ if (!this.alepha.has(ParameterAudits)) {
360
+ return;
361
+ }
362
+ try {
363
+ await this.alepha.inject(ParameterAudits).parameter.log(action, {
364
+ resourceType: "parameter",
365
+ resourceId: name,
366
+ metadata,
367
+ });
368
+ } catch {
369
+ // Auditing is best-effort; never fail the operation because of it.
370
+ }
371
+ }
296
372
  }
@@ -1,4 +1,5 @@
1
1
  import { $module } from "alepha";
2
+ import { ParameterAudits } from "./audits/ParameterAudits.ts";
2
3
  import { AdminParameterController } from "./controllers/AdminParameterController.ts";
3
4
  import { $parameter } from "./primitives/$parameter.ts";
4
5
  import { ParameterProvider } from "./services/ParameterProvider.ts";
@@ -6,6 +7,7 @@ import { ParameterProvider } from "./services/ParameterProvider.ts";
6
7
  // ---------------------------------------------------------------------------------------------------------------------
7
8
 
8
9
  // Controller exports
10
+ export * from "./audits/ParameterAudits.ts";
9
11
  export * from "./controllers/AdminParameterController.ts";
10
12
  // Entity exports
11
13
  export * from "./entities/parameters.ts";
@@ -45,4 +47,5 @@ export const AlephaApiParameters = $module({
45
47
  name: "alepha.api.parameters",
46
48
  primitives: [$parameter],
47
49
  services: [ParameterProvider, AdminParameterController],
50
+ variants: [ParameterAudits],
48
51
  });
@@ -3,12 +3,12 @@ import { parameters } from "../entities/parameters.ts";
3
3
 
4
4
  /**
5
5
  * Activate parameter body schema.
6
- * Uses t.pick for version and creator fields.
6
+ *
7
+ * Creator fields are omitted; the controller captures the authenticated user
8
+ * server-side.
7
9
  */
8
10
  export const activateParameterBodySchema = t.pick(parameters.schema, [
9
11
  "version",
10
- "creatorId",
11
- "creatorName",
12
12
  ]);
13
13
 
14
14
  export type ActivateParameterBody = Static<typeof activateParameterBodySchema>;
@@ -4,6 +4,9 @@ import { parameters } from "../entities/parameters.ts";
4
4
  /**
5
5
  * Create parameter version body schema.
6
6
  * Uses t.pick to derive from entity, with required fields made non-optional.
7
+ *
8
+ * Creator fields are intentionally omitted: the controller captures the
9
+ * authenticated user server-side, so they cannot be spoofed by the client.
7
10
  */
8
11
  export const createParameterVersionBodySchema = t.extend(
9
12
  t.pick(parameters.schema, [
@@ -11,8 +14,6 @@ export const createParameterVersionBodySchema = t.extend(
11
14
  "schemaHash",
12
15
  "changeDescription",
13
16
  "tags",
14
- "creatorId",
15
- "creatorName",
16
17
  ]),
17
18
  {
18
19
  activationDate: t.optional(
@@ -0,0 +1,25 @@
1
+ import { type Static, t } from "alepha";
2
+
3
+ /**
4
+ * Slim view of a parameter version's creator, embedded by the admin history
5
+ * endpoint via a best-effort left join (`parameters.creatorId` → `users.id`)
6
+ * so the UI can render a human-readable identifier (and link) instead of a
7
+ * bare UUID.
8
+ *
9
+ * Optional end-to-end: the join only runs when the `users` entity is
10
+ * registered in the running app (see `ParameterProvider.resolveCreatorJoin`),
11
+ * and a version whose creator was deleted — or who lives in a non-default
12
+ * realm — comes back with `creator` undefined. Callers fall back to the raw
13
+ * `creatorId`.
14
+ */
15
+ export const parameterCreatorSummarySchema = t.object({
16
+ id: t.uuid(),
17
+ email: t.optional(t.string({ format: "email" })),
18
+ username: t.optional(t.shortText({ minLength: 3, maxLength: 30 })),
19
+ firstName: t.optional(t.string()),
20
+ lastName: t.optional(t.string()),
21
+ });
22
+
23
+ export type ParameterCreatorSummary = Static<
24
+ typeof parameterCreatorSummarySchema
25
+ >;
@@ -1,14 +1,19 @@
1
1
  import { type Static, t } from "alepha";
2
2
  import { parameters } from "../entities/parameters.ts";
3
+ import { parameterCreatorSummarySchema } from "./parameterCreatorSummarySchema.ts";
3
4
  import { parameterStatusSchema } from "./parameterStatusSchema.ts";
4
5
 
5
6
  /**
6
7
  * Parameter response schema for API responses.
7
8
  * Extends the entity schema with a calculated status field.
8
9
  * Status is derived from activationDate at query time, not stored.
10
+ *
11
+ * `creator` is embedded on read via a best-effort left join on `creatorId`
12
+ * (see `parameterCreatorSummarySchema`); it is not a stored column.
9
13
  */
10
14
  export const parameterResponseSchema = t.extend(parameters.schema, {
11
15
  status: parameterStatusSchema,
16
+ creator: t.optional(parameterCreatorSummarySchema),
12
17
  });
13
18
 
14
19
  export type ParameterResponse = Static<typeof parameterResponseSchema>;
@@ -3,10 +3,12 @@ import { parameters } from "../entities/parameters.ts";
3
3
 
4
4
  /**
5
5
  * Rollback parameter body schema.
6
- * Uses t.pick for creator fields, adds targetVersion.
6
+ *
7
+ * Creator fields are omitted; the controller captures the authenticated user
8
+ * server-side.
7
9
  */
8
10
  export const rollbackParameterBodySchema = t.extend(
9
- t.pick(parameters.schema, ["changeDescription", "creatorId", "creatorName"]),
11
+ t.pick(parameters.schema, ["changeDescription"]),
10
12
  {
11
13
  targetVersion: t.integer({
12
14
  description: "Version number to rollback to",
@@ -12,7 +12,7 @@ import { CryptoProvider } from "alepha/crypto";
12
12
  import { DateTimeProvider } from "alepha/datetime";
13
13
  import { LockProvider } from "alepha/lock";
14
14
  import { $logger } from "alepha/logger";
15
- import { $repository } from "alepha/orm";
15
+ import { $repository, RepositoryProvider } from "alepha/orm";
16
16
  import { $topic } from "alepha/topic";
17
17
  import { type Parameter, parameters } from "../entities/parameters.ts";
18
18
  import type { ParameterPrimitive } from "../primitives/$parameter.ts";
@@ -50,6 +50,7 @@ export class ParameterProvider {
50
50
  protected readonly crypto = $inject(CryptoProvider);
51
51
  protected readonly lockProvider = $inject(LockProvider);
52
52
  protected readonly schemaValidator = $inject(SchemaValidator);
53
+ protected readonly repositoryProvider = $inject(RepositoryProvider);
53
54
  protected readonly repo = $repository(parameters);
54
55
 
55
56
  /**
@@ -326,10 +327,10 @@ export class ParameterProvider {
326
327
  * - Other future versions are "future"
327
328
  * - Other past versions are "expired"
328
329
  */
329
- public calculateStatuses(
330
- versions: Parameter[],
330
+ public calculateStatuses<T extends Parameter>(
331
+ versions: T[],
331
332
  now?: Date,
332
- ): ParameterWithStatus[] {
333
+ ): Array<T & { status: ParameterStatus }> {
333
334
  const effectiveNow = now ?? this.dateTimeProvider.now().toDate();
334
335
 
335
336
  // Sort by activationDate ascending, then version ascending for ties
@@ -458,17 +459,49 @@ export class ParameterProvider {
458
459
  }
459
460
 
460
461
  /**
461
- * Get all versions of a parameter.
462
+ * Best-effort left join embedding the creating user on each version, so the
463
+ * admin UI can render a human-readable identifier (live, not snapshotted)
464
+ * instead of the bare `creatorId`. Joins `parameters.creatorId` → `users.id`.
465
+ *
466
+ * The `users` entity is resolved from the repository registry at runtime
467
+ * rather than imported: that keeps the parameters module free of any
468
+ * dependency on the users module (no import, no circular-import risk). When
469
+ * the users module is not registered the join is skipped and `creator` comes
470
+ * back undefined.
471
+ */
472
+ protected resolveCreatorJoin() {
473
+ const usersEntity = this.repositoryProvider
474
+ .getRepositories()
475
+ .find((repo) => repo.entity.name === "users")?.entity;
476
+ if (!usersEntity) {
477
+ return undefined;
478
+ }
479
+ return {
480
+ creator: {
481
+ join: usersEntity,
482
+ on: ["creatorId", usersEntity.cols.id] as [
483
+ "creatorId",
484
+ { name: string },
485
+ ],
486
+ },
487
+ };
488
+ }
489
+
490
+ /**
491
+ * Get all versions of a parameter, each with the creating user embedded
492
+ * (best-effort, see {@link resolveCreatorJoin}).
462
493
  */
463
494
  public async getHistory(
464
495
  name: string,
465
496
  options?: { limit?: number; offset?: number },
466
497
  ): Promise<Parameter[]> {
498
+ const withCreator = this.resolveCreatorJoin();
467
499
  return this.repo.findMany({
468
500
  where: { name },
469
501
  orderBy: { column: "version", direction: "desc" },
470
502
  limit: options?.limit,
471
503
  offset: options?.offset,
504
+ ...(withCreator ? { with: withCreator } : {}),
472
505
  });
473
506
  }
474
507
 
@@ -563,6 +596,12 @@ export class ParameterProvider {
563
596
 
564
597
  /**
565
598
  * Get parameter info including current value with default fallback.
599
+ *
600
+ * When no version exists in the DB yet but a primitive is registered, this
601
+ * lazily materializes v1 from the primitive's `default`. After this call,
602
+ * the parameter has a concrete current row admins can edit / roll back /
603
+ * compare against, instead of running on phantom defaults-from-code state.
604
+ * Idempotent: subsequent calls return the same row without re-creating.
566
605
  */
567
606
  public async getCurrentWithDefault(name: string): Promise<{
568
607
  current: ParameterWithStatus | null;
@@ -571,10 +610,34 @@ export class ParameterProvider {
571
610
  currentValue: unknown | null;
572
611
  schema: TObject | null;
573
612
  }> {
574
- const { current, next } = await this.loadCurrentAndNext(name);
613
+ let { current, next } = await this.loadCurrentAndNext(name);
575
614
 
576
615
  // Get default and current from registered primitive
577
616
  const param = this.primitives.get(name);
617
+
618
+ // No version in DB yet but the primitive is registered: seed v1 from
619
+ // the compiled defaults. Always-on parameters are then a tangible row
620
+ // the admin UI can edit (and that history can grow from). Unregistered
621
+ // names (orphans from a removed `$parameter`) are not seeded.
622
+ if (!current && param) {
623
+ try {
624
+ current = await this.save(
625
+ name,
626
+ param.options.default as Static<TObject>,
627
+ this.schemaHashes.get(name) ?? "",
628
+ { changeDescription: "Auto-seeded from compiled defaults" },
629
+ );
630
+ } catch (err) {
631
+ // A concurrent caller may have raced us to insert v1; fall back to
632
+ // re-reading instead of bubbling up a unique-constraint error.
633
+ this.log.warn("Auto-seed of parameter failed, retrying read", {
634
+ name,
635
+ error: (err as Error).message,
636
+ });
637
+ ({ current, next } = await this.loadCurrentAndNext(name));
638
+ }
639
+ }
640
+
578
641
  const defaultValue = param?.options.default ?? null;
579
642
  const currentValue = this.getCachedCurrentContent(name) ?? null;
580
643
  const schema = param?.schema ?? null;
@@ -301,7 +301,7 @@ export class SubscriptionJobs {
301
301
  * Runs daily at 2 AM.
302
302
  */
303
303
  public readonly gracePeriodSweep = $job({
304
- cron: "0 2 * * *",
304
+ cron: "0 3 * * *",
305
305
  lock: true,
306
306
  handler: async ({ now }) => {
307
307
  const settings = await this.config.getSettings();
@@ -75,6 +75,43 @@ describe("alepha/api/users - AdminSessionController", () => {
75
75
  expect(result.userAgent?.browser).toBe("Chrome");
76
76
  });
77
77
 
78
+ it("should embed the slim user summary on findSessions + getSession", async ({
79
+ expect,
80
+ }) => {
81
+ const { sessionService, userService, controller, dateTimeProvider } =
82
+ await setup();
83
+
84
+ const user = await userService.users().create({
85
+ username: "withuser",
86
+ email: "withuser@example.com",
87
+ firstName: "With",
88
+ lastName: "User",
89
+ roles: ["user"],
90
+ });
91
+
92
+ const session = await sessionService.sessions().create({
93
+ userId: user.id,
94
+ refreshToken: crypto.randomUUID(),
95
+ expiresAt: dateTimeProvider.now().add(7, "days").toISOString(),
96
+ });
97
+
98
+ const listed = await controller.findSessions(
99
+ { query: { userId: user.id } },
100
+ { user: adminUser },
101
+ );
102
+ const found = listed.content.find((s) => s.id === session.id);
103
+ expect(found?.user?.id).toBe(user.id);
104
+ expect(found?.user?.email).toBe("withuser@example.com");
105
+ expect(found?.user?.username).toBe("withuser");
106
+ expect(found?.user?.firstName).toBe("With");
107
+
108
+ const fetched = await controller.getSession(
109
+ { params: { id: session.id } },
110
+ { user: adminUser },
111
+ );
112
+ expect(fetched.user?.email).toBe("withuser@example.com");
113
+ });
114
+
78
115
  it("should throw error for non-existent session", async ({ expect }) => {
79
116
  const { controller } = await setup();
80
117
 
@@ -0,0 +1,33 @@
1
+ import { $audit } from "alepha/api/audits";
2
+
3
+ /**
4
+ * Authentication & session-security audit events.
5
+ *
6
+ * Holds two audit types:
7
+ * - `auth` — login / logout / token refresh / MFA.
8
+ * - `security` — rate limiting, session invalidation, and related guards.
9
+ *
10
+ * Failed events are logged with `success: false`; severity (`warning`) is
11
+ * derived centrally in `AuditService.create`. Register as a module variant
12
+ * and log via the exposed primitives:
13
+ * `sessionAudits(realm)?.auth.log("login", { success: false, … })`.
14
+ */
15
+ export class SessionAudits {
16
+ public readonly auth = $audit({
17
+ type: "auth",
18
+ description: "Authentication events (login, logout, token refresh, MFA).",
19
+ actions: ["login", "logout", "token_refresh", "mfa_setup", "mfa_verify"],
20
+ });
21
+
22
+ public readonly security = $audit({
23
+ type: "security",
24
+ description:
25
+ "Security events (rate limiting, session invalidation, blocked access).",
26
+ actions: [
27
+ "rate_limited",
28
+ "sessions_invalidated",
29
+ "permission_denied",
30
+ "blocked",
31
+ ],
32
+ });
33
+ }
@@ -1,49 +1,25 @@
1
- import { $inject } from "alepha";
2
- import { AuditService, type CreateAudit } from "alepha/api/audits";
3
-
4
- type AuditContext = Omit<CreateAudit, "type" | "action">;
1
+ import { $audit } from "alepha/api/audits";
5
2
 
6
3
  /**
7
- * User-specific audit wrapper service.
8
- *
9
- * This service wraps the core AuditService to provide user-related audit logging.
4
+ * User-management audit events.
10
5
  *
11
- * Declared as a module variant not auto-injected. It is instantiated
12
- * lazily the first time something calls `alepha.inject(UserAudits)`.
6
+ * Holds the `user` audit type. Mirrors the `$notification`/`$job` holder
7
+ * pattern (see {@link UserNotifications}) register as a module variant and
8
+ * log via the exposed primitive: `userAudits(realm)?.user.log("create", …)`.
13
9
  */
14
10
  export class UserAudits {
15
- protected readonly auditService = $inject(AuditService);
16
-
17
- /**
18
- * Record a user-related audit event.
19
- */
20
- public recordUser(
21
- action:
22
- | "create"
23
- | "update"
24
- | "delete"
25
- | "role_change"
26
- | "enable"
27
- | "disable",
28
- context: AuditContext,
29
- ) {
30
- return this.auditService.recordUser(action, context);
31
- }
32
-
33
- /**
34
- * Record an authentication-related audit event.
35
- */
36
- public recordAuth(
37
- action: "login" | "logout" | "login_failed" | "token_refresh",
38
- context: AuditContext,
39
- ) {
40
- return this.auditService.recordAuth(action, context);
41
- }
42
-
43
- /**
44
- * Record a generic audit event.
45
- */
46
- public record(category: string, action: string, context: AuditContext) {
47
- return this.auditService.record(category, action, context);
48
- }
11
+ public readonly user = $audit({
12
+ type: "user",
13
+ description:
14
+ "User management events (create, update, delete, role/password changes).",
15
+ actions: [
16
+ "create",
17
+ "update",
18
+ "delete",
19
+ "role_change",
20
+ "password_change",
21
+ "enable",
22
+ "disable",
23
+ ],
24
+ });
49
25
  }