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:
Founding Engineer
2026-05-17 00:58:23 -04:00
committed by Michael Freno
parent 590e15e66e
commit bd881045f4
14 changed files with 1808 additions and 0 deletions

View File

@@ -27,6 +27,7 @@ export const AlertSource = {
SPAMSHIELD: "SPAMSHIELD",
VOICEPRINT: "VOICEPRINT",
CALL_ANALYSIS: "CALL_ANALYSIS",
INFO_BROKER: "INFO_BROKER",
} as const;
export type AlertSource = (typeof AlertSource)[keyof typeof AlertSource];
@@ -39,6 +40,9 @@ export const AlertCategory = {
CALL_QUALITY: "CALL_QUALITY",
CALL_ANOMALY: "CALL_ANOMALY",
CALL_EVENT: "CALL_EVENT",
HOME_TITLE: "HOME_TITLE",
INFO_BROKER_LISTING: "INFO_BROKER_LISTING",
INFO_BROKER_REMOVAL: "INFO_BROKER_REMOVAL",
} as const;
export type AlertCategory = (typeof AlertCategory)[keyof typeof AlertCategory];
@@ -280,6 +284,7 @@ export { generateRequestId, extractOrGenerateRequestId } from "./requestId";
export const ReportType = {
MONTHLY_PLUS: "MONTHLY_PLUS",
ANNUAL_PREMIUM: "ANNUAL_PREMIUM",
WEEKLY_DIGEST: "WEEKLY_DIGEST",
} as const;
export type ReportType = (typeof ReportType)[keyof typeof ReportType];
@@ -365,3 +370,93 @@ export interface SecurityReportOutput {
createdAt: Date;
deliveredAt?: Date;
}
// ============================================
// Info Broker Removal Types
// ============================================
export const BrokerStatus = {
ACTIVE: "ACTIVE",
INACTIVE: "INACTIVE",
UNKNOWN: "UNKNOWN",
} as const;
export type BrokerStatus = (typeof BrokerStatus)[keyof typeof BrokerStatus];
export const RemovalStatus = {
PENDING: "PENDING",
SUBMITTED: "SUBMITTED",
IN_PROGRESS: "IN_PROGRESS",
COMPLETED: "COMPLETED",
FAILED: "FAILED",
REJECTED: "REJECTED",
} as const;
export type RemovalStatus = (typeof RemovalStatus)[keyof typeof RemovalStatus];
export const RemovalMethod = {
AUTOMATED: "AUTOMATED",
MANUAL_FORM: "MANUAL_FORM",
EMAIL: "EMAIL",
PHONE: "PHONE",
MAIL: "MAIL",
NONE: "NONE",
} as const;
export type RemovalMethod = (typeof RemovalMethod)[keyof typeof RemovalMethod];
export interface BrokerDefinition {
id: string;
name: string;
domain: string;
category: string;
removalMethod: RemovalMethod;
removalUrl?: string;
requiresAccount: boolean;
requiresVerification: boolean;
estimatedDays: number;
isActive: boolean;
}
export interface RemovalRequestInput {
brokerId: string;
personalInfo: {
fullName: string;
email?: string;
phone?: string;
address?: {
street?: string;
city?: string;
state?: string;
zip?: string;
};
dob?: string;
};
notes?: string;
}
export interface RemovalRequestOutput {
id: string;
brokerId: string;
brokerName: string;
status: RemovalStatus;
submittedAt?: Date;
completedAt?: Date;
method: RemovalMethod;
attempts: number;
nextRetryAt?: Date;
notes?: string;
error?: string;
createdAt: Date;
updatedAt: Date;
}
export interface BrokerScanResult {
brokerId: string;
brokerName: string;
listingsFound: number;
listings: Array<{
id: string;
url: string;
dataFound: Record<string, string>;
screenshotUrl?: string;
}>;
scannedAt: Date;
}