alepha 0.13.6 → 0.13.7

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 (134) hide show
  1. package/dist/api-audits/index.browser.js +116 -0
  2. package/dist/api-audits/index.browser.js.map +1 -0
  3. package/dist/api-audits/index.d.ts +1194 -0
  4. package/dist/api-audits/index.js +674 -0
  5. package/dist/api-audits/index.js.map +1 -0
  6. package/dist/api-notifications/index.d.ts +147 -147
  7. package/dist/api-parameters/index.browser.js +36 -5
  8. package/dist/api-parameters/index.browser.js.map +1 -1
  9. package/dist/api-parameters/index.d.ts +711 -33
  10. package/dist/api-parameters/index.js +831 -17
  11. package/dist/api-parameters/index.js.map +1 -1
  12. package/dist/api-users/index.d.ts +793 -780
  13. package/dist/api-users/index.js +699 -19
  14. package/dist/api-users/index.js.map +1 -1
  15. package/dist/api-verifications/index.js +2 -1
  16. package/dist/api-verifications/index.js.map +1 -1
  17. package/dist/bin/index.js +1 -0
  18. package/dist/bin/index.js.map +1 -1
  19. package/dist/cli/index.d.ts +85 -31
  20. package/dist/cli/index.js +205 -33
  21. package/dist/cli/index.js.map +1 -1
  22. package/dist/command/index.d.ts +67 -6
  23. package/dist/command/index.js +30 -3
  24. package/dist/command/index.js.map +1 -1
  25. package/dist/core/index.browser.js +241 -61
  26. package/dist/core/index.browser.js.map +1 -1
  27. package/dist/core/index.d.ts +170 -90
  28. package/dist/core/index.js +264 -67
  29. package/dist/core/index.js.map +1 -1
  30. package/dist/core/index.native.js +248 -65
  31. package/dist/core/index.native.js.map +1 -1
  32. package/dist/email/index.js +15 -10554
  33. package/dist/email/index.js.map +1 -1
  34. package/dist/logger/index.d.ts +4 -4
  35. package/dist/logger/index.js +77 -72
  36. package/dist/logger/index.js.map +1 -1
  37. package/dist/orm/index.d.ts +5 -1
  38. package/dist/orm/index.js +24 -7
  39. package/dist/orm/index.js.map +1 -1
  40. package/dist/queue/index.d.ts +4 -4
  41. package/dist/scheduler/index.d.ts +6 -6
  42. package/dist/server/index.d.ts +10 -1
  43. package/dist/server/index.js +20 -6
  44. package/dist/server/index.js.map +1 -1
  45. package/dist/server-auth/index.d.ts +163 -152
  46. package/dist/server-auth/index.js +40 -10
  47. package/dist/server-auth/index.js.map +1 -1
  48. package/dist/server-cookies/index.js +5 -1
  49. package/dist/server-cookies/index.js.map +1 -1
  50. package/dist/server-links/index.d.ts +33 -33
  51. package/dist/server-security/index.d.ts +9 -9
  52. package/dist/thread/index.js +2 -2
  53. package/dist/thread/index.js.map +1 -1
  54. package/dist/vite/index.d.ts +2 -2
  55. package/dist/vite/index.js +102 -45
  56. package/dist/vite/index.js.map +1 -1
  57. package/dist/websocket/index.browser.js +3 -3
  58. package/dist/websocket/index.browser.js.map +1 -1
  59. package/dist/websocket/index.js +4 -4
  60. package/dist/websocket/index.js.map +1 -1
  61. package/package.json +14 -9
  62. package/src/api-audits/controllers/AuditController.ts +186 -0
  63. package/src/api-audits/entities/audits.ts +132 -0
  64. package/src/api-audits/index.browser.ts +18 -0
  65. package/src/api-audits/index.ts +58 -0
  66. package/src/api-audits/primitives/$audit.ts +159 -0
  67. package/src/api-audits/schemas/auditQuerySchema.ts +23 -0
  68. package/src/api-audits/schemas/auditResourceSchema.ts +9 -0
  69. package/src/api-audits/schemas/createAuditSchema.ts +27 -0
  70. package/src/api-audits/services/AuditService.ts +412 -0
  71. package/src/api-parameters/controllers/ConfigController.ts +324 -0
  72. package/src/api-parameters/entities/parameters.ts +93 -10
  73. package/src/api-parameters/index.ts +43 -4
  74. package/src/api-parameters/primitives/$config.ts +291 -19
  75. package/src/api-parameters/schedulers/ConfigActivationScheduler.ts +30 -0
  76. package/src/api-parameters/services/ConfigStore.ts +491 -0
  77. package/src/api-users/atoms/realmAuthSettingsAtom.ts +19 -0
  78. package/src/api-users/controllers/UserRealmController.ts +0 -2
  79. package/src/api-users/index.ts +2 -0
  80. package/src/api-users/primitives/$userRealm.ts +18 -3
  81. package/src/api-users/providers/UserRealmProvider.ts +6 -3
  82. package/src/api-users/services/RegistrationService.ts +2 -1
  83. package/src/api-users/services/SessionService.ts +4 -0
  84. package/src/api-users/services/UserService.ts +3 -0
  85. package/src/api-verifications/index.ts +7 -1
  86. package/src/bin/index.ts +1 -0
  87. package/src/cli/assets/biomeJson.ts +1 -1
  88. package/src/cli/assets/dummySpecTs.ts +7 -0
  89. package/src/cli/assets/editorconfig.ts +13 -0
  90. package/src/cli/assets/mainTs.ts +14 -0
  91. package/src/cli/commands/BiomeCommands.ts +2 -0
  92. package/src/cli/commands/CoreCommands.ts +28 -9
  93. package/src/cli/commands/VerifyCommands.ts +2 -1
  94. package/src/cli/commands/ViteCommands.ts +8 -9
  95. package/src/cli/services/AlephaCliUtils.ts +214 -23
  96. package/src/command/helpers/Asker.ts +0 -1
  97. package/src/command/primitives/$command.ts +67 -0
  98. package/src/command/providers/CliProvider.ts +39 -8
  99. package/src/core/Alepha.ts +40 -30
  100. package/src/core/helpers/jsonSchemaToTypeBox.ts +307 -0
  101. package/src/core/index.shared.ts +1 -0
  102. package/src/core/index.ts +30 -3
  103. package/src/core/providers/EventManager.ts +1 -1
  104. package/src/core/providers/StateManager.ts +23 -12
  105. package/src/core/providers/TypeProvider.ts +26 -34
  106. package/src/logger/index.ts +8 -6
  107. package/src/logger/primitives/$logger.ts +1 -1
  108. package/src/logger/providers/{SimpleFormatterProvider.ts → PrettyFormatterProvider.ts} +10 -1
  109. package/src/orm/index.ts +6 -0
  110. package/src/orm/services/PgRelationManager.ts +2 -2
  111. package/src/orm/services/PostgresModelBuilder.ts +11 -7
  112. package/src/orm/services/Repository.ts +16 -7
  113. package/src/orm/services/SqliteModelBuilder.ts +10 -0
  114. package/src/server/index.ts +6 -0
  115. package/src/server/primitives/$action.ts +10 -1
  116. package/src/server/providers/ServerBodyParserProvider.ts +11 -5
  117. package/src/server/providers/ServerRouterProvider.ts +13 -7
  118. package/src/server-auth/primitives/$auth.ts +7 -0
  119. package/src/server-auth/providers/ServerAuthProvider.ts +51 -8
  120. package/src/server-cookies/index.ts +2 -1
  121. package/src/thread/primitives/$thread.ts +2 -2
  122. package/src/vite/index.ts +0 -2
  123. package/src/vite/tasks/buildServer.ts +3 -4
  124. package/src/vite/tasks/generateCloudflare.ts +35 -19
  125. package/src/vite/tasks/generateDocker.ts +18 -4
  126. package/src/vite/tasks/generateSitemap.ts +5 -7
  127. package/src/vite/tasks/generateVercel.ts +76 -41
  128. package/src/vite/tasks/runAlepha.ts +16 -1
  129. package/src/websocket/providers/NodeWebSocketServerProvider.ts +3 -11
  130. package/src/websocket/services/WebSocketClient.ts +3 -3
  131. package/dist/cli/dist-BlfFtOk2.js +0 -2770
  132. package/dist/cli/dist-BlfFtOk2.js.map +0 -1
  133. package/src/api-parameters/controllers/ParameterController.ts +0 -45
  134. package/src/api-parameters/services/ParameterStore.ts +0 -23
@@ -0,0 +1,674 @@
1
+ import { $inject, $module, Alepha, KIND, Primitive, createPrimitive, t } from "alepha";
2
+ import { $entity, $repository, pageQuerySchema, pg } from "alepha/orm";
3
+ import { $action } from "alepha/server";
4
+ import { $logger } from "alepha/logger";
5
+
6
+ //#region ../../src/api-audits/entities/audits.ts
7
+ /**
8
+ * Audit severity levels for categorizing events.
9
+ */
10
+ const auditSeveritySchema = t.enum([
11
+ "info",
12
+ "warning",
13
+ "critical"
14
+ ], {
15
+ default: "info",
16
+ description: "Severity level of the audit event"
17
+ });
18
+ /**
19
+ * Audit log entity for tracking important system events.
20
+ *
21
+ * Stores comprehensive audit information including:
22
+ * - Who performed the action (userId, userRealm)
23
+ * - What happened (type, action, resource)
24
+ * - When it happened (createdAt)
25
+ * - Context and details (metadata, ipAddress, userAgent)
26
+ */
27
+ const audits = $entity({
28
+ name: "audits",
29
+ schema: t.object({
30
+ id: pg.primaryKey(t.bigint()),
31
+ createdAt: pg.createdAt(),
32
+ type: t.text({ description: "Audit event type (e.g., auth, user, payment, system)" }),
33
+ action: t.text({ description: "Specific action performed (e.g., login, create, update)" }),
34
+ severity: pg.default(auditSeveritySchema, "info"),
35
+ userId: t.optional(t.uuid()),
36
+ userRealm: t.optional(t.text()),
37
+ userEmail: t.optional(t.email()),
38
+ resourceType: t.optional(t.text()),
39
+ resourceId: t.optional(t.text()),
40
+ description: t.optional(t.text()),
41
+ metadata: t.optional(t.json()),
42
+ ipAddress: t.optional(t.text()),
43
+ userAgent: t.optional(t.text()),
44
+ sessionId: t.optional(t.uuid()),
45
+ requestId: t.optional(t.text()),
46
+ success: pg.default(t.boolean(), true),
47
+ errorMessage: t.optional(t.text())
48
+ }),
49
+ indexes: [
50
+ "createdAt",
51
+ "type",
52
+ "action",
53
+ "userId",
54
+ "userRealm",
55
+ "resourceType",
56
+ "resourceId",
57
+ "severity",
58
+ { columns: ["type", "action"] },
59
+ { columns: ["userId", "createdAt"] },
60
+ { columns: ["userRealm", "createdAt"] }
61
+ ]
62
+ });
63
+ const auditEntitySchema = audits.schema;
64
+ const auditEntityInsertSchema = audits.insertSchema;
65
+
66
+ //#endregion
67
+ //#region ../../src/api-audits/schemas/auditQuerySchema.ts
68
+ /**
69
+ * Query schema for searching and filtering audit logs.
70
+ */
71
+ const auditQuerySchema = t.extend(pageQuerySchema, {
72
+ type: t.optional(t.text({ description: "Filter by audit type" })),
73
+ action: t.optional(t.text({ description: "Filter by action" })),
74
+ severity: t.optional(auditSeveritySchema),
75
+ userId: t.optional(t.uuid({ description: "Filter by user ID" })),
76
+ userRealm: t.optional(t.text({ description: "Filter by user realm" })),
77
+ resourceType: t.optional(t.text({ description: "Filter by resource type" })),
78
+ resourceId: t.optional(t.text({ description: "Filter by resource ID" })),
79
+ success: t.optional(t.boolean({ description: "Filter by success status" })),
80
+ from: t.optional(t.datetime({ description: "Start date filter" })),
81
+ to: t.optional(t.datetime({ description: "End date filter" })),
82
+ search: t.optional(t.text({ description: "Search in description" }))
83
+ });
84
+
85
+ //#endregion
86
+ //#region ../../src/api-audits/schemas/auditResourceSchema.ts
87
+ /**
88
+ * Resource schema for audit log responses.
89
+ */
90
+ const auditResourceSchema = audits.schema;
91
+
92
+ //#endregion
93
+ //#region ../../src/api-audits/schemas/createAuditSchema.ts
94
+ /**
95
+ * Schema for creating a new audit log entry.
96
+ */
97
+ const createAuditSchema = t.object({
98
+ type: t.text({ description: "Audit event type" }),
99
+ action: t.text({ description: "Specific action performed" }),
100
+ severity: t.optional(auditSeveritySchema),
101
+ userId: t.optional(t.uuid()),
102
+ userRealm: t.optional(t.text()),
103
+ userEmail: t.optional(t.email()),
104
+ resourceType: t.optional(t.text()),
105
+ resourceId: t.optional(t.text()),
106
+ description: t.optional(t.text()),
107
+ metadata: t.optional(t.json()),
108
+ ipAddress: t.optional(t.text()),
109
+ userAgent: t.optional(t.text()),
110
+ sessionId: t.optional(t.uuid()),
111
+ requestId: t.optional(t.text()),
112
+ success: t.optional(t.boolean()),
113
+ errorMessage: t.optional(t.text())
114
+ });
115
+
116
+ //#endregion
117
+ //#region ../../src/api-audits/services/AuditService.ts
118
+ /**
119
+ * Service for managing audit logs.
120
+ *
121
+ * Provides methods for:
122
+ * - Creating audit entries
123
+ * - Querying audit history
124
+ * - Aggregating audit statistics
125
+ * - Managing registered audit types
126
+ */
127
+ var AuditService = class {
128
+ alepha = $inject(Alepha);
129
+ log = $logger();
130
+ repo = $repository(audits);
131
+ /**
132
+ * Registry of audit types and their allowed actions.
133
+ */
134
+ auditTypes = /* @__PURE__ */ new Map();
135
+ /**
136
+ * Register an audit type with its allowed actions.
137
+ */
138
+ registerType(definition) {
139
+ this.auditTypes.set(definition.type, definition);
140
+ this.log.debug("Audit type registered", {
141
+ type: definition.type,
142
+ actions: definition.actions
143
+ });
144
+ }
145
+ /**
146
+ * Get all registered audit types.
147
+ */
148
+ getRegisteredTypes() {
149
+ return Array.from(this.auditTypes.values());
150
+ }
151
+ /**
152
+ * Get current request context if available.
153
+ */
154
+ getRequestContext() {
155
+ return this.alepha.context.get("request");
156
+ }
157
+ /**
158
+ * Create a new audit log entry.
159
+ * Automatically populates ipAddress, userAgent, and requestId from the current request context.
160
+ */
161
+ async create(data) {
162
+ const request = this.getRequestContext();
163
+ const contextData = {};
164
+ if (request) {
165
+ if (!data.ipAddress && request.ip) contextData.ipAddress = request.ip;
166
+ if (!data.userAgent && request.headers["user-agent"]) contextData.userAgent = request.headers["user-agent"];
167
+ if (!data.requestId && request.requestId) contextData.requestId = request.requestId;
168
+ if (!data.sessionId && request.metadata?.sessionId) contextData.sessionId = request.metadata.sessionId;
169
+ const user = request.user;
170
+ if (user) {
171
+ if (!data.userId && user.id) contextData.userId = user.id;
172
+ if (!data.userEmail && user.email) contextData.userEmail = user.email;
173
+ if (!data.userRealm && user.realm) contextData.userRealm = user.realm;
174
+ }
175
+ }
176
+ this.log.trace("Creating audit entry", {
177
+ type: data.type,
178
+ action: data.action,
179
+ userId: data.userId ?? contextData.userId
180
+ });
181
+ const entry = await this.repo.create({
182
+ ...contextData,
183
+ ...data,
184
+ severity: data.severity ?? "info",
185
+ success: data.success ?? true
186
+ });
187
+ this.log.debug("Audit entry created", {
188
+ id: entry.id,
189
+ type: data.type,
190
+ action: data.action
191
+ });
192
+ return entry;
193
+ }
194
+ /**
195
+ * Record an audit event (convenience method).
196
+ */
197
+ async record(type, action, options = {}) {
198
+ return this.create({
199
+ type,
200
+ action,
201
+ ...options
202
+ });
203
+ }
204
+ /**
205
+ * Record an authentication event.
206
+ */
207
+ async recordAuth(action, options = {}) {
208
+ return this.create({
209
+ type: "auth",
210
+ action,
211
+ severity: action === "login_failed" ? "warning" : "info",
212
+ ...options
213
+ });
214
+ }
215
+ /**
216
+ * Record a user management event.
217
+ */
218
+ async recordUser(action, options = {}) {
219
+ return this.create({
220
+ type: "user",
221
+ action,
222
+ resourceType: "user",
223
+ ...options
224
+ });
225
+ }
226
+ /**
227
+ * Record a data access event.
228
+ */
229
+ async recordAccess(action, options = {}) {
230
+ return this.create({
231
+ type: "access",
232
+ action,
233
+ ...options
234
+ });
235
+ }
236
+ /**
237
+ * Record a security event.
238
+ */
239
+ async recordSecurity(action, options = {}) {
240
+ return this.create({
241
+ type: "security",
242
+ action,
243
+ severity: "warning",
244
+ ...options
245
+ });
246
+ }
247
+ /**
248
+ * Record a system event.
249
+ */
250
+ async recordSystem(action, options = {}) {
251
+ return this.create({
252
+ type: "system",
253
+ action,
254
+ severity: action === "error" ? "critical" : "info",
255
+ ...options
256
+ });
257
+ }
258
+ /**
259
+ * Find audit entries with filtering and pagination.
260
+ */
261
+ async find(query = {}) {
262
+ this.log.trace("Finding audit entries", { query });
263
+ query.sort ??= "-createdAt";
264
+ const where = this.repo.createQueryWhere();
265
+ if (query.type) where.type = { eq: query.type };
266
+ if (query.action) where.action = { eq: query.action };
267
+ if (query.severity) where.severity = { eq: query.severity };
268
+ if (query.userId) where.userId = { eq: query.userId };
269
+ if (query.userRealm) where.userRealm = { eq: query.userRealm };
270
+ if (query.resourceType) where.resourceType = { eq: query.resourceType };
271
+ if (query.resourceId) where.resourceId = { eq: query.resourceId };
272
+ if (query.success !== void 0) where.success = { eq: query.success };
273
+ if (query.from) where.createdAt = {
274
+ ...where.createdAt,
275
+ gte: query.from
276
+ };
277
+ if (query.to) where.createdAt = {
278
+ ...where.createdAt,
279
+ lte: query.to
280
+ };
281
+ if (query.search) where.description = { like: `%${query.search}%` };
282
+ const result = await this.repo.paginate(query, { where }, { count: true });
283
+ this.log.debug("Audit entries found", {
284
+ count: result.content.length,
285
+ total: result.page.totalElements
286
+ });
287
+ return result;
288
+ }
289
+ /**
290
+ * Get audit entry by ID.
291
+ */
292
+ async getById(id) {
293
+ return this.repo.findById(id);
294
+ }
295
+ /**
296
+ * Get audit entries for a specific user.
297
+ */
298
+ async findByUser(userId, query = {}) {
299
+ return this.find({
300
+ ...query,
301
+ userId
302
+ });
303
+ }
304
+ /**
305
+ * Get audit entries for a specific resource.
306
+ */
307
+ async findByResource(resourceType, resourceId, query = {}) {
308
+ return this.find({
309
+ ...query,
310
+ resourceType,
311
+ resourceId
312
+ });
313
+ }
314
+ /**
315
+ * Get audit statistics for a time period.
316
+ */
317
+ async getStats(options = {}) {
318
+ this.log.trace("Getting audit stats", options);
319
+ const where = this.repo.createQueryWhere();
320
+ if (options.from) where.createdAt = { gte: options.from.toISOString() };
321
+ if (options.to) where.createdAt = {
322
+ ...where.createdAt,
323
+ lte: options.to.toISOString()
324
+ };
325
+ if (options.userRealm) where.userRealm = { eq: options.userRealm };
326
+ const all = await this.repo.findMany({ where });
327
+ const stats = {
328
+ total: all.length,
329
+ byType: {},
330
+ bySeverity: {
331
+ info: 0,
332
+ warning: 0,
333
+ critical: 0
334
+ },
335
+ successRate: 0,
336
+ recentFailures: []
337
+ };
338
+ let successCount = 0;
339
+ for (const entry of all) {
340
+ stats.byType[entry.type] = (stats.byType[entry.type] || 0) + 1;
341
+ const severity = entry.severity;
342
+ stats.bySeverity[severity]++;
343
+ if (entry.success) successCount++;
344
+ }
345
+ stats.successRate = stats.total > 0 ? successCount / stats.total : 1;
346
+ stats.recentFailures = all.filter((e) => !e.success).sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()).slice(0, 10);
347
+ return stats;
348
+ }
349
+ /**
350
+ * Delete old audit entries (for retention policy).
351
+ */
352
+ async deleteOlderThan(date) {
353
+ this.log.info("Deleting old audit entries", { olderThan: date });
354
+ const old = await this.repo.findMany({ where: { createdAt: { lt: date.toISOString() } } });
355
+ for (const entry of old) await this.repo.deleteById(entry.id);
356
+ this.log.info("Old audit entries deleted", { count: old.length });
357
+ return old.length;
358
+ }
359
+ };
360
+
361
+ //#endregion
362
+ //#region ../../src/api-audits/controllers/AuditController.ts
363
+ /**
364
+ * REST API controller for audit log management.
365
+ *
366
+ * Provides endpoints for:
367
+ * - Querying audit logs with filtering
368
+ * - Creating audit entries
369
+ * - Getting audit statistics
370
+ * - Viewing registered audit types
371
+ */
372
+ var AuditController = class {
373
+ url = "/audits";
374
+ group = "audits";
375
+ auditService = $inject(AuditService);
376
+ /**
377
+ * Find audit entries with filtering and pagination.
378
+ */
379
+ findAudits = $action({
380
+ path: this.url,
381
+ group: this.group,
382
+ description: "Find audit entries with filtering and pagination",
383
+ schema: {
384
+ query: auditQuerySchema,
385
+ response: pg.page(auditResourceSchema)
386
+ },
387
+ handler: ({ query }) => this.auditService.find(query)
388
+ });
389
+ /**
390
+ * Get a single audit entry by ID.
391
+ */
392
+ getAudit = $action({
393
+ path: `${this.url}/:id`,
394
+ group: this.group,
395
+ description: "Get a single audit entry by ID",
396
+ schema: {
397
+ params: t.object({ id: t.text() }),
398
+ response: auditResourceSchema
399
+ },
400
+ handler: ({ params }) => this.auditService.getById(params.id)
401
+ });
402
+ /**
403
+ * Create a new audit entry.
404
+ */
405
+ createAudit = $action({
406
+ method: "POST",
407
+ path: this.url,
408
+ group: this.group,
409
+ description: "Create a new audit entry",
410
+ schema: {
411
+ body: createAuditSchema,
412
+ response: auditResourceSchema
413
+ },
414
+ handler: ({ body }) => this.auditService.create(body)
415
+ });
416
+ /**
417
+ * Get audit entries for a specific user.
418
+ */
419
+ findByUser = $action({
420
+ path: `${this.url}/user/:userId`,
421
+ group: this.group,
422
+ description: "Get audit entries for a specific user",
423
+ schema: {
424
+ params: t.object({ userId: t.uuid() }),
425
+ query: t.omit(auditQuerySchema, ["userId"]),
426
+ response: pg.page(auditResourceSchema)
427
+ },
428
+ handler: ({ params, query }) => this.auditService.findByUser(params.userId, query)
429
+ });
430
+ /**
431
+ * Get audit entries for a specific resource.
432
+ */
433
+ findByResource = $action({
434
+ path: `${this.url}/resource/:resourceType/:resourceId`,
435
+ group: this.group,
436
+ description: "Get audit entries for a specific resource",
437
+ schema: {
438
+ params: t.object({
439
+ resourceType: t.text(),
440
+ resourceId: t.text()
441
+ }),
442
+ query: t.omit(auditQuerySchema, ["resourceType", "resourceId"]),
443
+ response: pg.page(auditResourceSchema)
444
+ },
445
+ handler: ({ params, query }) => this.auditService.findByResource(params.resourceType, params.resourceId, query)
446
+ });
447
+ /**
448
+ * Get audit statistics.
449
+ */
450
+ getStats = $action({
451
+ path: `${this.url}/stats`,
452
+ group: this.group,
453
+ description: "Get audit statistics for a time period",
454
+ schema: {
455
+ query: t.object({
456
+ from: t.optional(t.datetime()),
457
+ to: t.optional(t.datetime()),
458
+ userRealm: t.optional(t.text())
459
+ }),
460
+ response: t.object({
461
+ total: t.integer(),
462
+ byType: t.record(t.text(), t.integer()),
463
+ bySeverity: t.object({
464
+ info: t.integer(),
465
+ warning: t.integer(),
466
+ critical: t.integer()
467
+ }),
468
+ successRate: t.number(),
469
+ recentFailures: t.array(auditResourceSchema)
470
+ })
471
+ },
472
+ handler: ({ query }) => this.auditService.getStats({
473
+ from: query.from ? new Date(query.from) : void 0,
474
+ to: query.to ? new Date(query.to) : void 0,
475
+ userRealm: query.userRealm
476
+ })
477
+ });
478
+ /**
479
+ * Get registered audit types.
480
+ */
481
+ getTypes = $action({
482
+ path: `${this.url}/types`,
483
+ group: this.group,
484
+ description: "Get all registered audit types",
485
+ schema: { response: t.array(t.object({
486
+ type: t.text(),
487
+ description: t.optional(t.text()),
488
+ actions: t.array(t.text())
489
+ })) },
490
+ handler: () => this.auditService.getRegisteredTypes()
491
+ });
492
+ /**
493
+ * Get distinct values for filters.
494
+ */
495
+ getFilterOptions = $action({
496
+ path: `${this.url}/filters`,
497
+ group: this.group,
498
+ description: "Get distinct values for audit filters",
499
+ schema: { response: t.object({
500
+ types: t.array(t.text()),
501
+ actions: t.array(t.text()),
502
+ resourceTypes: t.array(t.text()),
503
+ userRealms: t.array(t.text())
504
+ }) },
505
+ handler: async () => {
506
+ const types = this.auditService.getRegisteredTypes();
507
+ return {
508
+ types: types.map((t$1) => t$1.type),
509
+ actions: types.flatMap((t$1) => t$1.actions),
510
+ resourceTypes: [
511
+ "user",
512
+ "session",
513
+ "file",
514
+ "order",
515
+ "payment"
516
+ ],
517
+ userRealms: ["default"]
518
+ };
519
+ }
520
+ });
521
+ };
522
+
523
+ //#endregion
524
+ //#region ../../src/api-audits/primitives/$audit.ts
525
+ /**
526
+ * Audit type primitive for registering domain-specific audit events.
527
+ *
528
+ * Provides a type-safe way to define and log audit events within a specific domain.
529
+ *
530
+ * @example
531
+ * ```ts
532
+ * class PaymentAudits {
533
+ * audit = $audit({
534
+ * type: "payment",
535
+ * description: "Payment-related audit events",
536
+ * actions: ["create", "refund", "cancel", "dispute"],
537
+ * });
538
+ *
539
+ * async logPaymentCreated(paymentId: string, userId: string, amount: number) {
540
+ * await this.audit.log("create", {
541
+ * userId,
542
+ * resourceType: "payment",
543
+ * resourceId: paymentId,
544
+ * description: `Payment of ${amount} created`,
545
+ * metadata: { amount },
546
+ * });
547
+ * }
548
+ * }
549
+ * ```
550
+ */
551
+ var AuditPrimitive = class extends Primitive {
552
+ auditService = $inject(AuditService);
553
+ /**
554
+ * The audit type identifier.
555
+ */
556
+ get type() {
557
+ return this.options.type;
558
+ }
559
+ /**
560
+ * The audit type description.
561
+ */
562
+ get description() {
563
+ return this.options.description;
564
+ }
565
+ /**
566
+ * The allowed actions for this audit type.
567
+ */
568
+ get actions() {
569
+ return this.options.actions;
570
+ }
571
+ /**
572
+ * Log an audit event for this type.
573
+ */
574
+ async log(action, options = {}) {
575
+ await this.auditService.record(this.options.type, action, options);
576
+ }
577
+ /**
578
+ * Log a successful audit event.
579
+ */
580
+ async logSuccess(action, options = {}) {
581
+ await this.log(action, {
582
+ ...options,
583
+ success: true
584
+ });
585
+ }
586
+ /**
587
+ * Log a failed audit event.
588
+ */
589
+ async logFailure(action, errorMessage, options = {}) {
590
+ await this.log(action, {
591
+ ...options,
592
+ success: false,
593
+ errorMessage
594
+ });
595
+ }
596
+ /**
597
+ * Called during initialization to register this audit type.
598
+ */
599
+ onInit() {
600
+ const definition = {
601
+ type: this.options.type,
602
+ description: this.options.description,
603
+ actions: this.options.actions
604
+ };
605
+ this.auditService.registerType(definition);
606
+ }
607
+ };
608
+ /**
609
+ * Create an audit type primitive.
610
+ *
611
+ * @example
612
+ * ```ts
613
+ * class OrderAudits {
614
+ * audit = $audit({
615
+ * type: "order",
616
+ * description: "Order management events",
617
+ * actions: ["create", "update", "cancel", "fulfill", "ship"],
618
+ * });
619
+ * }
620
+ * ```
621
+ */
622
+ const $audit = (options) => {
623
+ return createPrimitive(AuditPrimitive, options);
624
+ };
625
+ $audit[KIND] = AuditPrimitive;
626
+
627
+ //#endregion
628
+ //#region ../../src/api-audits/index.ts
629
+ /**
630
+ * Provides audit logging API endpoints for Alepha applications.
631
+ *
632
+ * This module includes:
633
+ * - Audit log CRUD operations
634
+ * - Filtering and searching audit events
635
+ * - Audit statistics and analytics
636
+ * - `$audit` primitive for domain-specific audit types
637
+ *
638
+ * @module alepha.api.audits
639
+ *
640
+ * @example
641
+ * ```ts
642
+ * // In your app module
643
+ * import { AlephaApiAudits } from "alepha/api/audits";
644
+ *
645
+ * const App = $module({
646
+ * name: "app",
647
+ * services: [AlephaApiAudits, ...],
648
+ * });
649
+ *
650
+ * // Create domain-specific audit types
651
+ * class PaymentAudits {
652
+ * audit = $audit({
653
+ * type: "payment",
654
+ * actions: ["create", "refund", "cancel"],
655
+ * });
656
+ *
657
+ * async onPaymentCreated(paymentId: string, userId: string) {
658
+ * await this.audit.log("create", {
659
+ * userId,
660
+ * resourceType: "payment",
661
+ * resourceId: paymentId,
662
+ * });
663
+ * }
664
+ * }
665
+ * ```
666
+ */
667
+ const AlephaApiAudits = $module({
668
+ name: "alepha.api.audits",
669
+ services: [AuditService, AuditController]
670
+ });
671
+
672
+ //#endregion
673
+ export { $audit, AlephaApiAudits, AuditController, AuditPrimitive, AuditService, auditEntityInsertSchema, auditEntitySchema, auditQuerySchema, auditResourceSchema, auditSeveritySchema, audits, createAuditSchema };
674
+ //# sourceMappingURL=index.js.map