# 21. Backend Router — Security Report Generation meta: id: kordant-unified-restructure-21 feature: kordant-unified-restructure priority: P1 depends_on: [kordant-unified-restructure-20] tags: [backend, trpc, reports, pdf, api] objective: - Build the tRPC router for security report generation. Port logic from `packages/report/` and `packages/api/src/routes/report.routes.ts` into a unified `reports` router that generates branded PDF and HTML security reports. deliverables: - `web/src/server/api/routers/reports.ts` — Reports router: - `reports.getReports` — `protectedProcedure` returning user's generated reports - `reports.generateReport` — `protectedProcedure` triggering report generation - `reports.getReport` — `protectedProcedure` returning single report with download URL - `reports.deleteReport` — `protectedProcedure` deleting a report - `reports.getScheduledReports` — `protectedProcedure` returning scheduled report settings - `reports.updateSchedule` — `protectedProcedure` updating report schedule - `web/src/server/services/reports.service.ts` — Core business logic: - `generateReport(userId, reportType, periodStart, periodEnd)` — compile data and generate report: - Collect alerts, exposures, detections, changes for period - Calculate threat score trend - Generate HTML content - Convert to PDF - Save to storage and update DB - `getReports(userId, filters?)` — query generated reports - `deleteReport(userId, reportId)` — remove file and DB record - `getScheduledReports(userId)` — read schedule preferences - `updateSchedule(userId, schedule)` — write schedule preferences - `web/src/server/services/reports/generator.ts` — Report generator: - `compileData(userId, periodStart, periodEnd)` — aggregate data from all services - `renderHTML(data)` — generate branded HTML using template engine - `generatePDF(html)` — convert HTML to PDF using Puppeteer or PDFKit - `uploadPDF(userId, pdfBuffer, filename)` — save to storage, return URL - `web/src/server/services/reports/templates/` — HTML templates: - `monthly-plus.html` — Monthly report for Plus tier - `annual-premium.html` — Annual comprehensive report for Premium tier - `weekly-digest.html` — Weekly summary email format - Shared partials: header, footer, alert list, exposure table, trend chart steps: 1. Create `web/src/server/api/routers/reports.ts`. 2. Define Zod schemas: - `generateReportSchema`: `reportType: z.enum(['MONTHLY_PLUS', 'ANNUAL_PREMIUM', 'WEEKLY_DIGEST'])`, `periodStart: z.date().optional()`, `periodEnd: z.date().optional()` - `updateScheduleSchema`: `enabled: z.boolean()`, `frequency: z.enum(['weekly', 'monthly', 'quarterly'])`, `reportType: z.enum([...])` 3. Implement router procedures: - Report listing with pagination - Report generation (async, returns job ID or report ID) - Report retrieval with presigned download URL - Schedule CRUD 4. Create `web/src/server/services/reports.service.ts`: - Port from `packages/report/src/` - Implement report lifecycle: PENDING → GENERATING → COMPLETED/FAILED 5. Create report generator: - `compileData`: query normalized alerts, exposures, voice analyses, spam detections, property changes for the period - Calculate trends: compare current period to previous period - `renderHTML`: use Handlebars or EJS template engine with Kordant branding - `generatePDF`: use `puppeteer` (headless Chrome) for high-fidelity HTML-to-PDF, or `pdfkit` for programmatic generation - `uploadPDF`: save to local disk or S3/R2, generate presigned URL 6. Create HTML templates: - Design consistent report layout with Kordant colors and logo - Include: executive summary, threat score trend, alert breakdown by service, exposure details, recommendations - Make templates responsive for HTML email format 7. Implement scheduling: - Store schedule preferences in DB (may need new table or extend existing) - Background job (task 22) reads schedules and triggers generation 8. Wire router into `web/src/server/api/root.ts`. 9. Write unit tests for generator functions with mocked data. steps: - Unit: `compileData` aggregates correct data for a time period - Unit: `renderHTML` produces valid HTML with all sections - Unit: `generatePDF` creates readable PDF from HTML - Unit: `uploadPDF` saves file and returns accessible URL - Integration: tRPC `generateReport` creates report record and triggers generation acceptance_criteria: - [ ] Reports can be generated for weekly, monthly, and annual periods - [ ] Reports include data from all 5 services with trend analysis - [ ] PDF output is branded with Kordant colors and logo - [ ] HTML email format is responsive and readable - [ ] Report generation status is trackable (PENDING → COMPLETED) - [ ] Generated reports are stored securely with user-scoped access - [ ] Scheduled reports can be configured per user - [ ] Report deletion removes both file and DB record validation: - Generate a test report and verify PDF output - Open PDF and check branding, data accuracy, and readability - Test HTML email template by rendering in browser - Verify scheduled report configuration persists in DB - Run `cd web && pnpm test` for reports unit tests notes: - Reference legacy: `packages/report/src/`, `packages/api/src/routes/report.routes.ts` - Puppeteer adds significant dependency weight (~100MB Chromium). For serverless environments, consider: - `pdfkit` or `jsPDF` for lighter PDF generation (less HTML fidelity) - `@sparticuz/chromium` for serverless-compatible Puppeteer - Offloading PDF generation to a background worker with full Chromium - Report generation can be slow. Make the tRPC procedure return immediately with a report ID, and update status asynchronously. - For Premium tier, offer annual comprehensive reports. For Plus, monthly. For Basic, only on-demand. - Include actionable recommendations in reports (e.g., "Enable two-factor authentication", "Review exposed passwords"). - Consider adding a "share with advisor" feature that generates a shareable (but limited) report link.