@@ -478,11 +478,70 @@ export async function runControlsFailing(flags) {
478478 return buildControlsFailingPayload ( data , flags ) ;
479479}
480480
481+ export async function runControlsGet ( flags , options = { } ) {
482+ const code = String ( options . code ?? "" ) ;
483+ const queryFlags = cloneFlags ( flags ) ;
484+ pushNamed ( queryFlags , "q" , code ) ;
485+ const { data } = await listV1 ( "controls-get-controls" , queryFlags ) ;
486+ const control = dataItems ( data ) . map ( enrichControl ) . find ( ( item ) => item . code === code ) ;
487+ if ( ! control ) {
488+ fail ( "control_not_found" , `Control ${ code } was not found.` , { code } ) ;
489+ }
490+
491+ return flags . compact
492+ ? { kind : "controls.get" , control : compactControlsPayload ( { controls : [ control ] } ) . controls [ 0 ] }
493+ : { kind : "controls.get" , control } ;
494+ }
495+
481496export async function runMonitorsFailing ( flags ) {
482497 const { data } = await listV1 ( "list-monitors" , flags ) ;
483498 return buildMonitorsFailingPayload ( data , flags ) ;
484499}
485500
501+ function controlIdentifierMatches ( control , target ) {
502+ return [ control . code , control . id ] . filter ( ( value ) => value !== undefined && value !== null ) . some ( ( value ) => String ( value ) === target ) ;
503+ }
504+
505+ export async function runMonitorsForControl ( flags , options = { } ) {
506+ const code = String ( options . code ?? "" ) ;
507+ const { data } = await listV1 ( "list-monitors" , flags ) ;
508+ // This uses controls embedded on the list response; use `monitors get --workspace-id` for detail-only fields.
509+ const monitors = dataItems ( data ) . filter ( ( monitor ) => ( monitor . controls ?? [ ] ) . some ( ( control ) => controlIdentifierMatches ( control , code ) ) ) ;
510+ const limitedMonitors = applyLimit ( monitors , flags ) ;
511+ const payload = {
512+ kind : "monitors.for-control" ,
513+ code,
514+ total : payloadTotal ( data , dataItems ( data ) ) ,
515+ matching : monitors . length ,
516+ showing : limitedMonitors . length ,
517+ monitors : limitedMonitors ,
518+ } ;
519+
520+ return flags . compact ? compactMonitorsPayload ( payload ) : payload ;
521+ }
522+
523+ export async function runMonitorsGet ( flags , options = { } ) {
524+ const id = String ( options . id ?? "" ) ;
525+ let monitor = null ;
526+
527+ if ( options . workspaceId ) {
528+ const detailFlags = withPath ( flags , { workspaceId : options . workspaceId , testId : id } ) ;
529+ const { data } = await runWorkflowOperation ( "v1" , "get-control-test-instance" , detailFlags ) ;
530+ monitor = data ;
531+ } else {
532+ const { data } = await listV1 ( "list-monitors" , flags ) ;
533+ monitor = dataItems ( data ) . find ( ( item ) => String ( item . id ) === id ) ;
534+ }
535+
536+ if ( ! monitor ) {
537+ fail ( "monitor_not_found" , `Monitor ${ id } was not found.` , { id } ) ;
538+ }
539+
540+ return flags . compact
541+ ? { kind : "monitors.get" , monitor : compactMonitorsPayload ( { monitors : [ monitor ] } ) . monitors [ 0 ] }
542+ : { kind : "monitors.get" , monitor } ;
543+ }
544+
486545export async function runConnectionsList ( flags , options = { } ) {
487546 const { data } = await listV1 ( "get-connections" , flags ) ;
488547 return buildConnectionsListPayload ( data , flags , options . status ) ;
@@ -493,6 +552,43 @@ export async function runPersonnelIssues(flags) {
493552 return buildPersonnelIssuesPayload ( data , flags ) ;
494553}
495554
555+ export async function runPersonnelGet ( flags , options = { } ) {
556+ if ( options . email && options . id ) {
557+ fail ( "conflicting_personnel_lookup" , "Use either a personnel id or --email, not both." ) ;
558+ }
559+
560+ if ( options . email ) {
561+ const detailFlags = withPath ( flags , { email : options . email } ) ;
562+ const { data } = await runWorkflowOperation ( "v1" , "get-personnel-details-by-email" , detailFlags ) ;
563+ return flags . compact ? { kind : "personnel.get" , personnel : compactPersonnel ( data ) } : { kind : "personnel.get" , personnel : data } ;
564+ }
565+
566+ if ( options . id ) {
567+ const detailFlags = withPath ( flags , { id : options . id } ) ;
568+ const { data } = await runWorkflowOperation ( "v1" , "get-personnel-details" , detailFlags ) ;
569+ return flags . compact ? { kind : "personnel.get" , personnel : compactPersonnel ( data ) } : { kind : "personnel.get" , personnel : data } ;
570+ }
571+
572+ fail ( "missing_personnel_lookup" , "Provide a personnel id or --email." ) ;
573+ }
574+
575+ export async function runEvidenceList ( flags , options = { } ) {
576+ const workspaceId = options . workspaceId || ( await getFirstWorkspaceId ( flags ) ) ;
577+ const listFlags = withPath ( withListDefaults ( flags ) , { workspaceId } ) ;
578+ const { data } = await runWorkflowOperation ( "v1" , "list-evidence" , listFlags ) ;
579+ const evidence = applyLimit ( dataItems ( data ) , flags ) ;
580+ const payload = {
581+ kind : "evidence.list" ,
582+ workspaceId,
583+ total : payloadTotal ( data , dataItems ( data ) ) ,
584+ matching : dataItems ( data ) . length ,
585+ showing : evidence . length ,
586+ evidence,
587+ } ;
588+
589+ return flags . compact ? compactEvidencePayload ( payload ) : payload ;
590+ }
591+
496592export async function runEvidenceExpiring ( flags , options = { } ) {
497593 // Defaulting to the first workspace keeps the command ergonomic for single-workspace tenants.
498594 // Multi-workspace tenants should pass --workspace-id explicitly for deterministic scope.
@@ -533,12 +629,22 @@ function formatWorkflowText(payload) {
533629 . join ( "\n" ) ;
534630 case "controls.failing" :
535631 return [ `Failing Controls: matching=${ payload . matching } showing=${ payload . showing } ` , ...payload . controls . map ( ( c ) => `${ c . code ?? c . id } ${ c . status } ${ c . name } ` ) ] . join ( "\n" ) ;
632+ case "controls.get" :
633+ return `${ payload . control . code ?? payload . control . id } ${ payload . control . status } ${ payload . control . name } ` ;
536634 case "monitors.failing" :
537635 return [ `Failing Monitors: matching=${ payload . matching } showing=${ payload . showing } ` , ...payload . monitors . map ( ( m ) => `${ m . id } ${ monitorStatus ( m ) } ${ m . name } ` ) ] . join ( "\n" ) ;
636+ case "monitors.for-control" :
637+ return [ `Monitors for ${ payload . code } : matching=${ payload . matching } showing=${ payload . showing } ` , ...payload . monitors . map ( ( m ) => `${ m . id } ${ monitorStatus ( m ) } ${ m . name } ` ) ] . join ( "\n" ) ;
638+ case "monitors.get" :
639+ return `${ payload . monitor . id } ${ payload . monitor . status ?? monitorStatus ( payload . monitor ) } ${ payload . monitor . name } ` ;
538640 case "connections.list" :
539641 return [ `Connections: matching=${ payload . matching } showing=${ payload . showing } ` , ...payload . connections . map ( ( c ) => `${ c . id } ${ connectionState ( c ) } ${ c . clientAlias || c . clientType || "" } ` ) ] . join ( "\n" ) ;
540642 case "personnel.issues" :
541643 return [ `Personnel with device issues: matching=${ payload . matching } showing=${ payload . showing } ` , ...payload . personnel . map ( ( p ) => `${ p . id } ${ p . user ?. email ?? p . email ?? "" } failing_devices=${ p . devicesFailingComplianceCount ?? 0 } ` ) ] . join ( "\n" ) ;
644+ case "personnel.get" :
645+ return `${ payload . personnel . id } ${ payload . personnel . user ?. email ?? payload . personnel . email ?? "" } ` ;
646+ case "evidence.list" :
647+ return [ `Evidence: workspace=${ payload . workspaceId } total=${ payload . total } showing=${ payload . showing } ` , ...payload . evidence . map ( ( e ) => `${ e . id } ${ e . updatedAt ?? "unknown" } ${ e . name ?? "" } ` ) ] . join ( "\n" ) ;
542648 case "evidence.expiring" :
543649 return [ `Stale Evidence: workspace=${ payload . workspaceId ?? "auto" } days=${ payload . days } matching=${ payload . matching } showing=${ payload . showing } ` , ...payload . evidence . map ( ( e ) => `${ e . id } ${ e . updatedAt ?? "unknown" } ${ e . name ?? "" } ` ) ] . join ( "\n" ) ;
544650 default :
0 commit comments