coverme-scanner 1.3.3 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1630,6 +1630,187 @@ The final report should ONLY contain findings that are:
1630
1630
  }
1631
1631
  },
1632
1632
 
1633
+ "architectureOverview": {
1634
+ "components": [
1635
+ {
1636
+ "name": "API Server",
1637
+ "type": "service",
1638
+ "description": "Express.js REST API handling all client requests",
1639
+ "trustLevel": "semi-trusted"
1640
+ },
1641
+ {
1642
+ "name": "PostgreSQL",
1643
+ "type": "database",
1644
+ "description": "Primary data store for user and application data",
1645
+ "trustLevel": "trusted"
1646
+ },
1647
+ {
1648
+ "name": "Redis",
1649
+ "type": "cache",
1650
+ "description": "Session storage and rate limiting",
1651
+ "trustLevel": "trusted"
1652
+ },
1653
+ {
1654
+ "name": "External Payment API",
1655
+ "type": "external",
1656
+ "description": "Third-party payment processor",
1657
+ "trustLevel": "untrusted"
1658
+ }
1659
+ ],
1660
+ "trustBoundaries": [
1661
+ {
1662
+ "name": "Client to API",
1663
+ "from": "Browser/Mobile",
1664
+ "to": "API Server",
1665
+ "protocol": "HTTPS"
1666
+ },
1667
+ {
1668
+ "name": "API to Database",
1669
+ "from": "API Server",
1670
+ "to": "PostgreSQL",
1671
+ "protocol": "TLS"
1672
+ }
1673
+ ],
1674
+ "criticalAssets": [
1675
+ {
1676
+ "name": "User Credentials",
1677
+ "type": "credential",
1678
+ "location": "PostgreSQL users table",
1679
+ "protection": "bcrypt hashed"
1680
+ },
1681
+ {
1682
+ "name": "API Keys",
1683
+ "type": "key",
1684
+ "location": "Environment variables",
1685
+ "protection": "Encrypted at rest"
1686
+ },
1687
+ {
1688
+ "name": "Session Tokens",
1689
+ "type": "token",
1690
+ "location": "Redis",
1691
+ "protection": "HMAC signed"
1692
+ }
1693
+ ],
1694
+ "dataFlows": [
1695
+ "User Authentication Flow",
1696
+ "Payment Processing Flow",
1697
+ "Data Export Flow"
1698
+ ]
1699
+ },
1700
+
1701
+ "threatModel": [
1702
+ {
1703
+ "id": "T-001",
1704
+ "threat": "SQL Injection via user input",
1705
+ "category": "STRIDE",
1706
+ "strideType": "T",
1707
+ "status": "open",
1708
+ "relatedFindings": ["SEC-001", "DB-002"],
1709
+ "mitigation": "Use parameterized queries",
1710
+ "dreadScore": 8.5
1711
+ },
1712
+ {
1713
+ "id": "T-002",
1714
+ "threat": "Session hijacking via XSS",
1715
+ "category": "STRIDE",
1716
+ "strideType": "S",
1717
+ "status": "partial",
1718
+ "relatedFindings": ["SEC-003"],
1719
+ "mitigation": "CSP headers implemented but not comprehensive",
1720
+ "dreadScore": 7.2
1721
+ },
1722
+ {
1723
+ "id": "T-003",
1724
+ "threat": "Unauthorized data access",
1725
+ "category": "LINDDUN",
1726
+ "status": "mitigated",
1727
+ "relatedFindings": [],
1728
+ "mitigation": "Row-level security implemented",
1729
+ "dreadScore": 3.0
1730
+ }
1731
+ ],
1732
+
1733
+ "qualityReview": {
1734
+ "deleteItems": [
1735
+ {
1736
+ "type": "delete",
1737
+ "file": "src/utils/oldHelpers.ts",
1738
+ "lines": 250,
1739
+ "description": "Entire file is dead code - functions never called",
1740
+ "reason": "No imports found in codebase"
1741
+ },
1742
+ {
1743
+ "type": "delete",
1744
+ "file": "src/legacy/auth.js",
1745
+ "lines": 180,
1746
+ "description": "Legacy auth implementation replaced by Clerk",
1747
+ "reason": "Migration completed 6 months ago"
1748
+ }
1749
+ ],
1750
+ "mergeItems": [
1751
+ {
1752
+ "type": "merge",
1753
+ "file": "src/utils/validate.ts, src/helpers/validation.ts",
1754
+ "description": "Two files with overlapping validation functions",
1755
+ "reason": "DRY violation - consolidate into single module"
1756
+ }
1757
+ ],
1758
+ "simplifyItems": [
1759
+ {
1760
+ "type": "simplify",
1761
+ "file": "src/services/payment.ts",
1762
+ "lines": 450,
1763
+ "description": "Overly complex payment flow with excessive error handling",
1764
+ "reason": "Can be reduced to ~200 lines with proper abstraction"
1765
+ }
1766
+ ],
1767
+ "totalLinesRemovable": 680,
1768
+ "percentageOfCodebase": 4.2
1769
+ },
1770
+
1771
+ "actionItems": [
1772
+ {
1773
+ "id": "A-001",
1774
+ "title": "Fix SQL injection in user search",
1775
+ "priority": "immediate",
1776
+ "relatedFindings": ["SEC-001"],
1777
+ "effort": "low",
1778
+ "description": "Replace string concatenation with parameterized query"
1779
+ },
1780
+ {
1781
+ "id": "A-002",
1782
+ "title": "Implement rate limiting on auth endpoints",
1783
+ "priority": "immediate",
1784
+ "relatedFindings": ["AUTH-003"],
1785
+ "effort": "medium",
1786
+ "description": "Add Redis-based rate limiter to /login and /register"
1787
+ },
1788
+ {
1789
+ "id": "A-003",
1790
+ "title": "Add CSP headers",
1791
+ "priority": "high",
1792
+ "relatedFindings": ["SEC-005"],
1793
+ "effort": "low",
1794
+ "description": "Configure helmet with strict CSP policy"
1795
+ },
1796
+ {
1797
+ "id": "A-004",
1798
+ "title": "Clean up dead code",
1799
+ "priority": "medium",
1800
+ "relatedFindings": ["DEAD-001", "DEAD-002"],
1801
+ "effort": "medium",
1802
+ "description": "Remove 680 lines of unused code identified in quality review"
1803
+ },
1804
+ {
1805
+ "id": "A-005",
1806
+ "title": "Implement audit logging",
1807
+ "priority": "long-term",
1808
+ "relatedFindings": ["DATA-002"],
1809
+ "effort": "high",
1810
+ "description": "Add comprehensive audit trail for sensitive operations"
1811
+ }
1812
+ ],
1813
+
1633
1814
  "summary": {
1634
1815
  "total": 10,
1635
1816
  "critical": 1,
@@ -1638,17 +1819,42 @@ The final report should ONLY contain findings that are:
1638
1819
  "low": 2,
1639
1820
  "info": 0,
1640
1821
  "mitigatedCount": 5,
1641
- "falsePositiveCount": 3
1822
+ "falsePositiveCount": 3,
1823
+ "avgConfidence": 0.85
1642
1824
  },
1643
1825
 
1644
1826
  "findings": [
1645
1827
  {
1646
1828
  "id": "SEC-001",
1647
- "title": "Example finding",
1648
- "severity": "high",
1829
+ "title": "SQL Injection in User Search",
1830
+ "severity": "critical",
1831
+ "category": "security",
1832
+ "file": "src/routes/users.ts",
1833
+ "line": 45,
1834
+ "code": "db.query(`SELECT * FROM users WHERE name LIKE '%${searchTerm}%'`)",
1835
+ "description": "User search parameter is directly concatenated into SQL query without sanitization",
1836
+ "impact": "Attacker can extract entire database contents, modify data, or execute system commands",
1837
+ "attackChain": [
1838
+ {"step": 1, "action": "Send malicious search term: ' OR '1'='1' --", "result": "Query returns all users"},
1839
+ {"step": 2, "action": "Use UNION SELECT to extract data from other tables", "result": "Database schema exposed"},
1840
+ {"step": 3, "action": "Extract password hashes and sensitive data", "result": "Full data breach"}
1841
+ ],
1842
+ "recommendation": "Use parameterized queries: db.query('SELECT * FROM users WHERE name LIKE $1', [`%${searchTerm}%`])",
1843
+ "cwe": "CWE-89",
1844
+ "owasp": "A03:2021",
1845
+ "dreadScore": {
1846
+ "damage": 10,
1847
+ "reproducibility": 10,
1848
+ "exploitability": 9,
1849
+ "affectedUsers": 10,
1850
+ "discoverability": 8,
1851
+ "total": 9.4
1852
+ },
1853
+ "status": "open",
1854
+ "crossReferences": ["T-001"],
1855
+ "confidence": 95,
1649
1856
  "fixOwner": "developer",
1650
- "fixType": "code",
1651
- "...": "other fields"
1857
+ "fixType": "code"
1652
1858
  }
1653
1859
  ],
1654
1860
 
@@ -1682,8 +1888,22 @@ The final report should ONLY contain findings that are:
1682
1888
  ],
1683
1889
 
1684
1890
  "positiveObservations": [
1685
- "Good pattern 1",
1686
- "Good pattern 2"
1891
+ {
1892
+ "title": "Strong Authentication Implementation",
1893
+ "description": "Clerk integration with proper session management, MFA support, and secure cookie settings"
1894
+ },
1895
+ {
1896
+ "title": "Comprehensive Input Validation",
1897
+ "description": "Zod schemas used consistently across API endpoints with proper error handling"
1898
+ },
1899
+ {
1900
+ "title": "Secure Database Access",
1901
+ "description": "Prisma ORM with parameterized queries, preventing SQL injection in core modules"
1902
+ },
1903
+ {
1904
+ "title": "Good Error Handling Patterns",
1905
+ "description": "Errors are caught and logged without exposing internal details to clients"
1906
+ }
1687
1907
  ],
1688
1908
 
1689
1909
  "validationSummary": {
@@ -56,6 +56,30 @@ interface ExecutiveSummaryData {
56
56
  architect?: number;
57
57
  };
58
58
  }
59
+ interface ScanStats {
60
+ filesScanned: number;
61
+ linesOfCode: number;
62
+ agentCount: number;
63
+ avgConfidence: number;
64
+ }
65
+ interface QualityReviewData {
66
+ deleteItems: Array<{
67
+ file: string;
68
+ lines: number;
69
+ description: string;
70
+ }>;
71
+ mergeItems: Array<{
72
+ file: string;
73
+ description: string;
74
+ }>;
75
+ simplifyItems: Array<{
76
+ file: string;
77
+ description: string;
78
+ }>;
79
+ totalLinesRemovable: number;
80
+ percentageOfCodebase: number;
81
+ totalItems: number;
82
+ }
59
83
  interface ReportData {
60
84
  projectName: string;
61
85
  scanDate: string;
@@ -97,6 +121,9 @@ interface ReportData {
97
121
  architectureOverviewHtml: string;
98
122
  threatModelHtml: string;
99
123
  actionItemsHtml: string;
124
+ scanStats?: ScanStats;
125
+ projectTree?: string;
126
+ qualityReview?: QualityReviewData;
100
127
  }
101
128
  export declare function calculateScore(result: ScanResult): {
102
129
  grade: string;
@@ -116,5 +143,11 @@ export declare function generateHtmlReport(result: ScanResult, outputPath: strin
116
143
  file?: string;
117
144
  rejectionReason: string;
118
145
  }>): Promise<void>;
146
+ export declare function generateProfessionalPdf(result: ScanResult, outputPath: string, falsePositives?: Array<{
147
+ id: string;
148
+ title: string;
149
+ file?: string;
150
+ rejectionReason: string;
151
+ }>): Promise<void>;
119
152
  export {};
120
153
  //# sourceMappingURL=generator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/report/generator.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAY,MAAM,aAAa,CAAC;AAE1E,UAAU,SAAS;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,gBAAgB,EAAE,CAAC;CAC9B;AAED,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,gBAAgB,EAAE,CAAC;CAC9B;AAED,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,gBAAgB,EAAE,CAAC;CAC9B;AAED,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,oBAAoB;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,kBAAkB,CAAC,EAAE,KAAK,CAAC;QACzB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;IACH,OAAO,CAAC,EAAE;QACR,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED,UAAU,UAAU;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,gBAAgB,EAAE,gBAAgB,EAAE,CAAC;IACrC,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,cAAc,EAAE,gBAAgB,EAAE,CAAC;IACnC,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,gBAAgB,EAAE,eAAe,EAAE,CAAC;IACpC,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7F,kBAAkB,EAAE,MAAM,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,oBAAoB,EAAE,CAAC,MAAM,GAAG;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,CAAC;IAC5E,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IAEnB,wBAAwB,EAAE,MAAM,CAAC;IACjC,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;CACzB;AA2BD,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CA0BnF;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAkBnE;AA6bD,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,CAuB7E;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,UAAU,EAClB,UAAU,EAAE,MAAM,EAClB,cAAc,GAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,CAAM,GAChG,OAAO,CAAC,IAAI,CAAC,CAoFf;AAED,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,UAAU,EAClB,UAAU,EAAE,MAAM,EAClB,cAAc,GAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,CAAM,GAChG,OAAO,CAAC,IAAI,CAAC,CA8Df"}
1
+ {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/report/generator.ts"],"names":[],"mappings":"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"}
@@ -41,6 +41,7 @@ exports.generateExecutiveSummary = generateExecutiveSummary;
41
41
  exports.renderTemplate = renderTemplate;
42
42
  exports.generatePdfReport = generatePdfReport;
43
43
  exports.generateHtmlReport = generateHtmlReport;
44
+ exports.generateProfessionalPdf = generateProfessionalPdf;
44
45
  const fs = __importStar(require("fs"));
45
46
  const path = __importStar(require("path"));
46
47
  const puppeteer_1 = __importDefault(require("puppeteer"));
@@ -616,6 +617,33 @@ async function generateHtmlReport(result, outputPath, falsePositives = []) {
616
617
  const typeGroups = createTypeGroups(result.findings);
617
618
  const codeGroup = typeGroups.find(g => g.type === 'code');
618
619
  const devopsGroup = typeGroups.find(g => g.type === 'devops');
620
+ // Prepare scan statistics
621
+ const scanStats = (result.filesScanned || result.linesOfCode) ? {
622
+ filesScanned: result.filesScanned || 0,
623
+ linesOfCode: result.linesOfCode || 0,
624
+ agentCount: result.agentsUsed?.length || 0,
625
+ avgConfidence: Math.round((result.summary?.avgConfidence || 0) * 100),
626
+ } : undefined;
627
+ // Prepare quality review data
628
+ const qr = result.qualityReview;
629
+ const qualityReview = qr ? {
630
+ deleteItems: qr.deleteItems?.map(i => ({
631
+ file: i.file,
632
+ lines: i.lines || 0,
633
+ description: i.description,
634
+ })) || [],
635
+ mergeItems: qr.mergeItems?.map(i => ({
636
+ file: i.file,
637
+ description: i.description,
638
+ })) || [],
639
+ simplifyItems: qr.simplifyItems?.map(i => ({
640
+ file: i.file,
641
+ description: i.description,
642
+ })) || [],
643
+ totalLinesRemovable: qr.totalLinesRemovable || 0,
644
+ percentageOfCodebase: qr.percentageOfCodebase || 0,
645
+ totalItems: (qr.deleteItems?.length || 0) + (qr.mergeItems?.length || 0) + (qr.simplifyItems?.length || 0),
646
+ } : undefined;
619
647
  const data = {
620
648
  projectName: result.projectName,
621
649
  scanDate: new Date(result.scanDate).toLocaleDateString('en-US', {
@@ -654,9 +682,248 @@ async function generateHtmlReport(result, outputPath, falsePositives = []) {
654
682
  architectureOverviewHtml: generateArchitectureOverviewHtml(result),
655
683
  threatModelHtml: generateThreatModelHtml(result),
656
684
  actionItemsHtml: generateActionItemsHtml(result),
685
+ // New scan statistics and quality review
686
+ scanStats,
687
+ projectTree: result.projectTree,
688
+ qualityReview,
657
689
  };
658
690
  const renderedHtml = renderTemplate(templateHtml, data);
659
691
  fs.writeFileSync(outputPath, renderedHtml);
660
692
  console.log(`HTML report generated: ${outputPath}`);
661
693
  }
694
+ function formatDreadScore(score) {
695
+ if (!score)
696
+ return 'N/A';
697
+ return score.total.toFixed(2);
698
+ }
699
+ function getRiskLevel(result) {
700
+ const counts = getSeverityCounts(result.summary);
701
+ if (counts.critical > 0)
702
+ return 'CRITICAL';
703
+ if (counts.high > 0)
704
+ return 'HIGH';
705
+ if (counts.medium > 0)
706
+ return 'MEDIUM';
707
+ return 'LOW';
708
+ }
709
+ function enhanceFinding(f) {
710
+ return {
711
+ ...f,
712
+ dreadTotal: formatDreadScore(f.dreadScore),
713
+ };
714
+ }
715
+ async function generateProfessionalPdf(result, outputPath, falsePositives = []) {
716
+ const templatePath = path.join(__dirname, '..', 'templates', 'report-pdf.html');
717
+ const templateHtml = fs.readFileSync(templatePath, 'utf-8');
718
+ const counts = getSeverityCounts(result.summary);
719
+ const riskLevel = getRiskLevel(result);
720
+ const { grade, value } = calculateScore(result);
721
+ // Prepare findings with enhanced data
722
+ const criticalFindings = result.findings.filter(f => f.severity === 'critical').map(enhanceFinding);
723
+ const highFindings = result.findings.filter(f => f.severity === 'high').map(enhanceFinding);
724
+ const mediumFindings = result.findings.filter(f => f.severity === 'medium').map(enhanceFinding);
725
+ const lowFindings = result.findings.filter(f => f.severity === 'low' || f.severity === 'info').map(enhanceFinding);
726
+ // Prepare executive summary data
727
+ const execSummary = result.executiveSummary;
728
+ const topRisks = typeof execSummary === 'object' && execSummary?.topRisks
729
+ ? execSummary.topRisks
730
+ : criticalFindings.slice(0, 3).map(f => f.title);
731
+ const keyPositives = typeof execSummary === 'object' && execSummary?.positives
732
+ ? execSummary.positives
733
+ : (result.positiveObservations || []).slice(0, 3).map(o => typeof o === 'string' ? o : o.title || o.description || '');
734
+ // Prepare architecture data
735
+ const arch = result.architectureOverview;
736
+ const architectureComponents = arch?.components?.map(c => ({
737
+ name: c.name,
738
+ type: c.type,
739
+ description: c.description,
740
+ trustLevel: c.trustLevel,
741
+ })) || [];
742
+ const criticalAssets = arch?.criticalAssets?.map(a => ({
743
+ name: a.name,
744
+ type: a.type,
745
+ location: a.location,
746
+ })) || [];
747
+ const entryPoints = arch?.dataFlows || [];
748
+ // Prepare threat model
749
+ const threatModelEntries = result.threatModel?.map(t => ({
750
+ id: t.id,
751
+ threat: t.threat,
752
+ category: t.category,
753
+ strideType: t.strideType,
754
+ status: t.status,
755
+ dreadScore: t.dreadScore,
756
+ relatedFindings: t.relatedFindings?.join(', ') || '',
757
+ })) || [];
758
+ // Prepare quality review
759
+ const qr = result.qualityReview;
760
+ const qualityReview = {
761
+ deleteItems: qr?.deleteItems?.map(i => ({
762
+ file: i.file,
763
+ lines: i.lines || 0,
764
+ description: i.description,
765
+ })) || [],
766
+ mergeItems: qr?.mergeItems?.map(i => ({
767
+ files: i.file,
768
+ description: i.description,
769
+ })) || [],
770
+ simplifyItems: qr?.simplifyItems?.map(i => ({
771
+ file: i.file,
772
+ description: i.description,
773
+ })) || [],
774
+ totalLinesRemovable: qr?.totalLinesRemovable || 0,
775
+ percentageOfCodebase: qr?.percentageOfCodebase || 0,
776
+ };
777
+ // Prepare action items
778
+ const actions = result.actionItems || [];
779
+ const mapActions = (items) => items.map(a => ({
780
+ id: a.id,
781
+ title: a.title,
782
+ effort: a.effort,
783
+ relatedFindings: a.relatedFindings?.join(', ') || '',
784
+ }));
785
+ const immediateActions = mapActions(actions.filter(a => a.priority === 'immediate'));
786
+ const highPriorityActions = mapActions(actions.filter(a => a.priority === 'high'));
787
+ const mediumPriorityActions = mapActions(actions.filter(a => a.priority === 'medium'));
788
+ const longTermActions = mapActions(actions.filter(a => a.priority === 'long-term'));
789
+ // Prepare positive observations
790
+ const positiveObservations = (result.positiveObservations || []).map(o => {
791
+ if (typeof o === 'string') {
792
+ return { title: o, description: '' };
793
+ }
794
+ return { title: o.title || '', description: o.description || '' };
795
+ });
796
+ // Prepare project overview
797
+ const projOverview = result.projectOverview;
798
+ const projectType = projOverview?.type || 'Application';
799
+ const projectDescription = projOverview?.purpose || '';
800
+ const stack = projOverview?.stack?.join(', ') || '';
801
+ const componentsText = projOverview?.keyComponents?.join(', ') || '';
802
+ // Prepare trust boundaries and assets as strings for display
803
+ const trustBoundariesText = arch?.trustBoundaries?.map(b => `${b.from} -> ${b.to} (${b.protocol || 'N/A'})`).join(', ') || '';
804
+ const criticalAssetsText = arch?.criticalAssets?.map(a => `${a.name} (${a.type})`).join(', ') || '';
805
+ const entryPointsText = entryPoints.join(', ') || '';
806
+ // Quality review with total items count
807
+ const qualityReviewWithTotals = {
808
+ ...qualityReview,
809
+ totalItems: (qualityReview.deleteItems?.length || 0) +
810
+ (qualityReview.mergeItems?.length || 0) +
811
+ (qualityReview.simplifyItems?.length || 0),
812
+ };
813
+ // Generate executive summary HTML
814
+ const execSummaryText = generateExecutiveSummary(result);
815
+ const executiveSummaryHtml = `<p>${execSummaryText}</p>`;
816
+ // Cover description
817
+ const coverDescription = projectDescription ||
818
+ `Security assessment covering ${result.filesScanned || 0} files with ${result.findings?.length || 0} findings identified.`;
819
+ const data = {
820
+ projectName: result.projectName,
821
+ scanDate: new Date(result.scanDate).toLocaleDateString('en-US', {
822
+ year: 'numeric',
823
+ month: 'long',
824
+ day: 'numeric',
825
+ }),
826
+ scanDateFull: new Date(result.scanDate).toISOString(),
827
+ branch: result.branch,
828
+ commit: result.commit?.substring(0, 8),
829
+ scope: 'Full Security Assessment',
830
+ assessedBy: 'CoverMe Security Scanner',
831
+ version: '2.0',
832
+ // Project Overview
833
+ projectType,
834
+ projectDescription,
835
+ stack,
836
+ componentsText,
837
+ coverDescription,
838
+ // Project Tree and Lines of Code
839
+ projectTree: result.projectTree,
840
+ linesOfCode: result.linesOfCode || 0,
841
+ // Severity counts
842
+ criticalCount: counts.critical,
843
+ highCount: counts.high,
844
+ mediumCount: counts.medium,
845
+ lowCount: counts.low,
846
+ infoCount: counts.info,
847
+ totalFindings: result.findings?.length || 0,
848
+ // Risk
849
+ riskScore: `${grade.toUpperCase()} (${value}/100)`,
850
+ riskLevel,
851
+ // Executive Summary
852
+ executiveSummary: execSummaryText,
853
+ executiveSummaryHtml,
854
+ topRisks,
855
+ keyPositives,
856
+ // Architecture
857
+ architectureComponents,
858
+ criticalAssets: criticalAssetsText,
859
+ trustBoundaries: trustBoundariesText,
860
+ entryPoints: entryPointsText,
861
+ // Findings
862
+ criticalFindings,
863
+ highFindings,
864
+ mediumFindings,
865
+ lowFindings,
866
+ // Threat Model
867
+ threatModel: threatModelEntries,
868
+ // Quality Review
869
+ qualityReview: qualityReviewWithTotals,
870
+ // Resolved Issues (empty for now, can be populated from scan results)
871
+ resolvedIssues: [],
872
+ // Action Items
873
+ immediateActions,
874
+ highPriorityActions,
875
+ mediumPriorityActions,
876
+ longTermActions,
877
+ // Positive Observations
878
+ positiveObservations,
879
+ // Stats
880
+ filesScanned: result.filesScanned || 0,
881
+ agentCount: result.agentsUsed?.length || 0,
882
+ scanDuration: `${Math.round((result.scanDuration || 0) / 1000)} seconds`,
883
+ avgConfidence: Math.round((result.summary?.avgConfidence || 0) * 100),
884
+ };
885
+ // Register Handlebars helpers
886
+ handlebars_1.default.registerHelper('eq', (a, b) => a === b);
887
+ handlebars_1.default.registerHelper('gt', (a, b) => a > b);
888
+ handlebars_1.default.registerHelper('gte', (a, b) => a >= b);
889
+ handlebars_1.default.registerHelper('lt', (a, b) => a < b);
890
+ handlebars_1.default.registerHelper('add', (a, b) => a + b);
891
+ handlebars_1.default.registerHelper('toFixed', (n, digits) => n?.toFixed(digits) || 'N/A');
892
+ const template = handlebars_1.default.compile(templateHtml);
893
+ const renderedHtml = template(data);
894
+ // Generate PDF with proper pagination
895
+ const browser = await puppeteer_1.default.launch({
896
+ headless: true,
897
+ args: ['--no-sandbox', '--disable-setuid-sandbox'],
898
+ });
899
+ const page = await browser.newPage();
900
+ await page.setContent(renderedHtml, { waitUntil: 'networkidle0' });
901
+ // A4 PDF with proper page breaks
902
+ await page.pdf({
903
+ path: outputPath,
904
+ format: 'A4',
905
+ margin: {
906
+ top: '20mm',
907
+ right: '15mm',
908
+ bottom: '20mm',
909
+ left: '15mm',
910
+ },
911
+ printBackground: true,
912
+ displayHeaderFooter: true,
913
+ headerTemplate: `
914
+ <div style="width: 100%; font-size: 9px; color: #666; padding: 0 15mm; display: flex; justify-content: space-between;">
915
+ <span>${escapeHtml(result.projectName)} - Security Assessment</span>
916
+ <span>CONFIDENTIAL</span>
917
+ </div>
918
+ `,
919
+ footerTemplate: `
920
+ <div style="width: 100%; font-size: 9px; color: #666; padding: 0 15mm; display: flex; justify-content: space-between;">
921
+ <span>Generated by CoverMe Security Scanner</span>
922
+ <span>Page <span class="pageNumber"></span> of <span class="totalPages"></span></span>
923
+ </div>
924
+ `,
925
+ });
926
+ await browser.close();
927
+ console.log(`Professional PDF report generated: ${outputPath}`);
928
+ }
662
929
  //# sourceMappingURL=generator.js.map