Add Info Broker Removal service (FRE-5402)
New service for helping clients remove personal listings from data broker sites. Service features: - BrokerRegistry: Catalog of 20+ data brokers with removal methods - RemoveBrokersService: Core service for scanning, creating removal requests, submitting removals, and verifying completions - RemoveBrokersScheduler: Automated processing of pending removals and verification of completed removals - BrokerAlertPipeline: Alert integration for listing discoveries and removal status API endpoints (/removebrokers): - GET /brokers - List available data brokers - GET /status - Get removal request status and stats - POST /scan - Scan for personal listings across brokers - POST /request - Create a new removal request - GET /request/:id - Get specific removal request details - DELETE /request/:id - Cancel a removal request - POST /process - Trigger processing of pending removals - POST /verify/:id - Manually verify a removal completion DB models: InfoBroker, RemovalRequest, BrokerListing Types: BrokerStatus, RemovalStatus, RemovalMethod, and related interfaces
This commit is contained in:
@@ -25,6 +25,7 @@ model User {
|
||||
// Relationships
|
||||
accounts Account[]
|
||||
sessions Session[]
|
||||
deviceTokens DeviceToken[]
|
||||
familyGroups FamilyGroupMember[]
|
||||
familyGroupOwned FamilyGroup[] @relation("FamilyGroupOwner")
|
||||
subscriptions Subscription[]
|
||||
@@ -37,6 +38,8 @@ model User {
|
||||
correlationGroups CorrelationGroup[]
|
||||
securityReports SecurityReport[]
|
||||
analysisJobs AnalysisJob[]
|
||||
removalRequests RemovalRequest[]
|
||||
brokerListings BrokerListing[]
|
||||
|
||||
// Audit
|
||||
createdAt DateTime @default(now())
|
||||
@@ -107,6 +110,42 @@ model Session {
|
||||
@@index([userId])
|
||||
}
|
||||
|
||||
model DeviceToken {
|
||||
id String @id @default(uuid())
|
||||
userId String
|
||||
deviceType DeviceType
|
||||
token String @unique
|
||||
platform Platform
|
||||
appName String?
|
||||
appVersion String?
|
||||
osVersion String?
|
||||
model String?
|
||||
isActive Boolean @default(true)
|
||||
lastUsedAt DateTime @default(now())
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([userId])
|
||||
@@index([deviceType])
|
||||
@@index([platform])
|
||||
@@index([isActive])
|
||||
}
|
||||
|
||||
enum DeviceType {
|
||||
mobile
|
||||
web
|
||||
desktop
|
||||
}
|
||||
|
||||
enum Platform {
|
||||
ios
|
||||
android
|
||||
web
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// Family & Subscription Models
|
||||
// ============================================
|
||||
@@ -167,6 +206,9 @@ model Subscription {
|
||||
watchlistItems WatchlistItem[]
|
||||
exposures Exposure[]
|
||||
alerts Alert[]
|
||||
propertyWatchlistItems PropertyWatchlistItem[]
|
||||
removalRequests RemovalRequest[]
|
||||
brokerListings BrokerListing[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
@@ -506,6 +548,8 @@ enum AlertSource {
|
||||
SPAMSHIELD
|
||||
VOICEPRINT
|
||||
CALL_ANALYSIS
|
||||
HOME_TITLE
|
||||
INFO_BROKER
|
||||
}
|
||||
|
||||
enum AlertCategory {
|
||||
@@ -517,6 +561,9 @@ enum AlertCategory {
|
||||
CALL_ANOMALY
|
||||
CALL_QUALITY
|
||||
CALL_EVENT
|
||||
HOME_TITLE
|
||||
INFO_BROKER_LISTING
|
||||
INFO_BROKER_REMOVAL
|
||||
}
|
||||
|
||||
enum NormalizedAlertSeverity {
|
||||
@@ -588,6 +635,7 @@ model CorrelationGroup {
|
||||
enum ReportType {
|
||||
MONTHLY_PLUS
|
||||
ANNUAL_PREMIUM
|
||||
WEEKLY_DIGEST
|
||||
}
|
||||
|
||||
enum ReportStatus {
|
||||
@@ -676,3 +724,192 @@ model BlogPost {
|
||||
@@index([published, publishedAt])
|
||||
@@index([tags])
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// Home Title Service Models
|
||||
// ============================================
|
||||
|
||||
enum PropertyChangeType {
|
||||
tax_change
|
||||
deed_change
|
||||
ownership_transfer
|
||||
lien_filing
|
||||
metadata_change
|
||||
}
|
||||
|
||||
enum PropertyChangeSeverity {
|
||||
info
|
||||
warning
|
||||
critical
|
||||
}
|
||||
|
||||
model PropertyWatchlistItem {
|
||||
id String @id @default(uuid())
|
||||
subscriptionId String
|
||||
address String
|
||||
parcelId String?
|
||||
ownerName String?
|
||||
streetAddress String
|
||||
city String? @default("")
|
||||
state String? @default("")
|
||||
zipCode String? @default("")
|
||||
latitude Float?
|
||||
longitude Float?
|
||||
isActive Boolean @default(true)
|
||||
|
||||
subscription Subscription @relation(fields: [subscriptionId], references: [id], onDelete: Cascade)
|
||||
snapshots PropertySnapshot[]
|
||||
changes PropertyChange[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@unique([subscriptionId, parcelId])
|
||||
@@index([subscriptionId])
|
||||
@@index([parcelId])
|
||||
@@index([address])
|
||||
}
|
||||
|
||||
model PropertySnapshot {
|
||||
id String @id @default(uuid())
|
||||
propertyWatchlistItemId String
|
||||
subscriptionId String
|
||||
capturedAt DateTime
|
||||
ownerName String
|
||||
address Json // { streetNumber, streetName, streetType, unit, city, state, zip, latitude?, longitude? }
|
||||
deedDate String?
|
||||
taxId String?
|
||||
propertyType String @default("residential")
|
||||
taxAmount Float?
|
||||
lienCount Int @default(0)
|
||||
|
||||
propertyWatchlistItem PropertyWatchlistItem @relation(fields: [propertyWatchlistItemId], references: [id], onDelete: Cascade)
|
||||
changes PropertyChange[] @relation("SnapshotChanges")
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([propertyWatchlistItemId])
|
||||
@@index([subscriptionId])
|
||||
@@index([capturedAt])
|
||||
}
|
||||
|
||||
model PropertyChange {
|
||||
id String @id @default(uuid())
|
||||
propertyWatchlistItemId String
|
||||
snapshotId String?
|
||||
changeType PropertyChangeType
|
||||
severity PropertyChangeSeverity @default(info)
|
||||
details Json?
|
||||
detectedAt DateTime @default(now())
|
||||
|
||||
propertyWatchlistItem PropertyWatchlistItem @relation(fields: [propertyWatchlistItemId], references: [id], onDelete: Cascade)
|
||||
snapshot PropertySnapshot? @relation("SnapshotChanges", fields: [snapshotId], references: [id])
|
||||
|
||||
@@index([propertyWatchlistItemId])
|
||||
@@index([snapshotId])
|
||||
@@index([changeType])
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// Info Broker Removal Models
|
||||
// ============================================
|
||||
|
||||
enum BrokerCategory {
|
||||
people_search
|
||||
background_check
|
||||
public_records
|
||||
reverse_lookup
|
||||
social_media
|
||||
}
|
||||
|
||||
enum RemovalMethod {
|
||||
automated
|
||||
manual_form
|
||||
email
|
||||
phone
|
||||
mail
|
||||
none
|
||||
}
|
||||
|
||||
enum RemovalStatus {
|
||||
pending
|
||||
submitted
|
||||
in_progress
|
||||
completed
|
||||
failed
|
||||
rejected
|
||||
}
|
||||
|
||||
model InfoBroker {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
domain String @unique
|
||||
category BrokerCategory
|
||||
removalMethod RemovalMethod
|
||||
removalUrl String?
|
||||
requiresAccount Boolean @default(false)
|
||||
requiresVerification Boolean @default(false)
|
||||
estimatedDays Int @default(14)
|
||||
isActive Boolean @default(true)
|
||||
|
||||
removalRequests RemovalRequest[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
|
||||
@@index([category])
|
||||
@@index([isActive])
|
||||
@@index([removalMethod])
|
||||
}
|
||||
|
||||
model RemovalRequest {
|
||||
id String @id @default(uuid())
|
||||
subscriptionId String
|
||||
brokerId String
|
||||
status RemovalStatus @default(pending)
|
||||
personalInfo Json // { fullName, email?, phone?, address?, dob? }
|
||||
method RemovalMethod
|
||||
attempts Int @default(0)
|
||||
nextRetryAt DateTime?
|
||||
submittedAt DateTime?
|
||||
completedAt DateTime?
|
||||
error String?
|
||||
notes String?
|
||||
metadata Json? // Broker response data, tracking info
|
||||
|
||||
broker InfoBroker @relation(fields: [brokerId], references: [id])
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
|
||||
@@index([subscriptionId])
|
||||
@@index([brokerId])
|
||||
@@index([status])
|
||||
@@index([submittedAt])
|
||||
@@index([subscriptionId, status])
|
||||
}
|
||||
|
||||
model BrokerListing {
|
||||
id String @id @default(uuid())
|
||||
subscriptionId String
|
||||
brokerId String
|
||||
removalRequestId String?
|
||||
url String
|
||||
dataFound Json // Fields found on the listing
|
||||
screenshotUrl String?
|
||||
isRemoved Boolean @default(false)
|
||||
removedAt DateTime?
|
||||
|
||||
removalRequest RemovalRequest? @relation(fields: [removalRequestId], references: [id])
|
||||
|
||||
scannedAt DateTime @default(now())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @default(now()) @updatedAt
|
||||
|
||||
@@index([subscriptionId])
|
||||
@@index([brokerId])
|
||||
@@index([removalRequestId])
|
||||
@@index([isRemoved])
|
||||
@@index([subscriptionId, isRemoved])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user