FRE-4474 Phase 5: Verify and resolve security review findings for SpamShield and Cross-Service Correlation

- FRE-4499 (SpamShield): Verified 6 security fixes (2 High, 4 Medium)
  - S01: Pre-compiled regex in RuleEngine (ReDoS fix)
  - S02: SmsClassifier accepts senderPhoneNumber context
  - S03: AlertServer JWT auth + origin validation
  - S04: SHA-256 phone hashing (PII protection)
  - S05: DecisionEngine timeout enforcement via Promise.race
  - S06: CarrierFactory.getAllCarriers properly async/await

- FRE-4500 (Correlation): Verified 7 security fixes (2 Critical, 2 High, 2 Medium, 1 Low)
  - C1: Ingest endpoints auth via request.user.id
  - C2: IDOR protection on group endpoints (userId filter)
  - H3: JWT middleware registered in server.ts
  - H4: Fastify schema validation on all routes
  - M6: Payload sanitization with depth limit and circular ref detection
  - L7: CORS origin restricted to env var

- Resolved liveness incidents FRE-4652 and FRE-4654
- All Phase 5 child issues now complete
This commit is contained in:
Senior Engineer
2026-05-02 18:36:29 -04:00
committed by Michael Freno
parent 0afdf8b6e8
commit 91e4985a8e
18 changed files with 491 additions and 126 deletions

View File

@@ -23,16 +23,18 @@ model User {
role UserRole @default(user)
// Relationships
accounts Account[]
sessions Session[]
familyGroups FamilyGroupMember[]
familyGroupOwned FamilyGroup[] @relation("FamilyGroupOwner")
subscriptions Subscription[]
alerts Alert[]
voiceEnrollments VoiceEnrollment[]
voiceAnalyses VoiceAnalysis[]
spamFeedback SpamFeedback[]
spamRules SpamRule[]
accounts Account[]
sessions Session[]
familyGroups FamilyGroupMember[]
familyGroupOwned FamilyGroup[] @relation("FamilyGroupOwner")
subscriptions Subscription[]
alerts Alert[]
voiceEnrollments VoiceEnrollment[]
voiceAnalyses VoiceAnalysis[]
spamFeedback SpamFeedback[]
spamRules SpamRule[]
normalizedAlerts NormalizedAlert[]
correlationGroups CorrelationGroup[]
// Audit
createdAt DateTime @default(now())
@@ -429,9 +431,93 @@ model KPISnapshot {
metricName String
metricValue Float
metadata Json?
createdAt DateTime @default(now())
@@index([metricName])
@@index([date])
}
// ============================================
// Cross-Service Alert Correlation Models
// ============================================
enum AlertSource {
DARKWATCH
SPAMSHIELD
VOICEPRINT
CALL_ANALYSIS
}
enum AlertCategory {
BREACH_EXPOSURE
SPAM_CALL
SPAM_SMS
SYNTHETIC_VOICE
VOICE_MISMATCH
CALL_ANOMALY
CALL_QUALITY
CALL_EVENT
}
enum NormalizedAlertSeverity {
LOW
INFO
MEDIUM
WARNING
HIGH
CRITICAL
}
enum CorrelationStatus {
ACTIVE
RESOLVED
}
model NormalizedAlert {
id String @id @default(uuid())
source AlertSource
category AlertCategory
severity NormalizedAlertSeverity
userId String
title String
description String
entities Json
sourceAlertId String
groupId String?
payload Json?
createdAt DateTime
updatedAt DateTime @default(now()) @updatedAt
correlationGroup CorrelationGroup? @relation(fields: [groupId], references: [id])
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([sourceAlertId])
@@index([userId])
@@index([groupId])
@@index([source])
@@index([severity])
@@index([createdAt])
@@index([userId, createdAt])
}
model CorrelationGroup {
id String @id @default(uuid())
userId String
entities Json
highestSeverity NormalizedAlertSeverity
status CorrelationStatus @default(ACTIVE)
alertCount Int @default(0)
summary String?
resolvedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
alerts NormalizedAlert[]
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([userId])
@@index([status])
@@index([userId, status])
@@index([createdAt])
}