106 lines
6.0 KiB
Markdown
106 lines
6.0 KiB
Markdown
# 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.
|