diff --git a/Makefile b/Makefile
index 9da3c2b3fabf48a3bb8659a6c39bf9f04e4e5e14..b98227b3cdace7fdabf7849386a91eb3f134a01a 100644
--- a/Makefile
+++ b/Makefile
@@ -81,8 +81,9 @@ recovering: $(SERVICERECOVERING)
 # Генерация моков для всех интерфейсов, найденных в директории. Выходные файлы с моками сохраняются в `./mocks`
 MOCKSDIRS?=$(shell find . -name "service.go" -exec dirname {} \;)
 MOCKS=$(MOCKSDIRS:=/mocks)
+PROTOMOCKS=$(PROTODIR:=/mocks)
 
-mocks: $(MOCKS)
+mocks: $(PROTOMOCKS)
 	@echo "Generate mocks $<"
 
 %/mocks: %
diff --git a/Taskfile.yaml b/Taskfile.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..244b11e774703bd26b17efaeadb51d279456384e
--- /dev/null
+++ b/Taskfile.yaml
@@ -0,0 +1,14 @@
+version: '3'
+
+tasks:
+  mocks:
+    deps:
+      - mocks.proto
+  mocks.proto:
+    sources:
+      - proto/**/*.proto
+    generates:
+      - proto/mocks/*.go
+    cmds:
+      - mockery --all --dir proto --output proto/mocks
+
diff --git a/pkg/clients/mocks/Clients.go b/pkg/clients/mocks/Clients.go
index f82320372fe227f84b9b5e49e306a7564aa1177f..289555adbc9e75dde72d65485e7e7961f5a12062 100644
--- a/pkg/clients/mocks/Clients.go
+++ b/pkg/clients/mocks/Clients.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -20,6 +20,10 @@ func (_m *Clients) Create(ctx context.Context, client *clients.Client) (*clients
 	ret := _m.Called(ctx, client)
 
 	var r0 *clients.Client
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.Client) (*clients.Client, error)); ok {
+		return rf(ctx, client)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *clients.Client) *clients.Client); ok {
 		r0 = rf(ctx, client)
 	} else {
@@ -28,7 +32,6 @@ func (_m *Clients) Create(ctx context.Context, client *clients.Client) (*clients
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *clients.Client) error); ok {
 		r1 = rf(ctx, client)
 	} else {
@@ -71,6 +74,10 @@ func (_m *Clients) Get(ctx context.Context, spaceId string, id string) (*clients
 	ret := _m.Called(ctx, spaceId, id)
 
 	var r0 *clients.Client
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string, string) (*clients.Client, error)); ok {
+		return rf(ctx, spaceId, id)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string, string) *clients.Client); ok {
 		r0 = rf(ctx, spaceId, id)
 	} else {
@@ -79,7 +86,6 @@ func (_m *Clients) Get(ctx context.Context, spaceId string, id string) (*clients
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
 		r1 = rf(ctx, spaceId, id)
 	} else {
@@ -94,6 +100,10 @@ func (_m *Clients) GetBy(ctx context.Context, spaceId string, params *clients.Ge
 	ret := _m.Called(ctx, spaceId, params)
 
 	var r0 *clients.Client
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string, *clients.GetByParams) (*clients.Client, error)); ok {
+		return rf(ctx, spaceId, params)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string, *clients.GetByParams) *clients.Client); ok {
 		r0 = rf(ctx, spaceId, params)
 	} else {
@@ -102,7 +112,6 @@ func (_m *Clients) GetBy(ctx context.Context, spaceId string, params *clients.Ge
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string, *clients.GetByParams) error); ok {
 		r1 = rf(ctx, spaceId, params)
 	} else {
@@ -117,6 +126,10 @@ func (_m *Clients) List(ctx context.Context, spaceId string) ([]*clients.Client,
 	ret := _m.Called(ctx, spaceId)
 
 	var r0 []*clients.Client
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string) ([]*clients.Client, error)); ok {
+		return rf(ctx, spaceId)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string) []*clients.Client); ok {
 		r0 = rf(ctx, spaceId)
 	} else {
@@ -125,7 +138,6 @@ func (_m *Clients) List(ctx context.Context, spaceId string) ([]*clients.Client,
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
 		r1 = rf(ctx, spaceId)
 	} else {
@@ -149,13 +161,12 @@ func (_m *Clients) Update(ctx context.Context, client *clients.Client) error {
 	return r0
 }
 
-type mockConstructorTestingTNewClients interface {
+// NewClients creates a new instance of Clients. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewClients(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewClients creates a new instance of Clients. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewClients(t mockConstructorTestingTNewClients) *Clients {
+}) *Clients {
 	mock := &Clients{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/clients/mocks/Middleware.go b/pkg/clients/mocks/Middleware.go
index b3b45df720893370e26363da2e9209f59163e091..7a409ad308e232500469b0cd69589e4f3ccbe89d 100644
--- a/pkg/clients/mocks/Middleware.go
+++ b/pkg/clients/mocks/Middleware.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -29,13 +29,12 @@ func (_m *Middleware) Execute(_a0 clients.Clients) clients.Clients {
 	return r0
 }
 
-type mockConstructorTestingTNewMiddleware interface {
+// NewMiddleware creates a new instance of Middleware. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewMiddleware(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewMiddleware creates a new instance of Middleware. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewMiddleware(t mockConstructorTestingTNewMiddleware) *Middleware {
+}) *Middleware {
 	mock := &Middleware{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/clients/mocks/Storage.go b/pkg/clients/mocks/Storage.go
index 43166e0d3f4a21bb80d5179e23d0ee87596a565e..d5cb616c077940ecdd4bfe969c98db0d974c53b2 100644
--- a/pkg/clients/mocks/Storage.go
+++ b/pkg/clients/mocks/Storage.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -22,6 +22,10 @@ func (_m *Storage) Create(ctx context.Context, client *clients.Client) (*clients
 	ret := _m.Called(ctx, client)
 
 	var r0 *clients.Client
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.Client) (*clients.Client, error)); ok {
+		return rf(ctx, client)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *clients.Client) *clients.Client); ok {
 		r0 = rf(ctx, client)
 	} else {
@@ -30,7 +34,6 @@ func (_m *Storage) Create(ctx context.Context, client *clients.Client) (*clients
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *clients.Client) error); ok {
 		r1 = rf(ctx, client)
 	} else {
@@ -59,6 +62,11 @@ func (_m *Storage) Find(ctx context.Context, spaceId string, filter *clients.Fil
 	ret := _m.Called(ctx, spaceId, filter, opts)
 
 	var r0 []*clients.Client
+	var r1 int
+	var r2 error
+	if rf, ok := ret.Get(0).(func(context.Context, string, *clients.Filter, *options.FindOptions) ([]*clients.Client, int, error)); ok {
+		return rf(ctx, spaceId, filter, opts)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string, *clients.Filter, *options.FindOptions) []*clients.Client); ok {
 		r0 = rf(ctx, spaceId, filter, opts)
 	} else {
@@ -67,14 +75,12 @@ func (_m *Storage) Find(ctx context.Context, spaceId string, filter *clients.Fil
 		}
 	}
 
-	var r1 int
 	if rf, ok := ret.Get(1).(func(context.Context, string, *clients.Filter, *options.FindOptions) int); ok {
 		r1 = rf(ctx, spaceId, filter, opts)
 	} else {
 		r1 = ret.Get(1).(int)
 	}
 
-	var r2 error
 	if rf, ok := ret.Get(2).(func(context.Context, string, *clients.Filter, *options.FindOptions) error); ok {
 		r2 = rf(ctx, spaceId, filter, opts)
 	} else {
@@ -117,20 +123,23 @@ func (_m *Storage) Update(ctx context.Context, upd *clients.Client) (int, int, e
 	ret := _m.Called(ctx, upd)
 
 	var r0 int
+	var r1 int
+	var r2 error
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.Client) (int, int, error)); ok {
+		return rf(ctx, upd)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *clients.Client) int); ok {
 		r0 = rf(ctx, upd)
 	} else {
 		r0 = ret.Get(0).(int)
 	}
 
-	var r1 int
 	if rf, ok := ret.Get(1).(func(context.Context, *clients.Client) int); ok {
 		r1 = rf(ctx, upd)
 	} else {
 		r1 = ret.Get(1).(int)
 	}
 
-	var r2 error
 	if rf, ok := ret.Get(2).(func(context.Context, *clients.Client) error); ok {
 		r2 = rf(ctx, upd)
 	} else {
@@ -140,13 +149,12 @@ func (_m *Storage) Update(ctx context.Context, upd *clients.Client) (int, int, e
 	return r0, r1, r2
 }
 
-type mockConstructorTestingTNewStorage interface {
+// NewStorage creates a new instance of Storage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewStorage(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewStorage creates a new instance of Storage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewStorage(t mockConstructorTestingTNewStorage) *Storage {
+}) *Storage {
 	mock := &Storage{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/collaborators/mocks/CollaboratorObserver.go b/pkg/collaborators/mocks/CollaboratorObserver.go
index c7f5aed4d5525f2d9136ea7645696dba9418e785..50f0d3490d114d3d99f1a20cce09df8300e5af87 100644
--- a/pkg/collaborators/mocks/CollaboratorObserver.go
+++ b/pkg/collaborators/mocks/CollaboratorObserver.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -9,13 +9,12 @@ type CollaboratorObserver struct {
 	mock.Mock
 }
 
-type mockConstructorTestingTNewCollaboratorObserver interface {
+// NewCollaboratorObserver creates a new instance of CollaboratorObserver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewCollaboratorObserver(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewCollaboratorObserver creates a new instance of CollaboratorObserver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewCollaboratorObserver(t mockConstructorTestingTNewCollaboratorObserver) *CollaboratorObserver {
+}) *CollaboratorObserver {
 	mock := &CollaboratorObserver{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/collaborators/mocks/CollaboratorRemoveObserver.go b/pkg/collaborators/mocks/CollaboratorRemoveObserver.go
index 8733c7430a5b0a7b4c8b5d34a2a09bf90373a7c9..e2f1b0fc83c34186a3eb06bf82715d1bc44d1aa7 100644
--- a/pkg/collaborators/mocks/CollaboratorRemoveObserver.go
+++ b/pkg/collaborators/mocks/CollaboratorRemoveObserver.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -20,13 +20,16 @@ func (_m *CollaboratorRemoveObserver) OnCollaboratorRemove(ctx context.Context,
 	ret := _m.Called(ctx, collaborator)
 
 	var r0 string
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.Collaborator) (string, error)); ok {
+		return rf(ctx, collaborator)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.Collaborator) string); ok {
 		r0 = rf(ctx, collaborator)
 	} else {
 		r0 = ret.Get(0).(string)
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *collaborators.Collaborator) error); ok {
 		r1 = rf(ctx, collaborator)
 	} else {
@@ -36,13 +39,12 @@ func (_m *CollaboratorRemoveObserver) OnCollaboratorRemove(ctx context.Context,
 	return r0, r1
 }
 
-type mockConstructorTestingTNewCollaboratorRemoveObserver interface {
+// NewCollaboratorRemoveObserver creates a new instance of CollaboratorRemoveObserver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewCollaboratorRemoveObserver(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewCollaboratorRemoveObserver creates a new instance of CollaboratorRemoveObserver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewCollaboratorRemoveObserver(t mockConstructorTestingTNewCollaboratorRemoveObserver) *CollaboratorRemoveObserver {
+}) *CollaboratorRemoveObserver {
 	mock := &CollaboratorRemoveObserver{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/collaborators/mocks/CollaboratorSetObserver.go b/pkg/collaborators/mocks/CollaboratorSetObserver.go
index 296c37f12fd206923b904386a6a15924992fe3f7..160c16b4e95c8ec7b7842b761a73ed89c1a7bc30 100644
--- a/pkg/collaborators/mocks/CollaboratorSetObserver.go
+++ b/pkg/collaborators/mocks/CollaboratorSetObserver.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -20,13 +20,16 @@ func (_m *CollaboratorSetObserver) OnCollaboratorSet(ctx context.Context, collab
 	ret := _m.Called(ctx, collaborator)
 
 	var r0 string
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.Collaborator) (string, error)); ok {
+		return rf(ctx, collaborator)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.Collaborator) string); ok {
 		r0 = rf(ctx, collaborator)
 	} else {
 		r0 = ret.Get(0).(string)
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *collaborators.Collaborator) error); ok {
 		r1 = rf(ctx, collaborator)
 	} else {
@@ -36,13 +39,12 @@ func (_m *CollaboratorSetObserver) OnCollaboratorSet(ctx context.Context, collab
 	return r0, r1
 }
 
-type mockConstructorTestingTNewCollaboratorSetObserver interface {
+// NewCollaboratorSetObserver creates a new instance of CollaboratorSetObserver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewCollaboratorSetObserver(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewCollaboratorSetObserver creates a new instance of CollaboratorSetObserver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewCollaboratorSetObserver(t mockConstructorTestingTNewCollaboratorSetObserver) *CollaboratorSetObserver {
+}) *CollaboratorSetObserver {
 	mock := &CollaboratorSetObserver{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/collaborators/mocks/Collaborators.go b/pkg/collaborators/mocks/Collaborators.go
index c3fb5291d2d4fdb4781f951677bbc3bd0f01ac5b..079b9020adda3a36c9d877f7f662b4c9b844ac4f 100644
--- a/pkg/collaborators/mocks/Collaborators.go
+++ b/pkg/collaborators/mocks/Collaborators.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -20,13 +20,16 @@ func (_m *Collaborators) Get(ctx context.Context, spaceId string, subject string
 	ret := _m.Called(ctx, spaceId, subject)
 
 	var r0 string
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string, string) (string, error)); ok {
+		return rf(ctx, spaceId, subject)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string, string) string); ok {
 		r0 = rf(ctx, spaceId, subject)
 	} else {
 		r0 = ret.Get(0).(string)
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
 		r1 = rf(ctx, spaceId, subject)
 	} else {
@@ -41,6 +44,10 @@ func (_m *Collaborators) ListCollaborators(ctx context.Context, spaceId string)
 	ret := _m.Called(ctx, spaceId)
 
 	var r0 []*collaborators.Collaborator
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string) ([]*collaborators.Collaborator, error)); ok {
+		return rf(ctx, spaceId)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string) []*collaborators.Collaborator); ok {
 		r0 = rf(ctx, spaceId)
 	} else {
@@ -49,7 +56,6 @@ func (_m *Collaborators) ListCollaborators(ctx context.Context, spaceId string)
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
 		r1 = rf(ctx, spaceId)
 	} else {
@@ -64,6 +70,10 @@ func (_m *Collaborators) ListSpaces(ctx context.Context, subject string) ([]*col
 	ret := _m.Called(ctx, subject)
 
 	var r0 []*collaborators.Collaborator
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string) ([]*collaborators.Collaborator, error)); ok {
+		return rf(ctx, subject)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string) []*collaborators.Collaborator); ok {
 		r0 = rf(ctx, subject)
 	} else {
@@ -72,7 +82,6 @@ func (_m *Collaborators) ListSpaces(ctx context.Context, subject string) ([]*col
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
 		r1 = rf(ctx, subject)
 	} else {
@@ -110,13 +119,12 @@ func (_m *Collaborators) Set(ctx context.Context, spaceId string, subject string
 	return r0
 }
 
-type mockConstructorTestingTNewCollaborators interface {
+// NewCollaborators creates a new instance of Collaborators. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewCollaborators(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewCollaborators creates a new instance of Collaborators. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewCollaborators(t mockConstructorTestingTNewCollaborators) *Collaborators {
+}) *Collaborators {
 	mock := &Collaborators{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/collaborators/mocks/Middleware.go b/pkg/collaborators/mocks/Middleware.go
index c3fa37385c431b4584703566c33ea6fea3e0ac95..10a10f31d239813b95778bb287595fd1cbc96051 100644
--- a/pkg/collaborators/mocks/Middleware.go
+++ b/pkg/collaborators/mocks/Middleware.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -29,13 +29,12 @@ func (_m *Middleware) Execute(_a0 collaborators.Collaborators) collaborators.Col
 	return r0
 }
 
-type mockConstructorTestingTNewMiddleware interface {
+// NewMiddleware creates a new instance of Middleware. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewMiddleware(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewMiddleware creates a new instance of Middleware. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewMiddleware(t mockConstructorTestingTNewMiddleware) *Middleware {
+}) *Middleware {
 	mock := &Middleware{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/collaborators/mocks/Storage.go b/pkg/collaborators/mocks/Storage.go
index b2645f347aba5eeb418a5fb4228944bd051e46b0..a7ded86e00cbab6a810bc82a5f05224b150a3c79 100644
--- a/pkg/collaborators/mocks/Storage.go
+++ b/pkg/collaborators/mocks/Storage.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -22,13 +22,16 @@ func (_m *Storage) Delete(ctx context.Context, filter *collaborators.Filter) (in
 	ret := _m.Called(ctx, filter)
 
 	var r0 int
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.Filter) (int, error)); ok {
+		return rf(ctx, filter)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.Filter) int); ok {
 		r0 = rf(ctx, filter)
 	} else {
 		r0 = ret.Get(0).(int)
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *collaborators.Filter) error); ok {
 		r1 = rf(ctx, filter)
 	} else {
@@ -43,6 +46,10 @@ func (_m *Storage) Find(ctx context.Context, filter *collaborators.Filter, opts
 	ret := _m.Called(ctx, filter, opts)
 
 	var r0 []*collaborators.Collaborator
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.Filter, *options.FindOptions) ([]*collaborators.Collaborator, error)); ok {
+		return rf(ctx, filter, opts)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.Filter, *options.FindOptions) []*collaborators.Collaborator); ok {
 		r0 = rf(ctx, filter, opts)
 	} else {
@@ -51,7 +58,6 @@ func (_m *Storage) Find(ctx context.Context, filter *collaborators.Filter, opts
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *collaborators.Filter, *options.FindOptions) error); ok {
 		r1 = rf(ctx, filter, opts)
 	} else {
@@ -103,13 +109,12 @@ func (_m *Storage) Set(ctx context.Context, collaborator *collaborators.Collabor
 	return r0
 }
 
-type mockConstructorTestingTNewStorage interface {
+// NewStorage creates a new instance of Storage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewStorage(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewStorage creates a new instance of Storage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewStorage(t mockConstructorTestingTNewStorage) *Storage {
+}) *Storage {
 	mock := &Storage{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/collections/mocks/Collections.go b/pkg/collections/mocks/Collections.go
index e8bf9f486093a284dcdcb9d7034cb54c8bf26996..9a0a67f6dba82b5e7343dba1f0cc152ce82acb6a 100644
--- a/pkg/collections/mocks/Collections.go
+++ b/pkg/collections/mocks/Collections.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -22,6 +22,10 @@ func (_m *Collections) Create(ctx context.Context, collection *collections.Colle
 	ret := _m.Called(ctx, collection)
 
 	var r0 *collections.Collection
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.Collection) (*collections.Collection, error)); ok {
+		return rf(ctx, collection)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *collections.Collection) *collections.Collection); ok {
 		r0 = rf(ctx, collection)
 	} else {
@@ -30,7 +34,6 @@ func (_m *Collections) Create(ctx context.Context, collection *collections.Colle
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *collections.Collection) error); ok {
 		r1 = rf(ctx, collection)
 	} else {
@@ -66,6 +69,10 @@ func (_m *Collections) Get(ctx context.Context, spaceId string, envId string, co
 	ret := _m.Called(_ca...)
 
 	var r0 *collections.Collection
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string, string, string, ...*collections.GetOptions) (*collections.Collection, error)); ok {
+		return rf(ctx, spaceId, envId, collectionId, options...)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string, string, string, ...*collections.GetOptions) *collections.Collection); ok {
 		r0 = rf(ctx, spaceId, envId, collectionId, options...)
 	} else {
@@ -74,7 +81,6 @@ func (_m *Collections) Get(ctx context.Context, spaceId string, envId string, co
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string, string, string, ...*collections.GetOptions) error); ok {
 		r1 = rf(ctx, spaceId, envId, collectionId, options...)
 	} else {
@@ -89,6 +95,10 @@ func (_m *Collections) List(ctx context.Context, spaceId string, envId string, f
 	ret := _m.Called(ctx, spaceId, envId, filter)
 
 	var r0 []*collections.Collection
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string, string, *collections.Filter) ([]*collections.Collection, error)); ok {
+		return rf(ctx, spaceId, envId, filter)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string, string, *collections.Filter) []*collections.Collection); ok {
 		r0 = rf(ctx, spaceId, envId, filter)
 	} else {
@@ -97,7 +107,6 @@ func (_m *Collections) List(ctx context.Context, spaceId string, envId string, f
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string, string, *collections.Filter) error); ok {
 		r1 = rf(ctx, spaceId, envId, filter)
 	} else {
@@ -149,13 +158,12 @@ func (_m *Collections) Update(ctx context.Context, coll *collections.Collection)
 	return r0
 }
 
-type mockConstructorTestingTNewCollections interface {
+// NewCollections creates a new instance of Collections. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewCollections(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewCollections creates a new instance of Collections. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewCollections(t mockConstructorTestingTNewCollections) *Collections {
+}) *Collections {
 	mock := &Collections{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/collections/mocks/Middleware.go b/pkg/collections/mocks/Middleware.go
index a0be631888dca02fadc204d3c256f57e9466eb5d..761a6f460bf8a54c406f7137a903782cd01b9486 100644
--- a/pkg/collections/mocks/Middleware.go
+++ b/pkg/collections/mocks/Middleware.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -29,13 +29,12 @@ func (_m *Middleware) Execute(_a0 collections.Collections) collections.Collectio
 	return r0
 }
 
-type mockConstructorTestingTNewMiddleware interface {
+// NewMiddleware creates a new instance of Middleware. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewMiddleware(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewMiddleware creates a new instance of Middleware. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewMiddleware(t mockConstructorTestingTNewMiddleware) *Middleware {
+}) *Middleware {
 	mock := &Middleware{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/collections/mocks/Storage.go b/pkg/collections/mocks/Storage.go
index eb171b5884308f01753827496de9569a575ff818..7e4bdb4a9f9b3c7632c8157750ada779aa10223c 100644
--- a/pkg/collections/mocks/Storage.go
+++ b/pkg/collections/mocks/Storage.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -20,6 +20,10 @@ func (_m *Storage) Create(ctx context.Context, coll *collections.Collection) (*c
 	ret := _m.Called(ctx, coll)
 
 	var r0 *collections.Collection
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.Collection) (*collections.Collection, error)); ok {
+		return rf(ctx, coll)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *collections.Collection) *collections.Collection); ok {
 		r0 = rf(ctx, coll)
 	} else {
@@ -28,7 +32,6 @@ func (_m *Storage) Create(ctx context.Context, coll *collections.Collection) (*c
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *collections.Collection) error); ok {
 		r1 = rf(ctx, coll)
 	} else {
@@ -57,6 +60,10 @@ func (_m *Storage) Get(ctx context.Context, spaceId string, envId string, collec
 	ret := _m.Called(ctx, spaceId, envId, collectionId)
 
 	var r0 *collections.Collection
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string, string, string) (*collections.Collection, error)); ok {
+		return rf(ctx, spaceId, envId, collectionId)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string, string, string) *collections.Collection); ok {
 		r0 = rf(ctx, spaceId, envId, collectionId)
 	} else {
@@ -65,7 +72,6 @@ func (_m *Storage) Get(ctx context.Context, spaceId string, envId string, collec
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string, string, string) error); ok {
 		r1 = rf(ctx, spaceId, envId, collectionId)
 	} else {
@@ -94,6 +100,10 @@ func (_m *Storage) List(ctx context.Context, spaceId string, envId string, filte
 	ret := _m.Called(ctx, spaceId, envId, filter)
 
 	var r0 []*collections.Collection
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string, string, *collections.Filter) ([]*collections.Collection, error)); ok {
+		return rf(ctx, spaceId, envId, filter)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string, string, *collections.Filter) []*collections.Collection); ok {
 		r0 = rf(ctx, spaceId, envId, filter)
 	} else {
@@ -102,7 +112,6 @@ func (_m *Storage) List(ctx context.Context, spaceId string, envId string, filte
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string, string, *collections.Filter) error); ok {
 		r1 = rf(ctx, spaceId, envId, filter)
 	} else {
@@ -131,20 +140,23 @@ func (_m *Storage) Update(ctx context.Context, coll *collections.Collection) (in
 	ret := _m.Called(ctx, coll)
 
 	var r0 int
+	var r1 int
+	var r2 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.Collection) (int, int, error)); ok {
+		return rf(ctx, coll)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *collections.Collection) int); ok {
 		r0 = rf(ctx, coll)
 	} else {
 		r0 = ret.Get(0).(int)
 	}
 
-	var r1 int
 	if rf, ok := ret.Get(1).(func(context.Context, *collections.Collection) int); ok {
 		r1 = rf(ctx, coll)
 	} else {
 		r1 = ret.Get(1).(int)
 	}
 
-	var r2 error
 	if rf, ok := ret.Get(2).(func(context.Context, *collections.Collection) error); ok {
 		r2 = rf(ctx, coll)
 	} else {
@@ -154,13 +166,12 @@ func (_m *Storage) Update(ctx context.Context, coll *collections.Collection) (in
 	return r0, r1, r2
 }
 
-type mockConstructorTestingTNewStorage interface {
+// NewStorage creates a new instance of Storage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewStorage(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewStorage creates a new instance of Storage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewStorage(t mockConstructorTestingTNewStorage) *Storage {
+}) *Storage {
 	mock := &Storage{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/delivery/mocks/Delivery.go b/pkg/delivery/mocks/Delivery.go
index 1f8d05f53b9b07737cee4c505069060cf3b2c647..6a10b46a01d7d3972338b26d2c82de0f46458b51 100644
--- a/pkg/delivery/mocks/Delivery.go
+++ b/pkg/delivery/mocks/Delivery.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -33,6 +33,10 @@ func (_m *Delivery) Aggregate(ctx context.Context, spaceId string, envId string,
 	ret := _m.Called(_ca...)
 
 	var r0 map[string]interface{}
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string, string, string, *items.Filter, ...*items.AggregatePublishedOptions) (map[string]interface{}, error)); ok {
+		return rf(ctx, spaceId, envId, collectionId, filter, options...)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string, string, string, *items.Filter, ...*items.AggregatePublishedOptions) map[string]interface{}); ok {
 		r0 = rf(ctx, spaceId, envId, collectionId, filter, options...)
 	} else {
@@ -41,7 +45,6 @@ func (_m *Delivery) Aggregate(ctx context.Context, spaceId string, envId string,
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string, string, string, *items.Filter, ...*items.AggregatePublishedOptions) error); ok {
 		r1 = rf(ctx, spaceId, envId, collectionId, filter, options...)
 	} else {
@@ -63,6 +66,11 @@ func (_m *Delivery) FindItems(ctx context.Context, spaceId string, envId string,
 	ret := _m.Called(_ca...)
 
 	var r0 []*items.Item
+	var r1 int
+	var r2 error
+	if rf, ok := ret.Get(0).(func(context.Context, string, string, string, *items.Filter, ...*items.FindPublishedOptions) ([]*items.Item, int, error)); ok {
+		return rf(ctx, spaceId, envId, collectionId, filter, options...)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string, string, string, *items.Filter, ...*items.FindPublishedOptions) []*items.Item); ok {
 		r0 = rf(ctx, spaceId, envId, collectionId, filter, options...)
 	} else {
@@ -71,14 +79,12 @@ func (_m *Delivery) FindItems(ctx context.Context, spaceId string, envId string,
 		}
 	}
 
-	var r1 int
 	if rf, ok := ret.Get(1).(func(context.Context, string, string, string, *items.Filter, ...*items.FindPublishedOptions) int); ok {
 		r1 = rf(ctx, spaceId, envId, collectionId, filter, options...)
 	} else {
 		r1 = ret.Get(1).(int)
 	}
 
-	var r2 error
 	if rf, ok := ret.Get(2).(func(context.Context, string, string, string, *items.Filter, ...*items.FindPublishedOptions) error); ok {
 		r2 = rf(ctx, spaceId, envId, collectionId, filter, options...)
 	} else {
@@ -93,6 +99,10 @@ func (_m *Delivery) GetCollection(ctx context.Context, spaceId string, envId str
 	ret := _m.Called(ctx, spaceId, envId, collectionId)
 
 	var r0 *collections.Collection
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string, string, string) (*collections.Collection, error)); ok {
+		return rf(ctx, spaceId, envId, collectionId)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string, string, string) *collections.Collection); ok {
 		r0 = rf(ctx, spaceId, envId, collectionId)
 	} else {
@@ -101,7 +111,6 @@ func (_m *Delivery) GetCollection(ctx context.Context, spaceId string, envId str
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string, string, string) error); ok {
 		r1 = rf(ctx, spaceId, envId, collectionId)
 	} else {
@@ -116,6 +125,10 @@ func (_m *Delivery) GetEnvironment(ctx context.Context, spaceId string, envId st
 	ret := _m.Called(ctx, spaceId, envId)
 
 	var r0 *environments.Environment
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string, string) (*environments.Environment, error)); ok {
+		return rf(ctx, spaceId, envId)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string, string) *environments.Environment); ok {
 		r0 = rf(ctx, spaceId, envId)
 	} else {
@@ -124,7 +137,6 @@ func (_m *Delivery) GetEnvironment(ctx context.Context, spaceId string, envId st
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
 		r1 = rf(ctx, spaceId, envId)
 	} else {
@@ -146,6 +158,10 @@ func (_m *Delivery) GetItem(ctx context.Context, spaceId string, envId string, c
 	ret := _m.Called(_ca...)
 
 	var r0 *items.Item
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string, string, string, string, ...*items.GetPublishedOptions) (*items.Item, error)); ok {
+		return rf(ctx, spaceId, envId, collectionId, itemId, options...)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string, string, string, string, ...*items.GetPublishedOptions) *items.Item); ok {
 		r0 = rf(ctx, spaceId, envId, collectionId, itemId, options...)
 	} else {
@@ -154,7 +170,6 @@ func (_m *Delivery) GetItem(ctx context.Context, spaceId string, envId string, c
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string, string, string, string, ...*items.GetPublishedOptions) error); ok {
 		r1 = rf(ctx, spaceId, envId, collectionId, itemId, options...)
 	} else {
@@ -169,6 +184,10 @@ func (_m *Delivery) ListCollections(ctx context.Context, spaceId string, envId s
 	ret := _m.Called(ctx, spaceId, envId)
 
 	var r0 []*collections.Collection
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string, string) ([]*collections.Collection, error)); ok {
+		return rf(ctx, spaceId, envId)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string, string) []*collections.Collection); ok {
 		r0 = rf(ctx, spaceId, envId)
 	} else {
@@ -177,7 +196,6 @@ func (_m *Delivery) ListCollections(ctx context.Context, spaceId string, envId s
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
 		r1 = rf(ctx, spaceId, envId)
 	} else {
@@ -192,6 +210,10 @@ func (_m *Delivery) ListEnvironments(ctx context.Context, spaceId string) ([]*en
 	ret := _m.Called(ctx, spaceId)
 
 	var r0 []*environments.Environment
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string) ([]*environments.Environment, error)); ok {
+		return rf(ctx, spaceId)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string) []*environments.Environment); ok {
 		r0 = rf(ctx, spaceId)
 	} else {
@@ -200,7 +222,6 @@ func (_m *Delivery) ListEnvironments(ctx context.Context, spaceId string) ([]*en
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
 		r1 = rf(ctx, spaceId)
 	} else {
@@ -215,6 +236,10 @@ func (_m *Delivery) ListLocales(ctx context.Context, spaceId string) ([]*locales
 	ret := _m.Called(ctx, spaceId)
 
 	var r0 []*locales.Locale
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string) ([]*locales.Locale, error)); ok {
+		return rf(ctx, spaceId)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string) []*locales.Locale); ok {
 		r0 = rf(ctx, spaceId)
 	} else {
@@ -223,7 +248,6 @@ func (_m *Delivery) ListLocales(ctx context.Context, spaceId string) ([]*locales
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
 		r1 = rf(ctx, spaceId)
 	} else {
@@ -233,13 +257,12 @@ func (_m *Delivery) ListLocales(ctx context.Context, spaceId string) ([]*locales
 	return r0, r1
 }
 
-type mockConstructorTestingTNewDelivery interface {
+// NewDelivery creates a new instance of Delivery. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewDelivery(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewDelivery creates a new instance of Delivery. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewDelivery(t mockConstructorTestingTNewDelivery) *Delivery {
+}) *Delivery {
 	mock := &Delivery{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/environments/mocks/EnvironmentConfigurationObserver.go b/pkg/environments/mocks/EnvironmentConfigurationObserver.go
index e5920c9de716195cbcc1efcd71fbcb75b91d5c40..32c8efd8b78c3e7af8e4d1d887223329fd76a43a 100644
--- a/pkg/environments/mocks/EnvironmentConfigurationObserver.go
+++ b/pkg/environments/mocks/EnvironmentConfigurationObserver.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -28,13 +28,12 @@ func (_m *EnvironmentConfigurationObserver) OnEnvironmentConfiguration(ctx conte
 	return r0
 }
 
-type mockConstructorTestingTNewEnvironmentConfigurationObserver interface {
+// NewEnvironmentConfigurationObserver creates a new instance of EnvironmentConfigurationObserver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewEnvironmentConfigurationObserver(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewEnvironmentConfigurationObserver creates a new instance of EnvironmentConfigurationObserver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewEnvironmentConfigurationObserver(t mockConstructorTestingTNewEnvironmentConfigurationObserver) *EnvironmentConfigurationObserver {
+}) *EnvironmentConfigurationObserver {
 	mock := &EnvironmentConfigurationObserver{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/environments/mocks/EnvironmentCreatedObserver.go b/pkg/environments/mocks/EnvironmentCreatedObserver.go
index a2a0eb73e40ef01d0e3732a6011facd3cd4b7abe..6bed116a9a28f1ad913eed0abb0cd2f2b2931548 100644
--- a/pkg/environments/mocks/EnvironmentCreatedObserver.go
+++ b/pkg/environments/mocks/EnvironmentCreatedObserver.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -19,13 +19,16 @@ func (_m *EnvironmentCreatedObserver) OnEnvironmentCreated(ctx context.Context,
 	ret := _m.Called(ctx, env)
 
 	var r0 string
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.Environment) (string, error)); ok {
+		return rf(ctx, env)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *environments.Environment) string); ok {
 		r0 = rf(ctx, env)
 	} else {
 		r0 = ret.Get(0).(string)
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *environments.Environment) error); ok {
 		r1 = rf(ctx, env)
 	} else {
@@ -35,13 +38,12 @@ func (_m *EnvironmentCreatedObserver) OnEnvironmentCreated(ctx context.Context,
 	return r0, r1
 }
 
-type mockConstructorTestingTNewEnvironmentCreatedObserver interface {
+// NewEnvironmentCreatedObserver creates a new instance of EnvironmentCreatedObserver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewEnvironmentCreatedObserver(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewEnvironmentCreatedObserver creates a new instance of EnvironmentCreatedObserver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewEnvironmentCreatedObserver(t mockConstructorTestingTNewEnvironmentCreatedObserver) *EnvironmentCreatedObserver {
+}) *EnvironmentCreatedObserver {
 	mock := &EnvironmentCreatedObserver{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/environments/mocks/EnvironmentDeletedObserver.go b/pkg/environments/mocks/EnvironmentDeletedObserver.go
index 852cec94086338d53518afff08d18764b88e5170..1a101f04be093b1b48e89d8173c969beebb66754 100644
--- a/pkg/environments/mocks/EnvironmentDeletedObserver.go
+++ b/pkg/environments/mocks/EnvironmentDeletedObserver.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -28,13 +28,12 @@ func (_m *EnvironmentDeletedObserver) OnEnvironmentDeleted(ctx context.Context,
 	return r0
 }
 
-type mockConstructorTestingTNewEnvironmentDeletedObserver interface {
+// NewEnvironmentDeletedObserver creates a new instance of EnvironmentDeletedObserver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewEnvironmentDeletedObserver(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewEnvironmentDeletedObserver creates a new instance of EnvironmentDeletedObserver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewEnvironmentDeletedObserver(t mockConstructorTestingTNewEnvironmentDeletedObserver) *EnvironmentDeletedObserver {
+}) *EnvironmentDeletedObserver {
 	mock := &EnvironmentDeletedObserver{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/environments/mocks/EnvironmentMigratedObserver.go b/pkg/environments/mocks/EnvironmentMigratedObserver.go
index a2f042880ffe88d86187263d1688596d9a878507..c529a8b81f9caecbb4d78b4d10079f406dc88bf6 100644
--- a/pkg/environments/mocks/EnvironmentMigratedObserver.go
+++ b/pkg/environments/mocks/EnvironmentMigratedObserver.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -28,13 +28,12 @@ func (_m *EnvironmentMigratedObserver) OnEnvironmentMigrated(ctx context.Context
 	return r0
 }
 
-type mockConstructorTestingTNewEnvironmentMigratedObserver interface {
+// NewEnvironmentMigratedObserver creates a new instance of EnvironmentMigratedObserver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewEnvironmentMigratedObserver(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewEnvironmentMigratedObserver creates a new instance of EnvironmentMigratedObserver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewEnvironmentMigratedObserver(t mockConstructorTestingTNewEnvironmentMigratedObserver) *EnvironmentMigratedObserver {
+}) *EnvironmentMigratedObserver {
 	mock := &EnvironmentMigratedObserver{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/environments/mocks/EnvironmentObserver.go b/pkg/environments/mocks/EnvironmentObserver.go
index 309d0ed217317c53be90e4f6a43afcddc3587eb4..15f243d920ce58b8d770d742fa778bd4ca9a7133 100644
--- a/pkg/environments/mocks/EnvironmentObserver.go
+++ b/pkg/environments/mocks/EnvironmentObserver.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -9,13 +9,12 @@ type EnvironmentObserver struct {
 	mock.Mock
 }
 
-type mockConstructorTestingTNewEnvironmentObserver interface {
+// NewEnvironmentObserver creates a new instance of EnvironmentObserver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewEnvironmentObserver(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewEnvironmentObserver creates a new instance of EnvironmentObserver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewEnvironmentObserver(t mockConstructorTestingTNewEnvironmentObserver) *EnvironmentObserver {
+}) *EnvironmentObserver {
 	mock := &EnvironmentObserver{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/environments/mocks/EnvironmentUpdatedObserver.go b/pkg/environments/mocks/EnvironmentUpdatedObserver.go
index 4a7e76673439dcf09d9b3b52c461482e637960a3..75073188aeb89593bf12555d9ada3a7cc9ec7837 100644
--- a/pkg/environments/mocks/EnvironmentUpdatedObserver.go
+++ b/pkg/environments/mocks/EnvironmentUpdatedObserver.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -28,13 +28,12 @@ func (_m *EnvironmentUpdatedObserver) OnEnvironmentUpdated(ctx context.Context,
 	return r0
 }
 
-type mockConstructorTestingTNewEnvironmentUpdatedObserver interface {
+// NewEnvironmentUpdatedObserver creates a new instance of EnvironmentUpdatedObserver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewEnvironmentUpdatedObserver(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewEnvironmentUpdatedObserver creates a new instance of EnvironmentUpdatedObserver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewEnvironmentUpdatedObserver(t mockConstructorTestingTNewEnvironmentUpdatedObserver) *EnvironmentUpdatedObserver {
+}) *EnvironmentUpdatedObserver {
 	mock := &EnvironmentUpdatedObserver{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/environments/mocks/Environments.go b/pkg/environments/mocks/Environments.go
index cfd1ef59a95c18881afa675ef92a12d3bf455fd7..22da5d024c9cd43506a35e6e11a264fff9189a54 100644
--- a/pkg/environments/mocks/Environments.go
+++ b/pkg/environments/mocks/Environments.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -19,6 +19,10 @@ func (_m *Environments) Create(ctx context.Context, env *environments.Environmen
 	ret := _m.Called(ctx, env)
 
 	var r0 *environments.Environment
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.Environment) (*environments.Environment, error)); ok {
+		return rf(ctx, env)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *environments.Environment) *environments.Environment); ok {
 		r0 = rf(ctx, env)
 	} else {
@@ -27,7 +31,6 @@ func (_m *Environments) Create(ctx context.Context, env *environments.Environmen
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *environments.Environment) error); ok {
 		r1 = rf(ctx, env)
 	} else {
@@ -56,6 +59,10 @@ func (_m *Environments) Get(ctx context.Context, spaceId string, envId string) (
 	ret := _m.Called(ctx, spaceId, envId)
 
 	var r0 *environments.Environment
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string, string) (*environments.Environment, error)); ok {
+		return rf(ctx, spaceId, envId)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string, string) *environments.Environment); ok {
 		r0 = rf(ctx, spaceId, envId)
 	} else {
@@ -64,7 +71,6 @@ func (_m *Environments) Get(ctx context.Context, spaceId string, envId string) (
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
 		r1 = rf(ctx, spaceId, envId)
 	} else {
@@ -79,6 +85,10 @@ func (_m *Environments) List(ctx context.Context, spaceId string) ([]*environmen
 	ret := _m.Called(ctx, spaceId)
 
 	var r0 []*environments.Environment
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string) ([]*environments.Environment, error)); ok {
+		return rf(ctx, spaceId)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string) []*environments.Environment); ok {
 		r0 = rf(ctx, spaceId)
 	} else {
@@ -87,7 +97,6 @@ func (_m *Environments) List(ctx context.Context, spaceId string) ([]*environmen
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
 		r1 = rf(ctx, spaceId)
 	} else {
@@ -160,13 +169,12 @@ func (_m *Environments) Update(ctx context.Context, env *environments.Environmen
 	return r0
 }
 
-type mockConstructorTestingTNewEnvironments interface {
+// NewEnvironments creates a new instance of Environments. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewEnvironments(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewEnvironments creates a new instance of Environments. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewEnvironments(t mockConstructorTestingTNewEnvironments) *Environments {
+}) *Environments {
 	mock := &Environments{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/environments/mocks/Middleware.go b/pkg/environments/mocks/Middleware.go
index 3620aacf4a16f9ecf159bd56508e7db27f72625d..e88e67e9c4b541450200ab8cf9f313383366d44b 100644
--- a/pkg/environments/mocks/Middleware.go
+++ b/pkg/environments/mocks/Middleware.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -29,13 +29,12 @@ func (_m *Middleware) Execute(_a0 environments.Environments) environments.Enviro
 	return r0
 }
 
-type mockConstructorTestingTNewMiddleware interface {
+// NewMiddleware creates a new instance of Middleware. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewMiddleware(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewMiddleware creates a new instance of Middleware. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewMiddleware(t mockConstructorTestingTNewMiddleware) *Middleware {
+}) *Middleware {
 	mock := &Middleware{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/environments/mocks/Storage.go b/pkg/environments/mocks/Storage.go
index 68411694c5fc03e497e8c37e6a1ff0a1f1a68721..37b8f6e5ef7349b4739969b8bba457979a8faad0 100644
--- a/pkg/environments/mocks/Storage.go
+++ b/pkg/environments/mocks/Storage.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -19,6 +19,10 @@ func (_m *Storage) Create(ctx context.Context, create *environments.Environment)
 	ret := _m.Called(ctx, create)
 
 	var r0 *environments.Environment
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.Environment) (*environments.Environment, error)); ok {
+		return rf(ctx, create)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *environments.Environment) *environments.Environment); ok {
 		r0 = rf(ctx, create)
 	} else {
@@ -27,7 +31,6 @@ func (_m *Storage) Create(ctx context.Context, create *environments.Environment)
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *environments.Environment) error); ok {
 		r1 = rf(ctx, create)
 	} else {
@@ -56,6 +59,10 @@ func (_m *Storage) Get(ctx context.Context, spaceId string, envId string) (*envi
 	ret := _m.Called(ctx, spaceId, envId)
 
 	var r0 *environments.Environment
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string, string) (*environments.Environment, error)); ok {
+		return rf(ctx, spaceId, envId)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string, string) *environments.Environment); ok {
 		r0 = rf(ctx, spaceId, envId)
 	} else {
@@ -64,7 +71,6 @@ func (_m *Storage) Get(ctx context.Context, spaceId string, envId string) (*envi
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
 		r1 = rf(ctx, spaceId, envId)
 	} else {
@@ -93,6 +99,10 @@ func (_m *Storage) List(ctx context.Context, spaceId string) ([]*environments.En
 	ret := _m.Called(ctx, spaceId)
 
 	var r0 []*environments.Environment
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string) ([]*environments.Environment, error)); ok {
+		return rf(ctx, spaceId)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string) []*environments.Environment); ok {
 		r0 = rf(ctx, spaceId)
 	} else {
@@ -101,7 +111,6 @@ func (_m *Storage) List(ctx context.Context, spaceId string) ([]*environments.En
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
 		r1 = rf(ctx, spaceId)
 	} else {
@@ -156,20 +165,23 @@ func (_m *Storage) Update(ctx context.Context, up *environments.Environment, opt
 	ret := _m.Called(_ca...)
 
 	var r0 int
+	var r1 int
+	var r2 error
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.Environment, ...*environments.UpdateOptions) (int, int, error)); ok {
+		return rf(ctx, up, options...)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *environments.Environment, ...*environments.UpdateOptions) int); ok {
 		r0 = rf(ctx, up, options...)
 	} else {
 		r0 = ret.Get(0).(int)
 	}
 
-	var r1 int
 	if rf, ok := ret.Get(1).(func(context.Context, *environments.Environment, ...*environments.UpdateOptions) int); ok {
 		r1 = rf(ctx, up, options...)
 	} else {
 		r1 = ret.Get(1).(int)
 	}
 
-	var r2 error
 	if rf, ok := ret.Get(2).(func(context.Context, *environments.Environment, ...*environments.UpdateOptions) error); ok {
 		r2 = rf(ctx, up, options...)
 	} else {
@@ -179,13 +191,12 @@ func (_m *Storage) Update(ctx context.Context, up *environments.Environment, opt
 	return r0, r1, r2
 }
 
-type mockConstructorTestingTNewStorage interface {
+// NewStorage creates a new instance of Storage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewStorage(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewStorage creates a new instance of Storage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewStorage(t mockConstructorTestingTNewStorage) *Storage {
+}) *Storage {
 	mock := &Storage{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/files/mocks/Downloader.go b/pkg/files/mocks/Downloader.go
index 99c3e32cb685b311c4e66827ce6f9eef615f73d4..099ac390d135d7d4bb92debd3f7aacf26ca1cbff 100644
--- a/pkg/files/mocks/Downloader.go
+++ b/pkg/files/mocks/Downloader.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -29,13 +29,12 @@ func (_m *Downloader) Download(dst io.Writer, file *files.File) error {
 	return r0
 }
 
-type mockConstructorTestingTNewDownloader interface {
+// NewDownloader creates a new instance of Downloader. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewDownloader(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewDownloader creates a new instance of Downloader. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewDownloader(t mockConstructorTestingTNewDownloader) *Downloader {
+}) *Downloader {
 	mock := &Downloader{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/files/mocks/Files.go b/pkg/files/mocks/Files.go
index fa78a1809f968dbc21a10e4154284c07261a90ce..16e213ab3a0cbac0fb1f348bff9a0d5a45203bab 100644
--- a/pkg/files/mocks/Files.go
+++ b/pkg/files/mocks/Files.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -33,6 +33,10 @@ func (_m *Files) CompleteUpload(ctx context.Context, upload *files.MultipartUplo
 	ret := _m.Called(ctx, upload)
 
 	var r0 *files.MultipartUpload
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *files.MultipartUpload) (*files.MultipartUpload, error)); ok {
+		return rf(ctx, upload)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *files.MultipartUpload) *files.MultipartUpload); ok {
 		r0 = rf(ctx, upload)
 	} else {
@@ -41,7 +45,6 @@ func (_m *Files) CompleteUpload(ctx context.Context, upload *files.MultipartUplo
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *files.MultipartUpload) error); ok {
 		r1 = rf(ctx, upload)
 	} else {
@@ -70,6 +73,10 @@ func (_m *Files) GetFile(ctx context.Context, file *files.File) (*files.File, er
 	ret := _m.Called(ctx, file)
 
 	var r0 *files.File
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *files.File) (*files.File, error)); ok {
+		return rf(ctx, file)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *files.File) *files.File); ok {
 		r0 = rf(ctx, file)
 	} else {
@@ -78,7 +85,6 @@ func (_m *Files) GetFile(ctx context.Context, file *files.File) (*files.File, er
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *files.File) error); ok {
 		r1 = rf(ctx, file)
 	} else {
@@ -93,6 +99,10 @@ func (_m *Files) MoveUpload(ctx context.Context, upload *files.MultipartUpload)
 	ret := _m.Called(ctx, upload)
 
 	var r0 *files.File
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *files.MultipartUpload) (*files.File, error)); ok {
+		return rf(ctx, upload)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *files.MultipartUpload) *files.File); ok {
 		r0 = rf(ctx, upload)
 	} else {
@@ -101,7 +111,6 @@ func (_m *Files) MoveUpload(ctx context.Context, upload *files.MultipartUpload)
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *files.MultipartUpload) error); ok {
 		r1 = rf(ctx, upload)
 	} else {
@@ -116,6 +125,10 @@ func (_m *Files) StartUpload(ctx context.Context, upload *files.MultipartUpload)
 	ret := _m.Called(ctx, upload)
 
 	var r0 *files.MultipartUpload
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *files.MultipartUpload) (*files.MultipartUpload, error)); ok {
+		return rf(ctx, upload)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *files.MultipartUpload) *files.MultipartUpload); ok {
 		r0 = rf(ctx, upload)
 	} else {
@@ -124,7 +137,6 @@ func (_m *Files) StartUpload(ctx context.Context, upload *files.MultipartUpload)
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *files.MultipartUpload) error); ok {
 		r1 = rf(ctx, upload)
 	} else {
@@ -139,6 +151,10 @@ func (_m *Files) Upload(ctx context.Context, file *files.File) (*files.Upload, e
 	ret := _m.Called(ctx, file)
 
 	var r0 *files.Upload
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *files.File) (*files.Upload, error)); ok {
+		return rf(ctx, file)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *files.File) *files.Upload); ok {
 		r0 = rf(ctx, file)
 	} else {
@@ -147,7 +163,6 @@ func (_m *Files) Upload(ctx context.Context, file *files.File) (*files.Upload, e
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *files.File) error); ok {
 		r1 = rf(ctx, file)
 	} else {
@@ -157,13 +172,12 @@ func (_m *Files) Upload(ctx context.Context, file *files.File) (*files.Upload, e
 	return r0, r1
 }
 
-type mockConstructorTestingTNewFiles interface {
+// NewFiles creates a new instance of Files. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewFiles(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewFiles creates a new instance of Files. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewFiles(t mockConstructorTestingTNewFiles) *Files {
+}) *Files {
 	mock := &Files{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/files/mocks/Middleware.go b/pkg/files/mocks/Middleware.go
index 4a47061df1e1fe7b868cba7da09a5615cf313985..f857bcd35fd5f610dda001de0f47dcde038935c8 100644
--- a/pkg/files/mocks/Middleware.go
+++ b/pkg/files/mocks/Middleware.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -29,13 +29,12 @@ func (_m *Middleware) Execute(_a0 files.Files) files.Files {
 	return r0
 }
 
-type mockConstructorTestingTNewMiddleware interface {
+// NewMiddleware creates a new instance of Middleware. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewMiddleware(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewMiddleware creates a new instance of Middleware. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewMiddleware(t mockConstructorTestingTNewMiddleware) *Middleware {
+}) *Middleware {
 	mock := &Middleware{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/files/mocks/Storage.go b/pkg/files/mocks/Storage.go
index 7d4a411253dc517fb1a034f79035cf85756daccd..64e7974f1532be0cbba77c7cd23f8ecd4fa56918 100644
--- a/pkg/files/mocks/Storage.go
+++ b/pkg/files/mocks/Storage.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -33,6 +33,10 @@ func (_m *Storage) CompleteUpload(ctx context.Context, upload *files.MultipartUp
 	ret := _m.Called(ctx, upload)
 
 	var r0 *files.MultipartUpload
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *files.MultipartUpload) (*files.MultipartUpload, error)); ok {
+		return rf(ctx, upload)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *files.MultipartUpload) *files.MultipartUpload); ok {
 		r0 = rf(ctx, upload)
 	} else {
@@ -41,7 +45,6 @@ func (_m *Storage) CompleteUpload(ctx context.Context, upload *files.MultipartUp
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *files.MultipartUpload) error); ok {
 		r1 = rf(ctx, upload)
 	} else {
@@ -70,6 +73,10 @@ func (_m *Storage) GetFile(ctx context.Context, file *files.File) (*files.File,
 	ret := _m.Called(ctx, file)
 
 	var r0 *files.File
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *files.File) (*files.File, error)); ok {
+		return rf(ctx, file)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *files.File) *files.File); ok {
 		r0 = rf(ctx, file)
 	} else {
@@ -78,7 +85,6 @@ func (_m *Storage) GetFile(ctx context.Context, file *files.File) (*files.File,
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *files.File) error); ok {
 		r1 = rf(ctx, file)
 	} else {
@@ -93,6 +99,10 @@ func (_m *Storage) Move(ctx context.Context, src *files.File, dst *files.File) (
 	ret := _m.Called(ctx, src, dst)
 
 	var r0 *files.File
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *files.File, *files.File) (*files.File, error)); ok {
+		return rf(ctx, src, dst)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *files.File, *files.File) *files.File); ok {
 		r0 = rf(ctx, src, dst)
 	} else {
@@ -101,7 +111,6 @@ func (_m *Storage) Move(ctx context.Context, src *files.File, dst *files.File) (
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *files.File, *files.File) error); ok {
 		r1 = rf(ctx, src, dst)
 	} else {
@@ -116,6 +125,10 @@ func (_m *Storage) StartUpload(ctx context.Context, upload *files.MultipartUploa
 	ret := _m.Called(ctx, upload)
 
 	var r0 *files.MultipartUpload
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *files.MultipartUpload) (*files.MultipartUpload, error)); ok {
+		return rf(ctx, upload)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *files.MultipartUpload) *files.MultipartUpload); ok {
 		r0 = rf(ctx, upload)
 	} else {
@@ -124,7 +137,6 @@ func (_m *Storage) StartUpload(ctx context.Context, upload *files.MultipartUploa
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *files.MultipartUpload) error); ok {
 		r1 = rf(ctx, upload)
 	} else {
@@ -139,6 +151,10 @@ func (_m *Storage) Upload(ctx context.Context, file *files.File) (*files.Upload,
 	ret := _m.Called(ctx, file)
 
 	var r0 *files.Upload
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *files.File) (*files.Upload, error)); ok {
+		return rf(ctx, file)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *files.File) *files.Upload); ok {
 		r0 = rf(ctx, file)
 	} else {
@@ -147,7 +163,6 @@ func (_m *Storage) Upload(ctx context.Context, file *files.File) (*files.Upload,
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *files.File) error); ok {
 		r1 = rf(ctx, file)
 	} else {
@@ -157,13 +172,12 @@ func (_m *Storage) Upload(ctx context.Context, file *files.File) (*files.Upload,
 	return r0, r1
 }
 
-type mockConstructorTestingTNewStorage interface {
+// NewStorage creates a new instance of Storage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewStorage(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewStorage creates a new instance of Storage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewStorage(t mockConstructorTestingTNewStorage) *Storage {
+}) *Storage {
 	mock := &Storage{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/files/mocks/Uploader.go b/pkg/files/mocks/Uploader.go
index 4ae80e348de2001158ff9e93c9a65180a06c9165..5e6e9f1414e437e2cf078cf2f576b73d0b0b7cd5 100644
--- a/pkg/files/mocks/Uploader.go
+++ b/pkg/files/mocks/Uploader.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -29,13 +29,12 @@ func (_m *Uploader) Upload(src io.Reader, upload *files.Upload) error {
 	return r0
 }
 
-type mockConstructorTestingTNewUploader interface {
+// NewUploader creates a new instance of Uploader. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewUploader(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewUploader creates a new instance of Uploader. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewUploader(t mockConstructorTestingTNewUploader) *Uploader {
+}) *Uploader {
 	mock := &Uploader{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/items/mocks/ItemObserver.go b/pkg/items/mocks/ItemObserver.go
index c4b4954c210235ff09677615cdffdcb2b2fa38b7..d826e04045f01e504200e742afa16e68181bc6c9 100644
--- a/pkg/items/mocks/ItemObserver.go
+++ b/pkg/items/mocks/ItemObserver.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.27.1. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -9,13 +9,12 @@ type ItemObserver struct {
 	mock.Mock
 }
 
-type mockConstructorTestingTNewItemObserver interface {
+// NewItemObserver creates a new instance of ItemObserver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewItemObserver(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewItemObserver creates a new instance of ItemObserver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewItemObserver(t mockConstructorTestingTNewItemObserver) *ItemObserver {
+}) *ItemObserver {
 	mock := &ItemObserver{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/items/mocks/ItemReadObserver.go b/pkg/items/mocks/ItemReadObserver.go
index cdbc43d4ce043adce90daabeda427b8bd9f3d670..212f09ad7a046086f1cc99230699a304ec2a9878 100644
--- a/pkg/items/mocks/ItemReadObserver.go
+++ b/pkg/items/mocks/ItemReadObserver.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.27.1. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -101,13 +101,12 @@ func (_m *ItemReadObserver) OnPreGet(ctx context.Context, spaceId string, envId
 	return r0
 }
 
-type mockConstructorTestingTNewItemReadObserver interface {
+// NewItemReadObserver creates a new instance of ItemReadObserver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewItemReadObserver(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewItemReadObserver creates a new instance of ItemReadObserver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewItemReadObserver(t mockConstructorTestingTNewItemReadObserver) *ItemReadObserver {
+}) *ItemReadObserver {
 	mock := &ItemReadObserver{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/items/mocks/Items.go b/pkg/items/mocks/Items.go
index 1f6833ff8ac1db35c895fc30cf50968a0fcb4349..9bbd8948668a7ec665fdefd2f5e086cb235d579d 100644
--- a/pkg/items/mocks/Items.go
+++ b/pkg/items/mocks/Items.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.27.1. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -556,13 +556,12 @@ func (_m *Items) Update(ctx context.Context, item *items.Item, options ...*items
 	return r0
 }
 
-type mockConstructorTestingTNewItems interface {
+// NewItems creates a new instance of Items. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewItems(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewItems creates a new instance of Items. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewItems(t mockConstructorTestingTNewItems) *Items {
+}) *Items {
 	mock := &Items{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/items/mocks/Middleware.go b/pkg/items/mocks/Middleware.go
index 89adb97469b8df07f8acfc380339e5115ac21478..1cde36c075701f58cd108a677fc73537cf25bf52 100644
--- a/pkg/items/mocks/Middleware.go
+++ b/pkg/items/mocks/Middleware.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.27.1. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -29,13 +29,12 @@ func (_m *Middleware) Execute(_a0 items.Items) items.Items {
 	return r0
 }
 
-type mockConstructorTestingTNewMiddleware interface {
+// NewMiddleware creates a new instance of Middleware. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewMiddleware(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewMiddleware creates a new instance of Middleware. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewMiddleware(t mockConstructorTestingTNewMiddleware) *Middleware {
+}) *Middleware {
 	mock := &Middleware{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/items/mocks/PreSaver.go b/pkg/items/mocks/PreSaver.go
index eb4e0cc2831e523db94d2c6881fef15b0353dc92..729c1ebfc4e7e60e2920b082e22f35617bf22e4e 100644
--- a/pkg/items/mocks/PreSaver.go
+++ b/pkg/items/mocks/PreSaver.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.27.1. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -49,13 +49,12 @@ func (_m *PreSaver) PreSave(ctx context.Context, f *field.Field, v interface{},
 	return r0, r1, r2
 }
 
-type mockConstructorTestingTNewPreSaver interface {
+// NewPreSaver creates a new instance of PreSaver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewPreSaver(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewPreSaver creates a new instance of PreSaver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewPreSaver(t mockConstructorTestingTNewPreSaver) *PreSaver {
+}) *PreSaver {
 	mock := &PreSaver{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/items/mocks/ProcessDataFunc.go b/pkg/items/mocks/ProcessDataFunc.go
index cb04ca90c304c51574dfdeb3a297bbd71fbbf80d..6ba38c984c7bba69461acc206393ebb66ba1cc07 100644
--- a/pkg/items/mocks/ProcessDataFunc.go
+++ b/pkg/items/mocks/ProcessDataFunc.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.27.1. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -41,13 +41,12 @@ func (_m *ProcessDataFunc) Execute(ctx context.Context, sch *schema.Schema, data
 	return r0, r1
 }
 
-type mockConstructorTestingTNewProcessDataFunc interface {
+// NewProcessDataFunc creates a new instance of ProcessDataFunc. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewProcessDataFunc(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewProcessDataFunc creates a new instance of ProcessDataFunc. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewProcessDataFunc(t mockConstructorTestingTNewProcessDataFunc) *ProcessDataFunc {
+}) *ProcessDataFunc {
 	mock := &ProcessDataFunc{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/items/mocks/Storage.go b/pkg/items/mocks/Storage.go
index 5630fc8b09c1a036a1580a6e1b85052ca93beecd..6f8082b98690dab97058c6775f3a53c2c655c80f 100644
--- a/pkg/items/mocks/Storage.go
+++ b/pkg/items/mocks/Storage.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.27.1. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -589,13 +589,12 @@ func (_m *Storage) Update(ctx context.Context, coll *collections.Collection, ite
 	return r0
 }
 
-type mockConstructorTestingTNewStorage interface {
+// NewStorage creates a new instance of Storage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewStorage(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewStorage creates a new instance of Storage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewStorage(t mockConstructorTestingTNewStorage) *Storage {
+}) *Storage {
 	mock := &Storage{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/members/mocks/Members.go b/pkg/members/mocks/Members.go
index 894bc76d5652c37559e1c77e6f0d290b3551497a..92a4f955147c04320a00c4df7193280022327dbf 100644
--- a/pkg/members/mocks/Members.go
+++ b/pkg/members/mocks/Members.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -19,13 +19,16 @@ func (_m *Members) Get(ctx context.Context, orgId string, userId string) (member
 	ret := _m.Called(ctx, orgId, userId)
 
 	var r0 members.Role
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string, string) (members.Role, error)); ok {
+		return rf(ctx, orgId, userId)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string, string) members.Role); ok {
 		r0 = rf(ctx, orgId, userId)
 	} else {
 		r0 = ret.Get(0).(members.Role)
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
 		r1 = rf(ctx, orgId, userId)
 	} else {
@@ -40,6 +43,10 @@ func (_m *Members) ListMembers(ctx context.Context, orgId string) ([]*members.Me
 	ret := _m.Called(ctx, orgId)
 
 	var r0 []*members.Member
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string) ([]*members.Member, error)); ok {
+		return rf(ctx, orgId)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string) []*members.Member); ok {
 		r0 = rf(ctx, orgId)
 	} else {
@@ -48,7 +55,6 @@ func (_m *Members) ListMembers(ctx context.Context, orgId string) ([]*members.Me
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
 		r1 = rf(ctx, orgId)
 	} else {
@@ -63,6 +69,10 @@ func (_m *Members) ListOrganizations(ctx context.Context, userId string) ([]*mem
 	ret := _m.Called(ctx, userId)
 
 	var r0 []*members.Member
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string) ([]*members.Member, error)); ok {
+		return rf(ctx, userId)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string) []*members.Member); ok {
 		r0 = rf(ctx, userId)
 	} else {
@@ -71,7 +81,6 @@ func (_m *Members) ListOrganizations(ctx context.Context, userId string) ([]*mem
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
 		r1 = rf(ctx, userId)
 	} else {
@@ -123,13 +132,12 @@ func (_m *Members) Set(ctx context.Context, orgId string, userId string, role me
 	return r0
 }
 
-type mockConstructorTestingTNewMembers interface {
+// NewMembers creates a new instance of Members. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewMembers(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewMembers creates a new instance of Members. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewMembers(t mockConstructorTestingTNewMembers) *Members {
+}) *Members {
 	mock := &Members{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/members/mocks/Middleware.go b/pkg/members/mocks/Middleware.go
index b953cf79d8239ef8da125e809bd29e1cf0a649f0..d32b22b62cbbd086862f53ce845d13dc89b552d7 100644
--- a/pkg/members/mocks/Middleware.go
+++ b/pkg/members/mocks/Middleware.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -28,13 +28,12 @@ func (_m *Middleware) Execute(_a0 observer.Observer) observer.Observer {
 	return r0
 }
 
-type mockConstructorTestingTNewMiddleware interface {
+// NewMiddleware creates a new instance of Middleware. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewMiddleware(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewMiddleware creates a new instance of Middleware. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewMiddleware(t mockConstructorTestingTNewMiddleware) *Middleware {
+}) *Middleware {
 	mock := &Middleware{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/members/mocks/Observer.go b/pkg/members/mocks/Observer.go
index f2feb9607c89babdb3e27262a8095d47bc209873..8914e2119836d48d78069c4315d03ceafc083170 100644
--- a/pkg/members/mocks/Observer.go
+++ b/pkg/members/mocks/Observer.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -20,13 +20,16 @@ func (_m *Observer) OnCollaboratorSet(ctx context.Context, collaborator *collabo
 	ret := _m.Called(ctx, collaborator)
 
 	var r0 string
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.Collaborator) (string, error)); ok {
+		return rf(ctx, collaborator)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.Collaborator) string); ok {
 		r0 = rf(ctx, collaborator)
 	} else {
 		r0 = ret.Get(0).(string)
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *collaborators.Collaborator) error); ok {
 		r1 = rf(ctx, collaborator)
 	} else {
@@ -36,13 +39,12 @@ func (_m *Observer) OnCollaboratorSet(ctx context.Context, collaborator *collabo
 	return r0, r1
 }
 
-type mockConstructorTestingTNewObserver interface {
+// NewObserver creates a new instance of Observer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewObserver(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewObserver creates a new instance of Observer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewObserver(t mockConstructorTestingTNewObserver) *Observer {
+}) *Observer {
 	mock := &Observer{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/members/mocks/Storage.go b/pkg/members/mocks/Storage.go
index 1527b6e09fce71d7b35d84d04613d2dcbfa96249..6732079eaf193795802339d4dae24c176c304037 100644
--- a/pkg/members/mocks/Storage.go
+++ b/pkg/members/mocks/Storage.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -21,6 +21,10 @@ func (_m *Storage) Find(ctx context.Context, filter *members.Filter, opts *optio
 	ret := _m.Called(ctx, filter, opts)
 
 	var r0 []*members.Member
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *members.Filter, *options.FindOptions) ([]*members.Member, error)); ok {
+		return rf(ctx, filter, opts)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *members.Filter, *options.FindOptions) []*members.Member); ok {
 		r0 = rf(ctx, filter, opts)
 	} else {
@@ -29,7 +33,6 @@ func (_m *Storage) Find(ctx context.Context, filter *members.Filter, opts *optio
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *members.Filter, *options.FindOptions) error); ok {
 		r1 = rf(ctx, filter, opts)
 	} else {
@@ -58,13 +61,16 @@ func (_m *Storage) Remove(ctx context.Context, filter *members.Filter) (int, err
 	ret := _m.Called(ctx, filter)
 
 	var r0 int
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *members.Filter) (int, error)); ok {
+		return rf(ctx, filter)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *members.Filter) int); ok {
 		r0 = rf(ctx, filter)
 	} else {
 		r0 = ret.Get(0).(int)
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *members.Filter) error); ok {
 		r1 = rf(ctx, filter)
 	} else {
@@ -102,13 +108,12 @@ func (_m *Storage) Set(ctx context.Context, orgID string, userID string, role me
 	return r0
 }
 
-type mockConstructorTestingTNewStorage interface {
+// NewStorage creates a new instance of Storage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewStorage(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewStorage creates a new instance of Storage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewStorage(t mockConstructorTestingTNewStorage) *Storage {
+}) *Storage {
 	mock := &Storage{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/operation/operation.go b/pkg/operation/operation.go
index 8b15ecc064f8d42c30e6f6c60d17275ac68486a8..ae2731ec0d3c3908b14de7df7467578819c07e02 100644
--- a/pkg/operation/operation.go
+++ b/pkg/operation/operation.go
@@ -49,8 +49,9 @@ func Wrap(client Client, proto *Proto) *Operation {
 	}
 
 	return &Operation{
-		proto:  proto,
-		client: client,
+		proto:    proto,
+		client:   client,
+		newTimer: time.NewTimer(),
 	}
 }
 
diff --git a/pkg/operation/operation_test.go b/pkg/operation/operation_test.go
index 6fea95d54f56f03c9dddd91e0797ac0346242acf..e769214556d16b91b24974de90bef8ab20554a0c 100644
--- a/pkg/operation/operation_test.go
+++ b/pkg/operation/operation_test.go
@@ -2,9 +2,14 @@ package operation
 
 import (
 	"context"
+	"fmt"
 	"testing"
 	"time"
 
+	"github.com/stretchr/testify/mock"
+
+	"git.perx.ru/perxis/perxis-go/proto/mocks"
+
 	"github.com/stretchr/testify/assert"
 )
 
@@ -23,3 +28,23 @@ func TestOperation(t *testing.T) {
 		// do nothing
 	})
 }
+
+func TestOperation_Wait(t *testing.T) {
+	count := 0
+	client := &mocks.OperationServiceClient{}
+	client.On("Get", mock.Anything, mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
+		fmt.Println(count)
+		count++
+	}).Return(&Proto{Id: "test"}, nil)
+
+	op := Wrap(client, &Proto{
+		Id: "test",
+	})
+	assert.NotNil(t, op)
+
+	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
+	defer cancel()
+
+	assert.Error(t, op.Wait(ctx))
+	mock.AssertExpectationsForObjects(t, client)
+}
diff --git a/pkg/operation/service.go b/pkg/operation/service.go
index d4daada31b71a5af8c4a9f5c5f97298102c88168..2bf8282899167d10cd7e21e319da9fcc75d692a1 100644
--- a/pkg/operation/service.go
+++ b/pkg/operation/service.go
@@ -9,7 +9,8 @@ import (
 )
 
 const (
-	DefaultRetention = time.Hour
+	DefaultRetention       = time.Hour
+	DefaultCleanupInterval = time.Minute
 )
 
 type Service interface {
@@ -20,26 +21,25 @@ type Service interface {
 }
 
 type service struct {
-	ops           map[string]*Operation
-	mu            sync.RWMutex
-	lastCleanup   time.Time
-	cleanupPeriod time.Duration
+	ops             map[string]*Operation // Registry of operations
+	mu              sync.RWMutex          // Mutex for operations registry
+	lastCleanup     time.Time             // Last time when cleanup was performed
+	cleanupInterval time.Duration         // Cleanup interval
 }
 
 func NewService(retention, cleanupPeriod time.Duration) Service {
 	return &service{
-		ops:           make(map[string]*Operation),
-		mu:            sync.RWMutex{},
-		cleanupPeriod: time.Minute,
+		ops:             make(map[string]*Operation),
+		mu:              sync.RWMutex{},
+		cleanupInterval: time.Minute,
 	}
 }
 
 func NewDefaultService() Service {
 	return &service{
-		ops:           make(map[string]*Operation),
-		mu:            sync.RWMutex{},
-		lastCleanup:   time.Now(),
-		cleanupPeriod: time.Minute,
+		ops:             make(map[string]*Operation),
+		mu:              sync.RWMutex{},
+		cleanupInterval: DefaultCleanupInterval,
 	}
 }
 
@@ -54,9 +54,9 @@ func (s *service) Cleanup() {
 }
 
 func (s *service) CleanupIfNeeded() {
-	if time.Since(s.lastCleanup) > s.cleanupPeriod {
-		s.Cleanup()
+	if time.Since(s.lastCleanup) > s.cleanupInterval {
 		s.lastCleanup = time.Now()
+		s.Cleanup()
 	}
 }
 
diff --git a/pkg/roles/mocks/Middleware.go b/pkg/roles/mocks/Middleware.go
index 35f4f9798cdb83f05ded631cf0b23f1815fe0b47..507b37154a40a1176a940bd29b6a6d23556a6bba 100644
--- a/pkg/roles/mocks/Middleware.go
+++ b/pkg/roles/mocks/Middleware.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -28,13 +28,12 @@ func (_m *Middleware) Execute(_a0 roles.Roles) roles.Roles {
 	return r0
 }
 
-type mockConstructorTestingTNewMiddleware interface {
+// NewMiddleware creates a new instance of Middleware. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewMiddleware(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewMiddleware creates a new instance of Middleware. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewMiddleware(t mockConstructorTestingTNewMiddleware) *Middleware {
+}) *Middleware {
 	mock := &Middleware{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/roles/mocks/Roles.go b/pkg/roles/mocks/Roles.go
index 1fc212541053dcfa1a05bdcd2d0b528d3f95fc34..08c523e06bc5082685ea1f7669a4b15849712222 100644
--- a/pkg/roles/mocks/Roles.go
+++ b/pkg/roles/mocks/Roles.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -19,6 +19,10 @@ func (_m *Roles) Create(ctx context.Context, role *roles.Role) (*roles.Role, err
 	ret := _m.Called(ctx, role)
 
 	var r0 *roles.Role
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *roles.Role) (*roles.Role, error)); ok {
+		return rf(ctx, role)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *roles.Role) *roles.Role); ok {
 		r0 = rf(ctx, role)
 	} else {
@@ -27,7 +31,6 @@ func (_m *Roles) Create(ctx context.Context, role *roles.Role) (*roles.Role, err
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *roles.Role) error); ok {
 		r1 = rf(ctx, role)
 	} else {
@@ -56,6 +59,10 @@ func (_m *Roles) Get(ctx context.Context, spaceId string, roleId string) (*roles
 	ret := _m.Called(ctx, spaceId, roleId)
 
 	var r0 *roles.Role
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string, string) (*roles.Role, error)); ok {
+		return rf(ctx, spaceId, roleId)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string, string) *roles.Role); ok {
 		r0 = rf(ctx, spaceId, roleId)
 	} else {
@@ -64,7 +71,6 @@ func (_m *Roles) Get(ctx context.Context, spaceId string, roleId string) (*roles
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
 		r1 = rf(ctx, spaceId, roleId)
 	} else {
@@ -79,6 +85,10 @@ func (_m *Roles) List(ctx context.Context, spaceId string) ([]*roles.Role, error
 	ret := _m.Called(ctx, spaceId)
 
 	var r0 []*roles.Role
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string) ([]*roles.Role, error)); ok {
+		return rf(ctx, spaceId)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string) []*roles.Role); ok {
 		r0 = rf(ctx, spaceId)
 	} else {
@@ -87,7 +97,6 @@ func (_m *Roles) List(ctx context.Context, spaceId string) ([]*roles.Role, error
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
 		r1 = rf(ctx, spaceId)
 	} else {
@@ -111,13 +120,12 @@ func (_m *Roles) Update(ctx context.Context, role *roles.Role) error {
 	return r0
 }
 
-type mockConstructorTestingTNewRoles interface {
+// NewRoles creates a new instance of Roles. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewRoles(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewRoles creates a new instance of Roles. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewRoles(t mockConstructorTestingTNewRoles) *Roles {
+}) *Roles {
 	mock := &Roles{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/roles/mocks/Storage.go b/pkg/roles/mocks/Storage.go
index d2d525a19e2c10096a0a1222122e302ad5ea0ce7..dc01f165aa37163cf23f28302e9f90f72420171e 100644
--- a/pkg/roles/mocks/Storage.go
+++ b/pkg/roles/mocks/Storage.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -21,6 +21,10 @@ func (_m *Storage) Create(ctx context.Context, role *roles.Role) (*roles.Role, e
 	ret := _m.Called(ctx, role)
 
 	var r0 *roles.Role
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *roles.Role) (*roles.Role, error)); ok {
+		return rf(ctx, role)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *roles.Role) *roles.Role); ok {
 		r0 = rf(ctx, role)
 	} else {
@@ -29,7 +33,6 @@ func (_m *Storage) Create(ctx context.Context, role *roles.Role) (*roles.Role, e
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *roles.Role) error); ok {
 		r1 = rf(ctx, role)
 	} else {
@@ -58,6 +61,11 @@ func (_m *Storage) Find(ctx context.Context, spaceID string, f *roles.Filter, op
 	ret := _m.Called(ctx, spaceID, f, opts)
 
 	var r0 []*roles.Role
+	var r1 int
+	var r2 error
+	if rf, ok := ret.Get(0).(func(context.Context, string, *roles.Filter, *options.FindOptions) ([]*roles.Role, int, error)); ok {
+		return rf(ctx, spaceID, f, opts)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string, *roles.Filter, *options.FindOptions) []*roles.Role); ok {
 		r0 = rf(ctx, spaceID, f, opts)
 	} else {
@@ -66,14 +74,12 @@ func (_m *Storage) Find(ctx context.Context, spaceID string, f *roles.Filter, op
 		}
 	}
 
-	var r1 int
 	if rf, ok := ret.Get(1).(func(context.Context, string, *roles.Filter, *options.FindOptions) int); ok {
 		r1 = rf(ctx, spaceID, f, opts)
 	} else {
 		r1 = ret.Get(1).(int)
 	}
 
-	var r2 error
 	if rf, ok := ret.Get(2).(func(context.Context, string, *roles.Filter, *options.FindOptions) error); ok {
 		r2 = rf(ctx, spaceID, f, opts)
 	} else {
@@ -102,20 +108,23 @@ func (_m *Storage) Update(ctx context.Context, role *roles.Role) (int, int, erro
 	ret := _m.Called(ctx, role)
 
 	var r0 int
+	var r1 int
+	var r2 error
+	if rf, ok := ret.Get(0).(func(context.Context, *roles.Role) (int, int, error)); ok {
+		return rf(ctx, role)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *roles.Role) int); ok {
 		r0 = rf(ctx, role)
 	} else {
 		r0 = ret.Get(0).(int)
 	}
 
-	var r1 int
 	if rf, ok := ret.Get(1).(func(context.Context, *roles.Role) int); ok {
 		r1 = rf(ctx, role)
 	} else {
 		r1 = ret.Get(1).(int)
 	}
 
-	var r2 error
 	if rf, ok := ret.Get(2).(func(context.Context, *roles.Role) error); ok {
 		r2 = rf(ctx, role)
 	} else {
@@ -125,13 +134,12 @@ func (_m *Storage) Update(ctx context.Context, role *roles.Role) (int, int, erro
 	return r0, r1, r2
 }
 
-type mockConstructorTestingTNewStorage interface {
+// NewStorage creates a new instance of Storage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewStorage(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewStorage creates a new instance of Storage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewStorage(t mockConstructorTestingTNewStorage) *Storage {
+}) *Storage {
 	mock := &Storage{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/users/mocks/Middleware.go b/pkg/users/mocks/Middleware.go
index 7a8e59c7ce2ef43db52d15457ac0c57494bb383a..63d457eb9c26bfa2b297a44ba994cc2be35e2055 100644
--- a/pkg/users/mocks/Middleware.go
+++ b/pkg/users/mocks/Middleware.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -28,13 +28,12 @@ func (_m *Middleware) Execute(_a0 users.Users) users.Users {
 	return r0
 }
 
-type mockConstructorTestingTNewMiddleware interface {
+// NewMiddleware creates a new instance of Middleware. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewMiddleware(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewMiddleware creates a new instance of Middleware. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewMiddleware(t mockConstructorTestingTNewMiddleware) *Middleware {
+}) *Middleware {
 	mock := &Middleware{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/users/mocks/Storage.go b/pkg/users/mocks/Storage.go
index e918d42414221cc2b6f29abe27116777714df08a..a1001d78cacac9825e7a5cfdfc7f0a712a661d8a 100644
--- a/pkg/users/mocks/Storage.go
+++ b/pkg/users/mocks/Storage.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -21,6 +21,10 @@ func (_m *Storage) Create(ctx context.Context, create *users.User) (*users.User,
 	ret := _m.Called(ctx, create)
 
 	var r0 *users.User
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *users.User) (*users.User, error)); ok {
+		return rf(ctx, create)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *users.User) *users.User); ok {
 		r0 = rf(ctx, create)
 	} else {
@@ -29,7 +33,6 @@ func (_m *Storage) Create(ctx context.Context, create *users.User) (*users.User,
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *users.User) error); ok {
 		r1 = rf(ctx, create)
 	} else {
@@ -44,13 +47,16 @@ func (_m *Storage) Delete(ctx context.Context, filter *users.Filter) (int, error
 	ret := _m.Called(ctx, filter)
 
 	var r0 int
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *users.Filter) (int, error)); ok {
+		return rf(ctx, filter)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *users.Filter) int); ok {
 		r0 = rf(ctx, filter)
 	} else {
 		r0 = ret.Get(0).(int)
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *users.Filter) error); ok {
 		r1 = rf(ctx, filter)
 	} else {
@@ -65,6 +71,11 @@ func (_m *Storage) Find(ctx context.Context, filter *users.Filter, opts *options
 	ret := _m.Called(ctx, filter, opts)
 
 	var r0 []*users.User
+	var r1 int
+	var r2 error
+	if rf, ok := ret.Get(0).(func(context.Context, *users.Filter, *options.FindOptions) ([]*users.User, int, error)); ok {
+		return rf(ctx, filter, opts)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *users.Filter, *options.FindOptions) []*users.User); ok {
 		r0 = rf(ctx, filter, opts)
 	} else {
@@ -73,14 +84,12 @@ func (_m *Storage) Find(ctx context.Context, filter *users.Filter, opts *options
 		}
 	}
 
-	var r1 int
 	if rf, ok := ret.Get(1).(func(context.Context, *users.Filter, *options.FindOptions) int); ok {
 		r1 = rf(ctx, filter, opts)
 	} else {
 		r1 = ret.Get(1).(int)
 	}
 
-	var r2 error
 	if rf, ok := ret.Get(2).(func(context.Context, *users.Filter, *options.FindOptions) error); ok {
 		r2 = rf(ctx, filter, opts)
 	} else {
@@ -123,20 +132,23 @@ func (_m *Storage) Update(ctx context.Context, update *users.User, filter *users
 	ret := _m.Called(ctx, update, filter)
 
 	var r0 int
+	var r1 int
+	var r2 error
+	if rf, ok := ret.Get(0).(func(context.Context, *users.User, *users.Filter) (int, int, error)); ok {
+		return rf(ctx, update, filter)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *users.User, *users.Filter) int); ok {
 		r0 = rf(ctx, update, filter)
 	} else {
 		r0 = ret.Get(0).(int)
 	}
 
-	var r1 int
 	if rf, ok := ret.Get(1).(func(context.Context, *users.User, *users.Filter) int); ok {
 		r1 = rf(ctx, update, filter)
 	} else {
 		r1 = ret.Get(1).(int)
 	}
 
-	var r2 error
 	if rf, ok := ret.Get(2).(func(context.Context, *users.User, *users.Filter) error); ok {
 		r2 = rf(ctx, update, filter)
 	} else {
@@ -146,13 +158,12 @@ func (_m *Storage) Update(ctx context.Context, update *users.User, filter *users
 	return r0, r1, r2
 }
 
-type mockConstructorTestingTNewStorage interface {
+// NewStorage creates a new instance of Storage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewStorage(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewStorage creates a new instance of Storage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewStorage(t mockConstructorTestingTNewStorage) *Storage {
+}) *Storage {
 	mock := &Storage{}
 	mock.Mock.Test(t)
 
diff --git a/pkg/users/mocks/Users.go b/pkg/users/mocks/Users.go
index 124cc3c5096fbd00a9554c5e182610236e162574..4db80b6d31f883092ab690f2d4ffe1616a339d35 100644
--- a/pkg/users/mocks/Users.go
+++ b/pkg/users/mocks/Users.go
@@ -1,4 +1,4 @@
-// Code generated by mockery v2.15.0. DO NOT EDIT.
+// Code generated by mockery v2.33.3. DO NOT EDIT.
 
 package mocks
 
@@ -21,6 +21,10 @@ func (_m *Users) Create(ctx context.Context, create *users.User) (*users.User, e
 	ret := _m.Called(ctx, create)
 
 	var r0 *users.User
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *users.User) (*users.User, error)); ok {
+		return rf(ctx, create)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *users.User) *users.User); ok {
 		r0 = rf(ctx, create)
 	} else {
@@ -29,7 +33,6 @@ func (_m *Users) Create(ctx context.Context, create *users.User) (*users.User, e
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, *users.User) error); ok {
 		r1 = rf(ctx, create)
 	} else {
@@ -58,6 +61,11 @@ func (_m *Users) Find(ctx context.Context, filter *users.Filter, _a2 *options.Fi
 	ret := _m.Called(ctx, filter, _a2)
 
 	var r0 []*users.User
+	var r1 int
+	var r2 error
+	if rf, ok := ret.Get(0).(func(context.Context, *users.Filter, *options.FindOptions) ([]*users.User, int, error)); ok {
+		return rf(ctx, filter, _a2)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, *users.Filter, *options.FindOptions) []*users.User); ok {
 		r0 = rf(ctx, filter, _a2)
 	} else {
@@ -66,14 +74,12 @@ func (_m *Users) Find(ctx context.Context, filter *users.Filter, _a2 *options.Fi
 		}
 	}
 
-	var r1 int
 	if rf, ok := ret.Get(1).(func(context.Context, *users.Filter, *options.FindOptions) int); ok {
 		r1 = rf(ctx, filter, _a2)
 	} else {
 		r1 = ret.Get(1).(int)
 	}
 
-	var r2 error
 	if rf, ok := ret.Get(2).(func(context.Context, *users.Filter, *options.FindOptions) error); ok {
 		r2 = rf(ctx, filter, _a2)
 	} else {
@@ -88,6 +94,10 @@ func (_m *Users) Get(ctx context.Context, userId string) (*users.User, error) {
 	ret := _m.Called(ctx, userId)
 
 	var r0 *users.User
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string) (*users.User, error)); ok {
+		return rf(ctx, userId)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string) *users.User); ok {
 		r0 = rf(ctx, userId)
 	} else {
@@ -96,7 +106,6 @@ func (_m *Users) Get(ctx context.Context, userId string) (*users.User, error) {
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
 		r1 = rf(ctx, userId)
 	} else {
@@ -111,6 +120,10 @@ func (_m *Users) GetByIdentity(ctx context.Context, identity string) (*users.Use
 	ret := _m.Called(ctx, identity)
 
 	var r0 *users.User
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, string) (*users.User, error)); ok {
+		return rf(ctx, identity)
+	}
 	if rf, ok := ret.Get(0).(func(context.Context, string) *users.User); ok {
 		r0 = rf(ctx, identity)
 	} else {
@@ -119,7 +132,6 @@ func (_m *Users) GetByIdentity(ctx context.Context, identity string) (*users.Use
 		}
 	}
 
-	var r1 error
 	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
 		r1 = rf(ctx, identity)
 	} else {
@@ -143,13 +155,12 @@ func (_m *Users) Update(ctx context.Context, update *users.User) error {
 	return r0
 }
 
-type mockConstructorTestingTNewUsers interface {
+// NewUsers creates a new instance of Users. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewUsers(t interface {
 	mock.TestingT
 	Cleanup(func())
-}
-
-// NewUsers creates a new instance of Users. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-func NewUsers(t mockConstructorTestingTNewUsers) *Users {
+}) *Users {
 	mock := &Users{}
 	mock.Mock.Test(t)
 
diff --git a/proto/mocks/ClientsClient.go b/proto/mocks/ClientsClient.go
new file mode 100644
index 0000000000000000000000000000000000000000..3234e72429d2ea922307b4acf9afde5042433a7a
--- /dev/null
+++ b/proto/mocks/ClientsClient.go
@@ -0,0 +1,265 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	clients "git.perx.ru/perxis/perxis-go/proto/clients"
+
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	grpc "google.golang.org/grpc"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// ClientsClient is an autogenerated mock type for the ClientsClient type
+type ClientsClient struct {
+	mock.Mock
+}
+
+// Create provides a mock function with given fields: ctx, in, opts
+func (_m *ClientsClient) Create(ctx context.Context, in *clients.CreateRequest, opts ...grpc.CallOption) (*clients.CreateResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *clients.CreateResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.CreateRequest, ...grpc.CallOption) (*clients.CreateResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.CreateRequest, ...grpc.CallOption) *clients.CreateResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*clients.CreateResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *clients.CreateRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Delete provides a mock function with given fields: ctx, in, opts
+func (_m *ClientsClient) Delete(ctx context.Context, in *clients.DeleteRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.DeleteRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.DeleteRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *clients.DeleteRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Enable provides a mock function with given fields: ctx, in, opts
+func (_m *ClientsClient) Enable(ctx context.Context, in *clients.EnableRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.EnableRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.EnableRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *clients.EnableRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Get provides a mock function with given fields: ctx, in, opts
+func (_m *ClientsClient) Get(ctx context.Context, in *clients.GetRequest, opts ...grpc.CallOption) (*clients.GetResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *clients.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.GetRequest, ...grpc.CallOption) (*clients.GetResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.GetRequest, ...grpc.CallOption) *clients.GetResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*clients.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *clients.GetRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// GetBy provides a mock function with given fields: ctx, in, opts
+func (_m *ClientsClient) GetBy(ctx context.Context, in *clients.GetByRequest, opts ...grpc.CallOption) (*clients.GetByResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *clients.GetByResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.GetByRequest, ...grpc.CallOption) (*clients.GetByResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.GetByRequest, ...grpc.CallOption) *clients.GetByResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*clients.GetByResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *clients.GetByRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// List provides a mock function with given fields: ctx, in, opts
+func (_m *ClientsClient) List(ctx context.Context, in *clients.ListRequest, opts ...grpc.CallOption) (*clients.ListResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *clients.ListResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.ListRequest, ...grpc.CallOption) (*clients.ListResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.ListRequest, ...grpc.CallOption) *clients.ListResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*clients.ListResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *clients.ListRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Update provides a mock function with given fields: ctx, in, opts
+func (_m *ClientsClient) Update(ctx context.Context, in *clients.UpdateRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.UpdateRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.UpdateRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *clients.UpdateRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// NewClientsClient creates a new instance of ClientsClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewClientsClient(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *ClientsClient {
+	mock := &ClientsClient{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/ClientsServer.go b/proto/mocks/ClientsServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..75d6e4f176b69f5c6a03307c588c66d0362e4835
--- /dev/null
+++ b/proto/mocks/ClientsServer.go
@@ -0,0 +1,219 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	clients "git.perx.ru/perxis/perxis-go/proto/clients"
+
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// ClientsServer is an autogenerated mock type for the ClientsServer type
+type ClientsServer struct {
+	mock.Mock
+}
+
+// Create provides a mock function with given fields: _a0, _a1
+func (_m *ClientsServer) Create(_a0 context.Context, _a1 *clients.CreateRequest) (*clients.CreateResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *clients.CreateResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.CreateRequest) (*clients.CreateResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.CreateRequest) *clients.CreateResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*clients.CreateResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *clients.CreateRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Delete provides a mock function with given fields: _a0, _a1
+func (_m *ClientsServer) Delete(_a0 context.Context, _a1 *clients.DeleteRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.DeleteRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.DeleteRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *clients.DeleteRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Enable provides a mock function with given fields: _a0, _a1
+func (_m *ClientsServer) Enable(_a0 context.Context, _a1 *clients.EnableRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.EnableRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.EnableRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *clients.EnableRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Get provides a mock function with given fields: _a0, _a1
+func (_m *ClientsServer) Get(_a0 context.Context, _a1 *clients.GetRequest) (*clients.GetResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *clients.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.GetRequest) (*clients.GetResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.GetRequest) *clients.GetResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*clients.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *clients.GetRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// GetBy provides a mock function with given fields: _a0, _a1
+func (_m *ClientsServer) GetBy(_a0 context.Context, _a1 *clients.GetByRequest) (*clients.GetByResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *clients.GetByResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.GetByRequest) (*clients.GetByResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.GetByRequest) *clients.GetByResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*clients.GetByResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *clients.GetByRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// List provides a mock function with given fields: _a0, _a1
+func (_m *ClientsServer) List(_a0 context.Context, _a1 *clients.ListRequest) (*clients.ListResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *clients.ListResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.ListRequest) (*clients.ListResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.ListRequest) *clients.ListResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*clients.ListResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *clients.ListRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Update provides a mock function with given fields: _a0, _a1
+func (_m *ClientsServer) Update(_a0 context.Context, _a1 *clients.UpdateRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.UpdateRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *clients.UpdateRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *clients.UpdateRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// mustEmbedUnimplementedClientsServer provides a mock function with given fields:
+func (_m *ClientsServer) mustEmbedUnimplementedClientsServer() {
+	_m.Called()
+}
+
+// NewClientsServer creates a new instance of ClientsServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewClientsServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *ClientsServer {
+	mock := &ClientsServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/CollaboratorsClient.go b/proto/mocks/CollaboratorsClient.go
new file mode 100644
index 0000000000000000000000000000000000000000..8d9cb07fce907d4a130fe26ec08aa3c266d442ec
--- /dev/null
+++ b/proto/mocks/CollaboratorsClient.go
@@ -0,0 +1,199 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	collaborators "git.perx.ru/perxis/perxis-go/proto/collaborators"
+
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	grpc "google.golang.org/grpc"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// CollaboratorsClient is an autogenerated mock type for the CollaboratorsClient type
+type CollaboratorsClient struct {
+	mock.Mock
+}
+
+// Get provides a mock function with given fields: ctx, in, opts
+func (_m *CollaboratorsClient) Get(ctx context.Context, in *collaborators.GetRequest, opts ...grpc.CallOption) (*collaborators.GetResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *collaborators.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.GetRequest, ...grpc.CallOption) (*collaborators.GetResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.GetRequest, ...grpc.CallOption) *collaborators.GetResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*collaborators.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *collaborators.GetRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// ListCollaborators provides a mock function with given fields: ctx, in, opts
+func (_m *CollaboratorsClient) ListCollaborators(ctx context.Context, in *collaborators.ListCollaboratorsRequest, opts ...grpc.CallOption) (*collaborators.ListCollaboratorsResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *collaborators.ListCollaboratorsResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.ListCollaboratorsRequest, ...grpc.CallOption) (*collaborators.ListCollaboratorsResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.ListCollaboratorsRequest, ...grpc.CallOption) *collaborators.ListCollaboratorsResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*collaborators.ListCollaboratorsResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *collaborators.ListCollaboratorsRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// ListSpaces provides a mock function with given fields: ctx, in, opts
+func (_m *CollaboratorsClient) ListSpaces(ctx context.Context, in *collaborators.ListSpacesRequest, opts ...grpc.CallOption) (*collaborators.ListSpacesResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *collaborators.ListSpacesResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.ListSpacesRequest, ...grpc.CallOption) (*collaborators.ListSpacesResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.ListSpacesRequest, ...grpc.CallOption) *collaborators.ListSpacesResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*collaborators.ListSpacesResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *collaborators.ListSpacesRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Remove provides a mock function with given fields: ctx, in, opts
+func (_m *CollaboratorsClient) Remove(ctx context.Context, in *collaborators.RemoveRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.RemoveRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.RemoveRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *collaborators.RemoveRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Set provides a mock function with given fields: ctx, in, opts
+func (_m *CollaboratorsClient) Set(ctx context.Context, in *collaborators.SetRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.SetRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.SetRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *collaborators.SetRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// NewCollaboratorsClient creates a new instance of CollaboratorsClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewCollaboratorsClient(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *CollaboratorsClient {
+	mock := &CollaboratorsClient{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/CollaboratorsServer.go b/proto/mocks/CollaboratorsServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..4e2fe0e00ed5628baa0d2478340f687a13bae9bb
--- /dev/null
+++ b/proto/mocks/CollaboratorsServer.go
@@ -0,0 +1,167 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	collaborators "git.perx.ru/perxis/perxis-go/proto/collaborators"
+
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// CollaboratorsServer is an autogenerated mock type for the CollaboratorsServer type
+type CollaboratorsServer struct {
+	mock.Mock
+}
+
+// Get provides a mock function with given fields: _a0, _a1
+func (_m *CollaboratorsServer) Get(_a0 context.Context, _a1 *collaborators.GetRequest) (*collaborators.GetResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *collaborators.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.GetRequest) (*collaborators.GetResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.GetRequest) *collaborators.GetResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*collaborators.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *collaborators.GetRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// ListCollaborators provides a mock function with given fields: _a0, _a1
+func (_m *CollaboratorsServer) ListCollaborators(_a0 context.Context, _a1 *collaborators.ListCollaboratorsRequest) (*collaborators.ListCollaboratorsResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *collaborators.ListCollaboratorsResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.ListCollaboratorsRequest) (*collaborators.ListCollaboratorsResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.ListCollaboratorsRequest) *collaborators.ListCollaboratorsResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*collaborators.ListCollaboratorsResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *collaborators.ListCollaboratorsRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// ListSpaces provides a mock function with given fields: _a0, _a1
+func (_m *CollaboratorsServer) ListSpaces(_a0 context.Context, _a1 *collaborators.ListSpacesRequest) (*collaborators.ListSpacesResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *collaborators.ListSpacesResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.ListSpacesRequest) (*collaborators.ListSpacesResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.ListSpacesRequest) *collaborators.ListSpacesResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*collaborators.ListSpacesResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *collaborators.ListSpacesRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Remove provides a mock function with given fields: _a0, _a1
+func (_m *CollaboratorsServer) Remove(_a0 context.Context, _a1 *collaborators.RemoveRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.RemoveRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.RemoveRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *collaborators.RemoveRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Set provides a mock function with given fields: _a0, _a1
+func (_m *CollaboratorsServer) Set(_a0 context.Context, _a1 *collaborators.SetRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.SetRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *collaborators.SetRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *collaborators.SetRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// mustEmbedUnimplementedCollaboratorsServer provides a mock function with given fields:
+func (_m *CollaboratorsServer) mustEmbedUnimplementedCollaboratorsServer() {
+	_m.Called()
+}
+
+// NewCollaboratorsServer creates a new instance of CollaboratorsServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewCollaboratorsServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *CollaboratorsServer {
+	mock := &CollaboratorsServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/CollectionsClient.go b/proto/mocks/CollectionsClient.go
new file mode 100644
index 0000000000000000000000000000000000000000..9c8ae28c4658aaf21f483353d1f98f0f71a52e1e
--- /dev/null
+++ b/proto/mocks/CollectionsClient.go
@@ -0,0 +1,232 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	collections "git.perx.ru/perxis/perxis-go/proto/collections"
+
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	grpc "google.golang.org/grpc"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// CollectionsClient is an autogenerated mock type for the CollectionsClient type
+type CollectionsClient struct {
+	mock.Mock
+}
+
+// Create provides a mock function with given fields: ctx, in, opts
+func (_m *CollectionsClient) Create(ctx context.Context, in *collections.CreateRequest, opts ...grpc.CallOption) (*collections.CreateResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *collections.CreateResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.CreateRequest, ...grpc.CallOption) (*collections.CreateResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.CreateRequest, ...grpc.CallOption) *collections.CreateResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*collections.CreateResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *collections.CreateRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Delete provides a mock function with given fields: ctx, in, opts
+func (_m *CollectionsClient) Delete(ctx context.Context, in *collections.DeleteRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.DeleteRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.DeleteRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *collections.DeleteRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Get provides a mock function with given fields: ctx, in, opts
+func (_m *CollectionsClient) Get(ctx context.Context, in *collections.GetRequest, opts ...grpc.CallOption) (*collections.GetResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *collections.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.GetRequest, ...grpc.CallOption) (*collections.GetResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.GetRequest, ...grpc.CallOption) *collections.GetResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*collections.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *collections.GetRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// List provides a mock function with given fields: ctx, in, opts
+func (_m *CollectionsClient) List(ctx context.Context, in *collections.ListRequest, opts ...grpc.CallOption) (*collections.ListResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *collections.ListResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.ListRequest, ...grpc.CallOption) (*collections.ListResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.ListRequest, ...grpc.CallOption) *collections.ListResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*collections.ListResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *collections.ListRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// SetSchema provides a mock function with given fields: ctx, in, opts
+func (_m *CollectionsClient) SetSchema(ctx context.Context, in *collections.SetSchemaRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.SetSchemaRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.SetSchemaRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *collections.SetSchemaRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Update provides a mock function with given fields: ctx, in, opts
+func (_m *CollectionsClient) Update(ctx context.Context, in *collections.UpdateRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.UpdateRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.UpdateRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *collections.UpdateRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// NewCollectionsClient creates a new instance of CollectionsClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewCollectionsClient(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *CollectionsClient {
+	mock := &CollectionsClient{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/CollectionsServer.go b/proto/mocks/CollectionsServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..5e49e0c96779e8f3262e2b9f6a13ca782f0bb4c7
--- /dev/null
+++ b/proto/mocks/CollectionsServer.go
@@ -0,0 +1,193 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	collections "git.perx.ru/perxis/perxis-go/proto/collections"
+
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// CollectionsServer is an autogenerated mock type for the CollectionsServer type
+type CollectionsServer struct {
+	mock.Mock
+}
+
+// Create provides a mock function with given fields: _a0, _a1
+func (_m *CollectionsServer) Create(_a0 context.Context, _a1 *collections.CreateRequest) (*collections.CreateResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *collections.CreateResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.CreateRequest) (*collections.CreateResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.CreateRequest) *collections.CreateResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*collections.CreateResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *collections.CreateRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Delete provides a mock function with given fields: _a0, _a1
+func (_m *CollectionsServer) Delete(_a0 context.Context, _a1 *collections.DeleteRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.DeleteRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.DeleteRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *collections.DeleteRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Get provides a mock function with given fields: _a0, _a1
+func (_m *CollectionsServer) Get(_a0 context.Context, _a1 *collections.GetRequest) (*collections.GetResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *collections.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.GetRequest) (*collections.GetResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.GetRequest) *collections.GetResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*collections.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *collections.GetRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// List provides a mock function with given fields: _a0, _a1
+func (_m *CollectionsServer) List(_a0 context.Context, _a1 *collections.ListRequest) (*collections.ListResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *collections.ListResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.ListRequest) (*collections.ListResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.ListRequest) *collections.ListResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*collections.ListResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *collections.ListRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// SetSchema provides a mock function with given fields: _a0, _a1
+func (_m *CollectionsServer) SetSchema(_a0 context.Context, _a1 *collections.SetSchemaRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.SetSchemaRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.SetSchemaRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *collections.SetSchemaRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Update provides a mock function with given fields: _a0, _a1
+func (_m *CollectionsServer) Update(_a0 context.Context, _a1 *collections.UpdateRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.UpdateRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *collections.UpdateRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *collections.UpdateRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// mustEmbedUnimplementedCollectionsServer provides a mock function with given fields:
+func (_m *CollectionsServer) mustEmbedUnimplementedCollectionsServer() {
+	_m.Called()
+}
+
+// NewCollectionsServer creates a new instance of CollectionsServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewCollectionsServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *CollectionsServer {
+	mock := &CollectionsServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/DeliveryClient.go b/proto/mocks/DeliveryClient.go
new file mode 100644
index 0000000000000000000000000000000000000000..21327821d69ce9db1611848da91b243c4e6149ad
--- /dev/null
+++ b/proto/mocks/DeliveryClient.go
@@ -0,0 +1,295 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	delivery "git.perx.ru/perxis/perxis-go/proto/delivery"
+	grpc "google.golang.org/grpc"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// DeliveryClient is an autogenerated mock type for the DeliveryClient type
+type DeliveryClient struct {
+	mock.Mock
+}
+
+// Aggregate provides a mock function with given fields: ctx, in, opts
+func (_m *DeliveryClient) Aggregate(ctx context.Context, in *delivery.AggregateRequest, opts ...grpc.CallOption) (*delivery.AggregateResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *delivery.AggregateResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.AggregateRequest, ...grpc.CallOption) (*delivery.AggregateResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.AggregateRequest, ...grpc.CallOption) *delivery.AggregateResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*delivery.AggregateResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *delivery.AggregateRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// FindItems provides a mock function with given fields: ctx, in, opts
+func (_m *DeliveryClient) FindItems(ctx context.Context, in *delivery.FindItemsRequest, opts ...grpc.CallOption) (*delivery.FindItemsResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *delivery.FindItemsResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.FindItemsRequest, ...grpc.CallOption) (*delivery.FindItemsResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.FindItemsRequest, ...grpc.CallOption) *delivery.FindItemsResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*delivery.FindItemsResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *delivery.FindItemsRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// GetCollection provides a mock function with given fields: ctx, in, opts
+func (_m *DeliveryClient) GetCollection(ctx context.Context, in *delivery.GetCollectionRequest, opts ...grpc.CallOption) (*delivery.GetCollectionResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *delivery.GetCollectionResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.GetCollectionRequest, ...grpc.CallOption) (*delivery.GetCollectionResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.GetCollectionRequest, ...grpc.CallOption) *delivery.GetCollectionResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*delivery.GetCollectionResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *delivery.GetCollectionRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// GetEnvironment provides a mock function with given fields: ctx, in, opts
+func (_m *DeliveryClient) GetEnvironment(ctx context.Context, in *delivery.GetEnvironmentRequest, opts ...grpc.CallOption) (*delivery.GetEnvironmentResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *delivery.GetEnvironmentResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.GetEnvironmentRequest, ...grpc.CallOption) (*delivery.GetEnvironmentResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.GetEnvironmentRequest, ...grpc.CallOption) *delivery.GetEnvironmentResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*delivery.GetEnvironmentResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *delivery.GetEnvironmentRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// GetItem provides a mock function with given fields: ctx, in, opts
+func (_m *DeliveryClient) GetItem(ctx context.Context, in *delivery.GetItemRequest, opts ...grpc.CallOption) (*delivery.GetItemResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *delivery.GetItemResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.GetItemRequest, ...grpc.CallOption) (*delivery.GetItemResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.GetItemRequest, ...grpc.CallOption) *delivery.GetItemResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*delivery.GetItemResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *delivery.GetItemRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// ListCollections provides a mock function with given fields: ctx, in, opts
+func (_m *DeliveryClient) ListCollections(ctx context.Context, in *delivery.ListCollectionsRequest, opts ...grpc.CallOption) (*delivery.ListCollectionsResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *delivery.ListCollectionsResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.ListCollectionsRequest, ...grpc.CallOption) (*delivery.ListCollectionsResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.ListCollectionsRequest, ...grpc.CallOption) *delivery.ListCollectionsResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*delivery.ListCollectionsResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *delivery.ListCollectionsRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// ListEnvironments provides a mock function with given fields: ctx, in, opts
+func (_m *DeliveryClient) ListEnvironments(ctx context.Context, in *delivery.ListEnvironmentsRequest, opts ...grpc.CallOption) (*delivery.ListEnvironmentsResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *delivery.ListEnvironmentsResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.ListEnvironmentsRequest, ...grpc.CallOption) (*delivery.ListEnvironmentsResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.ListEnvironmentsRequest, ...grpc.CallOption) *delivery.ListEnvironmentsResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*delivery.ListEnvironmentsResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *delivery.ListEnvironmentsRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// ListLocales provides a mock function with given fields: ctx, in, opts
+func (_m *DeliveryClient) ListLocales(ctx context.Context, in *delivery.ListLocalesRequest, opts ...grpc.CallOption) (*delivery.ListLocalesResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *delivery.ListLocalesResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.ListLocalesRequest, ...grpc.CallOption) (*delivery.ListLocalesResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.ListLocalesRequest, ...grpc.CallOption) *delivery.ListLocalesResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*delivery.ListLocalesResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *delivery.ListLocalesRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// NewDeliveryClient creates a new instance of DeliveryClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewDeliveryClient(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *DeliveryClient {
+	mock := &DeliveryClient{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/DeliveryServer.go b/proto/mocks/DeliveryServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..2b42c46696a6076c767e904c97ea605a4ac7f738
--- /dev/null
+++ b/proto/mocks/DeliveryServer.go
@@ -0,0 +1,242 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	delivery "git.perx.ru/perxis/perxis-go/proto/delivery"
+	mock "github.com/stretchr/testify/mock"
+)
+
+// DeliveryServer is an autogenerated mock type for the DeliveryServer type
+type DeliveryServer struct {
+	mock.Mock
+}
+
+// Aggregate provides a mock function with given fields: _a0, _a1
+func (_m *DeliveryServer) Aggregate(_a0 context.Context, _a1 *delivery.AggregateRequest) (*delivery.AggregateResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *delivery.AggregateResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.AggregateRequest) (*delivery.AggregateResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.AggregateRequest) *delivery.AggregateResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*delivery.AggregateResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *delivery.AggregateRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// FindItems provides a mock function with given fields: _a0, _a1
+func (_m *DeliveryServer) FindItems(_a0 context.Context, _a1 *delivery.FindItemsRequest) (*delivery.FindItemsResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *delivery.FindItemsResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.FindItemsRequest) (*delivery.FindItemsResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.FindItemsRequest) *delivery.FindItemsResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*delivery.FindItemsResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *delivery.FindItemsRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// GetCollection provides a mock function with given fields: _a0, _a1
+func (_m *DeliveryServer) GetCollection(_a0 context.Context, _a1 *delivery.GetCollectionRequest) (*delivery.GetCollectionResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *delivery.GetCollectionResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.GetCollectionRequest) (*delivery.GetCollectionResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.GetCollectionRequest) *delivery.GetCollectionResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*delivery.GetCollectionResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *delivery.GetCollectionRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// GetEnvironment provides a mock function with given fields: _a0, _a1
+func (_m *DeliveryServer) GetEnvironment(_a0 context.Context, _a1 *delivery.GetEnvironmentRequest) (*delivery.GetEnvironmentResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *delivery.GetEnvironmentResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.GetEnvironmentRequest) (*delivery.GetEnvironmentResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.GetEnvironmentRequest) *delivery.GetEnvironmentResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*delivery.GetEnvironmentResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *delivery.GetEnvironmentRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// GetItem provides a mock function with given fields: _a0, _a1
+func (_m *DeliveryServer) GetItem(_a0 context.Context, _a1 *delivery.GetItemRequest) (*delivery.GetItemResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *delivery.GetItemResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.GetItemRequest) (*delivery.GetItemResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.GetItemRequest) *delivery.GetItemResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*delivery.GetItemResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *delivery.GetItemRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// ListCollections provides a mock function with given fields: _a0, _a1
+func (_m *DeliveryServer) ListCollections(_a0 context.Context, _a1 *delivery.ListCollectionsRequest) (*delivery.ListCollectionsResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *delivery.ListCollectionsResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.ListCollectionsRequest) (*delivery.ListCollectionsResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.ListCollectionsRequest) *delivery.ListCollectionsResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*delivery.ListCollectionsResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *delivery.ListCollectionsRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// ListEnvironments provides a mock function with given fields: _a0, _a1
+func (_m *DeliveryServer) ListEnvironments(_a0 context.Context, _a1 *delivery.ListEnvironmentsRequest) (*delivery.ListEnvironmentsResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *delivery.ListEnvironmentsResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.ListEnvironmentsRequest) (*delivery.ListEnvironmentsResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.ListEnvironmentsRequest) *delivery.ListEnvironmentsResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*delivery.ListEnvironmentsResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *delivery.ListEnvironmentsRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// ListLocales provides a mock function with given fields: _a0, _a1
+func (_m *DeliveryServer) ListLocales(_a0 context.Context, _a1 *delivery.ListLocalesRequest) (*delivery.ListLocalesResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *delivery.ListLocalesResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.ListLocalesRequest) (*delivery.ListLocalesResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *delivery.ListLocalesRequest) *delivery.ListLocalesResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*delivery.ListLocalesResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *delivery.ListLocalesRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// mustEmbedUnimplementedDeliveryServer provides a mock function with given fields:
+func (_m *DeliveryServer) mustEmbedUnimplementedDeliveryServer() {
+	_m.Called()
+}
+
+// NewDeliveryServer creates a new instance of DeliveryServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewDeliveryServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *DeliveryServer {
+	mock := &DeliveryServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/EnvironmentsClient.go b/proto/mocks/EnvironmentsClient.go
new file mode 100644
index 0000000000000000000000000000000000000000..9dfa19055c8f93806b238c7b29d9c04d1b90dfb2
--- /dev/null
+++ b/proto/mocks/EnvironmentsClient.go
@@ -0,0 +1,297 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	environments "git.perx.ru/perxis/perxis-go/proto/environments"
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	grpc "google.golang.org/grpc"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// EnvironmentsClient is an autogenerated mock type for the EnvironmentsClient type
+type EnvironmentsClient struct {
+	mock.Mock
+}
+
+// Create provides a mock function with given fields: ctx, in, opts
+func (_m *EnvironmentsClient) Create(ctx context.Context, in *environments.CreateRequest, opts ...grpc.CallOption) (*environments.CreateResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *environments.CreateResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.CreateRequest, ...grpc.CallOption) (*environments.CreateResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.CreateRequest, ...grpc.CallOption) *environments.CreateResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*environments.CreateResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *environments.CreateRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Delete provides a mock function with given fields: ctx, in, opts
+func (_m *EnvironmentsClient) Delete(ctx context.Context, in *environments.DeleteRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.DeleteRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.DeleteRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *environments.DeleteRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Get provides a mock function with given fields: ctx, in, opts
+func (_m *EnvironmentsClient) Get(ctx context.Context, in *environments.GetRequest, opts ...grpc.CallOption) (*environments.GetResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *environments.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.GetRequest, ...grpc.CallOption) (*environments.GetResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.GetRequest, ...grpc.CallOption) *environments.GetResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*environments.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *environments.GetRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// List provides a mock function with given fields: ctx, in, opts
+func (_m *EnvironmentsClient) List(ctx context.Context, in *environments.ListRequest, opts ...grpc.CallOption) (*environments.ListResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *environments.ListResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.ListRequest, ...grpc.CallOption) (*environments.ListResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.ListRequest, ...grpc.CallOption) *environments.ListResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*environments.ListResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *environments.ListRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Migrate provides a mock function with given fields: ctx, in, opts
+func (_m *EnvironmentsClient) Migrate(ctx context.Context, in *environments.MigrateRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.MigrateRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.MigrateRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *environments.MigrateRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// RemoveAlias provides a mock function with given fields: ctx, in, opts
+func (_m *EnvironmentsClient) RemoveAlias(ctx context.Context, in *environments.RemoveAliasRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.RemoveAliasRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.RemoveAliasRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *environments.RemoveAliasRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// SetAlias provides a mock function with given fields: ctx, in, opts
+func (_m *EnvironmentsClient) SetAlias(ctx context.Context, in *environments.SetAliasRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.SetAliasRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.SetAliasRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *environments.SetAliasRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Update provides a mock function with given fields: ctx, in, opts
+func (_m *EnvironmentsClient) Update(ctx context.Context, in *environments.UpdateRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.UpdateRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.UpdateRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *environments.UpdateRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// NewEnvironmentsClient creates a new instance of EnvironmentsClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewEnvironmentsClient(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *EnvironmentsClient {
+	mock := &EnvironmentsClient{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/EnvironmentsServer.go b/proto/mocks/EnvironmentsServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..e62b612e0eac04d79bbd24550b4c80b8c421bf6b
--- /dev/null
+++ b/proto/mocks/EnvironmentsServer.go
@@ -0,0 +1,244 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	environments "git.perx.ru/perxis/perxis-go/proto/environments"
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// EnvironmentsServer is an autogenerated mock type for the EnvironmentsServer type
+type EnvironmentsServer struct {
+	mock.Mock
+}
+
+// Create provides a mock function with given fields: _a0, _a1
+func (_m *EnvironmentsServer) Create(_a0 context.Context, _a1 *environments.CreateRequest) (*environments.CreateResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *environments.CreateResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.CreateRequest) (*environments.CreateResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.CreateRequest) *environments.CreateResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*environments.CreateResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *environments.CreateRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Delete provides a mock function with given fields: _a0, _a1
+func (_m *EnvironmentsServer) Delete(_a0 context.Context, _a1 *environments.DeleteRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.DeleteRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.DeleteRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *environments.DeleteRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Get provides a mock function with given fields: _a0, _a1
+func (_m *EnvironmentsServer) Get(_a0 context.Context, _a1 *environments.GetRequest) (*environments.GetResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *environments.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.GetRequest) (*environments.GetResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.GetRequest) *environments.GetResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*environments.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *environments.GetRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// List provides a mock function with given fields: _a0, _a1
+func (_m *EnvironmentsServer) List(_a0 context.Context, _a1 *environments.ListRequest) (*environments.ListResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *environments.ListResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.ListRequest) (*environments.ListResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.ListRequest) *environments.ListResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*environments.ListResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *environments.ListRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Migrate provides a mock function with given fields: _a0, _a1
+func (_m *EnvironmentsServer) Migrate(_a0 context.Context, _a1 *environments.MigrateRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.MigrateRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.MigrateRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *environments.MigrateRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// RemoveAlias provides a mock function with given fields: _a0, _a1
+func (_m *EnvironmentsServer) RemoveAlias(_a0 context.Context, _a1 *environments.RemoveAliasRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.RemoveAliasRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.RemoveAliasRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *environments.RemoveAliasRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// SetAlias provides a mock function with given fields: _a0, _a1
+func (_m *EnvironmentsServer) SetAlias(_a0 context.Context, _a1 *environments.SetAliasRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.SetAliasRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.SetAliasRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *environments.SetAliasRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Update provides a mock function with given fields: _a0, _a1
+func (_m *EnvironmentsServer) Update(_a0 context.Context, _a1 *environments.UpdateRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.UpdateRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *environments.UpdateRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *environments.UpdateRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// mustEmbedUnimplementedEnvironmentsServer provides a mock function with given fields:
+func (_m *EnvironmentsServer) mustEmbedUnimplementedEnvironmentsServer() {
+	_m.Called()
+}
+
+// NewEnvironmentsServer creates a new instance of EnvironmentsServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewEnvironmentsServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *EnvironmentsServer {
+	mock := &EnvironmentsServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/FilesClient.go b/proto/mocks/FilesClient.go
new file mode 100644
index 0000000000000000000000000000000000000000..b935c55866ac5928a9df36cb1d5e3c9e97598269
--- /dev/null
+++ b/proto/mocks/FilesClient.go
@@ -0,0 +1,264 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	files "git.perx.ru/perxis/perxis-go/proto/files"
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	grpc "google.golang.org/grpc"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// FilesClient is an autogenerated mock type for the FilesClient type
+type FilesClient struct {
+	mock.Mock
+}
+
+// AbortUpload provides a mock function with given fields: ctx, in, opts
+func (_m *FilesClient) AbortUpload(ctx context.Context, in *files.AbortUploadRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *files.AbortUploadRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *files.AbortUploadRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *files.AbortUploadRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// CompleteUpload provides a mock function with given fields: ctx, in, opts
+func (_m *FilesClient) CompleteUpload(ctx context.Context, in *files.CompleteUploadRequest, opts ...grpc.CallOption) (*files.CompleteUploadResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *files.CompleteUploadResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *files.CompleteUploadRequest, ...grpc.CallOption) (*files.CompleteUploadResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *files.CompleteUploadRequest, ...grpc.CallOption) *files.CompleteUploadResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*files.CompleteUploadResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *files.CompleteUploadRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// DeleteFile provides a mock function with given fields: ctx, in, opts
+func (_m *FilesClient) DeleteFile(ctx context.Context, in *files.DeleteFileRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *files.DeleteFileRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *files.DeleteFileRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *files.DeleteFileRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// GetFile provides a mock function with given fields: ctx, in, opts
+func (_m *FilesClient) GetFile(ctx context.Context, in *files.GetFileRequest, opts ...grpc.CallOption) (*files.GetFileResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *files.GetFileResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *files.GetFileRequest, ...grpc.CallOption) (*files.GetFileResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *files.GetFileRequest, ...grpc.CallOption) *files.GetFileResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*files.GetFileResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *files.GetFileRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// MoveUpload provides a mock function with given fields: ctx, in, opts
+func (_m *FilesClient) MoveUpload(ctx context.Context, in *files.MoveUploadRequest, opts ...grpc.CallOption) (*files.MoveUploadResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *files.MoveUploadResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *files.MoveUploadRequest, ...grpc.CallOption) (*files.MoveUploadResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *files.MoveUploadRequest, ...grpc.CallOption) *files.MoveUploadResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*files.MoveUploadResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *files.MoveUploadRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// StartUpload provides a mock function with given fields: ctx, in, opts
+func (_m *FilesClient) StartUpload(ctx context.Context, in *files.StartUploadRequest, opts ...grpc.CallOption) (*files.StartUploadResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *files.StartUploadResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *files.StartUploadRequest, ...grpc.CallOption) (*files.StartUploadResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *files.StartUploadRequest, ...grpc.CallOption) *files.StartUploadResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*files.StartUploadResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *files.StartUploadRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Upload provides a mock function with given fields: ctx, in, opts
+func (_m *FilesClient) Upload(ctx context.Context, in *files.UploadRequest, opts ...grpc.CallOption) (*files.UploadResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *files.UploadResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *files.UploadRequest, ...grpc.CallOption) (*files.UploadResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *files.UploadRequest, ...grpc.CallOption) *files.UploadResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*files.UploadResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *files.UploadRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// NewFilesClient creates a new instance of FilesClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewFilesClient(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *FilesClient {
+	mock := &FilesClient{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/FilesServer.go b/proto/mocks/FilesServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..3040249d215cfc9edd3376ef08c8697c6d8c3ced
--- /dev/null
+++ b/proto/mocks/FilesServer.go
@@ -0,0 +1,218 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	files "git.perx.ru/perxis/perxis-go/proto/files"
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// FilesServer is an autogenerated mock type for the FilesServer type
+type FilesServer struct {
+	mock.Mock
+}
+
+// AbortUpload provides a mock function with given fields: _a0, _a1
+func (_m *FilesServer) AbortUpload(_a0 context.Context, _a1 *files.AbortUploadRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *files.AbortUploadRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *files.AbortUploadRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *files.AbortUploadRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// CompleteUpload provides a mock function with given fields: _a0, _a1
+func (_m *FilesServer) CompleteUpload(_a0 context.Context, _a1 *files.CompleteUploadRequest) (*files.CompleteUploadResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *files.CompleteUploadResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *files.CompleteUploadRequest) (*files.CompleteUploadResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *files.CompleteUploadRequest) *files.CompleteUploadResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*files.CompleteUploadResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *files.CompleteUploadRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// DeleteFile provides a mock function with given fields: _a0, _a1
+func (_m *FilesServer) DeleteFile(_a0 context.Context, _a1 *files.DeleteFileRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *files.DeleteFileRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *files.DeleteFileRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *files.DeleteFileRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// GetFile provides a mock function with given fields: _a0, _a1
+func (_m *FilesServer) GetFile(_a0 context.Context, _a1 *files.GetFileRequest) (*files.GetFileResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *files.GetFileResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *files.GetFileRequest) (*files.GetFileResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *files.GetFileRequest) *files.GetFileResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*files.GetFileResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *files.GetFileRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// MoveUpload provides a mock function with given fields: _a0, _a1
+func (_m *FilesServer) MoveUpload(_a0 context.Context, _a1 *files.MoveUploadRequest) (*files.MoveUploadResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *files.MoveUploadResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *files.MoveUploadRequest) (*files.MoveUploadResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *files.MoveUploadRequest) *files.MoveUploadResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*files.MoveUploadResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *files.MoveUploadRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// StartUpload provides a mock function with given fields: _a0, _a1
+func (_m *FilesServer) StartUpload(_a0 context.Context, _a1 *files.StartUploadRequest) (*files.StartUploadResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *files.StartUploadResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *files.StartUploadRequest) (*files.StartUploadResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *files.StartUploadRequest) *files.StartUploadResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*files.StartUploadResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *files.StartUploadRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Upload provides a mock function with given fields: _a0, _a1
+func (_m *FilesServer) Upload(_a0 context.Context, _a1 *files.UploadRequest) (*files.UploadResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *files.UploadResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *files.UploadRequest) (*files.UploadResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *files.UploadRequest) *files.UploadResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*files.UploadResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *files.UploadRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// mustEmbedUnimplementedFilesServer provides a mock function with given fields:
+func (_m *FilesServer) mustEmbedUnimplementedFilesServer() {
+	_m.Called()
+}
+
+// NewFilesServer creates a new instance of FilesServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewFilesServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *FilesServer {
+	mock := &FilesServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/ImagesClient.go b/proto/mocks/ImagesClient.go
new file mode 100644
index 0000000000000000000000000000000000000000..f0d517b5341725649ddea5002187548bbb6c1ec1
--- /dev/null
+++ b/proto/mocks/ImagesClient.go
@@ -0,0 +1,65 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	grpc "google.golang.org/grpc"
+
+	images "git.perx.ru/perxis/perxis-go/proto/images"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// ImagesClient is an autogenerated mock type for the ImagesClient type
+type ImagesClient struct {
+	mock.Mock
+}
+
+// Get provides a mock function with given fields: ctx, in, opts
+func (_m *ImagesClient) Get(ctx context.Context, in *images.GetRequest, opts ...grpc.CallOption) (*images.GetResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *images.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *images.GetRequest, ...grpc.CallOption) (*images.GetResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *images.GetRequest, ...grpc.CallOption) *images.GetResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*images.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *images.GetRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// NewImagesClient creates a new instance of ImagesClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewImagesClient(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *ImagesClient {
+	mock := &ImagesClient{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/ImagesServer.go b/proto/mocks/ImagesServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..48dc9e4719c4cc85c1707a301f53ed4b44656a86
--- /dev/null
+++ b/proto/mocks/ImagesServer.go
@@ -0,0 +1,60 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	images "git.perx.ru/perxis/perxis-go/proto/images"
+	mock "github.com/stretchr/testify/mock"
+)
+
+// ImagesServer is an autogenerated mock type for the ImagesServer type
+type ImagesServer struct {
+	mock.Mock
+}
+
+// Get provides a mock function with given fields: _a0, _a1
+func (_m *ImagesServer) Get(_a0 context.Context, _a1 *images.GetRequest) (*images.GetResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *images.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *images.GetRequest) (*images.GetResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *images.GetRequest) *images.GetResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*images.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *images.GetRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// mustEmbedUnimplementedImagesServer provides a mock function with given fields:
+func (_m *ImagesServer) mustEmbedUnimplementedImagesServer() {
+	_m.Called()
+}
+
+// NewImagesServer creates a new instance of ImagesServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewImagesServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *ImagesServer {
+	mock := &ImagesServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/InvitationsClient.go b/proto/mocks/InvitationsClient.go
new file mode 100644
index 0000000000000000000000000000000000000000..442560a76aabadae72784e35a867c3384acb1d83
--- /dev/null
+++ b/proto/mocks/InvitationsClient.go
@@ -0,0 +1,198 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	grpc "google.golang.org/grpc"
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	invitations "git.perx.ru/perxis/perxis-go/proto/invitations"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// InvitationsClient is an autogenerated mock type for the InvitationsClient type
+type InvitationsClient struct {
+	mock.Mock
+}
+
+// Accept provides a mock function with given fields: ctx, in, opts
+func (_m *InvitationsClient) Accept(ctx context.Context, in *invitations.AcceptRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *invitations.AcceptRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *invitations.AcceptRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *invitations.AcceptRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Create provides a mock function with given fields: ctx, in, opts
+func (_m *InvitationsClient) Create(ctx context.Context, in *invitations.CreateRequest, opts ...grpc.CallOption) (*invitations.CreateResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *invitations.CreateResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *invitations.CreateRequest, ...grpc.CallOption) (*invitations.CreateResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *invitations.CreateRequest, ...grpc.CallOption) *invitations.CreateResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*invitations.CreateResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *invitations.CreateRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Delete provides a mock function with given fields: ctx, in, opts
+func (_m *InvitationsClient) Delete(ctx context.Context, in *invitations.DeleteRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *invitations.DeleteRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *invitations.DeleteRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *invitations.DeleteRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Find provides a mock function with given fields: ctx, in, opts
+func (_m *InvitationsClient) Find(ctx context.Context, in *invitations.FindRequest, opts ...grpc.CallOption) (*invitations.FindResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *invitations.FindResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *invitations.FindRequest, ...grpc.CallOption) (*invitations.FindResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *invitations.FindRequest, ...grpc.CallOption) *invitations.FindResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*invitations.FindResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *invitations.FindRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Get provides a mock function with given fields: ctx, in, opts
+func (_m *InvitationsClient) Get(ctx context.Context, in *invitations.GetRequest, opts ...grpc.CallOption) (*invitations.GetResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *invitations.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *invitations.GetRequest, ...grpc.CallOption) (*invitations.GetResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *invitations.GetRequest, ...grpc.CallOption) *invitations.GetResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*invitations.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *invitations.GetRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// NewInvitationsClient creates a new instance of InvitationsClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewInvitationsClient(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *InvitationsClient {
+	mock := &InvitationsClient{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/InvitationsServer.go b/proto/mocks/InvitationsServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..d48c99cdad7727b915c90dca136018d0c6d9d7f8
--- /dev/null
+++ b/proto/mocks/InvitationsServer.go
@@ -0,0 +1,166 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	invitations "git.perx.ru/perxis/perxis-go/proto/invitations"
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// InvitationsServer is an autogenerated mock type for the InvitationsServer type
+type InvitationsServer struct {
+	mock.Mock
+}
+
+// Accept provides a mock function with given fields: _a0, _a1
+func (_m *InvitationsServer) Accept(_a0 context.Context, _a1 *invitations.AcceptRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *invitations.AcceptRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *invitations.AcceptRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *invitations.AcceptRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Create provides a mock function with given fields: _a0, _a1
+func (_m *InvitationsServer) Create(_a0 context.Context, _a1 *invitations.CreateRequest) (*invitations.CreateResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *invitations.CreateResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *invitations.CreateRequest) (*invitations.CreateResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *invitations.CreateRequest) *invitations.CreateResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*invitations.CreateResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *invitations.CreateRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Delete provides a mock function with given fields: _a0, _a1
+func (_m *InvitationsServer) Delete(_a0 context.Context, _a1 *invitations.DeleteRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *invitations.DeleteRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *invitations.DeleteRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *invitations.DeleteRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Find provides a mock function with given fields: _a0, _a1
+func (_m *InvitationsServer) Find(_a0 context.Context, _a1 *invitations.FindRequest) (*invitations.FindResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *invitations.FindResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *invitations.FindRequest) (*invitations.FindResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *invitations.FindRequest) *invitations.FindResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*invitations.FindResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *invitations.FindRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Get provides a mock function with given fields: _a0, _a1
+func (_m *InvitationsServer) Get(_a0 context.Context, _a1 *invitations.GetRequest) (*invitations.GetResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *invitations.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *invitations.GetRequest) (*invitations.GetResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *invitations.GetRequest) *invitations.GetResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*invitations.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *invitations.GetRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// mustEmbedUnimplementedInvitationsServer provides a mock function with given fields:
+func (_m *InvitationsServer) mustEmbedUnimplementedInvitationsServer() {
+	_m.Called()
+}
+
+// NewInvitationsServer creates a new instance of InvitationsServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewInvitationsServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *InvitationsServer {
+	mock := &InvitationsServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/ItemsClient.go b/proto/mocks/ItemsClient.go
new file mode 100644
index 0000000000000000000000000000000000000000..bf9494d98adfc1413a2691b72e57ef3ec7b89b82
--- /dev/null
+++ b/proto/mocks/ItemsClient.go
@@ -0,0 +1,627 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	grpc "google.golang.org/grpc"
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	items "git.perx.ru/perxis/perxis-go/proto/items"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// ItemsClient is an autogenerated mock type for the ItemsClient type
+type ItemsClient struct {
+	mock.Mock
+}
+
+// Aggregate provides a mock function with given fields: ctx, in, opts
+func (_m *ItemsClient) Aggregate(ctx context.Context, in *items.AggregateRequest, opts ...grpc.CallOption) (*items.AggregateResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *items.AggregateResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.AggregateRequest, ...grpc.CallOption) (*items.AggregateResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.AggregateRequest, ...grpc.CallOption) *items.AggregateResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*items.AggregateResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.AggregateRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// AggregatePublished provides a mock function with given fields: ctx, in, opts
+func (_m *ItemsClient) AggregatePublished(ctx context.Context, in *items.AggregatePublishedRequest, opts ...grpc.CallOption) (*items.AggregatePublishedResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *items.AggregatePublishedResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.AggregatePublishedRequest, ...grpc.CallOption) (*items.AggregatePublishedResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.AggregatePublishedRequest, ...grpc.CallOption) *items.AggregatePublishedResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*items.AggregatePublishedResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.AggregatePublishedRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Archive provides a mock function with given fields: ctx, in, opts
+func (_m *ItemsClient) Archive(ctx context.Context, in *items.ArchiveRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.ArchiveRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.ArchiveRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.ArchiveRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Create provides a mock function with given fields: ctx, in, opts
+func (_m *ItemsClient) Create(ctx context.Context, in *items.CreateRequest, opts ...grpc.CallOption) (*items.CreateResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *items.CreateResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.CreateRequest, ...grpc.CallOption) (*items.CreateResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.CreateRequest, ...grpc.CallOption) *items.CreateResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*items.CreateResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.CreateRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Delete provides a mock function with given fields: ctx, in, opts
+func (_m *ItemsClient) Delete(ctx context.Context, in *items.DeleteRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.DeleteRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.DeleteRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.DeleteRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Find provides a mock function with given fields: ctx, in, opts
+func (_m *ItemsClient) Find(ctx context.Context, in *items.FindRequest, opts ...grpc.CallOption) (*items.FindResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *items.FindResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.FindRequest, ...grpc.CallOption) (*items.FindResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.FindRequest, ...grpc.CallOption) *items.FindResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*items.FindResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.FindRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// FindArchived provides a mock function with given fields: ctx, in, opts
+func (_m *ItemsClient) FindArchived(ctx context.Context, in *items.FindArchivedRequest, opts ...grpc.CallOption) (*items.FindArchivedResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *items.FindArchivedResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.FindArchivedRequest, ...grpc.CallOption) (*items.FindArchivedResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.FindArchivedRequest, ...grpc.CallOption) *items.FindArchivedResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*items.FindArchivedResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.FindArchivedRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// FindPublished provides a mock function with given fields: ctx, in, opts
+func (_m *ItemsClient) FindPublished(ctx context.Context, in *items.FindPublishedRequest, opts ...grpc.CallOption) (*items.FindPublishedResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *items.FindPublishedResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.FindPublishedRequest, ...grpc.CallOption) (*items.FindPublishedResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.FindPublishedRequest, ...grpc.CallOption) *items.FindPublishedResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*items.FindPublishedResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.FindPublishedRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Get provides a mock function with given fields: ctx, in, opts
+func (_m *ItemsClient) Get(ctx context.Context, in *items.GetRequest, opts ...grpc.CallOption) (*items.GetResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *items.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.GetRequest, ...grpc.CallOption) (*items.GetResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.GetRequest, ...grpc.CallOption) *items.GetResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*items.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.GetRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// GetPublished provides a mock function with given fields: ctx, in, opts
+func (_m *ItemsClient) GetPublished(ctx context.Context, in *items.GetPublishedRequest, opts ...grpc.CallOption) (*items.GetPublishedResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *items.GetPublishedResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.GetPublishedRequest, ...grpc.CallOption) (*items.GetPublishedResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.GetPublishedRequest, ...grpc.CallOption) *items.GetPublishedResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*items.GetPublishedResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.GetPublishedRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// GetRevision provides a mock function with given fields: ctx, in, opts
+func (_m *ItemsClient) GetRevision(ctx context.Context, in *items.GetRevisionRequest, opts ...grpc.CallOption) (*items.GetRevisionResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *items.GetRevisionResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.GetRevisionRequest, ...grpc.CallOption) (*items.GetRevisionResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.GetRevisionRequest, ...grpc.CallOption) *items.GetRevisionResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*items.GetRevisionResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.GetRevisionRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Introspect provides a mock function with given fields: ctx, in, opts
+func (_m *ItemsClient) Introspect(ctx context.Context, in *items.IntrospectRequest, opts ...grpc.CallOption) (*items.IntrospectResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *items.IntrospectResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.IntrospectRequest, ...grpc.CallOption) (*items.IntrospectResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.IntrospectRequest, ...grpc.CallOption) *items.IntrospectResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*items.IntrospectResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.IntrospectRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// ListRevisions provides a mock function with given fields: ctx, in, opts
+func (_m *ItemsClient) ListRevisions(ctx context.Context, in *items.ListRevisionsRequest, opts ...grpc.CallOption) (*items.ListRevisionsResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *items.ListRevisionsResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.ListRevisionsRequest, ...grpc.CallOption) (*items.ListRevisionsResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.ListRevisionsRequest, ...grpc.CallOption) *items.ListRevisionsResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*items.ListRevisionsResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.ListRevisionsRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Publish provides a mock function with given fields: ctx, in, opts
+func (_m *ItemsClient) Publish(ctx context.Context, in *items.PublishRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.PublishRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.PublishRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.PublishRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Unarchive provides a mock function with given fields: ctx, in, opts
+func (_m *ItemsClient) Unarchive(ctx context.Context, in *items.UnarchiveRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.UnarchiveRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.UnarchiveRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.UnarchiveRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Undelete provides a mock function with given fields: ctx, in, opts
+func (_m *ItemsClient) Undelete(ctx context.Context, in *items.UndeleteRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.UndeleteRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.UndeleteRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.UndeleteRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Unpublish provides a mock function with given fields: ctx, in, opts
+func (_m *ItemsClient) Unpublish(ctx context.Context, in *items.UnpublishRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.UnpublishRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.UnpublishRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.UnpublishRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Update provides a mock function with given fields: ctx, in, opts
+func (_m *ItemsClient) Update(ctx context.Context, in *items.UpdateRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.UpdateRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.UpdateRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.UpdateRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// NewItemsClient creates a new instance of ItemsClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewItemsClient(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *ItemsClient {
+	mock := &ItemsClient{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/ItemsServer.go b/proto/mocks/ItemsServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..89cb4de56d09ef13df9cd1da1ed0654d28f4059c
--- /dev/null
+++ b/proto/mocks/ItemsServer.go
@@ -0,0 +1,504 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	items "git.perx.ru/perxis/perxis-go/proto/items"
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// ItemsServer is an autogenerated mock type for the ItemsServer type
+type ItemsServer struct {
+	mock.Mock
+}
+
+// Aggregate provides a mock function with given fields: _a0, _a1
+func (_m *ItemsServer) Aggregate(_a0 context.Context, _a1 *items.AggregateRequest) (*items.AggregateResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *items.AggregateResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.AggregateRequest) (*items.AggregateResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.AggregateRequest) *items.AggregateResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*items.AggregateResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.AggregateRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// AggregatePublished provides a mock function with given fields: _a0, _a1
+func (_m *ItemsServer) AggregatePublished(_a0 context.Context, _a1 *items.AggregatePublishedRequest) (*items.AggregatePublishedResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *items.AggregatePublishedResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.AggregatePublishedRequest) (*items.AggregatePublishedResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.AggregatePublishedRequest) *items.AggregatePublishedResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*items.AggregatePublishedResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.AggregatePublishedRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Archive provides a mock function with given fields: _a0, _a1
+func (_m *ItemsServer) Archive(_a0 context.Context, _a1 *items.ArchiveRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.ArchiveRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.ArchiveRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.ArchiveRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Create provides a mock function with given fields: _a0, _a1
+func (_m *ItemsServer) Create(_a0 context.Context, _a1 *items.CreateRequest) (*items.CreateResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *items.CreateResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.CreateRequest) (*items.CreateResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.CreateRequest) *items.CreateResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*items.CreateResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.CreateRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Delete provides a mock function with given fields: _a0, _a1
+func (_m *ItemsServer) Delete(_a0 context.Context, _a1 *items.DeleteRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.DeleteRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.DeleteRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.DeleteRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Find provides a mock function with given fields: _a0, _a1
+func (_m *ItemsServer) Find(_a0 context.Context, _a1 *items.FindRequest) (*items.FindResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *items.FindResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.FindRequest) (*items.FindResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.FindRequest) *items.FindResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*items.FindResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.FindRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// FindArchived provides a mock function with given fields: _a0, _a1
+func (_m *ItemsServer) FindArchived(_a0 context.Context, _a1 *items.FindArchivedRequest) (*items.FindArchivedResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *items.FindArchivedResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.FindArchivedRequest) (*items.FindArchivedResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.FindArchivedRequest) *items.FindArchivedResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*items.FindArchivedResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.FindArchivedRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// FindPublished provides a mock function with given fields: _a0, _a1
+func (_m *ItemsServer) FindPublished(_a0 context.Context, _a1 *items.FindPublishedRequest) (*items.FindPublishedResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *items.FindPublishedResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.FindPublishedRequest) (*items.FindPublishedResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.FindPublishedRequest) *items.FindPublishedResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*items.FindPublishedResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.FindPublishedRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Get provides a mock function with given fields: _a0, _a1
+func (_m *ItemsServer) Get(_a0 context.Context, _a1 *items.GetRequest) (*items.GetResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *items.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.GetRequest) (*items.GetResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.GetRequest) *items.GetResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*items.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.GetRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// GetPublished provides a mock function with given fields: _a0, _a1
+func (_m *ItemsServer) GetPublished(_a0 context.Context, _a1 *items.GetPublishedRequest) (*items.GetPublishedResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *items.GetPublishedResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.GetPublishedRequest) (*items.GetPublishedResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.GetPublishedRequest) *items.GetPublishedResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*items.GetPublishedResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.GetPublishedRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// GetRevision provides a mock function with given fields: _a0, _a1
+func (_m *ItemsServer) GetRevision(_a0 context.Context, _a1 *items.GetRevisionRequest) (*items.GetRevisionResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *items.GetRevisionResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.GetRevisionRequest) (*items.GetRevisionResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.GetRevisionRequest) *items.GetRevisionResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*items.GetRevisionResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.GetRevisionRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Introspect provides a mock function with given fields: _a0, _a1
+func (_m *ItemsServer) Introspect(_a0 context.Context, _a1 *items.IntrospectRequest) (*items.IntrospectResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *items.IntrospectResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.IntrospectRequest) (*items.IntrospectResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.IntrospectRequest) *items.IntrospectResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*items.IntrospectResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.IntrospectRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// ListRevisions provides a mock function with given fields: _a0, _a1
+func (_m *ItemsServer) ListRevisions(_a0 context.Context, _a1 *items.ListRevisionsRequest) (*items.ListRevisionsResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *items.ListRevisionsResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.ListRevisionsRequest) (*items.ListRevisionsResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.ListRevisionsRequest) *items.ListRevisionsResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*items.ListRevisionsResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.ListRevisionsRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Publish provides a mock function with given fields: _a0, _a1
+func (_m *ItemsServer) Publish(_a0 context.Context, _a1 *items.PublishRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.PublishRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.PublishRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.PublishRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Unarchive provides a mock function with given fields: _a0, _a1
+func (_m *ItemsServer) Unarchive(_a0 context.Context, _a1 *items.UnarchiveRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.UnarchiveRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.UnarchiveRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.UnarchiveRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Undelete provides a mock function with given fields: _a0, _a1
+func (_m *ItemsServer) Undelete(_a0 context.Context, _a1 *items.UndeleteRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.UndeleteRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.UndeleteRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.UndeleteRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Unpublish provides a mock function with given fields: _a0, _a1
+func (_m *ItemsServer) Unpublish(_a0 context.Context, _a1 *items.UnpublishRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.UnpublishRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.UnpublishRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.UnpublishRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Update provides a mock function with given fields: _a0, _a1
+func (_m *ItemsServer) Update(_a0 context.Context, _a1 *items.UpdateRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *items.UpdateRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *items.UpdateRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *items.UpdateRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// mustEmbedUnimplementedItemsServer provides a mock function with given fields:
+func (_m *ItemsServer) mustEmbedUnimplementedItemsServer() {
+	_m.Called()
+}
+
+// NewItemsServer creates a new instance of ItemsServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewItemsServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *ItemsServer {
+	mock := &ItemsServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/LocalesClient.go b/proto/mocks/LocalesClient.go
new file mode 100644
index 0000000000000000000000000000000000000000..8ed98fd037a2b6ee59ba0ecb379ae7cca62f81c3
--- /dev/null
+++ b/proto/mocks/LocalesClient.go
@@ -0,0 +1,132 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	grpc "google.golang.org/grpc"
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	locales "git.perx.ru/perxis/perxis-go/proto/locales"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// LocalesClient is an autogenerated mock type for the LocalesClient type
+type LocalesClient struct {
+	mock.Mock
+}
+
+// Create provides a mock function with given fields: ctx, in, opts
+func (_m *LocalesClient) Create(ctx context.Context, in *locales.CreateRequest, opts ...grpc.CallOption) (*locales.CreateResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *locales.CreateResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *locales.CreateRequest, ...grpc.CallOption) (*locales.CreateResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *locales.CreateRequest, ...grpc.CallOption) *locales.CreateResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*locales.CreateResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *locales.CreateRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Delete provides a mock function with given fields: ctx, in, opts
+func (_m *LocalesClient) Delete(ctx context.Context, in *locales.DeleteRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *locales.DeleteRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *locales.DeleteRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *locales.DeleteRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// List provides a mock function with given fields: ctx, in, opts
+func (_m *LocalesClient) List(ctx context.Context, in *locales.ListRequest, opts ...grpc.CallOption) (*locales.ListResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *locales.ListResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *locales.ListRequest, ...grpc.CallOption) (*locales.ListResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *locales.ListRequest, ...grpc.CallOption) *locales.ListResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*locales.ListResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *locales.ListRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// NewLocalesClient creates a new instance of LocalesClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewLocalesClient(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *LocalesClient {
+	mock := &LocalesClient{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/LocalesServer.go b/proto/mocks/LocalesServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..8afc56d23f226ac41f44a58d1c7435c474ccde90
--- /dev/null
+++ b/proto/mocks/LocalesServer.go
@@ -0,0 +1,114 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	locales "git.perx.ru/perxis/perxis-go/proto/locales"
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// LocalesServer is an autogenerated mock type for the LocalesServer type
+type LocalesServer struct {
+	mock.Mock
+}
+
+// Create provides a mock function with given fields: _a0, _a1
+func (_m *LocalesServer) Create(_a0 context.Context, _a1 *locales.CreateRequest) (*locales.CreateResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *locales.CreateResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *locales.CreateRequest) (*locales.CreateResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *locales.CreateRequest) *locales.CreateResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*locales.CreateResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *locales.CreateRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Delete provides a mock function with given fields: _a0, _a1
+func (_m *LocalesServer) Delete(_a0 context.Context, _a1 *locales.DeleteRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *locales.DeleteRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *locales.DeleteRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *locales.DeleteRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// List provides a mock function with given fields: _a0, _a1
+func (_m *LocalesServer) List(_a0 context.Context, _a1 *locales.ListRequest) (*locales.ListResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *locales.ListResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *locales.ListRequest) (*locales.ListResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *locales.ListRequest) *locales.ListResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*locales.ListResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *locales.ListRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// mustEmbedUnimplementedLocalesServer provides a mock function with given fields:
+func (_m *LocalesServer) mustEmbedUnimplementedLocalesServer() {
+	_m.Called()
+}
+
+// NewLocalesServer creates a new instance of LocalesServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewLocalesServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *LocalesServer {
+	mock := &LocalesServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/MembersClient.go b/proto/mocks/MembersClient.go
new file mode 100644
index 0000000000000000000000000000000000000000..0e24c1c47873ae473bacb6ce434b2eb6e0ff0765
--- /dev/null
+++ b/proto/mocks/MembersClient.go
@@ -0,0 +1,198 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	grpc "google.golang.org/grpc"
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	members "git.perx.ru/perxis/perxis-go/proto/members"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// MembersClient is an autogenerated mock type for the MembersClient type
+type MembersClient struct {
+	mock.Mock
+}
+
+// Get provides a mock function with given fields: ctx, in, opts
+func (_m *MembersClient) Get(ctx context.Context, in *members.GetRequest, opts ...grpc.CallOption) (*members.GetResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *members.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *members.GetRequest, ...grpc.CallOption) (*members.GetResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *members.GetRequest, ...grpc.CallOption) *members.GetResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*members.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *members.GetRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// ListMembers provides a mock function with given fields: ctx, in, opts
+func (_m *MembersClient) ListMembers(ctx context.Context, in *members.ListMembersRequest, opts ...grpc.CallOption) (*members.ListMembersResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *members.ListMembersResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *members.ListMembersRequest, ...grpc.CallOption) (*members.ListMembersResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *members.ListMembersRequest, ...grpc.CallOption) *members.ListMembersResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*members.ListMembersResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *members.ListMembersRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// ListOrganizations provides a mock function with given fields: ctx, in, opts
+func (_m *MembersClient) ListOrganizations(ctx context.Context, in *members.ListOrganizationsRequest, opts ...grpc.CallOption) (*members.ListOrganizationsResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *members.ListOrganizationsResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *members.ListOrganizationsRequest, ...grpc.CallOption) (*members.ListOrganizationsResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *members.ListOrganizationsRequest, ...grpc.CallOption) *members.ListOrganizationsResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*members.ListOrganizationsResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *members.ListOrganizationsRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Remove provides a mock function with given fields: ctx, in, opts
+func (_m *MembersClient) Remove(ctx context.Context, in *members.RemoveRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *members.RemoveRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *members.RemoveRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *members.RemoveRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Set provides a mock function with given fields: ctx, in, opts
+func (_m *MembersClient) Set(ctx context.Context, in *members.SetRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *members.SetRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *members.SetRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *members.SetRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// NewMembersClient creates a new instance of MembersClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewMembersClient(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *MembersClient {
+	mock := &MembersClient{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/MembersServer.go b/proto/mocks/MembersServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..6adaf990dcf17a092711fac6b4ca31c4561ee103
--- /dev/null
+++ b/proto/mocks/MembersServer.go
@@ -0,0 +1,166 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	members "git.perx.ru/perxis/perxis-go/proto/members"
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// MembersServer is an autogenerated mock type for the MembersServer type
+type MembersServer struct {
+	mock.Mock
+}
+
+// Get provides a mock function with given fields: _a0, _a1
+func (_m *MembersServer) Get(_a0 context.Context, _a1 *members.GetRequest) (*members.GetResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *members.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *members.GetRequest) (*members.GetResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *members.GetRequest) *members.GetResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*members.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *members.GetRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// ListMembers provides a mock function with given fields: _a0, _a1
+func (_m *MembersServer) ListMembers(_a0 context.Context, _a1 *members.ListMembersRequest) (*members.ListMembersResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *members.ListMembersResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *members.ListMembersRequest) (*members.ListMembersResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *members.ListMembersRequest) *members.ListMembersResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*members.ListMembersResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *members.ListMembersRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// ListOrganizations provides a mock function with given fields: _a0, _a1
+func (_m *MembersServer) ListOrganizations(_a0 context.Context, _a1 *members.ListOrganizationsRequest) (*members.ListOrganizationsResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *members.ListOrganizationsResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *members.ListOrganizationsRequest) (*members.ListOrganizationsResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *members.ListOrganizationsRequest) *members.ListOrganizationsResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*members.ListOrganizationsResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *members.ListOrganizationsRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Remove provides a mock function with given fields: _a0, _a1
+func (_m *MembersServer) Remove(_a0 context.Context, _a1 *members.RemoveRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *members.RemoveRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *members.RemoveRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *members.RemoveRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Set provides a mock function with given fields: _a0, _a1
+func (_m *MembersServer) Set(_a0 context.Context, _a1 *members.SetRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *members.SetRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *members.SetRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *members.SetRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// mustEmbedUnimplementedMembersServer provides a mock function with given fields:
+func (_m *MembersServer) mustEmbedUnimplementedMembersServer() {
+	_m.Called()
+}
+
+// NewMembersServer creates a new instance of MembersServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewMembersServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *MembersServer {
+	mock := &MembersServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/ObserverClient.go b/proto/mocks/ObserverClient.go
new file mode 100644
index 0000000000000000000000000000000000000000..7e5463516e7a70aa9826185791a1bd8ebfbcb241
--- /dev/null
+++ b/proto/mocks/ObserverClient.go
@@ -0,0 +1,65 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	grpc "google.golang.org/grpc"
+
+	members "git.perx.ru/perxis/perxis-go/proto/members"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// ObserverClient is an autogenerated mock type for the ObserverClient type
+type ObserverClient struct {
+	mock.Mock
+}
+
+// OnCollaboratorSet provides a mock function with given fields: ctx, in, opts
+func (_m *ObserverClient) OnCollaboratorSet(ctx context.Context, in *members.OnCollaboratorSetRequest, opts ...grpc.CallOption) (*members.OnCollaboratorSetResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *members.OnCollaboratorSetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *members.OnCollaboratorSetRequest, ...grpc.CallOption) (*members.OnCollaboratorSetResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *members.OnCollaboratorSetRequest, ...grpc.CallOption) *members.OnCollaboratorSetResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*members.OnCollaboratorSetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *members.OnCollaboratorSetRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// NewObserverClient creates a new instance of ObserverClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewObserverClient(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *ObserverClient {
+	mock := &ObserverClient{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/ObserverServer.go b/proto/mocks/ObserverServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..87cba94c518b9cb06d725a5dd0224a29f4a7bbc9
--- /dev/null
+++ b/proto/mocks/ObserverServer.go
@@ -0,0 +1,60 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	members "git.perx.ru/perxis/perxis-go/proto/members"
+	mock "github.com/stretchr/testify/mock"
+)
+
+// ObserverServer is an autogenerated mock type for the ObserverServer type
+type ObserverServer struct {
+	mock.Mock
+}
+
+// OnCollaboratorSet provides a mock function with given fields: _a0, _a1
+func (_m *ObserverServer) OnCollaboratorSet(_a0 context.Context, _a1 *members.OnCollaboratorSetRequest) (*members.OnCollaboratorSetResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *members.OnCollaboratorSetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *members.OnCollaboratorSetRequest) (*members.OnCollaboratorSetResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *members.OnCollaboratorSetRequest) *members.OnCollaboratorSetResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*members.OnCollaboratorSetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *members.OnCollaboratorSetRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// mustEmbedUnimplementedObserverServer provides a mock function with given fields:
+func (_m *ObserverServer) mustEmbedUnimplementedObserverServer() {
+	_m.Called()
+}
+
+// NewObserverServer creates a new instance of ObserverServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewObserverServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *ObserverServer {
+	mock := &ObserverServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/OperationServiceClient.go b/proto/mocks/OperationServiceClient.go
new file mode 100644
index 0000000000000000000000000000000000000000..4118237072bf6a086cd211a0e04de528b6b259be
--- /dev/null
+++ b/proto/mocks/OperationServiceClient.go
@@ -0,0 +1,98 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	common "git.perx.ru/perxis/perxis-go/proto/common"
+
+	grpc "google.golang.org/grpc"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// OperationServiceClient is an autogenerated mock type for the OperationServiceClient type
+type OperationServiceClient struct {
+	mock.Mock
+}
+
+// Cancel provides a mock function with given fields: ctx, in, opts
+func (_m *OperationServiceClient) Cancel(ctx context.Context, in *common.CancelOperationRequest, opts ...grpc.CallOption) (*common.Operation, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *common.Operation
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *common.CancelOperationRequest, ...grpc.CallOption) (*common.Operation, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *common.CancelOperationRequest, ...grpc.CallOption) *common.Operation); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*common.Operation)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *common.CancelOperationRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Get provides a mock function with given fields: ctx, in, opts
+func (_m *OperationServiceClient) Get(ctx context.Context, in *common.GetOperationRequest, opts ...grpc.CallOption) (*common.Operation, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *common.Operation
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *common.GetOperationRequest, ...grpc.CallOption) (*common.Operation, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *common.GetOperationRequest, ...grpc.CallOption) *common.Operation); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*common.Operation)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *common.GetOperationRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// NewOperationServiceClient creates a new instance of OperationServiceClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewOperationServiceClient(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *OperationServiceClient {
+	mock := &OperationServiceClient{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/OperationServiceServer.go b/proto/mocks/OperationServiceServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..661a205ea0050fa4c5c33dd2eb13a824f9cfc24d
--- /dev/null
+++ b/proto/mocks/OperationServiceServer.go
@@ -0,0 +1,87 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	common "git.perx.ru/perxis/perxis-go/proto/common"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// OperationServiceServer is an autogenerated mock type for the OperationServiceServer type
+type OperationServiceServer struct {
+	mock.Mock
+}
+
+// Cancel provides a mock function with given fields: _a0, _a1
+func (_m *OperationServiceServer) Cancel(_a0 context.Context, _a1 *common.CancelOperationRequest) (*common.Operation, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *common.Operation
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *common.CancelOperationRequest) (*common.Operation, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *common.CancelOperationRequest) *common.Operation); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*common.Operation)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *common.CancelOperationRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Get provides a mock function with given fields: _a0, _a1
+func (_m *OperationServiceServer) Get(_a0 context.Context, _a1 *common.GetOperationRequest) (*common.Operation, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *common.Operation
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *common.GetOperationRequest) (*common.Operation, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *common.GetOperationRequest) *common.Operation); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*common.Operation)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *common.GetOperationRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// mustEmbedUnimplementedOperationServiceServer provides a mock function with given fields:
+func (_m *OperationServiceServer) mustEmbedUnimplementedOperationServiceServer() {
+	_m.Called()
+}
+
+// NewOperationServiceServer creates a new instance of OperationServiceServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewOperationServiceServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *OperationServiceServer {
+	mock := &OperationServiceServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/OrganizationsClient.go b/proto/mocks/OrganizationsClient.go
new file mode 100644
index 0000000000000000000000000000000000000000..972d316dd0e1507b98ddc096709cc93acd5b80d2
--- /dev/null
+++ b/proto/mocks/OrganizationsClient.go
@@ -0,0 +1,198 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	grpc "google.golang.org/grpc"
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	mock "github.com/stretchr/testify/mock"
+
+	organizations "git.perx.ru/perxis/perxis-go/proto/organizations"
+)
+
+// OrganizationsClient is an autogenerated mock type for the OrganizationsClient type
+type OrganizationsClient struct {
+	mock.Mock
+}
+
+// Create provides a mock function with given fields: ctx, in, opts
+func (_m *OrganizationsClient) Create(ctx context.Context, in *organizations.CreateRequest, opts ...grpc.CallOption) (*organizations.CreateResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *organizations.CreateResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *organizations.CreateRequest, ...grpc.CallOption) (*organizations.CreateResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *organizations.CreateRequest, ...grpc.CallOption) *organizations.CreateResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*organizations.CreateResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *organizations.CreateRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Delete provides a mock function with given fields: ctx, in, opts
+func (_m *OrganizationsClient) Delete(ctx context.Context, in *organizations.DeleteRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *organizations.DeleteRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *organizations.DeleteRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *organizations.DeleteRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Find provides a mock function with given fields: ctx, in, opts
+func (_m *OrganizationsClient) Find(ctx context.Context, in *organizations.FindRequest, opts ...grpc.CallOption) (*organizations.FindResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *organizations.FindResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *organizations.FindRequest, ...grpc.CallOption) (*organizations.FindResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *organizations.FindRequest, ...grpc.CallOption) *organizations.FindResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*organizations.FindResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *organizations.FindRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Get provides a mock function with given fields: ctx, in, opts
+func (_m *OrganizationsClient) Get(ctx context.Context, in *organizations.GetRequest, opts ...grpc.CallOption) (*organizations.GetResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *organizations.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *organizations.GetRequest, ...grpc.CallOption) (*organizations.GetResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *organizations.GetRequest, ...grpc.CallOption) *organizations.GetResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*organizations.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *organizations.GetRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Update provides a mock function with given fields: ctx, in, opts
+func (_m *OrganizationsClient) Update(ctx context.Context, in *organizations.UpdateRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *organizations.UpdateRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *organizations.UpdateRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *organizations.UpdateRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// NewOrganizationsClient creates a new instance of OrganizationsClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewOrganizationsClient(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *OrganizationsClient {
+	mock := &OrganizationsClient{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/OrganizationsServer.go b/proto/mocks/OrganizationsServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..aa3ef3ad77177f56dd272bbcd19abacdd7e6a0a8
--- /dev/null
+++ b/proto/mocks/OrganizationsServer.go
@@ -0,0 +1,166 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	mock "github.com/stretchr/testify/mock"
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	organizations "git.perx.ru/perxis/perxis-go/proto/organizations"
+)
+
+// OrganizationsServer is an autogenerated mock type for the OrganizationsServer type
+type OrganizationsServer struct {
+	mock.Mock
+}
+
+// Create provides a mock function with given fields: _a0, _a1
+func (_m *OrganizationsServer) Create(_a0 context.Context, _a1 *organizations.CreateRequest) (*organizations.CreateResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *organizations.CreateResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *organizations.CreateRequest) (*organizations.CreateResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *organizations.CreateRequest) *organizations.CreateResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*organizations.CreateResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *organizations.CreateRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Delete provides a mock function with given fields: _a0, _a1
+func (_m *OrganizationsServer) Delete(_a0 context.Context, _a1 *organizations.DeleteRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *organizations.DeleteRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *organizations.DeleteRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *organizations.DeleteRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Find provides a mock function with given fields: _a0, _a1
+func (_m *OrganizationsServer) Find(_a0 context.Context, _a1 *organizations.FindRequest) (*organizations.FindResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *organizations.FindResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *organizations.FindRequest) (*organizations.FindResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *organizations.FindRequest) *organizations.FindResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*organizations.FindResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *organizations.FindRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Get provides a mock function with given fields: _a0, _a1
+func (_m *OrganizationsServer) Get(_a0 context.Context, _a1 *organizations.GetRequest) (*organizations.GetResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *organizations.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *organizations.GetRequest) (*organizations.GetResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *organizations.GetRequest) *organizations.GetResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*organizations.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *organizations.GetRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Update provides a mock function with given fields: _a0, _a1
+func (_m *OrganizationsServer) Update(_a0 context.Context, _a1 *organizations.UpdateRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *organizations.UpdateRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *organizations.UpdateRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *organizations.UpdateRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// mustEmbedUnimplementedOrganizationsServer provides a mock function with given fields:
+func (_m *OrganizationsServer) mustEmbedUnimplementedOrganizationsServer() {
+	_m.Called()
+}
+
+// NewOrganizationsServer creates a new instance of OrganizationsServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewOrganizationsServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *OrganizationsServer {
+	mock := &OrganizationsServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/ReferencesClient.go b/proto/mocks/ReferencesClient.go
new file mode 100644
index 0000000000000000000000000000000000000000..cc9a4344287be8e20da771edcb4869b474596f7f
--- /dev/null
+++ b/proto/mocks/ReferencesClient.go
@@ -0,0 +1,98 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	grpc "google.golang.org/grpc"
+
+	mock "github.com/stretchr/testify/mock"
+
+	references "git.perx.ru/perxis/perxis-go/proto/references"
+)
+
+// ReferencesClient is an autogenerated mock type for the ReferencesClient type
+type ReferencesClient struct {
+	mock.Mock
+}
+
+// Get provides a mock function with given fields: ctx, in, opts
+func (_m *ReferencesClient) Get(ctx context.Context, in *references.GetRequest, opts ...grpc.CallOption) (*references.GetResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *references.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *references.GetRequest, ...grpc.CallOption) (*references.GetResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *references.GetRequest, ...grpc.CallOption) *references.GetResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*references.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *references.GetRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Publish provides a mock function with given fields: ctx, in, opts
+func (_m *ReferencesClient) Publish(ctx context.Context, in *references.PublishRequest, opts ...grpc.CallOption) (*references.PublishResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *references.PublishResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *references.PublishRequest, ...grpc.CallOption) (*references.PublishResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *references.PublishRequest, ...grpc.CallOption) *references.PublishResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*references.PublishResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *references.PublishRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// NewReferencesClient creates a new instance of ReferencesClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewReferencesClient(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *ReferencesClient {
+	mock := &ReferencesClient{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/ReferencesServer.go b/proto/mocks/ReferencesServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..14555790eb4fbc287347fbbe6695c45c5339426b
--- /dev/null
+++ b/proto/mocks/ReferencesServer.go
@@ -0,0 +1,86 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	references "git.perx.ru/perxis/perxis-go/proto/references"
+	mock "github.com/stretchr/testify/mock"
+)
+
+// ReferencesServer is an autogenerated mock type for the ReferencesServer type
+type ReferencesServer struct {
+	mock.Mock
+}
+
+// Get provides a mock function with given fields: _a0, _a1
+func (_m *ReferencesServer) Get(_a0 context.Context, _a1 *references.GetRequest) (*references.GetResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *references.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *references.GetRequest) (*references.GetResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *references.GetRequest) *references.GetResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*references.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *references.GetRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Publish provides a mock function with given fields: _a0, _a1
+func (_m *ReferencesServer) Publish(_a0 context.Context, _a1 *references.PublishRequest) (*references.PublishResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *references.PublishResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *references.PublishRequest) (*references.PublishResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *references.PublishRequest) *references.PublishResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*references.PublishResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *references.PublishRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// mustEmbedUnimplementedReferencesServer provides a mock function with given fields:
+func (_m *ReferencesServer) mustEmbedUnimplementedReferencesServer() {
+	_m.Called()
+}
+
+// NewReferencesServer creates a new instance of ReferencesServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewReferencesServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *ReferencesServer {
+	mock := &ReferencesServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/RolesClient.go b/proto/mocks/RolesClient.go
new file mode 100644
index 0000000000000000000000000000000000000000..a70da1481947e96f722937fa1ecc969c8c475cc7
--- /dev/null
+++ b/proto/mocks/RolesClient.go
@@ -0,0 +1,198 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	grpc "google.golang.org/grpc"
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	mock "github.com/stretchr/testify/mock"
+
+	roles "git.perx.ru/perxis/perxis-go/proto/roles"
+)
+
+// RolesClient is an autogenerated mock type for the RolesClient type
+type RolesClient struct {
+	mock.Mock
+}
+
+// Create provides a mock function with given fields: ctx, in, opts
+func (_m *RolesClient) Create(ctx context.Context, in *roles.CreateRequest, opts ...grpc.CallOption) (*roles.CreateResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *roles.CreateResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *roles.CreateRequest, ...grpc.CallOption) (*roles.CreateResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *roles.CreateRequest, ...grpc.CallOption) *roles.CreateResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*roles.CreateResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *roles.CreateRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Delete provides a mock function with given fields: ctx, in, opts
+func (_m *RolesClient) Delete(ctx context.Context, in *roles.DeleteRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *roles.DeleteRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *roles.DeleteRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *roles.DeleteRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Get provides a mock function with given fields: ctx, in, opts
+func (_m *RolesClient) Get(ctx context.Context, in *roles.GetRequest, opts ...grpc.CallOption) (*roles.GetResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *roles.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *roles.GetRequest, ...grpc.CallOption) (*roles.GetResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *roles.GetRequest, ...grpc.CallOption) *roles.GetResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*roles.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *roles.GetRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// List provides a mock function with given fields: ctx, in, opts
+func (_m *RolesClient) List(ctx context.Context, in *roles.ListRequest, opts ...grpc.CallOption) (*roles.ListResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *roles.ListResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *roles.ListRequest, ...grpc.CallOption) (*roles.ListResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *roles.ListRequest, ...grpc.CallOption) *roles.ListResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*roles.ListResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *roles.ListRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Update provides a mock function with given fields: ctx, in, opts
+func (_m *RolesClient) Update(ctx context.Context, in *roles.UpdateRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *roles.UpdateRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *roles.UpdateRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *roles.UpdateRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// NewRolesClient creates a new instance of RolesClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewRolesClient(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *RolesClient {
+	mock := &RolesClient{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/RolesServer.go b/proto/mocks/RolesServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..7a9119863bde4807b2dc47a5ad0e6c35521acef2
--- /dev/null
+++ b/proto/mocks/RolesServer.go
@@ -0,0 +1,166 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	mock "github.com/stretchr/testify/mock"
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	roles "git.perx.ru/perxis/perxis-go/proto/roles"
+)
+
+// RolesServer is an autogenerated mock type for the RolesServer type
+type RolesServer struct {
+	mock.Mock
+}
+
+// Create provides a mock function with given fields: _a0, _a1
+func (_m *RolesServer) Create(_a0 context.Context, _a1 *roles.CreateRequest) (*roles.CreateResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *roles.CreateResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *roles.CreateRequest) (*roles.CreateResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *roles.CreateRequest) *roles.CreateResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*roles.CreateResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *roles.CreateRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Delete provides a mock function with given fields: _a0, _a1
+func (_m *RolesServer) Delete(_a0 context.Context, _a1 *roles.DeleteRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *roles.DeleteRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *roles.DeleteRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *roles.DeleteRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Get provides a mock function with given fields: _a0, _a1
+func (_m *RolesServer) Get(_a0 context.Context, _a1 *roles.GetRequest) (*roles.GetResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *roles.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *roles.GetRequest) (*roles.GetResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *roles.GetRequest) *roles.GetResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*roles.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *roles.GetRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// List provides a mock function with given fields: _a0, _a1
+func (_m *RolesServer) List(_a0 context.Context, _a1 *roles.ListRequest) (*roles.ListResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *roles.ListResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *roles.ListRequest) (*roles.ListResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *roles.ListRequest) *roles.ListResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*roles.ListResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *roles.ListRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Update provides a mock function with given fields: _a0, _a1
+func (_m *RolesServer) Update(_a0 context.Context, _a1 *roles.UpdateRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *roles.UpdateRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *roles.UpdateRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *roles.UpdateRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// mustEmbedUnimplementedRolesServer provides a mock function with given fields:
+func (_m *RolesServer) mustEmbedUnimplementedRolesServer() {
+	_m.Called()
+}
+
+// NewRolesServer creates a new instance of RolesServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewRolesServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *RolesServer {
+	mock := &RolesServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/SpacesClient.go b/proto/mocks/SpacesClient.go
new file mode 100644
index 0000000000000000000000000000000000000000..c73344dfd7c46cde2cbddea687129ff0c0f78bae
--- /dev/null
+++ b/proto/mocks/SpacesClient.go
@@ -0,0 +1,363 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	grpc "google.golang.org/grpc"
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	mock "github.com/stretchr/testify/mock"
+
+	spaces "git.perx.ru/perxis/perxis-go/proto/spaces"
+)
+
+// SpacesClient is an autogenerated mock type for the SpacesClient type
+type SpacesClient struct {
+	mock.Mock
+}
+
+// AbortTransfer provides a mock function with given fields: ctx, in, opts
+func (_m *SpacesClient) AbortTransfer(ctx context.Context, in *spaces.AbortTransferRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.AbortTransferRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.AbortTransferRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *spaces.AbortTransferRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Create provides a mock function with given fields: ctx, in, opts
+func (_m *SpacesClient) Create(ctx context.Context, in *spaces.CreateRequest, opts ...grpc.CallOption) (*spaces.CreateResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *spaces.CreateResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.CreateRequest, ...grpc.CallOption) (*spaces.CreateResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.CreateRequest, ...grpc.CallOption) *spaces.CreateResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*spaces.CreateResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *spaces.CreateRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Delete provides a mock function with given fields: ctx, in, opts
+func (_m *SpacesClient) Delete(ctx context.Context, in *spaces.DeleteRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.DeleteRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.DeleteRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *spaces.DeleteRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Get provides a mock function with given fields: ctx, in, opts
+func (_m *SpacesClient) Get(ctx context.Context, in *spaces.GetRequest, opts ...grpc.CallOption) (*spaces.GetResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *spaces.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.GetRequest, ...grpc.CallOption) (*spaces.GetResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.GetRequest, ...grpc.CallOption) *spaces.GetResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*spaces.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *spaces.GetRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// List provides a mock function with given fields: ctx, in, opts
+func (_m *SpacesClient) List(ctx context.Context, in *spaces.ListRequest, opts ...grpc.CallOption) (*spaces.ListResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *spaces.ListResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.ListRequest, ...grpc.CallOption) (*spaces.ListResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.ListRequest, ...grpc.CallOption) *spaces.ListResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*spaces.ListResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *spaces.ListRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// ListTransfers provides a mock function with given fields: ctx, in, opts
+func (_m *SpacesClient) ListTransfers(ctx context.Context, in *spaces.ListTransfersRequest, opts ...grpc.CallOption) (*spaces.ListTransfersResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *spaces.ListTransfersResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.ListTransfersRequest, ...grpc.CallOption) (*spaces.ListTransfersResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.ListTransfersRequest, ...grpc.CallOption) *spaces.ListTransfersResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*spaces.ListTransfersResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *spaces.ListTransfersRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Move provides a mock function with given fields: ctx, in, opts
+func (_m *SpacesClient) Move(ctx context.Context, in *spaces.MoveRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.MoveRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.MoveRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *spaces.MoveRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Transfer provides a mock function with given fields: ctx, in, opts
+func (_m *SpacesClient) Transfer(ctx context.Context, in *spaces.TransferRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.TransferRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.TransferRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *spaces.TransferRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Update provides a mock function with given fields: ctx, in, opts
+func (_m *SpacesClient) Update(ctx context.Context, in *spaces.UpdateRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.UpdateRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.UpdateRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *spaces.UpdateRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// UpdateConfig provides a mock function with given fields: ctx, in, opts
+func (_m *SpacesClient) UpdateConfig(ctx context.Context, in *spaces.UpdateConfigRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.UpdateConfigRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.UpdateConfigRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *spaces.UpdateConfigRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// NewSpacesClient creates a new instance of SpacesClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewSpacesClient(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *SpacesClient {
+	mock := &SpacesClient{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/SpacesServer.go b/proto/mocks/SpacesServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..410c1651174b63a1555f43a38ce91872b922aa76
--- /dev/null
+++ b/proto/mocks/SpacesServer.go
@@ -0,0 +1,296 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	mock "github.com/stretchr/testify/mock"
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	spaces "git.perx.ru/perxis/perxis-go/proto/spaces"
+)
+
+// SpacesServer is an autogenerated mock type for the SpacesServer type
+type SpacesServer struct {
+	mock.Mock
+}
+
+// AbortTransfer provides a mock function with given fields: _a0, _a1
+func (_m *SpacesServer) AbortTransfer(_a0 context.Context, _a1 *spaces.AbortTransferRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.AbortTransferRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.AbortTransferRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *spaces.AbortTransferRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Create provides a mock function with given fields: _a0, _a1
+func (_m *SpacesServer) Create(_a0 context.Context, _a1 *spaces.CreateRequest) (*spaces.CreateResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *spaces.CreateResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.CreateRequest) (*spaces.CreateResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.CreateRequest) *spaces.CreateResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*spaces.CreateResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *spaces.CreateRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Delete provides a mock function with given fields: _a0, _a1
+func (_m *SpacesServer) Delete(_a0 context.Context, _a1 *spaces.DeleteRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.DeleteRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.DeleteRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *spaces.DeleteRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Get provides a mock function with given fields: _a0, _a1
+func (_m *SpacesServer) Get(_a0 context.Context, _a1 *spaces.GetRequest) (*spaces.GetResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *spaces.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.GetRequest) (*spaces.GetResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.GetRequest) *spaces.GetResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*spaces.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *spaces.GetRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// List provides a mock function with given fields: _a0, _a1
+func (_m *SpacesServer) List(_a0 context.Context, _a1 *spaces.ListRequest) (*spaces.ListResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *spaces.ListResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.ListRequest) (*spaces.ListResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.ListRequest) *spaces.ListResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*spaces.ListResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *spaces.ListRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// ListTransfers provides a mock function with given fields: _a0, _a1
+func (_m *SpacesServer) ListTransfers(_a0 context.Context, _a1 *spaces.ListTransfersRequest) (*spaces.ListTransfersResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *spaces.ListTransfersResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.ListTransfersRequest) (*spaces.ListTransfersResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.ListTransfersRequest) *spaces.ListTransfersResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*spaces.ListTransfersResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *spaces.ListTransfersRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Move provides a mock function with given fields: _a0, _a1
+func (_m *SpacesServer) Move(_a0 context.Context, _a1 *spaces.MoveRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.MoveRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.MoveRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *spaces.MoveRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Transfer provides a mock function with given fields: _a0, _a1
+func (_m *SpacesServer) Transfer(_a0 context.Context, _a1 *spaces.TransferRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.TransferRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.TransferRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *spaces.TransferRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Update provides a mock function with given fields: _a0, _a1
+func (_m *SpacesServer) Update(_a0 context.Context, _a1 *spaces.UpdateRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.UpdateRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.UpdateRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *spaces.UpdateRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// UpdateConfig provides a mock function with given fields: _a0, _a1
+func (_m *SpacesServer) UpdateConfig(_a0 context.Context, _a1 *spaces.UpdateConfigRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.UpdateConfigRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *spaces.UpdateConfigRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *spaces.UpdateConfigRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// mustEmbedUnimplementedSpacesServer provides a mock function with given fields:
+func (_m *SpacesServer) mustEmbedUnimplementedSpacesServer() {
+	_m.Called()
+}
+
+// NewSpacesServer creates a new instance of SpacesServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewSpacesServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *SpacesServer {
+	mock := &SpacesServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/UnsafeClientsServer.go b/proto/mocks/UnsafeClientsServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..edaae9de67b00ad2de5e73568457380a3942a0cf
--- /dev/null
+++ b/proto/mocks/UnsafeClientsServer.go
@@ -0,0 +1,29 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+
+// UnsafeClientsServer is an autogenerated mock type for the UnsafeClientsServer type
+type UnsafeClientsServer struct {
+	mock.Mock
+}
+
+// mustEmbedUnimplementedClientsServer provides a mock function with given fields:
+func (_m *UnsafeClientsServer) mustEmbedUnimplementedClientsServer() {
+	_m.Called()
+}
+
+// NewUnsafeClientsServer creates a new instance of UnsafeClientsServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewUnsafeClientsServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *UnsafeClientsServer {
+	mock := &UnsafeClientsServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/UnsafeCollaboratorsServer.go b/proto/mocks/UnsafeCollaboratorsServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..032a8659ddecf0af1f06afb59759bd5356d47df8
--- /dev/null
+++ b/proto/mocks/UnsafeCollaboratorsServer.go
@@ -0,0 +1,29 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+
+// UnsafeCollaboratorsServer is an autogenerated mock type for the UnsafeCollaboratorsServer type
+type UnsafeCollaboratorsServer struct {
+	mock.Mock
+}
+
+// mustEmbedUnimplementedCollaboratorsServer provides a mock function with given fields:
+func (_m *UnsafeCollaboratorsServer) mustEmbedUnimplementedCollaboratorsServer() {
+	_m.Called()
+}
+
+// NewUnsafeCollaboratorsServer creates a new instance of UnsafeCollaboratorsServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewUnsafeCollaboratorsServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *UnsafeCollaboratorsServer {
+	mock := &UnsafeCollaboratorsServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/UnsafeCollectionsServer.go b/proto/mocks/UnsafeCollectionsServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..f827fa421970a92974109459487cbac4b2692524
--- /dev/null
+++ b/proto/mocks/UnsafeCollectionsServer.go
@@ -0,0 +1,29 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+
+// UnsafeCollectionsServer is an autogenerated mock type for the UnsafeCollectionsServer type
+type UnsafeCollectionsServer struct {
+	mock.Mock
+}
+
+// mustEmbedUnimplementedCollectionsServer provides a mock function with given fields:
+func (_m *UnsafeCollectionsServer) mustEmbedUnimplementedCollectionsServer() {
+	_m.Called()
+}
+
+// NewUnsafeCollectionsServer creates a new instance of UnsafeCollectionsServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewUnsafeCollectionsServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *UnsafeCollectionsServer {
+	mock := &UnsafeCollectionsServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/UnsafeDeliveryServer.go b/proto/mocks/UnsafeDeliveryServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..ad857a41f102912e0ce115145900b0541286e4cd
--- /dev/null
+++ b/proto/mocks/UnsafeDeliveryServer.go
@@ -0,0 +1,29 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+
+// UnsafeDeliveryServer is an autogenerated mock type for the UnsafeDeliveryServer type
+type UnsafeDeliveryServer struct {
+	mock.Mock
+}
+
+// mustEmbedUnimplementedDeliveryServer provides a mock function with given fields:
+func (_m *UnsafeDeliveryServer) mustEmbedUnimplementedDeliveryServer() {
+	_m.Called()
+}
+
+// NewUnsafeDeliveryServer creates a new instance of UnsafeDeliveryServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewUnsafeDeliveryServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *UnsafeDeliveryServer {
+	mock := &UnsafeDeliveryServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/UnsafeEnvironmentsServer.go b/proto/mocks/UnsafeEnvironmentsServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..c6499e683c1e940b868c8b2a45e3a5a28d72240f
--- /dev/null
+++ b/proto/mocks/UnsafeEnvironmentsServer.go
@@ -0,0 +1,29 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+
+// UnsafeEnvironmentsServer is an autogenerated mock type for the UnsafeEnvironmentsServer type
+type UnsafeEnvironmentsServer struct {
+	mock.Mock
+}
+
+// mustEmbedUnimplementedEnvironmentsServer provides a mock function with given fields:
+func (_m *UnsafeEnvironmentsServer) mustEmbedUnimplementedEnvironmentsServer() {
+	_m.Called()
+}
+
+// NewUnsafeEnvironmentsServer creates a new instance of UnsafeEnvironmentsServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewUnsafeEnvironmentsServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *UnsafeEnvironmentsServer {
+	mock := &UnsafeEnvironmentsServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/UnsafeFilesServer.go b/proto/mocks/UnsafeFilesServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..4b952359a53fcf45b88f015ae53aebbb1273d0a6
--- /dev/null
+++ b/proto/mocks/UnsafeFilesServer.go
@@ -0,0 +1,29 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+
+// UnsafeFilesServer is an autogenerated mock type for the UnsafeFilesServer type
+type UnsafeFilesServer struct {
+	mock.Mock
+}
+
+// mustEmbedUnimplementedFilesServer provides a mock function with given fields:
+func (_m *UnsafeFilesServer) mustEmbedUnimplementedFilesServer() {
+	_m.Called()
+}
+
+// NewUnsafeFilesServer creates a new instance of UnsafeFilesServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewUnsafeFilesServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *UnsafeFilesServer {
+	mock := &UnsafeFilesServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/UnsafeImagesServer.go b/proto/mocks/UnsafeImagesServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..b99df04a247a0772ddb4e22624045539e5ee65c9
--- /dev/null
+++ b/proto/mocks/UnsafeImagesServer.go
@@ -0,0 +1,29 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+
+// UnsafeImagesServer is an autogenerated mock type for the UnsafeImagesServer type
+type UnsafeImagesServer struct {
+	mock.Mock
+}
+
+// mustEmbedUnimplementedImagesServer provides a mock function with given fields:
+func (_m *UnsafeImagesServer) mustEmbedUnimplementedImagesServer() {
+	_m.Called()
+}
+
+// NewUnsafeImagesServer creates a new instance of UnsafeImagesServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewUnsafeImagesServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *UnsafeImagesServer {
+	mock := &UnsafeImagesServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/UnsafeInvitationsServer.go b/proto/mocks/UnsafeInvitationsServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..f7cfa3550e3b274aa92c2de1757973991e40a8f6
--- /dev/null
+++ b/proto/mocks/UnsafeInvitationsServer.go
@@ -0,0 +1,29 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+
+// UnsafeInvitationsServer is an autogenerated mock type for the UnsafeInvitationsServer type
+type UnsafeInvitationsServer struct {
+	mock.Mock
+}
+
+// mustEmbedUnimplementedInvitationsServer provides a mock function with given fields:
+func (_m *UnsafeInvitationsServer) mustEmbedUnimplementedInvitationsServer() {
+	_m.Called()
+}
+
+// NewUnsafeInvitationsServer creates a new instance of UnsafeInvitationsServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewUnsafeInvitationsServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *UnsafeInvitationsServer {
+	mock := &UnsafeInvitationsServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/UnsafeItemsServer.go b/proto/mocks/UnsafeItemsServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..a261bf4ab6d04bf02baf6a82d1abb2ac9d92cc0a
--- /dev/null
+++ b/proto/mocks/UnsafeItemsServer.go
@@ -0,0 +1,29 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+
+// UnsafeItemsServer is an autogenerated mock type for the UnsafeItemsServer type
+type UnsafeItemsServer struct {
+	mock.Mock
+}
+
+// mustEmbedUnimplementedItemsServer provides a mock function with given fields:
+func (_m *UnsafeItemsServer) mustEmbedUnimplementedItemsServer() {
+	_m.Called()
+}
+
+// NewUnsafeItemsServer creates a new instance of UnsafeItemsServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewUnsafeItemsServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *UnsafeItemsServer {
+	mock := &UnsafeItemsServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/UnsafeLocalesServer.go b/proto/mocks/UnsafeLocalesServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..e66f9ac5cc32336dd6d11db3380c1469a5bc4893
--- /dev/null
+++ b/proto/mocks/UnsafeLocalesServer.go
@@ -0,0 +1,29 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+
+// UnsafeLocalesServer is an autogenerated mock type for the UnsafeLocalesServer type
+type UnsafeLocalesServer struct {
+	mock.Mock
+}
+
+// mustEmbedUnimplementedLocalesServer provides a mock function with given fields:
+func (_m *UnsafeLocalesServer) mustEmbedUnimplementedLocalesServer() {
+	_m.Called()
+}
+
+// NewUnsafeLocalesServer creates a new instance of UnsafeLocalesServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewUnsafeLocalesServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *UnsafeLocalesServer {
+	mock := &UnsafeLocalesServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/UnsafeMembersServer.go b/proto/mocks/UnsafeMembersServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..14df5465251661b5257fb5ea56ff085f027e0639
--- /dev/null
+++ b/proto/mocks/UnsafeMembersServer.go
@@ -0,0 +1,29 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+
+// UnsafeMembersServer is an autogenerated mock type for the UnsafeMembersServer type
+type UnsafeMembersServer struct {
+	mock.Mock
+}
+
+// mustEmbedUnimplementedMembersServer provides a mock function with given fields:
+func (_m *UnsafeMembersServer) mustEmbedUnimplementedMembersServer() {
+	_m.Called()
+}
+
+// NewUnsafeMembersServer creates a new instance of UnsafeMembersServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewUnsafeMembersServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *UnsafeMembersServer {
+	mock := &UnsafeMembersServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/UnsafeObserverServer.go b/proto/mocks/UnsafeObserverServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..8c68681a2d0428ce19a25378fd27910707a870ed
--- /dev/null
+++ b/proto/mocks/UnsafeObserverServer.go
@@ -0,0 +1,29 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+
+// UnsafeObserverServer is an autogenerated mock type for the UnsafeObserverServer type
+type UnsafeObserverServer struct {
+	mock.Mock
+}
+
+// mustEmbedUnimplementedObserverServer provides a mock function with given fields:
+func (_m *UnsafeObserverServer) mustEmbedUnimplementedObserverServer() {
+	_m.Called()
+}
+
+// NewUnsafeObserverServer creates a new instance of UnsafeObserverServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewUnsafeObserverServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *UnsafeObserverServer {
+	mock := &UnsafeObserverServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/UnsafeOperationServiceServer.go b/proto/mocks/UnsafeOperationServiceServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..46d3cdaa3f846a56633072495e607e4d9e8e23c8
--- /dev/null
+++ b/proto/mocks/UnsafeOperationServiceServer.go
@@ -0,0 +1,29 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+
+// UnsafeOperationServiceServer is an autogenerated mock type for the UnsafeOperationServiceServer type
+type UnsafeOperationServiceServer struct {
+	mock.Mock
+}
+
+// mustEmbedUnimplementedOperationServiceServer provides a mock function with given fields:
+func (_m *UnsafeOperationServiceServer) mustEmbedUnimplementedOperationServiceServer() {
+	_m.Called()
+}
+
+// NewUnsafeOperationServiceServer creates a new instance of UnsafeOperationServiceServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewUnsafeOperationServiceServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *UnsafeOperationServiceServer {
+	mock := &UnsafeOperationServiceServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/UnsafeOrganizationsServer.go b/proto/mocks/UnsafeOrganizationsServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..378edd0eb09d9556bb1d667bb4d99d162e4da8a0
--- /dev/null
+++ b/proto/mocks/UnsafeOrganizationsServer.go
@@ -0,0 +1,29 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+
+// UnsafeOrganizationsServer is an autogenerated mock type for the UnsafeOrganizationsServer type
+type UnsafeOrganizationsServer struct {
+	mock.Mock
+}
+
+// mustEmbedUnimplementedOrganizationsServer provides a mock function with given fields:
+func (_m *UnsafeOrganizationsServer) mustEmbedUnimplementedOrganizationsServer() {
+	_m.Called()
+}
+
+// NewUnsafeOrganizationsServer creates a new instance of UnsafeOrganizationsServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewUnsafeOrganizationsServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *UnsafeOrganizationsServer {
+	mock := &UnsafeOrganizationsServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/UnsafeReferencesServer.go b/proto/mocks/UnsafeReferencesServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..f0ba11eb665bb280e79ee26f39328fcc5f8df6f6
--- /dev/null
+++ b/proto/mocks/UnsafeReferencesServer.go
@@ -0,0 +1,29 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+
+// UnsafeReferencesServer is an autogenerated mock type for the UnsafeReferencesServer type
+type UnsafeReferencesServer struct {
+	mock.Mock
+}
+
+// mustEmbedUnimplementedReferencesServer provides a mock function with given fields:
+func (_m *UnsafeReferencesServer) mustEmbedUnimplementedReferencesServer() {
+	_m.Called()
+}
+
+// NewUnsafeReferencesServer creates a new instance of UnsafeReferencesServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewUnsafeReferencesServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *UnsafeReferencesServer {
+	mock := &UnsafeReferencesServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/UnsafeRolesServer.go b/proto/mocks/UnsafeRolesServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..5ac0028d3c1ce25b36ae39db5bf3bdeab3d6d411
--- /dev/null
+++ b/proto/mocks/UnsafeRolesServer.go
@@ -0,0 +1,29 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+
+// UnsafeRolesServer is an autogenerated mock type for the UnsafeRolesServer type
+type UnsafeRolesServer struct {
+	mock.Mock
+}
+
+// mustEmbedUnimplementedRolesServer provides a mock function with given fields:
+func (_m *UnsafeRolesServer) mustEmbedUnimplementedRolesServer() {
+	_m.Called()
+}
+
+// NewUnsafeRolesServer creates a new instance of UnsafeRolesServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewUnsafeRolesServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *UnsafeRolesServer {
+	mock := &UnsafeRolesServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/UnsafeSpacesServer.go b/proto/mocks/UnsafeSpacesServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..3985b213a578bbdba843c55ea9d417742d28397a
--- /dev/null
+++ b/proto/mocks/UnsafeSpacesServer.go
@@ -0,0 +1,29 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+
+// UnsafeSpacesServer is an autogenerated mock type for the UnsafeSpacesServer type
+type UnsafeSpacesServer struct {
+	mock.Mock
+}
+
+// mustEmbedUnimplementedSpacesServer provides a mock function with given fields:
+func (_m *UnsafeSpacesServer) mustEmbedUnimplementedSpacesServer() {
+	_m.Called()
+}
+
+// NewUnsafeSpacesServer creates a new instance of UnsafeSpacesServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewUnsafeSpacesServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *UnsafeSpacesServer {
+	mock := &UnsafeSpacesServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/UnsafeUsersServer.go b/proto/mocks/UnsafeUsersServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..6fb87834b8833d591be1472515baacf05e53817b
--- /dev/null
+++ b/proto/mocks/UnsafeUsersServer.go
@@ -0,0 +1,29 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+
+// UnsafeUsersServer is an autogenerated mock type for the UnsafeUsersServer type
+type UnsafeUsersServer struct {
+	mock.Mock
+}
+
+// mustEmbedUnimplementedUsersServer provides a mock function with given fields:
+func (_m *UnsafeUsersServer) mustEmbedUnimplementedUsersServer() {
+	_m.Called()
+}
+
+// NewUnsafeUsersServer creates a new instance of UnsafeUsersServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewUnsafeUsersServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *UnsafeUsersServer {
+	mock := &UnsafeUsersServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/UnsafeVersionsServer.go b/proto/mocks/UnsafeVersionsServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..551623161886a3f4f852c90a57dc8a4027dbf401
--- /dev/null
+++ b/proto/mocks/UnsafeVersionsServer.go
@@ -0,0 +1,29 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+
+// UnsafeVersionsServer is an autogenerated mock type for the UnsafeVersionsServer type
+type UnsafeVersionsServer struct {
+	mock.Mock
+}
+
+// mustEmbedUnimplementedVersionsServer provides a mock function with given fields:
+func (_m *UnsafeVersionsServer) mustEmbedUnimplementedVersionsServer() {
+	_m.Called()
+}
+
+// NewUnsafeVersionsServer creates a new instance of UnsafeVersionsServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewUnsafeVersionsServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *UnsafeVersionsServer {
+	mock := &UnsafeVersionsServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/UsersClient.go b/proto/mocks/UsersClient.go
new file mode 100644
index 0000000000000000000000000000000000000000..3bc7707535e4644f66f4105fbe01ae2374de3274
--- /dev/null
+++ b/proto/mocks/UsersClient.go
@@ -0,0 +1,231 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	grpc "google.golang.org/grpc"
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	mock "github.com/stretchr/testify/mock"
+
+	users "git.perx.ru/perxis/perxis-go/proto/users"
+)
+
+// UsersClient is an autogenerated mock type for the UsersClient type
+type UsersClient struct {
+	mock.Mock
+}
+
+// Create provides a mock function with given fields: ctx, in, opts
+func (_m *UsersClient) Create(ctx context.Context, in *users.CreateRequest, opts ...grpc.CallOption) (*users.CreateResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *users.CreateResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *users.CreateRequest, ...grpc.CallOption) (*users.CreateResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *users.CreateRequest, ...grpc.CallOption) *users.CreateResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*users.CreateResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *users.CreateRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Delete provides a mock function with given fields: ctx, in, opts
+func (_m *UsersClient) Delete(ctx context.Context, in *users.DeleteRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *users.DeleteRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *users.DeleteRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *users.DeleteRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Find provides a mock function with given fields: ctx, in, opts
+func (_m *UsersClient) Find(ctx context.Context, in *users.FindRequest, opts ...grpc.CallOption) (*users.FindResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *users.FindResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *users.FindRequest, ...grpc.CallOption) (*users.FindResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *users.FindRequest, ...grpc.CallOption) *users.FindResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*users.FindResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *users.FindRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Get provides a mock function with given fields: ctx, in, opts
+func (_m *UsersClient) Get(ctx context.Context, in *users.GetRequest, opts ...grpc.CallOption) (*users.GetResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *users.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *users.GetRequest, ...grpc.CallOption) (*users.GetResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *users.GetRequest, ...grpc.CallOption) *users.GetResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*users.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *users.GetRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// GetByIdentity provides a mock function with given fields: ctx, in, opts
+func (_m *UsersClient) GetByIdentity(ctx context.Context, in *users.GetByIdentityRequest, opts ...grpc.CallOption) (*users.GetByIdentityResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *users.GetByIdentityResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *users.GetByIdentityRequest, ...grpc.CallOption) (*users.GetByIdentityResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *users.GetByIdentityRequest, ...grpc.CallOption) *users.GetByIdentityResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*users.GetByIdentityResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *users.GetByIdentityRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Update provides a mock function with given fields: ctx, in, opts
+func (_m *UsersClient) Update(ctx context.Context, in *users.UpdateRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *users.UpdateRequest, ...grpc.CallOption) (*emptypb.Empty, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *users.UpdateRequest, ...grpc.CallOption) *emptypb.Empty); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *users.UpdateRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// NewUsersClient creates a new instance of UsersClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewUsersClient(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *UsersClient {
+	mock := &UsersClient{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/UsersServer.go b/proto/mocks/UsersServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..837d164578df39775f03cb3845cdbe57f2f11bb6
--- /dev/null
+++ b/proto/mocks/UsersServer.go
@@ -0,0 +1,192 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	mock "github.com/stretchr/testify/mock"
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	users "git.perx.ru/perxis/perxis-go/proto/users"
+)
+
+// UsersServer is an autogenerated mock type for the UsersServer type
+type UsersServer struct {
+	mock.Mock
+}
+
+// Create provides a mock function with given fields: _a0, _a1
+func (_m *UsersServer) Create(_a0 context.Context, _a1 *users.CreateRequest) (*users.CreateResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *users.CreateResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *users.CreateRequest) (*users.CreateResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *users.CreateRequest) *users.CreateResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*users.CreateResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *users.CreateRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Delete provides a mock function with given fields: _a0, _a1
+func (_m *UsersServer) Delete(_a0 context.Context, _a1 *users.DeleteRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *users.DeleteRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *users.DeleteRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *users.DeleteRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Find provides a mock function with given fields: _a0, _a1
+func (_m *UsersServer) Find(_a0 context.Context, _a1 *users.FindRequest) (*users.FindResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *users.FindResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *users.FindRequest) (*users.FindResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *users.FindRequest) *users.FindResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*users.FindResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *users.FindRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Get provides a mock function with given fields: _a0, _a1
+func (_m *UsersServer) Get(_a0 context.Context, _a1 *users.GetRequest) (*users.GetResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *users.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *users.GetRequest) (*users.GetResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *users.GetRequest) *users.GetResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*users.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *users.GetRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// GetByIdentity provides a mock function with given fields: _a0, _a1
+func (_m *UsersServer) GetByIdentity(_a0 context.Context, _a1 *users.GetByIdentityRequest) (*users.GetByIdentityResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *users.GetByIdentityResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *users.GetByIdentityRequest) (*users.GetByIdentityResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *users.GetByIdentityRequest) *users.GetByIdentityResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*users.GetByIdentityResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *users.GetByIdentityRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Update provides a mock function with given fields: _a0, _a1
+func (_m *UsersServer) Update(_a0 context.Context, _a1 *users.UpdateRequest) (*emptypb.Empty, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *emptypb.Empty
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *users.UpdateRequest) (*emptypb.Empty, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *users.UpdateRequest) *emptypb.Empty); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*emptypb.Empty)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *users.UpdateRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// mustEmbedUnimplementedUsersServer provides a mock function with given fields:
+func (_m *UsersServer) mustEmbedUnimplementedUsersServer() {
+	_m.Called()
+}
+
+// NewUsersServer creates a new instance of UsersServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewUsersServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *UsersServer {
+	mock := &UsersServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/VersionsClient.go b/proto/mocks/VersionsClient.go
new file mode 100644
index 0000000000000000000000000000000000000000..587b1cf8bf8c5e365fe3726800374c5bd042605a
--- /dev/null
+++ b/proto/mocks/VersionsClient.go
@@ -0,0 +1,67 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	content "git.perx.ru/perxis/perxis-go/proto/versions/content"
+
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	grpc "google.golang.org/grpc"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// VersionsClient is an autogenerated mock type for the VersionsClient type
+type VersionsClient struct {
+	mock.Mock
+}
+
+// Get provides a mock function with given fields: ctx, in, opts
+func (_m *VersionsClient) Get(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*content.GetResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *content.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *emptypb.Empty, ...grpc.CallOption) (*content.GetResponse, error)); ok {
+		return rf(ctx, in, opts...)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *emptypb.Empty, ...grpc.CallOption) *content.GetResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*content.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *emptypb.Empty, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// NewVersionsClient creates a new instance of VersionsClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewVersionsClient(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *VersionsClient {
+	mock := &VersionsClient{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/VersionsServer.go b/proto/mocks/VersionsServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..4509e2c4d3bc39ac42d12a91cc709b1f973a5c90
--- /dev/null
+++ b/proto/mocks/VersionsServer.go
@@ -0,0 +1,63 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	content "git.perx.ru/perxis/perxis-go/proto/versions/content"
+
+	emptypb "google.golang.org/protobuf/types/known/emptypb"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// VersionsServer is an autogenerated mock type for the VersionsServer type
+type VersionsServer struct {
+	mock.Mock
+}
+
+// Get provides a mock function with given fields: _a0, _a1
+func (_m *VersionsServer) Get(_a0 context.Context, _a1 *emptypb.Empty) (*content.GetResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *content.GetResponse
+	var r1 error
+	if rf, ok := ret.Get(0).(func(context.Context, *emptypb.Empty) (*content.GetResponse, error)); ok {
+		return rf(_a0, _a1)
+	}
+	if rf, ok := ret.Get(0).(func(context.Context, *emptypb.Empty) *content.GetResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*content.GetResponse)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(context.Context, *emptypb.Empty) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// mustEmbedUnimplementedVersionsServer provides a mock function with given fields:
+func (_m *VersionsServer) mustEmbedUnimplementedVersionsServer() {
+	_m.Called()
+}
+
+// NewVersionsServer creates a new instance of VersionsServer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func NewVersionsServer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *VersionsServer {
+	mock := &VersionsServer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/proto/mocks/isOperation_Result.go b/proto/mocks/isOperation_Result.go
new file mode 100644
index 0000000000000000000000000000000000000000..cc9c1717419e4b8d48f627947b360689af80841c
--- /dev/null
+++ b/proto/mocks/isOperation_Result.go
@@ -0,0 +1,29 @@
+// Code generated by mockery v2.33.3. DO NOT EDIT.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+
+// isOperation_Result is an autogenerated mock type for the isOperation_Result type
+type isOperation_Result struct {
+	mock.Mock
+}
+
+// isOperation_Result provides a mock function with given fields:
+func (_m *isOperation_Result) isOperation_Result() {
+	_m.Called()
+}
+
+// newIsOperation_Result creates a new instance of isOperation_Result. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func newIsOperation_Result(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *isOperation_Result {
+	mock := &isOperation_Result{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}