5.9 KiB
5.9 KiB
15. Backend Router — DarkWatch (Dark Web Monitoring)
meta: id: kordant-unified-restructure-15 feature: kordant-unified-restructure priority: P1 depends_on: [kordant-unified-restructure-12, kordant-unified-restructure-13, kordant-unified-restructure-14] tags: [backend, trpc, darkwatch, security, api]
objective:
- Build the tRPC router for DarkWatch, the dark web monitoring service. Port all logic from
services/darkwatch/andpackages/api/src/routes/darkwatch.routes.tsinto a unifieddarkwatchrouter and service layer.
deliverables:
web/src/server/api/routers/darkwatch.ts— DarkWatch router:darkwatch.getWatchlist—protectedProcedurereturning user's watchlist itemsdarkwatch.addWatchlistItem—protectedProcedureadding email/phone/SSN/domain to watchlistdarkwatch.removeWatchlistItem—protectedProcedureremoving itemdarkwatch.getExposures—protectedProcedurereturning detected exposuresdarkwatch.getExposureDetails—protectedProcedurereturning single exposure with metadatadarkwatch.runScan—protectedProceduretriggering manual scan (respects tier limits)darkwatch.getScanStatus—protectedProcedurechecking scan progressdarkwatch.getReports—protectedProcedurereturning generated PDF reports
web/src/server/services/darkwatch.service.ts— Core business logic:addWatchlistItem(userId, type, value)— hash value, deduplicate, save to DBremoveWatchlistItem(userId, itemId)— delete and cascadegetExposures(userId, filters?)— query exposures with pagination, sortingrunScan(userId)— orchestrate multi-source scan:- HIBP breach check
- SecurityTrails lookup
- Censys/Shodan queries
- Dark web forum scraping (where applicable)
generateReport(userId, periodStart, periodEnd)— compile exposures into PDF reportcheckTierLimits(userId)— verify scan frequency against subscription tier
web/src/server/services/darkwatch/scan.engine.ts— Scan orchestration:scanHIBP(email)— query Have I Been Pwned APIscanSecurityTrails(identifier)— query SecurityTrails APIscanCensys(query)— query Censys APIscanShodan(query)— query Shodan APIscanForums(identifier)— placeholder for forum scraping logic
web/src/server/services/darkwatch/alert.pipeline.ts— Exposure-to-alert pipeline:processExposure(exposure)— severity scoring, deduplication, alert creationseverityScore(exposure)— calculate severity based on source, data type, recurrence
steps:
- Create
web/src/server/api/routers/darkwatch.ts. - Define Zod schemas:
addWatchlistItemSchema:type: z.enum(['email', 'phoneNumber', 'ssn', 'address', 'domain']),value: z.string()exposureFilterSchema:severity: z.enum(['info', 'warning', 'critical']).optional(),source: z.enum([...]).optional(),page: z.number().default(1),limit: z.number().default(20)
- Implement router procedures:
- Watchlist CRUD with user ownership checks
- Exposure queries with filtering and pagination
- Manual scan with tier limit enforcement
- Create
web/src/server/services/darkwatch.service.ts:- Port logic from
services/darkwatch/src/watchlist.service.ts - Port logic from
services/darkwatch/src/scan.service.ts - Port logic from
services/darkwatch/src/alert.pipeline.ts
- Port logic from
- Create scan engine modules:
- Each scanner is a function that takes an identifier and returns raw results
- Use environment variables for API keys (
HIBP_API_KEY,SECURITYTRAILS_API_KEY, etc.) - Implement circuit breaker pattern for external APIs (reference
services/spamshield/test/circuit-breaker.test.ts)
- Create alert pipeline:
processExposurecreates or updatesExposurerecord- If new or severity increased, create
Alertrecord and trigger notification (via task 14 service) - Deduplicate based on
identifierHashandsource
- Implement tier limit checks:
- Basic: 1 manual scan/month
- Plus: 1 manual scan/week
- Premium: unlimited + real-time monitoring
- Wire router into
web/src/server/api/root.ts. - Write unit tests for service functions with mocked external APIs.
steps:
- Unit:
addWatchlistItemhashes and deduplicates values - Unit:
runScancalls all scan engines and aggregates results - Unit:
severityScorereturns correct severity for different exposure types - Unit:
checkTierLimitsenforces scan frequency correctly - Unit: Alert pipeline creates alert only for new/high-severity exposures
- Integration: tRPC procedures enforce user ownership
acceptance_criteria:
- Watchlist items can be added, listed, and removed per user
- Exposures are queryable with filtering and pagination
- Manual scan orchestrates all data sources and creates exposure records
- Tier limits prevent excessive scanning based on subscription level
- Alert pipeline creates notifications for new/high-severity exposures
- External API failures are handled gracefully (circuit breaker, retries)
- All user data is properly scoped (users cannot see other users' exposures)
validation:
- Add a test watchlist item, run manual scan, verify exposure records created
- Check that exceeding tier limit returns appropriate error
- Simulate HIBP API failure and verify circuit breaker opens
- Run
cd web && pnpm testfor DarkWatch unit tests
notes:
- Reference legacy:
services/darkwatch/src/,packages/api/src/routes/darkwatch.routes.ts - The HIBP API requires an API key for breach lookups. Store in
HIBP_API_KEY. - SecurityTrails, Censys, and Shodan also require API keys. Document all required env vars.
- SSN values should be hashed before storage (already in schema). Never log raw SSNs.
- The scan engine should be designed to run both synchronously (manual scan) and asynchronously (scheduled scans via task 22).
- Consider rate-limiting the
runScanendpoint independently to prevent abuse.