FRE-4471: Scaffold DarkWatch MVP — monorepo, schema, services, API routes, tests
- Turborepo monorepo structure (packages: api, db, types, jobs; services: darkwatch) - Prisma schema: User, WatchListItem, Exposure, Alert, ScanJob models - WatchListService: CRUD with normalization, dedup, tier-based limits - HIBPService: API integration with severity scoring - MatchingEngine: exact-match with content hash dedup - AlertPipeline: dedup window, email notifications - ScanService: orchestrates watch list -> HIBP -> match -> alert flow - BullMQ job workers for scan and alert processing - Fastify API routes: watchlist, exposures, alerts, scan - Docker Compose: PostgreSQL 16 + Redis 7 - 15 unit tests passing - Implementation plan document uploaded
This commit is contained in:
13
packages/types/package.json
Normal file
13
packages/types/package.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "@shieldai/types",
|
||||
"version": "0.1.0",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.js",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"lint": "eslint src/"
|
||||
},
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
}
|
||||
}
|
||||
84
packages/types/src/index.ts
Normal file
84
packages/types/src/index.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
export const IdentifierType = {
|
||||
EMAIL: "EMAIL",
|
||||
PHONE: "PHONE",
|
||||
SSN: "SSN",
|
||||
} as const;
|
||||
export type IdentifierType = (typeof IdentifierType)[keyof typeof IdentifierType];
|
||||
|
||||
export const SubscriptionTier = {
|
||||
BASIC: "BASIC",
|
||||
PLUS: "PLUS",
|
||||
PREMIUM: "PREMIUM",
|
||||
} as const;
|
||||
export type SubscriptionTier = (typeof SubscriptionTier)[keyof typeof SubscriptionTier];
|
||||
|
||||
export const Severity = {
|
||||
INFO: "INFO",
|
||||
WARNING: "WARNING",
|
||||
CRITICAL: "CRITICAL",
|
||||
} as const;
|
||||
export type Severity = (typeof Severity)[keyof typeof Severity];
|
||||
|
||||
export const AlertChannel = {
|
||||
EMAIL: "EMAIL",
|
||||
PUSH: "PUSH",
|
||||
SMS: "SMS",
|
||||
} as const;
|
||||
export type AlertChannel = (typeof AlertChannel)[keyof typeof AlertChannel];
|
||||
|
||||
export const AlertStatus = {
|
||||
PENDING: "PENDING",
|
||||
SENT: "SENT",
|
||||
READ: "READ",
|
||||
} as const;
|
||||
export type AlertStatus = (typeof AlertStatus)[keyof typeof AlertStatus];
|
||||
|
||||
export const ScanJobStatus = {
|
||||
PENDING: "PENDING",
|
||||
RUNNING: "RUNNING",
|
||||
COMPLETED: "COMPLETED",
|
||||
FAILED: "FAILED",
|
||||
} as const;
|
||||
export type ScanJobStatus = (typeof ScanJobStatus)[keyof typeof ScanJobStatus];
|
||||
|
||||
export const WatchListStatus = {
|
||||
ACTIVE: "ACTIVE",
|
||||
PAUSED: "PAUSED",
|
||||
} as const;
|
||||
export type WatchListStatus = (typeof WatchListStatus)[keyof typeof WatchListStatus];
|
||||
|
||||
export const DataSource = {
|
||||
HIBP: "HIBP",
|
||||
SECURITY_TRAILS: "SECURITY_TRAILS",
|
||||
CENSYS: "CENSYS",
|
||||
SHODAN: "SHODAN",
|
||||
HONEYPOT: "HONEYPOT",
|
||||
} as const;
|
||||
export type DataSource = (typeof DataSource)[keyof typeof DataSource];
|
||||
|
||||
export interface WatchListItemInput {
|
||||
identifierType: IdentifierType;
|
||||
identifierValue: string;
|
||||
}
|
||||
|
||||
export interface ScanTriggerInput {
|
||||
userId: string;
|
||||
source?: DataSource;
|
||||
}
|
||||
|
||||
export interface ExposureResult {
|
||||
dataSource: DataSource;
|
||||
breachName: string;
|
||||
exposedAt: Date;
|
||||
dataType: string[];
|
||||
severity: Severity;
|
||||
details: string;
|
||||
}
|
||||
|
||||
export interface AlertInput {
|
||||
userId: string;
|
||||
exposureId: string;
|
||||
severity: Severity;
|
||||
channel: AlertChannel;
|
||||
dedupKey: string;
|
||||
}
|
||||
8
packages/types/tsconfig.json
Normal file
8
packages/types/tsconfig.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
Reference in New Issue
Block a user