@@ -157,7 +157,7 @@ function buildConnectorPluginApprovalElicitation(overrides: Record<string, unkno
157157function createPluginAppPolicyContext (
158158 params : {
159159 allowDestructiveActions ?: boolean ;
160- destructiveApprovalMode ?: "allow" | "deny" | "auto" ;
160+ destructiveApprovalMode ?: "allow" | "deny" | "auto" | "always" ;
161161 apps ?: Array < { appId : string ; pluginName : string ; mcpServerNames : string [ ] } > ;
162162 } = { } ,
163163) {
@@ -1017,6 +1017,96 @@ describe("Codex app-server elicitation bridge", () => {
10171017 } ) ;
10181018 } ) ;
10191019
1020+ it ( "does not expose allow-always for always plugin policy" , async ( ) => {
1021+ mockCallGatewayTool
1022+ . mockResolvedValueOnce ( { id : "plugin:approval-calendar-always-policy" , status : "accepted" } )
1023+ . mockResolvedValueOnce ( {
1024+ id : "plugin:approval-calendar-always-policy" ,
1025+ decision : "allow-once" ,
1026+ } ) ;
1027+
1028+ const result = await handleCodexAppServerElicitationRequest ( {
1029+ requestParams : buildConnectorPluginApprovalElicitation ( {
1030+ _meta : {
1031+ codex_approval_kind : "mcp_tool_call" ,
1032+ source : "connector" ,
1033+ connector_id : "connector_google_calendar" ,
1034+ connector_name : "Google Calendar" ,
1035+ persist : [ "session" , "always" ] ,
1036+ tool_title : "create_event" ,
1037+ } ,
1038+ } ) ,
1039+ paramsForRun : createParams ( ) ,
1040+ threadId : "thread-1" ,
1041+ turnId : "turn-1" ,
1042+ pluginAppPolicyContext : createPluginAppPolicyContext ( {
1043+ allowDestructiveActions : true ,
1044+ destructiveApprovalMode : "always" ,
1045+ apps : [
1046+ {
1047+ appId : "connector_google_calendar" ,
1048+ pluginName : "google-calendar" ,
1049+ mcpServerNames : [ ] ,
1050+ } ,
1051+ ] ,
1052+ } ) ,
1053+ } ) ;
1054+
1055+ expect ( result ) . toEqual ( {
1056+ action : "accept" ,
1057+ content : null ,
1058+ _meta : null ,
1059+ } ) ;
1060+ expect ( gatewayToolArg ( 0 , 2 ) ) . toMatchObject ( {
1061+ allowedDecisions : [ "allow-once" , "deny" ] ,
1062+ } ) ;
1063+ } ) ;
1064+
1065+ it ( "maps unexpected allow-always decisions to one-shot for always plugin policy" , async ( ) => {
1066+ mockCallGatewayTool
1067+ . mockResolvedValueOnce ( {
1068+ id : "plugin:approval-calendar-unexpected-always" ,
1069+ status : "accepted" ,
1070+ } )
1071+ . mockResolvedValueOnce ( {
1072+ id : "plugin:approval-calendar-unexpected-always" ,
1073+ decision : "allow-always" ,
1074+ } ) ;
1075+
1076+ const result = await handleCodexAppServerElicitationRequest ( {
1077+ requestParams : buildConnectorPluginApprovalElicitation ( {
1078+ _meta : {
1079+ codex_approval_kind : "mcp_tool_call" ,
1080+ source : "connector" ,
1081+ connector_id : "connector_google_calendar" ,
1082+ connector_name : "Google Calendar" ,
1083+ persist : [ "session" , "always" ] ,
1084+ tool_title : "create_event" ,
1085+ } ,
1086+ } ) ,
1087+ paramsForRun : createParams ( ) ,
1088+ threadId : "thread-1" ,
1089+ turnId : "turn-1" ,
1090+ pluginAppPolicyContext : createPluginAppPolicyContext ( {
1091+ allowDestructiveActions : true ,
1092+ destructiveApprovalMode : "always" ,
1093+ apps : [
1094+ {
1095+ appId : "connector_google_calendar" ,
1096+ pluginName : "google-calendar" ,
1097+ mcpServerNames : [ ] ,
1098+ } ,
1099+ ] ,
1100+ } ) ,
1101+ } ) ;
1102+
1103+ expect ( result ) . toEqual ( {
1104+ action : "accept" ,
1105+ content : null ,
1106+ _meta : null ,
1107+ } ) ;
1108+ } ) ;
1109+
10201110 it ( "declines denied auto plugin app approvals" , async ( ) => {
10211111 mockCallGatewayTool
10221112 . mockResolvedValueOnce ( { id : "plugin:approval-calendar-deny" , status : "accepted" } )
0 commit comments