verification-layer 0.20.0 → 0.22.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.
Files changed (180) hide show
  1. package/README.md +251 -615
  2. package/dist/cli.js +542 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/marketplace/index.d.ts +8 -0
  5. package/dist/marketplace/index.d.ts.map +1 -0
  6. package/dist/marketplace/index.js +7 -0
  7. package/dist/marketplace/index.js.map +1 -0
  8. package/dist/marketplace/installer.d.ts +62 -0
  9. package/dist/marketplace/installer.d.ts.map +1 -0
  10. package/dist/marketplace/installer.js +254 -0
  11. package/dist/marketplace/installer.js.map +1 -0
  12. package/dist/marketplace/registry.d.ts +52 -0
  13. package/dist/marketplace/registry.d.ts.map +1 -0
  14. package/dist/marketplace/registry.js +759 -0
  15. package/dist/marketplace/registry.js.map +1 -0
  16. package/dist/marketplace/types.d.ts +123 -0
  17. package/dist/marketplace/types.d.ts.map +1 -0
  18. package/dist/marketplace/types.js +6 -0
  19. package/dist/marketplace/types.js.map +1 -0
  20. package/dist/reporters/audit-report.d.ts.map +1 -1
  21. package/dist/reporters/audit-report.js +180 -0
  22. package/dist/reporters/audit-report.js.map +1 -1
  23. package/dist/reporters/index.d.ts.map +1 -1
  24. package/dist/reporters/index.js +2612 -5
  25. package/dist/reporters/index.js.map +1 -1
  26. package/dist/scan.d.ts.map +1 -1
  27. package/dist/scan.js +15 -1
  28. package/dist/scan.js.map +1 -1
  29. package/dist/scanners/api-security/index.d.ts +7 -0
  30. package/dist/scanners/api-security/index.d.ts.map +1 -0
  31. package/dist/scanners/api-security/index.js +139 -0
  32. package/dist/scanners/api-security/index.js.map +1 -0
  33. package/dist/scanners/api-security/index.test.d.ts +5 -0
  34. package/dist/scanners/api-security/index.test.d.ts.map +1 -0
  35. package/dist/scanners/api-security/index.test.js +360 -0
  36. package/dist/scanners/api-security/index.test.js.map +1 -0
  37. package/dist/scanners/api-security/patterns.d.ts +32 -0
  38. package/dist/scanners/api-security/patterns.d.ts.map +1 -0
  39. package/dist/scanners/api-security/patterns.js +159 -0
  40. package/dist/scanners/api-security/patterns.js.map +1 -0
  41. package/dist/scanners/authentication/index.d.ts +7 -0
  42. package/dist/scanners/authentication/index.d.ts.map +1 -0
  43. package/dist/scanners/authentication/index.js +107 -0
  44. package/dist/scanners/authentication/index.js.map +1 -0
  45. package/dist/scanners/authentication/index.test.d.ts +5 -0
  46. package/dist/scanners/authentication/index.test.d.ts.map +1 -0
  47. package/dist/scanners/authentication/index.test.js +379 -0
  48. package/dist/scanners/authentication/index.test.js.map +1 -0
  49. package/dist/scanners/authentication/patterns.d.ts +32 -0
  50. package/dist/scanners/authentication/patterns.d.ts.map +1 -0
  51. package/dist/scanners/authentication/patterns.js +133 -0
  52. package/dist/scanners/authentication/patterns.js.map +1 -0
  53. package/dist/scanners/configuration/index.d.ts +8 -0
  54. package/dist/scanners/configuration/index.d.ts.map +1 -0
  55. package/dist/scanners/configuration/index.js +87 -0
  56. package/dist/scanners/configuration/index.js.map +1 -0
  57. package/dist/scanners/configuration/index.test.d.ts +5 -0
  58. package/dist/scanners/configuration/index.test.d.ts.map +1 -0
  59. package/dist/scanners/configuration/index.test.js +344 -0
  60. package/dist/scanners/configuration/index.test.js.map +1 -0
  61. package/dist/scanners/configuration/patterns.d.ts +32 -0
  62. package/dist/scanners/configuration/patterns.d.ts.map +1 -0
  63. package/dist/scanners/configuration/patterns.js +146 -0
  64. package/dist/scanners/configuration/patterns.js.map +1 -0
  65. package/dist/scanners/credentials/index.d.ts +7 -0
  66. package/dist/scanners/credentials/index.d.ts.map +1 -0
  67. package/dist/scanners/credentials/index.js +129 -0
  68. package/dist/scanners/credentials/index.js.map +1 -0
  69. package/dist/scanners/credentials/index.test.d.ts +5 -0
  70. package/dist/scanners/credentials/index.test.d.ts.map +1 -0
  71. package/dist/scanners/credentials/index.test.js +395 -0
  72. package/dist/scanners/credentials/index.test.js.map +1 -0
  73. package/dist/scanners/credentials/patterns.d.ts +32 -0
  74. package/dist/scanners/credentials/patterns.d.ts.map +1 -0
  75. package/dist/scanners/credentials/patterns.js +140 -0
  76. package/dist/scanners/credentials/patterns.js.map +1 -0
  77. package/dist/scanners/errors/index.d.ts +8 -0
  78. package/dist/scanners/errors/index.d.ts.map +1 -0
  79. package/dist/scanners/errors/index.js +78 -0
  80. package/dist/scanners/errors/index.js.map +1 -0
  81. package/dist/scanners/errors/index.test.d.ts +5 -0
  82. package/dist/scanners/errors/index.test.d.ts.map +1 -0
  83. package/dist/scanners/errors/index.test.js +330 -0
  84. package/dist/scanners/errors/index.test.js.map +1 -0
  85. package/dist/scanners/errors/patterns.d.ts +27 -0
  86. package/dist/scanners/errors/patterns.d.ts.map +1 -0
  87. package/dist/scanners/errors/patterns.js +97 -0
  88. package/dist/scanners/errors/patterns.js.map +1 -0
  89. package/dist/scanners/hipaa2026/index.d.ts +8 -0
  90. package/dist/scanners/hipaa2026/index.d.ts.map +1 -0
  91. package/dist/scanners/hipaa2026/index.js +345 -0
  92. package/dist/scanners/hipaa2026/index.js.map +1 -0
  93. package/dist/scanners/hipaa2026/index.test.d.ts +5 -0
  94. package/dist/scanners/hipaa2026/index.test.d.ts.map +1 -0
  95. package/dist/scanners/hipaa2026/index.test.js +332 -0
  96. package/dist/scanners/hipaa2026/index.test.js.map +1 -0
  97. package/dist/scanners/hipaa2026/patterns.d.ts +57 -0
  98. package/dist/scanners/hipaa2026/patterns.d.ts.map +1 -0
  99. package/dist/scanners/hipaa2026/patterns.js +268 -0
  100. package/dist/scanners/hipaa2026/patterns.js.map +1 -0
  101. package/dist/scanners/operational/index.d.ts +7 -0
  102. package/dist/scanners/operational/index.d.ts.map +1 -0
  103. package/dist/scanners/operational/index.js +171 -0
  104. package/dist/scanners/operational/index.js.map +1 -0
  105. package/dist/scanners/operational/index.test.d.ts +5 -0
  106. package/dist/scanners/operational/index.test.d.ts.map +1 -0
  107. package/dist/scanners/operational/index.test.js +406 -0
  108. package/dist/scanners/operational/index.test.js.map +1 -0
  109. package/dist/scanners/operational/patterns.d.ts +33 -0
  110. package/dist/scanners/operational/patterns.d.ts.map +1 -0
  111. package/dist/scanners/operational/patterns.js +151 -0
  112. package/dist/scanners/operational/patterns.js.map +1 -0
  113. package/dist/scanners/rbac/index.d.ts +7 -0
  114. package/dist/scanners/rbac/index.d.ts.map +1 -0
  115. package/dist/scanners/rbac/index.js +145 -0
  116. package/dist/scanners/rbac/index.js.map +1 -0
  117. package/dist/scanners/rbac/index.test.d.ts +5 -0
  118. package/dist/scanners/rbac/index.test.d.ts.map +1 -0
  119. package/dist/scanners/rbac/index.test.js +422 -0
  120. package/dist/scanners/rbac/index.test.js.map +1 -0
  121. package/dist/scanners/rbac/patterns.d.ts +32 -0
  122. package/dist/scanners/rbac/patterns.d.ts.map +1 -0
  123. package/dist/scanners/rbac/patterns.js +124 -0
  124. package/dist/scanners/rbac/patterns.js.map +1 -0
  125. package/dist/scanners/revocation/index.d.ts +8 -0
  126. package/dist/scanners/revocation/index.d.ts.map +1 -0
  127. package/dist/scanners/revocation/index.js +83 -0
  128. package/dist/scanners/revocation/index.js.map +1 -0
  129. package/dist/scanners/revocation/index.test.d.ts +5 -0
  130. package/dist/scanners/revocation/index.test.d.ts.map +1 -0
  131. package/dist/scanners/revocation/index.test.js +332 -0
  132. package/dist/scanners/revocation/index.test.js.map +1 -0
  133. package/dist/scanners/revocation/patterns.d.ts +27 -0
  134. package/dist/scanners/revocation/patterns.d.ts.map +1 -0
  135. package/dist/scanners/revocation/patterns.js +109 -0
  136. package/dist/scanners/revocation/patterns.js.map +1 -0
  137. package/dist/scanners/sanitization/index.d.ts +8 -0
  138. package/dist/scanners/sanitization/index.d.ts.map +1 -0
  139. package/dist/scanners/sanitization/index.js +98 -0
  140. package/dist/scanners/sanitization/index.js.map +1 -0
  141. package/dist/scanners/sanitization/index.test.d.ts +5 -0
  142. package/dist/scanners/sanitization/index.test.d.ts.map +1 -0
  143. package/dist/scanners/sanitization/index.test.js +370 -0
  144. package/dist/scanners/sanitization/index.test.js.map +1 -0
  145. package/dist/scanners/sanitization/patterns.d.ts +27 -0
  146. package/dist/scanners/sanitization/patterns.d.ts.map +1 -0
  147. package/dist/scanners/sanitization/patterns.js +117 -0
  148. package/dist/scanners/sanitization/patterns.js.map +1 -0
  149. package/dist/training/certificate.d.ts +26 -0
  150. package/dist/training/certificate.d.ts.map +1 -0
  151. package/dist/training/certificate.js +92 -0
  152. package/dist/training/certificate.js.map +1 -0
  153. package/dist/training/index.d.ts +3 -0
  154. package/dist/training/index.d.ts.map +1 -0
  155. package/dist/training/index.js +243 -0
  156. package/dist/training/index.js.map +1 -0
  157. package/dist/training/modules.d.ts +13 -0
  158. package/dist/training/modules.d.ts.map +1 -0
  159. package/dist/training/modules.js +608 -0
  160. package/dist/training/modules.js.map +1 -0
  161. package/dist/training/questions.d.ts +9 -0
  162. package/dist/training/questions.d.ts.map +1 -0
  163. package/dist/training/questions.js +505 -0
  164. package/dist/training/questions.js.map +1 -0
  165. package/dist/types.d.ts +45 -0
  166. package/dist/types.d.ts.map +1 -1
  167. package/dist/utils/npm-audit.d.ts +6 -0
  168. package/dist/utils/npm-audit.d.ts.map +1 -0
  169. package/dist/utils/npm-audit.js +95 -0
  170. package/dist/utils/npm-audit.js.map +1 -0
  171. package/dist/utils/scan-history.d.ts +59 -0
  172. package/dist/utils/scan-history.d.ts.map +1 -0
  173. package/dist/utils/scan-history.js +170 -0
  174. package/dist/utils/scan-history.js.map +1 -0
  175. package/package.json +4 -1
  176. package/templates/baa-verification-letter.md +105 -0
  177. package/templates/irp.md +545 -0
  178. package/templates/notice-of-privacy-practices.md +491 -0
  179. package/templates/physical-safeguards-checklist.md +247 -0
  180. package/templates/security-officer-designation.md +237 -0
@@ -0,0 +1,95 @@
1
+ import { exec } from 'child_process';
2
+ import { promisify } from 'util';
3
+ const execAsync = promisify(exec);
4
+ export async function runNpmAudit(projectPath) {
5
+ try {
6
+ // Execute npm audit --json in the project directory
7
+ const { stdout } = await execAsync('npm audit --json', {
8
+ cwd: projectPath,
9
+ maxBuffer: 10 * 1024 * 1024, // 10MB buffer
10
+ timeout: 30000, // 30 second timeout
11
+ });
12
+ // Parse the JSON output
13
+ const auditResult = JSON.parse(stdout);
14
+ // Extract and transform vulnerabilities
15
+ const vulnerabilities = [];
16
+ for (const [packageName, vuln] of Object.entries(auditResult.vulnerabilities || {})) {
17
+ // Extract URL from via if it's an array
18
+ let url;
19
+ let via = '';
20
+ if (Array.isArray(vuln.via)) {
21
+ // via is an array of vulnerability details
22
+ const firstVia = vuln.via[0];
23
+ if (typeof firstVia === 'object' && 'url' in firstVia) {
24
+ url = firstVia.url;
25
+ via = firstVia.title || packageName;
26
+ }
27
+ else {
28
+ via = String(firstVia);
29
+ }
30
+ }
31
+ else {
32
+ via = String(vuln.via);
33
+ }
34
+ vulnerabilities.push({
35
+ name: packageName,
36
+ severity: vuln.severity,
37
+ via,
38
+ range: vuln.range,
39
+ fixAvailable: vuln.fixAvailable,
40
+ url,
41
+ });
42
+ }
43
+ return { vulnerabilities };
44
+ }
45
+ catch (error) {
46
+ // npm audit exits with non-zero if vulnerabilities are found
47
+ // Check if error contains JSON output
48
+ if (error.stdout) {
49
+ try {
50
+ const auditResult = JSON.parse(error.stdout);
51
+ const vulnerabilities = [];
52
+ for (const [packageName, vuln] of Object.entries(auditResult.vulnerabilities || {})) {
53
+ let url;
54
+ let via = '';
55
+ if (Array.isArray(vuln.via)) {
56
+ const firstVia = vuln.via[0];
57
+ if (typeof firstVia === 'object' && 'url' in firstVia) {
58
+ url = firstVia.url;
59
+ via = firstVia.title || packageName;
60
+ }
61
+ else {
62
+ via = String(firstVia);
63
+ }
64
+ }
65
+ else {
66
+ via = String(vuln.via);
67
+ }
68
+ vulnerabilities.push({
69
+ name: packageName,
70
+ severity: vuln.severity,
71
+ via,
72
+ range: vuln.range,
73
+ fixAvailable: vuln.fixAvailable,
74
+ url,
75
+ });
76
+ }
77
+ return { vulnerabilities };
78
+ }
79
+ catch {
80
+ // Failed to parse JSON from error output
81
+ }
82
+ }
83
+ // Real error - npm audit failed or not available
84
+ const errorMessage = error.message || 'Unknown error';
85
+ // Common error scenarios
86
+ if (errorMessage.includes('ENOENT') || errorMessage.includes('not found')) {
87
+ return { vulnerabilities: [], error: 'npm command not found. Is Node.js/npm installed?' };
88
+ }
89
+ if (errorMessage.includes('package.json')) {
90
+ return { vulnerabilities: [], error: 'No package.json found in project directory' };
91
+ }
92
+ return { vulnerabilities: [], error: `npm audit failed: ${errorMessage}` };
93
+ }
94
+ }
95
+ //# sourceMappingURL=npm-audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"npm-audit.js","sourceRoot":"","sources":["../../src/utils/npm-audit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import type { Finding } from '../types.js';
2
+ export interface ScanHistoryEntry {
3
+ timestamp: string;
4
+ date: string;
5
+ complianceScore: number;
6
+ severity: {
7
+ critical: number;
8
+ high: number;
9
+ medium: number;
10
+ low: number;
11
+ };
12
+ failedRuleIds: string[];
13
+ totalFilesScanned: number;
14
+ }
15
+ export interface ScanComparison {
16
+ previousScan?: ScanHistoryEntry;
17
+ scoreChange: number;
18
+ severityChanges: {
19
+ critical: number;
20
+ high: number;
21
+ medium: number;
22
+ low: number;
23
+ };
24
+ newIssues: string[];
25
+ resolvedIssues: string[];
26
+ }
27
+ /**
28
+ * Get the history directory path for a project
29
+ */
30
+ export declare function getHistoryDir(projectPath: string): string;
31
+ /**
32
+ * Ensure the history directory exists
33
+ */
34
+ export declare function ensureHistoryDir(projectPath: string): Promise<void>;
35
+ /**
36
+ * Generate filename for a scan history entry
37
+ */
38
+ export declare function generateHistoryFilename(): string;
39
+ /**
40
+ * Save scan results to history
41
+ */
42
+ export declare function saveScanHistory(projectPath: string, score: number, findings: Finding[], scannedFiles: number): Promise<void>;
43
+ /**
44
+ * Get the most recent scan history entry
45
+ */
46
+ export declare function getMostRecentScan(projectPath: string): Promise<ScanHistoryEntry | null>;
47
+ /**
48
+ * Get all scan history entries
49
+ */
50
+ export declare function getAllScans(projectPath: string): Promise<ScanHistoryEntry[]>;
51
+ /**
52
+ * Compare current scan with previous scan
53
+ */
54
+ export declare function compareScan(currentScore: number, currentFindings: Finding[], previousScan: ScanHistoryEntry | null): ScanComparison;
55
+ /**
56
+ * Format a date string from history filename format
57
+ */
58
+ export declare function formatHistoryDate(dateStr: string): string;
59
+ //# sourceMappingURL=scan-history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-history.d.ts","sourceRoot":"","sources":["../../src/utils/scan-history.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE;QACR,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,CAAC,EAAE,gBAAgB,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKzE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAUhD;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,OAAO,EAAE,EACnB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CA2Bf;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAwB7F;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA4BlF;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,OAAO,EAAE,EAC1B,YAAY,EAAE,gBAAgB,GAAG,IAAI,GACpC,cAAc,CAgDhB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAUzD"}
@@ -0,0 +1,170 @@
1
+ import { readdir, readFile, writeFile, mkdir } from 'fs/promises';
2
+ import { join } from 'path';
3
+ import { existsSync } from 'fs';
4
+ /**
5
+ * Get the history directory path for a project
6
+ */
7
+ export function getHistoryDir(projectPath) {
8
+ return join(projectPath, '.vlayer', 'history');
9
+ }
10
+ /**
11
+ * Ensure the history directory exists
12
+ */
13
+ export async function ensureHistoryDir(projectPath) {
14
+ const historyDir = getHistoryDir(projectPath);
15
+ if (!existsSync(historyDir)) {
16
+ await mkdir(historyDir, { recursive: true });
17
+ }
18
+ }
19
+ /**
20
+ * Generate filename for a scan history entry
21
+ */
22
+ export function generateHistoryFilename() {
23
+ const now = new Date();
24
+ const yyyy = now.getFullYear();
25
+ const mm = String(now.getMonth() + 1).padStart(2, '0');
26
+ const dd = String(now.getDate()).padStart(2, '0');
27
+ const hh = String(now.getHours()).padStart(2, '0');
28
+ const min = String(now.getMinutes()).padStart(2, '0');
29
+ const ss = String(now.getSeconds()).padStart(2, '0');
30
+ return `scan-${yyyy}-${mm}-${dd}-${hh}${min}${ss}.json`;
31
+ }
32
+ /**
33
+ * Save scan results to history
34
+ */
35
+ export async function saveScanHistory(projectPath, score, findings, scannedFiles) {
36
+ await ensureHistoryDir(projectPath);
37
+ // Filter to active findings (not baseline, not suppressed, not acknowledged)
38
+ const activeFindings = findings.filter(f => !f.isBaseline && !f.suppressed && !f.acknowledged);
39
+ const entry = {
40
+ timestamp: new Date().toISOString(),
41
+ date: generateHistoryFilename().replace('scan-', '').replace('.json', ''),
42
+ complianceScore: score,
43
+ severity: {
44
+ critical: activeFindings.filter(f => f.severity === 'critical').length,
45
+ high: activeFindings.filter(f => f.severity === 'high').length,
46
+ medium: activeFindings.filter(f => f.severity === 'medium').length,
47
+ low: activeFindings.filter(f => f.severity === 'low').length,
48
+ },
49
+ failedRuleIds: [...new Set(activeFindings.map(f => f.id))],
50
+ totalFilesScanned: scannedFiles,
51
+ };
52
+ const historyDir = getHistoryDir(projectPath);
53
+ const filename = generateHistoryFilename();
54
+ const filePath = join(historyDir, filename);
55
+ await writeFile(filePath, JSON.stringify(entry, null, 2), 'utf-8');
56
+ }
57
+ /**
58
+ * Get the most recent scan history entry
59
+ */
60
+ export async function getMostRecentScan(projectPath) {
61
+ const historyDir = getHistoryDir(projectPath);
62
+ if (!existsSync(historyDir)) {
63
+ return null;
64
+ }
65
+ try {
66
+ const files = await readdir(historyDir);
67
+ const scanFiles = files
68
+ .filter(f => f.startsWith('scan-') && f.endsWith('.json'))
69
+ .sort()
70
+ .reverse(); // Most recent first
71
+ if (scanFiles.length === 0) {
72
+ return null;
73
+ }
74
+ const mostRecentFile = scanFiles[0];
75
+ const content = await readFile(join(historyDir, mostRecentFile), 'utf-8');
76
+ return JSON.parse(content);
77
+ }
78
+ catch (error) {
79
+ return null;
80
+ }
81
+ }
82
+ /**
83
+ * Get all scan history entries
84
+ */
85
+ export async function getAllScans(projectPath) {
86
+ const historyDir = getHistoryDir(projectPath);
87
+ if (!existsSync(historyDir)) {
88
+ return [];
89
+ }
90
+ try {
91
+ const files = await readdir(historyDir);
92
+ const scanFiles = files
93
+ .filter(f => f.startsWith('scan-') && f.endsWith('.json'))
94
+ .sort()
95
+ .reverse(); // Most recent first
96
+ const scans = [];
97
+ for (const file of scanFiles) {
98
+ try {
99
+ const content = await readFile(join(historyDir, file), 'utf-8');
100
+ scans.push(JSON.parse(content));
101
+ }
102
+ catch {
103
+ // Skip corrupted files
104
+ }
105
+ }
106
+ return scans;
107
+ }
108
+ catch (error) {
109
+ return [];
110
+ }
111
+ }
112
+ /**
113
+ * Compare current scan with previous scan
114
+ */
115
+ export function compareScan(currentScore, currentFindings, previousScan) {
116
+ if (!previousScan) {
117
+ return {
118
+ previousScan: undefined,
119
+ scoreChange: 0,
120
+ severityChanges: {
121
+ critical: 0,
122
+ high: 0,
123
+ medium: 0,
124
+ low: 0,
125
+ },
126
+ newIssues: [],
127
+ resolvedIssues: [],
128
+ };
129
+ }
130
+ // Filter to active findings
131
+ const activeFindings = currentFindings.filter(f => !f.isBaseline && !f.suppressed && !f.acknowledged);
132
+ const currentRuleIds = new Set(activeFindings.map(f => f.id));
133
+ const previousRuleIds = new Set(previousScan.failedRuleIds);
134
+ // Find new and resolved issues
135
+ const newIssues = [...currentRuleIds].filter(id => !previousRuleIds.has(id));
136
+ const resolvedIssues = [...previousRuleIds].filter(id => !currentRuleIds.has(id));
137
+ // Calculate severity changes
138
+ const currentSeverity = {
139
+ critical: activeFindings.filter(f => f.severity === 'critical').length,
140
+ high: activeFindings.filter(f => f.severity === 'high').length,
141
+ medium: activeFindings.filter(f => f.severity === 'medium').length,
142
+ low: activeFindings.filter(f => f.severity === 'low').length,
143
+ };
144
+ return {
145
+ previousScan,
146
+ scoreChange: currentScore - previousScan.complianceScore,
147
+ severityChanges: {
148
+ critical: currentSeverity.critical - previousScan.severity.critical,
149
+ high: currentSeverity.high - previousScan.severity.high,
150
+ medium: currentSeverity.medium - previousScan.severity.medium,
151
+ low: currentSeverity.low - previousScan.severity.low,
152
+ },
153
+ newIssues,
154
+ resolvedIssues,
155
+ };
156
+ }
157
+ /**
158
+ * Format a date string from history filename format
159
+ */
160
+ export function formatHistoryDate(dateStr) {
161
+ // dateStr format: YYYY-MM-DD-HHmmss
162
+ const year = dateStr.substring(0, 4);
163
+ const month = dateStr.substring(5, 7);
164
+ const day = dateStr.substring(8, 10);
165
+ const hour = dateStr.substring(11, 13);
166
+ const minute = dateStr.substring(13, 15);
167
+ const second = dateStr.substring(15, 17);
168
+ return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
169
+ }
170
+ //# sourceMappingURL=scan-history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-history.js","sourceRoot":"","sources":["../../src/utils/scan-history.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "verification-layer",
3
- "version": "0.20.0",
3
+ "version": "0.22.0",
4
4
  "description": "CLI tool for HIPAA compliance scanning and reporting",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -16,6 +16,7 @@
16
16
  },
17
17
  "files": [
18
18
  "dist",
19
+ "templates",
19
20
  "README.md",
20
21
  "LICENSE"
21
22
  ],
@@ -74,12 +75,14 @@
74
75
  },
75
76
  "dependencies": {
76
77
  "@anthropic-ai/sdk": "^0.73.0",
78
+ "@types/inquirer": "^9.0.9",
77
79
  "@types/pdfkit": "^0.17.4",
78
80
  "@typescript-eslint/typescript-estree": "^8.54.0",
79
81
  "chalk": "^5.3.0",
80
82
  "chokidar": "^5.0.0",
81
83
  "commander": "^12.0.0",
82
84
  "glob": "^10.3.0",
85
+ "inquirer": "^9.3.8",
83
86
  "minimatch": "^10.1.1",
84
87
  "ora": "^8.0.0",
85
88
  "pdfkit": "^0.17.2",
@@ -0,0 +1,105 @@
1
+ # Annual Business Associate Security Verification
2
+
3
+ **Date:** [DATE]
4
+
5
+ **To:** [COVERED ENTITY NAME]
6
+ **Attention:** [CE CONTACT NAME]
7
+
8
+ **From:** [BA COMPANY NAME]
9
+ **Contact:** [BA CONTACT NAME]
10
+ **Email:** [BA EMAIL]
11
+
12
+ ---
13
+
14
+ ## Certification Statement
15
+
16
+ This letter certifies that **[BA COMPANY NAME]** has reviewed and verified deployment of the following HIPAA Security Rule technical safeguards as required under our Business Associate Agreement with **[COVERED ENTITY NAME]**.
17
+
18
+ ## Technical Safeguards Verification Checklist
19
+
20
+ As required by 45 CFR §164.312, the following technical safeguards have been implemented and verified:
21
+
22
+ ### Required Safeguards (45 CFR §164.312)
23
+
24
+ - ☐ **Access Controls** (§164.312(a)(1))
25
+ - Unique user identification
26
+ - Emergency access procedures
27
+ - Automatic logoff
28
+ - Encryption and decryption
29
+
30
+ - ☐ **Audit Controls** (§164.312(b))
31
+ - Hardware, software, and/or procedural mechanisms to record and examine access and activity in systems containing ePHI
32
+
33
+ - ☐ **Integrity** (§164.312(c)(1))
34
+ - Mechanisms to authenticate ePHI and ensure it has not been altered or destroyed in an unauthorized manner
35
+
36
+ - ☐ **Person or Entity Authentication** (§164.312(d))
37
+ - Procedures to verify that a person or entity seeking access to ePHI is the one claimed
38
+
39
+ - ☐ **Transmission Security** (§164.312(e)(1))
40
+ - Technical security measures to guard against unauthorized access to ePHI transmitted over electronic networks
41
+
42
+ ### Additional Security Measures Verified
43
+
44
+ - ☐ **Encryption at Rest**
45
+ - ePHI stored in encrypted format using industry-standard algorithms (AES-256 or equivalent)
46
+
47
+ - ☐ **Encryption in Transit**
48
+ - All ePHI transmissions protected with TLS 1.2 or higher
49
+
50
+ - ☐ **Multi-Factor Authentication (MFA)**
51
+ - MFA implemented for all accounts with access to ePHI
52
+
53
+ - ☐ **Role-Based Access Control (RBAC)**
54
+ - Access to ePHI restricted based on job function and minimum necessary principle
55
+
56
+ ## Compliance Report Attachment
57
+
58
+ The vlayer HIPAA Compliance Report dated **[DATE]** is attached as **Exhibit A** to this verification letter.
59
+
60
+ **Compliance Score:** [SCORE]/100
61
+
62
+ This automated security assessment confirms the technical implementation of the above safeguards and identifies any gaps requiring remediation.
63
+
64
+ ## Security Incident Reporting
65
+
66
+ [BA COMPANY NAME] confirms that:
67
+ - No security incidents affecting ePHI have occurred during this reporting period, OR
68
+ - All security incidents have been reported to [COVERED ENTITY NAME] in accordance with our BAA within the required timeframes
69
+
70
+ ## Signatures
71
+
72
+ By signing below, both parties acknowledge receipt and review of this annual security verification.
73
+
74
+ ### Business Associate
75
+
76
+ **Signature:** \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_
77
+
78
+ **Name:** [BA CONTACT NAME]
79
+
80
+ **Title:** \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_
81
+
82
+ **Date:** \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_
83
+
84
+ ### Covered Entity
85
+
86
+ **Signature:** \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_
87
+
88
+ **Name:** [CE CONTACT NAME]
89
+
90
+ **Title:** \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_
91
+
92
+ **Date:** \_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_
93
+
94
+ ---
95
+
96
+ ## Disclaimer
97
+
98
+ This verification does not guarantee absolute security but confirms that technical safeguards have been deployed and verified as of the date above. Security is an ongoing process requiring continuous monitoring, assessment, and improvement. [BA COMPANY NAME] commits to maintaining these safeguards and promptly notifying [COVERED ENTITY NAME] of any material changes or security incidents affecting ePHI.
99
+
100
+ **Retention:** This verification letter and attached compliance report must be retained for a minimum of six (6) years as required by 45 CFR §164.316(b)(2).
101
+
102
+ ---
103
+
104
+ *Generated using vlayer - HIPAA Compliance Scanner*
105
+ *https://github.com/Francosimon53/verification-layer*