vaspera 2.7.0 → 2.9.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.
- package/CHANGELOG.md +72 -0
- package/README.md +111 -7
- package/dist/__tests__/agents/adversary/tactics/api.test.d.ts +5 -0
- package/dist/__tests__/agents/adversary/tactics/api.test.d.ts.map +1 -0
- package/dist/__tests__/agents/adversary/tactics/api.test.js +369 -0
- package/dist/__tests__/agents/adversary/tactics/api.test.js.map +1 -0
- package/dist/__tests__/agents/adversary/tactics/llm.test.d.ts +5 -0
- package/dist/__tests__/agents/adversary/tactics/llm.test.d.ts.map +1 -0
- package/dist/__tests__/agents/adversary/tactics/llm.test.js +409 -0
- package/dist/__tests__/agents/adversary/tactics/llm.test.js.map +1 -0
- package/dist/__tests__/agents/adversary/tactics/registry.test.d.ts +7 -0
- package/dist/__tests__/agents/adversary/tactics/registry.test.d.ts.map +1 -0
- package/dist/__tests__/agents/adversary/tactics/registry.test.js +74 -0
- package/dist/__tests__/agents/adversary/tactics/registry.test.js.map +1 -0
- package/dist/__tests__/agents/adversary/tactics/web-app.test.d.ts +7 -0
- package/dist/__tests__/agents/adversary/tactics/web-app.test.d.ts.map +1 -0
- package/dist/__tests__/agents/adversary/tactics/web-app.test.js +374 -0
- package/dist/__tests__/agents/adversary/tactics/web-app.test.js.map +1 -0
- package/dist/__tests__/compliance-bundle.test.d.ts +9 -0
- package/dist/__tests__/compliance-bundle.test.d.ts.map +1 -0
- package/dist/__tests__/compliance-bundle.test.js +344 -0
- package/dist/__tests__/compliance-bundle.test.js.map +1 -0
- package/dist/__tests__/healthcare-compliance.test.d.ts +9 -0
- package/dist/__tests__/healthcare-compliance.test.d.ts.map +1 -0
- package/dist/__tests__/healthcare-compliance.test.js +233 -0
- package/dist/__tests__/healthcare-compliance.test.js.map +1 -0
- package/dist/action/diff-mode.d.ts +124 -8
- package/dist/action/diff-mode.d.ts.map +1 -1
- package/dist/action/diff-mode.js +384 -65
- package/dist/action/diff-mode.js.map +1 -1
- package/dist/action/diff-mode.test.js +3 -3
- package/dist/action/diff-mode.test.js.map +1 -1
- package/dist/action/pr-comment.test.js +1 -0
- package/dist/action/pr-comment.test.js.map +1 -1
- package/dist/action/sarif-upload.test.js +1 -0
- package/dist/action/sarif-upload.test.js.map +1 -1
- package/dist/agents/adversary/config.d.ts +113 -0
- package/dist/agents/adversary/config.d.ts.map +1 -0
- package/dist/agents/adversary/config.js +391 -0
- package/dist/agents/adversary/config.js.map +1 -0
- package/dist/agents/adversary/index.d.ts +41 -0
- package/dist/agents/adversary/index.d.ts.map +1 -0
- package/dist/agents/adversary/index.js +838 -0
- package/dist/agents/adversary/index.js.map +1 -0
- package/dist/agents/adversary/reporting/compliance-mapper.d.ts +108 -0
- package/dist/agents/adversary/reporting/compliance-mapper.d.ts.map +1 -0
- package/dist/agents/adversary/reporting/compliance-mapper.js +391 -0
- package/dist/agents/adversary/reporting/compliance-mapper.js.map +1 -0
- package/dist/agents/adversary/reporting/index.d.ts +10 -0
- package/dist/agents/adversary/reporting/index.d.ts.map +1 -0
- package/dist/agents/adversary/reporting/index.js +10 -0
- package/dist/agents/adversary/reporting/index.js.map +1 -0
- package/dist/agents/adversary/reporting/poc-generator.d.ts +44 -0
- package/dist/agents/adversary/reporting/poc-generator.d.ts.map +1 -0
- package/dist/agents/adversary/reporting/poc-generator.js +308 -0
- package/dist/agents/adversary/reporting/poc-generator.js.map +1 -0
- package/dist/agents/adversary/tactics/api.d.ts +13 -0
- package/dist/agents/adversary/tactics/api.d.ts.map +1 -0
- package/dist/agents/adversary/tactics/api.js +815 -0
- package/dist/agents/adversary/tactics/api.js.map +1 -0
- package/dist/agents/adversary/tactics/auth.d.ts +13 -0
- package/dist/agents/adversary/tactics/auth.d.ts.map +1 -0
- package/dist/agents/adversary/tactics/auth.js +676 -0
- package/dist/agents/adversary/tactics/auth.js.map +1 -0
- package/dist/agents/adversary/tactics/index.d.ts +129 -0
- package/dist/agents/adversary/tactics/index.d.ts.map +1 -0
- package/dist/agents/adversary/tactics/index.js +199 -0
- package/dist/agents/adversary/tactics/index.js.map +1 -0
- package/dist/agents/adversary/tactics/infra.d.ts +13 -0
- package/dist/agents/adversary/tactics/infra.d.ts.map +1 -0
- package/dist/agents/adversary/tactics/infra.js +827 -0
- package/dist/agents/adversary/tactics/infra.js.map +1 -0
- package/dist/agents/adversary/tactics/injection.d.ts +12 -0
- package/dist/agents/adversary/tactics/injection.d.ts.map +1 -0
- package/dist/agents/adversary/tactics/injection.js +549 -0
- package/dist/agents/adversary/tactics/injection.js.map +1 -0
- package/dist/agents/adversary/tactics/llm.d.ts +13 -0
- package/dist/agents/adversary/tactics/llm.d.ts.map +1 -0
- package/dist/agents/adversary/tactics/llm.js +767 -0
- package/dist/agents/adversary/tactics/llm.js.map +1 -0
- package/dist/agents/adversary/tactics/web-app.d.ts +13 -0
- package/dist/agents/adversary/tactics/web-app.d.ts.map +1 -0
- package/dist/agents/adversary/tactics/web-app.js +717 -0
- package/dist/agents/adversary/tactics/web-app.js.map +1 -0
- package/dist/agents/adversary/types.d.ts +407 -0
- package/dist/agents/adversary/types.d.ts.map +1 -0
- package/dist/agents/adversary/types.js +12 -0
- package/dist/agents/adversary/types.js.map +1 -0
- package/dist/agents/index.d.ts +1 -0
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +2 -0
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/zero-day-hunter.d.ts +1 -1
- package/dist/agents/zero-day-hunter.d.ts.map +1 -1
- package/dist/analysis/data-flow.d.ts +154 -0
- package/dist/analysis/data-flow.d.ts.map +1 -0
- package/dist/analysis/data-flow.js +393 -0
- package/dist/analysis/data-flow.js.map +1 -0
- package/dist/analysis/index.d.ts +9 -0
- package/dist/analysis/index.d.ts.map +1 -0
- package/dist/analysis/index.js +9 -0
- package/dist/analysis/index.js.map +1 -0
- package/dist/badge-service/index.d.ts +144 -0
- package/dist/badge-service/index.d.ts.map +1 -0
- package/dist/badge-service/index.js +206 -0
- package/dist/badge-service/index.js.map +1 -0
- package/dist/certification/consensus.test.js +2 -0
- package/dist/certification/consensus.test.js.map +1 -1
- package/dist/certification/store.d.ts.map +1 -1
- package/dist/certification/store.js +4 -0
- package/dist/certification/store.js.map +1 -1
- package/dist/certification/types.d.ts +3 -3
- package/dist/certification/types.d.ts.map +1 -1
- package/dist/certification/types.js +2 -0
- package/dist/certification/types.js.map +1 -1
- package/dist/commands/certification/certify.d.ts.map +1 -1
- package/dist/commands/certification/certify.js +18 -4
- package/dist/commands/certification/certify.js.map +1 -1
- package/dist/compliance/attestation.d.ts +39 -0
- package/dist/compliance/attestation.d.ts.map +1 -0
- package/dist/compliance/attestation.js +364 -0
- package/dist/compliance/attestation.js.map +1 -0
- package/dist/compliance/cfr42-part2.d.ts +42 -0
- package/dist/compliance/cfr42-part2.d.ts.map +1 -0
- package/dist/compliance/cfr42-part2.js +408 -0
- package/dist/compliance/cfr42-part2.js.map +1 -0
- package/dist/compliance/compliance-bundle.d.ts +100 -0
- package/dist/compliance/compliance-bundle.d.ts.map +1 -0
- package/dist/compliance/compliance-bundle.js +210 -0
- package/dist/compliance/compliance-bundle.js.map +1 -0
- package/dist/compliance/healthcare-bundle.d.ts +68 -0
- package/dist/compliance/healthcare-bundle.d.ts.map +1 -0
- package/dist/compliance/healthcare-bundle.js +104 -0
- package/dist/compliance/healthcare-bundle.js.map +1 -0
- package/dist/compliance/hipaa.d.ts.map +1 -1
- package/dist/compliance/hipaa.js +14 -11
- package/dist/compliance/hipaa.js.map +1 -1
- package/dist/compliance/index.d.ts +10 -2
- package/dist/compliance/index.d.ts.map +1 -1
- package/dist/compliance/index.js +9 -3
- package/dist/compliance/index.js.map +1 -1
- package/dist/compliance/mapper.d.ts.map +1 -1
- package/dist/compliance/mapper.js +3 -17
- package/dist/compliance/mapper.js.map +1 -1
- package/dist/compliance/nist-800-53.d.ts +22 -6
- package/dist/compliance/nist-800-53.d.ts.map +1 -1
- package/dist/compliance/nist-800-53.js +264 -272
- package/dist/compliance/nist-800-53.js.map +1 -1
- package/dist/compliance/report.d.ts +31 -2
- package/dist/compliance/report.d.ts.map +1 -1
- package/dist/compliance/report.js +255 -4
- package/dist/compliance/report.js.map +1 -1
- package/dist/compliance/types.d.ts +1 -1
- package/dist/compliance/types.d.ts.map +1 -1
- package/dist/config/flags.d.ts +12 -12
- package/dist/cost/index.d.ts +1 -1
- package/dist/cost/index.d.ts.map +1 -1
- package/dist/cost/index.js +1 -1
- package/dist/cost/index.js.map +1 -1
- package/dist/cost/tracker.d.ts +64 -0
- package/dist/cost/tracker.d.ts.map +1 -1
- package/dist/cost/tracker.js +165 -0
- package/dist/cost/tracker.js.map +1 -1
- package/dist/eval/fixtures/healthcare/audit-gaps.d.ts +28 -0
- package/dist/eval/fixtures/healthcare/audit-gaps.d.ts.map +1 -0
- package/dist/eval/fixtures/healthcare/audit-gaps.js +90 -0
- package/dist/eval/fixtures/healthcare/audit-gaps.js.map +1 -0
- package/dist/eval/fixtures/healthcare/consent-bypass.d.ts +31 -0
- package/dist/eval/fixtures/healthcare/consent-bypass.d.ts.map +1 -0
- package/dist/eval/fixtures/healthcare/consent-bypass.js +61 -0
- package/dist/eval/fixtures/healthcare/consent-bypass.js.map +1 -0
- package/dist/eval/fixtures/healthcare/phi-in-logs.d.ts +24 -0
- package/dist/eval/fixtures/healthcare/phi-in-logs.d.ts.map +1 -0
- package/dist/eval/fixtures/healthcare/phi-in-logs.js +41 -0
- package/dist/eval/fixtures/healthcare/phi-in-logs.js.map +1 -0
- package/dist/evidence/collector.d.ts +21 -0
- package/dist/evidence/collector.d.ts.map +1 -0
- package/dist/evidence/collector.js +340 -0
- package/dist/evidence/collector.js.map +1 -0
- package/dist/evidence/index.d.ts +11 -0
- package/dist/evidence/index.d.ts.map +1 -0
- package/dist/evidence/index.js +12 -0
- package/dist/evidence/index.js.map +1 -0
- package/dist/evidence/store.d.ts +39 -0
- package/dist/evidence/store.d.ts.map +1 -0
- package/dist/evidence/store.js +173 -0
- package/dist/evidence/store.js.map +1 -0
- package/dist/evidence/types.d.ts +175 -0
- package/dist/evidence/types.d.ts.map +1 -0
- package/dist/evidence/types.js +9 -0
- package/dist/evidence/types.js.map +1 -0
- package/dist/exporters/checkmarx.d.ts +18 -0
- package/dist/exporters/checkmarx.d.ts.map +1 -0
- package/dist/exporters/checkmarx.js +203 -0
- package/dist/exporters/checkmarx.js.map +1 -0
- package/dist/exporters/index.d.ts +22 -0
- package/dist/exporters/index.d.ts.map +1 -0
- package/dist/exporters/index.js +41 -0
- package/dist/exporters/index.js.map +1 -0
- package/dist/exporters/snyk.d.ts +18 -0
- package/dist/exporters/snyk.d.ts.map +1 -0
- package/dist/exporters/snyk.js +119 -0
- package/dist/exporters/snyk.js.map +1 -0
- package/dist/exporters/sonarqube.d.ts +18 -0
- package/dist/exporters/sonarqube.d.ts.map +1 -0
- package/dist/exporters/sonarqube.js +125 -0
- package/dist/exporters/sonarqube.js.map +1 -0
- package/dist/exporters/types.d.ts +190 -0
- package/dist/exporters/types.d.ts.map +1 -0
- package/dist/exporters/types.js +9 -0
- package/dist/exporters/types.js.map +1 -0
- package/dist/frontier/index.d.ts +12 -0
- package/dist/frontier/index.d.ts.map +1 -0
- package/dist/frontier/index.js +12 -0
- package/dist/frontier/index.js.map +1 -0
- package/dist/frontier/orchestrator.d.ts +73 -0
- package/dist/frontier/orchestrator.d.ts.map +1 -0
- package/dist/frontier/orchestrator.js +312 -0
- package/dist/frontier/orchestrator.js.map +1 -0
- package/dist/frontier/providers/stub.d.ts +32 -0
- package/dist/frontier/providers/stub.d.ts.map +1 -0
- package/dist/frontier/providers/stub.js +66 -0
- package/dist/frontier/providers/stub.js.map +1 -0
- package/dist/frontier/types.d.ts +318 -0
- package/dist/frontier/types.d.ts.map +1 -0
- package/dist/frontier/types.js +27 -0
- package/dist/frontier/types.js.map +1 -0
- package/dist/history/index.d.ts +13 -0
- package/dist/history/index.d.ts.map +1 -0
- package/dist/history/index.js +15 -0
- package/dist/history/index.js.map +1 -0
- package/dist/history/store.d.ts +74 -0
- package/dist/history/store.d.ts.map +1 -0
- package/dist/history/store.js +399 -0
- package/dist/history/store.js.map +1 -0
- package/dist/history/types.d.ts +282 -0
- package/dist/history/types.d.ts.map +1 -0
- package/dist/history/types.js +41 -0
- package/dist/history/types.js.map +1 -0
- package/dist/history/verify.d.ts +44 -0
- package/dist/history/verify.d.ts.map +1 -0
- package/dist/history/verify.js +230 -0
- package/dist/history/verify.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +431 -18
- package/dist/index.js.map +1 -1
- package/dist/multimodel/index.d.ts +1 -0
- package/dist/multimodel/index.d.ts.map +1 -1
- package/dist/multimodel/index.js +2 -0
- package/dist/multimodel/index.js.map +1 -1
- package/dist/multimodel/leaderboard.d.ts +116 -0
- package/dist/multimodel/leaderboard.d.ts.map +1 -0
- package/dist/multimodel/leaderboard.js +262 -0
- package/dist/multimodel/leaderboard.js.map +1 -0
- package/dist/observability/otel.d.ts.map +1 -1
- package/dist/observability/otel.js +1 -3
- package/dist/observability/otel.js.map +1 -1
- package/dist/plugins/loader.js +1 -1
- package/dist/plugins/loader.js.map +1 -1
- package/dist/sbom/provenance.test.js +2 -2
- package/dist/sbom/provenance.test.js.map +1 -1
- package/dist/scanners/agent/agent-chain-analysis.d.ts +152 -0
- package/dist/scanners/agent/agent-chain-analysis.d.ts.map +1 -0
- package/dist/scanners/agent/agent-chain-analysis.js +438 -0
- package/dist/scanners/agent/agent-chain-analysis.js.map +1 -0
- package/dist/scanners/agent/manifest-audit.d.ts.map +1 -1
- package/dist/scanners/agent/manifest-audit.js +30 -18
- package/dist/scanners/agent/manifest-audit.js.map +1 -1
- package/dist/scanners/agent/payloads/index.d.ts +2 -1
- package/dist/scanners/agent/payloads/index.d.ts.map +1 -1
- package/dist/scanners/agent/payloads/index.js +25 -6
- package/dist/scanners/agent/payloads/index.js.map +1 -1
- package/dist/scanners/agent/prompt-injection-fuzzer.d.ts.map +1 -1
- package/dist/scanners/agent/prompt-injection-fuzzer.js +14 -0
- package/dist/scanners/agent/prompt-injection-fuzzer.js.map +1 -1
- package/dist/scanners/agent/types.d.ts +5 -5
- package/dist/scanners/agent/types.d.ts.map +1 -1
- package/dist/scanners/agent/types.js.map +1 -1
- package/dist/scanners/cache.d.ts +156 -0
- package/dist/scanners/cache.d.ts.map +1 -0
- package/dist/scanners/cache.js +462 -0
- package/dist/scanners/cache.js.map +1 -0
- package/dist/scanners/dependencies.d.ts.map +1 -1
- package/dist/scanners/dependencies.js +5 -6
- package/dist/scanners/dependencies.js.map +1 -1
- package/dist/scanners/gosec.d.ts.map +1 -1
- package/dist/scanners/gosec.js +47 -9
- package/dist/scanners/gosec.js.map +1 -1
- package/dist/scanners/healthcare.d.ts +29 -0
- package/dist/scanners/healthcare.d.ts.map +1 -0
- package/dist/scanners/healthcare.js +526 -0
- package/dist/scanners/healthcare.js.map +1 -0
- package/dist/scanners/index.d.ts +1 -0
- package/dist/scanners/index.d.ts.map +1 -1
- package/dist/scanners/index.js +33 -0
- package/dist/scanners/index.js.map +1 -1
- package/dist/scanners/index.test.js +6 -6
- package/dist/scanners/index.test.js.map +1 -1
- package/dist/scanners/secrets.js +4 -4
- package/dist/scanners/secrets.js.map +1 -1
- package/dist/scanners/semgrep.js +5 -5
- package/dist/scanners/semgrep.js.map +1 -1
- package/dist/scanners/types.d.ts +1 -1
- package/dist/scanners/types.d.ts.map +1 -1
- package/dist/scanners/types.js +1 -0
- package/dist/scanners/types.js.map +1 -1
- package/dist/scanners/typescript.test.js +1 -1
- package/dist/scanners/typescript.test.js.map +1 -1
- package/dist/telemetry/index.d.ts +10 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +10 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/registry.d.ts +178 -0
- package/dist/telemetry/registry.d.ts.map +1 -0
- package/dist/telemetry/registry.js +297 -0
- package/dist/telemetry/registry.js.map +1 -0
- package/dist/telemetry/usage.d.ts +197 -0
- package/dist/telemetry/usage.d.ts.map +1 -0
- package/dist/telemetry/usage.js +244 -0
- package/dist/telemetry/usage.js.map +1 -0
- package/package.json +11 -2
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Incremental Scanner Cache
|
|
3
|
+
*
|
|
4
|
+
* Caches scanner results to enable incremental scanning. Only changed files
|
|
5
|
+
* are re-scanned, dramatically improving performance on subsequent runs.
|
|
6
|
+
*
|
|
7
|
+
* Cache structure:
|
|
8
|
+
* ```
|
|
9
|
+
* .vaspera/cache/scanners/{scanner}/{hash}.json
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* Cache key: sha256(filePath + fileHash + scannerVersion + ruleHash)
|
|
13
|
+
*
|
|
14
|
+
* @module scanners/cache
|
|
15
|
+
*/
|
|
16
|
+
import type { ScannerType, DeterministicFinding, ScannerResult } from "./types.js";
|
|
17
|
+
/**
|
|
18
|
+
* Cache entry for a single file's scanner results
|
|
19
|
+
*/
|
|
20
|
+
export interface ScannerCacheEntry {
|
|
21
|
+
/** Cache format version */
|
|
22
|
+
version: 1;
|
|
23
|
+
/** Scanner type */
|
|
24
|
+
scanner: ScannerType;
|
|
25
|
+
/** Scanner version that produced this result */
|
|
26
|
+
scannerVersion: string;
|
|
27
|
+
/** Hash of the rules/config used */
|
|
28
|
+
ruleHash: string;
|
|
29
|
+
/** Relative file path */
|
|
30
|
+
filePath: string;
|
|
31
|
+
/** Hash of file contents when scanned */
|
|
32
|
+
fileHash: string;
|
|
33
|
+
/** Findings from the scan */
|
|
34
|
+
findings: DeterministicFinding[];
|
|
35
|
+
/** Timestamp when cached */
|
|
36
|
+
cachedAt: string;
|
|
37
|
+
/** Scan duration in ms (for metrics) */
|
|
38
|
+
scanDuration: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Cache statistics
|
|
42
|
+
*/
|
|
43
|
+
export interface CacheStats {
|
|
44
|
+
/** Total entries in cache */
|
|
45
|
+
totalEntries: number;
|
|
46
|
+
/** Total size in bytes */
|
|
47
|
+
totalSizeBytes: number;
|
|
48
|
+
/** Entries by scanner */
|
|
49
|
+
byScanner: Record<ScannerType, number>;
|
|
50
|
+
/** Oldest entry timestamp */
|
|
51
|
+
oldestEntry?: string;
|
|
52
|
+
/** Newest entry timestamp */
|
|
53
|
+
newestEntry?: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Cache lookup result
|
|
57
|
+
*/
|
|
58
|
+
export interface CacheLookupResult {
|
|
59
|
+
/** Whether a valid cache entry was found */
|
|
60
|
+
hit: boolean;
|
|
61
|
+
/** The cached entry if found */
|
|
62
|
+
entry?: ScannerCacheEntry;
|
|
63
|
+
/** Reason for cache miss */
|
|
64
|
+
missReason?: "not_found" | "version_mismatch" | "rule_mismatch" | "file_changed" | "expired";
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Options for the scanner cache
|
|
68
|
+
*/
|
|
69
|
+
export interface ScannerCacheOptions {
|
|
70
|
+
/** Maximum number of entries per scanner (default: 10000) */
|
|
71
|
+
maxEntriesPerScanner?: number;
|
|
72
|
+
/** Maximum age of cache entries in ms (default: 7 days) */
|
|
73
|
+
maxAgeMs?: number;
|
|
74
|
+
/** Cache directory path (default: .vaspera/cache/scanners) */
|
|
75
|
+
cacheDir?: string;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Scanner cache manager
|
|
79
|
+
*
|
|
80
|
+
* Provides LRU cache with configurable limits per scanner type.
|
|
81
|
+
*/
|
|
82
|
+
export declare class ScannerCache {
|
|
83
|
+
private readonly cacheDir;
|
|
84
|
+
private readonly maxEntriesPerScanner;
|
|
85
|
+
private readonly maxAgeMs;
|
|
86
|
+
private readonly projectPath;
|
|
87
|
+
constructor(projectPath: string, options?: ScannerCacheOptions);
|
|
88
|
+
/**
|
|
89
|
+
* Generate a cache key for a file + scanner + version + rules combination
|
|
90
|
+
*/
|
|
91
|
+
generateCacheKey(filePath: string, fileHash: string, scanner: ScannerType, scannerVersion: string, ruleHash: string): string;
|
|
92
|
+
/**
|
|
93
|
+
* Get the cache file path for a given key
|
|
94
|
+
*/
|
|
95
|
+
private getCachePath;
|
|
96
|
+
/**
|
|
97
|
+
* Ensure cache directory exists
|
|
98
|
+
*/
|
|
99
|
+
private ensureCacheDir;
|
|
100
|
+
/**
|
|
101
|
+
* Look up cached results for a file
|
|
102
|
+
*/
|
|
103
|
+
lookup(filePath: string, fileHash: string, scanner: ScannerType, scannerVersion: string, ruleHash: string): Promise<CacheLookupResult>;
|
|
104
|
+
/**
|
|
105
|
+
* Store scanner results in cache
|
|
106
|
+
*/
|
|
107
|
+
store(filePath: string, fileHash: string, scanner: ScannerType, scannerVersion: string, ruleHash: string, findings: DeterministicFinding[], scanDuration: number): Promise<void>;
|
|
108
|
+
/**
|
|
109
|
+
* Invalidate cache for a specific file
|
|
110
|
+
*/
|
|
111
|
+
invalidate(filePath: string, scanner?: ScannerType): Promise<number>;
|
|
112
|
+
/**
|
|
113
|
+
* Run LRU eviction to stay within limits
|
|
114
|
+
*/
|
|
115
|
+
evict(): Promise<number>;
|
|
116
|
+
/**
|
|
117
|
+
* Get cache statistics
|
|
118
|
+
*/
|
|
119
|
+
getStats(): Promise<CacheStats>;
|
|
120
|
+
/**
|
|
121
|
+
* Clear all cache entries
|
|
122
|
+
*/
|
|
123
|
+
clear(): Promise<number>;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Compute hash of file contents
|
|
127
|
+
*/
|
|
128
|
+
export declare function hashFileContents(filePath: string): Promise<string>;
|
|
129
|
+
/**
|
|
130
|
+
* Compute hash of scanner rules/config
|
|
131
|
+
*
|
|
132
|
+
* This is used to invalidate cache when rules change.
|
|
133
|
+
*/
|
|
134
|
+
export declare function hashRules(rules: string[] | undefined, configFile?: string): string;
|
|
135
|
+
/**
|
|
136
|
+
* Run scanner with caching
|
|
137
|
+
*
|
|
138
|
+
* Wraps a scanner function to use the cache. Only scans files that:
|
|
139
|
+
* 1. Are not in cache
|
|
140
|
+
* 2. Have changed since last scan
|
|
141
|
+
* 3. Were scanned with different scanner version or rules
|
|
142
|
+
*/
|
|
143
|
+
export declare function runScannerWithCache<T extends ScannerResult>(cache: ScannerCache, scanner: ScannerType, scannerVersion: string, ruleHash: string, files: Array<{
|
|
144
|
+
path: string;
|
|
145
|
+
hash: string;
|
|
146
|
+
}>, scanFn: (filePaths: string[]) => Promise<T>): Promise<{
|
|
147
|
+
result: T;
|
|
148
|
+
cacheHits: number;
|
|
149
|
+
cacheMisses: number;
|
|
150
|
+
savedTimeMs: number;
|
|
151
|
+
}>;
|
|
152
|
+
/**
|
|
153
|
+
* Create a default scanner cache instance
|
|
154
|
+
*/
|
|
155
|
+
export declare function createScannerCache(projectPath: string, options?: ScannerCacheOptions): ScannerCache;
|
|
156
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/scanners/cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Incremental Scanner Cache
|
|
3
|
+
*
|
|
4
|
+
* Caches scanner results to enable incremental scanning. Only changed files
|
|
5
|
+
* are re-scanned, dramatically improving performance on subsequent runs.
|
|
6
|
+
*
|
|
7
|
+
* Cache structure:
|
|
8
|
+
* ```
|
|
9
|
+
* .vaspera/cache/scanners/{scanner}/{hash}.json
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* Cache key: sha256(filePath + fileHash + scannerVersion + ruleHash)
|
|
13
|
+
*
|
|
14
|
+
* @module scanners/cache
|
|
15
|
+
*/
|
|
16
|
+
import { createHash } from "crypto";
|
|
17
|
+
import { readFile, writeFile, readdir, mkdir, unlink, stat } from "fs/promises";
|
|
18
|
+
import { join } from "path";
|
|
19
|
+
import { logger } from "../logger.js";
|
|
20
|
+
const DEFAULT_OPTIONS = {
|
|
21
|
+
maxEntriesPerScanner: 10000,
|
|
22
|
+
maxAgeMs: 7 * 24 * 60 * 60 * 1000, // 7 days
|
|
23
|
+
cacheDir: ".vaspera/cache/scanners",
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Scanner cache manager
|
|
27
|
+
*
|
|
28
|
+
* Provides LRU cache with configurable limits per scanner type.
|
|
29
|
+
*/
|
|
30
|
+
export class ScannerCache {
|
|
31
|
+
cacheDir;
|
|
32
|
+
maxEntriesPerScanner;
|
|
33
|
+
maxAgeMs;
|
|
34
|
+
projectPath;
|
|
35
|
+
constructor(projectPath, options = {}) {
|
|
36
|
+
this.projectPath = projectPath;
|
|
37
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
38
|
+
this.cacheDir = join(projectPath, opts.cacheDir);
|
|
39
|
+
this.maxEntriesPerScanner = opts.maxEntriesPerScanner;
|
|
40
|
+
this.maxAgeMs = opts.maxAgeMs;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Generate a cache key for a file + scanner + version + rules combination
|
|
44
|
+
*/
|
|
45
|
+
generateCacheKey(filePath, fileHash, scanner, scannerVersion, ruleHash) {
|
|
46
|
+
const input = `${filePath}:${fileHash}:${scanner}:${scannerVersion}:${ruleHash}`;
|
|
47
|
+
return createHash("sha256").update(input).digest("hex");
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get the cache file path for a given key
|
|
51
|
+
*/
|
|
52
|
+
getCachePath(scanner, key) {
|
|
53
|
+
// Use first 2 chars as subdirectory for better filesystem performance
|
|
54
|
+
const subdir = key.slice(0, 2);
|
|
55
|
+
return join(this.cacheDir, scanner, subdir, `${key}.json`);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Ensure cache directory exists
|
|
59
|
+
*/
|
|
60
|
+
async ensureCacheDir(scanner, key) {
|
|
61
|
+
const subdir = key.slice(0, 2);
|
|
62
|
+
const dir = join(this.cacheDir, scanner, subdir);
|
|
63
|
+
await mkdir(dir, { recursive: true });
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Look up cached results for a file
|
|
67
|
+
*/
|
|
68
|
+
async lookup(filePath, fileHash, scanner, scannerVersion, ruleHash) {
|
|
69
|
+
const key = this.generateCacheKey(filePath, fileHash, scanner, scannerVersion, ruleHash);
|
|
70
|
+
const cachePath = this.getCachePath(scanner, key);
|
|
71
|
+
try {
|
|
72
|
+
const content = await readFile(cachePath, "utf-8");
|
|
73
|
+
const entry = JSON.parse(content);
|
|
74
|
+
// Validate entry version
|
|
75
|
+
if (entry.version !== 1) {
|
|
76
|
+
return { hit: false, missReason: "version_mismatch" };
|
|
77
|
+
}
|
|
78
|
+
// Check scanner version
|
|
79
|
+
if (entry.scannerVersion !== scannerVersion) {
|
|
80
|
+
return { hit: false, missReason: "version_mismatch" };
|
|
81
|
+
}
|
|
82
|
+
// Check rule hash
|
|
83
|
+
if (entry.ruleHash !== ruleHash) {
|
|
84
|
+
return { hit: false, missReason: "rule_mismatch" };
|
|
85
|
+
}
|
|
86
|
+
// Check file hash
|
|
87
|
+
if (entry.fileHash !== fileHash) {
|
|
88
|
+
return { hit: false, missReason: "file_changed" };
|
|
89
|
+
}
|
|
90
|
+
// Check age
|
|
91
|
+
const age = Date.now() - new Date(entry.cachedAt).getTime();
|
|
92
|
+
if (age > this.maxAgeMs) {
|
|
93
|
+
return { hit: false, missReason: "expired" };
|
|
94
|
+
}
|
|
95
|
+
logger.debug("scanner_cache.hit", {
|
|
96
|
+
scanner,
|
|
97
|
+
filePath,
|
|
98
|
+
findingsCount: entry.findings.length,
|
|
99
|
+
});
|
|
100
|
+
return { hit: true, entry };
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return { hit: false, missReason: "not_found" };
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Store scanner results in cache
|
|
108
|
+
*/
|
|
109
|
+
async store(filePath, fileHash, scanner, scannerVersion, ruleHash, findings, scanDuration) {
|
|
110
|
+
const key = this.generateCacheKey(filePath, fileHash, scanner, scannerVersion, ruleHash);
|
|
111
|
+
const entry = {
|
|
112
|
+
version: 1,
|
|
113
|
+
scanner,
|
|
114
|
+
scannerVersion,
|
|
115
|
+
ruleHash,
|
|
116
|
+
filePath,
|
|
117
|
+
fileHash,
|
|
118
|
+
findings,
|
|
119
|
+
cachedAt: new Date().toISOString(),
|
|
120
|
+
scanDuration,
|
|
121
|
+
};
|
|
122
|
+
try {
|
|
123
|
+
await this.ensureCacheDir(scanner, key);
|
|
124
|
+
const cachePath = this.getCachePath(scanner, key);
|
|
125
|
+
await writeFile(cachePath, JSON.stringify(entry), "utf-8");
|
|
126
|
+
logger.debug("scanner_cache.stored", {
|
|
127
|
+
scanner,
|
|
128
|
+
filePath,
|
|
129
|
+
findingsCount: findings.length,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
logger.warn("scanner_cache.store_error", {
|
|
134
|
+
scanner,
|
|
135
|
+
filePath,
|
|
136
|
+
error: String(error),
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Invalidate cache for a specific file
|
|
142
|
+
*/
|
|
143
|
+
async invalidate(filePath, scanner) {
|
|
144
|
+
let invalidated = 0;
|
|
145
|
+
const scanners = scanner
|
|
146
|
+
? [scanner]
|
|
147
|
+
: ["semgrep", "npm-audit", "gitleaks", "tsc", "eslint", "bandit", "gosec", "brakeman", "trivy"];
|
|
148
|
+
for (const s of scanners) {
|
|
149
|
+
const scannerDir = join(this.cacheDir, s);
|
|
150
|
+
try {
|
|
151
|
+
const subdirs = await readdir(scannerDir);
|
|
152
|
+
for (const subdir of subdirs) {
|
|
153
|
+
const subdirPath = join(scannerDir, subdir);
|
|
154
|
+
const files = await readdir(subdirPath);
|
|
155
|
+
for (const file of files) {
|
|
156
|
+
try {
|
|
157
|
+
const content = await readFile(join(subdirPath, file), "utf-8");
|
|
158
|
+
const entry = JSON.parse(content);
|
|
159
|
+
if (entry.filePath === filePath) {
|
|
160
|
+
await unlink(join(subdirPath, file));
|
|
161
|
+
invalidated++;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
// Ignore individual file errors
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
// Scanner directory doesn't exist
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
logger.debug("scanner_cache.invalidated", {
|
|
175
|
+
filePath,
|
|
176
|
+
scanner,
|
|
177
|
+
count: invalidated,
|
|
178
|
+
});
|
|
179
|
+
return invalidated;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Run LRU eviction to stay within limits
|
|
183
|
+
*/
|
|
184
|
+
async evict() {
|
|
185
|
+
let evicted = 0;
|
|
186
|
+
const scanners = [
|
|
187
|
+
"semgrep", "npm-audit", "gitleaks", "tsc", "eslint",
|
|
188
|
+
"bandit", "gosec", "brakeman", "trivy",
|
|
189
|
+
];
|
|
190
|
+
for (const scanner of scanners) {
|
|
191
|
+
const scannerDir = join(this.cacheDir, scanner);
|
|
192
|
+
const entries = [];
|
|
193
|
+
try {
|
|
194
|
+
const subdirs = await readdir(scannerDir);
|
|
195
|
+
for (const subdir of subdirs) {
|
|
196
|
+
const subdirPath = join(scannerDir, subdir);
|
|
197
|
+
try {
|
|
198
|
+
const files = await readdir(subdirPath);
|
|
199
|
+
for (const file of files) {
|
|
200
|
+
const filePath = join(subdirPath, file);
|
|
201
|
+
try {
|
|
202
|
+
const stats = await stat(filePath);
|
|
203
|
+
entries.push({ path: filePath, mtime: stats.mtimeMs });
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
// Ignore stat errors
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
// Ignore readdir errors
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
// Scanner directory doesn't exist
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
// Sort by mtime (oldest first)
|
|
220
|
+
entries.sort((a, b) => a.mtime - b.mtime);
|
|
221
|
+
// Evict oldest entries if over limit
|
|
222
|
+
const toEvict = entries.length - this.maxEntriesPerScanner;
|
|
223
|
+
if (toEvict > 0) {
|
|
224
|
+
for (let i = 0; i < toEvict; i++) {
|
|
225
|
+
try {
|
|
226
|
+
await unlink(entries[i].path);
|
|
227
|
+
evicted++;
|
|
228
|
+
}
|
|
229
|
+
catch {
|
|
230
|
+
// Ignore unlink errors
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
// Also evict expired entries
|
|
235
|
+
const now = Date.now();
|
|
236
|
+
for (const entry of entries.slice(toEvict > 0 ? toEvict : 0)) {
|
|
237
|
+
if (now - entry.mtime > this.maxAgeMs) {
|
|
238
|
+
try {
|
|
239
|
+
await unlink(entry.path);
|
|
240
|
+
evicted++;
|
|
241
|
+
}
|
|
242
|
+
catch {
|
|
243
|
+
// Ignore unlink errors
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
if (evicted > 0) {
|
|
249
|
+
logger.info("scanner_cache.evicted", { count: evicted });
|
|
250
|
+
}
|
|
251
|
+
return evicted;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Get cache statistics
|
|
255
|
+
*/
|
|
256
|
+
async getStats() {
|
|
257
|
+
const stats = {
|
|
258
|
+
totalEntries: 0,
|
|
259
|
+
totalSizeBytes: 0,
|
|
260
|
+
byScanner: {
|
|
261
|
+
semgrep: 0,
|
|
262
|
+
"npm-audit": 0,
|
|
263
|
+
gitleaks: 0,
|
|
264
|
+
tsc: 0,
|
|
265
|
+
eslint: 0,
|
|
266
|
+
bandit: 0,
|
|
267
|
+
gosec: 0,
|
|
268
|
+
brakeman: 0,
|
|
269
|
+
trivy: 0,
|
|
270
|
+
"binary-analysis": 0,
|
|
271
|
+
"memory-safety": 0,
|
|
272
|
+
"race-condition": 0,
|
|
273
|
+
healthcare: 0,
|
|
274
|
+
plugin: 0,
|
|
275
|
+
},
|
|
276
|
+
};
|
|
277
|
+
let oldestTime = Infinity;
|
|
278
|
+
let newestTime = 0;
|
|
279
|
+
const scanners = Object.keys(stats.byScanner);
|
|
280
|
+
for (const scanner of scanners) {
|
|
281
|
+
const scannerDir = join(this.cacheDir, scanner);
|
|
282
|
+
try {
|
|
283
|
+
const subdirs = await readdir(scannerDir);
|
|
284
|
+
for (const subdir of subdirs) {
|
|
285
|
+
const subdirPath = join(scannerDir, subdir);
|
|
286
|
+
try {
|
|
287
|
+
const files = await readdir(subdirPath);
|
|
288
|
+
for (const file of files) {
|
|
289
|
+
try {
|
|
290
|
+
const fileStat = await stat(join(subdirPath, file));
|
|
291
|
+
stats.totalEntries++;
|
|
292
|
+
stats.byScanner[scanner]++;
|
|
293
|
+
stats.totalSizeBytes += fileStat.size;
|
|
294
|
+
if (fileStat.mtimeMs < oldestTime) {
|
|
295
|
+
oldestTime = fileStat.mtimeMs;
|
|
296
|
+
stats.oldestEntry = new Date(fileStat.mtimeMs).toISOString();
|
|
297
|
+
}
|
|
298
|
+
if (fileStat.mtimeMs > newestTime) {
|
|
299
|
+
newestTime = fileStat.mtimeMs;
|
|
300
|
+
stats.newestEntry = new Date(fileStat.mtimeMs).toISOString();
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
catch {
|
|
304
|
+
// Ignore stat errors
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
catch {
|
|
309
|
+
// Ignore readdir errors
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
catch {
|
|
314
|
+
// Scanner directory doesn't exist
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return stats;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Clear all cache entries
|
|
321
|
+
*/
|
|
322
|
+
async clear() {
|
|
323
|
+
let cleared = 0;
|
|
324
|
+
const scanners = [
|
|
325
|
+
"semgrep", "npm-audit", "gitleaks", "tsc", "eslint",
|
|
326
|
+
"bandit", "gosec", "brakeman", "trivy",
|
|
327
|
+
];
|
|
328
|
+
for (const scanner of scanners) {
|
|
329
|
+
const scannerDir = join(this.cacheDir, scanner);
|
|
330
|
+
try {
|
|
331
|
+
const subdirs = await readdir(scannerDir);
|
|
332
|
+
for (const subdir of subdirs) {
|
|
333
|
+
const subdirPath = join(scannerDir, subdir);
|
|
334
|
+
try {
|
|
335
|
+
const files = await readdir(subdirPath);
|
|
336
|
+
for (const file of files) {
|
|
337
|
+
try {
|
|
338
|
+
await unlink(join(subdirPath, file));
|
|
339
|
+
cleared++;
|
|
340
|
+
}
|
|
341
|
+
catch {
|
|
342
|
+
// Ignore unlink errors
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
catch {
|
|
347
|
+
// Ignore readdir errors
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
catch {
|
|
352
|
+
// Scanner directory doesn't exist
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
logger.info("scanner_cache.cleared", { count: cleared });
|
|
356
|
+
return cleared;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Compute hash of file contents
|
|
361
|
+
*/
|
|
362
|
+
export async function hashFileContents(filePath) {
|
|
363
|
+
const content = await readFile(filePath);
|
|
364
|
+
return createHash("sha256").update(content).digest("hex");
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Compute hash of scanner rules/config
|
|
368
|
+
*
|
|
369
|
+
* This is used to invalidate cache when rules change.
|
|
370
|
+
*/
|
|
371
|
+
export function hashRules(rules, configFile) {
|
|
372
|
+
const input = JSON.stringify({ rules: rules?.sort() || [], configFile });
|
|
373
|
+
return createHash("sha256").update(input).digest("hex").slice(0, 16);
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Run scanner with caching
|
|
377
|
+
*
|
|
378
|
+
* Wraps a scanner function to use the cache. Only scans files that:
|
|
379
|
+
* 1. Are not in cache
|
|
380
|
+
* 2. Have changed since last scan
|
|
381
|
+
* 3. Were scanned with different scanner version or rules
|
|
382
|
+
*/
|
|
383
|
+
export async function runScannerWithCache(cache, scanner, scannerVersion, ruleHash, files, scanFn) {
|
|
384
|
+
const startTime = Date.now();
|
|
385
|
+
const cachedFindings = [];
|
|
386
|
+
const filesToScan = [];
|
|
387
|
+
let cacheHits = 0;
|
|
388
|
+
let cacheMisses = 0;
|
|
389
|
+
let savedTimeMs = 0;
|
|
390
|
+
// Check cache for each file
|
|
391
|
+
for (const file of files) {
|
|
392
|
+
const lookup = await cache.lookup(file.path, file.hash, scanner, scannerVersion, ruleHash);
|
|
393
|
+
if (lookup.hit && lookup.entry) {
|
|
394
|
+
cacheHits++;
|
|
395
|
+
cachedFindings.push(...lookup.entry.findings);
|
|
396
|
+
savedTimeMs += lookup.entry.scanDuration;
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
cacheMisses++;
|
|
400
|
+
filesToScan.push(file.path);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
// Run scanner only on uncached files
|
|
404
|
+
let scanResult;
|
|
405
|
+
if (filesToScan.length > 0) {
|
|
406
|
+
scanResult = await scanFn(filesToScan);
|
|
407
|
+
// Store new results in cache (group findings by file)
|
|
408
|
+
const findingsByFile = new Map();
|
|
409
|
+
for (const finding of scanResult.findings) {
|
|
410
|
+
const existing = findingsByFile.get(finding.file) || [];
|
|
411
|
+
existing.push(finding);
|
|
412
|
+
findingsByFile.set(finding.file, existing);
|
|
413
|
+
}
|
|
414
|
+
const scanDurationPerFile = scanResult.duration / Math.max(filesToScan.length, 1);
|
|
415
|
+
for (const file of files) {
|
|
416
|
+
if (filesToScan.includes(file.path)) {
|
|
417
|
+
const fileFindings = findingsByFile.get(file.path) || [];
|
|
418
|
+
await cache.store(file.path, file.hash, scanner, scannerVersion, ruleHash, fileFindings, scanDurationPerFile);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
else {
|
|
423
|
+
// All files were cached, return empty scanner result
|
|
424
|
+
scanResult = {
|
|
425
|
+
scanner,
|
|
426
|
+
findings: [],
|
|
427
|
+
duration: 0,
|
|
428
|
+
success: true,
|
|
429
|
+
version: scannerVersion,
|
|
430
|
+
filesScanned: 0,
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
// Combine cached findings with new findings
|
|
434
|
+
const combinedFindings = [...cachedFindings, ...scanResult.findings];
|
|
435
|
+
const result = {
|
|
436
|
+
...scanResult,
|
|
437
|
+
findings: combinedFindings,
|
|
438
|
+
filesScanned: files.length,
|
|
439
|
+
};
|
|
440
|
+
const totalTime = Date.now() - startTime;
|
|
441
|
+
logger.info("scanner_cache.run_complete", {
|
|
442
|
+
scanner,
|
|
443
|
+
cacheHits,
|
|
444
|
+
cacheMisses,
|
|
445
|
+
savedTimeMs,
|
|
446
|
+
actualTimeMs: totalTime,
|
|
447
|
+
totalFindings: combinedFindings.length,
|
|
448
|
+
});
|
|
449
|
+
return {
|
|
450
|
+
result,
|
|
451
|
+
cacheHits,
|
|
452
|
+
cacheMisses,
|
|
453
|
+
savedTimeMs,
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Create a default scanner cache instance
|
|
458
|
+
*/
|
|
459
|
+
export function createScannerCache(projectPath, options) {
|
|
460
|
+
return new ScannerCache(projectPath, options);
|
|
461
|
+
}
|
|
462
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/scanners/cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dependencies.d.ts","sourceRoot":"","sources":["../../src/scanners/dependencies.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAwB,aAAa,EAAE,MAAM,YAAY,CAAC;AAyDtE;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAgEpF;
|
|
1
|
+
{"version":3,"file":"dependencies.d.ts","sourceRoot":"","sources":["../../src/scanners/dependencies.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAwB,aAAa,EAAE,MAAM,YAAY,CAAC;AAyDtE;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAgEpF;AAwHD;;GAEG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC;IACjD,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CAsBD"}
|