ExecuteRemotePlugin executes a plugin on the server and returns the output. Security (C1): Requires at least "user" role — readonly users cannot execute plugins.
(ctx context.Context, req *pb.ExecuteRemotePluginRequest)
| 192 | // ExecuteRemotePlugin executes a plugin on the server and returns the output. |
| 193 | // Security (C1): Requires at least "user" role — readonly users cannot execute plugins. |
| 194 | func (h *Handler) ExecuteRemotePlugin(ctx context.Context, req *pb.ExecuteRemotePluginRequest) (*pb.ExecuteRemotePluginResponse, error) { |
| 195 | // Access control: readonly users cannot execute plugins |
| 196 | if user := UserFromContext(ctx); user != nil && !user.HasRole(RoleUser) { |
| 197 | return nil, status.Errorf(codes.PermissionDenied, "insufficient permissions: role %q cannot execute plugins", user.Role) |
| 198 | } |
| 199 | |
| 200 | if h.pluginManager == nil { |
| 201 | return nil, status.Errorf(codes.Unavailable, "%s", i18n.T("server.remote.plugin_unavailable")) |
| 202 | } |
| 203 | if req.PluginName == "" { |
| 204 | return nil, status.Errorf(codes.InvalidArgument, "%s", i18n.T("server.remote.plugin_name_required")) |
| 205 | } |
| 206 | |
| 207 | plugin, ok := h.pluginManager.GetPlugin(req.PluginName) |
| 208 | if !ok { |
| 209 | return nil, status.Errorf(codes.NotFound, "%s", i18n.T("server.remote.plugin_not_found", req.PluginName)) |
| 210 | } |
| 211 | |
| 212 | h.logger.Info(i18n.T("server.remote.plugin_executing"), |
| 213 | zap.String("plugin", req.PluginName), |
| 214 | zap.Strings("args", req.Args), |
| 215 | ) |
| 216 | |
| 217 | output, err := plugin.Execute(ctx, req.Args) |
| 218 | resp := &pb.ExecuteRemotePluginResponse{ |
| 219 | Output: output, |
| 220 | Done: true, |
| 221 | } |
| 222 | if err != nil { |
| 223 | resp.Error = err.Error() |
| 224 | } |
| 225 | |
| 226 | return resp, nil |
| 227 | } |
| 228 | |
| 229 | // DownloadPlugin streams the plugin binary to the client. |
| 230 | func (h *Handler) DownloadPlugin(req *pb.DownloadPluginRequest, stream pb.ChatCLIService_DownloadPluginServer) error { |