@prism-d1/cli 1.2.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/github-workflows/prism-eval-gate-kiro.yml +2 -2
- package/dist/assets/infra/bin/app.ts +61 -37
- package/dist/assets/infra/lib/constructs/security-agent-construct.ts +35 -30
- package/dist/assets/infra/lib/metrics-pipeline-stack.ts +2 -110
- package/dist/assets/infra/lib/security-agent-resources.ts +136 -0
- package/dist/assets/infra/lib/security-agent-stack.ts +69 -0
- package/dist/assets/pentest-cdk/bin/app.ts +12 -0
- package/dist/assets/pentest-cdk/cdk.json +7 -0
- package/dist/assets/pentest-cdk/lib/pentest-target-stack.ts +206 -0
- package/dist/assets/pentest-cdk/package.json +18 -0
- package/dist/assets/pentest-cdk/tsconfig.json +12 -0
- package/dist/src/aws/advice.d.ts +33 -0
- package/dist/src/aws/advice.d.ts.map +1 -0
- package/dist/src/aws/advice.js +174 -0
- package/dist/src/aws/advice.js.map +1 -0
- package/dist/src/aws/check.d.ts +64 -0
- package/dist/src/aws/check.d.ts.map +1 -0
- package/dist/src/aws/check.js +269 -0
- package/dist/src/aws/check.js.map +1 -0
- package/dist/src/aws/connect.d.ts +65 -0
- package/dist/src/aws/connect.d.ts.map +1 -0
- package/dist/src/aws/connect.js +250 -0
- package/dist/src/aws/connect.js.map +1 -0
- package/dist/src/aws/connection.d.ts +67 -0
- package/dist/src/aws/connection.d.ts.map +1 -0
- package/dist/src/aws/connection.js +137 -0
- package/dist/src/aws/connection.js.map +1 -0
- package/dist/src/aws/recommend.d.ts +70 -0
- package/dist/src/aws/recommend.d.ts.map +1 -0
- package/dist/src/aws/recommend.js +244 -0
- package/dist/src/aws/recommend.js.map +1 -0
- package/dist/src/aws/run-check.d.ts +31 -0
- package/dist/src/aws/run-check.d.ts.map +1 -0
- package/dist/src/aws/run-check.js +91 -0
- package/dist/src/aws/run-check.js.map +1 -0
- package/dist/src/codewatch/results.d.ts +155 -4
- package/dist/src/codewatch/results.d.ts.map +1 -1
- package/dist/src/codewatch/results.js +12 -2
- package/dist/src/codewatch/results.js.map +1 -1
- package/dist/src/commands/_top/version.d.ts +62 -0
- package/dist/src/commands/_top/version.d.ts.map +1 -0
- package/dist/src/commands/_top/version.js +175 -0
- package/dist/src/commands/_top/version.js.map +1 -0
- package/dist/src/commands/aws/check.d.ts +25 -0
- package/dist/src/commands/aws/check.d.ts.map +1 -0
- package/dist/src/commands/aws/check.js +42 -0
- package/dist/src/commands/aws/check.js.map +1 -0
- package/dist/src/commands/aws/connect.d.ts +16 -0
- package/dist/src/commands/aws/connect.d.ts.map +1 -0
- package/dist/src/commands/aws/connect.js +39 -0
- package/dist/src/commands/aws/connect.js.map +1 -0
- package/dist/src/commands/aws/recommend.d.ts +12 -0
- package/dist/src/commands/aws/recommend.d.ts.map +1 -0
- package/dist/src/commands/aws/recommend.js +21 -0
- package/dist/src/commands/aws/recommend.js.map +1 -0
- package/dist/src/commands/bedrock-protection/scan-account.d.ts.map +1 -1
- package/dist/src/commands/bedrock-protection/scan-account.js +14 -35
- package/dist/src/commands/bedrock-protection/scan-account.js.map +1 -1
- package/dist/src/commands/bedrock-protection/scan-org.d.ts.map +1 -1
- package/dist/src/commands/bedrock-protection/scan-org.js +12 -5
- package/dist/src/commands/bedrock-protection/scan-org.js.map +1 -1
- package/dist/src/commands/bootstrapper/setup-otel-sync.d.ts +12 -6
- package/dist/src/commands/bootstrapper/setup-otel-sync.d.ts.map +1 -1
- package/dist/src/commands/bootstrapper/setup-otel-sync.js +18 -409
- package/dist/src/commands/bootstrapper/setup-otel-sync.js.map +1 -1
- package/dist/src/commands/enable/codeburn.d.ts +59 -0
- package/dist/src/commands/enable/codeburn.d.ts.map +1 -0
- package/dist/src/commands/enable/codeburn.js +531 -0
- package/dist/src/commands/enable/codeburn.js.map +1 -0
- package/dist/src/commands/enable/security.d.ts +41 -0
- package/dist/src/commands/enable/security.d.ts.map +1 -0
- package/dist/src/commands/enable/security.js +128 -0
- package/dist/src/commands/enable/security.js.map +1 -0
- package/dist/src/commands/export/otel.d.ts +31 -0
- package/dist/src/commands/export/otel.d.ts.map +1 -0
- package/dist/src/commands/export/otel.js +52 -0
- package/dist/src/commands/export/otel.js.map +1 -0
- package/dist/src/commands/security/code-review.d.ts +22 -0
- package/dist/src/commands/security/code-review.d.ts.map +1 -0
- package/dist/src/commands/security/code-review.js +44 -0
- package/dist/src/commands/security/code-review.js.map +1 -0
- package/dist/src/commands/security/findings.d.ts +15 -0
- package/dist/src/commands/security/findings.d.ts.map +1 -0
- package/dist/src/commands/security/findings.js +33 -0
- package/dist/src/commands/security/findings.js.map +1 -0
- package/dist/src/commands/security/pentest.d.ts +18 -0
- package/dist/src/commands/security/pentest.d.ts.map +1 -0
- package/dist/src/commands/security/pentest.js +33 -0
- package/dist/src/commands/security/pentest.js.map +1 -0
- package/dist/src/commands/security/threat-model.d.ts +16 -0
- package/dist/src/commands/security/threat-model.d.ts.map +1 -0
- package/dist/src/commands/security/threat-model.js +25 -0
- package/dist/src/commands/security/threat-model.js.map +1 -0
- package/dist/src/commands/security/threats.d.ts +12 -0
- package/dist/src/commands/security/threats.d.ts.map +1 -0
- package/dist/src/commands/security/threats.js +24 -0
- package/dist/src/commands/security/threats.js.map +1 -0
- package/dist/src/commands/securityagent/setup.d.ts +19 -5
- package/dist/src/commands/securityagent/setup.d.ts.map +1 -1
- package/dist/src/commands/securityagent/setup.js +25 -189
- package/dist/src/commands/securityagent/setup.js.map +1 -1
- package/dist/src/dashboard/aws.d.ts +39 -0
- package/dist/src/dashboard/aws.d.ts.map +1 -0
- package/dist/src/dashboard/aws.js +35 -0
- package/dist/src/dashboard/aws.js.map +1 -0
- package/dist/src/dashboard/codewatch.d.ts.map +1 -1
- package/dist/src/dashboard/codewatch.js +2 -1
- package/dist/src/dashboard/codewatch.js.map +1 -1
- package/dist/src/dashboard/page.d.ts.map +1 -1
- package/dist/src/dashboard/page.js +193 -5
- package/dist/src/dashboard/page.js.map +1 -1
- package/dist/src/dashboard/payload.d.ts +11 -5
- package/dist/src/dashboard/payload.d.ts.map +1 -1
- package/dist/src/dashboard/payload.js +7 -2
- package/dist/src/dashboard/payload.js.map +1 -1
- package/dist/src/dashboard/security.d.ts +130 -0
- package/dist/src/dashboard/security.d.ts.map +1 -0
- package/dist/src/dashboard/security.js +144 -0
- package/dist/src/dashboard/security.js.map +1 -0
- package/dist/src/dashboard/setup.d.ts +15 -0
- package/dist/src/dashboard/setup.d.ts.map +1 -1
- package/dist/src/dashboard/setup.js +20 -3
- package/dist/src/dashboard/setup.js.map +1 -1
- package/dist/src/dashboard/usage.js +1 -1
- package/dist/src/dashboard/usage.js.map +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +9 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/security/cfn-diff.d.ts +57 -0
- package/dist/src/security/cfn-diff.d.ts.map +1 -0
- package/dist/src/security/cfn-diff.js +112 -0
- package/dist/src/security/cfn-diff.js.map +1 -0
- package/dist/src/security/errors.d.ts +45 -0
- package/dist/src/security/errors.d.ts.map +1 -0
- package/dist/src/security/errors.js +116 -0
- package/dist/src/security/errors.js.map +1 -0
- package/dist/src/security/marker.d.ts +46 -0
- package/dist/src/security/marker.d.ts.map +1 -0
- package/dist/src/security/marker.js +120 -0
- package/dist/src/security/marker.js.map +1 -0
- package/dist/src/security/pentest-dockerfile.d.ts +8 -0
- package/dist/src/security/pentest-dockerfile.d.ts.map +1 -0
- package/dist/src/security/pentest-dockerfile.js +163 -0
- package/dist/src/security/pentest-dockerfile.js.map +1 -0
- package/dist/src/security/pentest.d.ts +233 -0
- package/dist/src/security/pentest.d.ts.map +1 -0
- package/dist/src/security/pentest.js +1057 -0
- package/dist/src/security/pentest.js.map +1 -0
- package/dist/src/security/repo.d.ts +25 -0
- package/dist/src/security/repo.d.ts.map +1 -0
- package/dist/src/security/repo.js +38 -0
- package/dist/src/security/repo.js.map +1 -0
- package/dist/src/security/review.d.ts +202 -0
- package/dist/src/security/review.d.ts.map +1 -0
- package/dist/src/security/review.js +706 -0
- package/dist/src/security/review.js.map +1 -0
- package/dist/src/security/setup.d.ts +209 -0
- package/dist/src/security/setup.d.ts.map +1 -0
- package/dist/src/security/setup.js +742 -0
- package/dist/src/security/setup.js.map +1 -0
- package/dist/src/security/threat-model.d.ts +133 -0
- package/dist/src/security/threat-model.d.ts.map +1 -0
- package/dist/src/security/threat-model.js +653 -0
- package/dist/src/security/threat-model.js.map +1 -0
- package/dist/src/utils/audit-account.d.ts +50 -0
- package/dist/src/utils/audit-account.d.ts.map +1 -0
- package/dist/src/utils/audit-account.js +69 -0
- package/dist/src/utils/audit-account.js.map +1 -0
- package/dist/src/utils/audit-iam.d.ts +1 -1
- package/dist/src/utils/audit-iam.d.ts.map +1 -1
- package/dist/src/utils/audit-iam.js +11 -7
- package/dist/src/utils/audit-iam.js.map +1 -1
- package/dist/src/utils/exec.d.ts +6 -0
- package/dist/src/utils/exec.d.ts.map +1 -1
- package/dist/src/utils/exec.js +12 -1
- package/dist/src/utils/exec.js.map +1 -1
- package/dist/src/utils/otel-sync-schedule.d.ts +19 -0
- package/dist/src/utils/otel-sync-schedule.d.ts.map +1 -1
- package/dist/src/utils/otel-sync-schedule.js +24 -2
- package/dist/src/utils/otel-sync-schedule.js.map +1 -1
- package/package.json +3 -3
|
@@ -19,6 +19,8 @@ button { font:inherit; padding:4px 10px; border:1px solid var(--line); border-ra
|
|
|
19
19
|
main { padding:16px 20px; display:grid; gap:16px; grid-template-columns: repeat(auto-fit, minmax(420px, 1fr)); }
|
|
20
20
|
section.card { background:var(--card); border:1px solid var(--line); border-radius:10px; padding:14px 16px; min-width:0; }
|
|
21
21
|
section.wide { grid-column: 1 / -1; }
|
|
22
|
+
.sec-repo { border-top:1px solid var(--line); padding:10px 0; } .sec-repo:first-of-type { border-top:none; padding-top:0; } .sec-head { display:flex; gap:6px; align-items:baseline; flex-wrap:wrap; overflow-wrap:anywhere; }
|
|
23
|
+
.sec-pills { display:flex; gap:6px; flex-wrap:wrap; margin:6px 0; } ul.sec-findings { list-style:none; margin:4px 0 0; padding:0; } ul.sec-findings li { padding:6px 0; border-top:1px dashed var(--line); font-size:13px; overflow-wrap:anywhere; } .sec-title { font-weight:600; } ul.sec-findings code { white-space:normal; overflow-wrap:anywhere; }
|
|
22
24
|
h2 { font-size:15px; margin:0 0 10px; } h3 { font-size:13px; margin:14px 0 6px; color:var(--muted); text-transform:uppercase; letter-spacing:.04em; }
|
|
23
25
|
.empty { color:var(--muted); padding:8px 0; } code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size:12px; background:var(--bg); padding:1px 4px; border-radius:4px; }
|
|
24
26
|
.tablewrap { overflow-x:auto; }
|
|
@@ -257,7 +259,7 @@ function setupPanel(data) {
|
|
|
257
259
|
const rows = (items) => items.map((i) => [pill(i.status), i.label, el('div', {}, i.detail, i.fix ? el('div', { class: 'fix' }, 'Fix: ' + i.fix) : null)]);
|
|
258
260
|
s.append(el('h3', {}, 'This machine'), table(['', 'Check', 'Detail'], rows(data.machine.setup)));
|
|
259
261
|
const repos = data.overview.setup, c = data.overview.counts;
|
|
260
|
-
s.append(el('h3', {}, '
|
|
262
|
+
s.append(el('h3', {}, 'Per repo: codewatch (' + c.codewatch + ' of ' + c.repos + ' installed)'));
|
|
261
263
|
const label = { ok: 'ok', warn: 'warn', missing: 'missing', 'opted-out': 'opted out' };
|
|
262
264
|
const pillClass = { ok: 'ok', warn: 'warn', missing: 'missing', 'opted-out': 'skipped' };
|
|
263
265
|
const rowOf = (r) => [
|
|
@@ -265,24 +267,210 @@ function setupPanel(data) {
|
|
|
265
267
|
el('div', {}, pill(pillClass[r.status] || 'missing', (label[r.status] || r.status) + (r.status === 'ok' && r.global ? ' (global)' : '')), ' ',
|
|
266
268
|
r.status === 'ok' ? 'reviewer ' + txt(r.reviewer || 'none') : txt(r.detail),
|
|
267
269
|
r.fix ? el('div', { class: 'fix' }, 'Fix: ', el('code', {}, r.fix)) : null),
|
|
270
|
+
securityCell(r.security),
|
|
268
271
|
];
|
|
269
272
|
const sg = (data.suggestions || []).find((x) => x.id === 'codewatch-global');
|
|
270
273
|
if (sg) s.append(suggestionCallout(sg));
|
|
271
274
|
// Always shown: the current repo (installed or not) and every installed repo.
|
|
272
275
|
const shown = repos.filter((r) => !r.collapsed);
|
|
273
276
|
const hidden = repos.filter((r) => r.collapsed);
|
|
274
|
-
if (shown.length) s.append(table(['Repo', 'Codewatch'], shown.map(rowOf)));
|
|
277
|
+
if (shown.length) s.append(table(['Repo', 'Codewatch', 'Security Agent'], shown.map(rowOf)));
|
|
275
278
|
else if (!hidden.length) s.append(el('p', { class: 'empty' }, 'No git repositories found under ' + txt(data.scope.root_display) + '.'));
|
|
276
279
|
if (hidden.length) {
|
|
277
280
|
s.append(el('details', { class: 'missing-group' },
|
|
278
281
|
el('summary', {}, hidden.length + ' repo' + (hidden.length === 1 ? '' : 's') + ' without codewatch'),
|
|
279
|
-
table(['Repo', 'Codewatch'], hidden.map(rowOf))));
|
|
282
|
+
table(['Repo', 'Codewatch', 'Security Agent'], hidden.map(rowOf))));
|
|
280
283
|
}
|
|
281
284
|
return s;
|
|
282
285
|
}
|
|
283
286
|
|
|
287
|
+
/** Security Agent per repo, from the enable security marker (local evidence; the page makes no AWS calls). */
|
|
288
|
+
function securityCell(sec) {
|
|
289
|
+
if (!sec) return el('span', { class: 'fix' }, '-');
|
|
290
|
+
return el('div', {}, pill(sec.status === 'ok' ? 'ok' : 'missing', sec.status), ' ', sec.status === 'ok' ? txt(sec.detail) : '',
|
|
291
|
+
sec.fix ? el('div', { class: 'fix' }, 'Fix: ', el('code', {}, sec.fix)) : null);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/** Cached Security Agent code review results; the page only reads them. */
|
|
295
|
+
const RISKS = ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW', 'INFORMATIONAL', 'UNKNOWN'];
|
|
296
|
+
const RISK_CLASS = { CRITICAL: 'sev-high', HIGH: 'sev-high', MEDIUM: 'sev-medium', LOW: 'sev-low' };
|
|
297
|
+
/** A risk-level pill; colour follows the codewatch severity colours. */
|
|
298
|
+
const riskPill = (level, label) => el('span', { class: 'pill ' + (RISK_CLASS[level] || 'fix') }, label);
|
|
299
|
+
|
|
300
|
+
/** One column wide (fits beside Usage and Setup): a compact block per repo, findings as wrapping rows. */
|
|
284
301
|
function securityPanel(sec) {
|
|
285
|
-
|
|
302
|
+
const s = el('section', { class: 'card' }, el('h2', {}, 'Security findings'));
|
|
303
|
+
const rows = (sec && sec.repos) || [];
|
|
304
|
+
const tms = (sec && sec.threat_models) || [];
|
|
305
|
+
const pts = (sec && sec.pentests) || [];
|
|
306
|
+
if (!rows.length && !tms.length && !pts.length) {
|
|
307
|
+
s.append(el('p', { class: 'empty' }, 'No Security Agent code reviews, threat models or penetration tests yet. Run ', el('code', {}, (sec && sec.hint) || 'prism-cli security code-review'), ', ', el('code', {}, 'prism-cli security threat-model'), ' or ', el('code', {}, 'prism-cli security pentest'), ' in a repo set up with ', el('code', {}, 'prism-cli enable security'), '.'));
|
|
308
|
+
return s;
|
|
309
|
+
}
|
|
310
|
+
for (const r of rows) {
|
|
311
|
+
const counts = r.counts || {};
|
|
312
|
+
const b = el('div', { class: 'sec-repo' });
|
|
313
|
+
b.append(el('div', { class: 'sec-head' }, el('b', {}, txt(r.name)), r.current ? el('span', { class: 'tag' }, 'this repo') : null));
|
|
314
|
+
b.append(el('div', { class: 'fix' },
|
|
315
|
+
(r.pending ? 'started ' + when(r.started_at) : when(r.finished_at)) + ' · ' + (r.scope === 'diff' ? 'branch diff' : r.scope === 'full' ? 'whole repo' : 'fetched') + ' · job ' + txt(r.job_id).slice(0, 12)));
|
|
316
|
+
const pills = el('div', { class: 'sec-pills' });
|
|
317
|
+
if (r.pending) {
|
|
318
|
+
// Results are local: the page only knows the job was started, not whether it has finished since.
|
|
319
|
+
pills.append(pill('warn', 'review running'));
|
|
320
|
+
if (r.stale) pills.append(pill('skipped', 'stale?'));
|
|
321
|
+
b.append(pills, el('p', { class: 'note' }, r.stale ? 'Started over 2 h ago and not fetched yet; it has most likely finished. ' : '', 'Fetch the results with ', el('code', {}, (sec && sec.pending_hint) || 'prism-cli security findings'), '.'));
|
|
322
|
+
s.append(b);
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
if (r.status === 'error') pills.append(pill('error', txt(r.job_status).toLowerCase()));
|
|
326
|
+
else {
|
|
327
|
+
const shown = RISKS.filter((k) => (counts[k] || 0) > 0);
|
|
328
|
+
if (!shown.length) pills.append(pill('ok', 'no findings'));
|
|
329
|
+
for (const k of shown) pills.append(riskPill(k, counts[k] + ' ' + k.toLowerCase()));
|
|
330
|
+
}
|
|
331
|
+
b.append(pills);
|
|
332
|
+
if (r.reason) b.append(el('p', { class: 'note' }, txt(r.reason)));
|
|
333
|
+
if (r.status === 'error' && !r.findings.length) b.append(el('p', { class: 'empty' }, 'The job did not complete.'));
|
|
334
|
+
if (r.findings.length) {
|
|
335
|
+
const list = el('ul', { class: 'sec-findings' });
|
|
336
|
+
for (const f of r.findings) {
|
|
337
|
+
list.append(el('li', {},
|
|
338
|
+
riskPill(f.risk_level, txt(f.risk_level).toLowerCase()), ' ',
|
|
339
|
+
el('span', { class: 'sec-title' }, txt(f.title)),
|
|
340
|
+
el('div', { class: 'fix' }, el('code', {}, f.file ? f.file + (f.line ? ':' + f.line : '') : 'no location'), f.cwe ? ' · ' + txt(f.cwe) : '')));
|
|
341
|
+
}
|
|
342
|
+
b.append(list);
|
|
343
|
+
}
|
|
344
|
+
if (r.truncated) b.append(el('p', { class: 'note' }, 'showing the first ' + r.findings.length + '; run prism-cli security findings for all'));
|
|
345
|
+
s.append(b);
|
|
346
|
+
}
|
|
347
|
+
securityPentestRows(s, sec);
|
|
348
|
+
if (tms.length) {
|
|
349
|
+
s.append(el('h3', {}, 'Threat models'));
|
|
350
|
+
for (const t of tms) s.append(threatModelBlock(t, (sec && sec.threats_hint) || 'prism-cli security threats'));
|
|
351
|
+
}
|
|
352
|
+
return s;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
const THREAT_LEVELS = ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW', 'INFO'];
|
|
356
|
+
/** "INFORMATION_DISCLOSURE" -> "information disclosure". */
|
|
357
|
+
const strideText = (list) => (list || []).map((x) => txt(x).toLowerCase().replace(/_/g, ' ')).join(', ');
|
|
358
|
+
|
|
359
|
+
/** One cached threat model per repo, in the code review blocks' compact style. */
|
|
360
|
+
function threatModelBlock(t, hint) {
|
|
361
|
+
const b = el('div', { class: 'sec-repo' });
|
|
362
|
+
b.append(el('div', { class: 'sec-head' }, el('b', {}, txt(t.name)), t.current ? el('span', { class: 'tag' }, 'this repo') : null));
|
|
363
|
+
const docs = (t.scope_docs || []).length;
|
|
364
|
+
b.append(el('div', { class: 'fix' },
|
|
365
|
+
(t.pending ? 'started ' + when(t.started_at) : when(t.finished_at)) + ' · commit ' + txt(t.commit).slice(0, 12)
|
|
366
|
+
+ ' · ' + (docs ? docs + ' scope doc' + (docs === 1 ? '' : 's') : 'source only') + ' · job ' + txt(t.job_id).slice(0, 12)));
|
|
367
|
+
const pills = el('div', { class: 'sec-pills' });
|
|
368
|
+
if (t.pending) {
|
|
369
|
+
// Results are local: the page only knows the job was started, not whether it has finished since.
|
|
370
|
+
pills.append(pill('warn', 'threat model running'));
|
|
371
|
+
if (t.stale) pills.append(pill('skipped', 'stale?'));
|
|
372
|
+
b.append(pills, el('p', { class: 'note' }, t.stale ? 'Started over 2 h ago and not fetched yet; it has most likely finished. ' : '', 'Fetch the threats with ', el('code', {}, hint), '.'));
|
|
373
|
+
return b;
|
|
374
|
+
}
|
|
375
|
+
if (t.status === 'error') pills.append(pill('error', txt(t.job_status).toLowerCase()));
|
|
376
|
+
else {
|
|
377
|
+
const counts = t.counts || {};
|
|
378
|
+
const shown = THREAT_LEVELS.filter((k) => (counts[k] || 0) > 0);
|
|
379
|
+
if (!shown.length) pills.append(pill('ok', 'no threats'));
|
|
380
|
+
for (const k of shown) pills.append(riskPill(k, counts[k] + ' ' + k.toLowerCase()));
|
|
381
|
+
}
|
|
382
|
+
b.append(pills);
|
|
383
|
+
if (t.reason) b.append(el('p', { class: 'note' }, txt(t.reason)));
|
|
384
|
+
if (t.overview) b.append(el('p', { class: 'note' }, txt(t.overview)));
|
|
385
|
+
if ((t.threats || []).length) {
|
|
386
|
+
const list = el('ul', { class: 'sec-findings' });
|
|
387
|
+
for (const x of t.threats) {
|
|
388
|
+
list.append(el('li', {},
|
|
389
|
+
riskPill(x.severity, txt(x.severity).toLowerCase()), ' ',
|
|
390
|
+
el('span', { class: 'sec-title' }, txt(x.title)),
|
|
391
|
+
(x.stride || []).length ? el('div', { class: 'fix' }, strideText(x.stride)) : null));
|
|
392
|
+
}
|
|
393
|
+
b.append(list);
|
|
394
|
+
}
|
|
395
|
+
if (t.more) b.append(el('p', { class: 'note' }, t.more + ' more; run ' + hint + ' for all'));
|
|
396
|
+
return b;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/** Penetration-test rows, in the same Security card below the code-review rows. */
|
|
400
|
+
function securityPentestRows(s, sec) {
|
|
401
|
+
const rows = (sec && sec.pentests) || [];
|
|
402
|
+
if (!rows.length) return;
|
|
403
|
+
s.append(el('h3', {}, 'Penetration tests'));
|
|
404
|
+
for (const r of rows) {
|
|
405
|
+
const counts = r.counts || {};
|
|
406
|
+
const b = el('div', { class: 'sec-repo' });
|
|
407
|
+
b.append(el('div', { class: 'sec-head' }, el('b', {}, txt(r.name)), r.current ? el('span', { class: 'tag' }, 'this repo') : null));
|
|
408
|
+
b.append(el('div', { class: 'fix' },
|
|
409
|
+
(r.pending ? 'started ' + when(r.started_at) : when(r.finished_at)) + ' · ' + txt(r.target_host) + ' · job ' + txt(r.job_id).slice(0, 12)));
|
|
410
|
+
const pills = el('div', { class: 'sec-pills' });
|
|
411
|
+
if (r.pending) {
|
|
412
|
+
pills.append(pill('warn', 'pentest running'));
|
|
413
|
+
if (r.stale) pills.append(pill('skipped', 'stale?'));
|
|
414
|
+
b.append(pills, el('p', { class: 'note' }, r.stale ? 'Started over 6 h ago and not refreshed. ' : '', 'Refresh with ', el('code', {}, (sec && sec.pentest_hint) || 'prism-cli security pentest --status'), '.'));
|
|
415
|
+
s.append(b);
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
if (r.status === 'error') pills.append(pill('error', txt(r.job_status).toLowerCase()));
|
|
419
|
+
else {
|
|
420
|
+
const shown = RISKS.filter((k) => (counts[k] || 0) > 0);
|
|
421
|
+
if (!shown.length) pills.append(pill('ok', 'no findings'));
|
|
422
|
+
for (const k of shown) pills.append(riskPill(k, counts[k] + ' ' + k.toLowerCase()));
|
|
423
|
+
}
|
|
424
|
+
if (r.teardown_failed) pills.append(pill('error', 'teardown failed'));
|
|
425
|
+
b.append(pills);
|
|
426
|
+
if (r.reason) b.append(el('p', { class: 'note' }, txt(r.reason)));
|
|
427
|
+
if (r.teardown_failed) b.append(el('p', { class: 'note' }, 'The environment is still up (' + txt(r.teardown_failed.reason) + '). Retry with ', el('code', {}, 'prism-cli security pentest --cleanup'), '.'));
|
|
428
|
+
if (r.findings.length) {
|
|
429
|
+
const list = el('ul', { class: 'sec-findings' });
|
|
430
|
+
for (const f of r.findings) {
|
|
431
|
+
list.append(el('li', {},
|
|
432
|
+
riskPill(f.risk_level, txt(f.risk_level).toLowerCase()), ' ',
|
|
433
|
+
el('span', { class: 'sec-title' }, txt(f.title)),
|
|
434
|
+
f.confidence ? el('div', { class: 'fix' }, txt(f.confidence).toLowerCase() + ' confidence') : null));
|
|
435
|
+
}
|
|
436
|
+
b.append(list);
|
|
437
|
+
}
|
|
438
|
+
if (r.truncated) b.append(el('p', { class: 'note' }, 'showing the first ' + r.findings.length + '; run prism-cli security findings --pentest for all'));
|
|
439
|
+
s.append(b);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
const AUDIT_SEVERITIES = ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW'];
|
|
444
|
+
|
|
445
|
+
/** The latest aws check per account, in the Security panel's compact style. Local results only. */
|
|
446
|
+
function awsPanel(aws) {
|
|
447
|
+
const s = el('section', { class: 'card' }, el('h2', {}, 'AWS account'));
|
|
448
|
+
const rows = (aws && aws.accounts) || [];
|
|
449
|
+
if (!rows.length) {
|
|
450
|
+
s.append(el('p', { class: 'empty' }, 'No AWS account checks yet. Run ', el('code', {}, (aws && aws.hint) || 'prism-cli aws check'), ' (read-only).'));
|
|
451
|
+
return s;
|
|
452
|
+
}
|
|
453
|
+
for (const a of rows) {
|
|
454
|
+
const b = el('div', { class: 'sec-repo' });
|
|
455
|
+
b.append(el('div', { class: 'sec-head' }, el('b', {}, txt(a.account)), a.alias ? el('span', { class: 'tag' }, txt(a.alias)) : null));
|
|
456
|
+
b.append(el('div', { class: 'fix' }, txt(a.region) + ' · ' + when(a.checked_at) + (a.profile ? ' · profile ' + txt(a.profile) + (a.profile_source ? ' (' + txt(a.profile_source) + ')' : '') : '')));
|
|
457
|
+
const c = a.counts || {}, pills = el('div', { class: 'sec-pills' });
|
|
458
|
+
pills.append(pill('ok', (c.pass || 0) + ' pass'));
|
|
459
|
+
if (c.fail) pills.append(pill('error', c.fail + ' fail'));
|
|
460
|
+
if (c.indeterminate) pills.append(pill('warn', c.indeterminate + ' not checked'));
|
|
461
|
+
for (const k of AUDIT_SEVERITIES) if ((a.fail_by_severity || {})[k]) pills.append(riskPill(k, a.fail_by_severity[k] + ' ' + k.toLowerCase()));
|
|
462
|
+
b.append(pills);
|
|
463
|
+
if ((a.top_failures || []).length) {
|
|
464
|
+
const list = el('ul', { class: 'sec-findings' });
|
|
465
|
+
for (const f of a.top_failures) list.append(el('li', {}, riskPill(f.severity, txt(f.severity).toLowerCase()), ' ', el('span', { class: 'sec-title' }, txt(f.title)), el('div', { class: 'fix' }, txt(f.section))));
|
|
466
|
+
b.append(list);
|
|
467
|
+
}
|
|
468
|
+
if (a.more) b.append(el('p', { class: 'note' }, a.more + ' more'));
|
|
469
|
+
if (c.indeterminate) b.append(el('p', { class: 'note' }, 'Checks that could not run are not passes.'));
|
|
470
|
+
s.append(b);
|
|
471
|
+
}
|
|
472
|
+
s.append(el('p', { class: 'note' }, 'Ranked fixes: run ', el('code', {}, (aws && aws.recommend_hint) || 'prism-cli aws recommend'), '.'));
|
|
473
|
+
return s;
|
|
286
474
|
}
|
|
287
475
|
|
|
288
476
|
async function load() {
|
|
@@ -296,7 +484,7 @@ async function load() {
|
|
|
296
484
|
} catch (e) { meta.textContent = 'failed to load: ' + e.message; return; }
|
|
297
485
|
main.replaceChildren();
|
|
298
486
|
if (data.scope.error) main.append(el('section', { class: 'card wide' }, pill('error'), ' ', data.scope.error));
|
|
299
|
-
main.append(codewatchPanel(data), usagePanel(data.usage), setupPanel(data), securityPanel(data.security));
|
|
487
|
+
main.append(codewatchPanel(data), usagePanel(data.usage), setupPanel(data), securityPanel(data.security), awsPanel(data.aws));
|
|
300
488
|
const c = data.overview.counts;
|
|
301
489
|
meta.textContent = c.repos + ' repos under ' + txt(data.scope.root_display) + ' · ' + c.codewatch + ' with codewatch' + (data.scope.truncated ? ' (scan capped)' : '') + ' · updated ' + when(data.generated_at);
|
|
302
490
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page.js","sourceRoot":"","sources":["../../../src/dashboard/page.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,KAAK,GAAG
|
|
1
|
+
{"version":3,"file":"page.js","sourceRoot":"","sources":["../../../src/dashboard/page.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwCb,CAAC;AAEF,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2bd,CAAC;AAEF,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,wFAAwF;IACxF,OAAO;;8CAEqC,KAAK,KAAK,KAAK;;;iBAG5C,KAAK,KAAK,MAAM,yBAAyB,CAAC;AAC3D,CAAC"}
|
|
@@ -5,10 +5,12 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { type CodewatchPanel, type SecretScanning } from './codewatch.js';
|
|
7
7
|
import { type DiscoverOptions } from './repos.js';
|
|
8
|
-
import { type CheckItem, type CodewatchSetup, type MachineDeps } from './setup.js';
|
|
8
|
+
import { type CheckItem, type CodewatchSetup, type MachineDeps, type SecuritySetup } from './setup.js';
|
|
9
9
|
import { type GlobalStatus } from '../codewatch/globalHooks.js';
|
|
10
10
|
export declare function tildeHome(p: string, home: string): string;
|
|
11
11
|
import { type CodeburnExport, type UsagePanel } from './usage.js';
|
|
12
|
+
import { type SecurityPanel } from './security.js';
|
|
13
|
+
import { type AwsPanel } from './aws.js';
|
|
12
14
|
export declare const PAYLOAD_SCHEMA = "prism.dashboard.v2";
|
|
13
15
|
export interface RepoPayload {
|
|
14
16
|
name: string;
|
|
@@ -17,6 +19,8 @@ export interface RepoPayload {
|
|
|
17
19
|
hasPrism: boolean;
|
|
18
20
|
codewatch: CodewatchPanel;
|
|
19
21
|
setup: CodewatchSetup;
|
|
22
|
+
/** Security Agent, from the enable security marker. */
|
|
23
|
+
security: SecuritySetup;
|
|
20
24
|
}
|
|
21
25
|
/** One row of the setup table. */
|
|
22
26
|
export interface SetupRow {
|
|
@@ -29,6 +33,8 @@ export interface SetupRow {
|
|
|
29
33
|
fix: string;
|
|
30
34
|
/** Global hooks cover this repo. */
|
|
31
35
|
global: boolean;
|
|
36
|
+
/** Security Agent row for this repo. */
|
|
37
|
+
security: SecuritySetup;
|
|
32
38
|
/** Shown inside the collapsed "repos without codewatch" group: missing or opted out, and not the current repo. */
|
|
33
39
|
collapsed: boolean;
|
|
34
40
|
}
|
|
@@ -92,10 +98,10 @@ export interface DashboardPayload {
|
|
|
92
98
|
};
|
|
93
99
|
suggestions: Suggestion[];
|
|
94
100
|
usage: UsagePanel;
|
|
95
|
-
security
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
101
|
+
/** Cached Security Agent code review results (security-review), per repo. */
|
|
102
|
+
security: SecurityPanel;
|
|
103
|
+
/** The latest cached aws check result per AWS account (repos and ~). */
|
|
104
|
+
aws: AwsPanel;
|
|
99
105
|
}
|
|
100
106
|
export interface PayloadOptions extends DiscoverOptions {
|
|
101
107
|
trendRuns?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../../src/dashboard/payload.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAA2C,KAAK,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACnH,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,
|
|
1
|
+
{"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../../src/dashboard/payload.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { collectCodewatch, combineSecretScanning } from './codewatch.js';
|
|
7
7
|
import { discoverRepos } from './repos.js';
|
|
8
|
-
import { codewatchSetup, GLOBAL_FORCE_CMD, GLOBAL_INSTALL_CMD, machineChecks } from './setup.js';
|
|
8
|
+
import { codewatchSetup, GLOBAL_FORCE_CMD, GLOBAL_INSTALL_CMD, machineChecks, securitySetup } from './setup.js';
|
|
9
9
|
import { globalStatus } from '../codewatch/globalHooks.js';
|
|
10
10
|
import { findOnPath } from '../utils/tool-check.js';
|
|
11
11
|
import { homedir } from 'node:os';
|
|
@@ -16,6 +16,8 @@ export function tildeHome(p, home) {
|
|
|
16
16
|
return p.startsWith(home + sep) ? '~' + p.slice(home.length) : p;
|
|
17
17
|
}
|
|
18
18
|
import { collectUsage } from './usage.js';
|
|
19
|
+
import { collectSecurity } from './security.js';
|
|
20
|
+
import { collectAws } from './aws.js';
|
|
19
21
|
export const PAYLOAD_SCHEMA = 'prism.dashboard.v2';
|
|
20
22
|
/** Minimum missing repos before the global install is suggested; one repo is served by its own fix line. */
|
|
21
23
|
export const SUGGEST_GLOBAL_MIN_MISSING = 2;
|
|
@@ -55,10 +57,12 @@ export async function buildPayload(opts) {
|
|
|
55
57
|
hasPrism: r.hasPrism,
|
|
56
58
|
codewatch: collectCodewatch(r.path, opts.trendRuns, gitleaksAvailable),
|
|
57
59
|
setup: codewatchSetup(r.path, { pathEnv: opts.pathEnv, global: g }),
|
|
60
|
+
security: securitySetup(r.path),
|
|
58
61
|
}));
|
|
59
62
|
const setupRows = sortSetupRows(repos.map((r) => ({
|
|
60
63
|
name: r.name, path: r.path, current: r.current, status: r.setup.status, reviewer: r.setup.reviewer, detail: r.setup.detail, fix: r.setup.fix,
|
|
61
64
|
global: r.setup.global,
|
|
65
|
+
security: r.security,
|
|
62
66
|
// Bypassed repos (warn) need attention, so they stay visible.
|
|
63
67
|
collapsed: !r.current && (r.setup.status === 'missing' || r.setup.status === 'opted-out'),
|
|
64
68
|
})));
|
|
@@ -87,7 +91,8 @@ export async function buildPayload(opts) {
|
|
|
87
91
|
},
|
|
88
92
|
suggestions: [globalSuggestion(g, setupRows.filter((r) => r.status === 'missing').length)].filter((x) => x !== null),
|
|
89
93
|
usage,
|
|
90
|
-
security:
|
|
94
|
+
security: collectSecurity(repos),
|
|
95
|
+
aws: collectAws([...repos.map((r) => r.path), opts.home || homedir()]),
|
|
91
96
|
};
|
|
92
97
|
}
|
|
93
98
|
//# sourceMappingURL=payload.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payload.js","sourceRoot":"","sources":["../../../src/dashboard/payload.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAA4C,MAAM,gBAAgB,CAAC;AACnH,OAAO,EAAE,aAAa,EAAwB,MAAM,YAAY,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"payload.js","sourceRoot":"","sources":["../../../src/dashboard/payload.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Security findings panel: the cached `security-review` results that
|
|
3
|
+
* `prism-cli security code-review` and `security findings` write to
|
|
4
|
+
* .prism/results/. Local files only; no AWS calls.
|
|
5
|
+
*/
|
|
6
|
+
import { type PrismResult } from '../codewatch/results.js';
|
|
7
|
+
export declare const MAX_PANEL_FINDINGS = 50;
|
|
8
|
+
/** A pending record older than this is marked `stale?`: results are local, so the dashboard cannot know the job's real state. */
|
|
9
|
+
export declare const PENDING_STALE_MS: number;
|
|
10
|
+
export declare const PENDING_HINT = "prism-cli security findings";
|
|
11
|
+
export interface SecurityFindingRow {
|
|
12
|
+
risk_level: string;
|
|
13
|
+
title: string;
|
|
14
|
+
file: string;
|
|
15
|
+
line: number | null;
|
|
16
|
+
cwe: string | null;
|
|
17
|
+
}
|
|
18
|
+
export interface SecurityRepoRow {
|
|
19
|
+
name: string;
|
|
20
|
+
path: string;
|
|
21
|
+
current: boolean;
|
|
22
|
+
job_id: string;
|
|
23
|
+
job_status: string;
|
|
24
|
+
status: PrismResult['status'];
|
|
25
|
+
scope: string;
|
|
26
|
+
started_at: string;
|
|
27
|
+
finished_at: string;
|
|
28
|
+
counts: Record<string, number>;
|
|
29
|
+
findings: SecurityFindingRow[];
|
|
30
|
+
truncated: boolean;
|
|
31
|
+
reason: string | null;
|
|
32
|
+
/** Started by code-review, no verdict recorded yet. */
|
|
33
|
+
pending: boolean;
|
|
34
|
+
/** Pending for longer than PENDING_STALE_MS: the job most likely finished and nobody fetched it. */
|
|
35
|
+
stale: boolean;
|
|
36
|
+
}
|
|
37
|
+
/** A pentest runs for hours, so its pending record goes stale later than a review's. */
|
|
38
|
+
export declare const PENTEST_PENDING_STALE_MS: number;
|
|
39
|
+
export declare const PENTEST_HINT = "prism-cli security pentest --status";
|
|
40
|
+
export interface SecurityPentestFindingRow {
|
|
41
|
+
risk_level: string;
|
|
42
|
+
title: string;
|
|
43
|
+
confidence: string | null;
|
|
44
|
+
}
|
|
45
|
+
export interface SecurityPentestRow {
|
|
46
|
+
name: string;
|
|
47
|
+
path: string;
|
|
48
|
+
current: boolean;
|
|
49
|
+
job_id: string;
|
|
50
|
+
job_status: string;
|
|
51
|
+
status: PrismResult['status'];
|
|
52
|
+
target_host: string;
|
|
53
|
+
started_at: string;
|
|
54
|
+
finished_at: string;
|
|
55
|
+
counts: Record<string, number>;
|
|
56
|
+
findings: SecurityPentestFindingRow[];
|
|
57
|
+
truncated: boolean;
|
|
58
|
+
reason: string | null;
|
|
59
|
+
overview: string | null;
|
|
60
|
+
/** The last teardown left the stack up; --cleanup retries it. */
|
|
61
|
+
teardown_failed: {
|
|
62
|
+
at: string;
|
|
63
|
+
reason: string;
|
|
64
|
+
} | null;
|
|
65
|
+
pending: boolean;
|
|
66
|
+
stale: boolean;
|
|
67
|
+
}
|
|
68
|
+
export interface SecurityPanel {
|
|
69
|
+
/** One row per repo with a cached code-review result, newest job first. */
|
|
70
|
+
repos: SecurityRepoRow[];
|
|
71
|
+
/** One row per repo with a cached penetration-test result, newest job first. */
|
|
72
|
+
pentests: SecurityPentestRow[];
|
|
73
|
+
hint: string;
|
|
74
|
+
/** Shown on a pending repo: how to fetch the job's results. */
|
|
75
|
+
pending_hint: string;
|
|
76
|
+
/** Shown on a pending pentest: how to refresh it. */
|
|
77
|
+
pentest_hint: string;
|
|
78
|
+
/** One row per repo with a cached threat model, current repo first. */
|
|
79
|
+
threat_models: ThreatModelRow[];
|
|
80
|
+
/** Shown on a pending threat model: how to fetch its threats. */
|
|
81
|
+
threats_hint: string;
|
|
82
|
+
}
|
|
83
|
+
/** Threats shown per repo; the rest are in the result file and `prism-cli security threats`. */
|
|
84
|
+
export declare const MAX_PANEL_THREATS = 5;
|
|
85
|
+
export declare const THREATS_HINT = "prism-cli security threats";
|
|
86
|
+
export interface ThreatModelRow {
|
|
87
|
+
name: string;
|
|
88
|
+
path: string;
|
|
89
|
+
current: boolean;
|
|
90
|
+
job_id: string;
|
|
91
|
+
job_status: string;
|
|
92
|
+
status: PrismResult['status'];
|
|
93
|
+
commit: string | null;
|
|
94
|
+
started_at: string;
|
|
95
|
+
finished_at: string;
|
|
96
|
+
counts: Record<string, number>;
|
|
97
|
+
scope_docs: string[];
|
|
98
|
+
/** The system overview's first paragraph. */
|
|
99
|
+
overview: string;
|
|
100
|
+
threats: {
|
|
101
|
+
severity: string;
|
|
102
|
+
title: string;
|
|
103
|
+
stride: string[];
|
|
104
|
+
}[];
|
|
105
|
+
/** Threats beyond MAX_PANEL_THREATS. */
|
|
106
|
+
more: number;
|
|
107
|
+
reason: string | null;
|
|
108
|
+
pending: boolean;
|
|
109
|
+
stale: boolean;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* The latest job of a repo. Two files can hold the same job (code-review
|
|
113
|
+
* writes it with its scope, `security findings` again without); the one that
|
|
114
|
+
* knows its scope wins, then the newest write. A pending record is completed
|
|
115
|
+
* in place, but should a verdict for the same job exist elsewhere, it wins.
|
|
116
|
+
*/
|
|
117
|
+
export declare function latestSecurityReview(results: PrismResult[]): PrismResult | null;
|
|
118
|
+
/**
|
|
119
|
+
* The latest pentest job of a repo. Like latestSecurityReview: newest write per
|
|
120
|
+
* job, but a completed record for a job wins over its pending record.
|
|
121
|
+
*/
|
|
122
|
+
export declare function latestPentest(results: PrismResult[]): PrismResult | null;
|
|
123
|
+
export declare function collectSecurity(repos: {
|
|
124
|
+
name: string;
|
|
125
|
+
path: string;
|
|
126
|
+
current: boolean;
|
|
127
|
+
}[], read?: (root: string) => PrismResult[], now?: Date): SecurityPanel;
|
|
128
|
+
/** The newest threat model job of a repo; for one job, a verdict wins over a pending record. */
|
|
129
|
+
export declare function latestThreatModel(results: PrismResult[]): PrismResult | null;
|
|
130
|
+
//# sourceMappingURL=security.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../../src/dashboard/security.ts"],"names":[],"mappings":"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"}
|