@@ -94,6 +94,18 @@ describe('toolCallNeedsApproval', () => {
9494 expect ( toolCallNeedsApproval ( 'terminal' , context , { } , false , runCall ) ) . toBe ( false )
9595 } )
9696
97+ it ( 'applies the normal saved permission to code with a secret reference' , ( ) => {
98+ const context = makeContext ( )
99+ context . toolPermissions . autoAllowed . add ( 'function_execute' )
100+
101+ expect (
102+ toolCallNeedsApproval ( 'function_execute' , context , { } , false , {
103+ language : 'javascript' ,
104+ code : 'return {{API_KEY}}' ,
105+ } )
106+ ) . toBe ( false )
107+ } )
108+
97109 it ( 'never gates a non-interactive run, which has nobody to answer the prompt' , ( ) => {
98110 expect (
99111 toolCallNeedsApproval ( 'terminal' , makeContext ( ) , { interactive : false } , false , runCall )
@@ -106,6 +118,18 @@ describe('toolCallNeedsApproval', () => {
106118 expect ( toolCallNeedsApproval ( 'terminal' , context , { } , false , runCall ) ) . toBe ( false )
107119 } )
108120
121+ it ( 'does not add a secret-specific gate when the permission feature is off' , ( ) => {
122+ const context = makeContext ( )
123+ context . toolPermissions . enabled = false
124+
125+ expect (
126+ toolCallNeedsApproval ( 'function_execute' , context , { } , false , {
127+ language : 'javascript' ,
128+ code : 'return {{API_KEY}}' ,
129+ } )
130+ ) . toBe ( false )
131+ } )
132+
109133 it ( 'gates a resolved integration operation off the frame Go stamped' , ( ) => {
110134 // gmail_read_v2 is request-local: it is not in the catalog at all, so the
111135 // only thing marking it is the awaiting_approval status on the frame.
@@ -284,6 +308,23 @@ describe('runGatedToolExecution', () => {
284308 expect ( context . toolPermissions . autoAllowed . has ( 'terminal' ) ) . toBe ( true )
285309 } )
286310
311+ it ( 'accepts the normal chat-level decision for code with a secret reference' , async ( ) => {
312+ const context = makeContext ( )
313+ const toolCall = makeToolCall ( )
314+ toolCall . name = 'function_execute'
315+ toolCall . params = { language : 'javascript' , code : 'return {{API_KEY}}' }
316+ const execute = vi . fn ( ) . mockResolvedValue ( { status : 'success' } )
317+ waitForToolPermissionDecision . mockResolvedValue ( {
318+ toolCallId : 'call-1' ,
319+ decision : 'allow_chat' ,
320+ } )
321+
322+ await gate ( context , toolCall , execute , [ ] )
323+
324+ expect ( execute ) . toHaveBeenCalledTimes ( 1 )
325+ expect ( context . toolPermissions . autoAllowed . has ( 'function_execute' ) ) . toBe ( true )
326+ } )
327+
287328 it ( 'does not suppress later prompts for a one-off allow' , async ( ) => {
288329 const context = makeContext ( )
289330 const toolCall = makeToolCall ( )
0 commit comments