diff --git a/pkg/roles/role.go b/pkg/roles/role.go
new file mode 100644
index 0000000000000000000000000000000000000000..4c284ee5d45026aedfc284ecc16e146e78b56bb2
--- /dev/null
+++ b/pkg/roles/role.go
@@ -0,0 +1,65 @@
+package roles
+
+import (
+	"context"
+
+	"git.perx.ru/perxis/perxis-go/pkg/data"
+	"git.perx.ru/perxis/perxis-go/pkg/environments"
+	"git.perx.ru/perxis/perxis-go/pkg/permission"
+)
+
+const (
+	AnonymousRole  = "anonymous"
+	AuthorizedRole = "authorized"
+	ViewRole       = "view"
+)
+
+type Role struct {
+	// Внутренний идентификатор роли
+	ID string `json:"id" bson:"_id"`
+
+	// Идентификатор пространства
+	SpaceID string `json:"spaceId" bson:"-"`
+
+	// Описание роли, назначение
+	Description string `json:"description" bson:"description"`
+
+	// Список доступных окружений (ID или Alias)
+	Environments []string `json:"environments" bson:"environments"`
+
+	// Список правил доступа к коллекциям
+	Rules permission.Rules `json:"rules" bson:"rules"`
+
+	// Разрешить доступ API управления
+	AllowManagement bool `json:"allow_management" bson:"allow_management"`
+}
+
+func (r Role) CanAccessEnvironment(ctx context.Context, service environments.Environments, spaceID, envID string) bool {
+	if spaceID == "" || envID == "" {
+		return false
+	}
+
+	// Если явно не указаны доступные окружения - доступ по умолчанию к окружению master
+	if len(r.Environments) == 0 {
+		r.Environments = []string{environments.DefaultEnvironment}
+	}
+
+	if data.Contains(envID, r.Environments) {
+		return true
+	}
+
+	e, err := service.Get(ctx, spaceID, envID)
+	if err != nil || e == nil {
+		return false
+	}
+
+	aliases := append(e.Aliases, e.ID)
+
+	for _, ce := range r.Environments {
+		if data.Contains(ce, aliases) {
+			return true
+		}
+	}
+
+	return false
+}
diff --git a/pkg/roles/service.go b/pkg/roles/service.go
index 4606e3dd2309ace03ce6caa7f02bddfc6ce4aa2f..b003008b10c7c0a0de6549c60262741fdf441f65 100644
--- a/pkg/roles/service.go
+++ b/pkg/roles/service.go
@@ -2,38 +2,8 @@ package roles
 
 import (
 	"context"
-
-	"git.perx.ru/perxis/perxis-go/pkg/data"
-	"git.perx.ru/perxis/perxis-go/pkg/environments"
-	"git.perx.ru/perxis/perxis-go/pkg/permission"
-)
-
-const (
-	AnonymousRole  = "anonymous"
-	AuthorizedRole = "authorized"
-	ViewRole       = "view"
 )
 
-type Role struct {
-	// Внутренний идентификатор роли
-	ID string `json:"id" bson:"_id"`
-
-	// Идентификатор пространства
-	SpaceID string `json:"spaceId" bson:"-"`
-
-	// Описание роли, назначение
-	Description string `json:"description" bson:"description"`
-
-	// Список доступных окружений (ID или Alias)
-	Environments []string `json:"environments" bson:"environments"`
-
-	// Список правил доступа к коллекциям
-	Rules permission.Rules `json:"rules" bson:"rules"`
-
-	// Разрешить доступ API управления
-	AllowManagement bool `json:"allow_management" bson:"allow_management"`
-}
-
 // @microgen grpc
 // @protobuf git.perx.ru/perxis/perxis-go/proto/roles
 // @grpc-addr content.roles.Roles
@@ -44,33 +14,3 @@ type Roles interface {
 	Update(ctx context.Context, role *Role) (err error)
 	Delete(ctx context.Context, spaceId, roleId string) (err error)
 }
-
-func (r Role) CanAccessEnvironment(ctx context.Context, service environments.Environments, spaceID, envID string) bool {
-	if spaceID == "" || envID == "" {
-		return false
-	}
-
-	// Если явно не указаны доступные окружения - доступ по умолчанию к окружению master
-	if len(r.Environments) == 0 {
-		r.Environments = []string{environments.DefaultEnvironment}
-	}
-
-	if data.Contains(envID, r.Environments) {
-		return true
-	}
-
-	e, err := service.Get(ctx, spaceID, envID)
-	if err != nil || e == nil {
-		return false
-	}
-
-	aliases := append(e.Aliases, e.ID)
-
-	for _, ce := range r.Environments {
-		if data.Contains(ce, aliases) {
-			return true
-		}
-	}
-
-	return false
-}