@@ -22,6 +22,18 @@ import {
2222 type FindingRestoreResult ,
2323 type FindingDeleteResult ,
2424} from "../findings.js" ;
25+ import {
26+ printArchivedSummaries ,
27+ printArchiveResult ,
28+ printDeleteResult ,
29+ printFindingDetail ,
30+ printFindingDoctor ,
31+ printFindingSummaries ,
32+ printFindingTemplateResult ,
33+ printFindingValidation ,
34+ printRestoreResult ,
35+ printWorkflowSummaries ,
36+ } from "../render.js" ;
2537import { usage } from "../usage.js" ;
2638import { firstPositionalAfter , parseStatus , parseReason , wantsJson } from "./shared.js" ;
2739import {
@@ -232,41 +244,6 @@ async function runFindingsDoctor(args: string[], json: boolean): Promise<void> {
232244 }
233245}
234246
235- function printFindingDoctor ( result : FindingDoctorResult ) : void {
236- console . log ( title ( `doctor ${ result . id } ` ) ) ;
237- console . log (
238- panel ( "readiness" , [
239- ...kv ( [
240- [ "status" , statusBadge ( result . status as "candidate" | "confirmed" | "blocked" ) ] ,
241- [ "validation" , validationBadge ( result . validationOk ) ] ,
242- [ "evidence" , readiness ( result . evidenceScore ) ] ,
243- [ "submission" , readiness ( result . submissionScore ) ] ,
244- [ "threshold" , String ( result . submissionThreshold ) ] ,
245- [ "report ready" , result . reportReady ? "yes" : "no" ] ,
246- [ "next" , cmd ( result . nextAction ) ] ,
247- ] ) ,
248- ] ) ,
249- ) ;
250-
251- if ( result . issues . length === 0 ) {
252- console . log ( empty ( "No readiness issues." ) ) ;
253- return ;
254- }
255-
256- console . log ( section ( "Issues" ) ) ;
257- console . log (
258- table (
259- [ "" , "severity" , "message" , "next action" ] ,
260- result . issues . map ( ( issue ) => [
261- statusIcon ( issue . severity === "error" ? "fail" : issue . severity === "warning" ? "warn" : "pass" ) ,
262- issue . severity ,
263- truncate ( issue . message , 64 ) ,
264- cmd ( truncate ( issue . nextAction , 40 ) ) ,
265- ] ) ,
266- ) ,
267- ) ;
268- }
269-
270247async function runFindingsPromote ( args : string [ ] , json : boolean ) : Promise < void > {
271248 const target = firstPositionalAfter ( args , "promote" ) ;
272249 const status = parseStatus ( args ) ;
@@ -352,198 +329,3 @@ async function runFindingsDelete(args: string[], json: boolean): Promise<void> {
352329 }
353330 printDeleteResult ( result ) ;
354331}
355-
356- function printFindingSummaries ( findings : FindingSummary [ ] ) : void {
357- console . log ( title ( "active findings" ) ) ;
358- console . log (
359- table (
360- [ "id" , "status" , "evidence" , "submission" , "package" , "vulnerability" ] ,
361- findings . map ( ( finding ) => [
362- truncate ( finding . id , 36 ) ,
363- statusBadge ( finding . status ) ,
364- readiness ( finding . evidenceScore ) ,
365- readiness ( finding . submissionScore ) ,
366- truncate ( `${ finding . ecosystem } :${ finding . package } ` , 42 ) ,
367- truncate ( finding . vulnerability , 36 ) ,
368- ] ) ,
369- ) ,
370- ) ;
371- }
372-
373- function printWorkflowSummaries ( findings : FindingWorkflowSummary [ ] ) : void {
374- console . log ( title ( "workflow queue" ) ) ;
375- console . log (
376- table (
377- [ "id" , "priority" , "status" , "evidence" , "submission" , "next action" , "package" , "vulnerability" ] ,
378- findings . map ( ( finding ) => [
379- truncate ( finding . id , 30 ) ,
380- String ( finding . priority ) ,
381- statusBadge ( finding . status ) ,
382- readiness ( finding . evidenceScore ) ,
383- readiness ( finding . submissionScore ) ,
384- cmd ( truncate ( finding . nextAction , 46 ) ) ,
385- truncate ( `${ finding . ecosystem } :${ finding . package } ` , 34 ) ,
386- truncate ( finding . vulnerability , 30 ) ,
387- ] ) ,
388- ) ,
389- ) ;
390- }
391-
392- function printFindingDetail ( finding : FindingDetail ) : void {
393- console . log ( title ( `finding ${ finding . id } ` ) ) ;
394- const lines = kv ( [
395- [ "status" , statusBadge ( finding . status ) ] ,
396- [ "evidence" , readiness ( finding . evidenceScore ) ] ,
397- [ "submission" , readiness ( finding . submissionScore ) ] ,
398- [ "verdict" , `${ finding . verdict . exploitability } /${ finding . verdict . confidence } ` ] ,
399- [ "validation" , validationBadge ( finding . validation . ok ) ] ,
400- [ "priority" , `${ finding . priority } (${ finding . priorityReason } )` ] ,
401- [ "path" , finding . path ] ,
402- [ "package" , `${ finding . ecosystem } :${ finding . package } ` ] ,
403- [ "vulnerability" , finding . vulnerability ] ,
404- ] ) ;
405- if ( finding . reproArtifacts . length > 0 ) {
406- lines . push ( ...kv ( [ [ "repro artifacts" , String ( finding . reproArtifacts . length ) ] ] ) ) ;
407- }
408- if ( finding . threatMap ) {
409- lines . push ( ...kv ( [ [ "threat map" , finding . threatMap . path ] ] ) ) ;
410- lines . push ( "" , muted ( "threat map" ) ) ;
411- lines . push ( ...finding . threatMap . rendered . map ( ( item ) => ` ${ item } ` ) ) ;
412- }
413- if ( finding . archived ) {
414- lines . push ( ...kv ( [
415- [ "archived" , finding . archivedAt ?? "unknown" ] ,
416- [ "reason" , finding . archiveReason ?? "unknown" ] ,
417- ] ) ) ;
418- }
419- lines . push ( ...kv ( [ [ "next" , cmd ( finding . nextAction ) ] ] ) ) ;
420- if ( finding . validation . errors . length > 0 ) {
421- lines . push ( "" , tuiError ( "errors" ) ) ;
422- lines . push ( ...finding . validation . errors . map ( ( item ) => ` ${ item } ` ) ) ;
423- }
424- if ( finding . validation . warnings . length > 0 ) {
425- lines . push ( "" , warn ( "warnings" ) ) ;
426- lines . push ( ...finding . validation . warnings . slice ( 0 , 8 ) . map ( ( item ) => ` ${ item } ` ) ) ;
427- if ( finding . validation . warnings . length > 8 ) {
428- lines . push ( muted ( ` ... ${ finding . validation . warnings . length - 8 } more warning(s)` ) ) ;
429- }
430- }
431- if ( finding . missingFields . length > 0 ) {
432- lines . push ( "" , muted ( `missing ${ finding . missingFields . join ( ", " ) } ` ) ) ;
433- }
434- console . log ( panel ( finding . id , lines ) ) ;
435- }
436-
437- function printArchivedSummaries ( findings : ArchivedFindingSummary [ ] ) : void {
438- if ( findings . length === 0 ) {
439- console . log ( empty ( "No archived findings." ) ) ;
440- return ;
441- }
442- console . log ( title ( "archive" ) ) ;
443- console . log (
444- table (
445- [ "id" , "status" , "archived" , "reason" , "package" ] ,
446- findings . map ( ( finding ) => [
447- truncate ( finding . id , 34 ) ,
448- statusBadge ( finding . status ) ,
449- truncate ( finding . archivedAt , 27 ) ,
450- truncate ( finding . archiveReason , 26 ) ,
451- truncate ( `${ finding . ecosystem } :${ finding . package } ` , 40 ) ,
452- ] ) ,
453- ) ,
454- ) ;
455- }
456-
457- function printFindingValidation ( result : FindingValidation ) : void {
458- const lines = kv ( [
459- [ "status" , statusBadge ( result . status ) ] ,
460- [ "evidence" , readiness ( result . evidenceScore ) ] ,
461- [ "submission" , readiness ( result . submissionScore ) ] ,
462- [ "validation" , validationBadge ( result . ok ) ] ,
463- [ "path" , result . path ] ,
464- ] ) ;
465- if ( result . errors . length > 0 ) {
466- lines . push ( "" , tuiError ( "errors" ) ) ;
467- lines . push ( ...result . errors . map ( ( item ) => ` ${ item } ` ) ) ;
468- }
469- if ( result . warnings . length > 0 ) {
470- lines . push ( "" , warn ( "warnings" ) ) ;
471- lines . push ( ...result . warnings . map ( ( item ) => ` ${ item } ` ) ) ;
472- }
473- console . log ( panel ( result . id , lines ) ) ;
474- }
475-
476- function printFindingTemplateResult ( result : FindingTemplateResult ) : void {
477- console . log (
478- panel ( "finding created" , [
479- ...kv ( [
480- [ "id" , result . id ] ,
481- [ "path" , result . path ] ,
482- [ "status" , statusBadge ( result . status ) ] ,
483- [ "next" , cmd ( `omv findings show ${ result . id } ` ) ] ,
484- ] ) ,
485- ] ) ,
486- ) ;
487- }
488-
489- function printArchiveResult ( result : FindingArchiveResult ) : void {
490- console . log (
491- panel ( "finding archived" , [
492- ...kv ( [
493- [ "id" , result . id ] ,
494- [ "status" , statusBadge ( result . status ) ] ,
495- [ "from" , result . from ] ,
496- [ "to" , result . to ] ,
497- [ "reason" , result . archiveReason ] ,
498- [ "reports" , result . reportArtifactPaths . length > 0 ? `${ result . reportArtifactPaths . length } artifact(s)` : "none" ] ,
499- [ "submissions" , result . submissionRecords . length > 0 ? `${ result . submissionRecords . length } record(s)` : "none" ] ,
500- [ "next" , cmd ( `omv findings show ${ result . id } --archived` ) ] ,
501- ] ) ,
502- ...result . warnings . map ( ( item ) => warn ( `warning ${ item } ` ) ) ,
503- ] ) ,
504- ) ;
505- }
506-
507- function printRestoreResult ( result : FindingRestoreResult ) : void {
508- console . log (
509- panel ( "finding restored" , [
510- ...kv ( [
511- [ "id" , result . id ] ,
512- [ "status" , statusBadge ( result . status ) ] ,
513- [ "from" , result . from ] ,
514- [ "to" , result . to ] ,
515- [ "next" , cmd ( "omv findings workflow" ) ] ,
516- ] ) ,
517- ] ) ,
518- ) ;
519- }
520-
521- function printDeleteResult ( result : FindingDeleteResult ) : void {
522- if ( ! result . deleted ) {
523- console . log (
524- panel ( "finding delete preview" , [
525- ...kv ( [
526- [ "id" , result . id ] ,
527- [ "action" , "preview only" ] ,
528- [ "next" , cmd ( `omv findings delete ${ result . id } --force` ) ] ,
529- ] ) ,
530- "" ,
531- muted ( "paths to delete" ) ,
532- ...result . paths . map ( ( p ) => ` ${ p } ` ) ,
533- ] ) ,
534- ) ;
535- return ;
536- }
537-
538- const finalState = result . errors . length > 0 ? "warn" : "pass" ;
539- console . log (
540- panel ( "finding deleted" , [
541- ...kv ( [
542- [ "id" , result . id ] ,
543- [ "result" , outcomeBadge ( finalState ) ] ,
544- [ "paths" , `${ result . paths . length } file(s) removed` ] ,
545- ] ) ,
546- ...( result . errors . length > 0 ? [ "" , warn ( "errors" ) , ...result . errors . map ( ( e ) => ` ${ e } ` ) ] : [ ] ) ,
547- ] ) ,
548- ) ;
549- }
0 commit comments