@@ -584,6 +584,63 @@ impl VerifierClient {
584584 ) -> Result < Option < Value > , KeylimectlError > {
585585 debug ! ( "Getting agent {agent_uuid} from verifier" ) ;
586586
587+ // Try API v3.0+ first, fallback to v2.x if not implemented
588+ if self . api_version . parse :: < f32 > ( ) . unwrap_or ( 2.0 ) >= 3.0 {
589+ match self . get_agent_v3 ( agent_uuid) . await {
590+ Ok ( result) => return Ok ( result) ,
591+ Err ( KeylimectlError :: Api { status : 404 , .. } ) => {
592+ debug ! ( "V3.0 get agent endpoint not implemented, falling back to v2.x" ) ;
593+ // Continue to v2.x fallback below
594+ }
595+ Err ( e) => return Err ( e) ,
596+ }
597+ }
598+
599+ // V2.x endpoint (or fallback from v3.0)
600+ let url = format ! (
601+ "{}/v2.1/agents/{}" , // Use v2.1 as stable legacy version
602+ self . base. base_url, agent_uuid
603+ ) ;
604+
605+ let response = self
606+ . base
607+ . client
608+ . get_request ( Method :: GET , & url)
609+ . send ( )
610+ . await
611+ . with_context ( || {
612+ "Failed to send get agent request to verifier" . to_string ( )
613+ } ) ?;
614+
615+ match response. status ( ) {
616+ StatusCode :: OK => {
617+ let json_response: Value = self
618+ . base
619+ . handle_response ( response)
620+ . await
621+ . map_err ( KeylimectlError :: from) ?;
622+ Ok ( Some ( json_response) )
623+ }
624+ StatusCode :: NOT_FOUND => Ok ( None ) ,
625+ _ => {
626+ let error_response: Result < Value , KeylimectlError > = self
627+ . base
628+ . handle_response ( response)
629+ . await
630+ . map_err ( KeylimectlError :: from) ;
631+ match error_response {
632+ Ok ( _) => Ok ( None ) ,
633+ Err ( e) => Err ( e) ,
634+ }
635+ }
636+ }
637+ }
638+
639+ /// Get agent using v3.0 API (when implemented)
640+ async fn get_agent_v3 (
641+ & self ,
642+ agent_uuid : & str ,
643+ ) -> Result < Option < Value > , KeylimectlError > {
587644 let url = format ! (
588645 "{}/v{}/agents/{}" ,
589646 self . base. base_url, self . api_version, agent_uuid
@@ -596,7 +653,8 @@ impl VerifierClient {
596653 . send ( )
597654 . await
598655 . with_context ( || {
599- "Failed to send get agent request to verifier" . to_string ( )
656+ "Failed to send get agent request to verifier (v3.0)"
657+ . to_string ( )
600658 } ) ?;
601659
602660 match response. status ( ) {
@@ -668,6 +726,45 @@ impl VerifierClient {
668726 ) -> Result < Value , KeylimectlError > {
669727 debug ! ( "Deleting agent {agent_uuid} from verifier" ) ;
670728
729+ // Try API v3.0+ first, fallback to v2.x if not implemented
730+ if self . api_version . parse :: < f32 > ( ) . unwrap_or ( 2.0 ) >= 3.0 {
731+ match self . delete_agent_v3 ( agent_uuid) . await {
732+ Ok ( result) => return Ok ( result) ,
733+ Err ( KeylimectlError :: Api { status : 404 , .. } ) => {
734+ debug ! ( "V3.0 delete endpoint not implemented, falling back to v2.x" ) ;
735+ // Continue to v2.x fallback below
736+ }
737+ Err ( e) => return Err ( e) ,
738+ }
739+ }
740+
741+ // V2.x endpoint (or fallback from v3.0)
742+ let url = format ! (
743+ "{}/v2.1/agents/{}" , // Use v2.1 as stable legacy version
744+ self . base. base_url, agent_uuid
745+ ) ;
746+
747+ let response = self
748+ . base
749+ . client
750+ . get_request ( Method :: DELETE , & url)
751+ . send ( )
752+ . await
753+ . with_context ( || {
754+ "Failed to send delete agent request to verifier" . to_string ( )
755+ } ) ?;
756+
757+ self . base
758+ . handle_response ( response)
759+ . await
760+ . map_err ( KeylimectlError :: from)
761+ }
762+
763+ /// Delete agent using v3.0 API (when implemented)
764+ async fn delete_agent_v3 (
765+ & self ,
766+ agent_uuid : & str ,
767+ ) -> Result < Value , KeylimectlError > {
671768 let url = format ! (
672769 "{}/v{}/agents/{}" ,
673770 self . base. base_url, self . api_version, agent_uuid
@@ -680,7 +777,8 @@ impl VerifierClient {
680777 . send ( )
681778 . await
682779 . with_context ( || {
683- "Failed to send delete agent request to verifier" . to_string ( )
780+ "Failed to send delete agent request to verifier (v3.0)"
781+ . to_string ( )
684782 } ) ?;
685783
686784 self . base
@@ -696,6 +794,47 @@ impl VerifierClient {
696794 ) -> Result < Value , KeylimectlError > {
697795 debug ! ( "Reactivating agent {agent_uuid} on verifier" ) ;
698796
797+ // Try API v3.0+ first, fallback to v2.x if not implemented
798+ if self . api_version . parse :: < f32 > ( ) . unwrap_or ( 2.0 ) >= 3.0 {
799+ match self . reactivate_agent_v3 ( agent_uuid) . await {
800+ Ok ( result) => return Ok ( result) ,
801+ Err ( KeylimectlError :: Api { status : 404 , .. } ) => {
802+ debug ! ( "V3.0 reactivate endpoint not implemented, falling back to v2.x" ) ;
803+ // Continue to v2.x fallback below
804+ }
805+ Err ( e) => return Err ( e) ,
806+ }
807+ }
808+
809+ // V2.x endpoint (or fallback from v3.0)
810+ let url = format ! (
811+ "{}/v2.1/agents/{}/reactivate" , // Use v2.1 as stable legacy version
812+ self . base. base_url, agent_uuid
813+ ) ;
814+
815+ let response = self
816+ . base
817+ . client
818+ . get_request ( Method :: PUT , & url)
819+ . body ( "" )
820+ . send ( )
821+ . await
822+ . with_context ( || {
823+ "Failed to send reactivate agent request to verifier"
824+ . to_string ( )
825+ } ) ?;
826+
827+ self . base
828+ . handle_response ( response)
829+ . await
830+ . map_err ( KeylimectlError :: from)
831+ }
832+
833+ /// Reactivate agent using v3.0 API (when implemented)
834+ async fn reactivate_agent_v3 (
835+ & self ,
836+ agent_uuid : & str ,
837+ ) -> Result < Value , KeylimectlError > {
699838 let url = format ! (
700839 "{}/v{}/agents/{}/reactivate" ,
701840 self . base. base_url, self . api_version, agent_uuid
@@ -709,7 +848,7 @@ impl VerifierClient {
709848 . send ( )
710849 . await
711850 . with_context ( || {
712- "Failed to send reactivate agent request to verifier"
851+ "Failed to send reactivate agent request to verifier (v3.0) "
713852 . to_string ( )
714853 } ) ?;
715854
@@ -781,6 +920,46 @@ impl VerifierClient {
781920 ) -> Result < Value , KeylimectlError > {
782921 debug ! ( "Listing agents on verifier" ) ;
783922
923+ // Try API v3.0+ first, fallback to v2.x if not implemented
924+ if self . api_version . parse :: < f32 > ( ) . unwrap_or ( 2.0 ) >= 3.0 {
925+ match self . list_agents_v3 ( verifier_id) . await {
926+ Ok ( result) => return Ok ( result) ,
927+ Err ( KeylimectlError :: Api { status : 404 , .. } ) => {
928+ debug ! ( "V3.0 list agents endpoint not implemented, falling back to v2.x" ) ;
929+ // Continue to v2.x fallback below
930+ }
931+ Err ( e) => return Err ( e) ,
932+ }
933+ }
934+
935+ // V2.x endpoint (or fallback from v3.0)
936+ let mut url = format ! ( "{}/v2.1/agents/" , self . base. base_url) ; // Use v2.1 as stable legacy version
937+
938+ if let Some ( vid) = verifier_id {
939+ url. push_str ( & format ! ( "?verifier={vid}" ) ) ;
940+ }
941+
942+ let response = self
943+ . base
944+ . client
945+ . get_request ( Method :: GET , & url)
946+ . send ( )
947+ . await
948+ . with_context ( || {
949+ "Failed to send list agents request to verifier" . to_string ( )
950+ } ) ?;
951+
952+ self . base
953+ . handle_response ( response)
954+ . await
955+ . map_err ( KeylimectlError :: from)
956+ }
957+
958+ /// List agents using v3.0 API (when implemented)
959+ async fn list_agents_v3 (
960+ & self ,
961+ verifier_id : Option < & str > ,
962+ ) -> Result < Value , KeylimectlError > {
784963 let mut url =
785964 format ! ( "{}/v{}/agents/" , self . base. base_url, self . api_version) ;
786965
@@ -795,7 +974,8 @@ impl VerifierClient {
795974 . send ( )
796975 . await
797976 . with_context ( || {
798- "Failed to send list agents request to verifier" . to_string ( )
977+ "Failed to send list agents request to verifier (v3.0)"
978+ . to_string ( )
799979 } ) ?;
800980
801981 self . base
@@ -870,6 +1050,49 @@ impl VerifierClient {
8701050 ) -> Result < Value , KeylimectlError > {
8711051 debug ! ( "Getting bulk agent info from verifier" ) ;
8721052
1053+ // Try API v3.0+ first, fallback to v2.x if not implemented
1054+ if self . api_version . parse :: < f32 > ( ) . unwrap_or ( 2.0 ) >= 3.0 {
1055+ match self . get_bulk_info_v3 ( verifier_id) . await {
1056+ Ok ( result) => return Ok ( result) ,
1057+ Err ( KeylimectlError :: Api { status : 404 , .. } ) => {
1058+ debug ! ( "V3.0 bulk info endpoint not implemented, falling back to v2.x" ) ;
1059+ // Continue to v2.x fallback below
1060+ }
1061+ Err ( e) => return Err ( e) ,
1062+ }
1063+ }
1064+
1065+ // V2.x endpoint (or fallback from v3.0)
1066+ let mut url = format ! (
1067+ "{}/v2.1/agents/?bulk=true" , // Use v2.1 as stable legacy version
1068+ self . base. base_url
1069+ ) ;
1070+
1071+ if let Some ( vid) = verifier_id {
1072+ url. push_str ( & format ! ( "&verifier={vid}" ) ) ;
1073+ }
1074+
1075+ let response = self
1076+ . base
1077+ . client
1078+ . get_request ( Method :: GET , & url)
1079+ . send ( )
1080+ . await
1081+ . with_context ( || {
1082+ "Failed to send bulk info request to verifier" . to_string ( )
1083+ } ) ?;
1084+
1085+ self . base
1086+ . handle_response ( response)
1087+ . await
1088+ . map_err ( KeylimectlError :: from)
1089+ }
1090+
1091+ /// Get bulk info using v3.0 API (when implemented)
1092+ async fn get_bulk_info_v3 (
1093+ & self ,
1094+ verifier_id : Option < & str > ,
1095+ ) -> Result < Value , KeylimectlError > {
8731096 let mut url = format ! (
8741097 "{}/v{}/agents/?bulk=true" ,
8751098 self . base. base_url, self . api_version
@@ -886,7 +1109,8 @@ impl VerifierClient {
8861109 . send ( )
8871110 . await
8881111 . with_context ( || {
889- "Failed to send bulk info request to verifier" . to_string ( )
1112+ "Failed to send bulk info request to verifier (v3.0)"
1113+ . to_string ( )
8901114 } ) ?;
8911115
8921116 self . base
@@ -903,9 +1127,25 @@ impl VerifierClient {
9031127 ) -> Result < Value , KeylimectlError > {
9041128 debug ! ( "Adding runtime policy {policy_name} to verifier" ) ;
9051129
1130+ // Try API v3.0+ first, fallback to v2.x if not implemented
1131+ if self . api_version . parse :: < f32 > ( ) . unwrap_or ( 2.0 ) >= 3.0 {
1132+ match self
1133+ . add_runtime_policy_v3 ( policy_name, policy_data. clone ( ) )
1134+ . await
1135+ {
1136+ Ok ( result) => return Ok ( result) ,
1137+ Err ( KeylimectlError :: Api { status : 404 , .. } ) => {
1138+ debug ! ( "V3.0 runtime policy endpoint not implemented, falling back to v2.x" ) ;
1139+ // Continue to v2.x fallback below
1140+ }
1141+ Err ( e) => return Err ( e) ,
1142+ }
1143+ }
1144+
1145+ // V2.x endpoint (or fallback from v3.0)
9061146 let url = format ! (
907- "{}/v{} /allowlists/{}" ,
908- self . base. base_url, self . api_version , policy_name
1147+ "{}/v2.1 /allowlists/{}" , // Use v2.1 as stable legacy version
1148+ self . base. base_url, policy_name
9091149 ) ;
9101150
9111151 let response = self
@@ -931,6 +1171,40 @@ impl VerifierClient {
9311171 . map_err ( KeylimectlError :: from)
9321172 }
9331173
1174+ /// Add runtime policy using v3.0 API (when implemented)
1175+ async fn add_runtime_policy_v3 (
1176+ & self ,
1177+ policy_name : & str ,
1178+ policy_data : Value ,
1179+ ) -> Result < Value , KeylimectlError > {
1180+ let url = format ! (
1181+ "{}/v{}/policies/ima/{}" ,
1182+ self . base. base_url, self . api_version, policy_name
1183+ ) ;
1184+
1185+ let response = self
1186+ . base
1187+ . client
1188+ . get_json_request_from_struct (
1189+ Method :: POST ,
1190+ & url,
1191+ & policy_data,
1192+ None ,
1193+ )
1194+ . map_err ( KeylimectlError :: Json ) ?
1195+ . send ( )
1196+ . await
1197+ . with_context ( || {
1198+ "Failed to send add runtime policy request to verifier (v3.0)"
1199+ . to_string ( )
1200+ } ) ?;
1201+
1202+ self . base
1203+ . handle_response ( response)
1204+ . await
1205+ . map_err ( KeylimectlError :: from)
1206+ }
1207+
9341208 /// Get a runtime policy
9351209 pub async fn get_runtime_policy (
9361210 & self ,
0 commit comments