@objectstack/plugin-audit 4.0.3 → 4.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,414 @@
1
+ # @objectstack/plugin-audit
2
+
3
+ Audit Plugin for ObjectStack — System audit log object and audit trail for compliance and security monitoring.
4
+
5
+ ## Features
6
+
7
+ - **Comprehensive Audit Trail**: Track all CRUD operations across all objects
8
+ - **User Activity Logging**: Record who did what, when, and from where
9
+ - **Field-Level Changes**: Capture before/after values for all field changes
10
+ - **Compliance Ready**: Meet SOC 2, HIPAA, GDPR audit requirements
11
+ - **Query Filtering**: Search audit logs by user, object, action, date range
12
+ - **Retention Policies**: Auto-archive or delete old audit logs
13
+ - **Security Events**: Track authentication, authorization, and security-related events
14
+ - **Immutable Logs**: Audit records cannot be modified or deleted (only archived)
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ pnpm add @objectstack/plugin-audit
20
+ ```
21
+
22
+ ## Basic Usage
23
+
24
+ ```typescript
25
+ import { defineStack } from '@objectstack/spec';
26
+ import { PluginAudit } from '@objectstack/plugin-audit';
27
+
28
+ const stack = defineStack({
29
+ plugins: [
30
+ PluginAudit.configure({
31
+ enabled: true,
32
+ trackObjects: '*', // Track all objects
33
+ trackFields: '*', // Track all field changes
34
+ }),
35
+ ],
36
+ });
37
+ ```
38
+
39
+ ## Configuration
40
+
41
+ ```typescript
42
+ interface AuditPluginConfig {
43
+ /** Enable audit logging (default: true) */
44
+ enabled?: boolean;
45
+
46
+ /** Objects to track ('*' for all, or array of object names) */
47
+ trackObjects?: '*' | string[];
48
+
49
+ /** Fields to track ('*' for all, or object-specific config) */
50
+ trackFields?: '*' | Record<string, string[]>;
51
+
52
+ /** Track system events (login, logout, failed auth, etc.) */
53
+ trackSystemEvents?: boolean;
54
+
55
+ /** Retention period in days (default: 365) */
56
+ retentionDays?: number;
57
+
58
+ /** Auto-archive after retention period (default: true) */
59
+ autoArchive?: boolean;
60
+
61
+ /** Exclude certain users from audit (e.g., system users) */
62
+ excludeUsers?: string[];
63
+ }
64
+ ```
65
+
66
+ ## Audit Log Schema
67
+
68
+ The plugin automatically creates the `audit_log` object:
69
+
70
+ ```typescript
71
+ {
72
+ id: string; // Unique audit log entry ID
73
+ timestamp: datetime; // When the action occurred
74
+ userId: string; // User who performed the action
75
+ userName: string; // User's name at time of action
76
+ userEmail: string; // User's email at time of action
77
+ action: string; // 'insert', 'update', 'delete', 'read'
78
+ object: string; // Object type (e.g., 'opportunity')
79
+ recordId: string; // Record ID that was affected
80
+ recordName: string; // Record display name
81
+ changes: json; // Field-level changes (before/after)
82
+ metadata: json; // Additional context (IP, user agent, etc.)
83
+ ipAddress: string; // Client IP address
84
+ userAgent: string; // Client user agent
85
+ sessionId: string; // Session ID
86
+ status: string; // 'success' | 'failed'
87
+ errorMessage: string; // Error message if action failed
88
+ }
89
+ ```
90
+
91
+ ## Automatic Audit Logging
92
+
93
+ All CRUD operations are automatically audited:
94
+
95
+ ```typescript
96
+ // This operation is automatically audited
97
+ await kernel.getDriver().insert({
98
+ object: 'opportunity',
99
+ data: {
100
+ name: 'Big Deal',
101
+ amount: 100000,
102
+ stage: 'prospecting',
103
+ },
104
+ });
105
+
106
+ // Audit log entry created:
107
+ // {
108
+ // action: 'insert',
109
+ // object: 'opportunity',
110
+ // recordId: '123',
111
+ // recordName: 'Big Deal',
112
+ // changes: {
113
+ // name: { from: null, to: 'Big Deal' },
114
+ // amount: { from: null, to: 100000 },
115
+ // stage: { from: null, to: 'prospecting' }
116
+ // }
117
+ // }
118
+ ```
119
+
120
+ ## Querying Audit Logs
121
+
122
+ ```typescript
123
+ // Get audit logs via kernel
124
+ const auditService = kernel.getService('audit');
125
+
126
+ // Get all changes for a specific record
127
+ const recordHistory = await auditService.getRecordHistory({
128
+ object: 'opportunity',
129
+ recordId: '123',
130
+ });
131
+
132
+ // Get user activity
133
+ const userActivity = await auditService.getUserActivity({
134
+ userId: 'user:456',
135
+ from: '2024-01-01',
136
+ to: '2024-01-31',
137
+ });
138
+
139
+ // Search audit logs
140
+ const logs = await auditService.searchLogs({
141
+ action: 'delete',
142
+ object: 'account',
143
+ from: '2024-01-01',
144
+ to: '2024-01-31',
145
+ });
146
+
147
+ // Get failed actions (security monitoring)
148
+ const failures = await auditService.getFailedActions({
149
+ from: '2024-01-01',
150
+ limit: 100,
151
+ });
152
+ ```
153
+
154
+ ## Selective Tracking
155
+
156
+ ### Track Specific Objects
157
+
158
+ ```typescript
159
+ PluginAudit.configure({
160
+ trackObjects: ['opportunity', 'account', 'contact'],
161
+ // Only these objects will be audited
162
+ });
163
+ ```
164
+
165
+ ### Track Specific Fields
166
+
167
+ ```typescript
168
+ PluginAudit.configure({
169
+ trackFields: {
170
+ opportunity: ['stage', 'amount', 'close_date'], // Only track these fields
171
+ account: '*', // Track all fields for accounts
172
+ contact: ['email', 'phone'], // Only email and phone for contacts
173
+ },
174
+ });
175
+ ```
176
+
177
+ ### Exclude System Users
178
+
179
+ ```typescript
180
+ PluginAudit.configure({
181
+ excludeUsers: [
182
+ 'system:integration',
183
+ 'system:cron',
184
+ 'service:automation',
185
+ ],
186
+ // These users' actions won't be audited
187
+ });
188
+ ```
189
+
190
+ ## Advanced Features
191
+
192
+ ### Manual Audit Entries
193
+
194
+ ```typescript
195
+ // Log custom security event
196
+ await auditService.log({
197
+ action: 'security:password_reset',
198
+ userId: 'user:456',
199
+ metadata: {
200
+ resetMethod: 'email',
201
+ ipAddress: '192.168.1.100',
202
+ },
203
+ });
204
+
205
+ // Log business process event
206
+ await auditService.log({
207
+ action: 'workflow:approval',
208
+ object: 'opportunity',
209
+ recordId: '123',
210
+ metadata: {
211
+ approver: 'manager:789',
212
+ decision: 'approved',
213
+ },
214
+ });
215
+ ```
216
+
217
+ ### Audit Snapshots
218
+
219
+ ```typescript
220
+ // Create snapshot of record state at a specific time
221
+ const snapshot = await auditService.getRecordSnapshot({
222
+ object: 'opportunity',
223
+ recordId: '123',
224
+ asOf: '2024-01-15T10:30:00Z',
225
+ });
226
+
227
+ // Returns: Record state as it existed on Jan 15, 2024 at 10:30 AM
228
+ ```
229
+
230
+ ### Audit Reports
231
+
232
+ ```typescript
233
+ // Generate compliance report
234
+ const report = await auditService.generateReport({
235
+ type: 'compliance',
236
+ from: '2024-01-01',
237
+ to: '2024-03-31',
238
+ format: 'pdf',
239
+ });
240
+
241
+ // Generate user activity report
242
+ const userReport = await auditService.generateReport({
243
+ type: 'user_activity',
244
+ userId: 'user:456',
245
+ from: '2024-01-01',
246
+ to: '2024-01-31',
247
+ includeDetails: true,
248
+ });
249
+ ```
250
+
251
+ ### Data Retention & Archival
252
+
253
+ ```typescript
254
+ // Archive old audit logs
255
+ await auditService.archiveLogs({
256
+ olderThan: '2023-01-01',
257
+ destination: 's3://audit-archive/2023/',
258
+ });
259
+
260
+ // Permanently delete archived logs (compliance approved)
261
+ await auditService.purgeLogs({
262
+ olderThan: '2020-01-01',
263
+ confirmed: true, // Safety check
264
+ });
265
+ ```
266
+
267
+ ## Security Events
268
+
269
+ The plugin automatically logs security-related events:
270
+
271
+ - **Authentication**: Login, logout, password changes
272
+ - **Authorization**: Permission denied, role changes
273
+ - **Data Access**: Read operations on sensitive fields
274
+ - **Configuration**: System setting changes
275
+ - **API**: API key usage, rate limit violations
276
+
277
+ ```typescript
278
+ // Automatically logged:
279
+ // - Login attempts (success/failure)
280
+ // - Permission denied errors
281
+ // - Sensitive field access
282
+ // - API authentication failures
283
+ ```
284
+
285
+ ## Compliance Integration
286
+
287
+ ### GDPR Compliance
288
+
289
+ ```typescript
290
+ // Right to be forgotten - audit trail for deletions
291
+ await auditService.logDataDeletion({
292
+ userId: 'user:456',
293
+ reason: 'gdpr_right_to_be_forgotten',
294
+ deletedRecords: [
295
+ { object: 'user', recordId: '456' },
296
+ { object: 'contact', recordId: '789' },
297
+ ],
298
+ });
299
+
300
+ // Right of access - audit trail for data exports
301
+ await auditService.logDataExport({
302
+ userId: 'user:456',
303
+ reason: 'gdpr_data_access_request',
304
+ exportedObjects: ['user', 'contact', 'activity'],
305
+ });
306
+ ```
307
+
308
+ ### SOC 2 Compliance
309
+
310
+ ```typescript
311
+ // Log administrative actions
312
+ await auditService.logAdminAction({
313
+ adminId: 'admin:123',
314
+ action: 'user_role_change',
315
+ targetUserId: 'user:456',
316
+ changes: {
317
+ roles: { from: ['user'], to: ['user', 'admin'] },
318
+ },
319
+ });
320
+ ```
321
+
322
+ ### HIPAA Compliance
323
+
324
+ ```typescript
325
+ // Track PHI access
326
+ PluginAudit.configure({
327
+ trackFields: {
328
+ patient: ['ssn', 'medical_record_number', 'diagnosis'], // PHI fields
329
+ },
330
+ trackSystemEvents: true,
331
+ });
332
+ ```
333
+
334
+ ## REST API Endpoints
335
+
336
+ ```
337
+ GET /api/v1/audit # List audit logs
338
+ GET /api/v1/audit/:id # Get specific log entry
339
+ GET /api/v1/audit/record/:object/:id # Get record history
340
+ GET /api/v1/audit/user/:userId # Get user activity
341
+ POST /api/v1/audit/report # Generate report
342
+ POST /api/v1/audit/archive # Archive old logs
343
+ ```
344
+
345
+ ## Dashboard Integration
346
+
347
+ ```typescript
348
+ // Audit dashboard widget
349
+ const auditWidget = {
350
+ title: 'Recent Activity',
351
+ query: {
352
+ object: 'audit_log',
353
+ limit: 50,
354
+ sort: [{ field: 'timestamp', direction: 'desc' }],
355
+ },
356
+ };
357
+
358
+ // Security alerts dashboard
359
+ const securityWidget = {
360
+ title: 'Failed Login Attempts',
361
+ query: {
362
+ object: 'audit_log',
363
+ filters: [
364
+ { field: 'action', operator: 'eq', value: 'auth:login' },
365
+ { field: 'status', operator: 'eq', value: 'failed' },
366
+ { field: 'timestamp', operator: 'gte', value: 'today' },
367
+ ],
368
+ },
369
+ };
370
+ ```
371
+
372
+ ## Best Practices
373
+
374
+ 1. **Selective Tracking**: Only audit what's necessary for compliance
375
+ 2. **Retention Policy**: Set appropriate retention based on regulations
376
+ 3. **Performance**: Archive old logs to keep query performance high
377
+ 4. **Security**: Restrict access to audit logs (admin only)
378
+ 5. **Immutability**: Never allow modification of audit records
379
+ 6. **Monitoring**: Set alerts for suspicious activity patterns
380
+ 7. **Regular Review**: Periodically review audit logs for anomalies
381
+
382
+ ## Performance Considerations
383
+
384
+ - **Async Logging**: Audit writes happen asynchronously (no performance impact)
385
+ - **Indexing**: Automatically indexes `userId`, `object`, `recordId`, `timestamp`
386
+ - **Partitioning**: Consider table partitioning for high-volume deployments
387
+ - **Archival**: Move old logs to cold storage (S3, Glacier)
388
+
389
+ ## Contract Implementation
390
+
391
+ Implements audit logging hooks from `@objectstack/spec/contracts`:
392
+
393
+ ```typescript
394
+ interface IAuditService {
395
+ log(entry: AuditLogEntry): Promise<void>;
396
+ getRecordHistory(options: RecordHistoryOptions): Promise<AuditLog[]>;
397
+ getUserActivity(options: UserActivityOptions): Promise<AuditLog[]>;
398
+ searchLogs(filter: AuditLogFilter): Promise<AuditLog[]>;
399
+ getRecordSnapshot(options: SnapshotOptions): Promise<any>;
400
+ archiveLogs(options: ArchiveOptions): Promise<void>;
401
+ }
402
+ ```
403
+
404
+ ## License
405
+
406
+ Apache-2.0
407
+
408
+ ## See Also
409
+
410
+ - [SOC 2 Compliance Guide](https://www.aicpa.org/interestareas/frc/assuranceadvisoryservices/sorhome)
411
+ - [GDPR Requirements](https://gdpr.eu/)
412
+ - [HIPAA Compliance](https://www.hhs.gov/hipaa/)
413
+ - [@objectstack/plugin-security](../plugin-security/)
414
+ - [Audit Logging Best Practices](/content/docs/guides/audit/)