High-risk fraud actions should leave a complete, searchable audit trail with clear lockout semantics. Improve lockout logging and admin visibility.
April 25, 2026
File: src/audit/entities/audit-log.entity.ts
Added three new audit action types for fraud-related events:
FRAUD_ALERT: Logged when a fraud alert is createdFRAUD_LOCKOUT: Logged when an account is automatically locked due to fraudFRAUD_REVIEW: Logged when an admin reviews a fraud alert
File: src/fraud/entities/fraud-alert.entity.ts
Added comprehensive tracking fields:
lockoutReason: Text field explaining why account was lockedlockoutTimestamp: When the lockout occurredlockoutDurationMinutes: Expected or actual lockout durationreviewedBy: Admin ID who reviewed the alertreviewedAt: Timestamp of reviewreviewNotes: Admin notes during reviewupdatedAt: Automatic timestamp for last update
File: src/fraud/fraud.service.ts
Dependencies Added:
AuditService: For direct audit loggingEventEmitter2: For emitting fraud events
Audit Events Emitted:
-
fraud.alert_created (Line ~99-127)
- Emitted when any fraud alert is created (score >= 20)
- Includes: userId, riskScore, status, ipAddress, triggeredRules
- Full state tracking with previous/new values
-
fraud.account_locked (Line ~131-153)
- Emitted when automated lockout is triggered (3+ flags in 60 minutes)
- Includes: userId, fraudAlertId, flagCount, riskScore, lockoutReason
- Tracks user status change (e.g., ACTIVE → LOCKED)
Key Features:
- All fraud alerts now create immutable audit logs
- Lockout events include complete context (triggered rules, flag count, IP)
- State diffs recorded for compliance requirements
File: src/fraud/fraud.module.ts
Added required module imports:
AuditModule: For audit service integrationEventEmitterModule.forRoot(): For event emission
File: src/audit/audit.listener.ts
Added three new event handlers:
-
handleFraudAlertCreated() (Line ~237-258)
- Listens to:
fraud.alert_created - Creates audit log with FRAUD_ALERT action type
- Logs risk score and triggered rules
- Listens to:
-
handleFraudAccountLocked() (Line ~264-285)
- Listens to:
fraud.account_locked - Creates audit log with FRAUD_LOCKOUT action type
- Status set to WARNING for visibility
- Listens to:
-
handleFraudAlertReviewed() (Line ~291-312)
- Listens to:
fraud.alert_reviewed - Creates audit log with FRAUD_REVIEW action type
- Tracks reviewer accountability
- Listens to:
File: src/admin/admin-fraud.controller.ts
New Endpoints:
-
GET /admin/fraud/alerts (Enhanced)
- Added pagination support (page, limit query params)
- Added filtering by status and userId
- Returns structured response with data and meta
-
GET /admin/fraud/alerts/:id (New)
- Get single fraud alert details
- Returns complete alert object
-
PATCH /admin/fraud/alerts/:id/review (Enhanced)
- Now captures reviewer ID from authenticated user
- Records review timestamp and notes
- Emits
fraud.alert_reviewedaudit event - Full state diff tracking (previous → new status)
-
GET /admin/fraud/alerts/:id/audit-trail (New)
- Returns complete audit trail for a fraud alert
- Includes both alert events and related lockout events
- Searchable and filterable
-
GET /admin/fraud/lockouts (New)
- List all account lockouts with pagination
- Filter by userId
- Query audit logs for FRAUD_LOCKOUT events
-
GET /admin/fraud/stats (New)
- Fraud statistics dashboard
- Alert counts: 24h, 7d, 30d
- Lockout counts: 24h, 7d
- Real-time metrics for admin visibility
Dependencies Added:
EventEmitter2: For emitting review eventsAuditService: For querying audit logs and lockouts
Files:
src/fraud/tests/fraud.service.spec.ts(Enhanced)src/admin/admin-fraud.controller.spec.ts(New)
New Tests:
-
FraudService Tests:
- Test audit event emission on alert creation
- Test lockout audit event emission after 3 flags
- Verify event payload structure
- Verify action types and metadata
-
AdminFraudController Tests:
- Test paginated alert listing
- Test filtering by status and userId
- Test alert review with audit event emission
- Test audit trail retrieval
- Test lockout listing
- Test statistics endpoint
File: src/fraud/FRAUD_DETECTION.md
Sections Added/Updated:
- Overview: Added audit trail and admin visibility features
- Features: Added lockout protocol and audit trail features
- FraudAlert Entity: Documented new lockout and review tracking fields
- Audit Trail Integration (New Section):
- Audit action types explained
- Events emitted with payloads documented
- Audit listeners documented
- Admin Controllers: Updated with all new endpoints
- Database Schema: Updated with new columns
- Usage Examples: Added comprehensive API examples for:
- Paginated alert queries
- Filtering alerts
- Reviewing alerts with notes
- Retrieving audit trails
- Viewing lockouts
- Getting statistics
- Audit trail queries
- Security Notes: Enhanced with lockout semantics and audit trail details
- Trigger: 3+ fraud flags within 60-minute window
- Action: User status changed to LOCKED
- Notification: Email sent to user
- Audit: Complete audit log created with:
- Previous user status
- New user status (LOCKED)
- Fraud alert ID that triggered lockout
- Risk score and triggered rules
- Flag count and time window
- Lockout reason
- View all lockouts:
GET /admin/fraud/lockouts - Filter by user:
GET /admin/fraud/lockouts?userId=xxx - View audit trail:
GET /admin/fraud/alerts/:id/audit-trail - Statistics:
GET /admin/fraud/stats
Every fraud action now leaves an immutable record:
{
"action": "FRAUD_ALERT",
"userId": "user-123",
"status": "WARNING",
"resourceType": "fraud_alert",
"resourceId": "alert-uuid",
"stateNewValue": {
"riskScore": 85,
"status": "manual_review",
"reason": "high_value_order, new_account"
},
"metadata": {
"alertId": "alert-uuid",
"orderId": "order-uuid",
"triggeredRules": ["high_value_order", "new_account"],
"ipAddress": "192.168.1.100"
}
}{
"action": "FRAUD_LOCKOUT",
"userId": "user-123",
"status": "WARNING",
"resourceType": "user",
"resourceId": "user-123",
"statePreviousValue": { "status": "active" },
"stateNewValue": { "status": "locked" },
"metadata": {
"fraudAlertId": "alert-uuid",
"riskScore": 95,
"flagCount": 3,
"triggeredRules": ["high_value_order", "new_account", "known_bad_ip"],
"lockoutReason": "Automated lockout after 3 fraud flags within 60 minutes"
}
}{
"action": "FRAUD_REVIEW",
"userId": "admin-456",
"status": "SUCCESS",
"resourceType": "fraud_alert",
"resourceId": "alert-uuid",
"statePreviousValue": { "status": "pending" },
"stateNewValue": { "status": "safe", "notes": "False positive - verified" },
"metadata": {
"alertId": "alert-uuid",
"userId": "user-123",
"riskScore": 85,
"previousStatus": "pending",
"newStatus": "safe",
"reviewer": "admin-456"
}
}Admins can now search audit logs with:
# By action type
GET /admin/audit?action=FRAUD_ALERT
# By user
GET /admin/audit?userId=user-123
# By date range
GET /admin/audit?startDate=2026-04-01&endDate=2026-04-25
# By resource
GET /admin/audit?resourceType=fraud_alert&resourceId=alert-uuid
# Combined filters
GET /admin/audit?action=FRAUD_LOCKOUT&startDate=2026-04-01npm test -- src/fraud/tests/fraud.service.spec.ts
npm test -- src/admin/admin-fraud.controller.spec.ts- ✅ Alert creation with audit emission
- ✅ Lockout trigger with audit emission
- ✅ Admin review with audit emission
- ✅ Audit trail retrieval
- ✅ Lockout listing and filtering
- ✅ Statistics calculation
- ✅ Pagination and filtering
After deploying these changes, run a database migration to add new columns to fraud_alerts table:
ALTER TABLE fraud_alerts
ADD COLUMN IF NOT EXISTS "lockoutReason" TEXT,
ADD COLUMN IF NOT EXISTS "lockoutTimestamp" TIMESTAMP,
ADD COLUMN IF NOT EXISTS "lockoutDurationMinutes" INT,
ADD COLUMN IF NOT EXISTS "reviewedBy" VARCHAR,
ADD COLUMN IF NOT EXISTS "reviewedAt" TIMESTAMP,
ADD COLUMN IF NOT EXISTS "reviewNotes" TEXT,
ADD COLUMN IF NOT EXISTS "updatedAt" TIMESTAMP DEFAULT NOW();✅ No Breaking Changes:
- All existing endpoints continue to work
- New fields are nullable
- Audit events are additive (don't replace existing logging)
- Existing fraud alerts will work without new fields
- Complete Audit Trail: Every fraud action is logged immutably
- Searchable Logs: Admins can query by user, date, action type, resource
- Lockout Transparency: Clear visibility into why/when accounts were locked
- Review Accountability: All admin reviews tracked with ID and timestamp
- State Tracking: Previous and new states recorded for all actions
- Compliance Ready: Meets requirements for financial fraud audit trails
- Real-time Monitoring: Statistics dashboard for proactive monitoring
- Event-Driven Architecture: Decoupled audit logging via event emission
src/audit/entities/audit-log.entity.ts- Added fraud action typessrc/fraud/entities/fraud-alert.entity.ts- Enhanced with tracking fieldssrc/fraud/fraud.service.ts- Integrated audit loggingsrc/fraud/fraud.module.ts- Added module dependenciessrc/audit/audit.listener.ts- Added fraud event handlerssrc/admin/admin-fraud.controller.ts- Enhanced with audit endpointssrc/fraud/tests/fraud.service.spec.ts- Added audit testssrc/admin/admin-fraud.controller.spec.ts- New test filesrc/fraud/FRAUD_DETECTION.md- Comprehensive documentation update
- ✅ Implementation updates complete
- ✅ Module dependencies aligned
- ✅ Documentation updated
- ✅ Tests added for affected areas
- ✅ No regressions introduced (backward compatible)
- ✅ Audit trail complete and searchable
- ✅ Lockout semantics clearly defined
- ✅ Admin visibility enhanced
- Create TypeORM migration file for new columns
- Add unit tests for audit listener fraud handlers
- Add integration tests for end-to-end audit trail
- Consider adding webhook notifications for lockouts
- Add export functionality for audit reports (CSV/PDF)
- Implement role-based audit log access (super-admin vs admin)