@@ -3022,6 +3022,97 @@ describe("exec approval handlers", () => {
30223022 expect ( manager . getSnapshot ( "approval-reviewer-runtime" ) ?. decision ) . toBe ( "allow-once" ) ;
30233023 } ) ;
30243024
3025+ it ( "allows admin clients to resolve reviewer-targeted runtime approvals" , async ( ) => {
3026+ const { manager, handlers, respond, context } = createExecApprovalFixture ( ) ;
3027+ const requesterClient = createExecApprovalClient ( {
3028+ connId : "conn-gateway-runtime" ,
3029+ clientId : GATEWAY_CLIENT_IDS . GATEWAY_CLIENT ,
3030+ deviceId : "device-gateway-runtime" ,
3031+ scopes : [ "operator.approvals" ] ,
3032+ approvalRuntime : true ,
3033+ } ) ;
3034+ const adminClient = createExecApprovalClient ( {
3035+ connId : "conn-admin" ,
3036+ clientId : GATEWAY_CLIENT_IDS . CONTROL_UI ,
3037+ deviceId : "device-admin" ,
3038+ scopes : [ "operator.admin" ] ,
3039+ } ) ;
3040+
3041+ const requestPromise = requestExecApproval ( {
3042+ handlers,
3043+ respond,
3044+ context,
3045+ client : requesterClient ,
3046+ params : {
3047+ id : "approval-reviewer-runtime-admin" ,
3048+ twoPhase : true ,
3049+ approvalReviewerDeviceIds : [ "device-ios-reviewer" ] ,
3050+ } ,
3051+ } ) ;
3052+ await vi . waitFor ( ( ) => {
3053+ expect ( respond . mock . calls . some ( ( call ) => call [ 1 ] ?. status === "accepted" ) ) . toBe ( true ) ;
3054+ } ) ;
3055+
3056+ const resolveRespond = vi . fn ( ) ;
3057+ await resolveExecApproval ( {
3058+ handlers,
3059+ id : "approval-reviewer-runtime-admin" ,
3060+ respond : resolveRespond ,
3061+ context,
3062+ client : adminClient ,
3063+ } ) ;
3064+ await requestPromise ;
3065+
3066+ expect ( resolveRespond ) . toHaveBeenCalledWith ( true , { ok : true } , undefined ) ;
3067+ expect ( manager . getSnapshot ( "approval-reviewer-runtime-admin" ) ?. decision ) . toBe ( "allow-once" ) ;
3068+ } ) ;
3069+
3070+ it ( "allows the internal approval runtime to resolve reviewer-targeted runtime approvals" , async ( ) => {
3071+ const { manager, handlers, respond, context } = createExecApprovalFixture ( ) ;
3072+ const requesterClient = createExecApprovalClient ( {
3073+ connId : "conn-gateway-runtime-requester" ,
3074+ clientId : GATEWAY_CLIENT_IDS . GATEWAY_CLIENT ,
3075+ deviceId : "device-gateway-runtime-requester" ,
3076+ scopes : [ "operator.approvals" ] ,
3077+ approvalRuntime : true ,
3078+ } ) ;
3079+ const runtimeResolverClient = createExecApprovalClient ( {
3080+ connId : "conn-gateway-runtime-resolver" ,
3081+ clientId : GATEWAY_CLIENT_IDS . GATEWAY_CLIENT ,
3082+ deviceId : "device-gateway-runtime-resolver" ,
3083+ scopes : [ "operator.approvals" ] ,
3084+ approvalRuntime : true ,
3085+ } ) ;
3086+
3087+ const requestPromise = requestExecApproval ( {
3088+ handlers,
3089+ respond,
3090+ context,
3091+ client : requesterClient ,
3092+ params : {
3093+ id : "approval-reviewer-runtime-runtime" ,
3094+ twoPhase : true ,
3095+ approvalReviewerDeviceIds : [ "device-ios-reviewer" ] ,
3096+ } ,
3097+ } ) ;
3098+ await vi . waitFor ( ( ) => {
3099+ expect ( respond . mock . calls . some ( ( call ) => call [ 1 ] ?. status === "accepted" ) ) . toBe ( true ) ;
3100+ } ) ;
3101+
3102+ const resolveRespond = vi . fn ( ) ;
3103+ await resolveExecApproval ( {
3104+ handlers,
3105+ id : "approval-reviewer-runtime-runtime" ,
3106+ respond : resolveRespond ,
3107+ context,
3108+ client : runtimeResolverClient ,
3109+ } ) ;
3110+ await requestPromise ;
3111+
3112+ expect ( resolveRespond ) . toHaveBeenCalledWith ( true , { ok : true } , undefined ) ;
3113+ expect ( manager . getSnapshot ( "approval-reviewer-runtime-runtime" ) ?. decision ) . toBe ( "allow-once" ) ;
3114+ } ) ;
3115+
30253116 it ( "does not allow reviewer devices without approval scope to resolve runtime approvals" , async ( ) => {
30263117 const { manager, handlers, respond, context } = createExecApprovalFixture ( ) ;
30273118 const requesterClient = createExecApprovalClient ( {
0 commit comments