Files
Kordant/tasks/kordant-unified-restructure/17-spamshield-router.md
2026-05-25 22:49:37 -04:00

103 lines
6.2 KiB
Markdown

# 17. Backend Router — SpamShield (Spam Detection & Call Analysis)
meta:
id: kordant-unified-restructure-17
feature: kordant-unified-restructure
priority: P1
depends_on: [kordant-unified-restructure-12, kordant-unified-restructure-13, kordant-unified-restructure-14]
tags: [backend, trpc, spamshield, ml, api]
objective:
- Build the tRPC router for SpamShield, the spam detection and call analysis service. Port all logic from `services/spamshield/` and `packages/api/src/routes/spamshield.routes.ts` into a unified `spamshield` router and service layer.
deliverables:
- `web/src/server/api/routers/spamshield.ts` — SpamShield router:
- `spamshield.checkNumber``publicProcedure` (or API-key protected) checking phone number reputation
- `spamshield.classifySMS``publicProcedure` classifying SMS text as spam/ham
- `spamshield.classifyCall``publicProcedure` analyzing call metadata for spam likelihood
- `spamshield.getRules``protectedProcedure` returning user's spam rules
- `spamshield.createRule``protectedProcedure` creating a custom spam rule
- `spamshield.deleteRule``protectedProcedure` deleting a rule
- `spamshield.submitFeedback``protectedProcedure` submitting false positive/negative feedback
- `spamshield.getStats``protectedProcedure` returning spam detection statistics
- `web/src/server/services/spamshield.service.ts` — Core business logic:
- `checkNumberReputation(phoneNumber)` — query Hiya/Truecaller/other reputation APIs
- `classifySMS(text)` — run BERT-based spam classification
- `classifyCall(metadata)` — run rule engine + ML model on call data
- `createRule(userId, ruleType, pattern, action)` — save custom rule
- `applyRules(userId, phoneNumber, text?)` — evaluate custom rules against input
- `submitFeedback(userId, phoneNumber, isSpam, feedbackType)` — log feedback for model retraining
- `getStats(userId, period?)` — aggregate detection stats
- `web/src/server/services/spamshield/ml.engine.ts` — ML inference:
- `classifyTextBERT(text)` — BERT model inference for SMS spam
- `extractFeatures(metadata)` — feature extraction for call analysis
- `ruleEngine(rules, input)` — evaluate user-defined and global rules
- `web/src/server/services/spamshield/reputation.api.ts` — External reputation lookups:
- `lookupHiya(phoneNumber)` — Hiya API
- `lookupTruecaller(phoneNumber)` — Truecaller API
- `lookupInternalDB(phoneNumber)` — query cached reputation scores
steps:
1. Create `web/src/server/api/routers/spamshield.ts`.
2. Define Zod schemas:
- `checkNumberSchema`: `phoneNumber: z.string()` (E.164 format validation)
- `classifySMSSchema`: `text: z.string().max(2000)`
- `classifyCallSchema`: `callerNumber: z.string()`, `duration: z.number().optional()`, `timeOfDay: z.number().optional()`
- `createRuleSchema`: `ruleType: z.enum([...])`, `pattern: z.string()`, `action: z.enum([...])`, `priority: z.number().default(0)`
- `feedbackSchema`: `phoneNumber: z.string()`, `isSpam: z.boolean()`, `feedbackType: z.enum([...])`
3. Implement router procedures:
- Number reputation check (may be called by extension or mobile apps)
- SMS and call classification
- Rule CRUD with user scoping
- Feedback submission
4. Create `web/src/server/services/spamshield.service.ts`:
- Port from `services/spamshield/src/`
- Implement number normalization (E.164)
- Implement reputation caching (Redis or in-memory with TTL)
5. Create ML engine:
- `classifyTextBERT`: placeholder for BERT model. If not available in JS, create a Python bridge or use a pre-trained ONNX model.
- `extractFeatures`: derive features from call metadata (time patterns, area code, duration)
- `ruleEngine`: evaluate regex patterns, area code blocks, prefix blocks, reputation scores
6. Create reputation API module:
- Implement circuit breaker for external APIs (reference legacy `services/spamshield/test/circuit-breaker.test.ts`)
- Cache results in DB or Redis for 24 hours
- Fallback to internal database if external APIs fail
7. Implement audit logging:
- Every classification decision is logged to `AuditLog` table
- Include input, output, confidence, model version, timestamp
8. Wire router into `web/src/server/api/root.ts`.
9. Write unit tests with mocked ML engine and reputation APIs.
steps:
- Unit: `checkNumberReputation` normalizes phone and queries APIs with circuit breaker
- Unit: `classifySMS` returns spam/ham with confidence
- Unit: `ruleEngine` evaluates custom rules correctly
- Unit: `submitFeedback` creates feedback record
- Unit: Audit logging captures all classification decisions
- Integration: tRPC `checkNumber` returns reputation for valid E.164 number
acceptance_criteria:
- [ ] Phone numbers are normalized to E.164 before processing
- [ ] Number reputation checks query external APIs with circuit breaker and caching
- [ ] SMS classification returns spam/ham verdict with confidence score
- [ ] Call analysis evaluates rules and ML model
- [ ] Users can create, list, and delete custom spam rules
- [ ] Feedback submissions are logged for model improvement
- [ ] All classification decisions are audit-logged
- [ ] Stats endpoint returns aggregated detection metrics per user
validation:
- Call `spamshield.checkNumber` with a test phone number → verify reputation response
- Call `spamshield.classifySMS` with known spam text → verify high spam score
- Create a custom rule and verify it blocks matching numbers
- Submit feedback and verify record created in DB
- Run `cd web && pnpm test` for SpamShield unit tests
notes:
- Reference legacy: `services/spamshield/src/`, `packages/api/src/routes/spamshield.routes.ts`
- The BERT model for SMS classification may require Python. Use the same approach as VoicePrint: pluggable ML engine with Python bridge or ONNX.
- Hiya and Truecaller APIs require commercial agreements. For development, mock these or use free alternatives like NumVerify.
- The `checkNumber` endpoint may receive high traffic from the browser extension. Ensure it is rate-limited and cached aggressively.
- Consider adding a global spam database that accumulates feedback from all users (anonymized) to improve detection.
- The rule engine should support both user-specific rules and global admin rules.