@axova/shared 1.0.1 → 1.0.2
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.
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -2
- package/dist/middleware/storeOwnership.js +3 -22
- package/dist/middleware/storeValidationMiddleware.js +39 -16
- package/dist/schemas/admin/admin-schema.d.ts +2 -2
- package/dist/schemas/ai-moderation/ai-moderation-schema.d.ts +2 -2
- package/dist/schemas/index.d.ts +0 -28
- package/dist/schemas/index.js +3 -125
- package/dist/utils/subdomain.d.ts +1 -1
- package/dist/utils/subdomain.js +15 -10
- package/package.json +1 -1
- package/src/index.ts +0 -3
- package/src/middleware/storeOwnership.ts +3 -21
- package/src/middleware/storeValidationMiddleware.ts +50 -17
- package/src/schemas/index.ts +5 -194
- package/src/utils/subdomain.ts +15 -11
- package/src/schemas/compliance/compliance-schema.ts +0 -927
- package/src/schemas/compliance/kyc-schema.ts +0 -649
- package/src/schemas/customer/customer-schema.ts +0 -576
- package/src/schemas/inventory/inventory-tables.ts +0 -1927
- package/src/schemas/inventory/lot-tables.ts +0 -799
- package/src/schemas/order/order-schema.ts +0 -1400
- package/src/schemas/product/discount-relations.ts +0 -44
- package/src/schemas/product/discount-schema.ts +0 -464
- package/src/schemas/product/product-relations.ts +0 -187
- package/src/schemas/product/product-schema.ts +0 -955
- package/src/schemas/store/ethiopian_business_api.md.resolved +0 -212
- package/src/schemas/store/store-audit-schema.ts +0 -1257
- package/src/schemas/store/store-schema.ts +0 -661
- package/src/schemas/store/store-settings-schema.ts +0 -231
- package/src/schemas/store/storefront-config-schema.ts +0 -604
|
@@ -1,1257 +0,0 @@
|
|
|
1
|
-
import { createId } from "@paralleldrive/cuid2";
|
|
2
|
-
import { relations } from "drizzle-orm";
|
|
3
|
-
import {
|
|
4
|
-
boolean,
|
|
5
|
-
index,
|
|
6
|
-
integer,
|
|
7
|
-
jsonb,
|
|
8
|
-
pgTable,
|
|
9
|
-
real,
|
|
10
|
-
text,
|
|
11
|
-
timestamp,
|
|
12
|
-
varchar,
|
|
13
|
-
} from "drizzle-orm/pg-core";
|
|
14
|
-
|
|
15
|
-
// =====================================================
|
|
16
|
-
// STORE AUDIT LOGS - COMPREHENSIVE TRACKING SYSTEM
|
|
17
|
-
// =====================================================
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Primary Store Audit Logs Table
|
|
21
|
-
* Immutable, append-only design for complete store operation tracking
|
|
22
|
-
* Optimized for high-volume insertions with comprehensive indexing
|
|
23
|
-
*/
|
|
24
|
-
export const storeAuditLogs = pgTable(
|
|
25
|
-
"store_audit_logs",
|
|
26
|
-
{
|
|
27
|
-
// Primary Identification
|
|
28
|
-
id: text("id")
|
|
29
|
-
.primaryKey()
|
|
30
|
-
.$defaultFn(() => createId()),
|
|
31
|
-
|
|
32
|
-
// Store Context - Core Business Entity
|
|
33
|
-
storeId: text("store_id").notNull(),
|
|
34
|
-
storeName: varchar("store_name", { length: 255 }),
|
|
35
|
-
storeSubdomain: varchar("store_subdomain", { length: 63 }),
|
|
36
|
-
storeUrl: varchar("store_url", { length: 255 }),
|
|
37
|
-
|
|
38
|
-
// Event Classification - Enhanced Categorization
|
|
39
|
-
eventType: varchar("event_type", { length: 30 })
|
|
40
|
-
.notNull()
|
|
41
|
-
.$type<
|
|
42
|
-
| "CREATE"
|
|
43
|
-
| "READ"
|
|
44
|
-
| "UPDATE"
|
|
45
|
-
| "DELETE"
|
|
46
|
-
| "UPLOAD"
|
|
47
|
-
| "DOWNLOAD"
|
|
48
|
-
| "EXPORT"
|
|
49
|
-
| "IMPORT"
|
|
50
|
-
| "LOGIN"
|
|
51
|
-
| "LOGOUT"
|
|
52
|
-
| "ACCESS"
|
|
53
|
-
| "PERMISSION_CHANGE"
|
|
54
|
-
| "SYSTEM_ACTION"
|
|
55
|
-
| "COMPLIANCE_ACTION"
|
|
56
|
-
| "SECURITY_EVENT"
|
|
57
|
-
| "CONFIGURATION_CHANGE"
|
|
58
|
-
| "BULK_OPERATION"
|
|
59
|
-
>(),
|
|
60
|
-
|
|
61
|
-
eventCategory: varchar("event_category", { length: 30 })
|
|
62
|
-
.notNull()
|
|
63
|
-
.$type<
|
|
64
|
-
| "USER_ACTION"
|
|
65
|
-
| "ADMIN_ACTION"
|
|
66
|
-
| "SYSTEM_ACTION"
|
|
67
|
-
| "DATA_ACTION"
|
|
68
|
-
| "CONTENT_ACTION"
|
|
69
|
-
| "SECURITY_ACTION"
|
|
70
|
-
| "COMPLIANCE_ACTION"
|
|
71
|
-
| "BUSINESS_ACTION"
|
|
72
|
-
| "INTEGRATION_ACTION"
|
|
73
|
-
| "NOTIFICATION_ACTION"
|
|
74
|
-
| "ANALYTICS_ACTION"
|
|
75
|
-
| "MAINTENANCE_ACTION"
|
|
76
|
-
>(),
|
|
77
|
-
|
|
78
|
-
// Action Details - Comprehensive Operation Tracking
|
|
79
|
-
action: varchar("action", { length: 100 }).notNull(),
|
|
80
|
-
actionDescription: text("action_description"),
|
|
81
|
-
|
|
82
|
-
// Resource Information - What Was Affected
|
|
83
|
-
resource: varchar("resource", { length: 100 }).notNull(),
|
|
84
|
-
resourceId: text("resource_id").notNull(),
|
|
85
|
-
resourceType: varchar("resource_type", { length: 30 }).$type<
|
|
86
|
-
| "STORE"
|
|
87
|
-
| "PRODUCT"
|
|
88
|
-
| "ORDER"
|
|
89
|
-
| "USER"
|
|
90
|
-
| "BLOG"
|
|
91
|
-
| "CONTACT"
|
|
92
|
-
| "BUSINESS_DETAILS"
|
|
93
|
-
| "SOCIAL_PROFILE"
|
|
94
|
-
| "FILE"
|
|
95
|
-
| "MEDIA"
|
|
96
|
-
| "ANALYTICS"
|
|
97
|
-
| "CONFIGURATION"
|
|
98
|
-
| "INTEGRATION"
|
|
99
|
-
| "NOTIFICATION"
|
|
100
|
-
| "PAYMENT"
|
|
101
|
-
| "SHIPPING"
|
|
102
|
-
| "INVENTORY"
|
|
103
|
-
| "PROMOTION"
|
|
104
|
-
| "REVIEW"
|
|
105
|
-
| "CATEGORY"
|
|
106
|
-
| "ATTRIBUTE"
|
|
107
|
-
| "THEME"
|
|
108
|
-
| "PLUGIN"
|
|
109
|
-
| "WEBHOOK"
|
|
110
|
-
>(),
|
|
111
|
-
|
|
112
|
-
resourceName: varchar("resource_name", { length: 255 }),
|
|
113
|
-
parentResourceId: text("parent_resource_id"),
|
|
114
|
-
parentResourceType: varchar("parent_resource_type", { length: 30 }),
|
|
115
|
-
|
|
116
|
-
// Actor Information - Who Performed the Action
|
|
117
|
-
performedBy: text("performed_by").notNull(),
|
|
118
|
-
performedByType: varchar("performed_by_type", { length: 20 })
|
|
119
|
-
.notNull()
|
|
120
|
-
.$type<
|
|
121
|
-
| "USER"
|
|
122
|
-
| "ADMIN"
|
|
123
|
-
| "STORE_OWNER"
|
|
124
|
-
| "STORE_MANAGER"
|
|
125
|
-
| "STORE_EMPLOYEE"
|
|
126
|
-
| "CUSTOMER"
|
|
127
|
-
| "SYSTEM"
|
|
128
|
-
| "SERVICE"
|
|
129
|
-
| "AI"
|
|
130
|
-
| "AUTOMATION"
|
|
131
|
-
| "WEBHOOK"
|
|
132
|
-
| "CRON_JOB"
|
|
133
|
-
| "ANONYMOUS"
|
|
134
|
-
| "API_CLIENT"
|
|
135
|
-
| "INTEGRATION"
|
|
136
|
-
>(),
|
|
137
|
-
|
|
138
|
-
performedByName: varchar("performed_by_name", { length: 255 }),
|
|
139
|
-
performedByEmail: varchar("performed_by_email", { length: 320 }),
|
|
140
|
-
|
|
141
|
-
// User Role and Permissions Context
|
|
142
|
-
userRole: varchar("user_role", { length: 50 }).$type<
|
|
143
|
-
| "SUPER_ADMIN"
|
|
144
|
-
| "STORE_OWNER"
|
|
145
|
-
| "STORE_ADMIN"
|
|
146
|
-
| "STORE_MANAGER"
|
|
147
|
-
| "STORE_EMPLOYEE"
|
|
148
|
-
| "CONTENT_CREATOR"
|
|
149
|
-
| "CUSTOMER_SERVICE"
|
|
150
|
-
| "VIEWER"
|
|
151
|
-
| "CUSTOMER"
|
|
152
|
-
| "GUEST"
|
|
153
|
-
>(),
|
|
154
|
-
|
|
155
|
-
userPermissions: jsonb("user_permissions").$type<string[]>().default([]),
|
|
156
|
-
|
|
157
|
-
// Session and Request Context
|
|
158
|
-
sessionId: text("session_id"),
|
|
159
|
-
requestId: text("request_id"),
|
|
160
|
-
correlationId: text("correlation_id"),
|
|
161
|
-
traceId: text("trace_id"),
|
|
162
|
-
spanId: text("span_id"),
|
|
163
|
-
|
|
164
|
-
// Network and Client Information
|
|
165
|
-
ipAddress: varchar("ip_address", { length: 45 }), // IPv6 support
|
|
166
|
-
userAgent: text("user_agent"),
|
|
167
|
-
|
|
168
|
-
clientType: varchar("client_type", { length: 30 }).$type<
|
|
169
|
-
| "WEB_BROWSER"
|
|
170
|
-
| "MOBILE_APP"
|
|
171
|
-
| "DESKTOP_APP"
|
|
172
|
-
| "API_CLIENT"
|
|
173
|
-
| "ADMIN_PANEL"
|
|
174
|
-
| "POS_SYSTEM"
|
|
175
|
-
| "MOBILE_POS"
|
|
176
|
-
| "WEBHOOK"
|
|
177
|
-
| "CRON_JOB"
|
|
178
|
-
| "SYSTEM_SERVICE"
|
|
179
|
-
| "INTEGRATION"
|
|
180
|
-
| "BOT"
|
|
181
|
-
| "UNKNOWN"
|
|
182
|
-
>(),
|
|
183
|
-
|
|
184
|
-
clientId: text("client_id"),
|
|
185
|
-
clientVersion: varchar("client_version", { length: 50 }),
|
|
186
|
-
clientPlatform: varchar("client_platform", { length: 50 }),
|
|
187
|
-
|
|
188
|
-
// Device Information
|
|
189
|
-
deviceInfo: jsonb("device_info").$type<{
|
|
190
|
-
type?: "desktop" | "mobile" | "tablet" | "tv" | "watch" | "embedded";
|
|
191
|
-
os?: string;
|
|
192
|
-
osVersion?: string;
|
|
193
|
-
browser?: string;
|
|
194
|
-
browserVersion?: string;
|
|
195
|
-
vendor?: string;
|
|
196
|
-
model?: string;
|
|
197
|
-
screenResolution?: string;
|
|
198
|
-
language?: string;
|
|
199
|
-
timezone?: string;
|
|
200
|
-
}>(),
|
|
201
|
-
|
|
202
|
-
// Geographic Information
|
|
203
|
-
location: jsonb("location").$type<{
|
|
204
|
-
country?: string;
|
|
205
|
-
countryCode?: string;
|
|
206
|
-
region?: string;
|
|
207
|
-
regionCode?: string;
|
|
208
|
-
city?: string;
|
|
209
|
-
postalCode?: string;
|
|
210
|
-
coordinates?: { lat: number; lng: number };
|
|
211
|
-
timezone?: string;
|
|
212
|
-
isp?: string;
|
|
213
|
-
organization?: string;
|
|
214
|
-
}>(),
|
|
215
|
-
|
|
216
|
-
// HTTP Context
|
|
217
|
-
httpMethod: varchar("http_method", { length: 10 }),
|
|
218
|
-
httpPath: text("http_path"),
|
|
219
|
-
httpQuery: text("http_query"),
|
|
220
|
-
httpHeaders: jsonb("http_headers").$type<Record<string, string>>(),
|
|
221
|
-
httpStatusCode: integer("http_status_code"),
|
|
222
|
-
httpResponseSize: integer("http_response_size"),
|
|
223
|
-
|
|
224
|
-
// Data Changes and Content
|
|
225
|
-
changes: jsonb("changes").$type<{
|
|
226
|
-
before?: Record<string, unknown>;
|
|
227
|
-
after?: Record<string, unknown>;
|
|
228
|
-
fields?: string[];
|
|
229
|
-
summary?: string;
|
|
230
|
-
changeCount?: number;
|
|
231
|
-
significantChanges?: string[];
|
|
232
|
-
}>(),
|
|
233
|
-
|
|
234
|
-
// Request/Response Data (Sanitized)
|
|
235
|
-
requestData: jsonb("request_data").$type<Record<string, unknown>>(),
|
|
236
|
-
responseData: jsonb("response_data").$type<Record<string, unknown>>(),
|
|
237
|
-
|
|
238
|
-
// Business Context and Metadata
|
|
239
|
-
businessContext: jsonb("business_context").$type<{
|
|
240
|
-
department?: string;
|
|
241
|
-
project?: string;
|
|
242
|
-
feature?: string;
|
|
243
|
-
campaign?: string;
|
|
244
|
-
businessUnit?: string;
|
|
245
|
-
costCenter?: string;
|
|
246
|
-
workflowId?: string;
|
|
247
|
-
workflowStep?: string;
|
|
248
|
-
processName?: string;
|
|
249
|
-
businessImpact?: string;
|
|
250
|
-
revenueImpact?: number;
|
|
251
|
-
customerImpact?: string;
|
|
252
|
-
}>(),
|
|
253
|
-
|
|
254
|
-
// Enhanced Metadata
|
|
255
|
-
metadata: jsonb("metadata").$type<{
|
|
256
|
-
// Technical Metadata
|
|
257
|
-
version?: string;
|
|
258
|
-
environment?: "DEVELOPMENT" | "STAGING" | "PRODUCTION" | "TESTING";
|
|
259
|
-
buildVersion?: string;
|
|
260
|
-
deploymentId?: string;
|
|
261
|
-
|
|
262
|
-
// Feature Flags and Experiments
|
|
263
|
-
featureFlags?: Record<string, boolean>;
|
|
264
|
-
experiments?: Record<string, string>;
|
|
265
|
-
abTestVariant?: string;
|
|
266
|
-
|
|
267
|
-
// Business Tags and Categories
|
|
268
|
-
tags?: string[];
|
|
269
|
-
categories?: string[];
|
|
270
|
-
priority?: "LOW" | "MEDIUM" | "HIGH" | "CRITICAL";
|
|
271
|
-
severity?: "INFO" | "WARNING" | "ERROR" | "CRITICAL";
|
|
272
|
-
|
|
273
|
-
// Content and Media
|
|
274
|
-
contentType?: string;
|
|
275
|
-
fileSize?: number;
|
|
276
|
-
dimensions?: { width: number; height: number };
|
|
277
|
-
duration?: number;
|
|
278
|
-
format?: string;
|
|
279
|
-
|
|
280
|
-
// E-commerce Specific
|
|
281
|
-
orderValue?: number;
|
|
282
|
-
productCount?: number;
|
|
283
|
-
customerSegment?: string;
|
|
284
|
-
paymentMethod?: string;
|
|
285
|
-
shippingMethod?: string;
|
|
286
|
-
|
|
287
|
-
// Marketing and Analytics
|
|
288
|
-
source?: string;
|
|
289
|
-
medium?: string;
|
|
290
|
-
campaign?: string;
|
|
291
|
-
referrer?: string;
|
|
292
|
-
utmParameters?: Record<string, string>;
|
|
293
|
-
|
|
294
|
-
// Custom Fields
|
|
295
|
-
customFields?: Record<string, unknown>;
|
|
296
|
-
}>(),
|
|
297
|
-
|
|
298
|
-
// Performance Metrics
|
|
299
|
-
duration: integer("duration"), // milliseconds
|
|
300
|
-
responseTime: integer("response_time"), // milliseconds
|
|
301
|
-
processingTime: integer("processing_time"), // milliseconds
|
|
302
|
-
databaseTime: integer("database_time"), // milliseconds
|
|
303
|
-
cacheHitRate: real("cache_hit_rate"), // percentage
|
|
304
|
-
memoryUsage: integer("memory_usage"), // bytes
|
|
305
|
-
cpuUsage: real("cpu_usage"), // percentage
|
|
306
|
-
|
|
307
|
-
// Operation Success and Error Information
|
|
308
|
-
success: boolean("success").notNull().default(true),
|
|
309
|
-
errorCode: varchar("error_code", { length: 100 }),
|
|
310
|
-
errorMessage: text("error_message"),
|
|
311
|
-
errorType: varchar("error_type", { length: 50 }).$type<
|
|
312
|
-
| "VALIDATION_ERROR"
|
|
313
|
-
| "AUTHENTICATION_ERROR"
|
|
314
|
-
| "AUTHORIZATION_ERROR"
|
|
315
|
-
| "NOT_FOUND_ERROR"
|
|
316
|
-
| "CONFLICT_ERROR"
|
|
317
|
-
| "RATE_LIMIT_ERROR"
|
|
318
|
-
| "TIMEOUT_ERROR"
|
|
319
|
-
| "NETWORK_ERROR"
|
|
320
|
-
| "DATABASE_ERROR"
|
|
321
|
-
| "EXTERNAL_SERVICE_ERROR"
|
|
322
|
-
| "BUSINESS_LOGIC_ERROR"
|
|
323
|
-
| "SYSTEM_ERROR"
|
|
324
|
-
| "UNKNOWN_ERROR"
|
|
325
|
-
>(),
|
|
326
|
-
errorDetails: jsonb("error_details").$type<Record<string, unknown>>(),
|
|
327
|
-
stackTrace: text("stack_trace"),
|
|
328
|
-
|
|
329
|
-
// Recovery and Retry Information
|
|
330
|
-
retryCount: integer("retry_count").default(0),
|
|
331
|
-
recoveryAction: varchar("recovery_action", { length: 100 }),
|
|
332
|
-
fallbackUsed: boolean("fallback_used").default(false),
|
|
333
|
-
|
|
334
|
-
// Security and Compliance
|
|
335
|
-
sensitiveData: boolean("sensitive_data").notNull().default(false),
|
|
336
|
-
piiInvolved: boolean("pii_involved").notNull().default(false),
|
|
337
|
-
complianceRelevant: boolean("compliance_relevant").notNull().default(false),
|
|
338
|
-
|
|
339
|
-
dataClassification: varchar("data_classification", { length: 20 })
|
|
340
|
-
.$type<"PUBLIC" | "INTERNAL" | "CONFIDENTIAL" | "RESTRICTED">()
|
|
341
|
-
.default("INTERNAL"),
|
|
342
|
-
|
|
343
|
-
// Risk Assessment
|
|
344
|
-
riskLevel: varchar("risk_level", { length: 20 })
|
|
345
|
-
.$type<"NONE" | "LOW" | "MEDIUM" | "HIGH" | "CRITICAL">()
|
|
346
|
-
.default("LOW"),
|
|
347
|
-
|
|
348
|
-
securityImpact: varchar("security_impact", { length: 20 })
|
|
349
|
-
.$type<"NONE" | "LOW" | "MEDIUM" | "HIGH" | "CRITICAL">()
|
|
350
|
-
.default("NONE"),
|
|
351
|
-
|
|
352
|
-
privacyImpact: varchar("privacy_impact", { length: 20 })
|
|
353
|
-
.$type<"NONE" | "LOW" | "MEDIUM" | "HIGH" | "CRITICAL">()
|
|
354
|
-
.default("NONE"),
|
|
355
|
-
|
|
356
|
-
// Threat Detection
|
|
357
|
-
threatIndicators: jsonb("threat_indicators")
|
|
358
|
-
.$type<
|
|
359
|
-
Array<{
|
|
360
|
-
type: string;
|
|
361
|
-
severity: "LOW" | "MEDIUM" | "HIGH" | "CRITICAL";
|
|
362
|
-
description: string;
|
|
363
|
-
confidence: number;
|
|
364
|
-
}>
|
|
365
|
-
>()
|
|
366
|
-
.default([]),
|
|
367
|
-
|
|
368
|
-
anomalyScore: real("anomaly_score"), // 0-1 scale
|
|
369
|
-
fraudScore: real("fraud_score"), // 0-1 scale
|
|
370
|
-
|
|
371
|
-
// Compliance Framework Tracking
|
|
372
|
-
complianceFrameworks: jsonb("compliance_frameworks")
|
|
373
|
-
.$type<
|
|
374
|
-
Array<{
|
|
375
|
-
framework:
|
|
376
|
-
| "GDPR"
|
|
377
|
-
| "CCPA"
|
|
378
|
-
| "COPPA"
|
|
379
|
-
| "PCI_DSS"
|
|
380
|
-
| "SOX"
|
|
381
|
-
| "HIPAA"
|
|
382
|
-
| "ISO27001";
|
|
383
|
-
requirement: string;
|
|
384
|
-
status: "COMPLIANT" | "NON_COMPLIANT" | "PARTIAL" | "NOT_APPLICABLE";
|
|
385
|
-
}>
|
|
386
|
-
>()
|
|
387
|
-
.default([]),
|
|
388
|
-
|
|
389
|
-
// Data Lifecycle
|
|
390
|
-
retentionPeriod: integer("retention_period"), // days
|
|
391
|
-
archiveDate: timestamp("archive_date", { withTimezone: true }),
|
|
392
|
-
purgeDate: timestamp("purge_date", { withTimezone: true }),
|
|
393
|
-
|
|
394
|
-
// Workflow and Process Tracking
|
|
395
|
-
workflowId: text("workflow_id"),
|
|
396
|
-
workflowStep: varchar("workflow_step", { length: 100 }),
|
|
397
|
-
workflowStatus: varchar("workflow_status", { length: 30 }).$type<
|
|
398
|
-
| "INITIATED"
|
|
399
|
-
| "IN_PROGRESS"
|
|
400
|
-
| "COMPLETED"
|
|
401
|
-
| "FAILED"
|
|
402
|
-
| "CANCELLED"
|
|
403
|
-
| "SUSPENDED"
|
|
404
|
-
>(),
|
|
405
|
-
parentEventId: text("parent_event_id"),
|
|
406
|
-
childEventIds: jsonb("child_event_ids").$type<string[]>().default([]),
|
|
407
|
-
|
|
408
|
-
// Batch and Bulk Operations
|
|
409
|
-
batchId: text("batch_id"),
|
|
410
|
-
batchSize: integer("batch_size"),
|
|
411
|
-
batchIndex: integer("batch_index"),
|
|
412
|
-
isBulkOperation: boolean("is_bulk_operation").default(false),
|
|
413
|
-
|
|
414
|
-
// Integration and External Systems
|
|
415
|
-
externalSystemId: text("external_system_id"),
|
|
416
|
-
externalSystemName: varchar("external_system_name", { length: 100 }),
|
|
417
|
-
externalEventId: text("external_event_id"),
|
|
418
|
-
syncStatus: varchar("sync_status", { length: 20 }).$type<
|
|
419
|
-
"PENDING" | "SYNCED" | "FAILED" | "PARTIAL" | "CONFLICT"
|
|
420
|
-
>(),
|
|
421
|
-
|
|
422
|
-
// Notification and Alerting
|
|
423
|
-
alertLevel: varchar("alert_level", { length: 20 })
|
|
424
|
-
.$type<"NONE" | "INFO" | "WARNING" | "ERROR" | "CRITICAL">()
|
|
425
|
-
.default("NONE"),
|
|
426
|
-
|
|
427
|
-
notificationsSent: jsonb("notifications_sent")
|
|
428
|
-
.$type<
|
|
429
|
-
Array<{
|
|
430
|
-
type: string;
|
|
431
|
-
recipient: string;
|
|
432
|
-
channel: "EMAIL" | "SMS" | "PUSH" | "WEBHOOK" | "SLACK";
|
|
433
|
-
status: "SENT" | "FAILED" | "PENDING";
|
|
434
|
-
sentAt: string;
|
|
435
|
-
}>
|
|
436
|
-
>()
|
|
437
|
-
.default([]),
|
|
438
|
-
|
|
439
|
-
// Data Integrity and Verification
|
|
440
|
-
checksum: varchar("checksum", { length: 64 }), // SHA-256
|
|
441
|
-
signature: text("signature"), // Digital signature for critical events
|
|
442
|
-
verified: boolean("verified").default(false),
|
|
443
|
-
|
|
444
|
-
// Immutable Timestamp - Core Audit Requirement
|
|
445
|
-
timestamp: timestamp("timestamp", { withTimezone: true })
|
|
446
|
-
.defaultNow()
|
|
447
|
-
.notNull(),
|
|
448
|
-
|
|
449
|
-
// Processing Timestamps
|
|
450
|
-
processedAt: timestamp("processed_at", { withTimezone: true }),
|
|
451
|
-
indexedAt: timestamp("indexed_at", { withTimezone: true }),
|
|
452
|
-
|
|
453
|
-
// Export and Reporting
|
|
454
|
-
exportedAt: timestamp("exported_at", { withTimezone: true }),
|
|
455
|
-
reportingPeriod: varchar("reporting_period", { length: 20 }),
|
|
456
|
-
|
|
457
|
-
// System Information
|
|
458
|
-
serviceVersion: varchar("service_version", { length: 50 }),
|
|
459
|
-
nodeId: varchar("node_id", { length: 100 }),
|
|
460
|
-
instanceId: varchar("instance_id", { length: 100 }),
|
|
461
|
-
},
|
|
462
|
-
(table) => ({
|
|
463
|
-
// === PRIMARY PERFORMANCE INDEXES ===
|
|
464
|
-
|
|
465
|
-
// Core timestamp index - most important for audit queries
|
|
466
|
-
timestampIndex: index("idx_store_audit_timestamp").on(table.timestamp),
|
|
467
|
-
|
|
468
|
-
// Store-centric indexes for business queries
|
|
469
|
-
storeIdIndex: index("idx_store_audit_store_id").on(table.storeId),
|
|
470
|
-
storeTimestampIndex: index("idx_store_audit_store_timestamp").on(
|
|
471
|
-
table.storeId,
|
|
472
|
-
table.timestamp,
|
|
473
|
-
),
|
|
474
|
-
|
|
475
|
-
// Event classification indexes
|
|
476
|
-
eventTypeIndex: index("idx_store_audit_event_type").on(
|
|
477
|
-
table.eventType,
|
|
478
|
-
table.eventCategory,
|
|
479
|
-
),
|
|
480
|
-
actionIndex: index("idx_store_audit_action").on(table.action),
|
|
481
|
-
|
|
482
|
-
// Resource tracking indexes
|
|
483
|
-
resourceIndex: index("idx_store_audit_resource").on(
|
|
484
|
-
table.resource,
|
|
485
|
-
table.resourceId,
|
|
486
|
-
),
|
|
487
|
-
resourceTypeIndex: index("idx_store_audit_resource_type").on(
|
|
488
|
-
table.resourceType,
|
|
489
|
-
table.timestamp,
|
|
490
|
-
),
|
|
491
|
-
|
|
492
|
-
// Actor and user tracking
|
|
493
|
-
performedByIndex: index("idx_store_audit_performed_by").on(
|
|
494
|
-
table.performedBy,
|
|
495
|
-
table.performedByType,
|
|
496
|
-
),
|
|
497
|
-
userRoleIndex: index("idx_store_audit_user_role").on(
|
|
498
|
-
table.userRole,
|
|
499
|
-
table.timestamp,
|
|
500
|
-
),
|
|
501
|
-
|
|
502
|
-
// === SECURITY AND COMPLIANCE INDEXES ===
|
|
503
|
-
|
|
504
|
-
// Security monitoring
|
|
505
|
-
securityIndex: index("idx_store_audit_security").on(
|
|
506
|
-
table.riskLevel,
|
|
507
|
-
table.securityImpact,
|
|
508
|
-
table.timestamp,
|
|
509
|
-
),
|
|
510
|
-
threatIndex: index("idx_store_audit_threats").on(
|
|
511
|
-
table.anomalyScore,
|
|
512
|
-
table.fraudScore,
|
|
513
|
-
table.timestamp,
|
|
514
|
-
),
|
|
515
|
-
|
|
516
|
-
// Compliance tracking
|
|
517
|
-
complianceIndex: index("idx_store_audit_compliance").on(
|
|
518
|
-
table.complianceRelevant,
|
|
519
|
-
table.piiInvolved,
|
|
520
|
-
table.sensitiveData,
|
|
521
|
-
),
|
|
522
|
-
dataClassificationIndex: index("idx_store_audit_data_classification").on(
|
|
523
|
-
table.dataClassification,
|
|
524
|
-
table.timestamp,
|
|
525
|
-
),
|
|
526
|
-
|
|
527
|
-
// === OPERATIONAL INDEXES ===
|
|
528
|
-
|
|
529
|
-
// Error and success tracking
|
|
530
|
-
errorIndex: index("idx_store_audit_errors").on(
|
|
531
|
-
table.success,
|
|
532
|
-
table.errorCode,
|
|
533
|
-
table.timestamp,
|
|
534
|
-
),
|
|
535
|
-
errorTypeIndex: index("idx_store_audit_error_type").on(
|
|
536
|
-
table.errorType,
|
|
537
|
-
table.timestamp,
|
|
538
|
-
),
|
|
539
|
-
|
|
540
|
-
// Performance monitoring
|
|
541
|
-
performanceIndex: index("idx_store_audit_performance").on(
|
|
542
|
-
table.duration,
|
|
543
|
-
table.responseTime,
|
|
544
|
-
table.timestamp,
|
|
545
|
-
),
|
|
546
|
-
|
|
547
|
-
// Session and correlation tracking
|
|
548
|
-
sessionIndex: index("idx_store_audit_session").on(
|
|
549
|
-
table.sessionId,
|
|
550
|
-
table.timestamp,
|
|
551
|
-
),
|
|
552
|
-
correlationIndex: index("idx_store_audit_correlation").on(
|
|
553
|
-
table.correlationId,
|
|
554
|
-
),
|
|
555
|
-
requestIndex: index("idx_store_audit_request").on(table.requestId),
|
|
556
|
-
|
|
557
|
-
// === BUSINESS INTELLIGENCE INDEXES ===
|
|
558
|
-
|
|
559
|
-
// Client and device analytics
|
|
560
|
-
clientTypeIndex: index("idx_store_audit_client_type").on(
|
|
561
|
-
table.clientType,
|
|
562
|
-
table.timestamp,
|
|
563
|
-
),
|
|
564
|
-
userAgentIndex: index("idx_store_audit_user_agent").on(table.userAgent),
|
|
565
|
-
|
|
566
|
-
// Geographic analytics
|
|
567
|
-
locationIndex: index("idx_store_audit_location").on(
|
|
568
|
-
table.ipAddress,
|
|
569
|
-
table.timestamp,
|
|
570
|
-
),
|
|
571
|
-
|
|
572
|
-
// HTTP tracking
|
|
573
|
-
httpMethodIndex: index("idx_store_audit_http_method").on(
|
|
574
|
-
table.httpMethod,
|
|
575
|
-
table.httpStatusCode,
|
|
576
|
-
),
|
|
577
|
-
|
|
578
|
-
// === WORKFLOW AND PROCESS INDEXES ===
|
|
579
|
-
|
|
580
|
-
// Workflow tracking
|
|
581
|
-
workflowIndex: index("idx_store_audit_workflow").on(
|
|
582
|
-
table.workflowId,
|
|
583
|
-
table.workflowStep,
|
|
584
|
-
table.timestamp,
|
|
585
|
-
),
|
|
586
|
-
parentEventIndex: index("idx_store_audit_parent_event").on(
|
|
587
|
-
table.parentEventId,
|
|
588
|
-
),
|
|
589
|
-
|
|
590
|
-
// Batch operations
|
|
591
|
-
batchIndex: index("idx_store_audit_batch").on(
|
|
592
|
-
table.batchId,
|
|
593
|
-
table.batchIndex,
|
|
594
|
-
),
|
|
595
|
-
bulkOperationIndex: index("idx_store_audit_bulk").on(
|
|
596
|
-
table.isBulkOperation,
|
|
597
|
-
table.timestamp,
|
|
598
|
-
),
|
|
599
|
-
|
|
600
|
-
// === INTEGRATION INDEXES ===
|
|
601
|
-
|
|
602
|
-
// External system tracking
|
|
603
|
-
externalSystemIndex: index("idx_store_audit_external_system").on(
|
|
604
|
-
table.externalSystemId,
|
|
605
|
-
table.syncStatus,
|
|
606
|
-
),
|
|
607
|
-
|
|
608
|
-
// Notification tracking
|
|
609
|
-
alertLevelIndex: index("idx_store_audit_alert_level").on(
|
|
610
|
-
table.alertLevel,
|
|
611
|
-
table.timestamp,
|
|
612
|
-
),
|
|
613
|
-
|
|
614
|
-
// === COMPOSITE BUSINESS INDEXES ===
|
|
615
|
-
|
|
616
|
-
// Store activity analysis
|
|
617
|
-
storeActivityIndex: index("idx_store_audit_store_activity").on(
|
|
618
|
-
table.storeId,
|
|
619
|
-
table.eventType,
|
|
620
|
-
table.success,
|
|
621
|
-
table.timestamp,
|
|
622
|
-
),
|
|
623
|
-
|
|
624
|
-
// User activity patterns
|
|
625
|
-
userActivityIndex: index("idx_store_audit_user_activity").on(
|
|
626
|
-
table.performedBy,
|
|
627
|
-
table.storeId,
|
|
628
|
-
table.timestamp,
|
|
629
|
-
),
|
|
630
|
-
|
|
631
|
-
// Security events by store
|
|
632
|
-
storeSecurityIndex: index("idx_store_audit_store_security").on(
|
|
633
|
-
table.storeId,
|
|
634
|
-
table.riskLevel,
|
|
635
|
-
table.securityImpact,
|
|
636
|
-
table.timestamp,
|
|
637
|
-
),
|
|
638
|
-
|
|
639
|
-
// Resource changes by store
|
|
640
|
-
storeResourceIndex: index("idx_store_audit_store_resource").on(
|
|
641
|
-
table.storeId,
|
|
642
|
-
table.resourceType,
|
|
643
|
-
table.eventType,
|
|
644
|
-
table.timestamp,
|
|
645
|
-
),
|
|
646
|
-
|
|
647
|
-
// Error patterns by store
|
|
648
|
-
storeErrorIndex: index("idx_store_audit_store_errors").on(
|
|
649
|
-
table.storeId,
|
|
650
|
-
table.success,
|
|
651
|
-
table.errorType,
|
|
652
|
-
table.timestamp,
|
|
653
|
-
),
|
|
654
|
-
|
|
655
|
-
// === DATA LIFECYCLE INDEXES ===
|
|
656
|
-
|
|
657
|
-
// Retention and archival
|
|
658
|
-
retentionIndex: index("idx_store_audit_retention").on(
|
|
659
|
-
table.retentionPeriod,
|
|
660
|
-
table.timestamp,
|
|
661
|
-
),
|
|
662
|
-
archiveIndex: index("idx_store_audit_archive").on(table.archiveDate),
|
|
663
|
-
purgeIndex: index("idx_store_audit_purge").on(table.purgeDate),
|
|
664
|
-
|
|
665
|
-
// Data integrity
|
|
666
|
-
checksumIndex: index("idx_store_audit_checksum").on(table.checksum),
|
|
667
|
-
verificationIndex: index("idx_store_audit_verified").on(
|
|
668
|
-
table.verified,
|
|
669
|
-
table.timestamp,
|
|
670
|
-
),
|
|
671
|
-
|
|
672
|
-
// === REPORTING INDEXES ===
|
|
673
|
-
|
|
674
|
-
// Note: Time-based reporting indexes with date_trunc functions
|
|
675
|
-
// can be added manually after table creation if needed for advanced analytics
|
|
676
|
-
}),
|
|
677
|
-
);
|
|
678
|
-
|
|
679
|
-
// =====================================================
|
|
680
|
-
// STORE AUDIT AGGREGATIONS - PERFORMANCE OPTIMIZATION
|
|
681
|
-
// =====================================================
|
|
682
|
-
|
|
683
|
-
/**
|
|
684
|
-
* Pre-computed Store Audit Aggregations
|
|
685
|
-
* For high-performance analytics and reporting
|
|
686
|
-
*/
|
|
687
|
-
export const storeAuditAggregations = pgTable(
|
|
688
|
-
"store_audit_aggregations",
|
|
689
|
-
{
|
|
690
|
-
id: text("id")
|
|
691
|
-
.primaryKey()
|
|
692
|
-
.$defaultFn(() => createId()),
|
|
693
|
-
|
|
694
|
-
// Aggregation Dimensions
|
|
695
|
-
storeId: text("store_id").notNull(),
|
|
696
|
-
aggregationType: varchar("aggregation_type", { length: 20 })
|
|
697
|
-
.notNull()
|
|
698
|
-
.$type<
|
|
699
|
-
"HOURLY" | "DAILY" | "WEEKLY" | "MONTHLY" | "QUARTERLY" | "YEARLY"
|
|
700
|
-
>(),
|
|
701
|
-
|
|
702
|
-
aggregationDate: timestamp("aggregation_date", {
|
|
703
|
-
withTimezone: true,
|
|
704
|
-
}).notNull(),
|
|
705
|
-
periodStart: timestamp("period_start", { withTimezone: true }).notNull(),
|
|
706
|
-
periodEnd: timestamp("period_end", { withTimezone: true }).notNull(),
|
|
707
|
-
|
|
708
|
-
// Dimensional Breakdowns
|
|
709
|
-
eventType: varchar("event_type", { length: 30 }),
|
|
710
|
-
eventCategory: varchar("event_category", { length: 30 }),
|
|
711
|
-
resourceType: varchar("resource_type", { length: 30 }),
|
|
712
|
-
performedByType: varchar("performed_by_type", { length: 20 }),
|
|
713
|
-
clientType: varchar("client_type", { length: 30 }),
|
|
714
|
-
userRole: varchar("user_role", { length: 50 }),
|
|
715
|
-
|
|
716
|
-
// Core Activity Metrics
|
|
717
|
-
totalEvents: integer("total_events").notNull().default(0),
|
|
718
|
-
successfulEvents: integer("successful_events").notNull().default(0),
|
|
719
|
-
failedEvents: integer("failed_events").notNull().default(0),
|
|
720
|
-
uniqueUsers: integer("unique_users").notNull().default(0),
|
|
721
|
-
uniqueResources: integer("unique_resources").notNull().default(0),
|
|
722
|
-
uniqueIPs: integer("unique_ips").notNull().default(0),
|
|
723
|
-
uniqueSessions: integer("unique_sessions").notNull().default(0),
|
|
724
|
-
|
|
725
|
-
// Performance Metrics
|
|
726
|
-
avgDuration: real("avg_duration"),
|
|
727
|
-
maxDuration: integer("max_duration"),
|
|
728
|
-
minDuration: integer("min_duration"),
|
|
729
|
-
p95Duration: integer("p95_duration"),
|
|
730
|
-
p99Duration: integer("p99_duration"),
|
|
731
|
-
|
|
732
|
-
avgResponseTime: real("avg_response_time"),
|
|
733
|
-
maxResponseTime: integer("max_response_time"),
|
|
734
|
-
p95ResponseTime: integer("p95_response_time"),
|
|
735
|
-
|
|
736
|
-
totalDataTransferred: integer("total_data_transferred"),
|
|
737
|
-
avgMemoryUsage: real("avg_memory_usage"),
|
|
738
|
-
maxMemoryUsage: integer("max_memory_usage"),
|
|
739
|
-
avgCpuUsage: real("avg_cpu_usage"),
|
|
740
|
-
|
|
741
|
-
// Security and Risk Metrics
|
|
742
|
-
securityEvents: integer("security_events").notNull().default(0),
|
|
743
|
-
highRiskEvents: integer("high_risk_events").notNull().default(0),
|
|
744
|
-
criticalEvents: integer("critical_events").notNull().default(0),
|
|
745
|
-
anomalousEvents: integer("anomalous_events").notNull().default(0),
|
|
746
|
-
fraudulentEvents: integer("fraudulent_events").notNull().default(0),
|
|
747
|
-
|
|
748
|
-
avgAnomalyScore: real("avg_anomaly_score"),
|
|
749
|
-
maxAnomalyScore: real("max_anomaly_score"),
|
|
750
|
-
avgFraudScore: real("avg_fraud_score"),
|
|
751
|
-
maxFraudScore: real("max_fraud_score"),
|
|
752
|
-
|
|
753
|
-
// Compliance Metrics
|
|
754
|
-
complianceEvents: integer("compliance_events").notNull().default(0),
|
|
755
|
-
piiEvents: integer("pii_events").notNull().default(0),
|
|
756
|
-
sensitiveDataEvents: integer("sensitive_data_events").notNull().default(0),
|
|
757
|
-
complianceViolations: integer("compliance_violations").notNull().default(0),
|
|
758
|
-
|
|
759
|
-
// Business Metrics
|
|
760
|
-
businessCriticalEvents: integer("business_critical_events")
|
|
761
|
-
.notNull()
|
|
762
|
-
.default(0),
|
|
763
|
-
revenueImpactEvents: integer("revenue_impact_events").notNull().default(0),
|
|
764
|
-
customerImpactEvents: integer("customer_impact_events")
|
|
765
|
-
.notNull()
|
|
766
|
-
.default(0),
|
|
767
|
-
|
|
768
|
-
// Error Analysis
|
|
769
|
-
errorBreakdown: jsonb("error_breakdown")
|
|
770
|
-
.$type<Record<string, number>>()
|
|
771
|
-
.default({}),
|
|
772
|
-
|
|
773
|
-
topErrors: jsonb("top_errors")
|
|
774
|
-
.$type<
|
|
775
|
-
Array<{
|
|
776
|
-
errorCode: string;
|
|
777
|
-
errorType: string;
|
|
778
|
-
count: number;
|
|
779
|
-
percentage: number;
|
|
780
|
-
firstOccurrence: string;
|
|
781
|
-
lastOccurrence: string;
|
|
782
|
-
}>
|
|
783
|
-
>()
|
|
784
|
-
.default([]),
|
|
785
|
-
|
|
786
|
-
// User Behavior Analytics
|
|
787
|
-
topUsers: jsonb("top_users")
|
|
788
|
-
.$type<
|
|
789
|
-
Array<{
|
|
790
|
-
userId: string;
|
|
791
|
-
userName?: string;
|
|
792
|
-
eventCount: number;
|
|
793
|
-
lastActivity: string;
|
|
794
|
-
riskScore: number;
|
|
795
|
-
}>
|
|
796
|
-
>()
|
|
797
|
-
.default([]),
|
|
798
|
-
|
|
799
|
-
// Resource Activity
|
|
800
|
-
topResources: jsonb("top_resources")
|
|
801
|
-
.$type<
|
|
802
|
-
Array<{
|
|
803
|
-
resourceType: string;
|
|
804
|
-
resourceId: string;
|
|
805
|
-
eventCount: number;
|
|
806
|
-
operations: Record<string, number>;
|
|
807
|
-
}>
|
|
808
|
-
>()
|
|
809
|
-
.default([]),
|
|
810
|
-
|
|
811
|
-
// Geographic Distribution
|
|
812
|
-
topCountries: jsonb("top_countries")
|
|
813
|
-
.$type<
|
|
814
|
-
Array<{
|
|
815
|
-
country: string;
|
|
816
|
-
countryCode: string;
|
|
817
|
-
count: number;
|
|
818
|
-
percentage: number;
|
|
819
|
-
}>
|
|
820
|
-
>()
|
|
821
|
-
.default([]),
|
|
822
|
-
|
|
823
|
-
topCities: jsonb("top_cities")
|
|
824
|
-
.$type<
|
|
825
|
-
Array<{
|
|
826
|
-
city: string;
|
|
827
|
-
country: string;
|
|
828
|
-
count: number;
|
|
829
|
-
percentage: number;
|
|
830
|
-
}>
|
|
831
|
-
>()
|
|
832
|
-
.default([]),
|
|
833
|
-
|
|
834
|
-
// Technology Analytics
|
|
835
|
-
deviceBreakdown: jsonb("device_breakdown")
|
|
836
|
-
.$type<{
|
|
837
|
-
desktop?: number;
|
|
838
|
-
mobile?: number;
|
|
839
|
-
tablet?: number;
|
|
840
|
-
other?: number;
|
|
841
|
-
}>()
|
|
842
|
-
.default({}),
|
|
843
|
-
|
|
844
|
-
browserBreakdown: jsonb("browser_breakdown")
|
|
845
|
-
.$type<Record<string, number>>()
|
|
846
|
-
.default({}),
|
|
847
|
-
|
|
848
|
-
osBreakdown: jsonb("os_breakdown")
|
|
849
|
-
.$type<Record<string, number>>()
|
|
850
|
-
.default({}),
|
|
851
|
-
|
|
852
|
-
// Traffic Patterns
|
|
853
|
-
hourlyDistribution: jsonb("hourly_distribution")
|
|
854
|
-
.$type<Record<string, number>>()
|
|
855
|
-
.default({}),
|
|
856
|
-
|
|
857
|
-
peakHour: integer("peak_hour"),
|
|
858
|
-
peakHourEvents: integer("peak_hour_events"),
|
|
859
|
-
|
|
860
|
-
// Growth and Trends
|
|
861
|
-
periodOverPeriodGrowth: real("period_over_period_growth"),
|
|
862
|
-
trendDirection: varchar("trend_direction", { length: 10 }).$type<
|
|
863
|
-
"UP" | "DOWN" | "STABLE" | "VOLATILE"
|
|
864
|
-
>(),
|
|
865
|
-
|
|
866
|
-
createdAt: timestamp("created_at", { withTimezone: true })
|
|
867
|
-
.defaultNow()
|
|
868
|
-
.notNull(),
|
|
869
|
-
updatedAt: timestamp("updated_at", { withTimezone: true })
|
|
870
|
-
.defaultNow()
|
|
871
|
-
.notNull(),
|
|
872
|
-
},
|
|
873
|
-
(table) => ({
|
|
874
|
-
// Primary aggregation indexes
|
|
875
|
-
storeAggregationIndex: index("idx_store_audit_agg_store").on(
|
|
876
|
-
table.storeId,
|
|
877
|
-
table.aggregationType,
|
|
878
|
-
table.aggregationDate,
|
|
879
|
-
),
|
|
880
|
-
|
|
881
|
-
aggregationDateIndex: index("idx_store_audit_agg_date").on(
|
|
882
|
-
table.aggregationDate,
|
|
883
|
-
table.aggregationType,
|
|
884
|
-
),
|
|
885
|
-
|
|
886
|
-
// Dimensional analysis indexes
|
|
887
|
-
eventTypeAggIndex: index("idx_store_audit_agg_event_type").on(
|
|
888
|
-
table.eventType,
|
|
889
|
-
table.aggregationDate,
|
|
890
|
-
),
|
|
891
|
-
|
|
892
|
-
// Performance monitoring
|
|
893
|
-
performanceAggIndex: index("idx_store_audit_agg_performance").on(
|
|
894
|
-
table.avgDuration,
|
|
895
|
-
table.p95Duration,
|
|
896
|
-
table.aggregationDate,
|
|
897
|
-
),
|
|
898
|
-
|
|
899
|
-
// Security analytics
|
|
900
|
-
securityAggIndex: index("idx_store_audit_agg_security").on(
|
|
901
|
-
table.securityEvents,
|
|
902
|
-
table.highRiskEvents,
|
|
903
|
-
table.aggregationDate,
|
|
904
|
-
),
|
|
905
|
-
}),
|
|
906
|
-
);
|
|
907
|
-
|
|
908
|
-
// =====================================================
|
|
909
|
-
// STORE AUDIT TRAILS - BUSINESS PROCESS TRACKING
|
|
910
|
-
// =====================================================
|
|
911
|
-
|
|
912
|
-
/**
|
|
913
|
-
* Store-Specific Audit Trails
|
|
914
|
-
* For tracking complex business processes and workflows
|
|
915
|
-
*/
|
|
916
|
-
export const storeAuditTrails = pgTable(
|
|
917
|
-
"store_audit_trails",
|
|
918
|
-
{
|
|
919
|
-
id: text("id")
|
|
920
|
-
.primaryKey()
|
|
921
|
-
.$defaultFn(() => createId()),
|
|
922
|
-
|
|
923
|
-
// Store Context
|
|
924
|
-
storeId: text("store_id").notNull(),
|
|
925
|
-
|
|
926
|
-
// Trail Information
|
|
927
|
-
trailName: varchar("trail_name", { length: 100 }).notNull(),
|
|
928
|
-
trailType: varchar("trail_type", { length: 30 })
|
|
929
|
-
.notNull()
|
|
930
|
-
.$type<
|
|
931
|
-
| "STORE_SETUP"
|
|
932
|
-
| "PRODUCT_LIFECYCLE"
|
|
933
|
-
| "ORDER_PROCESSING"
|
|
934
|
-
| "CUSTOMER_JOURNEY"
|
|
935
|
-
| "CONTENT_CREATION"
|
|
936
|
-
| "PAYMENT_PROCESSING"
|
|
937
|
-
| "INVENTORY_MANAGEMENT"
|
|
938
|
-
| "MARKETING_CAMPAIGN"
|
|
939
|
-
| "COMPLIANCE_AUDIT"
|
|
940
|
-
| "SECURITY_INVESTIGATION"
|
|
941
|
-
| "DATA_MIGRATION"
|
|
942
|
-
| "INTEGRATION_SETUP"
|
|
943
|
-
| "BUSINESS_WORKFLOW"
|
|
944
|
-
| "SYSTEM_MAINTENANCE"
|
|
945
|
-
>(),
|
|
946
|
-
|
|
947
|
-
trailDescription: text("trail_description"),
|
|
948
|
-
|
|
949
|
-
// Subject/Target Information
|
|
950
|
-
subjectType: varchar("subject_type", { length: 30 }).$type<
|
|
951
|
-
| "STORE"
|
|
952
|
-
| "USER"
|
|
953
|
-
| "PRODUCT"
|
|
954
|
-
| "ORDER"
|
|
955
|
-
| "CUSTOMER"
|
|
956
|
-
| "CAMPAIGN"
|
|
957
|
-
| "INTEGRATION"
|
|
958
|
-
| "PROCESS"
|
|
959
|
-
>(),
|
|
960
|
-
|
|
961
|
-
subjectId: text("subject_id").notNull(),
|
|
962
|
-
subjectName: varchar("subject_name", { length: 255 }),
|
|
963
|
-
|
|
964
|
-
// Trail Status and Lifecycle
|
|
965
|
-
status: varchar("status", { length: 20 })
|
|
966
|
-
.notNull()
|
|
967
|
-
.default("ACTIVE")
|
|
968
|
-
.$type<
|
|
969
|
-
| "PENDING"
|
|
970
|
-
| "ACTIVE"
|
|
971
|
-
| "COMPLETED"
|
|
972
|
-
| "FAILED"
|
|
973
|
-
| "SUSPENDED"
|
|
974
|
-
| "CANCELLED"
|
|
975
|
-
| "ARCHIVED"
|
|
976
|
-
>(),
|
|
977
|
-
|
|
978
|
-
// Timeline
|
|
979
|
-
startedAt: timestamp("started_at", { withTimezone: true }).notNull(),
|
|
980
|
-
completedAt: timestamp("completed_at", { withTimezone: true }),
|
|
981
|
-
estimatedCompletionAt: timestamp("estimated_completion_at", {
|
|
982
|
-
withTimezone: true,
|
|
983
|
-
}),
|
|
984
|
-
|
|
985
|
-
// Ownership and Responsibility
|
|
986
|
-
ownerId: text("owner_id"),
|
|
987
|
-
ownerName: varchar("owner_name", { length: 255 }),
|
|
988
|
-
ownerType: varchar("owner_type", { length: 20 }).$type<
|
|
989
|
-
"USER" | "SYSTEM" | "INTEGRATION" | "AUTOMATION"
|
|
990
|
-
>(),
|
|
991
|
-
|
|
992
|
-
assignedTo: text("assigned_to"),
|
|
993
|
-
department: varchar("department", { length: 100 }),
|
|
994
|
-
|
|
995
|
-
// Configuration and Settings
|
|
996
|
-
configuration: jsonb("configuration").$type<Record<string, unknown>>(),
|
|
997
|
-
|
|
998
|
-
// Purpose and Business Context
|
|
999
|
-
purpose: varchar("purpose", { length: 200 }),
|
|
1000
|
-
businessJustification: text("business_justification"),
|
|
1001
|
-
expectedOutcome: text("expected_outcome"),
|
|
1002
|
-
actualOutcome: text("actual_outcome"),
|
|
1003
|
-
|
|
1004
|
-
// Compliance and Governance
|
|
1005
|
-
complianceRequirements: jsonb("compliance_requirements")
|
|
1006
|
-
.$type<
|
|
1007
|
-
Array<{
|
|
1008
|
-
framework: string;
|
|
1009
|
-
requirement: string;
|
|
1010
|
-
status: "MET" | "NOT_MET" | "PARTIAL" | "PENDING";
|
|
1011
|
-
}>
|
|
1012
|
-
>()
|
|
1013
|
-
.default([]),
|
|
1014
|
-
|
|
1015
|
-
approvalRequired: boolean("approval_required").default(false),
|
|
1016
|
-
approvedBy: text("approved_by"),
|
|
1017
|
-
approvedAt: timestamp("approved_at", { withTimezone: true }),
|
|
1018
|
-
|
|
1019
|
-
// Risk Assessment
|
|
1020
|
-
riskLevel: varchar("risk_level", { length: 20 })
|
|
1021
|
-
.$type<"LOW" | "MEDIUM" | "HIGH" | "CRITICAL">()
|
|
1022
|
-
.default("LOW"),
|
|
1023
|
-
|
|
1024
|
-
riskFactors: jsonb("risk_factors")
|
|
1025
|
-
.$type<
|
|
1026
|
-
Array<{
|
|
1027
|
-
factor: string;
|
|
1028
|
-
impact: "LOW" | "MEDIUM" | "HIGH";
|
|
1029
|
-
likelihood: "LOW" | "MEDIUM" | "HIGH";
|
|
1030
|
-
mitigation: string;
|
|
1031
|
-
}>
|
|
1032
|
-
>()
|
|
1033
|
-
.default([]),
|
|
1034
|
-
|
|
1035
|
-
// Metrics and KPIs
|
|
1036
|
-
kpis: jsonb("kpis")
|
|
1037
|
-
.$type<
|
|
1038
|
-
Record<
|
|
1039
|
-
string,
|
|
1040
|
-
{
|
|
1041
|
-
target: number;
|
|
1042
|
-
actual?: number;
|
|
1043
|
-
unit: string;
|
|
1044
|
-
status: "ON_TRACK" | "AT_RISK" | "BEHIND" | "EXCEEDED";
|
|
1045
|
-
}
|
|
1046
|
-
>
|
|
1047
|
-
>()
|
|
1048
|
-
.default({}),
|
|
1049
|
-
|
|
1050
|
-
// Progress Tracking
|
|
1051
|
-
progress: integer("progress").default(0), // 0-100 percentage
|
|
1052
|
-
milestones: jsonb("milestones")
|
|
1053
|
-
.$type<
|
|
1054
|
-
Array<{
|
|
1055
|
-
name: string;
|
|
1056
|
-
description: string;
|
|
1057
|
-
targetDate: string;
|
|
1058
|
-
completedAt?: string;
|
|
1059
|
-
status: "PENDING" | "IN_PROGRESS" | "COMPLETED" | "SKIPPED";
|
|
1060
|
-
}>
|
|
1061
|
-
>()
|
|
1062
|
-
.default([]),
|
|
1063
|
-
|
|
1064
|
-
// Event Statistics
|
|
1065
|
-
totalEvents: integer("total_events").notNull().default(0),
|
|
1066
|
-
successfulEvents: integer("successful_events").notNull().default(0),
|
|
1067
|
-
failedEvents: integer("failed_events").notNull().default(0),
|
|
1068
|
-
|
|
1069
|
-
// Activity Tracking
|
|
1070
|
-
lastActivityAt: timestamp("last_activity_at", { withTimezone: true }),
|
|
1071
|
-
lastEventId: text("last_event_id"),
|
|
1072
|
-
|
|
1073
|
-
// Alerting and Monitoring
|
|
1074
|
-
alertingEnabled: boolean("alerting_enabled").notNull().default(true),
|
|
1075
|
-
alertThresholds: jsonb("alert_thresholds")
|
|
1076
|
-
.$type<{
|
|
1077
|
-
errorRate?: number;
|
|
1078
|
-
duration?: number;
|
|
1079
|
-
inactivity?: number;
|
|
1080
|
-
}>()
|
|
1081
|
-
.default({}),
|
|
1082
|
-
|
|
1083
|
-
// Data Retention
|
|
1084
|
-
retentionPeriod: integer("retention_period").default(2555), // days
|
|
1085
|
-
|
|
1086
|
-
// Integration and External Systems
|
|
1087
|
-
externalTrailId: text("external_trail_id"),
|
|
1088
|
-
externalSystemName: varchar("external_system_name", { length: 100 }),
|
|
1089
|
-
|
|
1090
|
-
// Audit Information
|
|
1091
|
-
createdAt: timestamp("created_at", { withTimezone: true })
|
|
1092
|
-
.defaultNow()
|
|
1093
|
-
.notNull(),
|
|
1094
|
-
updatedAt: timestamp("updated_at", { withTimezone: true })
|
|
1095
|
-
.defaultNow()
|
|
1096
|
-
.notNull(),
|
|
1097
|
-
createdBy: text("created_by"),
|
|
1098
|
-
lastModifiedBy: text("last_modified_by"),
|
|
1099
|
-
},
|
|
1100
|
-
(table) => ({
|
|
1101
|
-
// Primary business indexes
|
|
1102
|
-
storeTrailsIndex: index("idx_store_audit_trails_store").on(
|
|
1103
|
-
table.storeId,
|
|
1104
|
-
table.status,
|
|
1105
|
-
),
|
|
1106
|
-
|
|
1107
|
-
trailTypeIndex: index("idx_store_audit_trails_type").on(
|
|
1108
|
-
table.trailType,
|
|
1109
|
-
table.status,
|
|
1110
|
-
),
|
|
1111
|
-
|
|
1112
|
-
subjectIndex: index("idx_store_audit_trails_subject").on(
|
|
1113
|
-
table.subjectType,
|
|
1114
|
-
table.subjectId,
|
|
1115
|
-
),
|
|
1116
|
-
|
|
1117
|
-
// Status and timeline tracking
|
|
1118
|
-
statusIndex: index("idx_store_audit_trails_status").on(
|
|
1119
|
-
table.status,
|
|
1120
|
-
table.startedAt,
|
|
1121
|
-
),
|
|
1122
|
-
|
|
1123
|
-
timelineIndex: index("idx_store_audit_trails_timeline").on(
|
|
1124
|
-
table.startedAt,
|
|
1125
|
-
table.completedAt,
|
|
1126
|
-
),
|
|
1127
|
-
|
|
1128
|
-
// Ownership and responsibility
|
|
1129
|
-
ownerIndex: index("idx_store_audit_trails_owner").on(
|
|
1130
|
-
table.ownerId,
|
|
1131
|
-
table.status,
|
|
1132
|
-
),
|
|
1133
|
-
|
|
1134
|
-
// Activity monitoring
|
|
1135
|
-
activityIndex: index("idx_store_audit_trails_activity").on(
|
|
1136
|
-
table.lastActivityAt,
|
|
1137
|
-
table.status,
|
|
1138
|
-
),
|
|
1139
|
-
|
|
1140
|
-
// Risk and compliance
|
|
1141
|
-
riskIndex: index("idx_store_audit_trails_risk").on(
|
|
1142
|
-
table.riskLevel,
|
|
1143
|
-
table.storeId,
|
|
1144
|
-
),
|
|
1145
|
-
}),
|
|
1146
|
-
);
|
|
1147
|
-
|
|
1148
|
-
// =====================================================
|
|
1149
|
-
// STORE AUDIT RELATIONSHIPS
|
|
1150
|
-
// =====================================================
|
|
1151
|
-
|
|
1152
|
-
/**
|
|
1153
|
-
* Define relationships between audit tables and core store entities
|
|
1154
|
-
*/
|
|
1155
|
-
export const storeAuditRelations = relations(
|
|
1156
|
-
storeAuditLogs,
|
|
1157
|
-
({ one, many }) => ({
|
|
1158
|
-
// Link to trails (when workflowId is present)
|
|
1159
|
-
trail: one(storeAuditTrails, {
|
|
1160
|
-
fields: [storeAuditLogs.workflowId],
|
|
1161
|
-
references: [storeAuditTrails.id],
|
|
1162
|
-
}),
|
|
1163
|
-
|
|
1164
|
-
// Parent-child event relationships
|
|
1165
|
-
parentEvent: one(storeAuditLogs, {
|
|
1166
|
-
fields: [storeAuditLogs.parentEventId],
|
|
1167
|
-
references: [storeAuditLogs.id],
|
|
1168
|
-
relationName: "childEvents",
|
|
1169
|
-
}),
|
|
1170
|
-
|
|
1171
|
-
childEvents: many(storeAuditLogs, {
|
|
1172
|
-
relationName: "childEvents",
|
|
1173
|
-
}),
|
|
1174
|
-
}),
|
|
1175
|
-
);
|
|
1176
|
-
|
|
1177
|
-
// Note: Aggregation and Trail tables are independent analytics/workflow tables
|
|
1178
|
-
// They don't have direct foreign key relations to the main audit logs
|
|
1179
|
-
// Relations can be established at query time using storeId and timestamps
|
|
1180
|
-
|
|
1181
|
-
// =====================================================
|
|
1182
|
-
// TYPE EXPORTS
|
|
1183
|
-
// =====================================================
|
|
1184
|
-
|
|
1185
|
-
// Table Types
|
|
1186
|
-
export type StoreAuditLog = typeof storeAuditLogs.$inferSelect;
|
|
1187
|
-
export type NewStoreAuditLog = typeof storeAuditLogs.$inferInsert;
|
|
1188
|
-
|
|
1189
|
-
export type StoreAuditAggregation = typeof storeAuditAggregations.$inferSelect;
|
|
1190
|
-
export type NewStoreAuditAggregation =
|
|
1191
|
-
typeof storeAuditAggregations.$inferInsert;
|
|
1192
|
-
|
|
1193
|
-
export type StoreAuditTrail = typeof storeAuditTrails.$inferSelect;
|
|
1194
|
-
export type NewStoreAuditTrail = typeof storeAuditTrails.$inferInsert;
|
|
1195
|
-
|
|
1196
|
-
// Utility Types for Business Logic
|
|
1197
|
-
export type StoreAuditEventType = StoreAuditLog["eventType"];
|
|
1198
|
-
export type StoreAuditEventCategory = StoreAuditLog["eventCategory"];
|
|
1199
|
-
export type StoreAuditResourceType = StoreAuditLog["resourceType"];
|
|
1200
|
-
export type StoreAuditRiskLevel = StoreAuditLog["riskLevel"];
|
|
1201
|
-
export type StoreAuditUserRole = StoreAuditLog["userRole"];
|
|
1202
|
-
export type StoreAuditClientType = StoreAuditLog["clientType"];
|
|
1203
|
-
|
|
1204
|
-
// Complex Type Helpers
|
|
1205
|
-
export type StoreAuditChanges = NonNullable<StoreAuditLog["changes"]>;
|
|
1206
|
-
export type StoreAuditMetadata = NonNullable<StoreAuditLog["metadata"]>;
|
|
1207
|
-
export type StoreAuditLocation = NonNullable<StoreAuditLog["location"]>;
|
|
1208
|
-
export type StoreAuditDeviceInfo = NonNullable<StoreAuditLog["deviceInfo"]>;
|
|
1209
|
-
export type StoreAuditBusinessContext = NonNullable<
|
|
1210
|
-
StoreAuditLog["businessContext"]
|
|
1211
|
-
>;
|
|
1212
|
-
|
|
1213
|
-
// =====================================================
|
|
1214
|
-
// SCHEMA VALIDATION AND BUSINESS RULES
|
|
1215
|
-
// =====================================================
|
|
1216
|
-
|
|
1217
|
-
/**
|
|
1218
|
-
* Business rules and constraints for store audit logging
|
|
1219
|
-
*/
|
|
1220
|
-
export const STORE_AUDIT_BUSINESS_RULES = {
|
|
1221
|
-
// Retention periods by event type (in days)
|
|
1222
|
-
RETENTION_PERIODS: {
|
|
1223
|
-
SECURITY_EVENT: 2555, // 7 years
|
|
1224
|
-
COMPLIANCE_ACTION: 2555,
|
|
1225
|
-
DELETE: 2555,
|
|
1226
|
-
FINANCIAL: 2555,
|
|
1227
|
-
STANDARD: 1095, // 3 years
|
|
1228
|
-
SYSTEM_ACTION: 365, // 1 year
|
|
1229
|
-
},
|
|
1230
|
-
|
|
1231
|
-
// Risk level escalation rules
|
|
1232
|
-
RISK_ESCALATION: {
|
|
1233
|
-
CRITICAL: {
|
|
1234
|
-
immediateFlush: true,
|
|
1235
|
-
alertRequired: true,
|
|
1236
|
-
approvalRequired: true,
|
|
1237
|
-
},
|
|
1238
|
-
HIGH: {
|
|
1239
|
-
immediateFlush: true,
|
|
1240
|
-
alertRequired: true,
|
|
1241
|
-
},
|
|
1242
|
-
MEDIUM: {
|
|
1243
|
-
batchFlush: true,
|
|
1244
|
-
},
|
|
1245
|
-
LOW: {
|
|
1246
|
-
batchFlush: true,
|
|
1247
|
-
},
|
|
1248
|
-
},
|
|
1249
|
-
|
|
1250
|
-
// Compliance framework mappings
|
|
1251
|
-
COMPLIANCE_MAPPINGS: {
|
|
1252
|
-
PII_ACCESS: ["GDPR", "CCPA"],
|
|
1253
|
-
FINANCIAL_DATA: ["PCI_DSS", "SOX"],
|
|
1254
|
-
HEALTH_DATA: ["HIPAA"],
|
|
1255
|
-
ALL_DATA: ["ISO27001"],
|
|
1256
|
-
},
|
|
1257
|
-
} as const;
|