@@ -1068,6 +1068,47 @@ describe("tools.invoke Gateway RPC", () => {
10681068 expect ( hookCtx . sessionKey ) . toBe ( "agent:main:main" ) ;
10691069 } ) ;
10701070
1071+ it ( "keeps owner-only tools unavailable to non-owner RPC callers despite gateway.tools.allow" , async ( ) => {
1072+ setMainAllowedTools ( {
1073+ allow : [ "cron" , "gateway" , "nodes" ] ,
1074+ gatewayAllow : [ "cron" , "gateway" , "nodes" ] ,
1075+ } ) ;
1076+
1077+ for ( const tool of [ "cron" , "gateway" , "nodes" ] ) {
1078+ const call = await invokeToolsRpc ( {
1079+ name : tool ,
1080+ args : { } ,
1081+ sessionKey : "main" ,
1082+ } ) ;
1083+
1084+ expect ( call ?. [ 0 ] , tool ) . toBe ( true ) ;
1085+ expect ( call ?. [ 1 ] ?. ok , tool ) . toBe ( false ) ;
1086+ expect ( call ?. [ 1 ] ?. toolName , tool ) . toBe ( tool ) ;
1087+ const error = call ?. [ 1 ] ?. error as { code ?: string ; message ?: string } | undefined ;
1088+ expect ( error ?. code , tool ) . toBe ( "not_found" ) ;
1089+ }
1090+ expect ( lastCreateOpenClawToolsContext ?. senderIsOwner ) . toBe ( false ) ;
1091+ } ) ;
1092+
1093+ it ( "keeps operator.admin RPC callers as owner for explicitly allowed owner-only tools" , async ( ) => {
1094+ setMainAllowedTools ( { allow : [ "nodes" ] , gatewayAllow : [ "nodes" ] } ) ;
1095+
1096+ const call = await invokeToolsRpc (
1097+ {
1098+ name : "nodes" ,
1099+ args : { } ,
1100+ sessionKey : "main" ,
1101+ } ,
1102+ [ "operator.admin" ] ,
1103+ ) ;
1104+
1105+ expect ( call ?. [ 0 ] ) . toBe ( true ) ;
1106+ expect ( call ?. [ 1 ] ?. ok ) . toBe ( true ) ;
1107+ expect ( call ?. [ 1 ] ?. toolName ) . toBe ( "nodes" ) ;
1108+ expect ( call ?. [ 1 ] ?. output ) . toEqual ( { ok : true , result : "nodes" } ) ;
1109+ expect ( lastCreateOpenClawToolsContext ?. senderIsOwner ) . toBe ( true ) ;
1110+ } ) ;
1111+
10711112 it ( "returns typed approval-needed refusal when the policy hook blocks" , async ( ) => {
10721113 setMainAllowedTools ( { allow : [ "tools_invoke_test" ] } ) ;
10731114 hookMocks . runBeforeToolCallHook . mockResolvedValueOnce ( {
0 commit comments