@axova/shared 1.0.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 (112) hide show
  1. package/CONFIGURATION_GUIDE.md +1 -0
  2. package/README.md +384 -0
  3. package/SCHEMA_ORGANIZATION.md +209 -0
  4. package/dist/configs/index.d.ts +85 -0
  5. package/dist/configs/index.js +555 -0
  6. package/dist/events/kafka.d.ts +40 -0
  7. package/dist/events/kafka.js +311 -0
  8. package/dist/index.d.ts +13 -0
  9. package/dist/index.js +41 -0
  10. package/dist/interfaces/customer-events.d.ts +85 -0
  11. package/dist/interfaces/customer-events.js +2 -0
  12. package/dist/interfaces/inventory-events.d.ts +453 -0
  13. package/dist/interfaces/inventory-events.js +3 -0
  14. package/dist/interfaces/inventory-types.d.ts +894 -0
  15. package/dist/interfaces/inventory-types.js +3 -0
  16. package/dist/interfaces/order-events.d.ts +320 -0
  17. package/dist/interfaces/order-events.js +3 -0
  18. package/dist/lib/auditLogger.d.ts +162 -0
  19. package/dist/lib/auditLogger.js +626 -0
  20. package/dist/lib/authOrganization.d.ts +24 -0
  21. package/dist/lib/authOrganization.js +110 -0
  22. package/dist/lib/db.d.ts +6 -0
  23. package/dist/lib/db.js +88 -0
  24. package/dist/middleware/serviceAuth.d.ts +60 -0
  25. package/dist/middleware/serviceAuth.js +272 -0
  26. package/dist/middleware/storeOwnership.d.ts +15 -0
  27. package/dist/middleware/storeOwnership.js +156 -0
  28. package/dist/middleware/storeValidationMiddleware.d.ts +44 -0
  29. package/dist/middleware/storeValidationMiddleware.js +180 -0
  30. package/dist/middleware/userAuth.d.ts +27 -0
  31. package/dist/middleware/userAuth.js +218 -0
  32. package/dist/schemas/admin/admin-schema.d.ts +741 -0
  33. package/dist/schemas/admin/admin-schema.js +111 -0
  34. package/dist/schemas/ai-moderation/ai-moderation-schema.d.ts +648 -0
  35. package/dist/schemas/ai-moderation/ai-moderation-schema.js +88 -0
  36. package/dist/schemas/common/common-schemas.d.ts +436 -0
  37. package/dist/schemas/common/common-schemas.js +94 -0
  38. package/dist/schemas/compliance/compliance-schema.d.ts +3388 -0
  39. package/dist/schemas/compliance/compliance-schema.js +472 -0
  40. package/dist/schemas/compliance/kyc-schema.d.ts +2642 -0
  41. package/dist/schemas/compliance/kyc-schema.js +361 -0
  42. package/dist/schemas/customer/customer-schema.d.ts +2727 -0
  43. package/dist/schemas/customer/customer-schema.js +399 -0
  44. package/dist/schemas/index.d.ts +27 -0
  45. package/dist/schemas/index.js +138 -0
  46. package/dist/schemas/inventory/inventory-tables.d.ts +9476 -0
  47. package/dist/schemas/inventory/inventory-tables.js +1470 -0
  48. package/dist/schemas/inventory/lot-tables.d.ts +3281 -0
  49. package/dist/schemas/inventory/lot-tables.js +608 -0
  50. package/dist/schemas/order/order-schema.d.ts +5825 -0
  51. package/dist/schemas/order/order-schema.js +954 -0
  52. package/dist/schemas/product/discount-relations.d.ts +15 -0
  53. package/dist/schemas/product/discount-relations.js +34 -0
  54. package/dist/schemas/product/discount-schema.d.ts +1975 -0
  55. package/dist/schemas/product/discount-schema.js +297 -0
  56. package/dist/schemas/product/product-relations.d.ts +41 -0
  57. package/dist/schemas/product/product-relations.js +133 -0
  58. package/dist/schemas/product/product-schema.d.ts +4544 -0
  59. package/dist/schemas/product/product-schema.js +671 -0
  60. package/dist/schemas/store/store-audit-schema.d.ts +4135 -0
  61. package/dist/schemas/store/store-audit-schema.js +556 -0
  62. package/dist/schemas/store/store-schema.d.ts +3100 -0
  63. package/dist/schemas/store/store-schema.js +381 -0
  64. package/dist/schemas/store/store-settings-schema.d.ts +665 -0
  65. package/dist/schemas/store/store-settings-schema.js +141 -0
  66. package/dist/schemas/types.d.ts +50 -0
  67. package/dist/schemas/types.js +3 -0
  68. package/dist/types/events.d.ts +2396 -0
  69. package/dist/types/events.js +505 -0
  70. package/dist/utils/errorHandler.d.ts +12 -0
  71. package/dist/utils/errorHandler.js +36 -0
  72. package/dist/utils/subdomain.d.ts +6 -0
  73. package/dist/utils/subdomain.js +20 -0
  74. package/nul +8 -0
  75. package/package.json +43 -0
  76. package/src/configs/index.ts +654 -0
  77. package/src/events/kafka.ts +429 -0
  78. package/src/index.ts +26 -0
  79. package/src/interfaces/customer-events.ts +106 -0
  80. package/src/interfaces/inventory-events.ts +545 -0
  81. package/src/interfaces/inventory-types.ts +1004 -0
  82. package/src/interfaces/order-events.ts +381 -0
  83. package/src/lib/auditLogger.ts +1117 -0
  84. package/src/lib/authOrganization.ts +153 -0
  85. package/src/lib/db.ts +64 -0
  86. package/src/middleware/serviceAuth.ts +328 -0
  87. package/src/middleware/storeOwnership.ts +199 -0
  88. package/src/middleware/storeValidationMiddleware.ts +247 -0
  89. package/src/middleware/userAuth.ts +248 -0
  90. package/src/schemas/admin/admin-schema.ts +208 -0
  91. package/src/schemas/ai-moderation/ai-moderation-schema.ts +180 -0
  92. package/src/schemas/common/common-schemas.ts +108 -0
  93. package/src/schemas/compliance/compliance-schema.ts +927 -0
  94. package/src/schemas/compliance/kyc-schema.ts +649 -0
  95. package/src/schemas/customer/customer-schema.ts +576 -0
  96. package/src/schemas/index.ts +189 -0
  97. package/src/schemas/inventory/inventory-tables.ts +1927 -0
  98. package/src/schemas/inventory/lot-tables.ts +799 -0
  99. package/src/schemas/order/order-schema.ts +1400 -0
  100. package/src/schemas/product/discount-relations.ts +44 -0
  101. package/src/schemas/product/discount-schema.ts +464 -0
  102. package/src/schemas/product/product-relations.ts +187 -0
  103. package/src/schemas/product/product-schema.ts +955 -0
  104. package/src/schemas/store/ethiopian_business_api.md.resolved +212 -0
  105. package/src/schemas/store/store-audit-schema.ts +1257 -0
  106. package/src/schemas/store/store-schema.ts +661 -0
  107. package/src/schemas/store/store-settings-schema.ts +231 -0
  108. package/src/schemas/types.ts +67 -0
  109. package/src/types/events.ts +646 -0
  110. package/src/utils/errorHandler.ts +44 -0
  111. package/src/utils/subdomain.ts +19 -0
  112. package/tsconfig.json +21 -0
@@ -0,0 +1,626 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AuditLogger = void 0;
4
+ exports.createAuditLogger = createAuditLogger;
5
+ exports.createAuditMiddleware = createAuditMiddleware;
6
+ exports.logAuditEvent = logAuditEvent;
7
+ exports.logStoreAuditEvent = logStoreAuditEvent;
8
+ exports.setDefaultAuditLogger = setDefaultAuditLogger;
9
+ exports.getDefaultAuditLogger = getDefaultAuditLogger;
10
+ exports.quickLog = quickLog;
11
+ exports.quickLogUserAction = quickLogUserAction;
12
+ exports.quickLogSystemAction = quickLogSystemAction;
13
+ const node_perf_hooks_1 = require("node:perf_hooks");
14
+ const cuid2_1 = require("@paralleldrive/cuid2");
15
+ // Shared Audit Logger Class
16
+ class AuditLogger {
17
+ constructor(config, initialContext) {
18
+ this.buffer = [];
19
+ this.flushTimer = null;
20
+ this.performanceTrackers = new Map();
21
+ this.config = {
22
+ bufferSize: 100,
23
+ flushInterval: 5000,
24
+ defaultRetentionDays: 2555,
25
+ autoEnrichment: true,
26
+ sensitiveFieldMasking: true,
27
+ geoLocationEnabled: false,
28
+ enableLocalLogging: true,
29
+ enableRemoteLogging: true,
30
+ ...config,
31
+ };
32
+ this.context = {
33
+ serviceName: config.serviceName,
34
+ serviceVersion: config.serviceVersion,
35
+ environment: config.environment ||
36
+ process.env.NODE_ENV ||
37
+ "DEVELOPMENT",
38
+ ...initialContext,
39
+ };
40
+ this.setupAutoFlush();
41
+ }
42
+ // Update context (useful for request-scoped information)
43
+ updateContext(contextUpdate) {
44
+ this.context = { ...this.context, ...contextUpdate };
45
+ }
46
+ // Get current context
47
+ getContext() {
48
+ return { ...this.context };
49
+ }
50
+ // Log a custom audit event
51
+ async log(entry) {
52
+ try {
53
+ const enrichedEntry = await this.enrichEntry(entry);
54
+ const auditId = (0, cuid2_1.createId)();
55
+ // Add to buffer
56
+ this.addToBuffer(enrichedEntry);
57
+ // Local logging
58
+ if (this.config.enableLocalLogging) {
59
+ this.logLocally(enrichedEntry, auditId);
60
+ }
61
+ // Check if immediate flush is needed for critical events
62
+ if (this.isCriticalEvent(enrichedEntry)) {
63
+ await this.flush();
64
+ }
65
+ return auditId;
66
+ }
67
+ catch (error) {
68
+ console.error("Failed to log audit event:", error);
69
+ throw error;
70
+ }
71
+ }
72
+ // Performance tracking helpers
73
+ startPerformanceTracking(operationId) {
74
+ const id = operationId || (0, cuid2_1.createId)();
75
+ const tracker = {
76
+ start: node_perf_hooks_1.performance.now(),
77
+ end: () => node_perf_hooks_1.performance.now(),
78
+ duration: function () {
79
+ return this.end() - this.start;
80
+ },
81
+ };
82
+ this.performanceTrackers.set(id, tracker);
83
+ return id;
84
+ }
85
+ endPerformanceTracking(operationId) {
86
+ const tracker = this.performanceTrackers.get(operationId);
87
+ if (tracker) {
88
+ const duration = tracker.duration();
89
+ this.performanceTrackers.delete(operationId);
90
+ return Math.round(duration);
91
+ }
92
+ return 0;
93
+ }
94
+ // Quick action builders
95
+ get quick() {
96
+ return {
97
+ userLogin: (userId, additionalData) => ({
98
+ eventType: "LOGIN",
99
+ eventCategory: "USER_ACTION",
100
+ action: "user_login",
101
+ resource: "authentication",
102
+ resourceId: userId,
103
+ resourceType: "USER",
104
+ performedBy: userId,
105
+ performedByType: "USER",
106
+ riskLevel: "LOW",
107
+ complianceRelevant: true,
108
+ ...additionalData,
109
+ }),
110
+ userLogout: (userId, additionalData) => ({
111
+ eventType: "LOGOUT",
112
+ eventCategory: "USER_ACTION",
113
+ action: "user_logout",
114
+ resource: "authentication",
115
+ resourceId: userId,
116
+ resourceType: "USER",
117
+ performedBy: userId,
118
+ performedByType: "USER",
119
+ riskLevel: "NONE",
120
+ ...additionalData,
121
+ }),
122
+ dataAccess: (resource, resourceId, userId, additionalData) => ({
123
+ eventType: "ACCESS",
124
+ eventCategory: "DATA_ACTION",
125
+ action: "data_access",
126
+ resource,
127
+ resourceId,
128
+ performedBy: userId,
129
+ performedByType: "USER",
130
+ riskLevel: "LOW",
131
+ complianceRelevant: true,
132
+ ...additionalData,
133
+ }),
134
+ dataCreate: (resource, resourceId, userId, data, additionalData) => ({
135
+ eventType: "CREATE",
136
+ eventCategory: "DATA_ACTION",
137
+ action: "data_create",
138
+ resource,
139
+ resourceId,
140
+ performedBy: userId,
141
+ performedByType: "USER",
142
+ changes: data ? { after: data } : undefined,
143
+ riskLevel: "LOW",
144
+ ...additionalData,
145
+ }),
146
+ dataUpdate: (resource, resourceId, userId, changes, additionalData) => ({
147
+ eventType: "UPDATE",
148
+ eventCategory: "DATA_ACTION",
149
+ action: "data_update",
150
+ resource,
151
+ resourceId,
152
+ performedBy: userId,
153
+ performedByType: "USER",
154
+ changes: changes
155
+ ? {
156
+ before: changes?.before,
157
+ after: changes?.after,
158
+ fields: changes?.fields,
159
+ }
160
+ : undefined,
161
+ riskLevel: "MEDIUM",
162
+ ...additionalData,
163
+ }),
164
+ dataDelete: (resource, resourceId, userId, additionalData) => ({
165
+ eventType: "DELETE",
166
+ eventCategory: "DATA_ACTION",
167
+ action: "data_delete",
168
+ resource,
169
+ resourceId,
170
+ performedBy: userId,
171
+ performedByType: "USER",
172
+ riskLevel: "HIGH",
173
+ complianceRelevant: true,
174
+ ...additionalData,
175
+ }),
176
+ permissionChange: (targetUserId, changedBy, changes, additionalData) => ({
177
+ eventType: "PERMISSION_CHANGE",
178
+ eventCategory: "ADMIN_ACTION",
179
+ action: "permission_change",
180
+ resource: "user_permissions",
181
+ resourceId: targetUserId,
182
+ performedBy: changedBy,
183
+ performedByType: "ADMIN",
184
+ changes: changes
185
+ ? {
186
+ before: changes?.before,
187
+ after: changes?.after,
188
+ fields: changes?.fields,
189
+ }
190
+ : undefined,
191
+ riskLevel: "HIGH",
192
+ securityImpact: "MEDIUM",
193
+ ...additionalData,
194
+ }),
195
+ securityEvent: (eventType, description, severity, additionalData) => ({
196
+ eventType: "SECURITY_EVENT",
197
+ eventCategory: "SECURITY_ACTION",
198
+ action: eventType,
199
+ resource: "security",
200
+ resourceId: (0, cuid2_1.createId)(),
201
+ performedBy: "SYSTEM",
202
+ performedByType: "SYSTEM",
203
+ riskLevel: severity,
204
+ securityImpact: severity,
205
+ metadata: {
206
+ severity,
207
+ description,
208
+ businessImpact: severity === "CRITICAL"
209
+ ? "Service disruption possible"
210
+ : "Monitoring required",
211
+ },
212
+ ...additionalData,
213
+ }),
214
+ complianceEvent: (framework, requirement, status, additionalData) => ({
215
+ eventType: "COMPLIANCE_ACTION",
216
+ eventCategory: "COMPLIANCE_ACTION",
217
+ action: "compliance_check",
218
+ resource: "compliance_requirement",
219
+ resourceId: `${framework}_${requirement}`,
220
+ performedBy: "SYSTEM",
221
+ performedByType: "SYSTEM",
222
+ complianceRelevant: true,
223
+ riskLevel: status === "NOT_MET" ? "HIGH" : "LOW",
224
+ metadata: {
225
+ framework,
226
+ requirement,
227
+ status,
228
+ businessImpact: status === "NOT_MET"
229
+ ? "Compliance violation detected"
230
+ : "Compliance maintained",
231
+ },
232
+ ...additionalData,
233
+ }),
234
+ systemAction: (action, resource, resourceId, additionalData) => ({
235
+ eventType: "SYSTEM_ACTION",
236
+ eventCategory: "SYSTEM_ACTION",
237
+ action,
238
+ resource,
239
+ resourceId,
240
+ performedBy: this.context.serviceName,
241
+ performedByType: "SYSTEM",
242
+ riskLevel: "NONE",
243
+ ...additionalData,
244
+ }),
245
+ storeAction: (storeId, action, resource, resourceId, userId, additionalData) => ({
246
+ eventType: "UPDATE",
247
+ eventCategory: userId ? "USER_ACTION" : "SYSTEM_ACTION",
248
+ action,
249
+ resource,
250
+ resourceId,
251
+ resourceType: "STORE",
252
+ performedBy: userId || this.context.serviceName,
253
+ performedByType: userId ? "USER" : "SYSTEM",
254
+ storeId,
255
+ riskLevel: "LOW",
256
+ ...additionalData,
257
+ }),
258
+ };
259
+ }
260
+ // Convenience methods for common audit events
261
+ async logUserLogin(userId, additionalData) {
262
+ return this.log(this.quick.userLogin(userId, additionalData));
263
+ }
264
+ async logUserLogout(userId, additionalData) {
265
+ return this.log(this.quick.userLogout(userId, additionalData));
266
+ }
267
+ async logDataAccess(resource, resourceId, userId, additionalData) {
268
+ return this.log(this.quick.dataAccess(resource, resourceId, userId, additionalData));
269
+ }
270
+ async logDataCreate(resource, resourceId, userId, data, additionalData) {
271
+ return this.log(this.quick.dataCreate(resource, resourceId, userId, data, additionalData));
272
+ }
273
+ async logDataUpdate(resource, resourceId, userId, changes, additionalData) {
274
+ return this.log(this.quick.dataUpdate(resource, resourceId, userId, changes, additionalData));
275
+ }
276
+ async logDataDelete(resource, resourceId, userId, additionalData) {
277
+ return this.log(this.quick.dataDelete(resource, resourceId, userId, additionalData));
278
+ }
279
+ async logSecurityEvent(eventType, description, severity, additionalData) {
280
+ return this.log(this.quick.securityEvent(eventType, description, severity, additionalData));
281
+ }
282
+ async logStoreAction(storeId, action, resource, resourceId, userId, additionalData) {
283
+ return this.log(this.quick.storeAction(storeId, action, resource, resourceId, userId, additionalData));
284
+ }
285
+ // Wrapper for async operations with automatic audit logging
286
+ async auditedOperation(operationName, operation, auditData) {
287
+ const trackingId = this.startPerformanceTracking();
288
+ const _startTime = Date.now();
289
+ try {
290
+ const result = await operation();
291
+ const duration = this.endPerformanceTracking(trackingId);
292
+ const _auditId = await this.log({
293
+ ...auditData,
294
+ action: operationName,
295
+ success: true,
296
+ duration,
297
+ });
298
+ return { result, auditId: _auditId, duration };
299
+ }
300
+ catch (error) {
301
+ const duration = this.endPerformanceTracking(trackingId);
302
+ const _auditId = await this.log({
303
+ ...auditData,
304
+ action: operationName,
305
+ success: false,
306
+ duration,
307
+ errorMessage: error instanceof Error ? error.message : "Unknown error",
308
+ stackTrace: error instanceof Error ? error.stack : undefined,
309
+ riskLevel: "MEDIUM",
310
+ });
311
+ throw error;
312
+ }
313
+ }
314
+ // Bulk logging for batch operations
315
+ async logBatch(entries) {
316
+ try {
317
+ const enrichedEntries = await Promise.all(entries.map((entry) => this.enrichEntry(entry)));
318
+ const auditIds = enrichedEntries.map(() => (0, cuid2_1.createId)());
319
+ // Add all to buffer
320
+ enrichedEntries.forEach((entry) => this.addToBuffer(entry));
321
+ // Local logging
322
+ if (this.config.enableLocalLogging) {
323
+ enrichedEntries.forEach((entry, index) => {
324
+ this.logLocally(entry, auditIds[index]);
325
+ });
326
+ }
327
+ // Check if any critical events require immediate flush
328
+ const hasCriticalEvents = enrichedEntries.some((entry) => this.isCriticalEvent(entry));
329
+ if (hasCriticalEvents) {
330
+ await this.flush();
331
+ }
332
+ return auditIds;
333
+ }
334
+ catch (error) {
335
+ console.error("Failed to log batch audit events:", error);
336
+ throw error;
337
+ }
338
+ }
339
+ // Flush buffer manually
340
+ async flush() {
341
+ if (this.buffer.length === 0)
342
+ return;
343
+ try {
344
+ const entriesToFlush = this.buffer.splice(0);
345
+ if (this.config.enableRemoteLogging) {
346
+ await this.sendToAuditService(entriesToFlush);
347
+ }
348
+ console.log(`✅ Flushed ${entriesToFlush.length} audit log entries`);
349
+ }
350
+ catch (error) {
351
+ console.error("Failed to flush audit log buffer:", error);
352
+ // Re-add entries to buffer for retry
353
+ this.buffer.unshift(...this.buffer);
354
+ throw error;
355
+ }
356
+ }
357
+ // Private helper methods
358
+ async enrichEntry(entry) {
359
+ const baseEntry = {
360
+ eventType: entry.eventType || "SYSTEM_ACTION",
361
+ eventCategory: entry.eventCategory || "SYSTEM_ACTION",
362
+ action: entry.action || "unknown_action",
363
+ resource: entry.resource || "unknown_resource",
364
+ resourceId: entry.resourceId || (0, cuid2_1.createId)(),
365
+ performedBy: entry.performedBy || this.context.serviceName,
366
+ performedByType: entry.performedByType || "SYSTEM",
367
+ success: entry.success ?? true,
368
+ riskLevel: entry.riskLevel || "NONE",
369
+ securityImpact: entry.securityImpact || "NONE",
370
+ retentionPeriod: entry.retentionPeriod || this.config.defaultRetentionDays,
371
+ ...entry,
372
+ };
373
+ // Auto-enrichment from context
374
+ if (this.config.autoEnrichment) {
375
+ if (this.context.requestId && !baseEntry.requestId) {
376
+ baseEntry.requestId = this.context.requestId;
377
+ }
378
+ if (this.context.correlationId && !baseEntry.correlationId) {
379
+ baseEntry.correlationId = this.context.correlationId;
380
+ }
381
+ if (this.context.sessionId && !baseEntry.sessionId) {
382
+ baseEntry.sessionId = this.context.sessionId;
383
+ }
384
+ if (this.context.ipAddress && !baseEntry.ipAddress) {
385
+ baseEntry.ipAddress = this.context.ipAddress;
386
+ }
387
+ if (this.context.userAgent && !baseEntry.userAgent) {
388
+ baseEntry.userAgent = this.context.userAgent;
389
+ }
390
+ if (this.context.clientId && !baseEntry.clientId) {
391
+ baseEntry.clientId = this.context.clientId;
392
+ }
393
+ if (this.context.clientType && !baseEntry.clientType) {
394
+ baseEntry.clientType = this.context.clientType;
395
+ }
396
+ if (this.context.storeId && !baseEntry.storeId) {
397
+ baseEntry.storeId = this.context.storeId;
398
+ }
399
+ if (this.context.storeName && !baseEntry.storeName) {
400
+ baseEntry.storeName = this.context.storeName;
401
+ }
402
+ // Enrich metadata
403
+ if (!baseEntry.metadata) {
404
+ baseEntry.metadata = {};
405
+ }
406
+ baseEntry.metadata.environment = this.context.environment;
407
+ baseEntry.metadata.version = this.context.serviceVersion;
408
+ if (this.context.features?.length) {
409
+ baseEntry.metadata.tags = [
410
+ ...(baseEntry.metadata.tags || []),
411
+ ...this.context.features,
412
+ ];
413
+ }
414
+ if (this.context.tags?.length) {
415
+ baseEntry.metadata.tags = [
416
+ ...(baseEntry.metadata.tags || []),
417
+ ...this.context.tags,
418
+ ];
419
+ }
420
+ if (this.context.customMetadata) {
421
+ baseEntry.metadata.customFields = {
422
+ ...baseEntry.metadata.customFields,
423
+ ...this.context.customMetadata,
424
+ };
425
+ }
426
+ }
427
+ // Mask sensitive data if enabled
428
+ if (this.config.sensitiveFieldMasking) {
429
+ baseEntry.changes = this.maskSensitiveData(baseEntry.changes);
430
+ baseEntry.metadata = this.maskSensitiveData(baseEntry.metadata);
431
+ }
432
+ return baseEntry;
433
+ }
434
+ addToBuffer(entry) {
435
+ this.buffer.push(entry);
436
+ if (this.buffer.length >= (this.config.bufferSize || 100)) {
437
+ setImmediate(() => this.flush());
438
+ }
439
+ }
440
+ logLocally(entry, auditId) {
441
+ const logLevel = this.getLogLevel(entry);
442
+ const message = `AUDIT [${auditId}] ${entry.action} on ${entry.resource}:${entry.resourceId} by ${entry.performedBy}`;
443
+ switch (logLevel) {
444
+ case "error":
445
+ console.error(message, { auditEntry: entry });
446
+ break;
447
+ case "warn":
448
+ console.warn(message, { auditEntry: entry });
449
+ break;
450
+ default:
451
+ console.log(message, { auditEntry: entry });
452
+ break;
453
+ }
454
+ }
455
+ getLogLevel(entry) {
456
+ if (!entry.success ||
457
+ entry.riskLevel === "CRITICAL" ||
458
+ entry.securityImpact === "CRITICAL") {
459
+ return "error";
460
+ }
461
+ if (entry.riskLevel === "HIGH" || entry.securityImpact === "HIGH") {
462
+ return "warn";
463
+ }
464
+ return "info";
465
+ }
466
+ isCriticalEvent(entry) {
467
+ return (entry.riskLevel === "CRITICAL" ||
468
+ entry.securityImpact === "CRITICAL" ||
469
+ entry.eventCategory === "SECURITY_ACTION" ||
470
+ (entry.success === false && entry.eventType === "LOGIN"));
471
+ }
472
+ async sendToAuditService(entries) {
473
+ if (!this.config.auditServiceUrl)
474
+ return;
475
+ try {
476
+ const response = await fetch(`${this.config.auditServiceUrl}/audit/bulk`, {
477
+ method: "POST",
478
+ headers: {
479
+ "Content-Type": "application/json",
480
+ ...(this.config.auditServiceApiKey && {
481
+ Authorization: `Bearer ${this.config.auditServiceApiKey}`,
482
+ }),
483
+ },
484
+ body: JSON.stringify({ entries }),
485
+ });
486
+ if (!response.ok) {
487
+ throw new Error(`Audit service responded with status: ${response.status}`);
488
+ }
489
+ }
490
+ catch (error) {
491
+ console.error("Failed to send audit logs to audit service:", error);
492
+ throw error;
493
+ }
494
+ }
495
+ maskSensitiveData(data) {
496
+ if (!data || typeof data !== "object") {
497
+ return data;
498
+ }
499
+ const sensitiveKeys = [
500
+ "password",
501
+ "token",
502
+ "secret",
503
+ "key",
504
+ "ssn",
505
+ "credit",
506
+ "card",
507
+ "bank",
508
+ "account",
509
+ ];
510
+ const masked = { ...data };
511
+ Object.keys(masked).forEach((key) => {
512
+ const lowerKey = key.toLowerCase();
513
+ if (sensitiveKeys.some((sensitive) => lowerKey.includes(sensitive))) {
514
+ masked[key] = "[MASKED]";
515
+ }
516
+ else if (typeof masked[key] === "object" && masked[key] !== null) {
517
+ masked[key] = this.maskSensitiveData(masked[key]);
518
+ }
519
+ });
520
+ return masked;
521
+ }
522
+ setupAutoFlush() {
523
+ if (this.config.flushInterval && this.config.flushInterval > 0) {
524
+ this.flushTimer = setInterval(() => {
525
+ if (this.buffer.length > 0) {
526
+ this.flush().catch((error) => {
527
+ console.error("Auto-flush failed:", error);
528
+ });
529
+ }
530
+ }, this.config.flushInterval);
531
+ }
532
+ }
533
+ // Cleanup
534
+ async shutdown() {
535
+ try {
536
+ if (this.flushTimer) {
537
+ clearInterval(this.flushTimer);
538
+ this.flushTimer = null;
539
+ }
540
+ // Flush any remaining entries
541
+ if (this.buffer.length > 0) {
542
+ await this.flush();
543
+ }
544
+ console.log("✅ Audit Logger shutdown complete");
545
+ }
546
+ catch (error) {
547
+ console.error("❌ Error during audit logger shutdown:", error);
548
+ }
549
+ }
550
+ }
551
+ exports.AuditLogger = AuditLogger;
552
+ // Factory function for creating audit logger instances
553
+ function createAuditLogger(config, initialContext) {
554
+ return new AuditLogger(config, initialContext);
555
+ }
556
+ // Middleware factory for Express/Fastify request context
557
+ function createAuditMiddleware(logger) {
558
+ return (req, _res, next) => {
559
+ const requestId = req.headers?.["x-request-id"] || (0, cuid2_1.createId)();
560
+ const correlationId = req.headers?.["x-correlation-id"];
561
+ const sessionId = req.headers?.["x-session-id"] || req.session?.id;
562
+ // Update audit context for this request
563
+ logger.updateContext({
564
+ requestId,
565
+ correlationId,
566
+ sessionId,
567
+ ipAddress: req.ip || req.connection?.remoteAddress,
568
+ userAgent: req.headers?.["user-agent"],
569
+ userId: req.user?.id,
570
+ userType: req.user?.type,
571
+ clientId: req.headers?.["x-client-id"],
572
+ clientType: req.headers?.["x-client-type"],
573
+ });
574
+ // Attach audit logger to request for easy access
575
+ req.audit = logger;
576
+ next();
577
+ };
578
+ }
579
+ // Export convenience functions
580
+ async function logAuditEvent(serviceName, entry, context) {
581
+ const logger = createAuditLogger({ serviceName }, context);
582
+ return logger.log(entry);
583
+ }
584
+ async function logStoreAuditEvent(serviceName, storeId, action, resource, resourceId, userId, additionalData) {
585
+ const logger = createAuditLogger({ serviceName }, { storeId });
586
+ return logger.logStoreAction(storeId, action, resource, resourceId, userId, additionalData);
587
+ }
588
+ // Default audit logger instance (can be configured once and reused)
589
+ let defaultLogger = null;
590
+ function setDefaultAuditLogger(logger) {
591
+ defaultLogger = logger;
592
+ }
593
+ function getDefaultAuditLogger() {
594
+ if (!defaultLogger) {
595
+ throw new Error("Default audit logger not configured. Call setDefaultAuditLogger() first.");
596
+ }
597
+ return defaultLogger;
598
+ }
599
+ // Quick logging functions using default logger
600
+ async function quickLog(entry) {
601
+ return getDefaultAuditLogger().log(entry);
602
+ }
603
+ async function quickLogUserAction(action, resource, resourceId, userId, additionalData) {
604
+ return getDefaultAuditLogger().log({
605
+ eventType: "UPDATE",
606
+ eventCategory: "USER_ACTION",
607
+ action,
608
+ resource,
609
+ resourceId,
610
+ performedBy: userId,
611
+ performedByType: "USER",
612
+ ...additionalData,
613
+ });
614
+ }
615
+ async function quickLogSystemAction(action, resource, resourceId, additionalData) {
616
+ return getDefaultAuditLogger().log({
617
+ eventType: "SYSTEM_ACTION",
618
+ eventCategory: "SYSTEM_ACTION",
619
+ action,
620
+ resource,
621
+ resourceId,
622
+ performedBy: "SYSTEM",
623
+ performedByType: "SYSTEM",
624
+ ...additionalData,
625
+ });
626
+ }
@@ -0,0 +1,24 @@
1
+ export interface AuthOrganizationCreateRequest {
2
+ name: string;
3
+ slug: string;
4
+ logo?: string;
5
+ metadata?: Record<string, unknown>;
6
+ userId?: string;
7
+ keepCurrentActiveOrganization?: boolean;
8
+ }
9
+ export interface AuthOrganizationResponse {
10
+ id: string;
11
+ name: string;
12
+ slug: string;
13
+ logo?: string;
14
+ metadata?: Record<string, unknown>;
15
+ createdAt: Date;
16
+ updatedAt?: Date;
17
+ }
18
+ /**
19
+ * Creates an organization using the auth service
20
+ * @param organizationData Organization data to create
21
+ * @param headers Authentication headers to forward
22
+ * @returns Promise resolving to created organization data
23
+ */
24
+ export declare const createAuthOrganization: (organizationData: AuthOrganizationCreateRequest, headers?: Record<string, string>) => Promise<AuthOrganizationResponse>;