- Create heatmap_service.py with all layer-building logic (coverage, threat-actor, detection-rules, campaign)
- Service is framework-agnostic: no FastAPI imports, no HTTPException, no db.commit()
- Fix N+1 in coverage and threat-actor layers: bulk-fetch test_counts and rule_counts with GROUP BY
- Router reduced from 528 to 140 lines: validates request, calls service, returns response