vaspera 2.11.0 → 2.13.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 +46 -0
- package/dist/__tests__/audit-trail.test.d.ts +7 -0
- package/dist/__tests__/audit-trail.test.d.ts.map +1 -0
- package/dist/__tests__/audit-trail.test.js +336 -0
- package/dist/__tests__/audit-trail.test.js.map +1 -0
- package/dist/__tests__/property-test-helpers.d.ts +1 -1
- package/dist/__tests__/siem-integration.test.d.ts +7 -0
- package/dist/__tests__/siem-integration.test.d.ts.map +1 -0
- package/dist/__tests__/siem-integration.test.js +285 -0
- package/dist/__tests__/siem-integration.test.js.map +1 -0
- 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/autofix/ast/__tests__/typescript.test.d.ts +5 -0
- package/dist/autofix/ast/__tests__/typescript.test.d.ts.map +1 -0
- package/dist/autofix/ast/__tests__/typescript.test.js +210 -0
- package/dist/autofix/ast/__tests__/typescript.test.js.map +1 -0
- package/dist/autofix/ast/index.d.ts +11 -0
- package/dist/autofix/ast/index.d.ts.map +1 -0
- package/dist/autofix/ast/index.js +11 -0
- package/dist/autofix/ast/index.js.map +1 -0
- package/dist/autofix/ast/types.d.ts +77 -0
- package/dist/autofix/ast/types.d.ts.map +1 -0
- package/dist/autofix/ast/types.js +9 -0
- package/dist/autofix/ast/types.js.map +1 -0
- package/dist/autofix/ast/typescript.d.ts +17 -0
- package/dist/autofix/ast/typescript.d.ts.map +1 -0
- package/dist/autofix/ast/typescript.js +427 -0
- package/dist/autofix/ast/typescript.js.map +1 -0
- package/dist/autofix/constitution.schema.d.ts +21 -21
- package/dist/autofix/index.d.ts +1 -0
- package/dist/autofix/index.d.ts.map +1 -1
- package/dist/autofix/index.js +2 -0
- package/dist/autofix/index.js.map +1 -1
- package/dist/config/flags.d.ts +6 -6
- package/dist/history/store.d.ts +55 -1
- package/dist/history/store.d.ts.map +1 -1
- package/dist/history/store.js +152 -4
- package/dist/history/store.js.map +1 -1
- package/dist/history/types.d.ts +9 -5
- package/dist/history/types.d.ts.map +1 -1
- package/dist/history/verify.d.ts.map +1 -1
- package/dist/history/verify.js +5 -3
- package/dist/history/verify.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +923 -16
- package/dist/index.js.map +1 -1
- package/dist/integrations/siem/datadog.d.ts +44 -0
- package/dist/integrations/siem/datadog.d.ts.map +1 -0
- package/dist/integrations/siem/datadog.js +211 -0
- package/dist/integrations/siem/datadog.js.map +1 -0
- package/dist/integrations/siem/format.d.ts +59 -0
- package/dist/integrations/siem/format.d.ts.map +1 -0
- package/dist/integrations/siem/format.js +360 -0
- package/dist/integrations/siem/format.js.map +1 -0
- package/dist/integrations/siem/index.d.ts +56 -0
- package/dist/integrations/siem/index.d.ts.map +1 -0
- package/dist/integrations/siem/index.js +117 -0
- package/dist/integrations/siem/index.js.map +1 -0
- package/dist/integrations/siem/sentinel.d.ts +53 -0
- package/dist/integrations/siem/sentinel.d.ts.map +1 -0
- package/dist/integrations/siem/sentinel.js +231 -0
- package/dist/integrations/siem/sentinel.js.map +1 -0
- package/dist/integrations/siem/splunk.d.ts +46 -0
- package/dist/integrations/siem/splunk.d.ts.map +1 -0
- package/dist/integrations/siem/splunk.js +210 -0
- package/dist/integrations/siem/splunk.js.map +1 -0
- package/dist/integrations/siem/types.d.ts +210 -0
- package/dist/integrations/siem/types.d.ts.map +1 -0
- package/dist/integrations/siem/types.js +9 -0
- package/dist/integrations/siem/types.js.map +1 -0
- package/dist/persistence/__tests__/json-fallback.test.d.ts +5 -0
- package/dist/persistence/__tests__/json-fallback.test.d.ts.map +1 -0
- package/dist/persistence/__tests__/json-fallback.test.js +249 -0
- package/dist/persistence/__tests__/json-fallback.test.js.map +1 -0
- package/dist/persistence/__tests__/persistence.test.d.ts +5 -0
- package/dist/persistence/__tests__/persistence.test.d.ts.map +1 -0
- package/dist/persistence/__tests__/persistence.test.js +369 -0
- package/dist/persistence/__tests__/persistence.test.js.map +1 -0
- package/dist/persistence/db.d.ts +30 -0
- package/dist/persistence/db.d.ts.map +1 -0
- package/dist/persistence/db.js +128 -0
- package/dist/persistence/db.js.map +1 -0
- package/dist/persistence/index.d.ts +75 -0
- package/dist/persistence/index.d.ts.map +1 -0
- package/dist/persistence/index.js +268 -0
- package/dist/persistence/index.js.map +1 -0
- package/dist/persistence/json-fallback.d.ts +52 -0
- package/dist/persistence/json-fallback.d.ts.map +1 -0
- package/dist/persistence/json-fallback.js +283 -0
- package/dist/persistence/json-fallback.js.map +1 -0
- package/dist/persistence/migrations/index.d.ts +10 -0
- package/dist/persistence/migrations/index.d.ts.map +1 -0
- package/dist/persistence/migrations/index.js +125 -0
- package/dist/persistence/migrations/index.js.map +1 -0
- package/dist/persistence/repositories/findings.d.ts +41 -0
- package/dist/persistence/repositories/findings.d.ts.map +1 -0
- package/dist/persistence/repositories/findings.js +238 -0
- package/dist/persistence/repositories/findings.js.map +1 -0
- package/dist/persistence/repositories/projects.d.ts +22 -0
- package/dist/persistence/repositories/projects.d.ts.map +1 -0
- package/dist/persistence/repositories/projects.js +71 -0
- package/dist/persistence/repositories/projects.js.map +1 -0
- package/dist/persistence/repositories/scans.d.ts +30 -0
- package/dist/persistence/repositories/scans.d.ts.map +1 -0
- package/dist/persistence/repositories/scans.js +107 -0
- package/dist/persistence/repositories/scans.js.map +1 -0
- package/dist/persistence/repositories/trends.d.ts +42 -0
- package/dist/persistence/repositories/trends.d.ts.map +1 -0
- package/dist/persistence/repositories/trends.js +178 -0
- package/dist/persistence/repositories/trends.js.map +1 -0
- package/dist/persistence/types.d.ts +105 -0
- package/dist/persistence/types.d.ts.map +1 -0
- package/dist/persistence/types.js +13 -0
- package/dist/persistence/types.js.map +1 -0
- package/dist/plugins/types.d.ts +2 -2
- package/dist/scanners/ai-code/index.d.ts.map +1 -1
- package/dist/scanners/ai-code/index.js +90 -2
- package/dist/scanners/ai-code/index.js.map +1 -1
- package/dist/scanners/ai-code/types.d.ts +24 -12
- package/dist/scanners/ai-code/types.d.ts.map +1 -1
- package/dist/scanners/cache.d.ts.map +1 -1
- package/dist/scanners/cache.js +1 -0
- package/dist/scanners/cache.js.map +1 -1
- package/dist/scanners/deploy/types.d.ts +13 -13
- package/dist/scanners/detection/__tests__/detection.test.d.ts +5 -0
- package/dist/scanners/detection/__tests__/detection.test.d.ts.map +1 -0
- package/dist/scanners/detection/__tests__/detection.test.js +265 -0
- package/dist/scanners/detection/__tests__/detection.test.js.map +1 -0
- package/dist/scanners/detection/engines/ast-query.d.ts +23 -0
- package/dist/scanners/detection/engines/ast-query.d.ts.map +1 -0
- package/dist/scanners/detection/engines/ast-query.js +232 -0
- package/dist/scanners/detection/engines/ast-query.js.map +1 -0
- package/dist/scanners/detection/engines/data-flow.d.ts +12 -0
- package/dist/scanners/detection/engines/data-flow.d.ts.map +1 -0
- package/dist/scanners/detection/engines/data-flow.js +269 -0
- package/dist/scanners/detection/engines/data-flow.js.map +1 -0
- package/dist/scanners/detection/index.d.ts +29 -0
- package/dist/scanners/detection/index.d.ts.map +1 -0
- package/dist/scanners/detection/index.js +140 -0
- package/dist/scanners/detection/index.js.map +1 -0
- package/dist/scanners/detection/rules/builtin.d.ts +14 -0
- package/dist/scanners/detection/rules/builtin.d.ts.map +1 -0
- package/dist/scanners/detection/rules/builtin.js +307 -0
- package/dist/scanners/detection/rules/builtin.js.map +1 -0
- package/dist/scanners/detection/rules/loader.d.ts +19 -0
- package/dist/scanners/detection/rules/loader.d.ts.map +1 -0
- package/dist/scanners/detection/rules/loader.js +111 -0
- package/dist/scanners/detection/rules/loader.js.map +1 -0
- package/dist/scanners/detection/types.d.ts +171 -0
- package/dist/scanners/detection/types.d.ts.map +1 -0
- package/dist/scanners/detection/types.js +36 -0
- package/dist/scanners/detection/types.js.map +1 -0
- package/dist/scanners/eslint.d.ts.map +1 -1
- package/dist/scanners/eslint.js +45 -3
- package/dist/scanners/eslint.js.map +1 -1
- package/dist/scanners/index.d.ts +9 -1
- package/dist/scanners/index.d.ts.map +1 -1
- package/dist/scanners/index.js +64 -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/scale/bottleneck-detector.d.ts +13 -2
- package/dist/scanners/scale/bottleneck-detector.d.ts.map +1 -1
- package/dist/scanners/scale/bottleneck-detector.js +199 -72
- package/dist/scanners/scale/bottleneck-detector.js.map +1 -1
- package/dist/scanners/scale/types.d.ts +3 -3
- package/dist/scanners/types.d.ts +19 -2
- 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.d.ts.map +1 -1
- package/dist/scanners/typescript.js +36 -4
- package/dist/scanners/typescript.js.map +1 -1
- package/package.json +5 -1
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON File Fallback Storage
|
|
3
|
+
*
|
|
4
|
+
* Provides fallback storage when SQLite is unavailable.
|
|
5
|
+
* Uses atomic writes (temp file → rename) for data safety.
|
|
6
|
+
*
|
|
7
|
+
* @module persistence/json-fallback
|
|
8
|
+
*/
|
|
9
|
+
import { readFile, writeFile, rename, mkdir } from "fs/promises";
|
|
10
|
+
import { existsSync } from "fs";
|
|
11
|
+
import { join } from "path";
|
|
12
|
+
import { randomUUID } from "crypto";
|
|
13
|
+
import { tmpdir } from "os";
|
|
14
|
+
import { logger } from "../logger.js";
|
|
15
|
+
const FALLBACK_VERSION = 1;
|
|
16
|
+
export class JsonFallbackStorage {
|
|
17
|
+
data;
|
|
18
|
+
filePath;
|
|
19
|
+
isDirty = false;
|
|
20
|
+
constructor(filePath, data) {
|
|
21
|
+
this.filePath = filePath;
|
|
22
|
+
this.data = data;
|
|
23
|
+
}
|
|
24
|
+
static async create(projectPath) {
|
|
25
|
+
const fallbackDir = join(projectPath, ".vaspera");
|
|
26
|
+
const filePath = join(fallbackDir, "findings-fallback.json");
|
|
27
|
+
await mkdir(fallbackDir, { recursive: true });
|
|
28
|
+
let data;
|
|
29
|
+
if (existsSync(filePath)) {
|
|
30
|
+
try {
|
|
31
|
+
const content = await readFile(filePath, "utf-8");
|
|
32
|
+
data = JSON.parse(content);
|
|
33
|
+
if (data.version !== FALLBACK_VERSION) {
|
|
34
|
+
data = createEmptyData();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
data = createEmptyData();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
data = createEmptyData();
|
|
43
|
+
}
|
|
44
|
+
logger.info("persistence.fallback.initialized", { path: filePath });
|
|
45
|
+
return new JsonFallbackStorage(filePath, data);
|
|
46
|
+
}
|
|
47
|
+
async save() {
|
|
48
|
+
if (!this.isDirty)
|
|
49
|
+
return;
|
|
50
|
+
this.data.lastUpdated = new Date().toISOString();
|
|
51
|
+
const tempPath = join(tmpdir(), `vaspera-fallback-${randomUUID()}.json`);
|
|
52
|
+
await writeFile(tempPath, JSON.stringify(this.data, null, 2), "utf-8");
|
|
53
|
+
await rename(tempPath, this.filePath);
|
|
54
|
+
this.isDirty = false;
|
|
55
|
+
}
|
|
56
|
+
findOrCreateProject(path) {
|
|
57
|
+
const existing = Object.values(this.data.projects).find((p) => p.path === path);
|
|
58
|
+
if (existing)
|
|
59
|
+
return existing;
|
|
60
|
+
const project = {
|
|
61
|
+
id: randomUUID(),
|
|
62
|
+
path,
|
|
63
|
+
name: path.split("/").pop() || path,
|
|
64
|
+
createdAt: new Date().toISOString(),
|
|
65
|
+
};
|
|
66
|
+
this.data.projects[project.id] = project;
|
|
67
|
+
this.isDirty = true;
|
|
68
|
+
return project;
|
|
69
|
+
}
|
|
70
|
+
findProjectByPath(path) {
|
|
71
|
+
return Object.values(this.data.projects).find((p) => p.path === path);
|
|
72
|
+
}
|
|
73
|
+
updateProjectLastScan(projectId) {
|
|
74
|
+
const project = this.data.projects[projectId];
|
|
75
|
+
if (project) {
|
|
76
|
+
project.lastScanAt = new Date().toISOString();
|
|
77
|
+
this.isDirty = true;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
createFinding(finding) {
|
|
81
|
+
const now = new Date().toISOString();
|
|
82
|
+
const persisted = {
|
|
83
|
+
...finding,
|
|
84
|
+
id: randomUUID(),
|
|
85
|
+
firstSeenAt: now,
|
|
86
|
+
lastSeenAt: now,
|
|
87
|
+
status: finding.status || "open",
|
|
88
|
+
};
|
|
89
|
+
this.data.findings[persisted.id] = persisted;
|
|
90
|
+
this.isDirty = true;
|
|
91
|
+
return persisted;
|
|
92
|
+
}
|
|
93
|
+
upsertFinding(finding) {
|
|
94
|
+
const existing = this.findBySignature(finding.projectId, finding.file, finding.line, finding.category, finding.scannerSource);
|
|
95
|
+
if (existing) {
|
|
96
|
+
existing.lastSeenAt = new Date().toISOString();
|
|
97
|
+
this.isDirty = true;
|
|
98
|
+
return { finding: existing, isNew: false };
|
|
99
|
+
}
|
|
100
|
+
const created = this.createFinding({ ...finding, status: "open" });
|
|
101
|
+
return { finding: created, isNew: true };
|
|
102
|
+
}
|
|
103
|
+
findBySignature(projectId, file, line, category, scannerSource) {
|
|
104
|
+
return Object.values(this.data.findings).find((f) => f.projectId === projectId &&
|
|
105
|
+
f.file === file &&
|
|
106
|
+
f.line === line &&
|
|
107
|
+
f.category === category &&
|
|
108
|
+
f.scannerSource === scannerSource &&
|
|
109
|
+
f.status !== "fixed");
|
|
110
|
+
}
|
|
111
|
+
findById(id) {
|
|
112
|
+
return this.data.findings[id];
|
|
113
|
+
}
|
|
114
|
+
findFindings(filter) {
|
|
115
|
+
let results = Object.values(this.data.findings);
|
|
116
|
+
if (filter.projectId) {
|
|
117
|
+
results = results.filter((f) => f.projectId === filter.projectId);
|
|
118
|
+
}
|
|
119
|
+
if (filter.certificationId) {
|
|
120
|
+
results = results.filter((f) => f.certificationId === filter.certificationId);
|
|
121
|
+
}
|
|
122
|
+
if (filter.severity) {
|
|
123
|
+
const severities = Array.isArray(filter.severity) ? filter.severity : [filter.severity];
|
|
124
|
+
results = results.filter((f) => severities.includes(f.severity));
|
|
125
|
+
}
|
|
126
|
+
if (filter.status) {
|
|
127
|
+
const statuses = Array.isArray(filter.status) ? filter.status : [filter.status];
|
|
128
|
+
results = results.filter((f) => statuses.includes(f.status));
|
|
129
|
+
}
|
|
130
|
+
if (filter.category) {
|
|
131
|
+
const categories = Array.isArray(filter.category) ? filter.category : [filter.category];
|
|
132
|
+
results = results.filter((f) => categories.includes(f.category));
|
|
133
|
+
}
|
|
134
|
+
if (filter.file) {
|
|
135
|
+
results = results.filter((f) => f.file.includes(filter.file));
|
|
136
|
+
}
|
|
137
|
+
if (filter.scannerSource) {
|
|
138
|
+
results = results.filter((f) => f.scannerSource === filter.scannerSource);
|
|
139
|
+
}
|
|
140
|
+
if (filter.sinceDate) {
|
|
141
|
+
results = results.filter((f) => f.firstSeenAt >= filter.sinceDate);
|
|
142
|
+
}
|
|
143
|
+
if (filter.untilDate) {
|
|
144
|
+
results = results.filter((f) => f.firstSeenAt <= filter.untilDate);
|
|
145
|
+
}
|
|
146
|
+
results.sort((a, b) => b.firstSeenAt.localeCompare(a.firstSeenAt));
|
|
147
|
+
if (filter.offset) {
|
|
148
|
+
results = results.slice(filter.offset);
|
|
149
|
+
}
|
|
150
|
+
if (filter.limit) {
|
|
151
|
+
results = results.slice(0, filter.limit);
|
|
152
|
+
}
|
|
153
|
+
return results;
|
|
154
|
+
}
|
|
155
|
+
updateFindingStatus(id, status, fixedBy) {
|
|
156
|
+
const finding = this.data.findings[id];
|
|
157
|
+
if (!finding)
|
|
158
|
+
return false;
|
|
159
|
+
finding.status = status;
|
|
160
|
+
if (status === "fixed") {
|
|
161
|
+
finding.fixedAt = new Date().toISOString();
|
|
162
|
+
if (fixedBy) {
|
|
163
|
+
finding.fixedBy = fixedBy;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
this.isDirty = true;
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
markFixed(ids, fixedBy) {
|
|
170
|
+
let count = 0;
|
|
171
|
+
for (const id of ids) {
|
|
172
|
+
if (this.updateFindingStatus(id, "fixed", fixedBy)) {
|
|
173
|
+
count++;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return count;
|
|
177
|
+
}
|
|
178
|
+
markFalsePositive(id, reason) {
|
|
179
|
+
const finding = this.data.findings[id];
|
|
180
|
+
if (!finding)
|
|
181
|
+
return false;
|
|
182
|
+
finding.status = "false_positive";
|
|
183
|
+
finding.falsePositive = true;
|
|
184
|
+
finding.falsePositiveReason = reason;
|
|
185
|
+
this.isDirty = true;
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
188
|
+
getStats(projectId) {
|
|
189
|
+
const findings = Object.values(this.data.findings).filter((f) => f.projectId === projectId);
|
|
190
|
+
const openFindings = findings.filter((f) => f.status === "open");
|
|
191
|
+
const fixedFindings = findings.filter((f) => f.status === "fixed");
|
|
192
|
+
const falsePositives = findings.filter((f) => f.status === "false_positive");
|
|
193
|
+
const bySeverity = {
|
|
194
|
+
critical: 0,
|
|
195
|
+
high: 0,
|
|
196
|
+
medium: 0,
|
|
197
|
+
low: 0,
|
|
198
|
+
info: 0,
|
|
199
|
+
};
|
|
200
|
+
const byCategory = {};
|
|
201
|
+
const byScanner = {};
|
|
202
|
+
for (const f of openFindings) {
|
|
203
|
+
bySeverity[f.severity] = (bySeverity[f.severity] || 0) + 1;
|
|
204
|
+
byCategory[f.category] = (byCategory[f.category] || 0) + 1;
|
|
205
|
+
}
|
|
206
|
+
for (const f of findings) {
|
|
207
|
+
byScanner[f.scannerSource] = (byScanner[f.scannerSource] || 0) + 1;
|
|
208
|
+
}
|
|
209
|
+
let avgMttrHours;
|
|
210
|
+
const fixedWithTime = fixedFindings.filter((f) => f.fixedAt);
|
|
211
|
+
if (fixedWithTime.length > 0) {
|
|
212
|
+
const totalHours = fixedWithTime.reduce((sum, f) => {
|
|
213
|
+
const fixed = new Date(f.fixedAt).getTime();
|
|
214
|
+
const seen = new Date(f.firstSeenAt).getTime();
|
|
215
|
+
return sum + (fixed - seen) / (1000 * 60 * 60);
|
|
216
|
+
}, 0);
|
|
217
|
+
avgMttrHours = totalHours / fixedWithTime.length;
|
|
218
|
+
}
|
|
219
|
+
const scans = Object.values(this.data.scans).filter((s) => s.projectId === projectId);
|
|
220
|
+
const scanDates = scans.map((s) => s.startedAt).sort();
|
|
221
|
+
return {
|
|
222
|
+
projectId,
|
|
223
|
+
totalFindings: findings.length,
|
|
224
|
+
openFindings: openFindings.length,
|
|
225
|
+
fixedFindings: fixedFindings.length,
|
|
226
|
+
falsePositives: falsePositives.length,
|
|
227
|
+
bySeverity,
|
|
228
|
+
byCategory,
|
|
229
|
+
byScanner,
|
|
230
|
+
avgMttrHours,
|
|
231
|
+
firstScanAt: scanDates[0],
|
|
232
|
+
lastScanAt: scanDates[scanDates.length - 1],
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
createScan(projectId, certificationId) {
|
|
236
|
+
const scan = {
|
|
237
|
+
id: randomUUID(),
|
|
238
|
+
projectId,
|
|
239
|
+
certificationId,
|
|
240
|
+
startedAt: new Date().toISOString(),
|
|
241
|
+
status: "running",
|
|
242
|
+
totalFindings: 0,
|
|
243
|
+
newFindings: 0,
|
|
244
|
+
fixedFindings: 0,
|
|
245
|
+
bySeverity: { critical: 0, high: 0, medium: 0, low: 0, info: 0 },
|
|
246
|
+
byScanner: {},
|
|
247
|
+
};
|
|
248
|
+
this.data.scans[scan.id] = scan;
|
|
249
|
+
this.isDirty = true;
|
|
250
|
+
return scan;
|
|
251
|
+
}
|
|
252
|
+
completeScan(scanId, results) {
|
|
253
|
+
const scan = this.data.scans[scanId];
|
|
254
|
+
if (!scan)
|
|
255
|
+
return;
|
|
256
|
+
scan.completedAt = new Date().toISOString();
|
|
257
|
+
scan.status = "completed";
|
|
258
|
+
scan.totalFindings = results.totalFindings;
|
|
259
|
+
scan.newFindings = results.newFindings;
|
|
260
|
+
scan.fixedFindings = results.fixedFindings;
|
|
261
|
+
scan.bySeverity = results.bySeverity;
|
|
262
|
+
scan.byScanner = results.byScanner;
|
|
263
|
+
scan.duration = results.duration;
|
|
264
|
+
this.isDirty = true;
|
|
265
|
+
}
|
|
266
|
+
close() {
|
|
267
|
+
// Sync save on close
|
|
268
|
+
if (this.isDirty) {
|
|
269
|
+
const content = JSON.stringify(this.data, null, 2);
|
|
270
|
+
require("fs").writeFileSync(this.filePath, content, "utf-8");
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
function createEmptyData() {
|
|
275
|
+
return {
|
|
276
|
+
version: FALLBACK_VERSION,
|
|
277
|
+
projects: {},
|
|
278
|
+
findings: {},
|
|
279
|
+
scans: {},
|
|
280
|
+
lastUpdated: new Date().toISOString(),
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
//# sourceMappingURL=json-fallback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-fallback.js","sourceRoot":"","sources":["../../src/persistence/json-fallback.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/persistence/migrations/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,eAAO,MAAM,UAAU,EAAE,SAAS,EAoHjC,CAAC"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database Migrations
|
|
3
|
+
*
|
|
4
|
+
* Schema migrations for the SQLite database.
|
|
5
|
+
*
|
|
6
|
+
* @module persistence/migrations
|
|
7
|
+
*/
|
|
8
|
+
export const MIGRATIONS = [
|
|
9
|
+
{
|
|
10
|
+
version: 1,
|
|
11
|
+
name: "initial_schema",
|
|
12
|
+
up: `
|
|
13
|
+
-- Projects table
|
|
14
|
+
CREATE TABLE IF NOT EXISTS projects (
|
|
15
|
+
id TEXT PRIMARY KEY,
|
|
16
|
+
path TEXT UNIQUE NOT NULL,
|
|
17
|
+
name TEXT NOT NULL,
|
|
18
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
19
|
+
last_scan_at TEXT,
|
|
20
|
+
metadata TEXT
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
CREATE INDEX IF NOT EXISTS idx_projects_path ON projects(path);
|
|
24
|
+
|
|
25
|
+
-- Findings table
|
|
26
|
+
CREATE TABLE IF NOT EXISTS findings (
|
|
27
|
+
id TEXT PRIMARY KEY,
|
|
28
|
+
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
29
|
+
certification_id TEXT,
|
|
30
|
+
severity TEXT NOT NULL CHECK (severity IN ('critical', 'high', 'medium', 'low', 'info')),
|
|
31
|
+
category TEXT NOT NULL,
|
|
32
|
+
file TEXT NOT NULL,
|
|
33
|
+
line INTEGER NOT NULL,
|
|
34
|
+
column_num INTEGER,
|
|
35
|
+
description TEXT NOT NULL,
|
|
36
|
+
scanner_source TEXT NOT NULL,
|
|
37
|
+
rule_id TEXT,
|
|
38
|
+
status TEXT NOT NULL DEFAULT 'open' CHECK (status IN ('open', 'fixed', 'wontfix', 'false_positive', 'in_progress')),
|
|
39
|
+
confidence INTEGER NOT NULL DEFAULT 100,
|
|
40
|
+
cwe_ids TEXT,
|
|
41
|
+
first_seen_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
42
|
+
last_seen_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
43
|
+
fixed_at TEXT,
|
|
44
|
+
fixed_by TEXT,
|
|
45
|
+
false_positive INTEGER DEFAULT 0,
|
|
46
|
+
false_positive_reason TEXT,
|
|
47
|
+
metadata TEXT
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
CREATE INDEX IF NOT EXISTS idx_findings_project ON findings(project_id);
|
|
51
|
+
CREATE INDEX IF NOT EXISTS idx_findings_severity ON findings(severity);
|
|
52
|
+
CREATE INDEX IF NOT EXISTS idx_findings_status ON findings(status);
|
|
53
|
+
CREATE INDEX IF NOT EXISTS idx_findings_category ON findings(category);
|
|
54
|
+
CREATE INDEX IF NOT EXISTS idx_findings_file ON findings(file);
|
|
55
|
+
CREATE INDEX IF NOT EXISTS idx_findings_first_seen ON findings(first_seen_at);
|
|
56
|
+
|
|
57
|
+
-- Scans table
|
|
58
|
+
CREATE TABLE IF NOT EXISTS scans (
|
|
59
|
+
id TEXT PRIMARY KEY,
|
|
60
|
+
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
61
|
+
certification_id TEXT,
|
|
62
|
+
started_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
63
|
+
completed_at TEXT,
|
|
64
|
+
status TEXT NOT NULL DEFAULT 'running' CHECK (status IN ('running', 'completed', 'failed', 'cancelled')),
|
|
65
|
+
total_findings INTEGER DEFAULT 0,
|
|
66
|
+
new_findings INTEGER DEFAULT 0,
|
|
67
|
+
fixed_findings INTEGER DEFAULT 0,
|
|
68
|
+
by_severity TEXT,
|
|
69
|
+
by_scanner TEXT,
|
|
70
|
+
duration INTEGER,
|
|
71
|
+
error TEXT,
|
|
72
|
+
metadata TEXT
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
CREATE INDEX IF NOT EXISTS idx_scans_project ON scans(project_id);
|
|
76
|
+
CREATE INDEX IF NOT EXISTS idx_scans_started ON scans(started_at);
|
|
77
|
+
CREATE INDEX IF NOT EXISTS idx_scans_status ON scans(status);
|
|
78
|
+
|
|
79
|
+
-- Trends table (pre-aggregated for performance)
|
|
80
|
+
CREATE TABLE IF NOT EXISTS trends (
|
|
81
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
82
|
+
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
83
|
+
period TEXT NOT NULL CHECK (period IN ('day', 'week', 'month')),
|
|
84
|
+
period_start TEXT NOT NULL,
|
|
85
|
+
period_end TEXT NOT NULL,
|
|
86
|
+
findings_new INTEGER DEFAULT 0,
|
|
87
|
+
findings_fixed INTEGER DEFAULT 0,
|
|
88
|
+
findings_open INTEGER DEFAULT 0,
|
|
89
|
+
mttr_hours REAL,
|
|
90
|
+
by_severity TEXT,
|
|
91
|
+
UNIQUE(project_id, period, period_start)
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
CREATE INDEX IF NOT EXISTS idx_trends_project_period ON trends(project_id, period, period_start);
|
|
95
|
+
`,
|
|
96
|
+
down: `
|
|
97
|
+
DROP TABLE IF EXISTS trends;
|
|
98
|
+
DROP TABLE IF EXISTS scans;
|
|
99
|
+
DROP TABLE IF EXISTS findings;
|
|
100
|
+
DROP TABLE IF EXISTS projects;
|
|
101
|
+
`,
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
version: 2,
|
|
105
|
+
name: "add_fix_history",
|
|
106
|
+
up: `
|
|
107
|
+
-- Fix history for tracking individual fixes
|
|
108
|
+
CREATE TABLE IF NOT EXISTS fix_history (
|
|
109
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
110
|
+
finding_id TEXT NOT NULL REFERENCES findings(id) ON DELETE CASCADE,
|
|
111
|
+
action TEXT NOT NULL CHECK (action IN ('fixed', 'reopened', 'marked_false_positive', 'unmarked_false_positive')),
|
|
112
|
+
performed_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
113
|
+
performed_by TEXT,
|
|
114
|
+
notes TEXT
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
CREATE INDEX IF NOT EXISTS idx_fix_history_finding ON fix_history(finding_id);
|
|
118
|
+
CREATE INDEX IF NOT EXISTS idx_fix_history_performed ON fix_history(performed_at);
|
|
119
|
+
`,
|
|
120
|
+
down: `
|
|
121
|
+
DROP TABLE IF EXISTS fix_history;
|
|
122
|
+
`,
|
|
123
|
+
},
|
|
124
|
+
];
|
|
125
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/persistence/migrations/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,MAAM,CAAC,MAAM,UAAU,GAAgB;IACrC;QACE,OAAO,EAAE,CAAC;QACV,IAAI,EAAE,gBAAgB;QACtB,EAAE,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAmFH;QACD,IAAI,EAAE;;;;;KAKL;KACF;IACD;QACE,OAAO,EAAE,CAAC;QACV,IAAI,EAAE,iBAAiB;QACvB,EAAE,EAAE;;;;;;;;;;;;;KAaH;QACD,IAAI,EAAE;;KAEL;KACF;CACF,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Findings Repository
|
|
3
|
+
*
|
|
4
|
+
* CRUD operations for security findings with status tracking.
|
|
5
|
+
*
|
|
6
|
+
* @module persistence/repositories/findings
|
|
7
|
+
*/
|
|
8
|
+
import type Database from "better-sqlite3";
|
|
9
|
+
import type { PersistedFinding, FindingStatus, ProjectStats } from "../types.js";
|
|
10
|
+
import type { Severity } from "../../certification/types.js";
|
|
11
|
+
export interface FindingFilter {
|
|
12
|
+
projectId?: string;
|
|
13
|
+
certificationId?: string;
|
|
14
|
+
severity?: Severity | Severity[];
|
|
15
|
+
status?: FindingStatus | FindingStatus[];
|
|
16
|
+
category?: string | string[];
|
|
17
|
+
file?: string;
|
|
18
|
+
scannerSource?: string;
|
|
19
|
+
sinceDate?: string;
|
|
20
|
+
untilDate?: string;
|
|
21
|
+
limit?: number;
|
|
22
|
+
offset?: number;
|
|
23
|
+
}
|
|
24
|
+
export declare class FindingsRepository {
|
|
25
|
+
private db;
|
|
26
|
+
constructor(db: Database.Database);
|
|
27
|
+
create(finding: Omit<PersistedFinding, "id" | "firstSeenAt" | "lastSeenAt">): PersistedFinding;
|
|
28
|
+
upsertFromScan(finding: Omit<PersistedFinding, "id" | "firstSeenAt" | "lastSeenAt" | "status">): {
|
|
29
|
+
finding: PersistedFinding;
|
|
30
|
+
isNew: boolean;
|
|
31
|
+
};
|
|
32
|
+
findById(id: string): PersistedFinding | undefined;
|
|
33
|
+
findBySignature(projectId: string, file: string, line: number, category: string, scannerSource: string): PersistedFinding | undefined;
|
|
34
|
+
find(filter: FindingFilter): PersistedFinding[];
|
|
35
|
+
updateStatus(id: string, status: FindingStatus, fixedBy?: string): boolean;
|
|
36
|
+
markFixed(ids: string[], fixedBy?: string): number;
|
|
37
|
+
markFalsePositive(id: string, reason?: string): boolean;
|
|
38
|
+
getStats(projectId: string): ProjectStats;
|
|
39
|
+
private mapRow;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=findings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"findings.d.ts","sourceRoot":"","sources":["../../../src/persistence/repositories/findings.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACjF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAG7D,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,QAAQ,GAAG,QAAQ,EAAE,CAAC;IACjC,MAAM,CAAC,EAAE,aAAa,GAAG,aAAa,EAAE,CAAC;IACzC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,kBAAkB;IACjB,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ,CAAC,QAAQ;IAEzC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,IAAI,GAAG,aAAa,GAAG,YAAY,CAAC,GAAG,gBAAgB;IAyC9F,cAAc,CACZ,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,IAAI,GAAG,aAAa,GAAG,YAAY,GAAG,QAAQ,CAAC,GAC9E;QAAE,OAAO,EAAE,gBAAgB,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE;IAwBhD,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAQlD,eAAe,CACb,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,GACpB,gBAAgB,GAAG,SAAS;IAY/B,IAAI,CAAC,MAAM,EAAE,aAAa,GAAG,gBAAgB,EAAE;IAoE/C,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO;IA8B1E,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM;IAYlD,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO;IAqBvD,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY;IA+EzC,OAAO,CAAC,MAAM;CAyBf"}
|